66
64
    from bzrlib.transport.http._pycurl import PyCurlTransport
 
69
 
def load_tests(standard_tests, module, loader):
 
70
 
    """Multiply tests for http clients and protocol versions."""
 
71
 
    result = loader.suiteClass()
 
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,
 
 
67
load_tests = load_tests_apply_scenarios
 
 
70
def vary_by_http_client_implementation():
 
 
71
    """Test the two libraries we can use, pycurl and urllib."""
 
80
72
    transport_scenarios = [
 
81
73
        ('urllib', dict(_transport=_urllib.HttpTransport_urllib,
 
82
74
                        _server=http_server.HttpServer_urllib,
 
83
 
                        _qualified_prefix='http+urllib',)),
 
 
75
                        _url_protocol='http+urllib',)),
 
85
77
    if features.pycurl.available():
 
86
78
        transport_scenarios.append(
 
87
79
            ('pycurl', dict(_transport=PyCurlTransport,
 
88
80
                            _server=http_server.HttpServer_PyCurl,
 
89
 
                            _qualified_prefix='http+pycurl',)))
 
90
 
    tests.multiply_tests(t_tests, transport_scenarios, result)
 
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,
 
99
 
                TestHTTPSilentRedirections,
 
100
 
                TestLimitedRangeRequestServer,
 
104
 
                TestSpecificRequestHandler,
 
106
 
    protocol_scenarios = [
 
107
 
            ('HTTP/1.0',  dict(_protocol_version='HTTP/1.0')),
 
108
 
            ('HTTP/1.1',  dict(_protocol_version='HTTP/1.1')),
 
110
 
    tp_scenarios = tests.multiply_scenarios(transport_scenarios,
 
112
 
    tests.multiply_tests(tp_tests, tp_scenarios, result)
 
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((
 
119
 
    proxy_auth_scheme_scenarios = [
 
 
81
                            _url_protocol='http+pycurl',)))
 
 
82
    return transport_scenarios
 
 
85
def vary_by_http_protocol_version():
 
 
86
    """Test on http/1.0 and 1.1"""
 
 
88
        ('HTTP/1.0',  dict(_protocol_version='HTTP/1.0')),
 
 
89
        ('HTTP/1.1',  dict(_protocol_version='HTTP/1.1')),
 
 
93
def vary_by_http_proxy_auth_scheme():
 
120
95
        ('basic', dict(_auth_server=http_utils.ProxyBasicAuthServer)),
 
121
96
        ('digest', dict(_auth_server=http_utils.ProxyDigestAuthServer)),
 
123
 
         dict(_auth_server=http_utils.ProxyBasicAndDigestAuthServer)),
 
 
98
            dict(_auth_server=http_utils.ProxyBasicAndDigestAuthServer)),
 
125
 
    tppa_scenarios = tests.multiply_scenarios(tp_scenarios,
 
126
 
                                              proxy_auth_scheme_scenarios)
 
127
 
    tests.multiply_tests(tppa_tests, tppa_scenarios, result)
 
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((
 
134
 
    auth_scheme_scenarios = [
 
 
102
def vary_by_http_auth_scheme():
 
135
104
        ('basic', dict(_auth_server=http_utils.HTTPBasicAuthServer)),
 
136
105
        ('digest', dict(_auth_server=http_utils.HTTPDigestAuthServer)),
 
138
 
         dict(_auth_server=http_utils.HTTPBasicAndDigestAuthServer)),
 
 
107
            dict(_auth_server=http_utils.HTTPBasicAndDigestAuthServer)),
 
140
 
    tpa_scenarios = tests.multiply_scenarios(tp_scenarios,
 
141
 
                                             auth_scheme_scenarios)
 
142
 
    tests.multiply_tests(tpa_tests, tpa_scenarios, result)
 
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((
 
 
111
def vary_by_http_activity():
 
149
112
    activity_scenarios = [
 
150
113
        ('urllib,http', dict(_activity_server=ActivityHTTPServer,
 
151
 
                             _transport=_urllib.HttpTransport_urllib,)),
 
 
114
                            _transport=_urllib.HttpTransport_urllib,)),
 
153
116
    if tests.HTTPSServerFeature.available():
 
154
117
        activity_scenarios.append(
 
155
118
            ('urllib,https', dict(_activity_server=ActivityHTTPSServer,
 
156
 
                                  _transport=_urllib.HttpTransport_urllib,)),)
 
 
119
                                _transport=_urllib.HttpTransport_urllib,)),)
 
