~launchpad-pqm/launchpad/devel

8687.15.17 by Karl Fogel
Add the copyright header block to the rest of the files under lib/lp/.
1
# Copyright 2009 Canonical Ltd.  This software is licensed under the
2
# GNU Affero General Public License version 3 (see the file LICENSE).
7362.4.18 by Jonathan Lange
Unit tests for the contexts.
3
4
"""Tests for branch contexts."""
5
6
__metaclass__ = type
7
8
import unittest
9
8031.2.1 by Jonathan Lange
Move the default stacking product doctests to be branch target unit tests
10
from zope.security.proxy import removeSecurityProxy
11
7847.1.24 by Jonathan Lange
Allow us to get a canonical_url for a branch target.
12
from canonical.launchpad.webapp import canonical_url
7849.5.2 by Jonathan Lange
Guarantee that the primary context of the branch is the context of the target.
13
from canonical.launchpad.webapp.interfaces import IPrimaryContext
11666.3.5 by Curtis Hovey
Import layers from canonical.testing.layers.
14
from canonical.testing.layers import DatabaseFunctionalLayer
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
15
from lp.code.enums import (
16
    BranchType,
17
    RevisionControlSystems,
18
    )
19
from lp.code.interfaces.branchtarget import IBranchTarget
20
from lp.code.interfaces.codeimport import ICodeImport
21
from lp.code.model.branchtarget import (
22
    check_default_stacked_on,
23
    PackageBranchTarget,
24
    PersonBranchTarget,
25
    ProductBranchTarget,
26
    )
27
from lp.registry.interfaces.pocket import PackagePublishingPocket
28
from lp.testing import (
13139.3.8 by Francis J. Lacoste
More ubuntu_branches removal.
29
    person_logged_in,
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
30
    run_with_login,
31
    TestCaseWithFactory,
32
    )
7362.4.18 by Jonathan Lange
Unit tests for the contexts.
33
34
7849.5.5 by Jonathan Lange
A round of golf
35
class BaseBranchTargetTests:
36
11270.3.2 by Tim Penhey
Stop IBranchTarget inheriting from IPrimaryContext.
37
    def test_provides_IBranchTarget(self):
38
        self.assertProvides(self.target, IBranchTarget)
7849.5.5 by Jonathan Lange
A round of golf
39
40
    def test_context(self):
41
        # IBranchTarget.context is the original object.
42
        self.assertEqual(self.original, self.target.context)
43
7847.1.24 by Jonathan Lange
Allow us to get a canonical_url for a branch target.
44
    def test_canonical_url(self):
45
        # The canonical URL of a branch target is the canonical url of its
46
        # context.
47
        self.assertEqual(
48
            canonical_url(self.original), canonical_url(self.target))
49
8269.7.13 by Paul Hummer
Made docstring changes, and shifted tests around
50
    def test_collection(self):
51
        # The collection attribute is an IBranchCollection containing all
52
        # branches related to the branch target.
53
        self.assertEqual(self.target.collection.getBranches().count(), 0)
54
        branch = self.makeBranchForTarget()
12504.1.3 by Robert Collins
Reject reversion of this branch on trunk.
55
        branches = self.target.collection.getBranches(eager_load=False)
8269.7.13 by Paul Hummer
Made docstring changes, and shifted tests around
56
        self.assertEqual([branch], list(branches))
57
8971.24.4 by Tim Penhey
Added BranchTarget.retargetBranch.
58
    def test_retargetBranch_packageBranch(self):
59
        # Retarget an existing package branch to this target.
60
        branch = self.factory.makePackageBranch()
8971.24.27 by Tim Penhey
Updates following review. Just some more tests for error conditions to go.
61
        self.target._retargetBranch(removeSecurityProxy(branch))
8971.24.4 by Tim Penhey
Added BranchTarget.retargetBranch.
62
        self.assertEqual(self.target, branch.target)
63
64
    def test_retargetBranch_productBranch(self):
65
        # Retarget an existing product branch to this target.
66
        branch = self.factory.makeProductBranch()
8971.24.27 by Tim Penhey
Updates following review. Just some more tests for error conditions to go.
67
        self.target._retargetBranch(removeSecurityProxy(branch))
8971.24.4 by Tim Penhey
Added BranchTarget.retargetBranch.
68
        self.assertEqual(self.target, branch.target)
69
70
    def test_retargetBranch_personalBranch(self):
71
        # Retarget an existing personal branch to this target.
72
        branch = self.factory.makePersonalBranch()
8971.24.27 by Tim Penhey
Updates following review. Just some more tests for error conditions to go.
73
        self.target._retargetBranch(removeSecurityProxy(branch))
