async def test_empty_request(loop): cs = ClientStream(loop=loop, cardinality=Cardinality.STREAM_UNARY, send_type=DummyRequest, recv_type=DummyReply) async with cs.client_stream as stream: await stream.send_request(end=True) events = cs.client_conn.to_server_transport.events() stream_ended = events[-1] assert isinstance(stream_ended, StreamEnded) stream_id = stream_ended.stream_id cs.client_conn.server_h2c.send_headers(stream_id, [ (':status', '200'), ('content-type', 'application/grpc+proto'), ]) cs.client_conn.server_h2c.send_data( stream_id, grpc_encode(DummyReply(value='pong'), DummyReply), ) cs.client_conn.server_h2c.send_headers(stream_id, [ ('grpc-status', str(Status.OK.value)), ], end_stream=True) cs.client_conn.server_flush() reply = await stream.recv_message() assert reply == DummyReply(value='pong')
async def test_client_receive_invalid(loop): cs = ClientStream(loop=loop, codec=JSONCodec()) with pytest.raises(GRPCError) as exc: async with cs.client_stream as stream: await stream.send_request() _, request_received = cs.client_conn.to_server_transport.events() content_type = dict(request_received.headers)['content-type'] assert content_type == 'application/grpc+json' cs.client_conn.server_h2c.send_headers( request_received.stream_id, [ (':status', '200'), ('content-type', 'application/grpc+proto'), ], ) cs.client_conn.server_h2c.send_data( request_received.stream_id, grpc_encode({'value': 'pong'}, None, JSONCodec()), ) cs.client_conn.server_h2c.send_headers( request_received.stream_id, [ ('grpc-status', str(grpclib.const.Status.OK.value)), ], end_stream=True, ) cs.client_conn.server_flush() await stream.recv_message() exc.match(r"Invalid content-type: 'application/grpc\+proto'")
async def test_no_end(loop): cs = ClientStream(loop=loop, send_type=DummyRequest, recv_type=DummyReply, cardinality=Cardinality.STREAM_UNARY) with pytest.raises(ProtocolError) as exc: async with cs.client_stream as stream: await stream.send_request() await stream.send_message(DummyRequest(value='ping')) # no end events = cs.client_conn.to_server_transport.events() stream_id = events[-1].stream_id cs.client_conn.server_h2c.send_headers( stream_id, [(':status', '200'), ('content-type', 'application/grpc+proto')], ) cs.client_conn.server_flush() await stream.recv_initial_metadata() cs.client_conn.server_h2c.send_data( stream_id, grpc_encode(DummyReply(value='pong'), DummyReply), ) cs.client_conn.server_flush() assert await stream.recv_message() == DummyReply(value='pong') await stream.recv_trailing_metadata() exc.match('Outgoing stream was not ended')
async def test_deadline_during_recv_trailing_metadata(loop): cs = ClientStream(loop=loop, timeout=0.01, send_type=DummyRequest, recv_type=DummyReply) with pytest.raises(ErrorDetected): with async_timeout.timeout(5) as safety_timeout: async with cs.client_stream as stream: await stream.send_message(DummyRequest(value='ping'), end=True) events = cs.client_conn.to_server_transport.events() stream_id = events[-1].stream_id cs.client_conn.server_h2c.send_headers( stream_id, [(':status', '200'), ('content-type', 'application/grpc+proto')], ) cs.client_conn.server_flush() await stream.recv_initial_metadata() cs.client_conn.server_h2c.send_data( stream_id, grpc_encode(DummyReply(value='pong'), DummyReply), ) cs.client_conn.server_flush() await stream.recv_message() try: await stream.recv_trailing_metadata() except asyncio.TimeoutError: if safety_timeout.expired: raise else: raise ErrorDetected()
async def test_client_receive_json(loop): cs = ClientStream(loop=loop, codec=JSONCodec()) async with cs.client_stream as stream: await stream.send_request() _, request_received = cs.client_conn.to_server_transport.events() await stream.send_message({'value': 'ping'}, end=True) content_type = dict(request_received.headers)['content-type'] assert content_type == 'application/grpc+json' cs.client_conn.server_h2c.send_headers( request_received.stream_id, [ (':status', '200'), ('content-type', 'application/grpc+json'), ], ) cs.client_conn.server_h2c.send_data( request_received.stream_id, grpc_encode({'value': 'pong'}, None, JSONCodec()), ) cs.client_conn.server_h2c.send_headers( request_received.stream_id, [ ('grpc-status', str(grpclib.const.Status.OK.value)), ], end_stream=True, ) cs.client_conn.server_flush() reply = await stream.recv_message() assert reply == {'value': 'pong'}
async def worker2(): cs = ClientStream(client_conn=client_conn, send_type=DummyRequest, recv_type=DummyReply) async with cs.client_stream as stream: await stream.send_message(DummyRequest(value='ping'), end=True) assert await stream.recv_message() == DummyReply(value='pong')
async def test_deadline_during_send_request(loop): cs = ClientStream(loop=loop, timeout=0.01, connect_time=1, send_type=DummyRequest, recv_type=DummyReply) with pytest.raises(ErrorDetected): with async_timeout.timeout(5) as safety_timeout: async with cs.client_stream as stream: try: await stream.send_request() except asyncio.TimeoutError: if safety_timeout.expired: raise else: raise ErrorDetected()
async def test_deadline_during_cancel(loop): cs = ClientStream(loop=loop, timeout=0.01, send_type=DummyRequest, recv_type=DummyReply) with pytest.raises(ErrorDetected): with async_timeout.timeout(5) as safety_timeout: async with cs.client_stream as stream: await stream.send_request() cs.client_conn.client_proto.connection.write_ready.clear() try: await stream.cancel() except asyncio.TimeoutError: if safety_timeout.expired: raise else: raise ErrorDetected()
async def test_deadline_during_recv_initial_metadata(loop): cs = ClientStream(loop=loop, timeout=0.01, send_type=DummyRequest, recv_type=DummyReply) with pytest.raises(ErrorDetected): with async_timeout.timeout(5) as safety_timeout: async with cs.client_stream as stream: await stream.send_message(DummyRequest(value='ping'), end=True) try: await stream.recv_initial_metadata() except asyncio.TimeoutError: if safety_timeout.expired: raise else: raise ErrorDetected()
async def test_no_messages_for_stream(loop): cs = ClientStream(loop=loop, cardinality=Cardinality.STREAM_STREAM, send_type=DummyRequest, recv_type=DummyReply) async with cs.client_stream as stream: await stream.send_request() await stream.end() events = cs.client_conn.to_server_transport.events() stream_id = events[-1].stream_id cs.client_conn.server_h2c.send_headers(stream_id, [ (':status', '200'), ('content-type', 'application/grpc+proto'), ]) cs.client_conn.server_h2c.send_headers(stream_id, [ ('grpc-status', str(Status.OK.value)), ], end_stream=True) cs.client_conn.server_flush()
async def test_empty_trailers_only_response(): cs = ClientStream(cardinality=Cardinality.UNARY_STREAM, send_type=DummyRequest, recv_type=DummyReply) async with cs.client_stream as stream: await stream.send_message(DummyRequest(value='ping'), end=True) events = cs.client_conn.to_server_transport.events() stream_id = events[-1].stream_id cs.client_conn.server_h2c.send_headers(stream_id, [ (':status', '200'), ('content-type', 'application/grpc+proto'), ('grpc-status', str(Status.OK.value)), ], end_stream=True) cs.client_conn.server_flush() reply = await stream.recv_message() assert reply is None await stream.recv_trailing_metadata() # should be noop
async def test_request_headers_with_deadline(loop): deadline = Mock() deadline.time_remaining.return_value = 0.1 cs = ClientStream(loop=loop, deadline=deadline) async with cs.client_stream as stream: await stream.send_request() events = cs.client_conn.to_server_transport.events() request_received = events[-1] assert request_received.headers == [ (':method', 'POST'), (':scheme', 'http'), (':path', '/foo/bar'), (':authority', 'test.com'), ('grpc-timeout', '100m'), ('te', 'trailers'), ('content-type', 'application/grpc+proto'), ('user-agent', USER_AGENT), ] await stream.cancel()
def client_stream_fixture(loop): return ClientStream(loop=loop, send_type=DummyRequest, recv_type=DummyReply)
def client_stream_fixture(): return ClientStream(send_type=DummyRequest, recv_type=DummyReply)