86
86
def vary_by_http_protocol_version():
87
87
"""Test on http/1.0 and 1.1"""
89
('HTTP/1.0', dict(_protocol_version='HTTP/1.0')),
90
('HTTP/1.1', dict(_protocol_version='HTTP/1.1')),
89
('HTTP/1.0', dict(_protocol_version='HTTP/1.0')),
90
('HTTP/1.1', dict(_protocol_version='HTTP/1.1')),
124
124
def vary_by_http_activity():
125
125
activity_scenarios = [
126
126
('urllib,http', dict(_activity_server=ActivityHTTPServer,
127
_transport=HttpTransport,)),
127
_transport=HttpTransport,)),
129
129
if features.HTTPSServerFeature.available():
130
130
# FIXME: Until we have a better way to handle self-signed certificates
226
225
def parse_header(self, header, auth_handler_class=None):
227
226
if auth_handler_class is None:
228
auth_handler_class = http.AbstractAuthHandler
229
self.auth_handler = auth_handler_class()
227
auth_handler_class = _urllib2_wrappers.AbstractAuthHandler
228
self.auth_handler = auth_handler_class()
230
229
return self.auth_handler._parse_auth_header(header)
232
231
def test_empty_header(self):
258
257
def test_basic_extract_realm(self):
259
258
scheme, remainder = self.parse_header(
260
259
'Basic realm="Thou should not pass"',
261
http.BasicAuthHandler)
260
_urllib2_wrappers.BasicAuthHandler)
262
261
match, realm = self.auth_handler.extract_realm(remainder)
263
262
self.assertTrue(match is not None)
264
self.assertEqual(u'Thou should not pass', realm)
263
self.assertEqual('Thou should not pass', realm)
266
265
def test_digest_header(self):
267
266
scheme, remainder = self.parse_header(
276
275
super(TestHTTPRangeParsing, self).setUp()
277
276
# We focus on range parsing here and ignore everything else
279
277
class RequestHandler(http_server.TestingHTTPRequestHandler):
280
278
def setup(self): pass
282
279
def handle(self): pass
284
280
def finish(self): pass
286
282
self.req_handler = RequestHandler(None, None, None)
288
284
def assertRanges(self, ranges, header, file_size):
289
285
self.assertEqual(ranges,
290
self.req_handler._parse_ranges(header, file_size))
286
self.req_handler._parse_ranges(header, file_size))
292
288
def test_simple_range(self):
293
289
self.assertRanges([(0, 2)], 'bytes=0-2', 12)
431
427
self.assertEqual(t.has('foo/bar'), True)
432
428
self.assertEqual(len(server.logs), 1)
433
429
self.assertContainsRe(server.logs[0],
434
r'"HEAD /foo/bar HTTP/1.." (200|302) - "-" "Breezy/')
430
r'"HEAD /foo/bar HTTP/1.." (200|302) - "-" "Breezy/')
436
432
def test_http_has_not_found(self):
437
433
server = self.get_readonly_server()
438
434
t = self.get_readonly_transport()
439
435
self.assertEqual(t.has('not-found'), False)
440
436
self.assertContainsRe(server.logs[1],
441
r'"HEAD /not-found HTTP/1.." 404 - "-" "Breezy/')
437
r'"HEAD /not-found HTTP/1.." 404 - "-" "Breezy/')
443
439
def test_http_get(self):
444
440
server = self.get_readonly_server()
489
485
def test_post_body_is_received(self):
490
server = RecordingServer(expect_body_tail=b'end-of-body',
486
server = RecordingServer(expect_body_tail='end-of-body',
491
487
scheme=self._url_protocol)
492
488
self.start_server(server)
493
489
url = server.get_url()
494
490
# FIXME: needs a cleanup -- vila 20100611
495
491
http_transport = transport.get_transport_from_url(url)
496
code, response = http_transport._post(b'abc def end-of-body')
498
server.received_bytes.startswith(b'POST /.bzr/smart HTTP/1.'))
500
b'content-length: 19\r' in server.received_bytes.lower())
501
self.assertTrue(b'content-type: application/octet-stream\r'
492
code, response = http_transport._post('abc def end-of-body')
494
server.received_bytes.startswith('POST /.bzr/smart HTTP/1.'))
495
self.assertTrue('content-length: 19\r' in server.received_bytes.lower())
496
self.assertTrue('content-type: application/octet-stream\r'
502
497
in server.received_bytes.lower())
503
498
# The transport should not be assuming that the server can accept
504
499
# chunked encoding the first time it connects, because HTTP/1.1, so we
505
500
# check for the literal string.
507
server.received_bytes.endswith(b'\r\n\r\nabc def end-of-body'))
502
server.received_bytes.endswith('\r\n\r\nabc def end-of-body'))
510
505
class TestRangeHeader(tests.TestCase):
511
506
"""Test range_header method"""
513
508
def check_header(self, value, ranges=[], tail=0):
514
offsets = [(start, end - start + 1) for start, end in ranges]
509
offsets = [ (start, end - start + 1) for start, end in ranges]
515
510
coalesce = transport.Transport._coalesce_offsets
516
511
coalesced = list(coalesce(offsets, limit=0, fudge_factor=0))
517
512
range_header = http.HttpTransport._range_header
633
628
def parse_request(self):
634
629
"""Fakes handling a single HTTP request, returns a bad status"""
635
630
ignored = http_server.TestingHTTPRequestHandler.parse_request(self)
636
self.wfile.write(b"Invalid status line\r\n")
631
self.wfile.write("Invalid status line\r\n")
637
632
# If we don't close the connection pycurl will hang. Since this is a
638
633
# stress test we don't *have* to respect the protocol, but we don't
639
634
# have to sabotage it too much either.
658
653
ignored = http_server.TestingHTTPRequestHandler.parse_request(self)
659
654
# Returns an invalid protocol version, but curl just
660
655
# ignores it and those cannot be tested.
661
self.wfile.write(b"%s %d %s\r\n" % (
662
b'HTTP/0.0', 404, b'Look at my protocol version'))
656
self.wfile.write("%s %d %s\r\n" % ('HTTP/0.0',
658
'Look at my protocol version'))
721
717
self.assertEqual(None, server.port)
723
719
def test_send_receive_bytes(self):
724
server = RecordingServer(expect_body_tail=b'c', scheme='http')
720
server = RecordingServer(expect_body_tail='c', scheme='http')
725
721
self.start_server(server)
726
722
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
727
723
sock.connect((server.host, server.port))
729
self.assertEqual(b'HTTP/1.1 200 OK\r\n',
725
self.assertEqual('HTTP/1.1 200 OK\r\n',
730
726
osutils.recv_all(sock, 4096))
731
self.assertEqual(b'abc', server.received_bytes)
727
self.assertEqual('abc', server.received_bytes)
734
730
class TestRangeRequestServer(TestSpecificRequestHandler):
744
740
def test_readv(self):
745
741
t = self.get_readonly_transport()
746
742
l = list(t.readv('a', ((0, 1), (1, 1), (3, 2), (9, 1))))
747
self.assertEqual(l[0], (0, b'0'))
748
self.assertEqual(l[1], (1, b'1'))
749
self.assertEqual(l[2], (3, b'34'))
750
self.assertEqual(l[3], (9, b'9'))
743
self.assertEqual(l[0], (0, '0'))
744
self.assertEqual(l[1], (1, '1'))
745
self.assertEqual(l[2], (3, '34'))
746
self.assertEqual(l[3], (9, '9'))
752
748
def test_readv_out_of_order(self):
753
749
t = self.get_readonly_transport()
754
750
l = list(t.readv('a', ((1, 1), (9, 1), (0, 1), (3, 2))))
755
self.assertEqual(l[0], (1, b'1'))
756
self.assertEqual(l[1], (9, b'9'))
757
self.assertEqual(l[2], (0, b'0'))
758
self.assertEqual(l[3], (3, b'34'))
751
self.assertEqual(l[0], (1, '1'))
752
self.assertEqual(l[1], (9, '9'))
753
self.assertEqual(l[2], (0, '0'))
754
self.assertEqual(l[3], (3, '34'))
760
756
def test_readv_invalid_ranges(self):
761
757
t = self.get_readonly_transport()
777
773
t._max_readv_combine = 1
778
774
t._max_get_ranges = 1
779
775
l = list(t.readv('a', ((0, 1), (1, 1), (3, 2), (9, 1))))
780
self.assertEqual(l[0], (0, b'0'))
781
self.assertEqual(l[1], (1, b'1'))
782
self.assertEqual(l[2], (3, b'34'))
783
self.assertEqual(l[3], (9, b'9'))
776
self.assertEqual(l[0], (0, '0'))
777
self.assertEqual(l[1], (1, '1'))
778
self.assertEqual(l[2], (3, '34'))
779
self.assertEqual(l[3], (9, '9'))
784
780
# The server should have issued 4 requests
785
781
self.assertEqual(4, server.GET_request_nb)
792
788
# single range will keep its size even if bigger than the limit.
793
789
t._get_max_size = 2
794
790
l = list(t.readv('a', ((0, 1), (1, 1), (2, 4), (6, 4))))
795
self.assertEqual(l[0], (0, b'0'))
796
self.assertEqual(l[1], (1, b'1'))
797
self.assertEqual(l[2], (2, b'2345'))
798
self.assertEqual(l[3], (6, b'6789'))
791
self.assertEqual(l[0], (0, '0'))
792
self.assertEqual(l[1], (1, '1'))
793
self.assertEqual(l[2], (2, '2345'))
794
self.assertEqual(l[3], (6, '6789'))
799
795
# The server should have issued 3 requests
800
796
self.assertEqual(3, server.GET_request_nb)
807
803
list(t.readv('a', ((0, 1), (1, 1), (2, 4), (6, 4))))
808
804
# The server should have issued 3 requests
809
805
self.assertEqual(3, server.GET_request_nb)
810
self.assertEqual(b'0123456789', t.get_bytes('a'))
806
self.assertEqual('0123456789', t.get_bytes('a'))
811
807
self.assertEqual(4, server.GET_request_nb)
813
809
def test_incomplete_readv_leave_pipe_clean(self):
818
814
# Don't collapse readv results into a list so that we leave unread
819
815
# bytes on the socket
820
816
ireadv = iter(t.readv('a', ((0, 1), (1, 1), (2, 4), (6, 4))))
821
self.assertEqual((0, b'0'), next(ireadv))
817
self.assertEqual((0, '0'), next(ireadv))
822
818
# The server should have issued one request so far
823
819
self.assertEqual(1, server.GET_request_nb)
824
self.assertEqual(b'0123456789', t.get_bytes('a'))
820
self.assertEqual('0123456789', t.get_bytes('a'))
825
821
# get_bytes issued an additional request, the readv pending ones are
827
823
self.assertEqual(2, server.GET_request_nb)
894
890
"multipart/byteranges; boundary=%s" % boundary)
895
891
self.end_headers()
896
892
for (start, end) in ranges:
897
self.wfile.write(b"--%s\r\n" % boundary.encode('ascii'))
893
self.wfile.write("--%s\r\n" % boundary)
898
894
self.send_header("Content-type", 'application/octet-stream')
899
895
self.send_header("Content-Range", "bytes %d-%d/%d" % (start,
936
932
'Content-type', 'application/octet-stream')
937
933
content_length += self._header_line_length(
938
934
'Content-Range', 'bytes %d-%d/%d' % (start, end, file_size))
939
content_length += len('\r\n') # end headers
940
content_length += end - start # + 1
935
content_length += len('\r\n') # end headers
936
content_length += end - start # + 1
941
937
content_length += len(boundary_line)
942
938
self.send_header('Content-length', content_length)
943
939
self.end_headers()
974
970
# Force separate ranges for each offset
975
971
t._bytes_to_read_before_seek = 0
976
972
ireadv = iter(t.readv('a', ((0, 1), (2, 1), (4, 2), (9, 1))))
977
self.assertEqual((0, b'0'), next(ireadv))
978
self.assertEqual((2, b'2'), next(ireadv))
973
self.assertEqual((0, '0'), next(ireadv))
974
self.assertEqual((2, '2'), next(ireadv))
979
975
# Only one request have been issued so far
980
976
self.assertEqual(1, server.GET_request_nb)
981
self.assertEqual((4, b'45'), next(ireadv))
982
self.assertEqual((9, b'9'), next(ireadv))
977
self.assertEqual((4, '45'), next(ireadv))
978
self.assertEqual((9, '9'), next(ireadv))
983
979
# We issue 3 requests: two multiple (4 ranges, then 2 ranges) then a
985
981
self.assertEqual(3, server.GET_request_nb)
1009
1005
'Content-type', 'application/octet-stream')
1010
1006
content_length += self._header_line_length(
1011
1007
'Content-Range', 'bytes %d-%d/%d' % (start, end, file_size))
1012
content_length += len('\r\n') # end headers
1013
content_length += end - start # + 1
1008
content_length += len('\r\n') # end headers
1009
content_length += end - start # + 1
1014
1010
content_length += len(boundary_line)
1015
1011
self.send_header('Content-length', content_length)
1016
1012
self.end_headers()
1048
1044
# Force separate ranges for each offset
1049
1045
t._bytes_to_read_before_seek = 0
1050
1046
ireadv = iter(t.readv('a', ((0, 1), (2, 1), (4, 2), (9, 1))))
1051
self.assertEqual((0, b'0'), next(ireadv))
1052
self.assertEqual((2, b'2'), next(ireadv))
1053
self.assertEqual((4, b'45'), next(ireadv))
1054
self.assertEqual((9, b'9'), next(ireadv))
1047
self.assertEqual((0, '0'), next(ireadv))
1048
self.assertEqual((2, '2'), next(ireadv))
1049
self.assertEqual((4, '45'), next(ireadv))
1050
self.assertEqual((9, '9'), next(ireadv))
1057
1053
class LimitedRangeRequestHandler(http_server.TestingHTTPRequestHandler):
1106
1102
def test_few_ranges(self):
1107
1103
t = self.get_readonly_transport()
1108
1104
l = list(t.readv('a', ((0, 4), (1024, 4), )))
1109
self.assertEqual(l[0], (0, b'0000'))
1110
self.assertEqual(l[1], (1024, b'0001'))
1105
self.assertEqual(l[0], (0, '0000'))
1106
self.assertEqual(l[1], (1024, '0001'))
1111
1107
self.assertEqual(1, self.get_readonly_server().GET_request_nb)
1113
1109
def test_more_ranges(self):
1114
1110
t = self.get_readonly_transport()
1115
1111
l = list(t.readv('a', ((0, 4), (1024, 4), (4096, 4), (8192, 4))))
1116
self.assertEqual(l[0], (0, b'0000'))
1117
self.assertEqual(l[1], (1024, b'0001'))
1118
self.assertEqual(l[2], (4096, b'0004'))
1119
self.assertEqual(l[3], (8192, b'0008'))
1112
self.assertEqual(l[0], (0, '0000'))
1113
self.assertEqual(l[1], (1024, '0001'))
1114
self.assertEqual(l[2], (4096, '0004'))
1115
self.assertEqual(l[3], (8192, '0008'))
1120
1116
# The server will refuse to serve the first request (too much ranges),
1121
1117
# a second request will succeed.
1122
1118
self.assertEqual(2, self.get_readonly_server().GET_request_nb)
1131
1127
def _proxied_request(self):
1132
handler = http.ProxyHandler()
1133
request = http.Request('GET', 'http://baz/buzzle')
1128
handler = _urllib2_wrappers.ProxyHandler()
1129
request = _urllib2_wrappers.Request('GET', 'http://baz/buzzle')
1134
1130
handler.set_proxy(request, 'http')
1137
1133
def assertEvaluateProxyBypass(self, expected, host, no_proxy):
1138
handler = http.ProxyHandler()
1134
handler = _urllib2_wrappers.ProxyHandler()
1139
1135
self.assertEqual(expected,
1140
handler.evaluate_proxy_bypass(host, no_proxy))
1136
handler.evaluate_proxy_bypass(host, no_proxy))
1142
1138
def test_empty_user(self):
1143
1139
self.overrideEnv('http_proxy', 'http://bar.com')
1208
1204
def assertProxied(self):
1209
1205
t = self.get_readonly_transport()
1210
self.assertEqual(b'proxied contents of foo\n', t.get('foo').read())
1206
self.assertEqual('proxied contents of foo\n', t.get('foo').read())
1212
1208
def assertNotProxied(self):
1213
1209
t = self.get_readonly_transport()
1214
self.assertEqual(b'contents of foo\n', t.get('foo').read())
1210
self.assertEqual('contents of foo\n', t.get('foo').read())
1216
1212
def test_http_proxy(self):
1217
1213
self.overrideEnv('http_proxy', self.proxy_url)
1272
1268
def _file_contents(self, relpath, ranges):
1273
1269
t = self.get_readonly_transport()
1274
offsets = [(start, end - start + 1) for start, end in ranges]
1270
offsets = [ (start, end - start + 1) for start, end in ranges]
1275
1271
coalesce = t._coalesce_offsets
1276
1272
coalesced = list(coalesce(offsets, limit=0, fudge_factor=0))
1277
1273
code, data = t._get(relpath, coalesced)
1290
1286
def test_range_header(self):
1292
1288
self.assertEqual(
1293
[b'0', b'234'], list(self._file_contents('a', [(0, 0), (2, 4)])))
1289
['0', '234'], list(self._file_contents('a', [(0, 0), (2, 4)])))
1295
1291
def test_range_header_tail(self):
1296
self.assertEqual(b'789', self._file_tail('a', 3))
1292
self.assertEqual('789', self._file_tail('a', 3))
1298
1294
def test_syntactically_invalid_range_header(self):
1299
1295
self.assertListRaises(errors.InvalidHttpRange,
1300
self._file_contents, 'a', [(4, 3)])
1296
self._file_contents, 'a', [(4, 3)])
1302
1298
def test_semantically_invalid_range_header(self):
1303
1299
self.assertListRaises(errors.InvalidHttpRange,
1304
self._file_contents, 'a', [(42, 128)])
1300
self._file_contents, 'a', [(42, 128)])
1307
1303
class TestHTTPRedirections(http_utils.TestCaseWithRedirectedWebserver):
1316
1312
super(TestHTTPRedirections, self).setUp()
1317
1313
self.build_tree_contents([('a', b'0123456789'),
1319
b'# Bazaar revision bundle v0.9\n#\n')
1315
b'# Bazaar revision bundle v0.9\n#\n')
1322
1318
def test_redirected(self):
1323
1319
self.assertRaises(errors.RedirectRequested,
1324
1320
self.get_old_transport().get, 'a')
1327
self.get_new_transport().get('a').read())
1330
class RedirectedRequest(http.Request):
1321
self.assertEqual('0123456789', self.get_new_transport().get('a').read())
1324
class RedirectedRequest(_urllib2_wrappers.Request):
1331
1325
"""Request following redirections. """
1333
init_orig = http.Request.__init__
1327
init_orig = _urllib2_wrappers.Request.__init__
1335
1329
def __init__(self, method, url, *args, **kwargs):
1336
1330
"""Constructor.
1339
1333
# Since the tests using this class will replace
1340
# http.Request, we can't just call the base class __init__
1334
# _urllib2_wrappers.Request, we can't just call the base class __init__
1341
1335
# or we'll loop.
1342
1336
RedirectedRequest.init_orig(self, method, url, *args, **kwargs)
1343
1337
self.follow_redirections = True
1346
1340
def install_redirected_request(test):
1347
test.overrideAttr(http, 'Request', RedirectedRequest)
1341
test.overrideAttr(_urllib2_wrappers, 'Request', RedirectedRequest)
1350
1344
def cleanup_http_redirection_connections(test):
1351
1345
# Some sockets are opened but never seen by _urllib, so we trap them at
1352
# the http level to be able to clean them up.
1346
# the _urllib2_wrappers level to be able to clean them up.
1353
1347
def socket_disconnect(sock):
1355
1349
sock.shutdown(socket.SHUT_RDWR)
1357
1351
except socket.error:
1360
1353
def connect(connection):
1361
1354
test.http_connect_orig(connection)
1362
1355
test.addCleanup(socket_disconnect, connection.sock)
1363
1356
test.http_connect_orig = test.overrideAttr(
1364
http.HTTPConnection, 'connect', connect)
1357
_urllib2_wrappers.HTTPConnection, 'connect', connect)
1366
1358
def connect(connection):
1367
1359
test.https_connect_orig(connection)
1368
1360
test.addCleanup(socket_disconnect, connection.sock)
1369
1361
test.https_connect_orig = test.overrideAttr(
1370
http.HTTPSConnection, 'connect', connect)
1362
_urllib2_wrappers.HTTPSConnection, 'connect', connect)
1373
1365
class TestHTTPSilentRedirections(http_utils.TestCaseWithRedirectedWebserver):
1404
1396
def test_one_redirection(self):
1405
1397
t = self.get_old_transport()
1398
req = RedirectedRequest('GET', t._remote_path('a'))
1406
1399
new_prefix = 'http://%s:%s' % (self.new_server.host,
1407
1400
self.new_server.port)
1408
1401
self.old_server.redirections = \
1409
[('(.*)', r'%s/1\1' % (new_prefix), 301), ]
1412
t.request('GET', t._remote_path('a'), retries=1).read())
1402
[('(.*)', r'%s/1\1' % (new_prefix), 301),]
1403
self.assertEqual('redirected once', t._perform(req).read())
1414
1405
def test_five_redirections(self):
1415
1406
t = self.get_old_transport()
1407
req = RedirectedRequest('GET', t._remote_path('a'))
1416
1408
old_prefix = 'http://%s:%s' % (self.old_server.host,
1417
1409
self.old_server.port)
1418
1410
new_prefix = 'http://%s:%s' % (self.new_server.host,
1424
1416
('/4(.*)', r'%s/5\1' % (new_prefix), 301),
1425
1417
('(/[^/]+)', r'%s/1\1' % (old_prefix), 301),
1428
b'redirected 5 times',
1429
t.request('GET', t._remote_path('a'), retries=6).read())
1419
self.assertEqual('redirected 5 times', t._perform(req).read())
1432
1422
class TestDoCatchRedirections(http_utils.TestCaseWithRedirectedWebserver):
1440
1430
def setUp(self):
1441
1431
super(TestDoCatchRedirections, self).setUp()
1442
self.build_tree_contents([('a', b'0123456789'), ],)
1432
self.build_tree_contents([('a', b'0123456789'),],)
1443
1433
cleanup_http_redirection_connections(self)
1445
1435
self.old_transport = self.get_old_transport()
1451
1441
t = self.get_new_transport()
1453
1443
# We use None for redirected so that we fail if redirected
1454
self.assertEqual(b'0123456789',
1444
self.assertEqual('0123456789',
1455
1445
transport.do_catching_redirections(
1456
self.get_a, t, None).read())
1446
self.get_a, t, None).read())
1458
1448
def test_one_redirection(self):
1459
1449
self.redirections = 0
1463
1453
redirected_t = t._redirected_to(exception.source, exception.target)
1464
1454
return redirected_t
1466
self.assertEqual(b'0123456789',
1456
self.assertEqual('0123456789',
1467
1457
transport.do_catching_redirections(
1468
self.get_a, self.old_transport, redirected).read())
1458
self.get_a, self.old_transport, redirected).read())
1469
1459
self.assertEqual(1, self.redirections)
1471
1461
def test_redirection_loop(self):
1499
1489
password = 'foo'
1500
1490
_setup_authentication_config(scheme='http', host='localhost',
1501
1491
user=user, password=password)
1502
handler = http.HTTPAuthHandler()
1492
handler = _urllib2_wrappers.HTTPAuthHandler()
1503
1493
got_pass = handler.get_user_password(dict(
1505
1495
protocol='http',
1506
1496
host='localhost',
1510
1500
self.assertEqual((user, password), got_pass)
1523
1513
super(TestAuth, self).setUp()
1524
1514
self.server = self.get_readonly_server()
1525
1515
self.build_tree_contents([('a', b'contents of a\n'),
1526
('b', b'contents of b\n'), ])
1516
('b', b'contents of b\n'),])
1528
1518
def create_transport_readonly_server(self):
1529
1519
server = self._auth_server(protocol_version=self._protocol_version)
1556
1546
def test_empty_pass(self):
1557
1547
self.server.add_user('joe', '')
1558
1548
t = self.get_user_transport('joe', '')
1559
self.assertEqual(b'contents of a\n', t.get('a').read())
1549
self.assertEqual('contents of a\n', t.get('a').read())
1560
1550
# Only one 'Authentication Required' error should occur
1561
1551
self.assertEqual(1, self.server.auth_required_errors)
1563
1553
def test_user_pass(self):
1564
1554
self.server.add_user('joe', 'foo')
1565
1555
t = self.get_user_transport('joe', 'foo')
1566
self.assertEqual(b'contents of a\n', t.get('a').read())
1556
self.assertEqual('contents of a\n', t.get('a').read())
1567
1557
# Only one 'Authentication Required' error should occur
1568
1558
self.assertEqual(1, self.server.auth_required_errors)
1589
1579
t = self.get_user_transport(None, None)
1590
1580
ui.ui_factory = tests.TestUIFactory(stdin='joe\nfoo\n')
1591
1581
stdout, stderr = ui.ui_factory.stdout, ui.ui_factory.stderr
1592
self.assertEqual(b'contents of a\n', t.get('a').read())
1582
self.assertEqual('contents of a\n', t.get('a').read())
1593
1583
# stdin should be empty
1594
1584
self.assertEqual('', ui.ui_factory.stdin.readline())
1604
1594
t = self.get_user_transport('joe', None)
1605
1595
ui.ui_factory = tests.TestUIFactory(stdin='foo\n')
1606
1596
stdout, stderr = ui.ui_factory.stdout, ui.ui_factory.stderr
1607
self.assertEqual(b'contents of a\n', t.get('a').read())
1597
self.assertEqual('contents of a\n', t.get('a').read())
1608
1598
# stdin should be empty
1609
1599
self.assertEqual('', ui.ui_factory.stdin.readline())
1610
1600
self._check_password_prompt(t._unqualified_scheme, 'joe',
1612
1602
self.assertEqual('', stdout.getvalue())
1613
1603
# And we shouldn't prompt again for a different request
1614
1604
# against the same transport.
1615
self.assertEqual(b'contents of b\n', t.get('b').read())
1605
self.assertEqual('contents of b\n', t.get('b').read())
1617
1607
# And neither against a clone
1618
self.assertEqual(b'contents of b\n', t2.get('b').read())
1608
self.assertEqual('contents of b\n', t2.get('b').read())
1619
1609
# Only one 'Authentication Required' error should occur
1620
1610
self.assertEqual(1, self.server.auth_required_errors)
1630
1620
def _expected_username_prompt(self, scheme):
1631
1621
return (self._username_prompt_prefix
1632
1622
+ "%s %s:%d, Realm: '%s' username: " % (scheme.upper(),
1633
self.server.host, self.server.port,
1634
self.server.auth_realm))
1623
self.server.host, self.server.port,
1624
self.server.auth_realm))
1636
1626
def test_no_prompt_for_password_when_using_auth_config(self):
1638
1628
password = 'foo'
1639
1629
stdin_content = 'bar\n' # Not the right password
1640
1630
self.server.add_user(user, password)
1644
1634
_setup_authentication_config(scheme='http', port=self.server.port,
1645
1635
user=user, password=password)
1646
1636
# Issue a request to the server to connect
1647
with t.get('a') as f:
1648
self.assertEqual(b'contents of a\n', f.read())
1637
self.assertEqual('contents of a\n', t.get('a').read())
1649
1638
# stdin should have been left untouched
1650
1639
self.assertEqual(stdin_content, ui.ui_factory.stdin.readline())
1651
1640
# Only one 'Authentication Required' error should occur
1657
1646
raise tests.TestNotApplicable('HTTP/proxy auth digest only test')
1658
1647
self.server.add_user('joe', 'foo')
1659
1648
t = self.get_user_transport('joe', 'foo')
1660
with t.get('a') as f:
1661
self.assertEqual(b'contents of a\n', f.read())
1662
with t.get('b') as f:
1663
self.assertEqual(b'contents of b\n', f.read())
1649
self.assertEqual('contents of a\n', t.get('a').read())
1650
self.assertEqual('contents of b\n', t.get('b').read())
1664
1651
# Only one 'Authentication Required' error should have
1665
1652
# occured so far
1666
1653
self.assertEqual(1, self.server.auth_required_errors)
1667
1654
# The server invalidates the current nonce
1668
1655
self.server.auth_nonce = self.server.auth_nonce + '. No, now!'
1669
self.assertEqual(b'contents of a\n', t.get('a').read())
1656
self.assertEqual('contents of a\n', t.get('a').read())
1670
1657
# Two 'Authentication Required' errors should occur (the
1671
1658
# initial 'who are you' and a second 'who are you' with the new nonce)
1672
1659
self.assertEqual(2, self.server.auth_required_errors)
1679
1666
user=user, password=password)
1680
1667
t = self.get_user_transport(None, None)
1681
1668
# Issue a request to the server to connect
1682
with t.get('a') as f:
1683
self.assertEqual(b'contents of a\n', f.read())
1669
self.assertEqual('contents of a\n', t.get('a').read())
1684
1670
# Only one 'Authentication Required' error should occur
1685
1671
self.assertEqual(1, self.server.auth_required_errors)
1810
1792
remote_transport = remote.RemoteTransport('bzr://fake_host/',
1812
1794
self.assertEqual(
1813
[(0, b"c")], list(remote_transport.readv("data-file", [(0, 1)])))
1795
[(0, "c")], list(remote_transport.readv("data-file", [(0, 1)])))
1815
1797
def test_http_send_smart_request(self):
1817
post_body = b'hello\n'
1818
expected_reply_body = b'ok\x012\n'
1799
post_body = 'hello\n'
1800
expected_reply_body = 'ok\x012\n'
1820
1802
http_transport = transport.get_transport_from_url(
1821
1803
self.http_server.get_url())
1828
1810
httpd = self.http_server.server
1830
1812
socket = SampleSocket(
1831
b'POST /.bzr/smart %s \r\n' % self._protocol_version.encode('ascii') +
1813
'POST /.bzr/smart %s \r\n' % self._protocol_version
1832
1814
# HTTP/1.1 posts must have a Content-Length (but it doesn't hurt
1834
b'Content-Length: 6\r\n'
1816
+ 'Content-Length: 6\r\n'
1837
1819
# Beware: the ('localhost', 80) below is the
1838
1820
# client_address parameter, but we don't have one because
1839
1821
# we have defined a socket which is not bound to an
1843
1825
('localhost', 80),
1845
1827
response = socket.writefile.getvalue()
1846
self.assertStartsWith(
1848
b'%s 200 ' % self._protocol_version.encode('ascii'))
1828
self.assertStartsWith(response, '%s 200 ' % self._protocol_version)
1849
1829
# This includes the end of the HTTP headers, and all the body.
1850
expected_end_of_response = b'\r\n\r\nok\x012\n'
1830
expected_end_of_response = '\r\n\r\nok\x012\n'
1851
1831
self.assertEndsWith(response, expected_end_of_response)
1910
1890
'https://www.example.com/foo')
1911
1891
self.assertIsInstance(r, type(t))
1912
1892
self.assertEqual('https://www.example.com/foo/',
1915
1895
def test_redirected_to_same_host_different_protocol(self):
1916
1896
t = self._transport('http://www.example.com/foo')
1917
1897
r = t._redirected_to('http://www.example.com/foo',
1918
'bzr://www.example.com/foo')
1898
'ftp://www.example.com/foo')
1919
1899
self.assertNotEqual(type(r), type(t))
1920
self.assertEqual('bzr://www.example.com/foo/', r.external_url())
1900
self.assertEqual('ftp://www.example.com/foo/', r.external_url())
1922
1902
def test_redirected_to_same_host_specific_implementation(self):
1923
1903
t = self._transport('http://www.example.com/foo')
1949
1929
def _handle_one_request(self):
1950
1930
tcs = self.server.test_case_server
1951
1931
requestline = self.rfile.readline()
1953
headers = parse_headers(self.rfile)
1954
bytes_read = len(headers.as_bytes())
1955
bytes_read += headers.as_bytes().count(b'\n')
1956
bytes_read += len(requestline)
1958
headers = self.MessageClass(self.rfile, 0)
1959
# We just read: the request, the headers, an empty line indicating the
1960
# end of the headers.
1961
bytes_read = len(requestline)
1962
for line in headers.headers:
1963
bytes_read += len(line)
1964
bytes_read += len(b'\r\n')
1965
if requestline.startswith(b'POST'):
1932
headers = self.MessageClass(self.rfile, 0)
1933
# We just read: the request, the headers, an empty line indicating the
1934
# end of the headers.
1935
bytes_read = len(requestline)
1936
for line in headers.headers:
1937
bytes_read += len(line)
1938
bytes_read += len('\r\n')
1939
if requestline.startswith('POST'):
1966
1940
# The body should be a single line (or we don't know where it ends
1967
1941
# and we don't want to issue a blocking read)
1968
1942
body = self.rfile.readline()
2014
1987
self.server = self._activity_server(self._protocol_version)
2015
1988
self.server.start_server()
2016
1989
self.addCleanup(self.server.stop_server)
2017
_activities = {} # Don't close over self and create a cycle
1990
_activities = {} # Don't close over self and create a cycle
2019
1991
def report_activity(t, bytes, direction):
2020
1992
count = _activities.get(direction, 0)
2038
2010
self.activities.get('read', 0), 'read bytes')
2040
2012
def test_get(self):
2041
self.server.canned_response = b'''HTTP/1.1 200 OK\r
2013
self.server.canned_response = '''HTTP/1.1 200 OK\r
2042
2014
Date: Tue, 11 Jul 2006 04:32:56 GMT\r
2043
2015
Server: Apache/2.0.54 (Fedora)\r
2044
2016
Last-Modified: Sun, 23 Apr 2006 19:35:20 GMT\r
2051
2023
Bazaar-NG meta directory, format 1
2053
2025
t = self.get_transport()
2054
self.assertEqual(b'Bazaar-NG meta directory, format 1\n',
2026
self.assertEqual('Bazaar-NG meta directory, format 1\n',
2055
2027
t.get('foo/bar').read())
2056
2028
self.assertActivitiesMatch()
2058
2030
def test_has(self):
2059
self.server.canned_response = b'''HTTP/1.1 200 OK\r
2031
self.server.canned_response = '''HTTP/1.1 200 OK\r
2060
2032
Server: SimpleHTTP/0.6 Python/2.5.2\r
2061
2033
Date: Thu, 29 Jan 2009 20:21:47 GMT\r
2062
2034
Content-type: application/octet-stream\r
2122
2094
# Remember that the request is ignored and that the ranges below
2123
2095
# doesn't have to match the canned response.
2124
2096
l = list(t.readv('/foo/bar', ((0, 255), (1000, 1050))))
2125
# Force consumption of the last bytesrange boundary
2126
t._get_connection().cleanup_pipe()
2127
2097
self.assertEqual(2, len(l))
2128
2098
self.assertActivitiesMatch()
2130
2100
def test_post(self):
2131
self.server.canned_response = b'''HTTP/1.1 200 OK\r
2101
self.server.canned_response = '''HTTP/1.1 200 OK\r
2132
2102
Date: Tue, 11 Jul 2006 04:32:56 GMT\r
2133
2103
Server: Apache/2.0.54 (Fedora)\r
2134
2104
Last-Modified: Sun, 23 Apr 2006 19:35:20 GMT\r
2143
2113
t = self.get_transport()
2144
2114
# We must send a single line of body bytes, see
2145
2115
# PredefinedRequestHandler._handle_one_request
2146
code, f = t._post(b'abc def end-of-body\n')
2147
self.assertEqual(b'lalala whatever as long as itsssss\n', f.read())
2116
code, f = t._post('abc def end-of-body\n')
2117
self.assertEqual('lalala whatever as long as itsssss\n', f.read())
2148
2118
self.assertActivitiesMatch()
2200
2170
new_prefix = 'http://%s:%s' % (self.new_server.host,
2201
2171
self.new_server.port)
2202
2172
self.old_server.redirections = [
2203
('(.*)', r'%s/1\1' % (new_prefix), 301), ]
2173
('(.*)', r'%s/1\1' % (new_prefix), 301),]
2204
2174
self.old_transport = self.get_old_transport()
2205
2175
self.new_server.add_user('joe', 'foo')
2206
2176
cleanup_http_redirection_connections(self)
2223
2193
return redirected_t
2225
2195
ui.ui_factory = tests.TestUIFactory(stdin='joe\nfoo\n')
2226
self.assertEqual(b'redirected once',
2196
self.assertEqual('redirected once',
2227
2197
transport.do_catching_redirections(
2228
self.get_a, self.old_transport, redirected).read())
2198
self.get_a, self.old_transport, redirected).read())
2229
2199
self.assertEqual(1, self.redirections)
2230
2200
# stdin should be empty
2231
2201
self.assertEqual('', ui.ui_factory.stdin.readline())
2236
2206
self.new_server.add_user('joe', 'foo')
2237
2207
ui.ui_factory = tests.TestUIFactory(stdin='joe\nfoo\n')
2238
2208
t = self.old_transport
2209
req = RedirectedRequest('GET', t.abspath('a'))
2239
2210
new_prefix = 'http://%s:%s' % (self.new_server.host,
2240
2211
self.new_server.port)
2241
2212
self.old_server.redirections = [
2242
('(.*)', r'%s/1\1' % (new_prefix), 301), ]
2245
t.request('GET', t.abspath('a'), retries=3).read())
2213
('(.*)', r'%s/1\1' % (new_prefix), 301),]
2214
self.assertEqual('redirected once', t._perform(req).read())
2246
2215
# stdin should be empty
2247
2216
self.assertEqual('', ui.ui_factory.stdin.readline())
2248
2217
# stdout should be empty, stderr will contains the prompts
2249
2218
self.assertEqual('', ui.ui_factory.stdout.getvalue())