#!/usr/bin/python3

import logging, os, sys, unittest
from six.moves import StringIO

# direct imports; autotest_lib has not been setup while testing this.
from client.common_lib.test_utils import mock
from client import setup_modules


class LoggingErrorStderrTests(unittest.TestCase):
    """Test the setup_modules."""

    def setUp(self):
        autotest_dir = os.path.abspath(os.path.join(setup_modules.dirname,
                                                    '..'))
        setup_modules.setup(autotest_dir, root_module_name='autotest_lib')
        self.god = mock.mock_god()
        self.test_stderr = StringIO()
        self.god.stub_with(sys, 'stderr', self.test_stderr)
        self.old_root_logging_level = logging.root.level
        logging.basicConfig(level=logging.ERROR)
        # _autotest_logging_handle_error unsets this after being called once.
        logging.raiseExceptions = 1

    def tearDown(self):
        self.god.unstub_all()
        # Undo the setUp logging.basicConfig call.
        logging.basicConfig(level=self.old_root_logging_level)

    def assert_autotest_logging_handle_error_called(self):
        self.stderr_str = self.test_stderr.getvalue()
        self.assertTrue('Exception occurred formatting' in self.stderr_str,
                        repr(self.stderr_str))

    def test_autotest_logging_handle_error(self):
        record = logging.LogRecord(
                'test', logging.DEBUG, __file__, 0, 'MESSAGE', 'ARGS', None)
        try:
            raise RuntimeError('Exception context needed for the test.')
        except RuntimeError:
            setup_modules._autotest_logging_handle_error(logging.Handler(),
                                                         record)
        else:
            self.fail()
        self.assert_autotest_logging_handle_error_called()
        stderr_repr = repr(self.stderr_str)
        self.assertTrue(('MESSAGE' in self.stderr_str), stderr_repr)
        self.assertTrue(('ARGS' in self.stderr_str), stderr_repr)
        self.assertTrue(('Exception' in self.stderr_str), stderr_repr)
        self.assertTrue(('setup_modules_unittest.py' in self.stderr_str),
                        stderr_repr)
        self.assertTrue(('disabled.\n' in self.stderr_str), stderr_repr)
        # Make sure this was turned off by our handle_error.
        self.assertFalse(logging.raiseExceptions)

    def test_logging_monkey_patch_wrong_number_of_args(self):
        logging.error('logging unittest %d %s', 32)
        self.assert_autotest_logging_handle_error_called()
        self.assertTrue('logging unittest' in self.stderr_str,
                        repr(self.stderr_str))

    def test_logging_monkey_patch_wrong_type_of_arg(self):
        logging.error('logging unittest %d', 'eighteen')
        self.assert_autotest_logging_handle_error_called()
        self.assertTrue('logging unittest' in self.stderr_str,
                        repr(self.stderr_str))

    def test_logging_no_error(self):
        logging.error('logging unittest.  %s %s', 'meep', 'meep!')
        self.assertEqual('', self.test_stderr.getvalue())


if __name__ == "__main__":
    unittest.main()
