~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_http.py

  • Committer: Jelmer Vernooij
  • Date: 2010-04-30 11:03:59 UTC
  • mto: This revision was merged to the branch mainline in revision 5197.
  • Revision ID: jelmer@samba.org-20100430110359-ow3e3grh7sxy93pa
Remove more unused imports.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
 
1
# Copyright (C) 2005-2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
23
23
# TODO: Should be renamed to bzrlib.transport.http.tests?
24
24
# TODO: What about renaming to bzrlib.tests.transport.http ?
25
25
 
 
26
from cStringIO import StringIO
26
27
import httplib
 
28
import os
 
29
import select
27
30
import SimpleHTTPServer
28
31
import socket
29
32
import sys
32
35
import bzrlib
33
36
from bzrlib import (
34
37
    bzrdir,
35
 
    cethread,
36
38
    config,
37
39
    errors,
38
40
    osutils,
40
42
    tests,
41
43
    transport,
42
44
    ui,
 
45
    urlutils,
 
46
    )
 
47
from bzrlib.symbol_versioning import (
 
48
    deprecated_in,
43
49
    )
44
50
from bzrlib.tests import (
45
51
    features,
46
52
    http_server,
47
53
    http_utils,
48
 
    test_server,
49
 
    )
50
 
from bzrlib.tests.scenarios import (
51
 
    load_tests_apply_scenarios,
52
 
    multiply_scenarios,
53
54
    )
54
55
from bzrlib.transport import (
55
56
    http,
65
66
    from bzrlib.transport.http._pycurl import PyCurlTransport
66
67
 
67
68
 
68
 
load_tests = load_tests_apply_scenarios
69
 
 
70
 
 
71
 
def vary_by_http_client_implementation():
72
 
    """Test the two libraries we can use, pycurl and urllib."""
 
69
def load_tests(standard_tests, module, loader):
 
70
    """Multiply tests for http clients and protocol versions."""
 
71
    result = loader.suiteClass()
 
72
 
 
73
    # one for each transport implementation
 
74
    t_tests, remaining_tests = tests.split_suite_by_condition(
 
75
        standard_tests, tests.condition_isinstance((
 
76
                TestHttpTransportRegistration,
 
77
                TestHttpTransportUrls,
 
78
                Test_redirected_to,
 
79
                )))
73
80
    transport_scenarios = [
74
81
        ('urllib', dict(_transport=_urllib.HttpTransport_urllib,
75
82
                        _server=http_server.HttpServer_urllib,
76
 
                        _url_protocol='http+urllib',)),
 
83
                        _qualified_prefix='http+urllib',)),
77
84
        ]
78
85
    if features.pycurl.available():
79
86
        transport_scenarios.append(
80
87
            ('pycurl', dict(_transport=PyCurlTransport,
81
88
                            _server=http_server.HttpServer_PyCurl,
82
 
                            _url_protocol='http+pycurl',)))
83
 
    return transport_scenarios
84
 
 
85
 
 
86
 
def vary_by_http_protocol_version():
87
 
    """Test on http/1.0 and 1.1"""
88
 
    return [
89
 
        ('HTTP/1.0',  dict(_protocol_version='HTTP/1.0')),
90
 
        ('HTTP/1.1',  dict(_protocol_version='HTTP/1.1')),
91
 
        ]
92
 
 
93
 
 
94
 
def vary_by_http_proxy_auth_scheme():
95
 
    return [
 
89
                            _qualified_prefix='http+pycurl',)))
 
90
    tests.multiply_tests(t_tests, transport_scenarios, result)
 
91
 
 
92
    # each implementation tested with each HTTP version
 
93
    tp_tests, remaining_tests = tests.split_suite_by_condition(
 
94
        remaining_tests, tests.condition_isinstance((
 
95
                SmartHTTPTunnellingTest,
 
96
                TestDoCatchRedirections,
 
97
                TestHTTPConnections,
 
98
                TestHTTPRedirections,
 
99
                TestHTTPSilentRedirections,
 
100
                TestLimitedRangeRequestServer,
 
101
                TestPost,
 
102
                TestProxyHttpServer,
 
103
                TestRanges,
 
104
                TestSpecificRequestHandler,
 
105
                )))
 
106
    protocol_scenarios = [
 
107
            ('HTTP/1.0',  dict(_protocol_version='HTTP/1.0')),
 
108
            ('HTTP/1.1',  dict(_protocol_version='HTTP/1.1')),
 
109
            ]
 
110
    tp_scenarios = tests.multiply_scenarios(transport_scenarios,
 
111
                                            protocol_scenarios)
 
112
    tests.multiply_tests(tp_tests, tp_scenarios, result)
 
113
 
 
114
    # proxy auth: each auth scheme on all http versions on all implementations.
 
115
    tppa_tests, remaining_tests = tests.split_suite_by_condition(
 
116
        remaining_tests, tests.condition_isinstance((
 
117
                TestProxyAuth,
 
118
                )))
 
119
    proxy_auth_scheme_scenarios = [
96
120
        ('basic', dict(_auth_server=http_utils.ProxyBasicAuthServer)),
97
121
        ('digest', dict(_auth_server=http_utils.ProxyDigestAuthServer)),
98
122
        ('basicdigest',
99
 
            dict(_auth_server=http_utils.ProxyBasicAndDigestAuthServer)),
 
123
         dict(_auth_server=http_utils.ProxyBasicAndDigestAuthServer)),
100
124
        ]
101
 
 
102
 
 
103
 
def vary_by_http_auth_scheme():
104
 
    return [
 
125
    tppa_scenarios = tests.multiply_scenarios(tp_scenarios,
 
126
                                              proxy_auth_scheme_scenarios)
 
127
    tests.multiply_tests(tppa_tests, tppa_scenarios, result)
 
128
 
 
129
    # auth: each auth scheme on all http versions on all implementations.
 
130
    tpa_tests, remaining_tests = tests.split_suite_by_condition(
 
131
        remaining_tests, tests.condition_isinstance((
 
132
                TestAuth,
 
133
                )))
 
134
    auth_scheme_scenarios = [
105
135
        ('basic', dict(_auth_server=http_utils.HTTPBasicAuthServer)),
106
136
        ('digest', dict(_auth_server=http_utils.HTTPDigestAuthServer)),
107
137
        ('basicdigest',
108
 
            dict(_auth_server=http_utils.HTTPBasicAndDigestAuthServer)),
 
138
         dict(_auth_server=http_utils.HTTPBasicAndDigestAuthServer)),
109
139
        ]
110
 
 
111
 
 
112
 
def vary_by_http_activity():
 
140
    tpa_scenarios = tests.multiply_scenarios(tp_scenarios,
 
141
                                             auth_scheme_scenarios)
 
142
    tests.multiply_tests(tpa_tests, tpa_scenarios, result)
 
143
 
 
144
    # activity: on all http[s] versions on all implementations
 
145
    tpact_tests, remaining_tests = tests.split_suite_by_condition(
 
146
        remaining_tests, tests.condition_isinstance((
 
147
                TestActivity,
 
148
                )))
113
149
    activity_scenarios = [
114
150
        ('urllib,http', dict(_activity_server=ActivityHTTPServer,
115
 
                            _transport=_urllib.HttpTransport_urllib,)),
 
151
                             _transport=_urllib.HttpTransport_urllib,)),
116
152
        ]
117
153
    if tests.HTTPSServerFeature.available():
118
154
        activity_scenarios.append(
119
155
            ('urllib,https', dict(_activity_server=ActivityHTTPSServer,
120
 
                                _transport=_urllib.HttpTransport_urllib,)),)
 
156
                                  _transport=_urllib.HttpTransport_urllib,)),)
121
157
    if features.pycurl.available():
122
158
        activity_scenarios.append(
123
159
            ('pycurl,http', dict(_activity_server=ActivityHTTPServer,
124
 
                                _transport=PyCurlTransport,)),)
 
160
                                 _transport=PyCurlTransport,)),)
125
161
        if tests.HTTPSServerFeature.available():
126
162
            from bzrlib.tests import (
127
163
                ssl_certs,
139
175
 
140
176
            activity_scenarios.append(
141
177
                ('pycurl,https', dict(_activity_server=ActivityHTTPSServer,
142
 
                                    _transport=HTTPS_pycurl_transport,)),)
143
 
    return activity_scenarios
 
178
                                      _transport=HTTPS_pycurl_transport,)),)
 
179
 
 
180
    tpact_scenarios = tests.multiply_scenarios(activity_scenarios,
 
181
                                               protocol_scenarios)
 
182
    tests.multiply_tests(tpact_tests, tpact_scenarios, result)
 
183
 
 
184
    # No parametrization for the remaining tests
 
185
    result.addTests(remaining_tests)
 
186
 
 
187
    return result
144
188
 
145
189
 
146
190
class FakeManager(object):
179
223
        self._sock.bind(('127.0.0.1', 0))
180
224
        self.host, self.port = self._sock.getsockname()
181
225
        self._ready = threading.Event()
182
 
        self._thread = test_server.TestThread(
183
 
            sync_event=self._ready, target=self._accept_read_and_reply)
 
226
        self._thread = threading.Thread(target=self._accept_read_and_reply)
 
227
        self._thread.setDaemon(True)
184
228
        self._thread.start()
185
 
        if 'threads' in tests.selftest_debug_flags:
186
 
            sys.stderr.write('Thread started: %s\n' % (self._thread.ident,))
187
 
        self._ready.wait()
 
229
        self._ready.wait(5)
188
230
 
189
231
    def _accept_read_and_reply(self):
190
232
        self._sock.listen(1)
191
233
        self._ready.set()
192
 
        conn, address = self._sock.accept()
193
 
        if self._expect_body_tail is not None:
 
