~launchpad-pqm/launchpad/devel

12252.1.8 by j.c.sackett
Fixed copyright.
1
# Copyright 2009-2010 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).
4960.1.8 by Michael Hudson
add sort_by parameter to getBranchesForPerson().
3
4960.1.13 by Michael Hudson
docstrings and line lengths in database/branch.py
4
"""Unit tests for methods of Branch and BranchSet."""
4960.1.8 by Michael Hudson
add sort_by parameter to getBranchesForPerson().
5
6876.8.1 by Jonathan Lange
Unit tests for the current behaviour.
6
from zope.component import getUtility
7
from zope.security.proxy import removeSecurityProxy
8
7675.349.2 by Jonathan Lange
Change the tests to use launchpad.View, rather than directly invoking
9
from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities
10
from canonical.launchpad.webapp.authorization import check_permission
11666.3.5 by Curtis Hovey
Import layers from canonical.testing.layers.
11
from canonical.testing.layers import DatabaseFunctionalLayer
8555.2.5 by Tim Penhey
Move the branch subscription enums.
12
from lp.code.enums import (
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
13
    BranchSubscriptionDiffSize,
14
    BranchSubscriptionNotificationLevel,
15
    CodeReviewNotificationLevel,
16
    )
11474.5.6 by Tim Penhey
Get the supported schemes from the right place.
17
from lp.code.interfaces.codehosting import SUPPORTED_SCHEMES
10843.3.1 by Tim Penhey
Extract the method to make an official package branch.
18
from lp.code.tests.helpers import make_official_package_branch
9609.3.2 by Muharem Hrnjadovic
Revised test_package_upload_permissions_grant_branch_edit() so that the person in the test does have package upload permission to the package the branch is linked to.
19
from lp.soyuz.interfaces.archivepermission import IArchivePermissionSet
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
20
from lp.testing import (
21
    run_with_login,
22
    TestCaseWithFactory,
23
    )
4960.1.8 by Michael Hudson
add sort_by parameter to getBranchesForPerson().
24
4960.1.27 by Michael Hudson
review inspired changes
25
7675.349.3 by Jonathan Lange
Factor out a base class.
26
class PermissionTest(TestCaseWithFactory):
6876.8.1 by Jonathan Lange
Unit tests for the current behaviour.
27
28
    layer = DatabaseFunctionalLayer
29
7675.349.5 by Jonathan Lange
Generic assertion method.
30
    def assertPermission(self, can_access, person, secure_object, permission):
31
        """Assert that 'person' can or cannot access 'secure_object'.
32
33
        :param can_access: Whether or not the person can access the object.
34
        :param person: The `IPerson` who is trying to access the object.
35
        :param secure_object: The secured object.
36
        :param permission: The Launchpad permission that 'person' is trying to
37
            access 'secure_object' with.
38
        """
7675.349.7 by Jonathan Lange
Add an incomplete, failing test for package upload permission linking.
39
        self.assertEqual(
40
            can_access,
41
            run_with_login(
42
                person, check_permission, permission, secure_object))
7675.349.5 by Jonathan Lange
Generic assertion method.
43
7675.349.4 by Jonathan Lange
Rename to be more clear on what the hell we are asserting.
44
    def assertAuthenticatedView(self, branch, person, can_access):
7675.349.2 by Jonathan Lange
Change the tests to use launchpad.View, rather than directly invoking
45
        """Can 'branch' be accessed by 'person'?
46
47
        :param branch: The `IBranch` we're curious about.
48
        :param person: The `IPerson` trying to access it.
49
        :param can_access: Whether we expect 'person' be able to access it.
50
        """
7675.349.5 by Jonathan Lange
Generic assertion method.
51
        self.assertPermission(can_access, person, branch, 'launchpad.View')
6876.8.1 by Jonathan Lange
Unit tests for the current behaviour.
52
7675.349.4 by Jonathan Lange
Rename to be more clear on what the hell we are asserting.
53
    def assertUnauthenticatedView(self, branch, can_access):
7675.349.2 by Jonathan Lange
Change the tests to use launchpad.View, rather than directly invoking
54
        """Can 'branch' be accessed anonymously?
55
56
        :param branch: The `IBranch` we're curious about.
57
        :param can_access: Whether we expect to access it anonymously.
58
        """
