/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/tests/test_http.py

Merge trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
63
63
    )
64
64
 
65
65
 
66
 
if features.pycurl.available():
67
 
    from ..transport.http._pycurl import PyCurlTransport
68
 
 
69
 
 
70
66
load_tests = load_tests_apply_scenarios
71
67
 
72
68
 
73
69
def vary_by_http_client_implementation():
74
 
    """Test the two libraries we can use, pycurl and urllib."""
 
70
    """Test the libraries we can use, currently just urllib."""
75
71
    transport_scenarios = [
76
72
        ('urllib', dict(_transport=_urllib.HttpTransport_urllib,
77
73
                        _server=http_server.HttpServer_urllib,
78
74
                        _url_protocol='http+urllib',)),
79
75
        ]
80
 
    if features.pycurl.available():
81
 
        transport_scenarios.append(
82
 
            ('pycurl', dict(_transport=PyCurlTransport,
83
 
                            _server=http_server.HttpServer_PyCurl,
84
 
                            _url_protocol='http+pycurl',)))
85
76
    return transport_scenarios
86
77
 
87
78
 
128
119
        ('urllib,http', dict(_activity_server=ActivityHTTPServer,
129
120
                            _transport=_urllib.HttpTransport_urllib,)),
130
121
        ]
131
 
    if features.pycurl.available():
132
 
        activity_scenarios.append(
133
 
            ('pycurl,http', dict(_activity_server=ActivityHTTPServer,
134
 
                                _transport=PyCurlTransport,)),)
135
122
    if features.HTTPSServerFeature.available():
136
123
        # FIXME: Until we have a better way to handle self-signed certificates
137
124
        # (like allowing them in a test specific authentication.conf for
138
 
        # example), we need some specialized pycurl/urllib transport for tests.
 
125
        # example), we need some specialized urllib transport for tests.
139
126
        # -- vila 2012-01-20
140
127
        from . import (
141
128
            ssl_certs,
150
137
        activity_scenarios.append(
151
138
            ('urllib,https', dict(_activity_server=ActivityHTTPSServer,
152
139
                                  _transport=HTTPS_urllib_transport,)),)
153
 
        if features.pycurl.available():
154
 
            class HTTPS_pycurl_transport(PyCurlTransport):
155
 
 
156
 
                def __init__(self, base, _from_transport=None):
157
 
                    super(HTTPS_pycurl_transport, self).__init__(
158
 
                        base, _from_transport)
159
 
                    self.cabundle = str(ssl_certs.build_path('ca.crt'))
160
 
 
161
 
            activity_scenarios.append(
162
 
                ('pycurl,https', dict(_activity_server=ActivityHTTPSServer,
163
 
                                    _transport=HTTPS_pycurl_transport,)),)
164
140
    return activity_scenarios
165
141
 
166
142
 
385
361
                              http_server.TestingHTTPServer)
386
362
 
387
363
 
388
 
class TestWithTransport_pycurl(object):
389
 
    """Test case to inherit from if pycurl is present"""
390
 
 
391
 
    def _get_pycurl_maybe(self):
392
 
        self.requireFeature(features.pycurl)
393
 
        return PyCurlTransport
394
 
 
395
 
    _transport = property(_get_pycurl_maybe)
396
 
 
397
 
 
398
364
class TestHttpTransportUrls(tests.TestCase):
399
365
    """Test the http urls."""
400
366
 
435
401
            server.stop_server()
436
402
 
437
403
 
438
 
class TestHttps_pycurl(TestWithTransport_pycurl, tests.TestCase):
439
 
 
440
 
    # TODO: This should really be moved into another pycurl
441
 
    # specific test. When https tests will be implemented, take
442
 
    # this one into account.
443
 
    def test_pycurl_without_https_support(self):
444
 
        """Test that pycurl without SSL do not fail with a traceback.
445
 
 
446
 
        For the purpose of the test, we force pycurl to ignore
447
 
        https by supplying a fake version_info that do not
448
 
        support it.
449
 
        """
450
 
        self.requireFeature(features.pycurl)