234
        self._sock.settimeout(5)
 
235
        try:
 
236
            conn, address = self._sock.accept()
 
237
            # On win32, the accepted connection will be non-blocking to start
 
238
            # with because we're using settimeout.
 
239
            conn.setblocking(True)
194
240
            while not self.received_bytes.endswith(self._expect_body_tail):
195
241
                self.received_bytes += conn.recv(4096)
196
242
            conn.sendall('HTTP/1.1 200 OK\r\n')
197
 
        try:
 
243
        except socket.timeout:
 
244
            # Make sure the client isn't stuck waiting for us to e.g. accept.
198
245
            self._sock.close()
199
246
        except socket.error:
200
247
            # The client may have already closed the socket.
202
249
 
203
250
    def stop_server(self):
204
251
        try:
205
 
            # Issue a fake connection to wake up the server and allow it to
206
 
            # finish quickly
207
 
            fake_conn = osutils.connect_socket((self.host, self.port))
208
 
            fake_conn.close()
 
252
            self._sock.close()
209
253
        except socket.error:
210
254
            # We might have already closed it.  We don't care.
211
255
            pass
212
256
        self.host = None
213
257
        self.port = None
214
 
        self._thread.join()
215
 
        if 'threads' in tests.selftest_debug_flags:
216
 
            sys.stderr.write('Thread  joined: %s\n' % (self._thread.ident,))
217
258
 
218
259
 
219
260
class TestAuthHeader(tests.TestCase):
255
296
        self.assertEqual('realm="Thou should not pass"', remainder)
256
297
 
257
298
 
258
 
class TestHTTPRangeParsing(tests.TestCase):
259
 
 
260
 
    def setUp(self):
261
 
        super(TestHTTPRangeParsing, self).setUp()
262
 
        # We focus on range  parsing here and ignore everything else
263
 
        class RequestHandler(http_server.TestingHTTPRequestHandler):
264
 
            def setup(self): pass
265
 
            def handle(self): pass
266
 
            def finish(self): pass
267
 
 
268
 
        self.req_handler = RequestHandler(None, None, None)
269
 
 
270
 
    def assertRanges(self, ranges, header, file_size):
271
 
        self.assertEquals(ranges,
272
 
                          self.req_handler._parse_ranges(header, file_size))
273
 
 
274
 
    def test_simple_range(self):
275
 
        self.assertRanges([(0,2)], 'bytes=0-2', 12)
276
 
 
277
 
    def test_tail(self):
278
 
        self.assertRanges([(8, 11)], 'bytes=-4', 12)
279
 
 
280
 
    def test_tail_bigger_than_file(self):
281
 
        self.assertRanges([(0, 11)], 'bytes=-99', 12)
282
 
 
283
 
    def test_range_without_end(self):
284
 
        self.assertRanges([(4, 11)], 'bytes=4-', 12)
285
 
 
286
 
    def test_invalid_ranges(self):
287
 
        self.assertRanges(None, 'bytes=12-22', 12)
288
 
        self.assertRanges(None, 'bytes=1-3,12-22', 12)
289
 
        self.assertRanges(None, 'bytes=-', 12)
290
 
 
291
 
 
292
299
class TestHTTPServer(tests.TestCase):
293
300
    """Test the HTTP servers implementations."""
294
301
 
297
304
 
298
305
            protocol_version = 'HTTP/0.1'
299
306
 
300
 
        self.assertRaises(httplib.UnknownProtocol,
301
 
                          http_server.HttpServer, BogusRequestHandler)
 
307
        server = http_server.HttpServer(BogusRequestHandler)
 
308
        try:
 
309
            self.assertRaises(httplib.UnknownProtocol, server.start_server)
 
310
        except:
 
311
            server.stop_server()
 
312
            self.fail('HTTP Server creation did not raise UnknownProtocol')
302
313
 
303
314
    def test_force_invalid_protocol(self):
304
 
        self.assertRaises(httplib.UnknownProtocol,
305
 
                          http_server.HttpServer, protocol_version='HTTP/0.1')
 
315
        server = http_server.HttpServer(protocol_version='HTTP/0.1')
 
316
        try:
 
317
            self.assertRaises(httplib.UnknownProtocol, server.start_server)
 
318
        except:
 
319
            server.stop_server()
 
320
            self.fail('HTTP Server creation did not raise UnknownProtocol')
306
321
 
307
322
    def test_server_start_and_stop(self):
308
323
        server = http_server.HttpServer()
309
 
        self.addCleanup(server.stop_server)
310
324
        server.start_server()
311
 
        self.assertTrue(server.server is not None)
312
 
        self.assertTrue(server.server.serving is not None)
313
 
        self.assertTrue(server.server.serving)
 
325
        try:
 
326
            self.assertTrue(server._http_running)
 
327
        finally:
 
328
            server.stop_server()
 
329
        self.assertFalse(server._http_running)
314
330
 
315
331
    def test_create_http_server_one_zero(self):
316
332
        class RequestHandlerOneZero(http_server.TestingHTTPRequestHandler):
319
335
 
320
336
        server = http_server.HttpServer(RequestHandlerOneZero)
321
337
        self.start_server(server)
322
 
        self.assertIsInstance(server.server, http_server.TestingHTTPServer)
 
338
        self.assertIsInstance(server._httpd, http_server.TestingHTTPServer)
323
339
 
324
340
    def test_create_http_server_one_one(self):
325
341
        class RequestHandlerOneOne(http_server.TestingHTTPRequestHandler):
328
344
 
329
345
        server = http_server.HttpServer(RequestHandlerOneOne)
330
346
        self.start_server(server)
331
 
        self.assertIsInstance(server.server,
 
347
        self.assertIsInstance(server._httpd,
332
348
                              http_server.TestingThreadingHTTPServer)
333
349
 
334
350
    def test_create_http_server_force_one_one(self):
339
355
        server = http_server.HttpServer(RequestHandlerOneZero,
340
356
                                        protocol_version='HTTP/1.1')
341
357
        self.start_server(server)
342
 
        self.assertIsInstance(server.server,
 
358
        self.assertIsInstance(server._httpd,
343
359
                              http_server.TestingThreadingHTTPServer)
344
360
 
345
361
    def test_create_http_server_force_one_zero(self):
350
366
        server = http_server.HttpServer(RequestHandlerOneOne,
351
367
                                        protocol_version='HTTP/1.0')
352
368
        self.start_server(server)
353
 
        self.assertIsInstance(server.server,
 
369
        self.assertIsInstance(server._httpd,
354
370
                              http_server.TestingHTTPServer)
355
371
 
356
372
 
385
401
class TestHttpTransportUrls(tests.TestCase):
386
402
    """Test the http urls."""
387
403
 
388
 
    scenarios = vary_by_http_client_implementation()
389
 
 
390
404
    def test_abs_url(self):
391
405
        """Construction of absolute http URLs"""
392
 
        t = self._transport('http://example.com/bzr/bzr.dev/')
 
406
        t = self._transport('http://bazaar-vcs.org/bzr/bzr.dev/')
393
407
        eq = self.assertEqualDiff
394
 
        eq(t.abspath('.'), 'http://example.com/bzr/bzr.dev')
395
 
        eq(t.abspath('foo/bar'), 'http://example.com/bzr/bzr.dev/foo/bar')
396
 
        eq(t.abspath('.bzr'), 'http://example.com/bzr/bzr.dev/.bzr')
 
408
        eq(t.abspath('.'), 'http://bazaar-vcs.org/bzr/bzr.dev')
 
409
        eq(t.abspath('foo/bar'), 'http://bazaar-vcs.org/bzr/bzr.dev/foo/bar')
 
410
        eq(t.abspath('.bzr'), 'http://bazaar-vcs.org/bzr/bzr.dev/.bzr')
397
411
        eq(t.abspath('.bzr/1//2/./3'),
398
 
           'http://example.com/bzr/bzr.dev/.bzr/1/2/3')
 
412
           'http://bazaar-vcs.org/bzr/bzr.dev/.bzr/1/2/3')
399
413
 
400
414
    def test_invalid_http_urls(self):
401
415
        """Trap invalid construction of urls"""
402
 
        self._transport('http://example.com/bzr/bzr.dev/')
 
416
        t = self._transport('http://bazaar-vcs.org/bzr/bzr.dev/')
403
417
        self.assertRaises(errors.InvalidURL,
404
418
                          self._transport,
405
 
                          'http://http://example.com/bzr/bzr.dev/')
 
419
                          'http://http://bazaar-vcs.org/bzr/bzr.dev/')
406
420
 
407
421
    def test_http_root_urls(self):
408
422
        """Construction of URLs from server root"""
409
 
        t = self._transport('http://example.com/')
 
423
        t = self._transport('http://bzr.ozlabs.org/')
410
424
        eq = self.assertEqualDiff
411
425
        eq(t.abspath('.bzr/tree-version'),
412
 
           'http://example.com/.bzr/tree-version')
 
426
           'http://bzr.ozlabs.org/.bzr/tree-version')
413
427
 
414
428
    def test_http_impl_urls(self):
415
429
        """There are servers which ask for particular clients to connect"""
417
431
        server.start_server()
418
432
        try:
419
433
            url = server.get_url()
420
 
            self.assertTrue(url.startswith('%s://' % self._url_protocol))
 
434
            self.assertTrue(url.startswith('%s://' % self._qualified_prefix))
421
435
        finally:
422
436
            server.stop_server()
423
437
 
461
475
class TestHTTPConnections(http_utils.TestCaseWithWebserver):
462
476
    """Test the http connections."""
463
477
 
464
 
    scenarios = multiply_scenarios(
465
 
        vary_by_http_client_implementation(),
466
 
        vary_by_http_protocol_version(),
467
 
        )
