Move betterproto/tests → tests

This commit is contained in:
Arun Babu Neelicattu
2020-07-10 13:45:52 +02:00
committed by Bouke Versteegh
parent 8864f4fdbd
commit cebf9176a3
112 changed files with 27 additions and 27 deletions

View File

@@ -0,0 +1,3 @@
{
"value": true
}

View File

@@ -0,0 +1,5 @@
syntax = "proto3";
message Test {
bool value = 1;
}

View File

@@ -0,0 +1,6 @@
from tests.output_betterproto.bool import Test
def test_value():
message = Test()
assert not message.value, "Boolean is False by default"

View File

@@ -0,0 +1,3 @@
{
"data": "SGVsbG8sIFdvcmxkIQ=="
}

View File

@@ -0,0 +1,5 @@
syntax = "proto3";
message Test {
bytes data = 1;
}

View File

@@ -0,0 +1,4 @@
{
"camelCase": 1,
"snakeCase": "ONE"
}

View File

@@ -0,0 +1,18 @@
syntax = "proto3";
enum my_enum {
ZERO = 0;
ONE = 1;
TWO = 2;
}
message Test {
int32 camelCase = 1;
my_enum snake_case = 2;
snake_case_message snake_case_message = 3;
int32 UPPERCASE = 4;
}
message snake_case_message {
}

View File

@@ -0,0 +1,23 @@
import tests.output_betterproto.casing as casing
from tests.output_betterproto.casing import Test
def test_message_attributes():
message = Test()
assert hasattr(
message, "snake_case_message"
), "snake_case field name is same in python"
assert hasattr(message, "camel_case"), "CamelCase field is snake_case in python"
assert hasattr(message, "uppercase"), "UPPERCASE field is lowercase in python"
def test_message_casing():
assert hasattr(
casing, "SnakeCaseMessage"
), "snake_case Message name is converted to CamelCase in python"
def test_enum_casing():
assert hasattr(
casing, "MyEnum"
), "snake_case Enum name is converted to CamelCase in python"

View File

@@ -0,0 +1,7 @@
syntax = "proto3";
message Test {
int32 UPPERCASE = 1;
int32 UPPERCASE_V2 = 2;
int32 UPPER_CAMEL_CASE = 3;
}

View File

@@ -0,0 +1,14 @@
from tests.output_betterproto.casing_message_field_uppercase import Test
def test_message_casing():
message = Test()
assert hasattr(
message, "uppercase"
), "UPPERCASE attribute is converted to 'uppercase' in python"
assert hasattr(
message, "uppercase_v2"
), "UPPERCASE_V2 attribute is converted to 'uppercase_v2' in python"
assert hasattr(
message, "upper_camel_case"
), "UPPER_CAMEL_CASE attribute is converted to upper_camel_case in python"

20
tests/inputs/config.py Normal file
View File

@@ -0,0 +1,20 @@
# Test cases that are expected to fail, e.g. unimplemented features or bug-fixes.
# Remove from list when fixed.
xfail = {
"oneof_enum", # 63
"namespace_keywords", # 70
"namespace_builtin_types", # 53
"googletypes_struct", # 9
"googletypes_value", # 9,
"import_capitalized_package",
"example", # This is the example in the readme. Not a test.
}
services = {
"googletypes_response",
"googletypes_response_embedded",
"service",
"import_service_input_message",
"googletypes_service_returns_empty",
"googletypes_service_returns_googletype",
}

View File

@@ -0,0 +1,3 @@
{
"count": -123.45
}

View File

@@ -0,0 +1,3 @@
{
"count": 123.45
}

View File

@@ -0,0 +1,5 @@
syntax = "proto3";
message Test {
double count = 1;
}

View File

@@ -0,0 +1,3 @@
{
"greeting": "HEY"
}

View File

@@ -0,0 +1,14 @@
syntax = "proto3";
// Enum for the different greeting types
enum Greeting {
HI = 0;
HEY = 1;
// Formal greeting
HELLO = 2;
}
message Test {
// Greeting enum example
Greeting greeting = 1;
}

View File

@@ -0,0 +1,8 @@
syntax = "proto3";
package hello;
// Greeting represents a message you can tell a user.
message Greeting {
string message = 1;
}