451
 
        # Import the module locally now that we now it's available.
452
 
        pycurl = features.pycurl.module
453
 
 
454
 
        self.overrideAttr(pycurl, 'version_info',
455
 
                          # Fake the pycurl version_info This was taken from
456
 
                          # a windows pycurl without SSL (thanks to bialix)
457
 
                          lambda : (2,
458
 
                                    '7.13.2',
459
 
                                    462082,
460
 
                                    'i386-pc-win32',
461
 
                                    2576,
462
 
                                    None,
463
 
                                    0,
464
 
                                    None,
465
 
                                    ('ftp', 'gopher', 'telnet',
466
 
                                     'dict', 'ldap', 'http', 'file'),
467
 
                                    None,
468
 
                                    0,
469
 
                                    None))
470
 
        self.assertRaises(errors.DependencyNotPresent, self._transport,
471
 
                          'https://launchpad.net')
472
 
 
473
 
 
474
404
class TestHTTPConnections(http_utils.TestCaseWithWebserver):
475
405
    """Test the http connections."""
476
406
 
613
543
        server._url_protocol = self._url_protocol
614
544
        return server
615
545
 
616
 
    def _testing_pycurl(self):
617
 
        # TODO: This is duplicated for lots of the classes in this file
618
 
        return (features.pycurl.available()
619
 
                and self._transport == PyCurlTransport)
620
 
 
621
546
 
622
547
class WallRequestHandler(http_server.TestingHTTPRequestHandler):
623
548
    """Whatever request comes in, close the connection"""
638
563
        # for details) make no distinction between a closed
639
564
        # socket and badly formatted status line, so we can't
640
565
        # just test for ConnectionError, we have to test
641
 
        # InvalidHttpResponse too. And pycurl may raise ConnectionReset
642
 
        # instead of ConnectionError too.