8971.24.4 by Tim Penhey
Added BranchTarget.retargetBranch.
74
        self.assertEqual(self.target, branch.target)
75
7849.5.5 by Jonathan Lange
A round of golf
76
77
class TestPackageBranchTarget(TestCaseWithFactory, BaseBranchTargetTests):
7362.4.18 by Jonathan Lange
Unit tests for the contexts.
78
79
    layer = DatabaseFunctionalLayer
80
7849.5.5 by Jonathan Lange
A round of golf
81
    def setUp(self):
82
        TestCaseWithFactory.setUp(self)
83
        self.original = self.factory.makeSourcePackage()
84
        self.target = PackageBranchTarget(self.original)
85
8269.7.13 by Paul Hummer
Made docstring changes, and shifted tests around
86
    def makeBranchForTarget(self):
87
        return self.factory.makePackageBranch(sourcepackage=self.original)
88
7362.4.18 by Jonathan Lange
Unit tests for the contexts.
89
    def test_name(self):
90
        # The name of a package context is distro/series/sourcepackage
7849.5.5 by Jonathan Lange
A round of golf
91
        self.assertEqual(self.original.path, self.target.name)
7849.5.3 by Jonathan Lange
Make IBranchTarget the IPrimaryContext for a branch.
92
7659.3.27 by Aaron Bentley
Get namespace from target container.
93
    def test_getNamespace(self):
94
        """Get namespace produces the correct namespace."""
95
        person = self.factory.makePerson()
7849.5.5 by Jonathan Lange
A round of golf
96
        namespace = self.target.getNamespace(person)
7659.3.27 by Aaron Bentley
Get namespace from target container.
97
        self.assertEqual(person, namespace.owner)
7849.5.5 by Jonathan Lange
A round of golf
98
        self.assertEqual(self.original, namespace.sourcepackage)
7659.3.27 by Aaron Bentley
Get namespace from target container.
99
7779.1.6 by Jonathan Lange
Adapt from the objects to IBranchTarget.
100
    def test_adapter(self):
7849.5.5 by Jonathan Lange
A round of golf
101
        target = IBranchTarget(self.original)
10454.4.16 by James Westby
Make ICodeImportSet.new act on IBranchTargets.
102
        self.assertIsInstance(target, PackageBranchTarget)
7849.5.5 by Jonathan Lange
A round of golf
103
11270.2.14 by Tim Penhey
Add an adapter for distribution source package to branch target.
104
    def test_distrosourcepackage_adapter(self):
11270.2.15 by Tim Penhey
Add test comments.
105
        # Adapting a distrosourcepackage will make a branch target with the
106
        # current series of the distro as the distroseries.
11270.2.14 by Tim Penhey
Add an adapter for distribution source package to branch target.
107
        distro = self.original.distribution
108
        distro_sourcepackage = distro.getSourcePackage(
109
            self.original.sourcepackagename)
110
        target = IBranchTarget(distro_sourcepackage)
111
        self.assertIsInstance(target, PackageBranchTarget)
112
        self.assertEqual(
113
            [distro, distro.currentseries],
114
            target.components[:2])
115
        self.assertEqual(
116
            self.original.sourcepackagename,
117
            target.components[2].sourcepackagename)
118
7847.1.19 by Jonathan Lange
Add a 'components' attribute to branch target, that returns the objects
119
    def test_components(self):
120
        target = IBranchTarget(self.original)
121
        self.assertEqual(
122
            [self.original.distribution, self.original.distroseries,
123
             self.original],
124
            list(target.components))
125
8031.2.10 by Jonathan Lange
Complete the implementation.
126
    def test_default_stacked_on_branch(self):
8031.4.6 by Jonathan Lange
Use the correct stacked-on branch for package branches.
127
        # The default stacked-on branch for a source package is the branch
128
        # linked to the release pocket of the current series of that package.
8031.2.10 by Jonathan Lange
Complete the implementation.
129
        target = IBranchTarget(self.original)
8031.4.6 by Jonathan Lange
Use the correct stacked-on branch for package branches.
130
        development_package = self.original.development_version
131
        default_branch = self.factory.makePackageBranch(
132
            sourcepackage=development_package)
9590.1.78 by Michael Hudson
add some removeSecurityProxys to the tests
133
        removeSecurityProxy(default_branch).branchChanged(
9590.1.77 by Michael Hudson
remove mirrorComplete and all uses of it
134
            '', self.factory.getUniqueString(), None, None, None)
13139.3.8 by Francis J. Lacoste
More ubuntu_branches removal.
135
        registrant = development_package.distribution.owner
136
        with person_logged_in(registrant):
137
            development_package.setBranch(
138
                PackagePublishingPocket.RELEASE, default_branch,
139
                registrant)
