~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_smart_transport.py

  • Committer: Andrew Bennetts
  • Date: 2007-08-30 11:32:12 UTC
  • mto: (2535.4.1 streaming-smart-fetch)
  • mto: This revision was merged to the branch mainline in revision 2985.
  • Revision ID: andrew.bennetts@canonical.com-20070830113212-j6zhw555ma5x21yi
Add protocol (version two) support for streaming bodies (using chunking) in responses.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1614
1614
        self.assertOffsetSerialisation([(1,2), (3,4), (100, 200)],
1615
1615
            '1,2\n3,4\n100,200', self.client_protocol)
1616
1616
 
 
1617
    def assertBodyStreamSerialisation(self, expected_serialisation,
 
1618
                                      body_stream):
 
1619
        """Assert that body_stream is serialised as expected_serialisation."""
 
1620
        out_stream = StringIO()
 
1621
        smart_protocol = self.server_protocol_class(None, out_stream.write)
 
1622
        response = request.SuccessfulSmartServerResponse(
 
1623
            ('args',), body_stream=body_stream)
 
1624
        smart_protocol._send_response(response)
 
1625
        expected_prefix = protocol.RESPONSE_VERSION_TWO + 'success\n'
 
1626
        expected_args = 'args\n'
 
1627
        self.assertStartsWith(
 
1628
            out_stream.getvalue(), expected_prefix + expected_args)
 
1629
        body = out_stream.getvalue()[len(expected_prefix + expected_args):]
 
1630
        self.assertEqual(expected_serialisation, body)
 
1631
 
 
1632
    def test_body_stream_serialisation_empty(self):
 
1633
        """A body_stream with no bytes can be serialised."""
 
1634
        self.assertBodyStreamSerialisation('0\n', [])
 
1635
 
 
1636
    def test_body_stream_serialisation(self):
 
1637
        self.assertBodyStreamSerialisation(
 
1638
            '9\nchunk one' + '9\nchunk two' + 'b\nchunk three' + '0\n',
 
1639
            ['chunk one', 'chunk two', 'chunk three'])
 
1640
 
 
1641
    def test_body_stream_with_empty_element_serialisation(self):
 
1642
        """A body stream that includes '' does not prematurely end the stream.
 
1643
 
 
1644
        If the body stream yields an empty string, the protocol should not send
 
1645
        an empty chunk, because that is the signal for end-of-stream.
 
1646
        """
 
1647
        self.assertBodyStreamSerialisation('5\nchunk' + '0\n', ['', 'chunk'])
 
1648
 
1617
1649
    def test_accept_bytes_of_bad_request_to_protocol(self):
1618
1650
        out_stream = StringIO()
1619
1651
        smart_protocol = protocol.SmartServerRequestProtocolTwo(
1700
1732
            request.SuccessfulSmartServerResponse(('x',)))
1701
1733
        self.assertEqual(0, smart_protocol.next_read_size())
1702
1734
 
 
1735
    def test__send_response_with_body_stream_sets_finished_reading(self):
 
1736
        smart_protocol = protocol.SmartServerRequestProtocolTwo(
 
1737
            None, lambda x: None)
 
1738
        self.assertEqual(1, smart_protocol.next_read_size())
 
1739
        smart_protocol._send_response(
 
1740
            request.SuccessfulSmartServerResponse(('x',), body_stream=[]))
 
1741
        self.assertEqual(0, smart_protocol.next_read_size())
 
1742
 
1703
1743
    def test__send_response_errors_with_base_response(self):
1704
1744
        """Ensure that only the Successful/Failed subclasses are used."""
