blob: 7c9a912383cf72953ed603606e81772388099af5 [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
Herbie Ong800c9902018-12-06 15:28:53 -080012 protoV1 "github.com/golang/protobuf/proto"
Herbie Ongcddf8192018-11-28 18:25:20 -080013 "github.com/golang/protobuf/v2/encoding/textpb"
Herbie Ongcddf8192018-11-28 18:25:20 -080014 "github.com/golang/protobuf/v2/internal/detrand"
Herbie Ong20a1d312018-12-11 21:08:58 -080015 "github.com/golang/protobuf/v2/internal/encoding/pack"
Herbie Ongcddf8192018-11-28 18:25:20 -080016 "github.com/golang/protobuf/v2/internal/impl"
17 "github.com/golang/protobuf/v2/internal/scalar"
18 "github.com/golang/protobuf/v2/proto"
19 "github.com/google/go-cmp/cmp"
20 "github.com/google/go-cmp/cmp/cmpopts"
21
Joe Tsai08e00302018-11-26 22:32:06 -080022 // The legacy package must be imported prior to use of any legacy messages.
23 // TODO: Remove this when protoV1 registers these hooks for you.
24 _ "github.com/golang/protobuf/v2/internal/legacy"
25
Joe Tsai08e00302018-11-26 22:32:06 -080026 "github.com/golang/protobuf/v2/encoding/textpb/testprotos/pb2"
27 "github.com/golang/protobuf/v2/encoding/textpb/testprotos/pb3"
Herbie Ongcddf8192018-11-28 18:25:20 -080028)
29
30func init() {
31 // Disable detrand to enable direct comparisons on outputs.
32 detrand.Disable()
33}
34
35func M(m interface{}) proto.Message {
Joe Tsai08e00302018-11-26 22:32:06 -080036 return impl.Export{}.MessageOf(m).Interface()
Herbie Ongcddf8192018-11-28 18:25:20 -080037}
38
39// splitLines is a cmpopts.Option for comparing strings with line breaks.
40var splitLines = cmpopts.AcyclicTransformer("SplitLines", func(s string) []string {
41 return strings.Split(s, "\n")
42})
43
Herbie Ong800c9902018-12-06 15:28:53 -080044func pb2Enum(i int32) *pb2.Enum {
45 p := new(pb2.Enum)
46 *p = pb2.Enum(i)
47 return p
48}
49
50func pb2Enums_NestedEnum(i int32) *pb2.Enums_NestedEnum {
51 p := new(pb2.Enums_NestedEnum)
52 *p = pb2.Enums_NestedEnum(i)
53 return p
54}
55
Herbie Ongcddf8192018-11-28 18:25:20 -080056func TestMarshal(t *testing.T) {
57 tests := []struct {
58 desc string
Herbie Ong800c9902018-12-06 15:28:53 -080059 input protoV1.Message
Herbie Ongcddf8192018-11-28 18:25:20 -080060 want string
61 wantErr bool
62 }{{
Herbie Ongcddf8192018-11-28 18:25:20 -080063 desc: "proto2 optional scalar fields not set",
Herbie Ong800c9902018-12-06 15:28:53 -080064 input: &pb2.Scalars{},
Herbie Ongcddf8192018-11-28 18:25:20 -080065 want: "\n",
66 }, {
67 desc: "proto3 scalar fields not set",
Herbie Ong800c9902018-12-06 15:28:53 -080068 input: &pb3.Scalars{},
Herbie Ongcddf8192018-11-28 18:25:20 -080069 want: "\n",
70 }, {
71 desc: "proto2 optional scalar fields set to zero values",
Herbie Ong800c9902018-12-06 15:28:53 -080072 input: &pb2.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -080073 OptBool: scalar.Bool(false),
74 OptInt32: scalar.Int32(0),
75 OptInt64: scalar.Int64(0),
76 OptUint32: scalar.Uint32(0),
77 OptUint64: scalar.Uint64(0),
78 OptSint32: scalar.Int32(0),
79 OptSint64: scalar.Int64(0),
80 OptFixed32: scalar.Uint32(0),
81 OptFixed64: scalar.Uint64(0),
82 OptSfixed32: scalar.Int32(0),
83 OptSfixed64: scalar.Int64(0),
84 OptFloat: scalar.Float32(0),
85 OptDouble: scalar.Float64(0),
86 OptBytes: []byte{},
87 OptString: scalar.String(""),
Herbie Ong800c9902018-12-06 15:28:53 -080088 },
Herbie Ongcddf8192018-11-28 18:25:20 -080089 want: `opt_bool: false
90opt_int32: 0
91opt_int64: 0
92opt_uint32: 0
93opt_uint64: 0
94opt_sint32: 0
95opt_sint64: 0
96opt_fixed32: 0
97opt_fixed64: 0
98opt_sfixed32: 0
99opt_sfixed64: 0
100opt_float: 0
101opt_double: 0
102opt_bytes: ""
103opt_string: ""
104`,
105 }, {
106 desc: "proto3 scalar fields set to zero values",
Herbie Ong800c9902018-12-06 15:28:53 -0800107 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800108 SBool: false,
109 SInt32: 0,
110 SInt64: 0,
111 SUint32: 0,
112 SUint64: 0,
113 SSint32: 0,
114 SSint64: 0,
115 SFixed32: 0,
116 SFixed64: 0,
117 SSfixed32: 0,
118 SSfixed64: 0,
119 SFloat: 0,
120 SDouble: 0,
121 SBytes: []byte{},
122 SString: "",
Herbie Ong800c9902018-12-06 15:28:53 -0800123 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800124 want: "\n",
125 }, {
126 desc: "proto2 optional scalar fields set to some values",
Herbie Ong800c9902018-12-06 15:28:53 -0800127 input: &pb2.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800128 OptBool: scalar.Bool(true),
129 OptInt32: scalar.Int32(0xff),
130 OptInt64: scalar.Int64(0xdeadbeef),
131 OptUint32: scalar.Uint32(47),
132 OptUint64: scalar.Uint64(0xdeadbeef),
133 OptSint32: scalar.Int32(-1001),
134 OptSint64: scalar.Int64(-0xffff),
135 OptFixed64: scalar.Uint64(64),
136 OptSfixed32: scalar.Int32(-32),
137 // TODO: Update encoder to output same decimals.
138 OptFloat: scalar.Float32(1.02),
139 OptDouble: scalar.Float64(1.23e100),
140 // TODO: Update encoder to not output UTF8 for bytes.
141 OptBytes: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
142 OptString: scalar.String("谷歌"),
Herbie Ong800c9902018-12-06 15:28:53 -0800143 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800144 want: `opt_bool: true
145opt_int32: 255
146opt_int64: 3735928559
147opt_uint32: 47
148opt_uint64: 3735928559
149opt_sint32: -1001
150opt_sint64: -65535
151opt_fixed64: 64
152opt_sfixed32: -32
153opt_float: 1.0199999809265137
154opt_double: 1.23e+100
155opt_bytes: "谷歌"
156opt_string: "谷歌"
157`,
158 }, {
Herbie Ongcddf8192018-11-28 18:25:20 -0800159 desc: "float32 nan",
Herbie Ong800c9902018-12-06 15:28:53 -0800160 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800161 SFloat: float32(math.NaN()),
Herbie Ong800c9902018-12-06 15:28:53 -0800162 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800163 want: "s_float: nan\n",
164 }, {
165 desc: "float32 positive 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: "float32 negative infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800172 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800173 SFloat: float32(math.Inf(-1)),
Herbie Ong800c9902018-12-06 15:28:53 -0800174 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800175 want: "s_float: -inf\n",
176 }, {
177 desc: "float64 nan",
Herbie Ong800c9902018-12-06 15:28:53 -0800178 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800179 SDouble: math.NaN(),
Herbie Ong800c9902018-12-06 15:28:53 -0800180 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800181 want: "s_double: nan\n",
182 }, {
183 desc: "float64 positive 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: "float64 negative infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800190 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800191 SDouble: math.Inf(-1),
Herbie Ong800c9902018-12-06 15:28:53 -0800192 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800193 want: "s_double: -inf\n",
194 }, {
195 desc: "proto2 bytes set to empty string",
Herbie Ong800c9902018-12-06 15:28:53 -0800196 input: &pb2.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800197 OptBytes: []byte(""),
Herbie Ong800c9902018-12-06 15:28:53 -0800198 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800199 want: "opt_bytes: \"\"\n",
200 }, {
201 desc: "proto3 bytes set to empty string",
Herbie Ong800c9902018-12-06 15:28:53 -0800202 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800203 SBytes: []byte(""),
Herbie Ong800c9902018-12-06 15:28:53 -0800204 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800205 want: "\n",
206 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800207 desc: "proto2 enum not set",
208 input: &pb2.Enums{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800209 want: "\n",
210 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800211 desc: "proto2 enum set to zero value",
212 input: &pb2.Enums{
213 OptEnum: pb2.Enum_UNKNOWN.Enum(),
214 OptNestedEnum: pb2Enums_NestedEnum(0),
215 },
216 want: `opt_enum: UNKNOWN
217opt_nested_enum: 0
218`,
219 }, {
220 desc: "proto2 enum",
221 input: &pb2.Enums{
222 OptEnum: pb2.Enum_FIRST.Enum(),
223 OptNestedEnum: pb2.Enums_UNO.Enum(),
224 },
225 want: `opt_enum: FIRST
226opt_nested_enum: UNO
227`,
228 }, {
229 desc: "proto2 enum set to numeric values",
230 input: &pb2.Enums{
231 OptEnum: pb2Enum(1),
232 OptNestedEnum: pb2Enums_NestedEnum(2),
233 },
234 want: `opt_enum: FIRST
235opt_nested_enum: DOS
236`,
237 }, {
238 desc: "proto2 enum set to unnamed numeric values",
239 input: &pb2.Enums{
240 OptEnum: pb2Enum(101),
241 OptNestedEnum: pb2Enums_NestedEnum(-101),
242 },
243 want: `opt_enum: 101
244opt_nested_enum: -101
245`,
246 }, {
247 desc: "proto3 enum not set",
248 input: &pb3.Enums{},
249 want: "\n",
250 }, {
251 desc: "proto3 enum set to zero value",
252 input: &pb3.Enums{
253 SEnum: pb3.Enum_ZERO,
254 SNestedEnum: pb3.Enums_CERO,
255 },
256 want: "\n",
257 }, {
258 desc: "proto3 enum",
259 input: &pb3.Enums{
260 SEnum: pb3.Enum_ONE,
261 SNestedEnum: pb3.Enums_DIEZ,
262 },
263 want: `s_enum: ONE
264s_nested_enum: DIEZ
265`,
266 }, {
267 desc: "proto3 enum set to numeric values",
268 input: &pb3.Enums{
269 SEnum: 2,
270 SNestedEnum: 1,
271 },
272 want: `s_enum: TWO
273s_nested_enum: UNO
274`,
275 }, {
276 desc: "proto3 enum set to unnamed numeric values",
277 input: &pb3.Enums{
278 SEnum: -47,
279 SNestedEnum: 47,
280 },
281 want: `s_enum: -47
282s_nested_enum: 47
283`,
284 }, {
285 desc: "proto2 nested message not set",
286 input: &pb2.Nests{},
287 want: "\n",
288 }, {
289 desc: "proto2 nested message set to empty",
290 input: &pb2.Nests{
291 OptNested: &pb2.Nested{},
292 Optgroup: &pb2.Nests_OptGroup{},
293 },
294 want: `opt_nested: {}
295optgroup: {}
296`,
297 }, {
298 desc: "proto2 nested messages",
299 input: &pb2.Nests{
300 OptNested: &pb2.Nested{
301 OptString: scalar.String("nested message"),
302 OptNested: &pb2.Nested{
303 OptString: scalar.String("another nested message"),
304 },
305 },
306 },
307 want: `opt_nested: {
308 opt_string: "nested message"
309 opt_nested: {
310 opt_string: "another nested message"
311 }
312}
313`,
314 }, {
315 desc: "proto2 group fields",
316 input: &pb2.Nests{
317 Optgroup: &pb2.Nests_OptGroup{
318 OptBool: scalar.Bool(true),
319 OptString: scalar.String("inside a group"),
320 OptNested: &pb2.Nested{
321 OptString: scalar.String("nested message inside a group"),
322 },
323 Optnestedgroup: &pb2.Nests_OptGroup_OptNestedGroup{
324 OptEnum: pb2.Enum_TENTH.Enum(),
325 },
326 },
327 },
328 want: `optgroup: {
329 opt_bool: true
330 opt_string: "inside a group"
331 opt_nested: {
332 opt_string: "nested message inside a group"
333 }
334 optnestedgroup: {
335 opt_enum: TENTH
336 }
337}
338`,
339 }, {
340 desc: "proto3 nested message not set",
341 input: &pb3.Nests{},
342 want: "\n",
343 }, {
344 desc: "proto3 nested message",
345 input: &pb3.Nests{
346 SNested: &pb3.Nested{
347 SString: "nested message",
348 SNested: &pb3.Nested{
349 SString: "another nested message",
350 },
351 },
352 },
353 want: `s_nested: {
354 s_string: "nested message"
355 s_nested: {
356 s_string: "another nested message"
357 }
358}
359`,
360 }, {
361 desc: "oneof fields",
362 input: &pb2.Oneofs{},
363 want: "\n",
364 }, {
365 desc: "oneof field set to empty string",
366 input: &pb2.Oneofs{
367 Union: &pb2.Oneofs_Str{},
368 },
369 want: "str: \"\"\n",
370 }, {
371 desc: "oneof field set to string",
372 input: &pb2.Oneofs{
373 Union: &pb2.Oneofs_Str{
374 Str: "hello",
375 },
376 },
377 want: "str: \"hello\"\n",
378 }, {
379 desc: "oneof field set to empty message",
380 input: &pb2.Oneofs{
381 Union: &pb2.Oneofs_Msg{
382 Msg: &pb2.Nested{},
383 },
384 },
385 want: "msg: {}\n",
386 }, {
387 desc: "oneof field set to message",
388 input: &pb2.Oneofs{
389 Union: &pb2.Oneofs_Msg{
390 Msg: &pb2.Nested{
391 OptString: scalar.String("nested message"),
392 },
393 },
394 },
395 want: `msg: {
396 opt_string: "nested message"
397}
398`,
399 }, {
400 desc: "repeated not set",
401 input: &pb2.Repeats{},
402 want: "\n",
403 }, {
404 desc: "repeated set to empty slices",
405 input: &pb2.Repeats{
Herbie Ongcddf8192018-11-28 18:25:20 -0800406 RptBool: []bool{},
407 RptInt32: []int32{},
408 RptInt64: []int64{},
409 RptUint32: []uint32{},
410 RptUint64: []uint64{},
411 RptFloat: []float32{},
412 RptDouble: []float64{},
413 RptBytes: [][]byte{},
Herbie Ong800c9902018-12-06 15:28:53 -0800414 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800415 want: "\n",
416 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800417 desc: "repeated set to some values",
418 input: &pb2.Repeats{
Herbie Ongcddf8192018-11-28 18:25:20 -0800419 RptBool: []bool{true, false, true, true},
420 RptInt32: []int32{1, 6, 0, 0},
421 RptInt64: []int64{-64, 47},
422 RptUint32: []uint32{0xff, 0xffff},
423 RptUint64: []uint64{0xdeadbeef},
424 // TODO: add float32 examples.
425 RptDouble: []float64{math.NaN(), math.Inf(1), math.Inf(-1), 1.23e-308},
426 RptString: []string{"hello", "世界"},
427 RptBytes: [][]byte{
428 []byte("hello"),
429 []byte("\xe4\xb8\x96\xe7\x95\x8c"),
430 },
Herbie Ong800c9902018-12-06 15:28:53 -0800431 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800432 want: `rpt_bool: true
433rpt_bool: false
434rpt_bool: true
435rpt_bool: true
436rpt_int32: 1
437rpt_int32: 6
438rpt_int32: 0
439rpt_int32: 0
440rpt_int64: -64
441rpt_int64: 47
442rpt_uint32: 255
443rpt_uint32: 65535
444rpt_uint64: 3735928559
445rpt_double: nan
446rpt_double: inf
447rpt_double: -inf
448rpt_double: 1.23e-308
449rpt_string: "hello"
450rpt_string: "世界"
451rpt_bytes: "hello"
452rpt_bytes: "世界"
453`,
454 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800455 desc: "repeated enum",
456 input: &pb2.Enums{
Herbie Ongcddf8192018-11-28 18:25:20 -0800457 RptEnum: []pb2.Enum{pb2.Enum_FIRST, 2, pb2.Enum_TENTH, 42},
Herbie Ongcddf8192018-11-28 18:25:20 -0800458 RptNestedEnum: []pb2.Enums_NestedEnum{2, 47, 10},
Herbie Ong800c9902018-12-06 15:28:53 -0800459 },
460 want: `rpt_enum: FIRST
Herbie Ongcddf8192018-11-28 18:25:20 -0800461rpt_enum: SECOND
462rpt_enum: TENTH
463rpt_enum: 42
Herbie Ongcddf8192018-11-28 18:25:20 -0800464rpt_nested_enum: DOS
465rpt_nested_enum: 47
466rpt_nested_enum: DIEZ
467`,
468 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800469 desc: "repeated nested message set to empty",
470 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800471 RptNested: []*pb2.Nested{},
472 Rptgroup: []*pb2.Nests_RptGroup{},
Herbie Ong800c9902018-12-06 15:28:53 -0800473 },
474 want: "\n",
Herbie Ongcddf8192018-11-28 18:25:20 -0800475 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800476 desc: "repeated nested messages",
477 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800478 RptNested: []*pb2.Nested{
479 {
480 OptString: scalar.String("repeat nested one"),
481 },
482 {
483 OptString: scalar.String("repeat nested two"),
484 OptNested: &pb2.Nested{
485 OptString: scalar.String("inside repeat nested two"),
486 },
487 },
488 {},
489 },
Herbie Ong800c9902018-12-06 15:28:53 -0800490 },
491 want: `rpt_nested: {
Herbie Ongcddf8192018-11-28 18:25:20 -0800492 opt_string: "repeat nested one"
493}
494rpt_nested: {
495 opt_string: "repeat nested two"
496 opt_nested: {
497 opt_string: "inside repeat nested two"
498 }
499}
500rpt_nested: {}
501`,
502 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800503 desc: "repeated group fields",
504 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800505 Rptgroup: []*pb2.Nests_RptGroup{
506 {
507 RptBool: []bool{true, false},
508 },
509 {},
510 },
Herbie Ong800c9902018-12-06 15:28:53 -0800511 },
512 want: `rptgroup: {
Herbie Ongcddf8192018-11-28 18:25:20 -0800513 rpt_bool: true
514 rpt_bool: false
515}
516rptgroup: {}
517`,
518 }, {
Herbie Ongcddf8192018-11-28 18:25:20 -0800519 desc: "map fields empty",
Herbie Ong800c9902018-12-06 15:28:53 -0800520 input: &pb2.Maps{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800521 want: "\n",
522 }, {
523 desc: "map fields set to empty maps",
Herbie Ong800c9902018-12-06 15:28:53 -0800524 input: &pb2.Maps{
Herbie Ongcddf8192018-11-28 18:25:20 -0800525 Int32ToStr: map[int32]string{},
526 Sfixed64ToBool: map[int64]bool{},
527 BoolToUint32: map[bool]uint32{},
528 Uint64ToEnum: map[uint64]pb2.Enum{},
529 StrToNested: map[string]*pb2.Nested{},
530 StrToOneofs: map[string]*pb2.Oneofs{},
Herbie Ong800c9902018-12-06 15:28:53 -0800531 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800532 want: "\n",
533 }, {
534 desc: "map fields 1",
Herbie Ong800c9902018-12-06 15:28:53 -0800535 input: &pb2.Maps{
Herbie Ongcddf8192018-11-28 18:25:20 -0800536 Int32ToStr: map[int32]string{
537 -101: "-101",
538 0xff: "0xff",
539 0: "zero",
540 },
541 Sfixed64ToBool: map[int64]bool{
542 0xcafe: true,
543 0: false,
544 },
545 BoolToUint32: map[bool]uint32{
546 true: 42,
547 false: 101,
548 },
Herbie Ong800c9902018-12-06 15:28:53 -0800549 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800550 want: `int32_to_str: {
551 key: -101
552 value: "-101"
553}
554int32_to_str: {
555 key: 0
556 value: "zero"
557}
558int32_to_str: {
559 key: 255
560 value: "0xff"
561}
562sfixed64_to_bool: {
563 key: 0
564 value: false
565}
566sfixed64_to_bool: {
567 key: 51966
568 value: true
569}
570bool_to_uint32: {
571 key: false
572 value: 101
573}
574bool_to_uint32: {
575 key: true
576 value: 42
577}
578`,
579 }, {
580 desc: "map fields 2",
Herbie Ong800c9902018-12-06 15:28:53 -0800581 input: &pb2.Maps{
Herbie Ongcddf8192018-11-28 18:25:20 -0800582 Uint64ToEnum: map[uint64]pb2.Enum{
583 1: pb2.Enum_FIRST,
584 2: pb2.Enum_SECOND,
585 10: pb2.Enum_TENTH,
586 },
Herbie Ong800c9902018-12-06 15:28:53 -0800587 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800588 want: `uint64_to_enum: {
589 key: 1
590 value: FIRST
591}
592uint64_to_enum: {
593 key: 2
594 value: SECOND
595}
596uint64_to_enum: {
597 key: 10
598 value: TENTH
599}
600`,
601 }, {
602 desc: "map fields 3",
Herbie Ong800c9902018-12-06 15:28:53 -0800603 input: &pb2.Maps{
Herbie Ongcddf8192018-11-28 18:25:20 -0800604 StrToNested: map[string]*pb2.Nested{
605 "nested_one": &pb2.Nested{
606 OptString: scalar.String("nested in a map"),
607 },
608 },
Herbie Ong800c9902018-12-06 15:28:53 -0800609 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800610 want: `str_to_nested: {
611 key: "nested_one"
612 value: {
613 opt_string: "nested in a map"
614 }
615}
616`,
617 }, {
618 desc: "map fields 4",
Herbie Ong800c9902018-12-06 15:28:53 -0800619 input: &pb2.Maps{
Herbie Ongcddf8192018-11-28 18:25:20 -0800620 StrToOneofs: map[string]*pb2.Oneofs{
621 "string": &pb2.Oneofs{
622 Union: &pb2.Oneofs_Str{
623 Str: "hello",
624 },
625 },
626 "nested": &pb2.Oneofs{
627 Union: &pb2.Oneofs_Msg{
628 Msg: &pb2.Nested{
629 OptString: scalar.String("nested oneof in map field value"),
630 },
631 },
632 },
633 },
Herbie Ong800c9902018-12-06 15:28:53 -0800634 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800635 want: `str_to_oneofs: {
636 key: "nested"
637 value: {
638 msg: {
639 opt_string: "nested oneof in map field value"
640 }
641 }
642}
643str_to_oneofs: {
644 key: "string"
645 value: {
646 str: "hello"
647 }
648}
649`,
650 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800651 desc: "proto2 required fields not set",
652 input: &pb2.Requireds{},
653 want: "\n",
654 wantErr: true,
Herbie Ongcddf8192018-11-28 18:25:20 -0800655 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800656 desc: "proto2 required fields partially set",
657 input: &pb2.Requireds{
658 ReqBool: scalar.Bool(false),
659 ReqFixed32: scalar.Uint32(47),
660 ReqSfixed64: scalar.Int64(0xbeefcafe),
661 ReqDouble: scalar.Float64(math.NaN()),
662 ReqString: scalar.String("hello"),
663 ReqEnum: pb2.Enum_FIRST.Enum(),
664 },
665 want: `req_bool: false
666req_fixed32: 47
667req_sfixed64: 3203386110
668req_double: nan
669req_string: "hello"
670req_enum: FIRST
671`,
672 wantErr: true,
673 }, {
674 desc: "proto2 required fields all set",
675 input: &pb2.Requireds{
676 ReqBool: scalar.Bool(false),
677 ReqFixed32: scalar.Uint32(0),
678 ReqFixed64: scalar.Uint64(0),
679 ReqSfixed32: scalar.Int32(0),
680 ReqSfixed64: scalar.Int64(0),
681 ReqFloat: scalar.Float32(0),
682 ReqDouble: scalar.Float64(0),
683 ReqString: scalar.String(""),
684 ReqEnum: pb2.Enum_UNKNOWN.Enum(),
685 ReqBytes: []byte{},
686 ReqNested: &pb2.Nested{},
687 },
688 want: `req_bool: false
689req_fixed32: 0
690req_fixed64: 0
691req_sfixed32: 0
692req_sfixed64: 0
693req_float: 0
694req_double: 0
695req_string: ""
696req_bytes: ""
697req_enum: UNKNOWN
698req_nested: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800699`,
700 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800701 desc: "indirect required field",
702 input: &pb2.IndirectRequired{
703 OptNested: &pb2.NestedWithRequired{},
704 },
705 want: "opt_nested: {}\n",
706 wantErr: true,
Herbie Ongcddf8192018-11-28 18:25:20 -0800707 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800708 desc: "indirect required field in empty repeated",
709 input: &pb2.IndirectRequired{
710 RptNested: []*pb2.NestedWithRequired{},
711 },
712 want: "\n",
Herbie Ongcddf8192018-11-28 18:25:20 -0800713 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800714 desc: "indirect required field in repeated",
715 input: &pb2.IndirectRequired{
716 RptNested: []*pb2.NestedWithRequired{
717 &pb2.NestedWithRequired{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800718 },
Herbie Ong800c9902018-12-06 15:28:53 -0800719 },
720 want: "rpt_nested: {}\n",
721 wantErr: true,
722 }, {
723 desc: "indirect required field in empty map",
724 input: &pb2.IndirectRequired{
725 StrToNested: map[string]*pb2.NestedWithRequired{},
726 },
727 want: "\n",
728 }, {
729 desc: "indirect required field in map",
730 input: &pb2.IndirectRequired{
731 StrToNested: map[string]*pb2.NestedWithRequired{
732 "fail": &pb2.NestedWithRequired{},
733 },
734 },
735 want: `str_to_nested: {
736 key: "fail"
737 value: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800738}
739`,
Herbie Ong800c9902018-12-06 15:28:53 -0800740 wantErr: true,
Herbie Ong20a1d312018-12-11 21:08:58 -0800741 }, {
742 desc: "unknown varint and fixed types",
743 input: &pb2.Scalars{
744 OptString: scalar.String("this message contains unknown fields"),
745 XXX_unrecognized: pack.Message{
746 pack.Tag{101, pack.VarintType}, pack.Bool(true),
747 pack.Tag{102, pack.VarintType}, pack.Varint(0xff),
748 pack.Tag{103, pack.Fixed32Type}, pack.Uint32(47),
749 pack.Tag{104, pack.Fixed64Type}, pack.Int64(0xdeadbeef),
750 }.Marshal(),
751 },
752 want: `opt_string: "this message contains unknown fields"
753101: 1
754102: 255
755103: 47
756104: 3735928559
757`,
758 }, {
759 desc: "unknown length-delimited",
760 input: &pb2.Scalars{
761 XXX_unrecognized: pack.Message{
762 pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false)},
763 pack.Tag{102, pack.BytesType}, pack.String("hello world"),
764 pack.Tag{103, pack.BytesType}, pack.Bytes("\xe4\xb8\x96\xe7\x95\x8c"),
765 }.Marshal(),
766 },
767 want: `101: "\x01\x00"
768102: "hello world"
769103: "世界"
770`,
771 }, {
772 desc: "unknown group type",
773 input: &pb2.Scalars{
774 XXX_unrecognized: pack.Message{
775 pack.Tag{101, pack.StartGroupType}, pack.Tag{101, pack.EndGroupType},
776 pack.Tag{102, pack.StartGroupType},
777 pack.Tag{101, pack.VarintType}, pack.Bool(false),
778 pack.Tag{102, pack.BytesType}, pack.String("inside a group"),
779 pack.Tag{102, pack.EndGroupType},
780 }.Marshal(),
781 },
782 want: `101: {}
783102: {
784 101: 0
785 102: "inside a group"
786}
787`,
788 }, {
789 desc: "unknown unpack repeated field",
790 input: &pb2.Scalars{
791 XXX_unrecognized: pack.Message{
792 pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false), pack.Bool(true)},
793 pack.Tag{102, pack.BytesType}, pack.String("hello"),
794 pack.Tag{101, pack.VarintType}, pack.Bool(true),
795 pack.Tag{102, pack.BytesType}, pack.String("世界"),
796 }.Marshal(),
797 },
798 want: `101: "\x01\x00\x01"
799101: 1
800102: "hello"
801102: "世界"
802`,
Herbie Ongcddf8192018-11-28 18:25:20 -0800803 }}
804
805 for _, tt := range tests {
806 tt := tt
807 t.Run(tt.desc, func(t *testing.T) {
808 t.Parallel()
Herbie Ong800c9902018-12-06 15:28:53 -0800809 b, err := textpb.Marshal(M(tt.input))
Herbie Ongcddf8192018-11-28 18:25:20 -0800810 if err != nil && !tt.wantErr {
811 t.Errorf("Marshal() returned error: %v\n\n", err)
812 }
Herbie Ong800c9902018-12-06 15:28:53 -0800813 if err == nil && tt.wantErr {
814 t.Error("Marshal() got nil error, want error\n\n")
Herbie Ongcddf8192018-11-28 18:25:20 -0800815 }
Herbie Ong800c9902018-12-06 15:28:53 -0800816 got := string(b)
817 if tt.want != "" && got != tt.want {
818 t.Errorf("Marshal()\n<got>\n%v\n<want>\n%v\n", got, tt.want)
819 if diff := cmp.Diff(tt.want, got, splitLines); diff != "" {
Herbie Ongcddf8192018-11-28 18:25:20 -0800820 t.Errorf("Marshal() diff -want +got\n%v\n", diff)
821 }
822 }
823 })
824 }
825}