def test_increment_counts(self): """ Every event should keep a list of prior events which occurred in the session """ def next_callable(event): pass middleware = SessionMiddleware(next_callable) self.sessiontracker.start_session() event = Notification(Exception('shucks'), self.config, None) middleware(event) assert event.session['events']['unhandled'] == 0 assert event.session['events']['handled'] == 1 event2 = Notification(Exception('oh no'), self.config, None) middleware(event2) assert event2.session['events']['unhandled'] == 0 assert event2.session['events']['handled'] == 2 # Session counts should not change for events already handled assert event.session['events']['unhandled'] == 0 assert event.session['events']['handled'] == 1
def test_code(self): """ It should include code """ config = Configuration() line = inspect.currentframe().f_lineno + 1 notification = Notification(Exception("oops"), config, {}) payload = json.loads(notification._payload()) code = payload['events'][0]['exceptions'][0]['stacktrace'][0]['code'] lvl = " " self.assertEqual(code[str(line - 3)], lvl + "\"\"\"") self.assertEqual(code[str(line - 2)], lvl + "config = Configuration()") self.assertEqual(code[str(line - 1)], lvl + "line = inspect.currentframe().f_lineno + 1") self.assertEqual( code[str(line)], lvl + "notification = Notification(Exception(\"oops\"), config, {})" ) self.assertEqual(code[str(line + 1)], "") self.assertEqual(code[str(line + 2)], lvl + "payload = json.loads(notification._payload())") self.assertEqual(code[str(line + 3)], "")
def test_code_turned_off(self): config = Configuration() config.send_code = False notification = Notification(Exception("oops"), config, {}, traceback=fixtures.end_of_file[2]) payload = json.loads(notification._payload()) code = payload['events'][0]['exceptions'][0]['stacktrace'][0]['code'] self.assertEqual(code, None)
def test_default_app_type(self): """ app_type is None by default """ config = Configuration() notification = Notification(Exception("oops"), config, {}) payload = json.loads(notification._payload()) app = payload['events'][0]['app'] assert app['type'] is None
def test_configured_app_type(self): """ It should include app type if specified """ config = Configuration() config.configure(app_type='rq') notification = Notification(Exception("oops"), config, {}) payload = json.loads(notification._payload()) app = payload['events'][0]['app'] assert app['type'] == 'rq'
def test_code_turned_off(): config = Configuration() config.send_code = False notification = Notification(Exception("oops"), config, {}, traceback=fixtures.end_of_file[2]) payload = notification._payload() code = payload['events'][0]['exceptions'][0]['stacktrace'][0]['code'] assert (None == code)
def notify(self, exception, asynchronous=None, **options): """ Notify bugsnag of an exception. >>> client.notify(Exception('Example')) """ notification = Notification(exception, self.configuration, RequestConfiguration.get_instance(), **options) self.deliver(notification, asynchronous=asynchronous)
def notify_exc_info(self, exc_type, exc_value, traceback, **options): """ Notify bugsnag of an exception via exc_info. >>> client.notify_exc_info(*sys.exc_info()) """ exception = exc_value options['traceback'] = traceback notification = Notification(exception, self.configuration, RequestConfiguration.get_instance(), **options) self.deliver(notification)
def test_device_data(self): """ It should include device data """ config = Configuration() config.hostname = 'test_host_name' config.runtime_versions = {'python': '9.9.9'} notification = Notification(Exception("oops"), config, {}) payload = json.loads(notification._payload()) device = payload['events'][0]['device'] self.assertEqual('test_host_name', device['hostname']) self.assertEqual('9.9.9', device['runtimeVersions']['python'])
def test_sanitize(self): """ It should sanitize request data """ config = Configuration() notification = Notification(Exception("oops"), config, {}, request={"params": {"password": "******"}}) notification.add_tab("request", {"arguments": {"password": "******"}}) payload = json.loads(notification._payload()) request = payload['events'][0]['metaData']['request'] self.assertEqual(request['arguments']['password'], '[FILTERED]') self.assertEqual(request['params']['password'], '[FILTERED]')
def notify(exception, **options): """ Notify bugsnag of an exception. """ try: if isinstance(exception, (list, tuple)): # Exception tuples, eg. from sys.exc_info if not "traceback" in options: options["traceback"] = exception[2] Notification(exception[1], configuration, RequestConfiguration.get_instance(), **options).deliver() else: # Exception objects Notification(exception, configuration, RequestConfiguration.get_instance(), **options).deliver() except Exception: try: log("Notification failed") print((traceback.format_exc())) except Exception: print(("[BUGSNAG] error in exception handler")) print((traceback.format_exc()))
def test_code_at_end_of_file(self): config = Configuration() notification = Notification(fixtures.end_of_file[1], config, {}, traceback=fixtures.end_of_file[2]) payload = json.loads(notification._payload()) code = payload['events'][0]['exceptions'][0]['stacktrace'][0]['code'] self.assertEqual( {'6': '# 5', '7': '# 6', '8': '# 7', '9': '# 8', '10': 'try:', '11': ' import sys; raise Exception("end")', '12': 'except Exception: end_of_file = sys.exc_info()'}, code)
def test_code_at_start_of_file(self): config = Configuration() notification = Notification(fixtures.start_of_file[1], config, {}, traceback=fixtures.start_of_file[2]) payload = json.loads(notification._payload()) code = payload['events'][0]['exceptions'][0]['stacktrace'][0]['code'] self.assertEqual( {'1': '# flake8: noqa', '2': 'try:', '3': ' import sys; raise Exception("start")', '4': 'except Exception: start_of_file = sys.exc_info()', '5': '# 4', '6': '# 5', '7': '# 6'}, code)
def test_path_supports_ascii_characters(self): import bugsnag.wsgi.middleware environ = self.environ.copy() environ['PATH_INFO'] = '/hello/world' bugsnag.configure_request(wsgi_environ=environ) config = Configuration() notification = Notification(Exception("oops"), config, RequestConfiguration.get_instance()) bugsnag.wsgi.middleware.add_wsgi_request_data_to_notification( notification) self.assertEqual('http://localhost/hello/world', notification.meta_data['request']['url'])
def test_path_supports_non_ascii_characters(self): import bugsnag.wsgi.middleware environ = self.environ.copy() environ['PATH_INFO'] = '/ôßłガ' config = Configuration() notification = Notification(Exception("oops"), config, RequestConfiguration.get_instance()) bugsnag.configure_request(wsgi_environ=environ) bugsnag.wsgi.middleware.add_wsgi_request_data_to_notification( notification) # You can validate this by using "encodeURIComponent" in a browser. self.assertEqual('http://localhost/%C3%B4%C3%9F%C5%82%E3%82%AC', notification.meta_data['request']['url'])
def test_path_supports_emoji(self): import bugsnag.wsgi.middleware environ = self.environ.copy() environ['PATH_INFO'] = '/😇' config = Configuration() notification = Notification(Exception("oops"), config, RequestConfiguration.get_instance()) bugsnag.configure_request(wsgi_environ=environ) bugsnag.wsgi.middleware.add_wsgi_request_data_to_notification( notification) # You can validate this by using "encodeURIComponent" in a browser. self.assertEqual('http://localhost/%F0%9F%98%87', notification.meta_data['request']['url'])
def test_sanitize(): """ It should sanitize request data """ config = Configuration() notification = Notification(Exception("oops"), config, {}, request={"params": { "password": "******" }}) notification.add_tab("request", {"arguments": {"password": "******"}}) payload = notification._payload() assert (payload['events'][0]['metaData']['request']['arguments'] ['password'] == '[FILTERED]') assert (payload['events'][0]['metaData']['request']['params']['password'] == '[FILTERED]')
def test_wrongly_encoded_url_should_not_raise(self): import bugsnag.wsgi.middleware environ = self.environ.copy() environ['PATH_INFO'] = '/%83' bugsnag.configure_request(wsgi_environ=environ) config = Configuration() notification = Notification(Exception("oops"), config, RequestConfiguration.get_instance()) bugsnag.wsgi.middleware.add_wsgi_request_data_to_notification( notification) # We have to use "urllib.parse.quote" here because the exact output # differs on different Python versions because of how they handle # invalid encoding sequences self.assertEqual('http://localhost/%s' % urllib.parse.quote('%83'), notification.meta_data['request']['url'])
def test_code(): """ It should include code """ config = Configuration() line = inspect.currentframe().f_lineno + 1 notification = Notification(Exception("oops"), config, {}) payload = notification._payload() code = payload['events'][0]['exceptions'][0]['stacktrace'][0]['code'] assert (code[line - 3] == " \"\"\"") assert (code[line - 2] == " config = Configuration()") assert (code[line - 1] == " line = inspect.currentframe().f_lineno + 1") assert (code[line + 0] == " notification = Notification(Exception(\"oops\"), config, {})") assert (code[line + 1] == "") assert (code[line + 2] == " payload = notification._payload()") assert (code[line + 3] == "")
def test_code_at_end_of_file(): config = Configuration() line = inspect.currentframe().f_lineno + 1 notification = Notification(fixtures.end_of_file[1], config, {}, traceback=fixtures.end_of_file[2]) payload = notification._payload() code = payload['events'][0]['exceptions'][0]['stacktrace'][0]['code'] assert ({ 5: '# 5', 6: '# 6', 7: '# 7', 8: '# 8', 9: 'try:', 10: ' import sys; raise Exception("end")', 11: 'except Exception: end_of_file = sys.exc_info()' } == code)
def invoke_exception_on_other_file(config): from bugsnag.notification import Notification return Notification(Exception("another file!"), config, {})