def test_nested_series(self): """Handle a series sent in-reply-to an existing series.""" # create an old series with a "cover letter" msgids = [make_msgid()] project = create_project() series_v1 = create_series(project=project) create_series_reference(msgid=msgids[0], series=series_v1) # ...and three patches for i in range(3): msgids.append(make_msgid()) create_series_reference(msgid=msgids[-1], series=series_v1) # now create a new series with "cover letter" msgids.append(make_msgid()) series_v2 = create_series(project=project) ref_v2 = create_series_reference(msgid=msgids[-1], series=series_v2) # ...and the "first patch" of this new series msgid = make_msgid() email = self._create_email(msgid, msgids) series = find_series(project, email, get_or_create_author(email)) # this should link to the second series - not the first self.assertEqual(len(msgids), 4 + 1) # old series + new cover self.assertEqual(series, ref_v2.series)
def test_nested_series(self): """Handle a series sent in-reply-to an existing series.""" # create an old series with a "cover letter" msgids = [make_msgid()] project = create_project() series_v1 = create_series(project=project) create_series_reference(msgid=msgids[0], series=series_v1) # ...and three patches for i in range(3): msgids.append(make_msgid()) create_series_reference(msgid=msgids[-1], series=series_v1) # now create a new series with "cover letter" msgids.append(make_msgid()) series_v2 = create_series(project=project) ref_v2 = create_series_reference(msgid=msgids[-1], series=series_v2) # ...and the "first patch" of this new series msgid = make_msgid() email = self._create_email(msgid, msgids) series = find_series(project, email) # this should link to the second series - not the first self.assertEqual(len(msgids), 4 + 1) # old series + new cover self.assertEqual(series, ref_v2.series)
def test_list_old_version(self): """Validate that newer fields are dropped for older API versions.""" create_series() resp = self.client.get(self.api_url(version='1.0')) self.assertEqual(status.HTTP_200_OK, resp.status_code) self.assertEqual(1, len(resp.data)) self.assertIn('url', resp.data[0]) self.assertNotIn('web_url', resp.data[0])
def test_list_filter_project(self): """Filter events by project.""" events = self._create_events() project = events[0].project create_series() # create series in a random project resp = self.client.get(self.api_url(), {'project': project.pk}) # All but one event belongs to the same project self.assertEqual(8, len(resp.data)) resp = self.client.get(self.api_url(), {'project': 'invalidproject'}) self.assertEqual(0, len(resp.data))
def test_series_created(self): series = utils.create_series() events = _get_events(series=series) self.assertEqual(events.count(), 1) self.assertEqual(events[0].category, Event.CATEGORY_SERIES_CREATED) self.assertEqual(events[0].project, series.project) self.assertEventFields(events[0])
def test_patch_dependencies_out_of_order(self): series = utils.create_series() series_patch_3 = utils.create_series_patch(series=series, number=3) series_patch_2 = utils.create_series_patch(series=series, number=2) # This should only raise the CATEGORY_PATCH_CREATED event for # both patches as they are both missing dependencies for series_patch in [series_patch_2, series_patch_3]: events = _get_events(patch=series_patch.patch) self.assertEqual(events.count(), 1) self.assertEqual(events[0].category, Event.CATEGORY_PATCH_CREATED) self.assertEventFields(events[0]) series_patch_1 = utils.create_series_patch(series=series, number=1) # We should now see the CATEGORY_PATCH_COMPLETED event for all patches # as the dependencies for all have been met for series_patch in [series_patch_1, series_patch_2, series_patch_3]: events = _get_events(patch=series_patch.patch) self.assertEqual(events.count(), 2) self.assertEqual(events[0].category, Event.CATEGORY_PATCH_CREATED) self.assertEqual(events[1].category, Event.CATEGORY_PATCH_COMPLETED) self.assertEventFields(events[0]) self.assertEventFields(events[1])
def _create_events(self): """Create sample events. This one's a bit weird. While we could generate event models ourselves, it seems wiser to test the event machinery as many times as possible. As a result, we actually create a load of *other* objects, which will raise signals and trigger the remainder. """ # series-created series = create_series() # patch-created, patch-completed, series-completed patch = create_patch(series=series) # cover-created create_cover(series=series) # check-created create_check(patch=patch) # patch-delegated, patch-state-changed actor = create_maintainer(project=patch.project) user = create_maintainer(project=patch.project) state = create_state() patch.delegate = user patch.state = state self.assertTrue(patch.is_editable(actor)) patch.save() return Event.objects.all()
def test_patch_dependencies_out_of_order(self): series = utils.create_series() patch_3 = utils.create_patch(series=series, number=3) patch_2 = utils.create_patch(series=series, number=2) # This should only raise the CATEGORY_PATCH_CREATED event for # both patches as they are both missing dependencies for patch in [patch_2, patch_3]: events = _get_events(patch=patch) self.assertEqual(events.count(), 1) self.assertEqual(events[0].category, Event.CATEGORY_PATCH_CREATED) self.assertEventFields(events[0]) patch_1 = utils.create_patch(series=series, number=1) # We should now see the CATEGORY_PATCH_COMPLETED event for all patches # as the dependencies for all have been met for patch in [patch_1, patch_2, patch_3]: events = _get_events(patch=patch) self.assertEqual(events.count(), 2) self.assertEqual(events[0].category, Event.CATEGORY_PATCH_CREATED) self.assertEqual(events[1].category, Event.CATEGORY_PATCH_COMPLETED) self.assertEventFields(events[0]) self.assertEventFields(events[1])
def test_list_bug_335(self): """Ensure we retrieve the embedded series project in O(1).""" series = create_series() create_patches(5, series=series) with self.assertNumQueries(5): self.client.get(self.api_url())
def _create_series(self): project_obj = create_project(linkname='myproject') person_obj = create_person(email='*****@*****.**') series_obj = create_series(project=project_obj, submitter=person_obj) create_cover(series=series_obj) create_patch(series=series_obj) return series_obj
def test_detail(self): """Validate we can get a specific series.""" series = create_series() create_cover(series=series) resp = self.client.get(self.api_url(series.id)) self.assertEqual(status.HTTP_200_OK, resp.status_code) self.assertSerialized(series, resp.data)
def test_series(self): series = create_series() patch_a = create_patch(series=series) patch_b = create_patch(series=series) response = self.client.get(reverse('series-mbox', args=[series.id])) self.assertContains(response, patch_a.content) self.assertContains(response, patch_b.content)
def test_series(self): series = create_series() patch_a = create_patch(series=series) patch_b = create_patch(series=series) mbox = utils.series_to_mbox(series) self.assertIn(patch_a.content, mbox) self.assertIn(patch_b.content, mbox)
def test_patch_dependencies_missing(self): series = utils.create_series() patch = utils.create_patch(series=series, number=2) # This should only raise the CATEGORY_PATCH_CREATED event as # there is a missing dependency (patch 1) events = _get_events(patch=patch) self.assertEqual(events.count(), 1) self.assertEqual(events[0].category, Event.CATEGORY_PATCH_CREATED) self.assertEventFields(events[0])
def test_list_bug_335(self): """Ensure we retrieve the embedded series project in O(1).""" series = create_series() create_patches(5, series=series) # TODO(stephenfin): Remove when we drop support for Django < 3.2 num_queries = 7 if django.VERSION < (3, 2) else 5 with self.assertNumQueries(num_queries): self.client.get(self.api_url())
def test_list_bug_335(self): """Ensure we retrieve the embedded cover letter project in O(1).""" project_obj = create_project(linkname='myproject') person_obj = create_person(email='*****@*****.**') for i in range(10): series_obj = create_series( project=project_obj, submitter=person_obj, ) create_cover(series=series_obj) create_patch(series=series_obj) with self.assertNumQueries(6): self.client.get(self.api_url())
def test_series_dropdown(self): patch = create_patch() series = [create_series() for x in range(5)] for series_ in series: series_.add_patch(patch, 1) response = self.client.get( reverse('patch-detail', kwargs={'patch_id': patch.id})) for series_ in series: self.assertContains( response, reverse('series-mbox', kwargs={'series_id': series_.id}))
def test_detail(self): """Validate we can get a specific series.""" series = create_series() resp = self.client.get(self.api_url(series.id)) self.assertEqual(status.HTTP_200_OK, resp.status_code) self.assertSerialized(series, resp.data) patch = create_patch(project=series.project) series.add_patch(patch, 1) resp = self.client.get(self.api_url(series.id)) self.assertSerialized(series, resp.data) cover_letter = create_cover(project=series.project) series.add_cover_letter(cover_letter) resp = self.client.get(self.api_url(series.id)) self.assertSerialized(series, resp.data)
def test_create_update_delete(self): """Ensure creates, updates and deletes aren't allowed""" user = create_maintainer() user.is_superuser = True user.save() self.client.force_authenticate(user=user) resp = self.client.post(self.api_url(), {'name': 'Test'}) self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code) series = create_series() resp = self.client.patch(self.api_url(series.id), {'name': 'Test'}) self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code) resp = self.client.delete(self.api_url(series.id)) self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
def test_list(self): """Validate we can list series.""" resp = self.client.get(self.api_url()) self.assertEqual(status.HTTP_200_OK, resp.status_code) self.assertEqual(0, len(resp.data)) project_obj = create_project(linkname='myproject') person_obj = create_person(email='*****@*****.**') cover_obj = create_cover() series_obj = create_series(project=project_obj, submitter=person_obj) series_obj.add_cover_letter(cover_obj) create_series_patch(series=series_obj) # anonymous users resp = self.client.get(self.api_url()) self.assertEqual(status.HTTP_200_OK, resp.status_code) self.assertEqual(1, len(resp.data)) series_rsp = resp.data[0] self.assertSerialized(series_obj, series_rsp) # authenticated user user = create_user() self.client.force_authenticate(user=user) resp = self.client.get(self.api_url()) self.assertEqual(status.HTTP_200_OK, resp.status_code) self.assertEqual(1, len(resp.data)) series_rsp = resp.data[0] self.assertSerialized(series_obj, series_rsp) # test filtering by project resp = self.client.get(self.api_url(), {'project': 'myproject'}) self.assertEqual([series_obj.id], [x['id'] for x in resp.data]) resp = self.client.get(self.api_url(), {'project': 'invalidproject'}) self.assertEqual(0, len(resp.data)) # test filtering by owner, both ID and email resp = self.client.get(self.api_url(), {'submitter': person_obj.id}) self.assertEqual([series_obj.id], [x['id'] for x in resp.data]) resp = self.client.get(self.api_url(), {'submitter': '*****@*****.**'}) self.assertEqual([series_obj.id], [x['id'] for x in resp.data]) resp = self.client.get(self.api_url(), {'submitter': '*****@*****.**'}) self.assertEqual(0, len(resp.data))
def test_list(self): """Validate we can list series.""" resp = self.client.get(self.api_url()) self.assertEqual(status.HTTP_200_OK, resp.status_code) self.assertEqual(0, len(resp.data)) project_obj = create_project(linkname='myproject') person_obj = create_person(email='*****@*****.**') series_obj = create_series(project=project_obj, submitter=person_obj) create_cover(series=series_obj) create_patch(series=series_obj) # anonymous users resp = self.client.get(self.api_url()) self.assertEqual(status.HTTP_200_OK, resp.status_code) self.assertEqual(1, len(resp.data)) series_rsp = resp.data[0] self.assertSerialized(series_obj, series_rsp) # authenticated user user = create_user() self.client.force_authenticate(user=user) resp = self.client.get(self.api_url()) self.assertEqual(status.HTTP_200_OK, resp.status_code) self.assertEqual(1, len(resp.data)) series_rsp = resp.data[0] self.assertSerialized(series_obj, series_rsp) # test filtering by project resp = self.client.get(self.api_url(), {'project': 'myproject'}) self.assertEqual([series_obj.id], [x['id'] for x in resp.data]) resp = self.client.get(self.api_url(), {'project': 'invalidproject'}) self.assertEqual(0, len(resp.data)) # test filtering by owner, both ID and email resp = self.client.get(self.api_url(), {'submitter': person_obj.id}) self.assertEqual([series_obj.id], [x['id'] for x in resp.data]) resp = self.client.get(self.api_url(), { 'submitter': '*****@*****.**'}) self.assertEqual([series_obj.id], [x['id'] for x in resp.data]) resp = self.client.get(self.api_url(), { 'submitter': '*****@*****.**'}) self.assertEqual(0, len(resp.data))
def test_series_completed(self): """Validate 'series-completed' events.""" series = utils.create_series(total=2) # the series has no patches associated with it so it's not yet complete events = _get_events(series=series) self.assertNotIn(Event.CATEGORY_SERIES_COMPLETED, [x.category for x in events]) # create the second of two patches in the series; series is still not # complete utils.create_patch(series=series, number=2) events = _get_events(series=series) self.assertNotIn(Event.CATEGORY_SERIES_COMPLETED, [x.category for x in events]) # now create the first patch, which will "complete" the series utils.create_patch(series=series, number=1) events = _get_events(series=series) self.assertIn(Event.CATEGORY_SERIES_COMPLETED, [x.category for x in events])
def test_list(self): """Validate we can list series.""" resp = self.client.get(self.api_url()) self.assertEqual(status.HTTP_200_OK, resp.status_code) self.assertEqual(0, len(resp.data)) series = create_series() # anonymous user resp = self.client.get(self.api_url()) self.assertEqual(status.HTTP_200_OK, resp.status_code) self.assertEqual(1, len(resp.data)) self.assertSerialized(series, resp.data[0]) # authenticated user user = create_user() self.client.force_authenticate(user=user) resp = self.client.get(self.api_url()) self.assertEqual(status.HTTP_200_OK, resp.status_code) self.assertEqual(1, len(resp.data)) self.assertSerialized(series, resp.data[0])
def test_patch_dependencies_present_series(self): """Patch dependencies already exist.""" series = utils.create_series() patch = utils.create_patch(series=series) # This should raise both the CATEGORY_PATCH_CREATED and # CATEGORY_PATCH_COMPLETED events events = _get_events(patch=patch) self.assertEqual(events.count(), 2) self.assertEqual(events[0].category, Event.CATEGORY_PATCH_CREATED) self.assertEqual(events[0].project, patch.project) self.assertEqual(events[1].category, Event.CATEGORY_PATCH_COMPLETED) self.assertEqual(events[1].project, patch.project) self.assertEventFields(events[0]) self.assertEventFields(events[1]) # This shouldn't be affected by another update to the patch patch.commit_ref = 'aac76f0b0f8dd657ff07bb32df369705696d4831' patch.save() events = _get_events(patch=patch) self.assertEqual(events.count(), 2)
def test_detail_version_1_0(self): series = create_series() resp = self.client.get(self.api_url(series.id, version='1.0')) self.assertIn('url', resp.data) self.assertNotIn('web_url', resp.data)
def _create_patches(): series = create_series() patch_a = create_patch(series=series) patch_b = create_patch(series=series) return series, patch_a, patch_b