7675.349.4 by Jonathan Lange
Rename to be more clear on what the hell we are asserting.
59
        self.assertAuthenticatedView(branch, None, can_access)
6876.8.1 by Jonathan Lange
Unit tests for the current behaviour.
60
7675.349.6 by Jonathan Lange
Tests for the current behaviour.
61
    def assertCanEdit(self, person, secured_object):
62
        """Assert 'person' can edit 'secured_object'.
63
64
        That is, assert 'person' has 'launchpad.Edit' permissions on
65
        'secured_object'.
66
67
        :param person: An `IPerson`. None means anonymous.
68
        :param secured_object: An object, secured through the Zope security
69
            layer.
70
        """
71
        self.assertPermission(True, person, secured_object, 'launchpad.Edit')
72
73
    def assertCannotEdit(self, person, secured_object):
74
        """Assert 'person' cannot edit 'secured_object'.
75
76
        That is, assert 'person' does not have 'launchpad.Edit' permissions on
77
        'secured_object'.
78
79
        :param person: An `IPerson`. None means anonymous.
80
        :param secured_object: An object, secured through the Zope security
81
            layer.
82
        """
83
        self.assertPermission(False, person, secured_object, 'launchpad.Edit')
84
7675.349.3 by Jonathan Lange
Factor out a base class.
85
86
class TestAccessBranch(PermissionTest):
87
6876.8.1 by Jonathan Lange
Unit tests for the current behaviour.
88
    def test_publicBranchUnauthenticated(self):
89
        # Public branches can be accessed without authentication.
7362.12.24 by Jonathan Lange
Restore change that somehow got lost.
90
        branch = self.factory.makeAnyBranch()
7675.349.4 by Jonathan Lange
Rename to be more clear on what the hell we are asserting.
91
        self.assertUnauthenticatedView(branch, True)
6876.8.1 by Jonathan Lange
Unit tests for the current behaviour.
92
93
    def test_publicBranchArbitraryUser(self):
94
        # Public branches can be accessed by anyone.
7362.12.24 by Jonathan Lange
Restore change that somehow got lost.
95
        branch = self.factory.makeAnyBranch()
6876.8.1 by Jonathan Lange
Unit tests for the current behaviour.
96
        person = self.factory.makePerson()
7675.349.4 by Jonathan Lange
Rename to be more clear on what the hell we are asserting.
97
        self.assertAuthenticatedView(branch, person, True)
6876.8.1 by Jonathan Lange
Unit tests for the current behaviour.
98
99
    def test_privateBranchUnauthenticated(self):
100
        # Private branches cannot be accessed without authentication.
7362.12.24 by Jonathan Lange
Restore change that somehow got lost.
101
        branch = self.factory.makeAnyBranch(private=True)
7675.349.4 by Jonathan Lange
Rename to be more clear on what the hell we are asserting.
102
        self.assertUnauthenticatedView(branch, False)
6876.8.1 by Jonathan Lange
Unit tests for the current behaviour.
103
104
    def test_privateBranchOwner(self):
105
        # The owner of a branch can always access it.
106
        owner = self.factory.makePerson()
7362.12.24 by Jonathan Lange
Restore change that somehow got lost.
107
        branch = self.factory.makeAnyBranch(private=True, owner=owner)
7675.349.4 by Jonathan Lange
Rename to be more clear on what the hell we are asserting.
108
        self.assertAuthenticatedView(branch, owner, True)
6876.8.1 by Jonathan Lange
Unit tests for the current behaviour.
109
110
    def test_privateBranchOwnerMember(self):
111
        # Any member of the team that owns the branch can access it.
112
        team_owner = self.factory.makePerson()
113
        team = self.factory.makeTeam(team_owner)
114
        person = self.factory.makePerson()
115
        removeSecurityProxy(team).addMember(person, team_owner)
7362.12.24 by Jonathan Lange
Restore change that somehow got lost.
116
        branch = self.factory.makeAnyBranch(private=True, owner=team)
7675.349.4 by Jonathan Lange
Rename to be more clear on what the hell we are asserting.
117
        self.assertAuthenticatedView(branch, person, True)