8031.4.6 by Jonathan Lange
Use the correct stacked-on branch for package branches.
140
        self.assertEqual(default_branch, target.default_stacked_on_branch)
8031.2.10 by Jonathan Lange
Complete the implementation.
141
8377.8.1 by Tim Penhey
Add a supports_merge_proposals attribute to branch namespaces.
142
    def test_supports_merge_proposals(self):
143
        # Package branches do support merge proposals.
144
        self.assertTrue(self.target.supports_merge_proposals)
145
9080.8.25 by Tim Penhey
Replace IBranch.is_personal_branch with IBranchTarget.supports_short_identities.
146
    def test_supports_short_identites(self):
147
        # Package branches do support short bzr identites.
148
        self.assertTrue(self.target.supports_short_identites)
149
8120.2.21 by Jonathan Lange
Add a displayname attribute to IBranchTarget.
150
    def test_displayname(self):
151
        # The display name of a source package target is the display name of
152
        # the source package.
153
        target = IBranchTarget(self.original)
154
        self.assertEqual(self.original.displayname, target.displayname)
155
8377.8.2 by Tim Penhey
add IBranchTarget.areBranchesMergeable and tests.
156
    def test_areBranchesMergeable_same_sourcepackage(self):
157
        # Branches of the same sourcepackage are mergeable.
158
        same_target = PackageBranchTarget(self.original)
159
        self.assertTrue(self.target.areBranchesMergeable(same_target))
160
161
    def test_areBranchesMergeable_same_sourcepackagename(self):
162
        # Branches with the same sourcepackagename are mergeable.
163
        sourcepackage = self.factory.makeSourcePackage(
164
            self.original.sourcepackagename)
165
        same_name = PackageBranchTarget(sourcepackage)
166
        self.assertTrue(self.target.areBranchesMergeable(same_name))
167
168
    def test_areBranchesMergeable_different_sourcepackage(self):
169
        # Package branches for a different sorucepackagename are not
170
        # mergeable.
171
        branch = self.factory.makePackageBranch()
172
        self.assertFalse(self.target.areBranchesMergeable(branch.target))
173
174
    def test_areBranchesMergeable_personal_branches(self):
175
        # Personal branches are not mergeable.
176
        branch = self.factory.makePersonalBranch()
177
        self.assertFalse(self.target.areBranchesMergeable(branch.target))
178
179
    def test_areBranchesMergeable_unlinked_product(self):
180
        # Product branches are not normally mergeable into package branches.
181
        branch = self.factory.makeProductBranch()
182
        self.assertFalse(self.target.areBranchesMergeable(branch.target))
183
184
    def test_areBranchesMergeable_linked_product(self):
185
        # Products that are linked to the packages are mergeable.
186
        branch = self.factory.makeProductBranch()
187
        # Link it up.
188
        self.original.setPackaging(
189
            branch.product.development_focus, branch.owner)
190
        self.assertTrue(self.target.areBranchesMergeable(branch.target))
191
8377.8.6 by Tim Penhey
Add default_merge_target to IBranchTarget.
192
    def test_default_merge_target(self):
193
        # The default merge target is official release branch.
194
        self.assertIs(None, self.target.default_merge_target)
195
        # Now create and link a branch.
196
        branch = self.factory.makePackageBranch(sourcepackage=self.original)
13139.3.8 by Francis J. Lacoste
More ubuntu_branches removal.
197
        with person_logged_in(self.original.distribution.owner):
198
            self.original.setBranch(
199
                PackagePublishingPocket.RELEASE, branch,
200
                self.original.distribution.owner)
8377.8.6 by Tim Penhey
Add default_merge_target to IBranchTarget.
201
        self.assertEqual(branch, self.target.default_merge_target)
202
10454.11.1 by James Westby
Flip the bit on PackageBranchTarget.
203
    def test_supports_code_imports(self):
204
        self.assertTrue(self.target.supports_code_imports)
10454.9.1 by James Westby
Add a check that the IBranchTarget supports code imports.
205
10454.11.1 by James Westby
Flip the bit on PackageBranchTarget.
206
    def test_creating_code_import_succeeds(self):
207
        target_url = self.factory.getUniqueURL()
208
        branch_name = self.factory.getUniqueString("name-")
209
        owner = self.factory.makePerson()
210
        code_import = self.target.newCodeImport(
211
            owner, branch_name, RevisionControlSystems.GIT, url=target_url)
212
        code_import = removeSecurityProxy(code_import)
213
        self.assertProvides(code_import, ICodeImport)
214
        self.assertEqual(target_url, code_import.url)
215
        self.assertEqual(branch_name, code_import.branch.name)
