/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
    )
0.4.13 by Martin Pool
Update xmlrpc api to pass product name as a parameter.
29
from bzrlib.tests import TestCase, 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']
95
            assert len(auth_hdrs) == 1
96
            authinfo = auth_hdrs[0]
97
            expected_auth = 'testuser@launchpad.net:testpassword'
98
            test.assertEquals(authinfo,
99
                    'Basic ' + base64.encodestring(expected_auth).strip())
100
        else:
101
            assert not http_headers
0.4.8 by Martin Pool
More instrumentation of xmlrpc requests
102
        return InstrumentedXMLRPCConnection(test)
0.4.7 by Martin Pool
Start making provision to test using a mock xmlrpc transport.
103
104
    def send_request(self, connection, handler_path, request_body):
105
        test = self.testcase
106
        self.got_request = True
107
108
    def send_host(self, conn, host):
109
        pass
110
111
    def send_user_agent(self, conn):
112
        # TODO: send special user agent string, including bzrlib version
113
        # number
114
        pass
115
116
    def send_content(self, conn, request_body):
117
        unpacked, method = xmlrpclib.loads(request_body)
0.4.10 by Martin Pool
Move test-specific values out of InstrumentedXMLRPCTransport
118
        assert None not in unpacked, \
119
                "xmlrpc result %r shouldn't contain None" % (unpacked,)
120
        self.sent_params = unpacked
0.4.7 by Martin Pool
Start making provision to test using a mock xmlrpc transport.
121
122
0.4.22 by Martin Pool
(register-branch) Update tests to be in-process calls to a mock server.
123
class MockLaunchpadService(LaunchpadService):
124
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
125
    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.
126
        """Stash away the method details rather than sending them to a real server"""
127
        self.called_method_name = method_name
128
        self.called_method_params = method_params
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
129
        self.called_authenticated = authenticated
0.4.22 by Martin Pool
(register-branch) Update tests to be in-process calls to a mock server.
130
131
0.4.1 by Martin Pool
Start lp-register command
132
class TestBranchRegistration(TestCase):
0.4.4 by Martin Pool
Start forming xmlrpc requests
133
    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.
134
    SAMPLE_OWNER = 'jhacker@foo.com'
135
    SAMPLE_BRANCH_ID = 'bzr.dev'
0.4.4 by Martin Pool
Start forming xmlrpc requests
136
0.4.23 by Martin Pool
(register-branch) fix ordering of parameters and restore transport-level test.
137
    def setUp(self):
138
        super(TestBranchRegistration, self).setUp()
139
        # 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.
140
        self._captureVar('BZR_LP_XMLRPC_URL', None)
0.4.23 by Martin Pool
(register-branch) fix ordering of parameters and restore transport-level test.
141
0.4.22 by Martin Pool
(register-branch) Update tests to be in-process calls to a mock server.
142
    def test_register_help(self):
143
        """register-branch accepts --help"""
2581.1.4 by Martin Pool
fixup run_bzr syntax in launchpad plugin
144
        out, err = self.run_bzr(['register-branch', '--help'])
0.4.2 by Martin Pool
Rename command to 'register-branch'
145
        self.assertContainsRe(out, r'Register a branch')
146
0.4.22 by Martin Pool
(register-branch) Update tests to be in-process calls to a mock server.
147
    def test_register_no_url(self):
148
        """register-branch command requires parameters"""
0.4.3 by Martin Pool
More command line processing
149
        self.run_bzr('register-branch', retcode=3)
150
1668.1.12 by Martin Pool
(launchpad plugin) Improved --dry-run that uses a dummy xmlrpc service.
151
    def test_register_dry_run(self):
2581.1.4 by Martin Pool
fixup run_bzr syntax in launchpad plugin
152
        out, err = self.run_bzr(['register-branch',
1668.1.12 by Martin Pool
(launchpad plugin) Improved --dry-run that uses a dummy xmlrpc service.
153
                                'http://test-server.com/bzr/branch',
2581.1.4 by Martin Pool
fixup run_bzr syntax in launchpad plugin
154
                                '--dry-run'])