6876.8.1 by Jonathan Lange
Unit tests for the current behaviour.
118
119
    def test_privateBranchBazaarExperts(self):
120
        # The Bazaar experts can access any branch.
121
        celebs = getUtility(ILaunchpadCelebrities)
7362.12.24 by Jonathan Lange
Restore change that somehow got lost.
122
        branch = self.factory.makeAnyBranch(private=True)
7675.349.4 by Jonathan Lange
Rename to be more clear on what the hell we are asserting.
123
        self.assertAuthenticatedView(
7675.349.2 by Jonathan Lange
Change the tests to use launchpad.View, rather than directly invoking
124
            branch, celebs.bazaar_experts.teamowner, True)
6876.8.1 by Jonathan Lange
Unit tests for the current behaviour.
125
126
    def test_privateBranchAdmins(self):
127
        # Launchpad admins can access any branch.
128
        celebs = getUtility(ILaunchpadCelebrities)
7362.12.24 by Jonathan Lange
Restore change that somehow got lost.
129
        branch = self.factory.makeAnyBranch(private=True)
7675.349.4 by Jonathan Lange
Rename to be more clear on what the hell we are asserting.
130
        self.assertAuthenticatedView(branch, celebs.admin.teamowner, True)
6876.8.1 by Jonathan Lange
Unit tests for the current behaviour.
131
132
    def test_privateBranchSubscriber(self):
133
        # If you are subscribed to a branch, you can access it.
7362.12.24 by Jonathan Lange
Restore change that somehow got lost.
134
        branch = self.factory.makeAnyBranch(private=True)
6876.8.1 by Jonathan Lange
Unit tests for the current behaviour.
135
        person = self.factory.makePerson()
136
        removeSecurityProxy(branch).subscribe(
137
            person, BranchSubscriptionNotificationLevel.NOEMAIL,
138
            BranchSubscriptionDiffSize.NODIFF,
7675.708.3 by Tim Penhey
Add subscribed_by and unsubscribed_by to the subscribe and unsubscribe branch methods.
139
            CodeReviewNotificationLevel.NOEMAIL, person)
7675.349.4 by Jonathan Lange
Rename to be more clear on what the hell we are asserting.
140
        self.assertAuthenticatedView(branch, person, True)
6876.8.1 by Jonathan Lange
Unit tests for the current behaviour.
141
142
    def test_privateBranchAnyoneElse(self):
143
        # In general, you can't access a private branch.
7362.12.24 by Jonathan Lange
Restore change that somehow got lost.
144
        branch = self.factory.makeAnyBranch(private=True)
6876.8.1 by Jonathan Lange
Unit tests for the current behaviour.
145
        person = self.factory.makePerson()
7675.349.4 by Jonathan Lange
Rename to be more clear on what the hell we are asserting.
146
        self.assertAuthenticatedView(branch, person, False)
6876.8.1 by Jonathan Lange
Unit tests for the current behaviour.
147
6876.8.2 by Jonathan Lange
Check the stacked branch for authentication.
148
    def test_stackedOnPrivateBranchUnauthenticated(self):
149
        # If a branch is stacked on a private branch, then you cannot access
150
        # it when unauthenticated.
7362.12.24 by Jonathan Lange
Restore change that somehow got lost.
151
        stacked_on_branch = self.factory.makeAnyBranch(private=True)
152
        stacked_branch = self.factory.makeAnyBranch(
153
            stacked_on=stacked_on_branch)
7675.349.4 by Jonathan Lange
Rename to be more clear on what the hell we are asserting.
154
        self.assertUnauthenticatedView(stacked_branch, False)
6876.8.2 by Jonathan Lange
Check the stacked branch for authentication.
155
156
    def test_stackedOnPrivateBranchAuthenticated(self):
157
        # If a branch is stacked on a private branch, you can only access it
158
        # if you can access both branches.
7362.12.24 by Jonathan Lange
Restore change that somehow got lost.
159
        stacked_on_branch = self.factory.makeAnyBranch(private=True)
160
        stacked_branch = self.factory.makeAnyBranch(
161
            stacked_on=stacked_on_branch)
