def test_cannot_receive_three_header_blocks(self): first = [('a', 'b'), ('c', 'd'), (':status', '200')] s = Stream(1, None, None, None, None, FixedDecoder(first), None) s.state = STATE_HALF_CLOSED_LOCAL # Provide the first two header frames. f = HeadersFrame(1) f.data = b'hi there!' f.flags.add('END_HEADERS') s.receive_frame(f) f = HeadersFrame(1) f.data = b'hi there again!' f.flags.add('END_HEADERS') s.receive_frame(f) # Provide the third. This one blows up. f = HeadersFrame(1) f.data = b'hi there again!' f.flags.add('END_STREAM') f.flags.add('END_HEADERS') with pytest.raises(ProtocolError): s.receive_frame(f)
def test_flow_control_manager_update_includes_padding(self): out_frames = [] in_frames = [] def send_cb(frame): out_frames.append(frame) def recv_cb(s): def inner(): s.receive_frame(in_frames.pop(0)) return inner start_window = 65535 s = Stream(1, send_cb, None, None, None, None, FlowControlManager(start_window)) s._recv_cb = recv_cb(s) s.state = STATE_HALF_CLOSED_LOCAL # Provide two data frames to read. f = DataFrame(1) f.data = b'hi there!' f.pad_length = 10 f.flags.add('END_STREAM') in_frames.append(f) data = s._read() assert data == b'hi there!' assert s._in_window_manager.window_size == start_window - f.pad_length - len( data) - 1
def test_can_receive_trailers(self): headers = [('a', 'b'), ('c', 'd'), (':status', '200')] trailers = [('e', 'f'), ('g', 'h')] s = Stream(1, None, None, None, None, FixedDecoder(headers), None) s.state = STATE_HALF_CLOSED_LOCAL # Provide the first HEADERS frame. f = HeadersFrame(1) f.data = b'hi there!' f.flags.add('END_HEADERS') s.receive_frame(f) assert s.response_headers == HTTPHeaderMap(headers) # Now, replace the dummy decoder to ensure we get a new header block. s._decoder = FixedDecoder(trailers) # Provide the trailers. f = HeadersFrame(1) f.data = b'hi there again!' f.flags.add('END_STREAM') f.flags.add('END_HEADERS') s.receive_frame(f) # Now, check the trailers. assert s.response_trailers == HTTPHeaderMap(trailers) # Confirm we closed the stream. assert s.state == STATE_CLOSED
def test_stream_reading_works(self): out_frames = [] in_frames = [] def send_cb(frame): out_frames.append(frame) def recv_cb(s): def inner(): s.receive_frame(in_frames.pop(0)) return inner s = Stream(1, send_cb, None, None, None) s._recv_cb = recv_cb(s) s.state = STATE_HALF_CLOSED_LOCAL # Provide a data frame to read. f = DataFrame(1) f.data = b'hi there!' f.flags.add('END_STREAM') in_frames.append(f) data = s._read() assert data == b'hi there!' assert len(out_frames) == 0
def test_flow_control_manager_update_includes_padding(self): out_frames = [] in_frames = [] def send_cb(frame): out_frames.append(frame) def recv_cb(s): def inner(): s.receive_frame(in_frames.pop(0)) return inner start_window = 65535 s = Stream(1, send_cb, None, None, None, None, FlowControlManager(start_window)) s._recv_cb = recv_cb(s) s.state = STATE_HALF_CLOSED_LOCAL # Provide two data frames to read. f = DataFrame(1) f.data = b'hi there!' f.pad_length = 10 f.flags.add('END_STREAM') in_frames.append(f) data = s._read() assert data == b'hi there!' assert s._in_window_manager.window_size == start_window - f.pad_length - len(data) - 1
def test_can_read_multiple_frames_from_streams(self): out_frames = [] in_frames = [] def send_cb(frame): out_frames.append(frame) def recv_cb(s): def inner(): s.receive_frame(in_frames.pop(0)) return inner s = Stream(1, send_cb, None, None, None) s._recv_cb = recv_cb(s) s.state = STATE_HALF_CLOSED_LOCAL # Provide two data frames to read. f = DataFrame(1) f.data = b'hi there!' in_frames.append(f) f = DataFrame(1) f.data = b'hi there again!' f.flags.add('END_STREAM') in_frames.append(f) data = s._read() assert data == b'hi there!hi there again!' assert len(out_frames) == 1 assert isinstance(out_frames[0], WindowUpdateFrame) assert out_frames[0].window_increment == len(b'hi there!')
def test_bytestrings_can_be_sent(self): def data_callback(frame): assert isinstance(frame, DataFrame) assert frame.data == b'Hi there!' assert frame.flags == set(['END_STREAM']) s = Stream(1, data_callback, None, NullEncoder, None) s.state = STATE_OPEN s.send_data(b'Hi there!', True) assert s.state == STATE_HALF_CLOSED_LOCAL assert s._out_flow_control_window == 65535 - len(b'Hi there!')
def test_file_objects_can_be_sent(self): def data_callback(frame): assert isinstance(frame, DataFrame) assert frame.data == b"Hi there!" assert frame.flags == set(["END_STREAM"]) s = Stream(1, data_callback, None, None, NullEncoder, None, None) s.state = STATE_OPEN s.send_data(BytesIO(b"Hi there!"), True) assert s.state == STATE_HALF_CLOSED_LOCAL assert s._out_flow_control_window == 65535 - len(b"Hi there!")
def test_reading_trailers_early_reads_all_data(self): in_frames = [] headers = [('a', 'b'), ('c', 'd'), (':status', '200')] trailers = [('e', 'f'), ('g', 'h')] def recv_cb(s): def inner(): s.receive_frame(in_frames.pop(0)) return inner s = Stream(1, None, None, None, None, FixedDecoder(headers), FlowControlManager(65535)) s._recv_cb = recv_cb(s) s.state = STATE_HALF_CLOSED_LOCAL # Provide the first HEADERS frame. f = HeadersFrame(1) f.data = b'hi there!' f.flags.add('END_HEADERS') in_frames.append(f) # Provide some data. f = DataFrame(1) f.data = b'testdata' in_frames.append(f) # Provide the trailers. f = HeadersFrame(1) f.data = b'hi there again!' f.flags.add('END_STREAM') f.flags.add('END_HEADERS') in_frames.append(f) # Begin by reading the first headers. assert s.getheaders() == HTTPHeaderMap(headers) # Now, replace the dummy decoder to ensure we get a new header block. s._decoder = FixedDecoder(trailers) # Ask for the trailers. This should also read the data frames. assert s.gettrailers() == HTTPHeaderMap(trailers) assert s.data == [b'testdata']
def test_long_bytestrings_are_split(self): frame_count = [0] recent_frame = [None] def data_callback(frame): assert isinstance(frame, DataFrame) assert len(frame.data) <= MAX_CHUNK frame_count[0] += 1 recent_frame[0] = frame data = b'test' * (MAX_CHUNK + 1) s = Stream(1, data_callback, None, NullEncoder, None) s.state = STATE_OPEN s.send_data(data, True) assert s.state == STATE_HALF_CLOSED_LOCAL assert recent_frame[0].flags == set(['END_STREAM']) assert frame_count[0] == 5 assert s._out_flow_control_window == 65535 - len(data)
def test_large_file_objects_are_broken_into_chunks(self): frame_count = [0] recent_frame = [None] def data_callback(frame): assert isinstance(frame, DataFrame) assert len(frame.data) <= MAX_CHUNK frame_count[0] += 1 recent_frame[0] = frame data = b"test" * (MAX_CHUNK + 1) s = Stream(1, data_callback, None, None, NullEncoder, None, None) s.state = STATE_OPEN s.send_data(BytesIO(data), True) assert s.state == STATE_HALF_CLOSED_LOCAL assert recent_frame[0].flags == set(["END_STREAM"]) assert frame_count[0] == 5 assert s._out_flow_control_window == 65535 - len(data)
def test_blocked_frames_cause_window_updates(self): out_frames = [] def send_cb(frame, *args): out_frames.append(frame) start_window = 65535 s = Stream(1, send_cb, None, None, None, None, FlowControlManager(start_window)) s._data_cb = send_cb s.state = STATE_HALF_CLOSED_LOCAL # Change the window size. s._in_window_manager.window_size = 60000 # Provide a BLOCKED frame. f = BlockedFrame(1) s.receive_frame(f) assert len(out_frames) == 1 assert out_frames[0].type == WindowUpdateFrame.type assert out_frames[0].window_increment == 5535
def test_partial_reads_from_streams(self): out_frames = [] in_frames = [] def send_cb(frame): out_frames.append(frame) def recv_cb(s): def inner(): s.receive_frame(in_frames.pop(0)) return inner s = Stream(1, send_cb, None, None, None, None, FlowControlManager(65535)) s._recv_cb = recv_cb(s) s.state = STATE_HALF_CLOSED_LOCAL # Provide two data frames to read. f = DataFrame(1) f.data = b'hi there!' in_frames.append(f) f = DataFrame(1) f.data = b'hi there again!' f.flags.add('END_STREAM') in_frames.append(f) # We'll get the entire first frame. data = s._read(4) assert data == b'hi there!' assert len(out_frames) == 1 # Now we'll get the entire of the second frame. data = s._read(4) assert data == b'hi there again!' assert len(out_frames) == 1 assert s.state == STATE_CLOSED
def test_can_read_single_frames_from_streams(self): out_frames = [] in_frames = [] def send_cb(frame, tolerate_peer_gone=False): out_frames.append(frame) def recv_cb(s): def inner(): s.receive_frame(in_frames.pop(0)) return inner s = Stream(1, send_cb, None, None, None, None, FlowControlManager(800)) s._recv_cb = recv_cb(s) s.state = STATE_HALF_CLOSED_LOCAL # Provide two data frames to read. f = DataFrame(1) f.data = b'hi there!' in_frames.append(f) f = DataFrame(1) f.data = b'hi there again!' f.flags.add('END_STREAM') in_frames.append(f) data = s._read_one_frame() assert data == b'hi there!' data = s._read_one_frame() assert data == b'hi there again!' data = s._read_one_frame() assert data is None data = s._read() assert data == b''
def test_partial_reads_from_streams(self): out_frames = [] in_frames = [] def send_cb(frame): out_frames.append(frame) def recv_cb(s): def inner(): s.receive_frame(in_frames.pop(0)) return inner s = Stream(1, send_cb, None, None, None, None, FlowControlManager(65535)) s._recv_cb = recv_cb(s) s.state = STATE_HALF_CLOSED_LOCAL # Provide two data frames to read. f = DataFrame(1) f.data = b"hi there!" in_frames.append(f) f = DataFrame(1) f.data = b"hi there again!" f.flags.add("END_STREAM") in_frames.append(f) # We'll get the entire first frame. data = s._read(4) assert data == b"hi there!" assert len(out_frames) == 1 # Now we'll get the entire of the second frame. data = s._read(4) assert data == b"hi there again!" assert len(out_frames) == 1 assert s.state == STATE_CLOSED