示例#1
0
    def setUp(self) -> None:
        self.handler = AdminZulipHandler()
        # Prevent the exceptions we're going to raise from being printed
        # You may want to disable this when debugging tests
        settings.LOGGING_NOT_DISABLED = False

        global captured_exc_info
        global captured_request
        captured_request = None
        captured_exc_info = None
    def setUp(self):
        # type: () -> None
        self.handler = AdminZulipHandler()
        # Prevent the exceptions we're going to raise from being printed
        # You may want to disable this when debugging tests
        settings.LOGGING_NOT_DISABLED = False

        global captured_exc_info
        global captured_request
        captured_request = None
        captured_exc_info = None
示例#3
0
class AdminZulipHandlerTest(ZulipTestCase):
    logger = logging.getLogger('django')

    def setUp(self):
        # type: () -> None
        self.handler = AdminZulipHandler()
        # Prevent the exceptions we're going to raise from being printed
        # You may want to disable this when debugging tests
        settings.LOGGING_NOT_DISABLED = False

        global captured_exc_info
        global captured_request
        captured_request = None
        captured_exc_info = None

    def tearDown(self):
        # type: () -> None
        settings.LOGGING_NOT_DISABLED = True

    def get_admin_zulip_handler(self):
        # type: () -> AdminZulipHandler
        return [
            h for h in logging.getLogger('').handlers
            if isinstance(h, AdminZulipHandler)
        ][0]

    def test_basic(self):
        # type: () -> None
        """A random exception passes happily through AdminZulipHandler"""
        handler = self.get_admin_zulip_handler()
        try:
            raise Exception("Testing Error!")
        except Exception:
            exc_info = sys.exc_info()
        record = self.logger.makeRecord('name', logging.ERROR, 'function', 16,
                                        'message', {}, exc_info)
        handler.emit(record)

    def run_handler(self, record):
        # type: (logging.LogRecord) -> Dict[str, Any]
        with patch('zerver.logging_handlers.queue_json_publish'
                   ) as patched_publish:
            self.handler.emit(record)
            patched_publish.assert_called_once()
            event = patched_publish.call_args[0][1]
            self.assertIn("report", event)
            return event["report"]

    def test_long_exception_request(self):
        # type: () -> None
        """A request with with no stack where report.getMessage() has newlines
        in it is handled properly"""
        email = self.example_email('hamlet')
        self.login(email)
        with patch("zerver.decorator.rate_limit") as rate_limit_patch:
            rate_limit_patch.side_effect = capture_and_throw
            result = self.client_get("/json/users")
            self.assert_json_error(result,
                                   "Internal server error",
                                   status_code=500)
            rate_limit_patch.assert_called_once()

            global captured_request
            global captured_exc_info
            record = self.logger.makeRecord('name', logging.ERROR, 'function',
                                            15, 'message\nmoremesssage\nmore',
                                            {}, None)
            record.request = captured_request  # type: ignore # this field is dynamically added

            report = self.run_handler(record)
            self.assertIn("user_email", report)
            self.assertIn("message", report)
            self.assertIn("stack_trace", report)
            self.assertEqual(report['stack_trace'],
                             'message\nmoremesssage\nmore')
            self.assertEqual(report['message'], 'message')

    def test_request(self):
        # type: () -> None
        """A normal request is handled properly"""
        email = self.example_email('hamlet')
        self.login(email)
        with patch("zerver.decorator.rate_limit") as rate_limit_patch:
            rate_limit_patch.side_effect = capture_and_throw
            result = self.client_get("/json/users")
            self.assert_json_error(result,
                                   "Internal server error",
                                   status_code=500)
            rate_limit_patch.assert_called_once()

            global captured_request
            global captured_exc_info
            record = self.logger.makeRecord('name', logging.ERROR, 'function',
                                            15, 'message', {},
                                            captured_exc_info)
            record.request = captured_request  # type: ignore # this field is dynamically added

            report = self.run_handler(record)
            self.assertIn("user_email", report)
            self.assertIn("message", report)
            self.assertIn("stack_trace", report)

            # Test that `add_request_metadata` throwing an exception is fine
            with patch("zerver.logging_handlers.traceback.print_exc"):
                with patch("zerver.logging_handlers.add_request_metadata",
                           side_effect=Exception("Unexpected exception!")):
                    report = self.run_handler(record)
            self.assertNotIn("user_email", report)
            self.assertIn("message", report)
            self.assertEqual(report["stack_trace"],
                             "See /var/log/zulip/errors.log")

            # Check anonymous user is handled correctly
            record.request.user = AnonymousUser(
            )  # type: ignore # this field is dynamically added
            report = self.run_handler(record)
            self.assertIn("host", report)
            self.assertIn("user_email", report)
            self.assertIn("message", report)
            self.assertIn("stack_trace", report)

            # Now simulate a DisallowedHost exception
            def get_host_error():
                # type: () -> None
                raise Exception("Get Host Failure!")

            orig_get_host = record.request.get_host  # type: ignore # this field is dynamically added
            record.request.get_host = get_host_error  # type: ignore # this field is dynamically added
            report = self.run_handler(record)
            record.request.get_host = orig_get_host  # type: ignore # this field is dynamically added
            self.assertIn("host", report)
            self.assertIn("user_email", report)
            self.assertIn("message", report)
            self.assertIn("stack_trace", report)

            # Test an exception_filter exception
            with patch("zerver.logging_handlers.get_exception_reporter_filter",
                       return_value=15):
                record.request.method = "POST"  # type: ignore # this field is dynamically added
                report = self.run_handler(record)
                record.request.method = "GET"  # type: ignore # this field is dynamically added
            self.assertIn("host", report)
            self.assertIn("user_email", report)
            self.assertIn("message", report)
            self.assertIn("stack_trace", report)

            # Test the catch-all exception handler doesn't throw
            with patch('zerver.logging_handlers.queue_json_publish',
                       side_effect=Exception("queue error")):
                self.handler.emit(record)

            # Test the STAGING_ERROR_NOTIFICATIONS code path
            with self.settings(STAGING_ERROR_NOTIFICATIONS=True):
                with patch('zerver.lib.error_notify.notify_server_error',
                           side_effect=Exception("queue error")):
                    self.handler.emit(record)

            # Test no exc_info
            record.exc_info = None
            report = self.run_handler(record)
            self.assertIn("host", report)
            self.assertIn("user_email", report)
            self.assertIn("message", report)
            self.assertEqual(report["stack_trace"], None)

            # Test arbitrary exceptions from request.user
            record.request.user = None  # type: ignore # this field is dynamically added
            with patch("zerver.logging_handlers.traceback.print_exc"):
                report = self.run_handler(record)
            self.assertIn("host", report)
            self.assertIn("user_email", report)
            self.assertIn("message", report)
            self.assertIn("stack_trace", report)
