async def test_call_rpc_error_awaited(self): class Interceptor(aio.UnaryUnaryClientInterceptor): async def intercept_unary_unary(self, continuation, client_call_details, request): call = await continuation(client_call_details, request) await call return call async with aio.insecure_channel(self._server_target, interceptors=[Interceptor() ]) as channel: multicallable = channel.unary_unary( '/grpc.testing.TestService/UnaryCallWithSleep', request_serializer=messages_pb2.SimpleRequest.SerializeToString, response_deserializer=messages_pb2.SimpleResponse.FromString) call = multicallable( messages_pb2.SimpleRequest(), timeout=_constants.UNARY_CALL_WITH_SLEEP_VALUE / 2) with self.assertRaises(aio.AioRpcError) as exception_context: await call self.assertTrue(call.done()) self.assertFalse(call.cancelled()) self.assertEqual(await call.code(), grpc.StatusCode.DEADLINE_EXCEEDED) self.assertEqual(await call.details(), 'Deadline Exceeded') self.assertEqual(await call.initial_metadata(), aio.Metadata()) self.assertEqual(await call.trailing_metadata(), aio.Metadata())
async def test_cancel_inside_interceptor_after_rpc_not_awaiting(self): class Interceptor(aio.UnaryUnaryClientInterceptor): async def intercept_unary_unary(self, continuation, client_call_details, request): call = await continuation(client_call_details, request) call.cancel() return call async with aio.insecure_channel(self._server_target, interceptors=[Interceptor() ]) as channel: multicallable = channel.unary_unary( '/grpc.testing.TestService/UnaryCall', request_serializer=messages_pb2.SimpleRequest.SerializeToString, response_deserializer=messages_pb2.SimpleResponse.FromString) call = multicallable(messages_pb2.SimpleRequest()) with self.assertRaises(asyncio.CancelledError): await call self.assertTrue(call.cancelled()) self.assertTrue(call.done()) self.assertEqual(await call.code(), grpc.StatusCode.CANCELLED) self.assertEqual(await call.details(), _LOCAL_CANCEL_DETAILS_EXPECTATION) self.assertEqual(await call.initial_metadata(), aio.Metadata()) self.assertEqual( await call.trailing_metadata(), aio.Metadata(), "When the raw response is None, empty metadata is returned")
async def test_call_ok_awaited(self): class Interceptor(aio.UnaryUnaryClientInterceptor): async def intercept_unary_unary(self, continuation, client_call_details, request): call = await continuation(client_call_details, request) await call return call async with aio.insecure_channel(self._server_target, interceptors=[Interceptor() ]) as channel: multicallable = channel.unary_unary( '/grpc.testing.TestService/UnaryCall', request_serializer=messages_pb2.SimpleRequest.SerializeToString, response_deserializer=messages_pb2.SimpleResponse.FromString) call = multicallable(messages_pb2.SimpleRequest()) response = await call self.assertTrue(call.done()) self.assertFalse(call.cancelled()) self.assertEqual(type(response), messages_pb2.SimpleResponse) self.assertEqual(await call.code(), grpc.StatusCode.OK) self.assertEqual(await call.details(), '') self.assertEqual(await call.initial_metadata(), aio.Metadata()) self.assertEqual(await call.trailing_metadata(), aio.Metadata())
async def test_compatibility_with_tuple(self): metadata_obj = aio.Metadata(('key', '42'), ('key-2', 'value')) self.assertEqual(metadata_obj, tuple(metadata_obj)) self.assertEqual(tuple(metadata_obj), metadata_obj) expected_sum = tuple(metadata_obj) + (('third', '3'), ) self.assertEqual(expected_sum, metadata_obj + (('third', '3'), )) self.assertEqual(expected_sum, metadata_obj + aio.Metadata( ('third', '3')))
async def test_intercepts(self): for interceptor_class in ( _StreamStreamInterceptorEmpty, _StreamStreamInterceptorWithRequestAndResponseIterator): with self.subTest(name=interceptor_class): interceptor = interceptor_class() channel = aio.insecure_channel(self._server_target, interceptors=[interceptor]) stub = test_pb2_grpc.TestServiceStub(channel) # Prepares the request request = messages_pb2.StreamingOutputCallRequest() request.response_parameters.append( messages_pb2.ResponseParameters( size=_RESPONSE_PAYLOAD_SIZE)) async def request_iterator(): for _ in range(_NUM_STREAM_REQUESTS): yield request call = stub.FullDuplexCall(request_iterator()) await call.wait_for_connection() response_cnt = 0 async for response in call: response_cnt += 1 self.assertIsInstance( response, messages_pb2.StreamingOutputCallResponse) self.assertEqual(_RESPONSE_PAYLOAD_SIZE, len(response.payload.body)) self.assertEqual(response_cnt, _NUM_STREAM_RESPONSES) self.assertEqual(await call.code(), grpc.StatusCode.OK) self.assertEqual(await call.initial_metadata(), aio.Metadata()) self.assertEqual(await call.trailing_metadata(), aio.Metadata()) self.assertEqual(await call.details(), '') self.assertEqual(await call.debug_error_string(), '') self.assertEqual(call.cancel(), False) self.assertEqual(call.cancelled(), False) self.assertEqual(call.done(), True) interceptor.assert_in_final_state(self) await channel.close()
async def test_call_initial_metadata_multiple_waiters(self): call = self._stub.UnaryCall(messages_pb2.SimpleRequest()) async def coro(): return await call.initial_metadata() task1 = self.loop.create_task(coro()) task2 = self.loop.create_task(coro()) await call expected = [aio.Metadata() for _ in range(2)] self.assertEqual(expected, await asyncio.gather(*[task1, task2]))
async def intercept_unary_unary(self, continuation, client_call_details, request): new_metadata = aio.Metadata(*client_call_details.metadata, *_INITIAL_METADATA_TO_INJECT) new_details = aio.ClientCallDetails( method=client_call_details.method, timeout=client_call_details.timeout, metadata=new_metadata, credentials=client_call_details.credentials, wait_for_ready=client_call_details.wait_for_ready, ) return await continuation(new_details, request)
async def test_multiple_interceptors_request_iterator(self): for interceptor_class in (_StreamUnaryInterceptorEmpty, _StreamUnaryInterceptorWithRequestIterator): with self.subTest(name=interceptor_class): interceptors = [interceptor_class(), interceptor_class()] channel = aio.insecure_channel(self._server_target, interceptors=interceptors) stub = test_pb2_grpc.TestServiceStub(channel) payload = messages_pb2.Payload(body=b'\0' * _REQUEST_PAYLOAD_SIZE) request = messages_pb2.StreamingInputCallRequest( payload=payload) async def request_iterator(): for _ in range(_NUM_STREAM_REQUESTS): yield request call = stub.StreamingInputCall(request_iterator()) response = await call self.assertEqual(_NUM_STREAM_REQUESTS * _REQUEST_PAYLOAD_SIZE, response.aggregated_payload_size) self.assertEqual(await call.code(), grpc.StatusCode.OK) self.assertEqual(await call.initial_metadata(), aio.Metadata()) self.assertEqual(await call.trailing_metadata(), aio.Metadata()) self.assertEqual(await call.details(), '') self.assertEqual(await call.debug_error_string(), '') self.assertEqual(call.cancel(), False) self.assertEqual(call.cancelled(), False) self.assertEqual(call.done(), True) for interceptor in interceptors: interceptor.assert_in_final_state(self) await channel.close()
async def test_sync_unary_unary_metadata(self): metadata = (('unique', 'key-42'),) @grpc.unary_unary_rpc_method_handler def metadata_unary_unary(request: bytes, context: grpc.ServicerContext): context.send_initial_metadata(metadata) return request self._adhoc_handlers.set_adhoc_handler(metadata_unary_unary) call = self._async_channel.unary_unary(_common.ADHOC_METHOD)(_REQUEST) self.assertTrue( _common.seen_metadata(aio.Metadata(*metadata), await call.initial_metadata()))
async def test_apply_different_interceptors_by_metadata(self): record = [] conditional_interceptor = _filter_server_interceptor( lambda x: ('secret', '42') in x.invocation_metadata, _LoggingInterceptor('log3', record)) server_target, _ = await start_test_server(interceptors=( _LoggingInterceptor('log1', record), conditional_interceptor, _LoggingInterceptor('log2', record), )) async with aio.insecure_channel(server_target) as channel: multicallable = channel.unary_unary( '/grpc.testing.TestService/UnaryCall', request_serializer=messages_pb2.SimpleRequest. SerializeToString, response_deserializer=messages_pb2.SimpleResponse.FromString) metadata = aio.Metadata(('key', 'value'), ) call = multicallable(messages_pb2.SimpleRequest(), metadata=metadata) await call self.assertSequenceEqual([ 'log1:intercept_service', 'log2:intercept_service', ], record) record.clear() metadata = aio.Metadata(('key', 'value'), ('secret', '42')) call = multicallable(messages_pb2.SimpleRequest(), metadata=metadata) await call self.assertSequenceEqual([ 'log1:intercept_service', 'log3:intercept_service', 'log2:intercept_service', ], record)
async def test_call_initial_metadata_cancelable(self): coro_started = asyncio.Event() call = self._stub.UnaryCall(messages_pb2.SimpleRequest()) async def coro(): coro_started.set() await call.initial_metadata() task = self.loop.create_task(coro()) await coro_started.wait() task.cancel() # Test that initial metadata can still be asked thought # a cancellation happened with the previous task self.assertEqual(aio.Metadata(), await call.initial_metadata())
async def _custom_metadata(stub: test_pb2_grpc.TestServiceStub): initial_metadata_value = "test_initial_metadata_value" trailing_metadata_value = b"\x0a\x0b\x0a\x0b\x0a\x0b" metadata = aio.Metadata( (_INITIAL_METADATA_KEY, initial_metadata_value), (_TRAILING_METADATA_KEY, trailing_metadata_value), ) async def _validate_metadata(call): initial_metadata = await call.initial_metadata() if initial_metadata[_INITIAL_METADATA_KEY] != initial_metadata_value: raise ValueError('expected initial metadata %s, got %s' % (initial_metadata_value, initial_metadata[_INITIAL_METADATA_KEY])) trailing_metadata = await call.trailing_metadata() if trailing_metadata[_TRAILING_METADATA_KEY] != trailing_metadata_value: raise ValueError('expected trailing metadata %s, got %s' % (trailing_metadata_value, trailing_metadata[_TRAILING_METADATA_KEY])) # Testing with UnaryCall request = messages_pb2.SimpleRequest( response_type=messages_pb2.COMPRESSABLE, response_size=1, payload=messages_pb2.Payload(body=b'\x00')) call = stub.UnaryCall(request, metadata=metadata) await _validate_metadata(call) # Testing with FullDuplexCall call = stub.FullDuplexCall(metadata=metadata) request = messages_pb2.StreamingOutputCallRequest( response_type=messages_pb2.COMPRESSABLE, response_parameters=(messages_pb2.ResponseParameters(size=1), )) await call.write(request) await call.read() await call.done_writing() await _validate_metadata(call)
async def test_call_trailing_metadata_awaitable(self): call = self._stub.UnaryCall(messages_pb2.SimpleRequest()) self.assertEqual(aio.Metadata(), await call.trailing_metadata())
import asyncio import logging import unittest import grpc from grpc.experimental import aio from tests_aio.unit._test_server import start_test_server, _INITIAL_METADATA_KEY, _TRAILING_METADATA_KEY from tests_aio.unit import _constants from tests_aio.unit import _common from tests_aio.unit._test_base import AioTestBase from src.proto.grpc.testing import messages_pb2, test_pb2_grpc _LOCAL_CANCEL_DETAILS_EXPECTATION = 'Locally cancelled by application!' _INITIAL_METADATA_TO_INJECT = aio.Metadata( (_INITIAL_METADATA_KEY, 'extra info'), (_TRAILING_METADATA_KEY, b'\x13\x37'), ) _TIMEOUT_CHECK_IF_CALLBACK_WAS_CALLED = 1.0 class TestUnaryUnaryClientInterceptor(AioTestBase): async def setUp(self): self._server_target, self._server = await start_test_server() async def tearDown(self): await self._server.stop(None) def test_invalid_interceptor(self): class InvalidInterceptor:
from tests_aio.unit import _common _TEST_CLIENT_TO_SERVER = '/test/TestClientToServer' _TEST_SERVER_TO_CLIENT = '/test/TestServerToClient' _TEST_TRAILING_METADATA = '/test/TestTrailingMetadata' _TEST_ECHO_INITIAL_METADATA = '/test/TestEchoInitialMetadata' _TEST_GENERIC_HANDLER = '/test/TestGenericHandler' _TEST_UNARY_STREAM = '/test/TestUnaryStream' _TEST_STREAM_UNARY = '/test/TestStreamUnary' _TEST_STREAM_STREAM = '/test/TestStreamStream' _REQUEST = b'\x00\x00\x00' _RESPONSE = b'\x01\x01\x01' _INITIAL_METADATA_FROM_CLIENT_TO_SERVER = aio.Metadata( ('client-to-server', 'question'), ('client-to-server-bin', b'\x07\x07\x07'), ) _INITIAL_METADATA_FROM_SERVER_TO_CLIENT = aio.Metadata( ('server-to-client', 'answer'), ('server-to-client-bin', b'\x06\x06\x06'), ) _TRAILING_METADATA = aio.Metadata( ('a-trailing-metadata', 'stack-trace'), ('a-trailing-metadata-bin', b'\x05\x05\x05'), ) _INITIAL_METADATA_FOR_GENERIC_HANDLER = aio.Metadata( ('a-must-have-key', 'secret'), ) _INVALID_METADATA_TEST_CASES = ( ( TypeError,
# distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests AioRpcError class.""" import logging import unittest import grpc from grpc.experimental import aio from grpc.aio._call import AioRpcError from tests_aio.unit._test_base import AioTestBase _TEST_INITIAL_METADATA = aio.Metadata( ('initial metadata key', 'initial metadata value')) _TEST_TRAILING_METADATA = aio.Metadata( ('trailing metadata key', 'trailing metadata value')) _TEST_DEBUG_ERROR_STRING = '{This is a debug string}' class TestAioRpcError(unittest.TestCase): def test_attributes(self): aio_rpc_error = AioRpcError( grpc.StatusCode.CANCELLED, initial_metadata=_TEST_INITIAL_METADATA, trailing_metadata=_TEST_TRAILING_METADATA, details="details", debug_error_string=_TEST_DEBUG_ERROR_STRING) self.assertEqual(aio_rpc_error.code(), grpc.StatusCode.CANCELLED) self.assertEqual(aio_rpc_error.details(), 'details')