~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_http.py

  • Committer: Ian Clatworthy
  • Date: 2007-07-03 07:03:32 UTC
  • mfrom: (2520.2.3 115209)
  • mto: This revision was merged to the branch mainline in revision 2575.
  • Revision ID: ian.clatworthy@internode.on.net-20070703070332-45j7qw8z03fnulav
(Vincent Ladeuil) Fix #115209 - Unable to handle http code 400: Bad Request When issuing too many ranges

Show diffs side-by-side

added added

removed removed

Lines of Context:
53
53
    HTTPDigestAuthServer,
54
54
    HTTPServerRedirecting,
55
55
    InvalidStatusRequestHandler,
 
56
    LimitedRangeHTTPServer,
56
57
    NoRangeRequestHandler,
57
58
    ProxyBasicAuthServer,
58
59
    ProxyDigestAuthServer,
65
66
    WallRequestHandler,
66
67
    )
67
68
from bzrlib.transport import (
 
69
    _CoalescedOffset,
68
70
    do_catching_redirections,
69
71
    get_transport,
70
72
    Transport,
361
363
        self.assertIsInstance(t, HttpTransport_urllib)
362
364
 
363
365
 
364
 
class TestOffsets(TestCase):
365
 
    """Test offsets_to_ranges method"""
366
 
 
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)
371
 
 
372
 
        ranges = to_range([(0, 1), (1, 1)])
373
 
        self.assertEqual([[0, 1]], ranges)
374
 
 
375
 
        ranges = to_range([(1, 1), (0, 1)])
376
 
        self.assertEqual([[0, 1]], ranges)
377
 
 
378
 
    def test_offset_to_ranges_overlapped(self):
379
 
        to_range = HttpTransportBase.offsets_to_ranges
380
 
 
381
 
        ranges = to_range([(10, 1), (20, 2), (22, 5)])
382
 
        self.assertEqual([[10, 10], [20, 26]], ranges)
383
 
 
384
 
        ranges = to_range([(10, 1), (11, 2), (22, 5)])
385
 
        self.assertEqual([[10, 12], [22, 26]], ranges)
386
 
 
387
 
 
388
366
class TestPost(object):
389
367
 
390
368
    def _test_post_body_is_received(self, scheme):
427
405
    """Test range_header method"""
428
406
 
429
407
    def check_header(self, value, ranges=[], tail=0):
430
 
        range_header = HttpTransportBase.range_header
431
 
        self.assertEqual(value, range_header(ranges, tail))
 
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))
432
413
 
433
414
    def test_range_header_single(self):
434
 
        self.check_header('0-9', ranges=[[0,9]])
435
 
        self.check_header('100-109', ranges=[[100,109]])
 
415
        self.check_header('0-9', ranges=[(0,9)])
 
416
        self.check_header('100-109', ranges=[(100,109)])
436
417
 
437
418
    def test_range_header_tail(self):
438
419
        self.check_header('-10', tail=10)
734
715
    """Tests range requests refusing server for pycurl implementation"""
735
716
 
736
717
 
 
718
class TestLimitedRangeRequestServer(object):
 
719
    """Tests readv requests against server that errors out on too much ranges.
 
720
 
 
721
    This MUST be used by daughter classes that also inherit from
 
722
    TestCaseWithWebserver.
 
723
 
 
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.
 
727
    """
 
728
 
 
729
    range_limit = 3
 
730
 
 
731
    def create_transport_readonly_server(self):
 
732
        # Requests with more range specifiers will error out
 
733
        return LimitedRangeHTTPServer(range_limit=self.range_limit)
 
734
 
 
735
    def get_transport(self):
 
736
        return self._transport(self.get_readonly_server().get_url())
 
737
 
 
738
    def setUp(self):
 
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)],)
 
745
 
 
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)
 
752
 
 
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)
 
763
 
 
764
 
 
765
class TestLimitedRangeRequestServer_urllib(TestLimitedRangeRequestServer,
 
766
                                          TestCaseWithWebserver):
 
767
    """Tests limited range requests server for urllib implementation"""
 
768
 
 
769
    _transport = HttpTransport_urllib
 
770
 
 
771
 
 
772
class TestLimitedRangeRequestServer_pycurl(TestWithTransport_pycurl,
 
773
                                          TestLimitedRangeRequestServer,
 
774
                                          TestCaseWithWebserver):
 
775
    """Tests limited range requests server for pycurl implementation"""
 
776
 
 
777
 
 
778
 
737
779
class TestHttpProxyWhiteBox(TestCase):
738
780
    """Whitebox test proxy http authorization.
739
781
 
926
968
        server = self.get_readonly_server()
927
969
        self.transport = self._transport(server.get_url())
928
970
 
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:
933
 
             data.seek(start)
934
 
             yield data.read(end - start + 1)
 
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:
 
978
            data.seek(start)
 
979
            yield data.read(end - start + 1)
935
980
 
936
981
    def _file_tail(self, relpath, 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)
 
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)
941
986
 
942
987
    def test_range_header(self):
943
988
        # Valid ranges
946
991
        # Tail
947
992
        self.assertEqual('789', self._file_tail('a', 3))
948
993
        # Syntactically invalid range
949
 
        self.assertRaises(errors.InvalidRange,
950
 
                          self.transport._get, 'a', [(4, 3)])
 
994
        self.assertListRaises(errors.InvalidRange,
 
995
                          self._file_contents, 'a', [(4, 3)])
951
996
        # Semantically invalid range
952
 
        self.assertRaises(errors.InvalidRange,
953
 
                          self.transport._get, 'a', [(42, 128)])
 
997
        self.assertListRaises(errors.InvalidRange,
 
998
                          self._file_contents, 'a', [(42, 128)])
954
999
 
955
1000
 
956
1001
class TestRanges_urllib(TestRanges, TestCaseWithWebserver):