~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_smart_transport.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2007-04-26 10:41:48 UTC
  • mfrom: (2420.1.22 bzr.http.auth)
  • Revision ID: pqm@pqm.ubuntu.com-20070426104148-4l5wq2zemlzv0shg
http authentication and other integrated fixes

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
        medium,
36
36
        protocol,
37
37
        request,
 
38
        request as _mod_request,
38
39
        server,
39
40
        vfs,
40
41
)
1266
1267
            def do_body(cmd, body_bytes):
1267
1268
                self.end_received = True
1268
1269
                self.assertEqual('abcdefg', body_bytes)
1269
 
                return request.SmartServerResponse(('ok', ))
 
1270
                return request.SuccessfulSmartServerResponse(('ok', ))
1270
1271
        smart_protocol.request._command = FakeCommand()
1271
1272
        # Call accept_bytes to make sure that internal state like _body_decoder
1272
1273
        # is initialised.  This test should probably be given a clearer
1286
1287
            server_output = StringIO()
1287
1288
            server_protocol = self.server_protocol_class(
1288
1289
                None, server_output.write)
1289
 
            server_protocol._send_response(input_tuple)
 
1290
            server_protocol._send_response(
 
1291
                _mod_request.SuccessfulSmartServerResponse(input_tuple))
1290
1292
            self.assertEqual(expected_bytes, server_output.getvalue())
1291
1293
        # check the decoding of the client smart_protocol from expected_bytes:
1292
1294
        input = StringIO(expected_bytes)
1403
1405
        smart_protocol = protocol.SmartServerRequestProtocolOne(
1404
1406
            None, lambda x: None)
1405
1407
        self.assertEqual(1, smart_protocol.next_read_size())
1406
 
        smart_protocol._send_response(('x',))
 
1408
        smart_protocol._send_response(
 
1409
            request.SuccessfulSmartServerResponse(('x',)))
1407
1410
        self.assertEqual(0, smart_protocol.next_read_size())
1408
1411
 
 
1412
    def test__send_response_errors_with_base_response(self):
 
1413
        """Ensure that only the Successful/Failed subclasses are used."""
 
1414
        smart_protocol = protocol.SmartServerRequestProtocolOne(
 
1415
            None, lambda x: None)
 
1416
        self.assertRaises(AttributeError, smart_protocol._send_response,
 
1417
            request.SmartServerResponse(('x',)))
 
1418
 
1409
1419
    def test_query_version(self):
