/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2052.3.2 by John Arbash Meinel
Change Copyright .. by Canonical to Copyright ... Canonical
1
# Copyright (C) 2006 Canonical Ltd
0.4.1 by Martin Pool
Start lp-register command
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
0.4.8 by Martin Pool
More instrumentation of xmlrpc requests
17
import base64
0.4.13 by Martin Pool
Update xmlrpc api to pass product name as a parameter.
18
import os
0.4.8 by Martin Pool
More instrumentation of xmlrpc requests
19
from StringIO import StringIO
2978.5.1 by John Arbash Meinel
Fix bug #162494, 'bzr register-branch' needs proper auth handling.
20
import urlparse
0.4.5 by Martin Pool
Add structured test for parameters passed through xmlrpc
21
import xmlrpclib
22
2978.5.1 by John Arbash Meinel
Fix bug #162494, 'bzr register-branch' needs proper auth handling.
23
from bzrlib import (
24
    config,
25
    osutils,
26
    tests,
27
    ui,
28
    )
3200.2.1 by Robert Collins
* The ``register-branch`` command will now use the public url of the branch
29
from bzrlib.tests import TestCaseWithTransport, TestSkipped
0.4.1 by Martin Pool
Start lp-register command
30
0.4.5 by Martin Pool
Add structured test for parameters passed through xmlrpc
31
# local import
2898.3.8 by James Henstridge
Get rid of relative imports in Launchpad plugin.
32
from bzrlib.plugins.launchpad.lp_registration import (
0.4.26 by Martin Pool
(register-branch) Add test for link_branch_to_bug and fix its parameters
33
        BaseRequest,
34
        BranchBugLinkRequest,
35
        BranchRegistrationRequest,
2898.4.3 by James Henstridge
Make launchpad_transport_indirect() use XMLRPC to resolve the lp: URL.
36
        ResolveLaunchpadPathRequest,
0.4.26 by Martin Pool
(register-branch) Add test for link_branch_to_bug and fix its parameters
37
        LaunchpadService,
38
        )
0.4.5 by Martin Pool
Add structured test for parameters passed through xmlrpc
39
0.4.7 by Martin Pool
Start making provision to test using a mock xmlrpc transport.
40
0.4.12 by Martin Pool
doc
41
# TODO: Test that the command-line client, making sure that it'll pass the
42
# request through to a dummy transport, and that the transport will validate
43
# the results passed in.  Not sure how to get the transport object back out to
44
# validate that its OK - may not be necessary.
45
46
# TODO: Add test for (and implement) other command-line options to set
0.4.14 by Martin Pool
Update xmlrpc api
47
# project, author_email, description.
0.4.12 by Martin Pool
doc
48
49
# TODO: project_id is not properly handled -- must be passed in rpc or path.
50
0.4.8 by Martin Pool
More instrumentation of xmlrpc requests
51
class InstrumentedXMLRPCConnection(object):
52
    """Stands in place of an http connection for the purposes of testing"""
53
54
    def __init__(self, testcase):
55
        self.testcase = testcase
56
57
    def getreply(self):
58
        """Fake the http reply.
59
60
        :returns: (errcode, errmsg, headers)
61
        """
62
        return (200, 'OK', [])
63
64
    def getfile(self):
65
        """Return a fake file containing the response content."""
66
        return StringIO('''\
67
<?xml version="1.0" ?>
68
<methodResponse>
0.4.11 by Martin Pool
Check the correct params are seen by the server
69
    <params>
70
        <param>
71
            <value>
72
                <string>victoria dock</string>
73
            </value>
74
        </param>
75
    </params>
0.4.8 by Martin Pool
More instrumentation of xmlrpc requests
76
</methodResponse>''')
77
78
79
0.4.7 by Martin Pool
Start making provision to test using a mock xmlrpc transport.
80
class InstrumentedXMLRPCTransport(xmlrpclib.Transport):
81
2027.2.2 by Marien Zwart
Fixes for python 2.5.
82
    # Python 2.5's xmlrpclib looks for this.
83
    _use_datetime = False
84
2898.4.2 by James Henstridge
Add ResolveLaunchpadURLRequest() class to handle lp: URL resolution.
85
    def __init__(self, testcase, expect_auth):
0.4.7 by Martin Pool
Start making provision to test using a mock xmlrpc transport.
86
        self.testcase = testcase
2898.4.2 by James Henstridge
Add ResolveLaunchpadURLRequest() class to handle lp: URL resolution.
87
        self.expect_auth = expect_auth
