blob: 42f4e9805080412eaf9161540579448e0c5a1b05 [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
Damien Neil5c5b5312019-05-14 12:44:37 -07005package prototext_test
Herbie Ongcddf8192018-11-28 18:25:20 -08006
7import (
Herbie Onga94f78c2019-01-03 15:39:58 -08008 "encoding/hex"
Herbie Ongcddf8192018-11-28 18:25:20 -08009 "math"
Herbie Ongcddf8192018-11-28 18:25:20 -080010 "testing"
11
Herbie Ongcddf8192018-11-28 18:25:20 -080012 "github.com/google/go-cmp/cmp"
Damien Neil5c5b5312019-05-14 12:44:37 -070013 "google.golang.org/protobuf/encoding/prototext"
Damien Neile89e6242019-05-13 23:55:40 -070014 "google.golang.org/protobuf/internal/detrand"
15 "google.golang.org/protobuf/internal/encoding/pack"
Damien Neile89e6242019-05-13 23:55:40 -070016 pimpl "google.golang.org/protobuf/internal/impl"
17 "google.golang.org/protobuf/internal/scalar"
18 "google.golang.org/protobuf/proto"
19 preg "google.golang.org/protobuf/reflect/protoregistry"
20 "google.golang.org/protobuf/runtime/protoiface"
Herbie Ongcddf8192018-11-28 18:25:20 -080021
Damien Neile89e6242019-05-13 23:55:40 -070022 "google.golang.org/protobuf/encoding/testprotos/pb2"
23 "google.golang.org/protobuf/encoding/testprotos/pb3"
Joe Tsaia95b29f2019-05-16 12:47:20 -070024 "google.golang.org/protobuf/types/known/anypb"
Herbie Ongcddf8192018-11-28 18:25:20 -080025)
26
27func init() {
28 // Disable detrand to enable direct comparisons on outputs.
29 detrand.Disable()
30}
31
Herbie Ong800c9902018-12-06 15:28:53 -080032func pb2Enum(i int32) *pb2.Enum {
33 p := new(pb2.Enum)
34 *p = pb2.Enum(i)
35 return p
36}
37
38func pb2Enums_NestedEnum(i int32) *pb2.Enums_NestedEnum {
39 p := new(pb2.Enums_NestedEnum)
40 *p = pb2.Enums_NestedEnum(i)
41 return p
42}
43
Joe Tsai378c1322019-04-25 23:48:08 -070044// TODO: Use proto.SetExtension when available.
Joe Tsai4fddeba2019-03-20 18:29:32 -070045func setExtension(m proto.Message, xd *protoiface.ExtensionDescV1, val interface{}) {
Joe Tsai378c1322019-04-25 23:48:08 -070046 m.ProtoReflect().Set(xd.Type, xd.Type.ValueOf(val))
Herbie Ongcf253082018-12-17 17:13:07 -080047}
48
Herbie Onga94f78c2019-01-03 15:39:58 -080049// dhex decodes a hex-string and returns the bytes and panics if s is invalid.
50func dhex(s string) []byte {
51 b, err := hex.DecodeString(s)
52 if err != nil {
53 panic(err)
54 }
55 return b
56}
57
Herbie Ongcddf8192018-11-28 18:25:20 -080058func TestMarshal(t *testing.T) {
59 tests := []struct {
60 desc string
Damien Neil5c5b5312019-05-14 12:44:37 -070061 mo prototext.MarshalOptions
Herbie Ong70651952018-12-13 14:19:50 -080062 input proto.Message
Herbie Ongcddf8192018-11-28 18:25:20 -080063 want string
Herbie Ong300cff02019-03-20 18:05:16 -070064 wantErr bool // TODO: Verify error message content.
Herbie Ongcddf8192018-11-28 18:25:20 -080065 }{{
Herbie Ong8170d692019-02-13 14:13:21 -080066 desc: "proto2 optional scalars not set",
Herbie Ong800c9902018-12-06 15:28:53 -080067 input: &pb2.Scalars{},
Herbie Ongcddf8192018-11-28 18:25:20 -080068 want: "\n",
69 }, {
Herbie Ong8170d692019-02-13 14:13:21 -080070 desc: "proto3 scalars not set",
Herbie Ong800c9902018-12-06 15:28:53 -080071 input: &pb3.Scalars{},
Herbie Ongcddf8192018-11-28 18:25:20 -080072 want: "\n",
73 }, {
Herbie Ong8170d692019-02-13 14:13:21 -080074 desc: "proto2 optional scalars set to zero values",
Herbie Ong800c9902018-12-06 15:28:53 -080075 input: &pb2.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -080076 OptBool: scalar.Bool(false),
77 OptInt32: scalar.Int32(0),
78 OptInt64: scalar.Int64(0),
79 OptUint32: scalar.Uint32(0),
80 OptUint64: scalar.Uint64(0),
81 OptSint32: scalar.Int32(0),
82 OptSint64: scalar.Int64(0),
83 OptFixed32: scalar.Uint32(0),
84 OptFixed64: scalar.Uint64(0),
85 OptSfixed32: scalar.Int32(0),
86 OptSfixed64: scalar.Int64(0),
87 OptFloat: scalar.Float32(0),
88 OptDouble: scalar.Float64(0),
89 OptBytes: []byte{},
90 OptString: scalar.String(""),
Herbie Ong800c9902018-12-06 15:28:53 -080091 },
Herbie Ongcddf8192018-11-28 18:25:20 -080092 want: `opt_bool: false
93opt_int32: 0
94opt_int64: 0
95opt_uint32: 0
96opt_uint64: 0
97opt_sint32: 0
98opt_sint64: 0
99opt_fixed32: 0
100opt_fixed64: 0
101opt_sfixed32: 0
102opt_sfixed64: 0
103opt_float: 0
104opt_double: 0
105opt_bytes: ""
106opt_string: ""
107`,
108 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800109 desc: "proto3 scalars set to zero values",
Herbie Ong800c9902018-12-06 15:28:53 -0800110 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800111 SBool: false,
112 SInt32: 0,
113 SInt64: 0,
114 SUint32: 0,
115 SUint64: 0,
116 SSint32: 0,
117 SSint64: 0,
118 SFixed32: 0,
119 SFixed64: 0,
120 SSfixed32: 0,
121 SSfixed64: 0,
122 SFloat: 0,
123 SDouble: 0,
124 SBytes: []byte{},
125 SString: "",
Herbie Ong800c9902018-12-06 15:28:53 -0800126 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800127 want: "\n",
128 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800129 desc: "proto2 optional scalars set to some values",
Herbie Ong800c9902018-12-06 15:28:53 -0800130 input: &pb2.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800131 OptBool: scalar.Bool(true),
132 OptInt32: scalar.Int32(0xff),
133 OptInt64: scalar.Int64(0xdeadbeef),
134 OptUint32: scalar.Uint32(47),
135 OptUint64: scalar.Uint64(0xdeadbeef),
136 OptSint32: scalar.Int32(-1001),
137 OptSint64: scalar.Int64(-0xffff),
138 OptFixed64: scalar.Uint64(64),
139 OptSfixed32: scalar.Int32(-32),
Herbie Ong84f09602019-01-17 19:31:47 -0800140 OptFloat: scalar.Float32(1.02),
141 OptDouble: scalar.Float64(1.0199999809265137),
Herbie Ong8170d692019-02-13 14:13:21 -0800142 OptBytes: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
143 OptString: scalar.String("谷歌"),
Herbie Ong800c9902018-12-06 15:28:53 -0800144 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800145 want: `opt_bool: true
146opt_int32: 255
147opt_int64: 3735928559
148opt_uint32: 47
149opt_uint64: 3735928559
150opt_sint32: -1001
151opt_sint64: -65535
152opt_fixed64: 64
153opt_sfixed32: -32
Herbie Ong84f09602019-01-17 19:31:47 -0800154opt_float: 1.02
155opt_double: 1.0199999809265137
Herbie Ongcddf8192018-11-28 18:25:20 -0800156opt_bytes: "谷歌"
157opt_string: "谷歌"
158`,
159 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700160 desc: "string with invalid UTF-8",
161 input: &pb3.Scalars{
162 SString: "abc\xff",
163 },
Herbie Ong21a39742019-04-08 17:32:44 -0700164 wantErr: true,
165 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800166 desc: "float nan",
Herbie Ong800c9902018-12-06 15:28:53 -0800167 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800168 SFloat: float32(math.NaN()),
Herbie Ong800c9902018-12-06 15:28:53 -0800169 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800170 want: "s_float: nan\n",
171 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800172 desc: "float positive infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800173 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800174 SFloat: float32(math.Inf(1)),
Herbie Ong800c9902018-12-06 15:28:53 -0800175 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800176 want: "s_float: inf\n",
177 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800178 desc: "float negative infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800179 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800180 SFloat: float32(math.Inf(-1)),
Herbie Ong800c9902018-12-06 15:28:53 -0800181 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800182 want: "s_float: -inf\n",
183 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800184 desc: "double nan",
Herbie Ong800c9902018-12-06 15:28:53 -0800185 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800186 SDouble: math.NaN(),
Herbie Ong800c9902018-12-06 15:28:53 -0800187 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800188 want: "s_double: nan\n",
189 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800190 desc: "double positive infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800191 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800192 SDouble: math.Inf(1),
Herbie Ong800c9902018-12-06 15:28:53 -0800193 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800194 want: "s_double: inf\n",
195 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800196 desc: "double negative infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800197 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800198 SDouble: math.Inf(-1),
Herbie Ong800c9902018-12-06 15:28:53 -0800199 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800200 want: "s_double: -inf\n",
201 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800202 desc: "proto2 enum not set",
203 input: &pb2.Enums{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800204 want: "\n",
205 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800206 desc: "proto2 enum set to zero value",
207 input: &pb2.Enums{
Herbie Ong8170d692019-02-13 14:13:21 -0800208 OptEnum: pb2Enum(0),
Herbie Ong800c9902018-12-06 15:28:53 -0800209 OptNestedEnum: pb2Enums_NestedEnum(0),
210 },
Herbie Ong8170d692019-02-13 14:13:21 -0800211 want: `opt_enum: 0
Herbie Ong800c9902018-12-06 15:28:53 -0800212opt_nested_enum: 0
213`,
214 }, {
215 desc: "proto2 enum",
216 input: &pb2.Enums{
Herbie Ong8170d692019-02-13 14:13:21 -0800217 OptEnum: pb2.Enum_ONE.Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800218 OptNestedEnum: pb2.Enums_UNO.Enum(),
219 },
Herbie Ong8170d692019-02-13 14:13:21 -0800220 want: `opt_enum: ONE
Herbie Ong800c9902018-12-06 15:28:53 -0800221opt_nested_enum: UNO
222`,
223 }, {
224 desc: "proto2 enum set to numeric values",
225 input: &pb2.Enums{
Herbie Ong8170d692019-02-13 14:13:21 -0800226 OptEnum: pb2Enum(2),
Herbie Ong800c9902018-12-06 15:28:53 -0800227 OptNestedEnum: pb2Enums_NestedEnum(2),
228 },
Herbie Ong8170d692019-02-13 14:13:21 -0800229 want: `opt_enum: TWO
Herbie Ong800c9902018-12-06 15:28:53 -0800230opt_nested_enum: DOS
231`,
232 }, {
233 desc: "proto2 enum set to unnamed numeric values",
234 input: &pb2.Enums{
235 OptEnum: pb2Enum(101),
236 OptNestedEnum: pb2Enums_NestedEnum(-101),
237 },
238 want: `opt_enum: 101
239opt_nested_enum: -101
240`,
241 }, {
242 desc: "proto3 enum not set",
243 input: &pb3.Enums{},
244 want: "\n",
245 }, {
246 desc: "proto3 enum set to zero value",
247 input: &pb3.Enums{
248 SEnum: pb3.Enum_ZERO,
249 SNestedEnum: pb3.Enums_CERO,
250 },
251 want: "\n",
252 }, {
253 desc: "proto3 enum",
254 input: &pb3.Enums{
255 SEnum: pb3.Enum_ONE,
Herbie Ong8170d692019-02-13 14:13:21 -0800256 SNestedEnum: pb3.Enums_UNO,
Herbie Ong800c9902018-12-06 15:28:53 -0800257 },
258 want: `s_enum: ONE
Herbie Ong8170d692019-02-13 14:13:21 -0800259s_nested_enum: UNO
Herbie Ong800c9902018-12-06 15:28:53 -0800260`,
261 }, {
262 desc: "proto3 enum set to numeric values",
263 input: &pb3.Enums{
264 SEnum: 2,
Herbie Ong8170d692019-02-13 14:13:21 -0800265 SNestedEnum: 2,
Herbie Ong800c9902018-12-06 15:28:53 -0800266 },
267 want: `s_enum: TWO
Herbie Ong8170d692019-02-13 14:13:21 -0800268s_nested_enum: DOS
Herbie Ong800c9902018-12-06 15:28:53 -0800269`,
270 }, {
271 desc: "proto3 enum set to unnamed numeric values",
272 input: &pb3.Enums{
273 SEnum: -47,
274 SNestedEnum: 47,
275 },
276 want: `s_enum: -47
277s_nested_enum: 47
278`,
279 }, {
280 desc: "proto2 nested message not set",
281 input: &pb2.Nests{},
282 want: "\n",
283 }, {
284 desc: "proto2 nested message set to empty",
285 input: &pb2.Nests{
286 OptNested: &pb2.Nested{},
287 Optgroup: &pb2.Nests_OptGroup{},
288 },
289 want: `opt_nested: {}
Herbie Ong0dcfb9a2019-01-14 15:32:26 -0800290OptGroup: {}
Herbie Ong800c9902018-12-06 15:28:53 -0800291`,
292 }, {
293 desc: "proto2 nested messages",
294 input: &pb2.Nests{
295 OptNested: &pb2.Nested{
296 OptString: scalar.String("nested message"),
297 OptNested: &pb2.Nested{
298 OptString: scalar.String("another nested message"),
299 },
300 },
301 },
302 want: `opt_nested: {
303 opt_string: "nested message"
304 opt_nested: {
305 opt_string: "another nested message"
306 }
307}
308`,
309 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800310 desc: "proto2 groups",
Herbie Ong800c9902018-12-06 15:28:53 -0800311 input: &pb2.Nests{
312 Optgroup: &pb2.Nests_OptGroup{
Herbie Ong800c9902018-12-06 15:28:53 -0800313 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{
Herbie Ong8170d692019-02-13 14:13:21 -0800318 OptFixed32: scalar.Uint32(47),
Herbie Ong800c9902018-12-06 15:28:53 -0800319 },
320 },
321 },
Herbie Ong0dcfb9a2019-01-14 15:32:26 -0800322 want: `OptGroup: {
Herbie Ong800c9902018-12-06 15:28:53 -0800323 opt_string: "inside a group"
324 opt_nested: {
325 opt_string: "nested message inside a group"
326 }
Herbie Ong0dcfb9a2019-01-14 15:32:26 -0800327 OptNestedGroup: {
Herbie Ong8170d692019-02-13 14:13:21 -0800328 opt_fixed32: 47
Herbie Ong800c9902018-12-06 15:28:53 -0800329 }
330}
331`,
332 }, {
333 desc: "proto3 nested message not set",
334 input: &pb3.Nests{},
335 want: "\n",
336 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800337 desc: "proto3 nested message set to empty",
338 input: &pb3.Nests{
339 SNested: &pb3.Nested{},
340 },
341 want: "s_nested: {}\n",
342 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800343 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 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700360 desc: "proto3 nested message contains invalid UTF-8",
361 input: &pb3.Nests{
362 SNested: &pb3.Nested{
363 SString: "abc\xff",
364 },
365 },
Herbie Ong21a39742019-04-08 17:32:44 -0700366 wantErr: true,
367 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800368 desc: "oneof not set",
369 input: &pb3.Oneofs{},
Herbie Ong800c9902018-12-06 15:28:53 -0800370 want: "\n",
371 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800372 desc: "oneof set to empty string",
373 input: &pb3.Oneofs{
374 Union: &pb3.Oneofs_OneofString{},
Herbie Ong800c9902018-12-06 15:28:53 -0800375 },
Herbie Ong8170d692019-02-13 14:13:21 -0800376 want: `oneof_string: ""
377`,
Herbie Ong800c9902018-12-06 15:28:53 -0800378 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800379 desc: "oneof set to string",
380 input: &pb3.Oneofs{
381 Union: &pb3.Oneofs_OneofString{
382 OneofString: "hello",
Herbie Ong800c9902018-12-06 15:28:53 -0800383 },
384 },
Herbie Ong8170d692019-02-13 14:13:21 -0800385 want: `oneof_string: "hello"
386`,
Herbie Ong800c9902018-12-06 15:28:53 -0800387 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800388 desc: "oneof set to enum",
389 input: &pb3.Oneofs{
390 Union: &pb3.Oneofs_OneofEnum{
391 OneofEnum: pb3.Enum_ZERO,
Herbie Ong800c9902018-12-06 15:28:53 -0800392 },
393 },
Herbie Ong8170d692019-02-13 14:13:21 -0800394 want: `oneof_enum: ZERO
395`,
Herbie Ong800c9902018-12-06 15:28:53 -0800396 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800397 desc: "oneof set to empty message",
398 input: &pb3.Oneofs{
399 Union: &pb3.Oneofs_OneofNested{
400 OneofNested: &pb3.Nested{},
401 },
402 },
403 want: "oneof_nested: {}\n",
404 }, {
405 desc: "oneof set to message",
406 input: &pb3.Oneofs{
407 Union: &pb3.Oneofs_OneofNested{
408 OneofNested: &pb3.Nested{
409 SString: "nested message",
Herbie Ong800c9902018-12-06 15:28:53 -0800410 },
411 },
412 },
Herbie Ong8170d692019-02-13 14:13:21 -0800413 want: `oneof_nested: {
414 s_string: "nested message"
Herbie Ong800c9902018-12-06 15:28:53 -0800415}
416`,
417 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800418 desc: "repeated fields not set",
Herbie Ong800c9902018-12-06 15:28:53 -0800419 input: &pb2.Repeats{},
420 want: "\n",
421 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800422 desc: "repeated fields set to empty slices",
Herbie Ong800c9902018-12-06 15:28:53 -0800423 input: &pb2.Repeats{
Herbie Ongcddf8192018-11-28 18:25:20 -0800424 RptBool: []bool{},
425 RptInt32: []int32{},
426 RptInt64: []int64{},
427 RptUint32: []uint32{},
428 RptUint64: []uint64{},
429 RptFloat: []float32{},
430 RptDouble: []float64{},
431 RptBytes: [][]byte{},
Herbie Ong800c9902018-12-06 15:28:53 -0800432 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800433 want: "\n",
434 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800435 desc: "repeated fields set to some values",
Herbie Ong800c9902018-12-06 15:28:53 -0800436 input: &pb2.Repeats{
Herbie Ongcddf8192018-11-28 18:25:20 -0800437 RptBool: []bool{true, false, true, true},
438 RptInt32: []int32{1, 6, 0, 0},
439 RptInt64: []int64{-64, 47},
440 RptUint32: []uint32{0xff, 0xffff},
441 RptUint64: []uint64{0xdeadbeef},
Herbie Ong84f09602019-01-17 19:31:47 -0800442 RptFloat: []float32{float32(math.NaN()), float32(math.Inf(1)), float32(math.Inf(-1)), 1.034},
Herbie Ongcddf8192018-11-28 18:25:20 -0800443 RptDouble: []float64{math.NaN(), math.Inf(1), math.Inf(-1), 1.23e-308},
444 RptString: []string{"hello", "世界"},
445 RptBytes: [][]byte{
446 []byte("hello"),
447 []byte("\xe4\xb8\x96\xe7\x95\x8c"),
448 },
Herbie Ong800c9902018-12-06 15:28:53 -0800449 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800450 want: `rpt_bool: true
451rpt_bool: false
452rpt_bool: true
453rpt_bool: true
454rpt_int32: 1
455rpt_int32: 6
456rpt_int32: 0
457rpt_int32: 0
458rpt_int64: -64
459rpt_int64: 47
460rpt_uint32: 255
461rpt_uint32: 65535
462rpt_uint64: 3735928559
Herbie Ong84f09602019-01-17 19:31:47 -0800463rpt_float: nan
464rpt_float: inf
465rpt_float: -inf
466rpt_float: 1.034
Herbie Ongcddf8192018-11-28 18:25:20 -0800467rpt_double: nan
468rpt_double: inf
469rpt_double: -inf
470rpt_double: 1.23e-308
471rpt_string: "hello"
472rpt_string: "世界"
473rpt_bytes: "hello"
474rpt_bytes: "世界"
475`,
476 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700477 desc: "repeated contains invalid UTF-8",
478 input: &pb2.Repeats{
479 RptString: []string{"abc\xff"},
480 },
Herbie Ong21a39742019-04-08 17:32:44 -0700481 wantErr: true,
482 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800483 desc: "repeated enums",
Herbie Ong800c9902018-12-06 15:28:53 -0800484 input: &pb2.Enums{
Herbie Ong8170d692019-02-13 14:13:21 -0800485 RptEnum: []pb2.Enum{pb2.Enum_ONE, 2, pb2.Enum_TEN, 42},
Herbie Ongcddf8192018-11-28 18:25:20 -0800486 RptNestedEnum: []pb2.Enums_NestedEnum{2, 47, 10},
Herbie Ong800c9902018-12-06 15:28:53 -0800487 },
Herbie Ong8170d692019-02-13 14:13:21 -0800488 want: `rpt_enum: ONE
489rpt_enum: TWO
490rpt_enum: TEN
Herbie Ongcddf8192018-11-28 18:25:20 -0800491rpt_enum: 42
Herbie Ongcddf8192018-11-28 18:25:20 -0800492rpt_nested_enum: DOS
493rpt_nested_enum: 47
494rpt_nested_enum: DIEZ
495`,
496 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800497 desc: "repeated messages set to empty",
Herbie Ong800c9902018-12-06 15:28:53 -0800498 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800499 RptNested: []*pb2.Nested{},
500 Rptgroup: []*pb2.Nests_RptGroup{},
Herbie Ong800c9902018-12-06 15:28:53 -0800501 },
502 want: "\n",
Herbie Ongcddf8192018-11-28 18:25:20 -0800503 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800504 desc: "repeated messages",
Herbie Ong800c9902018-12-06 15:28:53 -0800505 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800506 RptNested: []*pb2.Nested{
507 {
508 OptString: scalar.String("repeat nested one"),
509 },
510 {
511 OptString: scalar.String("repeat nested two"),
512 OptNested: &pb2.Nested{
513 OptString: scalar.String("inside repeat nested two"),
514 },
515 },
516 {},
517 },
Herbie Ong800c9902018-12-06 15:28:53 -0800518 },
519 want: `rpt_nested: {
Herbie Ongcddf8192018-11-28 18:25:20 -0800520 opt_string: "repeat nested one"
521}
522rpt_nested: {
523 opt_string: "repeat nested two"
524 opt_nested: {
525 opt_string: "inside repeat nested two"
526 }
527}
528rpt_nested: {}
529`,
530 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800531 desc: "repeated messages contains nil value",
Herbie Ongf5db2df2019-02-07 20:17:45 -0800532 input: &pb2.Nests{
533 RptNested: []*pb2.Nested{nil, {}},
534 },
535 want: `rpt_nested: {}
536rpt_nested: {}
537`,
538 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800539 desc: "repeated groups",
Herbie Ong800c9902018-12-06 15:28:53 -0800540 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800541 Rptgroup: []*pb2.Nests_RptGroup{
542 {
Herbie Ong8170d692019-02-13 14:13:21 -0800543 RptString: []string{"hello", "world"},
Herbie Ongcddf8192018-11-28 18:25:20 -0800544 },
545 {},
Herbie Ong8170d692019-02-13 14:13:21 -0800546 nil,
Herbie Ongcddf8192018-11-28 18:25:20 -0800547 },
Herbie Ong800c9902018-12-06 15:28:53 -0800548 },
Herbie Ongde7313b2019-01-14 19:26:50 -0800549 want: `RptGroup: {
Herbie Ong8170d692019-02-13 14:13:21 -0800550 rpt_string: "hello"
551 rpt_string: "world"
Herbie Ongcddf8192018-11-28 18:25:20 -0800552}
Herbie Ongde7313b2019-01-14 19:26:50 -0800553RptGroup: {}
Herbie Ong8170d692019-02-13 14:13:21 -0800554RptGroup: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800555`,
556 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800557 desc: "map fields not set",
558 input: &pb3.Maps{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800559 want: "\n",
560 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800561 desc: "map fields set to empty",
562 input: &pb3.Maps{
563 Int32ToStr: map[int32]string{},
564 BoolToUint32: map[bool]uint32{},
565 Uint64ToEnum: map[uint64]pb3.Enum{},
566 StrToNested: map[string]*pb3.Nested{},
567 StrToOneofs: map[string]*pb3.Oneofs{},
Herbie Ong800c9902018-12-06 15:28:53 -0800568 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800569 want: "\n",
570 }, {
571 desc: "map fields 1",
Herbie Ong8170d692019-02-13 14:13:21 -0800572 input: &pb3.Maps{
Herbie Ongcddf8192018-11-28 18:25:20 -0800573 Int32ToStr: map[int32]string{
574 -101: "-101",
575 0xff: "0xff",
576 0: "zero",
577 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800578 BoolToUint32: map[bool]uint32{
579 true: 42,
580 false: 101,
581 },
Herbie Ong800c9902018-12-06 15:28:53 -0800582 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800583 want: `int32_to_str: {
584 key: -101
585 value: "-101"
586}
587int32_to_str: {
588 key: 0
589 value: "zero"
590}
591int32_to_str: {
592 key: 255
593 value: "0xff"
594}
Herbie Ongcddf8192018-11-28 18:25:20 -0800595bool_to_uint32: {
596 key: false
597 value: 101
598}
599bool_to_uint32: {
600 key: true
601 value: 42
602}
603`,
604 }, {
605 desc: "map fields 2",
Herbie Ong8170d692019-02-13 14:13:21 -0800606 input: &pb3.Maps{
607 Uint64ToEnum: map[uint64]pb3.Enum{
608 1: pb3.Enum_ONE,
609 2: pb3.Enum_TWO,
610 10: pb3.Enum_TEN,
611 47: 47,
Herbie Ongcddf8192018-11-28 18:25:20 -0800612 },
Herbie Ong800c9902018-12-06 15:28:53 -0800613 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800614 want: `uint64_to_enum: {
615 key: 1
Herbie Ong8170d692019-02-13 14:13:21 -0800616 value: ONE
Herbie Ongcddf8192018-11-28 18:25:20 -0800617}
618uint64_to_enum: {
619 key: 2
Herbie Ong8170d692019-02-13 14:13:21 -0800620 value: TWO
Herbie Ongcddf8192018-11-28 18:25:20 -0800621}
622uint64_to_enum: {
623 key: 10
Herbie Ong8170d692019-02-13 14:13:21 -0800624 value: TEN
625}
626uint64_to_enum: {
627 key: 47
628 value: 47
Herbie Ongcddf8192018-11-28 18:25:20 -0800629}
630`,
631 }, {
632 desc: "map fields 3",
Herbie Ong8170d692019-02-13 14:13:21 -0800633 input: &pb3.Maps{
634 StrToNested: map[string]*pb3.Nested{
635 "nested": &pb3.Nested{
636 SString: "nested in a map",
Herbie Ongcddf8192018-11-28 18:25:20 -0800637 },
638 },
Herbie Ong800c9902018-12-06 15:28:53 -0800639 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800640 want: `str_to_nested: {
Herbie Ong8170d692019-02-13 14:13:21 -0800641 key: "nested"
Herbie Ongcddf8192018-11-28 18:25:20 -0800642 value: {
Herbie Ong8170d692019-02-13 14:13:21 -0800643 s_string: "nested in a map"
Herbie Ongcddf8192018-11-28 18:25:20 -0800644 }
645}
646`,
647 }, {
648 desc: "map fields 4",
Herbie Ong8170d692019-02-13 14:13:21 -0800649 input: &pb3.Maps{
650 StrToOneofs: map[string]*pb3.Oneofs{
651 "string": &pb3.Oneofs{
652 Union: &pb3.Oneofs_OneofString{
653 OneofString: "hello",
Herbie Ongcddf8192018-11-28 18:25:20 -0800654 },
655 },
Herbie Ong8170d692019-02-13 14:13:21 -0800656 "nested": &pb3.Oneofs{
657 Union: &pb3.Oneofs_OneofNested{
658 OneofNested: &pb3.Nested{
659 SString: "nested oneof in map field value",
Herbie Ongcddf8192018-11-28 18:25:20 -0800660 },
661 },
662 },
663 },
Herbie Ong800c9902018-12-06 15:28:53 -0800664 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800665 want: `str_to_oneofs: {
666 key: "nested"
667 value: {
Herbie Ong8170d692019-02-13 14:13:21 -0800668 oneof_nested: {
669 s_string: "nested oneof in map field value"
Herbie Ongcddf8192018-11-28 18:25:20 -0800670 }
671 }
672}
673str_to_oneofs: {
674 key: "string"
675 value: {
Herbie Ong8170d692019-02-13 14:13:21 -0800676 oneof_string: "hello"
Herbie Ongcddf8192018-11-28 18:25:20 -0800677 }
678}
679`,
680 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700681 desc: "map field value contains invalid UTF-8",
682 input: &pb3.Maps{
683 Int32ToStr: map[int32]string{
684 101: "abc\xff",
685 },
686 },
Herbie Ong21a39742019-04-08 17:32:44 -0700687 wantErr: true,
688 }, {
689 desc: "map field key contains invalid UTF-8",
690 input: &pb3.Maps{
691 StrToNested: map[string]*pb3.Nested{
692 "abc\xff": {},
693 },
694 },
Herbie Ong21a39742019-04-08 17:32:44 -0700695 wantErr: true,
696 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800697 desc: "map field contains nil value",
698 input: &pb3.Maps{
699 StrToNested: map[string]*pb3.Nested{
Herbie Ongf5db2df2019-02-07 20:17:45 -0800700 "nil": nil,
701 },
702 },
703 want: `str_to_nested: {
704 key: "nil"
705 value: {}
706}
707`,
708 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700709 desc: "required fields not set",
Herbie Ong800c9902018-12-06 15:28:53 -0800710 input: &pb2.Requireds{},
711 want: "\n",
712 wantErr: true,
Herbie Ongcddf8192018-11-28 18:25:20 -0800713 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700714 desc: "required fields partially set",
Herbie Ong800c9902018-12-06 15:28:53 -0800715 input: &pb2.Requireds{
716 ReqBool: scalar.Bool(false),
Herbie Ong800c9902018-12-06 15:28:53 -0800717 ReqSfixed64: scalar.Int64(0xbeefcafe),
718 ReqDouble: scalar.Float64(math.NaN()),
719 ReqString: scalar.String("hello"),
Herbie Ong8170d692019-02-13 14:13:21 -0800720 ReqEnum: pb2.Enum_ONE.Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800721 },
722 want: `req_bool: false
Herbie Ong800c9902018-12-06 15:28:53 -0800723req_sfixed64: 3203386110
724req_double: nan
725req_string: "hello"
Herbie Ong8170d692019-02-13 14:13:21 -0800726req_enum: ONE
Herbie Ong800c9902018-12-06 15:28:53 -0800727`,
728 wantErr: true,
729 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700730 desc: "required fields not set with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700731 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong42577ea2019-03-26 16:26:22 -0700732 input: &pb2.Requireds{
733 ReqBool: scalar.Bool(false),
734 ReqSfixed64: scalar.Int64(0xbeefcafe),
735 ReqDouble: scalar.Float64(math.NaN()),
736 ReqString: scalar.String("hello"),
737 ReqEnum: pb2.Enum_ONE.Enum(),
738 },
739 want: `req_bool: false
740req_sfixed64: 3203386110
741req_double: nan
742req_string: "hello"
743req_enum: ONE
744`,
745 }, {
746 desc: "required fields all set",
Herbie Ong800c9902018-12-06 15:28:53 -0800747 input: &pb2.Requireds{
748 ReqBool: scalar.Bool(false),
Herbie Ong800c9902018-12-06 15:28:53 -0800749 ReqSfixed64: scalar.Int64(0),
Herbie Ong8170d692019-02-13 14:13:21 -0800750 ReqDouble: scalar.Float64(1.23),
Herbie Ong800c9902018-12-06 15:28:53 -0800751 ReqString: scalar.String(""),
Herbie Ong8170d692019-02-13 14:13:21 -0800752 ReqEnum: pb2.Enum_ONE.Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800753 ReqNested: &pb2.Nested{},
754 },
755 want: `req_bool: false
Herbie Ong800c9902018-12-06 15:28:53 -0800756req_sfixed64: 0
Herbie Ong8170d692019-02-13 14:13:21 -0800757req_double: 1.23
Herbie Ong800c9902018-12-06 15:28:53 -0800758req_string: ""
Herbie Ong8170d692019-02-13 14:13:21 -0800759req_enum: ONE
Herbie Ong800c9902018-12-06 15:28:53 -0800760req_nested: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800761`,
762 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800763 desc: "indirect required field",
764 input: &pb2.IndirectRequired{
765 OptNested: &pb2.NestedWithRequired{},
766 },
767 want: "opt_nested: {}\n",
768 wantErr: true,
Herbie Ongcddf8192018-11-28 18:25:20 -0800769 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700770 desc: "indirect required field with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700771 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong42577ea2019-03-26 16:26:22 -0700772 input: &pb2.IndirectRequired{
773 OptNested: &pb2.NestedWithRequired{},
774 },
775 want: "opt_nested: {}\n",
776 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800777 desc: "indirect required field in empty repeated",
778 input: &pb2.IndirectRequired{
779 RptNested: []*pb2.NestedWithRequired{},
780 },
781 want: "\n",
Herbie Ongcddf8192018-11-28 18:25:20 -0800782 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800783 desc: "indirect required field in repeated",
784 input: &pb2.IndirectRequired{
785 RptNested: []*pb2.NestedWithRequired{
786 &pb2.NestedWithRequired{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800787 },
Herbie Ong800c9902018-12-06 15:28:53 -0800788 },
789 want: "rpt_nested: {}\n",
790 wantErr: true,
791 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700792 desc: "indirect required field in repeated with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700793 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong42577ea2019-03-26 16:26:22 -0700794 input: &pb2.IndirectRequired{
795 RptNested: []*pb2.NestedWithRequired{
796 &pb2.NestedWithRequired{},
797 },
798 },
799 want: "rpt_nested: {}\n",
800 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800801 desc: "indirect required field in empty map",
802 input: &pb2.IndirectRequired{
803 StrToNested: map[string]*pb2.NestedWithRequired{},
804 },
805 want: "\n",
806 }, {
807 desc: "indirect required field in map",
808 input: &pb2.IndirectRequired{
809 StrToNested: map[string]*pb2.NestedWithRequired{
810 "fail": &pb2.NestedWithRequired{},
811 },
812 },
813 want: `str_to_nested: {
814 key: "fail"
815 value: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800816}
817`,
Herbie Ong800c9902018-12-06 15:28:53 -0800818 wantErr: true,
Herbie Ong20a1d312018-12-11 21:08:58 -0800819 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700820 desc: "indirect required field in map with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700821 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong42577ea2019-03-26 16:26:22 -0700822 input: &pb2.IndirectRequired{
823 StrToNested: map[string]*pb2.NestedWithRequired{
824 "fail": &pb2.NestedWithRequired{},
825 },
826 },
827 want: `str_to_nested: {
828 key: "fail"
829 value: {}
830}
831`,
832 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800833 desc: "indirect required field in oneof",
834 input: &pb2.IndirectRequired{
835 Union: &pb2.IndirectRequired_OneofNested{
836 OneofNested: &pb2.NestedWithRequired{},
837 },
838 },
839 want: "oneof_nested: {}\n",
840 wantErr: true,
841 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700842 desc: "indirect required field in oneof with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700843 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong42577ea2019-03-26 16:26:22 -0700844 input: &pb2.IndirectRequired{
845 Union: &pb2.IndirectRequired_OneofNested{
846 OneofNested: &pb2.NestedWithRequired{},
847 },
848 },
849 want: "oneof_nested: {}\n",
850 }, {
Herbie Ong20a1d312018-12-11 21:08:58 -0800851 desc: "unknown varint and fixed types",
852 input: &pb2.Scalars{
853 OptString: scalar.String("this message contains unknown fields"),
854 XXX_unrecognized: pack.Message{
855 pack.Tag{101, pack.VarintType}, pack.Bool(true),
856 pack.Tag{102, pack.VarintType}, pack.Varint(0xff),
857 pack.Tag{103, pack.Fixed32Type}, pack.Uint32(47),
858 pack.Tag{104, pack.Fixed64Type}, pack.Int64(0xdeadbeef),
859 }.Marshal(),
860 },
861 want: `opt_string: "this message contains unknown fields"
862101: 1
863102: 255
864103: 47
865104: 3735928559
866`,
867 }, {
868 desc: "unknown length-delimited",
869 input: &pb2.Scalars{
870 XXX_unrecognized: pack.Message{
871 pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false)},
872 pack.Tag{102, pack.BytesType}, pack.String("hello world"),
873 pack.Tag{103, pack.BytesType}, pack.Bytes("\xe4\xb8\x96\xe7\x95\x8c"),
874 }.Marshal(),
875 },
876 want: `101: "\x01\x00"
877102: "hello world"
878103: "世界"
879`,
880 }, {
881 desc: "unknown group type",
882 input: &pb2.Scalars{
883 XXX_unrecognized: pack.Message{
884 pack.Tag{101, pack.StartGroupType}, pack.Tag{101, pack.EndGroupType},
885 pack.Tag{102, pack.StartGroupType},
886 pack.Tag{101, pack.VarintType}, pack.Bool(false),
887 pack.Tag{102, pack.BytesType}, pack.String("inside a group"),
888 pack.Tag{102, pack.EndGroupType},
889 }.Marshal(),
890 },
891 want: `101: {}
892102: {
893 101: 0
894 102: "inside a group"
895}
896`,
897 }, {
898 desc: "unknown unpack repeated field",
899 input: &pb2.Scalars{
900 XXX_unrecognized: pack.Message{
901 pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false), pack.Bool(true)},
902 pack.Tag{102, pack.BytesType}, pack.String("hello"),
903 pack.Tag{101, pack.VarintType}, pack.Bool(true),
904 pack.Tag{102, pack.BytesType}, pack.String("世界"),
905 }.Marshal(),
906 },
907 want: `101: "\x01\x00\x01"
Herbie Ong20a1d312018-12-11 21:08:58 -0800908102: "hello"
Joe Tsai378c1322019-04-25 23:48:08 -0700909101: 1
Herbie Ong20a1d312018-12-11 21:08:58 -0800910102: "世界"
911`,
Herbie Ongcf253082018-12-17 17:13:07 -0800912 }, {
913 desc: "extensions of non-repeated fields",
914 input: func() proto.Message {
915 m := &pb2.Extensions{
916 OptString: scalar.String("non-extension field"),
917 OptBool: scalar.Bool(true),
918 OptInt32: scalar.Int32(42),
919 }
920 setExtension(m, pb2.E_OptExtBool, true)
921 setExtension(m, pb2.E_OptExtString, "extension field")
Herbie Ong8170d692019-02-13 14:13:21 -0800922 setExtension(m, pb2.E_OptExtEnum, pb2.Enum_TEN)
Herbie Ongcf253082018-12-17 17:13:07 -0800923 setExtension(m, pb2.E_OptExtNested, &pb2.Nested{
924 OptString: scalar.String("nested in an extension"),
925 OptNested: &pb2.Nested{
926 OptString: scalar.String("another nested in an extension"),
927 },
928 })
929 return m
930 }(),
931 want: `opt_string: "non-extension field"
932opt_bool: true
933opt_int32: 42
934[pb2.opt_ext_bool]: true
Herbie Ong8170d692019-02-13 14:13:21 -0800935[pb2.opt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -0800936[pb2.opt_ext_nested]: {
937 opt_string: "nested in an extension"
938 opt_nested: {
939 opt_string: "another nested in an extension"
940 }
941}
942[pb2.opt_ext_string]: "extension field"
943`,
944 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700945 desc: "extension field contains invalid UTF-8",
946 input: func() proto.Message {
947 m := &pb2.Extensions{}
948 setExtension(m, pb2.E_OptExtString, "abc\xff")
949 return m
950 }(),
Herbie Ong21a39742019-04-08 17:32:44 -0700951 wantErr: true,
952 }, {
Herbie Ong09b28a92019-04-03 15:42:41 -0700953 desc: "extension partial returns error",
954 input: func() proto.Message {
955 m := &pb2.Extensions{}
956 setExtension(m, pb2.E_OptExtPartial, &pb2.PartialRequired{
957 OptString: scalar.String("partial1"),
958 })
959 setExtension(m, pb2.E_ExtensionsContainer_OptExtPartial, &pb2.PartialRequired{
960 OptString: scalar.String("partial2"),
961 })
962 return m
963 }(),
964 want: `[pb2.ExtensionsContainer.opt_ext_partial]: {
965 opt_string: "partial2"
966}
967[pb2.opt_ext_partial]: {
968 opt_string: "partial1"
969}
970`,
971 wantErr: true,
972 }, {
973 desc: "extension partial with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700974 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong09b28a92019-04-03 15:42:41 -0700975 input: func() proto.Message {
976 m := &pb2.Extensions{}
977 setExtension(m, pb2.E_OptExtPartial, &pb2.PartialRequired{
978 OptString: scalar.String("partial1"),
979 })
980 return m
981 }(),
982 want: `[pb2.opt_ext_partial]: {
983 opt_string: "partial1"
984}
985`,
986 }, {
Herbie Ongcf253082018-12-17 17:13:07 -0800987 desc: "extensions of repeated fields",
988 input: func() proto.Message {
989 m := &pb2.Extensions{}
Herbie Ong8170d692019-02-13 14:13:21 -0800990 setExtension(m, pb2.E_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
Herbie Ongcf253082018-12-17 17:13:07 -0800991 setExtension(m, pb2.E_RptExtFixed32, &[]uint32{42, 47})
992 setExtension(m, pb2.E_RptExtNested, &[]*pb2.Nested{
993 &pb2.Nested{OptString: scalar.String("one")},
994 &pb2.Nested{OptString: scalar.String("two")},
995 &pb2.Nested{OptString: scalar.String("three")},
996 })
997 return m
998 }(),
Herbie Ong8170d692019-02-13 14:13:21 -0800999 want: `[pb2.rpt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -08001000[pb2.rpt_ext_enum]: 101
Herbie Ong8170d692019-02-13 14:13:21 -08001001[pb2.rpt_ext_enum]: ONE
Herbie Ongcf253082018-12-17 17:13:07 -08001002[pb2.rpt_ext_fixed32]: 42
1003[pb2.rpt_ext_fixed32]: 47
1004[pb2.rpt_ext_nested]: {
1005 opt_string: "one"
1006}
1007[pb2.rpt_ext_nested]: {
1008 opt_string: "two"
1009}
1010[pb2.rpt_ext_nested]: {
1011 opt_string: "three"
1012}
1013`,
1014 }, {
1015 desc: "extensions of non-repeated fields in another message",
1016 input: func() proto.Message {
1017 m := &pb2.Extensions{}
1018 setExtension(m, pb2.E_ExtensionsContainer_OptExtBool, true)
1019 setExtension(m, pb2.E_ExtensionsContainer_OptExtString, "extension field")
Herbie Ong8170d692019-02-13 14:13:21 -08001020 setExtension(m, pb2.E_ExtensionsContainer_OptExtEnum, pb2.Enum_TEN)
Herbie Ongcf253082018-12-17 17:13:07 -08001021 setExtension(m, pb2.E_ExtensionsContainer_OptExtNested, &pb2.Nested{
1022 OptString: scalar.String("nested in an extension"),
1023 OptNested: &pb2.Nested{
1024 OptString: scalar.String("another nested in an extension"),
1025 },
1026 })
1027 return m
1028 }(),
1029 want: `[pb2.ExtensionsContainer.opt_ext_bool]: true
Herbie Ong8170d692019-02-13 14:13:21 -08001030[pb2.ExtensionsContainer.opt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -08001031[pb2.ExtensionsContainer.opt_ext_nested]: {
1032 opt_string: "nested in an extension"
1033 opt_nested: {
1034 opt_string: "another nested in an extension"
1035 }
1036}
1037[pb2.ExtensionsContainer.opt_ext_string]: "extension field"
1038`,
1039 }, {
1040 desc: "extensions of repeated fields in another message",
1041 input: func() proto.Message {
1042 m := &pb2.Extensions{
1043 OptString: scalar.String("non-extension field"),
1044 OptBool: scalar.Bool(true),
1045 OptInt32: scalar.Int32(42),
1046 }
Herbie Ong8170d692019-02-13 14:13:21 -08001047 setExtension(m, pb2.E_ExtensionsContainer_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
Herbie Ongcf253082018-12-17 17:13:07 -08001048 setExtension(m, pb2.E_ExtensionsContainer_RptExtString, &[]string{"hello", "world"})
1049 setExtension(m, pb2.E_ExtensionsContainer_RptExtNested, &[]*pb2.Nested{
1050 &pb2.Nested{OptString: scalar.String("one")},
1051 &pb2.Nested{OptString: scalar.String("two")},
1052 &pb2.Nested{OptString: scalar.String("three")},
1053 })
1054 return m
1055 }(),
1056 want: `opt_string: "non-extension field"
1057opt_bool: true
1058opt_int32: 42
Herbie Ong8170d692019-02-13 14:13:21 -08001059[pb2.ExtensionsContainer.rpt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -08001060[pb2.ExtensionsContainer.rpt_ext_enum]: 101
Herbie Ong8170d692019-02-13 14:13:21 -08001061[pb2.ExtensionsContainer.rpt_ext_enum]: ONE
Herbie Ongcf253082018-12-17 17:13:07 -08001062[pb2.ExtensionsContainer.rpt_ext_nested]: {
1063 opt_string: "one"
1064}
1065[pb2.ExtensionsContainer.rpt_ext_nested]: {
1066 opt_string: "two"
1067}
1068[pb2.ExtensionsContainer.rpt_ext_nested]: {
1069 opt_string: "three"
1070}
1071[pb2.ExtensionsContainer.rpt_ext_string]: "hello"
1072[pb2.ExtensionsContainer.rpt_ext_string]: "world"
1073`,
Herbie Ong6470ea62019-01-07 18:56:57 -08001074 }, {
1075 desc: "MessageSet",
1076 input: func() proto.Message {
1077 m := &pb2.MessageSet{}
1078 setExtension(m, pb2.E_MessageSetExtension_MessageSetExtension, &pb2.MessageSetExtension{
1079 OptString: scalar.String("a messageset extension"),
1080 })
1081 setExtension(m, pb2.E_MessageSetExtension_NotMessageSetExtension, &pb2.MessageSetExtension{
1082 OptString: scalar.String("not a messageset extension"),
1083 })
1084 setExtension(m, pb2.E_MessageSetExtension_ExtNested, &pb2.Nested{
1085 OptString: scalar.String("just a regular extension"),
1086 })
1087 return m
1088 }(),
1089 want: `[pb2.MessageSetExtension]: {
1090 opt_string: "a messageset extension"
1091}
1092[pb2.MessageSetExtension.ext_nested]: {
1093 opt_string: "just a regular extension"
1094}
1095[pb2.MessageSetExtension.not_message_set_extension]: {
1096 opt_string: "not a messageset extension"
1097}
1098`,
1099 }, {
1100 desc: "not real MessageSet 1",
1101 input: func() proto.Message {
1102 m := &pb2.FakeMessageSet{}
1103 setExtension(m, pb2.E_FakeMessageSetExtension_MessageSetExtension, &pb2.FakeMessageSetExtension{
1104 OptString: scalar.String("not a messageset extension"),
1105 })
1106 return m
1107 }(),
1108 want: `[pb2.FakeMessageSetExtension.message_set_extension]: {
1109 opt_string: "not a messageset extension"
1110}
1111`,
1112 }, {
1113 desc: "not real MessageSet 2",
1114 input: func() proto.Message {
1115 m := &pb2.MessageSet{}
1116 setExtension(m, pb2.E_MessageSetExtension, &pb2.FakeMessageSetExtension{
1117 OptString: scalar.String("another not a messageset extension"),
1118 })
1119 return m
1120 }(),
1121 want: `[pb2.message_set_extension]: {
1122 opt_string: "another not a messageset extension"
1123}
1124`,
Herbie Ongf42b55f2019-01-02 15:46:07 -08001125 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001126 desc: "Any not expanded",
Damien Neil5c5b5312019-05-14 12:44:37 -07001127 mo: prototext.MarshalOptions{
Herbie Ong66c365c2019-01-04 14:08:41 -08001128 Resolver: preg.NewTypes(),
1129 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001130 input: func() proto.Message {
1131 m := &pb2.Nested{
1132 OptString: scalar.String("embedded inside Any"),
1133 OptNested: &pb2.Nested{
1134 OptString: scalar.String("inception"),
1135 },
1136 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -07001137 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ongf42b55f2019-01-02 15:46:07 -08001138 if err != nil {
1139 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1140 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07001141 return &anypb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001142 TypeUrl: "pb2.Nested",
Herbie Ongf42b55f2019-01-02 15:46:07 -08001143 Value: b,
Herbie Ong300cff02019-03-20 18:05:16 -07001144 }
Herbie Ongf42b55f2019-01-02 15:46:07 -08001145 }(),
1146 want: `type_url: "pb2.Nested"
1147value: "\n\x13embedded inside Any\x12\x0b\n\tinception"
1148`,
1149 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001150 desc: "Any expanded",
Damien Neil5c5b5312019-05-14 12:44:37 -07001151 mo: prototext.MarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001152 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
Herbie Ong66c365c2019-01-04 14:08:41 -08001153 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001154 input: func() proto.Message {
1155 m := &pb2.Nested{
1156 OptString: scalar.String("embedded inside Any"),
1157 OptNested: &pb2.Nested{
1158 OptString: scalar.String("inception"),
1159 },
1160 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -07001161 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ongf42b55f2019-01-02 15:46:07 -08001162 if err != nil {
1163 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1164 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07001165 return &anypb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001166 TypeUrl: "foo/pb2.Nested",
Herbie Ongf42b55f2019-01-02 15:46:07 -08001167 Value: b,
Herbie Ong300cff02019-03-20 18:05:16 -07001168 }
Herbie Ongf42b55f2019-01-02 15:46:07 -08001169 }(),
Herbie Ong66c365c2019-01-04 14:08:41 -08001170 want: `[foo/pb2.Nested]: {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001171 opt_string: "embedded inside Any"
1172 opt_nested: {
1173 opt_string: "inception"
1174 }
1175}
1176`,
1177 }, {
Damien Neil0c9f0a92019-06-19 10:41:09 -07001178 desc: "Any expanded with missing required",
Damien Neil5c5b5312019-05-14 12:44:37 -07001179 mo: prototext.MarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001180 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.PartialRequired{})),
Herbie Ong66c365c2019-01-04 14:08:41 -08001181 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001182 input: func() proto.Message {
1183 m := &pb2.PartialRequired{
1184 OptString: scalar.String("embedded inside Any"),
1185 }
Damien Neil96c229a2019-04-03 12:17:24 -07001186 b, err := proto.MarshalOptions{
1187 AllowPartial: true,
1188 Deterministic: true,
1189 }.Marshal(m)
Herbie Ong300cff02019-03-20 18:05:16 -07001190 if err != nil {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001191 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1192 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07001193 return &anypb.Any{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001194 TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
Herbie Ongf42b55f2019-01-02 15:46:07 -08001195 Value: b,
Herbie Ong300cff02019-03-20 18:05:16 -07001196 }
Herbie Ongf42b55f2019-01-02 15:46:07 -08001197 }(),
1198 want: `[pb2.PartialRequired]: {
1199 opt_string: "embedded inside Any"
1200}
1201`,
Herbie Ongf42b55f2019-01-02 15:46:07 -08001202 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001203 desc: "Any with invalid value",
Damien Neil5c5b5312019-05-14 12:44:37 -07001204 mo: prototext.MarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001205 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
Herbie Ong66c365c2019-01-04 14:08:41 -08001206 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07001207 input: &anypb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001208 TypeUrl: "foo/pb2.Nested",
1209 Value: dhex("80"),
Herbie Ong300cff02019-03-20 18:05:16 -07001210 },
Herbie Ong66c365c2019-01-04 14:08:41 -08001211 want: `type_url: "foo/pb2.Nested"
Herbie Onga94f78c2019-01-03 15:39:58 -08001212value: "\x80"
1213`,
Herbie Ongcddf8192018-11-28 18:25:20 -08001214 }}
1215
1216 for _, tt := range tests {
1217 tt := tt
1218 t.Run(tt.desc, func(t *testing.T) {
Herbie Ong3a385912019-03-20 14:04:24 -07001219 // Use 2-space indentation on all MarshalOptions.
1220 tt.mo.Indent = " "
Herbie Ongf42b55f2019-01-02 15:46:07 -08001221 b, err := tt.mo.Marshal(tt.input)
Herbie Ongcddf8192018-11-28 18:25:20 -08001222 if err != nil && !tt.wantErr {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001223 t.Errorf("Marshal() returned error: %v\n", err)
Herbie Ongcddf8192018-11-28 18:25:20 -08001224 }
Herbie Ong800c9902018-12-06 15:28:53 -08001225 if err == nil && tt.wantErr {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001226 t.Error("Marshal() got nil error, want error\n")
Herbie Ongcddf8192018-11-28 18:25:20 -08001227 }
Herbie Ong800c9902018-12-06 15:28:53 -08001228 got := string(b)
1229 if tt.want != "" && got != tt.want {
1230 t.Errorf("Marshal()\n<got>\n%v\n<want>\n%v\n", got, tt.want)
Joe Tsai378c1322019-04-25 23:48:08 -07001231 if diff := cmp.Diff(tt.want, got); diff != "" {
Herbie Ongcddf8192018-11-28 18:25:20 -08001232 t.Errorf("Marshal() diff -want +got\n%v\n", diff)
1233 }
1234 }
1235 })
1236 }
1237}