class MboxGeneratedHeaderTest(TestCase): fixtures = ['default_states', 'default_events'] def setUp(self): defaults.project.save() self.person = defaults.patch_author_person self.person.save() self.user = create_user() self.patch = Patch(project=defaults.project, msgid='p1', name='testpatch', submitter=self.person, delegate=self.user, content='') self.patch.save() def testPatchworkIdHeader(self): response = self.client.get('/patch/%d/mbox/' % self.patch.id) self.assertContains(response, 'X-Patchwork-Id: %d' % self.patch.id) def testPatchworkDelegateHeader(self): response = self.client.get('/patch/%d/mbox/' % self.patch.id) self.assertContains(response, 'X-Patchwork-Delegate: %s' % self.user.email)
class MboxPassThroughHeaderTest(TestCase): """ Test that we see 'Cc' and 'To' headers passed through from original message to mbox view """ def setUp(self): defaults.project.save() self.person = defaults.patch_author_person self.person.save() self.cc_header = 'Cc: CC Person <*****@*****.**>' self.to_header = 'To: To Person <*****@*****.**>' self.patch = Patch(project = defaults.project, msgid = 'p1', name = 'testpatch', submitter = self.person, content = '') def testCCHeader(self): self.patch.headers = self.cc_header + '\n' self.patch.save() response = self.client.get('/patch/%d/mbox/' % self.patch.id) self.assertContains(response, self.cc_header) def testToHeader(self): self.patch.headers = self.to_header + '\n' self.patch.save() response = self.client.get('/patch/%d/mbox/' % self.patch.id) self.assertContains(response, self.to_header)
class MboxGeneratedHeaderTest(TestCase): fixtures = ['default_states'] def setUp(self): defaults.project.save() self.person = defaults.patch_author_person self.person.save() self.user = create_user() self.patch = Patch(project=defaults.project, msgid='p1', name='testpatch', submitter=self.person, delegate=self.user, content='') self.patch.save() def testPatchworkIdHeader(self): response = self.client.get('/patch/%d/mbox/' % self.patch.id) self.assertContains(response, 'X-Patchwork-Id: %d' % self.patch.id) def testPatchworkDelegateHeader(self): response = self.client.get('/patch/%d/mbox/' % self.patch.id) self.assertContains(response, 'X-Patchwork-Delegate: %s' % self.user.email)
class UTF8HeaderPatchViewTest(UTF8PatchViewTest): fixtures = ['default_states', 'default_events'] patch_filename = '0002-utf-8.patch' patch_encoding = 'utf-8' patch_author_name = u'P\xe4tch Author' def setUp(self): defaults.project.save() self.patch_author = Person(name=self.patch_author_name, email=defaults.patch_author_person.email) self.patch_author.save() self.patch_content = read_patch(self.patch_filename, encoding=self.patch_encoding) self.patch = Patch(project=defaults.project, msgid='x', name=defaults.patch_name, submitter=self.patch_author, content=self.patch_content) self.patch.save() self.client = Client() def tearDown(self): self.patch.delete() self.patch_author.delete() defaults.project.delete()
class MboxCommentPostcriptUnchangedTest(TestCase): fixtures = ['default_states', 'default_events'] """ Test that the mbox view doesn't change the postscript part of a mail. There where always a missing blank right after the postscript delimiter '---' and an additional newline right before. """ def setUp(self): defaults.project.save() self.person = defaults.patch_author_person self.person.save() self.patch = Patch(project=defaults.project, msgid='p1', name='testpatch', submitter=self.person, content='') self.patch.save() self.txt = 'some comment\n---\n some/file | 1 +\n' comment = Comment(patch=self.patch, msgid='p1', submitter=self.person, content=self.txt) comment.save() def testCommentUnchanged(self): response = self.client.get('/patch/%d/mbox/' % self.patch.id) self.assertContains(response, self.txt) self.txt += "\n" self.assertNotContains(response, self.txt)
def _insert_patch(self): patch = Patch(project=defaults.project, submitter=defaults.patch_author_person, msgid=defaults.patch_name, content=defaults.patch) patch.save() return patch
class MboxPatchSplitResponseTest(TestCase): fixtures = ['default_states', 'default_events'] """ Test that the mbox view appends the Acked-by from a patch comment, and places it before an '---' update line. """ def setUp(self): defaults.project.save() self.person = defaults.patch_author_person self.person.save() self.patch = Patch(project=defaults.project, msgid='p1', name='testpatch', submitter=self.person, content='') self.patch.save() comment = Comment(patch=self.patch, msgid='p1', submitter=self.person, content='comment 1 text\nAcked-by: 1\n---\nupdate\n') comment.save() comment = Comment(patch=self.patch, msgid='p2', submitter=self.person, content='comment 2 text\nAcked-by: 2\n') comment.save() def testPatchResponse(self): response = self.client.get('/patch/%d/mbox/' % self.patch.id) self.assertContains(response, 'Acked-by: 1\nAcked-by: 2\n')
class MboxPatchResponseTest(TestCase): fixtures = ['default_states'] """ Test that the mbox view appends the Acked-by from a patch comment """ def setUp(self): defaults.project.save() self.person = defaults.patch_author_person self.person.save() self.patch = Patch(project=defaults.project, msgid='p1', name='testpatch', submitter=self.person, diff='', content='comment 1 text\nAcked-by: 1\n') self.patch.save() comment = Comment(submission=self.patch, msgid='p2', submitter=self.person, content='comment 2 text\nAcked-by: 2\n') comment.save() def testPatchResponse(self): response = self.client.get('/patch/%d/mbox/' % self.patch.id) self.assertContains(response, 'Acked-by: 1\nAcked-by: 2\n')
def setUp(self): defaults.project.save() self.user = create_maintainer(defaults.project) self.client.login(username=self.user.username, password=self.user.username) self.properties_form_id = 'patchform-properties' self.url = reverse('patchwork.views.patch.list', args=[defaults.project.linkname]) self.base_data = { 'action': 'Update', 'project': str(defaults.project.id), 'form': 'patchlistform', 'archived': '*', 'delegate': '*', 'state': '*' } self.patches = [] for name in ['patch one', 'patch two', 'patch three']: patch = Patch(project=defaults.project, msgid=name, name=name, content='', submitter=Person.objects.get(user=self.user)) patch.save() self.patches.append(patch)
class MboxCommentPostcriptUnchangedTest(TestCase): """ Test that the mbox view doesn't change the postscript part of a mail. There where always a missing blank right after the postscript delimiter '---' and an additional newline right before. """ def setUp(self): defaults.project.save() self.person = defaults.patch_author_person self.person.save() self.patch = Patch(project = defaults.project, msgid = 'p1', name = 'testpatch', submitter = self.person, content = '') self.patch.save() self.txt = 'some comment\n---\n some/file | 1 +\n' comment = Comment(patch = self.patch, msgid = 'p1', submitter = self.person, content = self.txt) comment.save() def testCommentUnchanged(self): response = self.client.get('/patch/%d/mbox/' % self.patch.id) self.assertContains(response, self.txt) self.txt += "\n" self.assertNotContains(response, self.txt)
class MboxDateHeaderTest(TestCase): """ Test that the date provided in the patch mail view is correct """ def setUp(self): defaults.project.save() self.person = defaults.patch_author_person self.person.save() self.patch = Patch(project = defaults.project, msgid = 'p1', name = 'testpatch', submitter = self.person, content = '') self.patch.save() def testDateHeader(self): response = self.client.get('/patch/%d/mbox/' % self.patch.id) mail = email.message_from_string(response.content) mail_date = dateutil.parser.parse(mail['Date']) # patch dates are all in UTC patch_date = self.patch.date.replace(tzinfo=dateutil.tz.tzutc(), microsecond=0) self.assertEqual(mail_date, patch_date) def testSuppliedDateHeader(self): hour_offset = 3 tz = dateutil.tz.tzoffset(None, hour_offset * 60 * 60) date = datetime.datetime.utcnow() - datetime.timedelta(days = 1) date = date.replace(tzinfo=tz, microsecond=0) self.patch.headers = 'Date: %s\n' % date.strftime("%a, %d %b %Y %T %z") self.patch.save() response = self.client.get('/patch/%d/mbox/' % self.patch.id) mail = email.message_from_string(response.content) mail_date = dateutil.parser.parse(mail['Date']) self.assertEqual(mail_date, date)
class MboxPatchSplitResponseTest(TestCase): """ Test that the mbox view appends the Acked-by from a patch comment, and places it before an '---' update line. """ def setUp(self): defaults.project.save() self.person = defaults.patch_author_person self.person.save() self.patch = Patch(project = defaults.project, msgid = 'p1', name = 'testpatch', submitter = self.person, content = '') self.patch.save() comment = Comment(patch = self.patch, msgid = 'p1', submitter = self.person, content = 'comment 1 text\nAcked-by: 1\n---\nupdate\n') comment.save() comment = Comment(patch = self.patch, msgid = 'p2', submitter = self.person, content = 'comment 2 text\nAcked-by: 2\n') comment.save() def testPatchResponse(self): response = self.client.get('/patch/%d/mbox/' % self.patch.id) self.assertContains(response, 'Acked-by: 1\nAcked-by: 2\n')
def _insert_patch(self): patch = Patch(project=defaults.project, submitter=defaults.patch_author_person, msgid=make_msgid(), content=defaults.patch, date=self.last_patch_ts) self.last_patch_ts += datetime.timedelta(0, 1) patch.save() return patch
def setUp(self): defaults.project.save() for (name, email, date) in self.patchmeta: patch_name = 'testpatch' + name person = Person(name = name, email = email) person.save() patch = Patch(project = defaults.project, msgid = patch_name, submitter = person, content = '', date = date) patch.save()
def setUp(self): defaults.project.save() self.person = defaults.patch_author_person self.person.save() self.patch = Patch(project=defaults.project, msgid='p1', name='testpatch', submitter=self.person, content='') self.patch.save()
def setUp(self): self.project = defaults.project self.project.send_notifications = True self.project.save() self.submitter = defaults.patch_author_person self.submitter.save() self.patch = Patch(project=self.project, msgid='testpatch', name='testpatch', content='', submitter=self.submitter)
def setUp(self): project = Project(linkname='test-project', name='Test Project', use_tags=True) project.save() defaults.patch_author_person.save() self.patch = Patch(project=project, msgid='x', name=defaults.patch_name, submitter=defaults.patch_author_person, content='') self.patch.save() self.tagger = 'Test Tagger <*****@*****.**>'
def testList(self): defaults.project.save() defaults.patch_author_person.save() patch = Patch(project=defaults.project, submitter=defaults.patch_author_person, msgid=defaults.patch_name, content=defaults.patch) patch.save() patches = self.rpc.patch_list() self.assertEqual(len(patches), 1) self.assertEqual(patches[0]['id'], patch.id)
def testList(self): defaults.project.save() defaults.patch_author_person.save() patch = Patch(project = defaults.project, submitter = defaults.patch_author_person, msgid = defaults.patch_name, content = defaults.patch) patch.save() patches = self.rpc.patch_list() self.assertEqual(len(patches), 1) self.assertEqual(patches[0]['id'], patch.id)
def setUp(self): defaults.project.save() defaults.patch_author_person.save() self.patch_content = read_patch(self.patch_filename, encoding=self.patch_encoding) self.patch = Patch(project=defaults.project, msgid='x', name=defaults.patch_name, submitter=defaults.patch_author_person, content=self.patch_content) self.patch.save() self.client = Client()
def setUp(self): defaults.project.save() for (name, email, date) in self.patchmeta: patch_name = 'testpatch' + name person = Person(name=name, email=email) person.save() patch = Patch(project=defaults.project, msgid=patch_name, submitter=person, content='', date=date) patch.save()
def testWithChangedPersonName(self): self.patch = Patch(project=defaults.project, msgid='p1', name='testpatch', submitter=self.person, content='', headers='From: {}'.format(self.original_author)) self.patch.save() response = self.client.get('/patch/%d/mbox/' % self.patch.id) self.assertContains(response, 'From: {}'.format(self.original_author)) self.assertNotContains(response, self.person.name) self.assertNotContains(response, self.person.email)
def testWithoutTheHeaderFallback(self): """ this should fallback to the Person """ self.patch = Patch(project=defaults.project, msgid='p1', name='testpatch', submitter=self.person, content='', headers='') self.patch.save() response = self.client.get('/patch/%d/mbox/' % self.patch.id) self.assertContains( response, 'From: {} <{}>'.format(self.person.name, self.person.email))
def setUp(self): defaults.project.save() self.person = defaults.patch_author_person self.person.save() self.cc_header = 'Cc: CC Person <*****@*****.**>' self.to_header = 'To: To Person <*****@*****.**>' self.date_header = 'Date: Fri, 7 Jun 2013 15:42:54 +1000' self.patch = Patch(project=defaults.project, msgid='p1', name='testpatch', submitter=self.person, content='')
def create_patches(count=1): """Create 'count' unique patches.""" defaults.project.save() defaults.patch_author_person.save() patches = [] for i in range(0, count): patch = Patch(project=defaults.project, submitter=defaults.patch_author_person, msgid=make_msgid(), name='testpatch%d' % (i + 1), diff=defaults.patch) patch.save() patches.append(patch) return patches
def testPatchSubmitterExpiry(self): defaults.project.save() defaults.patch_author_person.save() # someone submits a patch... patch = Patch(project=defaults.project, msgid='*****@*****.**', name='test patch', submitter=defaults.patch_author_person, content=defaults.patch) patch.save() # ... then starts registration... date = ((datetime.datetime.now() - EmailConfirmation.validity) - datetime.timedelta(hours=1)) userid = 'test-user' user = User.objects.create_user(userid, defaults.patch_author_person.email, userid) user.is_active = False user.date_joined = user.last_login = date user.save() self.assertEqual(user.email, patch.submitter.email) conf = EmailConfirmation(type='registration', user=user, email=user.email) conf.date = date conf.save() # ... which expires do_expiry() # we should see no matching user self.assertFalse( User.objects.filter(email=patch.submitter.email).exists()) # but the patch and person should still be present self.assertTrue( Person.objects.filter(pk=defaults.patch_author_person.pk).exists()) self.assertTrue(Patch.objects.filter(pk=patch.pk).exists()) # and there should be no user associated with the person self.assertEqual( Person.objects.get(pk=defaults.patch_author_person.pk).user, None)
def setUp(self, patch_count=3): patch_names = ['testpatch%d' % (i) for i in range(1, patch_count+1)] self.user = create_user() self.client.login(username = self.user.username, password = self.user.username) defaults.project.save() self.bundle = Bundle(owner = self.user, project = defaults.project, name = 'testbundle') self.bundle.save() self.patches = [] for patch_name in patch_names: patch = Patch(project = defaults.project, msgid = patch_name, name = patch_name, submitter = Person.objects.get(user = self.user), content = '') patch.save() self.patches.append(patch)
def setUp(self): self.project = defaults.project self.project.send_notifications = True self.project.save() self.submitter = defaults.patch_author_person self.submitter.save() self.patch = Patch(project = self.project, msgid = 'testpatch', name = 'testpatch', content = '', submitter = self.submitter)
def setUp(self): defaults.project.save() self.person = defaults.patch_author_person self.person.save() self.patch = Patch(project = defaults.project, msgid = 'p1', name = 'testpatch', submitter = self.person, content = '') self.patch.save()
def setUp(self): project = defaults.project defaults.project.save() defaults.patch_author_person.save() self.patch = Patch(project=project, msgid='x', name=defaults.patch_name, submitter=defaults.patch_author_person, diff='') self.patch.save() self.user = create_user()
def assertTagsEqual(self, str, acks, reviews, tests): # noqa counts = Patch.extract_tags(str, Tag.objects.all()) self.assertEqual( (acks, reviews, tests), ( counts[Tag.objects.get(name='Acked-by')], counts[Tag.objects.get(name='Reviewed-by')], counts[Tag.objects.get(name='Tested-by')], ), )
def testPatchSubmitterExpiry(self): defaults.project.save() defaults.patch_author_person.save() # someone submits a patch... patch = Patch(project=defaults.project, msgid='*****@*****.**', name='test patch', submitter=defaults.patch_author_person, content=defaults.patch) patch.save() # ... then starts registration... date = ((datetime.datetime.now() - EmailConfirmation.validity) - datetime.timedelta(hours=1)) userid = 'test-user' user = User.objects.create_user( userid, defaults.patch_author_person.email, userid) user.is_active = False user.date_joined = user.last_login = date user.save() self.assertEqual(user.email, patch.submitter.email) conf = EmailConfirmation(type='registration', user=user, email=user.email) conf.date = date conf.save() # ... which expires do_expiry() # we should see no matching user self.assertFalse(User.objects.filter(email=patch.submitter.email) .exists()) # but the patch and person should still be present self.assertTrue(Person.objects.filter( pk=defaults.patch_author_person.pk).exists()) self.assertTrue(Patch.objects.filter(pk=patch.pk).exists()) # and there should be no user associated with the person self.assertEqual(Person.objects.get( pk=defaults.patch_author_person.pk).user, None)
def setUp(self): defaults.project.save() self.user = create_maintainer(defaults.project) self.client.login(username = self.user.username, password = self.user.username) self.properties_form_id = 'patchform-properties' self.url = reverse( 'patchwork.views.patch.list', args = [defaults.project.linkname]) self.base_data = { 'action': 'Update', 'project': str(defaults.project.id), 'form': 'patchlistform', 'archived': '*', 'delegate': '*', 'state': '*'} self.patches = [] for name in ['patch one', 'patch two', 'patch three']: patch = Patch(project = defaults.project, msgid = name, name = name, content = '', submitter = Person.objects.get(user = self.user)) patch.save() self.patches.append(patch)
def create_patch(**kwargs): """Create 'Patch' object.""" num = Patch.objects.count() values = { 'submitter': create_person(), 'delegate': None, 'project': create_project(), 'msgid': make_msgid(), 'name': 'testpatch%d' % num, 'headers': '', 'content': '', 'diff': SAMPLE_DIFF, } values.update(kwargs) patch = Patch(**values) patch.save() return patch
def setUp(self): defaults.project.save() defaults.patch_author_person.save() self.patch_content = read_patch(self.patch_filename, encoding = self.patch_encoding) self.patch = Patch(project = defaults.project, msgid = 'x', name = defaults.patch_name, submitter = defaults.patch_author_person, content = self.patch_content) self.patch.save() self.client = Client()
def testPullRequestEvent(self): submitter = Person() submitter.save() patch = Patch(project=self.project, pull_url="git://foo.bar master", submitter=submitter) patch.save() # n events for n series, +1 for the pull request above events = self.get_json('/projects/%(project_id)s/events/') self.assertEqual(events['count'], self.n_series + 1) prs = filter(lambda r: r['name'] == 'pull-request-new', events['results']) prs = list(prs) self.assertEqual(len(prs), 1) self.assertEqual(prs[0]['patch'], patch.id) self.assertEqual(prs[0]['parameters']['pull_url'], patch.pull_url)
def setUp(self): defaults.project.save() self.person = defaults.patch_author_person self.person.save() self.patch = Patch(project=defaults.project, msgid='p1', name='testpatch', submitter=self.person, content='') self.patch.save() self.txt = 'some comment\n---\n some/file | 1 +\n' comment = Comment(patch=self.patch, msgid='p1', submitter=self.person, content=self.txt) comment.save()
def setUp(self): defaults.project.save() self.person = defaults.patch_author_person self.person.save() self.cc_header = 'Cc: CC Person <*****@*****.**>' self.to_header = 'To: To Person <*****@*****.**>' self.patch = Patch(project = defaults.project, msgid = 'p1', name = 'testpatch', submitter = self.person, content = '')
class MboxAuthorship(TestCase): fixtures = ['default_states', 'default_events'] """ Test that the From in mbox is the same as in the original header """ def setUp(self): defaults.project.save() self.original_author = "Orignal Author <*****@*****.**>" self.person = defaults.patch_author_person self.person.name = "Changed Name" self.person.email = "*****@*****.**" self.person.save() def testWithChangedPersonName(self): self.patch = Patch(project=defaults.project, msgid='p1', name='testpatch', submitter=self.person, content='', headers='From: {}'.format(self.original_author)) self.patch.save() response = self.client.get('/patch/%d/mbox/' % self.patch.id) self.assertContains(response, 'From: {}'.format(self.original_author)) self.assertNotContains(response, self.person.name) self.assertNotContains(response, self.person.email) def testWithoutTheHeaderFallback(self): """ this should fallback to the Person """ self.patch = Patch(project=defaults.project, msgid='p1', name='testpatch', submitter=self.person, content='', headers='') self.patch.save() response = self.client.get('/patch/%d/mbox/' % self.patch.id) self.assertContains( response, 'From: {} <{}>'.format(self.person.name, self.person.email))
def setUp(self): defaults.project.save() self.person = defaults.patch_author_person self.person.save() self.txt = 'some comment\n---\n some/file | 1 +\n' self.patch = Patch(project=defaults.project, msgid='p1', name='testpatch', submitter=self.person, diff='', content=self.txt) self.patch.save()
class MboxBrokenFromHeaderTest(TestCase): """ Test that a person with characters outside ASCII in his name do produce correct From header. As RFC 2822 state we must retain the <*****@*****.**> format for the mail while the name part may be coded in some ways. """ def setUp(self): defaults.project.save() self.person = defaults.patch_author_person self.person.name = u'©ool guŷ' self.person.save() self.patch = Patch(project = defaults.project, msgid = 'p1', name = 'testpatch', submitter = self.person, content = '') def testFromHeader(self): self.patch.save() from_email = '<' + self.person.email + '>' response = self.client.get('/patch/%d/mbox/' % self.patch.id) self.assertContains(response, from_email)
class UTF8PatchViewTest(TestCase): fixtures = ['default_states', 'default_events'] patch_filename = '0002-utf-8.patch' patch_encoding = 'utf-8' def setUp(self): defaults.project.save() defaults.patch_author_person.save() self.patch_content = read_patch(self.patch_filename, encoding=self.patch_encoding) self.patch = Patch(project=defaults.project, msgid='x', name=defaults.patch_name, submitter=defaults.patch_author_person, content=self.patch_content) self.patch.save() self.client = Client() def testPatchView(self): response = self.client.get('/patch/%d/' % self.patch.id) self.assertContains(response, self.patch.name) def testMboxView(self): response = self.client.get('/patch/%d/mbox/' % self.patch.id) self.assertEqual(response.status_code, 200) self.assertTrue( self.patch.content in response.content.decode(self.patch_encoding)) def testRawView(self): response = self.client.get('/patch/%d/raw/' % self.patch.id) self.assertEqual(response.status_code, 200) self.assertEqual(response.content.decode(self.patch_encoding), self.patch.content) def tearDown(self): self.patch.delete() defaults.patch_author_person.delete() defaults.project.delete()
class MboxPatchworkLink(TestCase): fixtures = ['default_states', 'default_events'] """ Test that the mbox view appends the patch link """ def setUp(self): defaults.project.save() self.person = defaults.patch_author_person self.person.save() self.patch = Patch(project=defaults.project, msgid='p1', name='testpatch', submitter=self.person, content='') self.patch.save() def testPatchResponse(self): response = self.client.get('/patch/%d/mbox/' % self.patch.id, {'link': 'Patchwork'}) m = re.search(r'^Patchwork:.*/%d/$' % self.patch.pk, response.content, re.M) self.assertTrue(m)
class UTF8HeaderPatchViewTest(UTF8PatchViewTest): patch_filename = '0002-utf-8.patch' patch_encoding = 'utf-8' patch_author_name = u'P\xe4tch Author' def setUp(self): defaults.project.save() self.patch_author = Person(name = self.patch_author_name, email = defaults.patch_author_person.email) self.patch_author.save() self.patch_content = read_patch(self.patch_filename, encoding = self.patch_encoding) self.patch = Patch(project = defaults.project, msgid = 'x', name = defaults.patch_name, submitter = self.patch_author, content = self.patch_content) self.patch.save() self.client = Client() def tearDown(self): self.patch.delete() self.patch_author.delete() defaults.project.delete()
def setUp(self): defaults.project.save() self.person = defaults.patch_author_person self.person.save() self.patch = Patch(project=defaults.project, msgid='p1', name='testpatch', submitter=self.person, content='') self.patch.save() comment = Comment(patch=self.patch, msgid='p1', submitter=self.person, content='comment 1 text\nAcked-by: 1\n---\nupdate\n') comment.save() comment = Comment(patch=self.patch, msgid='p2', submitter=self.person, content='comment 2 text\nAcked-by: 2\n') comment.save()
class UTF8PatchViewTest(TestCase): fixtures = ['default_states', 'default_events'] patch_filename = '0002-utf-8.patch' patch_encoding = 'utf-8' def setUp(self): defaults.project.save() defaults.patch_author_person.save() self.patch_content = read_patch(self.patch_filename, encoding = self.patch_encoding) self.patch = Patch(project = defaults.project, msgid = 'x', name = defaults.patch_name, submitter = defaults.patch_author_person, content = self.patch_content) self.patch.save() self.client = Client() def testPatchView(self): response = self.client.get('/patch/%d/' % self.patch.id) self.assertContains(response, self.patch.name) def testMboxView(self): response = self.client.get('/patch/%d/mbox/' % self.patch.id) self.assertEquals(response.status_code, 200) self.assertTrue(self.patch.content in \ response.content.decode(self.patch_encoding)) def testRawView(self): response = self.client.get('/patch/%d/raw/' % self.patch.id) self.assertEquals(response.status_code, 200) self.assertEquals(response.content.decode(self.patch_encoding), self.patch.content) def tearDown(self): self.patch.delete() defaults.patch_author_person.delete() defaults.project.delete()
class MboxDateHeaderTest(TestCase): fixtures = ['default_states', 'default_events'] """ Test that the date provided in the patch mail view is correct """ def setUp(self): defaults.project.save() self.person = defaults.patch_author_person self.person.save() self.patch = Patch(project=defaults.project, msgid='p1', name='testpatch', submitter=self.person, content='') self.patch.save() def testDateHeader(self): response = self.client.get('/patch/%d/mbox/' % self.patch.id) mail = email.message_from_string(response.content) mail_date = dateutil.parser.parse(mail['Date']) # patch dates are all in UTC patch_date = self.patch.date.replace(tzinfo=dateutil.tz.tzutc(), microsecond=0) self.assertEqual(mail_date, patch_date) def testSuppliedDateHeader(self): hour_offset = 3 tz = dateutil.tz.tzoffset(None, hour_offset * 60 * 60) date = datetime.datetime.utcnow() - datetime.timedelta(days=1) date = date.replace(tzinfo=tz, microsecond=0) self.patch.headers = 'Date: %s\n' % date.strftime("%a, %d %b %Y %T %z") self.patch.save() response = self.client.get('/patch/%d/mbox/' % self.patch.id) mail = email.message_from_string(response.content) mail_date = dateutil.parser.parse(mail['Date']) self.assertEqual(mail_date, date)
class MboxBrokenFromHeaderTest(TestCase): fixtures = ['default_states', 'default_events'] """ Test that a person with characters outside ASCII in his name do produce correct From header. As RFC 2822 state we must retain the <*****@*****.**> format for the mail while the name part may be coded in some ways. """ def setUp(self): defaults.project.save() self.person = defaults.patch_author_person self.person.name = u'©ool guŷ' self.person.save() self.patch = Patch(project=defaults.project, msgid='p1', name='testpatch', submitter=self.person, content='') def testFromHeader(self): self.patch.save() from_email = '<' + self.person.email + '>' response = self.client.get('/patch/%d/mbox/' % self.patch.id) self.assertContains(response, from_email)
def setUp(self): defaults.project.save() self.person = defaults.patch_author_person self.person.save() self.patch = Patch(project=defaults.project, msgid='p1', name='testpatch', submitter=self.person, diff='', content='comment 1 text\nAcked-by: 1\n') self.patch.save() comment = Comment(submission=self.patch, msgid='p2', submitter=self.person, content='comment 2 text\nAcked-by: 2\n') comment.save()
def testUnexpiredNotificationMerge(self): """Test that when there are multiple pending notifications, with at least one within the notification delay, that other notifications are held""" patches = [ self.patch, Patch(project=self.project, msgid='testpatch-2', name='testpatch 2', content='', submitter=self.submitter) ] for patch in patches: patch.save() PatchChangeNotification(patch=patch, orig_state=patch.state).save() self.assertEquals(PatchChangeNotification.objects.count(), len(patches)) self._expireNotifications() # update one notification, to bring it out of the notification delay patches[0].state = State.objects.exclude(pk=patches[0].state.pk)[0] patches[0].save() # the updated notification should prevent the other from being sent errors = send_notifications() self.assertEquals(errors, []) self.assertEquals(len(mail.outbox), 0) # expire the updated notification self._expireNotifications() errors = send_notifications() self.assertEquals(errors, []) self.assertEquals(len(mail.outbox), 1) msg = mail.outbox[0] self.assertTrue(patches[0].get_absolute_url() in msg.body) self.assertTrue(patches[1].get_absolute_url() in msg.body)
def testNotificationMerge(self): patches = [ self.patch, Patch(project=self.project, msgid='testpatch-2', name='testpatch 2', content='', submitter=self.submitter) ] for patch in patches: patch.save() PatchChangeNotification(patch=patch, orig_state=patch.state).save() self.assertEqual(PatchChangeNotification.objects.count(), len(patches)) self._expireNotifications() errors = send_notifications() self.assertEqual(errors, []) self.assertEqual(len(mail.outbox), 1) msg = mail.outbox[0] self.assertIn(patches[0].get_absolute_url(), msg.body) self.assertIn(patches[1].get_absolute_url(), msg.body)
class MboxPassThroughHeaderTest(TestCase): fixtures = ['default_states', 'default_events'] """ Test that we see 'Cc' and 'To' headers passed through from original message to mbox view """ def setUp(self): defaults.project.save() self.person = defaults.patch_author_person self.person.save() self.cc_header = 'Cc: CC Person <*****@*****.**>' self.to_header = 'To: To Person <*****@*****.**>' self.date_header = 'Date: Fri, 7 Jun 2013 15:42:54 +1000' self.patch = Patch(project=defaults.project, msgid='p1', name='testpatch', submitter=self.person, content='') def testCCHeader(self): self.patch.headers = self.cc_header + '\n' self.patch.save() response = self.client.get('/patch/%d/mbox/' % self.patch.id) self.assertContains(response, self.cc_header) def testToHeader(self): self.patch.headers = self.to_header + '\n' self.patch.save() response = self.client.get('/patch/%d/mbox/' % self.patch.id) self.assertContains(response, self.to_header) def testDateHeader(self): self.patch.headers = self.date_header + '\n' self.patch.save() response = self.client.get('/patch/%d/mbox/' % self.patch.id) self.assertContains(response, self.date_header)
def parse_mail(mail, list_id=None): """Parse a mail and add to the database. Args: mail (`mbox.Mail`): Mail to parse and add. list_id (str): Mailing list ID Returns: None """ # some basic sanity checks if 'From' not in mail: raise ValueError("Missing 'From' header") if 'Subject' not in mail: raise ValueError("Missing 'Subject' header") if 'Message-Id' not in mail: raise ValueError("Missing 'Message-Id' header") hint = clean_header(mail.get('X-Patchwork-Hint', '')) if hint and hint.lower() == 'ignore': logger.debug("Ignoring email due to 'ignore' hint") return if list_id: project = find_project_by_id(list_id) else: project = find_project_by_header(mail) if project is None: logger.error('Failed to find a project for email') return # parse metadata msgid = clean_header(mail.get('Message-Id')) if not msgid: raise ValueError("Broken 'Message-Id' header") msgid = msgid[:255] author = find_author(mail) subject = mail.get('Subject') name, prefixes = clean_subject(subject, [project.linkname]) is_comment = subject_check(subject) x, n = parse_series_marker(prefixes) version = parse_version(name, prefixes) refs = find_references(mail) date = find_date(mail) headers = find_headers(mail) # parse content if not is_comment: diff, message = find_patch_content(mail) else: diff, message = find_comment_content(mail) if not (diff or message): return # nothing to work with pull_url = parse_pull_request(message) # build objects if not is_comment and (diff or pull_url): # patches or pull requests # we delay the saving until we know we have a patch. author.save() delegate = find_delegate_by_header(mail) if not delegate and diff: filenames = find_filenames(diff) delegate = find_delegate_by_filename(project, filenames) # if we don't have a series marker, we will never have an existing # series to match against. series = None if n: series = find_series(project, mail) else: x = n = 1 # We will create a new series if: # - there is no existing series to assign this patch to, or # - there is an existing series, but it already has a patch with this # number in it if not series or ( SeriesPatch.objects.filter(series=series, number=x).count()): series = Series(project=project, date=date, submitter=author, version=version, total=n) series.save() # NOTE(stephenfin) We must save references for series. We # do this to handle the case where a later patch is # received first. Without storing references, it would not # be possible to identify the relationship between patches # as the earlier patch does not reference the later one. for ref in refs + [msgid]: ref = ref[:255] # we don't want duplicates try: # we could have a ref to a previous series. (For # example, a series sent in reply to another # series.) That should not create a series ref # for this series, so check for the msg-id only, # not the msg-id/series pair. SeriesReference.objects.get(msgid=ref, series__project=project) except SeriesReference.DoesNotExist: SeriesReference.objects.create(series=series, msgid=ref) patch = Patch( msgid=msgid, project=project, name=name[:255], date=date, headers=headers, submitter=author, content=message, diff=diff, pull_url=pull_url, delegate=delegate, state=find_state(mail)) patch.save() logger.debug('Patch saved') # add to a series if we have found one, and we have a numbered # patch. Don't add unnumbered patches (for example diffs sent # in reply, or just messages with random refs/in-reply-tos) if series and x: series.add_patch(patch, x) return patch elif x == 0: # (potential) cover letters # if refs are empty, it's implicitly a cover letter. If not, # however, we need to see if a match already exists and, if # not, assume that it is indeed a new cover letter is_cover_letter = False if not is_comment: if not refs == []: try: CoverLetter.objects.all().get(name=name) except CoverLetter.DoesNotExist: # if no match, this is a new cover letter is_cover_letter = True except CoverLetter.MultipleObjectsReturned: # if multiple cover letters are found, just ignore pass else: is_cover_letter = True if is_cover_letter: author.save() # we don't use 'find_series' here as a cover letter will # always be the first item in a thread, thus the references # could only point to a different series or unrelated # message try: series = SeriesReference.objects.get( msgid=msgid, series__project=project).series except SeriesReference.DoesNotExist: series = None if not series: series = Series(project=project, date=date, submitter=author, version=version, total=n) series.save() # we don't save the in-reply-to or references fields # for a cover letter, as they can't refer to the same # series SeriesReference.objects.get_or_create(series=series, msgid=msgid) cover_letter = CoverLetter( msgid=msgid, project=project, name=name[:255], date=date, headers=headers, submitter=author, content=message) cover_letter.save() logger.debug('Cover letter saved') series.add_cover_letter(cover_letter) return cover_letter # comments # we only save comments if we have the parent email submission = find_submission_for_comment(project, refs) if not submission: return author.save() comment = Comment( submission=submission, msgid=msgid, date=date, headers=headers, submitter=author, content=message) comment.save() logger.debug('Comment saved') return comment
class PatchTagsTest(TransactionTestCase): ACK = 1 REVIEW = 2 TEST = 3 fixtures = ['default_tags', 'default_states'] def assertTagsEqual(self, patch, acks, reviews, tests): patch = Patch.objects.get(pk=patch.pk) def count(name): try: return patch.patchtag_set.get(tag__name=name).count except PatchTag.DoesNotExist: return 0 counts = ( count(name='Acked-by'), count(name='Reviewed-by'), count(name='Tested-by'), ) self.assertEqual(counts, (acks, reviews, tests)) def create_tag(self, tagtype = None): tags = { self.ACK: 'Acked', self.REVIEW: 'Reviewed', self.TEST: 'Tested' } if tagtype not in tags: return '' return '%s-by: %s\n' % (tags[tagtype], self.tagger) def create_tag_comment(self, patch, tagtype = None): comment = Comment(patch=patch, msgid=str(datetime.datetime.now()), submitter=defaults.patch_author_person, content=self.create_tag(tagtype)) comment.save() return comment def setUp(self): settings.DEBUG = True project = Project(linkname='test-project', name='Test Project', use_tags=True) project.save() defaults.patch_author_person.save() self.patch = Patch(project=project, msgid='x', name=defaults.patch_name, submitter=defaults.patch_author_person, content='') self.patch.save() self.tagger = 'Test Tagger <*****@*****.**>' def tearDown(self): self.patch.delete() def testNoComments(self): self.assertTagsEqual(self.patch, 0, 0, 0) def testNoTagComment(self): self.create_tag_comment(self.patch, None) self.assertTagsEqual(self.patch, 0, 0, 0) def testSingleComment(self): self.create_tag_comment(self.patch, self.ACK) self.assertTagsEqual(self.patch, 1, 0, 0) def testMultipleComments(self): self.create_tag_comment(self.patch, self.ACK) self.create_tag_comment(self.patch, self.ACK) self.assertTagsEqual(self.patch, 2, 0, 0) def testMultipleCommentTypes(self): self.create_tag_comment(self.patch, self.ACK) self.create_tag_comment(self.patch, self.REVIEW) self.create_tag_comment(self.patch, self.TEST) self.assertTagsEqual(self.patch, 1, 1, 1) def testCommentAdd(self): self.create_tag_comment(self.patch, self.ACK) self.assertTagsEqual(self.patch, 1, 0, 0) self.create_tag_comment(self.patch, self.ACK) self.assertTagsEqual(self.patch, 2, 0, 0) def testCommentUpdate(self): comment = self.create_tag_comment(self.patch, self.ACK) self.assertTagsEqual(self.patch, 1, 0, 0) comment.content += self.create_tag(self.ACK) comment.save() self.assertTagsEqual(self.patch, 2, 0, 0) def testCommentDelete(self): comment = self.create_tag_comment(self.patch, self.ACK) self.assertTagsEqual(self.patch, 1, 0, 0) comment.delete() self.assertTagsEqual(self.patch, 0, 0, 0) def testSingleCommentMultipleTags(self): comment = self.create_tag_comment(self.patch, self.ACK) comment.content += self.create_tag(self.REVIEW) comment.save() self.assertTagsEqual(self.patch, 1, 1, 0) def testMultipleCommentsMultipleTags(self): c1 = self.create_tag_comment(self.patch, self.ACK) c1.content += self.create_tag(self.REVIEW) c1.save() self.assertTagsEqual(self.patch, 1, 1, 0)
def assertTagsEqual(self, str, acks, reviews, tests): counts = Patch.extract_tags(str, Tag.objects.all()) self.assertEqual((acks, reviews, tests), (counts[Tag.objects.get(name='Acked-by')], counts[Tag.objects.get(name='Reviewed-by')], counts[Tag.objects.get(name='Tested-by')]))