View File

@@ -0,0 +1,6 @@
{
"foo": 4294967295,
"bar": -2147483648,
"baz": "18446744073709551615",
"qux": "-9223372036854775808"
}

View File

@@ -0,0 +1,8 @@
syntax = "proto3";
message Test {
fixed32 foo = 1;
sfixed32 bar = 2;
fixed64 baz = 3;
sfixed64 qux = 4;
}

View File

@@ -0,0 +1 @@
{}

View File

@@ -0,0 +1,7 @@
{
"maybe": false,
"ts": "1972-01-01T10:00:20.021Z",
"duration": "1.200s",
"important": 10,
"empty": {}
}

View File

@@ -0,0 +1,14 @@
syntax = "proto3";
import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/wrappers.proto";
import "google/protobuf/empty.proto";
message Test {
google.protobuf.BoolValue maybe = 1;
google.protobuf.Timestamp ts = 2;
google.protobuf.Duration duration = 3;
google.protobuf.Int32Value important = 4;
google.protobuf.Empty empty = 5;
}

View File

@@ -0,0 +1,21 @@
syntax = "proto3";
import "google/protobuf/wrappers.proto";
// Tests that wrapped values can be used directly as return values
service Test {
rpc GetDouble (Input) returns (google.protobuf.DoubleValue);
rpc GetFloat (Input) returns (google.protobuf.FloatValue);
rpc GetInt64 (Input) returns (google.protobuf.Int64Value);
rpc GetUInt64 (Input) returns (google.protobuf.UInt64Value);
rpc GetInt32 (Input) returns (google.protobuf.Int32Value);
rpc GetUInt32 (Input) returns (google.protobuf.UInt32Value);
rpc GetBool (Input) returns (google.protobuf.BoolValue);
rpc GetString (Input) returns (google.protobuf.StringValue);
rpc GetBytes (Input) returns (google.protobuf.BytesValue);
}
message Input {
}

View File

@@ -0,0 +1,54 @@
from typing import Any, Callable, Optional
import betterproto.lib.google.protobuf as protobuf
import pytest
from tests.mocks import MockChannel
from tests.output_betterproto.googletypes_response import TestStub
test_cases = [
(TestStub.get_double, protobuf.DoubleValue, 2.5),
(TestStub.get_float, protobuf.FloatValue, 2.5),
(TestStub.get_int64, protobuf.Int64Value, -64),
(TestStub.get_u_int64, protobuf.UInt64Value, 64),
(TestStub.get_int32, protobuf.Int32Value, -32),
(TestStub.get_u_int32, protobuf.UInt32Value, 32),
(TestStub.get_bool, protobuf.BoolValue, True),
(TestStub.get_string, protobuf.StringValue, "string"),
(TestStub.get_bytes, protobuf.BytesValue, bytes(0xFF)[0:4]),
]
@pytest.mark.asyncio
@pytest.mark.parametrize(["service_method", "wrapper_class", "value"], test_cases)
async def test_channel_receives_wrapped_type(
service_method: Callable[[TestStub], Any], wrapper_class: Callable, value
):
wrapped_value = wrapper_class()
wrapped_value.value = value
channel = MockChannel(responses=[wrapped_value])
service = TestStub(channel)
await service_method(service)
assert channel.requests[0]["response_type"] != Optional[type(value)]
assert channel.requests[0]["response_type"] == type(wrapped_value)
@pytest.mark.asyncio
@pytest.mark.xfail
@pytest.mark.parametrize(["service_method", "wrapper_class", "value"], test_cases)
async def test_service_unwraps_response(
service_method: Callable[[TestStub], Any], wrapper_class: Callable, value
):
"""
grpclib does not unwrap wrapper values returned by services
"""
wrapped_value = wrapper_class()
wrapped_value.value = value
service = TestStub(MockChannel(responses=[wrapped_value]))
response_value = await service_method(service)
assert response_value == value
assert type(response_value) == type(value)

View File

