53
53
54
54
HOST = '127.0.0.1'
55
55
RESOURCE = '/resource'
56
+ DEFAULT_TEST_MAX_DURATION = 1
56
57
57
58
# Timeout tests follow a general pattern: one side waits TIMEOUT seconds for an
58
59
# event. The other side delays for FORCE_TIMEOUT seconds to force the timeout
59
60
# to trigger. Each test also has maximum runtime (measure by Trio's clock) to
60
61
# prevent a faulty test from hanging the entire suite.
61
62
TIMEOUT = 1
62
63
FORCE_TIMEOUT = 2
63
- MAX_TIMEOUT_TEST_DURATION = 3
64
+ TIMEOUT_TEST_MAX_DURATION = 3
65
+ import logging
64
66
65
67
66
68
@pytest .fixture
@@ -89,12 +91,6 @@ async def echo_request_handler(request):
89
91
Accept incoming request and then pass off to echo connection handler.
90
92
'''
91
93
conn = await request .accept ()
92
- await echo_conn_handler (conn )
93
-
94
-
95
- async def echo_conn_handler (conn ):
96
- ''' A connection handler that reads one message, sends back the same
97
- message, then exits. '''
98
94
try :
99
95
msg = await conn .get_message ()
100
96
await conn .send_message (msg )
@@ -391,7 +387,7 @@ async def handler(stream):
391
387
await client .send_message ('Hello from client!' )
392
388
393
389
394
- @fail_after (MAX_TIMEOUT_TEST_DURATION )
390
+ @fail_after (TIMEOUT_TEST_MAX_DURATION )
395
391
async def test_client_open_timeout (nursery , autojump_clock ):
396
392
'''
397
393
The client times out waiting for the server to complete the opening
@@ -411,7 +407,7 @@ async def handler(request):
411
407
pass
412
408
413
409
414
- @fail_after (MAX_TIMEOUT_TEST_DURATION )
410
+ @fail_after (TIMEOUT_TEST_MAX_DURATION )
415
411
async def test_client_close_timeout (nursery , autojump_clock ):
416
412
'''
417
413
This client times out waiting for the server to complete the closing
@@ -430,15 +426,16 @@ async def handler(request):
430
426
pytest .fail ('Should not reach this line.' )
431
427
432
428
server = await nursery .start (
433
- partial (serve_websocket , handler , HOST , 0 , ssl_context = None ))
429
+ partial (serve_websocket , handler , HOST , 0 , ssl_context = None ,
430
+ message_queue_size = 0 ))
434
431
435
432
with pytest .raises (trio .TooSlowError ):
436
433
async with open_websocket (HOST , server .port , RESOURCE , use_ssl = False ,
437
434
disconnect_timeout = TIMEOUT ) as client_ws :
438
435
await client_ws .send_message ('test' )
439
436
440
437
441
- @fail_after (MAX_TIMEOUT_TEST_DURATION )
438
+ @fail_after (TIMEOUT_TEST_MAX_DURATION )
442
439
async def test_server_open_timeout (autojump_clock ):
443
440
'''
444
441
The server times out waiting for the client to complete the opening
@@ -470,7 +467,7 @@ async def handler(request):
470
467
nursery .cancel_scope .cancel ()
471
468
472
469
473
- @fail_after (MAX_TIMEOUT_TEST_DURATION )
470
+ @fail_after (TIMEOUT_TEST_MAX_DURATION )
474
471
async def test_server_close_timeout (autojump_clock ):
475
472
'''
476
473
The server times out waiting for the client to complete the closing
@@ -523,7 +520,6 @@ async def handler(request):
523
520
with pytest .raises (ConnectionClosed ):
524
521
await server_ws .get_message ()
525
522
server = await nursery .start (serve_websocket , handler , HOST , 0 , None )
526
- port = server .port
527
523
stream = await trio .open_tcp_stream (HOST , server .port )
528
524
client_ws = await wrap_client_stream (nursery , stream , HOST , RESOURCE )
529
525
async with client_ws :
@@ -566,12 +562,14 @@ async def handler(request):
566
562
assert exc .reason .name == 'NORMAL_CLOSURE'
567
563
568
564
569
- @pytest . mark . skip ( reason = 'Hangs because channel size is hard coded to 0' )
565
+ @fail_after ( DEFAULT_TEST_MAX_DURATION )
570
566
async def test_read_messages_after_remote_close (nursery ):
571
567
'''
572
568
When the remote endpoint closes, the local endpoint can still read all
573
569
of the messages sent prior to closing. Any attempt to read beyond that will
574
570
raise ConnectionClosed.
571
+
572
+ This test also exercises the configuration of the queue size.
575
573
'''
576
574
server_closed = trio .Event ()
577
575
@@ -585,7 +583,10 @@ async def handler(request):
585
583
server = await nursery .start (
586
584
partial (serve_websocket , handler , HOST , 0 , ssl_context = None ))
587
585
588
- async with open_websocket (HOST , server .port , '/' , use_ssl = False ) as client :
586
+ # The client needs a message queue of size 2 so that it can buffer both
587
+ # incoming messages without blocking the reader task.
588
+ async with open_websocket (HOST , server .port , '/' , use_ssl = False ,
589
+ message_queue_size = 2 ) as client :
589
590
await server_closed .wait ()
590
591
assert await client .get_message () == '1'
591
592
assert await client .get_message () == '2'
@@ -618,12 +619,53 @@ async def handler(request):
618
619
client_closed .set ()
619
620
620
621
621
- async def test_client_cm_exit_with_pending_messages (echo_server , autojump_clock ):
622
+ async def test_cm_exit_with_pending_messages (echo_server , autojump_clock ):
623
+ '''
624
+ Regression test for #74, where a context manager was not able to exit when
625
+ there were pending messages in the receive queue.
626
+ '''
622
627
with trio .fail_after (1 ):
623
628
async with open_websocket (HOST , echo_server .port , RESOURCE ,
624
629
use_ssl = False ) as ws :
625
630
await ws .send_message ('hello' )
626
631
# allow time for the server to respond
627
632
await trio .sleep (.1 )
628
- # bug: context manager exit is blocked on unconsumed message
629
- #await ws.get_message()
633
+
634
+
635
+ @fail_after (DEFAULT_TEST_MAX_DURATION )
636
+ async def test_max_message_size (nursery ):
637
+ '''
638
+ Set the client's max message size to 100 bytes. The client can send a
639
+ message larger than 100 bytes, but when it receives a message larger than
640
+ 100 bytes, it closes the connection with code 1009.
641
+ '''
642
+ import logging
643
+ async def handler (request ):
644
+ ''' Similar to the echo_request_handler fixture except it runs in a
645
+ loop. '''
646
+ conn = await request .accept ()
647
+ while True :
648
+ try :
649
+ msg = await conn .get_message ()
650
+ await conn .send_message (msg )
651
+ except ConnectionClosed :
652
+ break
653
+
654
+ server = await nursery .start (
655
+ partial (serve_websocket , handler , HOST , 0 , ssl_context = None ))
656
+
657
+ async with open_websocket (HOST , server .port , RESOURCE , use_ssl = False ,
658
+ max_message_size = 100 ) as client :
659
+ # We can send and receive 100 bytes:
660
+ await client .send_message (b'A' * 100 )
661
+ msg = await client .get_message ()
662
+ assert len (msg ) == 100
663
+ # We can send 101 bytes but cannot receive 101 bytes:
664
+ await client .send_message (b'B' * 101 )
665
+ with pytest .raises (ConnectionClosed ):
666
+ await client .get_message ()
667
+ logging .debug ('TEST 0' )
668
+ assert client .closed
669
+ assert client .closed .code == 1009
670
+ logging .debug ('TEST 1' )
671
+ logging .debug ('TEST 2' )
0 commit comments