0.4.7 by Martin Pool
Start making provision to test using a mock xmlrpc transport.
88
89
    def make_connection(self, host):
90
        host, http_headers, x509 = self.get_host_info(host)
91
        test = self.testcase
0.4.10 by Martin Pool
Move test-specific values out of InstrumentedXMLRPCTransport
92
        self.connected_host = host
2898.4.2 by James Henstridge
Add ResolveLaunchpadURLRequest() class to handle lp: URL resolution.
93
        if self.expect_auth:
94
            auth_hdrs = [v for k,v in http_headers if k == 'Authorization']
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
95
            if len(auth_hdrs):
96
                raise AssertionError("multiple auth headers: %r"
97
                    % (auth_hdrs,))
2898.4.2 by James Henstridge
Add ResolveLaunchpadURLRequest() class to handle lp: URL resolution.
98
            authinfo = auth_hdrs[0]
99
            expected_auth = 'testuser@launchpad.net:testpassword'
100
            test.assertEquals(authinfo,
101
                    'Basic ' + base64.encodestring(expected_auth).strip())
102
        else:
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
103
            if http_headers:
104
                raise AssertionError()
0.4.8 by Martin Pool
More instrumentation of xmlrpc requests
105
        return InstrumentedXMLRPCConnection(test)
0.4.7 by Martin Pool
Start making provision to test using a mock xmlrpc transport.
106
107
    def send_request(self, connection, handler_path, request_body):
108
        test = self.testcase
109
        self.got_request = True
110
111
    def send_host(self, conn, host):
112
        pass
113
114
    def send_user_agent(self, conn):
115
        # TODO: send special user agent string, including bzrlib version
116
        # number
117
        pass
118
119
    def send_content(self, conn, request_body):
120
        unpacked, method = xmlrpclib.loads(request_body)
0.4.10 by Martin Pool
Move test-specific values out of InstrumentedXMLRPCTransport
121
        self.sent_params = unpacked
0.4.7 by Martin Pool
Start making provision to test using a mock xmlrpc transport.
122
123
0.4.22 by Martin Pool
(register-branch) Update tests to be in-process calls to a mock server.
124
class MockLaunchpadService(LaunchpadService):
125
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
126
    def send_request(self, method_name, method_params, authenticated):
0.4.22 by Martin Pool
(register-branch) Update tests to be in-process calls to a mock server.
127
        """Stash away the method details rather than sending them to a real server"""
128
        self.called_method_name = method_name
129
        self.called_method_params = method_params
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
130
        self.called_authenticated = authenticated
0.4.22 by Martin Pool
(register-branch) Update tests to be in-process calls to a mock server.
131
132
3200.2.1 by Robert Collins
* The ``register-branch`` command will now use the public url of the branch
133
class TestBranchRegistration(TestCaseWithTransport):
0.4.4 by Martin Pool
Start forming xmlrpc requests
134
    SAMPLE_URL = 'http://bazaar-vcs.org/bzr/bzr.dev/'
0.4.6 by Martin Pool
Put the rest of the parameters into the registration request.
135
    SAMPLE_OWNER = 'jhacker@foo.com'
136
    SAMPLE_BRANCH_ID = 'bzr.dev'
0.4.4 by Martin Pool
Start forming xmlrpc requests
137
0.4.23 by Martin Pool
(register-branch) fix ordering of parameters and restore transport-level test.
138
    def setUp(self):
139
        super(TestBranchRegistration, self).setUp()
140
        # make sure we have a reproducible standard environment
2978.5.1 by John Arbash Meinel
Fix bug #162494, 'bzr register-branch' needs proper auth handling.
141
        self._captureVar('BZR_LP_XMLRPC_URL', None)
0.4.23 by Martin Pool
(register-branch) fix ordering of parameters and restore transport-level test.
142
0.4.22 by Martin Pool
(register-branch) Update tests to be in-process calls to a mock server.
143
    def test_register_help(self):
144
        """register-branch accepts --help"""
2581.1.4 by Martin Pool
fixup run_bzr syntax in launchpad plugin
145
        out, err = self.run_bzr(['register-branch', '--help'])
0.4.2 by Martin Pool
Rename command to 'register-branch'
146
        self.assertContainsRe(out, r'Register a branch')
147
3200.2.1 by Robert Collins
* The ``register-branch`` command will now use the public url of the branch
148
    def test_register_no_url_no_branch(self):
0.4.22 by Martin Pool
(register-branch) Update tests to be in-process calls to a mock server.
149
        """register-branch command requires parameters"""
3200.2.1 by Robert Collins
* The ``register-branch`` command will now use the public url of the branch
150
        self.make_repository('.')
