14083.1.1
by Jeroen Vermeulen
Lint. |
1 |
# Copyright 2009-2011 Canonical Ltd. This software is licensed under the
|
8687.15.17
by Karl Fogel
Add the copyright header block to the rest of the files under lib/lp/. |
2 |
# GNU Affero General Public License version 3 (see the file LICENSE).
|
5743.2.1
by Tim Penhey
Add method to get branch revisions for multiple branches at once. |
3 |
|
5743.2.2
by Tim Penhey
Listing now has revision number and codebrowse hyperlink. |
4 |
"""Tests for Revisions."""
|
5743.2.1
by Tim Penhey
Add method to get branch revisions for multiple branches at once. |
5 |
|
6 |
__metaclass__ = type |
|
7 |
||
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
8 |
from datetime import ( |
9 |
datetime, |
|
10 |
timedelta, |
|
11 |
)
|
|
6789.3.9
by Jonathan Lange
Move the revision from bzr revision method into RevisionSet. |
12 |
import time |
13677.3.2
by Steve Kowalik
Remove unneeded unittest imports. |
13 |
from unittest import TestCase |
5743.2.6
by Tim Penhey
Updates following review |
14 |
|
5821.2.32
by James Henstridge
* s/psycopg/psycopg2/ in a few more places. |
15 |
import psycopg2 |
6789.3.9
by Jonathan Lange
Move the revision from bzr revision method into RevisionSet. |
16 |
import pytz |
6623.4.16
by Tim Penhey
Add a new cronscript to be run each night, and remove the creation of the historical karma revisions when a user validates an email address. This is now handled by the cronscript. |
17 |
from storm.store import Store |
5743.2.6
by Tim Penhey
Updates following review |
18 |
from zope.component import getUtility |
6789.3.9
by Jonathan Lange
Move the revision from bzr revision method into RevisionSet. |
19 |
from zope.security.proxy import removeSecurityProxy |
5743.2.1
by Tim Penhey
Add method to get branch revisions for multiple branches at once. |
20 |
|
8555.2.2
by Tim Penhey
Move enum -> enums. |
21 |
from lp.code.enums import BranchLifecycleStatus |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
22 |
from lp.code.interfaces.branchlookup import IBranchLookup |
8225.3.2
by Tim Penhey
Sort the imports. |
23 |
from lp.code.interfaces.revision import IRevisionSet |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
24 |
from lp.code.model.revision import ( |
25 |
RevisionCache, |
|
26 |
RevisionSet, |
|
27 |
)
|
|
8225.3.2
by Tim Penhey
Sort the imports. |
28 |
from lp.registry.model.karma import Karma |
14083.1.1
by Jeroen Vermeulen
Lint. |
29 |
from lp.scripts.garbo import RevisionAuthorEmailLinker |
14606.3.1
by William Grant
Merge canonical.database into lp.services.database. |
30 |
from lp.services.database.lpstorm import IMasterObject |
31 |
from lp.services.database.sqlbase import cursor |
|
14550.1.1
by Steve Kowalik
Run format-imports over lib/lp and lib/canonical/launchpad |
32 |
from lp.services.identity.interfaces.account import AccountStatus |
12070.1.17
by Tim Penhey
Replace MockLogger with DevNullLogger. |
33 |
from lp.services.log.logger import DevNullLogger |
14606.3.1
by William Grant
Merge canonical.database into lp.services.database. |
34 |
from lp.services.webapp.interfaces import ( |
35 |
DEFAULT_FLAVOR, |
|
36 |
IStoreSelector, |
|
37 |
MAIN_STORE, |
|
38 |
)
|
|
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
39 |
from lp.testing import ( |
14606.3.1
by William Grant
Merge canonical.database into lp.services.database. |
40 |
login, |
41 |
logout, |
|
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
42 |
TestCaseWithFactory, |
43 |
time_counter, |
|
44 |
)
|
|
7675.181.1
by Jonathan Lange
Merge stable, resolving conflict in test_revision.py |
45 |
from lp.testing.factory import LaunchpadObjectFactory |
14606.3.1
by William Grant
Merge canonical.database into lp.services.database. |
46 |
from lp.testing.layers import DatabaseFunctionalLayer |
8225.3.2
by Tim Penhey
Sort the imports. |
47 |
|
6736.3.4
by Tim Penhey
Added tests for addition Revision and RevisionSet methods. |
48 |
|
7925.4.1
by Tim Penhey
Don't create revisions with future revision_dates. |
49 |
class TestRevisionCreationDate(TestCaseWithFactory): |
50 |
"""Test that RevisionSet.new won't create revisions with future dates."""
|
|
51 |
||
52 |
layer = DatabaseFunctionalLayer |
|
53 |
||
54 |
def test_new_past_revision_date(self): |
|
55 |
# A revision created with a revision date in the past works fine.
|
|
56 |
past_date = datetime(2009, 1, 1, tzinfo=pytz.UTC) |
|
57 |
revision = RevisionSet().new( |
|
58 |
'rev_id', 'log body', past_date, 'author', [], {}) |
|
59 |
self.assertEqual(past_date, revision.revision_date) |
|
60 |
||
61 |
def test_new_future_revision_date(self): |
|
62 |
# A revision with a future date gets the revision date set to
|
|
63 |
# date_created.
|
|
64 |
now = datetime.now(pytz.UTC) |
|
65 |
future_date = now + timedelta(days=1) |
|
66 |
revision = RevisionSet().new( |
|
67 |
'rev_id', 'log body', future_date, 'author', [], {}) |
|
68 |
self.assertEqual(revision.date_created, revision.revision_date) |
|
69 |
self.assertTrue(revision.revision_date <= now) |
|
70 |
||
71 |
||
6623.4.6
by Tim Penhey
Hook up the claiming of older revisions. |
72 |
class TestRevisionKarma(TestCaseWithFactory): |
6623.4.25
by Tim Penhey
Make sure we don't try to allocate karma to junk branches. |
73 |
"""Test the allocation of karma for revisions."""
|
6623.4.6
by Tim Penhey
Hook up the claiming of older revisions. |
74 |
|
6623.4.13
by Tim Penhey
Change the layers for the tests. |
75 |
layer = DatabaseFunctionalLayer |
6623.4.6
by Tim Penhey
Hook up the claiming of older revisions. |
76 |
|
77 |
def setUp(self): |
|
78 |
# Use an administrator to set branch privacy easily.
|
|
6623.4.25
by Tim Penhey
Make sure we don't try to allocate karma to junk branches. |
79 |
TestCaseWithFactory.setUp(self, "admin@canonical.com") |
6623.4.6
by Tim Penhey
Hook up the claiming of older revisions. |
80 |
|
81 |
def test_revisionWithUnknownEmail(self): |
|
82 |
# A revision when created does not have karma allocated.
|
|
83 |
rev = self.factory.makeRevision() |
|
6623.4.20
by Tim Penhey
Testing the guts of the cron script and creating a dedicated db user. |
84 |
self.failIf(rev.karma_allocated) |
6623.4.6
by Tim Penhey
Hook up the claiming of older revisions. |
85 |
# Even if the revision author is someone we know.
|
86 |
author = self.factory.makePerson() |
|
87 |
rev = self.factory.makeRevision( |
|
88 |
author=author.preferredemail.email) |
|
6623.4.20
by Tim Penhey
Testing the guts of the cron script and creating a dedicated db user. |
89 |
self.failIf(rev.karma_allocated) |
6623.4.6
by Tim Penhey
Hook up the claiming of older revisions. |
90 |
|
91 |
def test_noKarmaForUnknownAuthor(self): |
|
6623.4.18
by Tim Penhey
More review updates. |
92 |
# If the revision author is unknown, karma isn't allocated.
|
6623.4.6
by Tim Penhey
Hook up the claiming of older revisions. |
93 |
rev = self.factory.makeRevision() |
7362.12.24
by Jonathan Lange
Restore change that somehow got lost. |
94 |
branch = self.factory.makeProductBranch() |
6623.4.6
by Tim Penhey
Hook up the claiming of older revisions. |
95 |
branch.createBranchRevision(1, rev) |
6623.4.20
by Tim Penhey
Testing the guts of the cron script and creating a dedicated db user. |
96 |
self.failIf(rev.karma_allocated) |
6623.4.6
by Tim Penhey
Hook up the claiming of older revisions. |
97 |
|
6623.4.16
by Tim Penhey
Add a new cronscript to be run each night, and remove the creation of the historical karma revisions when a user validates an email address. This is now handled by the cronscript. |
98 |
def test_noRevisionsNeedingAllocation(self): |
99 |
# There are no outstanding revisions needing karma allocated.
|
|
100 |
self.assertEqual( |
|
101 |
[], list(RevisionSet.getRevisionsNeedingKarmaAllocated())) |
|
102 |
||
6623.4.6
by Tim Penhey
Hook up the claiming of older revisions. |
103 |
def test_karmaAllocatedForKnownAuthor(self): |
104 |
# If the revision author is known, allocate karma.
|
|
105 |
author = self.factory.makePerson() |
|
106 |
rev = self.factory.makeRevision( |
|
6950.1.1
by Tim Penhey
Make sure that revision karma doesn't create a future karma event. |
107 |
author=author.preferredemail.email, |
108 |
revision_date=datetime.now(pytz.UTC) - timedelta(days=5)) |
|
7362.12.24
by Jonathan Lange
Restore change that somehow got lost. |
109 |
branch = self.factory.makeProductBranch() |
6623.4.6
by Tim Penhey
Hook up the claiming of older revisions. |
110 |
branch.createBranchRevision(1, rev) |
6623.4.20
by Tim Penhey
Testing the guts of the cron script and creating a dedicated db user. |
111 |
self.failUnless(rev.karma_allocated) |
6623.4.16
by Tim Penhey
Add a new cronscript to be run each night, and remove the creation of the historical karma revisions when a user validates an email address. This is now handled by the cronscript. |
112 |
# Get the karma event.
|
113 |
[karma] = list(Store.of(author).find( |
|
114 |
Karma, |
|
115 |
Karma.person == author, |
|
116 |
Karma.product == branch.product)) |
|
6623.4.6
by Tim Penhey
Hook up the claiming of older revisions. |
117 |
self.assertEqual(karma.datecreated, rev.revision_date) |
118 |
self.assertEqual(karma.product, branch.product) |
|
6623.4.16
by Tim Penhey
Add a new cronscript to be run each night, and remove the creation of the historical karma revisions when a user validates an email address. This is now handled by the cronscript. |
119 |
# Since karma has been allocated, the revision isn't in our list.
|
120 |
self.assertEqual( |
|
121 |
[], list(RevisionSet.getRevisionsNeedingKarmaAllocated())) |
|
122 |
||
6623.4.23
by Tim Penhey
Fix a bug with attempting to allocate karma to an inactive person, and fix logging in the cron script. |
123 |
def test_karmaNotAllocatedForKnownAuthorWithInactiveAccount(self): |
124 |
# If the revision author is known, but the account is not active,
|
|
125 |
# don't allocate karma.
|
|
126 |
author = self.factory.makePerson() |
|
127 |
rev = self.factory.makeRevision( |
|
128 |
author=author.preferredemail.email) |
|
7675.85.2
by Jonathan Lange
Undo revision generated by step 2 of process. |
129 |
IMasterObject(author.account).status = AccountStatus.SUSPENDED |
7362.12.24
by Jonathan Lange
Restore change that somehow got lost. |
130 |
branch = self.factory.makeProductBranch() |
6623.4.23
by Tim Penhey
Fix a bug with attempting to allocate karma to an inactive person, and fix logging in the cron script. |
131 |
branch.createBranchRevision(1, rev) |
132 |
self.failIf(rev.karma_allocated) |
|
133 |
# Even though the revision author is connected to the person, since
|
|
134 |
# the account status is suspended, the person is not "valid", and so
|
|
135 |
# the revisions are not returned as needing karma allocated.
|
|
136 |
self.assertEqual( |
|
137 |
[], list(RevisionSet.getRevisionsNeedingKarmaAllocated())) |
|
138 |
||
6623.4.16
by Tim Penhey
Add a new cronscript to be run each night, and remove the creation of the historical karma revisions when a user validates an email address. This is now handled by the cronscript. |
139 |
def test_noKarmaForJunk(self): |
140 |
# Revisions only associated with junk branches don't get karma.
|
|
141 |
author = self.factory.makePerson() |
|
142 |
rev = self.factory.makeRevision( |
|
143 |
author=author.preferredemail.email) |
|
7362.12.24
by Jonathan Lange
Restore change that somehow got lost. |
144 |
branch = self.factory.makePersonalBranch() |
6623.4.16
by Tim Penhey
Add a new cronscript to be run each night, and remove the creation of the historical karma revisions when a user validates an email address. This is now handled by the cronscript. |
145 |
branch.createBranchRevision(1, rev) |
6623.4.20
by Tim Penhey
Testing the guts of the cron script and creating a dedicated db user. |
146 |
self.failIf(rev.karma_allocated) |
6623.4.16
by Tim Penhey
Add a new cronscript to be run each night, and remove the creation of the historical karma revisions when a user validates an email address. This is now handled by the cronscript. |
147 |
# Nor is this revision identified as needing karma allocated.
|
148 |
self.assertEqual( |
|
149 |
[], list(RevisionSet.getRevisionsNeedingKarmaAllocated())) |
|
150 |
||
151 |
def test_junkBranchMovedToProductNeedsKarma(self): |
|
152 |
# A junk branch that moves to a product needs karma allocated.
|
|
153 |
author = self.factory.makePerson() |
|
7675.439.10
by Tim Penhey
Fix the test. |
154 |
rev = self.factory.makeRevision(author=author) |
7362.12.24
by Jonathan Lange
Restore change that somehow got lost. |
155 |
branch = self.factory.makePersonalBranch() |
6623.4.16
by Tim Penhey
Add a new cronscript to be run each night, and remove the creation of the historical karma revisions when a user validates an email address. This is now handled by the cronscript. |
156 |
branch.createBranchRevision(1, rev) |
157 |
# Once the branch is connected to the revision, we now specify
|
|
158 |
# a product for the branch.
|
|
8971.24.19
by Tim Penhey
More tests that move branches updated. |
159 |
project = self.factory.makeProduct() |
160 |
branch.setTarget(user=branch.owner, project=project) |
|
6623.4.18
by Tim Penhey
More review updates. |
161 |
# The revision is now identified as needing karma allocated.
|
6623.4.16
by Tim Penhey
Add a new cronscript to be run each night, and remove the creation of the historical karma revisions when a user validates an email address. This is now handled by the cronscript. |
162 |
self.assertEqual( |
163 |
[rev], list(RevisionSet.getRevisionsNeedingKarmaAllocated())) |
|
164 |
||
7675.439.10
by Tim Penhey
Fix the test. |
165 |
def test_junkBranchMovedToPackageNeedsKarma(self): |
166 |
# A junk branch that moves to a package needs karma allocated.
|
|
7675.439.8
by Tim Penhey
Test confirming that package revisions aren't yet being retrieved for karma allocation. |
167 |
author = self.factory.makePerson() |
168 |
rev = self.factory.makeRevision(author=author) |
|
7675.439.10
by Tim Penhey
Fix the test. |
169 |
branch = self.factory.makePersonalBranch() |
7675.439.8
by Tim Penhey
Test confirming that package revisions aren't yet being retrieved for karma allocation. |
170 |
branch.createBranchRevision(1, rev) |
7675.439.10
by Tim Penhey
Fix the test. |
171 |
# Once the branch is connected to the revision, we now specify
|
172 |
# a product for the branch.
|
|
173 |
source_package = self.factory.makeSourcePackage() |
|
174 |
branch.setTarget(user=branch.owner, source_package=source_package) |
|
175 |
# The revision is now identified as needing karma allocated.
|
|
7675.439.8
by Tim Penhey
Test confirming that package revisions aren't yet being retrieved for karma allocation. |
176 |
self.assertEqual( |
177 |
[rev], list(RevisionSet.getRevisionsNeedingKarmaAllocated())) |
|
178 |
||
6623.4.16
by Tim Penhey
Add a new cronscript to be run each night, and remove the creation of the historical karma revisions when a user validates an email address. This is now handled by the cronscript. |
179 |
def test_newRevisionAuthorLinkNeedsKarma(self): |
180 |
# If Launchpad knows of revisions by a particular author, and later
|
|
181 |
# that authoer registers with launchpad, the revisions need karma
|
|
182 |
# allocated.
|
|
6623.4.6
by Tim Penhey
Hook up the claiming of older revisions. |
183 |
email = self.factory.getUniqueEmailAddress() |
184 |
rev = self.factory.makeRevision(author=email) |
|
7362.12.24
by Jonathan Lange
Restore change that somehow got lost. |
185 |
branch = self.factory.makeProductBranch() |
6623.4.6
by Tim Penhey
Hook up the claiming of older revisions. |
186 |
branch.createBranchRevision(1, rev) |
6623.4.20
by Tim Penhey
Testing the guts of the cron script and creating a dedicated db user. |
187 |
self.failIf(rev.karma_allocated) |
6623.4.16
by Tim Penhey
Add a new cronscript to be run each night, and remove the creation of the historical karma revisions when a user validates an email address. This is now handled by the cronscript. |
188 |
# Since the revision author is not known, the revisions do not at this
|
189 |
# stage need karma allocated.
|
|
190 |
self.assertEqual( |
|
191 |
[], list(RevisionSet.getRevisionsNeedingKarmaAllocated())) |
|
192 |
# The person registers with Launchpad.
|
|
12070.1.17
by Tim Penhey
Replace MockLogger with DevNullLogger. |
193 |
self.factory.makePerson(email=email) |
8303.10.5
by James Henstridge
Update tests that expect RevisionAuthors or HWSubmissions to be linked |
194 |
# Garbo runs the RevisionAuthorEmailLinker job.
|
12070.1.17
by Tim Penhey
Replace MockLogger with DevNullLogger. |
195 |
RevisionAuthorEmailLinker(log=DevNullLogger()).run() |
6623.4.16
by Tim Penhey
Add a new cronscript to be run each night, and remove the creation of the historical karma revisions when a user validates an email address. This is now handled by the cronscript. |
196 |
# Now the kama needs allocating.
|
197 |
self.assertEqual( |
|
198 |
[rev], list(RevisionSet.getRevisionsNeedingKarmaAllocated())) |
|
6623.4.6
by Tim Penhey
Hook up the claiming of older revisions. |
199 |
|
6950.1.1
by Tim Penhey
Make sure that revision karma doesn't create a future karma event. |
200 |
def test_karmaDateForFutureRevisions(self): |
201 |
# If the revision date is some time in the future, then the karma date
|
|
202 |
# is set to be the time that the revision was created.
|
|
203 |
author = self.factory.makePerson() |
|
204 |
rev = self.factory.makeRevision( |
|
7675.439.5
by Tim Penhey
Make the test_karmaDateForFutureRevisions actually test what it says it is testing. |
205 |
author=author, |
6950.1.1
by Tim Penhey
Make sure that revision karma doesn't create a future karma event. |
206 |
revision_date=datetime.now(pytz.UTC) + timedelta(days=5)) |
7362.12.24
by Jonathan Lange
Restore change that somehow got lost. |
207 |
branch = self.factory.makeProductBranch() |
7675.439.5
by Tim Penhey
Make the test_karmaDateForFutureRevisions actually test what it says it is testing. |
208 |
karma = rev.allocateKarma(branch) |
6950.1.1
by Tim Penhey
Make sure that revision karma doesn't create a future karma event. |
209 |
self.assertEqual(karma.datecreated, rev.date_created) |
210 |
||
7675.439.6
by Tim Penhey
Tests to show karma allocation for products and packages. |
211 |
def test_allocateKarma_personal_branch(self): |
212 |
# A personal branch gets no karma event.
|
|
213 |
author = self.factory.makePerson() |
|
7675.439.7
by Tim Penhey
simplify the revision creation |
214 |
rev = self.factory.makeRevision(author=author) |
7675.439.6
by Tim Penhey
Tests to show karma allocation for products and packages. |
215 |
branch = self.factory.makePersonalBranch() |
216 |
karma = rev.allocateKarma(branch) |
|
217 |
self.assertIs(None, karma) |
|
218 |
||
219 |
def test_allocateKarma_package_branch(self): |
|
220 |
# A revision on a package branch gets karma.
|
|
221 |
author = self.factory.makePerson() |
|
7675.439.7
by Tim Penhey
simplify the revision creation |
222 |
rev = self.factory.makeRevision(author=author) |
7675.439.6
by Tim Penhey
Tests to show karma allocation for products and packages. |
223 |
branch = self.factory.makePackageBranch() |
224 |
karma = rev.allocateKarma(branch) |
|
225 |
self.assertEqual(author, karma.person) |
|
226 |
self.assertEqual(branch.distribution, karma.distribution) |
|
227 |
self.assertEqual(branch.sourcepackagename, karma.sourcepackagename) |
|
228 |
||
229 |
def test_allocateKarma_product_branch(self): |
|
230 |
# A revision on a product branch gets karma.
|
|
231 |
author = self.factory.makePerson() |
|
7675.439.7
by Tim Penhey
simplify the revision creation |
232 |
rev = self.factory.makeRevision(author=author) |
7675.439.6
by Tim Penhey
Tests to show karma allocation for products and packages. |
233 |
branch = self.factory.makeProductBranch() |
234 |
karma = rev.allocateKarma(branch) |
|
235 |
self.assertEqual(author, karma.person) |
|
236 |
self.assertEqual(branch.product, karma.product) |
|
237 |
||
6623.4.6
by Tim Penhey
Hook up the claiming of older revisions. |
238 |
|
11116.5.6
by Jonathan Lange
More unit test coverage to replace branch.txt |
239 |
class TestRevisionSet(TestCaseWithFactory): |
240 |
"""Tests for IRevisionSet."""
|
|
241 |
||
242 |
layer = DatabaseFunctionalLayer |
|
243 |
||
244 |
def setUp(self): |
|
245 |
super(TestRevisionSet, self).setUp() |
|
246 |
self.revision_set = getUtility(IRevisionSet) |
|
247 |
||
248 |
def test_getRevisionById_existing(self): |
|
249 |
# IRevisionSet.getByRevisionId returns the revision with that id.
|
|
250 |
revision = self.factory.makeRevision() |
|
251 |
found = self.revision_set.getByRevisionId(revision.revision_id) |
|
252 |
self.assertEquals(revision, found) |
|
253 |
||
254 |
def test_getRevisionById_nonexistent(self): |
|
255 |
# IRevisionSet.getByRevisionId returns None if there is no revision
|
|
256 |
# with that id.
|
|
257 |
found = self.revision_set.getByRevisionId('nonexistent') |
|
258 |
self.assertIs(None, found) |
|
259 |
||
260 |
||
6736.3.4
by Tim Penhey
Added tests for addition Revision and RevisionSet methods. |
261 |
class TestRevisionGetBranch(TestCaseWithFactory): |
262 |
"""Test the `getBranch` method of the revision."""
|
|
263 |
||
6736.3.22
by Tim Penhey
Changed the test layers. |
264 |
layer = DatabaseFunctionalLayer |
6736.3.4
by Tim Penhey
Added tests for addition Revision and RevisionSet methods. |
265 |
|
266 |
def setUp(self): |
|
267 |
# Use an administrator to set branch privacy easily.
|
|
6736.3.16
by Tim Penhey
Add the revision feed for products and projects. |
268 |
TestCaseWithFactory.setUp(self, "admin@canonical.com") |
6736.3.4
by Tim Penhey
Added tests for addition Revision and RevisionSet methods. |
269 |
self.author = self.factory.makePerson() |
270 |
self.revision = self.factory.makeRevision( |
|
271 |
author=self.author.preferredemail.email) |
|
272 |
||
6623.4.25
by Tim Penhey
Make sure we don't try to allocate karma to junk branches. |
273 |
def makeBranchWithRevision(self, sequence, **kwargs): |
7362.12.24
by Jonathan Lange
Restore change that somehow got lost. |
274 |
branch = self.factory.makeAnyBranch(**kwargs) |
6736.3.12
by Tim Penhey
Updates following review. |
275 |
branch.createBranchRevision(sequence, self.revision) |
276 |
return branch |
|
277 |
||
6736.3.4
by Tim Penhey
Added tests for addition Revision and RevisionSet methods. |
278 |
def testPreferAuthorBranch(self): |
279 |
# If a revision is on the mainline history of two (or more) different
|
|
280 |
# branches, then choose one owned by the revision author.
|
|
6736.3.12
by Tim Penhey
Updates following review. |
281 |
self.makeBranchWithRevision(1) |
6736.3.13
by Tim Penhey
Another tweak to the tests. |
282 |
b = self.makeBranchWithRevision(1, owner=self.author) |
6736.3.12
by Tim Penhey
Updates following review. |
283 |
self.assertEqual(b, self.revision.getBranch()) |
6736.3.4
by Tim Penhey
Added tests for addition Revision and RevisionSet methods. |
284 |
|
285 |
def testPreferMainlineRevisionBranch(self): |
|
286 |
# Choose a branch where the revision is on the mainline history over a
|
|
287 |
# branch where the revision is just in the ancestry.
|
|
6736.3.12
by Tim Penhey
Updates following review. |
288 |
self.makeBranchWithRevision(None) |
289 |
b = self.makeBranchWithRevision(1) |
|
290 |
self.assertEqual(b, self.revision.getBranch()) |
|
6736.3.4
by Tim Penhey
Added tests for addition Revision and RevisionSet methods. |
291 |
|
292 |
def testOwnerTrunksMainline(self): |
|
293 |
# If the revision is mainline on a branch not owned by the revision
|
|
294 |
# owner, but in the ancestry of a branch owned by the revision owner,
|
|
295 |
# choose the branch owned by the revision author.
|
|
6736.3.12
by Tim Penhey
Updates following review. |
296 |
self.makeBranchWithRevision(1) |
6736.3.13
by Tim Penhey
Another tweak to the tests. |
297 |
b = self.makeBranchWithRevision(None, owner=self.author) |
6736.3.12
by Tim Penhey
Updates following review. |
298 |
self.assertEqual(b, self.revision.getBranch()) |
6736.3.4
by Tim Penhey
Added tests for addition Revision and RevisionSet methods. |
299 |
|
300 |
def testPublicBranchTrumpsOwner(self): |
|
301 |
# Only public branches are returned.
|
|
6736.3.12
by Tim Penhey
Updates following review. |
302 |
b1 = self.makeBranchWithRevision(1) |
6736.3.13
by Tim Penhey
Another tweak to the tests. |
303 |
b2 = self.makeBranchWithRevision(1, owner=self.author) |
13760.3.10
by Ian Booth
Rework implementation to remove metaclass and setattr - use explicitly_private property |
304 |
removeSecurityProxy(b2).explicitly_private = True |
6736.3.4
by Tim Penhey
Added tests for addition Revision and RevisionSet methods. |
305 |
self.assertEqual(b1, self.revision.getBranch()) |
6623.4.18
by Tim Penhey
More review updates. |
306 |
|
307 |
def testAllowPrivateReturnsPrivateBranch(self): |
|
308 |
# If the allow_private flag is set, then private branches can be
|
|
309 |
# returned if they are the best match.
|
|
14083.1.1
by Jeroen Vermeulen
Lint. |
310 |
self.makeBranchWithRevision(1) |
6623.4.18
by Tim Penhey
More review updates. |
311 |
b2 = self.makeBranchWithRevision(1, owner=self.author) |
13760.3.10
by Ian Booth
Rework implementation to remove metaclass and setattr - use explicitly_private property |
312 |
removeSecurityProxy(b2).explicitly_private = True |
6623.4.18
by Tim Penhey
More review updates. |
313 |
self.assertEqual(b2, self.revision.getBranch(allow_private=True)) |
314 |
||
315 |
def testAllowPrivateCanReturnPublic(self): |
|
316 |
# Allowing private branches does not change the priority ordering of
|
|
317 |
# the branches.
|
|
318 |
b1 = self.makeBranchWithRevision(1) |
|
319 |
b2 = self.makeBranchWithRevision(1, owner=self.author) |
|
13760.3.10
by Ian Booth
Rework implementation to remove metaclass and setattr - use explicitly_private property |
320 |
removeSecurityProxy(b1).explicitly_private = True |
6623.4.6
by Tim Penhey
Hook up the claiming of older revisions. |
321 |
self.assertEqual(b2, self.revision.getBranch(allow_private=True)) |
6736.3.4
by Tim Penhey
Added tests for addition Revision and RevisionSet methods. |
322 |
|
6623.4.25
by Tim Penhey
Make sure we don't try to allocate karma to junk branches. |
323 |
def testGetBranchNotJunk(self): |
324 |
# If allow_junk is set to False, then branches without products are
|
|
6623.4.27
by Tim Penhey
Slight fixes following review. |
325 |
# not returned.
|
7362.12.35
by Jonathan Lange
Watch as I fix more code to use correct semantics. |
326 |
b1 = self.factory.makeProductBranch() |
327 |
b1.createBranchRevision(1, self.revision) |
|
328 |
b2 = self.factory.makePersonalBranch(owner=self.author) |
|
329 |
b2.createBranchRevision(1, self.revision) |
|
6623.4.25
by Tim Penhey
Make sure we don't try to allocate karma to junk branches. |
330 |
self.assertEqual( |
331 |
b1, self.revision.getBranch(allow_private=True, allow_junk=False)) |
|
332 |
||
9894.5.1
by Muharem Hrnjadovic
Bug fixed. |
333 |
def testGetBranchSourcePackage(self): |
334 |
# Branches targetting source packages are not junk.
|
|
335 |
b1 = self.factory.makePackageBranch() |
|
336 |
b1.createBranchRevision(1, self.revision) |
|
337 |
b2 = self.factory.makePersonalBranch(owner=self.author) |
|
338 |
b2.createBranchRevision(1, self.revision) |
|
339 |
self.assertEqual( |
|
340 |
b1, self.revision.getBranch(allow_private=True, allow_junk=False)) |
|
341 |
||
6736.3.4
by Tim Penhey
Added tests for addition Revision and RevisionSet methods. |
342 |
|
6950.2.1
by Tim Penhey
Update the revision getting methods to be date bound to speed up queries. |
343 |
class GetPublicRevisionsTestCase(TestCaseWithFactory): |
344 |
"""A base class for the tests for people, products and projects."""
|
|
345 |
||
346 |
layer = DatabaseFunctionalLayer |
|
347 |
||
348 |
def setUp(self): |
|
349 |
# Use an administrator to set branch privacy easily.
|
|
350 |
TestCaseWithFactory.setUp(self, "admin@canonical.com") |
|
351 |
# Since the tests order by date, but also limit to the last 30
|
|
352 |
# days, we want a time counter that starts 10 days ago.
|
|
353 |
self.date_generator = time_counter( |
|
354 |
datetime.now(pytz.UTC) - timedelta(days=10), |
|
355 |
delta=timedelta(days=1)) |
|
356 |
||
357 |
def _makeRevision(self, revision_date=None): |
|
358 |
"""Make a revision using the date generator."""
|
|
359 |
if revision_date is None: |
|
360 |
revision_date = self.date_generator.next() |
|
361 |
return self.factory.makeRevision( |
|
362 |
revision_date=revision_date) |
|
363 |
||
364 |
def _addRevisionsToBranch(self, branch, *revs): |
|
8037.2.1
by Brad Crittenden
fixed annoying typos |
365 |
# Add the revisions to the branch.
|
6950.2.1
by Tim Penhey
Update the revision getting methods to be date bound to speed up queries. |
366 |
for sequence, rev in enumerate(revs): |
367 |
branch.createBranchRevision(sequence, rev) |
|
368 |
||
369 |
def _makeBranch(self, product=None): |
|
370 |
# Make a branch.
|
|
371 |
if product is None: |
|
372 |
# If the test defines a product, use that, otherwise
|
|
373 |
# have the factory generate one.
|
|
374 |
product = getattr(self, 'product', None) |
|
7362.12.24
by Jonathan Lange
Restore change that somehow got lost. |
375 |
return self.factory.makeProductBranch(product=product) |
6950.2.1
by Tim Penhey
Update the revision getting methods to be date bound to speed up queries. |
376 |
|
377 |
def _makeRevisionInBranch(self, product=None): |
|
378 |
# Make a revision, and associate it with a branch. The branch is made
|
|
379 |
# with the product passed in, which means that if there was no product
|
|
380 |
# passed in, the factory makes a new one.
|
|
7362.12.35
by Jonathan Lange
Watch as I fix more code to use correct semantics. |
381 |
branch = self.factory.makeProductBranch(product=product) |
6950.2.1
by Tim Penhey
Update the revision getting methods to be date bound to speed up queries. |
382 |
rev = self._makeRevision() |
383 |
branch.createBranchRevision(1, rev) |
|
384 |
return rev |
|
385 |
||
386 |
def _getRevisions(self, day_limit=30): |
|
387 |
raise NotImplementedError('_getRevisions') |
|
388 |
||
6950.2.4
by Tim Penhey
Fix test failures |
389 |
|
390 |
class RevisionTestMixin: |
|
391 |
"""Common tests for the different GetPublicRevision test cases."""
|
|
392 |
||
6950.2.1
by Tim Penhey
Update the revision getting methods to be date bound to speed up queries. |
393 |
def testNewestRevisionFirst(self): |
394 |
# The revisions are ordered with the newest first.
|
|
395 |
rev1 = self._makeRevision() |
|
396 |
rev2 = self._makeRevision() |
|
397 |
rev3 = self._makeRevision() |
|
398 |
self._addRevisionsToBranch(self._makeBranch(), rev1, rev2, rev3) |
|
399 |
self.assertEqual([rev3, rev2, rev1], self._getRevisions()) |
|
400 |
||
401 |
def testRevisionsOnlyReturnedOnce(self): |
|
402 |
# If the revisions appear in multiple branches, they are only returned
|
|
403 |
# once.
|
|
404 |
rev1 = self._makeRevision() |
|
405 |
rev2 = self._makeRevision() |
|
406 |
rev3 = self._makeRevision() |
|
407 |
self._addRevisionsToBranch( |
|
408 |
self._makeBranch(), rev1, rev2, rev3) |
|
409 |
self._addRevisionsToBranch( |
|
410 |
self._makeBranch(), rev1, rev2, rev3) |
|
411 |
self.assertEqual([rev3, rev2, rev1], self._getRevisions()) |
|
412 |
||
413 |
def testRevisionsMustBeInABranch(self): |
|
414 |
# A revision authored by the person must be in a branch to be
|
|
415 |
# returned.
|
|
416 |
rev1 = self._makeRevision() |
|
417 |
self.assertEqual([], self._getRevisions()) |
|
418 |
b = self._makeBranch() |
|
419 |
b.createBranchRevision(1, rev1) |
|
420 |
self.assertEqual([rev1], self._getRevisions()) |
|
421 |
||
422 |
def testRevisionsMustBeInAPublicBranch(self): |
|
423 |
# A revision authored by the person must be in a branch to be
|
|
424 |
# returned.
|
|
425 |
rev1 = self._makeRevision() |
|
426 |
b = self._makeBranch() |
|
427 |
b.createBranchRevision(1, rev1) |
|
13760.3.10
by Ian Booth
Rework implementation to remove metaclass and setattr - use explicitly_private property |
428 |
removeSecurityProxy(b).explicitly_private = True |
6950.2.1
by Tim Penhey
Update the revision getting methods to be date bound to speed up queries. |
429 |
self.assertEqual([], self._getRevisions()) |
430 |
||
431 |
def testRevisionDateRange(self): |
|
7925.4.2
by Tim Penhey
Fix tests that relied on creating future revision dates. |
432 |
# Revisions where the revision_date is older than the day_limit are
|
433 |
# not returned.
|
|
6950.2.1
by Tim Penhey
Update the revision getting methods to be date bound to speed up queries. |
434 |
now = datetime.now(pytz.UTC) |
435 |
day_limit = 5 |
|
436 |
# Make the first revision earlier than our day limit.
|
|
437 |
rev1 = self._makeRevision( |
|
438 |
revision_date=(now - timedelta(days=(day_limit + 2)))) |
|
439 |
# The second one is just two days ago.
|
|
440 |
rev2 = self._makeRevision( |
|
441 |
revision_date=(now - timedelta(days=2))) |
|
7925.4.2
by Tim Penhey
Fix tests that relied on creating future revision dates. |
442 |
self._addRevisionsToBranch(self._makeBranch(), rev1, rev2) |
12337.2.5
by Jeroen Vermeulen
Lint. |
443 |
self.assertEqual([rev2], self._getRevisions(day_limit)) |
6950.2.1
by Tim Penhey
Update the revision getting methods to be date bound to speed up queries. |
444 |
|
445 |
||
6950.2.4
by Tim Penhey
Fix test failures |
446 |
class TestGetPublicRevisionsForPerson(GetPublicRevisionsTestCase, |
447 |
RevisionTestMixin): |
|
6736.3.4
by Tim Penhey
Added tests for addition Revision and RevisionSet methods. |
448 |
"""Test the `getPublicRevisionsForPerson` method of `RevisionSet`."""
|
449 |
||
450 |
def setUp(self): |
|
6950.2.1
by Tim Penhey
Update the revision getting methods to be date bound to speed up queries. |
451 |
GetPublicRevisionsTestCase.setUp(self) |
6736.3.4
by Tim Penhey
Added tests for addition Revision and RevisionSet methods. |
452 |
self.author = self.factory.makePerson() |
453 |
self.revision = self.factory.makeRevision( |
|
454 |
author=self.author.preferredemail.email) |
|
6950.2.1
by Tim Penhey
Update the revision getting methods to be date bound to speed up queries. |
455 |
|
456 |
def _getRevisions(self, day_limit=30): |
|
457 |
# Returns the revisions for the person.
|
|
458 |
return list(RevisionSet.getPublicRevisionsForPerson( |
|
459 |
self.author, day_limit)) |
|
460 |
||
461 |
def _makeRevision(self, author=None, revision_date=None): |
|
6736.3.12
by Tim Penhey
Updates following review. |
462 |
"""Make a revision owned by `author`.
|
463 |
||
464 |
`author` defaults to self.author if not set."""
|
|
6950.2.1
by Tim Penhey
Update the revision getting methods to be date bound to speed up queries. |
465 |
if revision_date is None: |
466 |
revision_date = self.date_generator.next() |
|
6736.3.4
by Tim Penhey
Added tests for addition Revision and RevisionSet methods. |
467 |
if author is None: |
468 |
author = self.author |
|
469 |
return self.factory.makeRevision( |
|
470 |
author=author.preferredemail.email, |
|
6950.2.1
by Tim Penhey
Update the revision getting methods to be date bound to speed up queries. |
471 |
revision_date=revision_date) |
6736.3.4
by Tim Penhey
Added tests for addition Revision and RevisionSet methods. |
472 |
|
473 |
def testTeamRevisions(self): |
|
6736.3.16
by Tim Penhey
Add the revision feed for products and projects. |
474 |
# Revisions owned by all members of a team are returned.
|
6736.3.4
by Tim Penhey
Added tests for addition Revision and RevisionSet methods. |
475 |
team = self.factory.makeTeam(self.author) |
476 |
team_member = self.factory.makePerson() |
|
477 |
team.addMember(team_member, self.author) |
|
478 |
rev1 = self._makeRevision() |
|
479 |
rev2 = self._makeRevision(team_member) |
|
480 |
rev3 = self._makeRevision(self.factory.makePerson()) |
|
7362.12.24
by Jonathan Lange
Restore change that somehow got lost. |
481 |
branch = self.factory.makeAnyBranch() |
6736.3.4
by Tim Penhey
Added tests for addition Revision and RevisionSet methods. |
482 |
self._addRevisionsToBranch(branch, rev1, rev2, rev3) |
6950.2.1
by Tim Penhey
Update the revision getting methods to be date bound to speed up queries. |
483 |
self.assertEqual([rev2, rev1], |
484 |
list(RevisionSet.getPublicRevisionsForPerson(team))) |
|
485 |
||
486 |
||
6950.2.4
by Tim Penhey
Fix test failures |
487 |
class TestGetPublicRevisionsForProduct(GetPublicRevisionsTestCase, |
488 |
RevisionTestMixin): |
|
6736.3.20
by Tim Penhey
Separate out the product and project method calls. |
489 |
"""Test the `getPublicRevisionsForProduct` method of `RevisionSet`."""
|
490 |
||
491 |
def setUp(self): |
|
6950.2.1
by Tim Penhey
Update the revision getting methods to be date bound to speed up queries. |
492 |
GetPublicRevisionsTestCase.setUp(self) |
6736.3.20
by Tim Penhey
Separate out the product and project method calls. |
493 |
self.product = self.factory.makeProduct() |
494 |
||
6950.2.1
by Tim Penhey
Update the revision getting methods to be date bound to speed up queries. |
495 |
def _getRevisions(self, day_limit=30): |
496 |
# Returns the revisions for the person.
|
|
497 |
return list(RevisionSet.getPublicRevisionsForProduct( |
|
498 |
self.product, day_limit)) |
|
6736.3.20
by Tim Penhey
Separate out the product and project method calls. |
499 |
|
500 |
def testRevisionsMustBeInABranchOfProduct(self): |
|
501 |
# The revision must be in a branch for the product.
|
|
502 |
# returned.
|
|
503 |
rev1 = self._makeRevisionInBranch(product=self.product) |
|
14083.1.1
by Jeroen Vermeulen
Lint. |
504 |
self._makeRevisionInBranch() |
6950.2.1
by Tim Penhey
Update the revision getting methods to be date bound to speed up queries. |
505 |
self.assertEqual([rev1], self._getRevisions()) |
506 |
||
507 |
||
10724.1.1
by Henning Eggers
First batch of Project -> ProjectGrpoup renamings. |
508 |
class TestGetPublicRevisionsForProjectGroup(GetPublicRevisionsTestCase, |
509 |
RevisionTestMixin): |
|
510 |
"""Test the `getPublicRevisionsForProjectGroup` method of `RevisionSet`.
|
|
511 |
"""
|
|
6736.3.16
by Tim Penhey
Add the revision feed for products and projects. |
512 |
|
513 |
def setUp(self): |
|
6950.2.1
by Tim Penhey
Update the revision getting methods to be date bound to speed up queries. |
514 |
GetPublicRevisionsTestCase.setUp(self) |
6736.3.16
by Tim Penhey
Add the revision feed for products and projects. |
515 |
self.project = self.factory.makeProject() |
516 |
self.product = self.factory.makeProduct(project=self.project) |
|
517 |
||
6950.2.1
by Tim Penhey
Update the revision getting methods to be date bound to speed up queries. |
518 |
def _getRevisions(self, day_limit=30): |
519 |
# Returns the revisions for the person.
|
|
10724.1.1
by Henning Eggers
First batch of Project -> ProjectGrpoup renamings. |
520 |
return list(RevisionSet.getPublicRevisionsForProjectGroup( |
6950.2.1
by Tim Penhey
Update the revision getting methods to be date bound to speed up queries. |
521 |
self.project, day_limit)) |
6736.3.16
by Tim Penhey
Add the revision feed for products and projects. |
522 |
|
523 |
def testRevisionsMustBeInABranchOfProduct(self): |
|
524 |
# The revision must be in a branch for the product.
|
|
525 |
# returned.
|
|
526 |
rev1 = self._makeRevisionInBranch(product=self.product) |
|
14083.1.1
by Jeroen Vermeulen
Lint. |
527 |
self._makeRevisionInBranch() |
6950.2.1
by Tim Penhey
Update the revision getting methods to be date bound to speed up queries. |
528 |
self.assertEqual([rev1], self._getRevisions()) |
6736.3.16
by Tim Penhey
Add the revision feed for products and projects. |
529 |
|
530 |
def testProjectRevisions(self): |
|
531 |
# Revisions in all products that are part of the project are returned.
|
|
532 |
another_product = self.factory.makeProduct(project=self.project) |
|
533 |
rev1 = self._makeRevisionInBranch(product=self.product) |
|
534 |
rev2 = self._makeRevisionInBranch(product=another_product) |
|
14083.1.1
by Jeroen Vermeulen
Lint. |
535 |
self._makeRevisionInBranch() |
6950.2.1
by Tim Penhey
Update the revision getting methods to be date bound to speed up queries. |
536 |
self.assertEqual([rev2, rev1], self._getRevisions()) |
6736.3.16
by Tim Penhey
Add the revision feed for products and projects. |
537 |
|
538 |
||
7028.1.1
by Tim Penhey
Speed up the query that is used to count the number of new revisions shown on the +code-index and +branches pages for products. |
539 |
class TestGetRecentRevisionsForProduct(GetPublicRevisionsTestCase): |
540 |
"""Test the `getRecentRevisionsForProduct` method of `RevisionSet`."""
|
|
541 |
||
542 |
def setUp(self): |
|
543 |
GetPublicRevisionsTestCase.setUp(self) |
|
544 |
self.product = self.factory.makeProduct() |
|
545 |
||
546 |
def _getRecentRevisions(self, day_limit=30): |
|
547 |
# Return a list of the recent revisions and revision authors.
|
|
548 |
return list(RevisionSet.getRecentRevisionsForProduct( |
|
549 |
self.product, day_limit)) |
|
550 |
||
551 |
def testRevisionAuthorMatchesRevision(self): |
|
552 |
# The revision author returned with the revision is the same as the
|
|
553 |
# author for the revision.
|
|
14083.1.1
by Jeroen Vermeulen
Lint. |
554 |
self._makeRevisionInBranch(product=self.product) |
7028.1.1
by Tim Penhey
Speed up the query that is used to count the number of new revisions shown on the +code-index and +branches pages for products. |
555 |
results = self._getRecentRevisions() |
14083.1.1
by Jeroen Vermeulen
Lint. |
556 |
[(revision, revision_author)] = results |
7028.1.1
by Tim Penhey
Speed up the query that is used to count the number of new revisions shown on the +code-index and +branches pages for products. |
557 |
self.assertEqual(revision.revision_author, revision_author) |
558 |
||
559 |
def testRevisionsMustBeInABranchOfProduct(self): |
|
560 |
# The revisions returned revision must be in a branch for the product.
|
|
561 |
rev1 = self._makeRevisionInBranch(product=self.product) |
|
14083.1.1
by Jeroen Vermeulen
Lint. |
562 |
self._makeRevisionInBranch() |
563 |
self.assertEqual( |
|
564 |
[(rev1, rev1.revision_author)], self._getRecentRevisions()) |
|
7028.1.1
by Tim Penhey
Speed up the query that is used to count the number of new revisions shown on the +code-index and +branches pages for products. |
565 |
|
8079.2.1
by Tim Penhey
Write the failing test. |
566 |
def testRevisionsMustBeInActiveBranches(self): |
567 |
# The revisions returned revision must be in a branch for the product.
|
|
568 |
rev1 = self._makeRevisionInBranch(product=self.product) |
|
569 |
branch = self.factory.makeProductBranch( |
|
570 |
product=self.product, |
|
571 |
lifecycle_status=BranchLifecycleStatus.MERGED) |
|
572 |
branch.createBranchRevision(1, self._makeRevision()) |
|
573 |
self.assertEqual([(rev1, rev1.revision_author)], |
|
574 |
self._getRecentRevisions()) |
|
575 |
||
7028.1.1
by Tim Penhey
Speed up the query that is used to count the number of new revisions shown on the +code-index and +branches pages for products. |
576 |
def testRevisionDateRange(self): |
7925.4.2
by Tim Penhey
Fix tests that relied on creating future revision dates. |
577 |
# Revisions where the revision_date is older than the day_limit are
|
578 |
# not returned.
|
|
7028.1.1
by Tim Penhey
Speed up the query that is used to count the number of new revisions shown on the +code-index and +branches pages for products. |
579 |
now = datetime.now(pytz.UTC) |
580 |
day_limit = 5 |
|
581 |
# Make the first revision earlier than our day limit.
|
|
582 |
rev1 = self._makeRevision( |
|
583 |
revision_date=(now - timedelta(days=(day_limit + 2)))) |
|
584 |
# The second one is just two days ago.
|
|
585 |
rev2 = self._makeRevision(revision_date=(now - timedelta(days=2))) |
|
7925.4.2
by Tim Penhey
Fix tests that relied on creating future revision dates. |
586 |
self._addRevisionsToBranch(self._makeBranch(), rev1, rev2) |
7028.1.1
by Tim Penhey
Speed up the query that is used to count the number of new revisions shown on the +code-index and +branches pages for products. |
587 |
self.assertEqual([(rev2, rev2.revision_author)], |
588 |
self._getRecentRevisions(day_limit)) |
|
589 |
||
590 |
||
5743.2.1
by Tim Penhey
Add method to get branch revisions for multiple branches at once. |
591 |
class TestTipRevisionsForBranches(TestCase): |
592 |
"""Test that the tip revisions get returned properly."""
|
|
593 |
||
6736.3.22
by Tim Penhey
Changed the test layers. |
594 |
layer = DatabaseFunctionalLayer |
5743.2.1
by Tim Penhey
Add method to get branch revisions for multiple branches at once. |
595 |
|
596 |
def setUp(self): |
|
597 |
login('test@canonical.com') |
|
598 |
||
599 |
factory = LaunchpadObjectFactory() |
|
7362.12.24
by Jonathan Lange
Restore change that somehow got lost. |
600 |
branches = [factory.makeAnyBranch() for count in range(5)] |
5743.2.1
by Tim Penhey
Add method to get branch revisions for multiple branches at once. |
601 |
branch_ids = [branch.id for branch in branches] |
602 |
for branch in branches: |
|
603 |
factory.makeRevisionsForBranch(branch) |
|
604 |
# Retrieve the updated branches (due to transaction boundaries).
|
|
7940.2.5
by Jonathan Lange
Move branch lookup methods to IBranchLookup |
605 |
branch_set = getUtility(IBranchLookup) |
5743.2.1
by Tim Penhey
Add method to get branch revisions for multiple branches at once. |
606 |
self.branches = [branch_set.get(id) for id in branch_ids] |
5743.2.2
by Tim Penhey
Listing now has revision number and codebrowse hyperlink. |
607 |
self.revision_set = getUtility(IRevisionSet) |
5743.2.1
by Tim Penhey
Add method to get branch revisions for multiple branches at once. |
608 |
|
609 |
def tearDown(self): |
|
610 |
logout() |
|
611 |
||
612 |
def _breakTransaction(self): |
|
613 |
# make sure the current transaction can not be committed by
|
|
614 |
# sending a broken SQL statement to the database
|
|
615 |
try: |
|
616 |
cursor().execute('break this transaction') |
|
5821.2.32
by James Henstridge
* s/psycopg/psycopg2/ in a few more places. |
617 |
except psycopg2.DatabaseError: |
5743.2.1
by Tim Penhey
Add method to get branch revisions for multiple branches at once. |
618 |
pass
|
619 |
||
620 |
def testNoBranches(self): |
|
621 |
"""Assert that when given an empty list, an empty list is returned."""
|
|
5743.2.2
by Tim Penhey
Listing now has revision number and codebrowse hyperlink. |
622 |
bs = self.revision_set |
623 |
revisions = bs.getTipRevisionsForBranches([]) |
|
5743.2.6
by Tim Penhey
Updates following review |
624 |
self.assertTrue(revisions is None) |
5743.2.1
by Tim Penhey
Add method to get branch revisions for multiple branches at once. |
625 |
|
626 |
def testOneBranches(self): |
|
627 |
"""When given one branch, one branch revision is returned."""
|
|
5743.2.2
by Tim Penhey
Listing now has revision number and codebrowse hyperlink. |
628 |
revisions = list( |
629 |
self.revision_set.getTipRevisionsForBranches( |
|
5743.2.1
by Tim Penhey
Add method to get branch revisions for multiple branches at once. |
630 |
self.branches[:1])) |
5821.6.10
by James Henstridge
Fix up some of the branch/revision tests to account for some |
631 |
# XXX jamesh 2008-06-02: ensure that branch[0] is loaded
|
7940.2.5
by Jonathan Lange
Move branch lookup methods to IBranchLookup |
632 |
last_scanned_id = self.branches[0].last_scanned_id |
5743.2.1
by Tim Penhey
Add method to get branch revisions for multiple branches at once. |
633 |
self._breakTransaction() |
5743.2.2
by Tim Penhey
Listing now has revision number and codebrowse hyperlink. |
634 |
self.assertEqual(1, len(revisions)) |
635 |
revision = revisions[0] |
|
14083.1.1
by Jeroen Vermeulen
Lint. |
636 |
self.assertEqual(last_scanned_id, revision.revision_id) |
5743.2.2
by Tim Penhey
Listing now has revision number and codebrowse hyperlink. |
637 |
# By accessing to the revision_author we can confirm that the
|
638 |
# revision author has in fact been retrieved already.
|
|
639 |
revision_author = revision.revision_author |
|
640 |
self.assertTrue(revision_author is not None) |
|
5743.2.1
by Tim Penhey
Add method to get branch revisions for multiple branches at once. |
641 |
|
642 |
def testManyBranches(self): |
|
643 |
"""Assert multiple branch revisions are returned correctly."""
|
|
5743.2.2
by Tim Penhey
Listing now has revision number and codebrowse hyperlink. |
644 |
revisions = list( |
645 |
self.revision_set.getTipRevisionsForBranches( |
|
5743.2.1
by Tim Penhey
Add method to get branch revisions for multiple branches at once. |
646 |
self.branches)) |
647 |
self._breakTransaction() |
|
5743.2.2
by Tim Penhey
Listing now has revision number and codebrowse hyperlink. |
648 |
self.assertEqual(5, len(revisions)) |
649 |
for revision in revisions: |
|
650 |
# By accessing to the revision_author we can confirm that the
|
|
651 |
# revision author has in fact been retrieved already.
|
|
652 |
revision_author = revision.revision_author |
|
653 |
self.assertTrue(revision_author is not None) |
|
5743.2.1
by Tim Penhey
Add method to get branch revisions for multiple branches at once. |
654 |
|
6789.3.9
by Jonathan Lange
Move the revision from bzr revision method into RevisionSet. |
655 |
def test_timestampToDatetime_with_negative_fractional(self): |
656 |
# timestampToDatetime should convert a negative, fractional timestamp
|
|
657 |
# into a valid, sane datetime object.
|
|
658 |
revision_set = removeSecurityProxy(getUtility(IRevisionSet)) |
|
659 |
UTC = pytz.timezone('UTC') |
|
660 |
timestamp = -0.5 |
|
661 |
date = revision_set._timestampToDatetime(timestamp) |
|
662 |
self.assertEqual( |
|
6789.3.12
by Jonathan Lange
Merge trunk, resolving conflicts. |
663 |
date, datetime(1969, 12, 31, 23, 59, 59, 500000, UTC)) |
6789.3.9
by Jonathan Lange
Move the revision from bzr revision method into RevisionSet. |
664 |
|
665 |
def test_timestampToDatetime(self): |
|
666 |
# timestampTODatetime should convert a regular timestamp into a valid,
|
|
667 |
# sane datetime object.
|
|
668 |
revision_set = removeSecurityProxy(getUtility(IRevisionSet)) |
|
669 |
UTC = pytz.timezone('UTC') |
|
670 |
timestamp = time.time() |
|
6789.3.12
by Jonathan Lange
Merge trunk, resolving conflicts. |
671 |
date = datetime.fromtimestamp(timestamp, tz=UTC) |
6789.3.9
by Jonathan Lange
Move the revision from bzr revision method into RevisionSet. |
672 |
self.assertEqual(date, revision_set._timestampToDatetime(timestamp)) |
673 |
||
5743.2.1
by Tim Penhey
Add method to get branch revisions for multiple branches at once. |
674 |
|
7049.1.13
by Michael Hudson
tests for onlyPresent |
675 |
class TestOnlyPresent(TestCaseWithFactory): |
7049.1.16
by Michael Hudson
docstrings, comments |
676 |
"""Tests for `RevisionSet.onlyPresent`.
|
677 |
||
678 |
Note that although onlyPresent returns a set, it is a security proxied
|
|
679 |
set, so we have to convert it to a real set before doing any comparisons.
|
|
680 |
"""
|
|
7049.1.13
by Michael Hudson
tests for onlyPresent |
681 |
|
682 |
layer = DatabaseFunctionalLayer |
|
683 |
||
684 |
def test_empty(self): |
|
7049.1.16
by Michael Hudson
docstrings, comments |
685 |
# onlyPresent returns no results when passed no revids.
|
686 |
self.assertEqual( |
|
687 |
set(), |
|
688 |
set(getUtility(IRevisionSet).onlyPresent([]))) |
|
7049.1.13
by Michael Hudson
tests for onlyPresent |
689 |
|
690 |
def test_none_present(self): |
|
7049.1.16
by Michael Hudson
docstrings, comments |
691 |
# onlyPresent returns no results when passed a revid not present in
|
692 |
# the database.
|
|
7049.1.13
by Michael Hudson
tests for onlyPresent |
693 |
not_present = self.factory.getUniqueString() |
694 |
self.assertEqual( |
|
695 |
set(), |
|
696 |
set(getUtility(IRevisionSet).onlyPresent([not_present]))) |
|
697 |
||
698 |
def test_one_present(self): |
|
7049.1.16
by Michael Hudson
docstrings, comments |
699 |
# onlyPresent returns a revid that is present in the database.
|
7049.1.13
by Michael Hudson
tests for onlyPresent |
700 |
present = self.factory.makeRevision().revision_id |
701 |
self.assertEqual( |
|
702 |
set([present]), |
|
703 |
set(getUtility(IRevisionSet).onlyPresent([present]))) |
|
704 |
||
705 |
def test_some_present(self): |
|
7049.1.16
by Michael Hudson
docstrings, comments |
706 |
# onlyPresent returns only the revid that is present in the database.
|
7049.1.13
by Michael Hudson
tests for onlyPresent |
707 |
not_present = self.factory.getUniqueString() |
708 |
present = self.factory.makeRevision().revision_id |
|
709 |
self.assertEqual( |
|
710 |
set([present]), |
|
711 |
set(getUtility(IRevisionSet).onlyPresent([present, not_present]))) |
|
712 |
||
7049.1.16
by Michael Hudson
docstrings, comments |
713 |
def test_call_twice_in_one_transaction(self): |
714 |
# onlyPresent creates temporary tables, but cleans after itself so
|
|
715 |
# that it can safely be called twice in one transaction.
|
|
716 |
not_present = self.factory.getUniqueString() |
|
717 |
getUtility(IRevisionSet).onlyPresent([not_present]) |
|
718 |
# This is just "assertNotRaises"
|
|
719 |
getUtility(IRevisionSet).onlyPresent([not_present]) |
|
720 |
||
7049.1.13
by Michael Hudson
tests for onlyPresent |
721 |
|
7675.169.3
by Tim Penhey
Add methods to populate and prune the RevisionCache. |
722 |
class RevisionCacheTestCase(TestCaseWithFactory): |
723 |
"""Base class for RevisionCache tests."""
|
|
724 |
||
725 |
layer = DatabaseFunctionalLayer |
|
726 |
||
727 |
def setUp(self): |
|
728 |
# Login as an admin as we don't care about permissions here.
|
|
729 |
TestCaseWithFactory.setUp(self, 'admin@canonical.com') |
|
730 |
self.store = getUtility(IStoreSelector).get( |
|
731 |
MAIN_STORE, DEFAULT_FLAVOR) |
|
7675.169.7
by Tim Penhey
Updates following review. |
732 |
# There should be no RevisionCache entries in the test data.
|
733 |
assert self.store.find(RevisionCache).count() == 0 |
|
7675.169.3
by Tim Penhey
Add methods to populate and prune the RevisionCache. |
734 |
|
735 |
def _getRevisionCache(self): |
|
736 |
return list(self.store.find(RevisionCache) |
|
737 |
.order_by(RevisionCache.revision_id)) |
|
738 |
||
739 |
||
740 |
class TestUpdateRevisionCacheForBranch(RevisionCacheTestCase): |
|
741 |
"""Tests for RevisionSet.updateRevisionCacheForBranch."""
|
|
742 |
||
743 |
def test_empty_branch(self): |
|
744 |
# A branch with no revisions should add no revisions to the cache.
|
|
745 |
branch = self.factory.makeAnyBranch() |
|
746 |
RevisionSet.updateRevisionCacheForBranch(branch) |
|
747 |
self.assertEqual(0, len(self._getRevisionCache())) |
|
748 |
||
749 |
def test_adds_revisions(self): |
|
750 |
# A branch with revisions should add the new revisions.
|
|
751 |
branch = self.factory.makeAnyBranch() |
|
752 |
revision = self.factory.makeRevision() |
|
753 |
branch.createBranchRevision(1, revision) |
|
754 |
RevisionSet.updateRevisionCacheForBranch(branch) |
|
755 |
[cached] = self._getRevisionCache() |
|
756 |
self.assertEqual(cached.revision, revision) |
|
757 |
self.assertEqual(cached.revision_author, revision.revision_author) |
|
758 |
self.assertEqual(cached.revision_date, revision.revision_date) |
|
759 |
||
760 |
def test_old_revisions_not_added(self): |
|
761 |
# Revisions older than the 30 day epoch are not added to the cache.
|
|
762 |
||
763 |
# Start 33 days ago.
|
|
764 |
epoch = datetime.now(pytz.UTC) - timedelta(days=30) |
|
765 |
date_generator = time_counter( |
|
766 |
epoch - timedelta(days=3), delta=timedelta(days=2)) |
|
767 |
# And add 4 revisions at 33, 31, 29, and 27 days ago
|
|
768 |
branch = self.factory.makeAnyBranch() |
|
769 |
self.factory.makeRevisionsForBranch( |
|
770 |
branch, count=4, date_generator=date_generator) |
|
771 |
RevisionSet.updateRevisionCacheForBranch(branch) |
|
772 |
cached = self._getRevisionCache() |
|
773 |
# Only two revisions are within the 30 day cutoff.
|
|
774 |
self.assertEqual(2, len(cached)) |
|
775 |
# And both the revisions stored are a date create after the epoch.
|
|
776 |
for rev in cached: |
|
777 |
self.assertTrue(rev.revision_date > epoch) |
|
778 |
||
779 |
def test_new_revisions_added(self): |
|
780 |
# If there are already revisions in the cache for the branch, updating
|
|
781 |
# the branch again will only add the new revisions.
|
|
782 |
date_generator = time_counter( |
|
783 |
datetime.now(pytz.UTC) - timedelta(days=29), |
|
784 |
delta=timedelta(days=1)) |
|
785 |
# Initially add in 4 revisions.
|
|
786 |
branch = self.factory.makeAnyBranch() |
|
787 |
self.factory.makeRevisionsForBranch( |
|
788 |
branch, count=4, date_generator=date_generator) |
|
789 |
RevisionSet.updateRevisionCacheForBranch(branch) |
|
790 |
# Now add two more revisions.
|
|
791 |
self.factory.makeRevisionsForBranch( |
|
792 |
branch, count=2, date_generator=date_generator) |
|
793 |
RevisionSet.updateRevisionCacheForBranch(branch) |
|
794 |
# There will be only six revisions cached.
|
|
795 |
cached = self._getRevisionCache() |
|
796 |
self.assertEqual(6, len(cached)) |
|
797 |
||
798 |
def test_revisions_for_public_branch_marked_public(self): |
|
799 |
# If the branch is public, then the revisions in the cache will be
|
|
800 |
# marked public too.
|
|
801 |
branch = self.factory.makeAnyBranch() |
|
802 |
revision = self.factory.makeRevision() |
|
803 |
branch.createBranchRevision(1, revision) |
|
804 |
RevisionSet.updateRevisionCacheForBranch(branch) |
|
805 |
[cached] = self._getRevisionCache() |
|
806 |
self.assertFalse(branch.private) |
|
807 |
self.assertFalse(cached.private) |
|
808 |
||
809 |
def test_revisions_for_private_branch_marked_private(self): |
|
810 |
# If the branch is private, then the revisions in the cache will be
|
|
811 |
# marked private too.
|
|
812 |
branch = self.factory.makeAnyBranch(private=True) |
|
813 |
revision = self.factory.makeRevision() |
|
814 |
branch.createBranchRevision(1, revision) |
|
815 |
RevisionSet.updateRevisionCacheForBranch(branch) |
|
816 |
[cached] = self._getRevisionCache() |
|
817 |
self.assertTrue(branch.private) |
|
818 |
self.assertTrue(cached.private) |
|
819 |
||
13875.2.1
by Ian Booth
Reimplement code to query for private branches to account for transitive privacy |
820 |
def test_revisions_for_transitive_private_branch_marked_private(self): |
821 |
# If the branch is stacked on a private branch, then the revisions in
|
|
822 |
# the cache will be marked private too.
|
|
823 |
private_branch = self.factory.makeAnyBranch(private=True) |
|
824 |
branch = self.factory.makeAnyBranch(stacked_on=private_branch) |
|
825 |
revision = self.factory.makeRevision() |
|
826 |
branch.createBranchRevision(1, revision) |
|
827 |
RevisionSet.updateRevisionCacheForBranch(branch) |
|
828 |
[cached] = self._getRevisionCache() |
|
829 |
self.assertTrue(branch.private) |
|
830 |
self.assertTrue(cached.private) |
|
831 |
||
7675.169.3
by Tim Penhey
Add methods to populate and prune the RevisionCache. |
832 |
def test_product_branch_revisions(self): |
833 |
# The revision cache knows the product for revisions in product
|
|
834 |
# branches.
|
|
835 |
branch = self.factory.makeProductBranch() |
|
836 |
revision = self.factory.makeRevision() |
|
837 |
branch.createBranchRevision(1, revision) |
|
838 |
RevisionSet.updateRevisionCacheForBranch(branch) |
|
839 |
[cached] = self._getRevisionCache() |
|
840 |
self.assertEqual(cached.product, branch.product) |
|
841 |
self.assertIs(None, cached.distroseries) |
|
842 |
self.assertIs(None, cached.sourcepackagename) |
|
843 |
||
844 |
def test_personal_branch_revisions(self): |
|
845 |
# If the branch is a personal branch, the revision cache stores NULL
|
|
846 |
# for the product, distroseries and sourcepackagename.
|
|
847 |
branch = self.factory.makePersonalBranch() |
|
848 |
revision = self.factory.makeRevision() |
|
849 |
branch.createBranchRevision(1, revision) |
|
850 |
RevisionSet.updateRevisionCacheForBranch(branch) |
|
851 |
[cached] = self._getRevisionCache() |
|
852 |
self.assertIs(None, cached.product) |
|
853 |
self.assertIs(None, cached.distroseries) |
|
854 |
self.assertIs(None, cached.sourcepackagename) |
|
855 |
||
856 |
def test_package_branch_revisions(self): |
|
857 |
# The revision cache stores the distroseries and sourcepackagename for
|
|
858 |
# package branches.
|
|
859 |
branch = self.factory.makePackageBranch() |
|
860 |
revision = self.factory.makeRevision() |
|
861 |
branch.createBranchRevision(1, revision) |
|
862 |
RevisionSet.updateRevisionCacheForBranch(branch) |
|
863 |
[cached] = self._getRevisionCache() |
|
864 |
self.assertIs(None, cached.product) |
|
865 |
self.assertEqual(branch.distroseries, cached.distroseries) |
|
866 |
self.assertEqual(branch.sourcepackagename, cached.sourcepackagename) |
|
867 |
||
868 |
def test_same_revision_multiple_targets(self): |
|
869 |
# If there are branches that have different targets that contain the
|
|
870 |
# same revision, the revision appears in the revision cache once for
|
|
871 |
# each different target.
|
|
872 |
b1 = self.factory.makeProductBranch() |
|
873 |
b2 = self.factory.makePackageBranch() |
|
874 |
revision = self.factory.makeRevision() |
|
875 |
b1.createBranchRevision(1, revision) |
|
876 |
RevisionSet.updateRevisionCacheForBranch(b1) |
|
877 |
b2.createBranchRevision(1, revision) |
|
878 |
RevisionSet.updateRevisionCacheForBranch(b2) |
|
879 |
[rev1, rev2] = self._getRevisionCache() |
|
880 |
# Both cached revisions point to the same underlying revisions, but
|
|
881 |
# for different targets.
|
|
882 |
self.assertEqual(rev1.revision, revision) |
|
883 |
self.assertEqual(rev2.revision, revision) |
|
884 |
# Make rev1 be the cached revision for the product branch.
|
|
885 |
if rev1.product is None: |
|
886 |
rev1, rev2 = rev2, rev1 |
|
887 |
self.assertEqual(b1.product, rev1.product) |
|
888 |
self.assertEqual(b2.distroseries, rev2.distroseries) |
|
889 |
self.assertEqual(b2.sourcepackagename, rev2.sourcepackagename) |
|
890 |
||
891 |
def test_existing_private_revisions_with_public_branch(self): |
|
892 |
# If a revision is in both public and private branches, there is a
|
|
893 |
# revision cache row for both public and private.
|
|
894 |
private_branch = self.factory.makeAnyBranch(private=True) |
|
895 |
public_branch = self.factory.makeAnyBranch(private=False) |
|
896 |
revision = self.factory.makeRevision() |
|
897 |
private_branch.createBranchRevision(1, revision) |
|
898 |
RevisionSet.updateRevisionCacheForBranch(private_branch) |
|
899 |
public_branch.createBranchRevision(1, revision) |
|
900 |
RevisionSet.updateRevisionCacheForBranch(public_branch) |
|
901 |
[rev1, rev2] = self._getRevisionCache() |
|
902 |
# Both revisions point to the same underlying revision.
|
|
903 |
self.assertEqual(rev1.revision, revision) |
|
904 |
self.assertEqual(rev2.revision, revision) |
|
905 |
# But the privacy flags are different.
|
|
906 |
self.assertNotEqual(rev1.private, rev2.private) |
|
907 |
||
13875.2.3
by Ian Booth
Lint |
908 |
def test_existing_transitive_private_revisions_with_public_branch(self): |
13875.2.1
by Ian Booth
Reimplement code to query for private branches to account for transitive privacy |
909 |
# If a revision is in both public and private branches, there is a
|
910 |
# revision cache row for both public and private. A branch is private
|
|
911 |
# if it is stacked on a private branch.
|
|
912 |
stacked_on_branch = self.factory.makeAnyBranch(private=True) |
|
913 |
private_branch = self.factory.makeAnyBranch( |
|
914 |
stacked_on=stacked_on_branch) |
|
915 |
public_branch = self.factory.makeAnyBranch(private=False) |
|
916 |
revision = self.factory.makeRevision() |
|
917 |
private_branch.createBranchRevision(1, revision) |
|
918 |
RevisionSet.updateRevisionCacheForBranch(private_branch) |
|
919 |
public_branch.createBranchRevision(1, revision) |
|
920 |
RevisionSet.updateRevisionCacheForBranch(public_branch) |
|
921 |
[rev1, rev2] = self._getRevisionCache() |
|
922 |
# Both revisions point to the same underlying revision.
|
|
923 |
self.assertEqual(rev1.revision, revision) |
|
924 |
self.assertEqual(rev2.revision, revision) |
|
925 |
# But the privacy flags are different.
|
|
926 |
self.assertNotEqual(rev1.private, rev2.private) |
|
927 |
||
7675.169.3
by Tim Penhey
Add methods to populate and prune the RevisionCache. |
928 |
|
929 |
class TestPruneRevisionCache(RevisionCacheTestCase): |
|
930 |
"""Tests for RevisionSet.pruneRevisionCache."""
|
|
931 |
||
932 |
def test_old_revisions_removed(self): |
|
933 |
# Revisions older than 30 days are removed.
|
|
934 |
date_generator = time_counter( |
|
7675.169.6
by Tim Penhey
Fix the pruning. |
935 |
datetime.now(pytz.UTC) - timedelta(days=33), |
7675.169.3
by Tim Penhey
Add methods to populate and prune the RevisionCache. |
936 |
delta=timedelta(days=2)) |
937 |
for i in range(4): |
|
938 |
revision = self.factory.makeRevision( |
|
939 |
revision_date=date_generator.next()) |
|
7675.169.6
by Tim Penhey
Fix the pruning. |
940 |
cache = RevisionCache(revision) |
7675.169.3
by Tim Penhey
Add methods to populate and prune the RevisionCache. |
941 |
self.store.add(cache) |
7675.169.6
by Tim Penhey
Fix the pruning. |
942 |
RevisionSet.pruneRevisionCache(5) |
7675.169.3
by Tim Penhey
Add methods to populate and prune the RevisionCache. |
943 |
self.assertEqual(2, len(self._getRevisionCache())) |
944 |
||
7675.169.6
by Tim Penhey
Fix the pruning. |
945 |
def test_pruning_limit(self): |
946 |
# The prune will only remove at most the parameter rows.
|
|
947 |
date_generator = time_counter( |
|
948 |
datetime.now(pytz.UTC) - timedelta(days=33), |
|
949 |
delta=timedelta(days=2)) |
|
950 |
for i in range(4): |
|
951 |
revision = self.factory.makeRevision( |
|
952 |
revision_date=date_generator.next()) |
|
953 |
cache = RevisionCache(revision) |
|
954 |
self.store.add(cache) |
|
955 |
RevisionSet.pruneRevisionCache(1) |
|
956 |
self.assertEqual(3, len(self._getRevisionCache())) |