157
120
    if features.pycurl.available():
 
158
121
        activity_scenarios.append(
 
159
122
            ('pycurl,http', dict(_activity_server=ActivityHTTPServer,
 
160
 
                                 _transport=PyCurlTransport,)),)
 
 
123
                                _transport=PyCurlTransport,)),)
 
161
124
        if tests.HTTPSServerFeature.available():
 
162
125
            from bzrlib.tests import (
 
 
223
178
        self._sock.bind(('127.0.0.1', 0))
 
224
179
        self.host, self.port = self._sock.getsockname()
 
225
180
        self._ready = threading.Event()
 
226
 
        self._thread = threading.Thread(target=self._accept_read_and_reply)
 
227
 
        self._thread.setDaemon(True)
 
 
181
        self._thread = test_server.ThreadWithException(
 
 
182
            event=self._ready, target=self._accept_read_and_reply)
 
228
183
        self._thread.start()
 
 
184
        if 'threads' in tests.selftest_debug_flags:
 
 
185
            sys.stderr.write('Thread started: %s\n' % (self._thread.ident,))
 
231
188
    def _accept_read_and_reply(self):
 
232
189
        self._sock.listen(1)
 
233
190
        self._ready.set()
 
234
 
        self._sock.settimeout(5)
 
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)
 
 
191
        conn, address = self._sock.accept()
 
 
192
        if self._expect_body_tail is not None:
 
240
193
            while not self.received_bytes.endswith(self._expect_body_tail):
 
241
194
                self.received_bytes += conn.recv(4096)
 
242
195
            conn.sendall('HTTP/1.1 200 OK\r\n')
 
243
 
        except socket.timeout:
 
244
 
            # Make sure the client isn't stuck waiting for us to e.g. accept.
 
245
197
            self._sock.close()
 
246
198
        except socket.error:
 
247
199
            # The client may have already closed the socket.
 
 
305
263
            protocol_version = 'HTTP/0.1'
 
307
 
        server = http_server.HttpServer(BogusRequestHandler)
 
309
 
            self.assertRaises(httplib.UnknownProtocol, server.start_server)
 
312
 
            self.fail('HTTP Server creation did not raise UnknownProtocol')
 
 
265
        self.assertRaises(httplib.UnknownProtocol,
 
 
266
                          http_server.HttpServer, BogusRequestHandler)
 
314
268
    def test_force_invalid_protocol(self):
 
315
 
        server = http_server.HttpServer(protocol_version='HTTP/0.1')
 
317
 
            self.assertRaises(httplib.UnknownProtocol, server.start_server)
 
320
 
            self.fail('HTTP Server creation did not raise UnknownProtocol')
 
 
269
        self.assertRaises(httplib.UnknownProtocol,
 
 
270
                          http_server.HttpServer, protocol_version='HTTP/0.1')
 
322
272
    def test_server_start_and_stop(self):
 
323
273
        server = http_server.HttpServer()
 
 
274
        self.addCleanup(server.stop_server)
 
324
275
        server.start_server()
 
326
 
            self.assertTrue(server._http_running)
 
329
 
        self.assertFalse(server._http_running)
 
 
276
        self.assertTrue(server.server is not None)
 
 
277
        self.assertTrue(server.server.serving is not None)
 
 
278
        self.assertTrue(server.server.serving)
 
331
280
    def test_create_http_server_one_zero(self):
 
332
281
        class RequestHandlerOneZero(http_server.TestingHTTPRequestHandler):
 
 
525
481
class TestHttpTransportRegistration(tests.TestCase):
 
526
482
    """Test registrations of various http implementations"""
 
 
484
    scenarios = vary_by_http_client_implementation()
 
528
486
    def test_http_registered(self):
 
529
 
        t = transport.get_transport('%s://foo.com/' % self._qualified_prefix)
 
 
487
        t = transport.get_transport('%s://foo.com/' % self._url_protocol)
 
530
488
        self.assertIsInstance(t, transport.Transport)
 
531
489
        self.assertIsInstance(t, self._transport)
 
534
492
class TestPost(tests.TestCase):
 
 
494
    scenarios = multiply_scenarios(
 
 
495
        vary_by_http_client_implementation(), 
 
 
496
        vary_by_http_protocol_version(),
 
536
499
    def test_post_body_is_received(self):
 
537
500
        server = RecordingServer(expect_body_tail='end-of-body',
 
538
 
            scheme=self._qualified_prefix)
 
 
501
                                 scheme=self._url_protocol)
 
