1# Copyright 2016 gRPC authors. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14"""Tests of grpc_reflection.v1alpha.reflection.""" 15 16import logging 17import unittest 18 19from google.protobuf import descriptor_pb2 20import grpc 21from grpc.experimental import aio 22from grpc_reflection.v1alpha import reflection 23from grpc_reflection.v1alpha import reflection_pb2 24from grpc_reflection.v1alpha import reflection_pb2_grpc 25 26from src.proto.grpc.testing import empty_pb2 27from src.proto.grpc.testing.proto2 import empty2_extensions_pb2 28from src.proto.grpc.testing.proto2 import empty2_pb2 29from tests_aio.unit._test_base import AioTestBase 30 31_EMPTY_PROTO_FILE_NAME = "src/proto/grpc/testing/empty.proto" 32_EMPTY_PROTO_SYMBOL_NAME = "grpc.testing.Empty" 33_SERVICE_NAMES = ( 34 "Angstrom", 35 "Bohr", 36 "Curie", 37 "Dyson", 38 "Einstein", 39 "Feynman", 40 "Galilei", 41) 42_EMPTY_EXTENSIONS_SYMBOL_NAME = "grpc.testing.proto2.EmptyWithExtensions" 43_EMPTY_EXTENSIONS_NUMBERS = ( 44 124, 45 125, 46 126, 47 127, 48 128, 49) 50 51 52def _file_descriptor_to_proto(descriptor): 53 proto = descriptor_pb2.FileDescriptorProto() 54 descriptor.CopyToProto(proto) 55 return proto.SerializeToString() 56 57 58class ReflectionServicerTest(AioTestBase): 59 async def setUp(self): 60 self._server = aio.server() 61 reflection.enable_server_reflection(_SERVICE_NAMES, self._server) 62 port = self._server.add_insecure_port("[::]:0") 63 await self._server.start() 64 65 self._channel = aio.insecure_channel("localhost:%d" % port) 66 self._stub = reflection_pb2_grpc.ServerReflectionStub(self._channel) 67 68 async def tearDown(self): 69 await self._server.stop(None) 70 await self._channel.close() 71 72 async def test_file_by_name(self): 73 requests = ( 74 reflection_pb2.ServerReflectionRequest( 75 file_by_filename=_EMPTY_PROTO_FILE_NAME 76 ), 77 reflection_pb2.ServerReflectionRequest( 78 file_by_filename="i-donut-exist" 79 ), 80 ) 81 responses = [] 82 async for response in self._stub.ServerReflectionInfo(iter(requests)): 83 responses.append(response) 84 expected_responses = ( 85 reflection_pb2.ServerReflectionResponse( 86 valid_host="", 87 file_descriptor_response=reflection_pb2.FileDescriptorResponse( 88 file_descriptor_proto=( 89 _file_descriptor_to_proto(empty_pb2.DESCRIPTOR), 90 ) 91 ), 92 original_request=requests[0], 93 ), 94 reflection_pb2.ServerReflectionResponse( 95 valid_host="", 96 error_response=reflection_pb2.ErrorResponse( 97 error_code=grpc.StatusCode.NOT_FOUND.value[0], 98 error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), 99 ), 100 original_request=requests[1], 101 ), 102 ) 103 self.assertSequenceEqual(expected_responses, responses) 104 105 async def test_file_by_symbol(self): 106 requests = ( 107 reflection_pb2.ServerReflectionRequest( 108 file_containing_symbol=_EMPTY_PROTO_SYMBOL_NAME 109 ), 110 reflection_pb2.ServerReflectionRequest( 111 file_containing_symbol="i.donut.exist.co.uk.org.net.me.name.foo" 112 ), 113 ) 114 responses = [] 115 async for response in self._stub.ServerReflectionInfo(iter(requests)): 116 responses.append(response) 117 expected_responses = ( 118 reflection_pb2.ServerReflectionResponse( 119 valid_host="", 120 file_descriptor_response=reflection_pb2.FileDescriptorResponse( 121 file_descriptor_proto=( 122 _file_descriptor_to_proto(empty_pb2.DESCRIPTOR), 123 ) 124 ), 125 original_request=requests[0], 126 ), 127 reflection_pb2.ServerReflectionResponse( 128 valid_host="", 129 error_response=reflection_pb2.ErrorResponse( 130 error_code=grpc.StatusCode.NOT_FOUND.value[0], 131 error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), 132 ), 133 original_request=requests[1], 134 ), 135 ) 136 self.assertSequenceEqual(expected_responses, responses) 137 138 async def test_file_containing_extension(self): 139 requests = ( 140 reflection_pb2.ServerReflectionRequest( 141 file_containing_extension=reflection_pb2.ExtensionRequest( 142 containing_type=_EMPTY_EXTENSIONS_SYMBOL_NAME, 143 extension_number=125, 144 ), 145 ), 146 reflection_pb2.ServerReflectionRequest( 147 file_containing_extension=reflection_pb2.ExtensionRequest( 148 containing_type="i.donut.exist.co.uk.org.net.me.name.foo", 149 extension_number=55, 150 ), 151 ), 152 ) 153 responses = [] 154 async for response in self._stub.ServerReflectionInfo(iter(requests)): 155 responses.append(response) 156 expected_responses = ( 157 reflection_pb2.ServerReflectionResponse( 158 valid_host="", 159 file_descriptor_response=reflection_pb2.FileDescriptorResponse( 160 file_descriptor_proto=( 161 _file_descriptor_to_proto( 162 empty2_extensions_pb2.DESCRIPTOR 163 ), 164 _file_descriptor_to_proto(empty2_pb2.DESCRIPTOR), 165 ) 166 ), 167 original_request=requests[0], 168 ), 169 reflection_pb2.ServerReflectionResponse( 170 valid_host="", 171 error_response=reflection_pb2.ErrorResponse( 172 error_code=grpc.StatusCode.NOT_FOUND.value[0], 173 error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), 174 ), 175 original_request=requests[1], 176 ), 177 ) 178 self.assertSequenceEqual(expected_responses, responses) 179 180 async def test_extension_numbers_of_type(self): 181 requests = ( 182 reflection_pb2.ServerReflectionRequest( 183 all_extension_numbers_of_type=_EMPTY_EXTENSIONS_SYMBOL_NAME 184 ), 185 reflection_pb2.ServerReflectionRequest( 186 all_extension_numbers_of_type="i.donut.exist.co.uk.net.name.foo" 187 ), 188 ) 189 responses = [] 190 async for response in self._stub.ServerReflectionInfo(iter(requests)): 191 responses.append(response) 192 expected_responses = ( 193 reflection_pb2.ServerReflectionResponse( 194 valid_host="", 195 all_extension_numbers_response=reflection_pb2.ExtensionNumberResponse( 196 base_type_name=_EMPTY_EXTENSIONS_SYMBOL_NAME, 197 extension_number=_EMPTY_EXTENSIONS_NUMBERS, 198 ), 199 original_request=requests[0], 200 ), 201 reflection_pb2.ServerReflectionResponse( 202 valid_host="", 203 error_response=reflection_pb2.ErrorResponse( 204 error_code=grpc.StatusCode.NOT_FOUND.value[0], 205 error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), 206 ), 207 original_request=requests[1], 208 ), 209 ) 210 self.assertSequenceEqual(expected_responses, responses) 211 212 async def test_list_services(self): 213 requests = ( 214 reflection_pb2.ServerReflectionRequest( 215 list_services="", 216 ), 217 ) 218 responses = [] 219 async for response in self._stub.ServerReflectionInfo(iter(requests)): 220 responses.append(response) 221 expected_responses = ( 222 reflection_pb2.ServerReflectionResponse( 223 valid_host="", 224 list_services_response=reflection_pb2.ListServiceResponse( 225 service=tuple( 226 reflection_pb2.ServiceResponse(name=name) 227 for name in _SERVICE_NAMES 228 ) 229 ), 230 original_request=requests[0], 231 ), 232 ) 233 self.assertSequenceEqual(expected_responses, responses) 234 235 def test_reflection_service_name(self): 236 self.assertEqual( 237 reflection.SERVICE_NAME, "grpc.reflection.v1alpha.ServerReflection" 238 ) 239 240 241if __name__ == "__main__": 242 logging.basicConfig(level=logging.DEBUG) 243 unittest.main(verbosity=2) 244