@@ -0,0 +1,24 @@
syntax = "proto3";
import "google/protobuf/wrappers.proto";
// Tests that wrapped values are supported as part of output message
service Test {
rpc getOutput (Input) returns (Output);
}
message Input {
}
message Output {
google.protobuf.DoubleValue double_value = 1;
google.protobuf.FloatValue float_value = 2;
google.protobuf.Int64Value int64_value = 3;
google.protobuf.UInt64Value uint64_value = 4;
google.protobuf.Int32Value int32_value = 5;
google.protobuf.UInt32Value uint32_value = 6;
google.protobuf.BoolValue bool_value = 7;
google.protobuf.StringValue string_value = 8;
google.protobuf.BytesValue bytes_value = 9;
}

View File

@@ -0,0 +1,39 @@
import pytest
from tests.mocks import MockChannel
from tests.output_betterproto.googletypes_response_embedded import (
Output,
TestStub,
)
@pytest.mark.asyncio
async def test_service_passes_through_unwrapped_values_embedded_in_response():
"""
We do not not need to implement value unwrapping for embedded well-known types,
as this is already handled by grpclib. This test merely shows that this is the case.
"""
output = Output(
double_value=10.0,
float_value=12.0,
int64_value=-13,
uint64_value=14,
int32_value=-15,
uint32_value=16,
bool_value=True,
string_value="string",
bytes_value=bytes(0xFF)[0:4],
)
service = TestStub(MockChannel(responses=[output]))
response = await service.get_output()
assert response.double_value == 10.0
assert response.float_value == 12.0
assert response.int64_value == -13
assert response.uint64_value == 14
assert response.int32_value == -15
assert response.uint32_value == 16
assert response.bool_value
assert response.string_value == "string"
assert response.bytes_value == bytes(0xFF)[0:4]

View File

@@ -0,0 +1,11 @@
syntax = "proto3";
import "google/protobuf/empty.proto";
service Test {
rpc Send (RequestMessage) returns (google.protobuf.Empty) {
}
}
message RequestMessage {
}

View File

@@ -0,0 +1,16 @@
syntax = "proto3";
import "google/protobuf/empty.proto";
import "google/protobuf/struct.proto";
// Tests that imports are generated correctly when returning Google well-known types
service Test {
rpc GetEmpty (RequestMessage) returns (google.protobuf.Empty);
rpc GetStruct (RequestMessage) returns (google.protobuf.Struct);
rpc GetListValue (RequestMessage) returns (google.protobuf.ListValue);
rpc GetValue (RequestMessage) returns (google.protobuf.Value);
}
message RequestMessage {
}

View File

@@ -0,0 +1,5 @@
{
"struct": {
"key": true
}
}

View File

@@ -0,0 +1,7 @@
syntax = "proto3";
import "google/protobuf/struct.proto";
message Test {
google.protobuf.Struct struct = 1;
}

View File

@@ -0,0 +1,11 @@
{
"value1": "hello world",
"value2": true,
"value3": 1,
"value4": null,
"value5": [
1,
2,
3
]
}

View File

@@ -0,0 +1,13 @@
syntax = "proto3";
import "google/protobuf/struct.proto";
// Tests that fields of type google.protobuf.Value can contain arbitrary JSON-values.
message Test {
google.protobuf.Value value1 = 1;
google.protobuf.Value value2 = 2;
google.protobuf.Value value3 = 3;
google.protobuf.Value value4 = 4;
google.protobuf.Value value5 = 5;
}

View File

@@ -0,0 +1,8 @@
syntax = "proto3";
package Capitalized;
message Message {
}

View File

@@ -0,0 +1,9 @@
syntax = "proto3";
import "capitalized.proto";
// Tests that we can import from a package with a capital name, that looks like a nested type, but isn't.
message Test {
Capitalized.Message message = 1;
}

View File

@@ -0,0 +1,7 @@
syntax = "proto3";
package package.childpackage;
message ChildMessage {
}

View File

@@ -0,0 +1,9 @@
syntax = "proto3";
import "package_message.proto";
// Tests generated imports when a message in a package refers to a message in a nested child package.
message Test {
package.PackageMessage message = 1;
}

View File

@@ -0,0 +1,9 @@
syntax = "proto3";
import "child.proto";
package package;
message PackageMessage {
package.childpackage.ChildMessage c = 1;
}

View File

@@ -0,0 +1,7 @@
syntax = "proto3";
package childpackage;
message Message {
}