6876.8.2 by Jonathan Lange
Check the stacked branch for authentication.
162
        person = self.factory.makePerson()
7675.349.4 by Jonathan Lange
Rename to be more clear on what the hell we are asserting.
163
        self.assertAuthenticatedView(stacked_branch, person, False)
6876.8.2 by Jonathan Lange
Check the stacked branch for authentication.
164
165
    def test_manyLevelsOfStackingUnauthenticated(self):
166
        # If a branch is stacked on a branch stacked on a private branch, you
167
        # still can't access it when unauthenticated.
7362.12.24 by Jonathan Lange
Restore change that somehow got lost.
168
        stacked_on_branch = self.factory.makeAnyBranch(private=True)
169
        branch_a = self.factory.makeAnyBranch(stacked_on=stacked_on_branch)
170
        branch_b = self.factory.makeAnyBranch(stacked_on=branch_a)
7675.349.4 by Jonathan Lange
Rename to be more clear on what the hell we are asserting.
171
        self.assertUnauthenticatedView(branch_b, False)
6876.8.2 by Jonathan Lange
Check the stacked branch for authentication.
172
173
    def test_manyLevelsOfStackingAuthenticated(self):
174
        # If a branch is stacked on a branch stacked on a private branch, you
175
        # still can't access it when unauthenticated.
7362.12.24 by Jonathan Lange
Restore change that somehow got lost.
176
        stacked_on_branch = self.factory.makeAnyBranch(private=True)
177
        branch_a = self.factory.makeAnyBranch(stacked_on=stacked_on_branch)
178
        branch_b = self.factory.makeAnyBranch(stacked_on=branch_a)
6876.8.2 by Jonathan Lange
Check the stacked branch for authentication.
179
        person = self.factory.makePerson()
7675.349.4 by Jonathan Lange
Rename to be more clear on what the hell we are asserting.
180
        self.assertAuthenticatedView(branch_b, person, False)
6876.8.2 by Jonathan Lange
Check the stacked branch for authentication.
181
182
    def test_loopedPublicStackedOn(self):
183
        # It's possible, although nonsensical, for branch stackings to form a
184
        # loop. e.g., branch A is stacked on branch B is stacked on branch A.
185
        # If all of these branches are public, then we want anyone to be able
186
        # to access it / them.
7362.12.24 by Jonathan Lange
Restore change that somehow got lost.
187
        stacked_branch = self.factory.makeAnyBranch()
6876.8.2 by Jonathan Lange
Check the stacked branch for authentication.
188
        removeSecurityProxy(stacked_branch).stacked_on = stacked_branch
189
        person = self.factory.makePerson()
7675.349.4 by Jonathan Lange
Rename to be more clear on what the hell we are asserting.
190
        self.assertAuthenticatedView(stacked_branch, person, True)
6876.8.2 by Jonathan Lange
Check the stacked branch for authentication.
191
192
    def test_loopedPrivateStackedOn(self):
193
        # It's possible, although nonsensical, for branch stackings to form a
194
        # loop. e.g., branch A is stacked on branch B is stacked on branch A.
195
        # If all of these branches are private, then only people who can
196
        # access all of them can get to them.
7362.12.24 by Jonathan Lange
Restore change that somehow got lost.
197
        stacked_branch = self.factory.makeAnyBranch(private=True)
6876.8.2 by Jonathan Lange
Check the stacked branch for authentication.
198
        removeSecurityProxy(stacked_branch).stacked_on = stacked_branch
199
        person = self.factory.makePerson()
7675.349.4 by Jonathan Lange
Rename to be more clear on what the hell we are asserting.
200
        self.assertAuthenticatedView(stacked_branch, person, False)
6876.8.2 by Jonathan Lange
Check the stacked branch for authentication.
201
202
    def test_loopedPublicStackedOnUnauthenticated(self):
203
        # It's possible, although nonsensical, for branch stackings to form a
204
        # loop. e.g., branch A is stacked on branch B is stacked on branch A.
205
        # If all of these branches are public, then you can get them without
206
        # being logged in.
7362.12.24 by Jonathan Lange
Restore change that somehow got lost.
207
        stacked_branch = self.factory.makeAnyBranch()
