~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: 2008-06-02 01:12:17 UTC
  • mto: This revision was merged to the branch mainline in revision 3494.
  • Revision ID: andrew.bennetts@canonical.com-20080602011217-91w8f210rc3adv6g
Fix infinite busy-loop caused by connection loss during read of response body in HPSS v1 and v2.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1803
1803
        self.assertRaises(
1804
1804
            errors.ReadingCompleted, smart_protocol.read_body_bytes)
1805
1805
 
 
1806
    def test_client_read_body_bytes_interrupted_connection(self):
 
1807
        server_bytes = "ok\n999\nincomplete body"
 
1808
        input = StringIO(server_bytes)
 
1809
        output = StringIO()
 
1810
        client_medium = medium.SmartSimplePipesClientMedium(
 
1811
            input, output, 'base')
 
1812
        request = client_medium.get_request()
 
1813
        smart_protocol = self.client_protocol_class(request)
 
1814
        smart_protocol.call('foo')
 
1815
        smart_protocol.read_response_tuple(True)
 
1816
        self.assertRaises(
 
1817
            errors.ConnectionReset, smart_protocol.read_body_bytes)
 
1818
 
1806
1819
 
1807
1820
class TestVersionOneFeaturesInProtocolTwo(
1808
1821
    TestSmartProtocol, CommonSmartProtocolTestMixin):
2029
2042
        self.assertRaises(
2030
2043
            errors.ReadingCompleted, smart_protocol.read_body_bytes)
2031
2044
 
 
2045
    def test_client_read_body_bytes_interrupted_connection(self):
 
2046
        server_bytes = (self.response_marker +
 
2047
                        "success\nok\n999\nincomplete body")
 
2048
        input = StringIO(server_bytes)
 
2049
        output = StringIO()
 
2050
        client_medium = medium.SmartSimplePipesClientMedium(
 
2051
            input, output, 'base')
 
2052
        request = client_medium.get_request()
 
2053
        smart_protocol = self.client_protocol_class(request)
 
2054
        smart_protocol.call('foo')
 
2055
        smart_protocol.read_response_tuple(True)
 
2056
        self.assertRaises(
 
2057
            errors.ConnectionReset, smart_protocol.read_body_bytes)
 
2058
 
2032
2059
 
2033
2060
class TestSmartProtocolTwoSpecificsMixin(object):
2034
2061
 
2154
2181
        stream = smart_protocol.read_streamed_body()
2155
2182
        self.assertEqual(expected_chunks, list(stream))
2156
2183
 
 
2184
    def test_streamed_body_bytes_interrupted_connection(self):
 
2185
        body_header = 'chunked\n'
 
2186
        incomplete_body_chunk = "9999\nincomplete chunk"
 
2187
        server_bytes = (protocol.RESPONSE_VERSION_TWO +
 
2188
                        "success\nok\n" + body_header + incomplete_body_chunk)
 
2189
        input = StringIO(server_bytes)
 
2190
        output = StringIO()
 
2191
        client_medium = medium.SmartSimplePipesClientMedium(
 
2192
            input, output, 'base')
 
2193
        request = client_medium.get_request()
 
2194
        smart_protocol = protocol.SmartClientRequestProtocolTwo(request)
 
2195
        smart_protocol.call('foo')
 
2196
        smart_protocol.read_response_tuple(True)
 
2197
        stream = smart_protocol.read_streamed_body()
 
2198
        self.assertRaises(errors.ConnectionReset, stream.next)
 
2199
 
2157
2200
    def test_client_read_response_tuple_sets_response_status(self):
2158
2201
        server_bytes = protocol.RESPONSE_VERSION_TWO + "success\nok\n"
2159
2202
        input = StringIO(server_bytes)
2338
2381
 
2339
2382
class TestConventionalResponseHandler(tests.TestCase):
2340
2383
 
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
2347
 
            'oE' # error flag
2348
 
            's\0\0\0\x0el5:error3:abce' # bencoded error
2349
 
            'e' # message end
2350
 
            )
 
2384
    def make_response_handler(self, response_bytes):
2351
2385
        from bzrlib.smart.message import ConventionalResponseHandler
2352
2386
        response_handler = ConventionalResponseHandler()
2353
2387
        protocol_decoder = protocol.ProtocolThreeDecoder(response_handler)
2355
2389
        protocol_decoder.state_accept = protocol_decoder._state_accept_expecting_message_part
2356
2390
        output = StringIO()
2357
2391
        client_medium = medium.SmartSimplePipesClientMedium(
2358
 
            StringIO(interrupted_body_stream), output, 'base')
 
2392
            StringIO(response_bytes), output, 'base')
2359
2393
        medium_request = client_medium.get_request()
2360
2394
        medium_request.finished_writing()
2361
2395
        response_handler.setProtoAndMediumRequest(
2362
2396
            protocol_decoder, medium_request)
 
2397
        return response_handler
 
2398
 
 
2399
    def test_body_stream_interrupted_by_error(self):
 
2400
        interrupted_body_stream = (
 
2401
            'oS' # successful response
 
2402
            's\0\0\0\x02le' # empty args
 
2403
            'b\0\0\0\x09chunk one' # first chunk
 
2404
            'b\0\0\0\x09chunk two' # second chunk
 
2405
            'oE' # error flag
 
2406
            's\0\0\0\x0el5:error3:abce' # bencoded error
 
2407
            'e' # message end
 
2408
            )
 
2409
        response_handler = self.make_response_handler(interrupted_body_stream)
2363
2410
        stream = response_handler.read_streamed_body()
2364
2411
        self.assertEqual('chunk one', stream.next())
2365
2412
        self.assertEqual('chunk two', stream.next())
2366
2413
        exc = self.assertRaises(errors.ErrorFromSmartServer, stream.next)
2367
2414
        self.assertEqual(('error', 'abc'), exc.error_tuple)
2368
2415
 
 
2416
    def test_body_stream_interrupted_by_connection_lost(self):
 
2417
        interrupted_body_stream = (
 
2418
            'oS' # successful response
 
2419
            's\0\0\0\x02le' # empty args
 
2420
            'b\0\0\xff\xffincomplete chunk')
 
2421
        response_handler = self.make_response_handler(interrupted_body_stream)
 
2422
        stream = response_handler.read_streamed_body()
 
2423
        self.assertRaises(errors.ConnectionReset, stream.next)
 
2424
 
 
2425
    def test_read_body_bytes_interrupted_by_connection_lost(self):
 
2426
        interrupted_body_stream = (
 
2427
            'oS' # successful response
 
2428
            's\0\0\0\x02le' # empty args
 
2429
            'b\0\0\xff\xffincomplete chunk')
 
2430
        response_handler = self.make_response_handler(interrupted_body_stream)
 
2431
        self.assertRaises(
 
2432
            errors.ConnectionReset, response_handler.read_body_bytes)
 
2433
 
2369
2434
 
2370
2435
class TestMessageHandlerErrors(tests.TestCase):
2371
2436
    """Tests for v3 that unrecognised (but well-formed) requests/responses are