View File

@@ -0,0 +1,9 @@
syntax = "proto3";
import "child.proto";
// Tests generated imports when a message in root refers to a message in a child package.
message Test {
childpackage.Message child = 1;
}

View File

@@ -0,0 +1,28 @@
syntax = "proto3";
import "root.proto";
import "other.proto";
// This test-case verifies support for circular dependencies in the generated python files.
//
// This is important because we generate 1 python file/module per package, rather than 1 file per proto file.
//
// Scenario:
//
// The proto messages depend on each other in a non-circular way:
//
// Test -------> RootPackageMessage <--------------.
// `------------------------------------> OtherPackageMessage
//
// Test and RootPackageMessage are in different files, but belong to the same package (root):
//
// (Test -------> RootPackageMessage) <------------.
// `------------------------------------> OtherPackageMessage
//
// After grouping the packages into single files or modules, a circular dependency is created:
//
// (root: Test & RootPackageMessage) <-------> (other: OtherPackageMessage)
message Test {
RootPackageMessage message = 1;
other.OtherPackageMessage other = 2;
}

View File

@@ -0,0 +1,8 @@
syntax = "proto3";
import "root.proto";
package other;
message OtherPackageMessage {
RootPackageMessage rootPackageMessage = 1;
}

View File

@@ -0,0 +1,5 @@
syntax = "proto3";
message RootPackageMessage {
}

View File

@@ -0,0 +1,6 @@
syntax = "proto3";
package cousin.cousin_subpackage;
message CousinMessage {
}

View File

@@ -0,0 +1,11 @@
syntax = "proto3";
package test.subpackage;
import "cousin.proto";
// Verify that we can import message unrelated to us
message Test {
cousin.cousin_subpackage.CousinMessage message = 1;
}

View File

@@ -0,0 +1,6 @@
syntax = "proto3";
package cousin.subpackage;
message CousinMessage {
}

View File

@@ -0,0 +1,11 @@
syntax = "proto3";
package test.subpackage;
import "cousin.proto";
// Verify that we can import a message unrelated to us, in a subpackage with the same name as us.
message Test {
cousin.subpackage.CousinMessage message = 1;
}

View File

@@ -0,0 +1,11 @@
syntax = "proto3";
import "users_v1.proto";
import "posts_v1.proto";
// Tests generated message can correctly reference two packages with the same leaf-name
message Test {
users.v1.User user = 1;
posts.v1.Post post = 2;
}

View File

@@ -0,0 +1,7 @@
syntax = "proto3";
package posts.v1;
message Post {
}

View File

@@ -0,0 +1,7 @@
syntax = "proto3";
package users.v1;
message User {
}

View File

@@ -0,0 +1,12 @@
syntax = "proto3";
import "parent_package_message.proto";
package parent.child;
// Tests generated imports when a message refers to a message defined in its parent package
message Test {
ParentPackageMessage message_implicit = 1;
parent.ParentPackageMessage message_explicit = 2;
}

View File

@@ -0,0 +1,6 @@
syntax = "proto3";
package parent;
message ParentPackageMessage {
}

View File

@@ -0,0 +1,11 @@
syntax = "proto3";
package child;
import "root.proto";
// Verify that we can import root message from child package
message Test {
RootMessage message = 1;
}

View File

@@ -0,0 +1,5 @@
syntax = "proto3";
message RootMessage {
}

View File

@@ -0,0 +1,9 @@
syntax = "proto3";
import "sibling.proto";
// Tests generated imports when a message in the root package refers to another message in the root package
message Test {
SiblingMessage sibling = 1;
}

View File

@@ -0,0 +1,5 @@
syntax = "proto3";
message SiblingMessage {
}

View File

@@ -0,0 +1,7 @@
syntax = "proto3";
package child;
message ChildRequestMessage {
int32 child_argument = 1;
}

View File

@@ -0,0 +1,23 @@
syntax = "proto3";
import "request_message.proto";
import "child_package_request_message.proto";
// Tests generated service correctly imports the RequestMessage
service Test {
rpc DoThing (RequestMessage) returns (RequestResponse);
rpc DoThing2 (child.ChildRequestMessage) returns (RequestResponse);
rpc DoThing3 (Nested.RequestMessage) returns (RequestResponse);
}
message RequestResponse {
int32 value = 1;
}
message Nested {
message RequestMessage {
int32 nestedArgument = 1;
}
}

