~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_smart_transport.py

Merge from bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
276
276
        self.assertEqual([('_call', ('get', '/foo'))], client._calls)
277
277
 
278
278
 
 
279
class InstrumentedClient(smart.SmartStreamClient):
 
280
    """A smart client whose writes are stored to a supplied list."""
 
281
 
 
282
    def __init__(self, write_output_list):
 
283
        smart.SmartStreamClient.__init__(self, None)
 
284
        self._write_output_list = write_output_list
 
285
 
 
286
    def _ensure_connection(self):
 
287
        """We are never strictly connected."""
 
288
 
 
289
    def _write_and_flush(self, bytes):
 
290
        self._write_output_list.append(bytes)
 
291
 
 
292
 
 
293
class InstrumentedServerProtocol(smart.SmartStreamServer):
 
294
    """A smart server which is backed by memory and saves its write requests."""
 
295
 
 
296
    def __init__(self, write_output_list):
 
297
        smart.SmartStreamServer.__init__(self, None, None,
 
298
            memory.MemoryTransport())
 
299
        self._write_output_list = write_output_list
 
300
 
 
301
    def _write_and_flush(self, bytes):
 
302
        self._write_output_list.append(bytes)
 
303
 
 
304
 
 
305
class TestSmartProtocol(tests.TestCase):
 
306
    """Tests for the smart protocol.
 
307
 
 
308
    Each test case gets a smart_server and smart_client created during setUp().
 
309
 
 
310
    It is planned that the client can be called with self.call_client() giving
 
311
    it an expected server response, which will be fed into it when it tries to
 
312
    read. Likewise, self.call_server will call a servers method with a canned
 
313
    serialised client request. Output done by the client or server for these
 
314
    calls will be captured to self.to_server and self.to_client. Each element
 
315
    in the list is a write call from the client or server respectively.
 
316
    """
 
317
 
 
318
    def setUp(self):
 
319
        super(TestSmartProtocol, self).setUp()
 
320
        self.to_server = []
 
321
        self.to_client = []
 
322
        self.smart_client = InstrumentedClient(self.to_server)
 
323
        self.smart_server = InstrumentedServerProtocol(self.to_client)
 
324
 
 
325
    def assertOffsetSerialisation(self, expected_offsets, expected_serialised,
 
326
        client, server_protocol):
 
327
        """Check that smart (de)serialises offsets as expected.
 
328
        
 
329
        We check both serialisation and deserialisation at the same time
 
330
        to ensure that the round tripping cannot skew: both directions should
 
331
        be as expected.
 
332
        
 
333
        :param expected_offsets: a readv offset list.
 
334
        :param expected_seralised: an expected serial form of the offsets.
 
335
        :param server: a SmartServer instance.
 
336
        """
 
337
        offsets = server_protocol.smart_server._deserialise_offsets(
 
338
            expected_serialised)
 
339
        self.assertEqual(expected_offsets, offsets)
 
340
        serialised = client._serialise_offsets(offsets)
 
341
        self.assertEqual(expected_serialised, serialised)
 
342
 
 
343
    def test_server_offset_serialisation(self):
 
344
        """The Smart protocol serialises offsets as a comma and \n string.
 
345
 
 
346
        We check a number of boundary cases are as expected: empty, one offset,
 
347
        one with the order of reads not increasing (an out of order read), and
 
348
        one that should coalesce.
 
349
        """
 
350
        self.assertOffsetSerialisation([], '',
 
351
            self.smart_client, self.smart_server)
 
352
        self.assertOffsetSerialisation([(1,2)], '1,2',
 
353
            self.smart_client, self.smart_server)
 
354
        self.assertOffsetSerialisation([(10,40), (0,5)], '10,40\n0,5',
 
355
            self.smart_client, self.smart_server)
 
356
        self.assertOffsetSerialisation([(1,2), (3,4), (100, 200)],
 
357
            '1,2\n3,4\n100,200', self.smart_client, self.smart_server)
 
358
 
 
359
 
279
360
# TODO: Client feature that does get_bundle and then installs that into a
280
361
# branch; this can be used in place of the regular pull/fetch operation when
281
362
# coming from a smart server.