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
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'}}
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',
    }
def test_mock_value_original_type_enum():
    mollusc_field = make_field(
        name="class",
        enum=make_enum(
            name="Class",
            values=[
                ("UNKNOWN", 0),
                ("GASTROPOD", 1),
                ("BIVALVE", 2),
                ("CEPHALOPOD", 3),
            ],
        ),
    )

    assert mollusc_field.mock_value_original_type == 1

    empty_field = make_field(
        name="empty",
        enum=make_enum(
            name="Empty",
            values=[("UNKNOWN", 0)],
        ),
    )

    assert empty_field.mock_value_original_type == 0
Exemple #5
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'
        }
    }
Exemple #6
0
def test_required_fields():
    REQUIRED = field_behavior_pb2.FieldBehavior.Value('REQUIRED')

    mass_kg = make_field(name="mass_kg", type=5)
    mass_kg.options.Extensions[field_behavior_pb2.field_behavior].append(
        REQUIRED)

    length_m = make_field(name="length_m", type=5)
    length_m.options.Extensions[field_behavior_pb2.field_behavior].append(
        REQUIRED)

    color = make_field(name="color", type=5)
    color.options.Extensions[field_behavior_pb2.field_behavior].append(
        REQUIRED)

    request = make_message(
        name="CreateMolluscReuqest",
        fields=(
            mass_kg,
            length_m,
            color,
        ),
    )

    assert set(request.required_fields) == {mass_kg, length_m, color}
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'}
Exemple #8
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
Exemple #9
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_field_types_recursive():
    enumeration = make_enum('Enumeration')
    innest_msg = make_message(
        'InnestMessage',
        fields=(
            make_field('enumeration', enum=enumeration),
        )
    )
    inner_msg = make_message(
        'InnerMessage',
        fields=(
            make_field('innest_message', message=innest_msg),
        )
    )
    topmost_msg = make_message(
        'TopmostMessage',
        fields=(
            make_field('inner_message', message=inner_msg),
            make_field('uninteresting')
        )
    )

    actual = {t.name for t in topmost_msg.recursive_field_types}
    expected = {t.name for t in (enumeration, innest_msg, inner_msg)}
    assert actual == expected
def test_field_types():
    # Create the inner message.
    inner_msg = make_message(
        'InnerMessage',
        fields=(
            make_field(
                'hidden_message',
                message=make_message('HiddenMessage'),
            ),
        )
    )
    inner_enum = make_enum('InnerEnum')

    # Create the outer message, which contains an Inner as a field.
    fields = (
        make_field('inner_message', message=inner_msg),
        make_field('inner_enum', enum=inner_enum),
        make_field('not_interesting'),
    )
    outer = make_message('Outer', fields=fields)

    # Assert that composite field types are recognized but primitives are not.
    assert len(outer.field_types) == 2
    assert inner_msg in outer.field_types
    assert inner_enum in outer.field_types
Exemple #12
0
def test_is_msg_field_pb():
    msg_field = make_field('msg_field', message=make_message('test_msg'))
    str_field = make_field('str_field', type=9)
    int_field = make_field('int_field', type=5)
    assert checks.is_msg_field_pb(msg_field.field_pb)
    assert not checks.is_msg_field_pb(str_field.field_pb)
    assert not checks.is_msg_field_pb(int_field.field_pb)
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
Exemple #14
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
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'}
def test_get_field_recursive():
    # Create the inner message.
    inner_fields = (make_field('zero'), make_field('one'))
    inner = make_message('Inner', fields=inner_fields, package='foo.v1')

    # Create the outer message, which contains an Inner as a field.
    outer_field = make_field('inner', message=inner)
    outer = make_message('Outer', fields=(outer_field, ))

    # Assert that a recusive retrieval works.
    assert outer.get_field('inner', 'zero') == inner_fields[0]
    assert outer.get_field('inner', 'one') == inner_fields[1]
def test_field_name_kword_disambiguation():
    from_field = make_field(name="from", )
    assert from_field.name == "from_"

    frum_field = make_field(name="frum", )
    assert frum_field.name == "frum"

    mapping_field = make_field(name="mapping")
    assert mapping_field.name == "mapping_"

    ignore_field = make_field(name="ignore_unknown_fields")
    assert ignore_field.name == "ignore_unknown_fields_"
def test_get_field_nested_not_found_error():
    # Create the inner message.
    inner_field = make_field('zero')
    inner = make_message('Inner', fields=(inner_field, ), package='foo.v1')

    # Create the outer message, which contains an Inner as a field.
    outer_field = make_field('inner', message=inner)
    outer = make_message('Outer', fields=(outer_field, ))

    # Assert that a recusive retrieval fails.
    with pytest.raises(KeyError):
        assert outer.get_field('inner', 'zero', 'beyond')
def test_field_map():
    # Create an Entry message.
    entry_msg = make_message(
        name='FooEntry',
        fields=(
            make_field(name='key', type=9),
            make_field(name='value', type=9),
        ),
        options=descriptor_pb2.MessageOptions(map_entry=True),
    )
    entry_field = make_field('foos', message=entry_msg, repeated=True)
    assert entry_msg.map
    assert entry_field.map