View File

@@ -0,0 +1,5 @@
syntax = "proto3";
message RequestMessage {
int32 argument = 1;
}

View File

@@ -0,0 +1,31 @@
import pytest
from tests.mocks import MockChannel
from tests.output_betterproto.import_service_input_message import (
RequestResponse,
TestStub,
)
@pytest.mark.asyncio
async def test_service_correctly_imports_reference_message():
mock_response = RequestResponse(value=10)
service = TestStub(MockChannel([mock_response]))
response = await service.do_thing(argument=1)
assert mock_response == response
@pytest.mark.asyncio
async def test_service_correctly_imports_reference_message_from_child_package():
mock_response = RequestResponse(value=10)
service = TestStub(MockChannel([mock_response]))
response = await service.do_thing2(child_argument=1)
assert mock_response == response
@pytest.mark.asyncio
async def test_service_correctly_imports_nested_reference():
mock_response = RequestResponse(value=10)
service = TestStub(MockChannel([mock_response]))
response = await service.do_thing3(nested_argument=1)
assert mock_response == response

View File

@@ -0,0 +1,4 @@
{
"positive": 150,
"negative": -150
}

View File

@@ -0,0 +1,8 @@
syntax = "proto3";
// Some documentation about the Test message.
message Test {
// Some documentation about the count.
int32 positive = 1;
int32 negative = 2;
}

View File

@@ -0,0 +1,7 @@
{
"counts": {
"item1": 1,
"item2": 2,
"item3": 3
}
}

View File

@@ -0,0 +1,5 @@
syntax = "proto3";
message Test {
map<string, int32> counts = 1;
}

View File

@@ -0,0 +1,10 @@
{
"items": {
"foo": {
"count": 1
},
"bar": {
"count": 2
}
}
}

View File

@@ -0,0 +1,9 @@
syntax = "proto3";
message Test {
map<string, Nested> items = 1;
}
message Nested {
int32 count = 1;
}

View File

@@ -0,0 +1,16 @@
{
"int": "value-for-int",
"float": "value-for-float",
"complex": "value-for-complex",
"list": "value-for-list",
"tuple": "value-for-tuple",
"range": "value-for-range",
"str": "value-for-str",
"bytearray": "value-for-bytearray",
"bytes": "value-for-bytes",
"memoryview": "value-for-memoryview",
"set": "value-for-set",
"frozenset": "value-for-frozenset",
"map": "value-for-map",
"bool": "value-for-bool"
}

View File

@@ -0,0 +1,38 @@
syntax = "proto3";
// Tests that messages may contain fields with names that are python types
message Test {
// https://docs.python.org/2/library/stdtypes.html#numeric-types-int-float-long-complex
string int = 1;
string float = 2;
string complex = 3;
// https://docs.python.org/3/library/stdtypes.html#sequence-types-list-tuple-range
string list = 4;
string tuple = 5;
string range = 6;
// https://docs.python.org/3/library/stdtypes.html#str
string str = 7;
// https://docs.python.org/3/library/stdtypes.html#bytearray-objects
string bytearray = 8;
// https://docs.python.org/3/library/stdtypes.html#bytes-and-bytearray-operations
string bytes = 9;
// https://docs.python.org/3/library/stdtypes.html#memory-views
string memoryview = 10;
// https://docs.python.org/3/library/stdtypes.html#set-types-set-frozenset
string set = 11;
string frozenset = 12;
// https://docs.python.org/3/library/stdtypes.html#dict
string map = 13;
string dict = 14;
// https://docs.python.org/3/library/stdtypes.html#boolean-values
string bool = 15;
}

View File