1410
1420
        """query_version on a SmartClientProtocolOne should return a number.
1411
1421
        
1557
1567
        smart_protocol.accept_bytes('\n')
1558
1568
        self.assertEqual(
1559
1569
            protocol.RESPONSE_VERSION_TWO +
1560
 
            "error\x01Generic bzr smart protocol error: bad request 'abc'\n",
 
1570
            "failed\nerror\x01Generic bzr smart protocol error: bad request 'abc'\n",
1561
1571
            out_stream.getvalue())
1562
1572
        self.assertTrue(smart_protocol.has_dispatched)
1563
1573
        self.assertEqual(0, smart_protocol.next_read_size())
1581
1591
                out_stream.write)
1582
1592
        smart_protocol.accept_bytes('readv\x01foo\n3\n3,3done\n')
1583
1593
        self.assertEqual(0, smart_protocol.next_read_size())
1584
 
        self.assertEqual(protocol.RESPONSE_VERSION_TWO + 'readv\n3\ndefdone\n',
 
1594
        self.assertEqual(protocol.RESPONSE_VERSION_TWO +
 
1595
                         'success\nreadv\n3\ndefdone\n',
1585
1596
                         out_stream.getvalue())
1586
1597
        self.assertEqual('', smart_protocol.excess_buffer)
1587
1598
        self.assertEqual('', smart_protocol.in_buffer)
1591
1602
        smart_protocol = protocol.SmartServerRequestProtocolTwo(
1592
1603
            None, out_stream.write)
1593
1604
        smart_protocol.accept_bytes('hello\nhello\n')
1594
 
        self.assertEqual(protocol.RESPONSE_VERSION_TWO + "ok\x012\n",
 
1605
        self.assertEqual(protocol.RESPONSE_VERSION_TWO + "success\nok\x012\n",
1595
1606
                         out_stream.getvalue())
1596
1607
        self.assertEqual("hello\n", smart_protocol.excess_buffer)
1597
1608
        self.assertEqual("", smart_protocol.in_buffer)
1615
1626
        smart_protocol = protocol.SmartServerRequestProtocolTwo(
1616
1627
            None, out_stream.write)
1617
1628
        smart_protocol.accept_bytes('hello\n')
1618
 
        self.assertEqual(protocol.RESPONSE_VERSION_TWO + "ok\x012\n",
 
1629
        self.assertEqual(protocol.RESPONSE_VERSION_TWO + "success\nok\x012\n",
1619
1630
                         out_stream.getvalue())
1620
1631
        smart_protocol.accept_bytes(protocol.REQUEST_VERSION_TWO + 'hel')
1621
1632
        self.assertEqual(protocol.REQUEST_VERSION_TWO + "hel",
1629
1640
        smart_protocol = protocol.SmartServerRequestProtocolTwo(
1630
1641
            None, lambda x: None)
1631
1642
        self.assertEqual(1, smart_protocol.next_read_size())
1632
 
        smart_protocol._send_response(('x',))
 
1643
        smart_protocol._send_response(
 
1644
            request.SuccessfulSmartServerResponse(('x',)))
1633
1645
        self.assertEqual(0, smart_protocol.next_read_size())
1634
1646
 
 
1647
    def test__send_response_errors_with_base_response(self):
 
1648
        """Ensure that only the Successful/Failed subclasses are used."""
 
1649
        smart_protocol = protocol.SmartServerRequestProtocolTwo(
 
1650
            None, lambda x: None)
 
1651
        self.assertRaises(AttributeError, smart_protocol._send_response,
 
1652
            request.SmartServerResponse(('x',)))
 
1653
 
 
1654
    def test__send_response_includes_failure_marker(self):
 
1655
        """FailedSmartServerResponse have 'failed\n' after the version."""
 
1656
        out_stream = StringIO()
 
1657
        smart_protocol = protocol.SmartServerRequestProtocolTwo(
 
1658
            None, out_stream.write)
 
1659
        smart_protocol._send_response(
 
1660
            request.FailedSmartServerResponse(('x',)))
 
1661
        self.assertEqual(protocol.RESPONSE_VERSION_TWO + 'failed\nx\n',
 
1662
                         out_stream.getvalue())
 
1663
 
 
1664
    def test__send_response_includes_success_marker(self):
 
1665
        """SuccessfulSmartServerResponse have 'success\n' after the version."""
 
1666
        out_stream = StringIO()
 
1667
        smart_protocol = protocol.SmartServerRequestProtocolTwo(
 
1668
            None, out_stream.write)
 
1669
        smart_protocol._send_response(
 
1670
            request.SuccessfulSmartServerResponse(('x',)))
 
1671
        self.assertEqual(protocol.RESPONSE_VERSION_TWO + 'success\nx\n',
 
1672
                         out_stream.getvalue())
 
1673
 
1635
1674
    def test_query_version(self):
1636
1675
        """query_version on a SmartClientProtocolTwo should return a number.
1637
1676
        
1642
1681
        # accept_bytes(tuple_based_encoding_of_hello) and reads and parses the
1643
1682
        # response of tuple-encoded (ok, 1).  Also, seperately we should test
1644
1683
        # the error if the response is a non-understood version.
1645
 
        input = StringIO(protocol.RESPONSE_VERSION_TWO + 'ok\x012\n')
 
1684
        input = StringIO(protocol.RESPONSE_VERSION_TWO + 'success\nok\x012\n')
1646
1685
        output = StringIO()
1647
1686
        client_medium = medium.SmartSimplePipesClientMedium(input, output)
1648
1687
        request = client_medium.get_request()
1654
1693
        # when the parsed line is an empty line, and results in a tuple with
1655
1694
        # one element - an empty string.
1656
1695
        self.assertServerToClientEncoding(
1657
 
            protocol.RESPONSE_VERSION_TWO + '\n', ('', ), [(), ('', )])
 
