예제 #1
0
def test_method_paged_result_field_no_page_field():
    input_msg = make_message(
        name='ListFoosRequest',
        fields=(
            make_field(name='parent', type=9),  # str
            make_field(name='page_size', type=5),  # int
            make_field(name='page_token', type=9),  # str
        ))
    output_msg = make_message(
        name='ListFoosResponse',
        fields=(
            make_field(name='foos',
                       message=make_message('Foo'),
                       repeated=False),
            make_field(name='next_page_token', type=9),  # str
        ))
    method = make_method(
        'ListFoos',
        input_message=input_msg,
        output_message=output_msg,
    )
    assert method.paged_result_field is None

    method = make_method(
        name='Foo',
        input_message=make_message(
            name='FooRequest',
            fields=(make_field(name='page_token', type=9), )  # str
        ),
        output_message=make_message(
            name='FooResponse',
            fields=(make_field(name='next_page_token', type=9), )  # str
        ))
    assert method.paged_result_field is None
예제 #2
0
def test_method_field_headers_present():
    verbs = [
        'get',
        'put',
        'post',
        'delete',
        'patch',
    ]

    for v in verbs:
        rule = http_pb2.HttpRule(**{v: '/v1/{parent=projects/*}/topics'})
        method = make_method('DoSomething', http_rule=rule)
        assert method.field_headers == (wrappers.FieldHeader('parent'), )
        assert method.field_headers[0].raw == 'parent'
        assert method.field_headers[0].disambiguated == 'parent'

        # test that reserved keyword in field header is disambiguated
        rule = http_pb2.HttpRule(**{v: '/v1/{object=objects/*}/topics'})
        method = make_method('DoSomething', http_rule=rule)
        assert method.field_headers == (wrappers.FieldHeader('object'), )
        assert method.field_headers[0].raw == 'object'
        assert method.field_headers[0].disambiguated == 'object_'

        # test w/o equal sign
        rule = http_pb2.HttpRule(**{v: '/v1/{parent}/topics'})
        method = make_method('DoSomething', http_rule=rule)
        assert method.field_headers == (wrappers.FieldHeader('parent'), )
        assert method.field_headers[0].raw == 'parent'
        assert method.field_headers[0].disambiguated == 'parent'
예제 #3
0
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.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,
    )

    # 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.custom_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.custom_polling_method
예제 #4
0
def test_method_http_options_empty_http_rule():
    http_rule = http_pb2.HttpRule()
    method = make_method('DoSomething', http_rule=http_rule)
    assert method.http_options == []

    http_rule = http_pb2.HttpRule(get='')
    method = make_method('DoSomething', http_rule=http_rule)
    assert method.http_options == []
예제 #5
0
def test_method_path_params():
    # tests only the basic case of grpc transcoding
    http_rule = http_pb2.HttpRule(post='/v1/{project}/topics')
    method = make_method('DoSomething', http_rule=http_rule)
    assert method.path_params == ['project']

    http_rule2 = http_pb2.HttpRule(post='/v1beta1/{name=rooms/*/blurbs/*}')
    method2 = make_method("DoSomething", http_rule=http_rule2)
    assert method2.path_params == ["name"]
예제 #6
0
def test_is_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)
        ],
    )

    # Correct positive
    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,
    )

    assert polling_method.is_operation_polling_method

    # Normal method that returns operation
    normal_method = make_method(
        name="Get",
        input_message=request,
        output_message=operation,
    )

    assert not normal_method.is_operation_polling_method

    # Method with invalid options combination
    response = make_message(name="Response", fields=[make_field(name="name")])

    invalid_method = make_method(
        name="Get",
        input_message=request,
        output_message=response,
        options=options,  # Reuse options from the actual polling method
    )

    assert not invalid_method.is_operation_polling_method
예제 #7
0
def test_transport_safe_name():
    unsafe_methods = {
        name: make_method(name=name)
        for name in ["CreateChannel", "GrpcChannel", "OperationsClient"]
    }

    safe_methods = {
        name: make_method(name=name)
        for name in ["Call", "Put", "Hold", "Raise"]
    }

    for name, method in safe_methods.items():
        assert method.transport_safe_name == name

    for name, method in unsafe_methods.items():
        assert method.transport_safe_name == f"{name}_"
예제 #8
0
def test_method_include_flattened_message_fields():
    a = make_field('a', type=5)
    b = make_field('b', type=11, type_name='Eggs',
                   message=make_message('Eggs'))
    input_msg = make_message('Z', fields=(a, b))
    method = make_method('F', input_message=input_msg, signatures=('a,b',))
    assert len(method.flattened_fields) == 2
