# Copyright 2016-2017 Versada # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import logging import sys import unittest import raven from odoo import exceptions from .. import initialize_raven from ..logutils import OdooSentryHandler def log_handler_by_class(logger, handler_cls): for handler in logger.handlers: if isinstance(handler, handler_cls): yield handler def remove_logging_handler(logger_name, handler_cls): """Removes handlers of specified classes from a :class:`logging.Logger` with a given name. :param string logger_name: name of the logger :param handler_cls: class of the handler to remove. You can pass a tuple of classes to catch several classes """ logger = logging.getLogger(logger_name) for handler in log_handler_by_class(logger, handler_cls): logger.removeHandler(handler) class InMemoryClient(raven.Client): """A :class:`raven.Client` subclass which simply stores events in a list. Extended based on the one found in raven-python to avoid additional testing dependencies: https://git.io/vyGO3 """ def __init__(self, **kwargs): self.events = [] super(InMemoryClient, self).__init__(**kwargs) def is_enabled(self): return True def send(self, **kwargs): self.events.append(kwargs) def has_event(self, event_level, event_msg): for event in self.events: if event.get("level") == event_level and event.get("message") == event_msg: return True return False class TestClientSetup(unittest.TestCase): def setUp(self): super(TestClientSetup, self).setUp() self.logger = logging.getLogger(__name__) # Sentry is enabled by default, so the default handler will be added # when the module is loaded. After that, subsequent calls to # setup_logging will not re-add our handler. We explicitly remove # OdooSentryHandler handler so we can test with our in-memory client. remove_logging_handler("", OdooSentryHandler) def assertEventCaptured(self, client, event_level, event_msg): self.assertTrue( client.has_event(event_level, event_msg), msg='Event: "%s" was not captured' % event_msg, ) def assertEventNotCaptured(self, client, event_level, event_msg): self.assertFalse( client.has_event(event_level, event_msg), msg='Event: "%s" was captured' % event_msg, ) def test_initialize_raven_sets_dsn(self): config = { "sentry_enabled": True, "sentry_dsn": "http://public:secret@example.com/1", } client = initialize_raven(config, client_cls=InMemoryClient) self.assertEqual(client.remote.base_url, "http://example.com") def test_capture_event(self): config = { "sentry_enabled": True, "sentry_dsn": "http://public:secret@example.com/1", } level, msg = logging.WARNING, "Test event, can be ignored" client = initialize_raven(config, client_cls=InMemoryClient) self.logger.log(level, msg) self.assertEventCaptured(client, level, msg) def test_ignore_exceptions(self): config = { "sentry_enabled": True, "sentry_dsn": "http://public:secret@example.com/1", "sentry_ignore_exceptions": "odoo.exceptions.UserError", } level, msg = logging.WARNING, "Test UserError" client = initialize_raven(config, client_cls=InMemoryClient) handlers = list(log_handler_by_class(logging.getLogger(), OdooSentryHandler)) self.assertTrue(handlers) handler = handlers[0] try: raise exceptions.UserError(msg) except exceptions.UserError: exc_info = sys.exc_info() record = logging.LogRecord(__name__, level, __file__, 42, msg, (), exc_info) handler.emit(record) self.assertEventNotCaptured(client, level, msg)