@@ -860,18 +860,35 @@ def test_connection_doesnt_send_window_update_on_zero_length_data_frame(self):
860860 # No frame should have been sent on the connection.
861861 assert len (sock .queue ) == 0
862862
863+ def test_streams_are_cleared_from_connections_on_close (self ):
864+ # Prepare a socket so we can open a stream.
865+ sock = DummySocket ()
866+ c = HTTP20Connection ('www.google.com' )
867+ c ._sock = sock
868+
869+ # Open a request (which creates a stream)
870+ c .request ('GET' , '/' )
871+
872+ # Close the stream.
873+ c .streams [1 ].close ()
874+
875+ # There should be nothing left, but the next stream ID should be
876+ # unchanged.
877+ assert not c .streams
878+ assert c .next_stream_id == 3
879+
863880
864881class TestHyperStream (object ):
865882 def test_streams_have_ids (self ):
866- s = Stream (1 , None , None , None , None )
883+ s = Stream (1 , None , None , None , None , None )
867884 assert s .stream_id == 1
868885
869886 def test_streams_initially_have_no_headers (self ):
870- s = Stream (1 , None , None , None , None )
887+ s = Stream (1 , None , None , None , None , None )
871888 assert s .headers == []
872889
873890 def test_streams_can_have_headers (self ):
874- s = Stream (1 , None , None , None , None )
891+ s = Stream (1 , None , None , None , None , None )
875892 s .add_header ("name" , "value" )
876893 assert s .headers == [("name" , "value" )]
877894
@@ -881,14 +898,14 @@ def data_callback(frame):
881898 assert frame .data == 'testkeyTestVal'
882899 assert frame .flags == set (['END_STREAM' , 'END_HEADERS' ])
883900
884- s = Stream (1 , data_callback , None , NullEncoder , None )
901+ s = Stream (1 , data_callback , None , None , NullEncoder , None )
885902 s .add_header ("TestKey" , "TestVal" )
886903 s .open (True )
887904
888905 assert s .state == STATE_HALF_CLOSED_LOCAL
889906
890907 def test_receiving_a_frame_queues_it (self ):
891- s = Stream (1 , None , None , None , None )
908+ s = Stream (1 , None , None , None , None , None )
892909 s .receive_frame (Frame (0 ))
893910 assert len (s ._queued_frames ) == 1
894911
@@ -898,7 +915,7 @@ def data_callback(frame):
898915 assert frame .data == b'Hi there!'
899916 assert frame .flags == set (['END_STREAM' ])
900917
901- s = Stream (1 , data_callback , None , NullEncoder , None )
918+ s = Stream (1 , data_callback , None , None , NullEncoder , None )
902919 s .state = STATE_OPEN
903920 s .send_data (BytesIO (b'Hi there!' ), True )
904921
@@ -917,7 +934,7 @@ def data_callback(frame):
917934
918935 data = b'test' * (MAX_CHUNK + 1 )
919936
920- s = Stream (1 , data_callback , None , NullEncoder , None )
937+ s = Stream (1 , data_callback , None , None , NullEncoder , None )
921938 s .state = STATE_OPEN
922939 s .send_data (BytesIO (data ), True )
923940
@@ -932,7 +949,7 @@ def data_callback(frame):
932949 assert frame .data == b'Hi there!'
933950 assert frame .flags == set (['END_STREAM' ])
934951
935- s = Stream (1 , data_callback , None , NullEncoder , None )
952+ s = Stream (1 , data_callback , None , None , NullEncoder , None )
936953 s .state = STATE_OPEN
937954 s .send_data (b'Hi there!' , True )
938955
@@ -951,7 +968,7 @@ def data_callback(frame):
951968
952969 data = b'test' * (MAX_CHUNK + 1 )
953970
954- s = Stream (1 , data_callback , None , NullEncoder , None )
971+ s = Stream (1 , data_callback , None , None , NullEncoder , None )
955972 s .state = STATE_OPEN
956973 s .send_data (data , True )
957974
@@ -961,7 +978,7 @@ def data_callback(frame):
961978 assert s ._out_flow_control_window == 65535 - len (data )
962979
963980 def test_windowupdate_frames_update_windows (self ):
964- s = Stream (1 , None , None , None , None )
981+ s = Stream (1 , None , None , None , None , None )
965982 f = WindowUpdateFrame (1 )
966983 f .window_increment = 1000
967984 s .receive_frame (f )
@@ -980,7 +997,7 @@ def inner():
980997 s .receive_frame (in_frames .pop (0 ))
981998 return inner
982999
983- s = Stream (1 , send_cb , None , None , None )
1000+ s = Stream (1 , send_cb , None , None , None , None )
9841001 s ._recv_cb = recv_cb (s )
9851002 s .state = STATE_HALF_CLOSED_LOCAL
9861003
@@ -1006,7 +1023,7 @@ def inner():
10061023 s .receive_frame (in_frames .pop (0 ))
10071024 return inner
10081025
1009- s = Stream (1 , send_cb , None , None , None )
1026+ s = Stream (1 , send_cb , None , None , None , None )
10101027 s ._recv_cb = recv_cb (s )
10111028 s .state = STATE_HALF_CLOSED_LOCAL
10121029
@@ -1038,7 +1055,7 @@ def inner():
10381055 s .receive_frame (in_frames .pop (0 ))
10391056 return inner
10401057
1041- s = Stream (1 , send_cb , None , None , None )
1058+ s = Stream (1 , send_cb , None , None , None , None )
10421059 s ._recv_cb = recv_cb (s )
10431060 s .state = STATE_HALF_CLOSED_LOCAL
10441061
@@ -1099,6 +1116,13 @@ def test_response_transparently_decrypts_wrong_deflate(self):
10991116
11001117 assert resp .read () == b'this is test data'
11011118
1119+ def test_response_calls_stream_close (self ):
1120+ stream = DummyStream ('' )
1121+ resp = HTTP20Response ({':status' : '200' }, stream )
1122+ resp .close ()
1123+
1124+ assert stream .closed
1125+
11021126
11031127class TestHTTP20Adapter (object ):
11041128 def test_adapter_reuses_connections (self ):
@@ -1131,6 +1155,13 @@ def close(self):
11311155class DummyStream (object ):
11321156 def __init__ (self , data ):
11331157 self .data = data
1158+ self .closed = False
11341159
11351160 def _read (self , * args , ** kwargs ):
11361161 return self .data
1162+
1163+ def close (self ):
1164+ if not self .closed :
1165+ self .closed = True
1166+ else :
1167+ assert False
0 commit comments