539
502
        self.start_server(server)
 
540
503
        url = server.get_url()
 
541
 
        http_transport = self._transport(url)
 
 
504
        # FIXME: needs a cleanup -- vila 20100611
 
 
505
        http_transport = transport.get_transport(url)
 
542
506
        code, response = http_transport._post('abc def end-of-body')
 
544
508
            server.received_bytes.startswith('POST /.bzr/smart HTTP/1.'))
 
 
1090
1046
        self.build_tree_contents([('a', content)],)
 
1092
1048
    def test_few_ranges(self):
 
1093
 
        t = self.get_transport()
 
 
1049
        t = self.get_readonly_transport()
 
1094
1050
        l = list(t.readv('a', ((0, 4), (1024, 4), )))
 
1095
1051
        self.assertEqual(l[0], (0, '0000'))
 
1096
1052
        self.assertEqual(l[1], (1024, '0001'))
 
1097
1053
        self.assertEqual(1, self.get_readonly_server().GET_request_nb)
 
1099
1055
    def test_more_ranges(self):
 
1100
 
        t = self.get_transport()
 
 
1056
        t = self.get_readonly_transport()
 
1101
1057
        l = list(t.readv('a', ((0, 4), (1024, 4), (4096, 4), (8192, 4))))
 
1102
1058
        self.assertEqual(l[0], (0, '0000'))
 
1103
1059
        self.assertEqual(l[1], (1024, '0001'))
 
 
1156
1109
    to the file names).
 
 
1112
    scenarios = multiply_scenarios(
 
 
1113
        vary_by_http_client_implementation(), 
 
 
1114
        vary_by_http_protocol_version(),
 
1159
1117
    # FIXME: We don't have an https server available, so we don't
 
1160
 
    # test https connections.
 
 
1118
    # test https connections. --vila toolongago
 
1162
1120
    def setUp(self):
 
1163
1121
        super(TestProxyHttpServer, self).setUp()
 
 
1122
        self.transport_secondary_server = http_utils.ProxyServer
 
1164
1123
        self.build_tree_contents([('foo', 'contents of foo\n'),
 
1165
1124
                                  ('foo-proxied', 'proxied contents of foo\n')])
 
1166
1125
        # Let's setup some attributes for tests
 
1167
 
        self.server = self.get_readonly_server()
 
1168
 
        self.proxy_address = '%s:%d' % (self.server.host, self.server.port)
 
 
1126
        server = self.get_readonly_server()
 
 
1127
        self.server_host_port = '%s:%d' % (server.host, server.port)
 
1169
1128
        if self._testing_pycurl():
 
1170
1129
            # Oh my ! pycurl does not check for the port as part of
 
1171
1130
            # no_proxy :-( So we just test the host part
 
1172
 
            self.no_proxy_host = self.server.host
 
 
1131
            self.no_proxy_host = server.host
 
1174
 
            self.no_proxy_host = self.proxy_address
 
 
1133
            self.no_proxy_host = self.server_host_port
 
1175
1134
        # The secondary server is the proxy
 
1176
 
        self.proxy = self.get_secondary_server()
 
1177
 
        self.proxy_url = self.proxy.get_url()
 
 
1135
        self.proxy_url = self.get_secondary_url()
 
1178
1136
        self._old_env = {}
 
1180
1138
    def _testing_pycurl(self):
 
 
1256
1206
            # pycurl *ignores* invalid proxy env variables. If that ever change
 
1257
1207
            # in the future, this test will fail indicating that pycurl do not
 
1258
1208
            # ignore anymore such variables.
 
1259
 
            self.not_proxied_in_env({'http_proxy': self.proxy_address})
 
 
1209
            self.not_proxied_in_env({'http_proxy': self.server_host_port})
 
1261
1211
            self.assertRaises(errors.InvalidURL,
 
1262
1212
                              self.proxied_in_env,
 
1263
 
                              {'http_proxy': self.proxy_address})
 
 
1213
                              {'http_proxy': self.server_host_port})
 
1266
1216
class TestRanges(http_utils.TestCaseWithWebserver):
 
1267
1217
    """Test the Range header in GET methods."""
 
 