151
        self.run_bzr_error(
152
            ['register-branch requires a public branch url - '
153
             'see bzr help register-branch'],
154
            'register-branch')
155
156
    def test_register_no_url_in_published_branch_no_error(self):
157
        b = self.make_branch('.')
158
        b.set_public_branch('http://test-server.com/bzr/branch')
159
        out, err = self.run_bzr(['register-branch', '--dry-run'])
160
        self.assertEqual('Branch registered.\n', out)
161
        self.assertEqual('', err)
162
163
    def test_register_no_url_in_unpublished_branch_errors(self):
164
        b = self.make_branch('.')
165
        out, err = self.run_bzr_error(['no public branch'],
166
            ['register-branch', '--dry-run'])
167
        self.assertEqual('', out)
0.4.3 by Martin Pool
More command line processing
168
1668.1.12 by Martin Pool
(launchpad plugin) Improved --dry-run that uses a dummy xmlrpc service.
169
    def test_register_dry_run(self):
2581.1.4 by Martin Pool
fixup run_bzr syntax in launchpad plugin
170
        out, err = self.run_bzr(['register-branch',
1668.1.12 by Martin Pool
(launchpad plugin) Improved --dry-run that uses a dummy xmlrpc service.
171
                                'http://test-server.com/bzr/branch',
2581.1.4 by Martin Pool
fixup run_bzr syntax in launchpad plugin
172
                                '--dry-run'])
1668.1.12 by Martin Pool
(launchpad plugin) Improved --dry-run that uses a dummy xmlrpc service.
173
        self.assertEquals(out, 'Branch registered.\n')
0.4.4 by Martin Pool
Start forming xmlrpc requests
174
0.4.23 by Martin Pool
(register-branch) fix ordering of parameters and restore transport-level test.
175
    def test_onto_transport(self):
0.4.7 by Martin Pool
Start making provision to test using a mock xmlrpc transport.
176
        """Test how the request is sent by transmitting across a mock Transport"""
0.4.23 by Martin Pool
(register-branch) fix ordering of parameters and restore transport-level test.
177
        # use a real transport, but intercept at the http/xml layer
2898.4.2 by James Henstridge
Add ResolveLaunchpadURLRequest() class to handle lp: URL resolution.
178
        transport = InstrumentedXMLRPCTransport(self, expect_auth=True)
0.4.30 by Martin Pool
Fix wierd syntax errors in test
179
        service = LaunchpadService(transport)
0.4.23 by Martin Pool
(register-branch) fix ordering of parameters and restore transport-level test.
180
        service.registrant_email = 'testuser@launchpad.net'
181
        service.registrant_password = 'testpassword'
0.4.7 by Martin Pool
Start making provision to test using a mock xmlrpc transport.
182
        rego = BranchRegistrationRequest('http://test-server.com/bzr/branch',
0.4.23 by Martin Pool
(register-branch) fix ordering of parameters and restore transport-level test.
183
                'branch-id',
184
                'my test branch',
185
                'description',
186
                'author@launchpad.net',
187
                'product')
0.4.20 by Bjorn Tillenius
try to fix the tests.
188
        rego.submit(service)
3200.2.2 by Robert Collins
* The launchpad plugin now uses the ``edge`` xmlrpc server to avoid
189
        self.assertEquals(transport.connected_host, 'xmlrpc.edge.launchpad.net')
0.4.14 by Martin Pool
Update xmlrpc api
190
        self.assertEquals(len(transport.sent_params), 6)
0.4.11 by Martin Pool
Check the correct params are seen by the server
191
        self.assertEquals(transport.sent_params,
0.4.23 by Martin Pool
(register-branch) fix ordering of parameters and restore transport-level test.
192
                ('http://test-server.com/bzr/branch',  # branch_url
193
                 'branch-id',                          # branch_name
194
                 'my test branch',                     # branch_title
195
                 'description',
196
                 'author@launchpad.net',
197
                 'product'))
0.4.8 by Martin Pool
More instrumentation of xmlrpc requests
198
        self.assertTrue(transport.got_request)
0.4.13 by Martin Pool
Update xmlrpc api to pass product name as a parameter.
199
2898.4.2 by James Henstridge
Add ResolveLaunchpadURLRequest() class to handle lp: URL resolution.
200
    def test_onto_transport_unauthenticated(self):
201
        """Test how an unauthenticated request is transmitted across a mock Transport"""
202
        transport = InstrumentedXMLRPCTransport(self, expect_auth=False)
203
        service = LaunchpadService(transport)