1696
            protocol.RESPONSE_VERSION_TWO + 'success\n\n', ('', ), [(), ('', )])
1658
1697
 
1659
1698
    def test_client_call_three_element_response(self):
1660
1699
        # protocol.call() can get back tuples of other lengths. A three element
1661
1700
        # tuple should be unpacked as three strings.
1662
1701
        self.assertServerToClientEncoding(
1663
 
            protocol.RESPONSE_VERSION_TWO + 'a\x01b\x0134\n', ('a', 'b', '34'),
 
1702
            protocol.RESPONSE_VERSION_TWO + 'success\na\x01b\x0134\n',
 
1703
            ('a', 'b', '34'),
1664
1704
            [('a', 'b', '34')])
1665
1705
 
1666
1706
    def test_client_call_with_body_bytes_uploads(self):
1687
1727
        smart_protocol.call_with_body_readv_array(('foo', ), [(1,2),(5,6)])
1688
1728
        self.assertEqual(expected_bytes, output.getvalue())
1689
1729
 
 
1730
    def test_client_read_response_tuple_sets_response_status(self):
 
1731
        server_bytes = protocol.RESPONSE_VERSION_TWO + "success\nok\n"
 
1732
        input = StringIO(server_bytes)
 
1733
        output = StringIO()
 
1734
        client_medium = medium.SmartSimplePipesClientMedium(input, output)
 
1735
        request = client_medium.get_request()
 
1736
        smart_protocol = protocol.SmartClientRequestProtocolTwo(request)
 
1737
        smart_protocol.call('foo')
 
1738
        smart_protocol.read_response_tuple(False)
 
1739
        self.assertEqual(True, smart_protocol.response_status)
 
1740
 
1690
1741
    def test_client_read_body_bytes_all(self):
1691
1742
        # read_body_bytes should decode the body bytes from the wire into
1692
1743
        # a response.
1693
1744
        expected_bytes = "1234567"
1694
 
        server_bytes = protocol.RESPONSE_VERSION_TWO + "ok\n7\n1234567done\n"
 
1745
        server_bytes = (protocol.RESPONSE_VERSION_TWO +
 
1746
                        "success\nok\n7\n1234567done\n")
1695
1747
        input = StringIO(server_bytes)
1696
1748
        output = StringIO()
1697
1749
        client_medium = medium.SmartSimplePipesClientMedium(input, output)
1708
1760
        # LengthPrefixedBodyDecoder that is already well tested - we can skip
1709
1761
        # that.
1710
1762
        expected_bytes = "1234567"
1711
 
        server_bytes = protocol.RESPONSE_VERSION_TWO + "ok\n7\n1234567done\n"
 
1763
        server_bytes = (protocol.RESPONSE_VERSION_TWO +
 
1764
                        "success\nok\n7\n1234567done\n")
1712
1765
        input = StringIO(server_bytes)
1713
1766
        output = StringIO()
1714
1767
        client_medium = medium.SmartSimplePipesClientMedium(input, output)
1725
1778
        # cancelling the expected body needs to finish the request, but not
1726
1779
        # read any more bytes.
1727
1780
        expected_bytes = "1234567"
1728
 
        server_bytes = protocol.RESPONSE_VERSION_TWO + "ok\n7\n1234567done\n"
 
1781
        server_bytes = (protocol.RESPONSE_VERSION_TWO +
 
1782
                        "success\nok\n7\n1234567done\n")
1729
1783
        input = StringIO(server_bytes)
1730
1784
        output = StringIO()
1731
1785
        client_medium = medium.SmartSimplePipesClientMedium(input, output)
1734
1788
        smart_protocol.call('foo')
1735
1789
        smart_protocol.read_response_tuple(True)
1736
1790
        smart_protocol.cancel_read_body()
