async def test_async_gen_for_stream_stream_request(): some_things = ["cake", "cricket", "coral reef"] more_things = [ "ball", "that", "56kmodem", "liberal humanism", "cheesesticks" ] expected_things = (*some_things, *more_things) async with ChannelFor([ThingService()]) as channel: client = ThingServiceClient(channel) # Use an AsyncChannel to decouple sending and recieving, it'll send some_things # immediately and we'll use it to send more_things later, after recieving some # results request_chan = AsyncChannel() send_initial_requests = asyncio.ensure_future( request_chan.send_from( GetThingRequest(name) for name in some_things)) response_index = 0 async for response in client.get_different_things(request_chan): assert response.name == expected_things[response_index] assert response.version == response_index + 1 response_index += 1 if more_things: # Send some more requests as we receive responses to be sure coordination of # send/receive events doesn't matter await request_chan.send(GetThingRequest(more_things.pop(0))) elif not send_initial_requests.done(): # Make sure the sending task it completed await send_initial_requests else: # No more things to send make sure channel is closed request_chan.close() assert response_index == len( expected_things), "Didn't receive all expected responses"
async def test_append(self) -> None: handler = Handler(AppendRequest, [AppendResponse()]) outfile = StringIO() args = Namespace(token=None, token_file=None, username='******', sender=None, recipient=None, mailbox='INBOX', data=BytesIO(b'test data'), flags=['\\Flagged', '\\Seen'], timestamp=1234567890) async with ChannelFor([handler]) as channel: command = AppendCommand(args, channel) code = await command(outfile) request = handler.request assert 0 == code assert b'test data' == request.data assert 1234567890.0 == request.when assert ['\\Flagged', '\\Seen'] == request.flags assert 'testuser' == request.user assert not request.HasField('sender') assert not request.HasField('recipient') assert 'INBOX' == request.mailbox assert '2.0.0 Message delivered\n' == outfile.getvalue()
async def test_server_stream(): cf = ChannelFor([WorkingDummyService()]) async with cf as channel: stub = DummyServiceStub(channel) handler, = cf._server._handlers async with stub.UnaryUnary.open() as stream: await stream.send_request() while not handler._tasks: await asyncio.sleep(0.001) server_stream, = handler._tasks.keys() _is_recent(server_stream.created) assert server_stream.data_sent == 0 assert server_stream.data_received == 0 assert server_stream.connection.messages_sent == 0 assert server_stream.connection.messages_received == 0 assert server_stream.connection.last_message_sent is None assert server_stream.connection.last_message_received is None await stream.send_message(DummyRequest(value='whatever'), end=True) await asyncio.sleep(0.01) assert server_stream.data_sent > 0 assert server_stream.data_received > 0 assert server_stream.connection.messages_sent == 1 assert server_stream.connection.messages_received == 1 _is_recent(server_stream.connection.last_data_sent) _is_recent(server_stream.connection.last_data_received) _is_recent(server_stream.connection.last_message_sent) _is_recent(server_stream.connection.last_message_received) reply = await stream.recv_message() assert reply == DummyReply(value='test')
async def test_watch_service_status(loop): svc = Service() s1 = ServiceStatus(loop=loop) s2 = ServiceStatus(loop=loop) health = Health({svc: [s1, s2]}) async with ChannelFor([svc, health]) as channel: stub = HealthStub(channel) async with stub.Watch.open() as stream: await stream.send_message( HealthCheckRequest(service=Service.__name__, )) assert await stream.recv_message() == HealthCheckResponse( status=HealthCheckResponse.UNKNOWN, ) s1.set(True) assert await stream.recv_message() == HealthCheckResponse( status=HealthCheckResponse.NOT_SERVING, ) s2.set(True) assert await stream.recv_message() == HealthCheckResponse( status=HealthCheckResponse.SERVING, ) s1.set(False) assert await stream.recv_message() == HealthCheckResponse( status=HealthCheckResponse.NOT_SERVING, ) s1.set(True) assert await stream.recv_message() == HealthCheckResponse( status=HealthCheckResponse.SERVING, ) # check that there are no unnecessary messages if status isn't # changed s1.set(True) try: with async_timeout.timeout(0.01): assert not await stream.recv_message() except asyncio.TimeoutError: pass await stream.cancel()
async def test_ping_failure(self) -> None: handler = Handler(PingRequest, [PingResponse(result=Result(code=FAILURE))]) args = Namespace(token=None, token_file=None) async with ChannelFor([handler]) as channel: command = PingCommand(args, channel) code = await command(StringIO()) assert 1 == code
async def test_service_call_mutable_defaults(mocker): async with ChannelFor([ThingService()]) as channel: client = ThingServiceClient(channel) spy = mocker.spy(client, "_unary_unary") await _test_client(client) comments = spy.call_args_list[-1].args[1].comments await _test_client(client) assert spy.call_args_list[-1].args[1].comments is not comments
async def test_check_zero_checks(): svc = Service() health = Health({svc: []}) async with ChannelFor([svc, health]) as channel: stub = HealthStub(channel) response = await stub.Check(HealthCheckRequest(service=SERVICE_NAME)) assert response == HealthCheckResponse( status=HealthCheckResponse.SERVING, )
async def test_service_call_lower_level_with_overrides(): THING_TO_DO = "get milk" # Setting deadline deadline = grpclib.metadata.Deadline.from_timeout(22) metadata = {"authorization": "12345"} kwarg_deadline = grpclib.metadata.Deadline.from_timeout(28) kwarg_metadata = {"authorization": "12345"} async with ChannelFor([ ThingService(test_hook=_assert_request_meta_received( deadline, metadata), ) ]) as channel: client = ThingServiceClient(channel, deadline=deadline, metadata=metadata) response = await client._unary_unary( "/service.Test/DoThing", DoThingRequest(THING_TO_DO), DoThingResponse, deadline=kwarg_deadline, metadata=kwarg_metadata, ) assert response.names == [THING_TO_DO] # Setting timeout timeout = 99 deadline = grpclib.metadata.Deadline.from_timeout(timeout) metadata = {"authorization": "12345"} kwarg_timeout = 9000 kwarg_deadline = grpclib.metadata.Deadline.from_timeout(kwarg_timeout) kwarg_metadata = {"authorization": "09876"} async with ChannelFor([ ThingService(test_hook=_assert_request_meta_received( kwarg_deadline, kwarg_metadata), ) ]) as channel: client = ThingServiceClient(channel, deadline=deadline, metadata=metadata) response = await client._unary_unary( "/service.Test/DoThing", DoThingRequest(THING_TO_DO), DoThingResponse, timeout=kwarg_timeout, metadata=kwarg_metadata, ) assert response.names == [THING_TO_DO]
async def test_check_unknown_service(): svc = Service() health = Health({svc: []}) async with ChannelFor([svc, health]) as channel: stub = HealthStub(channel) with pytest.raises(GRPCError) as err: await stub.Check(HealthCheckRequest(service='Unknown')) assert err.value.status == Status.NOT_FOUND
async def test_check_not_serving(self) -> None: handler = Handler(HealthCheckRequest, [HealthCheckResponse( status=HealthCheckResponse.ServingStatus.NOT_SERVING)]) args = Namespace(token=None, token_file=None) async with ChannelFor([handler]) as channel: command = CheckCommand(args, channel) code = await command(StringIO()) assert 1 == code
async def test_service_call_lower_level_with_overrides(): ITERATIONS = 99 # Setting deadline deadline = grpclib.metadata.Deadline.from_timeout(22) metadata = {"authorization": "12345"} kwarg_deadline = grpclib.metadata.Deadline.from_timeout(28) kwarg_metadata = {"authorization": "12345"} async with ChannelFor([ ExampleService(test_hook=_get_server_side_test(deadline, metadata)) ]) as channel: stub = ExampleServiceStub(channel, deadline=deadline, metadata=metadata) response = await stub._unary_unary( "/service.ExampleService/DoThing", DoThingRequest(ITERATIONS), DoThingResponse, deadline=kwarg_deadline, metadata=kwarg_metadata, ) assert response.successful_iterations == ITERATIONS # Setting timeout timeout = 99 deadline = grpclib.metadata.Deadline.from_timeout(timeout) metadata = {"authorization": "12345"} kwarg_timeout = 9000 kwarg_deadline = grpclib.metadata.Deadline.from_timeout(kwarg_timeout) kwarg_metadata = {"authorization": "09876"} async with ChannelFor([ ExampleService(test_hook=_get_server_side_test( kwarg_deadline, kwarg_metadata)) ]) as channel: stub = ExampleServiceStub(channel, deadline=deadline, metadata=metadata) response = await stub._unary_unary( "/service.ExampleService/DoThing", DoThingRequest(ITERATIONS), DoThingResponse, timeout=kwarg_timeout, metadata=kwarg_metadata, ) assert response.successful_iterations == ITERATIONS
async def test_async_gen_for_unary_stream_request(): thing_name = "my milkshakes" async with ChannelFor([ThingService()]) as channel: client = ThingServiceClient(channel) expected_versions = [5, 4, 3, 2, 1] async for response in client.get_thing_versions(name=thing_name): assert response.name == thing_name assert response.version == expected_versions.pop()
async def test_ping(self) -> None: handler = Handler( PingRequest, [PingResponse(pymap_version='test1', pymap_admin_version='test2')]) args = Namespace(token=None, token_file=None) async with ChannelFor([handler]) as channel: command = PingCommand(args, channel) code = await command(StringIO()) assert 0 == code
async def test_grpc_controller_shutdown(): shutdown_event = asyncio.Event() service = grpc_controller.GRPCController(shutdown_event=shutdown_event) async with ChannelFor([service]) as channel: stub = grpc_controller_grpc.GRPCControllerStub(channel) response = await stub.Shutdown(grpc_controller_pb2.Empty()) assert response == grpc_controller_pb2.Empty() assert shutdown_event.is_set()
async def test_failure(): class FailingService(DummyService): async def UnaryUnary(self, stream): raise GRPCError(Status.FAILED_PRECONDITION) async with ChannelFor([FailingService()]) as channel: stub = DummyServiceStub(channel) with pytest.raises(GRPCError) as err: await stub.UnaryUnary(DummyRequest(value='ping')) assert err.value.status is Status.FAILED_PRECONDITION
async def test_service_call_with_upfront_request_params(): # Setting deadline deadline = grpclib.metadata.Deadline.from_timeout(22) metadata = {"authorization": "12345"} async with ChannelFor([ ExampleService(test_hook=_get_server_side_test(deadline, metadata)) ]) as channel: await _test_stub( ExampleServiceStub(channel, deadline=deadline, metadata=metadata)) # Setting timeout timeout = 99 deadline = grpclib.metadata.Deadline.from_timeout(timeout) metadata = {"authorization": "12345"} async with ChannelFor([ ExampleService(test_hook=_get_server_side_test(deadline, metadata)) ]) as channel: await _test_stub( ExampleServiceStub(channel, timeout=timeout, metadata=metadata))
async def test_check_unknown_service(): svc = Service() health = Health({svc: []}) async with ChannelFor([svc, health]) as channel: stub = HealthStub(channel) with pytest.raises(GRPCError): await stub.Check(HealthCheckRequest()) with pytest.raises(GRPCError): await stub.Check(HealthCheckRequest(service='Unknown'))
async def test_check_service_status(v1, v2, status): svc = Service() s1 = ServiceStatus() s2 = ServiceStatus() health = Health({svc: [s1, s2]}) async with ChannelFor([svc, health]) as channel: stub = HealthStub(channel) s1.set(v1) s2.set(v2) response = await stub.Check(HealthCheckRequest(service=SERVICE_NAME)) assert response == HealthCheckResponse(status=status)
async def test_set_user_bad_param(self) -> None: handler = Handler(SetUserRequest, [UserResponse(username='******')]) outfile = StringIO() args = Namespace(token=None, token_file=None, username='******', no_password=True, params=['identity=test', 'badparam']) async with ChannelFor([handler]) as channel: command = SetUserCommand(args, channel) with pytest.raises(ValueError): await command(outfile)
async def test_delete_user(self) -> None: handler = Handler(DeleteUserRequest, [UserResponse(username='******')]) outfile = StringIO() args = Namespace(token=None, token_file=None, username='******') async with ChannelFor([handler]) as channel: command = DeleteUserCommand(args, channel) code = await command(outfile) request = handler.request assert 0 == code assert request is not None assert 'user1' == request.user assert 'username: "******"\n\n' == outfile.getvalue()
async def test_service_call_with_upfront_request_params(): # Setting deadline deadline = grpclib.metadata.Deadline.from_timeout(22) metadata = {"authorization": "12345"} async with ChannelFor([ ThingService(test_hook=_assert_request_meta_received( deadline, metadata), ) ]) as channel: await _test_client( ThingServiceClient(channel, deadline=deadline, metadata=metadata)) # Setting timeout timeout = 99 deadline = grpclib.metadata.Deadline.from_timeout(timeout) metadata = {"authorization": "12345"} async with ChannelFor([ ThingService(test_hook=_assert_request_meta_received( deadline, metadata), ) ]) as channel: await _test_client( ThingServiceClient(channel, timeout=timeout, metadata=metadata))
async def test_trailer_only_error_unary_unary( mocker, handler_trailer_only_unauthenticated): service = ThingService() mocker.patch.object( service, "do_thing", side_effect=handler_trailer_only_unauthenticated, autospec=True, ) async with ChannelFor([service]) as channel: with pytest.raises(grpclib.exceptions.GRPCError) as e: await ThingServiceClient(channel).do_thing(name="something") assert e.value.status == grpclib.Status.UNAUTHENTICATED
async def test_concurrent_connect(loop): count = 5 reqs = [DummyRequest(value='ping') for _ in range(count)] reps = [DummyReply(value='pong') for _ in range(count)] channel = Channel() stub = DummyServiceStub(channel) async with ChannelFor([DummyService()]) as _channel: with patch.object(loop, 'create_connection') as po: po.side_effect = _create_connection_gen(_channel._protocol) tasks = [loop.create_task(stub.UnaryUnary(req)) for req in reqs] replies = await asyncio.gather(*tasks) assert replies == reps po.assert_called_once_with(ANY, '127.0.0.1', 50051, ssl=None)
async def test_check_service_check(loop, v1, v2, status): svc = Service() c1 = Check() c2 = Check() health = Health({svc: [ ServiceCheck(c1, check_ttl=0), ServiceCheck(c2, check_ttl=0), ]}) async with ChannelFor([svc, health]) as channel: stub = HealthStub(channel) c1.__current_status__ = v1 c2.__current_status__ = v2 response = await stub.Check(HealthCheckRequest(service=SERVICE_NAME)) assert response == HealthCheckResponse(status=status)
async def test_send_trailing_metadata(loop, svc_type): async with ChannelFor( [svc_type()], codec=ProtoCodec(), status_details_codec=ProtoStatusDetailsCodec(), ) as channel: stub = DummyServiceStub(channel) with pytest.raises(GRPCError) as error: await stub.UnaryUnary(DummyRequest(value='ping')) assert error.value.status is Status.DATA_LOSS assert error.value.message == 'Some data loss occurred' assert error.value.details == [ Help(links=[Help.Link(url='https://example.com')]), ]
async def test_watch_unknown_service(request): svc = Service() health = Health({svc: []}) async with ChannelFor([svc, health]) as channel: stub = HealthStub(channel) async with stub.Watch.open() as stream: await stream.send_message(request, end=True) assert await stream.recv_message() == HealthCheckResponse( status=HealthCheckResponse.SERVICE_UNKNOWN, ) try: with async_timeout.timeout(0.01): assert not await stream.recv_message() except asyncio.TimeoutError: pass await stream.cancel()
async def main(): svc = Service() loop = asyncio.get_event_loop() test_check = ServiceCheck(test, loop=loop, check_ttl=5) health = Health({svc: [test_check]}) print(svc) print(health) async with ChannelFor([svc, health]) as channel: print(channel) stub = HealthStub(channel) print(stub) async with stub.Watch.open() as stream: await stream.send_message( HealthCheckRequest(service=Service.__name__, )) await stream.recv_message()
async def test_client_stream(): async with ChannelFor([WorkingDummyService()]) as channel: proto = await channel.__connect__() stub = DummyServiceStub(channel) async with stub.UnaryUnary.open() as stream: assert proto.connection.streams_started == 0 assert proto.connection.streams_succeeded == 0 assert proto.connection.streams_failed == 0 assert proto.connection.last_stream_created is None await stream.send_request() _is_recent(stream._stream.created) assert proto.connection.streams_started == 1 assert proto.connection.streams_succeeded == 0 assert proto.connection.streams_failed == 0 _is_recent(proto.connection.last_stream_created) assert stream._messages_sent == 0 assert stream._stream.data_sent == 0 assert proto.connection.messages_sent == 0 assert proto.connection.data_sent == 0 assert proto.connection.last_message_sent is None await stream.send_message(DummyRequest(value='whatever'), end=True) assert stream._messages_sent == 1 assert stream._stream.data_sent > 0 assert proto.connection.messages_sent == 1 assert proto.connection.data_sent > 0 _is_recent(proto.connection.last_message_sent) _is_recent(proto.connection.last_data_sent) assert stream._messages_received == 0 assert stream._stream.data_received == 0 assert proto.connection.messages_received == 0 assert proto.connection.data_received == 0 assert proto.connection.last_message_received is None reply = await stream.recv_message() assert stream._messages_received == 1 assert stream._stream.data_received > 0 assert proto.connection.messages_received == 1 assert proto.connection.data_received > 0 _is_recent(proto.connection.last_message_received) _is_recent(proto.connection.last_data_received) assert proto.connection.streams_started == 1 assert proto.connection.streams_succeeded == 1 assert proto.connection.streams_failed == 0 assert reply == DummyReply(value='test')
async def test_channel_calls_failed(): async with ChannelFor([FailingDummyService()]) as channel: stub = DummyServiceStub(channel) assert channel._calls_started == 0 assert channel._calls_succeeded == 0 assert channel._calls_failed == 0 assert channel._last_call_started is None with pytest.raises(GRPCError, match='Internal Server Error'): await stub.UnaryUnary(DummyRequest(value='whatever')) assert channel._calls_started == 1 assert channel._calls_succeeded == 0 assert channel._calls_failed == 1 _is_recent(channel._last_call_started)
async def test_channel_calls_succeeded(): async with ChannelFor([WorkingDummyService()]) as channel: stub = DummyServiceStub(channel) assert channel._calls_started == 0 assert channel._calls_succeeded == 0 assert channel._calls_failed == 0 assert channel._last_call_started is None reply = await stub.UnaryUnary(DummyRequest(value='whatever')) assert channel._calls_started == 1 assert channel._calls_succeeded == 1 assert channel._calls_failed == 0 _is_recent(channel._last_call_started) assert reply == DummyReply(value='test')