643
 
        self.assertRaises(( errors.ConnectionError, errors.ConnectionReset,
644
 
                            errors.InvalidHttpResponse),
 
566
        # InvalidHttpResponse too.
 
567
        self.assertRaises((errors.ConnectionError,
 
568
                           errors.InvalidHttpResponse),
645
569
                          t.has, 'foo/bar')
646
570
 
647
571
    def test_http_get(self):
733
657
 
734
658
    _req_handler_class = BadProtocolRequestHandler
735
659
 
736
 
    def setUp(self):
737
 
        if self._testing_pycurl():
738
 
            raise tests.TestNotApplicable(
739
 
                "pycurl doesn't check the protocol version")
740
 
        super(TestBadProtocolServer, self).setUp()
741
 
 
742
660
    def test_http_has(self):
743
661
        t = self.get_readonly_transport()
744
662
        self.assertRaises(errors.InvalidHttpResponse, t.has, 'foo/bar')
1047
965
        ireadv = iter(t.readv('a', ((0, 1), (2, 1), (4, 2), (9, 1))))
1048
966
        self.assertEqual((0, '0'), next(ireadv))
1049
967
        self.assertEqual((2, '2'), next(ireadv))
1050
 
        if not self._testing_pycurl():
1051
 
            # Only one request have been issued so far (except for pycurl that
1052
 
            # try to read the whole response at once)
1053
 
            self.assertEqual(1, server.GET_request_nb)
 
968
        # Only one request have been issued so far
 
969
        self.assertEqual(1, server.GET_request_nb)
1054
970
        self.assertEqual((4, '45'), next(ireadv))
1055
971
        self.assertEqual((9, '9'), next(ireadv))
1056
 
        # Both implementations issue 3 requests but:
1057
 
        # - urllib does two multiple (4 ranges, then 2 ranges) then a single
1058
 
        #   range,
1059
 
        # - pycurl does two multiple (4 ranges, 4 ranges) then a single range
 
972
        # We issue 3 requests: two multiple (4 ranges, then 2 ranges) then a
 
973
        # single range.
1060
974
        self.assertEqual(3, server.GET_request_nb)
1061
975
        # Finally the client have tried a single range request and stays in
1062
976
        # that mode
1276
1190
        # Let's setup some attributes for tests
1277
1191
        server = self.get_readonly_server()
1278
1192
        self.server_host_port = '%s:%d' % (server.host, server.port)
1279
 
        if self._testing_pycurl():
1280
 
            # Oh my ! pycurl does not check for the port as part of
1281
 
            # no_proxy :-( So we just test the host part
1282
 
            self.no_proxy_host = server.host
1283
 
        else:
1284
 
            self.no_proxy_host = self.server_host_port
 
1193
        self.no_proxy_host = self.server_host_port
1285
1194
        # The secondary server is the proxy
1286
1195
        self.proxy_url = self.get_secondary_url()
1287
 
        if self._testing_pycurl():
1288
 
            self.proxy_url = self.proxy_url.replace('+pycurl', '')
1289
 
 
1290
 
    def _testing_pycurl(self):
1291
 
        # TODO: This is duplicated for lots of the classes in this file
1292
 
        return (features.pycurl.available()
1293
 
                and self._transport == PyCurlTransport)
1294
1196
 
1295
1197
    def assertProxied(self):
1296
1198
        t = self.get_readonly_transport()
1305
1207
        self.assertProxied()
1306
1208
 
1307
1209
    def test_HTTP_PROXY(self):
1308
 
        if self._testing_pycurl():
1309
 
            # pycurl does not check HTTP_PROXY for security reasons
1310
 
            # (for use in a CGI context that we do not care
1311
 
            # about. Should we ?)
1312
 
            raise tests.TestNotApplicable(
1313
 
                'pycurl does not check HTTP_PROXY for security reasons')
1314
1210
        self.overrideEnv('HTTP_PROXY', self.proxy_url)
1315
1211
        self.assertProxied()
1316
1212
 
1328
1224
        self.assertNotProxied()
1329
1225
 
1330
1226
    def test_HTTP_PROXY_with_NO_PROXY(self):
1331
 
        if self._testing_pycurl():
1332
 
            raise tests.TestNotApplicable(
1333
 
                'pycurl does not check HTTP_PROXY for security reasons')
1334
1227
        self.overrideEnv('NO_PROXY', self.no_proxy_host)
1335
1228
        self.overrideEnv('HTTP_PROXY', self.proxy_url)
1336
1229
        self.assertNotProxied()
1347
1240
 
1348
1241
    def test_http_proxy_without_scheme(self):
1349
1242
        self.overrideEnv('http_proxy', self.server_host_port)
1350
 
        if self._testing_pycurl():
1351
 
            # pycurl *ignores* invalid proxy env variables. If that ever change
1352
 
            # in the future, this test will fail indicating that pycurl do not
1353
 
            # ignore anymore such variables.
1354
 
            self.assertNotProxied()
1355
 
        else:
1356
 
            self.assertRaises(errors.InvalidURL, self.assertProxied)
 
1243
        self.assertRaises(errors.InvalidURL, self.assertProxied)
1357
1244
 
1358
1245
 
1359
1246
class TestRanges(http_utils.TestCaseWithWebserver):
1475
1362
    do not redirect at all in fact). The mechanism is still in
1476
1363
    place at the _urllib2_wrappers.Request level and these tests
1477
1364
    exercise it.
1478
 
 
1479
 
    For the pycurl implementation
1480
 
    the redirection have been deleted as we may deprecate pycurl
1481
 
    and I have no place to keep a working implementation.
1482
 
    -- vila 20070212
