blob: 01e8a64677895edecf261cbe6bd3ee25b80bae26 [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",
Joe Tsai28216c72019-06-22 13:20:09 -0700852 input: func() proto.Message {
853 m := &pb2.Scalars{
854 OptString: scalar.String("this message contains unknown fields"),
855 }
856 m.ProtoReflect().SetUnknown(pack.Message{
Herbie Ong20a1d312018-12-11 21:08:58 -0800857 pack.Tag{101, pack.VarintType}, pack.Bool(true),
858 pack.Tag{102, pack.VarintType}, pack.Varint(0xff),
859 pack.Tag{103, pack.Fixed32Type}, pack.Uint32(47),
860 pack.Tag{104, pack.Fixed64Type}, pack.Int64(0xdeadbeef),
Joe Tsai28216c72019-06-22 13:20:09 -0700861 }.Marshal())
862 return m
863 }(),
Herbie Ong20a1d312018-12-11 21:08:58 -0800864 want: `opt_string: "this message contains unknown fields"
865101: 1
866102: 255
867103: 47
868104: 3735928559
869`,
870 }, {
871 desc: "unknown length-delimited",
Joe Tsai28216c72019-06-22 13:20:09 -0700872 input: func() proto.Message {
873 m := new(pb2.Scalars)
874 m.ProtoReflect().SetUnknown(pack.Message{
Herbie Ong20a1d312018-12-11 21:08:58 -0800875 pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false)},
876 pack.Tag{102, pack.BytesType}, pack.String("hello world"),
877 pack.Tag{103, pack.BytesType}, pack.Bytes("\xe4\xb8\x96\xe7\x95\x8c"),
Joe Tsai28216c72019-06-22 13:20:09 -0700878 }.Marshal())
879 return m
880 }(),
Herbie Ong20a1d312018-12-11 21:08:58 -0800881 want: `101: "\x01\x00"
882102: "hello world"
883103: "世界"
884`,
885 }, {
886 desc: "unknown group type",
Joe Tsai28216c72019-06-22 13:20:09 -0700887 input: func() proto.Message {
888 m := new(pb2.Scalars)
889 m.ProtoReflect().SetUnknown(pack.Message{
Herbie Ong20a1d312018-12-11 21:08:58 -0800890 pack.Tag{101, pack.StartGroupType}, pack.Tag{101, pack.EndGroupType},
891 pack.Tag{102, pack.StartGroupType},
892 pack.Tag{101, pack.VarintType}, pack.Bool(false),
893 pack.Tag{102, pack.BytesType}, pack.String("inside a group"),
894 pack.Tag{102, pack.EndGroupType},
Joe Tsai28216c72019-06-22 13:20:09 -0700895 }.Marshal())
896 return m
897 }(),
Herbie Ong20a1d312018-12-11 21:08:58 -0800898 want: `101: {}
899102: {
900 101: 0
901 102: "inside a group"
902}
903`,
904 }, {
905 desc: "unknown unpack repeated field",
Joe Tsai28216c72019-06-22 13:20:09 -0700906 input: func() proto.Message {
907 m := new(pb2.Scalars)
908 m.ProtoReflect().SetUnknown(pack.Message{
Herbie Ong20a1d312018-12-11 21:08:58 -0800909 pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false), pack.Bool(true)},
910 pack.Tag{102, pack.BytesType}, pack.String("hello"),
911 pack.Tag{101, pack.VarintType}, pack.Bool(true),
912 pack.Tag{102, pack.BytesType}, pack.String("世界"),
Joe Tsai28216c72019-06-22 13:20:09 -0700913 }.Marshal())
914 return m
915 }(),
Herbie Ong20a1d312018-12-11 21:08:58 -0800916 want: `101: "\x01\x00\x01"
Herbie Ong20a1d312018-12-11 21:08:58 -0800917102: "hello"
Joe Tsai378c1322019-04-25 23:48:08 -0700918101: 1
Herbie Ong20a1d312018-12-11 21:08:58 -0800919102: "世界"
920`,
Herbie Ongcf253082018-12-17 17:13:07 -0800921 }, {
922 desc: "extensions of non-repeated fields",
923 input: func() proto.Message {
924 m := &pb2.Extensions{
925 OptString: scalar.String("non-extension field"),
926 OptBool: scalar.Bool(true),
927 OptInt32: scalar.Int32(42),
928 }
929 setExtension(m, pb2.E_OptExtBool, true)
930 setExtension(m, pb2.E_OptExtString, "extension field")
Herbie Ong8170d692019-02-13 14:13:21 -0800931 setExtension(m, pb2.E_OptExtEnum, pb2.Enum_TEN)
Herbie Ongcf253082018-12-17 17:13:07 -0800932 setExtension(m, pb2.E_OptExtNested, &pb2.Nested{
933 OptString: scalar.String("nested in an extension"),
934 OptNested: &pb2.Nested{
935 OptString: scalar.String("another nested in an extension"),
936 },
937 })
938 return m
939 }(),
940 want: `opt_string: "non-extension field"
941opt_bool: true
942opt_int32: 42
943[pb2.opt_ext_bool]: true
Herbie Ong8170d692019-02-13 14:13:21 -0800944[pb2.opt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -0800945[pb2.opt_ext_nested]: {
946 opt_string: "nested in an extension"
947 opt_nested: {
948 opt_string: "another nested in an extension"
949 }
950}
951[pb2.opt_ext_string]: "extension field"
952`,
953 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700954 desc: "extension field contains invalid UTF-8",
955 input: func() proto.Message {
956 m := &pb2.Extensions{}
957 setExtension(m, pb2.E_OptExtString, "abc\xff")
958 return m
959 }(),
Herbie Ong21a39742019-04-08 17:32:44 -0700960 wantErr: true,
961 }, {
Herbie Ong09b28a92019-04-03 15:42:41 -0700962 desc: "extension partial returns error",
963 input: func() proto.Message {
964 m := &pb2.Extensions{}
965 setExtension(m, pb2.E_OptExtPartial, &pb2.PartialRequired{
966 OptString: scalar.String("partial1"),
967 })
968 setExtension(m, pb2.E_ExtensionsContainer_OptExtPartial, &pb2.PartialRequired{
969 OptString: scalar.String("partial2"),
970 })
971 return m
972 }(),
973 want: `[pb2.ExtensionsContainer.opt_ext_partial]: {
974 opt_string: "partial2"
975}
976[pb2.opt_ext_partial]: {
977 opt_string: "partial1"
978}
979`,
980 wantErr: true,
981 }, {
982 desc: "extension partial with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700983 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong09b28a92019-04-03 15:42:41 -0700984 input: func() proto.Message {
985 m := &pb2.Extensions{}
986 setExtension(m, pb2.E_OptExtPartial, &pb2.PartialRequired{
987 OptString: scalar.String("partial1"),
988 })
989 return m
990 }(),
991 want: `[pb2.opt_ext_partial]: {
992 opt_string: "partial1"
993}
994`,
995 }, {
Herbie Ongcf253082018-12-17 17:13:07 -0800996 desc: "extensions of repeated fields",
997 input: func() proto.Message {
998 m := &pb2.Extensions{}
Herbie Ong8170d692019-02-13 14:13:21 -0800999 setExtension(m, pb2.E_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
Herbie Ongcf253082018-12-17 17:13:07 -08001000 setExtension(m, pb2.E_RptExtFixed32, &[]uint32{42, 47})
1001 setExtension(m, pb2.E_RptExtNested, &[]*pb2.Nested{
1002 &pb2.Nested{OptString: scalar.String("one")},
1003 &pb2.Nested{OptString: scalar.String("two")},
1004 &pb2.Nested{OptString: scalar.String("three")},
1005 })
1006 return m
1007 }(),
Herbie Ong8170d692019-02-13 14:13:21 -08001008 want: `[pb2.rpt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -08001009[pb2.rpt_ext_enum]: 101
Herbie Ong8170d692019-02-13 14:13:21 -08001010[pb2.rpt_ext_enum]: ONE
Herbie Ongcf253082018-12-17 17:13:07 -08001011[pb2.rpt_ext_fixed32]: 42
1012[pb2.rpt_ext_fixed32]: 47
1013[pb2.rpt_ext_nested]: {
1014 opt_string: "one"
1015}
1016[pb2.rpt_ext_nested]: {
1017 opt_string: "two"
1018}
1019[pb2.rpt_ext_nested]: {
1020 opt_string: "three"
1021}
1022`,
1023 }, {
1024 desc: "extensions of non-repeated fields in another message",
1025 input: func() proto.Message {
1026 m := &pb2.Extensions{}
1027 setExtension(m, pb2.E_ExtensionsContainer_OptExtBool, true)
1028 setExtension(m, pb2.E_ExtensionsContainer_OptExtString, "extension field")
Herbie Ong8170d692019-02-13 14:13:21 -08001029 setExtension(m, pb2.E_ExtensionsContainer_OptExtEnum, pb2.Enum_TEN)
Herbie Ongcf253082018-12-17 17:13:07 -08001030 setExtension(m, pb2.E_ExtensionsContainer_OptExtNested, &pb2.Nested{
1031 OptString: scalar.String("nested in an extension"),
1032 OptNested: &pb2.Nested{
1033 OptString: scalar.String("another nested in an extension"),
1034 },
1035 })
1036 return m
1037 }(),
1038 want: `[pb2.ExtensionsContainer.opt_ext_bool]: true
Herbie Ong8170d692019-02-13 14:13:21 -08001039[pb2.ExtensionsContainer.opt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -08001040[pb2.ExtensionsContainer.opt_ext_nested]: {
1041 opt_string: "nested in an extension"
1042 opt_nested: {
1043 opt_string: "another nested in an extension"
1044 }
1045}
1046[pb2.ExtensionsContainer.opt_ext_string]: "extension field"
1047`,
1048 }, {
1049 desc: "extensions of repeated fields in another message",
1050 input: func() proto.Message {
1051 m := &pb2.Extensions{
1052 OptString: scalar.String("non-extension field"),
1053 OptBool: scalar.Bool(true),
1054 OptInt32: scalar.Int32(42),
1055 }
Herbie Ong8170d692019-02-13 14:13:21 -08001056 setExtension(m, pb2.E_ExtensionsContainer_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
Herbie Ongcf253082018-12-17 17:13:07 -08001057 setExtension(m, pb2.E_ExtensionsContainer_RptExtString, &[]string{"hello", "world"})
1058 setExtension(m, pb2.E_ExtensionsContainer_RptExtNested, &[]*pb2.Nested{
1059 &pb2.Nested{OptString: scalar.String("one")},
1060 &pb2.Nested{OptString: scalar.String("two")},
1061 &pb2.Nested{OptString: scalar.String("three")},
1062 })
1063 return m
1064 }(),
1065 want: `opt_string: "non-extension field"
1066opt_bool: true
1067opt_int32: 42
Herbie Ong8170d692019-02-13 14:13:21 -08001068[pb2.ExtensionsContainer.rpt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -08001069[pb2.ExtensionsContainer.rpt_ext_enum]: 101
Herbie Ong8170d692019-02-13 14:13:21 -08001070[pb2.ExtensionsContainer.rpt_ext_enum]: ONE
Herbie Ongcf253082018-12-17 17:13:07 -08001071[pb2.ExtensionsContainer.rpt_ext_nested]: {
1072 opt_string: "one"
1073}
1074[pb2.ExtensionsContainer.rpt_ext_nested]: {
1075 opt_string: "two"
1076}
1077[pb2.ExtensionsContainer.rpt_ext_nested]: {
1078 opt_string: "three"
1079}
1080[pb2.ExtensionsContainer.rpt_ext_string]: "hello"
1081[pb2.ExtensionsContainer.rpt_ext_string]: "world"
1082`,
Herbie Ong6470ea62019-01-07 18:56:57 -08001083 }, {
1084 desc: "MessageSet",
1085 input: func() proto.Message {
1086 m := &pb2.MessageSet{}
1087 setExtension(m, pb2.E_MessageSetExtension_MessageSetExtension, &pb2.MessageSetExtension{
1088 OptString: scalar.String("a messageset extension"),
1089 })
1090 setExtension(m, pb2.E_MessageSetExtension_NotMessageSetExtension, &pb2.MessageSetExtension{
1091 OptString: scalar.String("not a messageset extension"),
1092 })
1093 setExtension(m, pb2.E_MessageSetExtension_ExtNested, &pb2.Nested{
1094 OptString: scalar.String("just a regular extension"),
1095 })
1096 return m
1097 }(),
1098 want: `[pb2.MessageSetExtension]: {
1099 opt_string: "a messageset extension"
1100}
1101[pb2.MessageSetExtension.ext_nested]: {
1102 opt_string: "just a regular extension"
1103}
1104[pb2.MessageSetExtension.not_message_set_extension]: {
1105 opt_string: "not a messageset extension"
1106}
1107`,
1108 }, {
1109 desc: "not real MessageSet 1",
1110 input: func() proto.Message {
1111 m := &pb2.FakeMessageSet{}
1112 setExtension(m, pb2.E_FakeMessageSetExtension_MessageSetExtension, &pb2.FakeMessageSetExtension{
1113 OptString: scalar.String("not a messageset extension"),
1114 })
1115 return m
1116 }(),
1117 want: `[pb2.FakeMessageSetExtension.message_set_extension]: {
1118 opt_string: "not a messageset extension"
1119}
1120`,
1121 }, {
1122 desc: "not real MessageSet 2",
1123 input: func() proto.Message {
1124 m := &pb2.MessageSet{}
1125 setExtension(m, pb2.E_MessageSetExtension, &pb2.FakeMessageSetExtension{
1126 OptString: scalar.String("another not a messageset extension"),
1127 })
1128 return m
1129 }(),
1130 want: `[pb2.message_set_extension]: {
1131 opt_string: "another not a messageset extension"
1132}
1133`,
Herbie Ongf42b55f2019-01-02 15:46:07 -08001134 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001135 desc: "Any not expanded",
Damien Neil5c5b5312019-05-14 12:44:37 -07001136 mo: prototext.MarshalOptions{
Herbie Ong66c365c2019-01-04 14:08:41 -08001137 Resolver: preg.NewTypes(),
1138 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001139 input: func() proto.Message {
1140 m := &pb2.Nested{
1141 OptString: scalar.String("embedded inside Any"),
1142 OptNested: &pb2.Nested{
1143 OptString: scalar.String("inception"),
1144 },
1145 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -07001146 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ongf42b55f2019-01-02 15:46:07 -08001147 if err != nil {
1148 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1149 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07001150 return &anypb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001151 TypeUrl: "pb2.Nested",
Herbie Ongf42b55f2019-01-02 15:46:07 -08001152 Value: b,
Herbie Ong300cff02019-03-20 18:05:16 -07001153 }
Herbie Ongf42b55f2019-01-02 15:46:07 -08001154 }(),
1155 want: `type_url: "pb2.Nested"
1156value: "\n\x13embedded inside Any\x12\x0b\n\tinception"
1157`,
1158 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001159 desc: "Any expanded",
Damien Neil5c5b5312019-05-14 12:44:37 -07001160 mo: prototext.MarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001161 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
Herbie Ong66c365c2019-01-04 14:08:41 -08001162 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001163 input: func() proto.Message {
1164 m := &pb2.Nested{
1165 OptString: scalar.String("embedded inside Any"),
1166 OptNested: &pb2.Nested{
1167 OptString: scalar.String("inception"),
1168 },
1169 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -07001170 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ongf42b55f2019-01-02 15:46:07 -08001171 if err != nil {
1172 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1173 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07001174 return &anypb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001175 TypeUrl: "foo/pb2.Nested",
Herbie Ongf42b55f2019-01-02 15:46:07 -08001176 Value: b,
Herbie Ong300cff02019-03-20 18:05:16 -07001177 }
Herbie Ongf42b55f2019-01-02 15:46:07 -08001178 }(),
Herbie Ong66c365c2019-01-04 14:08:41 -08001179 want: `[foo/pb2.Nested]: {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001180 opt_string: "embedded inside Any"
1181 opt_nested: {
1182 opt_string: "inception"
1183 }
1184}
1185`,
1186 }, {
Damien Neil0c9f0a92019-06-19 10:41:09 -07001187 desc: "Any expanded with missing required",
Damien Neil5c5b5312019-05-14 12:44:37 -07001188 mo: prototext.MarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001189 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.PartialRequired{})),
Herbie Ong66c365c2019-01-04 14:08:41 -08001190 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001191 input: func() proto.Message {
1192 m := &pb2.PartialRequired{
1193 OptString: scalar.String("embedded inside Any"),
1194 }
Damien Neil96c229a2019-04-03 12:17:24 -07001195 b, err := proto.MarshalOptions{
1196 AllowPartial: true,
1197 Deterministic: true,
1198 }.Marshal(m)
Herbie Ong300cff02019-03-20 18:05:16 -07001199 if err != nil {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001200 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1201 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07001202 return &anypb.Any{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001203 TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
Herbie Ongf42b55f2019-01-02 15:46:07 -08001204 Value: b,
Herbie Ong300cff02019-03-20 18:05:16 -07001205 }
Herbie Ongf42b55f2019-01-02 15:46:07 -08001206 }(),
1207 want: `[pb2.PartialRequired]: {
1208 opt_string: "embedded inside Any"
1209}
1210`,
Herbie Ongf42b55f2019-01-02 15:46:07 -08001211 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001212 desc: "Any with invalid value",
Damien Neil5c5b5312019-05-14 12:44:37 -07001213 mo: prototext.MarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001214 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
Herbie Ong66c365c2019-01-04 14:08:41 -08001215 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07001216 input: &anypb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001217 TypeUrl: "foo/pb2.Nested",
1218 Value: dhex("80"),
Herbie Ong300cff02019-03-20 18:05:16 -07001219 },
Herbie Ong66c365c2019-01-04 14:08:41 -08001220 want: `type_url: "foo/pb2.Nested"
Herbie Onga94f78c2019-01-03 15:39:58 -08001221value: "\x80"
1222`,
Herbie Ongcddf8192018-11-28 18:25:20 -08001223 }}
1224
1225 for _, tt := range tests {
1226 tt := tt
1227 t.Run(tt.desc, func(t *testing.T) {
Herbie Ong3a385912019-03-20 14:04:24 -07001228 // Use 2-space indentation on all MarshalOptions.
1229 tt.mo.Indent = " "
Herbie Ongf42b55f2019-01-02 15:46:07 -08001230 b, err := tt.mo.Marshal(tt.input)
Herbie Ongcddf8192018-11-28 18:25:20 -08001231 if err != nil && !tt.wantErr {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001232 t.Errorf("Marshal() returned error: %v\n", err)
Herbie Ongcddf8192018-11-28 18:25:20 -08001233 }
Herbie Ong800c9902018-12-06 15:28:53 -08001234 if err == nil && tt.wantErr {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001235 t.Error("Marshal() got nil error, want error\n")
Herbie Ongcddf8192018-11-28 18:25:20 -08001236 }
Herbie Ong800c9902018-12-06 15:28:53 -08001237 got := string(b)
1238 if tt.want != "" && got != tt.want {
1239 t.Errorf("Marshal()\n<got>\n%v\n<want>\n%v\n", got, tt.want)
Joe Tsai378c1322019-04-25 23:48:08 -07001240 if diff := cmp.Diff(tt.want, got); diff != "" {
Herbie Ongcddf8192018-11-28 18:25:20 -08001241 t.Errorf("Marshal() diff -want +got\n%v\n", diff)
1242 }
1243 }
1244 })
1245 }
1246}