1219
    scenarios = multiply_scenarios(
 
 
1220
        vary_by_http_client_implementation(), 
 
 
1221
        vary_by_http_protocol_version(),
 
1269
1224
    def setUp(self):
 
1270
1225
        http_utils.TestCaseWithWebserver.setUp(self)
 
1271
1226
        self.build_tree_contents([('a', '0123456789')],)
 
1272
 
        server = self.get_readonly_server()
 
1273
 
        self.transport = self._transport(server.get_url())
 
1275
1228
    def create_transport_readonly_server(self):
 
1276
1229
        return http_server.HttpServer(protocol_version=self._protocol_version)
 
1278
1231
    def _file_contents(self, relpath, ranges):
 
 
1232
        t = self.get_readonly_transport()
 
1279
1233
        offsets = [ (start, end - start + 1) for start, end in ranges]
 
1280
 
        coalesce = self.transport._coalesce_offsets
 
 
1234
        coalesce = t._coalesce_offsets
 
1281
1235
        coalesced = list(coalesce(offsets, limit=0, fudge_factor=0))
 
1282
 
        code, data = self.transport._get(relpath, coalesced)
 
 
1236
        code, data = t._get(relpath, coalesced)
 
1283
1237
        self.assertTrue(code in (200, 206),'_get returns: %d' % code)
 
1284
1238
        for start, end in ranges:
 
1285
1239
            data.seek(start)
 
1286
1240
            yield data.read(end - start + 1)
 
1288
1242
    def _file_tail(self, relpath, tail_amount):
 
1289
 
        code, data = self.transport._get(relpath, [], tail_amount)
 
 
1243
        t = self.get_readonly_transport()
 
 
1244
        code, data = t._get(relpath, [], tail_amount)
 
1290
1245
        self.assertTrue(code in (200, 206),'_get returns: %d' % code)
 
1291
1246
        data.seek(-tail_amount, 2)
 
1292
1247
        return data.read(tail_amount)
 
 
1327
1278
                                  '# Bazaar revision bundle v0.9\n#\n')
 
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())
 
1332
1281
    def test_redirected(self):
 
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())
 
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)
 
 
1282
        self.assertRaises(errors.RedirectRequested,
 
 
1283
                          self.get_old_transport().get, 'a')
 
 
1284
        self.assertEqual('0123456789', self.get_new_transport().get('a').read())
 
1346
1287
class RedirectedRequest(_urllib2_wrappers.Request):
 
 
1397
1365
                                  ('5/a', 'redirected 5 times'),
 
1400
 
        self.old_transport = self._transport(self.old_server.get_url())
 
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)
 
1407
1368
    def test_one_redirection(self):
 
1408
 
        t = self.old_transport
 
1410
 
        req = RedirectedRequest('GET', t.abspath('a'))
 
 
1369
        t = self.get_old_transport()
 
 
1370
        req = RedirectedRequest('GET', t._remote_path('a'))
 
1411
1371
        new_prefix = 'http://%s:%s' % (self.new_server.host,
 
1412
1372
                                       self.new_server.port)
 
1413
1373
        self.old_server.redirections = \
 
1414
1374
            [('(.*)', r'%s/1\1' % (new_prefix), 301),]
 
1415
 
        self.assertEqual('redirected once',t._perform(req).read())
 
 
1375
        self.assertEqual('redirected once', t._perform(req).read())
 
1417
1377
    def test_five_redirections(self):
 
1418
 
        t = self.old_transport
 
1420
 
        req = RedirectedRequest('GET', t.abspath('a'))
 
 
1378
        t = self.get_old_transport()
 
 
1379
        req = RedirectedRequest('GET', t._remote_path('a'))
 
1421
1380
        old_prefix = 'http://%s:%s' % (self.old_server.host,
 
1422
1381
                                       self.old_server.port)
 
