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())
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',)))
1409
1419
def test_query_version(self):
1410
1420
"""query_version on a SmartClientProtocolOne should return a number.
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())
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',)))
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())
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())
1635
1674
def test_query_version(self):
1636
1675
"""query_version on a SmartClientProtocolTwo should return a number.
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', ('', ), [(), ('', )])
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',
1664
1704
[('a', 'b', '34')])
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())
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)
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)
1690
1741
def test_client_read_body_bytes_all(self):
1691
1742
# read_body_bytes should decode the body bytes from the wire into
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
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'),
1739
1793
self.assertRaises(
1740
1794
errors.ReadingCompleted, smart_protocol.read_body_bytes)
1844
1898
self.assertEqual('', decoder.unused_data)
1901
class TestSuccessfulSmartServerResponse(tests.TestCase):
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)
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())
1917
class TestFailedSmartServerResponse(tests.TestCase):
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)
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())
1847
1933
class FakeHTTPMedium(object):
1848
1934
def __init__(self):
1849
1935
self.written_request = None
1972
2058
return self.writefile
2061
class RemoteHTTPTransportTestCase(tests.TestCase):
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'))
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'))
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.