363
361
self.assertIsInstance(t, HttpTransport_urllib)
364
class TestOffsets(TestCase):
365
"""Test offsets_to_ranges method"""
367
def test_offsets_to_ranges_simple(self):
368
to_range = HttpTransportBase.offsets_to_ranges
369
ranges = to_range([(10, 1)])
370
self.assertEqual([[10, 10]], ranges)
372
ranges = to_range([(0, 1), (1, 1)])
373
self.assertEqual([[0, 1]], ranges)
375
ranges = to_range([(1, 1), (0, 1)])
376
self.assertEqual([[0, 1]], ranges)
378
def test_offset_to_ranges_overlapped(self):
379
to_range = HttpTransportBase.offsets_to_ranges
381
ranges = to_range([(10, 1), (20, 2), (22, 5)])
382
self.assertEqual([[10, 10], [20, 26]], ranges)
384
ranges = to_range([(10, 1), (11, 2), (22, 5)])
385
self.assertEqual([[10, 12], [22, 26]], ranges)
366
388
class TestPost(object):
368
390
def _test_post_body_is_received(self, scheme):
405
427
"""Test range_header method"""
407
429
def check_header(self, value, ranges=[], tail=0):
408
offsets = [ (start, end - start + 1) for start, end in ranges]
409
coalesce = Transport._coalesce_offsets
410
coalesced = list(coalesce(offsets, limit=0, fudge_factor=0))
411
range_header = HttpTransportBase._range_header
412
self.assertEqual(value, range_header(coalesced, tail))
430
range_header = HttpTransportBase.range_header
431
self.assertEqual(value, range_header(ranges, tail))
414
433
def test_range_header_single(self):
415
self.check_header('0-9', ranges=[(0,9)])
416
self.check_header('100-109', ranges=[(100,109)])
434
self.check_header('0-9', ranges=[[0,9]])
435
self.check_header('100-109', ranges=[[100,109]])
418
437
def test_range_header_tail(self):
419
438
self.check_header('-10', tail=10)
715
734
"""Tests range requests refusing server for pycurl implementation"""
718
class TestLimitedRangeRequestServer(object):
719
"""Tests readv requests against server that errors out on too much ranges.
721
This MUST be used by daughter classes that also inherit from
722
TestCaseWithWebserver.
724
We can't inherit directly from TestCaseWithWebserver or the
725
test framework will try to create an instance which cannot
726
run, its implementation being incomplete.
731
def create_transport_readonly_server(self):
732
# Requests with more range specifiers will error out
733
return LimitedRangeHTTPServer(range_limit=self.range_limit)
735
def get_transport(self):
736
return self._transport(self.get_readonly_server().get_url())
739
TestCaseWithWebserver.setUp(self)
740
# We need to manipulate ranges that correspond to real chunks in the
741
# response, so we build a content appropriately.
742
filler = ''.join(['abcdefghij' for _ in range(102)])
743
content = ''.join(['%04d' % v + filler for v in range(16)])
744
self.build_tree_contents([('a', content)],)
746
def test_few_ranges(self):
747
t = self.get_transport()
748
l = list(t.readv('a', ((0, 4), (1024, 4), )))
749
self.assertEqual(l[0], (0, '0000'))
750
self.assertEqual(l[1], (1024, '0001'))
751
self.assertEqual(1, self.get_readonly_server().GET_request_nb)
753
def test_a_lot_of_ranges(self):
754
t = self.get_transport()
755
l = list(t.readv('a', ((0, 4), (1024, 4), (4096, 4), (8192, 4))))
756
self.assertEqual(l[0], (0, '0000'))
757
self.assertEqual(l[1], (1024, '0001'))
758
self.assertEqual(l[2], (4096, '0004'))
759
self.assertEqual(l[3], (8192, '0008'))
760
# The server will refuse to serve the first request (too much ranges),
761
# a second request will succeeds.
762
self.assertEqual(2, self.get_readonly_server().GET_request_nb)
765
class TestLimitedRangeRequestServer_urllib(TestLimitedRangeRequestServer,
766
TestCaseWithWebserver):
767
"""Tests limited range requests server for urllib implementation"""
769
_transport = HttpTransport_urllib
772
class TestLimitedRangeRequestServer_pycurl(TestWithTransport_pycurl,
773
TestLimitedRangeRequestServer,
774
TestCaseWithWebserver):
775
"""Tests limited range requests server for pycurl implementation"""
779
737
class TestHttpProxyWhiteBox(TestCase):
780
738
"""Whitebox test proxy http authorization.
968
926
server = self.get_readonly_server()
969
927
self.transport = self._transport(server.get_url())
971
def _file_contents(self, relpath, ranges):
972
offsets = [ (start, end - start + 1) for start, end in ranges]
973
coalesce = self.transport._coalesce_offsets
974
coalesced = list(coalesce(offsets, limit=0, fudge_factor=0))
975
code, data = self.transport._get(relpath, coalesced)
976
self.assertTrue(code in (200, 206),'_get returns: %d' % code)
977
for start, end in ranges:
979
yield data.read(end - start + 1)
929
def _file_contents(self, relpath, ranges, tail_amount=0):
930
code, data = self.transport._get(relpath, ranges)
931
self.assertTrue(code in (200, 206),'_get returns: %d' % code)
932
for start, end in ranges:
934
yield data.read(end - start + 1)
981
936
def _file_tail(self, relpath, tail_amount):
982
code, data = self.transport._get(relpath, [], tail_amount)
983
self.assertTrue(code in (200, 206),'_get returns: %d' % code)
984
data.seek(-tail_amount + 1, 2)
985
return data.read(tail_amount)
937
code, data = self.transport._get(relpath, [], tail_amount)
938
self.assertTrue(code in (200, 206),'_get returns: %d' % code)
939
data.seek(-tail_amount + 1, 2)
940
return data.read(tail_amount)
987
942
def test_range_header(self):
992
947
self.assertEqual('789', self._file_tail('a', 3))
993
948
# Syntactically invalid range
994
self.assertListRaises(errors.InvalidRange,
995
self._file_contents, 'a', [(4, 3)])
949
self.assertRaises(errors.InvalidRange,
950
self.transport._get, 'a', [(4, 3)])
996
951
# Semantically invalid range
997
self.assertListRaises(errors.InvalidRange,
998
self._file_contents, 'a', [(42, 128)])
952
self.assertRaises(errors.InvalidRange,
953
self.transport._get, 'a', [(42, 128)])
1001
956
class TestRanges_urllib(TestRanges, TestCaseWithWebserver):
1221
1176
self.build_tree_contents([('a', 'contents of a\n'),
1222
1177
('b', 'contents of b\n'),])
1223
1178
self.old_factory = ui.ui_factory
1224
# The following has the unfortunate side-effect of hiding any ouput
1225
# during the tests (including pdb prompts). Feel free to comment them
1226
# for debugging purposes but leave them in place, there are needed to
1227
# run the tests without any console
1228
1179
self.old_stdout = sys.stdout
1229
1180
sys.stdout = StringIOWrapper()
1230
1181
self.addCleanup(self.restoreUIFactory)