blob: ea97c89894c4cfcb89c1aeacf3518da4f08b65b5 [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 (
Damien Neilbc310b52019-04-11 11:46:55 -07008 "bytes"
Herbie Onga94f78c2019-01-03 15:39:58 -08009 "encoding/hex"
Herbie Ongcddf8192018-11-28 18:25:20 -080010 "math"
Herbie Ongcddf8192018-11-28 18:25:20 -080011 "testing"
12
Herbie Ongcddf8192018-11-28 18:25:20 -080013 "github.com/google/go-cmp/cmp"
Damien Neil5c5b5312019-05-14 12:44:37 -070014 "google.golang.org/protobuf/encoding/prototext"
Damien Neile89e6242019-05-13 23:55:40 -070015 "google.golang.org/protobuf/internal/detrand"
16 "google.golang.org/protobuf/internal/encoding/pack"
Damien Neile89e6242019-05-13 23:55:40 -070017 pimpl "google.golang.org/protobuf/internal/impl"
18 "google.golang.org/protobuf/internal/scalar"
19 "google.golang.org/protobuf/proto"
20 preg "google.golang.org/protobuf/reflect/protoregistry"
21 "google.golang.org/protobuf/runtime/protoiface"
Herbie Ongcddf8192018-11-28 18:25:20 -080022
Damien Neile89e6242019-05-13 23:55:40 -070023 "google.golang.org/protobuf/encoding/testprotos/pb2"
24 "google.golang.org/protobuf/encoding/testprotos/pb3"
Joe Tsaia95b29f2019-05-16 12:47:20 -070025 "google.golang.org/protobuf/types/known/anypb"
Herbie Ongcddf8192018-11-28 18:25:20 -080026)
27
28func init() {
29 // Disable detrand to enable direct comparisons on outputs.
30 detrand.Disable()
31}
32
Herbie Ong800c9902018-12-06 15:28:53 -080033func pb2Enum(i int32) *pb2.Enum {
34 p := new(pb2.Enum)
35 *p = pb2.Enum(i)
36 return p
37}
38
39func pb2Enums_NestedEnum(i int32) *pb2.Enums_NestedEnum {
40 p := new(pb2.Enums_NestedEnum)
41 *p = pb2.Enums_NestedEnum(i)
42 return p
43}
44
Joe Tsai378c1322019-04-25 23:48:08 -070045// TODO: Use proto.SetExtension when available.
Joe Tsai4fddeba2019-03-20 18:29:32 -070046func setExtension(m proto.Message, xd *protoiface.ExtensionDescV1, val interface{}) {
Joe Tsai378c1322019-04-25 23:48:08 -070047 m.ProtoReflect().Set(xd.Type, xd.Type.ValueOf(val))
Herbie Ongcf253082018-12-17 17:13:07 -080048}
49
Herbie Onga94f78c2019-01-03 15:39:58 -080050// dhex decodes a hex-string and returns the bytes and panics if s is invalid.
51func dhex(s string) []byte {
52 b, err := hex.DecodeString(s)
53 if err != nil {
54 panic(err)
55 }
56 return b
57}
58
Herbie Ongcddf8192018-11-28 18:25:20 -080059func TestMarshal(t *testing.T) {
60 tests := []struct {
61 desc string
Damien Neil5c5b5312019-05-14 12:44:37 -070062 mo prototext.MarshalOptions
Herbie Ong70651952018-12-13 14:19:50 -080063 input proto.Message
Herbie Ongcddf8192018-11-28 18:25:20 -080064 want string
Herbie Ong300cff02019-03-20 18:05:16 -070065 wantErr bool // TODO: Verify error message content.
Herbie Ongcddf8192018-11-28 18:25:20 -080066 }{{
Herbie Ong8170d692019-02-13 14:13:21 -080067 desc: "proto2 optional scalars not set",
Herbie Ong800c9902018-12-06 15:28:53 -080068 input: &pb2.Scalars{},
Herbie Ongcddf8192018-11-28 18:25:20 -080069 want: "\n",
70 }, {
Herbie Ong8170d692019-02-13 14:13:21 -080071 desc: "proto3 scalars not set",
Herbie Ong800c9902018-12-06 15:28:53 -080072 input: &pb3.Scalars{},
Herbie Ongcddf8192018-11-28 18:25:20 -080073 want: "\n",
74 }, {
Herbie Ong8170d692019-02-13 14:13:21 -080075 desc: "proto2 optional scalars set to zero values",
Herbie Ong800c9902018-12-06 15:28:53 -080076 input: &pb2.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -080077 OptBool: scalar.Bool(false),
78 OptInt32: scalar.Int32(0),
79 OptInt64: scalar.Int64(0),
80 OptUint32: scalar.Uint32(0),
81 OptUint64: scalar.Uint64(0),
82 OptSint32: scalar.Int32(0),
83 OptSint64: scalar.Int64(0),
84 OptFixed32: scalar.Uint32(0),
85 OptFixed64: scalar.Uint64(0),
86 OptSfixed32: scalar.Int32(0),
87 OptSfixed64: scalar.Int64(0),
88 OptFloat: scalar.Float32(0),
89 OptDouble: scalar.Float64(0),
90 OptBytes: []byte{},
91 OptString: scalar.String(""),
Herbie Ong800c9902018-12-06 15:28:53 -080092 },
Herbie Ongcddf8192018-11-28 18:25:20 -080093 want: `opt_bool: false
94opt_int32: 0
95opt_int64: 0
96opt_uint32: 0
97opt_uint64: 0
98opt_sint32: 0
99opt_sint64: 0
100opt_fixed32: 0
101opt_fixed64: 0
102opt_sfixed32: 0
103opt_sfixed64: 0
104opt_float: 0
105opt_double: 0
106opt_bytes: ""
107opt_string: ""
108`,
109 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800110 desc: "proto3 scalars set to zero values",
Herbie Ong800c9902018-12-06 15:28:53 -0800111 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800112 SBool: false,
113 SInt32: 0,
114 SInt64: 0,
115 SUint32: 0,
116 SUint64: 0,
117 SSint32: 0,
118 SSint64: 0,
119 SFixed32: 0,
120 SFixed64: 0,
121 SSfixed32: 0,
122 SSfixed64: 0,
123 SFloat: 0,
124 SDouble: 0,
125 SBytes: []byte{},
126 SString: "",
Herbie Ong800c9902018-12-06 15:28:53 -0800127 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800128 want: "\n",
129 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800130 desc: "proto2 optional scalars set to some values",
Herbie Ong800c9902018-12-06 15:28:53 -0800131 input: &pb2.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800132 OptBool: scalar.Bool(true),
133 OptInt32: scalar.Int32(0xff),
134 OptInt64: scalar.Int64(0xdeadbeef),
135 OptUint32: scalar.Uint32(47),
136 OptUint64: scalar.Uint64(0xdeadbeef),
137 OptSint32: scalar.Int32(-1001),
138 OptSint64: scalar.Int64(-0xffff),
139 OptFixed64: scalar.Uint64(64),
140 OptSfixed32: scalar.Int32(-32),
Herbie Ong84f09602019-01-17 19:31:47 -0800141 OptFloat: scalar.Float32(1.02),
142 OptDouble: scalar.Float64(1.0199999809265137),
Herbie Ong8170d692019-02-13 14:13:21 -0800143 OptBytes: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
144 OptString: scalar.String("谷歌"),
Herbie Ong800c9902018-12-06 15:28:53 -0800145 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800146 want: `opt_bool: true
147opt_int32: 255
148opt_int64: 3735928559
149opt_uint32: 47
150opt_uint64: 3735928559
151opt_sint32: -1001
152opt_sint64: -65535
153opt_fixed64: 64
154opt_sfixed32: -32
Herbie Ong84f09602019-01-17 19:31:47 -0800155opt_float: 1.02
156opt_double: 1.0199999809265137
Herbie Ongcddf8192018-11-28 18:25:20 -0800157opt_bytes: "谷歌"
158opt_string: "谷歌"
159`,
160 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700161 desc: "string with invalid UTF-8",
162 input: &pb3.Scalars{
163 SString: "abc\xff",
164 },
165 want: `s_string: "abc\xff"
166`,
167 wantErr: true,
168 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800169 desc: "float nan",
Herbie Ong800c9902018-12-06 15:28:53 -0800170 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800171 SFloat: float32(math.NaN()),
Herbie Ong800c9902018-12-06 15:28:53 -0800172 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800173 want: "s_float: nan\n",
174 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800175 desc: "float positive infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800176 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800177 SFloat: float32(math.Inf(1)),
Herbie Ong800c9902018-12-06 15:28:53 -0800178 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800179 want: "s_float: inf\n",
180 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800181 desc: "float negative infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800182 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800183 SFloat: float32(math.Inf(-1)),
Herbie Ong800c9902018-12-06 15:28:53 -0800184 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800185 want: "s_float: -inf\n",
186 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800187 desc: "double nan",
Herbie Ong800c9902018-12-06 15:28:53 -0800188 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800189 SDouble: math.NaN(),
Herbie Ong800c9902018-12-06 15:28:53 -0800190 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800191 want: "s_double: nan\n",
192 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800193 desc: "double positive infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800194 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800195 SDouble: math.Inf(1),
Herbie Ong800c9902018-12-06 15:28:53 -0800196 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800197 want: "s_double: inf\n",
198 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800199 desc: "double negative infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800200 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800201 SDouble: math.Inf(-1),
Herbie Ong800c9902018-12-06 15:28:53 -0800202 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800203 want: "s_double: -inf\n",
204 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800205 desc: "proto2 enum not set",
206 input: &pb2.Enums{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800207 want: "\n",
208 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800209 desc: "proto2 enum set to zero value",
210 input: &pb2.Enums{
Herbie Ong8170d692019-02-13 14:13:21 -0800211 OptEnum: pb2Enum(0),
Herbie Ong800c9902018-12-06 15:28:53 -0800212 OptNestedEnum: pb2Enums_NestedEnum(0),
213 },
Herbie Ong8170d692019-02-13 14:13:21 -0800214 want: `opt_enum: 0
Herbie Ong800c9902018-12-06 15:28:53 -0800215opt_nested_enum: 0
216`,
217 }, {
218 desc: "proto2 enum",
219 input: &pb2.Enums{
Herbie Ong8170d692019-02-13 14:13:21 -0800220 OptEnum: pb2.Enum_ONE.Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800221 OptNestedEnum: pb2.Enums_UNO.Enum(),
222 },
Herbie Ong8170d692019-02-13 14:13:21 -0800223 want: `opt_enum: ONE
Herbie Ong800c9902018-12-06 15:28:53 -0800224opt_nested_enum: UNO
225`,
226 }, {
227 desc: "proto2 enum set to numeric values",
228 input: &pb2.Enums{
Herbie Ong8170d692019-02-13 14:13:21 -0800229 OptEnum: pb2Enum(2),
Herbie Ong800c9902018-12-06 15:28:53 -0800230 OptNestedEnum: pb2Enums_NestedEnum(2),
231 },
Herbie Ong8170d692019-02-13 14:13:21 -0800232 want: `opt_enum: TWO
Herbie Ong800c9902018-12-06 15:28:53 -0800233opt_nested_enum: DOS
234`,
235 }, {
236 desc: "proto2 enum set to unnamed numeric values",
237 input: &pb2.Enums{
238 OptEnum: pb2Enum(101),
239 OptNestedEnum: pb2Enums_NestedEnum(-101),
240 },
241 want: `opt_enum: 101
242opt_nested_enum: -101
243`,
244 }, {
245 desc: "proto3 enum not set",
246 input: &pb3.Enums{},
247 want: "\n",
248 }, {
249 desc: "proto3 enum set to zero value",
250 input: &pb3.Enums{
251 SEnum: pb3.Enum_ZERO,
252 SNestedEnum: pb3.Enums_CERO,
253 },
254 want: "\n",
255 }, {
256 desc: "proto3 enum",
257 input: &pb3.Enums{
258 SEnum: pb3.Enum_ONE,
Herbie Ong8170d692019-02-13 14:13:21 -0800259 SNestedEnum: pb3.Enums_UNO,
Herbie Ong800c9902018-12-06 15:28:53 -0800260 },
261 want: `s_enum: ONE
Herbie Ong8170d692019-02-13 14:13:21 -0800262s_nested_enum: UNO
Herbie Ong800c9902018-12-06 15:28:53 -0800263`,
264 }, {
265 desc: "proto3 enum set to numeric values",
266 input: &pb3.Enums{
267 SEnum: 2,
Herbie Ong8170d692019-02-13 14:13:21 -0800268 SNestedEnum: 2,
Herbie Ong800c9902018-12-06 15:28:53 -0800269 },
270 want: `s_enum: TWO
Herbie Ong8170d692019-02-13 14:13:21 -0800271s_nested_enum: DOS
Herbie Ong800c9902018-12-06 15:28:53 -0800272`,
273 }, {
274 desc: "proto3 enum set to unnamed numeric values",
275 input: &pb3.Enums{
276 SEnum: -47,
277 SNestedEnum: 47,
278 },
279 want: `s_enum: -47
280s_nested_enum: 47
281`,
282 }, {
283 desc: "proto2 nested message not set",
284 input: &pb2.Nests{},
285 want: "\n",
286 }, {
287 desc: "proto2 nested message set to empty",
288 input: &pb2.Nests{
289 OptNested: &pb2.Nested{},
290 Optgroup: &pb2.Nests_OptGroup{},
291 },
292 want: `opt_nested: {}
Herbie Ong0dcfb9a2019-01-14 15:32:26 -0800293OptGroup: {}
Herbie Ong800c9902018-12-06 15:28:53 -0800294`,
295 }, {
296 desc: "proto2 nested messages",
297 input: &pb2.Nests{
298 OptNested: &pb2.Nested{
299 OptString: scalar.String("nested message"),
300 OptNested: &pb2.Nested{
301 OptString: scalar.String("another nested message"),
302 },
303 },
304 },
305 want: `opt_nested: {
306 opt_string: "nested message"
307 opt_nested: {
308 opt_string: "another nested message"
309 }
310}
311`,
312 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800313 desc: "proto2 groups",
Herbie Ong800c9902018-12-06 15:28:53 -0800314 input: &pb2.Nests{
315 Optgroup: &pb2.Nests_OptGroup{
Herbie Ong800c9902018-12-06 15:28:53 -0800316 OptString: scalar.String("inside a group"),
317 OptNested: &pb2.Nested{
318 OptString: scalar.String("nested message inside a group"),
319 },
320 Optnestedgroup: &pb2.Nests_OptGroup_OptNestedGroup{
Herbie Ong8170d692019-02-13 14:13:21 -0800321 OptFixed32: scalar.Uint32(47),
Herbie Ong800c9902018-12-06 15:28:53 -0800322 },
323 },
324 },
Herbie Ong0dcfb9a2019-01-14 15:32:26 -0800325 want: `OptGroup: {
Herbie Ong800c9902018-12-06 15:28:53 -0800326 opt_string: "inside a group"
327 opt_nested: {
328 opt_string: "nested message inside a group"
329 }
Herbie Ong0dcfb9a2019-01-14 15:32:26 -0800330 OptNestedGroup: {
Herbie Ong8170d692019-02-13 14:13:21 -0800331 opt_fixed32: 47
Herbie Ong800c9902018-12-06 15:28:53 -0800332 }
333}
334`,
335 }, {
336 desc: "proto3 nested message not set",
337 input: &pb3.Nests{},
338 want: "\n",
339 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800340 desc: "proto3 nested message set to empty",
341 input: &pb3.Nests{
342 SNested: &pb3.Nested{},
343 },
344 want: "s_nested: {}\n",
345 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800346 desc: "proto3 nested message",
347 input: &pb3.Nests{
348 SNested: &pb3.Nested{
349 SString: "nested message",
350 SNested: &pb3.Nested{
351 SString: "another nested message",
352 },
353 },
354 },
355 want: `s_nested: {
356 s_string: "nested message"
357 s_nested: {
358 s_string: "another nested message"
359 }
360}
361`,
362 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700363 desc: "proto3 nested message contains invalid UTF-8",
364 input: &pb3.Nests{
365 SNested: &pb3.Nested{
366 SString: "abc\xff",
367 },
368 },
369 want: `s_nested: {
370 s_string: "abc\xff"
371}
372`,
373 wantErr: true,
374 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800375 desc: "oneof not set",
376 input: &pb3.Oneofs{},
Herbie Ong800c9902018-12-06 15:28:53 -0800377 want: "\n",
378 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800379 desc: "oneof set to empty string",
380 input: &pb3.Oneofs{
381 Union: &pb3.Oneofs_OneofString{},
Herbie Ong800c9902018-12-06 15:28:53 -0800382 },
Herbie Ong8170d692019-02-13 14:13:21 -0800383 want: `oneof_string: ""
384`,
Herbie Ong800c9902018-12-06 15:28:53 -0800385 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800386 desc: "oneof set to string",
387 input: &pb3.Oneofs{
388 Union: &pb3.Oneofs_OneofString{
389 OneofString: "hello",
Herbie Ong800c9902018-12-06 15:28:53 -0800390 },
391 },
Herbie Ong8170d692019-02-13 14:13:21 -0800392 want: `oneof_string: "hello"
393`,
Herbie Ong800c9902018-12-06 15:28:53 -0800394 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800395 desc: "oneof set to enum",
396 input: &pb3.Oneofs{
397 Union: &pb3.Oneofs_OneofEnum{
398 OneofEnum: pb3.Enum_ZERO,
Herbie Ong800c9902018-12-06 15:28:53 -0800399 },
400 },
Herbie Ong8170d692019-02-13 14:13:21 -0800401 want: `oneof_enum: ZERO
402`,
Herbie Ong800c9902018-12-06 15:28:53 -0800403 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800404 desc: "oneof set to empty message",
405 input: &pb3.Oneofs{
406 Union: &pb3.Oneofs_OneofNested{
407 OneofNested: &pb3.Nested{},
408 },
409 },
410 want: "oneof_nested: {}\n",
411 }, {
412 desc: "oneof set to message",
413 input: &pb3.Oneofs{
414 Union: &pb3.Oneofs_OneofNested{
415 OneofNested: &pb3.Nested{
416 SString: "nested message",
Herbie Ong800c9902018-12-06 15:28:53 -0800417 },
418 },
419 },
Herbie Ong8170d692019-02-13 14:13:21 -0800420 want: `oneof_nested: {
421 s_string: "nested message"
Herbie Ong800c9902018-12-06 15:28:53 -0800422}
423`,
424 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800425 desc: "repeated fields not set",
Herbie Ong800c9902018-12-06 15:28:53 -0800426 input: &pb2.Repeats{},
427 want: "\n",
428 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800429 desc: "repeated fields set to empty slices",
Herbie Ong800c9902018-12-06 15:28:53 -0800430 input: &pb2.Repeats{
Herbie Ongcddf8192018-11-28 18:25:20 -0800431 RptBool: []bool{},
432 RptInt32: []int32{},
433 RptInt64: []int64{},
434 RptUint32: []uint32{},
435 RptUint64: []uint64{},
436 RptFloat: []float32{},
437 RptDouble: []float64{},
438 RptBytes: [][]byte{},
Herbie Ong800c9902018-12-06 15:28:53 -0800439 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800440 want: "\n",
441 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800442 desc: "repeated fields set to some values",
Herbie Ong800c9902018-12-06 15:28:53 -0800443 input: &pb2.Repeats{
Herbie Ongcddf8192018-11-28 18:25:20 -0800444 RptBool: []bool{true, false, true, true},
445 RptInt32: []int32{1, 6, 0, 0},
446 RptInt64: []int64{-64, 47},
447 RptUint32: []uint32{0xff, 0xffff},
448 RptUint64: []uint64{0xdeadbeef},
Herbie Ong84f09602019-01-17 19:31:47 -0800449 RptFloat: []float32{float32(math.NaN()), float32(math.Inf(1)), float32(math.Inf(-1)), 1.034},
Herbie Ongcddf8192018-11-28 18:25:20 -0800450 RptDouble: []float64{math.NaN(), math.Inf(1), math.Inf(-1), 1.23e-308},
451 RptString: []string{"hello", "世界"},
452 RptBytes: [][]byte{
453 []byte("hello"),
454 []byte("\xe4\xb8\x96\xe7\x95\x8c"),
455 },
Herbie Ong800c9902018-12-06 15:28:53 -0800456 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800457 want: `rpt_bool: true
458rpt_bool: false
459rpt_bool: true
460rpt_bool: true
461rpt_int32: 1
462rpt_int32: 6
463rpt_int32: 0
464rpt_int32: 0
465rpt_int64: -64
466rpt_int64: 47
467rpt_uint32: 255
468rpt_uint32: 65535
469rpt_uint64: 3735928559
Herbie Ong84f09602019-01-17 19:31:47 -0800470rpt_float: nan
471rpt_float: inf
472rpt_float: -inf
473rpt_float: 1.034
Herbie Ongcddf8192018-11-28 18:25:20 -0800474rpt_double: nan
475rpt_double: inf
476rpt_double: -inf
477rpt_double: 1.23e-308
478rpt_string: "hello"
479rpt_string: "世界"
480rpt_bytes: "hello"
481rpt_bytes: "世界"
482`,
483 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700484 desc: "repeated contains invalid UTF-8",
485 input: &pb2.Repeats{
486 RptString: []string{"abc\xff"},
487 },
488 want: `rpt_string: "abc\xff"
489`,
490 wantErr: true,
491 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800492 desc: "repeated enums",
Herbie Ong800c9902018-12-06 15:28:53 -0800493 input: &pb2.Enums{
Herbie Ong8170d692019-02-13 14:13:21 -0800494 RptEnum: []pb2.Enum{pb2.Enum_ONE, 2, pb2.Enum_TEN, 42},
Herbie Ongcddf8192018-11-28 18:25:20 -0800495 RptNestedEnum: []pb2.Enums_NestedEnum{2, 47, 10},
Herbie Ong800c9902018-12-06 15:28:53 -0800496 },
Herbie Ong8170d692019-02-13 14:13:21 -0800497 want: `rpt_enum: ONE
498rpt_enum: TWO
499rpt_enum: TEN
Herbie Ongcddf8192018-11-28 18:25:20 -0800500rpt_enum: 42
Herbie Ongcddf8192018-11-28 18:25:20 -0800501rpt_nested_enum: DOS
502rpt_nested_enum: 47
503rpt_nested_enum: DIEZ
504`,
505 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800506 desc: "repeated messages set to empty",
Herbie Ong800c9902018-12-06 15:28:53 -0800507 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800508 RptNested: []*pb2.Nested{},
509 Rptgroup: []*pb2.Nests_RptGroup{},
Herbie Ong800c9902018-12-06 15:28:53 -0800510 },
511 want: "\n",
Herbie Ongcddf8192018-11-28 18:25:20 -0800512 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800513 desc: "repeated messages",
Herbie Ong800c9902018-12-06 15:28:53 -0800514 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800515 RptNested: []*pb2.Nested{
516 {
517 OptString: scalar.String("repeat nested one"),
518 },
519 {
520 OptString: scalar.String("repeat nested two"),
521 OptNested: &pb2.Nested{
522 OptString: scalar.String("inside repeat nested two"),
523 },
524 },
525 {},
526 },
Herbie Ong800c9902018-12-06 15:28:53 -0800527 },
528 want: `rpt_nested: {
Herbie Ongcddf8192018-11-28 18:25:20 -0800529 opt_string: "repeat nested one"
530}
531rpt_nested: {
532 opt_string: "repeat nested two"
533 opt_nested: {
534 opt_string: "inside repeat nested two"
535 }
536}
537rpt_nested: {}
538`,
539 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800540 desc: "repeated messages contains nil value",
Herbie Ongf5db2df2019-02-07 20:17:45 -0800541 input: &pb2.Nests{
542 RptNested: []*pb2.Nested{nil, {}},
543 },
544 want: `rpt_nested: {}
545rpt_nested: {}
546`,
547 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800548 desc: "repeated groups",
Herbie Ong800c9902018-12-06 15:28:53 -0800549 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800550 Rptgroup: []*pb2.Nests_RptGroup{
551 {
Herbie Ong8170d692019-02-13 14:13:21 -0800552 RptString: []string{"hello", "world"},
Herbie Ongcddf8192018-11-28 18:25:20 -0800553 },
554 {},
Herbie Ong8170d692019-02-13 14:13:21 -0800555 nil,
Herbie Ongcddf8192018-11-28 18:25:20 -0800556 },
Herbie Ong800c9902018-12-06 15:28:53 -0800557 },
Herbie Ongde7313b2019-01-14 19:26:50 -0800558 want: `RptGroup: {
Herbie Ong8170d692019-02-13 14:13:21 -0800559 rpt_string: "hello"
560 rpt_string: "world"
Herbie Ongcddf8192018-11-28 18:25:20 -0800561}
Herbie Ongde7313b2019-01-14 19:26:50 -0800562RptGroup: {}
Herbie Ong8170d692019-02-13 14:13:21 -0800563RptGroup: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800564`,
565 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800566 desc: "map fields not set",
567 input: &pb3.Maps{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800568 want: "\n",
569 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800570 desc: "map fields set to empty",
571 input: &pb3.Maps{
572 Int32ToStr: map[int32]string{},
573 BoolToUint32: map[bool]uint32{},
574 Uint64ToEnum: map[uint64]pb3.Enum{},
575 StrToNested: map[string]*pb3.Nested{},
576 StrToOneofs: map[string]*pb3.Oneofs{},
Herbie Ong800c9902018-12-06 15:28:53 -0800577 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800578 want: "\n",
579 }, {
580 desc: "map fields 1",
Herbie Ong8170d692019-02-13 14:13:21 -0800581 input: &pb3.Maps{
Herbie Ongcddf8192018-11-28 18:25:20 -0800582 Int32ToStr: map[int32]string{
583 -101: "-101",
584 0xff: "0xff",
585 0: "zero",
586 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800587 BoolToUint32: map[bool]uint32{
588 true: 42,
589 false: 101,
590 },
Herbie Ong800c9902018-12-06 15:28:53 -0800591 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800592 want: `int32_to_str: {
593 key: -101
594 value: "-101"
595}
596int32_to_str: {
597 key: 0
598 value: "zero"
599}
600int32_to_str: {
601 key: 255
602 value: "0xff"
603}
Herbie Ongcddf8192018-11-28 18:25:20 -0800604bool_to_uint32: {
605 key: false
606 value: 101
607}
608bool_to_uint32: {
609 key: true
610 value: 42
611}
612`,
613 }, {
614 desc: "map fields 2",
Herbie Ong8170d692019-02-13 14:13:21 -0800615 input: &pb3.Maps{
616 Uint64ToEnum: map[uint64]pb3.Enum{
617 1: pb3.Enum_ONE,
618 2: pb3.Enum_TWO,
619 10: pb3.Enum_TEN,
620 47: 47,
Herbie Ongcddf8192018-11-28 18:25:20 -0800621 },
Herbie Ong800c9902018-12-06 15:28:53 -0800622 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800623 want: `uint64_to_enum: {
624 key: 1
Herbie Ong8170d692019-02-13 14:13:21 -0800625 value: ONE
Herbie Ongcddf8192018-11-28 18:25:20 -0800626}
627uint64_to_enum: {
628 key: 2
Herbie Ong8170d692019-02-13 14:13:21 -0800629 value: TWO
Herbie Ongcddf8192018-11-28 18:25:20 -0800630}
631uint64_to_enum: {
632 key: 10
Herbie Ong8170d692019-02-13 14:13:21 -0800633 value: TEN
634}
635uint64_to_enum: {
636 key: 47
637 value: 47
Herbie Ongcddf8192018-11-28 18:25:20 -0800638}
639`,
640 }, {
641 desc: "map fields 3",
Herbie Ong8170d692019-02-13 14:13:21 -0800642 input: &pb3.Maps{
643 StrToNested: map[string]*pb3.Nested{
644 "nested": &pb3.Nested{
645 SString: "nested in a map",
Herbie Ongcddf8192018-11-28 18:25:20 -0800646 },
647 },
Herbie Ong800c9902018-12-06 15:28:53 -0800648 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800649 want: `str_to_nested: {
Herbie Ong8170d692019-02-13 14:13:21 -0800650 key: "nested"
Herbie Ongcddf8192018-11-28 18:25:20 -0800651 value: {
Herbie Ong8170d692019-02-13 14:13:21 -0800652 s_string: "nested in a map"
Herbie Ongcddf8192018-11-28 18:25:20 -0800653 }
654}
655`,
656 }, {
657 desc: "map fields 4",
Herbie Ong8170d692019-02-13 14:13:21 -0800658 input: &pb3.Maps{
659 StrToOneofs: map[string]*pb3.Oneofs{
660 "string": &pb3.Oneofs{
661 Union: &pb3.Oneofs_OneofString{
662 OneofString: "hello",
Herbie Ongcddf8192018-11-28 18:25:20 -0800663 },
664 },
Herbie Ong8170d692019-02-13 14:13:21 -0800665 "nested": &pb3.Oneofs{
666 Union: &pb3.Oneofs_OneofNested{
667 OneofNested: &pb3.Nested{
668 SString: "nested oneof in map field value",
Herbie Ongcddf8192018-11-28 18:25:20 -0800669 },
670 },
671 },
672 },
Herbie Ong800c9902018-12-06 15:28:53 -0800673 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800674 want: `str_to_oneofs: {
675 key: "nested"
676 value: {
Herbie Ong8170d692019-02-13 14:13:21 -0800677 oneof_nested: {
678 s_string: "nested oneof in map field value"
Herbie Ongcddf8192018-11-28 18:25:20 -0800679 }
680 }
681}
682str_to_oneofs: {
683 key: "string"
684 value: {
Herbie Ong8170d692019-02-13 14:13:21 -0800685 oneof_string: "hello"
Herbie Ongcddf8192018-11-28 18:25:20 -0800686 }
687}
688`,
689 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700690 desc: "map field value contains invalid UTF-8",
691 input: &pb3.Maps{
692 Int32ToStr: map[int32]string{
693 101: "abc\xff",
694 },
695 },
696 want: `int32_to_str: {
697 key: 101
698 value: "abc\xff"
699}
700`,
701 wantErr: true,
702 }, {
703 desc: "map field key contains invalid UTF-8",
704 input: &pb3.Maps{
705 StrToNested: map[string]*pb3.Nested{
706 "abc\xff": {},
707 },
708 },
709 want: `str_to_nested: {
710 key: "abc\xff"
711 value: {}
712}
713`,
714 wantErr: true,
715 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800716 desc: "map field contains nil value",
717 input: &pb3.Maps{
718 StrToNested: map[string]*pb3.Nested{
Herbie Ongf5db2df2019-02-07 20:17:45 -0800719 "nil": nil,
720 },
721 },
722 want: `str_to_nested: {
723 key: "nil"
724 value: {}
725}
726`,
727 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700728 desc: "required fields not set",
Herbie Ong800c9902018-12-06 15:28:53 -0800729 input: &pb2.Requireds{},
730 want: "\n",
731 wantErr: true,
Herbie Ongcddf8192018-11-28 18:25:20 -0800732 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700733 desc: "required fields partially set",
Herbie Ong800c9902018-12-06 15:28:53 -0800734 input: &pb2.Requireds{
735 ReqBool: scalar.Bool(false),
Herbie Ong800c9902018-12-06 15:28:53 -0800736 ReqSfixed64: scalar.Int64(0xbeefcafe),
737 ReqDouble: scalar.Float64(math.NaN()),
738 ReqString: scalar.String("hello"),
Herbie Ong8170d692019-02-13 14:13:21 -0800739 ReqEnum: pb2.Enum_ONE.Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800740 },
741 want: `req_bool: false
Herbie Ong800c9902018-12-06 15:28:53 -0800742req_sfixed64: 3203386110
743req_double: nan
744req_string: "hello"
Herbie Ong8170d692019-02-13 14:13:21 -0800745req_enum: ONE
Herbie Ong800c9902018-12-06 15:28:53 -0800746`,
747 wantErr: true,
748 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700749 desc: "required fields not set with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700750 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong42577ea2019-03-26 16:26:22 -0700751 input: &pb2.Requireds{
752 ReqBool: scalar.Bool(false),
753 ReqSfixed64: scalar.Int64(0xbeefcafe),
754 ReqDouble: scalar.Float64(math.NaN()),
755 ReqString: scalar.String("hello"),
756 ReqEnum: pb2.Enum_ONE.Enum(),
757 },
758 want: `req_bool: false
759req_sfixed64: 3203386110
760req_double: nan
761req_string: "hello"
762req_enum: ONE
763`,
764 }, {
765 desc: "required fields all set",
Herbie Ong800c9902018-12-06 15:28:53 -0800766 input: &pb2.Requireds{
767 ReqBool: scalar.Bool(false),
Herbie Ong800c9902018-12-06 15:28:53 -0800768 ReqSfixed64: scalar.Int64(0),
Herbie Ong8170d692019-02-13 14:13:21 -0800769 ReqDouble: scalar.Float64(1.23),
Herbie Ong800c9902018-12-06 15:28:53 -0800770 ReqString: scalar.String(""),
Herbie Ong8170d692019-02-13 14:13:21 -0800771 ReqEnum: pb2.Enum_ONE.Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800772 ReqNested: &pb2.Nested{},
773 },
774 want: `req_bool: false
Herbie Ong800c9902018-12-06 15:28:53 -0800775req_sfixed64: 0
Herbie Ong8170d692019-02-13 14:13:21 -0800776req_double: 1.23
Herbie Ong800c9902018-12-06 15:28:53 -0800777req_string: ""
Herbie Ong8170d692019-02-13 14:13:21 -0800778req_enum: ONE
Herbie Ong800c9902018-12-06 15:28:53 -0800779req_nested: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800780`,
781 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800782 desc: "indirect required field",
783 input: &pb2.IndirectRequired{
784 OptNested: &pb2.NestedWithRequired{},
785 },
786 want: "opt_nested: {}\n",
787 wantErr: true,
Herbie Ongcddf8192018-11-28 18:25:20 -0800788 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700789 desc: "indirect required field with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700790 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong42577ea2019-03-26 16:26:22 -0700791 input: &pb2.IndirectRequired{
792 OptNested: &pb2.NestedWithRequired{},
793 },
794 want: "opt_nested: {}\n",
795 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800796 desc: "indirect required field in empty repeated",
797 input: &pb2.IndirectRequired{
798 RptNested: []*pb2.NestedWithRequired{},
799 },
800 want: "\n",
Herbie Ongcddf8192018-11-28 18:25:20 -0800801 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800802 desc: "indirect required field in repeated",
803 input: &pb2.IndirectRequired{
804 RptNested: []*pb2.NestedWithRequired{
805 &pb2.NestedWithRequired{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800806 },
Herbie Ong800c9902018-12-06 15:28:53 -0800807 },
808 want: "rpt_nested: {}\n",
809 wantErr: true,
810 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700811 desc: "indirect required field in repeated with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700812 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong42577ea2019-03-26 16:26:22 -0700813 input: &pb2.IndirectRequired{
814 RptNested: []*pb2.NestedWithRequired{
815 &pb2.NestedWithRequired{},
816 },
817 },
818 want: "rpt_nested: {}\n",
819 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800820 desc: "indirect required field in empty map",
821 input: &pb2.IndirectRequired{
822 StrToNested: map[string]*pb2.NestedWithRequired{},
823 },
824 want: "\n",
825 }, {
826 desc: "indirect required field in map",
827 input: &pb2.IndirectRequired{
828 StrToNested: map[string]*pb2.NestedWithRequired{
829 "fail": &pb2.NestedWithRequired{},
830 },
831 },
832 want: `str_to_nested: {
833 key: "fail"
834 value: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800835}
836`,
Herbie Ong800c9902018-12-06 15:28:53 -0800837 wantErr: true,
Herbie Ong20a1d312018-12-11 21:08:58 -0800838 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700839 desc: "indirect required field in map with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700840 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong42577ea2019-03-26 16:26:22 -0700841 input: &pb2.IndirectRequired{
842 StrToNested: map[string]*pb2.NestedWithRequired{
843 "fail": &pb2.NestedWithRequired{},
844 },
845 },
846 want: `str_to_nested: {
847 key: "fail"
848 value: {}
849}
850`,
851 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800852 desc: "indirect required field in oneof",
853 input: &pb2.IndirectRequired{
854 Union: &pb2.IndirectRequired_OneofNested{
855 OneofNested: &pb2.NestedWithRequired{},
856 },
857 },
858 want: "oneof_nested: {}\n",
859 wantErr: true,
860 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700861 desc: "indirect required field in oneof with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700862 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong42577ea2019-03-26 16:26:22 -0700863 input: &pb2.IndirectRequired{
864 Union: &pb2.IndirectRequired_OneofNested{
865 OneofNested: &pb2.NestedWithRequired{},
866 },
867 },
868 want: "oneof_nested: {}\n",
869 }, {
Herbie Ong20a1d312018-12-11 21:08:58 -0800870 desc: "unknown varint and fixed types",
871 input: &pb2.Scalars{
872 OptString: scalar.String("this message contains unknown fields"),
873 XXX_unrecognized: pack.Message{
874 pack.Tag{101, pack.VarintType}, pack.Bool(true),
875 pack.Tag{102, pack.VarintType}, pack.Varint(0xff),
876 pack.Tag{103, pack.Fixed32Type}, pack.Uint32(47),
877 pack.Tag{104, pack.Fixed64Type}, pack.Int64(0xdeadbeef),
878 }.Marshal(),
879 },
880 want: `opt_string: "this message contains unknown fields"
881101: 1
882102: 255
883103: 47
884104: 3735928559
885`,
886 }, {
887 desc: "unknown length-delimited",
888 input: &pb2.Scalars{
889 XXX_unrecognized: pack.Message{
890 pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false)},
891 pack.Tag{102, pack.BytesType}, pack.String("hello world"),
892 pack.Tag{103, pack.BytesType}, pack.Bytes("\xe4\xb8\x96\xe7\x95\x8c"),
893 }.Marshal(),
894 },
895 want: `101: "\x01\x00"
896102: "hello world"
897103: "世界"
898`,
899 }, {
900 desc: "unknown group type",
901 input: &pb2.Scalars{
902 XXX_unrecognized: pack.Message{
903 pack.Tag{101, pack.StartGroupType}, pack.Tag{101, pack.EndGroupType},
904 pack.Tag{102, pack.StartGroupType},
905 pack.Tag{101, pack.VarintType}, pack.Bool(false),
906 pack.Tag{102, pack.BytesType}, pack.String("inside a group"),
907 pack.Tag{102, pack.EndGroupType},
908 }.Marshal(),
909 },
910 want: `101: {}
911102: {
912 101: 0
913 102: "inside a group"
914}
915`,
916 }, {
917 desc: "unknown unpack repeated field",
918 input: &pb2.Scalars{
919 XXX_unrecognized: pack.Message{
920 pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false), pack.Bool(true)},
921 pack.Tag{102, pack.BytesType}, pack.String("hello"),
922 pack.Tag{101, pack.VarintType}, pack.Bool(true),
923 pack.Tag{102, pack.BytesType}, pack.String("世界"),
924 }.Marshal(),
925 },
926 want: `101: "\x01\x00\x01"
Herbie Ong20a1d312018-12-11 21:08:58 -0800927102: "hello"
Joe Tsai378c1322019-04-25 23:48:08 -0700928101: 1
Herbie Ong20a1d312018-12-11 21:08:58 -0800929102: "世界"
930`,
Herbie Ongcf253082018-12-17 17:13:07 -0800931 }, {
932 desc: "extensions of non-repeated fields",
933 input: func() proto.Message {
934 m := &pb2.Extensions{
935 OptString: scalar.String("non-extension field"),
936 OptBool: scalar.Bool(true),
937 OptInt32: scalar.Int32(42),
938 }
939 setExtension(m, pb2.E_OptExtBool, true)
940 setExtension(m, pb2.E_OptExtString, "extension field")
Herbie Ong8170d692019-02-13 14:13:21 -0800941 setExtension(m, pb2.E_OptExtEnum, pb2.Enum_TEN)
Herbie Ongcf253082018-12-17 17:13:07 -0800942 setExtension(m, pb2.E_OptExtNested, &pb2.Nested{
943 OptString: scalar.String("nested in an extension"),
944 OptNested: &pb2.Nested{
945 OptString: scalar.String("another nested in an extension"),
946 },
947 })
948 return m
949 }(),
950 want: `opt_string: "non-extension field"
951opt_bool: true
952opt_int32: 42
953[pb2.opt_ext_bool]: true
Herbie Ong8170d692019-02-13 14:13:21 -0800954[pb2.opt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -0800955[pb2.opt_ext_nested]: {
956 opt_string: "nested in an extension"
957 opt_nested: {
958 opt_string: "another nested in an extension"
959 }
960}
961[pb2.opt_ext_string]: "extension field"
962`,
963 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700964 desc: "extension field contains invalid UTF-8",
965 input: func() proto.Message {
966 m := &pb2.Extensions{}
967 setExtension(m, pb2.E_OptExtString, "abc\xff")
968 return m
969 }(),
970 want: `[pb2.opt_ext_string]: "abc\xff"
971`,
972 wantErr: true,
973 }, {
Herbie Ong09b28a92019-04-03 15:42:41 -0700974 desc: "extension partial returns error",
975 input: func() proto.Message {
976 m := &pb2.Extensions{}
977 setExtension(m, pb2.E_OptExtPartial, &pb2.PartialRequired{
978 OptString: scalar.String("partial1"),
979 })
980 setExtension(m, pb2.E_ExtensionsContainer_OptExtPartial, &pb2.PartialRequired{
981 OptString: scalar.String("partial2"),
982 })
983 return m
984 }(),
985 want: `[pb2.ExtensionsContainer.opt_ext_partial]: {
986 opt_string: "partial2"
987}
988[pb2.opt_ext_partial]: {
989 opt_string: "partial1"
990}
991`,
992 wantErr: true,
993 }, {
994 desc: "extension partial with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700995 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong09b28a92019-04-03 15:42:41 -0700996 input: func() proto.Message {
997 m := &pb2.Extensions{}
998 setExtension(m, pb2.E_OptExtPartial, &pb2.PartialRequired{
999 OptString: scalar.String("partial1"),
1000 })
1001 return m
1002 }(),
1003 want: `[pb2.opt_ext_partial]: {
1004 opt_string: "partial1"
1005}
1006`,
1007 }, {
Herbie Ongcf253082018-12-17 17:13:07 -08001008 desc: "extensions of repeated fields",
1009 input: func() proto.Message {
1010 m := &pb2.Extensions{}
Herbie Ong8170d692019-02-13 14:13:21 -08001011 setExtension(m, pb2.E_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
Herbie Ongcf253082018-12-17 17:13:07 -08001012 setExtension(m, pb2.E_RptExtFixed32, &[]uint32{42, 47})
1013 setExtension(m, pb2.E_RptExtNested, &[]*pb2.Nested{
1014 &pb2.Nested{OptString: scalar.String("one")},
1015 &pb2.Nested{OptString: scalar.String("two")},
1016 &pb2.Nested{OptString: scalar.String("three")},
1017 })
1018 return m
1019 }(),
Herbie Ong8170d692019-02-13 14:13:21 -08001020 want: `[pb2.rpt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -08001021[pb2.rpt_ext_enum]: 101
Herbie Ong8170d692019-02-13 14:13:21 -08001022[pb2.rpt_ext_enum]: ONE
Herbie Ongcf253082018-12-17 17:13:07 -08001023[pb2.rpt_ext_fixed32]: 42
1024[pb2.rpt_ext_fixed32]: 47
1025[pb2.rpt_ext_nested]: {
1026 opt_string: "one"
1027}
1028[pb2.rpt_ext_nested]: {
1029 opt_string: "two"
1030}
1031[pb2.rpt_ext_nested]: {
1032 opt_string: "three"
1033}
1034`,
1035 }, {
1036 desc: "extensions of non-repeated fields in another message",
1037 input: func() proto.Message {
1038 m := &pb2.Extensions{}
1039 setExtension(m, pb2.E_ExtensionsContainer_OptExtBool, true)
1040 setExtension(m, pb2.E_ExtensionsContainer_OptExtString, "extension field")
Herbie Ong8170d692019-02-13 14:13:21 -08001041 setExtension(m, pb2.E_ExtensionsContainer_OptExtEnum, pb2.Enum_TEN)
Herbie Ongcf253082018-12-17 17:13:07 -08001042 setExtension(m, pb2.E_ExtensionsContainer_OptExtNested, &pb2.Nested{
1043 OptString: scalar.String("nested in an extension"),
1044 OptNested: &pb2.Nested{
1045 OptString: scalar.String("another nested in an extension"),
1046 },
1047 })
1048 return m
1049 }(),
1050 want: `[pb2.ExtensionsContainer.opt_ext_bool]: true
Herbie Ong8170d692019-02-13 14:13:21 -08001051[pb2.ExtensionsContainer.opt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -08001052[pb2.ExtensionsContainer.opt_ext_nested]: {
1053 opt_string: "nested in an extension"
1054 opt_nested: {
1055 opt_string: "another nested in an extension"
1056 }
1057}
1058[pb2.ExtensionsContainer.opt_ext_string]: "extension field"
1059`,
1060 }, {
1061 desc: "extensions of repeated fields in another message",
1062 input: func() proto.Message {
1063 m := &pb2.Extensions{
1064 OptString: scalar.String("non-extension field"),
1065 OptBool: scalar.Bool(true),
1066 OptInt32: scalar.Int32(42),
1067 }
Herbie Ong8170d692019-02-13 14:13:21 -08001068 setExtension(m, pb2.E_ExtensionsContainer_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
Herbie Ongcf253082018-12-17 17:13:07 -08001069 setExtension(m, pb2.E_ExtensionsContainer_RptExtString, &[]string{"hello", "world"})
1070 setExtension(m, pb2.E_ExtensionsContainer_RptExtNested, &[]*pb2.Nested{
1071 &pb2.Nested{OptString: scalar.String("one")},
1072 &pb2.Nested{OptString: scalar.String("two")},
1073 &pb2.Nested{OptString: scalar.String("three")},
1074 })
1075 return m
1076 }(),
1077 want: `opt_string: "non-extension field"
1078opt_bool: true
1079opt_int32: 42
Herbie Ong8170d692019-02-13 14:13:21 -08001080[pb2.ExtensionsContainer.rpt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -08001081[pb2.ExtensionsContainer.rpt_ext_enum]: 101
Herbie Ong8170d692019-02-13 14:13:21 -08001082[pb2.ExtensionsContainer.rpt_ext_enum]: ONE
Herbie Ongcf253082018-12-17 17:13:07 -08001083[pb2.ExtensionsContainer.rpt_ext_nested]: {
1084 opt_string: "one"
1085}
1086[pb2.ExtensionsContainer.rpt_ext_nested]: {
1087 opt_string: "two"
1088}
1089[pb2.ExtensionsContainer.rpt_ext_nested]: {
1090 opt_string: "three"
1091}
1092[pb2.ExtensionsContainer.rpt_ext_string]: "hello"
1093[pb2.ExtensionsContainer.rpt_ext_string]: "world"
1094`,
Herbie Ong6470ea62019-01-07 18:56:57 -08001095 }, {
1096 desc: "MessageSet",
1097 input: func() proto.Message {
1098 m := &pb2.MessageSet{}
1099 setExtension(m, pb2.E_MessageSetExtension_MessageSetExtension, &pb2.MessageSetExtension{
1100 OptString: scalar.String("a messageset extension"),
1101 })
1102 setExtension(m, pb2.E_MessageSetExtension_NotMessageSetExtension, &pb2.MessageSetExtension{
1103 OptString: scalar.String("not a messageset extension"),
1104 })
1105 setExtension(m, pb2.E_MessageSetExtension_ExtNested, &pb2.Nested{
1106 OptString: scalar.String("just a regular extension"),
1107 })
1108 return m
1109 }(),
1110 want: `[pb2.MessageSetExtension]: {
1111 opt_string: "a messageset extension"
1112}
1113[pb2.MessageSetExtension.ext_nested]: {
1114 opt_string: "just a regular extension"
1115}
1116[pb2.MessageSetExtension.not_message_set_extension]: {
1117 opt_string: "not a messageset extension"
1118}
1119`,
1120 }, {
1121 desc: "not real MessageSet 1",
1122 input: func() proto.Message {
1123 m := &pb2.FakeMessageSet{}
1124 setExtension(m, pb2.E_FakeMessageSetExtension_MessageSetExtension, &pb2.FakeMessageSetExtension{
1125 OptString: scalar.String("not a messageset extension"),
1126 })
1127 return m
1128 }(),
1129 want: `[pb2.FakeMessageSetExtension.message_set_extension]: {
1130 opt_string: "not a messageset extension"
1131}
1132`,
1133 }, {
1134 desc: "not real MessageSet 2",
1135 input: func() proto.Message {
1136 m := &pb2.MessageSet{}
1137 setExtension(m, pb2.E_MessageSetExtension, &pb2.FakeMessageSetExtension{
1138 OptString: scalar.String("another not a messageset extension"),
1139 })
1140 return m
1141 }(),
1142 want: `[pb2.message_set_extension]: {
1143 opt_string: "another not a messageset extension"
1144}
1145`,
Herbie Ongf42b55f2019-01-02 15:46:07 -08001146 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001147 desc: "Any not expanded",
Damien Neil5c5b5312019-05-14 12:44:37 -07001148 mo: prototext.MarshalOptions{
Herbie Ong66c365c2019-01-04 14:08:41 -08001149 Resolver: preg.NewTypes(),
1150 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001151 input: func() proto.Message {
1152 m := &pb2.Nested{
1153 OptString: scalar.String("embedded inside Any"),
1154 OptNested: &pb2.Nested{
1155 OptString: scalar.String("inception"),
1156 },
1157 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -07001158 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ongf42b55f2019-01-02 15:46:07 -08001159 if err != nil {
1160 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1161 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07001162 return &anypb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001163 TypeUrl: "pb2.Nested",
Herbie Ongf42b55f2019-01-02 15:46:07 -08001164 Value: b,
Herbie Ong300cff02019-03-20 18:05:16 -07001165 }
Herbie Ongf42b55f2019-01-02 15:46:07 -08001166 }(),
1167 want: `type_url: "pb2.Nested"
1168value: "\n\x13embedded inside Any\x12\x0b\n\tinception"
1169`,
1170 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001171 desc: "Any expanded",
Damien Neil5c5b5312019-05-14 12:44:37 -07001172 mo: prototext.MarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001173 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
Herbie Ong66c365c2019-01-04 14:08:41 -08001174 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001175 input: func() proto.Message {
1176 m := &pb2.Nested{
1177 OptString: scalar.String("embedded inside Any"),
1178 OptNested: &pb2.Nested{
1179 OptString: scalar.String("inception"),
1180 },
1181 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -07001182 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ongf42b55f2019-01-02 15:46:07 -08001183 if err != nil {
1184 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1185 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07001186 return &anypb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001187 TypeUrl: "foo/pb2.Nested",
Herbie Ongf42b55f2019-01-02 15:46:07 -08001188 Value: b,
Herbie Ong300cff02019-03-20 18:05:16 -07001189 }
Herbie Ongf42b55f2019-01-02 15:46:07 -08001190 }(),
Herbie Ong66c365c2019-01-04 14:08:41 -08001191 want: `[foo/pb2.Nested]: {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001192 opt_string: "embedded inside Any"
1193 opt_nested: {
1194 opt_string: "inception"
1195 }
1196}
1197`,
1198 }, {
Damien Neil0c9f0a92019-06-19 10:41:09 -07001199 desc: "Any expanded with missing required",
Damien Neil5c5b5312019-05-14 12:44:37 -07001200 mo: prototext.MarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001201 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.PartialRequired{})),
Herbie Ong66c365c2019-01-04 14:08:41 -08001202 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001203 input: func() proto.Message {
1204 m := &pb2.PartialRequired{
1205 OptString: scalar.String("embedded inside Any"),
1206 }
Damien Neil96c229a2019-04-03 12:17:24 -07001207 b, err := proto.MarshalOptions{
1208 AllowPartial: true,
1209 Deterministic: true,
1210 }.Marshal(m)
Herbie Ong300cff02019-03-20 18:05:16 -07001211 if err != nil {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001212 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1213 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07001214 return &anypb.Any{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001215 TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
Herbie Ongf42b55f2019-01-02 15:46:07 -08001216 Value: b,
Herbie Ong300cff02019-03-20 18:05:16 -07001217 }
Herbie Ongf42b55f2019-01-02 15:46:07 -08001218 }(),
1219 want: `[pb2.PartialRequired]: {
1220 opt_string: "embedded inside Any"
1221}
1222`,
Herbie Ongf42b55f2019-01-02 15:46:07 -08001223 }, {
Herbie Ong21a39742019-04-08 17:32:44 -07001224 desc: "Any with invalid UTF-8",
Damien Neil5c5b5312019-05-14 12:44:37 -07001225 mo: prototext.MarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001226 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb3.Nested{})),
Herbie Ong21a39742019-04-08 17:32:44 -07001227 },
1228 input: func() proto.Message {
1229 m := &pb3.Nested{
Damien Neilbc310b52019-04-11 11:46:55 -07001230 SString: "abcd",
Herbie Ong21a39742019-04-08 17:32:44 -07001231 }
1232 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
1233 if err != nil {
1234 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1235 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07001236 return &anypb.Any{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001237 TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
Damien Neilbc310b52019-04-11 11:46:55 -07001238 Value: bytes.Replace(b, []byte("abcd"), []byte("abc\xff"), -1),
Herbie Ong21a39742019-04-08 17:32:44 -07001239 }
1240 }(),
1241 want: `[pb3.Nested]: {
1242 s_string: "abc\xff"
1243}
1244`,
1245 wantErr: true,
1246 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001247 desc: "Any with invalid value",
Damien Neil5c5b5312019-05-14 12:44:37 -07001248 mo: prototext.MarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001249 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
Herbie Ong66c365c2019-01-04 14:08:41 -08001250 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07001251 input: &anypb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001252 TypeUrl: "foo/pb2.Nested",
1253 Value: dhex("80"),
Herbie Ong300cff02019-03-20 18:05:16 -07001254 },
Herbie Ong66c365c2019-01-04 14:08:41 -08001255 want: `type_url: "foo/pb2.Nested"
Herbie Onga94f78c2019-01-03 15:39:58 -08001256value: "\x80"
1257`,
Herbie Ongcddf8192018-11-28 18:25:20 -08001258 }}
1259
1260 for _, tt := range tests {
1261 tt := tt
1262 t.Run(tt.desc, func(t *testing.T) {
Herbie Ong3a385912019-03-20 14:04:24 -07001263 // Use 2-space indentation on all MarshalOptions.
1264 tt.mo.Indent = " "
Herbie Ongf42b55f2019-01-02 15:46:07 -08001265 b, err := tt.mo.Marshal(tt.input)
Herbie Ongcddf8192018-11-28 18:25:20 -08001266 if err != nil && !tt.wantErr {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001267 t.Errorf("Marshal() returned error: %v\n", err)
Herbie Ongcddf8192018-11-28 18:25:20 -08001268 }
Herbie Ong800c9902018-12-06 15:28:53 -08001269 if err == nil && tt.wantErr {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001270 t.Error("Marshal() got nil error, want error\n")
Herbie Ongcddf8192018-11-28 18:25:20 -08001271 }
Herbie Ong800c9902018-12-06 15:28:53 -08001272 got := string(b)
1273 if tt.want != "" && got != tt.want {
1274 t.Errorf("Marshal()\n<got>\n%v\n<want>\n%v\n", got, tt.want)
Joe Tsai378c1322019-04-25 23:48:08 -07001275 if diff := cmp.Diff(tt.want, got); diff != "" {
Herbie Ongcddf8192018-11-28 18:25:20 -08001276 t.Errorf("Marshal() diff -want +got\n%v\n", diff)
1277 }
1278 }
1279 })
1280 }
1281}