1747
1816
def test_construct_version_two_server_protocol(self):
1748
1817
smart_protocol = protocol.SmartServerRequestProtocolTwo(None, None)
1749
self.assertEqual('', smart_protocol.excess_buffer)
1818
self.assertEqual('', smart_protocol.unused_data)
1750
1819
self.assertEqual('', smart_protocol.in_buffer)
1751
self.assertFalse(smart_protocol.has_dispatched)
1820
self.assertFalse(smart_protocol._has_dispatched)
1752
1821
self.assertEqual(1, smart_protocol.next_read_size())
1754
1823
def test_construct_version_two_client_protocol(self):
1755
1824
# we can construct a client protocol from a client medium request
1756
1825
output = StringIO()
1757
client_medium = medium.SmartSimplePipesClientMedium(None, output)
1826
client_medium = medium.SmartSimplePipesClientMedium(
1827
None, output, 'base')
1758
1828
request = client_medium.get_request()
1759
1829
client_protocol = protocol.SmartClientRequestProtocolTwo(request)
1831
def test_accept_bytes_of_bad_request_to_protocol(self):
1832
out_stream = StringIO()
1833
smart_protocol = self.server_protocol_class(None, out_stream.write)
1834
smart_protocol.accept_bytes('abc')
1835
self.assertEqual('abc', smart_protocol.in_buffer)
1836
smart_protocol.accept_bytes('\n')
1838
self.response_marker +
1839
"failed\nerror\x01Generic bzr smart protocol error: bad request 'abc'\n",
1840
out_stream.getvalue())
1841
self.assertTrue(smart_protocol._has_dispatched)
1842
self.assertEqual(0, smart_protocol.next_read_size())
1844
def test_accept_body_bytes_to_protocol(self):
1845
protocol = self.build_protocol_waiting_for_body()
1846
self.assertEqual(6, protocol.next_read_size())
1847
protocol.accept_bytes('7\nabc')
1848
self.assertEqual(9, protocol.next_read_size())
1849
protocol.accept_bytes('defgd')
1850
protocol.accept_bytes('one\n')
1851
self.assertEqual(0, protocol.next_read_size())
1852
self.assertTrue(self.end_received)
1854
def test_accept_request_and_body_all_at_once(self):
1855
self._captureVar('BZR_NO_SMART_VFS', None)
1856
mem_transport = memory.MemoryTransport()
1857
mem_transport.put_bytes('foo', 'abcdefghij')
1858
out_stream = StringIO()
1859
smart_protocol = self.server_protocol_class(
1860
mem_transport, out_stream.write)
1861
smart_protocol.accept_bytes('readv\x01foo\n3\n3,3done\n')
1862
self.assertEqual(0, smart_protocol.next_read_size())
1863
self.assertEqual(self.response_marker +
1864
'success\nreadv\n3\ndefdone\n',
1865
out_stream.getvalue())
1866
self.assertEqual('', smart_protocol.unused_data)
1867
self.assertEqual('', smart_protocol.in_buffer)
1869
def test_accept_excess_bytes_are_preserved(self):
1870
out_stream = StringIO()
1871
smart_protocol = self.server_protocol_class(None, out_stream.write)
1872
smart_protocol.accept_bytes('hello\nhello\n')
1873
self.assertEqual(self.response_marker + "success\nok\x012\n",
1874
out_stream.getvalue())
1875
self.assertEqual("hello\n", smart_protocol.unused_data)
1876
self.assertEqual("", smart_protocol.in_buffer)
1878
def test_accept_excess_bytes_after_body(self):
1879
# The excess bytes look like the start of another request.
1880
server_protocol = self.build_protocol_waiting_for_body()
1881
server_protocol.accept_bytes('7\nabcdefgdone\n' + self.response_marker)
1882
self.assertTrue(self.end_received)
1883
self.assertEqual(self.response_marker,
1884
server_protocol.unused_data)
1885
self.assertEqual("", server_protocol.in_buffer)
1886
server_protocol.accept_bytes('Y')
1887
self.assertEqual(self.response_marker + "Y",
1888
server_protocol.unused_data)
1889
self.assertEqual("", server_protocol.in_buffer)
1891
def test_accept_excess_bytes_after_dispatch(self):
1892
out_stream = StringIO()
1893
smart_protocol = self.server_protocol_class(None, out_stream.write)
1894
smart_protocol.accept_bytes('hello\n')
1895
self.assertEqual(self.response_marker + "success\nok\x012\n",
1896
out_stream.getvalue())
1897
smart_protocol.accept_bytes(self.request_marker + 'hel')
1898
self.assertEqual(self.request_marker + "hel",
1899
smart_protocol.unused_data)
1900
smart_protocol.accept_bytes('lo\n')
1901
self.assertEqual(self.request_marker + "hello\n",
1902
smart_protocol.unused_data)
1903
self.assertEqual("", smart_protocol.in_buffer)
1905
def test__send_response_sets_finished_reading(self):
1906
smart_protocol = self.server_protocol_class(None, lambda x: None)
1907
self.assertEqual(1, smart_protocol.next_read_size())
1908
smart_protocol._send_response(
1909
_mod_request.SuccessfulSmartServerResponse(('x',)))
1910
self.assertEqual(0, smart_protocol.next_read_size())
1912
def test__send_response_errors_with_base_response(self):
1913
"""Ensure that only the Successful/Failed subclasses are used."""
1914
smart_protocol = self.server_protocol_class(None, lambda x: None)
1915
self.assertRaises(AttributeError, smart_protocol._send_response,
1916
_mod_request.SmartServerResponse(('x',)))
1918
def test_query_version(self):
1919
"""query_version on a SmartClientProtocolTwo should return a number.
1921
The protocol provides the query_version because the domain level clients
1922
may all need to be able to probe for capabilities.
1924
# What we really want to test here is that SmartClientProtocolTwo calls
1925
# accept_bytes(tuple_based_encoding_of_hello) and reads and parses the
1926
# response of tuple-encoded (ok, 1). Also, seperately we should test
1927
# the error if the response is a non-understood version.
1928
input = StringIO(self.response_marker + 'success\nok\x012\n')
1930
client_medium = medium.SmartSimplePipesClientMedium(
1931
input, output, 'base')
1932
request = client_medium.get_request()
1933
smart_protocol = self.client_protocol_class(request)
1934
self.assertEqual(2, smart_protocol.query_version())
1936
def test_client_call_empty_response(self):
1937
# protocol.call() can get back an empty tuple as a response. This occurs
1938
# when the parsed line is an empty line, and results in a tuple with
1939
# one element - an empty string.
1940
self.assertServerToClientEncoding(
1941
self.response_marker + 'success\n\n', ('', ), [(), ('', )])
1943
def test_client_call_three_element_response(self):
1944
# protocol.call() can get back tuples of other lengths. A three element
1945
# tuple should be unpacked as three strings.
1946
self.assertServerToClientEncoding(
1947
self.response_marker + 'success\na\x01b\x0134\n',
1951
def test_client_call_with_body_bytes_uploads(self):
1952
# protocol.call_with_body_bytes should length-prefix the bytes onto the
1954
expected_bytes = self.request_marker + "foo\n7\nabcdefgdone\n"
1955
input = StringIO("\n")
1957
client_medium = medium.SmartSimplePipesClientMedium(
1958
input, output, 'base')
1959
request = client_medium.get_request()
1960
smart_protocol = self.client_protocol_class(request)
1961
smart_protocol.call_with_body_bytes(('foo', ), "abcdefg")
1962
self.assertEqual(expected_bytes, output.getvalue())
1964
def test_client_call_with_body_readv_array(self):
1965
# protocol.call_with_upload should encode the readv array and then
1966
# length-prefix the bytes onto the wire.
1967
expected_bytes = self.request_marker + "foo\n7\n1,2\n5,6done\n"
1968
input = StringIO("\n")
1970
client_medium = medium.SmartSimplePipesClientMedium(
1971
input, output, 'base')
1972
request = client_medium.get_request()
1973
smart_protocol = self.client_protocol_class(request)
1974
smart_protocol.call_with_body_readv_array(('foo', ), [(1,2),(5,6)])
1975
self.assertEqual(expected_bytes, output.getvalue())
1977
def test_client_read_body_bytes_all(self):
1978
# read_body_bytes should decode the body bytes from the wire into
1980
expected_bytes = "1234567"
1981
server_bytes = (self.response_marker +
1982
"success\nok\n7\n1234567done\n")
1983
input = StringIO(server_bytes)
1985
client_medium = medium.SmartSimplePipesClientMedium(
1986
input, output, 'base')
1987
request = client_medium.get_request()
1988
smart_protocol = self.client_protocol_class(request)
1989
smart_protocol.call('foo')
1990
smart_protocol.read_response_tuple(True)
1991
self.assertEqual(expected_bytes, smart_protocol.read_body_bytes())
1993
def test_client_read_body_bytes_incremental(self):
1994
# test reading a few bytes at a time from the body
1995
# XXX: possibly we should test dribbling the bytes into the stringio
1996
# to make the state machine work harder: however, as we use the
1997
# LengthPrefixedBodyDecoder that is already well tested - we can skip
1999
expected_bytes = "1234567"
2000
server_bytes = self.response_marker + "success\nok\n7\n1234567done\n"
2001
input = StringIO(server_bytes)
2003
client_medium = medium.SmartSimplePipesClientMedium(
2004
input, output, 'base')
2005
request = client_medium.get_request()
2006
smart_protocol = self.client_protocol_class(request)
2007
smart_protocol.call('foo')
2008
smart_protocol.read_response_tuple(True)
2009
self.assertEqual(expected_bytes[0:2], smart_protocol.read_body_bytes(2))
2010
self.assertEqual(expected_bytes[2:4], smart_protocol.read_body_bytes(2))
2011
self.assertEqual(expected_bytes[4:6], smart_protocol.read_body_bytes(2))
2012
self.assertEqual(expected_bytes[6], smart_protocol.read_body_bytes())
2014
def test_client_cancel_read_body_does_not_eat_body_bytes(self):
2015
# cancelling the expected body needs to finish the request, but not
2016
# read any more bytes.
2017
server_bytes = self.response_marker + "success\nok\n7\n1234567done\n"
2018
input = StringIO(server_bytes)
2020
client_medium = medium.SmartSimplePipesClientMedium(
2021
input, output, 'base')
2022
request = client_medium.get_request()
2023
smart_protocol = self.client_protocol_class(request)
2024
smart_protocol.call('foo')
2025
smart_protocol.read_response_tuple(True)
2026
smart_protocol.cancel_read_body()
2027
self.assertEqual(len(self.response_marker + 'success\nok\n'),
2030
errors.ReadingCompleted, smart_protocol.read_body_bytes)
2033
class TestSmartProtocolTwoSpecificsMixin(object):
1761
2035
def assertBodyStreamSerialisation(self, expected_serialisation,
1763
2037
"""Assert that body_stream is serialised as expected_serialisation."""
1810
2084
self.assertBodyStreamSerialisation(expected_bytes, stream)
1811
2085
self.assertBodyStreamRoundTrips(stream)
1813
def test_accept_bytes_of_bad_request_to_protocol(self):
1814
out_stream = StringIO()
1815
smart_protocol = protocol.SmartServerRequestProtocolTwo(
1816
None, out_stream.write)
1817
smart_protocol.accept_bytes('abc')
1818
self.assertEqual('abc', smart_protocol.in_buffer)
1819
smart_protocol.accept_bytes('\n')
1821
protocol.RESPONSE_VERSION_TWO +
1822
"failed\nerror\x01Generic bzr smart protocol error: bad request 'abc'\n",
1823
out_stream.getvalue())
1824
self.assertTrue(smart_protocol.has_dispatched)
1825
self.assertEqual(0, smart_protocol.next_read_size())
1827
def test_accept_body_bytes_to_protocol(self):
1828
protocol = self.build_protocol_waiting_for_body()
1829
self.assertEqual(6, protocol.next_read_size())
1830
protocol.accept_bytes('7\nabc')
1831
self.assertEqual(9, protocol.next_read_size())
1832
protocol.accept_bytes('defgd')
1833
protocol.accept_bytes('one\n')
1834
self.assertEqual(0, protocol.next_read_size())
1835
self.assertTrue(self.end_received)
1837
def test_accept_request_and_body_all_at_once(self):
1838
self._captureVar('BZR_NO_SMART_VFS', None)
1839
mem_transport = memory.MemoryTransport()
1840
mem_transport.put_bytes('foo', 'abcdefghij')
1841
out_stream = StringIO()
1842
smart_protocol = protocol.SmartServerRequestProtocolTwo(mem_transport,
1844
smart_protocol.accept_bytes('readv\x01foo\n3\n3,3done\n')
1845
self.assertEqual(0, smart_protocol.next_read_size())
1846
self.assertEqual(protocol.RESPONSE_VERSION_TWO +
1847
'success\nreadv\n3\ndefdone\n',
1848
out_stream.getvalue())
1849
self.assertEqual('', smart_protocol.excess_buffer)
1850
self.assertEqual('', smart_protocol.in_buffer)
1852
def test_accept_excess_bytes_are_preserved(self):
1853
out_stream = StringIO()
1854
smart_protocol = protocol.SmartServerRequestProtocolTwo(
1855
None, out_stream.write)
1856
smart_protocol.accept_bytes('hello\nhello\n')
1857
self.assertEqual(protocol.RESPONSE_VERSION_TWO + "success\nok\x012\n",
1858
out_stream.getvalue())
1859
self.assertEqual("hello\n", smart_protocol.excess_buffer)
1860
self.assertEqual("", smart_protocol.in_buffer)
1862
def test_accept_excess_bytes_after_body(self):
1863
# The excess bytes look like the start of another request.
1864
server_protocol = self.build_protocol_waiting_for_body()
1865
server_protocol.accept_bytes(
1866
'7\nabcdefgdone\n' + protocol.RESPONSE_VERSION_TWO)
1867
self.assertTrue(self.end_received)
1868
self.assertEqual(protocol.RESPONSE_VERSION_TWO,
1869
server_protocol.excess_buffer)
1870
self.assertEqual("", server_protocol.in_buffer)
1871
server_protocol.accept_bytes('Y')
1872
self.assertEqual(protocol.RESPONSE_VERSION_TWO + "Y",
1873
server_protocol.excess_buffer)
1874
self.assertEqual("", server_protocol.in_buffer)
1876
def test_accept_excess_bytes_after_dispatch(self):
1877
out_stream = StringIO()
1878
smart_protocol = protocol.SmartServerRequestProtocolTwo(
1879
None, out_stream.write)
1880
smart_protocol.accept_bytes('hello\n')
1881
self.assertEqual(protocol.RESPONSE_VERSION_TWO + "success\nok\x012\n",
1882
out_stream.getvalue())
1883
smart_protocol.accept_bytes(protocol.REQUEST_VERSION_TWO + 'hel')
1884
self.assertEqual(protocol.REQUEST_VERSION_TWO + "hel",
1885
smart_protocol.excess_buffer)
1886
smart_protocol.accept_bytes('lo\n')
1887
self.assertEqual(protocol.REQUEST_VERSION_TWO + "hello\n",
1888
smart_protocol.excess_buffer)
1889
self.assertEqual("", smart_protocol.in_buffer)
1891
def test__send_response_sets_finished_reading(self):
1892
smart_protocol = protocol.SmartServerRequestProtocolTwo(
1893
None, lambda x: None)
1894
self.assertEqual(1, smart_protocol.next_read_size())
1895
smart_protocol._send_response(
1896
_mod_request.SuccessfulSmartServerResponse(('x',)))
1897
self.assertEqual(0, smart_protocol.next_read_size())
1899
def test__send_response_with_body_stream_sets_finished_reading(self):
1900
smart_protocol = protocol.SmartServerRequestProtocolTwo(
1901
None, lambda x: None)
1902
self.assertEqual(1, smart_protocol.next_read_size())
1903
smart_protocol._send_response(
1904
_mod_request.SuccessfulSmartServerResponse(('x',), body_stream=[]))
1905
self.assertEqual(0, smart_protocol.next_read_size())
1907
def test__send_response_errors_with_base_response(self):
1908
"""Ensure that only the Successful/Failed subclasses are used."""
1909
smart_protocol = protocol.SmartServerRequestProtocolTwo(
1910
None, lambda x: None)
1911
self.assertRaises(AttributeError, smart_protocol._send_response,
1912
_mod_request.SmartServerResponse(('x',)))
1914
2087
def test__send_response_includes_failure_marker(self):
1915
2088
"""FailedSmartServerResponse have 'failed\n' after the version."""
1916
2089
out_stream = StringIO()
1931
2104
self.assertEqual(protocol.RESPONSE_VERSION_TWO + 'success\nx\n',
1932
2105
out_stream.getvalue())
1934
def test_query_version(self):
1935
"""query_version on a SmartClientProtocolTwo should return a number.
1937
The protocol provides the query_version because the domain level clients
1938
may all need to be able to probe for capabilities.
1940
# What we really want to test here is that SmartClientProtocolTwo calls
1941
# accept_bytes(tuple_based_encoding_of_hello) and reads and parses the
1942
# response of tuple-encoded (ok, 1). Also, seperately we should test
1943
# the error if the response is a non-understood version.
1944
input = StringIO(protocol.RESPONSE_VERSION_TWO + 'success\nok\x012\n')
1946
client_medium = medium.SmartSimplePipesClientMedium(input, output)
1947
request = client_medium.get_request()
1948
smart_protocol = protocol.SmartClientRequestProtocolTwo(request)
1949
self.assertEqual(2, smart_protocol.query_version())
1951
def test_client_call_empty_response(self):
1952
# protocol.call() can get back an empty tuple as a response. This occurs
1953
# when the parsed line is an empty line, and results in a tuple with
1954
# one element - an empty string.
1955
self.assertServerToClientEncoding(
1956
protocol.RESPONSE_VERSION_TWO + 'success\n\n', ('', ), [(), ('', )])
1958
def test_client_call_three_element_response(self):
1959
# protocol.call() can get back tuples of other lengths. A three element
1960
# tuple should be unpacked as three strings.
1961
self.assertServerToClientEncoding(
1962
protocol.RESPONSE_VERSION_TWO + 'success\na\x01b\x0134\n',
1966
def test_client_call_with_body_bytes_uploads(self):
1967
# protocol.call_with_body_bytes should length-prefix the bytes onto the
1969
expected_bytes = protocol.REQUEST_VERSION_TWO + "foo\n7\nabcdefgdone\n"
1970
input = StringIO("\n")
1972
client_medium = medium.SmartSimplePipesClientMedium(input, output)
1973
request = client_medium.get_request()
1974
smart_protocol = protocol.SmartClientRequestProtocolTwo(request)
1975
smart_protocol.call_with_body_bytes(('foo', ), "abcdefg")
1976
self.assertEqual(expected_bytes, output.getvalue())
1978
def test_client_call_with_body_readv_array(self):
1979
# protocol.call_with_upload should encode the readv array and then
1980
# length-prefix the bytes onto the wire.
1981
expected_bytes = protocol.REQUEST_VERSION_TWO+"foo\n7\n1,2\n5,6done\n"
1982
input = StringIO("\n")
1984
client_medium = medium.SmartSimplePipesClientMedium(input, output)
1985
request = client_medium.get_request()
1986
smart_protocol = protocol.SmartClientRequestProtocolTwo(request)
1987
smart_protocol.call_with_body_readv_array(('foo', ), [(1,2),(5,6)])
1988
self.assertEqual(expected_bytes, output.getvalue())
1990
def test_client_read_response_tuple_sets_response_status(self):
1991
server_bytes = protocol.RESPONSE_VERSION_TWO + "success\nok\n"
1992
input = StringIO(server_bytes)
1994
client_medium = medium.SmartSimplePipesClientMedium(input, output)
1995
request = client_medium.get_request()
1996
smart_protocol = protocol.SmartClientRequestProtocolTwo(request)
1997
smart_protocol.call('foo')
1998
smart_protocol.read_response_tuple(False)
1999
self.assertEqual(True, smart_protocol.response_status)
2001
def test_client_read_response_tuple_raises_UnknownSmartMethod(self):
2002
"""read_response_tuple raises UnknownSmartMethod if the response is
2003
says the server did not recognise the request.
2006
protocol.RESPONSE_VERSION_TWO +
2008
"error\x01Generic bzr smart protocol error: bad request 'foo'\n")
2009
input = StringIO(server_bytes)
2011
client_medium = medium.SmartSimplePipesClientMedium(input, output)
2012
request = client_medium.get_request()
2013
smart_protocol = protocol.SmartClientRequestProtocolTwo(request)
2014
smart_protocol.call('foo')
2016
errors.UnknownSmartMethod, smart_protocol.read_response_tuple)
2017
self.assertEqual(False, smart_protocol.response_status)
2018
# The request has been finished. There is no body to read, and
2019
# attempts to read one will fail.
2021
errors.ReadingCompleted, smart_protocol.read_body_bytes)
2023
def test_client_read_body_bytes_all(self):
2024
# read_body_bytes should decode the body bytes from the wire into
2026
expected_bytes = "1234567"
2027
server_bytes = (protocol.RESPONSE_VERSION_TWO +
2028
"success\nok\n7\n1234567done\n")
2029
input = StringIO(server_bytes)
2031
client_medium = medium.SmartSimplePipesClientMedium(input, output)
2032
request = client_medium.get_request()
2033
smart_protocol = protocol.SmartClientRequestProtocolTwo(request)
2034
smart_protocol.call('foo')
2035
smart_protocol.read_response_tuple(True)
2036
self.assertEqual(expected_bytes, smart_protocol.read_body_bytes())
2038
def test_client_read_body_bytes_incremental(self):
2039
# test reading a few bytes at a time from the body
2040
# XXX: possibly we should test dribbling the bytes into the stringio
2041
# to make the state machine work harder: however, as we use the
2042
# LengthPrefixedBodyDecoder that is already well tested - we can skip
2044
expected_bytes = "1234567"
2045
server_bytes = (protocol.RESPONSE_VERSION_TWO +
2046
"success\nok\n7\n1234567done\n")
2047
input = StringIO(server_bytes)
2049
client_medium = medium.SmartSimplePipesClientMedium(input, output)
2050
request = client_medium.get_request()
2051
smart_protocol = protocol.SmartClientRequestProtocolTwo(request)
2052
smart_protocol.call('foo')
2053
smart_protocol.read_response_tuple(True)
2054
self.assertEqual(expected_bytes[0:2], smart_protocol.read_body_bytes(2))
2055
self.assertEqual(expected_bytes[2:4], smart_protocol.read_body_bytes(2))
2056
self.assertEqual(expected_bytes[4:6], smart_protocol.read_body_bytes(2))
2057
self.assertEqual(expected_bytes[6], smart_protocol.read_body_bytes())
2059
def test_client_cancel_read_body_does_not_eat_body_bytes(self):
2060
# cancelling the expected body needs to finish the request, but not
2061
# read any more bytes.
2062
server_bytes = (protocol.RESPONSE_VERSION_TWO +
2063
"success\nok\n7\n1234567done\n")
2064
input = StringIO(server_bytes)
2066
client_medium = medium.SmartSimplePipesClientMedium(input, output)
2067
request = client_medium.get_request()
2068
smart_protocol = protocol.SmartClientRequestProtocolTwo(request)
2069
smart_protocol.call('foo')
2070
smart_protocol.read_response_tuple(True)
2071
smart_protocol.cancel_read_body()
2072
self.assertEqual(len(protocol.RESPONSE_VERSION_TWO + 'success\nok\n'),
2075
errors.ReadingCompleted, smart_protocol.read_body_bytes)
2107
def test__send_response_with_body_stream_sets_finished_reading(self):
2108
smart_protocol = protocol.SmartServerRequestProtocolTwo(
2109
None, lambda x: None)
2110
self.assertEqual(1, smart_protocol.next_read_size())
2111
smart_protocol._send_response(
2112
_mod_request.SuccessfulSmartServerResponse(('x',), body_stream=[]))
2113
self.assertEqual(0, smart_protocol.next_read_size())
2077
2115
def test_streamed_body_bytes(self):
2078
2116
body_header = 'chunked\n'
2114
2154
stream = smart_protocol.read_streamed_body()
2115
2155
self.assertEqual(expected_chunks, list(stream))
2157
def test_client_read_response_tuple_sets_response_status(self):
2158
server_bytes = protocol.RESPONSE_VERSION_TWO + "success\nok\n"
2159
input = StringIO(server_bytes)
2161
client_medium = medium.SmartSimplePipesClientMedium(
2162
input, output, 'base')
2163
request = client_medium.get_request()
2164
smart_protocol = protocol.SmartClientRequestProtocolTwo(request)
2165
smart_protocol.call('foo')
2166
smart_protocol.read_response_tuple(False)
2167
self.assertEqual(True, smart_protocol.response_status)
2169
def test_client_read_response_tuple_raises_UnknownSmartMethod(self):
2170
"""read_response_tuple raises UnknownSmartMethod if the response says
2171
the server did not recognise the request.
2174
protocol.RESPONSE_VERSION_TWO +
2176
"error\x01Generic bzr smart protocol error: bad request 'foo'\n")
2177
input = StringIO(server_bytes)
2179
client_medium = medium.SmartSimplePipesClientMedium(
2180
input, output, 'base')
2181
request = client_medium.get_request()
2182
smart_protocol = protocol.SmartClientRequestProtocolTwo(request)
2183
smart_protocol.call('foo')
2185
errors.UnknownSmartMethod, smart_protocol.read_response_tuple)
2186
# The request has been finished. There is no body to read, and
2187
# attempts to read one will fail.
2189
errors.ReadingCompleted, smart_protocol.read_body_bytes)
2192
class TestSmartProtocolTwoSpecifics(
2193
TestSmartProtocol, TestSmartProtocolTwoSpecificsMixin):
2194
"""Tests for aspects of smart protocol version two that are unique to
2197
Thus tests involving body streams and success/failure markers belong here.
2200
client_protocol_class = protocol.SmartClientRequestProtocolTwo
2201
server_protocol_class = protocol.SmartServerRequestProtocolTwo
2204
class TestVersionOneFeaturesInProtocolThree(
2205
TestSmartProtocol, CommonSmartProtocolTestMixin):
2206
"""Tests for version one smart protocol features as implemented by version
2210
request_encoder = protocol.ProtocolThreeRequester
2211
response_decoder = protocol.ProtocolThreeDecoder
2212
# build_server_protocol_three is a function, so we can't set it as a class
2213
# attribute directly, because then Python will assume it is actually a
2214
# method. So we make server_protocol_class be a static method, rather than
2216
# "server_protocol_class = protocol.build_server_protocol_three".
2217
server_protocol_class = staticmethod(protocol.build_server_protocol_three)
2220
super(TestVersionOneFeaturesInProtocolThree, self).setUp()
2221
self.response_marker = protocol.MESSAGE_VERSION_THREE
2222
self.request_marker = protocol.MESSAGE_VERSION_THREE
2224
def test_construct_version_three_server_protocol(self):
2225
smart_protocol = protocol.ProtocolThreeDecoder(None)
2226
self.assertEqual('', smart_protocol.unused_data)
2227
self.assertEqual('', smart_protocol._in_buffer)
2228
self.assertFalse(smart_protocol._has_dispatched)
2229
# The protocol starts by expecting four bytes, a length prefix for the
2231
self.assertEqual(4, smart_protocol.next_read_size())
2234
class NoOpRequest(_mod_request.SmartServerRequest):
2237
return _mod_request.SuccessfulSmartServerResponse(())
2239
dummy_registry = {'ARG': NoOpRequest}
2242
class LoggingMessageHandler(object):
2247
def _log(self, *args):
2248
self.event_log.append(args)
2250
def headers_received(self, headers):
2251
self._log('headers', headers)
2253
def protocol_error(self, exception):
2254
self._log('protocol_error', exception)
2256
def byte_part_received(self, byte):
2257
self._log('byte', byte)
2259
def bytes_part_received(self, bytes):
2260
self._log('bytes', bytes)
2262
def structure_part_received(self, structure):
2263
self._log('structure', structure)
2265
def end_received(self):
2269
class TestProtocolThree(TestSmartProtocol):
2270
"""Tests for v3 of the server-side protocol."""
2272
request_encoder = protocol.ProtocolThreeRequester
2273
response_decoder = protocol.ProtocolThreeDecoder
2274
server_protocol_class = protocol.ProtocolThreeDecoder
2276
def test_trivial_request(self):
2277
"""Smoke test for the simplest possible v3 request: empty headers, no
2281
headers = '\0\0\0\x02de' # length-prefixed, bencoded empty dict
2283
request_bytes = headers + end
2284
smart_protocol = self.server_protocol_class(LoggingMessageHandler())
2285
smart_protocol.accept_bytes(request_bytes)
2286
self.assertEqual(0, smart_protocol.next_read_size())
2287
self.assertEqual('', smart_protocol.unused_data)
2289
def make_protocol_expecting_message_part(self):
2290
headers = '\0\0\0\x02de' # length-prefixed, bencoded empty dict
2291
message_handler = LoggingMessageHandler()
2292
smart_protocol = self.server_protocol_class(message_handler)
2293
smart_protocol.accept_bytes(headers)
2294
# Clear the event log
2295
del message_handler.event_log[:]
2296
return smart_protocol, message_handler.event_log
2298
def test_decode_one_byte(self):
2299
"""The protocol can decode a 'one byte' message part."""
2300
smart_protocol, event_log = self.make_protocol_expecting_message_part()
2301
smart_protocol.accept_bytes('ox')
2302
self.assertEqual([('byte', 'x')], event_log)
2304
def test_decode_bytes(self):
2305
"""The protocol can decode a 'bytes' message part."""
2306
smart_protocol, event_log = self.make_protocol_expecting_message_part()
2307
smart_protocol.accept_bytes(
2308
'b' # message part kind
2309
'\0\0\0\x07' # length prefix
2312
self.assertEqual([('bytes', 'payload')], event_log)
2314
def test_decode_structure(self):
2315
"""The protocol can decode a 'structure' message part."""
2316
smart_protocol, event_log = self.make_protocol_expecting_message_part()
2317
smart_protocol.accept_bytes(
2318
's' # message part kind
2319
'\0\0\0\x07' # length prefix
2322
self.assertEqual([('structure', ['ARG'])], event_log)
2324
def test_decode_multiple_bytes(self):
2325
"""The protocol can decode a multiple 'bytes' message parts."""
2326
smart_protocol, event_log = self.make_protocol_expecting_message_part()
2327
smart_protocol.accept_bytes(
2328
'b' # message part kind
2329
'\0\0\0\x05' # length prefix
2331
'b' # message part kind
2336
[('bytes', 'first'), ('bytes', 'second')], event_log)
2339
class TestConventionalResponseHandler(tests.TestCase):
2341
def test_interrupted_body_stream(self):
2342
interrupted_body_stream = (
2343
'oS' # successful response
2344
's\0\0\0\x02le' # empty args
2345
'b\0\0\0\x09chunk one' # first chunk
2346
'b\0\0\0\x09chunk two' # second chunk
2348
's\0\0\0\x0el5:error3:abce' # bencoded error
2351
from bzrlib.smart.message import ConventionalResponseHandler
2352
response_handler = ConventionalResponseHandler()
2353
protocol_decoder = protocol.ProtocolThreeDecoder(response_handler)
2354
# put decoder in desired state (waiting for message parts)
2355
protocol_decoder.state_accept = protocol_decoder._state_accept_expecting_message_part
2357
client_medium = medium.SmartSimplePipesClientMedium(
2358
StringIO(interrupted_body_stream), output, 'base')
2359
medium_request = client_medium.get_request()
2360
medium_request.finished_writing()
2361
response_handler.setProtoAndMediumRequest(
2362
protocol_decoder, medium_request)
2363
stream = response_handler.read_streamed_body()
2364
self.assertEqual('chunk one', stream.next())
2365
self.assertEqual('chunk two', stream.next())
2366
exc = self.assertRaises(errors.ErrorFromSmartServer, stream.next)
2367
self.assertEqual(('error', 'abc'), exc.error_tuple)
2370
class TestMessageHandlerErrors(tests.TestCase):
2371
"""Tests for v3 that unrecognised (but well-formed) requests/responses are
2372
still fully read off the wire, so that subsequent requests/responses on the
2373
same medium can be decoded.
2376
def test_non_conventional_request(self):
2377
"""ConventionalRequestHandler (the default message handler on the
2378
server side) will reject an unconventional message, but still consume
2379
all the bytes of that message and signal when it has done so.
2381
This is what allows a server to continue to accept requests after the
2382
client sends a completely unrecognised request.
2384
# Define an invalid request (but one that is a well-formed message).
2385
# This particular invalid request not only lacks the mandatory
2386
# verb+args tuple, it has a single-byte part, which is forbidden. In
2387
# fact it has that part twice, to trigger multiple errors.
2389
protocol.MESSAGE_VERSION_THREE + # protocol version marker
2390
'\0\0\0\x02de' + # empty headers
2391
'oX' + # a single byte part: 'X'. ConventionalRequestHandler will
2392
# error at this part.
2394
'e' # end of message
2397
to_server = StringIO(invalid_request)
2398
from_server = StringIO()
2399
transport = memory.MemoryTransport('memory:///')
2400
server = medium.SmartServerPipeStreamMedium(
2401
to_server, from_server, transport)
2402
proto = server._build_protocol()
2403
message_handler = proto.message_handler
2404
server._serve_one_request(proto)
2405
# All the bytes have been read from the medium...
2406
self.assertEqual('', to_server.read())
2407
# ...and the protocol decoder has consumed all the bytes, and has
2409
self.assertEqual('', proto.unused_data)
2410
self.assertEqual(0, proto.next_read_size())
2413
class InstrumentedRequestHandler(object):
2414
"""Test Double of SmartServerRequestHandler."""
2419
def body_chunk_received(self, chunk_bytes):
2420
self.calls.append(('body_chunk_received', chunk_bytes))
2422
def no_body_received(self):
2423
self.calls.append(('no_body_received',))
2425
def prefixed_body_received(self, body_bytes):
2426
self.calls.append(('prefixed_body_received', body_bytes))
2428
def end_received(self):
2429
self.calls.append(('end_received',))
2432
class StubRequest(object):
2434
def finished_reading(self):
2438
class TestClientDecodingProtocolThree(TestSmartProtocol):
2439
"""Tests for v3 of the client-side protocol decoding."""
2441
def make_logging_response_decoder(self):
2442
"""Make v3 response decoder using a test response handler."""
2443
response_handler = LoggingMessageHandler()
2444
decoder = protocol.ProtocolThreeDecoder(response_handler)
2445
return decoder, response_handler
2447
def make_conventional_response_decoder(self):
2448
"""Make v3 response decoder using a conventional response handler."""
2449
response_handler = message.ConventionalResponseHandler()
2450
decoder = protocol.ProtocolThreeDecoder(response_handler)
2451
response_handler.setProtoAndMediumRequest(decoder, StubRequest())
2452
return decoder, response_handler
2454
def test_trivial_response_decoding(self):
2455
"""Smoke test for the simplest possible v3 response: empty headers,
2456
status byte, empty args, no body.
2458
headers = '\0\0\0\x02de' # length-prefixed, bencoded empty dict
2459
response_status = 'oS' # success
2460
args = 's\0\0\0\x02le' # length-prefixed, bencoded empty list
2461
end = 'e' # end marker
2462
message_bytes = headers + response_status + args + end
2463
decoder, response_handler = self.make_logging_response_decoder()
2464
decoder.accept_bytes(message_bytes)
2465
# The protocol decoder has finished, and consumed all bytes
2466
self.assertEqual(0, decoder.next_read_size())
2467
self.assertEqual('', decoder.unused_data)
2468
# The message handler has been invoked with all the parts of the
2469
# trivial response: empty headers, status byte, no args, end.
2471
[('headers', {}), ('byte', 'S'), ('structure', []), ('end',)],
2472
response_handler.event_log)
2474
def test_incomplete_message(self):
2475
"""A decoder will keep signalling that it needs more bytes via
2476
next_read_size() != 0 until it has seen a complete message, regardless
2477
which state it is in.
2479
# Define a simple response that uses all possible message parts.
2480
headers = '\0\0\0\x02de' # length-prefixed, bencoded empty dict
2481
response_status = 'oS' # success
2482
args = 's\0\0\0\x02le' # length-prefixed, bencoded empty list
2483
body = 'b\0\0\0\x04BODY' # a body: 'BODY'
2484
end = 'e' # end marker
2485
simple_response = headers + response_status + args + body + end
2486
# Feed the request to the decoder one byte at a time.
2487
decoder, response_handler = self.make_logging_response_decoder()
2488
for byte in simple_response:
2489
self.assertNotEqual(0, decoder.next_read_size())
2490
decoder.accept_bytes(byte)
2491
# Now the response is complete
2492
self.assertEqual(0, decoder.next_read_size())
2494
def test_read_response_tuple_raises_UnknownSmartMethod(self):
2495
"""read_response_tuple raises UnknownSmartMethod if the server replied
2496
with 'UnknownMethod'.
2498
headers = '\0\0\0\x02de' # length-prefixed, bencoded empty dict
2499
response_status = 'oE' # error flag
2500
# args: ('UnknownMethod', 'method-name')
2501
args = 's\0\0\0\x20l13:UnknownMethod11:method-namee'
2502
end = 'e' # end marker
2503
message_bytes = headers + response_status + args + end
2504
decoder, response_handler = self.make_conventional_response_decoder()
2505
decoder.accept_bytes(message_bytes)
2506
error = self.assertRaises(
2507
errors.UnknownSmartMethod, response_handler.read_response_tuple)
2508
self.assertEqual('method-name', error.verb)
2510
def test_read_response_tuple_error(self):
2511
"""If the response has an error, it is raised as an exception."""
2512
headers = '\0\0\0\x02de' # length-prefixed, bencoded empty dict
2513
response_status = 'oE' # error
2514
args = 's\0\0\0\x1al9:first arg10:second arge' # two args
2515
end = 'e' # end marker
2516
message_bytes = headers + response_status + args + end
2517
decoder, response_handler = self.make_conventional_response_decoder()
2518
decoder.accept_bytes(message_bytes)
2519
error = self.assertRaises(
2520
errors.ErrorFromSmartServer, response_handler.read_response_tuple)
2521
self.assertEqual(('first arg', 'second arg'), error.error_tuple)
2524
class TestClientEncodingProtocolThree(TestSmartProtocol):
2526
request_encoder = protocol.ProtocolThreeRequester
2527
response_decoder = protocol.ProtocolThreeDecoder
2528
server_protocol_class = protocol.ProtocolThreeDecoder
2530
def make_client_encoder_and_output(self):
2531
result = self.make_client_protocol_and_output()
2532
requester, response_handler, output = result
2533
return requester, output
2535
def test_call_smoke_test(self):
2536
"""A smoke test for ProtocolThreeRequester.call.
2538
This test checks that a particular simple invocation of call emits the
2539
correct bytes for that invocation.
2541
requester, output = self.make_client_encoder_and_output()
2542
requester.set_headers({'header name': 'header value'})
2543
requester.call('one arg')
2545
'bzr message 3 (bzr 1.6)\n' # protocol version
2546
'\x00\x00\x00\x1fd11:header name12:header valuee' # headers
2547
's\x00\x00\x00\x0bl7:one arge' # args
2551
def test_call_with_body_bytes_smoke_test(self):
2552
"""A smoke test for ProtocolThreeRequester.call_with_body_bytes.
2554
This test checks that a particular simple invocation of
2555
call_with_body_bytes emits the correct bytes for that invocation.
2557
requester, output = self.make_client_encoder_and_output()
2558
requester.set_headers({'header name': 'header value'})
2559
requester.call_with_body_bytes(('one arg',), 'body bytes')
2561
'bzr message 3 (bzr 1.6)\n' # protocol version
2562
'\x00\x00\x00\x1fd11:header name12:header valuee' # headers
2563
's\x00\x00\x00\x0bl7:one arge' # args
2564
'b' # there is a prefixed body
2565
'\x00\x00\x00\nbody bytes' # the prefixed body
2569
def test_call_writes_just_once(self):
2570
"""A bodyless request is written to the medium all at once."""
2571
medium_request = StubMediumRequest()
2572
encoder = protocol.ProtocolThreeRequester(medium_request)
2573
encoder.call('arg1', 'arg2', 'arg3')
2575
['accept_bytes', 'finished_writing'], medium_request.calls)
2577
def test_call_with_body_bytes_writes_just_once(self):
2578
"""A request with body bytes is written to the medium all at once."""
2579
medium_request = StubMediumRequest()
2580
encoder = protocol.ProtocolThreeRequester(medium_request)
2581
encoder.call_with_body_bytes(('arg', 'arg'), 'body bytes')
2583
['accept_bytes', 'finished_writing'], medium_request.calls)
2586
class StubMediumRequest(object):
2587
"""A stub medium request that tracks the number of times accept_bytes is
2594
def accept_bytes(self, bytes):
2595
self.calls.append('accept_bytes')
2597
def finished_writing(self):
2598
self.calls.append('finished_writing')
2601
class TestResponseEncodingProtocolThree(tests.TestCase):
2603
def make_response_encoder(self):
2604
out_stream = StringIO()
2605
response_encoder = protocol.ProtocolThreeResponder(out_stream.write)
2606
return response_encoder, out_stream
2608
def test_send_error_unknown_method(self):
2609
encoder, out_stream = self.make_response_encoder()
2610
encoder.send_error(errors.UnknownSmartMethod('method name'))
2611
# Use assertEndsWith so that we don't compare the header, which varies
2612
# by bzrlib.__version__.
2613
self.assertEndsWith(
2614
out_stream.getvalue(),
2617
# tuple: 'UnknownMethod', 'method name'
2618
's\x00\x00\x00\x20l13:UnknownMethod11:method namee'
2623
class TestResponseEncoderBufferingProtocolThree(tests.TestCase):
2624
"""Tests for buffering of responses.
2626
We want to avoid doing many small writes when one would do, to avoid
2627
unnecessary network overhead.
2632
self.responder = protocol.ProtocolThreeResponder(self.writes.append)
2634
def assertWriteCount(self, expected_count):
2636
expected_count, len(self.writes),
2637
"Too many writes: %r" % (self.writes,))
2639
def test_send_error_writes_just_once(self):
2640
"""An error response is written to the medium all at once."""
2641
self.responder.send_error(Exception('An exception string.'))
2642
self.assertWriteCount(1)
2644
def test_send_response_writes_just_once(self):
2645
"""A normal response with no body is written to the medium all at once.
2647
response = _mod_request.SuccessfulSmartServerResponse(('arg', 'arg'))
2648
self.responder.send_response(response)
2649
self.assertWriteCount(1)
2651
def test_send_response_with_body_writes_just_once(self):
2652
"""A normal response with a monolithic body is written to the medium
2655
response = _mod_request.SuccessfulSmartServerResponse(
2656
('arg', 'arg'), body='body bytes')
2657
self.responder.send_response(response)
2658
self.assertWriteCount(1)
2660
def test_send_response_with_body_stream_writes_once_per_chunk(self):
2661
"""A normal response with a stream body is written to the medium
2662
writes to the medium once per chunk.
2664
# Construct a response with stream with 2 chunks in it.
2665
response = _mod_request.SuccessfulSmartServerResponse(
2666
('arg', 'arg'), body_stream=['chunk1', 'chunk2'])
2667
self.responder.send_response(response)
2668
# We will write 3 times: exactly once for each chunk, plus a final
2669
# write to end the response.
2670
self.assertWriteCount(3)
2118
2673
class TestSmartClientUnicode(tests.TestCase):
2119
2674
"""_SmartClient tests for unicode arguments.
2152
2708
self.assertCallDoesNotBreakMedium('method', ('args',), u'body')
2711
class MockMedium(object):
2712
"""A mock medium that can be used to test _SmartClient.
2714
It can be given a series of requests to expect (and responses it should
2715
return for them). It can also be told when the client is expected to
2716
disconnect a medium. Expectations must be satisfied in the order they are
2717
given, or else an AssertionError will be raised.
2719
Typical use looks like::
2721
medium = MockMedium()
2722
medium.expect_request(...)
2723
medium.expect_request(...)
2724
medium.expect_request(...)
2728
self.base = 'dummy base'
2729
self._mock_request = _MockMediumRequest(self)
2730
self._expected_events = []
2731
self._protocol_version = None
2733
def expect_request(self, request_bytes, response_bytes,
2734
allow_partial_read=False):
2735
"""Expect 'request_bytes' to be sent, and reply with 'response_bytes'.
2737
No assumption is made about how many times accept_bytes should be
2738
called to send the request. Similarly, no assumption is made about how
2739
many times read_bytes/read_line are called by protocol code to read a
2742
request.accept_bytes('ab')
2743
request.accept_bytes('cd')
2744
request.finished_writing()
2748
request.accept_bytes('abcd')
2749
request.finished_writing()
2751
Will both satisfy ``medium.expect_request('abcd', ...)``. Thus tests
2752
using this should not break due to irrelevant changes in protocol
2755
:param allow_partial_read: if True, no assertion is raised if a
2756
response is not fully read. Setting this is useful when the client
2757
is expected to disconnect without needing to read the complete
2758
response. Default is False.
2760
self._expected_events.append(('send request', request_bytes))
2761
if allow_partial_read:
2762
self._expected_events.append(
2763
('read response (partial)', response_bytes))
2765
self._expected_events.append(('read response', response_bytes))
2767
def expect_disconnect(self):
2768
"""Expect the client to call ``medium.disconnect()``."""
2769
self._expected_events.append('disconnect')
2771
def _assertEvent(self, observed_event):
2772
"""Raise AssertionError unless observed_event matches the next expected
2775
:seealso: expect_request
2776
:seealso: expect_disconnect
2779
expected_event = self._expected_events.pop(0)
2781
raise AssertionError(
2782
'Mock medium observed event %r, but no more events expected'
2783
% (observed_event,))
2784
if expected_event[0] == 'read response (partial)':
2785
if observed_event[0] != 'read response':
2786
raise AssertionError(
2787
'Mock medium observed event %r, but expected event %r'
2788
% (observed_event, expected_event))
2789
elif observed_event != expected_event:
2790
raise AssertionError(
2791
'Mock medium observed event %r, but expected event %r'
2792
% (observed_event, expected_event))
2793
if self._expected_events:
2794
next_event = self._expected_events[0]
2795
if next_event[0].startswith('read response'):
2796
self._mock_request._response = next_event[1]
2798
def get_request(self):
2799
return self._mock_request
2801
def disconnect(self):
2802
if self._mock_request._read_bytes:
2803
self._assertEvent(('read response', self._mock_request._read_bytes))
2804
self._mock_request._read_bytes = ''
2805
self._assertEvent('disconnect')
2808
class _MockMediumRequest(object):
2809
"""A mock ClientMediumRequest used by MockMedium."""
2811
def __init__(self, mock_medium):
2812
self._medium = mock_medium
2813
self._written_bytes = ''
2814
self._read_bytes = ''
2815
self._response = None
2817
def accept_bytes(self, bytes):
2818
self._written_bytes += bytes
2820
def finished_writing(self):
2821
self._medium._assertEvent(('send request', self._written_bytes))
2822
self._written_bytes = ''
2824
def finished_reading(self):
2825
self._medium._assertEvent(('read response', self._read_bytes))
2826
self._read_bytes = ''
2828
def read_bytes(self, size):
2829
resp = self._response
2830
bytes, resp = resp[:size], resp[size:]
2831
self._response = resp
2832
self._read_bytes += bytes
2835
def read_line(self):
2836
resp = self._response
2838
line, resp = resp.split('\n', 1)
2841
line, resp = resp, ''
2842
self._response = resp
2843
self._read_bytes += line
2847
class Test_SmartClientVersionDetection(tests.TestCase):
2848
"""Tests for _SmartClient's automatic protocol version detection.
2850
On the first remote call, _SmartClient will keep retrying the request with
2851
different protocol versions until it finds one that works.
2854
def test_version_three_server(self):
2855
"""With a protocol 3 server, only one request is needed."""
2856
medium = MockMedium()
2857
smart_client = client._SmartClient(medium, headers={})
2858
message_start = protocol.MESSAGE_VERSION_THREE + '\x00\x00\x00\x02de'
2859
medium.expect_request(
2861
's\x00\x00\x00\x1el11:method-name5:arg 15:arg 2ee',
2862
message_start + 's\0\0\0\x13l14:response valueee')
2863
result = smart_client.call('method-name', 'arg 1', 'arg 2')
2864
# The call succeeded without raising any exceptions from the mock
2865
# medium, and the smart_client returns the response from the server.
2866
self.assertEqual(('response value',), result)
2867
self.assertEqual([], medium._expected_events)
2869
def test_version_two_server(self):
2870
"""If the server only speaks protocol 2, the client will first try
2871
version 3, then fallback to protocol 2.
2873
Further, _SmartClient caches the detection, so future requests will all
2874
use protocol 2 immediately.
2876
medium = MockMedium()
2877
smart_client = client._SmartClient(medium, headers={})
2878
# First the client should send a v3 request, but the server will reply
2880
medium.expect_request(
2881
'bzr message 3 (bzr 1.6)\n\x00\x00\x00\x02de' +
2882
's\x00\x00\x00\x1el11:method-name5:arg 15:arg 2ee',
2883
'bzr response 2\nfailed\n\n')
2884
# So then the client should disconnect to reset the connection, because
2885
# the client needs to assume the server cannot read any further
2886
# requests off the original connection.
2887
medium.expect_disconnect()
2888
# The client should then retry the original request in v2
2889
medium.expect_request(
2890
'bzr request 2\nmethod-name\x01arg 1\x01arg 2\n',
2891
'bzr response 2\nsuccess\nresponse value\n')
2892
result = smart_client.call('method-name', 'arg 1', 'arg 2')
2893
# The smart_client object will return the result of the successful
2895
self.assertEqual(('response value',), result)
2897
# Now try another request, and this time the client will just use
2898
# protocol 2. (i.e. the autodetection won't be repeated)
2899
medium.expect_request(
2900
'bzr request 2\nanother-method\n',
2901
'bzr response 2\nsuccess\nanother response\n')
2902
result = smart_client.call('another-method')
2903
self.assertEqual(('another response',), result)
2904
self.assertEqual([], medium._expected_events)
2906
def test_unknown_version(self):
2907
"""If the server does not use any known (or at least supported)
2908
protocol version, a SmartProtocolError is raised.
2910
medium = MockMedium()
2911
smart_client = client._SmartClient(medium, headers={})
2912
unknown_protocol_bytes = 'Unknown protocol!'
2913
# The client will try v3 and v2 before eventually giving up.
2914
medium.expect_request(
2915
'bzr message 3 (bzr 1.6)\n\x00\x00\x00\x02de' +
2916
's\x00\x00\x00\x1el11:method-name5:arg 15:arg 2ee',
2917
unknown_protocol_bytes)
2918
medium.expect_disconnect()
2919
medium.expect_request(
2920
'bzr request 2\nmethod-name\x01arg 1\x01arg 2\n',
2921
unknown_protocol_bytes)
2922
medium.expect_disconnect()
2924
errors.SmartProtocolError,
2925
smart_client.call, 'method-name', 'arg 1', 'arg 2')
2926
self.assertEqual([], medium._expected_events)
2929
class Test_SmartClient(tests.TestCase):
2931
def test_call_default_headers(self):
2932
"""ProtocolThreeRequester.call by default sends a 'Software
2935
smart_client = client._SmartClient('dummy medium')
2937
bzrlib.__version__, smart_client._headers['Software version'])
2938
# XXX: need a test that smart_client._headers is passed to the request
2155
2942
class LengthPrefixedBodyDecoder(tests.TestCase):
2157
2944
# XXX: TODO: make accept_reading_trailer invoke translate_response or