1668.1.12 by Martin Pool
(launchpad plugin) Improved --dry-run that uses a dummy xmlrpc service.
155
        self.assertEquals(out, 'Branch registered.\n')
0.4.4 by Martin Pool
Start forming xmlrpc requests
156
0.4.23 by Martin Pool
(register-branch) fix ordering of parameters and restore transport-level test.
157
    def test_onto_transport(self):
0.4.7 by Martin Pool
Start making provision to test using a mock xmlrpc transport.
158
        """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.
159
        # 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.
160
        transport = InstrumentedXMLRPCTransport(self, expect_auth=True)
0.4.30 by Martin Pool
Fix wierd syntax errors in test
161
        service = LaunchpadService(transport)
0.4.23 by Martin Pool
(register-branch) fix ordering of parameters and restore transport-level test.
162
        service.registrant_email = 'testuser@launchpad.net'
163
        service.registrant_password = 'testpassword'
0.4.7 by Martin Pool
Start making provision to test using a mock xmlrpc transport.
164
        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.
165
                'branch-id',
166
                'my test branch',
167
                'description',
168
                'author@launchpad.net',
169
                'product')
0.4.20 by Bjorn Tillenius
try to fix the tests.
170
        rego.submit(service)
0.4.10 by Martin Pool
Move test-specific values out of InstrumentedXMLRPCTransport
171
        self.assertEquals(transport.connected_host, 'xmlrpc.launchpad.net')
0.4.14 by Martin Pool
Update xmlrpc api
172
        self.assertEquals(len(transport.sent_params), 6)
0.4.11 by Martin Pool
Check the correct params are seen by the server
173
        self.assertEquals(transport.sent_params,
0.4.23 by Martin Pool
(register-branch) fix ordering of parameters and restore transport-level test.
174
                ('http://test-server.com/bzr/branch',  # branch_url
175
                 'branch-id',                          # branch_name
176
                 'my test branch',                     # branch_title
177
                 'description',
178
                 'author@launchpad.net',
179
                 'product'))
0.4.8 by Martin Pool
More instrumentation of xmlrpc requests
180
        self.assertTrue(transport.got_request)
0.4.13 by Martin Pool
Update xmlrpc api to pass product name as a parameter.
181
2898.4.2 by James Henstridge
Add ResolveLaunchpadURLRequest() class to handle lp: URL resolution.
182
    def test_onto_transport_unauthenticated(self):
183
        """Test how an unauthenticated request is transmitted across a mock Transport"""
184
        transport = InstrumentedXMLRPCTransport(self, expect_auth=False)
185
        service = LaunchpadService(transport)
2898.4.3 by James Henstridge
Make launchpad_transport_indirect() use XMLRPC to resolve the lp: URL.
186
        resolve = ResolveLaunchpadPathRequest('bzr')
2898.4.2 by James Henstridge
Add ResolveLaunchpadURLRequest() class to handle lp: URL resolution.
187
        resolve.submit(service)
188
        self.assertEquals(transport.connected_host, 'xmlrpc.launchpad.net')
189
        self.assertEquals(len(transport.sent_params), 1)
190
        self.assertEquals(transport.sent_params, ('bzr', ))
191
        self.assertTrue(transport.got_request)
192
0.4.22 by Martin Pool
(register-branch) Update tests to be in-process calls to a mock server.
193
    def test_subclass_request(self):
194
        """Define a new type of xmlrpc request"""
195
        class DummyRequest(BaseRequest):
196
            _methodname = 'dummy_request'
197
            def _request_params(self):
198
                return (42,)
199
200
        service = MockLaunchpadService()
201
        service.registrant_email = 'test@launchpad.net'
202
        service.registrant_password = ''
203
        request = DummyRequest()
204
        request.submit(service)
205
        self.assertEquals(service.called_method_name, 'dummy_request')
206
        self.assertEquals(service.called_method_params, (42,))
207
0.4.24 by Martin Pool
(register-branch) additional test case against mock server
208
    def test_mock_server_registration(self):
209
        """Send registration to mock server"""
210
        test_case = self
211
        class MockRegistrationService(MockLaunchpadService):
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
212
            def send_request(self, method_name, method_params, authenticated):
0.4.24 by Martin Pool
(register-branch) additional test case against mock server
213
                test_case.assertEquals(method_name, "register_branch")
214
                test_case.assertEquals(list(method_params),
215
                        ['url', 'name', 'title', 'description', 'email', 'name'])
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
216
                test_case.assertEquals(authenticated, True)
0.4.24 by Martin Pool
(register-branch) additional test case against mock server
217
                return 'result'
218
        service = MockRegistrationService()
219
        rego = BranchRegistrationRequest('url', 'name', 'title',
220
                        'description', 'email', 'name')
221
        result = rego.submit(service)
222
        self.assertEquals(result, 'result')
0.4.25 by Martin Pool
(register-branch) additional test for registration with defaults
223
224
    def test_mock_server_registration_with_defaults(self):
225
        """Send registration to mock server"""
226
        test_case = self
227
        class MockRegistrationService(MockLaunchpadService):
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
228
            def send_request(self, method_name, method_params, authenticated):
0.4.25 by Martin Pool
(register-branch) additional test for registration with defaults
229
                test_case.assertEquals(method_name, "register_branch")
230
                test_case.assertEquals(list(method_params),
231
                        ['http://server/branch', 'branch', '', '', '', ''])
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
232
                test_case.assertEquals(authenticated, True)
0.4.25 by Martin Pool
(register-branch) additional test for registration with defaults
233
                return 'result'
234
        service = MockRegistrationService()
235
        rego = BranchRegistrationRequest('http://server/branch')
236
        result = rego.submit(service)
237
        self.assertEquals(result, 'result')
0.4.26 by Martin Pool
(register-branch) Add test for link_branch_to_bug and fix its parameters
238
239
    def test_mock_bug_branch_link(self):
240
        """Send bug-branch link to mock server"""
241
        test_case = self
242
        class MockService(MockLaunchpadService):
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
243
            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
244
                test_case.assertEquals(method_name, "link_branch_to_bug")
245
                test_case.assertEquals(list(method_params),
246
                        ['http://server/branch', 1234, ''])
2898.4.1 by James Henstridge
Make it possible to make unauthenticated XML-RPC requests.
247
                test_case.assertEquals(authenticated, True)
0.4.26 by Martin Pool
(register-branch) Add test for link_branch_to_bug and fix its parameters
248
                return 'http://launchpad.net/bug/1234'
249
        service = MockService()
250
        rego = BranchBugLinkRequest('http://server/branch', 1234)
251
        result = rego.submit(service)
252
        self.assertEquals(result, 'http://launchpad.net/bug/1234')
2898.4.2 by James Henstridge
Add ResolveLaunchpadURLRequest() class to handle lp: URL resolution.
253
254
    def test_mock_resolve_lp_url(self):
255
        test_case = self
256
        class MockService(MockLaunchpadService):
257
            def send_request(self, method_name, method_params, authenticated):
2898.4.7 by James Henstridge
Fix up tests.
258
                test_case.assertEquals(method_name, "resolve_lp_path")
2898.4.2 by James Henstridge
Add ResolveLaunchpadURLRequest() class to handle lp: URL resolution.
259
                test_case.assertEquals(list(method_params), ['bzr'])
260
                test_case.assertEquals(authenticated, False)
2898.4.4 by James Henstridge
Changes to account for modifications to the XMLRPC API.
261
                return dict(urls=[
262
                        'bzr+ssh://bazaar.launchpad.net~bzr/bzr/trunk',
263
                        'sftp://bazaar.launchpad.net~bzr/bzr/trunk',
264
                        'bzr+http://bazaar.launchpad.net~bzr/bzr/trunk',
265
                        'http://bazaar.launchpad.net~bzr/bzr/trunk'])
2898.4.2 by James Henstridge
Add ResolveLaunchpadURLRequest() class to handle lp: URL resolution.
266
        service = MockService()
2898.4.3 by James Henstridge
Make launchpad_transport_indirect() use XMLRPC to resolve the lp: URL.
267
        resolve = ResolveLaunchpadPathRequest('bzr')
2898.4.2 by James Henstridge
Add ResolveLaunchpadURLRequest() class to handle lp: URL resolution.
268
        result = resolve.submit(service)
2898.4.4 by James Henstridge
Changes to account for modifications to the XMLRPC API.
269
        self.assertTrue('urls' in result)
270
        self.assertEquals(result['urls'], [
271
                'bzr+ssh://bazaar.launchpad.net~bzr/bzr/trunk',
272
                'sftp://bazaar.launchpad.net~bzr/bzr/trunk',
273
                'bzr+http://bazaar.launchpad.net~bzr/bzr/trunk',
274
                'http://bazaar.launchpad.net~bzr/bzr/trunk'])
2978.5.2 by John Arbash Meinel
merge bzr.dev 2991
275
2978.5.1 by John Arbash Meinel
Fix bug #162494, 'bzr register-branch' needs proper auth handling.
276
277
class TestGatherUserCredentials(tests.TestCaseInTempDir):
278
279
    def setUp(self):
280
        super(TestGatherUserCredentials, self).setUp()
281
        # make sure we have a reproducible standard environment
282
        self._captureVar('BZR_LP_XMLRPC_URL', None)
283
284
    def test_gather_user_credentials_has_password(self):
285
        service = LaunchpadService()
286
        service.registrant_password = 'mypassword'
287
        # This should be a basic no-op, since we already have the password
288
        service.gather_user_credentials()
289
        self.assertEqual('mypassword', service.registrant_password)
290
291
    def test_gather_user_credentials_from_auth_conf(self):
292
        auth_path = config.authentication_config_filename()
293
        service = LaunchpadService()
294
        g_conf = config.GlobalConfig()
295
        g_conf.set_user_option('email', 'Test User <test@user.com>')
296
        f = open(auth_path, 'wb')
297
        try:
298
            scheme, hostinfo = urlparse.urlsplit(service.service_url)[:2]
299
            f.write('[section]\n'
300
                    'scheme=%s\n'
301
                    'host=%s\n'
302
                    'user=test@user.com\n'
303
                    'password=testpass\n'
304
                    % (scheme, hostinfo))
305
        finally:
306
            f.close()
307
        self.assertIs(None, service.registrant_password)
308
        service.gather_user_credentials()
309
        self.assertEqual('test@user.com', service.registrant_email)
310
        self.assertEqual('testpass', service.registrant_password)
311
312
    def test_gather_user_credentials_prompts(self):
313
        service = LaunchpadService()
314
        self.assertIs(None, service.registrant_password)
315
        g_conf = config.GlobalConfig()
316
        g_conf.set_user_option('email', 'Test User <test@user.com>')
317
        stdout = tests.StringIOWrapper()
318
        ui.ui_factory = tests.TestUIFactory(stdin='userpass\n',
319
                                            stdout=stdout)
320
        self.assertIs(None, service.registrant_password)
321
        service.gather_user_credentials()
322
        self.assertEqual('test@user.com', service.registrant_email)
323
        self.assertEqual('userpass', service.registrant_password)
324
        self.assertContainsRe(stdout.getvalue(),
325
                             'launchpad.net password for test@user\\.com')
326