468
 
 
469
478
    def setUp(self):
470
479
        http_utils.TestCaseWithWebserver.setUp(self)
471
480
        self.build_tree(['foo/', 'foo/bar'], line_endings='binary',
473
482
 
474
483
    def test_http_has(self):
475
484
        server = self.get_readonly_server()
476
 
        t = self.get_readonly_transport()
 
485
        t = self._transport(server.get_url())
477
486
        self.assertEqual(t.has('foo/bar'), True)
478
487
        self.assertEqual(len(server.logs), 1)
479
488
        self.assertContainsRe(server.logs[0],
481
490
 
482
491
    def test_http_has_not_found(self):
483
492
        server = self.get_readonly_server()
484
 
        t = self.get_readonly_transport()
 
493
        t = self._transport(server.get_url())
485
494
        self.assertEqual(t.has('not-found'), False)
486
495
        self.assertContainsRe(server.logs[1],
487
496
            r'"HEAD /not-found HTTP/1.." 404 - "-" "bzr/')
488
497
 
489
498
    def test_http_get(self):
490
499
        server = self.get_readonly_server()
491
 
        t = self.get_readonly_transport()
 
500
        t = self._transport(server.get_url())
492
501
        fp = t.get('foo/bar')
493
502
        self.assertEqualDiff(
494
503
            fp.read(),
516
525
class TestHttpTransportRegistration(tests.TestCase):
517
526
    """Test registrations of various http implementations"""
518
527
 
519
 
    scenarios = vary_by_http_client_implementation()
520
 
 
521
528
    def test_http_registered(self):
522
 
        t = transport.get_transport('%s://foo.com/' % self._url_protocol)
 
529
        t = transport.get_transport('%s://foo.com/' % self._qualified_prefix)
523
530
        self.assertIsInstance(t, transport.Transport)
524
531
        self.assertIsInstance(t, self._transport)
525
532
 
526
533
 
527
534
class TestPost(tests.TestCase):
528
535
 
529
 
    scenarios = multiply_scenarios(
530
 
        vary_by_http_client_implementation(),
531
 
        vary_by_http_protocol_version(),
532
 
        )
533
 
 
534
536
    def test_post_body_is_received(self):
535
537
        server = RecordingServer(expect_body_tail='end-of-body',
536
 
                                 scheme=self._url_protocol)
 
538
            scheme=self._qualified_prefix)
537
539
        self.start_server(server)
538
540
        url = server.get_url()
539
 
        # FIXME: needs a cleanup -- vila 20100611
540
 
        http_transport = transport.get_transport(url)
 
541
        http_transport = self._transport(url)
541
542
        code, response = http_transport._post('abc def end-of-body')
542
543
        self.assertTrue(
543
544
            server.received_bytes.startswith('POST /.bzr/smart HTTP/1.'))
544
545
        self.assertTrue('content-length: 19\r' in server.received_bytes.lower())
545
 
        self.assertTrue('content-type: application/octet-stream\r'
546
 
                        in server.received_bytes.lower())
547
546
        # The transport should not be assuming that the server can accept
548
547
        # chunked encoding the first time it connects, because HTTP/1.1, so we
549
548
        # check for the literal string.
585
584
    Daughter classes are expected to override _req_handler_class
586
585
    """
587
586
 
588
 
    scenarios = multiply_scenarios(
589
 
        vary_by_http_client_implementation(),
590
 
        vary_by_http_protocol_version(),
591
 
        )
592
 
 
593
587
    # Provide a useful default
594
588
    _req_handler_class = http_server.TestingHTTPRequestHandler
595
589
 
596
590
    def create_transport_readonly_server(self):
597
 
        server = http_server.HttpServer(self._req_handler_class,
598
 
                                        protocol_version=self._protocol_version)
599
 
        server._url_protocol = self._url_protocol
600
 
        return server
 
591
        return http_server.HttpServer(self._req_handler_class,
 
592
                                      protocol_version=self._protocol_version)
601
593
 
602
594
    def _testing_pycurl(self):
603
595
        # TODO: This is duplicated for lots of the classes in this file
608
600
class WallRequestHandler(http_server.TestingHTTPRequestHandler):
609
601
    """Whatever request comes in, close the connection"""
610
602
 
611
 
    def _handle_one_request(self):
 
603
    def handle_one_request(self):
612
604
        """Handle a single HTTP request, by abruptly closing the connection"""
613
605
        self.close_connection = 1
614
606
 
619
611
    _req_handler_class = WallRequestHandler
620
612
 
621
613
    def test_http_has(self):
622
 
        t = self.get_readonly_transport()
 
614
        server = self.get_readonly_server()
 
615
        t = self._transport(server.get_url())
623
616
        # Unfortunately httplib (see HTTPResponse._read_status
624
617
        # for details) make no distinction between a closed
625
618
        # socket and badly formatted status line, so we can't
631
624
                          t.has, 'foo/bar')
632
625
 
633
626
    def test_http_get(self):
634
 
        t = self.get_readonly_transport()
 
627
        server = self.get_readonly_server()
 
628
        t = self._transport(server.get_url())
635
629
        self.assertRaises((errors.ConnectionError, errors.ConnectionReset,
636
630
                           errors.InvalidHttpResponse),
637
631
                          t.get, 'foo/bar')
654
648
    _req_handler_class = BadStatusRequestHandler
655
649
 
656
650
    def test_http_has(self):
657
 
        t = self.get_readonly_transport()
 
651
        server = self.get_readonly_server()
 
652
        t = self._transport(server.get_url())
658
653
        self.assertRaises(errors.InvalidHttpResponse, t.has, 'foo/bar')
659
654
 
660
655
    def test_http_get(self):
661
 
        t = self.get_readonly_transport()
 
656
        server = self.get_readonly_server()
 
657
        t = self._transport(server.get_url())
662
658
        self.assertRaises(errors.InvalidHttpResponse, t.get, 'foo/bar')
663
659
 
664
660
 
669
665
        """Fakes handling a single HTTP request, returns a bad status"""
670
666
        ignored = http_server.TestingHTTPRequestHandler.parse_request(self)
671
667
        self.wfile.write("Invalid status line\r\n")
672
 
        # If we don't close the connection pycurl will hang. Since this is a
673
 
        # stress test we don't *have* to respect the protocol, but we don't
674
 
        # have to sabotage it too much either.
675
 
        self.close_connection = True
676
668
        return False
677
669
 
678
670
 
684
676
 
685
677
    _req_handler_class = InvalidStatusRequestHandler
686
678
 
 
679
    def test_http_has(self):
 
680
        if self._testing_pycurl() and self._protocol_version == 'HTTP/1.1':
 
681
            raise tests.KnownFailure(
 
682
                'pycurl hangs if the server send back garbage')
 
683
        super(TestInvalidStatusServer, self).test_http_has()
 
684
 
 
685
    def test_http_get(self):
 
686
        if self._testing_pycurl() and self._protocol_version == 'HTTP/1.1':
 
687
            raise tests.KnownFailure(
 
688
                'pycurl hangs if the server send back garbage')
 
689
        super(TestInvalidStatusServer, self).test_http_get()
 
690
 
687
691
 
688
692
class BadProtocolRequestHandler(http_server.TestingHTTPRequestHandler):
689
693
    """Whatever request comes in, returns a bad protocol version"""
711
715
        super(TestBadProtocolServer, self).setUp()
712
716
 
713
717
    def test_http_has(self):
714
 
        t = self.get_readonly_transport()
 
718
        server = self.get_readonly_server()
 
719
        t = self._transport(server.get_url())
715
720
        self.assertRaises(errors.InvalidHttpResponse, t.has, 'foo/bar')
716
721
 
717
722
    def test_http_get(self):
718
 
        t = self.get_readonly_transport()
 
723
        server = self.get_readonly_server()
 
724
        t = self._transport(server.get_url())
719
725
        self.assertRaises(errors.InvalidHttpResponse, t.get, 'foo/bar')
720
726
 
721
727
 
735
741
    _req_handler_class = ForbiddenRequestHandler
736
742
 
737
743
    def test_http_has(self):
738
 
        t = self.get_readonly_transport()
 
744
        server = self.get_readonly_server()
 
745
        t = self._transport(server.get_url())
739
746
        self.assertRaises(errors.TransportError, t.has, 'foo/bar')
740
747
 
741
748
    def test_http_get(self):
742
 
        t = self.get_readonly_transport()
 
749
        server = self.get_readonly_server()
 
750
        t = self._transport(server.get_url())
743
751
        self.assertRaises(errors.TransportError, t.get, 'foo/bar')
744
752
 
745
753
 
784
792
        self.build_tree_contents([('a', '0123456789')],)
785
793
 
786
794
    def test_readv(self):
787
 
        t = self.get_readonly_transport()
 
795
        server = self.get_readonly_server()
 
796
        t = self._transport(server.get_url())
788
797
        l = list(t.readv('a', ((0, 1), (1, 1), (3, 2), (9, 1))))
789
798
        self.assertEqual(l[0], (0, '0'))
790
799
        self.assertEqual(l[1], (1, '1'))
792
801
        self.assertEqual(l[3], (9, '9'))
793
802
 
794
803
    def test_readv_out_of_order(self):
795
 
        t = self.get_readonly_transport()
 
804
        server = self.get_readonly_server()
 
805
        t = self._transport(server.get_url())
796
806
        l = list(t.readv('a', ((1, 1), (9, 1), (0, 1), (3, 2))))
797
807
        self.assertEqual(l[0], (1, '1'))
798
808
        self.assertEqual(l[1], (9, '9'))
800
810
        self.assertEqual(l[3], (3, '34'))
801
811
 
802
812
    def test_readv_invalid_ranges(self):
803
 
        t = self.get_readonly_transport()
 
813
        server = self.get_readonly_server()
 
814
        t = self._transport(server.get_url())
804
815
 
805
816
        # This is intentionally reading off the end of the file
806
817
        # since we are sure that it cannot get there
814
825
 
815
826
    def test_readv_multiple_get_requests(self):
816
827
        server = self.get_readonly_server()
817
 
        t = self.get_readonly_transport()
 
828
        t = self._transport(server.get_url())
818
829
        # force transport to issue multiple requests
819
830
        t._max_readv_combine = 1
820
831
        t._max_get_ranges = 1
828
839
 
829
840
    def test_readv_get_max_size(self):
830
841
        server = self.get_readonly_server()
831
 
        t = self.get_readonly_transport()
 
842
        t = self._transport(server.get_url())
832
843
        # force transport to issue multiple requests by limiting the number of
833
844
        # bytes by request. Note that this apply to coalesced offsets only, a
834
845
        # single range will keep its size even if bigger than the limit.
843
854
 
844
855
    def test_complete_readv_leave_pipe_clean(self):
845
856
        server = self.get_readonly_server()
846
 
        t = self.get_readonly_transport()
 
857
        t = self._transport(server.get_url())
847
858
        # force transport to issue multiple requests
848
859
        t._get_max_size = 2
849
 
        list(t.readv('a', ((0, 1), (1, 1), (2, 4), (6, 4))))
 
860
        l = list(t.readv('a', ((0, 1), (1, 1), (2, 4), (6, 4))))
850
861
        # The server should have issued 3 requests
851
862
        self.assertEqual(3, server.GET_request_nb)
852
863
        self.assertEqual('0123456789', t.get_bytes('a'))
854
865
 
855
866
    def test_incomplete_readv_leave_pipe_clean(self):
856
867
        server = self.get_readonly_server()
857
 
        t = self.get_readonly_transport()
 
868
        t = self._transport(server.get_url())
858
869
        # force transport to issue multiple requests
859
870
        t._get_max_size = 2
860
871
        # Don't collapse readv results into a list so that we leave unread
929
940
    def get_multiple_ranges(self, file, file_size, ranges):
930
941
        self.send_response(206)
931
942
        self.send_header('Accept-Ranges', 'bytes')
932
 
        # XXX: this is strange; the 'random' name below seems undefined and
933
 
        # yet the tests pass -- mbp 2010-10-11 bug 658773
934
943
        boundary = "%d" % random.randint(0,0x7FFFFFFF)
935
944
        self.send_header("Content-Type",
936
945
                         "multipart/byteranges; boundary=%s" % boundary)
998
1007
                return
999
1008
            self.send_range_content(file, start, end - start + 1)
1000
1009
            cur += 1
1001
 
        # Final boundary
 
1010
        # No final boundary
1002
1011
        self.wfile.write(boundary_line)
1003
1012
 
1004
1013
 
1012
1021
 
1013
1022
    def test_readv_with_short_reads(self):
1014
1023
        server = self.get_readonly_server()
1015
 
        t = self.get_readonly_transport()
 
1024
        t = self._transport(server.get_url())
1016
1025
        # Force separate ranges for each offset
1017
1026
        t._bytes_to_read_before_seek = 0
1018
1027
        ireadv = iter(t.readv('a', ((0, 1), (2, 1), (4, 2), (9, 1))))
1033
1042
        # that mode
1034
1043
        self.assertEqual('single', t._range_hint)
1035
1044
 
1036
 
 
1037
1045
class LimitedRangeRequestHandler(http_server.TestingHTTPRequestHandler):
1038
1046
    """Errors out when range specifiers exceed the limit"""
1039
1047
 
1063
1071
class TestLimitedRangeRequestServer(http_utils.TestCaseWithWebserver):
1064
1072
    """Tests readv requests against a server erroring out on too much ranges."""
1065
1073
 
1066
 
    scenarios = multiply_scenarios(
1067
 
        vary_by_http_client_implementation(),
1068
 
        vary_by_http_protocol_version(),
1069
 
        )
1070
 
 
1071
1074
    # Requests with more range specifiers will error out
1072
1075
    range_limit = 3
1073
1076
 
1075
1078
        return LimitedRangeHTTPServer(range_limit=self.range_limit,
1076
1079
                                      protocol_version=self._protocol_version)
1077
1080
 
 
1081
    def get_transport(self):
 
1082
        return self._transport(self.get_readonly_server().get_url())
 
1083
 
1078
1084
    def setUp(self):
1079
1085
        http_utils.TestCaseWithWebserver.setUp(self)
1080
1086
        # We need to manipulate ranges that correspond to real chunks in the
1084
1090
        self.build_tree_contents([('a', content)],)
1085
1091
 
1086
1092
    def test_few_ranges(self):
1087
 
        t = self.get_readonly_transport()
 
1093
        t = self.get_transport()
1088
1094
        l = list(t.readv('a', ((0, 4), (1024, 4), )))
1089
1095
        self.assertEqual(l[0], (0, '0000'))
1090
1096
        self.assertEqual(l[1], (1024, '0001'))
1091
1097
        self.assertEqual(1, self.get_readonly_server().GET_request_nb)
1092
1098
 
1093
1099
    def test_more_ranges(self):
1094
 
        t = self.get_readonly_transport()
 
1100
        t = self.get_transport()
1095
1101
        l = list(t.readv('a', ((0, 4), (1024, 4), (4096, 4), (8192, 4))))
1096
1102
        self.assertEqual(l[0], (0, '0000'))
1097
1103
        self.assertEqual(l[1], (1024, '0001'))
1108
1114
    Only the urllib implementation is tested here.
1109
1115
    """
1110
1116
 
 
1117
    def setUp(self):
 
1118
        tests.TestCase.setUp(self)
 
1119
        self._old_env = {}
 
1120
 
 
1121
    def tearDown(self):
 
1122
        self._restore_env()
 
1123
        tests.TestCase.tearDown(self)
 
1124
 
 
1125
    def _install_env(self, env):
 
1126
        for name, value in env.iteritems():
 
1127
            self._old_env[name] = osutils.set_or_unset_env(name, value)
 
1128
 
 
1129
    def _restore_env(self):
 
1130
        for name, value in self._old_env.iteritems():
 
1131
            osutils.set_or_unset_env(name, value)
 
1132
 
1111
1133
    def _proxied_request(self):
1112
1134
        handler = _urllib2_wrappers.ProxyHandler()
1113
 
        request = _urllib2_wrappers.Request('GET', 'http://baz/buzzle')
 
1135
        request = _urllib2_wrappers.Request('GET','http://baz/buzzle')
1114
1136
        handler.set_proxy(request, 'http')
1115
1137
        return request
1116
1138
 
1117
 
    def assertEvaluateProxyBypass(self, expected, host, no_proxy):
1118
 
        handler = _urllib2_wrappers.ProxyHandler()
1119
 
        self.assertEquals(expected,
1120
 
                          handler.evaluate_proxy_bypass(host, no_proxy))
1121
 
 
1122
1139
    def test_empty_user(self):
1123
 
        self.overrideEnv('http_proxy', 'http://bar.com')
1124
 
        request = self._proxied_request()
1125
 
        self.assertFalse(request.headers.has_key('Proxy-authorization'))
1126
 
 
1127
 
    def test_user_with_at(self):
1128
 
        self.overrideEnv('http_proxy',
1129
 
                         'http://username@domain:password@proxy_host:1234')
 
1140
        self._install_env({'http_proxy': 'http://bar.com'})
1130
1141
        request = self._proxied_request()
1131
1142
        self.assertFalse(request.headers.has_key('Proxy-authorization'))
1132
1143
 
1133
1144
    def test_invalid_proxy(self):
1134
1145
        """A proxy env variable without scheme"""
1135
 
        self.overrideEnv('http_proxy', 'host:1234')
 
1146
        self._install_env({'http_proxy': 'host:1234'})
1136
1147
        self.assertRaises(errors.InvalidURL, self._proxied_request)
1137
1148
 
1138
 
    def test_evaluate_proxy_bypass_true(self):
1139
 
        """The host is not proxied"""
1140
 
        self.assertEvaluateProxyBypass(True, 'example.com', 'example.com')
1141
 
        self.assertEvaluateProxyBypass(True, 'bzr.example.com', '*example.com')
1142
 
 
1143
 
    def test_evaluate_proxy_bypass_false(self):
1144
 
        """The host is proxied"""
1145
 
        self.assertEvaluateProxyBypass(False, 'bzr.example.com', None)
1146
 
 
1147
 
    def test_evaluate_proxy_bypass_unknown(self):
1148
 
        """The host is not explicitly proxied"""
1149
 
        self.assertEvaluateProxyBypass(None, 'example.com', 'not.example.com')
1150
 
        self.assertEvaluateProxyBypass(None, 'bzr.example.com', 'example.com')
1151
 
 
1152
 
    def test_evaluate_proxy_bypass_empty_entries(self):
1153
 
        """Ignore empty entries"""
1154
 
        self.assertEvaluateProxyBypass(None, 'example.com', '')
1155
 
        self.assertEvaluateProxyBypass(None, 'example.com', ',')
1156
 
        self.assertEvaluateProxyBypass(None, 'example.com', 'foo,,bar')
1157
 
 
1158
1149
 
1159
1150
class TestProxyHttpServer(http_utils.TestCaseWithTwoWebservers):
1160
1151
    """Tests proxy server.
1165
1156
    to the file names).
1166
1157
    """
1167
1158
 
1168
 
    scenarios = multiply_scenarios(
1169
 
        vary_by_http_client_implementation(),
1170
 
        vary_by_http_protocol_version(),
1171
 
        )
1172
 
 
1173
1159
    # FIXME: We don't have an https server available, so we don't
1174
 
    # test https connections. --vila toolongago
 
1160
    # test https connections.
1175
1161
 
1176
1162
    def setUp(self):
1177
1163
        super(TestProxyHttpServer, self).setUp()
1178
 
        self.transport_secondary_server = http_utils.ProxyServer
1179
1164
        self.build_tree_contents([('foo', 'contents of foo\n'),
1180
1165
                                  ('foo-proxied', 'proxied contents of foo\n')])
1181
1166
        # Let's setup some attributes for tests
1182
 
        server = self.get_readonly_server()
1183
 
        self.server_host_port = '%s:%d' % (server.host, server.port)
 
1167
        self.server = self.get_readonly_server()
 
1168
        self.proxy_address = '%s:%d' % (self.server.host, self.server.port)
1184
1169
        if self._testing_pycurl():
1185
1170
            # Oh my ! pycurl does not check for the port as part of
1186
1171
            # no_proxy :-( So we just test the host part
1187
 
            self.no_proxy_host = server.host
 
1172
            self.no_proxy_host = self.server.host
1188
1173
        else:
1189
 
            self.no_proxy_host = self.server_host_port
 
1174
            self.no_proxy_host = self.proxy_address
1190
1175
        # The secondary server is the proxy
1191
 
        self.proxy_url = self.get_secondary_url()
 
1176
        self.proxy = self.get_secondary_server()
 
1177
        self.proxy_url = self.proxy.get_url()
 
1178
        self._old_env = {}
1192
1179
 
1193
1180
    def _testing_pycurl(self):
1194
1181
        # TODO: This is duplicated for lots of the classes in this file
1195
1182
        return (features.pycurl.available()
1196
1183
                and self._transport == PyCurlTransport)
1197
1184
 
1198
 
    def assertProxied(self):
1199
 
        t = self.get_readonly_transport()
1200
 
        self.assertEqual('proxied contents of foo\n', t.get('foo').read())
1201
 
 
1202
 
    def assertNotProxied(self):
1203
 
        t = self.get_readonly_transport()
1204
 
        self.assertEqual('contents of foo\n', t.get('foo').read())
 
1185
    def create_transport_secondary_server(self):
 
1186
        """Creates an http server that will serve files with
 
1187
        '-proxied' appended to their names.
 
1188
        """
 
1189
        return http_utils.ProxyServer(protocol_version=self._protocol_version)
 
1190
 
 
1191
    def _install_env(self, env):
 
1192
        for name, value in env.iteritems():
 
1193
            self._old_env[name] = osutils.set_or_unset_env(name, value)
 
1194
 
 
1195
    def _restore_env(self):
 
1196
        for name, value in self._old_env.iteritems():
 
1197
            osutils.set_or_unset_env(name, value)
 
1198
 
 
1199
    def proxied_in_env(self, env):
 
1200
        self._install_env(env)
 
1201
        url = self.server.get_url()
 
1202
        t = self._transport(url)
 
1203
        try:
 
1204
            self.assertEqual('proxied contents of foo\n', t.get('foo').read())
 
1205
        finally:
 
1206
            self._restore_env()
 
1207
 
 
1208
    def not_proxied_in_env(self, env):
 
1209
        self._install_env(env)
 
1210
        url = self.server.get_url()
 
1211
        t = self._transport(url)
 
1212
        try:
 
1213
            self.assertEqual('contents of foo\n', t.get('foo').read())
 
1214
        finally:
 
1215
            self._restore_env()
1205
1216
 
1206
1217
    def test_http_proxy(self):
1207
 
        self.overrideEnv('http_proxy', self.proxy_url)
1208
 
        self.assertProxied()
 
1218
        self.proxied_in_env({'http_proxy': self.proxy_url})
1209
1219
 
1210
1220
    def test_HTTP_PROXY(self):
1211
1221
        if self._testing_pycurl():
1214
1224
            # about. Should we ?)
1215
1225
            raise tests.TestNotApplicable(
1216
1226
                'pycurl does not check HTTP_PROXY for security reasons')
1217
 
        self.overrideEnv('HTTP_PROXY', self.proxy_url)
1218
 
        self.assertProxied()
 
1227
        self.proxied_in_env({'HTTP_PROXY': self.proxy_url})
1219
1228
 
1220
1229
    def test_all_proxy(self):
1221
 
        self.overrideEnv('all_proxy', self.proxy_url)
1222
 
        self.assertProxied()
 
1230
        self.proxied_in_env({'all_proxy': self.proxy_url})
1223
1231
 
1224
1232
    def test_ALL_PROXY(self):
1225
 
        self.overrideEnv('ALL_PROXY', self.proxy_url)
1226
 
        self.assertProxied()
 
1233
        self.proxied_in_env({'ALL_PROXY': self.proxy_url})
1227
1234
 
1228
1235
    def test_http_proxy_with_no_proxy(self):
1229
 
        self.overrideEnv('no_proxy', self.no_proxy_host)
1230
 
        self.overrideEnv('http_proxy', self.proxy_url)
1231
 
        self.assertNotProxied()
 
1236
        self.not_proxied_in_env({'http_proxy': self.proxy_url,
 
1237
                                 'no_proxy': self.no_proxy_host})
1232
1238
 
1233
1239
    def test_HTTP_PROXY_with_NO_PROXY(self):
1234
1240
        if self._testing_pycurl():
1235
1241
            raise tests.TestNotApplicable(
1236
1242
                'pycurl does not check HTTP_PROXY for security reasons')
1237
 
        self.overrideEnv('NO_PROXY', self.no_proxy_host)
1238
 
        self.overrideEnv('HTTP_PROXY', self.proxy_url)
1239
 
        self.assertNotProxied()
 
1243
        self.not_proxied_in_env({'HTTP_PROXY': self.proxy_url,
 
1244
                                 'NO_PROXY': self.no_proxy_host})
1240
1245
 
1241
1246
    def test_all_proxy_with_no_proxy(self):
1242
 
        self.overrideEnv('no_proxy', self.no_proxy_host)
1243
 
        self.overrideEnv('all_proxy', self.proxy_url)
1244
 
        self.assertNotProxied()
 
1247
        self.not_proxied_in_env({'all_proxy': self.proxy_url,
 
1248
                                 'no_proxy': self.no_proxy_host})
1245
1249
 
1246
1250
    def test_ALL_PROXY_with_NO_PROXY(self):
1247
 
        self.overrideEnv('NO_PROXY', self.no_proxy_host)
1248
 
        self.overrideEnv('ALL_PROXY', self.proxy_url)
1249
 
        self.assertNotProxied()
 
1251
        self.not_proxied_in_env({'ALL_PROXY': self.proxy_url,
 
1252
                                 'NO_PROXY': self.no_proxy_host})
1250
1253
 
1251
1254
    def test_http_proxy_without_scheme(self):
1252
 
        self.overrideEnv('http_proxy', self.server_host_port)
1253
1255
        if self._testing_pycurl():
1254
1256
            # pycurl *ignores* invalid proxy env variables. If that ever change
1255
1257
            # in the future, this test will fail indicating that pycurl do not
1256
1258
            # ignore anymore such variables.
1257
 
            self.assertNotProxied()
 
1259
            self.not_proxied_in_env({'http_proxy': self.proxy_address})
1258
1260
        else:
1259
 
            self.assertRaises(errors.InvalidURL, self.assertProxied)
 
1261
            self.assertRaises(errors.InvalidURL,
 
1262
                              self.proxied_in_env,
 
1263
                              {'http_proxy': self.proxy_address})
1260
1264
 
1261
1265
 
1262
1266
class TestRanges(http_utils.TestCaseWithWebserver):
1263
1267
    """Test the Range header in GET methods."""
1264
1268
 
1265
 
    scenarios = multiply_scenarios(
1266
 
        vary_by_http_client_implementation(),
1267
 
        vary_by_http_protocol_version(),
1268
 
        )
1269
 
 
1270
1269
    def setUp(self):
1271
1270
        http_utils.TestCaseWithWebserver.setUp(self)
1272
1271
        self.build_tree_contents([('a', '0123456789')],)
 
1272
        server = self.get_readonly_server()
 
1273
        self.transport = self._transport(server.get_url())
1273
1274
 
1274
1275
    def create_transport_readonly_server(self):
1275
1276
        return http_server.HttpServer(protocol_version=self._protocol_version)
1276
1277
 
1277
1278
    def _file_contents(self, relpath, ranges):
1278
 
        t = self.get_readonly_transport()
1279
1279
        offsets = [ (start, end - start + 1) for start, end in ranges]
1280
 
        coalesce = t._coalesce_offsets
 
1280
        coalesce = self.transport._coalesce_offsets
1281
1281
        coalesced = list(coalesce(offsets, limit=0, fudge_factor=0))
1282
 
        code, data = t._get(relpath, coalesced)
 
1282
        code, data = self.transport._get(relpath, coalesced)
1283
1283
        self.assertTrue(code in (200, 206),'_get returns: %d' % code)
1284
1284
        for start, end in ranges:
1285
1285
            data.seek(start)
1286
1286
            yield data.read(end - start + 1)
1287
1287
 
1288
1288
    def _file_tail(self, relpath, tail_amount):
1289
 
        t = self.get_readonly_transport()
1290
 
        code, data = t._get(relpath, [], tail_amount)
 
1289
        code, data = self.transport._get(relpath, [], tail_amount)
1291
1290
        self.assertTrue(code in (200, 206),'_get returns: %d' % code)
1292
1291
        data.seek(-tail_amount, 2)
1293
1292
        return data.read(tail_amount)
1312
1311
class TestHTTPRedirections(http_utils.TestCaseWithRedirectedWebserver):
1313
1312
    """Test redirection between http servers."""
1314
1313
 
1315
 
    scenarios = multiply_scenarios(
1316
 
        vary_by_http_client_implementation(),
1317
 
        vary_by_http_protocol_version(),
1318
 
        )
 
1314
    def create_transport_secondary_server(self):
 
1315
        """Create the secondary server redirecting to the primary server"""
 
1316
        new = self.get_readonly_server()
 
1317
 
 
1318
        redirecting = http_utils.HTTPServerRedirecting(
 
1319
            protocol_version=self._protocol_version)
 
1320
        redirecting.redirect_to(new.host, new.port)
 
1321
        return redirecting
1319
1322
 
1320
1323
    def setUp(self):
1321
1324
        super(TestHTTPRedirections, self).setUp()
1323
1326
                                  ('bundle',
1324
1327
                                  '# Bazaar revision bundle v0.9\n#\n')
1325
1328
                                  ],)
 
