def test_service_name_colliding_modules(): service = make_service(name='ThingDoer', methods=( get_method('DoThing', 'foo.bar.ThingRequest', 'foo.bar.ThingResponse'), get_method('Jump', 'bacon.bar.JumpRequest', 'bacon.bar.JumpResponse'), get_method('Yawn', 'a.b.v1.c.YawnRequest', 'a.b.v1.c.YawnResponse'), )) expected_names = { 'ThingDoer', 'ThingDoerClient', 'do_thing', 'jump', 'yawn', 'bar' } assert service.names == expected_names
def test_service_any_streaming(): for client, server in itertools.product((True, False), (True, False)): service = make_service( f'ClientStream{client}:ServerStream{server}', methods=((make_method( f"GetMollusc", input_message=make_message("GetMolluscRequest", ), output_message=make_message("GetMolluscResponse", ), client_streaming=client, server_streaming=server, ), ))) assert service.any_client_streaming == client assert service.any_server_streaming == server
def test_service_python_modules(): service = make_service(methods=( get_method('DoThing', 'foo.bar.ThingRequest', 'foo.baz.ThingResponse'), get_method('Jump', 'foo.bacon.JumpRequest', 'foo.bacon.JumpResponse'), get_method('Yawn', 'a.b.v1.c.YawnRequest', 'x.y.v1.z.YawnResponse'), )) imports = { i.ident.python_import for m in service.methods.values() for i in m.ref_types } assert imports == { imp.Import(package=('a', 'b', 'v1'), module='c'), imp.Import(package=('foo', ), module='bacon'), imp.Import(package=('foo', ), module='bar'), imp.Import(package=('foo', ), module='baz'), imp.Import(package=('x', 'y', 'v1'), module='z'), }
def test_service_unknown_resource_reference(): # This happens occasionally. opts = descriptor_pb2.FieldOptions() res_ref = opts.Extensions[resource_pb2.resource_reference] res_ref.type = "*" squid_request = make_message( "CreateSquid", fields=(make_field( "parent", type="TYPE_STRING", options=opts, ), ), ) squid_service = make_service( "SquidService", methods=(make_method( "CreateSquid", input_message=squid_request, ), ), ) assert not squid_service.resource_messages
def test_service_scopes(): service = make_service(scopes=('https://foo/user/', 'https://foo/admin/')) assert 'https://foo/user/' in service.oauth_scopes assert 'https://foo/admin/' in service.oauth_scopes
def test_service_no_host(): service = make_service() assert not service.host
def test_service_host(): service = make_service(host='thingdoer.googleapis.com') assert service.host == 'thingdoer.googleapis.com'
def test_extended_operations_lro_detection(): T = descriptor_pb2.FieldDescriptorProto.Type operation = make_message( name="Operation", fields=(make_field( name=name, type=T.Value("TYPE_STRING"), number=i) for i, name in enumerate( ("name", "status", "error_code", "error_message"), start=1)), ) for f in operation.field: options = descriptor_pb2.FieldOptions() # Note: The field numbers were carefully chosen to be the corresponding enum values. options.Extensions[ex_ops_pb2.operation_field] = f.number f.options.MergeFrom(options) request = make_message( name="GetOperation", fields=[ make_field(name="name", type=T.Value("TYPE_STRING"), number=1) ], ) options = descriptor_pb2.MethodOptions() options.Extensions[ex_ops_pb2.operation_polling_method] = True polling_method = make_method( name="Get", input_message=request, output_message=operation, options=options, ) ops_service = make_service( name="CustomOperations", methods=[ polling_method, make_method( name="Delete", input_message=make_message(name="Input"), output_message=make_message("Output"), ), ], ) assert not polling_method.operation_service # Methods are LROs, so they are not polling methods lro_opts = descriptor_pb2.MethodOptions() lro_opts.Extensions[ex_ops_pb2.operation_service] = "CustomOperations" lro = make_method( name="Start", input_message=make_message(name="StartRequest"), output_message=operation, options=lro_opts, ) user_service = make_service( name="ComputationStarter", methods=[ lro, ], ) # Note: we can't have the operation_serivce property point to the actual operation service # because Service objects can't perform the lookup. # Instead we kick that can to the API object and make it do the lookup and verification. assert lro.operation_service == "CustomOperations"
def test_resource_messages_dict(): # Regular, top level resource squid_resource = make_message("Squid", options=make_resource_opts("squid")) squid_request = make_message( "CreateSquid", fields=(make_field('squid', message=squid_resource), ), ) # Nested resource squamosa_message = make_message( "Squamosa", options=make_resource_opts("clam", "squamosa"), ) clam_resource = make_message( "Clam", options=make_resource_opts("clam"), fields=(make_field('squamosa', message=squamosa_message), ), ) clam_request = make_message( 'CreateClam', fields=( make_field('clam', message=clam_resource), # Red herring, not resources :) make_field('zone', 2, enum=make_enum('Zone')), make_field('pearls', 3, True, message=make_message('Pearl')), ), ) # Some special APIs have request messages that _are_ resources. whelk_resource = make_message("Whelk", options=make_resource_opts("whelk")) # Not a resource octopus_request = make_message( "CreateOctopus", fields=(make_field('Octopus', message=make_message('Octopus')), ), ) service = make_service('Molluscs', methods=(make_method( f"{message.name}", input_message=message, ) for message in ( squid_request, clam_request, whelk_resource, octopus_request, ))) expected = { # Service specific "squid/{squid}": squid_resource, "clam/{clam}": clam_resource, "whelk/{whelk}": whelk_resource, "clam/{clam}/squamosa/{squamosa}": squamosa_message, # Common resources "cloudresourcemanager.googleapis.com/Project": service.common_resources["cloudresourcemanager.googleapis.com/Project"] .message_type, "cloudresourcemanager.googleapis.com/Organization": service.common_resources[ "cloudresourcemanager.googleapis.com/Organization"].message_type, "cloudresourcemanager.googleapis.com/Folder": service.common_resources["cloudresourcemanager.googleapis.com/Folder"]. message_type, "cloudbilling.googleapis.com/BillingAccount": service.common_resources["cloudbilling.googleapis.com/BillingAccount"]. message_type, "locations.googleapis.com/Location": service.common_resources["locations.googleapis.com/Location"]. message_type } actual = service.resource_messages_dict assert expected == actual
def test_module_name(): service = make_service(name='MyService') assert service.module_name == 'my_service'
def test_service_no_lro(): service = make_service() assert service.has_lro is False
def test_service_no_scopes(): service = make_service() assert len(service.oauth_scopes) == 0
def test_resource_messages(): # Resources are labeled via an options extension def make_resource_opts(*args): opts = descriptor_pb2.MessageOptions() opts.Extensions[resource_pb2.resource].pattern.append( "/".join("{{{arg}}}/{arg}" for arg in args) ) return opts # Regular, top level resource squid_resource = make_message("Squid", options=make_resource_opts("squid")) squid_request = make_message( "CreateSquid", fields=( make_field('squid', message=squid_resource), ), ) # Nested resource squamosa_message = make_message( "Squamosa", options=make_resource_opts("clam", "squamosa"), ) clam_resource = make_message( "Clam", options=make_resource_opts("clam"), fields=( make_field('squamosa', message=squamosa_message), ), ) clam_request = make_message( 'CreateClam', fields=( make_field('clam', message=clam_resource), # Red herring, not resources :) make_field('zone', 2, enum=make_enum('Zone')), make_field('pearls', 3, True, message=make_message('Pearl')), ), ) # Some special APIs have request messages that _are_ resources. whelk_resource = make_message("Whelk", options=make_resource_opts("whelk")) # Not a resource octopus_request = make_message( "CreateOctopus", fields=( make_field('Octopus', message=make_message('Octopus')), ), ) service = make_service( 'Molluscs', methods=( make_method( f"{message.name}", input_message=message, ) for message in ( squid_request, clam_request, whelk_resource, octopus_request, ) ) ) expected = { squid_resource, clam_resource, whelk_resource, squamosa_message, } actual = service.resource_messages assert expected == actual
def test_service_properties(): service = make_service(name='ThingDoer') assert service.name == 'ThingDoer' assert service.client_name == 'ThingDoerClient' assert service.transport_name == 'ThingDoerTransport' assert service.grpc_transport_name == 'ThingDoerGrpcTransport'
def test_operation_polling_method(): T = descriptor_pb2.FieldDescriptorProto.Type operation = make_message( name="Operation", fields=[ make_field(name=name, type=T.Value("TYPE_STRING"), number=i) for i, name in enumerate( ("name", "status", "error_code", "error_message"), start=1) ], ) for f in operation.fields.values(): options = descriptor_pb2.FieldOptions() # Note: The field numbers were carefully chosen to be the corresponding enum values. options.Extensions[ex_ops_pb2.operation_field] = f.number f.options.MergeFrom(options) request = make_message( name="GetOperation", fields=[ make_field(name="name", type=T.Value("TYPE_STRING"), number=1) ], ) options = descriptor_pb2.MethodOptions() options.Extensions[ex_ops_pb2.operation_polling_method] = True polling_method = make_method( name="Get", input_message=request, output_message=operation, options=options, ) # Even though polling_method returns an Operation, it isn't an LRO ops_service = make_service( name="CustomOperations", methods=[ polling_method, make_method( name="Delete", input_message=make_message(name="Input"), output_message=make_message("Output"), ), ], ) assert ops_service.operation_polling_method == polling_method # Methods are LROs, so they are not polling methods user_service = make_service( name="ComputationStarter", methods=[ make_method( name="Start", input_message=make_message(name="StartRequest"), output_message=operation, ), ], ) assert not user_service.operation_polling_method