1370
1370
transport._translate_error, ("ReadOnlyError", ))
1373
class InstrumentedServerProtocol(medium.SmartServerStreamMedium):
1374
"""A smart server which is backed by memory and saves its write requests."""
1376
def __init__(self, write_output_list):
1377
medium.SmartServerStreamMedium.__init__(self, memory.MemoryTransport())
1378
self._write_output_list = write_output_list
1381
1373
class TestSmartProtocol(tests.TestCase):
1382
1374
"""Base class for smart protocol tests.
1396
1388
client_protocol_class = None
1397
1389
server_protocol_class = None
1400
super(TestSmartProtocol, self).setUp()
1401
# XXX: self.server_to_client doesn't seem to be used. If so,
1402
# InstrumentedServerProtocol is redundant too.
1403
self.server_to_client = []
1404
self.to_server = StringIO()
1405
self.to_client = StringIO()
1406
self.client_medium = medium.SmartSimplePipesClientMedium(self.to_client,
1408
self.client_protocol = self.client_protocol_class(self.client_medium)
1409
self.smart_server = InstrumentedServerProtocol(self.server_to_client)
1410
self.smart_server_request = _mod_request.SmartServerRequestHandler(
1411
None, _mod_request.request_handlers, root_client_path='/')
1391
def make_client_protocol(self):
1392
client_medium = medium.SmartSimplePipesClientMedium(
1393
StringIO(), StringIO())
1394
return self.client_protocol_class(client_medium.get_request())
1396
def make_server_protocol(self):
1397
out_stream = StringIO()
1398
smart_protocol = self.server_protocol_class(None, out_stream.write)
1399
return smart_protocol, out_stream
1413
1401
def assertOffsetSerialisation(self, expected_offsets, expected_serialised,
1430
1418
self.assertEqual(expected_serialised, serialised)
1432
1420
def build_protocol_waiting_for_body(self):
1433
out_stream = StringIO()
1434
smart_protocol = self.server_protocol_class(None, out_stream.write)
1421
smart_protocol, out_stream = self.make_server_protocol()
1435
1422
smart_protocol.has_dispatched = True
1436
smart_protocol.request = self.smart_server_request
1423
smart_protocol.request = _mod_request.SmartServerRequestHandler(
1424
None, _mod_request.request_handlers, '/')
1437
1425
class FakeCommand(object):
1438
1426
def do_body(cmd, body_bytes):
1439
1427
self.end_received = True
1455
1443
# check the encoding of the server for all input_tuples matches
1456
1444
# expected bytes
1457
1445
for input_tuple in input_tuples:
1458
server_output = StringIO()
1459
server_protocol = self.server_protocol_class(
1460
None, server_output.write)
1446
server_protocol, server_output = self.make_server_protocol()
1461
1447
server_protocol._send_response(
1462
1448
_mod_request.SuccessfulSmartServerResponse(input_tuple))
1463
1449
self.assertEqual(expected_bytes, server_output.getvalue())
1476
1462
def test_errors_are_logged(self):
1477
1463
"""If an error occurs during testing, it is logged to the test log."""
1478
out_stream = StringIO()
1479
smart_protocol = self.server_protocol_class(None, out_stream.write)
1464
smart_protocol, out_stream = self.make_server_protocol()
1480
1465
# This triggers a "bad request" error.
1481
1466
smart_protocol.accept_bytes('abc\n')
1482
1467
test_log = self._get_log(keep_log_file=True)
1484
1469
self.assertContainsRe(test_log, 'SmartProtocolError')
1486
1471
def test_connection_closed_reporting(self):
1489
client_medium = medium.SmartSimplePipesClientMedium(input, output)
1490
request = client_medium.get_request()
1491
smart_protocol = self.client_protocol_class(request)
1472
smart_protocol = self.make_client_protocol()
1492
1473
smart_protocol.call('hello')
1493
ex = self.assertRaises(errors.ConnectionReset,
1474
ex = self.assertRaises(errors.ConnectionReset,
1494
1475
smart_protocol.read_response_tuple)
1495
1476
self.assertEqual("Connection closed: "
1496
1477
"please check connectivity and permissions "
1497
1478
"(and try -Dhpss if further diagnosis is required)", str(ex))
1480
def test_server_offset_serialisation(self):
1481
"""The Smart protocol serialises offsets as a comma and \n string.
1483
We check a number of boundary cases are as expected: empty, one offset,
1484
one with the order of reads not increasing (an out of order read), and
1485
one that should coalesce.
1487
client_protocol = self.make_client_protocol()
1488
self.assertOffsetSerialisation([], '', client_protocol)
1489
self.assertOffsetSerialisation([(1,2)], '1,2', client_protocol)
1490
self.assertOffsetSerialisation([(10,40), (0,5)], '10,40\n0,5',
1492
self.assertOffsetSerialisation([(1,2), (3,4), (100, 200)],
1493
'1,2\n3,4\n100,200', client_protocol)
1500
1496
class TestSmartProtocolOne(TestSmartProtocol, CommonSmartProtocolTestMixin):
1501
1497
"""Tests for the smart protocol version one."""
1517
1513
request = client_medium.get_request()
1518
1514
client_protocol = protocol.SmartClientRequestProtocolOne(request)
1520
def test_server_offset_serialisation(self):
1521
"""The Smart protocol serialises offsets as a comma and \n string.
1523
We check a number of boundary cases are as expected: empty, one offset,
1524
one with the order of reads not increasing (an out of order read), and
1525
one that should coalesce.
1527
self.assertOffsetSerialisation([], '', self.client_protocol)
1528
self.assertOffsetSerialisation([(1,2)], '1,2', self.client_protocol)
1529
self.assertOffsetSerialisation([(10,40), (0,5)], '10,40\n0,5',
1530
self.client_protocol)
1531
self.assertOffsetSerialisation([(1,2), (3,4), (100, 200)],
1532
'1,2\n3,4\n100,200', self.client_protocol)
1534
1516
def test_accept_bytes_of_bad_request_to_protocol(self):
1535
1517
out_stream = StringIO()
1536
1518
smart_protocol = protocol.SmartServerRequestProtocolOne(
1776
1758
request = client_medium.get_request()
1777
1759
client_protocol = protocol.SmartClientRequestProtocolTwo(request)
1779
def test_server_offset_serialisation(self):
1780
"""The Smart protocol serialises offsets as a comma and \n string.
1782
We check a number of boundary cases are as expected: empty, one offset,
1783
one with the order of reads not increasing (an out of order read), and
1784
one that should coalesce.
1786
self.assertOffsetSerialisation([], '', self.client_protocol)
1787
self.assertOffsetSerialisation([(1,2)], '1,2', self.client_protocol)
1788
self.assertOffsetSerialisation([(10,40), (0,5)], '10,40\n0,5',
1789
self.client_protocol)
1790
self.assertOffsetSerialisation([(1,2), (3,4), (100, 200)],
1791
'1,2\n3,4\n100,200', self.client_protocol)
1793
1761
def assertBodyStreamSerialisation(self, expected_serialisation,
1795
1763
"""Assert that body_stream is serialised as expected_serialisation."""