1329
        # The requests to the old server will be redirected to the new server
 
1330
        self.old_transport = self._transport(self.old_server.get_url())
1326
1331
 
1327
1332
    def test_redirected(self):
1328
 
        self.assertRaises(errors.RedirectRequested,
1329
 
                          self.get_old_transport().get, 'a')
1330
 
        self.assertEqual('0123456789', self.get_new_transport().get('a').read())
 
1333
        self.assertRaises(errors.RedirectRequested, self.old_transport.get, 'a')
 
1334
        t = self._transport(self.new_server.get_url())
 
1335
        self.assertEqual('0123456789', t.get('a').read())
 
1336
 
 
1337
    def test_read_redirected_bundle_from_url(self):
 
1338
        from bzrlib.bundle import read_bundle_from_url
 
1339
        url = self.old_transport.abspath('bundle')
 
1340
        bundle = self.applyDeprecated(deprecated_in((1, 12, 0)),
 
1341
                read_bundle_from_url, url)
 
1342
        # If read_bundle_from_url was successful we get an empty bundle
 
1343
        self.assertEqual([], bundle.revisions)
1331
1344
 
1332
1345
 
1333
1346
class RedirectedRequest(_urllib2_wrappers.Request):
1350
1363
    test.overrideAttr(_urllib2_wrappers, 'Request', RedirectedRequest)