예제 #9
0
def test_method_http_options_generate_sample_implicit_template():
    http_rule = http_pb2.HttpRule(
        get='/v1/{resource.id}/stuff',
    )
    method = make_method(
        'DoSomething',
        make_message(
            name="Input",
            fields=[
                make_field(
                    name="resource",
                    number=1,
                    message=make_message(
                        "Resource",
                        fields=[
                            make_field(name="id", type=9),
                        ],
                    ),
                ),
            ],
        ),
        http_rule=http_rule,
    )

    sample = method.http_options[0].sample_request(method)
    assert sample == {'resource': {
        'id': 'sample1'}}
예제 #10
0
def test_method_http_options_additional_bindings():
    http_rule = http_pb2.HttpRule(
        post='/v1/{parent=projects/*}/topics',
        body='*',
        additional_bindings=[
            http_pb2.HttpRule(
                post='/v1/{parent=projects/*/regions/*}/topics',
                body='*',
            ),
            http_pb2.HttpRule(
                post='/v1/projects/p1/topics',
                body='body_field',
            ),
        ]
    )
    method = make_method('DoSomething', http_rule=http_rule)
    assert [dataclasses.asdict(http) for http in method.http_options] == [
        {
            'method': 'post',
            'uri': '/v1/{parent=projects/*}/topics',
            'body': '*'
            },
        {
            'method': 'post',
            'uri': '/v1/{parent=projects/*/regions/*}/topics',
            'body': '*'
            },
        {
            'method': 'post',
            'uri': '/v1/projects/p1/topics',
            'body': 'body_field'
            }]
예제 #11
0
def test_method_http_options_generate_sample():
    http_rule = http_pb2.HttpRule(
        get='/v1/{resource.id=projects/*/regions/*/id/**}/stuff', )

    method = make_method(
        'DoSomething',
        make_message(
            name="Input",
            fields=[
                make_field(
                    name="resource",
                    number=1,
                    type=11,
                    message=make_message(
                        "Resource",
                        fields=[
                            make_field(name="id", type=9),
                        ],
                    ),
                ),
            ],
        ),
        http_rule=http_rule,
    )
    sample = method.http_options[0].sample_request(method)
    assert sample == {
        'resource': {
            'id': 'projects/sample1/regions/sample2/id/sample3'
        }
    }
예제 #12
0
def test_has_pagers():
    paged = make_field(name='foos', message=make_message('Foo'), repeated=True)
    input_msg = make_message(
        name='ListFoosRequest',
        fields=(
            make_field(name='parent', type=9),  # str
            make_field(name='page_size', type=5),  # int
            make_field(name='page_token', type=9),  # str
        ),
    )
    output_msg = make_message(
        name='ListFoosResponse',
        fields=(
            paged,
            make_field(name='next_page_token', type=9),  # str
        ),
    )
    method = make_method(
        'ListFoos',
        input_message=input_msg,
        output_message=output_msg,
    )

    service = make_service(
        name="Fooer",
        methods=(method, ),
    )
    assert service.has_pagers

    other_service = make_service(
        name="Unfooer",
        methods=(get_method("Unfoo", "foo.bar.UnfooReq",
                            "foo.bar.UnFooResp"), ),
    )
    assert not other_service.has_pagers
def test_method_paged_result_ref_types():
    input_msg = make_message(
        name='ListSquidsRequest',
        fields=(
            make_field(name='parent', type=9),  # str
            make_field(name='page_size', type=5),  # int
            make_field(name='page_token', type=9),  # str
        ),
        module='squid',
    )
    mollusc_msg = make_message('Mollusc', module='mollusc')
    output_msg = make_message(name='ListMolluscsResponse',
                              fields=(make_field(name='molluscs',
                                                 message=mollusc_msg,
                                                 repeated=True),
                                      make_field(name='next_page_token',
                                                 type=9)),
                              module='mollusc')
    method = make_method('ListSquids',
                         input_message=input_msg,
                         output_message=output_msg,
                         module='squid')

    ref_type_names = {t.name for t in method.ref_types}
    assert ref_type_names == {
        'ListSquidsRequest',
        'ListSquidsPager',
        'ListSquidsAsyncPager',
        'Mollusc',
    }
예제 #14
0
def test_safe_name():
    unsafe_methods = {
        name: make_method(name=name)
        for name in ["import", "Import", "Raise"]
    }

    safe_methods = {
        name: make_method(name=name)
        for name in ["Call", "Put", "Hold"]
    }

    for name, method in safe_methods.items():
        assert method.safe_name == name

    for name, method in unsafe_methods.items():
        assert method.safe_name == f"{name}_"
