@@ -22,6 +22,7 @@ import os
from django.test import TestCase
from patchwork.models import Patch, Series, SeriesRevision, Project
from patchwork.tests.utils import read_mail
+from patchwork.tests.utils import defaults, read_mail, TestSeries
from patchwork.bin.parsemail import parse_mail
@@ -29,21 +30,23 @@ class SeriesTest(TestCase):
fixtures = ['default_states']
def setUp(self):
- # subclasses are responsible for defining those variables
self.assertTrue(self.project is not None)
- self.assertTrue(self.n_patches is not None)
- self.assertTrue(self.root_msgid is not None)
- self.assertTrue(self.series_name is not None)
-
self.project.save()
- # insert the mails
- self.n_mails = len(self.mails)
- for filename in self.mails:
- mail = read_mail(os.path.join('series', filename))
- parse_mail(mail)
+ # insert the mails. 'mails' is an optional field, for subclasses
+ # that do have a list of on-disk emails.
+ if hasattr(self, 'mails'):
+ self.n_mails = len(self.mails)
+ for filename in self.mails:
+ mail = read_mail(os.path.join('series', filename))
+ parse_mail(mail)
def commonInsertionChecks(self):
+ # subclasses are responsible for defining those variables
+ self.assertTrue(self.n_patches is not None)
+ self.assertTrue(self.root_msgid is not None)
+ self.assertTrue(self.series_name is not None)
+
# make sure the series has been correctly populated
series = Series.objects.all()
self.assertEquals(series.count(), 1)
@@ -70,6 +73,34 @@ class SeriesTest(TestCase):
patches = Patch.objects.all()
self.assertEquals(patches.count(), self.n_patches)
+class GeneratedSeriesTest(SeriesTest):
+ project = defaults.project
+
+ def _create_series(self, n_patches, has_cover_letter=True):
+ self.n_patches = n_patches
+ series = TestSeries(self.n_patches, has_cover_letter)
+ mails = series.create_mails()
+ self.root_msgid = mails[0].get('Message-Id')
+ self.has_cover_letter = has_cover_letter
+ if has_cover_letter:
+ self.series_name = defaults.series_name
+ self.cover_letter = defaults.series_cover_letter
+ else:
+ self.series_name = 'Untitled series'
+ self.cover_letter = None
+ return (series, mails)
+
+class BasicGeneratedSeriesTests(GeneratedSeriesTest):
+ def testInsertion(self):
+ (series, mails) = self._create_series(3)
+ series.insert(mails)
+ self.commonInsertionChecks()
+
+ def testInsertionNoCoverLetter(self):
+ (series, mails) = self._create_series(3, has_cover_letter=False)
+ series.insert(mails)
+ self.commonInsertionChecks()
+
class IntelGfxTest(SeriesTest):
project = Project(linkname = 'intel-gfx',
name = 'Intel Gfx',
@@ -20,6 +20,7 @@
import os
import codecs
from patchwork.models import Project, Person
+from patchwork.bin.parsemail import parse_mail
from django.contrib.auth.models import User
from django.forms.fields import EmailField
@@ -47,6 +48,11 @@ class defaults(object):
subject = 'Test Subject'
+ series_name = 'Test Series'
+
+ series_cover_letter = """This is the test series cover letter.
+I hope you'll like it."""
+
patch_name = 'Test Patch'
patch = """--- /dev/null 2011-01-01 00:00:00.000000000 +0800
@@ -55,6 +61,8 @@ class defaults(object):
+a
"""
+ review = """This is a great addition!"""
+
error_strings = {
'email': 'Enter a valid email address.',
}
@@ -111,7 +119,8 @@ def read_mail(filename, project = None):
return mail
def create_email(content, subject = None, sender = None, multipart = False,
- project = None, content_encoding = None):
+ project = None, content_encoding = None, in_reply_to = None,
+ references = None):
if subject is None:
subject = defaults.subject
if sender is None:
@@ -134,5 +143,80 @@ def create_email(content, subject = None, sender = None, multipart = False,
msg['Subject'] = subject
msg['From'] = sender
msg['List-Id'] = project.listid
+ if in_reply_to and references:
+ msg['References'] = ' '.join([m.get('Message-Id') for m in references])
+ msg['In-Reply-To'] = in_reply_to
+ elif references:
+ msg['References'] = references
+ msg['In-Reply-To'] = references.split()[-1]
+ elif in_reply_to:
+ msg['References'] = in_reply_to
+ msg['In-Reply-To'] = in_reply_to
return msg
+
+class TestSeries(object):
+ def __init__(self, n_patches, has_cover_letter=True):
+ if n_patches < 1:
+ raise ValueError
+ self.n_patches = n_patches
+ self.has_cover_letter = has_cover_letter
+
+ def create_cover_letter(self):
+ return create_email(defaults.series_cover_letter,
+ subject='[PATCH 0/%d] %s' % (self.n_patches,
+ defaults.series_name))
+
+ # in_reply_to: a mail instance
+ def create_patch(self, n=0, in_reply_to=None, references=None,
+ subject_prefix='PATCH'):
+ in_reply_to_str = None
+ if in_reply_to:
+ in_reply_to_str = in_reply_to.get('Message-Id')
+
+ if n != 0:
+ subject='[%s %d/%d] %s' % (subject_prefix, n,
+ self.n_patches,
+ defaults.patch_name)
+ else:
+ subject='[%s] %s' % (subject_prefix, defaults.patch_name)
+
+ mail = create_email(defaults.patch, subject=subject,
+ in_reply_to=in_reply_to_str, references=references)
+ mail['X-Mailer'] = 'git-send-email 2.1.0'
+ return mail
+
+ def create_reply(self, mail, references=None):
+ if not references:
+ references = mail.get('References') + ' ' + mail.get('Message-Id')
+ return create_email(defaults.review,
+ subject='Re: ' + mail.get('Subject'),
+ references=references)
+
+ def create_mails(self):
+ mails = []
+ root_msg = None
+
+ # cover letter
+ if self.has_cover_letter:
+ cover_letter = self.create_cover_letter()
+ mails.append(cover_letter)
+ root_msg = cover_letter
+
+ # insert the first patch
+ patch = self.create_patch(1, root_msg)
+ mails.append(patch)
+ if not root_msg:
+ root_msg = patch
+
+ # and the remaining patches
+ for i in range(2, self.n_patches + 1):
+ mails.append(self.create_patch(i, root_msg))
+
+ return mails
+
+ def insert(self, mails=[]):
+ if not mails:
+ mails = self.create_mails()
+ for mail in mails:
+ parse_mail(mail)
So far we've been using real emails stored on-disk. While it's interesting to have real data as input for unit tests, it's not as flexible as having generated data. With generated data we can easily create corner cases to improve the test coverage of the parsing code. This is just a start, adding a TestSeries classes that can create a series with n patches with or without a cover letter. Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> --- patchwork/tests/test_series.py | 51 ++++++++++++++++++++----- patchwork/tests/utils.py | 86 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 126 insertions(+), 11 deletions(-)