Example #1
0
    def testMetricsReporting(self):
        """Tests the subprocess creation by Popen in metrics.py."""
        popen_mock = self._StartObjectPatch(subprocess, 'Popen')

        # Set up the temp file for pickle dumping metrics into.
        metrics_file = tempfile.NamedTemporaryFile()
        metrics_file.close()
        temp_file_mock = self._StartObjectPatch(tempfile, 'NamedTemporaryFile')
        temp_file_mock.return_value = open(metrics_file.name, 'wb')

        # If there are no metrics, Popen should not be called.
        self.collector.ReportMetrics()
        self.assertEqual(0, popen_mock.call_count)

        _LogAllTestMetrics()

        # Report the metrics and check Popen calls.
        metrics.Shutdown()
        call_list = popen_mock.call_args_list
        self.assertEqual(1, len(call_list))
        # Check to make sure that we have the proper PYTHONPATH in the subprocess.
        args = call_list[0]
        self.assertIn('PYTHONPATH', args[1]['env'])
        # Ensure that we can access the same modules as the main process from
        # PYTHONPATH.
        missing_paths = (set(sys.path) -
                         set(args[1]['env']['PYTHONPATH'].split(os.pathsep)))
        self.assertEqual(set(), missing_paths)

        # Check that the metrics were correctly dumped into the temp file.
        with open(metrics_file.name, 'rb') as metrics_file:
            reported_metrics = pickle.load(metrics_file)
        self.assertEqual(COMMAND_AND_ERROR_TEST_METRICS,
                         MetricListToTestMetricSet(reported_metrics))
Example #2
0
    def testExceptionCatchingDecorator(self):
        """Tests the exception catching decorator CaptureAndLogException."""
        original_log_level = self.root_logger.getEffectiveLevel()
        self.root_logger.setLevel(logging.DEBUG)

        # Test that a wrapped function with an exception doesn't stop the process.
        mock_exc_fn = mock.MagicMock(__name__='mock_exc_fn',
                                     side_effect=Exception())
        wrapped_fn = metrics.CaptureAndLogException(mock_exc_fn)
        wrapped_fn()
        self.assertEqual(1, mock_exc_fn.call_count)
        with open(self.log_handler_file) as f:
            log_output = f.read()
            self.assertIn(
                'Exception captured in mock_exc_fn during metrics '
                'collection', log_output)

        mock_err_fn = mock.MagicMock(__name__='mock_err_fn',
                                     side_effect=TypeError())
        wrapped_fn = metrics.CaptureAndLogException(mock_err_fn)
        wrapped_fn()
        self.assertEqual(1, mock_err_fn.call_count)
        with open(self.log_handler_file) as f:
            log_output = f.read()
            self.assertIn(
                'Exception captured in mock_err_fn during metrics '
                'collection', log_output)

        # Test that exceptions in the unprotected metrics functions are caught.
        with mock.patch.object(MetricsCollector,
                               'GetCollector',
                               return_value='not a collector'):
            # These calls should all fail, but the exceptions shouldn't propagate up.
            metrics.Shutdown()
            metrics.LogCommandParams()
            metrics.LogRetryableError()
            metrics.LogFatalError()
            metrics.LogPerformanceSummary()
            metrics.CheckAndMaybePromptForAnalyticsEnabling('invalid argument')
            with open(self.log_handler_file) as f:
                log_output = f.read()
                self.assertIn(
                    'Exception captured in Shutdown during metrics collection',
                    log_output)
                self.assertIn(
                    'Exception captured in LogCommandParams during metrics collection',
                    log_output)
                self.assertIn(
                    'Exception captured in LogRetryableError during metrics collection',
                    log_output)
                self.assertIn(
                    'Exception captured in LogFatalError during metrics collection',
                    log_output)
                self.assertIn(
                    'Exception captured in LogPerformanceSummary during metrics '
                    'collection', log_output)
                self.assertIn(
                    'Exception captured in CheckAndMaybePromptForAnalyticsEnabling '
                    'during metrics collection', log_output)
        self.root_logger.setLevel(original_log_level)
Example #3
0
  def testExceptionCatchingDecorator(self):
    """Tests the exception catching decorator CaptureAndLogException."""

    # A wrapped function with an exception should not stop the process.
    mock_exc_fn = mock.MagicMock(__name__='mock_exc_fn',
                                 side_effect=Exception())
    wrapped_fn = metrics.CaptureAndLogException(mock_exc_fn)
    wrapped_fn()

    debug_messages = self.log_handler.messages['debug']
    self.assertIn('Exception captured in mock_exc_fn during metrics collection',
                  debug_messages[0])
    self.log_handler.reset()

    self.assertEqual(1, mock_exc_fn.call_count)

    mock_err_fn = mock.MagicMock(__name__='mock_err_fn',
                                 side_effect=TypeError())
    wrapped_fn = metrics.CaptureAndLogException(mock_err_fn)
    wrapped_fn()
    self.assertEqual(1, mock_err_fn.call_count)

    debug_messages = self.log_handler.messages['debug']
    self.assertIn('Exception captured in mock_err_fn during metrics collection',
                  debug_messages[0])
    self.log_handler.reset()

    # Test that exceptions in the unprotected metrics functions are caught.
    with mock.patch.object(MetricsCollector, 'GetCollector',
                           return_value='not a collector'):
      # These calls should all fail, but the exceptions shouldn't propagate up.
      metrics.Shutdown()
      metrics.LogCommandParams()
      metrics.LogRetryableError()
      metrics.LogFatalError()
      metrics.LogPerformanceSummaryParams()
      metrics.CheckAndMaybePromptForAnalyticsEnabling('invalid argument')

      debug_messages = self.log_handler.messages['debug']
      message_index = 0
      for func_name in ('Shutdown', 'LogCommandParams', 'LogRetryableError',
                        'LogFatalError', 'LogPerformanceSummaryParams',
                        'CheckAndMaybePromptForAnalyticsEnabling'):
        self.assertIn(
            'Exception captured in %s during metrics collection' % func_name,
            debug_messages[message_index])
        message_index += 1

      self.log_handler.reset()
Example #4
0
def MultithreadedMainSignalHandler(signal_num, cur_stack_frame):
  """Final signal handler for multi-threaded main process."""
  if signal_num == signal.SIGINT:
    if logging.getLogger().isEnabledFor(logging.DEBUG):
      stack_trace = ''.join(traceback.format_list(traceback.extract_stack()))
      err = ('DEBUG: Caught CTRL-C (signal %d) - Exception stack trace:\n'
             '    %s' % (signal_num, re.sub('\\n', '\n    ', stack_trace)))
      try:
        sys.stderr.write(err.encode(UTF8))
      except UnicodeDecodeError:
        # Can happen when outputting invalid Unicode filenames.
        sys.stderr.write(err)
    else:
      sys.stderr.write('Caught CTRL-C (signal %d) - exiting\n' % signal_num)

  metrics.LogFatalError(exception=ControlCException())
  metrics.Shutdown()
  KillProcess(os.getpid())