def test_method_http_opt_no_body():
    http_rule = http_pb2.HttpRule(post='/v1/{parent=projects/*}/topics')
    method = make_method('DoSomething', http_rule=http_rule)
    assert method.http_opt == {
        'verb': 'post',
        'url': '/v1/{parent=projects/*}/topics'
    }
예제 #16
0
def test_resource_response():
    # Top level response resource
    squid_resource = make_message("Squid", options=make_resource_opts("squid"))
    squid_request = make_message("CreateSquidRequest")

    # Nested response resource
    clam_resource = make_message("Clam", options=make_resource_opts("clam"))
    clam_response = make_message(
        "CreateClamResponse",
        fields=(make_field('clam', message=clam_resource), ),
    )
    clam_request = make_message("CreateClamRequest")

    mollusc_service = make_service(
        "MolluscService",
        methods=(make_method(f"{request.name}", request, response)
                 for request, response in (
                     (squid_request, squid_resource),
                     (clam_request, clam_response),
                 )),
    )

    expected = {squid_resource, clam_resource}
    actual = mollusc_service.resource_messages
    assert expected == actual
def test_method_flattened_fields_different_package_non_primitive():
    # This test verifies that method flattening handles a special case where:
    # * the method's request message type lives in a different package and
    # * a field in the method_signature is a non-primitive.
    #
    # If the message is defined in a different package it is not guaranteed to
    # be a proto-plus wrapped type, which puts restrictions on assigning
    # directly to its fields, which complicates request construction.
    # The easiest solution in this case is to just prohibit these fields
    # in the method flattening.
    message = make_message('Mantle',
                           package="mollusc.cephalopod.v1",
                           module="squid")
    mantle = make_field('mantle',
                        type=11,
                        type_name='Mantle',
                        message=message,
                        meta=message.meta)
    arms_count = make_field('arms_count', type=5, meta=message.meta)
    input_message = make_message('Squid',
                                 fields=(mantle, arms_count),
                                 package=".".join(
                                     message.meta.address.package),
                                 module=message.meta.address.module)
    method = make_method('PutSquid',
                         input_message=input_message,
                         package="remote.package.v1",
                         module="module",
                         signatures=("mantle,arms_count", ))
    assert set(method.flattened_fields) == {'arms_count'}
def test_method_flattened_fields():
    a = make_field('a', type=5)  # int
    b = make_field('b', type=5)
    input_msg = make_message('Z', fields=(a, b))
    method = make_method('F', input_message=input_msg, signatures=('a,b', ))
    assert len(method.flattened_fields) == 2
    assert 'a' in method.flattened_fields
    assert 'b' in method.flattened_fields
예제 #19
0
def test_method_types():
    input_msg = make_message(name='Input', module='baz')
    output_msg = make_message(name='Output', module='baz')
    method = make_method('DoSomething', input_msg, output_msg,
                         package='foo.bar', module='bacon')
    assert method.name == 'DoSomething'
    assert method.input.name == 'Input'
    assert method.output.name == 'Output'
예제 #20
0
def test_body_fields_no_body():
    http_rule = http_pb2.HttpRule(
        post='/v1/{arms_shape=arms/*}/squids',
    )

    method = make_method(
        'PutSquid', http_rule=http_rule)

    assert not method.body_fields
예제 #21
0
def test_resource_messages():
    # 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
예제 #22
0
def test_method_routing_rule():
    routing_rule = routing_pb2.RoutingRule()
    param = routing_rule.routing_parameters.add()
    param.field = 'table_name'
    param.path_template = 'projects/*/{table_location=instances/*}/tables/*'
    method = make_method('DoSomething', routing_rule=routing_rule)
    assert method.explicit_routing
    assert method.routing_rule.routing_parameters == [wrappers.RoutingParameter(
        x.field, x.path_template) for x in routing_rule.routing_parameters]
    assert method.routing_rule.routing_parameters[0].sample_request is not None
예제 #23
0
def test_method_http_options_reserved_name_in_url():
    http_rule = http_pb2.HttpRule(post='/v1/license/{license=lic/*}', body='*')
    method = make_method('DoSomething', http_rule=http_rule)
    assert [dataclasses.asdict(http) for http in method.http_options] == [{
        'method':
        'post',
        'uri':
        '/v1/license/{license_=lic/*}',
        'body':
        '*'
    }]
예제 #24
0
def test_method_http_options_body_field():
    http_rule = http_pb2.HttpRule(
        post='/v1/{parent=projects/*}/topics',
        body='body_field'
    )
    method = make_method('DoSomething', http_rule=http_rule)
    assert [dataclasses.asdict(http) for http in method.http_options] == [{
        'method': 'post',
        'uri': '/v1/{parent=projects/*}/topics',
        'body': 'body_field'
    }]