1351
1364
 
1352
1365
 
1353
 
def cleanup_http_redirection_connections(test):
1354
 
    # Some sockets are opened but never seen by _urllib, so we trap them at
1355
 
    # the _urllib2_wrappers level to be able to clean them up.
1356
 
    def socket_disconnect(sock):
1357
 
        try:
1358
 
            sock.shutdown(socket.SHUT_RDWR)
1359
 
            sock.close()
1360
 
        except socket.error:
1361
 
            pass
1362
 
    def connect(connection):
1363
 
        test.http_connect_orig(connection)
1364
 
        test.addCleanup(socket_disconnect, connection.sock)
1365
 
    test.http_connect_orig = test.overrideAttr(
1366
 
        _urllib2_wrappers.HTTPConnection, 'connect', connect)
1367
 
    def connect(connection):
1368
 
        test.https_connect_orig(connection)
1369
 
        test.addCleanup(socket_disconnect, connection.sock)
1370
 
    test.https_connect_orig = test.overrideAttr(
1371
 
        _urllib2_wrappers.HTTPSConnection, 'connect', connect)
1372
 
 
1373
 
 
1374
1366
class TestHTTPSilentRedirections(http_utils.TestCaseWithRedirectedWebserver):
1375
1367
    """Test redirections.
1376
1368
 
1385
1377
    -- vila 20070212
1386
1378
    """
