blob: 55f3e77a1ae8d20bd56664700c7521ffc7186ed3 [file] [log] [blame]
Herbie Ongcddf8192018-11-28 18:25:20 -08001// Copyright 2018 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package textpb_test
6
7import (
8 "math"
9 "strings"
10 "testing"
11
12 "github.com/golang/protobuf/v2/encoding/textpb"
Herbie Ongcddf8192018-11-28 18:25:20 -080013 "github.com/golang/protobuf/v2/internal/detrand"
Herbie Ong20a1d312018-12-11 21:08:58 -080014 "github.com/golang/protobuf/v2/internal/encoding/pack"
Herbie Ongcddf8192018-11-28 18:25:20 -080015 "github.com/golang/protobuf/v2/internal/scalar"
16 "github.com/golang/protobuf/v2/proto"
17 "github.com/google/go-cmp/cmp"
18 "github.com/google/go-cmp/cmp/cmpopts"
19
Joe Tsai08e00302018-11-26 22:32:06 -080020 // The legacy package must be imported prior to use of any legacy messages.
21 // TODO: Remove this when protoV1 registers these hooks for you.
22 _ "github.com/golang/protobuf/v2/internal/legacy"
23
Joe Tsai08e00302018-11-26 22:32:06 -080024 "github.com/golang/protobuf/v2/encoding/textpb/testprotos/pb2"
25 "github.com/golang/protobuf/v2/encoding/textpb/testprotos/pb3"
Herbie Ongcddf8192018-11-28 18:25:20 -080026)
27
28func init() {
29 // Disable detrand to enable direct comparisons on outputs.
30 detrand.Disable()
31}
32
Herbie Ongcddf8192018-11-28 18:25:20 -080033// splitLines is a cmpopts.Option for comparing strings with line breaks.
34var splitLines = cmpopts.AcyclicTransformer("SplitLines", func(s string) []string {
35 return strings.Split(s, "\n")
36})
37
Herbie Ong800c9902018-12-06 15:28:53 -080038func pb2Enum(i int32) *pb2.Enum {
39 p := new(pb2.Enum)
40 *p = pb2.Enum(i)
41 return p
42}
43
44func pb2Enums_NestedEnum(i int32) *pb2.Enums_NestedEnum {
45 p := new(pb2.Enums_NestedEnum)
46 *p = pb2.Enums_NestedEnum(i)
47 return p
48}
49
Herbie Ongcddf8192018-11-28 18:25:20 -080050func TestMarshal(t *testing.T) {
51 tests := []struct {
52 desc string
Herbie Ong70651952018-12-13 14:19:50 -080053 input proto.Message
Herbie Ongcddf8192018-11-28 18:25:20 -080054 want string
55 wantErr bool
56 }{{
Herbie Ongcddf8192018-11-28 18:25:20 -080057 desc: "proto2 optional scalar fields not set",
Herbie Ong800c9902018-12-06 15:28:53 -080058 input: &pb2.Scalars{},
Herbie Ongcddf8192018-11-28 18:25:20 -080059 want: "\n",
60 }, {
61 desc: "proto3 scalar fields not set",
Herbie Ong800c9902018-12-06 15:28:53 -080062 input: &pb3.Scalars{},
Herbie Ongcddf8192018-11-28 18:25:20 -080063 want: "\n",
64 }, {
65 desc: "proto2 optional scalar fields set to zero values",
Herbie Ong800c9902018-12-06 15:28:53 -080066 input: &pb2.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -080067 OptBool: scalar.Bool(false),
68 OptInt32: scalar.Int32(0),
69 OptInt64: scalar.Int64(0),
70 OptUint32: scalar.Uint32(0),
71 OptUint64: scalar.Uint64(0),
72 OptSint32: scalar.Int32(0),
73 OptSint64: scalar.Int64(0),
74 OptFixed32: scalar.Uint32(0),
75 OptFixed64: scalar.Uint64(0),
76 OptSfixed32: scalar.Int32(0),
77 OptSfixed64: scalar.Int64(0),
78 OptFloat: scalar.Float32(0),
79 OptDouble: scalar.Float64(0),
80 OptBytes: []byte{},
81 OptString: scalar.String(""),
Herbie Ong800c9902018-12-06 15:28:53 -080082 },
Herbie Ongcddf8192018-11-28 18:25:20 -080083 want: `opt_bool: false
84opt_int32: 0
85opt_int64: 0
86opt_uint32: 0
87opt_uint64: 0
88opt_sint32: 0
89opt_sint64: 0
90opt_fixed32: 0
91opt_fixed64: 0
92opt_sfixed32: 0
93opt_sfixed64: 0
94opt_float: 0
95opt_double: 0
96opt_bytes: ""
97opt_string: ""
98`,
99 }, {
100 desc: "proto3 scalar fields set to zero values",
Herbie Ong800c9902018-12-06 15:28:53 -0800101 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800102 SBool: false,
103 SInt32: 0,
104 SInt64: 0,
105 SUint32: 0,
106 SUint64: 0,
107 SSint32: 0,
108 SSint64: 0,
109 SFixed32: 0,
110 SFixed64: 0,
111 SSfixed32: 0,
112 SSfixed64: 0,
113 SFloat: 0,
114 SDouble: 0,
115 SBytes: []byte{},
116 SString: "",
Herbie Ong800c9902018-12-06 15:28:53 -0800117 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800118 want: "\n",
119 }, {
120 desc: "proto2 optional scalar fields set to some values",
Herbie Ong800c9902018-12-06 15:28:53 -0800121 input: &pb2.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800122 OptBool: scalar.Bool(true),
123 OptInt32: scalar.Int32(0xff),
124 OptInt64: scalar.Int64(0xdeadbeef),
125 OptUint32: scalar.Uint32(47),
126 OptUint64: scalar.Uint64(0xdeadbeef),
127 OptSint32: scalar.Int32(-1001),
128 OptSint64: scalar.Int64(-0xffff),
129 OptFixed64: scalar.Uint64(64),
130 OptSfixed32: scalar.Int32(-32),
131 // TODO: Update encoder to output same decimals.
132 OptFloat: scalar.Float32(1.02),
133 OptDouble: scalar.Float64(1.23e100),
134 // TODO: Update encoder to not output UTF8 for bytes.
135 OptBytes: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
136 OptString: scalar.String("谷歌"),
Herbie Ong800c9902018-12-06 15:28:53 -0800137 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800138 want: `opt_bool: true
139opt_int32: 255
140opt_int64: 3735928559
141opt_uint32: 47
142opt_uint64: 3735928559
143opt_sint32: -1001
144opt_sint64: -65535
145opt_fixed64: 64
146opt_sfixed32: -32
147opt_float: 1.0199999809265137
148opt_double: 1.23e+100
149opt_bytes: "谷歌"
150opt_string: "谷歌"
151`,
152 }, {
Herbie Ongcddf8192018-11-28 18:25:20 -0800153 desc: "float32 nan",
Herbie Ong800c9902018-12-06 15:28:53 -0800154 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800155 SFloat: float32(math.NaN()),
Herbie Ong800c9902018-12-06 15:28:53 -0800156 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800157 want: "s_float: nan\n",
158 }, {
159 desc: "float32 positive infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800160 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800161 SFloat: float32(math.Inf(1)),
Herbie Ong800c9902018-12-06 15:28:53 -0800162 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800163 want: "s_float: inf\n",
164 }, {
165 desc: "float32 negative infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800166 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800167 SFloat: float32(math.Inf(-1)),
Herbie Ong800c9902018-12-06 15:28:53 -0800168 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800169 want: "s_float: -inf\n",
170 }, {
171 desc: "float64 nan",
Herbie Ong800c9902018-12-06 15:28:53 -0800172 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800173 SDouble: math.NaN(),
Herbie Ong800c9902018-12-06 15:28:53 -0800174 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800175 want: "s_double: nan\n",
176 }, {
177 desc: "float64 positive infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800178 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800179 SDouble: math.Inf(1),
Herbie Ong800c9902018-12-06 15:28:53 -0800180 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800181 want: "s_double: inf\n",
182 }, {
183 desc: "float64 negative infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800184 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800185 SDouble: math.Inf(-1),
Herbie Ong800c9902018-12-06 15:28:53 -0800186 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800187 want: "s_double: -inf\n",
188 }, {
189 desc: "proto2 bytes set to empty string",
Herbie Ong800c9902018-12-06 15:28:53 -0800190 input: &pb2.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800191 OptBytes: []byte(""),
Herbie Ong800c9902018-12-06 15:28:53 -0800192 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800193 want: "opt_bytes: \"\"\n",
194 }, {
195 desc: "proto3 bytes set to empty string",
Herbie Ong800c9902018-12-06 15:28:53 -0800196 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800197 SBytes: []byte(""),
Herbie Ong800c9902018-12-06 15:28:53 -0800198 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800199 want: "\n",
200 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800201 desc: "proto2 enum not set",
202 input: &pb2.Enums{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800203 want: "\n",
204 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800205 desc: "proto2 enum set to zero value",
206 input: &pb2.Enums{
207 OptEnum: pb2.Enum_UNKNOWN.Enum(),
208 OptNestedEnum: pb2Enums_NestedEnum(0),
209 },
210 want: `opt_enum: UNKNOWN
211opt_nested_enum: 0
212`,
213 }, {
214 desc: "proto2 enum",
215 input: &pb2.Enums{
216 OptEnum: pb2.Enum_FIRST.Enum(),
217 OptNestedEnum: pb2.Enums_UNO.Enum(),
218 },
219 want: `opt_enum: FIRST
220opt_nested_enum: UNO
221`,
222 }, {
223 desc: "proto2 enum set to numeric values",
224 input: &pb2.Enums{
225 OptEnum: pb2Enum(1),
226 OptNestedEnum: pb2Enums_NestedEnum(2),
227 },
228 want: `opt_enum: FIRST
229opt_nested_enum: DOS
230`,
231 }, {
232 desc: "proto2 enum set to unnamed numeric values",
233 input: &pb2.Enums{
234 OptEnum: pb2Enum(101),
235 OptNestedEnum: pb2Enums_NestedEnum(-101),
236 },
237 want: `opt_enum: 101
238opt_nested_enum: -101
239`,
240 }, {
241 desc: "proto3 enum not set",
242 input: &pb3.Enums{},
243 want: "\n",
244 }, {
245 desc: "proto3 enum set to zero value",
246 input: &pb3.Enums{
247 SEnum: pb3.Enum_ZERO,
248 SNestedEnum: pb3.Enums_CERO,
249 },
250 want: "\n",
251 }, {
252 desc: "proto3 enum",
253 input: &pb3.Enums{
254 SEnum: pb3.Enum_ONE,
255 SNestedEnum: pb3.Enums_DIEZ,
256 },
257 want: `s_enum: ONE
258s_nested_enum: DIEZ
259`,
260 }, {
261 desc: "proto3 enum set to numeric values",
262 input: &pb3.Enums{
263 SEnum: 2,
264 SNestedEnum: 1,
265 },
266 want: `s_enum: TWO
267s_nested_enum: UNO
268`,
269 }, {
270 desc: "proto3 enum set to unnamed numeric values",
271 input: &pb3.Enums{
272 SEnum: -47,
273 SNestedEnum: 47,
274 },
275 want: `s_enum: -47
276s_nested_enum: 47
277`,
278 }, {
279 desc: "proto2 nested message not set",
280 input: &pb2.Nests{},
281 want: "\n",
282 }, {
283 desc: "proto2 nested message set to empty",
284 input: &pb2.Nests{
285 OptNested: &pb2.Nested{},
286 Optgroup: &pb2.Nests_OptGroup{},
287 },
288 want: `opt_nested: {}
289optgroup: {}
290`,
291 }, {
292 desc: "proto2 nested messages",
293 input: &pb2.Nests{
294 OptNested: &pb2.Nested{
295 OptString: scalar.String("nested message"),
296 OptNested: &pb2.Nested{
297 OptString: scalar.String("another nested message"),
298 },
299 },
300 },
301 want: `opt_nested: {
302 opt_string: "nested message"
303 opt_nested: {
304 opt_string: "another nested message"
305 }
306}
307`,
308 }, {
309 desc: "proto2 group fields",
310 input: &pb2.Nests{
311 Optgroup: &pb2.Nests_OptGroup{
312 OptBool: scalar.Bool(true),
313 OptString: scalar.String("inside a group"),
314 OptNested: &pb2.Nested{
315 OptString: scalar.String("nested message inside a group"),
316 },
317 Optnestedgroup: &pb2.Nests_OptGroup_OptNestedGroup{
318 OptEnum: pb2.Enum_TENTH.Enum(),
319 },
320 },
321 },
322 want: `optgroup: {
323 opt_bool: true
324 opt_string: "inside a group"
325 opt_nested: {
326 opt_string: "nested message inside a group"
327 }
328 optnestedgroup: {
329 opt_enum: TENTH
330 }
331}
332`,
333 }, {
334 desc: "proto3 nested message not set",
335 input: &pb3.Nests{},
336 want: "\n",
337 }, {
338 desc: "proto3 nested message",
339 input: &pb3.Nests{
340 SNested: &pb3.Nested{
341 SString: "nested message",
342 SNested: &pb3.Nested{
343 SString: "another nested message",
344 },
345 },
346 },
347 want: `s_nested: {
348 s_string: "nested message"
349 s_nested: {
350 s_string: "another nested message"
351 }
352}
353`,
354 }, {
355 desc: "oneof fields",
356 input: &pb2.Oneofs{},
357 want: "\n",
358 }, {
359 desc: "oneof field set to empty string",
360 input: &pb2.Oneofs{
361 Union: &pb2.Oneofs_Str{},
362 },
363 want: "str: \"\"\n",
364 }, {
365 desc: "oneof field set to string",
366 input: &pb2.Oneofs{
367 Union: &pb2.Oneofs_Str{
368 Str: "hello",
369 },
370 },
371 want: "str: \"hello\"\n",
372 }, {
373 desc: "oneof field set to empty message",
374 input: &pb2.Oneofs{
375 Union: &pb2.Oneofs_Msg{
376 Msg: &pb2.Nested{},
377 },
378 },
379 want: "msg: {}\n",
380 }, {
381 desc: "oneof field set to message",
382 input: &pb2.Oneofs{
383 Union: &pb2.Oneofs_Msg{
384 Msg: &pb2.Nested{
385 OptString: scalar.String("nested message"),
386 },
387 },
388 },
389 want: `msg: {
390 opt_string: "nested message"
391}
392`,
393 }, {
394 desc: "repeated not set",
395 input: &pb2.Repeats{},
396 want: "\n",
397 }, {
398 desc: "repeated set to empty slices",
399 input: &pb2.Repeats{
Herbie Ongcddf8192018-11-28 18:25:20 -0800400 RptBool: []bool{},
401 RptInt32: []int32{},
402 RptInt64: []int64{},
403 RptUint32: []uint32{},
404 RptUint64: []uint64{},
405 RptFloat: []float32{},
406 RptDouble: []float64{},
407 RptBytes: [][]byte{},
Herbie Ong800c9902018-12-06 15:28:53 -0800408 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800409 want: "\n",
410 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800411 desc: "repeated set to some values",
412 input: &pb2.Repeats{
Herbie Ongcddf8192018-11-28 18:25:20 -0800413 RptBool: []bool{true, false, true, true},
414 RptInt32: []int32{1, 6, 0, 0},
415 RptInt64: []int64{-64, 47},
416 RptUint32: []uint32{0xff, 0xffff},
417 RptUint64: []uint64{0xdeadbeef},
418 // TODO: add float32 examples.
419 RptDouble: []float64{math.NaN(), math.Inf(1), math.Inf(-1), 1.23e-308},
420 RptString: []string{"hello", "世界"},
421 RptBytes: [][]byte{
422 []byte("hello"),
423 []byte("\xe4\xb8\x96\xe7\x95\x8c"),
424 },
Herbie Ong800c9902018-12-06 15:28:53 -0800425 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800426 want: `rpt_bool: true
427rpt_bool: false
428rpt_bool: true
429rpt_bool: true
430rpt_int32: 1
431rpt_int32: 6
432rpt_int32: 0
433rpt_int32: 0
434rpt_int64: -64
435rpt_int64: 47
436rpt_uint32: 255
437rpt_uint32: 65535
438rpt_uint64: 3735928559
439rpt_double: nan
440rpt_double: inf
441rpt_double: -inf
442rpt_double: 1.23e-308
443rpt_string: "hello"
444rpt_string: "世界"
445rpt_bytes: "hello"
446rpt_bytes: "世界"
447`,
448 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800449 desc: "repeated enum",
450 input: &pb2.Enums{
Herbie Ongcddf8192018-11-28 18:25:20 -0800451 RptEnum: []pb2.Enum{pb2.Enum_FIRST, 2, pb2.Enum_TENTH, 42},
Herbie Ongcddf8192018-11-28 18:25:20 -0800452 RptNestedEnum: []pb2.Enums_NestedEnum{2, 47, 10},
Herbie Ong800c9902018-12-06 15:28:53 -0800453 },
454 want: `rpt_enum: FIRST
Herbie Ongcddf8192018-11-28 18:25:20 -0800455rpt_enum: SECOND
456rpt_enum: TENTH
457rpt_enum: 42
Herbie Ongcddf8192018-11-28 18:25:20 -0800458rpt_nested_enum: DOS
459rpt_nested_enum: 47
460rpt_nested_enum: DIEZ
461`,
462 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800463 desc: "repeated nested message set to empty",
464 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800465 RptNested: []*pb2.Nested{},
466 Rptgroup: []*pb2.Nests_RptGroup{},
Herbie Ong800c9902018-12-06 15:28:53 -0800467 },
468 want: "\n",
Herbie Ongcddf8192018-11-28 18:25:20 -0800469 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800470 desc: "repeated nested messages",
471 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800472 RptNested: []*pb2.Nested{
473 {
474 OptString: scalar.String("repeat nested one"),
475 },
476 {
477 OptString: scalar.String("repeat nested two"),
478 OptNested: &pb2.Nested{
479 OptString: scalar.String("inside repeat nested two"),
480 },
481 },
482 {},
483 },
Herbie Ong800c9902018-12-06 15:28:53 -0800484 },
485 want: `rpt_nested: {
Herbie Ongcddf8192018-11-28 18:25:20 -0800486 opt_string: "repeat nested one"
487}
488rpt_nested: {
489 opt_string: "repeat nested two"
490 opt_nested: {
491 opt_string: "inside repeat nested two"
492 }
493}
494rpt_nested: {}
495`,
496 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800497 desc: "repeated group fields",
498 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800499 Rptgroup: []*pb2.Nests_RptGroup{
500 {
501 RptBool: []bool{true, false},
502 },
503 {},
504 },
Herbie Ong800c9902018-12-06 15:28:53 -0800505 },
506 want: `rptgroup: {
Herbie Ongcddf8192018-11-28 18:25:20 -0800507 rpt_bool: true
508 rpt_bool: false
509}
510rptgroup: {}
511`,
512 }, {
Herbie Ongcddf8192018-11-28 18:25:20 -0800513 desc: "map fields empty",
Herbie Ong800c9902018-12-06 15:28:53 -0800514 input: &pb2.Maps{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800515 want: "\n",
516 }, {
517 desc: "map fields set to empty maps",
Herbie Ong800c9902018-12-06 15:28:53 -0800518 input: &pb2.Maps{
Herbie Ongcddf8192018-11-28 18:25:20 -0800519 Int32ToStr: map[int32]string{},
520 Sfixed64ToBool: map[int64]bool{},
521 BoolToUint32: map[bool]uint32{},
522 Uint64ToEnum: map[uint64]pb2.Enum{},
523 StrToNested: map[string]*pb2.Nested{},
524 StrToOneofs: map[string]*pb2.Oneofs{},
Herbie Ong800c9902018-12-06 15:28:53 -0800525 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800526 want: "\n",
527 }, {
528 desc: "map fields 1",
Herbie Ong800c9902018-12-06 15:28:53 -0800529 input: &pb2.Maps{
Herbie Ongcddf8192018-11-28 18:25:20 -0800530 Int32ToStr: map[int32]string{
531 -101: "-101",
532 0xff: "0xff",
533 0: "zero",
534 },
535 Sfixed64ToBool: map[int64]bool{
536 0xcafe: true,
537 0: false,
538 },
539 BoolToUint32: map[bool]uint32{
540 true: 42,
541 false: 101,
542 },
Herbie Ong800c9902018-12-06 15:28:53 -0800543 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800544 want: `int32_to_str: {
545 key: -101
546 value: "-101"
547}
548int32_to_str: {
549 key: 0
550 value: "zero"
551}
552int32_to_str: {
553 key: 255
554 value: "0xff"
555}
556sfixed64_to_bool: {
557 key: 0
558 value: false
559}
560sfixed64_to_bool: {
561 key: 51966
562 value: true
563}
564bool_to_uint32: {
565 key: false
566 value: 101
567}
568bool_to_uint32: {
569 key: true
570 value: 42
571}
572`,
573 }, {
574 desc: "map fields 2",
Herbie Ong800c9902018-12-06 15:28:53 -0800575 input: &pb2.Maps{
Herbie Ongcddf8192018-11-28 18:25:20 -0800576 Uint64ToEnum: map[uint64]pb2.Enum{
577 1: pb2.Enum_FIRST,
578 2: pb2.Enum_SECOND,
579 10: pb2.Enum_TENTH,
580 },
Herbie Ong800c9902018-12-06 15:28:53 -0800581 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800582 want: `uint64_to_enum: {
583 key: 1
584 value: FIRST
585}
586uint64_to_enum: {
587 key: 2
588 value: SECOND
589}
590uint64_to_enum: {
591 key: 10
592 value: TENTH
593}
594`,
595 }, {
596 desc: "map fields 3",
Herbie Ong800c9902018-12-06 15:28:53 -0800597 input: &pb2.Maps{
Herbie Ongcddf8192018-11-28 18:25:20 -0800598 StrToNested: map[string]*pb2.Nested{
599 "nested_one": &pb2.Nested{
600 OptString: scalar.String("nested in a map"),
601 },
602 },
Herbie Ong800c9902018-12-06 15:28:53 -0800603 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800604 want: `str_to_nested: {
605 key: "nested_one"
606 value: {
607 opt_string: "nested in a map"
608 }
609}
610`,
611 }, {
612 desc: "map fields 4",
Herbie Ong800c9902018-12-06 15:28:53 -0800613 input: &pb2.Maps{
Herbie Ongcddf8192018-11-28 18:25:20 -0800614 StrToOneofs: map[string]*pb2.Oneofs{
615 "string": &pb2.Oneofs{
616 Union: &pb2.Oneofs_Str{
617 Str: "hello",
618 },
619 },
620 "nested": &pb2.Oneofs{
621 Union: &pb2.Oneofs_Msg{
622 Msg: &pb2.Nested{
623 OptString: scalar.String("nested oneof in map field value"),
624 },
625 },
626 },
627 },
Herbie Ong800c9902018-12-06 15:28:53 -0800628 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800629 want: `str_to_oneofs: {
630 key: "nested"
631 value: {
632 msg: {
633 opt_string: "nested oneof in map field value"
634 }
635 }
636}
637str_to_oneofs: {
638 key: "string"
639 value: {
640 str: "hello"
641 }
642}
643`,
644 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800645 desc: "proto2 required fields not set",
646 input: &pb2.Requireds{},
647 want: "\n",
648 wantErr: true,
Herbie Ongcddf8192018-11-28 18:25:20 -0800649 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800650 desc: "proto2 required fields partially set",
651 input: &pb2.Requireds{
652 ReqBool: scalar.Bool(false),
653 ReqFixed32: scalar.Uint32(47),
654 ReqSfixed64: scalar.Int64(0xbeefcafe),
655 ReqDouble: scalar.Float64(math.NaN()),
656 ReqString: scalar.String("hello"),
657 ReqEnum: pb2.Enum_FIRST.Enum(),
658 },
659 want: `req_bool: false
660req_fixed32: 47
661req_sfixed64: 3203386110
662req_double: nan
663req_string: "hello"
664req_enum: FIRST
665`,
666 wantErr: true,
667 }, {
668 desc: "proto2 required fields all set",
669 input: &pb2.Requireds{
670 ReqBool: scalar.Bool(false),
671 ReqFixed32: scalar.Uint32(0),
672 ReqFixed64: scalar.Uint64(0),
673 ReqSfixed32: scalar.Int32(0),
674 ReqSfixed64: scalar.Int64(0),
675 ReqFloat: scalar.Float32(0),
676 ReqDouble: scalar.Float64(0),
677 ReqString: scalar.String(""),
678 ReqEnum: pb2.Enum_UNKNOWN.Enum(),
679 ReqBytes: []byte{},
680 ReqNested: &pb2.Nested{},
681 },
682 want: `req_bool: false
683req_fixed32: 0
684req_fixed64: 0
685req_sfixed32: 0
686req_sfixed64: 0
687req_float: 0
688req_double: 0
689req_string: ""
690req_bytes: ""
691req_enum: UNKNOWN
692req_nested: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800693`,
694 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800695 desc: "indirect required field",
696 input: &pb2.IndirectRequired{
697 OptNested: &pb2.NestedWithRequired{},
698 },
699 want: "opt_nested: {}\n",
700 wantErr: true,
Herbie Ongcddf8192018-11-28 18:25:20 -0800701 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800702 desc: "indirect required field in empty repeated",
703 input: &pb2.IndirectRequired{
704 RptNested: []*pb2.NestedWithRequired{},
705 },
706 want: "\n",
Herbie Ongcddf8192018-11-28 18:25:20 -0800707 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800708 desc: "indirect required field in repeated",
709 input: &pb2.IndirectRequired{
710 RptNested: []*pb2.NestedWithRequired{
711 &pb2.NestedWithRequired{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800712 },
Herbie Ong800c9902018-12-06 15:28:53 -0800713 },
714 want: "rpt_nested: {}\n",
715 wantErr: true,
716 }, {
717 desc: "indirect required field in empty map",
718 input: &pb2.IndirectRequired{
719 StrToNested: map[string]*pb2.NestedWithRequired{},
720 },
721 want: "\n",
722 }, {
723 desc: "indirect required field in map",
724 input: &pb2.IndirectRequired{
725 StrToNested: map[string]*pb2.NestedWithRequired{
726 "fail": &pb2.NestedWithRequired{},
727 },
728 },
729 want: `str_to_nested: {
730 key: "fail"
731 value: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800732}
733`,
Herbie Ong800c9902018-12-06 15:28:53 -0800734 wantErr: true,
Herbie Ong20a1d312018-12-11 21:08:58 -0800735 }, {
736 desc: "unknown varint and fixed types",
737 input: &pb2.Scalars{
738 OptString: scalar.String("this message contains unknown fields"),
739 XXX_unrecognized: pack.Message{
740 pack.Tag{101, pack.VarintType}, pack.Bool(true),
741 pack.Tag{102, pack.VarintType}, pack.Varint(0xff),
742 pack.Tag{103, pack.Fixed32Type}, pack.Uint32(47),
743 pack.Tag{104, pack.Fixed64Type}, pack.Int64(0xdeadbeef),
744 }.Marshal(),
745 },
746 want: `opt_string: "this message contains unknown fields"
747101: 1
748102: 255
749103: 47
750104: 3735928559
751`,
752 }, {
753 desc: "unknown length-delimited",
754 input: &pb2.Scalars{
755 XXX_unrecognized: pack.Message{
756 pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false)},
757 pack.Tag{102, pack.BytesType}, pack.String("hello world"),
758 pack.Tag{103, pack.BytesType}, pack.Bytes("\xe4\xb8\x96\xe7\x95\x8c"),
759 }.Marshal(),
760 },
761 want: `101: "\x01\x00"
762102: "hello world"
763103: "世界"
764`,
765 }, {
766 desc: "unknown group type",
767 input: &pb2.Scalars{
768 XXX_unrecognized: pack.Message{
769 pack.Tag{101, pack.StartGroupType}, pack.Tag{101, pack.EndGroupType},
770 pack.Tag{102, pack.StartGroupType},
771 pack.Tag{101, pack.VarintType}, pack.Bool(false),
772 pack.Tag{102, pack.BytesType}, pack.String("inside a group"),
773 pack.Tag{102, pack.EndGroupType},
774 }.Marshal(),
775 },
776 want: `101: {}
777102: {
778 101: 0
779 102: "inside a group"
780}
781`,
782 }, {
783 desc: "unknown unpack repeated field",
784 input: &pb2.Scalars{
785 XXX_unrecognized: pack.Message{
786 pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false), pack.Bool(true)},
787 pack.Tag{102, pack.BytesType}, pack.String("hello"),
788 pack.Tag{101, pack.VarintType}, pack.Bool(true),
789 pack.Tag{102, pack.BytesType}, pack.String("世界"),
790 }.Marshal(),
791 },
792 want: `101: "\x01\x00\x01"
793101: 1
794102: "hello"
795102: "世界"
796`,
Herbie Ongcddf8192018-11-28 18:25:20 -0800797 }}
798
799 for _, tt := range tests {
800 tt := tt
801 t.Run(tt.desc, func(t *testing.T) {
802 t.Parallel()
Herbie Ong70651952018-12-13 14:19:50 -0800803 b, err := textpb.Marshal(tt.input)
Herbie Ongcddf8192018-11-28 18:25:20 -0800804 if err != nil && !tt.wantErr {
805 t.Errorf("Marshal() returned error: %v\n\n", err)
806 }
Herbie Ong800c9902018-12-06 15:28:53 -0800807 if err == nil && tt.wantErr {
808 t.Error("Marshal() got nil error, want error\n\n")
Herbie Ongcddf8192018-11-28 18:25:20 -0800809 }
Herbie Ong800c9902018-12-06 15:28:53 -0800810 got := string(b)
811 if tt.want != "" && got != tt.want {
812 t.Errorf("Marshal()\n<got>\n%v\n<want>\n%v\n", got, tt.want)
813 if diff := cmp.Diff(tt.want, got, splitLines); diff != "" {
Herbie Ongcddf8192018-11-28 18:25:20 -0800814 t.Errorf("Marshal() diff -want +got\n%v\n", diff)
815 }
816 }
817 })
818 }
819}