Merge ~pappacena/launchpad:vcs-scenarios-for-bmp into launchpad:master
- Git
- lp:~pappacena/launchpad
- vcs-scenarios-for-bmp
- Merge into master
Proposed by
Thiago F. Pappacena
Status: | Superseded |
---|---|
Proposed branch: | ~pappacena/launchpad:vcs-scenarios-for-bmp |
Merge into: | launchpad:master |
Diff against target: |
671 lines (+164/-136) 3 files modified
lib/lp/code/model/branchmergeproposal.py (+5/-7) lib/lp/code/model/tests/test_branchmergeproposal.py (+146/-125) lib/lp/code/tests/helpers.py (+13/-4) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Launchpad code reviewers | Pending | ||
Review via email:
|
Commit message
Refactoring BMP test cases to extend scenarios on TestBranchMerge
Description of the change
To post a comment you must log in.
Unmerged commits
- 04850f4... by Thiago F. Pappacena
-
Refactoring BMP to extend scenarios to TestBranchMerge
ProposalNominat eReviewer - 7b57c36... by Thiago F. Pappacena
-
Refactoring test code nad removing unused attribute from GitRef
- 5577f7b... by Thiago F. Pappacena
-
LP: #1888396 Fixing webhook trigger for private git repositories
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/lib/lp/code/model/branchmergeproposal.py b/lib/lp/code/model/branchmergeproposal.py |
2 | index 5ebcf04..338cc29 100644 |
3 | --- a/lib/lp/code/model/branchmergeproposal.py |
4 | +++ b/lib/lp/code/model/branchmergeproposal.py |
5 | @@ -1,4 +1,4 @@ |
6 | -# Copyright 2009-2018 Canonical Ltd. This software is licensed under the |
7 | +# Copyright 2009-2020 Canonical Ltd. This software is licensed under the |
8 | # GNU Affero General Public License version 3 (see the file LICENSE). |
9 | |
10 | """Database class for branch merge proposals.""" |
11 | @@ -70,6 +70,7 @@ from lp.code.event.branchmergeproposal import ( |
12 | BranchMergeProposalNeedsReviewEvent, |
13 | ReviewerNominatedEvent, |
14 | ) |
15 | +from lp.code.interfaces.branch import IBranch |
16 | from lp.code.interfaces.branchcollection import IAllBranches |
17 | from lp.code.interfaces.branchmergeproposal import ( |
18 | BRANCH_MERGE_PROPOSAL_FINAL_STATES as FINAL_STATES, |
19 | @@ -881,7 +882,7 @@ class BranchMergeProposal(SQLBase, BugLinkTargetMixin): |
20 | BranchSubscriptionDiffSize.NODIFF, |
21 | CodeReviewNotificationLevel.FULL, |
22 | user) |
23 | - if branch.stacked_on is not None: |
24 | + if IBranch.providedBy(branch) and branch.stacked_on is not None: |
25 | checked_branches.append(branch) |
26 | if branch.stacked_on not in checked_branches: |
27 | self._subscribeUserToStackedBranch( |
28 | @@ -903,14 +904,11 @@ class BranchMergeProposal(SQLBase, BugLinkTargetMixin): |
29 | the reviewer if the branch is private and the reviewer is an open |
30 | team. |
31 | """ |
32 | - if self.source_branch is None: |
33 | - # This only applies to Bazaar, which has stacked branches. |
34 | - return |
35 | - source = self.source_branch |
36 | + source = self.merge_source |
37 | if (not source.visibleByUser(reviewer) and |
38 | self._acceptable_to_give_visibility(source, reviewer)): |
39 | self._subscribeUserToStackedBranch(source, reviewer) |
40 | - target = self.target_branch |
41 | + target = self.merge_target |
42 | if (not target.visibleByUser(reviewer) and |
43 | self._acceptable_to_give_visibility(source, reviewer)): |
44 | self._subscribeUserToStackedBranch(target, reviewer) |
45 | diff --git a/lib/lp/code/model/tests/test_branchmergeproposal.py b/lib/lp/code/model/tests/test_branchmergeproposal.py |
46 | index 8936574..0d2457d 100644 |
47 | --- a/lib/lp/code/model/tests/test_branchmergeproposal.py |
48 | +++ b/lib/lp/code/model/tests/test_branchmergeproposal.py |
49 | @@ -1,4 +1,4 @@ |
50 | -# Copyright 2009-2019 Canonical Ltd. This software is licensed under the |
51 | +# Copyright 2009-2020 Canonical Ltd. This software is licensed under the |
52 | # GNU Affero General Public License version 3 (see the file LICENSE). |
53 | |
54 | """Tests for BranchMergeProposals.""" |
55 | @@ -57,6 +57,7 @@ from lp.code.event.branchmergeproposal import ( |
56 | BranchMergeProposalNeedsReviewEvent, |
57 | ReviewerNominatedEvent, |
58 | ) |
59 | +from lp.code.interfaces.branch import IBranch |
60 | from lp.code.interfaces.branchmergeproposal import ( |
61 | BRANCH_MERGE_PROPOSAL_FINAL_STATES as FINAL_STATES, |
62 | BRANCH_MERGE_PROPOSAL_OBSOLETE_STATES as OBSOLETE_STATES, |
63 | @@ -91,6 +92,7 @@ from lp.services.webapp import canonical_url |
64 | from lp.services.webhooks.testing import LogsScheduledWebhooks |
65 | from lp.services.xref.interfaces import IXRefSet |
66 | from lp.testing import ( |
67 | + admin_logged_in, |
68 | ExpectedException, |
69 | launchpadlib_for, |
70 | login, |
71 | @@ -109,6 +111,49 @@ from lp.testing.layers import ( |
72 | ) |
73 | |
74 | |
75 | +class WithVCSScenarios(WithScenarios): |
76 | + |
77 | + scenarios = [ |
78 | + ("bzr", {"git": False}), |
79 | + ("git", {"git": True}), |
80 | + ] |
81 | + |
82 | + def makeBranch(self, same_target_as=None, product=None, stacked_on=None, |
83 | + information_type=None, owner=None): |
84 | + # Create the product pillar and its access policy if information |
85 | + # type is "PROPRIETARY". |
86 | + if product is None and same_target_as is None: |
87 | + product = self.factory.makeProduct() |
88 | + if information_type == InformationType.PROPRIETARY: |
89 | + self.factory.makeAccessPolicy(product) |
90 | + elif product is None: |
91 | + same_target_as = removeSecurityProxy(same_target_as) |
92 | + product = (same_target_as.target if self.git else |
93 | + same_target_as.product) |
94 | + |
95 | + kwargs = { |
96 | + "information_type": information_type, |
97 | + "owner": owner} |
98 | + if self.git: |
99 | + kwargs["target"] = product |
100 | + return self.factory.makeGitRefs(**kwargs)[0] |
101 | + else: |
102 | + kwargs["product"] = product |
103 | + kwargs["stacked_on"] = stacked_on |
104 | + return self.factory.makeProductBranch(**kwargs) |
105 | + |
106 | + def makeBranchMergeProposal(self, source=None, target=None, |
107 | + prerequisite=None, **kwargs): |
108 | + if self.git: |
109 | + return self.factory.makeBranchMergeProposalForGit( |
110 | + target_ref=target, source_ref=source, |
111 | + prerequisite_ref=prerequisite, **kwargs) |
112 | + else: |
113 | + return self.factory.makeBranchMergeProposal( |
114 | + source_branch=source, target_branch=target, |
115 | + prerequisite_branch=prerequisite, **kwargs) |
116 | + |
117 | + |
118 | class TestBranchMergeProposalInterface(TestCaseWithFactory): |
119 | """Ensure that BranchMergeProposal implements its interface.""" |
120 | |
121 | @@ -120,26 +165,16 @@ class TestBranchMergeProposalInterface(TestCaseWithFactory): |
122 | verifyObject(IBranchMergeProposal, bmp) |
123 | |
124 | |
125 | -class TestBranchMergeProposalCanonicalUrl(WithScenarios, TestCaseWithFactory): |
126 | +class TestBranchMergeProposalCanonicalUrl( |
127 | + WithVCSScenarios, TestCaseWithFactory): |
128 | """Tests canonical_url for merge proposals.""" |
129 | |
130 | layer = DatabaseFunctionalLayer |
131 | |
132 | - scenarios = [ |
133 | - ("bzr", {"git": False}), |
134 | - ("git", {"git": True}), |
135 | - ] |
136 | - |
137 | - def _makeBranchMergeProposal(self): |
138 | - if self.git: |
139 | - return self.factory.makeBranchMergeProposalForGit() |
140 | - else: |
141 | - return self.factory.makeBranchMergeProposal() |
142 | - |
143 | def test_BranchMergeProposal_canonical_url_base(self): |
144 | # The URL for a merge proposal starts with the parent (source branch |
145 | # or source Git repository). |
146 | - bmp = self._makeBranchMergeProposal() |
147 | + bmp = self.makeBranchMergeProposal() |
148 | url = canonical_url(bmp) |
149 | parent_url = canonical_url(bmp.parent) |
150 | self.assertTrue(url.startswith(parent_url)) |
151 | @@ -147,7 +182,7 @@ class TestBranchMergeProposalCanonicalUrl(WithScenarios, TestCaseWithFactory): |
152 | def test_BranchMergeProposal_canonical_url_rest(self): |
153 | # The rest of the URL for a merge proposal is +merge followed by the |
154 | # db id. |
155 | - bmp = self._makeBranchMergeProposal() |
156 | + bmp = self.makeBranchMergeProposal() |
157 | url = canonical_url(bmp) |
158 | parent_url = canonical_url(bmp.parent) |
159 | rest = url[len(parent_url):] |
160 | @@ -718,45 +753,14 @@ class TestMergeProposalGetPreviewDiff(TestCaseWithFactory): |
161 | self.mp_two.getPreviewDiff, self.preview_diff.id) |
162 | |
163 | |
164 | -class TestMergeProposalNotification(WithScenarios, TestCaseWithFactory): |
165 | +class TestMergeProposalNotification(WithVCSScenarios, TestCaseWithFactory): |
166 | """Test that events are created when merge proposals are manipulated""" |
167 | |
168 | layer = DatabaseFunctionalLayer |
169 | |
170 | - scenarios = [ |
171 | - ("bzr", {"git": False}), |
172 | - ("git", {"git": True}), |
173 | - ] |
174 | - |
175 | def setUp(self): |
176 | TestCaseWithFactory.setUp(self, user='test@canonical.com') |
177 | |
178 | - def makeBranch(self, same_target_as=None, target=None, **kwargs): |
179 | - kwargs = dict(kwargs) |
180 | - if self.git: |
181 | - if same_target_as is not None: |
182 | - kwargs["target"] = same_target_as.target |
183 | - elif target is not None: |
184 | - kwargs["target"] = target |
185 | - return self.factory.makeGitRefs(**kwargs)[0] |
186 | - else: |
187 | - if same_target_as is not None: |
188 | - kwargs["product"] = same_target_as.product |
189 | - elif target is not None: |
190 | - kwargs["product"] = target |
191 | - return self.factory.makeProductBranch(**kwargs) |
192 | - |
193 | - def makeBranchMergeProposal(self, source=None, target=None, |
194 | - prerequisite=None, **kwargs): |
195 | - if self.git: |
196 | - return self.factory.makeBranchMergeProposalForGit( |
197 | - source_ref=source, target_ref=target, |
198 | - prerequisite_ref=prerequisite, **kwargs) |
199 | - else: |
200 | - return self.factory.makeBranchMergeProposal( |
201 | - source_branch=source, target_branch=target, |
202 | - prerequisite_branch=prerequisite, **kwargs) |
203 | - |
204 | def test_notifyOnCreate_needs_review(self): |
205 | # When a merge proposal is created needing review, the |
206 | # BranchMergeProposalNeedsReviewEvent is raised as well as the usual |
207 | @@ -988,8 +992,8 @@ class TestMergeProposalNotification(WithScenarios, TestCaseWithFactory): |
208 | # they do not get email about the proposal. |
209 | owner = self.factory.makePerson() |
210 | product = self.factory.makeProduct() |
211 | - source = self.makeBranch(owner=owner, target=product) |
212 | - target = self.makeBranch(owner=owner, target=product) |
213 | + source = self.makeBranch(owner=owner, product=product) |
214 | + target = self.makeBranch(owner=owner, product=product) |
215 | bmp = self.makeBranchMergeProposal(source=source, target=target) |
216 | # Subscribe eric to the source branch only. |
217 | eric = self.factory.makePerson() |
218 | @@ -1021,31 +1025,15 @@ class TestMergeProposalNotification(WithScenarios, TestCaseWithFactory): |
219 | self.assertIn(charlie, recipients) |
220 | |
221 | |
222 | -class TestMergeProposalWebhooks(WithScenarios, TestCaseWithFactory): |
223 | +class TestMergeProposalWebhooks(WithVCSScenarios, TestCaseWithFactory): |
224 | |
225 | layer = DatabaseFunctionalLayer |
226 | |
227 | - scenarios = [ |
228 | - ("bzr", {"git": False}), |
229 | - ("git", {"git": True}), |
230 | - ] |
231 | - |
232 | def setUp(self): |
233 | super(TestMergeProposalWebhooks, self).setUp() |
234 | self.useFixture(FeatureFixture( |
235 | {BRANCH_MERGE_PROPOSAL_WEBHOOKS_FEATURE_FLAG: "on"})) |
236 | |
237 | - def makeBranch(self, same_target_as=None): |
238 | - kwargs = {} |
239 | - if self.git: |
240 | - if same_target_as is not None: |
241 | - kwargs["target"] = same_target_as.target |
242 | - return self.factory.makeGitRefs(**kwargs)[0] |
243 | - else: |
244 | - if same_target_as is not None: |
245 | - kwargs["product"] = same_target_as.product |
246 | - return self.factory.makeProductBranch(**kwargs) |
247 | - |
248 | def getWebhookTarget(self, branch): |
249 | if self.git: |
250 | return branch.repository |
251 | @@ -1102,6 +1090,39 @@ class TestMergeProposalWebhooks(WithScenarios, TestCaseWithFactory): |
252 | (hook, "merge-proposal:0.1", |
253 | MatchesDict(expected_redacted_payload))])) |
254 | |
255 | + def test_create_private_repo_triggers_webhooks(self): |
256 | + # When a merge proposal is created, any relevant webhooks are |
257 | + # triggered even if the repository is proprietary. |
258 | + logger = self.useFixture(FakeLogger()) |
259 | + source = self.makeBranch(information_type=InformationType.PROPRIETARY) |
260 | + target = self.makeBranch( |
261 | + same_target_as=source, |
262 | + information_type=InformationType.PROPRIETARY) |
263 | + |
264 | + with admin_logged_in(): |
265 | + # Create the web hook and the proposal. |
266 | + registrant = self.factory.makePerson() |
267 | + hook = self.factory.makeWebhook( |
268 | + target=self.getWebhookTarget(target), |
269 | + event_types=["merge-proposal:0.1"]) |
270 | + proposal = source.addLandingTarget( |
271 | + registrant, target, needs_review=True) |
272 | + target_owner = target.owner |
273 | + |
274 | + login_person(target_owner) |
275 | + delivery = hook.deliveries.one() |
276 | + expected_payload = { |
277 | + "merge_proposal": Equals(self.getURL(proposal)), |
278 | + "action": Equals("created"), |
279 | + "new": MatchesDict(self.getExpectedPayload(proposal)), |
280 | + } |
281 | + expected_redacted_payload = dict( |
282 | + expected_payload, |
283 | + new=MatchesDict( |
284 | + self.getExpectedPayload(proposal, redact=True))) |
285 | + self.assertCorrectDelivery(expected_payload, hook, delivery) |
286 | + self.assertCorrectLogging(expected_redacted_payload, hook, logger) |
287 | + |
288 | def test_create_triggers_webhooks(self): |
289 | # When a merge proposal is created, any relevant webhooks are |
290 | # triggered. |
291 | @@ -1486,15 +1507,10 @@ class TestBranchMergeProposalDeletion(TestCaseWithFactory): |
292 | SQLObjectNotFound, BranchMergeProposalJob.get, job_id) |
293 | |
294 | |
295 | -class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): |
296 | +class TestBranchMergeProposalBugs(WithVCSScenarios, TestCaseWithFactory): |
297 | |
298 | layer = DatabaseFunctionalLayer |
299 | |
300 | - scenarios = [ |
301 | - ("bzr", {"git": False}), |
302 | - ("git", {"git": True}), |
303 | - ] |
304 | - |
305 | def setUp(self): |
306 | super(TestBranchMergeProposalBugs, self).setUp() |
307 | self.user = self.factory.makePerson() |
308 | @@ -1502,15 +1518,9 @@ class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): |
309 | if self.git: |
310 | self.hosting_fixture = self.useFixture(GitHostingFixture()) |
311 | |
312 | - def _makeBranchMergeProposal(self): |
313 | - if self.git: |
314 | - return self.factory.makeBranchMergeProposalForGit() |
315 | - else: |
316 | - return self.factory.makeBranchMergeProposal() |
317 | - |
318 | def test_bugs(self): |
319 | # bugs includes all linked bugs. |
320 | - bmp = self._makeBranchMergeProposal() |
321 | + bmp = self.makeBranchMergeProposal() |
322 | self.assertEqual([], bmp.bugs) |
323 | bugs = [self.factory.makeBug() for _ in range(2)] |
324 | bmp.linkBug(bugs[0], bmp.registrant) |
325 | @@ -1525,7 +1535,7 @@ class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): |
326 | def test_related_bugtasks_includes_source_bugtasks(self): |
327 | # related_bugtasks includes bugtasks linked to the source branch in |
328 | # the Bazaar case, or directly to the MP in the Git case. |
329 | - bmp = self._makeBranchMergeProposal() |
330 | + bmp = self.makeBranchMergeProposal() |
331 | bug = self.factory.makeBug() |
332 | bmp.linkBug(bug, bmp.registrant) |
333 | self.assertEqual( |
334 | @@ -1533,7 +1543,7 @@ class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): |
335 | |
336 | def test_related_bugtasks_excludes_private_bugs(self): |
337 | # related_bugtasks ignores private bugs for non-authorised users. |
338 | - bmp = self._makeBranchMergeProposal() |
339 | + bmp = self.makeBranchMergeProposal() |
340 | bug = self.factory.makeBug() |
341 | bmp.linkBug(bug, bmp.registrant) |
342 | person = self.factory.makePerson() |
343 | @@ -1553,7 +1563,7 @@ class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): |
344 | # related_bugtasks ignores bugs linked to the target branch. |
345 | if self.git: |
346 | self.skipTest("Only relevant for Bazaar.") |
347 | - bmp = self._makeBranchMergeProposal() |
348 | + bmp = self.makeBranchMergeProposal() |
349 | bug = self.factory.makeBug() |
350 | bmp.target_branch.linkBug(bug, bmp.registrant) |
351 | self.assertEqual([], list(bmp.getRelatedBugTasks(self.user))) |
352 | @@ -1562,7 +1572,7 @@ class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): |
353 | # related_bugtasks ignores bugs linked to both branches. |
354 | if self.git: |
355 | self.skipTest("Only relevant for Bazaar.") |
356 | - bmp = self._makeBranchMergeProposal() |
357 | + bmp = self.makeBranchMergeProposal() |
358 | bug = self.factory.makeBug() |
359 | bmp.source_branch.linkBug(bug, bmp.registrant) |
360 | bmp.target_branch.linkBug(bug, bmp.registrant) |
361 | @@ -1574,7 +1584,7 @@ class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): |
362 | if not self.git: |
363 | self.skipTest("Only relevant for Git.") |
364 | bugs = [self.factory.makeBug() for _ in range(3)] |
365 | - bmp = self._makeBranchMergeProposal() |
366 | + bmp = self.makeBranchMergeProposal() |
367 | self.hosting_fixture.getLog.result = [ |
368 | { |
369 | "sha1": bmp.source_git_commit_sha1, |
370 | @@ -1621,7 +1631,7 @@ class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): |
371 | # bugs in either the database or the source branch. |
372 | if not self.git: |
373 | self.skipTest("Only relevant for Git.") |
374 | - bmp = self._makeBranchMergeProposal() |
375 | + bmp = self.makeBranchMergeProposal() |
376 | self._setUpLog([]) |
377 | bmp.updateRelatedBugsFromSource() |
378 | self.assertEqual([], bmp.bugs) |
379 | @@ -1632,7 +1642,7 @@ class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): |
380 | if not self.git: |
381 | self.skipTest("Only relevant for Git.") |
382 | bugs = [self.factory.makeBug() for _ in range(3)] |
383 | - bmp = self._makeBranchMergeProposal() |
384 | + bmp = self.makeBranchMergeProposal() |
385 | self._setUpLog([bugs[0]]) |
386 | bmp.updateRelatedBugsFromSource() |
387 | self.assertEqual([bugs[0]], bmp.bugs) |
388 | @@ -1646,7 +1656,7 @@ class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): |
389 | if not self.git: |
390 | self.skipTest("Only relevant for Git.") |
391 | bug = self.factory.makeBug() |
392 | - bmp = self._makeBranchMergeProposal() |
393 | + bmp = self.makeBranchMergeProposal() |
394 | self._setUpLog([bug]) |
395 | bmp.updateRelatedBugsFromSource() |
396 | self.assertEqual([bug], bmp.bugs) |
397 | @@ -1661,7 +1671,7 @@ class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): |
398 | if not self.git: |
399 | self.skipTest("Only relevant for Git.") |
400 | bug = self.factory.makeBug() |
401 | - bmp = self._makeBranchMergeProposal() |
402 | + bmp = self.makeBranchMergeProposal() |
403 | self._setUpLog([bug]) |
404 | bmp.updateRelatedBugsFromSource() |
405 | self.assertEqual([bug], bmp.bugs) |
406 | @@ -1676,7 +1686,7 @@ class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): |
407 | if not self.git: |
408 | self.skipTest("Only relevant for Git.") |
409 | bug = self.factory.makeBug() |
410 | - bmp = self._makeBranchMergeProposal() |
411 | + bmp = self.makeBranchMergeProposal() |
412 | bmp.linkBug(bug) |
413 | self._setUpLog([]) |
414 | bmp.updateRelatedBugsFromSource() |
415 | @@ -1701,7 +1711,7 @@ class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): |
416 | self.skipTest("Only relevant for Git.") |
417 | self.pushConfig("codehosting", related_bugs_from_source_limit=3) |
418 | bugs = [self.factory.makeBug() for _ in range(5)] |
419 | - bmp = self._makeBranchMergeProposal() |
420 | + bmp = self.makeBranchMergeProposal() |
421 | self._setUpLog([bugs[0]]) |
422 | bmp.updateRelatedBugsFromSource() |
423 | self.assertEqual([bugs[0]], bmp.bugs) |
424 | @@ -1713,45 +1723,48 @@ class TestBranchMergeProposalBugs(WithScenarios, TestCaseWithFactory): |
425 | self.assertEqual("TooManyRelatedBugs", self.oopses[0]["type"]) |
426 | |
427 | |
428 | -class TestBranchMergeProposalNominateReviewer(TestCaseWithFactory): |
429 | +class TestBranchMergeProposalNominateReviewer( |
430 | + WithVCSScenarios, TestCaseWithFactory): |
431 | """Test that the appropriate vote references get created.""" |
432 | |
433 | layer = DatabaseFunctionalLayer |
434 | |
435 | def setUp(self): |
436 | TestCaseWithFactory.setUp(self, user='test@canonical.com') |
437 | + if self.git: |
438 | + self.hosting_fixture = self.useFixture(GitHostingFixture()) |
439 | |
440 | def test_notify_on_nominate(self): |
441 | # Ensure that a notification is emitted on nomination. |
442 | - merge_proposal = self.factory.makeBranchMergeProposal() |
443 | - login_person(merge_proposal.source_branch.owner) |
444 | + merge_proposal = self.makeBranchMergeProposal() |
445 | + login_person(merge_proposal.merge_source.owner) |
446 | reviewer = self.factory.makePerson() |
447 | result, events = self.assertNotifies( |
448 | ReviewerNominatedEvent, False, |
449 | merge_proposal.nominateReviewer, |
450 | reviewer=reviewer, |
451 | - registrant=merge_proposal.source_branch.owner) |
452 | + registrant=merge_proposal.merge_source.owner) |
453 | self.assertEqual(result, events[0].object) |
454 | |
455 | def test_notify_on_nominate_suppressed_if_requested(self): |
456 | # Ensure that a notification is suppressed if notify listeners is set |
457 | # to False. |
458 | - merge_proposal = self.factory.makeBranchMergeProposal() |
459 | - login_person(merge_proposal.source_branch.owner) |
460 | + merge_proposal = self.makeBranchMergeProposal() |
461 | + login_person(merge_proposal.merge_source.owner) |
462 | reviewer = self.factory.makePerson() |
463 | self.assertNoNotification( |
464 | merge_proposal.nominateReviewer, |
465 | reviewer=reviewer, |
466 | - registrant=merge_proposal.source_branch.owner, |
467 | + registrant=merge_proposal.merge_source.owner, |
468 | _notify_listeners=False) |
469 | |
470 | def test_one_initial_votes(self): |
471 | """A new merge proposal has one vote of the default reviewer.""" |
472 | - merge_proposal = self.factory.makeBranchMergeProposal() |
473 | + merge_proposal = self.makeBranchMergeProposal() |
474 | self.assertEqual(1, len(list(merge_proposal.votes))) |
475 | [vote] = list(merge_proposal.votes) |
476 | self.assertEqual( |
477 | - merge_proposal.target_branch.owner, vote.reviewer) |
478 | + merge_proposal.merge_target.owner, vote.reviewer) |
479 | |
480 | def makeProposalWithReviewer(self, reviewer=None, review_type=None, |
481 | registrant=None, **kwargs): |
482 | @@ -1764,8 +1777,9 @@ class TestBranchMergeProposalNominateReviewer(TestCaseWithFactory): |
483 | if registrant is None: |
484 | registrant = self.factory.makePerson() |
485 | merge_proposal = make_merge_proposal_without_reviewers( |
486 | - factory=self.factory, registrant=registrant, **kwargs) |
487 | - login_person(merge_proposal.source_branch.owner) |
488 | + factory=self.factory, for_git=self.git, registrant=registrant, |
489 | + **kwargs) |
490 | + login_person(merge_proposal.merge_source.owner) |
491 | merge_proposal.nominateReviewer( |
492 | reviewer=reviewer, registrant=registrant, review_type=review_type) |
493 | return merge_proposal, reviewer |
494 | @@ -1871,15 +1885,15 @@ class TestBranchMergeProposalNominateReviewer(TestCaseWithFactory): |
495 | |
496 | def test_nominate_updates_reference(self): |
497 | """The existing reference is updated on re-nomination.""" |
498 | - merge_proposal = self.factory.makeBranchMergeProposal() |
499 | - login_person(merge_proposal.source_branch.owner) |
500 | + merge_proposal = self.makeBranchMergeProposal() |
501 | + login_person(merge_proposal.merge_source.owner) |
502 | reviewer = self.factory.makePerson() |
503 | reference = merge_proposal.nominateReviewer( |
504 | - reviewer=reviewer, registrant=merge_proposal.source_branch.owner, |
505 | + reviewer=reviewer, registrant=merge_proposal.merge_source.owner, |
506 | review_type='General') |
507 | self.assertEqual('general', reference.review_type) |
508 | merge_proposal.nominateReviewer( |
509 | - reviewer=reviewer, registrant=merge_proposal.source_branch.owner, |
510 | + reviewer=reviewer, registrant=merge_proposal.merge_source.owner, |
511 | review_type='Specific') |
512 | # Note we're using the reference from the first call |
513 | self.assertEqual('specific', reference.review_type) |
514 | @@ -1896,31 +1910,37 @@ class TestBranchMergeProposalNominateReviewer(TestCaseWithFactory): |
515 | CodeReviewNotificationLevel.FULL, sub.review_level) |
516 | # The reviewer can see the branch. |
517 | self.assertTrue(branch.visibleByUser(reviewer)) |
518 | - if branch.stacked_on is not None: |
519 | + if IBranch.providedBy(branch) and branch.stacked_on is not None: |
520 | self._check_mp_branch_visibility(branch.stacked_on, reviewer) |
521 | |
522 | def _test_nominate_grants_visibility(self, reviewer): |
523 | """Nominated reviewers can see the source and target branches.""" |
524 | owner = self.factory.makePerson() |
525 | product = self.factory.makeProduct() |
526 | - # We make a source branch stacked on a private one. |
527 | - base_branch = self.factory.makeBranch( |
528 | + # For bzr, we make a source branch stacked on a private one. |
529 | + # For git, we make the gitref itself private. |
530 | + if self.git: |
531 | + source_branch = self.makeBranch( |
532 | + product=product, owner=owner, |
533 | + information_type=InformationType.USERDATA) |
534 | + else: |
535 | + base_branch = self.makeBranch( |
536 | + owner=owner, product=product, |
537 | + information_type=InformationType.USERDATA) |
538 | + source_branch = self.makeBranch( |
539 | + stacked_on=base_branch, product=product, owner=owner) |
540 | + target_branch = self.makeBranch( |
541 | owner=owner, product=product, |
542 | information_type=InformationType.USERDATA) |
543 | - source_branch = self.factory.makeBranch( |
544 | - stacked_on=base_branch, product=product, owner=owner) |
545 | - target_branch = self.factory.makeBranch(owner=owner, product=product) |
546 | login_person(owner) |
547 | - merge_proposal = self.factory.makeBranchMergeProposal( |
548 | - source_branch=source_branch, |
549 | - target_branch=target_branch) |
550 | - target_branch.setPrivate(True, owner) |
551 | + merge_proposal = self.makeBranchMergeProposal( |
552 | + source=source_branch, target=target_branch) |
553 | # The reviewer can't see the source or target branches. |
554 | self.assertFalse(source_branch.visibleByUser(reviewer)) |
555 | self.assertFalse(target_branch.visibleByUser(reviewer)) |
556 | merge_proposal.nominateReviewer( |
557 | reviewer=reviewer, |
558 | - registrant=merge_proposal.source_branch.owner) |
559 | + registrant=merge_proposal.merge_source.owner) |
560 | for branch in [source_branch, target_branch]: |
561 | self._check_mp_branch_visibility(branch, reviewer) |
562 | |
563 | @@ -1944,7 +1964,7 @@ class TestBranchMergeProposalNominateReviewer(TestCaseWithFactory): |
564 | def test_comment_with_vote_creates_reference(self): |
565 | """A comment with a vote creates a vote reference.""" |
566 | reviewer = self.factory.makePerson() |
567 | - merge_proposal = self.factory.makeBranchMergeProposal( |
568 | + merge_proposal = self.makeBranchMergeProposal( |
569 | reviewer=reviewer, registrant=reviewer) |
570 | comment = merge_proposal.createComment( |
571 | reviewer, 'Message subject', 'Message content', |
572 | @@ -1955,7 +1975,8 @@ class TestBranchMergeProposalNominateReviewer(TestCaseWithFactory): |
573 | def test_comment_without_a_vote_does_not_create_reference(self): |
574 | """A comment with a vote creates a vote reference.""" |
575 | reviewer = self.factory.makePerson() |
576 | - merge_proposal = make_merge_proposal_without_reviewers(self.factory) |
577 | + merge_proposal = make_merge_proposal_without_reviewers( |
578 | + self.factory, for_git=self.git) |
579 | merge_proposal.createComment( |
580 | reviewer, 'Message subject', 'Message content') |
581 | self.assertEqual([], list(merge_proposal.votes)) |
582 | @@ -1963,7 +1984,7 @@ class TestBranchMergeProposalNominateReviewer(TestCaseWithFactory): |
583 | def test_second_vote_by_person_just_alters_reference(self): |
584 | """A second vote changes the comment reference only.""" |
585 | reviewer = self.factory.makePerson() |
586 | - merge_proposal = self.factory.makeBranchMergeProposal( |
587 | + merge_proposal = self.makeBranchMergeProposal( |
588 | reviewer=reviewer, registrant=reviewer) |
589 | merge_proposal.createComment( |
590 | reviewer, 'Message subject', 'Message content', |
591 | @@ -1979,7 +2000,7 @@ class TestBranchMergeProposalNominateReviewer(TestCaseWithFactory): |
592 | reviewer = self.factory.makePerson() |
593 | merge_proposal, ignore = self.makeProposalWithReviewer( |
594 | reviewer=reviewer, review_type='general') |
595 | - login(merge_proposal.source_branch.owner.preferredemail.email) |
596 | + login(merge_proposal.merge_source.owner.preferredemail.email) |
597 | comment = merge_proposal.createComment( |
598 | reviewer, 'Message subject', 'Message content', |
599 | vote=CodeReviewVote.APPROVE, review_type='general') |
600 | @@ -1999,7 +2020,7 @@ class TestBranchMergeProposalNominateReviewer(TestCaseWithFactory): |
601 | team = self.factory.makeTeam(owner=reviewer) |
602 | merge_proposal, ignore = self.makeProposalWithReviewer( |
603 | reviewer=team, review_type='general') |
604 | - login(merge_proposal.source_branch.owner.preferredemail.email) |
605 | + login(merge_proposal.merge_source.owner.preferredemail.email) |
606 | [vote] = list(merge_proposal.votes) |
607 | self.assertEqual(team, vote.reviewer) |
608 | comment = merge_proposal.createComment( |
609 | @@ -2016,8 +2037,8 @@ class TestBranchMergeProposalNominateReviewer(TestCaseWithFactory): |
610 | # one. |
611 | reviewer = self.factory.makePerson() |
612 | team = self.factory.makeTeam(owner=reviewer) |
613 | - merge_proposal = self.factory.makeBranchMergeProposal(reviewer=team) |
614 | - login(merge_proposal.source_branch.owner.preferredemail.email) |
615 | + merge_proposal = self.makeBranchMergeProposal(reviewer=team) |
616 | + login(merge_proposal.merge_source.owner.preferredemail.email) |
617 | [vote] = list(merge_proposal.votes) |
618 | self.assertEqual(team, vote.reviewer) |
619 | comment = merge_proposal.createComment( |
620 | @@ -2035,8 +2056,8 @@ class TestBranchMergeProposalNominateReviewer(TestCaseWithFactory): |
621 | merge_proposal_1, reviewer_1 = self.makeProposalWithReviewer( |
622 | set_state=BranchMergeProposalStatus.MERGED) |
623 | merge_proposal_2, _ = self.makeProposalWithReviewer( |
624 | - target_branch=merge_proposal_1.target_branch, |
625 | - source_branch=merge_proposal_1.source_branch) |
626 | + target=merge_proposal_1.merge_target, |
627 | + source=merge_proposal_1.merge_source) |
628 | merge_proposal_2.nominateReviewer( |
629 | reviewer=reviewer_1, registrant=merge_proposal_2.registrant) |
630 | votes_1 = list(merge_proposal_1.votes) |
631 | diff --git a/lib/lp/code/tests/helpers.py b/lib/lp/code/tests/helpers.py |
632 | index 46f12ed..0e784f0 100644 |
633 | --- a/lib/lp/code/tests/helpers.py |
634 | +++ b/lib/lp/code/tests/helpers.py |
635 | @@ -1,4 +1,4 @@ |
636 | -# Copyright 2009-2018 Canonical Ltd. This software is licensed under the |
637 | +# Copyright 2009-2020 Canonical Ltd. This software is licensed under the |
638 | # GNU Affero General Public License version 3 (see the file LICENSE). |
639 | |
640 | """Helper functions for code testing live here.""" |
641 | @@ -49,8 +49,8 @@ from lp.code.model.seriessourcepackagebranch import ( |
642 | from lp.registry.interfaces.pocket import PackagePublishingPocket |
643 | from lp.registry.interfaces.series import SeriesStatus |
644 | from lp.services.database.sqlbase import cursor |
645 | -from lp.services.propertycache import get_property_cache |
646 | from lp.services.memcache.testing import MemcacheFixture |
647 | +from lp.services.propertycache import get_property_cache |
648 | from lp.testing import ( |
649 | run_with_login, |
650 | time_counter, |
651 | @@ -271,9 +271,18 @@ def recipe_parser_newest_version(version): |
652 | RecipeParser.NEWEST_VERSION = old_version |
653 | |
654 | |
655 | -def make_merge_proposal_without_reviewers(factory, **kwargs): |
656 | +def make_merge_proposal_without_reviewers( |
657 | + factory, for_git=False, source=None, target=None, **kwargs): |
658 | """Make a merge proposal and strip of any review votes.""" |
659 | - proposal = factory.makeBranchMergeProposal(**kwargs) |
660 | + kwargs = dict(kwargs) |
661 | + if for_git: |
662 | + kwargs["source_ref"] = source |
663 | + kwargs["target_ref"] = target |
664 | + proposal = factory.makeBranchMergeProposalForGit(**kwargs) |
665 | + else: |
666 | + kwargs["source_branch"] = source |
667 | + kwargs["target_branch"] = target |
668 | + proposal = factory.makeBranchMergeProposal(**kwargs) |
669 | for vote in proposal.votes: |
670 | removeSecurityProxy(vote).destroySelf() |
671 | del get_property_cache(proposal).votes |