@@ -0,0 +1,37 @@
{
"False": 1,
"None": 2,
"True": 3,
"and": 4,
"as": 5,
"assert": 6,
"async": 7,
"await": 8,
"break": 9,
"class": 10,
"continue": 11,
"def": 12,
"del": 13,
"elif": 14,
"else": 15,
"except": 16,
"finally": 17,
"for": 18,
"from": 19,
"global": 20,
"if": 21,
"import": 22,
"in": 23,
"is": 24,
"lambda": 25,
"nonlocal": 26,
"not": 27,
"or": 28,
"pass": 29,
"raise": 30,
"return": 31,
"try": 32,
"while": 33,
"with": 34,
"yield": 35
}

View File

@@ -0,0 +1,44 @@
syntax = "proto3";
// Tests that messages may contain fields that are Python keywords
//
// Generated with Python 3.7.6
// print('\n'.join(f'string {k} = {i+1};' for i,k in enumerate(keyword.kwlist)))
message Test {
string False = 1;
string None = 2;
string True = 3;
string and = 4;
string as = 5;
string assert = 6;
string async = 7;
string await = 8;
string break = 9;
string class = 10;
string continue = 11;
string def = 12;
string del = 13;
string elif = 14;
string else = 15;
string except = 16;
string finally = 17;
string for = 18;
string from = 19;
string global = 20;
string if = 21;
string import = 22;
string in = 23;
string is = 24;
string lambda = 25;
string nonlocal = 26;
string not = 27;
string or = 28;
string pass = 29;
string raise = 30;
string return = 31;
string try = 32;
string while = 33;
string with = 34;
string yield = 35;
}

View File

@@ -0,0 +1,6 @@
{
"nested": {
"count": 150
},
"sibling": {}
}

View File

@@ -0,0 +1,18 @@
syntax = "proto3";
// A test message with a nested message inside of it.
message Test {
// This is the nested type.
message Nested {
// Stores a simple counter.
int32 count = 1;
}
Nested nested = 1;
Sibling sibling = 2;
Sibling sibling2 = 3;
}
message Sibling {
int32 foo = 1;
}

View File

@@ -0,0 +1,19 @@
syntax = "proto3";
import "package.proto";
message Game {
message Player {
enum Race {
human = 0;
orc = 1;
}
}
}
message Test {
Game game = 1;
Game.Player GamePlayer = 2;
Game.Player.Race GamePlayerRace = 3;
equipment.Weapon Weapon = 4;
}

View File

@@ -0,0 +1,7 @@
syntax = "proto3";
package equipment;
message Weapon {
}

View File

@@ -0,0 +1,11 @@
{
"top": {
"name": "double-nested",
"middle": {
"bottom": [{"foo": "hello"}],
"enumBottom": ["A"],
"topMiddleBottom": [{"a": "hello"}],
"bar": true
}
}
}

View File

@@ -0,0 +1,26 @@
syntax = "proto3";
message Test {
message Top {
message Middle {
message TopMiddleBottom {
string a = 1;
}
enum EnumBottom{
A = 0;
B = 1;
}
message Bottom {
string foo = 1;
}
reserved 1;
repeated Bottom bottom = 2;
repeated EnumBottom enumBottom=3;
repeated TopMiddleBottom topMiddleBottom=4;
bool bar = 5;
}
string name = 1;
Middle middle = 2;
}
Top top = 1;
}

View File

@@ -0,0 +1,3 @@
{
"name": "foobar"
}

View File

@@ -0,0 +1,3 @@
{
"count": 100
}

View File

@@ -0,0 +1,8 @@
syntax = "proto3";
message Test {
oneof foo {
int32 count = 1;
string name = 2;
}
}

View File

@@ -0,0 +1,15 @@
import betterproto
from tests.output_betterproto.oneof import Test
from tests.util import get_test_case_json_data
def test_which_count():
message = Test()
message.from_json(get_test_case_json_data("oneof"))
assert betterproto.which_one_of(message, "foo") == ("count", 100)
def test_which_name():
message = Test()
message.from_json(get_test_case_json_data("oneof", "oneof-name.json"))
assert betterproto.which_one_of(message, "foo") == ("name", "foobar")

View File

@@ -0,0 +1,3 @@
{
"signal": "PASS"
}

View File

@@ -0,0 +1,3 @@
{
"signal": "RESIGN"
}

View File

@@ -0,0 +1,6 @@
{
"move": {
"x": 2,
"y": 3
}
}

View File