1387
1379
 
1388
 
    scenarios = multiply_scenarios(
1389
 
        vary_by_http_client_implementation(),
1390
 
        vary_by_http_protocol_version(),
1391
 
        )
1392
 
 
1393
1380
    def setUp(self):
1394
1381
        if (features.pycurl.available()
1395
1382
            and self._transport == PyCurlTransport):
1396
1383
            raise tests.TestNotApplicable(
1397
 
                "pycurl doesn't redirect silently anymore")
 
1384
                "pycurl doesn't redirect silently annymore")
1398
1385
        super(TestHTTPSilentRedirections, self).setUp()
1399
1386
        install_redirected_request(self)
1400
 
        cleanup_http_redirection_connections(self)
1401
1387
        self.build_tree_contents([('a','a'),
1402
1388
                                  ('1/',),
1403
1389
                                  ('1/a', 'redirected once'),
1411
1397
                                  ('5/a', 'redirected 5 times'),
1412
1398
                                  ],)
1413
1399
 
 
1400
        self.old_transport = self._transport(self.old_server.get_url())
 
1401
 
 
1402
    def create_transport_secondary_server(self):
 
1403
        """Create the secondary server, redirections are defined in the tests"""
 
1404
        return http_utils.HTTPServerRedirecting(
 
1405
            protocol_version=self._protocol_version)
 
1406
 
1414
1407
    def test_one_redirection(self):
1415
 
        t = self.get_old_transport()
1416
 
        req = RedirectedRequest('GET', t._remote_path('a'))
 
1408
        t = self.old_transport
 
1409
 
 
1410
        req = RedirectedRequest('GET', t.abspath('a'))
1417
1411
        new_prefix = 'http://%s:%s' % (self.new_server.host,
1418
1412
                                       self.new_server.port)
1419
1413
        self.old_server.redirections = \
1420
1414
            [('(.*)', r'%s/1\1' % (new_prefix), 301),]
1421
 
        self.assertEqual('redirected once', t._perform(req).read())
 
1415
        self.assertEqual('redirected once',t._perform(req).read())
1422
1416
 
1423
1417
    def test_five_redirections(self):
1424
 
        t = self.get_old_transport()
1425
 
        req = RedirectedRequest('GET', t._remote_path('a'))
 
1418
        t = self.old_transport
 
1419
 
 
1420
        req = RedirectedRequest('GET', t.abspath('a'))
1426
1421
        old_prefix = 'http://%s:%s' % (self.old_server.host,
1427
1422
                                       self.old_server.port)
1428
1423
        new_prefix = 'http://%s:%s' % (self.new_server.host,
1434
1429
            ('/4(.*)', r'%s/5\1' % (new_prefix), 301),
1435
1430
            ('(/[^/]+)', r'%s/1\1' % (old_prefix), 301),
1436
1431
            ]
1437
 
        self.assertEqual('redirected 5 times', t._perform(req).read())
 
1432
        self.assertEqual('redirected 5 times',t._perform(req).read())
1438
1433
 
1439
1434
 
1440
1435
class TestDoCatchRedirections(http_utils.TestCaseWithRedirectedWebserver):
1441
1436
    """Test transport.do_catching_redirections."""
1442
1437
 
1443
 
    scenarios = multiply_scenarios(
1444
 
        vary_by_http_client_implementation(),
1445
 
        vary_by_http_protocol_version(),
1446
 
        )
1447
 
 
1448
1438
    def setUp(self):
1449
1439
        super(TestDoCatchRedirections, self).setUp()
1450
1440
        self.build_tree_contents([('a', '0123456789'),],)
1451
 
        cleanup_http_redirection_connections(self)
1452
 
 
1453
 
        self.old_transport = self.get_old_transport()
1454
 
 
1455
 
    def get_a(self, t):
1456
 
        return t.get('a')
 
1441
 
 
1442
        self.old_transport = self._transport(self.old_server.get_url())
 
1443
 
 
1444
    def get_a(self, transport):
 
1445
        return transport.get('a')
1457
1446
 
1458
1447
    def test_no_redirection(self):
1459
 
        t = self.get_new_transport()
 
1448
        t = self._transport(self.new_server.get_url())
1460
1449
 
1461
1450
        # We use None for redirected so that we fail if redirected
