1 package runtime
2
3 import (
4 "bytes"
5 "fmt"
6 "testing"
7
8 "google.golang.org/genproto/protobuf/field_mask"
9 )
10
11 func fieldMasksEqual(fm1, fm2 *field_mask.FieldMask) bool {
12 if fm1 == nil && fm2 == nil {
13 return true
14 }
15 if fm1 == nil || fm2 == nil {
16 return false
17 }
18 if len(fm1.GetPaths()) != len(fm2.GetPaths()) {
19 return false
20 }
21
22 paths := make(map[string]bool)
23 for _, path := range fm1.GetPaths() {
24 paths[path] = true
25 }
26 for _, path := range fm2.GetPaths() {
27 if _, ok := paths[path]; !ok {
28 return false
29 }
30 }
31
32 return true
33 }
34
35 func newFieldMask(paths ...string) *field_mask.FieldMask {
36 return &field_mask.FieldMask{Paths: paths}
37 }
38
39 func fieldMaskString(fm *field_mask.FieldMask) string {
40 if fm == nil {
41 return ""
42 }
43 return fmt.Sprintf("%v", fm.GetPaths())
44 }
45
46 func TestFieldMaskFromRequestBody(t *testing.T) {
47 for _, tc := range []struct {
48 name string
49 input string
50 expected *field_mask.FieldMask
51 expectedErr error
52 }{
53 {name: "empty", expected: newFieldMask()},
54 {name: "simple", input: `{"foo":1, "bar":"baz"}`, expected: newFieldMask("foo", "bar")},
55 {name: "nested", input: `{"foo": {"bar":1, "baz": 2}, "qux": 3}`, expected: newFieldMask("foo.bar", "foo.baz", "qux")},
56 {name: "canonical", input: `{"f": {"b": {"d": 1, "x": 2}, "c": 1}}`, expected: newFieldMask("f.b.d", "f.b.x", "f.c")},
57 {name: "deeply-nested", input: `{"foo": {"bar": {"baz": {"a": 1, "b": 2}}}}`, expected: newFieldMask("foo.bar.baz.a", "foo.bar.baz.b")},
58 } {
59 t.Run(tc.name, func(t *testing.T) {
60 actual, err := FieldMaskFromRequestBody(bytes.NewReader([]byte(tc.input)), nil)
61 if !fieldMasksEqual(actual, tc.expected) {
62 t.Errorf("want %v; got %v", fieldMaskString(tc.expected), fieldMaskString(actual))
63 }
64 if err != tc.expectedErr {
65 t.Errorf("want %v; got %v", tc.expectedErr, err)
66 }
67 })
68 }
69 }
70
71
72 var result *field_mask.FieldMask
73
74 func BenchmarkABEFieldMaskFromRequestBody(b *testing.B) {
75 input := `{` +
76 `"single_nested": {"name": "bar",` +
77 ` "amount": 10,` +
78 ` "ok": "TRUE"},` +
79 `"uuid": "6EC2446F-7E89-4127-B3E6-5C05E6BECBA7",` +
80 `"nested": [{"name": "bar",` +
81 ` "amount": 10},` +
82 ` {"name": "baz",` +
83 ` "amount": 20}],` +
84 `"float_value": 1.5,` +
85 `"double_value": 2.5,` +
86 `"int64_value": 4294967296,` +
87 `"uint64_value": 9223372036854775807,` +
88 `"int32_value": -2147483648,` +
89 `"fixed64_value": 9223372036854775807,` +
90 `"fixed32_value": 4294967295,` +
91 `"bool_value": true,` +
92 `"string_value": "strprefix/foo",` +
93 `"bytes_value": "132456",` +
94 `"uint32_value": 4294967295,` +
95 `"enum_value": "ONE",` +
96 `"path_enum_value": "DEF",` +
97 `"nested_path_enum_value": "JKL",` +
98 `"sfixed32_value": 2147483647,` +
99 `"sfixed64_value": -4611686018427387904,` +
100 `"sint32_value": 2147483647,` +
101 `"sint64_value": 4611686018427387903,` +
102 `"repeated_string_value": ["a", "b", "c"],` +
103 `"oneof_value": {"oneof_string":"x"},` +
104 `"map_value": {"a": "ONE",` +
105 ` "b": "ZERO"},` +
106 `"mapped_string_value": {"a": "x",` +
107 ` "b": "y"},` +
108 `"mapped_nested_value": {"a": {"name": "x", "amount": 1},` +
109 ` "b": {"name": "y", "amount": 2}},` +
110 `"nonConventionalNameValue": "camelCase",` +
111 `"timestamp_value": "2016-05-10T10:19:13.123Z",` +
112 `"repeated_enum_value": ["ONE", "ZERO"],` +
113 `"repeated_enum_annotation": ["ONE", "ZERO"],` +
114 `"enum_value_annotation": "ONE",` +
115 `"repeated_string_annotation": ["a", "b"],` +
116 `"repeated_nested_annotation": [{"name": "hoge",` +
117 ` "amount": 10},` +
118 ` {"name": "fuga",` +
119 ` "amount": 20}],` +
120 `"nested_annotation": {"name": "hoge",` +
121 ` "amount": 10},` +
122 `"int64_override_type": 12345` +
123 `}`
124 var r *field_mask.FieldMask
125 var err error
126 for i := 0; i < b.N; i++ {
127 r, err = FieldMaskFromRequestBody(bytes.NewReader([]byte(input)), nil)
128 }
129 if err != nil {
130 b.Error(err)
131 }
132 result = r
133 }
134
135 func BenchmarkNonStandardFieldMaskFromRequestBody(b *testing.B) {
136 input := `{` +
137 `"id": "foo",` +
138 `"Num": 2,` +
139 `"line_num": 3,` +
140 `"langIdent": "bar",` +
141 `"STATUS": "baz"` +
142 `}`
143 var r *field_mask.FieldMask
144 var err error
145 for i := 0; i < b.N; i++ {
146 r, err = FieldMaskFromRequestBody(bytes.NewReader([]byte(input)), nil)
147 }
148 if err != nil {
149 b.Error(err)
150 }
151 result = r
152 }
153
View as plain text