1705
1745
        smart_protocol = protocol.SmartServerRequestProtocolTwo(
1833
1873
    def test_client_cancel_read_body_does_not_eat_body_bytes(self):
1834
1874
        # cancelling the expected body needs to finish the request, but not
1835
1875
        # read any more bytes.
1836
 
        expected_bytes = "1234567"
1837
1876
        server_bytes = (protocol.RESPONSE_VERSION_TWO +
1838
1877
                        "success\nok\n7\n1234567done\n")
1839
1878
        input = StringIO(server_bytes)
1849
1888
        self.assertRaises(
1850
1889
            errors.ReadingCompleted, smart_protocol.read_body_bytes)
1851
1890
 
 
1891
    def test_streamed_body_bytes(self):
 
1892
        two_body_chunks = "4\n1234" + "3\n567"
 
1893
        body_terminator = "0\n"
 
1894
        server_bytes = (protocol.RESPONSE_VERSION_TWO +
 
1895
                        "success\nok\n" + two_body_chunks + body_terminator)
 
1896
        input = StringIO(server_bytes)
 
1897
        output = StringIO()
 
1898
        client_medium = medium.SmartSimplePipesClientMedium(input, output)
 
1899
        request = client_medium.get_request()
 
1900
        smart_protocol = protocol.SmartClientRequestProtocolTwo(request)
 
1901
        smart_protocol.call('foo')
 
1902
        smart_protocol.read_response_tuple(True)
 
1903
        stream = smart_protocol.read_streamed_body()
 
1904
        self.assertEqual(['1234', '567'], list(stream))
 
1905
 
1852
1906
 
1853
1907
class TestSmartClientUnicode(tests.TestCase):
1854
1908
    """_SmartClient tests for unicode arguments.
2015
2069
        self.assertFalse(decoder.finished_reading)
2016
2070
        self.assertEqual('', decoder.read_pending_data())
2017
2071
 
2018
 
    def test_accept_two_chunks(self):
 
2072
    def test_two_chunks(self):
2019
2073
        """Content from multiple chunks is concatenated."""
2020
2074
        decoder = protocol.ChunkedBodyDecoder()
2021
2075
        chunk_one = '3\naaa'
2068
2122
        self.assertEqual(chunk_content, decoder.read_pending_data())
2069
2123
        self.assertEqual('', decoder.unused_data)
2070
2124
 
 
2125
    def test_read_pending_data_resets(self):
 
2126
        """read_pending_data does not return the same bytes twice."""
 
2127
        decoder = protocol.ChunkedBodyDecoder()
 
2128
        chunk_one = '3\naaa'
 
2129
        chunk_two = '3\nbbb'
 
2130
        finish = '0\n'
 
2131
        decoder.accept_bytes(chunk_one)
 
2132
        self.assertEqual('aaa', decoder.read_pending_data())
 
2133
        decoder.accept_bytes(chunk_two)
 
2134
        self.assertEqual('bbb', decoder.read_pending_data())
 
2135
        self.assertEqual('', decoder.read_pending_data())
 
2136
 
2071
2137
 
2072
2138
class TestSuccessfulSmartServerResponse(tests.TestCase):
2073
2139
 
2074
 
    def test_construct(self):
 
2140
    def test_construct_no_body(self):
2075
2141
        response = request.SuccessfulSmartServerResponse(('foo', 'bar'))
2076
2142
        self.assertEqual(('foo', 'bar'), response.args)
2077
2143
        self.assertEqual(None, response.body)
2078
 
        response = request.SuccessfulSmartServerResponse(('foo', 'bar'), 'bytes')
 
2144
 
 
2145
    def test_construct_with_body(self):
 
2146
        response = request.SuccessfulSmartServerResponse(
 
2147
            ('foo', 'bar'), 'bytes')
2079
2148
        self.assertEqual(('foo', 'bar'), response.args)
2080
2149
        self.assertEqual('bytes', response.body)
2081
2150
 
 
2151
    def test_construct_with_body_stream(self):
 
2152
        bytes_iterable = ['abc']
 
2153
        response = request.SuccessfulSmartServerResponse(
 
2154
            ('foo', 'bar'), body_stream=bytes_iterable)
 
2155
        self.assertEqual(('foo', 'bar'), response.args)
 
2156
        self.assertEqual(bytes_iterable, response.body_stream)
 
2157
 
 
2158
    def test_construct_rejects_body_and_body_stream(self):
 
2159
        """'body' and 'body_stream' are mutually exclusive."""
 
2160
        self.assertRaises(
 
2161
            errors.BzrError,
 
2162
            request.SuccessfulSmartServerResponse, (), 'body', ['stream'])
 
2163
 
2082
2164
    def test_is_successful(self):
2083
2165
        """is_successful should return True for SuccessfulSmartServerResponse."""
2084
2166
        response = request.SuccessfulSmartServerResponse(('error',))