]> git.ozlabs.org Git - patchwork/blob - patchwork/tests/test_tags.py
Add patch tag infrastructure
[patchwork] / patchwork / tests / test_tags.py
1 # Patchwork - automated patch tracking system
2 # Copyright (C) 2014 Jeremy Kerr <jk@ozlabs.org>
3 #
4 # This file is part of the Patchwork package.
5 #
6 # Patchwork is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # Patchwork is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with Patchwork; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20 import unittest
21 import datetime
22 from django.test import TestCase, TransactionTestCase
23 from patchwork.models import Project, Patch, Comment, Tag, PatchTag
24 from patchwork.tests.utils import defaults
25 from patchwork.parser import extract_tags
26
27 from django.conf import settings
28 from django.db import connection
29
30 class ExtractTagsTest(TestCase):
31
32     email = 'test@exmaple.com'
33     name_email = 'test name <' + email + '>'
34     fixtures = ['default_tags']
35
36     def assertTagsEqual(self, str, acks, reviews, tests):
37         counts = extract_tags(str, Tag.objects.all())
38         self.assertEquals((acks, reviews, tests),
39                 (counts[Tag.objects.get(name='Acked-by')],
40                  counts[Tag.objects.get(name='Reviewed-by')],
41                  counts[Tag.objects.get(name='Tested-by')]))
42
43     def testEmpty(self):
44         self.assertTagsEqual("", 0, 0, 0)
45
46     def testNoTag(self):
47         self.assertTagsEqual("foo", 0, 0, 0)
48
49     def testAck(self):
50         self.assertTagsEqual("Acked-by: %s" % self.name_email, 1, 0, 0)
51
52     def testAckEmailOnly(self):
53         self.assertTagsEqual("Acked-by: %s" % self.email, 1, 0, 0)
54
55     def testReviewed(self):
56         self.assertTagsEqual("Reviewed-by: %s" % self.name_email, 0, 1, 0)
57
58     def testTested(self):
59         self.assertTagsEqual("Tested-by: %s" % self.name_email, 0, 0, 1)
60
61     def testAckAfterNewline(self):
62         self.assertTagsEqual("\nAcked-by: %s" % self.name_email, 1, 0, 0)
63
64     def testMultipleAcks(self):
65         str = "Acked-by: %s\nAcked-by: %s\n" % ((self.name_email,) * 2)
66         self.assertTagsEqual(str, 2, 0, 0)
67
68     def testMultipleTypes(self):
69         str = "Acked-by: %s\nAcked-by: %s\nReviewed-by: %s\n" % (
70                 (self.name_email,) * 3)
71         self.assertTagsEqual(str, 2, 1, 0)
72
73     def testLower(self):
74         self.assertTagsEqual("acked-by: %s" % self.name_email, 1, 0, 0)
75
76     def testUpper(self):
77         self.assertTagsEqual("ACKED-BY: %s" % self.name_email, 1, 0, 0)
78
79     def testAckInReply(self):
80         self.assertTagsEqual("> Acked-by: %s\n" % self.name_email, 0, 0, 0)
81
82 class PatchTagsTest(TransactionTestCase):
83     ACK = 1
84     REVIEW = 2
85     TEST = 3
86     fixtures = ['default_tags']
87
88     def assertTagsEqual(self, patch, acks, reviews, tests):
89         patch = Patch.objects.get(pk=patch.pk)
90
91         def count(name):
92             try:
93                 return patch.patchtag_set.get(tag__name=name).count
94             except PatchTag.DoesNotExist:
95                 return 0
96
97         counts = (
98             count(name='Acked-by'),
99             count(name='Reviewed-by'),
100             count(name='Tested-by'),
101         )
102
103         self.assertEqual(counts, (acks, reviews, tests))
104
105     def create_tag(self, tagtype = None):
106         tags = {
107             self.ACK: 'Acked',
108             self.REVIEW: 'Reviewed',
109             self.TEST: 'Tested'
110         }
111         if tagtype not in tags:
112             return ''
113         return '%s-by: %s\n' % (tags[tagtype], self.tagger)
114
115     def create_tag_comment(self, patch, tagtype = None):
116         comment = Comment(patch=patch, msgid=str(datetime.datetime.now()),
117                 submitter=defaults.patch_author_person,
118                 content=self.create_tag(tagtype))
119         comment.save()
120         return comment
121
122     def setUp(self):
123         settings.DEBUG = True
124         project = Project(linkname='test-project', name='Test Project',
125             use_tags=True)
126         project.save()
127         defaults.patch_author_person.save()
128         self.patch = Patch(project=project,
129                            msgid='x', name=defaults.patch_name,
130                            submitter=defaults.patch_author_person,
131                            content='')
132         self.patch.save()
133         self.tagger = 'Test Tagger <tagger@example.com>'
134
135     def tearDown(self):
136         self.patch.delete()
137
138     def testNoComments(self):
139         self.assertTagsEqual(self.patch, 0, 0, 0)
140
141     def testNoTagComment(self):
142         self.create_tag_comment(self.patch, None)
143         self.assertTagsEqual(self.patch, 0, 0, 0)
144
145     def testSingleComment(self):
146         self.create_tag_comment(self.patch, self.ACK)
147         self.assertTagsEqual(self.patch, 1, 0, 0)
148
149     def testMultipleComments(self):
150         self.create_tag_comment(self.patch, self.ACK)
151         self.create_tag_comment(self.patch, self.ACK)
152         self.assertTagsEqual(self.patch, 2, 0, 0)
153
154     def testMultipleCommentTypes(self):
155         self.create_tag_comment(self.patch, self.ACK)
156         self.create_tag_comment(self.patch, self.REVIEW)
157         self.create_tag_comment(self.patch, self.TEST)
158         self.assertTagsEqual(self.patch, 1, 1, 1)
159
160     def testCommentAdd(self):
161         self.create_tag_comment(self.patch, self.ACK)
162         self.assertTagsEqual(self.patch, 1, 0, 0)
163         self.create_tag_comment(self.patch, self.ACK)
164         self.assertTagsEqual(self.patch, 2, 0, 0)
165
166     def testCommentUpdate(self):
167         comment = self.create_tag_comment(self.patch, self.ACK)
168         self.assertTagsEqual(self.patch, 1, 0, 0)
169
170         comment.content += self.create_tag(self.ACK)
171         comment.save()
172         self.assertTagsEqual(self.patch, 2, 0, 0)
173
174     def testCommentDelete(self):
175         comment = self.create_tag_comment(self.patch, self.ACK)
176         self.assertTagsEqual(self.patch, 1, 0, 0)
177         comment.delete()
178         self.assertTagsEqual(self.patch, 0, 0, 0)
179
180     def testSingleCommentMultipleTags(self):
181         comment = self.create_tag_comment(self.patch, self.ACK)
182         comment.content += self.create_tag(self.REVIEW)
183         comment.save()
184         self.assertTagsEqual(self.patch, 1, 1, 0)
185
186     def testMultipleCommentsMultipleTags(self):
187         c1 = self.create_tag_comment(self.patch, self.ACK)
188         c1.content += self.create_tag(self.REVIEW)
189         c1.save()
190         self.assertTagsEqual(self.patch, 1, 1, 0)
191
192 class PatchTagManagerTest(PatchTagsTest):
193
194     def assertTagsEqual(self, patch, acks, reviews, tests):
195
196         tagattrs = {}
197         for tag in Tag.objects.all():
198             tagattrs[tag.name] = tag.attr_name
199
200         # force project.tags to be queried outside of the assertNumQueries
201         patch.project.tags
202
203         # we should be able to do this with two queries: one for
204         # the patch table lookup, and the prefetch_related for the
205         # projects table.
206         with self.assertNumQueries(2):
207             patch = Patch.objects.with_tag_counts(project=patch.project) \
208                     .get(pk = patch.pk)
209
210             counts = (
211                 getattr(patch, tagattrs['Acked-by']),
212                 getattr(patch, tagattrs['Reviewed-by']),
213                 getattr(patch, tagattrs['Tested-by']),
214             )
215
216         self.assertEqual(counts, (acks, reviews, tests))
217