216
        self.assertEqual(owner, code_import.registrant)
217
        self.assertEqual(owner, code_import.branch.owner)
218
        self.assertEqual(self.target, code_import.branch.target)
10454.9.2 by James Westby
Add a method to IBranchTarget to allow creating a code import directly.
219
11994.2.21 by Ian Booth
Refactor related branches methods to IBranchTarget and show distro series instead of source package for related package branches
220
    def test_related_branches(self):
221
        (branch, related_series_branch_info,
222
            related_package_branches) = (
223
                self.factory.makeRelatedBranchesForSourcePackage(
224
                sourcepackage=self.original))
225
        self.assertEqual(
226
            related_series_branch_info,
227
            self.target.getRelatedSeriesBranchInfo(branch))
228
        self.assertEqual(
229
            related_package_branches,
230
            self.target.getRelatedPackageBranchInfo(branch))
231
232
    def test_related_branches_with_private_branch(self):
233
        (branch, related_series_branch_info,
234
            related_package_branches) = (
235
                self.factory.makeRelatedBranchesForSourcePackage(
236
                sourcepackage=self.original, with_private_branches=True))
237
        self.assertEqual(
238
            related_series_branch_info,
239
            self.target.getRelatedSeriesBranchInfo(branch))
240
        self.assertEqual(
241
            related_package_branches,
242
            self.target.getRelatedPackageBranchInfo(branch))
243
7849.5.5 by Jonathan Lange
A round of golf
244
245
class TestPersonBranchTarget(TestCaseWithFactory, BaseBranchTargetTests):
7362.4.22 by Jonathan Lange
Rename JunkContainer to the slightly less punful PersonContainer
246
247
    layer = DatabaseFunctionalLayer
248
7849.5.5 by Jonathan Lange
A round of golf
249
    def setUp(self):
250
        TestCaseWithFactory.setUp(self)
251
        self.original = self.factory.makePerson()
252
        self.target = PersonBranchTarget(self.original)
253
8269.7.13 by Paul Hummer
Made docstring changes, and shifted tests around
254
    def makeBranchForTarget(self):
255
        return self.factory.makeBranch(owner=self.original, product=None)
256
7362.4.22 by Jonathan Lange
Rename JunkContainer to the slightly less punful PersonContainer
257
    def test_name(self):
258
        # The name of a junk context is '+junk'.
7849.5.5 by Jonathan Lange
A round of golf
259
        self.assertEqual('+junk', self.target.name)
7849.5.3 by Jonathan Lange
Make IBranchTarget the IPrimaryContext for a branch.
260
7659.3.27 by Aaron Bentley
Get namespace from target container.
261
    def test_getNamespace(self):
262
        """Get namespace produces the correct namespace."""
7849.5.5 by Jonathan Lange
A round of golf
263
        namespace = self.target.getNamespace(self.original)
264
        self.assertEqual(namespace.owner, self.original)
7659.3.27 by Aaron Bentley
Get namespace from target container.
265
        self.assertRaises(AttributeError, lambda: namespace.product)
266
        self.assertRaises(AttributeError, lambda: namespace.sourcepackage)
267
7779.1.6 by Jonathan Lange
Adapt from the objects to IBranchTarget.
268
    def test_adapter(self):
7849.5.5 by Jonathan Lange
A round of golf
269
        target = IBranchTarget(self.original)
7779.1.6 by Jonathan Lange
Adapt from the objects to IBranchTarget.
270
        self.assertIsInstance(target, PersonBranchTarget)
271
7847.1.19 by Jonathan Lange
Add a 'components' attribute to branch target, that returns the objects
272
    def test_components(self):
273
        target = IBranchTarget(self.original)
274
        self.assertEqual([self.original], list(target.components))
275
8031.2.2 by Jonathan Lange
Junk branches -- easy.
276
    def test_default_stacked_on_branch(self):
277
        # Junk branches are not stacked by default, ever.
278
        target = IBranchTarget(self.original)
279
        self.assertIs(None, target.default_stacked_on_branch)
280
8377.8.1 by Tim Penhey
Add a supports_merge_proposals attribute to branch namespaces.
281
    def test_supports_merge_proposals(self):
282
        # Personal branches do not support merge proposals.
283
        self.assertFalse(self.target.supports_merge_proposals)
284
9080.8.25 by Tim Penhey
Replace IBranch.is_personal_branch with IBranchTarget.supports_short_identities.
285
    def test_supports_short_identites(self):
286
        # Personal branches do not support short bzr identites.
287
        self.assertFalse(self.target.supports_short_identites)
288
8120.2.21 by Jonathan Lange
Add a displayname attribute to IBranchTarget.
289
    def test_displayname(self):