1483
1365
    """
1484
1366
 
1485
1367
    scenarios = multiply_scenarios(
1488
1370
        )
1489
1371
 
1490
1372
    def setUp(self):
1491
 
        if (features.pycurl.available()
1492
 
            and self._transport == PyCurlTransport):
1493
 
            raise tests.TestNotApplicable(
1494
 
                "pycurl doesn't redirect silently anymore")
1495
1373
        super(TestHTTPSilentRedirections, self).setUp()
1496
1374
        install_redirected_request(self)
1497
1375
        cleanup_http_redirection_connections(self)
1635
1513
        server._url_protocol = self._url_protocol
1636
1514
        return server
1637
1515
 
1638
 
    def _testing_pycurl(self):
1639
 
        # TODO: This is duplicated for lots of the classes in this file
1640
 
        return (features.pycurl.available()
1641
 
                and self._transport == PyCurlTransport)
1642
 
 
1643
1516
    def get_user_url(self, user, password):
1644
1517
        """Build an url embedding user and password"""
1645
1518
        url = '%s://' % self.server._url_protocol
1695
1568
        self.assertEqual(2, self.server.auth_required_errors)
1696
1569
 
1697
1570
    def test_prompt_for_username(self):
1698
 
        if self._testing_pycurl():
1699
 
            raise tests.TestNotApplicable(
1700
 
                'pycurl cannot prompt, it handles auth by embedding'
1701
 
                ' user:pass in urls only')
1702
 
 
1703
1571
        self.server.add_user('joe', 'foo')
1704
1572
        t = self.get_user_transport(None, None)
1705
1573
        ui.ui_factory = tests.TestUIFactory(stdin='joe\nfoo\n')
1715
1583
                                    stderr.readline())
1716
1584
 
1717
1585
    def test_prompt_for_password(self):
1718
 
        if self._testing_pycurl():
1719
 
            raise tests.TestNotApplicable(
1720
 
                'pycurl cannot prompt, it handles auth by embedding'
1721
 
                ' user:pass in urls only')
1722
 
 
1723
1586
        self.server.add_user('joe', 'foo')
1724
1587
        t = self.get_user_transport('joe', None)
1725
1588
        ui.ui_factory = tests.TestUIFactory(stdin='foo\n')
1754
1617
                                 self.server.auth_realm))
1755
1618
 
1756
1619
    def test_no_prompt_for_password_when_using_auth_config(self):
1757
 
        if self._testing_pycurl():
1758
 
            raise tests.TestNotApplicable(
1759
 
                'pycurl does not support authentication.conf'
1760
 
                ' since it cannot prompt')
1761
 
 
1762
1620
        user =' joe'
1763
1621
        password = 'foo'
1764
1622
        stdin_content = 'bar\n'  # Not the right password
1779
1637
        if self._auth_server not in (http_utils.HTTPDigestAuthServer,
1780
1638
                                     http_utils.ProxyDigestAuthServer):
1781
1639
            raise tests.TestNotApplicable('HTTP/proxy auth digest only test')
1782
 
        if self._testing_pycurl():
1783
 
            self.knownFailure(
1784
 
                'pycurl does not handle a nonce change')
1785
1640
        self.server.add_user('joe', 'foo')
1786
1641
        t = self.get_user_transport('joe', 'foo')
1787
1642
        self.assertEqual('contents of a\n', t.get('a').read())
1797
1652
        self.assertEqual(2, self.server.auth_required_errors)
1798
1653
 
1799
1654
    def test_user_from_auth_conf(self):
1800
 
        if self._testing_pycurl():
1801
 
            raise tests.TestNotApplicable(
1802
 
                'pycurl does not support authentication.conf')
1803
1655
        user = 'joe'
1804
1656
        password = 'foo'
1805
1657
        self.server.add_user(user, password)
1862
1714
 
1863
1715
    def get_user_transport(self, user, password):
1864
1716
        proxy_url = self.get_user_url(user, password)
1865
 
        if self._testing_pycurl():
1866
 
            proxy_url = proxy_url.replace('+pycurl', '')
1867
1717
        self.overrideEnv('all_proxy', proxy_url)
1868
1718
        return TestAuth.get_user_transport(self, user, password)
1869
1719
 
1870
 
    def test_empty_pass(self):
1871
 
        if self._testing_pycurl():
1872
 
            import pycurl
1873
 
            if pycurl.version_info()[1] < '7.16.0':
1874
 
                self.knownFailure(
1875
 
                    'pycurl < 7.16.0 does not handle empty proxy passwords')
1876
 
        super(TestProxyAuth, self).test_empty_pass()
1877
 
 
1878
1720
 
1879
1721
class NonClosingBytesIO(io.BytesIO):
1880
1722