def test_get_field_nonterminal_repeated_error():
    # Create the inner message.
    inner_fields = (make_field('zero'), make_field('one'))
    inner = make_message('Inner', fields=inner_fields, package='foo.v1')

    # Create the outer message, which contains an Inner as a field.
    outer_field = make_field('inner', message=inner, repeated=True)
    outer = make_message('Outer', fields=(outer_field, ))

    # Assert that a recusive retrieval fails.
    with pytest.raises(KeyError):
        assert outer.get_field('inner', 'zero') == inner_fields[0]
    with pytest.raises(KeyError):
        assert outer.get_field('inner', 'one') == inner_fields[1]
Exemple #21
0
def test_body_fields():
    http_rule = http_pb2.HttpRule(post='/v1/{arms_shape=arms/*}/squids',
                                  body='mantle')

    mantle_stuff = make_field(name='mantle_stuff', type=9)
    message = make_message('Mantle', fields=(mantle_stuff, ))
    mantle = make_field('mantle', type=11, type_name='Mantle', message=message)
    arms_shape = make_field('arms_shape', type=9)
    input_message = make_message('Squid', fields=(mantle, arms_shape))
    method = make_method('PutSquid',
                         input_message=input_message,
                         http_rule=http_rule)
    assert set(method.body_fields) == {'mantle'}
    mock_value = method.body_fields['mantle'].mock_value
    assert mock_value == "baz.Mantle(mantle_stuff='mantle_stuff_value')"
def test_resource_reference():
    field = make_field(type='TYPE_STRING')
    field.options.Extensions[
        resource_pb2.
        resource_reference].type = "translate.googleapis.com/Glossary"

    assert field.resource_reference == "translate.googleapis.com/Glossary"
Exemple #23
0
def test_differently_named_extended_operation_fields(
    all_field_names,
    canonical_name_to_field_name,
):
    T = descriptor_pb2.FieldDescriptorProto.Type
    operation = make_message(
        name="Operation",
        fields=[
            make_field(
                name=name.lower(),
                type=T.Value("TYPE_STRING"),
                number=i,
            ) for i, name in enumerate(all_field_names, start=1)
        ])
    for f in operation.fields.values():
        options = descriptor_pb2.FieldOptions()
        options.Extensions[ex_ops_pb2.operation_field] = f.number
        f.options.MergeFrom(options)

    expected = {
        k: operation.fields[v]
        for k, v in canonical_name_to_field_name.items()
    } if canonical_name_to_field_name is not None else None
    actual = operation.differently_named_extended_operation_fields

    assert expected == actual
def test_method_paged_result_field_not_first():
    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=(
        make_field(name='next_page_token', type=9),  # str
        paged,
    ))
    method = make_method('ListFoos',
                         input_message=input_msg,
                         output_message=output_msg,
                         )
    assert method.paged_result_field == paged
Exemple #25
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
Exemple #26
0
def test_mock_value_map():
    entry_msg = make_message(
        name='SquidEntry',
        fields=(
            make_field(name='key', type='TYPE_STRING'),
            make_field(name='value', type='TYPE_STRING'),
        ),
        options=descriptor_pb2.MessageOptions(map_entry=True),
    )
    field = make_field(
        name='squids',
        type_name='mollusc.SquidEntry',
        message=entry_msg,
        label=3,
        type='TYPE_MESSAGE',
    )
    assert field.mock_value == "{'key_value': 'value_value'}"
def test_ident_sphinx_map():
    entry_msg = make_message(
        name='SquidEntry',
        fields=(
            make_field(name='key', type='TYPE_STRING'),
            make_field(name='value', type='TYPE_STRING'),
        ),
        options=descriptor_pb2.MessageOptions(map_entry=True),
    )
    field = make_field(
        name='squids',
        type_name='mollusc.SquidEntry',
        message=entry_msg,
        label=3,
        type='TYPE_MESSAGE',
    )
    assert field.ident.sphinx == 'Mapping[str, str]'
def test_extended_operation_properties():
    options = descriptor_pb2.FieldOptions()
    options.Extensions[ex_ops_pb2.operation_request_field] = "squid"
    options.Extensions[ex_ops_pb2.operation_response_field] = "clam"
    f = make_field(options=options)

    assert f.operation_request_field == "squid"
    assert f.operation_response_field == "clam"
Exemple #29
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
def test_flattened_ref_types():
    method = make_method(
        'IdentifyMollusc',
        input_message=make_message(
            'IdentifyMolluscRequest',
            fields=(
                make_field(
                    'cephalopod',
                    message=make_message(
                        'Cephalopod',
                        fields=(
                            make_field('mass_kg', type='TYPE_INT32'),
                            make_field(
                                'squid',
                                number=2,
                                message=make_message('Squid'),
                            ),
                            make_field(
                                'clam',
                                number=3,
                                message=make_message('Clam'),
                            ),
                        ),
                    ),
                ),
                make_field(
                    'stratum',
                    enum=make_enum(
                        'Stratum',
                    )
                ),
            ),
        ),
        signatures=('cephalopod.squid,stratum',),
        output_message=make_message('Mollusc'),
    )

    expected_flat_ref_type_names = {
        'IdentifyMolluscRequest',
        'Squid',
        'Stratum',
        'Mollusc',
    }
    actual_flat_ref_type_names = {t.name for t in method.flat_ref_types}
    assert expected_flat_ref_type_names == actual_flat_ref_type_names