1737
 
        self.assertEqual(len(protocol.RESPONSE_VERSION_TWO + 'ok\n'),
 
1791
        self.assertEqual(len(protocol.RESPONSE_VERSION_TWO + 'success\nok\n'),
1738
1792
                         input.tell())
1739
1793
        self.assertRaises(
1740
1794
            errors.ReadingCompleted, smart_protocol.read_body_bytes)
1844
1898
        self.assertEqual('', decoder.unused_data)
1845
1899
 
1846
1900
 
 
1901
class TestSuccessfulSmartServerResponse(tests.TestCase):
 
1902
 
 
1903
    def test_construct(self):
 
1904
        response = request.SuccessfulSmartServerResponse(('foo', 'bar'))
 
1905
        self.assertEqual(('foo', 'bar'), response.args)
 
1906
        self.assertEqual(None, response.body)
 
1907
        response = request.SuccessfulSmartServerResponse(('foo', 'bar'), 'bytes')
 
1908
        self.assertEqual(('foo', 'bar'), response.args)
 
1909
        self.assertEqual('bytes', response.body)
 
1910
 
 
1911
    def test_is_successful(self):
 
1912
        """is_successful should return True for SuccessfulSmartServerResponse."""
 
1913
        response = request.SuccessfulSmartServerResponse(('error',))
 
1914
        self.assertEqual(True, response.is_successful())
 
1915
 
 
1916
 
 
1917
class TestFailedSmartServerResponse(tests.TestCase):
 
1918
 
 
1919
    def test_construct(self):
 
1920
        response = request.FailedSmartServerResponse(('foo', 'bar'))
 
1921
        self.assertEqual(('foo', 'bar'), response.args)
 
1922
        self.assertEqual(None, response.body)
 
1923
        response = request.FailedSmartServerResponse(('foo', 'bar'), 'bytes')
 
1924
        self.assertEqual(('foo', 'bar'), response.args)
 
1925
        self.assertEqual('bytes', response.body)
 
1926
 
 
1927
    def test_is_successful(self):
 
1928
        """is_successful should return False for FailedSmartServerResponse."""
 
1929
        response = request.FailedSmartServerResponse(('error',))
 
1930
        self.assertEqual(False, response.is_successful())
 
1931
 
 
1932
 
1847
1933
class FakeHTTPMedium(object):
1848
1934
    def __init__(self):
1849
1935
        self.written_request = None
1972
2058
            return self.writefile
1973
2059
 
1974
2060
 
 
2061
class RemoteHTTPTransportTestCase(tests.TestCase):
 
2062
 
 
2063
    def test_remote_path_after_clone_child(self):
 
2064
        # If a user enters "bzr+http://host/foo", we want to sent all smart
 
2065
        # requests for child URLs of that to the original URL.  i.e., we want to
 
2066
        # POST to "bzr+http://host/foo/.bzr/smart" and never something like
 
2067
        # "bzr+http://host/foo/.bzr/branch/.bzr/smart".  So, a cloned
 
2068
        # RemoteHTTPTransport remembers the initial URL, and adjusts the relpaths
 
2069
        # it sends in smart requests accordingly.
 
2070
        base_transport = remote.RemoteHTTPTransport('bzr+http://host/path')
 
2071
        new_transport = base_transport.clone('child_dir')
 
2072
        self.assertEqual(base_transport._http_transport,
 
2073
                         new_transport._http_transport)
 
2074
        self.assertEqual('child_dir/foo', new_transport._remote_path('foo'))
 
2075
 
 
2076
    def test_remote_path_after_clone_parent(self):
 
2077
        # However, accessing a parent directory should go direct to the parent's
 
2078
        # URL.  We don't send relpaths like "../foo" in smart requests.
 
2079
        base_transport = remote.RemoteHTTPTransport('bzr+http://host/path1/path2')
 
2080
        new_transport = base_transport.clone('..')
 
2081
        self.assertEqual('foo', new_transport._remote_path('foo'))
 
2082
        new_transport = base_transport.clone('../')
 
2083
        self.assertEqual('foo', new_transport._remote_path('foo'))
 
2084
        new_transport = base_transport.clone('../abc')
 
2085
        self.assertEqual('foo', new_transport._remote_path('foo'))
 
2086
        # "abc/../.." should be equivalent to ".."
 
2087
        new_transport = base_transport.clone('abc/../..')
 
2088
        self.assertEqual('foo', new_transport._remote_path('foo'))
 
2089
 
 
2090
        
1975
2091
# TODO: Client feature that does get_bundle and then installs that into a
1976
2092
# branch; this can be used in place of the regular pull/fetch operation when
1977
2093
# coming from a smart server.