290
        # The display name of a person branch target is ~$USER/+junk.
291
        target = IBranchTarget(self.original)
292
        self.assertEqual('~%s/+junk' % self.original.name, target.displayname)
293
8377.8.2 by Tim Penhey
add IBranchTarget.areBranchesMergeable and tests.
294
    def test_areBranchesMergeable(self):
295
        # No branches are mergeable with a PersonBranchTarget.
296
        branch = self.factory.makeAnyBranch()
297
        self.assertFalse(self.target.areBranchesMergeable(branch.target))
298
8377.8.6 by Tim Penhey
Add default_merge_target to IBranchTarget.
299
    def test_default_merge_target(self):
300
        # The default merge target is always None.
301
        self.assertIs(None, self.target.default_merge_target)
302
8971.24.4 by Tim Penhey
Added BranchTarget.retargetBranch.
303
    def test_retargetBranch_packageBranch(self):
304
        # Retarget an existing package branch to this target.  Override the
305
        # mixin tests, and specify the owner of the branch.  This is needed to
306
        # match the target as the target is the branch owner for a personal
307
        # branch.
308
        branch = self.factory.makePackageBranch(owner=self.original)
8971.24.27 by Tim Penhey
Updates following review. Just some more tests for error conditions to go.
309
        self.target._retargetBranch(removeSecurityProxy(branch))
8971.24.4 by Tim Penhey
Added BranchTarget.retargetBranch.
310
        self.assertEqual(self.target, branch.target)
311
312
    def test_retargetBranch_productBranch(self):
313
        # Retarget an existing product branch to this target.  Override the
314
        # mixin tests, and specify the owner of the branch.  This is needed to
315
        # match the target as the target is the branch owner for a personal
316
        # branch.
317
        branch = self.factory.makeProductBranch(owner=self.original)
8971.24.27 by Tim Penhey
Updates following review. Just some more tests for error conditions to go.
318
        self.target._retargetBranch(removeSecurityProxy(branch))
8971.24.4 by Tim Penhey
Added BranchTarget.retargetBranch.
319
        self.assertEqual(self.target, branch.target)
320
321
    def test_retargetBranch_personalBranch(self):
322
        # Retarget an existing personal branch to this target.  Override the
323
        # mixin tests, and specify the owner of the branch.  This is needed to
324
        # match the target as the target is the branch owner for a personal
325
        # branch.
326
        branch = self.factory.makePersonalBranch(owner=self.original)
8971.24.27 by Tim Penhey
Updates following review. Just some more tests for error conditions to go.
327
        self.target._retargetBranch(removeSecurityProxy(branch))
8971.24.4 by Tim Penhey
Added BranchTarget.retargetBranch.
328
        self.assertEqual(self.target, branch.target)
329
10454.9.1 by James Westby
Add a check that the IBranchTarget supports code imports.
330
    def test_doesnt_support_code_imports(self):
331
        self.assertFalse(self.target.supports_code_imports)
332
10454.9.2 by James Westby
Add a method to IBranchTarget to allow creating a code import directly.
333
    def test_creating_code_import_fails(self):
334
        self.assertRaises(
335
            AssertionError, self.target.newCodeImport,
336
                self.factory.makePerson(),
337
                self.factory.getUniqueString("name-"),
338
                RevisionControlSystems.GIT, url=self.factory.getUniqueURL())
339
7849.5.5 by Jonathan Lange
A round of golf
340
341
class TestProductBranchTarget(TestCaseWithFactory, BaseBranchTargetTests):
7362.4.23 by Jonathan Lange
Add a ProductContainer.
342
343
    layer = DatabaseFunctionalLayer
344
7849.5.5 by Jonathan Lange
A round of golf
345
    def setUp(self):
346
        TestCaseWithFactory.setUp(self)
347
        self.original = self.factory.makeProduct()
348
        self.target = ProductBranchTarget(self.original)
349
8269.7.13 by Paul Hummer
Made docstring changes, and shifted tests around
350
    def makeBranchForTarget(self):
351
        return self.factory.makeBranch(product=self.original)
352
7362.4.23 by Jonathan Lange
Add a ProductContainer.
353
    def test_name(self):
7849.5.5 by Jonathan Lange
A round of golf
354
        self.assertEqual(self.original.name, self.target.name)
7849.5.3 by Jonathan Lange
Make IBranchTarget the IPrimaryContext for a branch.
355
7659.3.27 by Aaron Bentley
Get namespace from target container.
356
    def test_getNamespace(self):
357
        """Get namespace produces the correct namespace."""
358
        person = self.factory.makePerson()
7849.5.5 by Jonathan Lange
A round of golf
359
        namespace = self.target.getNamespace(person)