6876.8.2 by Jonathan Lange
Check the stacked branch for authentication.
208
        removeSecurityProxy(stacked_branch).stacked_on = stacked_branch
7675.349.4 by Jonathan Lange
Rename to be more clear on what the hell we are asserting.
209
        self.assertUnauthenticatedView(stacked_branch, True)
6876.8.2 by Jonathan Lange
Check the stacked branch for authentication.
210
6876.8.1 by Jonathan Lange
Unit tests for the current behaviour.
211
7675.349.6 by Jonathan Lange
Tests for the current behaviour.
212
class TestWriteToBranch(PermissionTest):
213
    """Test who can write to branches."""
214
215
    def test_owner_can_write(self):
216
        # The owner of a branch can write to the branch.
217
        branch = self.factory.makeAnyBranch()
218
        self.assertCanEdit(branch.owner, branch)
219
220
    def test_random_person_cannot_write(self):
221
        # Arbitrary logged in people cannot write to branches.
222
        branch = self.factory.makeAnyBranch()
223
        person = self.factory.makePerson()
224
        self.assertCannotEdit(person, branch)
225
226
    def test_member_of_owning_team_can_write(self):
227
        # Members of the team that owns a branch can write to the branch.
228
        team = self.factory.makeTeam()
229
        person = self.factory.makePerson()
230
        removeSecurityProxy(team).addMember(person, team.teamowner)
231
        branch = self.factory.makeAnyBranch(owner=team)
232
        self.assertCanEdit(person, branch)
233
9636.5.18 by Jonathan Lange
Fix omission in the security story.
234
    def test_vcs_imports_members_can_edit_import_branch(self):
235
        # Even if a branch isn't owned by vcs-imports, vcs-imports members can
236
        # edit it if it has a code import associated with it.
237
        person = self.factory.makePerson()
10454.4.19 by James Westby
Drop makeAnyCodeImport as makeCodeImport does that anyway.
238
        branch = self.factory.makeCodeImport().branch
9636.5.18 by Jonathan Lange
Fix omission in the security story.
239
        vcs_imports = getUtility(ILaunchpadCelebrities).vcs_imports
240
        removeSecurityProxy(vcs_imports).addMember(
241
            person, vcs_imports.teamowner)
242
        self.assertCanEdit(person, branch)
243
7675.349.7 by Jonathan Lange
Add an incomplete, failing test for package upload permission linking.
244
    def makeOfficialPackageBranch(self):
245
        """Make a branch linked to the pocket of a source package."""
10843.3.1 by Tim Penhey
Extract the method to make an official package branch.
246
        return make_official_package_branch(self.factory)
7675.349.7 by Jonathan Lange
Add an incomplete, failing test for package upload permission linking.
247
248
    def test_owner_can_write_to_official_package_branch(self):
249
        # The owner of an official package branch can write to it, just like a
250
        # regular person.
251
        branch = self.makeOfficialPackageBranch()
252
        self.assertCanEdit(branch.owner, branch)
253
9609.3.6 by Muharem Hrnjadovic
Cleaned up code a bit.
254
    def assertCanUpload(self, person, spn, archive, component,
7675.384.6 by Muharem Hrnjadovic
Julian's review comments, round 1.
255
                        strict_component=True, distroseries=None):
9609.3.6 by Muharem Hrnjadovic
Cleaned up code a bit.
256
        """Assert that 'person' can upload 'spn' to 'archive'."""
257
        # For now, just check that doesn't raise an exception.
7675.384.6 by Muharem Hrnjadovic
Julian's review comments, round 1.
258
        if distroseries is None:
7675.384.8 by Muharem Hrnjadovic
Julian's review comments, round 2.
259
            distroseries = archive.distribution.currentseries
9609.3.6 by Muharem Hrnjadovic
Cleaned up code a bit.
260
        self.assertIs(
261
            None,
10156.2.4 by Jelmer Vernooij
Move verify_upload onto IArchive, some refactoring.
262
            archive.verifyUpload(
263
                person, spn, component, distroseries,
7675.384.6 by Muharem Hrnjadovic
Julian's review comments, round 1.
264
                strict_component))
