def test_prepare_upgrades_schema_and_sets_position(): source = MockSource(feed_end=50) worker = MockWorker() db = MockDB(is_initialized=False) settings = MockSettings(source=source, worker=worker, db=db) with spy_on(db.upgrade_schema), spy_on(worker.set_initial_position): prepare(settings) assert db.upgrade_schema.called assert worker.set_initial_position.calls[0].args[1] == 50
def test_put_revoke_ship_it_timestamp(self): """Testing the PUT <URL> API with revoking Ship It does not update timestamp """ # ReviewRequest.last_update is a # django.db.fields.ModificationTimestampField, which retrieves its # value from datetime.utcnow().replace(tzinfo=utc). # # django.utils.timezone.now has the same implementation. # # Unfortunately, we cannot spy on datetime.utcnow since it is a # builtin. So we replace get_tz_aware_utcnow with timezone.now and we # will replace that with a constant function in the spy_on calls below. self.spy_on(get_tz_aware_utcnow, call_fake=lambda: timezone.now()) creation_timestamp = datetime.fromtimestamp(0, timezone.utc) review_timestamp = creation_timestamp + timedelta(hours=1) revoke_timestamp = review_timestamp + timedelta(hours=1) with spy_on(timezone.now, call_fake=lambda: creation_timestamp): review_request = self.create_review_request(publish=True, submitter=self.user) with spy_on(timezone.now, call_fake=lambda: review_timestamp): review = self.create_review(review_request, body_top=Review.SHIP_IT_TEXT, ship_it=True, publish=True, user=self.user) review_request = ReviewRequest.objects.get(pk=review_request.pk) self.assertEqual(review_request.time_added, creation_timestamp) self.assertEqual(review_request.last_updated, review_timestamp) self.assertEqual(review.timestamp, review_timestamp) with spy_on(timezone.now, call_fake=lambda: revoke_timestamp): rsp = self.api_put( get_review_item_url(review_request, review.pk), {'ship_it': False}, expected_mimetype=review_item_mimetype, ) self.assertIn('stat', rsp) self.assertEqual(rsp['stat'], 'ok') review = Review.objects.get(pk=review.pk) review_request = ReviewRequest.objects.get(pk=review_request.pk) self.assertEqual(review_request.time_added, creation_timestamp) self.assertEqual(review_request.last_updated, review_timestamp) self.assertEqual(review.timestamp, review_timestamp)
def test_prepare_doesnt_upgrade_schema_if_already_initialized(): db = MockDB(is_initialized=True) settings = MockSettings(db=db) with spy_on(db.upgrade_schema) as spy: with pytest.raises(DBInitializedError): prepare(settings) assert not spy.called
def test_migrate_doesnt_upgrade_schema_if_not_initialized(): db = MockDB(is_initialized=False) settings = MockSettings(db=db) with spy_on(db.upgrade_schema) as spy: with pytest.raises(DBNotInitializedError): migrate(settings) assert not spy.called
def test_processes_with_minimal_context_if_full_context_error(): event = { "isSecure": True, "timestamp": 0, "context": { "thisContextIsMissingProperties": True, }, "minimalContext": { "revision": { "revisionId": 1, "link": "link", }, "recipients": [{ "username": "******", "email": "2@mail", "timezoneOffset": 0, "isActor": False, }], }, } mail = MockMail() render = Render(JinjaTemplateStore("", "", False)) logger = logging.create_dev_logger() with spy_on(mail.send) as spy: process_event(event, render, MockThreadStore(), logger, 0, Mock(), mail) assert len(spy.calls) == 1 assert spy.calls[0].args[0].template_path == "minimal"
def test_revoke_ship_it_timestamp(self): """Testing Review.revoke_ship_it does not modify the review timestamp """ # ReviewRequest.last_update is a # django.db.fields.ModificationTimestampField, which retrieves its # value from datetime.utcnow().replace(tzinfo=utc). # # django.utils.timezone.now has the same implementation. # # Unfortunately, we cannot spy on datetime.utcnow since it is a # builtin. So we replace get_tz_aware_utcnow with timezone.now and we # will replace that with a constant function in the spy_on calls below. self.spy_on(get_tz_aware_utcnow, call_fake=lambda: timezone.now()) creation_timestamp = datetime.fromtimestamp(0, timezone.utc) review_timestamp = creation_timestamp + timedelta(hours=1) revoke_timestamp = review_timestamp + timedelta(hours=1) with spy_on(timezone.now, call_fake=lambda: creation_timestamp): review_request = self.create_review_request(publish=True) with spy_on(timezone.now, call_fake=lambda: review_timestamp): review = self.create_review(review_request, body_top=Review.SHIP_IT_TEXT, ship_it=True, publish=True) review_request = ReviewRequest.objects.get(pk=review_request.pk) self.assertEqual(review_request.time_added, creation_timestamp) self.assertEqual(review_request.last_updated, review_timestamp) self.assertEqual(review.timestamp, review_timestamp) with spy_on(timezone.now, call_fake=lambda: revoke_timestamp): review.revoke_ship_it(review.user) review = Review.objects.get(pk=review.pk) review_request = ReviewRequest.objects.get(pk=review_request.pk) self.assertEqual(review_request.time_added, creation_timestamp) self.assertEqual(review_request.last_updated, review_timestamp) self.assertEqual(review.timestamp, review_timestamp)
def test_either_field_subclass(): """Testing projector.fields.EitherField when one field type is a subclass of another""" class Special(int): pass class SuperSpecial(Special): pass class NotSoSpecial(int): pass int_field = fields.Raw() special_field = fields.Raw() class TestSchema(Schema): field = EitherField(required=True, fields={Special: special_field, int: int_field}) schema = TestSchema() with spy_on(int_field._deserialize) as int_spy, spy_on( special_field._deserialize ) as special_spy: assert schema.load({"field": 3}) == {"field": 3} assert int_spy.called assert not special_spy.called int_spy.reset_calls() assert schema.load({"field": Special(3)}) == {"field": Special(3)} assert not int_spy.called assert special_spy.called special_spy.reset_calls() assert schema.load({"field": SuperSpecial(3)}) == {"field": SuperSpecial(3)} assert not int_spy.called assert special_spy.called special_spy.reset_calls() assert schema.load({"field": NotSoSpecial(3)}) == {"field": NotSoSpecial(3)} assert int_spy.called assert not special_spy.called with spy_on(int_field._serialize) as int_spy, spy_on(special_field._serialize) as special_spy: assert schema.dump({"field": 3}) == {"field": 3} assert int_spy.called assert not special_spy.called int_spy.reset_calls() assert schema.dump({"field": Special(3)}) == {"field": Special(3)} assert not int_spy.called assert special_spy.called special_spy.reset_calls() assert schema.dump({"field": SuperSpecial(3)}) == {"field": SuperSpecial(3)} assert not int_spy.called assert special_spy.called special_spy.reset_calls() assert schema.dump({"field": NotSoSpecial(3)}) == {"field": NotSoSpecial(3)} assert int_spy.called assert not special_spy.called
def test_migrate_upgrades_schema(): db = MockDB(is_initialized=True) settings = MockSettings(db=db) with spy_on(db.upgrade_schema) as spy: migrate(settings) assert spy.called
def test_integration_pipeline(): source = MockSource( next_result={ "data": { "storyErrors": 0, "events": [ { "isSecure": True, "timestamp": 0, "context": { "eventKind": "revision-reclaimed", "actor": { "userName": "******", "realName": "1" }, "body": { "reviewers": [ { "name": "2", "isActionable": False, "status": "accepted", "recipients": [{ "timezoneOffset": 0, "username": "******", "email": "2@mail", "isActor": False, }], }, { "name": "3", "isActionable": True, "status": "requested-changes", "recipients": [{ "timezoneOffset": 0, "username": "******", "email": "3@mail", "isActor": False, }], }, ], "subscribers": [{ "email": "3@mail", "username": "******", "timezoneOffset": 0, "isActor": False, }], "commentCount": 1, "transactionLink": "link", }, "revision": { "revisionId": 1, "repositoryName": "repo", "link": "link", "bug": { "bugId": 1, "link": "link" }, }, }, }, { "isSecure": False, "timestamp": 1, "context": { "eventKind": "revision-abandoned", "actor": { "userName": "******", "realName": "4" }, "body": { "reviewers": [{ "username": "******", "email": "5@mail", "timezoneOffset": 0, "isActor": False, }], "subscribers": [], "mainCommentMessage": { "asText": "Main comment", "asHtml": "<p>Main comment</p>", }, "inlineComments": [{ "contextKind": "code", "context": { "diff": [{ "lineNumber": 10, "type": "added", "rawContent": "hello world", }] }, "fileContext": "/README:20", "link": "link", "message": { "asText": "great content here.", "asHtml": "<em>great content here.</em>", }, }], "transactionLink": "link", }, "revision": { "revisionId": 2, "name": "name 2", "repositoryName": "repo", "link": "link", }, }, }, ], }, "cursor": { "after": 20 }, }) mail = MockMail() render = Render(JinjaTemplateStore("", "", False)) logger = logging.create_dev_logger() pipeline = Pipeline(source, render, mail, logger, 0, Mock(), False) with spy_on(mail.send) as send_spy, spy_on(source.fetch_next) as fetch_spy: new_position = pipeline.run(MockThreadStore(), 10) assert new_position == 20 assert fetch_spy.calls[0].args[0] == 10 emails = [] for call in send_spy.calls: emails.append(call.args[0]) _assert_mail( emails[0], "D1: (secure bug 1)", "2@mail", "1 reclaimed this revision that you've accepted and submitted a comment.", ) _assert_mail( emails[1], "D1: (secure bug 1)", "3@mail", "1 reclaimed this revision and submitted a comment.", ) _assert_mail( emails[2], "D2: name 2", "5@mail", "4 abandoned this revision and submitted comments.", )
def test_config_schema(): scm_tools = {"Git": Git} schema = ConfigSchema() try: with spy_on(_get_scm_tools_uncached, call_fake=lambda: scm_tools): with pytest.raises(ValidationError) as excinfo: schema.load({}) assert excinfo.value.messages == { "directories": ["Missing data for required field."], "repositories": ["Missing data for required field."], } with pytest.raises(ValidationError) as excinfo: schema.load({ "directories": { "source": "/src" }, "repositories": { "my-repo": { "scm": "unknown-scm" } }, }) assert excinfo.value.messages == { "repositories": { "my-repo": { "value": { "config": ["Missing data for required field."] } } } } with pytest.raises(ValidationError) as excinfo: schema.load({ "directories": { "source": "/src" }, "repositories": { "my-repo": { "scm": "unknown-scm", "config": {} } }, }) assert excinfo.value.messages == { "repositories": { "my-repo": { "value": { "scm": ["Unknown SCM: `unknown-scm'"] } } } } assert schema.load({ "directories": { "source": "/src" }, "repositories": {} }) == { "directories": { "source": Path("/src") }, "repositories": {}, } assert schema.load({ "directories": { "source": "/src" }, "repositories": { "projector": { "scm": "Git", "config": { "remotes": { "origin": { "url": "[email protected]:brennie/projector.git" } } }, } }, }) == { "directories": { "source": Path("/src") }, "repositories": { "projector": { "scm": "Git", "config": { "ref": "master", "detach": False, "remotes": { "origin": Remote( kind=RemoteKind.EXPLICIT, inner={ "url": "[email protected]:brennie/projector.git", "default": True, }, ) }, }, } }, } finally: get_scm_tools.cache_clear()
def test_config_schema(): scm_tools = {"Git": Git} schema = ConfigSchema() try: with spy_on(_get_scm_tools_uncached, call_fake=lambda: scm_tools): with pytest.raises(ValidationError) as excinfo: schema.load({}) assert excinfo.value.messages == { "directories": ["Missing data for required field."], "repositories": ["Missing data for required field."], } with pytest.raises(ValidationError) as excinfo: schema.load( { "directories": {"source": "/src"}, "repositories": {"my-repo": {"scm": "unknown-scm"}}, } ) assert excinfo.value.messages == { "repositories": { "my-repo": {"value": {"config": ["Missing data for required field."]}} } } with pytest.raises(ValidationError) as excinfo: schema.load( { "directories": {"source": "/src"}, "repositories": {"my-repo": {"scm": "unknown-scm", "config": {}}}, } ) assert excinfo.value.messages == { "repositories": {"my-repo": {"value": {"scm": ["Unknown SCM: `unknown-scm'"]}}} } assert schema.load({"directories": {"source": "/src"}, "repositories": {}}) == { "directories": {"source": Path("/src")}, "repositories": {}, } assert schema.load( { "directories": {"source": "/src"}, "repositories": { "projector": { "scm": "Git", "config": { "remotes": { "origin": {"url": "[email protected]:brennie/projector.git"} } }, } }, } ) == { "directories": {"source": Path("/src")}, "repositories": { "projector": { "scm": "Git", "config": { "ref": "master", "detach": False, "remotes": { "origin": Remote( kind=RemoteKind.EXPLICIT, inner={ "url": "[email protected]:brennie/projector.git", "default": True, }, ) }, }, } }, } finally: get_scm_tools.cache_clear()
def test_either_field_subclass(): """Testing projector.fields.EitherField when one field type is a subclass of another""" class Special(int): pass class SuperSpecial(Special): pass class NotSoSpecial(int): pass int_field = fields.Raw() special_field = fields.Raw() class TestSchema(Schema): field = EitherField(required=True, fields={ Special: special_field, int: int_field }) schema = TestSchema() with spy_on(int_field._deserialize) as int_spy, spy_on( special_field._deserialize) as special_spy: assert schema.load({"field": 3}) == {"field": 3} assert int_spy.called assert not special_spy.called int_spy.reset_calls() assert schema.load({"field": Special(3)}) == {"field": Special(3)} assert not int_spy.called assert special_spy.called special_spy.reset_calls() assert schema.load({"field": SuperSpecial(3)}) == { "field": SuperSpecial(3) } assert not int_spy.called assert special_spy.called special_spy.reset_calls() assert schema.load({"field": NotSoSpecial(3)}) == { "field": NotSoSpecial(3) } assert int_spy.called assert not special_spy.called with spy_on(int_field._serialize) as int_spy, spy_on( special_field._serialize) as special_spy: assert schema.dump({"field": 3}) == {"field": 3} assert int_spy.called assert not special_spy.called int_spy.reset_calls() assert schema.dump({"field": Special(3)}) == {"field": Special(3)} assert not int_spy.called assert special_spy.called special_spy.reset_calls() assert schema.dump({"field": SuperSpecial(3)}) == { "field": SuperSpecial(3) } assert not int_spy.called assert special_spy.called special_spy.reset_calls() assert schema.dump({"field": NotSoSpecial(3)}) == { "field": NotSoSpecial(3) } assert int_spy.called assert not special_spy.called