360
        self.assertEqual(namespace.product, self.original)
7659.3.27 by Aaron Bentley
Get namespace from target container.
361
        self.assertEqual(namespace.owner, person)
362
7779.1.6 by Jonathan Lange
Adapt from the objects to IBranchTarget.
363
    def test_adapter(self):
7849.5.5 by Jonathan Lange
A round of golf
364
        target = IBranchTarget(self.original)
7779.1.6 by Jonathan Lange
Adapt from the objects to IBranchTarget.
365
        self.assertIsInstance(target, ProductBranchTarget)
366
11270.2.13 by Tim Penhey
Add an adapter from product series to branch target.
367
    def test_productseries_adapter(self):
11270.2.15 by Tim Penhey
Add test comments.
368
        # Adapting a product series will make a product branch target.
369
        product = self.factory.makeProduct()
370
        series = self.factory.makeProductSeries(product)
11270.2.13 by Tim Penhey
Add an adapter from product series to branch target.
371
        target = IBranchTarget(series)
372
        self.assertIsInstance(target, ProductBranchTarget)
11270.2.15 by Tim Penhey
Add test comments.
373
        self.assertEqual([product], target.components)
11270.2.13 by Tim Penhey
Add an adapter from product series to branch target.
374
7847.1.19 by Jonathan Lange
Add a 'components' attribute to branch target, that returns the objects
375
    def test_components(self):
376
        target = IBranchTarget(self.original)
377
        self.assertEqual([self.original], list(target.components))
378
8031.2.1 by Jonathan Lange
Move the default stacking product doctests to be branch target unit tests
379
    def test_default_stacked_on_branch_no_dev_focus(self):
380
        # The default stacked-on branch for a product target that has no
381
        # development focus is None.
382
        target = IBranchTarget(self.original)
383
        self.assertIs(None, target.default_stacked_on_branch)
384
385
    def _setDevelopmentFocus(self, product, branch):
8137.2.1 by Jonathan Lange
Remove backwards compatibility shims for user_branch and series_branch.
386
        removeSecurityProxy(product).development_focus.branch = branch
8031.2.1 by Jonathan Lange
Move the default stacking product doctests to be branch target unit tests
387
388
    def test_default_stacked_on_branch_unmirrored_dev_focus(self):
389
        # If the development focus hasn't been mirrored, then don't use it as
390
        # the default stacked-on branch.
391
        branch = self.factory.makeProductBranch(product=self.original)
392
        self._setDevelopmentFocus(self.original, branch)
393
        target = IBranchTarget(self.original)
394
        self.assertIs(None, target.default_stacked_on_branch)
395
396
    def test_default_stacked_on_branch_has_been_mirrored(self):
397
        # If the development focus has been mirrored, then use it as the
398
        # default stacked-on branch.
399
        branch = self.factory.makeProductBranch(product=self.original)
400
        self._setDevelopmentFocus(self.original, branch)
9590.1.78 by Michael Hudson
add some removeSecurityProxys to the tests
401
        removeSecurityProxy(branch).branchChanged(
402
            '', 'rev1', None, None, None)
8031.2.1 by Jonathan Lange
Move the default stacking product doctests to be branch target unit tests
403
        target = IBranchTarget(self.original)
404
        self.assertEqual(branch, target.default_stacked_on_branch)
405
8377.8.1 by Tim Penhey
Add a supports_merge_proposals attribute to branch namespaces.
406
    def test_supports_merge_proposals(self):
407
        # Product branches do support merge proposals.
408
        self.assertTrue(self.target.supports_merge_proposals)
409
9080.8.25 by Tim Penhey
Replace IBranch.is_personal_branch with IBranchTarget.supports_short_identities.
410
    def test_supports_short_identites(self):
411
        # Product branches do support short bzr identites.
412
        self.assertTrue(self.target.supports_short_identites)
413
8120.2.21 by Jonathan Lange
Add a displayname attribute to IBranchTarget.
414
    def test_displayname(self):
415
        # The display name of a product branch target is the display name of
416
        # the product.
417
        target = IBranchTarget(self.original)
418
        self.assertEqual(self.original.displayname, target.displayname)
419
8377.8.2 by Tim Penhey
add IBranchTarget.areBranchesMergeable and tests.
420
    def test_areBranchesMergeable_same_product(self):
421
        # Branches of the same product are mergeable.
422
        same_target = ProductBranchTarget(self.original)
423
        self.assertTrue(self.target.areBranchesMergeable(same_target))
424
425
    def test_areBranchesMergeable_different_product(self):
426
        # Branches of a different product are not mergeable.
427
        other_target = ProductBranchTarget(self.factory.makeProduct())
428
        self.assertFalse(self.target.areBranchesMergeable(other_target))