class AdminZulipHandlerTest(ZulipTestCase):
    logger = logging.getLogger('django')

    def setUp(self):
        # type: () -> None
        self.handler = AdminZulipHandler()
        # Prevent the exceptions we're going to raise from being printed
        # You may want to disable this when debugging tests
        settings.LOGGING_NOT_DISABLED = False

        global captured_exc_info
        global captured_request
        captured_request = None
        captured_exc_info = None

    def tearDown(self):
        # type: () -> None
        settings.LOGGING_NOT_DISABLED = True

    def get_admin_zulip_handler(self):
        # type: () -> Any
        return [
            h for h in logging.getLogger('').handlers
            if h.__class__.__name__ == "AdminZulipHandler"
        ][0]

    def test_basic(self):
        # type: () -> None
        """A random exception passes happily through AdminZulipHandler"""
        handler = self.get_admin_zulip_handler()
        try:
            raise Exception("Testing Error!")
        except Exception:
            exc_info = sys.exc_info()
        record = self.logger.makeRecord('name', logging.ERROR, 'function', 16,
                                        'message', {}, exc_info)
        handler.emit(record)

    def run_handler(self, record):
        # type: (logging.LogRecord) -> Dict[str, Any]
        with patch('zerver.logging_handlers.queue_json_publish') as patched_publish:
            self.handler.emit(record)
            patched_publish.assert_called_once()
            event = patched_publish.call_args[0][1]
            self.assertIn("report", event)
            return event["report"]

    def test_long_exception_request(self):
        # type: () -> None
        """A request with with no stack where report.getMessage() has newlines
        in it is handled properly"""
        email = self.example_email('hamlet')
        self.login(email)
        with patch("zerver.decorator.rate_limit") as rate_limit_patch:
            rate_limit_patch.side_effect = capture_and_throw
            result = self.client_get("/json/users")
            self.assert_json_error(result, "Internal server error", status_code=500)
            rate_limit_patch.assert_called_once()

            global captured_request
            global captured_exc_info
            record = self.logger.makeRecord('name', logging.ERROR, 'function', 15,
                                            'message\nmoremesssage\nmore', {},
                                            None)
            record.request = captured_request  # type: ignore # this field is dynamically added

            report = self.run_handler(record)
            self.assertIn("user_email", report)
            self.assertIn("message", report)
            self.assertIn("stack_trace", report)
            self.assertEqual(report['stack_trace'], 'message\nmoremesssage\nmore')
            self.assertEqual(report['message'], 'message')

    def test_request(self):
        # type: () -> None
        """A normal request is handled properly"""
        email = self.example_email('hamlet')
        self.login(email)
        with patch("zerver.decorator.rate_limit") as rate_limit_patch:
            rate_limit_patch.side_effect = capture_and_throw
            result = self.client_get("/json/users")
            self.assert_json_error(result, "Internal server error", status_code=500)
            rate_limit_patch.assert_called_once()

            global captured_request
            global captured_exc_info
            record = self.logger.makeRecord('name', logging.ERROR, 'function', 15,
                                            'message', {}, captured_exc_info)
            record.request = captured_request  # type: ignore # this field is dynamically added

            report = self.run_handler(record)
            self.assertIn("user_email", report)
            self.assertIn("message", report)
            self.assertIn("stack_trace", report)

            # Test that `add_request_metadata` throwing an exception is fine
            with patch("zerver.logging_handlers.traceback.print_exc"):
                with patch("zerver.logging_handlers.add_request_metadata",
                           side_effect=Exception("Unexpected exception!")):
                    report = self.run_handler(record)
            self.assertNotIn("user_email", report)
            self.assertIn("message", report)
            self.assertEqual(report["stack_trace"], "See /var/log/zulip/errors.log")

            # Check anonymous user is handled correctly
            record.request.user = AnonymousUser()  # type: ignore # this field is dynamically added
            report = self.run_handler(record)
            self.assertIn("host", report)
            self.assertIn("user_email", report)
            self.assertIn("message", report)
            self.assertIn("stack_trace", report)

            # Now simulate a DisallowedHost exception
            def get_host_error():
                # type: () -> None
                raise Exception("Get Host Failure!")
            orig_get_host = record.request.get_host  # type: ignore # this field is dynamically added
            record.request.get_host = get_host_error  # type: ignore # this field is dynamically added
            report = self.run_handler(record)
            record.request.get_host = orig_get_host  # type: ignore # this field is dynamically added
            self.assertIn("host", report)
            self.assertIn("user_email", report)
            self.assertIn("message", report)
            self.assertIn("stack_trace", report)

            # Test an exception_filter exception
            with patch("zerver.logging_handlers.get_exception_reporter_filter",
                       return_value=15):
                record.request.method = "POST"  # type: ignore # this field is dynamically added
                report = self.run_handler(record)
                record.request.method = "GET"  # type: ignore # this field is dynamically added
            self.assertIn("host", report)
            self.assertIn("user_email", report)
            self.assertIn("message", report)
            self.assertIn("stack_trace", report)

            # Test the catch-all exception handler doesn't throw
            with patch('zerver.logging_handlers.queue_json_publish',
                       side_effect=Exception("queue error")):
                self.handler.emit(record)

            # Test the STAGING_ERROR_NOTIFICATIONS code path
            with self.settings(STAGING_ERROR_NOTIFICATIONS=True):
                with patch('zerver.lib.error_notify.notify_server_error',
                           side_effect=Exception("queue error")):
                    self.handler.emit(record)

            # Test no exc_info
            record.exc_info = None
            report = self.run_handler(record)
            self.assertIn("host", report)
            self.assertIn("user_email", report)
            self.assertIn("message", report)
            self.assertEqual(report["stack_trace"], None)

            # Test arbitrary exceptions from request.user
            record.request.user = None  # type: ignore # this field is dynamically added
            with patch("zerver.logging_handlers.traceback.print_exc"):
                report = self.run_handler(record)
            self.assertIn("host", report)
            self.assertIn("user_email", report)
            self.assertIn("message", report)
            self.assertIn("stack_trace", report)