1423
1382
        new_prefix = 'http://%s:%s' % (self.new_server.host,
 
 
1429
1388
            ('/4(.*)', r'%s/5\1' % (new_prefix), 301),
 
1430
1389
            ('(/[^/]+)', r'%s/1\1' % (old_prefix), 301),
 
1432
 
        self.assertEqual('redirected 5 times',t._perform(req).read())
 
 
1391
        self.assertEqual('redirected 5 times', t._perform(req).read())
 
1435
1394
class TestDoCatchRedirections(http_utils.TestCaseWithRedirectedWebserver):
 
1436
1395
    """Test transport.do_catching_redirections."""
 
 
1397
    scenarios = multiply_scenarios(
 
 
1398
        vary_by_http_client_implementation(), 
 
 
1399
        vary_by_http_protocol_version(),
 
1438
1402
    def setUp(self):
 
1439
1403
        super(TestDoCatchRedirections, self).setUp()
 
1440
1404
        self.build_tree_contents([('a', '0123456789'),],)
 
1442
 
        self.old_transport = self._transport(self.old_server.get_url())
 
1444
 
    def get_a(self, transport):
 
1445
 
        return transport.get('a')
 
 
1405
        cleanup_http_redirection_connections(self)
 
 
1407
        self.old_transport = self.get_old_transport()
 
1447
1412
    def test_no_redirection(self):
 
1448
 
        t = self._transport(self.new_server.get_url())
 
 
1413
        t = self.get_new_transport()
 
1450
1415
        # We use None for redirected so that we fail if redirected
 
1451
1416
        self.assertEqual('0123456789',
 
 
1642
1616
        # Only one 'Authentication Required' error should occur
 
1643
1617
        self.assertEqual(1, self.server.auth_required_errors)
 
1645
 
    def test_user_from_auth_conf(self):
 
1646
 
        if self._testing_pycurl():
 
1647
 
            raise tests.TestNotApplicable(
 
1648
 
                'pycurl does not support authentication.conf')
 
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}})
 
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)
 
1664
1619
    def test_changing_nonce(self):
 
1665
1620
        if self._auth_server not in (http_utils.HTTPDigestAuthServer,
 
1666
1621
                                     http_utils.ProxyDigestAuthServer):
 
 
1682
1637
        # initial 'who are you' and a second 'who are you' with the new nonce)
 
1683
1638
        self.assertEqual(2, self.server.auth_required_errors)
 
 
1640
    def test_user_from_auth_conf(self):
 
 
1641
        if self._testing_pycurl():
 
 
1642
            raise tests.TestNotApplicable(
 
 
1643
                'pycurl does not support authentication.conf')
 
 
1646
        self.server.add_user(user, password)
 
 