9609.3.6 by Muharem Hrnjadovic
Cleaned up code a bit.
265
7675.384.6 by Muharem Hrnjadovic
Julian's review comments, round 1.
266
    def assertCannotUpload(
267
        self, reason, person, spn, archive, component, distroseries=None):
9609.3.6 by Muharem Hrnjadovic
Cleaned up code a bit.
268
        """Assert that 'person' cannot upload to the archive.
269
270
        :param reason: The expected reason for not being able to upload. A
271
            string.
272
        :param person: The person trying to upload.
273
        :param spn: The `ISourcePackageName` being uploaded to. None if the
274
            package does not yet exist.
275
        :param archive: The `IArchive` being uploaded to.
276
        :param component: The IComponent to which the package belongs.
277
        """
7675.384.6 by Muharem Hrnjadovic
Julian's review comments, round 1.
278
        if distroseries is None:
7675.384.8 by Muharem Hrnjadovic
Julian's review comments, round 2.
279
            distroseries = archive.distribution.currentseries
10156.2.4 by Jelmer Vernooij
Move verify_upload onto IArchive, some refactoring.
280
        exception = archive.verifyUpload(
281
            person, spn, component, distroseries)
9609.3.6 by Muharem Hrnjadovic
Cleaned up code a bit.
282
        self.assertEqual(reason, str(exception))
283
7675.349.7 by Jonathan Lange
Add an incomplete, failing test for package upload permission linking.
284
    def test_package_upload_permissions_grant_branch_edit(self):
285
        # If you can upload to the package, then you are also allowed to write
286
        # to the branch.
9697.1.4 by Muharem Hrnjadovic
Refactored the pertinent test.
287
9609.3.2 by Muharem Hrnjadovic
Revised test_package_upload_permissions_grant_branch_edit() so that the person in the test does have package upload permission to the package the branch is linked to.
288
        permission_set = getUtility(IArchivePermissionSet)
289
        # Only admins or techboard members can add permissions normally. That
290
        # restriction isn't relevant to these tests.
10843.3.1 by Tim Penhey
Extract the method to make an official package branch.
291
        permission_set = removeSecurityProxy(permission_set)
7675.349.7 by Jonathan Lange
Add an incomplete, failing test for package upload permission linking.
292
        branch = self.makeOfficialPackageBranch()
293
        package = branch.sourcepackage
294
        person = self.factory.makePerson()
9609.3.4 by Muharem Hrnjadovic
Test refined.
295
296
        # Person is not allowed to edit the branch presently.
297
        self.assertCannotEdit(person, branch)
298
299
        # Now give 'person' permission to upload to 'package'.
9609.3.2 by Muharem Hrnjadovic
Revised test_package_upload_permissions_grant_branch_edit() so that the person in the test does have package upload permission to the package the branch is linked to.
300
        archive = branch.distroseries.distribution.main_archive
301
        spn = package.sourcepackagename
10843.3.1 by Tim Penhey
Extract the method to make an official package branch.
302
        permission_set.newPackageUploader(archive, person, spn)
9609.3.3 by Muharem Hrnjadovic
Expanded the test_package_upload_permissions_grant_branch_edit() test a bit and added another method (personMayEditBranch()) to make it work.
303
        # Make sure person *is* authorised to upload the source package
304
        # targeted by the branch at hand.
9609.3.2 by Muharem Hrnjadovic
Revised test_package_upload_permissions_grant_branch_edit() so that the person in the test does have package upload permission to the package the branch is linked to.
305
        self.assertCanUpload(person, spn, archive, None)
9609.3.4 by Muharem Hrnjadovic
Test refined.
306
9697.1.4 by Muharem Hrnjadovic
Refactored the pertinent test.
307
        # Now person can edit the branch on the basis of the upload
308
        # permissions granted above.
309
        self.assertCanEdit(person, branch)
7675.349.7 by Jonathan Lange
Add an incomplete, failing test for package upload permission linking.
310
9636.5.7 by Jonathan Lange
Allow registrant of code import branch owned by vcs_imports to edit the
311
    def test_arbitrary_person_cannot_edit(self):
9636.5.8 by Jonathan Lange
Comment on the test.
312
        # Arbitrary people cannot edit branches, you have to be someone
313
        # special.
