def test_value_error_raises_system_exit(self, mocked_glbl_cfg): """Test that a ValueError when writing to a log stream won't result in multiple exceptions (what could lead to infinite loop in some occasions. Instead, it **must** raise a SystemExit""" with tempfile.NamedTemporaryFile() as tf: # mock objects used when creating the file handler mocked = mock.MagicMock() mocked_glbl_cfg.return_value = mocked mocked.get_derived_host_item.return_value = tf.name mocked.get.return_value = 100 file_handler = TimestampRotatingFileHandler("suiteA", False) # next line is important as pytest can have a "Bad file descriptor" # due to a FileHandler with default "a" (pytest tries to r/w). file_handler.mode = "a+" # enable the logger LOG.setLevel(logging.INFO) LOG.addHandler(file_handler) # Disable raising uncaught exceptions in logging, due to file # handler using stdin.fileno. See the following links for more. # https://github.com/pytest-dev/pytest/issues/2276 & # https://github.com/pytest-dev/pytest/issues/1585 logging.raiseExceptions = False # first message will initialize the stream and the handler LOG.info("What could go") # here we change the stream of the handler old_stream = file_handler.stream file_handler.stream = mock.MagicMock() file_handler.stream.seek = mock.MagicMock() # in case where file_handler.stream.seek.side_effect = ValueError try: # next call will call the emit method and use the mocked stream LOG.info("wrong?!") self.fail("Exception SystemError was not raised") except SystemExit: pass finally: # clean up file_handler.stream = old_stream # for log_handler in LOG.handlers: # log_handler.close() file_handler.close() LOG.removeHandler(file_handler) logging.raiseExceptions = True
def parse_args(self, remove_opts=None): """Parse options and arguments, overrides OptionParser.parse_args.""" if self.auto_add: # Add common options after command-specific options. self.add_std_options() if remove_opts: for opt in remove_opts: try: self.remove_option(opt) except ValueError: pass (options, args) = OptionParser.parse_args(self) if len(args) < self.n_compulsory_args: self.error("Wrong number of arguments (too few)") elif not self.unlimited_args and \ len(args) > self.n_compulsory_args + self.n_optional_args: self.error("Wrong number of arguments (too many)") if self.jset: if options.templatevars_file: options.templatevars_file = os.path.abspath(os.path.expanduser( options.templatevars_file)) cylc.flags.verbose = options.verbose cylc.flags.debug = options.debug # Set up stream logging for CLI. Note: # 1. On choosing STDERR: Log messages are diagnostics, so STDERR is the # better choice for the logging stream. This allows us to use STDOUT # for verbosity agnostic outputs. # 2. Suite server programs will remove this handler when it becomes a # daemon. if options.debug or options.verbose: LOG.setLevel(logging.DEBUG) else: LOG.setLevel(logging.INFO) # Remove NullHandler before add the StreamHandler while LOG.handlers: LOG.handlers[0].close() LOG.removeHandler(LOG.handlers[0]) errhandler = logging.StreamHandler(sys.stderr) errhandler.setFormatter(CylcLogFormatter()) LOG.addHandler(errhandler) return (options, args)
def parse_args(self, remove_opts=None): """Parse options and arguments, overrides OptionParser.parse_args.""" if self.auto_add: # Add common options after command-specific options. self.add_std_options() if remove_opts: for opt in remove_opts: try: self.remove_option(opt) except ValueError: pass (options, args) = OptionParser.parse_args(self) if len(args) < self.n_compulsory_args: self.error("Wrong number of arguments (too few)") elif not self.unlimited_args and \ len(args) > self.n_compulsory_args + self.n_optional_args: self.error("Wrong number of arguments (too many)") if self.jset: if options.templatevars_file: options.templatevars_file = os.path.abspath( os.path.expanduser(options.templatevars_file)) cylc.flags.verbose = options.verbose cylc.flags.debug = options.debug # Set up stream logging if options.debug or options.verbose: LOG.setLevel(logging.DEBUG) else: LOG.setLevel(logging.INFO) errhandler = logging.StreamHandler(sys.stderr) errhandler.setFormatter(CylcLogFormatter()) LOG.addHandler(errhandler) return (options, args)