def test_method_query_params():
    # tests only the basic case of grpc transcoding
    http_rule = http_pb2.HttpRule(post='/v1/{project}/topics', body='address')
    input_message = make_message('MethodInput',
                                 fields=(make_field('region'),
                                         make_field('project'),
                                         make_field('address')))
    method = make_method('DoSomething',
                         http_rule=http_rule,
                         input_message=input_message)
    assert method.query_params == {'region'}
예제 #26
0
def test_flattened_oneof_fields():
    mass_kg = make_field(name="mass_kg", oneof="mass", type=5)
    mass_lbs = make_field(name="mass_lbs", oneof="mass", type=5)

    length_m = make_field(name="length_m", oneof="length", type=5)
    length_f = make_field(name="length_f", oneof="length", type=5)

    color = make_field(name="color", type=5)
    mantle = make_field(
        name="mantle",
        message=make_message(
            name="Mantle",
            fields=(
                make_field(name="color", type=5),
                mass_kg,
                mass_lbs,
            ),
        ),
    )
    request = make_message(
        name="CreateMolluscReuqest",
        fields=(
            length_m,
            length_f,
            color,
            mantle,
        ),
    )
    method = make_method(
        name="CreateMollusc",
        input_message=request,
        signatures=[
            "length_m,",
            "length_f,",
            "mantle.mass_kg,",
            "mantle.mass_lbs,",
            "color",
        ]
    )

    expected = {"mass": [mass_kg, mass_lbs], "length": [length_m, length_f]}
    actual = method.flattened_oneof_fields()
    assert expected == actual

    # Check this method too becasue the setup is a lot of work.
    expected = {
        "color": "color",
        "length_m": "length_m",
        "length_f": "length_f",
        "mass_kg": "mantle.mass_kg",
        "mass_lbs": "mantle.mass_lbs",
    }
    actual = method.flattened_field_to_key
    assert expected == actual
예제 #27
0
def test_service_any_deprecated():
    service = make_service(
        name='Service',
        methods=((make_method(
            f"GetMollusc",
            input_message=make_message("GetMolluscRequest", ),
            output_message=make_message("GetMolluscResponse", ),
        ), )))

    assert service.any_deprecated == False

    deprecated_service = make_service(
        name='ServiceWithDeprecatedMethod',
        methods=((make_method(
            f"GetMollusc",
            input_message=make_message("GetMolluscRequest", ),
            output_message=make_message("GetMolluscResponse", ),
            is_deprecated=True,
        ), )))

    assert deprecated_service.any_deprecated == True
예제 #28
0
def test_method_client_output_paged():
    paged = make_field(name='foos', message=make_message('Foo'), repeated=True)
    parent = make_field(name='parent', type=9)  # str
    page_size = make_field(name='page_size', type=5)  # int
    page_token = make_field(name='page_token', type=9)  # str

    input_msg = make_message(name='ListFoosRequest',
                             fields=(
                                 parent,
                                 page_size,
                                 page_token,
                             ))
    output_msg = make_message(
        name='ListFoosResponse',
        fields=(
            paged,
            make_field(name='next_page_token', type=9),  # str
        ))
    method = make_method(
        'ListFoos',
        input_message=input_msg,
        output_message=output_msg,
    )
    assert method.paged_result_field == paged
    assert method.client_output.ident.name == 'ListFoosPager'

    max_results = make_field(name='max_results', type=5)  # int
    input_msg = make_message(name='ListFoosRequest',
                             fields=(
                                 parent,
                                 max_results,
                                 page_token,
                             ))
    method = make_method(
        'ListFoos',
        input_message=input_msg,
        output_message=output_msg,
    )
    assert method.paged_result_field == paged
    assert method.client_output.ident.name == 'ListFoosPager'
예제 #29
0
def test_method_http_options():
    verbs = ['get', 'put', 'post', 'delete', 'patch']
    for v in verbs:
        http_rule = http_pb2.HttpRule(**{v: '/v1/{parent=projects/*}/topics'})
        method = make_method('DoSomething', http_rule=http_rule)
        assert [dataclasses.asdict(http) for http in method.http_options] == [{
            'method':
            v,
            'uri':
            '/v1/{parent=projects/*}/topics',
            'body':
            None
        }]
def test_method_field_headers_present():
    verbs = [
        'get',
        'put',
        'post',
        'delete',
        'patch',
    ]

    for v in verbs:
        rule = http_pb2.HttpRule(**{v: '/v1/{parent=projects/*}/topics'})
        method = make_method('DoSomething', http_rule=rule)
        assert method.field_headers == ('parent', )