9636.5.7 by Jonathan Lange
Allow registrant of code import branch owned by vcs_imports to edit the
314
        branch = self.factory.makeAnyBranch()
315
        person = self.factory.makePerson()
9636.5.17 by Jonathan Lange
Remove unnecessary subclass.
316
        self.assertCannotEdit(person, branch)
9636.5.7 by Jonathan Lange
Allow registrant of code import branch owned by vcs_imports to edit the
317
318
    def test_code_import_registrant_can_edit(self):
319
        # It used to be the case that all import branches were owned by the
320
        # special, restricted team ~vcs-imports. This made a lot of work for
321
        # the Launchpad development team, since they needed to delete and
322
        # rename import branches whenever people wanted it. To reduce this
323
        # work a little, whoever registered of a code import branch is allowed
324
        # to edit the branch, even if they aren't one of the owners.
325
        registrant = self.factory.makePerson()
10454.4.19 by James Westby
Drop makeAnyCodeImport as makeCodeImport does that anyway.
326
        code_import = self.factory.makeCodeImport(registrant=registrant)
9636.5.7 by Jonathan Lange
Allow registrant of code import branch owned by vcs_imports to edit the
327
        branch = code_import.branch
328
        removeSecurityProxy(branch).setOwner(
329
            getUtility(ILaunchpadCelebrities).vcs_imports,
330
            getUtility(ILaunchpadCelebrities).vcs_imports)
9636.5.17 by Jonathan Lange
Remove unnecessary subclass.
331
        self.assertCanEdit(registrant, branch)
9636.5.7 by Jonathan Lange
Allow registrant of code import branch owned by vcs_imports to edit the
332
7675.349.6 by Jonathan Lange
Tests for the current behaviour.
333
10312.5.5 by Jeroen Vermeulen
IBranch.composePublicURL.
334
class TestComposePublicURL(TestCaseWithFactory):
335
336
    layer = DatabaseFunctionalLayer
337
338
    def setUp(self):
339
        super(TestComposePublicURL, self).setUp('admin@canonical.com')
340
341
    def test_composePublicURL_accepts_supported_schemes(self):
342
        # composePublicURL accepts all schemes that PublicCodehostingAPI
343
        # supports.
344
        branch = self.factory.makeAnyBranch()
345
346
        url_pattern = '%%s://bazaar.launchpad.dev/~%s/%s/%s' % (
347
            branch.owner.name, branch.product.name, branch.name)
11474.5.6 by Tim Penhey
Get the supported schemes from the right place.
348
        for scheme in SUPPORTED_SCHEMES:
10312.5.5 by Jeroen Vermeulen
IBranch.composePublicURL.
349
            public_url = branch.composePublicURL(scheme)
350
            self.assertEqual(url_pattern % scheme, public_url)
351
352
        # sftp support is also grandfathered in.
353
        sftp_url = branch.composePublicURL('sftp')
354
        self.assertEqual(url_pattern % 'sftp', sftp_url)
355
356
    def test_composePublicURL_default_http(self):
357
        # The default scheme for composePublicURL is http.
358
        branch = self.factory.makeAnyBranch()
359
        prefix = 'http://'
360
        public_url = branch.composePublicURL()
361
        self.assertEqual(prefix, public_url[:len(prefix)])
362
363
    def test_composePublicURL_unknown_scheme(self):
10312.5.6 by Jeroen Vermeulen
Export composePublicURL, use unique_name instead of bzr_identity.
364
        # Schemes that aren't known to be supported are not accepted.
10312.5.5 by Jeroen Vermeulen
IBranch.composePublicURL.
365
        branch = self.factory.makeAnyBranch()
366
        self.assertRaises(AssertionError, branch.composePublicURL, 'irc')
367
368
    def test_composePublicURL_http_private(self):
369
        # Private branches don't have public http URLs.
370
        branch = self.factory.makeAnyBranch(private=True)
371
        self.assertRaises(AssertionError, branch.composePublicURL, 'http')
372
373
    def test_composePublicURL_no_https(self):
374
        # There's no https support.  If there were, it should probably
375
        # not work for private branches.
376
        branch = self.factory.makeAnyBranch()
377
        self.assertRaises(AssertionError, branch.composePublicURL, 'https')