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_invalid_grpc_status_in_trailers(cs: ClientStream, grpc_status): with pytest.raises(ErrorDetected): async with cs.client_stream as stream: await stream.send_request() 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_h2c.send_data( stream_id, grpc_encode(DummyReply(value='pong'), DummyReply), ) cs.client_conn.server_h2c.send_headers(stream_id, [ ('grpc-status', grpc_status), ], end_stream=True) cs.client_conn.server_flush() await stream.recv_initial_metadata() await stream.recv_message() try: await stream.recv_trailing_metadata() except GRPCError as exc: assert exc assert exc.status == Status.UNKNOWN assert exc.message == ( 'Invalid grpc-status: {!r}'.format(grpc_status)) raise ErrorDetected()
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_unary_unary(cs: ClientStream): async with cs.client_stream as stream: await stream.send_message(DummyRequest(value='ping')) events = cs.client_conn.to_server_transport.events() event = events[-1] assert isinstance(event, StreamEnded) stream_id = event.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() assert await stream.recv_message() == DummyReply(value='pong')
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 test_server_receive_invalid(loop): handler = PingServiceHandler() mapping = handler.__mapping__() path = next(iter(mapping.keys())) ss = ServerStream(loop=loop, codec=JSONCodec(), path=path, content_type='application/grpc+invalid') ss.server_conn.client_h2c.send_data( ss.stream_id, grpc_encode({'value': 'ping'}, None, JSONCodec()), end_stream=True, ) ss.server_conn.client_flush() await grpclib.server.request_handler( handler.__mapping__(), ss.server_h2s, ss.server_conn.server_proto.processor.handler.headers, JSONCodec(), _DispatchServerEvents(), lambda: None, ) response_received, _ = ss.server_conn.to_client_transport.events() assert dict(response_received.headers)[':status'] == '415' assert dict(response_received.headers)['grpc-status'] == '2' assert dict(response_received.headers)['grpc-message'] == \ 'Unacceptable content-type header'
async def test_server_receive_json(loop): handler = PingServiceHandler() mapping = handler.__mapping__() path = next(iter(mapping.keys())) ss = ServerStream(loop=loop, codec=JSONCodec(), path=path, content_type='application/grpc+json') ss.server_conn.client_h2c.send_data( ss.stream_id, grpc_encode({'value': 'ping'}, None, JSONCodec()), end_stream=True, ) ss.server_conn.client_flush() await grpclib.server.request_handler( handler.__mapping__(), ss.server_h2s, ss.server_conn.server_proto.processor.handler.headers, JSONCodec(), _DispatchServerEvents(), lambda: None, ) response_received, data_received, trailers_received, _ = \ ss.server_conn.to_client_transport.events() assert dict(response_received.headers)[':status'] == '200' assert dict(response_received.headers)['content-type'] == \ 'application/grpc+json' reply = grpc_decode(data_received.data, None, JSONCodec()) assert reply == {'value': 'pong'} assert dict(trailers_received.headers)['grpc-status'] == '0'
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_non_ok_grpc_status_in_trailers(cs: ClientStream, grpc_message): with pytest.raises(ErrorDetected): async with cs.client_stream as stream: await stream.send_request() 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_data( stream_id, grpc_encode(DummyReply(value='pong'), DummyReply), ) headers = [ ('grpc-status', str(Status.DATA_LOSS.value)), ] if grpc_message is not None: headers.append(('grpc-message', grpc_message)) cs.client_conn.server_h2c.send_headers(stream_id, headers, end_stream=True) cs.client_conn.server_flush() await stream.recv_initial_metadata() await stream.recv_message() try: await stream.recv_trailing_metadata() except GRPCError as exc: assert exc assert exc.status == Status.DATA_LOSS assert exc.message == grpc_message raise ErrorDetected()
def send_response(stream_id): client_conn.server_h2c.send_headers( stream_id, [ (':status', '200'), ('content-type', 'application/grpc+proto'), ], ) client_conn.server_h2c.send_data( stream_id, grpc_encode(DummyReply(value='pong'), DummyReply), ) client_conn.server_h2c.send_headers( stream_id, [ ('grpc-status', str(Status.OK.value)), ], end_stream=True, ) client_conn.server_flush()
async def test_server_return_json(loop): ss = ServerStream(loop=loop, codec=JSONCodec()) ss.server_conn.client_h2c.send_data( ss.stream_id, grpc_encode({'value': 'ping'}, None, JSONCodec()), end_stream=True, ) ss.server_conn.client_flush() message = await ss.server_stream.recv_message() assert message == {'value': 'ping'} await ss.server_stream.send_initial_metadata() response_received, = ss.server_conn.to_client_transport.events() content_type = dict(response_received.headers)['content-type'] assert content_type == 'application/grpc+json' await ss.server_stream.send_message({'value': 'pong'}) data_received, = ss.server_conn.to_client_transport.events() reply = grpc_decode(data_received.data, None, JSONCodec()) assert reply == {'value': 'pong'}