2898.4.3 by James Henstridge
Make launchpad_transport_indirect() use XMLRPC to resolve the lp: URL.
204
        resolve = ResolveLaunchpadPathRequest('bzr')
2898.4.2 by James Henstridge
Add ResolveLaunchpadURLRequest() class to handle lp: URL resolution.
205
        resolve.submit(service)
3200.2.2 by Robert Collins
* The launchpad plugin now uses the ``edge`` xmlrpc server to avoid
206
        self.assertEquals(transport.connected_host, 'xmlrpc.edge.launchpad.net')
2898.4.2 by James Henstridge
Add ResolveLaunchpadURLRequest() class to handle lp: URL resolution.
207
        self.assertEquals(len(transport.sent_params), 1)
208
        self.assertEquals(transport.sent_params, ('bzr', ))
209
        self.assertTrue(transport.got_request)
210
0.4.22 by Martin Pool
(register-branch) Update tests to be in-process calls to a mock server.
211
    def test_subclass_request(self):
212
        """Define a new type of xmlrpc request"""
213
        class DummyRequest(BaseRequest):
214
            _methodname = 'dummy_request'
215
            def _request_params(self):
216
                return (42,)
217
218
        service = MockLaunchpadService()
219
        service.registrant_email = 'test@launchpad.net'
220
        service.registrant_password = ''
221
        request = DummyRequest()
222
        request.submit(service)
223
        self.assertEquals(service.called_method_name, 'dummy_request')
224
        self.assertEquals(service.called_method_params, (42,))
225
0.4.24 by Martin Pool
(register-branch) additional test case against mock server
226
    def test_mock_server_registration(self):
227
        """Send registration to mock server"""
228
        test_case = self
229
        class MockRegistrationService(MockLaunchpadService):
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
230
            def send_request(self, method_name, method_params, authenticated):
0.4.24 by Martin Pool
(register-branch) additional test case against mock server
231
                test_case.assertEquals(method_name, "register_branch")
232
                test_case.assertEquals(list(method_params),
233
                        ['url', 'name', 'title', 'description', 'email', 'name'])
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
234
                test_case.assertEquals(authenticated, True)
0.4.24 by Martin Pool
(register-branch) additional test case against mock server
235
                return 'result'
236
        service = MockRegistrationService()
237
        rego = BranchRegistrationRequest('url', 'name', 'title',
238
                        'description', 'email', 'name')
239
        result = rego.submit(service)
240
        self.assertEquals(result, 'result')
0.4.25 by Martin Pool
(register-branch) additional test for registration with defaults
241
242
    def test_mock_server_registration_with_defaults(self):
243
        """Send registration to mock server"""
244
        test_case = self
245
        class MockRegistrationService(MockLaunchpadService):
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
246
            def send_request(self, method_name, method_params, authenticated):
0.4.25 by Martin Pool
(register-branch) additional test for registration with defaults
247
                test_case.assertEquals(method_name, "register_branch")
248
                test_case.assertEquals(list(method_params),
249
                        ['http://server/branch', 'branch', '', '', '', ''])
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
250
                test_case.assertEquals(authenticated, True)
0.4.25 by Martin Pool
(register-branch) additional test for registration with defaults
251
                return 'result'
252
        service = MockRegistrationService()
253
        rego = BranchRegistrationRequest('http://server/branch')
254
        result = rego.submit(service)
255
        self.assertEquals(result, 'result')
0.4.26 by Martin Pool
(register-branch) Add test for link_branch_to_bug and fix its parameters
256
257
    def test_mock_bug_branch_link(self):
258
        """Send bug-branch link to mock server"""
259
        test_case = self
260
        class MockService(MockLaunchpadService):
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
261
            def send_request(self, method_name, method_params, authenticated):
0.4.26 by Martin Pool
(register-branch) Add test for link_branch_to_bug and fix its parameters
262
                test_case.assertEquals(method_name, "link_branch_to_bug")
263
                test_case.assertEquals(list(method_params),
264
                        ['http://server/branch', 1234, ''])
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
265
                test_case.assertEquals(authenticated, True)
0.4.26 by Martin Pool
(register-branch) Add test for link_branch_to_bug and fix its parameters
266
                return 'http://launchpad.net/bug/1234'
267
        service = MockService()
268
        rego = BranchBugLinkRequest('http://server/branch', 1234)
269
        result = rego.submit(service)
270
        self.assertEquals(result, 'http://launchpad.net/bug/1234')
