-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support json names in field mask generation (#1050)
* Support json names in field mask generation Added tests for using jsonpb with OrigName: false Added benchmarks for FieldMaskFromRequestBody called with a message descriptor * Add descriptor dependency to go_proto_library
- Loading branch information
1 parent
a8afee1
commit 8eb1d0f
Showing
18 changed files
with
285 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
package integration_test | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/golang/protobuf/descriptor" | ||
"github.com/grpc-ecosystem/grpc-gateway/examples/proto/examplepb" | ||
"github.com/grpc-ecosystem/grpc-gateway/runtime" | ||
"google.golang.org/genproto/protobuf/field_mask" | ||
) | ||
|
||
func fieldMasksEqual(fm1, fm2 *field_mask.FieldMask) bool { | ||
if fm1 == nil && fm2 == nil { | ||
return true | ||
} | ||
if fm1 == nil || fm2 == nil { | ||
return false | ||
} | ||
if len(fm1.GetPaths()) != len(fm2.GetPaths()) { | ||
return false | ||
} | ||
|
||
paths := make(map[string]bool) | ||
for _, path := range fm1.GetPaths() { | ||
paths[path] = true | ||
} | ||
for _, path := range fm2.GetPaths() { | ||
if _, ok := paths[path]; !ok { | ||
return false | ||
} | ||
} | ||
|
||
return true | ||
} | ||
|
||
func newFieldMask(paths ...string) *field_mask.FieldMask { | ||
return &field_mask.FieldMask{Paths: paths} | ||
} | ||
|
||
func fieldMaskString(fm *field_mask.FieldMask) string { | ||
if fm == nil { | ||
return "" | ||
} | ||
return fmt.Sprintf("%v", fm.GetPaths()) | ||
} | ||
|
||
// N.B. These tests are here rather than in the runtime package because they need | ||
// to import examplepb for the descriptor, which would result in a circular | ||
// dependency since examplepb imports runtime from the pb.gw.go files | ||
func TestFieldMaskFromRequestBodyWithDescriptor(t *testing.T) { | ||
_, md := descriptor.ForMessage(new(examplepb.NonStandardMessage)) | ||
jsonInput := `{"id":"foo", "thing":{"subThing":{"sub_value":"bar"}}}` | ||
expected := newFieldMask("id", "thing.subThing.sub_value") | ||
|
||
actual, err := runtime.FieldMaskFromRequestBody(bytes.NewReader([]byte(jsonInput)), md) | ||
if !fieldMasksEqual(actual, expected) { | ||
t.Errorf("want %v; got %v", fieldMaskString(expected), fieldMaskString(actual)) | ||
} | ||
if err != nil { | ||
t.Errorf("err %v", err) | ||
} | ||
} | ||
|
||
func TestFieldMaskFromRequestBodyWithJsonNames(t *testing.T) { | ||
_, md := descriptor.ForMessage(new(examplepb.NonStandardMessageWithJSONNames)) | ||
jsonInput := `{"ID":"foo", "Thingy":{"SubThing":{"sub_Value":"bar"}}}` | ||
expected := newFieldMask("id", "thing.subThing.sub_value") | ||
|
||
actual, err := runtime.FieldMaskFromRequestBody(bytes.NewReader([]byte(jsonInput)), md) | ||
if !fieldMasksEqual(actual, expected) { | ||
t.Errorf("want %v; got %v", fieldMaskString(expected), fieldMaskString(actual)) | ||
} | ||
if err != nil { | ||
t.Errorf("err %v", err) | ||
} | ||
} | ||
|
||
// avoid compiler optimising benchmark away | ||
var result *field_mask.FieldMask | ||
|
||
func BenchmarkABEFieldMaskFromRequestBodyWithDescriptor(b *testing.B) { | ||
_, md := descriptor.ForMessage(new(examplepb.ABitOfEverything)) | ||
input := `{` + | ||
`"single_nested": {"name": "bar",` + | ||
` "amount": 10,` + | ||
` "ok": "TRUE"},` + | ||
`"uuid": "6EC2446F-7E89-4127-B3E6-5C05E6BECBA7",` + | ||
`"nested": [{"name": "bar",` + | ||
` "amount": 10},` + | ||
` {"name": "baz",` + | ||
` "amount": 20}],` + | ||
`"float_value": 1.5,` + | ||
`"double_value": 2.5,` + | ||
`"int64_value": 4294967296,` + | ||
`"uint64_value": 9223372036854775807,` + | ||
`"int32_value": -2147483648,` + | ||
`"fixed64_value": 9223372036854775807,` + | ||
`"fixed32_value": 4294967295,` + | ||
`"bool_value": true,` + | ||
`"string_value": "strprefix/foo",` + | ||
`"bytes_value": "132456",` + | ||
`"uint32_value": 4294967295,` + | ||
`"enum_value": "ONE",` + | ||
`"path_enum_value": "DEF",` + | ||
`"nested_path_enum_value": "JKL",` + | ||
`"sfixed32_value": 2147483647,` + | ||
`"sfixed64_value": -4611686018427387904,` + | ||
`"sint32_value": 2147483647,` + | ||
`"sint64_value": 4611686018427387903,` + | ||
`"repeated_string_value": ["a", "b", "c"],` + | ||
`"oneof_value": {"oneof_string":"x"},` + | ||
`"map_value": {"a": "ONE",` + | ||
` "b": "ZERO"},` + | ||
`"mapped_string_value": {"a": "x",` + | ||
` "b": "y"},` + | ||
`"mapped_nested_value": {"a": {"name": "x", "amount": 1},` + | ||
` "b": {"name": "y", "amount": 2}},` + | ||
`"nonConventionalNameValue": "camelCase",` + | ||
`"timestamp_value": "2016-05-10T10:19:13.123Z",` + | ||
`"repeated_enum_value": ["ONE", "ZERO"],` + | ||
`"repeated_enum_annotation": ["ONE", "ZERO"],` + | ||
`"enum_value_annotation": "ONE",` + | ||
`"repeated_string_annotation": ["a", "b"],` + | ||
`"repeated_nested_annotation": [{"name": "hoge",` + | ||
` "amount": 10},` + | ||
` {"name": "fuga",` + | ||
` "amount": 20}],` + | ||
`"nested_annotation": {"name": "hoge",` + | ||
` "amount": 10},` + | ||
`"int64_override_type": 12345` + | ||
`}` | ||
var r *field_mask.FieldMask | ||
var err error | ||
for i := 0; i < b.N; i++ { | ||
r, err = runtime.FieldMaskFromRequestBody(bytes.NewReader([]byte(input)), md) | ||
} | ||
if err != nil { | ||
b.Error(err) | ||
} | ||
result = r | ||
} | ||
|
||
func BenchmarkNonStandardFieldMaskFromRequestBodyWithDescriptor(b *testing.B) { | ||
_, md := descriptor.ForMessage(new(examplepb.NonStandardMessage)) | ||
input := `{` + | ||
`"id": "foo",` + | ||
`"Num": 2,` + | ||
`"line_num": 3,` + | ||
`"langIdent": "bar",` + | ||
`"STATUS": "baz"` + | ||
`}` | ||
var r *field_mask.FieldMask | ||
var err error | ||
for i := 0; i < b.N; i++ { | ||
r, err = runtime.FieldMaskFromRequestBody(bytes.NewReader([]byte(input)), md) | ||
} | ||
if err != nil { | ||
b.Error(err) | ||
} | ||
result = r | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.