def test_validate_styles_raises_when_no_location_exists(self, *_): """Tests that a style is invalid if it does not contain a log level. If the style does not contain a log level, then there is no way to pass the information coming from the logger to the correct file. """ with self.assertRaises(InvalidStyleSetError) as catch: log_stream.create_logger(self._testMethodName, log_styles=[LogStyles.LOG_INFO]) self.assertTrue( 'log location' in catch.exception.args[0], msg='__validate_styles did not raise the expected error message')
def test_cleanup_removes_all_handlers(self, *_): """ Tests that cleanup removes all handlers in the logger, except the NullHandler. """ info_testcase_log = LogStyles.LOG_INFO + LogStyles.MONOLITH_LOG with self.patch('MovableFileHandler'): log_stream.create_logger(self._testMethodName, log_styles=info_testcase_log) created_log_stream = log_stream._log_streams[self._testMethodName] created_log_stream.cleanup() self.assertEqual(len(created_log_stream.logger.handlers), 1)
def test_create_handler_creates_handler_at_correct_path(self, *_): """Tests that __create_handler calls the handler creator with the correct absolute path to the log file. """ info_monolith_log = LogStyles.LOG_INFO + LogStyles.MONOLITH_LOG base_path = 'BASEPATH' with self.patch('MovableFileHandler') as file_handler: log_stream.create_logger( self._testMethodName, log_styles=info_monolith_log, base_path=base_path) expected = os.path.join( base_path, '%s_%s.txt' % (self._testMethodName, 'info')) file_handler.assert_called_with(expected)
def test_validate_styles_raises_when_same_location_set_multiple_times( self, *_): """Tests that a style is invalid if it sets the same handler twice. If the error is NOT raised, then a LogStream can create a Logger that has multiple LogHandlers trying to write to the same file. """ with self.assertRaises(InvalidStyleSetError) as catch: log_stream.create_logger( self._testMethodName, log_styles=[LogStyles.LOG_DEBUG | LogStyles.MONOLITH_LOG, LogStyles.LOG_DEBUG | LogStyles.MONOLITH_LOG]) self.assertTrue( 'has been set multiple' in catch.exception.args[0], msg='__validate_styles did not raise the expected error message')
def start_syslog(serial, base_path, ip_address, ssh_username, ssh_config, extra_params=''): """Creates a FuchsiaSyslogProcess that automatically attempts to reconnect. Args: serial: The unique identifier for the device. base_path: The base directory used for syslog file output. ip_address: The ip address of the device to get the syslog. ssh_username: Username for the device for the Fuchsia Device. ssh_config: Location of the ssh_config for connecting to the remote device extra_params: Any additional params to be added to the syslog cmdline. Returns: A FuchsiaSyslogProcess object. """ logger = log_stream.create_logger('fuchsia_log_%s' % serial, base_path=base_path, log_styles=(LogStyles.LOG_DEBUG | LogStyles.MONOLITH_LOG)) syslog = FuchsiaSyslogProcess(ssh_username, ssh_config, ip_address, extra_params) timestamp_tracker = TimestampTracker() syslog.set_on_output_callback(_log_line_func(logger, timestamp_tracker)) return syslog
def _setup_test_logger(log_path, prefix=None): """Customizes the root logger for a test run. The logger object has a stream handler and a file handler. The stream handler logs INFO level to the terminal, the file handler logs DEBUG level to files. Args: log_path: Location of the log file. prefix: A prefix for each log line in terminal. """ logging.log_path = log_path log_styles = [ LogStyles.LOG_INFO + LogStyles.TO_STDOUT, LogStyles.DEFAULT_LEVELS + LogStyles.TESTCASE_LOG ] terminal_format = log_line_format if prefix: terminal_format = "[{}] {}".format(prefix, log_line_format) stream_formatter = ColoredLogFormatter(terminal_format, log_line_time_format) file_formatter = logging.Formatter(log_line_format, log_line_time_format) log = log_stream.create_logger('test_run', '', log_styles=log_styles, stream_format=stream_formatter, file_format=file_formatter) log.setLevel(logging.DEBUG) _enable_additional_log_levels()
def test_handle_style_to_stdout_creates_stream_handler(self, *_): """Tests that using the flag TO_STDOUT creates a StreamHandler.""" info_acts_log = LogStyles.LOG_INFO + LogStyles.TO_STDOUT log = log_stream.create_logger(self._testMethodName, log_styles=info_acts_log) self.assertTrue(isinstance(log.handlers[1], logging.StreamHandler))
def test_handle_style_to_acts_log_creates_handler(self, *_): """Tests that using the flag TO_ACTS_LOG creates an AlsoToLogHandler.""" info_acts_log = LogStyles.LOG_INFO + LogStyles.TO_ACTS_LOG log = log_stream.create_logger(self._testMethodName, log_styles=info_acts_log) self.assertTrue(isinstance(log.handlers[1], AlsoToLogHandler))
def test_validate_styles_raises_when_rotate_logs_no_file_handler(self, *_): """Tests that a LogStyle cannot set ROTATE_LOGS without *_LOG flag. If the LogStyle contains ROTATE_LOGS, it must be associated with a log that is rotatable. TO_ACTS_LOG and TO_STDOUT are not rotatable logs, since those are both controlled by another object/process. The user must specify MONOLITHIC_LOG or TESTCASE_LOG. """ with self.assertRaises(InvalidStyleSetError) as catch: log_stream.create_logger( self._testMethodName, # Added LOG_DEBUG here to prevent the no_level_exists raise from # occurring. log_styles=[LogStyles.LOG_DEBUG + LogStyles.ROTATE_LOGS]) self.assertTrue( 'log type' in catch.exception.args[0], msg='__validate_styles did not raise the expected error message')
def test_handle_style_creates_file_handler(self, *_): """Tests handle_style creates a MovableFileHandler for the MONOLITH_LOG.""" info_acts_log = LogStyles.LOG_INFO + LogStyles.MONOLITH_LOG expected = mock.MagicMock() with self.patch('MovableFileHandler', return_value=expected): log = log_stream.create_logger(self._testMethodName, log_styles=info_acts_log) self.assertEqual(log.handlers[1], expected)
def test_init_adds_null_handler(self, *_): """Tests that a NullHandler is added to the logger upon initialization. This ensures that no log output is generated when a test class is not running. """ debug_monolith_log = LogStyles.LOG_DEBUG | LogStyles.MONOLITH_LOG with self.patch('MovableFileHandler'): log = log_stream.create_logger(self._testMethodName, log_styles=debug_monolith_log) self.assertTrue(isinstance(log.handlers[0], logging.NullHandler))
def test_handle_style_to_acts_log_creates_handler_is_lowest_level(self, *_): """Tests that using the flag TO_ACTS_LOG creates an AlsoToLogHandler that is set to the lowest LogStyles level.""" info_acts_log = (LogStyles.LOG_DEBUG + LogStyles.LOG_INFO + LogStyles.TO_ACTS_LOG) log = log_stream.create_logger(self._testMethodName, log_styles=info_acts_log) self.assertTrue(isinstance(log.handlers[1], AlsoToLogHandler)) self.assertEqual(log.handlers[1].level, logging.DEBUG)
def test_validate_styles_raises_when_multiple_file_outputs_set(self, *_): """Tests that a style is invalid if more than one of MONOLITH_LOG, TESTCLASS_LOG, and TESTCASE_LOG is set for the same log level. If the error is NOT raised, then a LogStream can create a Logger that has multiple LogHandlers trying to write to the same file. """ with self.assertRaises(InvalidStyleSetError) as catch: log_stream.create_logger( self._testMethodName, log_styles=[LogStyles.LOG_DEBUG | LogStyles.TESTCASE_LOG, LogStyles.LOG_DEBUG | LogStyles.TESTCLASS_LOG]) self.assertTrue( 'More than one of' in catch.exception.args[0], msg='__validate_styles did not raise the expected error message') with self.assertRaises(InvalidStyleSetError) as catch: log_stream.create_logger( self._testMethodName, log_styles=[LogStyles.LOG_DEBUG | LogStyles.TESTCASE_LOG, LogStyles.LOG_DEBUG | LogStyles.MONOLITH_LOG]) self.assertTrue( 'More than one of' in catch.exception.args[0], msg='__validate_styles did not raise the expected error message') with self.assertRaises(InvalidStyleSetError) as catch: log_stream.create_logger( self._testMethodName, log_styles=[LogStyles.LOG_DEBUG | LogStyles.TESTCASE_LOG, LogStyles.LOG_DEBUG | LogStyles.TESTCLASS_LOG, LogStyles.LOG_DEBUG | LogStyles.MONOLITH_LOG]) self.assertTrue( 'More than one of' in catch.exception.args[0], msg='__validate_styles did not raise the expected error message')
def test_update_handlers_updates_filehandler_target(self, _): """Tests that update_handlers invokes the underlying MovableFileHandler.set_file method on the correct path. """ info_testclass_log = LogStyles.LOG_INFO + LogStyles.TESTCLASS_LOG file_name = 'FILENAME' with self.patch('MovableFileHandler'): log = log_stream.create_logger( self._testMethodName, log_styles=info_testclass_log) handler = log.handlers[-1] handler.baseFilename = file_name stream = log_stream._log_streams[log.name] stream._LogStream__get_current_output_dir = ( lambda: 'BASEPATH/TestClass' ) stream.update_handlers(context.NewTestClassContextEvent()) handler.set_file.assert_called_with('BASEPATH/TestClass/FILENAME')
def create_logcat_keepalive_process(serial, logcat_dir, extra_params=''): """Creates a Logcat Process that automatically attempts to reconnect. Args: serial: The serial of the device to read the logcat of. logcat_dir: The directory used for logcat file output. extra_params: Any additional params to be added to the logcat cmdline. Returns: A acts.libs.proc.process.Process object. """ logger = log_stream.create_logger( 'adblog_%s' % serial, log_name=serial, subcontext=logcat_dir, log_styles=(LogStyles.LOG_DEBUG | LogStyles.TESTCASE_LOG)) process = Process('adb -s %s logcat -T 1 -v year %s' % (serial, extra_params)) timestamp_tracker = TimestampTracker() process.set_on_output_callback(_log_line_func(logger, timestamp_tracker)) process.set_on_terminate_callback( _on_retry(serial, extra_params, timestamp_tracker)) return process