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
2593
self._medium = 'dummy medium'
2595
def accept_bytes(self, bytes):
2596
self.calls.append('accept_bytes')
2598
def finished_writing(self):
2599
self.calls.append('finished_writing')
2602
class TestResponseEncodingProtocolThree(tests.TestCase):
2604
def make_response_encoder(self):
2605
out_stream = StringIO()
2606
response_encoder = protocol.ProtocolThreeResponder(out_stream.write)
2607
return response_encoder, out_stream
2609
def test_send_error_unknown_method(self):
2610
encoder, out_stream = self.make_response_encoder()
2611
encoder.send_error(errors.UnknownSmartMethod('method name'))
2612
# Use assertEndsWith so that we don't compare the header, which varies
2613
# by bzrlib.__version__.
2614
self.assertEndsWith(
2615
out_stream.getvalue(),
2618
# tuple: 'UnknownMethod', 'method name'
2619
's\x00\x00\x00\x20l13:UnknownMethod11:method namee'
2624
class TestResponseEncoderBufferingProtocolThree(tests.TestCase):
2625
"""Tests for buffering of responses.
2627
We want to avoid doing many small writes when one would do, to avoid
2628
unnecessary network overhead.
2633
self.responder = protocol.ProtocolThreeResponder(self.writes.append)
2635
def assertWriteCount(self, expected_count):
2637
expected_count, len(self.writes),
2638
"Too many writes: %r" % (self.writes,))
2640
def test_send_error_writes_just_once(self):
2641
"""An error response is written to the medium all at once."""
2642
self.responder.send_error(Exception('An exception string.'))
2643
self.assertWriteCount(1)
2645
def test_send_response_writes_just_once(self):
2646
"""A normal response with no body is written to the medium all at once.
2648
response = _mod_request.SuccessfulSmartServerResponse(('arg', 'arg'))
2649
self.responder.send_response(response)
2650
self.assertWriteCount(1)
2652
def test_send_response_with_body_writes_just_once(self):
2653
"""A normal response with a monolithic body is written to the medium
2656
response = _mod_request.SuccessfulSmartServerResponse(
2657
('arg', 'arg'), body='body bytes')
2658
self.responder.send_response(response)
2659
self.assertWriteCount(1)
2661
def test_send_response_with_body_stream_writes_once_per_chunk(self):
2662
"""A normal response with a stream body is written to the medium
2663
writes to the medium once per chunk.
2665
# Construct a response with stream with 2 chunks in it.
2666
response = _mod_request.SuccessfulSmartServerResponse(
2667
('arg', 'arg'), body_stream=['chunk1', 'chunk2'])
2668
self.responder.send_response(response)
2669
# We will write 3 times: exactly once for each chunk, plus a final
2670
# write to end the response.
2671
self.assertWriteCount(3)
2118
2674
class TestSmartClientUnicode(tests.TestCase):
2119
2675
"""_SmartClient tests for unicode arguments.
2152
2709
self.assertCallDoesNotBreakMedium('method', ('args',), u'body')
2712
class MockMedium(object):
2713
"""A mock medium that can be used to test _SmartClient.
2715
It can be given a series of requests to expect (and responses it should
2716
return for them). It can also be told when the client is expected to
2717
disconnect a medium. Expectations must be satisfied in the order they are
2718
given, or else an AssertionError will be raised.
2720
Typical use looks like::
2722
medium = MockMedium()
2723
medium.expect_request(...)
2724
medium.expect_request(...)
2725
medium.expect_request(...)
2729
self.base = 'dummy base'
2730
self._mock_request = _MockMediumRequest(self)
2731
self._expected_events = []
2732
self._protocol_version = None
2734
def expect_request(self, request_bytes, response_bytes,
2735
allow_partial_read=False):
2736
"""Expect 'request_bytes' to be sent, and reply with 'response_bytes'.
2738
No assumption is made about how many times accept_bytes should be
2739
called to send the request. Similarly, no assumption is made about how
2740
many times read_bytes/read_line are called by protocol code to read a
2743
request.accept_bytes('ab')
2744
request.accept_bytes('cd')
2745
request.finished_writing()
2749
request.accept_bytes('abcd')
2750
request.finished_writing()
2752
Will both satisfy ``medium.expect_request('abcd', ...)``. Thus tests
2753
using this should not break due to irrelevant changes in protocol
2756
:param allow_partial_read: if True, no assertion is raised if a
2757
response is not fully read. Setting this is useful when the client
2758
is expected to disconnect without needing to read the complete
2759
response. Default is False.
2761
self._expected_events.append(('send request', request_bytes))
2762
if allow_partial_read:
2763
self._expected_events.append(
2764
('read response (partial)', response_bytes))
2766
self._expected_events.append(('read response', response_bytes))
2768
def expect_disconnect(self):
2769
"""Expect the client to call ``medium.disconnect()``."""
2770
self._expected_events.append('disconnect')
2772
def _assertEvent(self, observed_event):
2773
"""Raise AssertionError unless observed_event matches the next expected
2776
:seealso: expect_request
2777
:seealso: expect_disconnect
2780
expected_event = self._expected_events.pop(0)
2782
raise AssertionError(
2783
'Mock medium observed event %r, but no more events expected'
2784
% (observed_event,))
2785
if expected_event[0] == 'read response (partial)':
2786
if observed_event[0] != 'read response':
2787
raise AssertionError(
2788
'Mock medium observed event %r, but expected event %r'
2789
% (observed_event, expected_event))
2790
elif observed_event != expected_event:
2791
raise AssertionError(
2792
'Mock medium observed event %r, but expected event %r'
2793
% (observed_event, expected_event))
2794
if self._expected_events:
2795
next_event = self._expected_events[0]
2796
if next_event[0].startswith('read response'):
2797
self._mock_request._response = next_event[1]
2799
def get_request(self):
2800
return self._mock_request
2802
def disconnect(self):
2803
if self._mock_request._read_bytes:
2804
self._assertEvent(('read response', self._mock_request._read_bytes))
2805
self._mock_request._read_bytes = ''
2806
self._assertEvent('disconnect')
2809
class _MockMediumRequest(object):
2810
"""A mock ClientMediumRequest used by MockMedium."""
2812
def __init__(self, mock_medium):
2813
self._medium = mock_medium
2814
self._written_bytes = ''
2815
self._read_bytes = ''
2816
self._response = None
2818
def accept_bytes(self, bytes):
2819
self._written_bytes += bytes
2821
def finished_writing(self):
2822
self._medium._assertEvent(('send request', self._written_bytes))
2823
self._written_bytes = ''
2825
def finished_reading(self):
2826
self._medium._assertEvent(('read response', self._read_bytes))
2827
self._read_bytes = ''
2829
def read_bytes(self, size):
2830
resp = self._response
2831
bytes, resp = resp[:size], resp[size:]
2832
self._response = resp
2833
self._read_bytes += bytes
2836
def read_line(self):
2837
resp = self._response
2839
line, resp = resp.split('\n', 1)
2842
line, resp = resp, ''
2843
self._response = resp
2844
self._read_bytes += line
2848
class Test_SmartClientVersionDetection(tests.TestCase):
2849
"""Tests for _SmartClient's automatic protocol version detection.
2851
On the first remote call, _SmartClient will keep retrying the request with
2852
different protocol versions until it finds one that works.
2855
def test_version_three_server(self):
2856
"""With a protocol 3 server, only one request is needed."""
2857
medium = MockMedium()
2858
smart_client = client._SmartClient(medium, headers={})
2859
message_start = protocol.MESSAGE_VERSION_THREE + '\x00\x00\x00\x02de'
2860
medium.expect_request(
2862
's\x00\x00\x00\x1el11:method-name5:arg 15:arg 2ee',
2863
message_start + 's\0\0\0\x13l14:response valueee')
2864
result = smart_client.call('method-name', 'arg 1', 'arg 2')
2865
# The call succeeded without raising any exceptions from the mock
2866
# medium, and the smart_client returns the response from the server.
2867
self.assertEqual(('response value',), result)
2868
self.assertEqual([], medium._expected_events)
2870
def test_version_two_server(self):
2871
"""If the server only speaks protocol 2, the client will first try
2872
version 3, then fallback to protocol 2.
2874
Further, _SmartClient caches the detection, so future requests will all
2875
use protocol 2 immediately.
2877
medium = MockMedium()
2878
smart_client = client._SmartClient(medium, headers={})
2879
# First the client should send a v3 request, but the server will reply
2881
medium.expect_request(
2882
'bzr message 3 (bzr 1.6)\n\x00\x00\x00\x02de' +
2883
's\x00\x00\x00\x1el11:method-name5:arg 15:arg 2ee',
2884
'bzr response 2\nfailed\n\n')
2885
# So then the client should disconnect to reset the connection, because
2886
# the client needs to assume the server cannot read any further
2887
# requests off the original connection.
2888
medium.expect_disconnect()
2889
# The client should then retry the original request in v2
2890
medium.expect_request(
2891
'bzr request 2\nmethod-name\x01arg 1\x01arg 2\n',
2892
'bzr response 2\nsuccess\nresponse value\n')
2893
result = smart_client.call('method-name', 'arg 1', 'arg 2')
2894
# The smart_client object will return the result of the successful
2896
self.assertEqual(('response value',), result)
2898
# Now try another request, and this time the client will just use
2899
# protocol 2. (i.e. the autodetection won't be repeated)
2900
medium.expect_request(
2901
'bzr request 2\nanother-method\n',
2902
'bzr response 2\nsuccess\nanother response\n')
2903
result = smart_client.call('another-method')
2904
self.assertEqual(('another response',), result)
2905
self.assertEqual([], medium._expected_events)
2907
def test_unknown_version(self):
2908
"""If the server does not use any known (or at least supported)
2909
protocol version, a SmartProtocolError is raised.
2911
medium = MockMedium()
2912
smart_client = client._SmartClient(medium, headers={})
2913
unknown_protocol_bytes = 'Unknown protocol!'
2914
# The client will try v3 and v2 before eventually giving up.
2915
medium.expect_request(
2916
'bzr message 3 (bzr 1.6)\n\x00\x00\x00\x02de' +
2917
's\x00\x00\x00\x1el11:method-name5:arg 15:arg 2ee',
2918
unknown_protocol_bytes)
2919
medium.expect_disconnect()
2920
medium.expect_request(
2921
'bzr request 2\nmethod-name\x01arg 1\x01arg 2\n',
2922
unknown_protocol_bytes)
2923
medium.expect_disconnect()
2925
errors.SmartProtocolError,
2926
smart_client.call, 'method-name', 'arg 1', 'arg 2')
2927
self.assertEqual([], medium._expected_events)
2929
def test_first_response_is_error(self):
2930
"""If the server replies with an error, then the version detection
2933
This test is very similar to test_version_two_server, but catches a bug
2934
we had in the case where the first reply was an error response.
2936
medium = MockMedium()
2937
smart_client = client._SmartClient(medium, headers={})
2938
message_start = protocol.MESSAGE_VERSION_THREE + '\x00\x00\x00\x02de'
2939
# Issue a request that gets an error reply in a non-default protocol
2941
medium.expect_request(
2943
's\x00\x00\x00\x10l11:method-nameee',
2944
'bzr response 2\nfailed\n\n')
2945
medium.expect_disconnect()
2946
medium.expect_request(
2947
'bzr request 2\nmethod-name\n',
2948
'bzr response 2\nfailed\nFooBarError\n')
2949
err = self.assertRaises(
2950
errors.ErrorFromSmartServer,
2951
smart_client.call, 'method-name')
2952
self.assertEqual(('FooBarError',), err.error_tuple)
2953
# Now the medium should have remembered the protocol version, so
2954
# subsequent requests will use the remembered version immediately.
2955
medium.expect_request(
2956
'bzr request 2\nmethod-name\n',
2957
'bzr response 2\nsuccess\nresponse value\n')
2958
result = smart_client.call('method-name')
2959
self.assertEqual(('response value',), result)
2960
self.assertEqual([], medium._expected_events)
2963
class Test_SmartClient(tests.TestCase):
2965
def test_call_default_headers(self):
2966
"""ProtocolThreeRequester.call by default sends a 'Software
2969
smart_client = client._SmartClient('dummy medium')
2971
bzrlib.__version__, smart_client._headers['Software version'])
2972
# XXX: need a test that smart_client._headers is passed to the request
2155
2976
class LengthPrefixedBodyDecoder(tests.TestCase):
2157
2978
# XXX: TODO: make accept_reading_trailer invoke translate_response or