1462
1451
        self.assertEqual('0123456789',
1466
1455
    def test_one_redirection(self):
1467
1456
        self.redirections = 0
1468
1457
 
1469
 
        def redirected(t, exception, redirection_notice):
 
1458
        def redirected(transport, exception, redirection_notice):
1470
1459
            self.redirections += 1
1471
 
            redirected_t = t._redirected_to(exception.source, exception.target)
1472
 
            return redirected_t
 
1460
            dir, file = urlutils.split(exception.target)
 
1461
            return self._transport(dir)
1473
1462
 
1474
1463
        self.assertEqual('0123456789',
1475
1464
                         transport.do_catching_redirections(
1492
1481
class TestAuth(http_utils.TestCaseWithWebserver):
1493
1482
    """Test authentication scheme"""
1494
1483
 
1495
 
    scenarios = multiply_scenarios(
1496
 
        vary_by_http_client_implementation(),
1497
 
        vary_by_http_protocol_version(),
1498
 
        vary_by_http_auth_scheme(),
1499
 
        )
1500
 
 
1501
1484
    _auth_header = 'Authorization'
1502
1485
    _password_prompt_prefix = ''
1503
1486
    _username_prompt_prefix = ''
1511
1494
                                  ('b', 'contents of b\n'),])
1512
1495
 
1513
1496
    def create_transport_readonly_server(self):
1514
 
        server = self._auth_server(protocol_version=self._protocol_version)
1515
 
        server._url_protocol = self._url_protocol
1516
 
        return server
 
1497
        return self._auth_server(protocol_version=self._protocol_version)
1517
1498
 
1518
1499
    def _testing_pycurl(self):
1519
1500
        # TODO: This is duplicated for lots of the classes in this file
1532
1513
        return url
1533
1514
 
1534
1515
    def get_user_transport(self, user, password):
1535
 
        t = transport.get_transport(self.get_user_url(user, password))
1536
 
        return t
 
1516
        return self._transport(self.get_user_url(user, password))
1537
1517
 
1538
1518
    def test_no_user(self):
1539
1519
        self.server.add_user('joe', 'foo')
1650
1630
        ui.ui_factory = tests.TestUIFactory(stdin=stdin_content,
1651
1631
                                            stderr=tests.StringIOWrapper())
1652
1632
        # Create a minimal config file with the right password
1653
 
        _setup_authentication_config(
1654
 
            scheme='http', 
1655
 
            port=self.server.port,
1656
 
            user=user,
1657
 
            password=password)
 
1633
        conf = config.AuthenticationConfig()
 
1634
        conf._get_config().update(
 
1635
            {'httptest': {'scheme': 'http', 'port': self.server.port,
 
1636
                          'user': user, 'password': password}})
 
1637
        conf._save()
1658
1638
        # Issue a request to the server to connect
1659
1639
        self.assertEqual('contents of a\n',t.get('a').read())
1660
1640
        # stdin should have  been left untouched
1662
1642
        # Only one 'Authentication Required' error should occur
1663
1643
        self.assertEqual(1, self.server.auth_required_errors)
1664
1644
 
 
1645
    def test_user_from_auth_conf(self):
 
1646
        if self._testing_pycurl():
 
1647
            raise tests.TestNotApplicable(
 
1648
                'pycurl does not support authentication.conf')
 
1649
        user = 'joe'
 
1650
        password = 'foo'
 
1651
        self.server.add_user(user, password)
 
1652
        # Create a minimal config file with the right password
 
1653
        conf = config.AuthenticationConfig()
 
1654
        conf._get_config().update(
 
1655
            {'httptest': {'scheme': 'http', 'port': self.server.port,
 
1656
                          'user': user, 'password': password}})
 
1657
        conf._save()
 
1658
        t = self.get_user_transport(None, None)
 
1659
        # Issue a request to the server to connect
 
1660
        self.assertEqual('contents of a\n', t.get('a').read())
 
1661
        # Only one 'Authentication Required' error should occur
 
1662
        self.assertEqual(1, self.server.auth_required_errors)
 
1663
 
1665
1664
    def test_changing_nonce(self):
1666
1665
        if self._auth_server not in (http_utils.HTTPDigestAuthServer,
1667
1666
                                     http_utils.ProxyDigestAuthServer):
1683
1682
        # initial 'who are you' and a second 'who are you' with the new nonce)
1684
1683
        self.assertEqual(2, self.server.auth_required_errors)
1685
1684
 
1686
 
    def test_user_from_auth_conf(self):
1687
 
        if self._testing_pycurl():
1688
 
            raise tests.TestNotApplicable(
1689
 
                'pycurl does not support authentication.conf')
1690
 
        user = 'joe'
1691
 
        password = 'foo'
1692
 
        self.server.add_user(user, password)
1693
 
        _setup_authentication_config(
1694
 
            scheme='http', 
1695
 
            port=self.server.port,
1696
 
            user=user,
1697
 
            password=password)
1698
 
        t = self.get_user_transport(None, None)
1699
 
        # Issue a request to the server to connect
1700
 
        self.assertEqual('contents of a\n', t.get('a').read())
1701
 
        # Only one 'Authentication Required' error should occur
1702
 
        self.assertEqual(1, self.server.auth_required_errors)
1703
 
 
1704
 
 
1705
 
def _setup_authentication_config(**kwargs):
1706
 
    conf = config.AuthenticationConfig()
1707
 
    conf._get_config().update({'httptest': kwargs})
1708
 
    conf._save()
1709
 
 
1710
 
 
1711
 
 
1712
 
class TestUrllib2AuthHandler(tests.TestCaseWithTransport):
1713
 
    """Unit tests for glue by which urllib2 asks us for authentication"""
1714
 
 
1715
 
    def test_get_user_password_without_port(self):
1716
 
        """We cope if urllib2 doesn't tell us the port.
1717
 
 
1718
 
        See https://bugs.launchpad.net/bzr/+bug/654684
1719
 
        """
1720
 
        user = 'joe'
1721
 
        password = 'foo'
1722
 
        _setup_authentication_config(
1723
 
            scheme='http', 
1724
 
            host='localhost',
1725
 
            user=user,
1726
 
            password=password)
1727
 
        handler = _urllib2_wrappers.HTTPAuthHandler()
1728
 
        got_pass = handler.get_user_password(dict(
1729
 
            user='joe',
1730
 
            protocol='http',
1731
 
            host='localhost',
1732
 
            path='/',
1733
 
            realm='Realm',
1734
 
            ))
1735
 
        self.assertEquals((user, password), got_pass)
1736
1685
 
1737
1686
 
1738
1687
class TestProxyAuth(TestAuth):
1739
1688
    """Test proxy authentication schemes."""
1740
1689
 
1741
 
    scenarios = multiply_scenarios(
1742
 
        vary_by_http_client_implementation(),
1743
 
        vary_by_http_protocol_version(),
1744
 
        vary_by_http_proxy_auth_scheme(),
1745
 
        )
1746
 
 
1747
1690
    _auth_header = 'Proxy-authorization'
1748
1691
    _password_prompt_prefix = 'Proxy '
1749
1692
    _username_prompt_prefix = 'Proxy '
1750
1693
 
1751
1694
    def setUp(self):
1752
1695
        super(TestProxyAuth, self).setUp()
 
1696
        self._old_env = {}
 
1697
        self.addCleanup(self._restore_env)
1753
1698
        # Override the contents to avoid false positives
1754
1699
        self.build_tree_contents([('a', 'not proxied contents of a\n'),
1755
1700
                                  ('b', 'not proxied contents of b\n'),
1758
1703
                                  ])
1759
1704
 
1760
1705
    def get_user_transport(self, user, password):
1761
 
        self.overrideEnv('all_proxy', self.get_user_url(user, password))
1762
 
        return TestAuth.get_user_transport(self, user, password)
 
1706
        self._install_env({'all_proxy': self.get_user_url(user, password)})
 
1707
        return self._transport(self.server.get_url())
 
1708
 
 
1709
    def _install_env(self, env):
 
1710
        for name, value in env.iteritems():
 
1711
            self._old_env[name] = osutils.set_or_unset_env(name, value)
 
1712
 
 
1713
    def _restore_env(self):
 
1714
        for name, value in self._old_env.iteritems():
 
1715
            osutils.set_or_unset_env(name, value)
1763
1716
 
1764
1717
    def test_empty_pass(self):
1765
1718
        if self._testing_pycurl():
1784
1737
        self.readfile = StringIO(socket_read_content)
1785
1738
        self.writefile = StringIO()
1786
1739
        self.writefile.close = lambda: None
1787
 
        self.close = lambda: None
1788
1740
 
1789
1741
    def makefile(self, mode='r', bufsize=None):
1790
1742
        if 'r' in mode:
1795
1747
 
1796
1748
class SmartHTTPTunnellingTest(tests.TestCaseWithTransport):
1797
1749
 
1798
 
    scenarios = multiply_scenarios(
1799
 
        vary_by_http_client_implementation(),
1800
 
        vary_by_http_protocol_version(),
1801
 
        )
1802
 
 
1803
1750
    def setUp(self):
1804
1751
        super(SmartHTTPTunnellingTest, self).setUp()
1805
1752
        # We use the VFS layer as part of HTTP tunnelling tests.
1806
 
        self.overrideEnv('BZR_NO_SMART_VFS', None)
 
1753
        self._captureVar('BZR_NO_SMART_VFS', None)
1807
1754
        self.transport_readonly_server = http_utils.HTTPServerWithSmarts
1808
 
        self.http_server = self.get_readonly_server()
1809
1755
 
1810
1756
    def create_transport_readonly_server(self):
1811
 
        server = http_utils.HTTPServerWithSmarts(
 
1757
        return http_utils.HTTPServerWithSmarts(
1812
1758
            protocol_version=self._protocol_version)
1813
 
        server._url_protocol = self._url_protocol
1814
 
        return server
1815
1759
 
1816
1760
    def test_open_bzrdir(self):
1817
1761
        branch = self.make_branch('relpath')
1818
 
        url = self.http_server.get_url() + 'relpath'
 
1762
        http_server = self.get_readonly_server()
 
1763
        url = http_server.get_url() + 'relpath'
1819
1764
        bd = bzrdir.BzrDir.open(url)
1820
 
        self.addCleanup(bd.transport.disconnect)
1821
1765
        self.assertIsInstance(bd, _mod_remote.RemoteBzrDir)
1822
1766
 
1823
1767
    def test_bulk_data(self):
1825
1769
        # The 'readv' command in the smart protocol both sends and receives
1826
1770
        # bulk data, so we use that.
1827
1771
        self.build_tree(['data-file'])
1828
 
        http_transport = transport.get_transport(self.http_server.get_url())
 
1772
        http_server = self.get_readonly_server()
 
1773
        http_transport = self._transport(http_server.get_url())
1829
1774
        medium = http_transport.get_smart_medium()
1830
1775
        # Since we provide the medium, the url below will be mostly ignored
1831
1776
        # during the test, as long as the path is '/'.
1839
1784
        post_body = 'hello\n'
1840
1785
        expected_reply_body = 'ok\x012\n'
1841
1786
 
1842
 
        http_transport = transport.get_transport(self.http_server.get_url())
 
1787
        http_server = self.get_readonly_server()
 
1788
        http_transport = self._transport(http_server.get_url())
1843
1789
        medium = http_transport.get_smart_medium()
1844
1790
        response = medium.send_http_smart_request(post_body)
1845
1791
        reply_body = response.read()
1846
1792
        self.assertEqual(expected_reply_body, reply_body)
1847
1793
 
1848
1794
    def test_smart_http_server_post_request_handler(self):
1849
 
        httpd = self.http_server.server
 
1795
        httpd = self.get_readonly_server()._get_httpd()
1850
1796
 
1851
1797
        socket = SampleSocket(
1852
1798
            'POST /.bzr/smart %s \r\n' % self._protocol_version
1884
1830
 
1885
1831
    def test_probe_smart_server(self):
1886
1832
        """Test error handling against server refusing smart requests."""
1887
 
        t = self.get_readonly_transport()
 
1833
        server = self.get_readonly_server()
 
1834
        t = self._transport(server.get_url())
1888
1835
        # No need to build a valid smart request here, the server will not even
1889
1836
        # try to interpret it.
1890
1837
        self.assertRaises(errors.SmartProtocolError,
1891
1838
                          t.get_smart_medium().send_http_smart_request,
1892
1839
                          'whatever')
1893
1840
 
1894
 
 
1895
1841
class Test_redirected_to(tests.TestCase):
1896
1842
 
1897
 
    scenarios = vary_by_http_client_implementation()
1898
 
 
1899
1843
    def test_redirected_to_subdir(self):
1900
1844
        t = self._transport('http://www.example.com/foo')
1901
1845
        r = t._redirected_to('http://www.example.com/foo',
1952
1896
    line.
1953
1897
    """
1954
1898
 
1955
 
    def _handle_one_request(self):
 
1899
    def handle_one_request(self):
1956
1900
        tcs = self.server.test_case_server
1957
1901
        requestline = self.rfile.readline()
1958
1902
        headers = self.MessageClass(self.rfile, 0)
2022
1966
        # We override at class level because constructors may propagate the
2023
1967
        # bound method and render instance overriding ineffective (an
2024
1968
        # alternative would be to define a specific ui factory instead...)
2025
 
        self.overrideAttr(self._transport, '_report_activity', report_activity)
2026
 
        self.addCleanup(self.server.stop_server)
 
1969
        self.orig_report_activity = self._transport._report_activity
 
1970
        self._transport._report_activity = report_activity
 
1971
 
 
1972
    def tearDown(self):
 
1973
        self._transport._report_activity = self.orig_report_activity
 
1974
        self.server.stop_server()
 
1975
        tests.TestCase.tearDown(self)
2027
1976
 
2028
1977
    def get_transport(self):
2029
 
        t = self._transport(self.server.get_url())
2030
 
        # FIXME: Needs cleanup -- vila 20100611
2031
 
        return t
 
1978
        return self._transport(self.server.get_url())
2032
1979
 
2033
1980
    def assertActivitiesMatch(self):
2034
1981
        self.assertEqual(self.server.bytes_read,
2139
2086
'''
2140
2087
        t = self.get_transport()
2141
2088
        # We must send a single line of body bytes, see
2142
 
        # PredefinedRequestHandler._handle_one_request
 
2089
        # PredefinedRequestHandler.handle_one_request
2143
2090
        code, f = t._post('abc def end-of-body\n')
2144
2091
        self.assertEqual('lalala whatever as long as itsssss\n', f.read())
2145
2092
        self.assertActivitiesMatch()
2147
2094
 
2148
2095
class TestActivity(tests.TestCase, TestActivityMixin):
2149
2096
 
2150
 
    scenarios = multiply_scenarios(
2151
 
        vary_by_http_activity(),
2152
 
        vary_by_http_protocol_version(),
2153
 
        )
2154
 
 
2155
2097
    def setUp(self):
2156
 
        TestActivityMixin.setUp(self)
 
2098
        tests.TestCase.setUp(self)
 
2099
        self.server = self._activity_server(self._protocol_version)
 
2100
        self.server.start_server()
 
2101
        self.activities = {}
 
2102
        def report_activity(t, bytes, direction):
 
2103
            count = self.activities.get(direction, 0)
 
2104
            count += bytes
 
2105
            self.activities[direction] = count
 
2106
 
 
2107
        # We override at class level because constructors may propagate the
 
2108
        # bound method and render instance overriding ineffective (an
 
2109
        # alternative would be to define a specific ui factory instead...)
 
2110
        self.orig_report_activity = self._transport._report_activity
 
2111
        self._transport._report_activity = report_activity
 
2112
 
 
2113
    def tearDown(self):
 
2114
        self._transport._report_activity = self.orig_report_activity
 
2115
        self.server.stop_server()
 
2116
        tests.TestCase.tearDown(self)
2157
2117
 
2158
2118
 
2159
2119
class TestNoReportActivity(tests.TestCase, TestActivityMixin):
2160
2120
 
2161
 
    # Unlike TestActivity, we are really testing ReportingFileSocket and
2162
 
    # ReportingSocket, so we don't need all the parametrization. Since
2163
 
    # ReportingFileSocket and ReportingSocket are wrappers, it's easier to
2164
 
    # test them through their use by the transport than directly (that's a
2165
 
    # bit less clean but far more simpler and effective).
2166
 
    _activity_server = ActivityHTTPServer
2167
 
    _protocol_version = 'HTTP/1.1'
2168
 
 
2169
2121
    def setUp(self):
2170
 
        self._transport =_urllib.HttpTransport_urllib
2171
 
        TestActivityMixin.setUp(self)
 
2122
        tests.TestCase.setUp(self)
 
2123
        # Unlike TestActivity, we are really testing ReportingFileSocket and
 
2124
        # ReportingSocket, so we don't need all the parametrization. Since
 
2125
        # ReportingFileSocket and ReportingSocket are wrappers, it's easier to
 
2126
        # test them through their use by the transport than directly (that's a
 
2127
        # bit less clean but far more simpler and effective).
 
2128
        self.server = ActivityHTTPServer('HTTP/1.1')
 
2129
        self._transport=_urllib.HttpTransport_urllib
 
2130
 
 
2131
        self.server.start_server()
 
2132
 
 
2133
        # We override at class level because constructors may propagate the
 
2134
        # bound method and render instance overriding ineffective (an
 
2135
        # alternative would be to define a specific ui factory instead...)
 
2136
        self.orig_report_activity = self._transport._report_activity
 
2137
        self._transport._report_activity = None
 
2138
 
 
2139
    def tearDown(self):
 
2140
        self._transport._report_activity = self.orig_report_activity
 
2141
        self.server.stop_server()
 
2142
        tests.TestCase.tearDown(self)
2172
2143
 
2173
2144
    def assertActivitiesMatch(self):
2174
2145
        # Nothing to check here
2178
2149
class TestAuthOnRedirected(http_utils.TestCaseWithRedirectedWebserver):
2179
2150
    """Test authentication on the redirected http server."""
2180
2151
 
2181
 
    scenarios = vary_by_http_protocol_version()
2182
 
 
2183
2152
    _auth_header = 'Authorization'
2184
2153
    _password_prompt_prefix = ''
2185
2154
    _username_prompt_prefix = ''
2186
2155
    _auth_server = http_utils.HTTPBasicAuthServer
2187
2156
    _transport = _urllib.HttpTransport_urllib
2188
2157
 
 
2158
    def create_transport_readonly_server(self):
 
2159
        return self._auth_server()
 
2160
 
 
2161
    def create_transport_secondary_server(self):
 
2162
        """Create the secondary server redirecting to the primary server"""
 
2163
        new = self.get_readonly_server()
 
2164
 
 
2165
        redirecting = http_utils.HTTPServerRedirecting()
 
2166
        redirecting.redirect_to(new.host, new.port)
 
2167
        return redirecting
 
2168
 
2189
2169
    def setUp(self):
2190
2170
        super(TestAuthOnRedirected, self).setUp()
2191
2171
        self.build_tree_contents([('a','a'),
2196
2176
                                       self.new_server.port)
2197
2177
        self.old_server.redirections = [
2198
2178
            ('(.*)', r'%s/1\1' % (new_prefix), 301),]
2199
 
        self.old_transport = self.get_old_transport()
 
2179
        self.old_transport = self._transport(self.old_server.get_url())
2200
2180
        self.new_server.add_user('joe', 'foo')
2201
 
        cleanup_http_redirection_connections(self)
2202
 
 
2203
 
    def create_transport_readonly_server(self):
2204
 
        server = self._auth_server(protocol_version=self._protocol_version)
2205
 
        server._url_protocol = self._url_protocol
2206
 
        return server
2207
 
 
2208
 
    def get_a(self, t):
2209
 
        return t.get('a')
 
2181
 
 
2182
    def get_a(self, transport):
 
2183
        return transport.get('a')
2210
2184
 
2211
2185
    def test_auth_on_redirected_via_do_catching_redirections(self):
2212
2186
        self.redirections = 0
2213
2187
 
2214
 
        def redirected(t, exception, redirection_notice):
 
2188
        def redirected(transport, exception, redirection_notice):
2215
2189
            self.redirections += 1
2216
 
            redirected_t = t._redirected_to(exception.source, exception.target)
2217
 
            self.addCleanup(redirected_t.disconnect)
2218
 
            return redirected_t
 
2190
            dir, file = urlutils.split(exception.target)
 
2191
            return self._transport(dir)
2219
2192
 
2220
2193
        stdout = tests.StringIOWrapper()
2221
2194
        stderr = tests.StringIOWrapper()
2242
2215
                                       self.new_server.port)
2243
2216
        self.old_server.redirections = [
2244
2217
            ('(.*)', r'%s/1\1' % (new_prefix), 301),]
2245
 
        self.assertEqual('redirected once', t._perform(req).read())
 
2218
        self.assertEqual('redirected once',t._perform(req).read())
2246
2219
        # stdin should be empty
2247
2220
        self.assertEqual('', ui.ui_factory.stdin.readline())
2248
2221
        # stdout should be empty, stderr will contains the prompts