def test_throws_when_matches_discarded_hash(self): manager = EventManager(make_event(message="foo", event_id="a" * 32, fingerprint=["a" * 32])) with self.tasks(): event = manager.save(1) group = Group.objects.get(id=event.group_id) tombstone = GroupTombstone.objects.create( project_id=group.project_id, level=group.level, message=group.message, culprit=group.culprit, data=group.data, previous_group_id=group.id, ) GroupHash.objects.filter(group=group).update(group=None, group_tombstone_id=tombstone.id) manager = EventManager(make_event(message="foo", event_id="b" * 32, fingerprint=["a" * 32])) mock_event_discarded = mock.Mock() event_discarded.connect(mock_event_discarded) mock_event_saved = mock.Mock() event_saved.connect(mock_event_saved) with self.tasks(): with self.assertRaises(HashDiscarded): event = manager.save(1) assert not mock_event_saved.called assert_mock_called_once_with_partial( mock_event_discarded, project=group.project, sender=EventManager, signal=event_discarded )
def test_entity_handler(self): test_org = self.create_organization() # Add a registered handler registered_handler = mock.Mock() registered_handler.features = ["organizations:feature1"] manager = features.FeatureManager() manager.add("organizations:feature1", features.OrganizationFeature) # Add the entity handler entity_handler = mock.Mock() manager.add("organizations:unregistered-feature", features.OrganizationFeature) # Non entity feature manager.add("organizations:settings-feature", features.OrganizationFeature) manager.add_handler(registered_handler) manager.add_entity_handler(entity_handler) # A feature with a registered handler shouldn't use the entity handler assert manager.has("organizations:feature1", test_org) assert len(entity_handler.has.mock_calls) == 0 assert len(registered_handler.mock_calls) == 1 # The feature isn't registered, so it should try checking the entity_handler assert manager.has("organizations:unregistered-feature", test_org) assert len(entity_handler.has.mock_calls) == 1 assert len(registered_handler.mock_calls) == 1 # The entity_handler doesn't have a response for this feature either, so settings should be checked instead entity_handler.has.return_value = None settings.SENTRY_FEATURES["organizations:settings-feature"] = "test" assert manager.has("organizations:settings-feature", test_org) == "test" assert len(entity_handler.mock_calls) == 2
def test_get_option_with_project(self): with mock.patch("sentry.models.ProjectOption.objects.get_value") as get_value: project = mock.Mock() result = get_option("key", project) self.assertEquals(result, get_value.return_value) get_value.assert_called_once_with(project, "key", None)
def test_incr_delays_task(self, process_incr): model = mock.Mock() columns = {"times_seen": 1} filters = {"id": 1} self.buf.incr(model, columns, filters) kwargs = dict(model=model, columns=columns, filters=filters, extra=None, signal_only=None) process_incr.apply_async.assert_called_once_with(kwargs=kwargs)
def test_multiple_auth_suspicious(): helper = ClientAuthHelper() request = mock.Mock() request.GET = {"sentry_version": "1", "foo": "bar"} request.META = {"HTTP_X_SENTRY_AUTH": "Sentry sentry_key=value, biz=baz"} with pytest.raises(SuspiciousOperation): helper.auth_from_request(request)
def test_invalid_malformed_value(): helper = ClientAuthHelper() request = mock.Mock() request.META = {"HTTP_X_SENTRY_AUTH": "Sentry sentry_key=value,,biz=baz"} request.GET = {} with pytest.raises(APIUnauthorized): helper.auth_from_request(request)
class DependencyTest(TestCase): def raise_import_error(self, package): def callable(package_name): if package_name != package: return import_string(package_name) raise ImportError("No module named %s" % (package, )) return callable @mock.patch("django.conf.settings", mock.Mock()) @mock.patch("sentry.utils.settings.import_string") def validate_dependency(self, key, package, dependency_type, dependency, setting_value, import_string): import_string.side_effect = self.raise_import_error(package) with self.settings(**{key: setting_value}): with self.assertRaises(ConfigurationError): validate_settings(settings) def test_validate_fails_on_postgres(self): self.validate_dependency(*DEPENDENCY_TEST_DATA["postgresql"]) def test_validate_fails_on_memcache(self): self.validate_dependency(*DEPENDENCY_TEST_DATA["memcache"]) def test_validate_fails_on_pylibmc(self): self.validate_dependency(*DEPENDENCY_TEST_DATA["pylibmc"])
def test_registration_single_org_with_invite(self, from_cookie): self.session["can_register"] = True self.save_session() self.client.get(self.path) invite_helper = mock.Mock(valid_request=True) from_cookie.return_value = invite_helper resp = self.client.post( self.path, { "username": "******", "password": "******", "name": "Foo Bar", "op": "register", }, ) user = User.objects.get(username="******") # An organization member should NOT have been created, even though # we're in single org mode, accepting the invite will handle that # (which we assert next) assert not OrganizationMember.objects.filter(user=user).exists() # Invitation was accepted assert len(invite_helper.accept_invite.mock_calls) == 1 assert resp.status_code == 302
def test_hash_discarded_raised(default_project, mock_refund, mock_incr, register_plugin): register_plugin(BasicPreprocessorPlugin) data = { "project": default_project.id, "platform": "NOTMATTLANG", "logentry": { "formatted": "test" }, "event_id": uuid.uuid4().hex, "extra": { "foo": "bar" }, } now = time() mock_save = mock.Mock() mock_save.side_effect = HashDiscarded with mock.patch.object(EventManager, "save", mock_save): save_event(data=data, start_time=now) mock_incr.assert_called_with( [ (tsdb.models.project_total_received, default_project.id), (tsdb.models.organization_total_received, default_project.organization.id), (tsdb.models.project_total_blacklisted, default_project.id), (tsdb.models.organization_total_blacklisted, default_project.organization_id), (tsdb.models.project_total_received_discarded, default_project.id), ], timestamp=to_datetime(now), )
def test_incr_saves_to_redis(self): now = datetime(2017, 5, 3, 6, 6, 6, tzinfo=timezone.utc) client = self.buf.cluster.get_routing_client() model = mock.Mock() model.__name__ = "Mock" columns = {"times_seen": 1} filters = {"pk": 1, "datetime": now} self.buf.incr(model, columns, filters, extra={ "foo": "bar", "datetime": now }) result = client.hgetall("foo") assert result == { "e+foo": '["s","bar"]', "e+datetime": '["d","1493791566.000000"]', "f": '{"pk":["i","1"],"datetime":["d","1493791566.000000"]}', "i+times_seen": "1", "m": "mock.mock.Mock", } pending = client.zrange("b:p", 0, -1) assert pending == ["foo"] self.buf.incr(model, columns, filters, extra={"foo": "baz"}) result = client.hgetall("foo") assert result == { "e+foo": '["s","baz"]', "e+datetime": '["d","1493791566.000000"]', "f": '{"pk":["i","1"],"datetime":["d","1493791566.000000"]}', "i+times_seen": "2", "m": "mock.mock.Mock", } pending = client.zrange("b:p", 0, -1) assert pending == ["foo"]
def test_simple(self, mock_eventstream): key = "foo" val = "bar" project = self.create_project() self.store_event( data={"tags": {key: val}, "timestamp": iso_format(before_now(seconds=1))}, project_id=project.id, ) self.login_as(user=self.user) eventstream_state = object() mock_eventstream.start_delete_tag = mock.Mock(return_value=eventstream_state) url = reverse( "sentry-api-0-project-tagkey-details", kwargs={ "organization_slug": project.organization.slug, "project_slug": project.slug, "key": key, }, ) response = self.client.delete(url) assert response.status_code == 204 mock_eventstream.start_delete_tag.assert_called_once_with(project.id, "foo") mock_eventstream.end_delete_tag.assert_called_once_with(eventstream_state)
def test_attachment_outcomes(self): manager = EventManager(make_event(message="foo"), project=self.project) manager.normalize() a1 = CachedAttachment(name="a1", data=b"hello") a2 = CachedAttachment(name="a2", data=b"limited", rate_limited=True) a3 = CachedAttachment(name="a3", data=b"world") cache_key = cache_key_for_event(manager.get_data()) attachment_cache.set(cache_key, attachments=[a1, a2, a3]) mock_track_outcome = mock.Mock() with mock.patch("sentry.event_manager.track_outcome", mock_track_outcome): with self.feature("organizations:event-attachments"): manager.save(1, cache_key=cache_key) assert mock_track_outcome.call_count == 3 for o in mock_track_outcome.mock_calls: assert o.kwargs["outcome"] == Outcome.ACCEPTED for o in mock_track_outcome.mock_calls[:2]: assert o.kwargs["category"] == DataCategory.ATTACHMENT assert o.kwargs["quantity"] == 5 final = mock_track_outcome.mock_calls[2] assert final.kwargs["category"] == DataCategory.DEFAULT
class SecurityReportHpkpTest(TestCase): @fixture def path(self): path = reverse("sentry-api-security-report", kwargs={"project_id": self.project.id}) return path + "?sentry_key=%s" % self.projectkey.public_key @mock.patch("sentry.web.api.is_valid_origin", mock.Mock(return_value=True)) @mock.patch("sentry.web.api.SecurityReportView.process") def test_post_success(self, process): process.return_value = "ok" resp = self.client.post( self.path, content_type="application/json", data=json.dumps({ "date-time": "2014-04-06T13:00:50Z", "hostname": "www.example.com", "port": 443, "effective-expiration-date": "2014-05-01T12:40:50Z", "include-subdomains": False, "served-certificate-chain": ["-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"], "validated-certificate-chain": ["-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"], "known-pins": ['pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g="'], }), HTTP_USER_AGENT="awesome", ) assert resp.status_code == 201, resp.content
def test_incr_saves_to_redis(self): now = datetime(2017, 5, 3, 6, 6, 6, tzinfo=timezone.utc) client = self.buf.cluster.get_routing_client() model = mock.Mock() model.__name__ = "Mock" columns = {"times_seen": 1} filters = {"pk": 1, "datetime": now} self.buf.incr(model, columns, filters, extra={"foo": "bar", "datetime": now}) result = client.hgetall("foo") # Force keys to strings result = {force_text(k): v for k, v in result.items()} f = result.pop("f") assert pickle.loads(f) == {"pk": 1, "datetime": now} assert pickle.loads(result.pop("e+datetime")) == now assert pickle.loads(result.pop("e+foo")) == "bar" assert result == {"i+times_seen": b"1", "m": b"mock.mock.Mock"} pending = client.zrange("b:p", 0, -1) assert pending == [b"foo"] self.buf.incr(model, columns, filters, extra={"foo": "baz", "datetime": now}) result = client.hgetall("foo") # Force keys to strings result = {force_text(k): v for k, v in result.items()} f = result.pop("f") assert pickle.loads(f) == {"pk": 1, "datetime": now} assert pickle.loads(result.pop("e+datetime")) == now assert pickle.loads(result.pop("e+foo")) == "baz" assert result == {"i+times_seen": b"2", "m": b"mock.mock.Mock"} pending = client.zrange("b:p", 0, -1) assert pending == [b"foo"]
def test_blocking_aqcuire(self, mock_acquire, mock_random): backend = mock.Mock(spec=LockBackend) key = "lock" duration = 60 routing_key = None lock = Lock(backend, key, duration, routing_key) class MockTime: time = 0 @classmethod def incr(cls, delta): cls.time += delta with patch("sentry.utils.locking.lock.time.monotonic", side_effect=lambda: MockTime.time), patch( "sentry.utils.locking.lock.time.sleep", side_effect=MockTime.incr) as mock_sleep: with self.assertRaises(UnableToAcquireLock): lock.blocking_acquire(initial_delay=0.1, timeout=1, exp_base=2) # 0.0, 0.05, 0.15, 0.35, 0.75 assert len(mock_acquire.mock_calls) == 5 assert mock_sleep.mock_calls == [ call(0.05), call(0.1), call(0.2), call(0.4) ] with patch("sentry.utils.locking.lock.Lock.acquire", return_value="foo"): # Success case: assert lock.blocking_acquire(initial_delay=0, timeout=1) == "foo"
def test_subscription_registered(self): registration_key = "registered_test" mock_callback = mock.Mock() register_subscriber(registration_key)(mock_callback) with self.tasks(): snuba_query = create_snuba_query( QueryDatasets.EVENTS, "hello", "count()", timedelta(minutes=10), timedelta(minutes=1), None, ) sub = create_snuba_subscription(self.project, registration_key, snuba_query) sub.refresh_from_db() data = self.valid_wrapper data["payload"]["subscription_id"] = sub.subscription_id self.consumer.handle_message(self.build_mock_message(data)) data = deepcopy(data) data["payload"]["values"] = data["payload"]["result"] data["payload"]["timestamp"] = parse_date( data["payload"]["timestamp"]).replace(tzinfo=pytz.utc) mock_callback.assert_called_once_with(data["payload"], sub)
def test_valid_ignore_case(): helper = ClientAuthHelper() request = mock.Mock() request.META = {"HTTP_X_SENTRY_AUTH": "SeNtRy sentry_key=value, biz=baz"} request.GET = {} result = helper.auth_from_request(request) assert result.public_key == "value"
def test_set_option_with_project(self): with mock.patch( "sentry.models.ProjectOption.objects.set_value") as set_value: project = mock.Mock() set_option("key", "value", project) set_value.assert_called_once_with(project, "key", "value")
def test_invalid_legacy_header_defers_to_GET(): helper = ClientAuthHelper() request = mock.Mock() request.META = {"HTTP_AUTHORIZATION": "foobar"} request.GET = {"sentry_version": "1", "foo": "bar"} result = helper.auth_from_request(request) assert result.version == "1"
def test_basic(self, builder): builder.return_value.send_async = mock.Mock() self.login_as(user=self.user) with self.tasks(): response = self.get_response( self.organization.slug, targetUserEmail="*****@*****.**", ) assert response.status_code == 201 requester_name = self.user.get_display_name() requester_link = absolute_uri( f"/organizations/{self.organization.slug}/projects/new/?referrer=request_project&category=mobile" ) expected_email_args = { "subject": f"{requester_name} thinks Sentry can help monitor your mobile app", "template": "sentry/emails/requests/organization-project.txt", "html_template": "sentry/emails/requests/organization-project.html", "type": "organization.project.request", "context": { "requester_name": requester_name, "requester_link": requester_link, }, } builder.assert_called_with(**expected_email_args) builder.return_value.send_async.assert_called_once_with(["*****@*****.**"])
def test_invalid_header_missing_pair(): helper = ClientAuthHelper() request = mock.Mock() request.META = {"HTTP_X_SENTRY_AUTH": "Sentry foo"} request.GET = {} with pytest.raises(APIUnauthorized): helper.auth_from_request(request)
def test_calls_process(self, process): model = mock.Mock() columns = {"times_seen": 1} filters = {"pk": 1} process_incr(model=model, columns=columns, filters=filters) process.assert_called_once_with(model=model, columns=columns, filters=filters)
def test_future_set_callback_empty(): future_set = FutureSet([]) callback = mock.Mock() future_set.add_done_callback(callback) assert callback.call_count == 1 assert callback.call_args == mock.call(future_set)
def test_future_set_callback_error(): future_set = FutureSet([Future() for i in range(3)]) callback = mock.Mock() future_set.add_done_callback(callback) for i, future in enumerate(list(future_set)): assert callback.call_count == 0 future.set_exception(Exception) assert callback.call_count == 1 assert callback.call_args == mock.call(future_set) other_callback = mock.Mock() future_set.add_done_callback(other_callback) assert other_callback.call_count == 1 assert other_callback.call_args == mock.call(future_set)
def test_future_set_callback_success(): future_set = FutureSet([Future() for i in range(3)]) callback = mock.Mock() future_set.add_done_callback(callback) for i, future in enumerate(list(future_set)): assert callback.call_count == 0 future.set_result(True) assert callback.call_count == 1 assert callback.call_args == mock.call(future_set) other_callback = mock.Mock() future_set.add_done_callback(other_callback) assert other_callback.call_count == 1 assert other_callback.call_args == mock.call(future_set)
class SecurityReportCspTest(TestCase): @fixture def path(self): path = reverse("sentry-api-security-report", kwargs={"project_id": self.project.id}) return path + "?sentry_key=%s" % self.projectkey.public_key def test_get_response(self): resp = self.client.get(self.path) assert resp.status_code == 405, resp.content def test_invalid_content_type(self): resp = self.client.post(self.path, content_type="text/plain") assert resp.status_code == 400, resp.content def test_missing_csp_report(self): resp = self.client.post( self.path, content_type="application/csp-report", data='{"lol":1}', HTTP_USER_AGENT="awesome", ) assert resp.status_code == 400, resp.content @mock.patch("sentry.utils.http.get_origins") def test_bad_origin(self, get_origins): get_origins.return_value = ["example.com"] resp = self.client.post( self.path, content_type="application/csp-report", data= '{"csp-report":{"document-uri":"http://lolnope.com","effective-directive":"img-src","violated-directive":"img-src","source-file":"test.html"}}', HTTP_USER_AGENT="awesome", ) assert resp.status_code == 403, resp.content get_origins.return_value = ["*"] resp = self.client.post( self.path, content_type="application/csp-report", data='{"csp-report":{"document-uri":"about:blank"}}', HTTP_USER_AGENT="awesome", ) assert resp.status_code == 400, resp.content @mock.patch("sentry.web.api.is_valid_origin", mock.Mock(return_value=True)) @mock.patch("sentry.web.api.SecurityReportView.process") def test_post_success(self, process): process.return_value = "ok" resp = self._postCspWithHeader({ "document-uri": "http://example.com", "source-file": "http://example.com", "effective-directive": "style-src", "violated-directive": "style-src", "disposition": "enforce", }) assert resp.status_code == 201, resp.content
def test_get_digest_subject(self): assert ( self.adapter.get_digest_subject( mock.Mock(qualified_short_id="BAR-1"), {mock.sentinel.group: 3}, datetime(2016, 9, 19, 1, 2, 3, tzinfo=pytz.utc), ) == "BAR-1 - 1 new alert since Sept. 19, 2016, 1:02 a.m. UTC" )
def setUp(self): super(SlackRequestTest, self).setUp() self.request = mock.Mock() self.request.data = { "type": "foo", "team_id": "T001", "channel": {"id": "1"}, "user": {"id": "2"}, "api_app_id": "S1", }
def test_event_accepted_outcome(self): manager = EventManager(make_event(message="foo")) manager.normalize() mock_track_outcome = mock.Mock() with mock.patch("sentry.event_manager.track_outcome", mock_track_outcome): manager.save(1) assert_mock_called_once_with_partial( mock_track_outcome, outcome=Outcome.ACCEPTED, category=DataCategory.DEFAULT )
def test_policy_success(self): bomb = Exception("Boom!") callable = mock.MagicMock(side_effect=[bomb, mock.sentinel.OK]) retry = TimedRetryPolicy(0.3, delay=lambda i: 0.1) retry.clock = mock.Mock() retry.clock.sleep = mock.MagicMock() retry.clock.time = mock.MagicMock(side_effect=[0, 0.15]) assert retry(callable) is mock.sentinel.OK assert callable.call_count == 2