def test_touch(self): """Test :func:`humanfriendly.testing.touch()`.""" with TemporaryDirectory() as directory: # Create a file in the temporary directory. filename = os.path.join(directory, random_string()) assert not os.path.isfile(filename) touch(filename) assert os.path.isfile(filename) # Create a file in a subdirectory. filename = os.path.join(directory, random_string(), random_string()) assert not os.path.isfile(filename) touch(filename) assert os.path.isfile(filename)
def test_syslog_shortcut_enhanced(self): """Make sure that ``coloredlogs.install(syslog='warning')`` works.""" system_log_file = self.find_system_log() the_expected_message = random_string(50) not_an_expected_message = random_string(50) with cleanup_handlers(): # See test_system_logging() for the importance of these log levels. coloredlogs.install(syslog='error') logging.warning("%s", not_an_expected_message) logging.error("%s", the_expected_message) # See the comments in test_system_logging() on why this is retried. retry(lambda: check_contents(system_log_file, the_expected_message, True)) retry(lambda: check_contents(system_log_file, not_an_expected_message, False))
def get_logger_tree(self): """Create and return a tree of loggers.""" # Get the root logger. root = logging.getLogger() # Create a top level logger for ourselves. parent_name = random_string() parent = logging.getLogger(parent_name) # Create a child logger. child_name = '%s.%s' % (parent_name, random_string()) child = logging.getLogger(child_name) # Create a grand child logger. grand_child_name = '%s.%s' % (child_name, random_string()) grand_child = logging.getLogger(grand_child_name) return root, parent, child, grand_child
def test_plain_text_output_format(self): """Inspect the plain text output of colouredlogs.""" logger = VerboseLogger(random_string(25)) stream = StringIO() install(level=logging.NOTSET, logger=logger, stream=stream) # Test that filtering on severity works. logger.setLevel(logging.INFO) logger.debug("No one should see this message.") assert len(stream.getvalue().strip()) == 0 # Test that the default output format looks okay in plain text. logger.setLevel(logging.NOTSET) for method, severity in ((logger.debug, 'DEBUG'), (logger.info, 'INFO'), (logger.verbose, 'VERBOSE'), (logger.warning, 'WARNING'), (logger.error, 'ERROR'), (logger.critical, 'CRITICAL')): # Prepare the text. text = "This is a message with severity %r." % severity.lower() # Log the message with the given severity. method(text) # Get the line of output generated by the handler. output = stream.getvalue() lines = output.splitlines() last_line = lines[-1] assert text in last_line assert severity in last_line assert PLAIN_TEXT_PATTERN.match(last_line)
def test_plain_text_output_format(self): """Inspect the plain text output of coloredlogs.""" logger = VerboseLogger(random_string(25)) stream = StringIO() install(level=logging.NOTSET, logger=logger, stream=stream) # Test that filtering on severity works. logger.setLevel(logging.INFO) logger.debug("No one should see this message.") assert len(stream.getvalue().strip()) == 0 # Test that the default output format looks okay in plain text. logger.setLevel(logging.NOTSET) for method, severity in ((logger.debug, 'DEBUG'), (logger.info, 'INFO'), (logger.verbose, 'VERBOSE'), (logger.warning, 'WARNING'), (logger.error, 'ERROR'), (logger.critical, 'CRITICAL')): # Prepare the text. text = "This is a message with severity %r." % severity.lower() # Log the message with the given severity. method(text) # Get the line of output generated by the handler. output = stream.getvalue() lines = output.splitlines() last_line = lines[-1] assert text in last_line assert severity in last_line assert PLAIN_TEXT_PATTERN.match(last_line)
def test_mocked_program(self): """Test :class:`humanfriendly.testing.MockedProgram`.""" name = random_string() with MockedProgram(name=name, returncode=42) as directory: assert os.path.isdir(directory) assert os.path.isfile(os.path.join(directory, name)) assert subprocess.call(name) == 42
def test_syslog_shortcut_simple(self): """Make sure that ``coloredlogs.install(syslog=True)`` works.""" system_log_file = self.find_system_log() expected_message = random_string(50) with cleanup_handlers(): # See test_system_logging() for the importance of this log level. coloredlogs.install(syslog=True) logging.error("%s", expected_message) # See the comments in test_system_logging() on why this is retried. retry(lambda: check_contents(system_log_file, expected_message, True))
def __enter__(self): """ Create the mock program. :returns: The pathname of the directory that has been added to ``$PATH`` (a string). """ directory = super(MockedProgram, self).__enter__() self.program_signal_file = os.path.join(directory, 'program-was-run-%s' % random_string(10)) pathname = os.path.join(directory, self.program_name) with open(pathname, 'w') as handle: handle.write('#!/bin/sh\n') handle.write('echo > %s\n' % pipes.quote(self.program_signal_file)) handle.write('exit %i\n' % self.program_returncode) os.chmod(pathname, 0o755) return directory
def test_auto_install(self): """Test :func:`coloredlogs.auto_install()`.""" needle = random_string() command_line = [sys.executable, '-c', 'import logging; logging.info(%r)' % needle] # Sanity check that log messages aren't enabled by default. with CaptureOutput() as capturer: os.environ['COLOREDLOGS_AUTO_INSTALL'] = 'false' subprocess.check_call(command_line) output = capturer.get_text() assert needle not in output # Test that the $COLOREDLOGS_AUTO_INSTALL environment variable can be # used to automatically call coloredlogs.install() during initialization. with CaptureOutput() as capturer: os.environ['COLOREDLOGS_AUTO_INSTALL'] = 'true' subprocess.check_call(command_line) output = capturer.get_text() assert needle in output
def test_system_logging(self): """Make sure the :class:`coloredlogs.syslog.SystemLogging` context manager works.""" system_log_file = self.find_system_log() expected_message = random_string(50) with SystemLogging(programname='coloredlogs-test-suite') as syslog: if not syslog: return self.skipTest("couldn't connect to syslog daemon") # When I tried out the system logging support on macOS 10.13.1 on # 2018-01-05 I found that while WARNING and ERROR messages show up # in the system log DEBUG and INFO messages don't. This explains # the importance of the level of the log message below. logging.error("%s", expected_message) # Retry the following assertion (for up to 60 seconds) to give the # logging daemon time to write our log message to disk. This # appears to be needed on MacOS workers on Travis CI, see: # https://travis-ci.org/xolox/python-coloredlogs/jobs/325245853 retry(lambda: check_contents(system_log_file, expected_message, True))
def test_auto_install(self): """Test :func:`coloredlogs.auto_install()`.""" needle = random_string() command_line = [sys.executable, '-c', 'import logging; logging.info(%r)' % needle] # Sanity check that log messages aren't enabled by default. with CaptureOutput() as capturer: os.environ['COLOREDLOGS_AUTO_INSTALL'] = 'false' subprocess.call(command_line) output = capturer.get_text() assert needle not in output # Test that the $COLOREDLOGS_AUTO_INSTALL environment variable can be # used to automatically call coloredlogs.install() during initialization. with CaptureOutput() as capturer: os.environ['COLOREDLOGS_AUTO_INSTALL'] = 'true' subprocess.call(command_line) output = capturer.get_text() assert needle in output
def test_show_pager(self): """Test :func:`humanfriendly.terminal.show_pager()`.""" original_pager = os.environ.get('PAGER', None) try: # We specifically avoid `less' because it would become awkward to # run the test suite in an interactive terminal :-). os.environ['PAGER'] = 'cat' # Generate a significant amount of random text spread over multiple # lines that we expect to be reported literally on the terminal. random_text = "\n".join(random_string(25) for i in range(50)) # Run the pager command and validate the output. with CaptureOutput() as capturer: show_pager(random_text) assert random_text in capturer.get_text() finally: if original_pager is not None: # Restore the original $PAGER value. os.environ['PAGER'] = original_pager else: # Clear the custom $PAGER value. os.environ.pop('PAGER')
def test_plain_text_output_format(self): """Inspect the plain text output of coloredlogs.""" logger = VerboseLogger(random_string(25)) stream = StringIO() install(level=logging.NOTSET, logger=logger, stream=stream) # Test that filtering on severity works. logger.setLevel(logging.INFO) logger.debug("No one should see this message.") assert len(stream.getvalue().strip()) == 0 # Test that the default output format looks okay in plain text. logger.setLevel(logging.NOTSET) for method, severity in ((logger.debug, 'DEBUG'), (logger.info, 'INFO'), (logger.verbose, 'VERBOSE'), (logger.warning, 'WARNING'), (logger.error, 'ERROR'), (logger.critical, 'CRITICAL')): # XXX Workaround for a regression in Python 3.7 caused by the # Logger.isEnabledFor() method using stale cache entries. If we # don't clear the cache then logger.isEnabledFor(logging.DEBUG) # returns False and no DEBUG message is emitted. try: logger._cache.clear() except AttributeError: pass # Prepare the text. text = "This is a message with severity %r." % severity.lower() # Log the message with the given severity. method(text) # Get the line of output generated by the handler. output = stream.getvalue() lines = output.splitlines() last_line = lines[-1] assert text in last_line assert severity in last_line assert PLAIN_TEXT_PATTERN.match(last_line)
def test_run_cli_intercepts_output(self): """Test that run_cli() intercepts output.""" expected_output = random_string() + "\n" returncode, output = run_cli(lambda: sys.stdout.write(expected_output)) self.assertEqual(returncode, 0) self.assertEqual(output, expected_output)