85
86
sock.bind(('127.0.0.1', 0))
87
88
port = sock.getsockname()[1]
88
medium = smart.SmartTCPClientMedium('127.0.0.1', port)
89
client_medium = medium.SmartTCPClientMedium('127.0.0.1', port)
90
return sock, client_medium
91
92
def receive_bytes_on_server(self, sock, bytes):
92
93
"""Accept a connection on sock and read 3 bytes.
108
109
# this just ensures that the constructor stays parameter-free which
109
110
# is important for reuse : some subclasses will dynamically connect,
110
111
# others are always on, etc.
111
medium = smart.SmartClientStreamMedium()
112
client_medium = medium.SmartClientStreamMedium()
113
114
def test_construct_smart_client_medium(self):
114
115
# the base client medium takes no parameters
115
medium = smart.SmartClientMedium()
116
client_medium = medium.SmartClientMedium()
117
118
def test_construct_smart_simple_pipes_client_medium(self):
118
119
# the SimplePipes client medium takes two pipes:
119
120
# readable pipe, writeable pipe.
120
121
# Constructing one should just save these and do nothing.
121
122
# We test this by passing in None.
122
medium = smart.SmartSimplePipesClientMedium(None, None)
123
client_medium = medium.SmartSimplePipesClientMedium(None, None)
124
125
def test_simple_pipes_client_request_type(self):
125
126
# SimplePipesClient should use SmartClientStreamMediumRequest's.
126
medium = smart.SmartSimplePipesClientMedium(None, None)
127
request = medium.get_request()
128
self.assertIsInstance(request, smart.SmartClientStreamMediumRequest)
127
client_medium = medium.SmartSimplePipesClientMedium(None, None)
128
request = client_medium.get_request()
129
self.assertIsInstance(request, medium.SmartClientStreamMediumRequest)
130
131
def test_simple_pipes_client_get_concurrent_requests(self):
131
132
# the simple_pipes client does not support pipelined requests:
135
136
# classes - as the sibling classes share this logic, they do not have
136
137
# explicit tests for this.
137
138
output = StringIO()
138
medium = smart.SmartSimplePipesClientMedium(None, output)
139
request = medium.get_request()
139
client_medium = medium.SmartSimplePipesClientMedium(None, output)
140
request = client_medium.get_request()
140
141
request.finished_writing()
141
142
request.finished_reading()
142
request2 = medium.get_request()
143
request2 = client_medium.get_request()
143
144
request2.finished_writing()
144
145
request2.finished_reading()
146
147
def test_simple_pipes_client__accept_bytes_writes_to_writable(self):
147
148
# accept_bytes writes to the writeable pipe.
148
149
output = StringIO()
149
medium = smart.SmartSimplePipesClientMedium(None, output)
150
medium._accept_bytes('abc')
150
client_medium = medium.SmartSimplePipesClientMedium(None, output)
151
client_medium._accept_bytes('abc')
151
152
self.assertEqual('abc', output.getvalue())
153
154
def test_simple_pipes_client_disconnect_does_nothing(self):
154
155
# calling disconnect does nothing.
155
156
input = StringIO()
156
157
output = StringIO()
157
medium = smart.SmartSimplePipesClientMedium(input, output)
158
client_medium = medium.SmartSimplePipesClientMedium(input, output)
158
159
# send some bytes to ensure disconnecting after activity still does not
160
medium._accept_bytes('abc')
161
client_medium._accept_bytes('abc')
162
client_medium.disconnect()
162
163
self.assertFalse(input.closed)
163
164
self.assertFalse(output.closed)
167
168
# accept_bytes writes to.
168
169
input = StringIO()
169
170
output = StringIO()
170
medium = smart.SmartSimplePipesClientMedium(input, output)
171
medium._accept_bytes('abc')
173
medium._accept_bytes('abc')
171
client_medium = medium.SmartSimplePipesClientMedium(input, output)
172
client_medium._accept_bytes('abc')
173
client_medium.disconnect()
174
client_medium._accept_bytes('abc')
174
175
self.assertFalse(input.closed)
175
176
self.assertFalse(output.closed)
176
177
self.assertEqual('abcabc', output.getvalue())
178
179
def test_simple_pipes_client_ignores_disconnect_when_not_connected(self):
179
180
# Doing a disconnect on a new (and thus unconnected) SimplePipes medium
181
medium = smart.SmartSimplePipesClientMedium(None, None)
182
client_medium = medium.SmartSimplePipesClientMedium(None, None)
183
client_medium.disconnect()
184
185
def test_simple_pipes_client_can_always_read(self):
185
186
# SmartSimplePipesClientMedium is never disconnected, so read_bytes
186
187
# always tries to read from the underlying pipe.
187
188
input = StringIO('abcdef')
188
medium = smart.SmartSimplePipesClientMedium(input, None)
189
self.assertEqual('abc', medium.read_bytes(3))
191
self.assertEqual('def', medium.read_bytes(3))
189
client_medium = medium.SmartSimplePipesClientMedium(input, None)
190
self.assertEqual('abc', client_medium.read_bytes(3))
191
client_medium.disconnect()
192
self.assertEqual('def', client_medium.read_bytes(3))
193
194
def test_simple_pipes_client_supports__flush(self):
194
195
# invoking _flush on a SimplePipesClient should flush the output
201
202
def logging_flush(): flush_calls.append('flush')
202
203
output.flush = logging_flush
203
medium = smart.SmartSimplePipesClientMedium(input, output)
204
client_medium = medium.SmartSimplePipesClientMedium(input, output)
204
205
# this call is here to ensure we only flush once, not on every
205
206
# _accept_bytes call.
206
medium._accept_bytes('abc')
207
client_medium._accept_bytes('abc')
208
client_medium._flush()
209
client_medium.disconnect()
209
210
self.assertEqual(['flush'], flush_calls)
211
212
def test_construct_smart_ssh_client_medium(self):
219
220
unopened_port = sock.getsockname()[1]
220
221
# having vendor be invalid means that if it tries to connect via the
221
222
# vendor it will blow up.
222
medium = smart.SmartSSHClientMedium('127.0.0.1', unopened_port,
223
client_medium = medium.SmartSSHClientMedium('127.0.0.1', unopened_port,
223
224
username=None, password=None, vendor="not a vendor")
229
230
output = StringIO()
230
231
vendor = StringIOSSHVendor(StringIO(), output)
231
medium = smart.SmartSSHClientMedium('a hostname', 'a port', 'a username',
232
'a password', vendor)
233
medium._accept_bytes('abc')
232
client_medium = medium.SmartSSHClientMedium(
233
'a hostname', 'a port', 'a username', 'a password', vendor)
234
client_medium._accept_bytes('abc')
234
235
self.assertEqual('abc', output.getvalue())
235
236
self.assertEqual([('connect_ssh', 'a username', 'a password',
236
237
'a hostname', 'a port',
247
248
osutils.set_or_unset_env('BZR_REMOTE_PATH', orig_bzr_remote_path)
248
249
self.addCleanup(cleanup_environ)
249
250
os.environ['BZR_REMOTE_PATH'] = 'fugly'
250
medium = smart.SmartSSHClientMedium('a hostname', 'a port', 'a username',
251
client_medium = medium.SmartSSHClientMedium('a hostname', 'a port', 'a username',
251
252
'a password', vendor)
252
medium._accept_bytes('abc')
253
client_medium._accept_bytes('abc')
253
254
self.assertEqual('abc', output.getvalue())
254
255
self.assertEqual([('connect_ssh', 'a username', 'a password',
255
256
'a hostname', 'a port',
262
263
input = StringIO()
263
264
output = StringIO()
264
265
vendor = StringIOSSHVendor(input, output)
265
medium = smart.SmartSSHClientMedium('a hostname', vendor=vendor)
266
medium._accept_bytes('abc')
266
client_medium = medium.SmartSSHClientMedium('a hostname', vendor=vendor)
267
client_medium._accept_bytes('abc')
268
client_medium.disconnect()
268
269
self.assertTrue(input.closed)
269
270
self.assertTrue(output.closed)
270
271
self.assertEqual([
282
283
input = StringIO()
283
284
output = StringIO()
284
285
vendor = StringIOSSHVendor(input, output)
285
medium = smart.SmartSSHClientMedium('a hostname', vendor=vendor)
286
medium._accept_bytes('abc')
286
client_medium = medium.SmartSSHClientMedium('a hostname', vendor=vendor)
287
client_medium._accept_bytes('abc')
288
client_medium.disconnect()
288
289
# the disconnect has closed output, so we need a new output for the
289
290
# new connection to write to.
290
291
input2 = StringIO()
291
292
output2 = StringIO()
292
293
vendor.read_from = input2
293
294
vendor.write_to = output2
294
medium._accept_bytes('abc')
295
client_medium._accept_bytes('abc')
296
client_medium.disconnect()
296
297
self.assertTrue(input.closed)
297
298
self.assertTrue(output.closed)
298
299
self.assertTrue(input2.closed)
310
311
def test_ssh_client_ignores_disconnect_when_not_connected(self):
311
312
# Doing a disconnect on a new (and thus unconnected) SSH medium
312
313
# does not fail. It's ok to disconnect an unconnected medium.
313
medium = smart.SmartSSHClientMedium(None)
314
client_medium = medium.SmartSSHClientMedium(None)
315
client_medium.disconnect()
316
317
def test_ssh_client_raises_on_read_when_not_connected(self):
317
318
# Doing a read on a new (and thus unconnected) SSH medium raises
318
319
# MediumNotConnected.
319
medium = smart.SmartSSHClientMedium(None)
320
self.assertRaises(errors.MediumNotConnected, medium.read_bytes, 0)
321
self.assertRaises(errors.MediumNotConnected, medium.read_bytes, 1)
320
client_medium = medium.SmartSSHClientMedium(None)
321
self.assertRaises(errors.MediumNotConnected, client_medium.read_bytes, 0)
322
self.assertRaises(errors.MediumNotConnected, client_medium.read_bytes, 1)
323
324
def test_ssh_client_supports__flush(self):
324
325
# invoking _flush on a SSHClientMedium should flush the output
331
332
def logging_flush(): flush_calls.append('flush')
332
333
output.flush = logging_flush
333
334
vendor = StringIOSSHVendor(input, output)
334
medium = smart.SmartSSHClientMedium('a hostname', vendor=vendor)
335
client_medium = medium.SmartSSHClientMedium('a hostname', vendor=vendor)
335
336
# this call is here to ensure we only flush once, not on every
336
337
# _accept_bytes call.
337
medium._accept_bytes('abc')
338
client_medium._accept_bytes('abc')
339
client_medium._flush()
340
client_medium.disconnect()
340
341
self.assertEqual(['flush'], flush_calls)
342
343
def test_construct_smart_tcp_client_medium(self):
345
346
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
346
347
sock.bind(('127.0.0.1', 0))
347
348
unopened_port = sock.getsockname()[1]
348
medium = smart.SmartTCPClientMedium('127.0.0.1', unopened_port)
349
client_medium = medium.SmartTCPClientMedium('127.0.0.1', unopened_port)
351
352
def test_tcp_client_connects_on_first_use(self):
378
379
def test_tcp_client_ignores_disconnect_when_not_connected(self):
379
380
# Doing a disconnect on a new (and thus unconnected) TCP medium
380
381
# does not fail. It's ok to disconnect an unconnected medium.
381
medium = smart.SmartTCPClientMedium(None, None)
382
client_medium = medium.SmartTCPClientMedium(None, None)
383
client_medium.disconnect()
384
385
def test_tcp_client_raises_on_read_when_not_connected(self):
385
386
# Doing a read on a new (and thus unconnected) TCP medium raises
386
387
# MediumNotConnected.
387
medium = smart.SmartTCPClientMedium(None, None)
388
self.assertRaises(errors.MediumNotConnected, medium.read_bytes, 0)
389
self.assertRaises(errors.MediumNotConnected, medium.read_bytes, 1)
388
client_medium = medium.SmartTCPClientMedium(None, None)
389
self.assertRaises(errors.MediumNotConnected, client_medium.read_bytes, 0)
390
self.assertRaises(errors.MediumNotConnected, client_medium.read_bytes, 1)
391
392
def test_tcp_client_supports__flush(self):
392
393
# invoking _flush on a TCPClientMedium should do something useful.
421
422
# WritingCompleted to prevent bad assumptions on stream environments
422
423
# breaking the needs of message-based environments.
423
424
output = StringIO()
424
medium = smart.SmartSimplePipesClientMedium(None, output)
425
request = smart.SmartClientStreamMediumRequest(medium)
425
client_medium = medium.SmartSimplePipesClientMedium(None, output)
426
request = medium.SmartClientStreamMediumRequest(client_medium)
426
427
request.finished_writing()
427
428
self.assertRaises(errors.WritingCompleted, request.accept_bytes, None)
432
433
# and checking that the pipes get the data.
433
434
input = StringIO()
434
435
output = StringIO()
435
medium = smart.SmartSimplePipesClientMedium(input, output)
436
request = smart.SmartClientStreamMediumRequest(medium)
436
client_medium = medium.SmartSimplePipesClientMedium(input, output)
437
request = medium.SmartClientStreamMediumRequest(client_medium)
437
438
request.accept_bytes('123')
438
439
request.finished_writing()
439
440
request.finished_reading()
444
445
# constructing a SmartClientStreamMediumRequest on a StreamMedium sets
445
446
# the current request to the new SmartClientStreamMediumRequest
446
447
output = StringIO()
447
medium = smart.SmartSimplePipesClientMedium(None, output)
448
request = smart.SmartClientStreamMediumRequest(medium)
449
self.assertIs(medium._current_request, request)
448
client_medium = medium.SmartSimplePipesClientMedium(None, output)
449
request = medium.SmartClientStreamMediumRequest(client_medium)
450
self.assertIs(client_medium._current_request, request)
451
452
def test_construct_while_another_request_active_throws(self):
452
453
# constructing a SmartClientStreamMediumRequest on a StreamMedium with
453
454
# a non-None _current_request raises TooManyConcurrentRequests.
454
455
output = StringIO()
455
medium = smart.SmartSimplePipesClientMedium(None, output)
456
medium._current_request = "a"
456
client_medium = medium.SmartSimplePipesClientMedium(None, output)
457
client_medium._current_request = "a"
457
458
self.assertRaises(errors.TooManyConcurrentRequests,
458
smart.SmartClientStreamMediumRequest, medium)
459
medium.SmartClientStreamMediumRequest, client_medium)
460
461
def test_finished_read_clears_current_request(self):
461
462
# calling finished_reading clears the current request from the requests
463
464
output = StringIO()
464
medium = smart.SmartSimplePipesClientMedium(None, output)
465
request = smart.SmartClientStreamMediumRequest(medium)
465
client_medium = medium.SmartSimplePipesClientMedium(None, output)
466
request = medium.SmartClientStreamMediumRequest(client_medium)
466
467
request.finished_writing()
467
468
request.finished_reading()
468
self.assertEqual(None, medium._current_request)
469
self.assertEqual(None, client_medium._current_request)
470
471
def test_finished_read_before_finished_write_errors(self):
471
472
# calling finished_reading before calling finished_writing triggers a
472
473
# WritingNotComplete error.
473
medium = smart.SmartSimplePipesClientMedium(None, None)
474
request = smart.SmartClientStreamMediumRequest(medium)
474
client_medium = medium.SmartSimplePipesClientMedium(None, None)
475
request = medium.SmartClientStreamMediumRequest(client_medium)
475
476
self.assertRaises(errors.WritingNotComplete, request.finished_reading)
477
478
def test_read_bytes(self):
484
485
input = StringIO('321')
485
486
output = StringIO()
486
medium = smart.SmartSimplePipesClientMedium(input, output)
487
request = smart.SmartClientStreamMediumRequest(medium)
487
client_medium = medium.SmartSimplePipesClientMedium(input, output)
488
request = medium.SmartClientStreamMediumRequest(client_medium)
488
489
request.finished_writing()
489
490
self.assertEqual('321', request.read_bytes(3))
490
491
request.finished_reading()
496
497
# WritingNotComplete error because the Smart protocol is designed to be
497
498
# compatible with strict message based protocols like HTTP where the
498
499
# request cannot be submitted until the writing has completed.
499
medium = smart.SmartSimplePipesClientMedium(None, None)
500
request = smart.SmartClientStreamMediumRequest(medium)
500
client_medium = medium.SmartSimplePipesClientMedium(None, None)
501
request = medium.SmartClientStreamMediumRequest(client_medium)
501
502
self.assertRaises(errors.WritingNotComplete, request.read_bytes, None)
503
504
def test_read_bytes_after_finished_reading_errors(self):
505
506
# ReadingCompleted to prevent bad assumptions on stream environments
506
507
# breaking the needs of message-based environments.
507
508
output = StringIO()
508
medium = smart.SmartSimplePipesClientMedium(None, output)
509
request = smart.SmartClientStreamMediumRequest(medium)
509
client_medium = medium.SmartSimplePipesClientMedium(None, output)
510
request = medium.SmartClientStreamMediumRequest(client_medium)
510
511
request.finished_writing()
511
512
request.finished_reading()
512
513
self.assertRaises(errors.ReadingCompleted, request.read_bytes, None)
532
533
def test_get_medium_from_transport(self):
533
534
"""Remote transport has a medium always, which it can return."""
534
535
t = self.get_transport()
535
medium = t.get_smart_medium()
536
self.assertIsInstance(medium, smart.SmartClientMedium)
536
client_medium = t.get_smart_medium()
537
self.assertIsInstance(client_medium, medium.SmartClientMedium)
539
540
class ErrorRaisingProtocol(object):
588
589
to_server = StringIO('hello\n')
589
590
from_server = StringIO()
590
591
transport = local.LocalTransport(urlutils.local_path_to_url('/'))
591
server = smart.SmartServerPipeStreamMedium(
592
server = medium.SmartServerPipeStreamMedium(
592
593
to_server, from_server, transport)
593
594
protocol = smart.SmartServerRequestProtocolOne(transport,
594
595
from_server.write)
601
602
transport.put_bytes('testfile', 'contents\nof\nfile\n')
602
603
to_server = StringIO('get\001./testfile\n')
603
604
from_server = StringIO()
604
server = smart.SmartServerPipeStreamMedium(
605
server = medium.SmartServerPipeStreamMedium(
605
606
to_server, from_server, transport)
606
607
protocol = smart.SmartServerRequestProtocolOne(transport,
607
608
from_server.write)
619
620
transport.put_bytes(utf8_filename, 'contents\nof\nfile\n')
620
621
to_server = StringIO('get\001' + utf8_filename + '\n')
621
622
from_server = StringIO()
622
server = smart.SmartServerPipeStreamMedium(
623
server = medium.SmartServerPipeStreamMedium(
623
624
to_server, from_server, transport)
624
625
protocol = smart.SmartServerRequestProtocolOne(transport,
625
626
from_server.write)
634
635
sample_request_bytes = 'command\n9\nbulk datadone\n'
635
636
to_server = StringIO(sample_request_bytes)
636
637
from_server = StringIO()
637
server = smart.SmartServerPipeStreamMedium(to_server, from_server, None)
638
server = medium.SmartServerPipeStreamMedium(
639
to_server, from_server, None)
638
640
sample_protocol = SampleRequest(expected_bytes=sample_request_bytes)
639
641
server._serve_one_request(sample_protocol)
640
642
self.assertEqual('', from_server.getvalue())
644
646
def test_socket_stream_with_bulk_data(self):
645
647
sample_request_bytes = 'command\n9\nbulk datadone\n'
646
648
server_sock, client_sock = self.portable_socket_pair()
647
server = smart.SmartServerSocketStreamMedium(
649
server = medium.SmartServerSocketStreamMedium(
648
650
server_sock, None)
649
651
sample_protocol = SampleRequest(expected_bytes=sample_request_bytes)
650
652
client_sock.sendall(sample_request_bytes)
657
659
def test_pipe_like_stream_shutdown_detection(self):
658
660
to_server = StringIO('')
659
661
from_server = StringIO()
660
server = smart.SmartServerPipeStreamMedium(to_server, from_server, None)
662
server = medium.SmartServerPipeStreamMedium(to_server, from_server, None)
661
663
server._serve_one_request(SampleRequest('x'))
662
664
self.assertTrue(server.finished)
664
666
def test_socket_stream_shutdown_detection(self):
665
667
server_sock, client_sock = self.portable_socket_pair()
666
668
client_sock.close()
667
server = smart.SmartServerSocketStreamMedium(
669
server = medium.SmartServerSocketStreamMedium(
668
670
server_sock, None)
669
671
server._serve_one_request(SampleRequest('x'))
670
672
self.assertTrue(server.finished)
676
678
sample_request_bytes = 'command\n'
677
679
to_server = StringIO(sample_request_bytes * 2)
678
680
from_server = StringIO()
679
server = smart.SmartServerPipeStreamMedium(to_server, from_server, None)
681
server = medium.SmartServerPipeStreamMedium(
682
to_server, from_server, None)
680
683
first_protocol = SampleRequest(expected_bytes=sample_request_bytes)
681
684
server._serve_one_request(first_protocol)
682
685
self.assertEqual(0, first_protocol.next_read_size())
696
699
# been received seperately.
697
700
sample_request_bytes = 'command\n'
698
701
server_sock, client_sock = self.portable_socket_pair()
699
server = smart.SmartServerSocketStreamMedium(
702
server = medium.SmartServerSocketStreamMedium(
700
703
server_sock, None)
701
704
first_protocol = SampleRequest(expected_bytes=sample_request_bytes)
702
705
# Put two whole requests on the wire.
724
727
self.closed = True
725
728
from_server.close = close
726
server = smart.SmartServerPipeStreamMedium(to_server, from_server, None)
729
server = medium.SmartServerPipeStreamMedium(
730
to_server, from_server, None)
727
731
fake_protocol = ErrorRaisingProtocol(Exception('boom'))
728
732
server._serve_one_request(fake_protocol)
729
733
self.assertEqual('', from_server.getvalue())
735
739
# not discard the contents.
736
740
from StringIO import StringIO
737
741
server_sock, client_sock = self.portable_socket_pair()
738
server = smart.SmartServerSocketStreamMedium(
742
server = medium.SmartServerSocketStreamMedium(
739
743
server_sock, None)
740
744
fake_protocol = ErrorRaisingProtocol(Exception('boom'))
741
745
server._serve_one_request(fake_protocol)
749
753
# not discard the contents.
750
754
to_server = StringIO('')
751
755
from_server = StringIO()
752
server = smart.SmartServerPipeStreamMedium(to_server, from_server, None)
756
server = medium.SmartServerPipeStreamMedium(
757
to_server, from_server, None)
753
758
fake_protocol = ErrorRaisingProtocol(KeyboardInterrupt('boom'))
754
759
self.assertRaises(
755
760
KeyboardInterrupt, server._serve_one_request, fake_protocol)
1004
1009
# We want to be able to pass a client as a parameter to SmartTransport.
1005
1010
input = StringIO("ok\n3\nbardone\n")
1006
1011
output = StringIO()
1007
medium = smart.SmartSimplePipesClientMedium(input, output)
1008
transport = smart.SmartTransport('bzr://localhost/', medium=medium)
1012
client_medium = medium.SmartSimplePipesClientMedium(input, output)
1013
transport = smart.SmartTransport(
1014
'bzr://localhost/', medium=client_medium)
1010
1016
# We want to make sure the client is used when the first remote
1011
1017
# method is called. No data should have been sent, or read.
1024
1030
def test__translate_error_readonly(self):
1025
1031
"""Sending a ReadOnlyError to _translate_error raises TransportNotPossible."""
1026
medium = smart.SmartClientMedium()
1027
transport = smart.SmartTransport('bzr://localhost/', medium=medium)
1032
client_medium = medium.SmartClientMedium()
1033
transport = smart.SmartTransport(
1034
'bzr://localhost/', medium=client_medium)
1028
1035
self.assertRaises(errors.TransportNotPossible,
1029
1036
transport._translate_error, ("ReadOnlyError", ))
1032
class InstrumentedServerProtocol(smart.SmartServerStreamMedium):
1039
class InstrumentedServerProtocol(medium.SmartServerStreamMedium):
1033
1040
"""A smart server which is backed by memory and saves its write requests."""
1035
1042
def __init__(self, write_output_list):
1036
smart.SmartServerStreamMedium.__init__(self, memory.MemoryTransport())
1043
medium.SmartServerStreamMedium.__init__(self, memory.MemoryTransport())
1037
1044
self._write_output_list = write_output_list
1055
1062
self.server_to_client = []
1056
1063
self.to_server = StringIO()
1057
1064
self.to_client = StringIO()
1058
self.client_medium = smart.SmartSimplePipesClientMedium(self.to_client,
1065
self.client_medium = medium.SmartSimplePipesClientMedium(self.to_client,
1059
1066
self.to_server)
1060
1067
self.client_protocol = smart.SmartClientRequestProtocolOne(
1061
1068
self.client_medium)
1108
1115
def test_construct_version_one_client_protocol(self):
1109
1116
# we can construct a client protocol from a client medium request
1110
1117
output = StringIO()
1111
medium = smart.SmartSimplePipesClientMedium(None, output)
1112
request = medium.get_request()
1118
client_medium = medium.SmartSimplePipesClientMedium(None, output)
1119
request = client_medium.get_request()
1113
1120
client_protocol = smart.SmartClientRequestProtocolOne(request)
1115
1122
def test_server_offset_serialisation(self):
1208
1215
# the error if the response is a non-understood version.
1209
1216
input = StringIO('ok\x011\n')
1210
1217
output = StringIO()
1211
medium = smart.SmartSimplePipesClientMedium(input, output)
1212
protocol = smart.SmartClientRequestProtocolOne(medium.get_request())
1218
client_medium = medium.SmartSimplePipesClientMedium(input, output)
1219
request = client_medium.get_request()
1220
protocol = smart.SmartClientRequestProtocolOne(request)
1213
1221
self.assertEqual(1, protocol.query_version())
1215
1223
def assertServerToClientEncoding(self, expected_bytes, expected_tuple,
1228
1236
# check the decoding of the client protocol from expected_bytes:
1229
1237
input = StringIO(expected_bytes)
1230
1238
output = StringIO()
1231
medium = smart.SmartSimplePipesClientMedium(input, output)
1232
protocol = smart.SmartClientRequestProtocolOne(medium.get_request())
1239
client_medium = medium.SmartSimplePipesClientMedium(input, output)
1240
request = client_medium.get_request()
1241
protocol = smart.SmartClientRequestProtocolOne(request)
1233
1242
protocol.call('foo')
1234
1243
self.assertEqual(expected_tuple, protocol.read_response_tuple())
1251
1260
expected_bytes = "foo\n7\nabcdefgdone\n"
1252
1261
input = StringIO("\n")
1253
1262
output = StringIO()
1254
medium = smart.SmartSimplePipesClientMedium(input, output)
1255
protocol = smart.SmartClientRequestProtocolOne(medium.get_request())
1263
client_medium = medium.SmartSimplePipesClientMedium(input, output)
1264
request = client_medium.get_request()
1265
protocol = smart.SmartClientRequestProtocolOne(request)
1256
1266
protocol.call_with_body_bytes(('foo', ), "abcdefg")
1257
1267
self.assertEqual(expected_bytes, output.getvalue())
1262
1272
expected_bytes = "foo\n7\n1,2\n5,6done\n"
1263
1273
input = StringIO("\n")
1264
1274
output = StringIO()
1265
medium = smart.SmartSimplePipesClientMedium(input, output)
1266
protocol = smart.SmartClientRequestProtocolOne(medium.get_request())
1275
client_medium = medium.SmartSimplePipesClientMedium(input, output)
1276
request = client_medium.get_request()
1277
protocol = smart.SmartClientRequestProtocolOne(request)
1267
1278
protocol.call_with_body_readv_array(('foo', ), [(1,2),(5,6)])
1268
1279
self.assertEqual(expected_bytes, output.getvalue())
1274
1285
server_bytes = "ok\n7\n1234567done\n"
1275
1286
input = StringIO(server_bytes)
1276
1287
output = StringIO()
1277
medium = smart.SmartSimplePipesClientMedium(input, output)
1278
protocol = smart.SmartClientRequestProtocolOne(medium.get_request())
1288
client_medium = medium.SmartSimplePipesClientMedium(input, output)
1289
request = client_medium.get_request()
1290
protocol = smart.SmartClientRequestProtocolOne(request)
1279
1291
protocol.call('foo')
1280
1292
protocol.read_response_tuple(True)
1281
1293
self.assertEqual(expected_bytes, protocol.read_body_bytes())
1290
1302
server_bytes = "ok\n7\n1234567done\n"
1291
1303
input = StringIO(server_bytes)
1292
1304
output = StringIO()
1293
medium = smart.SmartSimplePipesClientMedium(input, output)
1294
protocol = smart.SmartClientRequestProtocolOne(medium.get_request())
1305
client_medium = medium.SmartSimplePipesClientMedium(input, output)
1306
request = client_medium.get_request()
1307
protocol = smart.SmartClientRequestProtocolOne(request)
1295
1308
protocol.call('foo')
1296
1309
protocol.read_response_tuple(True)
1297
1310
self.assertEqual(expected_bytes[0:2], protocol.read_body_bytes(2))
1306
1319
server_bytes = "ok\n7\n1234567done\n"
1307
1320
input = StringIO(server_bytes)
1308
1321
output = StringIO()
1309
medium = smart.SmartSimplePipesClientMedium(input, output)
1310
protocol = smart.SmartClientRequestProtocolOne(medium.get_request())
1322
client_medium = medium.SmartSimplePipesClientMedium(input, output)
1323
request = client_medium.get_request()
1324
protocol = smart.SmartClientRequestProtocolOne(request)
1311
1325
protocol.call('foo')
1312
1326
protocol.read_response_tuple(True)
1313
1327
protocol.cancel_read_body()