429
430
    def test_areBranchesMergeable_personal_branches(self):
431
        # Personal branches are not mergeable.
432
        branch = self.factory.makePersonalBranch()
433
        self.assertFalse(self.target.areBranchesMergeable(branch.target))
434
435
    def test_areBranchesMergeable_unlinked_package(self):
436
        # Package branches are not normally mergeable into products.
437
        branch = self.factory.makePackageBranch()
438
        self.assertFalse(self.target.areBranchesMergeable(branch.target))
439
440
    def test_areBranchesMergeable_linked_package(self):
441
        # Packages that are linked to the products are mergeable.
442
        branch = self.factory.makePackageBranch()
443
        # Link it up.
444
        branch.sourcepackage.setPackaging(
445
            self.original.development_focus, branch.owner)
446
        self.assertTrue(self.target.areBranchesMergeable(branch.target))
8269.7.11 by Paul Hummer
Added tests for the collection attribute
447
8377.8.6 by Tim Penhey
Add default_merge_target to IBranchTarget.
448
    def test_default_merge_target(self):
449
        # The default merge target is the development focus branch.
450
        self.assertIs(None, self.target.default_merge_target)
451
        # Now create and link a branch.
452
        branch = self.factory.makeProductBranch(product=self.original)
453
        run_with_login(
454
            self.original.owner,
455
            setattr, self.original.development_focus, 'branch', branch)
456
        self.assertEqual(branch, self.target.default_merge_target)
457
10454.9.1 by James Westby
Add a check that the IBranchTarget supports code imports.
458
    def test_supports_code_imports(self):
459
        self.assertTrue(self.target.supports_code_imports)
460
10454.9.2 by James Westby
Add a method to IBranchTarget to allow creating a code import directly.
461
    def test_creating_code_import_succeeds(self):
462
        target_url = self.factory.getUniqueURL()
463
        branch_name = self.factory.getUniqueString("name-")
464
        owner = self.factory.makePerson()
465
        code_import = self.target.newCodeImport(
466
            owner, branch_name, RevisionControlSystems.GIT, url=target_url)
467
        code_import = removeSecurityProxy(code_import)
468
        self.assertProvides(code_import, ICodeImport)
469
        self.assertEqual(target_url, code_import.url)
470
        self.assertEqual(branch_name, code_import.branch.name)
471
        self.assertEqual(owner, code_import.registrant)
472
        self.assertEqual(owner, code_import.branch.owner)
473
        self.assertEqual(self.target, code_import.branch.target)
474
11994.2.21 by Ian Booth
Refactor related branches methods to IBranchTarget and show distro series instead of source package for related package branches
475
    def test_related_branches(self):
476
        (branch, related_series_branch_info,
477
            related_package_branches) = (
478
                self.factory.makeRelatedBranchesForProduct(
479
                product=self.original))
480
        self.assertEqual(
481
            related_series_branch_info,
482
            self.target.getRelatedSeriesBranchInfo(branch))
483
        self.assertEqual(
484
            related_package_branches,
485
            self.target.getRelatedPackageBranchInfo(branch))
486
487
    def test_related_branches_with_private_branch(self):
488
        (branch, related_series_branch_info,
489
            related_package_branches) = (
490
                self.factory.makeRelatedBranchesForProduct(
491
                product=self.original, with_private_branches=True))
492
        self.assertEqual(
493
            related_series_branch_info,
494
            self.target.getRelatedSeriesBranchInfo(branch))
495
        self.assertEqual(
496
            related_package_branches,
497
            self.target.getRelatedPackageBranchInfo(branch))
498
11994.2.24 by Ian Booth
Add option to limit the related branches results. UI only displays top 5 most recent branches
499
    def test_related_branches_with_limit(self):
500
        (branch, related_series_branch_info,
501
            related_package_branches) = (
502
                self.factory.makeRelatedBranchesForProduct(
503
                product=self.original))
504
        self.assertEqual(
505
            related_series_branch_info[:2],
506
            self.target.getRelatedSeriesBranchInfo(branch, 2))
507
        self.assertEqual(
508
            related_package_branches[:2],
509
            self.target.getRelatedPackageBranchInfo(branch, 2))
510
7362.4.23 by Jonathan Lange
Add a ProductContainer.
511
8031.4.11 by Jonathan Lange
Add a helper function for checking whether a branch is suitable for
512
class TestCheckDefaultStackedOnBranch(TestCaseWithFactory):
513
    """Only certain branches are allowed to be default stacked-on branches."""
514
515
    layer = DatabaseFunctionalLayer
516
517
    def test_none(self):
518
        # `check_default_stacked_on` returns None if passed None.
