]> git.ozlabs.org Git - patchwork/blob - apps/patchwork/tests/bundles.py
tests: check some edge cases in bundle reordering tests
[patchwork] / apps / patchwork / tests / bundles.py
1 # Patchwork - automated patch tracking system
2 # Copyright (C) 2009 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 from django.test import TestCase
22 from django.test.client import Client
23 from patchwork.models import Patch, Bundle, BundlePatch, Person
24 from patchwork.tests.utils import defaults, create_user, find_in_context
25
26 class BundleListTest(TestCase):
27     def setUp(self):
28         self.user = create_user()
29         self.client.login(username = self.user.username,
30                 password = self.user.username)
31
32     def testNoBundles(self):
33         response = self.client.get('/user/bundles/')
34         self.failUnlessEqual(response.status_code, 200)
35         self.failUnlessEqual(
36                 len(find_in_context(response.context, 'bundles')), 0)
37
38     def testSingleBundle(self):
39         defaults.project.save()
40         bundle = Bundle(owner = self.user, project = defaults.project)
41         bundle.save()
42         response = self.client.get('/user/bundles/')
43         self.failUnlessEqual(response.status_code, 200)
44         self.failUnlessEqual(
45                 len(find_in_context(response.context, 'bundles')), 1)
46
47     def tearDown(self):
48         self.user.delete()
49
50 class BundleTestBase(TestCase):
51     def setUp(self, patch_count=3):
52         patch_names = ['testpatch%d' % (i) for i in range(1, patch_count+1)]
53         self.user = create_user()
54         self.client.login(username = self.user.username,
55                 password = self.user.username)
56         defaults.project.save()
57         self.bundle = Bundle(owner = self.user, project = defaults.project,
58                 name = 'testbundle')
59         self.bundle.save()
60         self.patches = []
61
62         for patch_name in patch_names:
63             patch = Patch(project = defaults.project,
64                                msgid = patch_name, name = patch_name,
65                                submitter = Person.objects.get(user = self.user),
66                                content = '')
67             patch.save()
68             self.patches.append(patch)
69
70     def tearDown(self):
71         for patch in self.patches:
72             patch.delete()
73         self.bundle.delete()
74         self.user.delete()
75
76 class BundleViewTest(BundleTestBase):
77
78     def testEmptyBundle(self):
79         response = self.client.get('/user/bundle/%d/' % self.bundle.id)
80         self.failUnlessEqual(response.status_code, 200)
81         page = find_in_context(response.context, 'page')
82         self.failUnlessEqual(len(page.object_list), 0)
83
84     def testNonEmptyBundle(self):
85         self.bundle.append_patch(self.patches[0])
86
87         response = self.client.get('/user/bundle/%d/' % self.bundle.id)
88         self.failUnlessEqual(response.status_code, 200)
89         page = find_in_context(response.context, 'page')
90         self.failUnlessEqual(len(page.object_list), 1)
91
92     def testBundleOrder(self):
93         for patch in self.patches:
94             self.bundle.append_patch(patch)
95
96         response = self.client.get('/user/bundle/%d/' % self.bundle.id)
97
98         pos = 0
99         for patch in self.patches:
100             next_pos = response.content.find(patch.name)
101             # ensure that this patch is after the previous
102             self.failUnless(next_pos > pos)
103             pos = next_pos
104
105         # reorder and recheck
106         i = 0
107         for patch in self.patches.__reversed__():
108             bundlepatch = BundlePatch.objects.get(bundle = self.bundle,
109                     patch = patch)
110             bundlepatch.order = i
111             bundlepatch.save()
112             i += 1
113
114         response = self.client.get('/user/bundle/%d/' % self.bundle.id)
115         pos = len(response.content)
116         for patch in self.patches:
117             next_pos = response.content.find(patch.name)
118             # ensure that this patch is now *before* the previous
119             self.failUnless(next_pos < pos)
120             pos = next_pos
121
122 class BundleCreateFromListTest(BundleTestBase):
123     def testCreateEmptyBundle(self):
124         newbundlename = 'testbundle-new'
125         params = {'form': 'patchlistform',
126                   'bundle_name': newbundlename,
127                   'action': 'Create',
128                   'project': defaults.project.id}
129
130         response = self.client.post(
131                 '/project/%s/list/' % defaults.project.linkname,
132                 params)
133
134         self.assertContains(response, 'Bundle %s created' % newbundlename)
135
136     def testCreateNonEmptyBundle(self):
137         newbundlename = 'testbundle-new'
138         patch = self.patches[0]
139
140         params = {'form': 'patchlistform',
141                   'bundle_name': newbundlename,
142                   'action': 'Create',
143                   'project': defaults.project.id,
144                   'patch_id:%d' % patch.id: 'checked'}
145
146         response = self.client.post(
147                 '/project/%s/list/' % defaults.project.linkname,
148                 params)
149
150         self.assertContains(response, 'Bundle %s created' % newbundlename)
151         self.assertContains(response, 'added to bundle %s' % newbundlename,
152             count = 1)
153
154         bundle = Bundle.objects.get(name = newbundlename)
155         self.failUnlessEqual(bundle.patches.count(), 1)
156         self.failUnlessEqual(bundle.patches.all()[0], patch)
157
158     def testCreateNonEmptyBundleEmptyName(self):
159         newbundlename = 'testbundle-new'
160         patch = self.patches[0]
161
162         n_bundles = Bundle.objects.count()
163
164         params = {'form': 'patchlistform',
165                   'bundle_name': '',
166                   'action': 'Create',
167                   'project': defaults.project.id,
168                   'patch_id:%d' % patch.id: 'checked'}
169
170         response = self.client.post(
171                 '/project/%s/list/' % defaults.project.linkname,
172                 params)
173
174         self.assertContains(response, 'No bundle name was specified',
175                 status_code = 200)
176
177         # test that no new bundles are present
178         self.failUnlessEqual(n_bundles, Bundle.objects.count())
179
180 class BundleCreateFromPatchTest(BundleTestBase):
181     def testCreateNonEmptyBundle(self):
182         newbundlename = 'testbundle-new'
183         patch = self.patches[0]
184
185         params = {'name': newbundlename,
186                   'action': 'createbundle'}
187
188         response = self.client.post('/patch/%d/' % patch.id, params)
189
190         self.assertContains(response,
191                 'Bundle %s created' % newbundlename)
192
193         bundle = Bundle.objects.get(name = newbundlename)
194         self.failUnlessEqual(bundle.patches.count(), 1)
195         self.failUnlessEqual(bundle.patches.all()[0], patch)
196
197     def testCreateWithExistingName(self):
198         newbundlename = self.bundle.name
199         patch = self.patches[0]
200
201         params = {'name': newbundlename,
202                   'action': 'createbundle'}
203
204         response = self.client.post('/patch/%d/' % patch.id, params)
205
206         self.assertContains(response,
207                 'A bundle called %s already exists' % newbundlename)
208
209         count = Bundle.objects.count()
210         self.failUnlessEqual(Bundle.objects.count(), 1)
211
212 class BundleAddFromListTest(BundleTestBase):
213     def testAddToEmptyBundle(self):
214         patch = self.patches[0]
215         params = {'form': 'patchlistform',
216                   'action': 'Add',
217                   'project': defaults.project.id,
218                   'bundle_id': self.bundle.id,
219                   'patch_id:%d' % patch.id: 'checked'}
220
221         response = self.client.post(
222                 '/project/%s/list/' % defaults.project.linkname,
223                 params)
224
225         self.assertContains(response, 'added to bundle %s' % self.bundle.name,
226             count = 1)
227
228         self.failUnlessEqual(self.bundle.patches.count(), 1)
229         self.failUnlessEqual(self.bundle.patches.all()[0], patch)
230
231     def testAddToNonEmptyBundle(self):
232         self.bundle.append_patch(self.patches[0])
233         patch = self.patches[1]
234         params = {'form': 'patchlistform',
235                   'action': 'Add',
236                   'project': defaults.project.id,
237                   'bundle_id': self.bundle.id,
238                   'patch_id:%d' % patch.id: 'checked'}
239
240         response = self.client.post(
241                 '/project/%s/list/' % defaults.project.linkname,
242                 params)
243
244         self.assertContains(response, 'added to bundle %s' % self.bundle.name,
245             count = 1)
246
247         self.failUnlessEqual(self.bundle.patches.count(), 2)
248         self.failUnless(self.patches[0] in self.bundle.patches.all())
249         self.failUnless(self.patches[1] in self.bundle.patches.all())
250
251         # check order
252         bps = [ BundlePatch.objects.get(bundle = self.bundle,
253                                         patch = self.patches[i]) \
254                 for i in [0, 1] ]
255         self.failUnless(bps[0].order < bps[1].order)
256
257     def testAddDuplicate(self):
258         self.bundle.append_patch(self.patches[0])
259         count = self.bundle.patches.count()
260         patch = self.patches[0]
261
262         params = {'form': 'patchlistform',
263                   'action': 'Add',
264                   'project': defaults.project.id,
265                   'bundle_id': self.bundle.id,
266                   'patch_id:%d' % patch.id: 'checked'}
267
268         response = self.client.post(
269                 '/project/%s/list/' % defaults.project.linkname,
270                 params)
271
272         self.assertContains(response, 'Patch &#39;%s&#39; already in bundle' \
273                             % patch.name, count = 1, status_code = 200)
274
275         self.assertEquals(count, self.bundle.patches.count())
276
277     def testAddNewAndDuplicate(self):
278         self.bundle.append_patch(self.patches[0])
279         count = self.bundle.patches.count()
280         patch = self.patches[0]
281
282         params = {'form': 'patchlistform',
283                   'action': 'Add',
284                   'project': defaults.project.id,
285                   'bundle_id': self.bundle.id,
286                   'patch_id:%d' % patch.id: 'checked',
287                   'patch_id:%d' % self.patches[1].id: 'checked'}
288
289         response = self.client.post(
290                 '/project/%s/list/' % defaults.project.linkname,
291                 params)
292
293         self.assertContains(response, 'Patch &#39;%s&#39; already in bundle' \
294                             % patch.name, count = 1, status_code = 200)
295         self.assertContains(response, 'Patch &#39;%s&#39; added to bundle' \
296                             % self.patches[1].name, count = 1,
297                             status_code = 200)
298         self.assertEquals(count + 1, self.bundle.patches.count())
299
300 class BundleAddFromPatchTest(BundleTestBase):
301     def testAddToEmptyBundle(self):
302         patch = self.patches[0]
303         params = {'action': 'addtobundle',
304                   'bundle_id': self.bundle.id}
305
306         response = self.client.post('/patch/%d/' % patch.id, params)
307
308         self.assertContains(response,
309                 'added to bundle &quot;%s&quot;' % self.bundle.name,
310                 count = 1)
311
312         self.failUnlessEqual(self.bundle.patches.count(), 1)
313         self.failUnlessEqual(self.bundle.patches.all()[0], patch)
314
315     def testAddToNonEmptyBundle(self):
316         self.bundle.append_patch(self.patches[0])
317         patch = self.patches[1]
318         params = {'action': 'addtobundle',
319                   'bundle_id': self.bundle.id}
320
321         response = self.client.post('/patch/%d/' % patch.id, params)
322
323         self.assertContains(response,
324                 'added to bundle &quot;%s&quot;' % self.bundle.name,
325                 count = 1)
326
327         self.failUnlessEqual(self.bundle.patches.count(), 2)
328         self.failUnless(self.patches[0] in self.bundle.patches.all())
329         self.failUnless(self.patches[1] in self.bundle.patches.all())
330
331         # check order
332         bps = [ BundlePatch.objects.get(bundle = self.bundle,
333                                         patch = self.patches[i]) \
334                 for i in [0, 1] ]
335         self.failUnless(bps[0].order < bps[1].order)
336
337 class BundleReorderTest(BundleTestBase):
338     def setUp(self):
339         super(BundleReorderTest, self).setUp(5)
340         for i in range(5):
341             self.bundle.append_patch(self.patches[i])
342
343     def checkReordering(self, neworder, start, end):
344         neworder_ids = [ self.patches[i].id for i in neworder ]
345
346         firstpatch = BundlePatch.objects.get(bundle = self.bundle,
347                 patch = self.patches[start]).patch
348
349         slice_ids = neworder_ids[start:end]
350         params = {'form': 'reorderform',
351                   'order_start': firstpatch.id,
352                   'neworder': slice_ids}
353
354         response = self.client.post('/user/bundle/%d/' % self.bundle.id,
355                                     params)
356
357         self.failUnlessEqual(response.status_code, 200)
358
359         bps = BundlePatch.objects.filter(bundle = self.bundle) \
360                         .order_by('order')
361
362         # check if patch IDs are in the expected order:
363         bundle_ids = [ bp.patch.id for bp in bps ]
364         self.failUnlessEqual(neworder_ids, bundle_ids)
365
366         # check if order field is still sequential:
367         order_numbers = [ bp.order for bp in bps ]
368         expected_order = range(1, len(neworder)+1) # [1 ... len(neworder)]
369         self.failUnlessEqual(order_numbers, expected_order)
370
371     def testBundleReorderAll(self):
372         # reorder all patches:
373         self.checkReordering([2,1,4,0,3], 0, 5)
374
375     def testBundleReorderEnd(self):
376         # reorder only the last three patches
377         self.checkReordering([0,1,3,2,4], 2, 5)
378
379     def testBundleReorderBegin(self):
380         # reorder only the first three patches
381         self.checkReordering([2,0,1,3,4], 0, 3)
382
383     def testBundleReorderMiddle(self):
384         # reorder only 2nd, 3rd, and 4th patches
385         self.checkReordering([0,2,3,1,4], 1, 4)