blob: 498b2a70b7bbe982cc977389ad86b37837ae3b83 [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"
15 "github.com/golang/protobuf/v2/internal/impl"
16 "github.com/golang/protobuf/v2/internal/scalar"
17 "github.com/golang/protobuf/v2/proto"
18 "github.com/google/go-cmp/cmp"
19 "github.com/google/go-cmp/cmp/cmpopts"
20
Joe Tsai08e00302018-11-26 22:32:06 -080021 // The legacy package must be imported prior to use of any legacy messages.
22 // TODO: Remove this when protoV1 registers these hooks for you.
23 _ "github.com/golang/protobuf/v2/internal/legacy"
24
Joe Tsai08e00302018-11-26 22:32:06 -080025 "github.com/golang/protobuf/v2/encoding/textpb/testprotos/pb2"
26 "github.com/golang/protobuf/v2/encoding/textpb/testprotos/pb3"
Herbie Ongcddf8192018-11-28 18:25:20 -080027)
28
29func init() {
30 // Disable detrand to enable direct comparisons on outputs.
31 detrand.Disable()
32}
33
34func M(m interface{}) proto.Message {
Joe Tsai08e00302018-11-26 22:32:06 -080035 return impl.Export{}.MessageOf(m).Interface()
Herbie Ongcddf8192018-11-28 18:25:20 -080036}
37
38// splitLines is a cmpopts.Option for comparing strings with line breaks.
39var splitLines = cmpopts.AcyclicTransformer("SplitLines", func(s string) []string {
40 return strings.Split(s, "\n")
41})
42
Herbie Ong800c9902018-12-06 15:28:53 -080043func pb2Enum(i int32) *pb2.Enum {
44 p := new(pb2.Enum)
45 *p = pb2.Enum(i)
46 return p
47}
48
49func pb2Enums_NestedEnum(i int32) *pb2.Enums_NestedEnum {
50 p := new(pb2.Enums_NestedEnum)
51 *p = pb2.Enums_NestedEnum(i)
52 return p
53}
54
Herbie Ongcddf8192018-11-28 18:25:20 -080055func TestMarshal(t *testing.T) {
56 tests := []struct {
57 desc string
Herbie Ong800c9902018-12-06 15:28:53 -080058 input protoV1.Message
Herbie Ongcddf8192018-11-28 18:25:20 -080059 want string
60 wantErr bool
61 }{{
Herbie Ongcddf8192018-11-28 18:25:20 -080062 desc: "proto2 optional scalar fields not set",
Herbie Ong800c9902018-12-06 15:28:53 -080063 input: &pb2.Scalars{},
Herbie Ongcddf8192018-11-28 18:25:20 -080064 want: "\n",
65 }, {
66 desc: "proto3 scalar fields not set",
Herbie Ong800c9902018-12-06 15:28:53 -080067 input: &pb3.Scalars{},
Herbie Ongcddf8192018-11-28 18:25:20 -080068 want: "\n",
69 }, {
70 desc: "proto2 optional scalar fields set to zero values",
Herbie Ong800c9902018-12-06 15:28:53 -080071 input: &pb2.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -080072 OptBool: scalar.Bool(false),
73 OptInt32: scalar.Int32(0),
74 OptInt64: scalar.Int64(0),
75 OptUint32: scalar.Uint32(0),
76 OptUint64: scalar.Uint64(0),
77 OptSint32: scalar.Int32(0),
78 OptSint64: scalar.Int64(0),
79 OptFixed32: scalar.Uint32(0),
80 OptFixed64: scalar.Uint64(0),
81 OptSfixed32: scalar.Int32(0),
82 OptSfixed64: scalar.Int64(0),
83 OptFloat: scalar.Float32(0),
84 OptDouble: scalar.Float64(0),
85 OptBytes: []byte{},
86 OptString: scalar.String(""),
Herbie Ong800c9902018-12-06 15:28:53 -080087 },
Herbie Ongcddf8192018-11-28 18:25:20 -080088 want: `opt_bool: false
89opt_int32: 0
90opt_int64: 0
91opt_uint32: 0
92opt_uint64: 0
93opt_sint32: 0
94opt_sint64: 0
95opt_fixed32: 0
96opt_fixed64: 0
97opt_sfixed32: 0
98opt_sfixed64: 0
99opt_float: 0
100opt_double: 0
101opt_bytes: ""
102opt_string: ""
103`,
104 }, {
105 desc: "proto3 scalar fields set to zero values",
Herbie Ong800c9902018-12-06 15:28:53 -0800106 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800107 SBool: false,
108 SInt32: 0,
109 SInt64: 0,
110 SUint32: 0,
111 SUint64: 0,
112 SSint32: 0,
113 SSint64: 0,
114 SFixed32: 0,
115 SFixed64: 0,
116 SSfixed32: 0,
117 SSfixed64: 0,
118 SFloat: 0,
119 SDouble: 0,
120 SBytes: []byte{},
121 SString: "",
Herbie Ong800c9902018-12-06 15:28:53 -0800122 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800123 want: "\n",
124 }, {
125 desc: "proto2 optional scalar fields set to some values",
Herbie Ong800c9902018-12-06 15:28:53 -0800126 input: &pb2.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800127 OptBool: scalar.Bool(true),
128 OptInt32: scalar.Int32(0xff),
129 OptInt64: scalar.Int64(0xdeadbeef),
130 OptUint32: scalar.Uint32(47),
131 OptUint64: scalar.Uint64(0xdeadbeef),
132 OptSint32: scalar.Int32(-1001),
133 OptSint64: scalar.Int64(-0xffff),
134 OptFixed64: scalar.Uint64(64),
135 OptSfixed32: scalar.Int32(-32),
136 // TODO: Update encoder to output same decimals.
137 OptFloat: scalar.Float32(1.02),
138 OptDouble: scalar.Float64(1.23e100),
139 // TODO: Update encoder to not output UTF8 for bytes.
140 OptBytes: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
141 OptString: scalar.String("谷歌"),
Herbie Ong800c9902018-12-06 15:28:53 -0800142 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800143 want: `opt_bool: true
144opt_int32: 255
145opt_int64: 3735928559
146opt_uint32: 47
147opt_uint64: 3735928559
148opt_sint32: -1001
149opt_sint64: -65535
150opt_fixed64: 64
151opt_sfixed32: -32
152opt_float: 1.0199999809265137
153opt_double: 1.23e+100
154opt_bytes: "谷歌"
155opt_string: "谷歌"
156`,
157 }, {
Herbie Ongcddf8192018-11-28 18:25:20 -0800158 desc: "float32 nan",
Herbie Ong800c9902018-12-06 15:28:53 -0800159 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800160 SFloat: float32(math.NaN()),
Herbie Ong800c9902018-12-06 15:28:53 -0800161 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800162 want: "s_float: nan\n",
163 }, {
164 desc: "float32 positive infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800165 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800166 SFloat: float32(math.Inf(1)),
Herbie Ong800c9902018-12-06 15:28:53 -0800167 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800168 want: "s_float: inf\n",
169 }, {
170 desc: "float32 negative infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800171 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800172 SFloat: float32(math.Inf(-1)),
Herbie Ong800c9902018-12-06 15:28:53 -0800173 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800174 want: "s_float: -inf\n",
175 }, {
176 desc: "float64 nan",
Herbie Ong800c9902018-12-06 15:28:53 -0800177 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800178 SDouble: math.NaN(),
Herbie Ong800c9902018-12-06 15:28:53 -0800179 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800180 want: "s_double: nan\n",
181 }, {
182 desc: "float64 positive infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800183 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800184 SDouble: math.Inf(1),
Herbie Ong800c9902018-12-06 15:28:53 -0800185 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800186 want: "s_double: inf\n",
187 }, {
188 desc: "float64 negative infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800189 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800190 SDouble: math.Inf(-1),
Herbie Ong800c9902018-12-06 15:28:53 -0800191 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800192 want: "s_double: -inf\n",
193 }, {
194 desc: "proto2 bytes set to empty string",
Herbie Ong800c9902018-12-06 15:28:53 -0800195 input: &pb2.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800196 OptBytes: []byte(""),
Herbie Ong800c9902018-12-06 15:28:53 -0800197 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800198 want: "opt_bytes: \"\"\n",
199 }, {
200 desc: "proto3 bytes set to empty string",
Herbie Ong800c9902018-12-06 15:28:53 -0800201 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800202 SBytes: []byte(""),
Herbie Ong800c9902018-12-06 15:28:53 -0800203 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800204 want: "\n",
205 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800206 desc: "proto2 enum not set",
207 input: &pb2.Enums{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800208 want: "\n",
209 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800210 desc: "proto2 enum set to zero value",
211 input: &pb2.Enums{
212 OptEnum: pb2.Enum_UNKNOWN.Enum(),
213 OptNestedEnum: pb2Enums_NestedEnum(0),
214 },
215 want: `opt_enum: UNKNOWN
216opt_nested_enum: 0
217`,
218 }, {
219 desc: "proto2 enum",
220 input: &pb2.Enums{
221 OptEnum: pb2.Enum_FIRST.Enum(),
222 OptNestedEnum: pb2.Enums_UNO.Enum(),
223 },
224 want: `opt_enum: FIRST
225opt_nested_enum: UNO
226`,
227 }, {
228 desc: "proto2 enum set to numeric values",
229 input: &pb2.Enums{
230 OptEnum: pb2Enum(1),
231 OptNestedEnum: pb2Enums_NestedEnum(2),
232 },
233 want: `opt_enum: FIRST
234opt_nested_enum: DOS
235`,
236 }, {
237 desc: "proto2 enum set to unnamed numeric values",
238 input: &pb2.Enums{
239 OptEnum: pb2Enum(101),
240 OptNestedEnum: pb2Enums_NestedEnum(-101),
241 },
242 want: `opt_enum: 101
243opt_nested_enum: -101
244`,
245 }, {
246 desc: "proto3 enum not set",
247 input: &pb3.Enums{},
248 want: "\n",
249 }, {
250 desc: "proto3 enum set to zero value",
251 input: &pb3.Enums{
252 SEnum: pb3.Enum_ZERO,
253 SNestedEnum: pb3.Enums_CERO,
254 },
255 want: "\n",
256 }, {
257 desc: "proto3 enum",
258 input: &pb3.Enums{
259 SEnum: pb3.Enum_ONE,
260 SNestedEnum: pb3.Enums_DIEZ,
261 },
262 want: `s_enum: ONE
263s_nested_enum: DIEZ
264`,
265 }, {
266 desc: "proto3 enum set to numeric values",
267 input: &pb3.Enums{
268 SEnum: 2,
269 SNestedEnum: 1,
270 },
271 want: `s_enum: TWO
272s_nested_enum: UNO
273`,
274 }, {
275 desc: "proto3 enum set to unnamed numeric values",
276 input: &pb3.Enums{
277 SEnum: -47,
278 SNestedEnum: 47,
279 },
280 want: `s_enum: -47
281s_nested_enum: 47
282`,
283 }, {
284 desc: "proto2 nested message not set",
285 input: &pb2.Nests{},
286 want: "\n",
287 }, {
288 desc: "proto2 nested message set to empty",
289 input: &pb2.Nests{
290 OptNested: &pb2.Nested{},
291 Optgroup: &pb2.Nests_OptGroup{},
292 },
293 want: `opt_nested: {}
294optgroup: {}
295`,
296 }, {
297 desc: "proto2 nested messages",
298 input: &pb2.Nests{
299 OptNested: &pb2.Nested{
300 OptString: scalar.String("nested message"),
301 OptNested: &pb2.Nested{
302 OptString: scalar.String("another nested message"),
303 },
304 },
305 },
306 want: `opt_nested: {
307 opt_string: "nested message"
308 opt_nested: {
309 opt_string: "another nested message"
310 }
311}
312`,
313 }, {
314 desc: "proto2 group fields",
315 input: &pb2.Nests{
316 Optgroup: &pb2.Nests_OptGroup{
317 OptBool: scalar.Bool(true),
318 OptString: scalar.String("inside a group"),
319 OptNested: &pb2.Nested{
320 OptString: scalar.String("nested message inside a group"),
321 },
322 Optnestedgroup: &pb2.Nests_OptGroup_OptNestedGroup{
323 OptEnum: pb2.Enum_TENTH.Enum(),
324 },
325 },
326 },
327 want: `optgroup: {
328 opt_bool: true
329 opt_string: "inside a group"
330 opt_nested: {
331 opt_string: "nested message inside a group"
332 }
333 optnestedgroup: {
334 opt_enum: TENTH
335 }
336}
337`,
338 }, {
339 desc: "proto3 nested message not set",
340 input: &pb3.Nests{},
341 want: "\n",
342 }, {
343 desc: "proto3 nested message",
344 input: &pb3.Nests{
345 SNested: &pb3.Nested{
346 SString: "nested message",
347 SNested: &pb3.Nested{
348 SString: "another nested message",
349 },
350 },
351 },
352 want: `s_nested: {
353 s_string: "nested message"
354 s_nested: {
355 s_string: "another nested message"
356 }
357}
358`,
359 }, {
360 desc: "oneof fields",
361 input: &pb2.Oneofs{},
362 want: "\n",
363 }, {
364 desc: "oneof field set to empty string",
365 input: &pb2.Oneofs{
366 Union: &pb2.Oneofs_Str{},
367 },
368 want: "str: \"\"\n",
369 }, {
370 desc: "oneof field set to string",
371 input: &pb2.Oneofs{
372 Union: &pb2.Oneofs_Str{
373 Str: "hello",
374 },
375 },
376 want: "str: \"hello\"\n",
377 }, {
378 desc: "oneof field set to empty message",
379 input: &pb2.Oneofs{
380 Union: &pb2.Oneofs_Msg{
381 Msg: &pb2.Nested{},
382 },
383 },
384 want: "msg: {}\n",
385 }, {
386 desc: "oneof field set to message",
387 input: &pb2.Oneofs{
388 Union: &pb2.Oneofs_Msg{
389 Msg: &pb2.Nested{
390 OptString: scalar.String("nested message"),
391 },
392 },
393 },
394 want: `msg: {
395 opt_string: "nested message"
396}
397`,
398 }, {
399 desc: "repeated not set",
400 input: &pb2.Repeats{},
401 want: "\n",
402 }, {
403 desc: "repeated set to empty slices",
404 input: &pb2.Repeats{
Herbie Ongcddf8192018-11-28 18:25:20 -0800405 RptBool: []bool{},
406 RptInt32: []int32{},
407 RptInt64: []int64{},
408 RptUint32: []uint32{},
409 RptUint64: []uint64{},
410 RptFloat: []float32{},
411 RptDouble: []float64{},
412 RptBytes: [][]byte{},
Herbie Ong800c9902018-12-06 15:28:53 -0800413 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800414 want: "\n",
415 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800416 desc: "repeated set to some values",
417 input: &pb2.Repeats{
Herbie Ongcddf8192018-11-28 18:25:20 -0800418 RptBool: []bool{true, false, true, true},
419 RptInt32: []int32{1, 6, 0, 0},
420 RptInt64: []int64{-64, 47},
421 RptUint32: []uint32{0xff, 0xffff},
422 RptUint64: []uint64{0xdeadbeef},
423 // TODO: add float32 examples.
424 RptDouble: []float64{math.NaN(), math.Inf(1), math.Inf(-1), 1.23e-308},
425 RptString: []string{"hello", "世界"},
426 RptBytes: [][]byte{
427 []byte("hello"),
428 []byte("\xe4\xb8\x96\xe7\x95\x8c"),
429 },
Herbie Ong800c9902018-12-06 15:28:53 -0800430 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800431 want: `rpt_bool: true
432rpt_bool: false
433rpt_bool: true
434rpt_bool: true
435rpt_int32: 1
436rpt_int32: 6
437rpt_int32: 0
438rpt_int32: 0
439rpt_int64: -64
440rpt_int64: 47
441rpt_uint32: 255
442rpt_uint32: 65535
443rpt_uint64: 3735928559
444rpt_double: nan
445rpt_double: inf
446rpt_double: -inf
447rpt_double: 1.23e-308
448rpt_string: "hello"
449rpt_string: "世界"
450rpt_bytes: "hello"
451rpt_bytes: "世界"
452`,
453 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800454 desc: "repeated enum",
455 input: &pb2.Enums{
Herbie Ongcddf8192018-11-28 18:25:20 -0800456 RptEnum: []pb2.Enum{pb2.Enum_FIRST, 2, pb2.Enum_TENTH, 42},
Herbie Ongcddf8192018-11-28 18:25:20 -0800457 RptNestedEnum: []pb2.Enums_NestedEnum{2, 47, 10},
Herbie Ong800c9902018-12-06 15:28:53 -0800458 },
459 want: `rpt_enum: FIRST
Herbie Ongcddf8192018-11-28 18:25:20 -0800460rpt_enum: SECOND
461rpt_enum: TENTH
462rpt_enum: 42
Herbie Ongcddf8192018-11-28 18:25:20 -0800463rpt_nested_enum: DOS
464rpt_nested_enum: 47
465rpt_nested_enum: DIEZ
466`,
467 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800468 desc: "repeated nested message set to empty",
469 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800470 RptNested: []*pb2.Nested{},
471 Rptgroup: []*pb2.Nests_RptGroup{},
Herbie Ong800c9902018-12-06 15:28:53 -0800472 },
473 want: "\n",
Herbie Ongcddf8192018-11-28 18:25:20 -0800474 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800475 desc: "repeated nested messages",
476 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800477 RptNested: []*pb2.Nested{
478 {
479 OptString: scalar.String("repeat nested one"),
480 },
481 {
482 OptString: scalar.String("repeat nested two"),
483 OptNested: &pb2.Nested{
484 OptString: scalar.String("inside repeat nested two"),
485 },
486 },
487 {},
488 },
Herbie Ong800c9902018-12-06 15:28:53 -0800489 },
490 want: `rpt_nested: {
Herbie Ongcddf8192018-11-28 18:25:20 -0800491 opt_string: "repeat nested one"
492}
493rpt_nested: {
494 opt_string: "repeat nested two"
495 opt_nested: {
496 opt_string: "inside repeat nested two"
497 }
498}
499rpt_nested: {}
500`,
501 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800502 desc: "repeated group fields",
503 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800504 Rptgroup: []*pb2.Nests_RptGroup{
505 {
506 RptBool: []bool{true, false},
507 },
508 {},
509 },
Herbie Ong800c9902018-12-06 15:28:53 -0800510 },
511 want: `rptgroup: {
Herbie Ongcddf8192018-11-28 18:25:20 -0800512 rpt_bool: true
513 rpt_bool: false
514}
515rptgroup: {}
516`,
517 }, {
Herbie Ongcddf8192018-11-28 18:25:20 -0800518 desc: "map fields empty",
Herbie Ong800c9902018-12-06 15:28:53 -0800519 input: &pb2.Maps{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800520 want: "\n",
521 }, {
522 desc: "map fields set to empty maps",
Herbie Ong800c9902018-12-06 15:28:53 -0800523 input: &pb2.Maps{
Herbie Ongcddf8192018-11-28 18:25:20 -0800524 Int32ToStr: map[int32]string{},
525 Sfixed64ToBool: map[int64]bool{},
526 BoolToUint32: map[bool]uint32{},
527 Uint64ToEnum: map[uint64]pb2.Enum{},
528 StrToNested: map[string]*pb2.Nested{},
529 StrToOneofs: map[string]*pb2.Oneofs{},
Herbie Ong800c9902018-12-06 15:28:53 -0800530 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800531 want: "\n",
532 }, {
533 desc: "map fields 1",
Herbie Ong800c9902018-12-06 15:28:53 -0800534 input: &pb2.Maps{
Herbie Ongcddf8192018-11-28 18:25:20 -0800535 Int32ToStr: map[int32]string{
536 -101: "-101",
537 0xff: "0xff",
538 0: "zero",
539 },
540 Sfixed64ToBool: map[int64]bool{
541 0xcafe: true,
542 0: false,
543 },
544 BoolToUint32: map[bool]uint32{
545 true: 42,
546 false: 101,
547 },
Herbie Ong800c9902018-12-06 15:28:53 -0800548 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800549 want: `int32_to_str: {
550 key: -101
551 value: "-101"
552}
553int32_to_str: {
554 key: 0
555 value: "zero"
556}
557int32_to_str: {
558 key: 255
559 value: "0xff"
560}
561sfixed64_to_bool: {
562 key: 0
563 value: false
564}
565sfixed64_to_bool: {
566 key: 51966
567 value: true
568}
569bool_to_uint32: {
570 key: false
571 value: 101
572}
573bool_to_uint32: {
574 key: true
575 value: 42
576}
577`,
578 }, {
579 desc: "map fields 2",
Herbie Ong800c9902018-12-06 15:28:53 -0800580 input: &pb2.Maps{
Herbie Ongcddf8192018-11-28 18:25:20 -0800581 Uint64ToEnum: map[uint64]pb2.Enum{
582 1: pb2.Enum_FIRST,
583 2: pb2.Enum_SECOND,
584 10: pb2.Enum_TENTH,
585 },
Herbie Ong800c9902018-12-06 15:28:53 -0800586 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800587 want: `uint64_to_enum: {
588 key: 1
589 value: FIRST
590}
591uint64_to_enum: {
592 key: 2
593 value: SECOND
594}
595uint64_to_enum: {
596 key: 10
597 value: TENTH
598}
599`,
600 }, {
601 desc: "map fields 3",
Herbie Ong800c9902018-12-06 15:28:53 -0800602 input: &pb2.Maps{
Herbie Ongcddf8192018-11-28 18:25:20 -0800603 StrToNested: map[string]*pb2.Nested{
604 "nested_one": &pb2.Nested{
605 OptString: scalar.String("nested in a map"),
606 },
607 },
Herbie Ong800c9902018-12-06 15:28:53 -0800608 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800609 want: `str_to_nested: {
610 key: "nested_one"
611 value: {
612 opt_string: "nested in a map"
613 }
614}
615`,
616 }, {
617 desc: "map fields 4",
Herbie Ong800c9902018-12-06 15:28:53 -0800618 input: &pb2.Maps{
Herbie Ongcddf8192018-11-28 18:25:20 -0800619 StrToOneofs: map[string]*pb2.Oneofs{
620 "string": &pb2.Oneofs{
621 Union: &pb2.Oneofs_Str{
622 Str: "hello",
623 },
624 },
625 "nested": &pb2.Oneofs{
626 Union: &pb2.Oneofs_Msg{
627 Msg: &pb2.Nested{
628 OptString: scalar.String("nested oneof in map field value"),
629 },
630 },
631 },
632 },
Herbie Ong800c9902018-12-06 15:28:53 -0800633 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800634 want: `str_to_oneofs: {
635 key: "nested"
636 value: {
637 msg: {
638 opt_string: "nested oneof in map field value"
639 }
640 }
641}
642str_to_oneofs: {
643 key: "string"
644 value: {
645 str: "hello"
646 }
647}
648`,
649 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800650 desc: "proto2 required fields not set",
651 input: &pb2.Requireds{},
652 want: "\n",
653 wantErr: true,
Herbie Ongcddf8192018-11-28 18:25:20 -0800654 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800655 desc: "proto2 required fields partially set",
656 input: &pb2.Requireds{
657 ReqBool: scalar.Bool(false),
658 ReqFixed32: scalar.Uint32(47),
659 ReqSfixed64: scalar.Int64(0xbeefcafe),
660 ReqDouble: scalar.Float64(math.NaN()),
661 ReqString: scalar.String("hello"),
662 ReqEnum: pb2.Enum_FIRST.Enum(),
663 },
664 want: `req_bool: false
665req_fixed32: 47
666req_sfixed64: 3203386110
667req_double: nan
668req_string: "hello"
669req_enum: FIRST
670`,
671 wantErr: true,
672 }, {
673 desc: "proto2 required fields all set",
674 input: &pb2.Requireds{
675 ReqBool: scalar.Bool(false),
676 ReqFixed32: scalar.Uint32(0),
677 ReqFixed64: scalar.Uint64(0),
678 ReqSfixed32: scalar.Int32(0),
679 ReqSfixed64: scalar.Int64(0),
680 ReqFloat: scalar.Float32(0),
681 ReqDouble: scalar.Float64(0),
682 ReqString: scalar.String(""),
683 ReqEnum: pb2.Enum_UNKNOWN.Enum(),
684 ReqBytes: []byte{},
685 ReqNested: &pb2.Nested{},
686 },
687 want: `req_bool: false
688req_fixed32: 0
689req_fixed64: 0
690req_sfixed32: 0
691req_sfixed64: 0
692req_float: 0
693req_double: 0
694req_string: ""
695req_bytes: ""
696req_enum: UNKNOWN
697req_nested: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800698`,
699 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800700 desc: "indirect required field",
701 input: &pb2.IndirectRequired{
702 OptNested: &pb2.NestedWithRequired{},
703 },
704 want: "opt_nested: {}\n",
705 wantErr: true,
Herbie Ongcddf8192018-11-28 18:25:20 -0800706 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800707 desc: "indirect required field in empty repeated",
708 input: &pb2.IndirectRequired{
709 RptNested: []*pb2.NestedWithRequired{},
710 },
711 want: "\n",
Herbie Ongcddf8192018-11-28 18:25:20 -0800712 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800713 desc: "indirect required field in repeated",
714 input: &pb2.IndirectRequired{
715 RptNested: []*pb2.NestedWithRequired{
716 &pb2.NestedWithRequired{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800717 },
Herbie Ong800c9902018-12-06 15:28:53 -0800718 },
719 want: "rpt_nested: {}\n",
720 wantErr: true,
721 }, {
722 desc: "indirect required field in empty map",
723 input: &pb2.IndirectRequired{
724 StrToNested: map[string]*pb2.NestedWithRequired{},
725 },
726 want: "\n",
727 }, {
728 desc: "indirect required field in map",
729 input: &pb2.IndirectRequired{
730 StrToNested: map[string]*pb2.NestedWithRequired{
731 "fail": &pb2.NestedWithRequired{},
732 },
733 },
734 want: `str_to_nested: {
735 key: "fail"
736 value: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800737}
738`,
Herbie Ong800c9902018-12-06 15:28:53 -0800739 wantErr: true,
Herbie Ongcddf8192018-11-28 18:25:20 -0800740 }}
741
742 for _, tt := range tests {
743 tt := tt
744 t.Run(tt.desc, func(t *testing.T) {
745 t.Parallel()
Herbie Ong800c9902018-12-06 15:28:53 -0800746 b, err := textpb.Marshal(M(tt.input))
Herbie Ongcddf8192018-11-28 18:25:20 -0800747 if err != nil && !tt.wantErr {
748 t.Errorf("Marshal() returned error: %v\n\n", err)
749 }
Herbie Ong800c9902018-12-06 15:28:53 -0800750 if err == nil && tt.wantErr {
751 t.Error("Marshal() got nil error, want error\n\n")
Herbie Ongcddf8192018-11-28 18:25:20 -0800752 }
Herbie Ong800c9902018-12-06 15:28:53 -0800753 got := string(b)
754 if tt.want != "" && got != tt.want {
755 t.Errorf("Marshal()\n<got>\n%v\n<want>\n%v\n", got, tt.want)
756 if diff := cmp.Diff(tt.want, got, splitLines); diff != "" {
Herbie Ongcddf8192018-11-28 18:25:20 -0800757 t.Errorf("Marshal() diff -want +got\n%v\n", diff)
758 }
759 }
760 })
761 }
762}