519
        self.assertIs(None, check_default_stacked_on(None))
520
521
    def test_unmirrored(self):
522
        # `check_default_stacked_on` returns None if passed an unmirrored
523
        # banch. This is because we don't want to stack things on unmirrored
524
        # branches.
525
        branch = self.factory.makeAnyBranch()
526
        self.assertIs(None, check_default_stacked_on(branch))
527
528
    def test_remote(self):
529
        # `check_default_stacked_on` returns None if passed a remote branch.
530
        # We have no Bazaar data for remote branches, so stacking on one is
531
        # futile.
532
        branch = self.factory.makeAnyBranch(branch_type=BranchType.REMOTE)
533
        self.assertIs(None, check_default_stacked_on(branch))
534
8031.4.21 by Jonathan Lange
More tests and fix a failing test.
535
    def test_remote_thats_been_mirrored(self):
536
        # Although REMOTE branches are not generally ever mirrored, it's
537
        # possible for a branch to be turned into a REMOTE branch later in
538
        # life.
539
        branch = self.factory.makeAnyBranch(branch_type=BranchType.MIRRORED)
540
        branch.startMirroring()
9590.1.78 by Michael Hudson
add some removeSecurityProxys to the tests
541
        removeSecurityProxy(branch).branchChanged(
9590.1.77 by Michael Hudson
remove mirrorComplete and all uses of it
542
            '', self.factory.getUniqueString(), None, None, None)
8031.4.21 by Jonathan Lange
More tests and fix a failing test.
543
        removeSecurityProxy(branch).branch_type = BranchType.REMOTE
544
        self.assertIs(None, check_default_stacked_on(branch))
545
8031.4.11 by Jonathan Lange
Add a helper function for checking whether a branch is suitable for
546
    def test_invisible(self):
547
        # `check_default_stacked_on` returns None for branches invisible to
548
        # the current user.
549
        branch = self.factory.makeAnyBranch(private=True)
550
        self.assertIs(None, check_default_stacked_on(branch))
551
8031.4.21 by Jonathan Lange
More tests and fix a failing test.
552
    def test_invisible_been_mirrored(self):
553
        # `check_default_stacked_on` returns None for branches invisible to
554
        # the current user, even if those branches have already been mirrored.
555
        branch = self.factory.makeAnyBranch(private=True)
556
        naked_branch = removeSecurityProxy(branch)
9590.1.77 by Michael Hudson
remove mirrorComplete and all uses of it
557
        naked_branch.branchChanged(
558
            '', self.factory.getUniqueString(), None, None, None)
8031.4.21 by Jonathan Lange
More tests and fix a failing test.
559
        self.assertIs(None, check_default_stacked_on(branch))
560
8031.4.11 by Jonathan Lange
Add a helper function for checking whether a branch is suitable for
561
    def test_been_mirrored(self):
10984.2.14 by Tim Penhey
Don't try to mirror hosted branches.
562
        # `check_default_stacked_on` returns the branch if it has revisions.
8031.4.11 by Jonathan Lange
Add a helper function for checking whether a branch is suitable for
563
        branch = self.factory.makeAnyBranch()
9590.1.77 by Michael Hudson
remove mirrorComplete and all uses of it
564
        removeSecurityProxy(branch).branchChanged(
565
            '', self.factory.getUniqueString(), None, None, None)
8031.4.11 by Jonathan Lange
Add a helper function for checking whether a branch is suitable for
566
        self.assertEqual(branch, check_default_stacked_on(branch))
567
568
7849.5.2 by Jonathan Lange
Guarantee that the primary context of the branch is the context of the target.
569
class TestPrimaryContext(TestCaseWithFactory):
570
571
    layer = DatabaseFunctionalLayer
572
573
    def test_package_branch(self):
574
        branch = self.factory.makePackageBranch()
7849.5.3 by Jonathan Lange
Make IBranchTarget the IPrimaryContext for a branch.
575
        self.assertEqual(branch.target, IPrimaryContext(branch))
7849.5.2 by Jonathan Lange
Guarantee that the primary context of the branch is the context of the target.
576
577
    def test_personal_branch(self):
578
        branch = self.factory.makePersonalBranch()
7849.5.3 by Jonathan Lange
Make IBranchTarget the IPrimaryContext for a branch.
579
        self.assertEqual(branch.target, IPrimaryContext(branch))
7849.5.2 by Jonathan Lange
Guarantee that the primary context of the branch is the context of the target.
580
581
    def test_product_branch(self):
582
        branch = self.factory.makeProductBranch()
7849.5.3 by Jonathan Lange
Make IBranchTarget the IPrimaryContext for a branch.
583
        self.assertEqual(branch.target, IPrimaryContext(branch))