@@ -0,0 +1,18 @@
syntax = "proto3";
message Test {
oneof action {
Signal signal = 1;
Move move = 2;
}
}
enum Signal {
PASS = 0;
RESIGN = 1;
}
message Move {
int32 x = 1;
int32 y = 2;
}

View File

@@ -0,0 +1,42 @@
import pytest
import betterproto
from tests.output_betterproto.oneof_enum import (
Move,
Signal,
Test,
)
from tests.util import get_test_case_json_data
@pytest.mark.xfail
def test_which_one_of_returns_enum_with_default_value():
"""
returns first field when it is enum and set with default value
"""
message = Test()
message.from_json(get_test_case_json_data("oneof_enum", "oneof_enum-enum-0.json"))
assert message.move is None
assert message.signal == Signal.PASS
assert betterproto.which_one_of(message, "action") == ("signal", Signal.PASS)
@pytest.mark.xfail
def test_which_one_of_returns_enum_with_non_default_value():
"""
returns first field when it is enum and set with non default value
"""
message = Test()
message.from_json(get_test_case_json_data("oneof_enum", "oneof_enum-enum-1.json"))
assert message.move is None
assert message.signal == Signal.PASS
assert betterproto.which_one_of(message, "action") == ("signal", Signal.RESIGN)
@pytest.mark.xfail
def test_which_one_of_returns_second_field_when_set():
message = Test()
message.from_json(get_test_case_json_data("oneof_enum"))
assert message.move == Move(x=2, y=3)
assert message.signal == 0
assert betterproto.which_one_of(message, "action") == ("move", Move(x=2, y=3))

View File

@@ -0,0 +1,5 @@
{
"greeting": {
"greeting": "hello"
}
}

View File

@@ -0,0 +1,7 @@
syntax = "proto3";
import "repeatedmessage.proto";
message Test {
repeatedmessage.Sub greeting = 1;
}

View File

@@ -0,0 +1,11 @@
syntax = "proto3";
package repeatedmessage;
message Test {
repeated Sub greetings = 1;
}
message Sub {
string greeting = 1;
}

View File

@@ -0,0 +1,3 @@
{
"names": ["one", "two", "three"]
}

View File

@@ -0,0 +1,5 @@
syntax = "proto3";
message Test {
repeated string names = 1;
}

View File

@@ -0,0 +1,10 @@
{
"greetings": [
{
"greeting": "hello"
},
{
"greeting": "hi"
}
]
}

View File

@@ -0,0 +1,11 @@
syntax = "proto3";
package repeatedmessage;
message Test {
repeated Sub greetings = 1;
}
message Sub {
string greeting = 1;
}

View File

@@ -0,0 +1,5 @@
{
"counts": [1, 2, -1, -2],
"signed": ["1", "2", "-1", "-2"],
"fixed": [1.0, 2.7, 3.4]
}

View File

@@ -0,0 +1,7 @@
syntax = "proto3";
message Test {
repeated int32 counts = 1;
repeated sint64 signed = 2;
repeated double fixed = 3;
}

View File

@@ -0,0 +1,27 @@
syntax = "proto3";
package service;
message DoThingRequest {
string name = 1;
}
message DoThingResponse {
repeated string names = 1;
}
message GetThingRequest {
string name = 1;
}
message GetThingResponse {
string name = 1;
int32 version = 2;
}
service Test {
rpc DoThing (DoThingRequest) returns (DoThingResponse);
rpc DoManyThings (stream DoThingRequest) returns (DoThingResponse);
rpc GetThingVersions (GetThingRequest) returns (stream GetThingResponse);
rpc GetDifferentThings (stream GetThingRequest) returns (stream GetThingResponse);
}

View File

@@ -0,0 +1,6 @@
{
"signed32": 150,
"negative32": -150,
"string64": "150",
"negative64": "-150"
}

View File

@@ -0,0 +1,9 @@
syntax = "proto3";
message Test {
// todo: rename fields after fixing bug where 'signed_32_positive' will map to 'signed_32Positive' as output json
sint32 signed32 = 1; // signed_32_positive
sint32 negative32 = 2; // signed_32_negative
sint64 string64 = 3; // signed_64_positive
sint64 negative64 = 4; // signed_64_negative
}