2898.4.2 by James Henstridge
Add ResolveLaunchpadURLRequest() class to handle lp: URL resolution.
271
272
    def test_mock_resolve_lp_url(self):
273
        test_case = self
274
        class MockService(MockLaunchpadService):
275
            def send_request(self, method_name, method_params, authenticated):
2898.4.7 by James Henstridge
Fix up tests.
276
                test_case.assertEquals(method_name, "resolve_lp_path")
2898.4.2 by James Henstridge
Add ResolveLaunchpadURLRequest() class to handle lp: URL resolution.
277
                test_case.assertEquals(list(method_params), ['bzr'])
278
                test_case.assertEquals(authenticated, False)
2898.4.4 by James Henstridge
Changes to account for modifications to the XMLRPC API.
279
                return dict(urls=[
280
                        'bzr+ssh://bazaar.launchpad.net~bzr/bzr/trunk',
281
                        'sftp://bazaar.launchpad.net~bzr/bzr/trunk',
282
                        'bzr+http://bazaar.launchpad.net~bzr/bzr/trunk',
283
                        'http://bazaar.launchpad.net~bzr/bzr/trunk'])
2898.4.2 by James Henstridge
Add ResolveLaunchpadURLRequest() class to handle lp: URL resolution.
284
        service = MockService()
2898.4.3 by James Henstridge
Make launchpad_transport_indirect() use XMLRPC to resolve the lp: URL.
285
        resolve = ResolveLaunchpadPathRequest('bzr')
2898.4.2 by James Henstridge
Add ResolveLaunchpadURLRequest() class to handle lp: URL resolution.
286
        result = resolve.submit(service)
2898.4.4 by James Henstridge
Changes to account for modifications to the XMLRPC API.
287
        self.assertTrue('urls' in result)
288
        self.assertEquals(result['urls'], [
289
                'bzr+ssh://bazaar.launchpad.net~bzr/bzr/trunk',
290
                'sftp://bazaar.launchpad.net~bzr/bzr/trunk',
291
                'bzr+http://bazaar.launchpad.net~bzr/bzr/trunk',
292
                'http://bazaar.launchpad.net~bzr/bzr/trunk'])
2978.5.2 by John Arbash Meinel
merge bzr.dev 2991
293
2978.5.1 by John Arbash Meinel
Fix bug #162494, 'bzr register-branch' needs proper auth handling.
294
295
class TestGatherUserCredentials(tests.TestCaseInTempDir):
296
297
    def setUp(self):
298
        super(TestGatherUserCredentials, self).setUp()
299
        # make sure we have a reproducible standard environment
300
        self._captureVar('BZR_LP_XMLRPC_URL', None)
301
302
    def test_gather_user_credentials_has_password(self):
303
        service = LaunchpadService()
304
        service.registrant_password = 'mypassword'
305
        # This should be a basic no-op, since we already have the password
306
        service.gather_user_credentials()
307
        self.assertEqual('mypassword', service.registrant_password)
308
309
    def test_gather_user_credentials_from_auth_conf(self):
310
        auth_path = config.authentication_config_filename()
311
        service = LaunchpadService()
312
        g_conf = config.GlobalConfig()
313
        g_conf.set_user_option('email', 'Test User <test@user.com>')
314
        f = open(auth_path, 'wb')
315
        try:
316
            scheme, hostinfo = urlparse.urlsplit(service.service_url)[:2]
317
            f.write('[section]\n'
318
                    'scheme=%s\n'
319
                    'host=%s\n'
320
                    'user=test@user.com\n'
321
                    'password=testpass\n'
322
                    % (scheme, hostinfo))
323
        finally:
324
            f.close()
325
        self.assertIs(None, service.registrant_password)
326
        service.gather_user_credentials()
327
        self.assertEqual('test@user.com', service.registrant_email)
328
        self.assertEqual('testpass', service.registrant_password)
329
330
    def test_gather_user_credentials_prompts(self):
331
        service = LaunchpadService()
332
        self.assertIs(None, service.registrant_password)
333
        g_conf = config.GlobalConfig()
334
        g_conf.set_user_option('email', 'Test User <test@user.com>')
335
        stdout = tests.StringIOWrapper()
336
        ui.ui_factory = tests.TestUIFactory(stdin='userpass\n',
337
                                            stdout=stdout)
338
        self.assertIs(None, service.registrant_password)
339
        service.gather_user_credentials()
340
        self.assertEqual('test@user.com', service.registrant_email)
341
        self.assertEqual('userpass', service.registrant_password)
342
        self.assertContainsRe(stdout.getvalue(),
343
                             'launchpad.net password for test@user\\.com')
344