1647
        _setup_authentication_config(
 
 
1649
            port=self.server.port,
 
 
1652
        t = self.get_user_transport(None, None)
 
 
1653
        # Issue a request to the server to connect
 
 
1654
        self.assertEqual('contents of a\n', t.get('a').read())
 
 
1655
        # Only one 'Authentication Required' error should occur
 
 
1656
        self.assertEqual(1, self.server.auth_required_errors)
 
 
1659
def _setup_authentication_config(**kwargs):
 
 
1660
    conf = config.AuthenticationConfig()
 
 
1661
    conf._get_config().update({'httptest': kwargs})
 
 
1666
class TestUrllib2AuthHandler(tests.TestCaseWithTransport):
 
 
1667
    """Unit tests for glue by which urllib2 asks us for authentication"""
 
 
1669
    def test_get_user_password_without_port(self):
 
 
1670
        """We cope if urllib2 doesn't tell us the port.
 
 
1672
        See https://bugs.launchpad.net/bzr/+bug/654684
 
 
1676
        _setup_authentication_config(
 
 
1681
        handler = _urllib2_wrappers.HTTPAuthHandler()
 
 
1682
        got_pass = handler.get_user_password(dict(
 
 
1689
        self.assertEquals((user, password), got_pass)
 
1687
1692
class TestProxyAuth(TestAuth):
 
1688
1693
    """Test proxy authentication schemes."""
 
 
1695
    scenarios = multiply_scenarios(
 
 
1696
        vary_by_http_client_implementation(),
 
 
1697
        vary_by_http_protocol_version(),
 
 
1698
        vary_by_http_proxy_auth_scheme(),
 
1690
1701
    _auth_header = 'Proxy-authorization'
 
1691
1702
    _password_prompt_prefix = 'Proxy '
 
1692
1703
    _username_prompt_prefix = 'Proxy '
 
 
1748
1760
class SmartHTTPTunnellingTest(tests.TestCaseWithTransport):
 
 
1762
    scenarios = multiply_scenarios(
 
 
1763
        vary_by_http_client_implementation(), 
 
 
1764
        vary_by_http_protocol_version(),
 
1750
1767
    def setUp(self):
 
1751
1768
        super(SmartHTTPTunnellingTest, self).setUp()
 
1752
1769
        # We use the VFS layer as part of HTTP tunnelling tests.
 
1753
1770
        self._captureVar('BZR_NO_SMART_VFS', None)
 
1754
1771
        self.transport_readonly_server = http_utils.HTTPServerWithSmarts
 
 
1772
        self.http_server = self.get_readonly_server()
 
1756
1774
    def create_transport_readonly_server(self):
 
1757
 
        return http_utils.HTTPServerWithSmarts(
 
 
1775
        server = http_utils.HTTPServerWithSmarts(
 
1758
1776
            protocol_version=self._protocol_version)
 
 
1777
        server._url_protocol = self._url_protocol
 
1760
1780
    def test_open_bzrdir(self):
 
1761
1781
        branch = self.make_branch('relpath')
 
1762
 
        http_server = self.get_readonly_server()
 
1763
 
        url = http_server.get_url() + 'relpath'
 
 
1782
        url = self.http_server.get_url() + 'relpath'
 
1764
1783
        bd = bzrdir.BzrDir.open(url)
 
 
1784
        self.addCleanup(bd.transport.disconnect)
 
1765
1785
        self.assertIsInstance(bd, _mod_remote.RemoteBzrDir)
 
1767
1787
    def test_bulk_data(self):
 
 
2095
2112
class TestActivity(tests.TestCase, TestActivityMixin):
 
 
2114
    scenarios = multiply_scenarios(
 
 
2115
        vary_by_http_activity(),
 
 
2116
        vary_by_http_protocol_version(),
 
2097
2119
    def 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)
 
2105
 
            self.activities[direction] = count
 
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
 
2114
 
        self._transport._report_activity = self.orig_report_activity
 
2115
 
        self.server.stop_server()
 
2116
 
        tests.TestCase.tearDown(self)
 
 
2120
        TestActivityMixin.setUp(self)
 
2119
2123
class TestNoReportActivity(tests.TestCase, TestActivityMixin):
 
 
2125
    # Unlike TestActivity, we are really testing ReportingFileSocket and
 
 
2126
    # ReportingSocket, so we don't need all the parametrization. Since
 
 
2127
    # ReportingFileSocket and ReportingSocket are wrappers, it's easier to
 
 
2128
    # test them through their use by the transport than directly (that's a
 
 
2129
    # bit less clean but far more simpler and effective).
 
 
2130
    _activity_server = ActivityHTTPServer
 
 
2131
    _protocol_version = 'HTTP/1.1'
 
2121
2133
    def 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
 
2131
 
        self.server.start_server()
 
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
 
2140
 
        self._transport._report_activity = self.orig_report_activity
 
2141
 
        self.server.stop_server()
 
2142
 
        tests.TestCase.tearDown(self)
 
 
2134
        self._transport =_urllib.HttpTransport_urllib
 
 
2135
        TestActivityMixin.setUp(self)
 
2144
2137
    def assertActivitiesMatch(self):
 
2145
2138
        # Nothing to check here
 
 
2176
2160
                                       self.new_server.port)
 
2177
2161
        self.old_server.redirections = [
 
2178
2162
            ('(.*)', r'%s/1\1' % (new_prefix), 301),]
 
2179
 
        self.old_transport = self._transport(self.old_server.get_url())
 
 
2163
        self.old_transport = self.get_old_transport()
 
2180
2164
        self.new_server.add_user('joe', 'foo')
 
2182
 
    def get_a(self, transport):
 
2183
 
        return transport.get('a')
 
 
2165
        cleanup_http_redirection_connections(self)
 
 
2167
    def create_transport_readonly_server(self):
 
 
2168
        server = self._auth_server(protocol_version=self._protocol_version)
 
 
2169
        server._url_protocol = self._url_protocol
 
2185
2175
    def test_auth_on_redirected_via_do_catching_redirections(self):
 
2186
2176
        self.redirections = 0
 
2188
 
        def redirected(transport, exception, redirection_notice):
 
 
2178
        def redirected(t, exception, redirection_notice):
 
2189
2179
            self.redirections += 1
 
2190
 
            dir, file = urlutils.split(exception.target)
 
2191
 
            return self._transport(dir)
 
 
2180
            redirected_t = t._redirected_to(exception.source, exception.target)
 
 
2181
            self.addCleanup(redirected_t.disconnect)
 
2193
2184
        stdout = tests.StringIOWrapper()
 
2194
2185
        stderr = tests.StringIOWrapper()