@@ -1861,6 +1861,44 @@ def inner():
18611861 assert s .gettrailers () == HTTPHeaderMap (trailers )
18621862 assert s .data == [b'testdata' ]
18631863
1864+ def test_can_read_single_frames_from_streams (self ):
1865+ out_frames = []
1866+ in_frames = []
1867+
1868+ def send_cb (frame , tolerate_peer_gone = False ):
1869+ out_frames .append (frame )
1870+
1871+ def recv_cb (s ):
1872+ def inner ():
1873+ s .receive_frame (in_frames .pop (0 ))
1874+ return inner
1875+
1876+ s = Stream (1 , send_cb , None , None , None , None , FlowControlManager (800 ))
1877+ s ._recv_cb = recv_cb (s )
1878+ s .state = STATE_HALF_CLOSED_LOCAL
1879+
1880+ # Provide two data frames to read.
1881+ f = DataFrame (1 )
1882+ f .data = b'hi there!'
1883+ in_frames .append (f )
1884+
1885+ f = DataFrame (1 )
1886+ f .data = b'hi there again!'
1887+ f .flags .add ('END_STREAM' )
1888+ in_frames .append (f )
1889+
1890+ data = s ._read_one_frame ()
1891+ assert data == b'hi there!'
1892+
1893+ data = s ._read_one_frame ()
1894+ assert data == b'hi there again!'
1895+
1896+ data = s ._read_one_frame ()
1897+ assert data is None
1898+
1899+ data = s ._read ()
1900+ assert data == b''
1901+
18641902
18651903class TestResponse (object ):
18661904 def test_status_is_stripped_from_headers (self ):
@@ -1968,6 +2006,33 @@ def test_trailers_are_read(self):
19682006 assert resp .trailers ['a' ] == [b'b' ]
19692007 assert resp .trailers ['c' ] == [b'd' ]
19702008
2009+ def test_read_frames (self ):
2010+ headers = HTTPHeaderMap ([(':status' , '200' )])
2011+ stream = DummyStream (None )
2012+ chunks = [b'12' , b'3456' , b'78' , b'9' ]
2013+ stream .data_frames = chunks
2014+ resp = HTTP20Response (headers , stream )
2015+
2016+ for recv , expected in zip (resp .read_chunked (), chunks [:]):
2017+ assert recv == expected
2018+
2019+ def test_read_compressed_frames (self ):
2020+ headers = HTTPHeaderMap ([(':status' , '200' ), ('content-encoding' , 'gzip' )])
2021+ c = zlib_compressobj (wbits = 24 )
2022+ body = c .compress (b'this is test data' )
2023+ body += c .flush ()
2024+
2025+ stream = DummyStream (None )
2026+ chunks = [body [x :x + 2 ] for x in range (0 , len (body ), 2 )]
2027+ stream .data_frames = chunks
2028+ resp = HTTP20Response (headers , stream )
2029+
2030+ received = b''
2031+ for chunk in resp .read_chunked ():
2032+ received += chunk
2033+
2034+ assert received == b'this is test data'
2035+
19712036
19722037class TestHTTP20Adapter (object ):
19732038 def test_adapter_reuses_connections (self ):
@@ -2090,6 +2155,7 @@ def recv(self, l):
20902155class DummyStream (object ):
20912156 def __init__ (self , data , trailers = None ):
20922157 self .data = data
2158+ self .data_frames = []
20932159 self .closed = False
20942160 self .response_headers = {}
20952161 self ._remote_closed = False
@@ -2112,6 +2178,12 @@ def _read(self, *args, **kwargs):
21122178
21132179 return d
21142180
2181+ def _read_one_frame (self ):
2182+ try :
2183+ return self .data_frames .pop (0 )
2184+ except IndexError :
2185+ return None
2186+
21152187 def close (self ):
21162188 if not self .closed :
21172189 self .closed = True
0 commit comments