blob: 41cae94fc3f0ae9b2ea0c0fa74aaddc657025d62 [file] [log] [blame]
Herbie Ongcddf8192018-11-28 18:25:20 -08001// Copyright 2018 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package textpb_test
6
7import (
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"
11 "strings"
12 "testing"
13
14 "github.com/golang/protobuf/v2/encoding/textpb"
Herbie Ongcddf8192018-11-28 18:25:20 -080015 "github.com/golang/protobuf/v2/internal/detrand"
Herbie Ong20a1d312018-12-11 21:08:58 -080016 "github.com/golang/protobuf/v2/internal/encoding/pack"
Herbie Ongcf253082018-12-17 17:13:07 -080017 "github.com/golang/protobuf/v2/internal/encoding/wire"
Herbie Ongcddf8192018-11-28 18:25:20 -080018 "github.com/golang/protobuf/v2/internal/scalar"
19 "github.com/golang/protobuf/v2/proto"
Herbie Ongf42b55f2019-01-02 15:46:07 -080020 preg "github.com/golang/protobuf/v2/reflect/protoregistry"
Joe Tsai4fddeba2019-03-20 18:29:32 -070021 "github.com/golang/protobuf/v2/runtime/protoiface"
Herbie Ongcddf8192018-11-28 18:25:20 -080022 "github.com/google/go-cmp/cmp"
23 "github.com/google/go-cmp/cmp/cmpopts"
24
Herbie Ong8170d692019-02-13 14:13:21 -080025 "github.com/golang/protobuf/v2/encoding/testprotos/pb2"
26 "github.com/golang/protobuf/v2/encoding/testprotos/pb3"
Joe Tsai19058432019-02-27 21:46:29 -080027 knownpb "github.com/golang/protobuf/v2/types/known"
Herbie Ongcddf8192018-11-28 18:25:20 -080028)
29
30func init() {
31 // Disable detrand to enable direct comparisons on outputs.
32 detrand.Disable()
33}
34
Herbie Ongcddf8192018-11-28 18:25:20 -080035// splitLines is a cmpopts.Option for comparing strings with line breaks.
36var splitLines = cmpopts.AcyclicTransformer("SplitLines", func(s string) []string {
37 return strings.Split(s, "\n")
38})
39
Herbie Ong800c9902018-12-06 15:28:53 -080040func pb2Enum(i int32) *pb2.Enum {
41 p := new(pb2.Enum)
42 *p = pb2.Enum(i)
43 return p
44}
45
46func pb2Enums_NestedEnum(i int32) *pb2.Enums_NestedEnum {
47 p := new(pb2.Enums_NestedEnum)
48 *p = pb2.Enums_NestedEnum(i)
49 return p
50}
51
Joe Tsai4fddeba2019-03-20 18:29:32 -070052func setExtension(m proto.Message, xd *protoiface.ExtensionDescV1, val interface{}) {
Herbie Ongcf253082018-12-17 17:13:07 -080053 knownFields := m.ProtoReflect().KnownFields()
54 extTypes := knownFields.ExtensionTypes()
Joe Tsaiafb455e2019-03-14 16:08:22 -070055 extTypes.Register(xd.Type)
Herbie Ongcf253082018-12-17 17:13:07 -080056 if val == nil {
57 return
58 }
Joe Tsaiafb455e2019-03-14 16:08:22 -070059 pval := xd.Type.ValueOf(val)
Herbie Ongcf253082018-12-17 17:13:07 -080060 knownFields.Set(wire.Number(xd.Field), pval)
61}
62
Herbie Onga94f78c2019-01-03 15:39:58 -080063// dhex decodes a hex-string and returns the bytes and panics if s is invalid.
64func dhex(s string) []byte {
65 b, err := hex.DecodeString(s)
66 if err != nil {
67 panic(err)
68 }
69 return b
70}
71
Herbie Ongcddf8192018-11-28 18:25:20 -080072func TestMarshal(t *testing.T) {
73 tests := []struct {
74 desc string
Herbie Ongf42b55f2019-01-02 15:46:07 -080075 mo textpb.MarshalOptions
Herbie Ong70651952018-12-13 14:19:50 -080076 input proto.Message
Herbie Ongcddf8192018-11-28 18:25:20 -080077 want string
Herbie Ong300cff02019-03-20 18:05:16 -070078 wantErr bool // TODO: Verify error message content.
Herbie Ongcddf8192018-11-28 18:25:20 -080079 }{{
Herbie Ong8170d692019-02-13 14:13:21 -080080 desc: "proto2 optional scalars not set",
Herbie Ong800c9902018-12-06 15:28:53 -080081 input: &pb2.Scalars{},
Herbie Ongcddf8192018-11-28 18:25:20 -080082 want: "\n",
83 }, {
Herbie Ong8170d692019-02-13 14:13:21 -080084 desc: "proto3 scalars not set",
Herbie Ong800c9902018-12-06 15:28:53 -080085 input: &pb3.Scalars{},
Herbie Ongcddf8192018-11-28 18:25:20 -080086 want: "\n",
87 }, {
Herbie Ong8170d692019-02-13 14:13:21 -080088 desc: "proto2 optional scalars set to zero values",
Herbie Ong800c9902018-12-06 15:28:53 -080089 input: &pb2.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -080090 OptBool: scalar.Bool(false),
91 OptInt32: scalar.Int32(0),
92 OptInt64: scalar.Int64(0),
93 OptUint32: scalar.Uint32(0),
94 OptUint64: scalar.Uint64(0),
95 OptSint32: scalar.Int32(0),
96 OptSint64: scalar.Int64(0),
97 OptFixed32: scalar.Uint32(0),
98 OptFixed64: scalar.Uint64(0),
99 OptSfixed32: scalar.Int32(0),
100 OptSfixed64: scalar.Int64(0),
101 OptFloat: scalar.Float32(0),
102 OptDouble: scalar.Float64(0),
103 OptBytes: []byte{},
104 OptString: scalar.String(""),
Herbie Ong800c9902018-12-06 15:28:53 -0800105 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800106 want: `opt_bool: false
107opt_int32: 0
108opt_int64: 0
109opt_uint32: 0
110opt_uint64: 0
111opt_sint32: 0
112opt_sint64: 0
113opt_fixed32: 0
114opt_fixed64: 0
115opt_sfixed32: 0
116opt_sfixed64: 0
117opt_float: 0
118opt_double: 0
119opt_bytes: ""
120opt_string: ""
121`,
122 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800123 desc: "proto3 scalars set to zero values",
Herbie Ong800c9902018-12-06 15:28:53 -0800124 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800125 SBool: false,
126 SInt32: 0,
127 SInt64: 0,
128 SUint32: 0,
129 SUint64: 0,
130 SSint32: 0,
131 SSint64: 0,
132 SFixed32: 0,
133 SFixed64: 0,
134 SSfixed32: 0,
135 SSfixed64: 0,
136 SFloat: 0,
137 SDouble: 0,
138 SBytes: []byte{},
139 SString: "",
Herbie Ong800c9902018-12-06 15:28:53 -0800140 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800141 want: "\n",
142 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800143 desc: "proto2 optional scalars set to some values",
Herbie Ong800c9902018-12-06 15:28:53 -0800144 input: &pb2.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800145 OptBool: scalar.Bool(true),
146 OptInt32: scalar.Int32(0xff),
147 OptInt64: scalar.Int64(0xdeadbeef),
148 OptUint32: scalar.Uint32(47),
149 OptUint64: scalar.Uint64(0xdeadbeef),
150 OptSint32: scalar.Int32(-1001),
151 OptSint64: scalar.Int64(-0xffff),
152 OptFixed64: scalar.Uint64(64),
153 OptSfixed32: scalar.Int32(-32),
Herbie Ong84f09602019-01-17 19:31:47 -0800154 OptFloat: scalar.Float32(1.02),
155 OptDouble: scalar.Float64(1.0199999809265137),
Herbie Ong8170d692019-02-13 14:13:21 -0800156 OptBytes: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
157 OptString: scalar.String("谷歌"),
Herbie Ong800c9902018-12-06 15:28:53 -0800158 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800159 want: `opt_bool: true
160opt_int32: 255
161opt_int64: 3735928559
162opt_uint32: 47
163opt_uint64: 3735928559
164opt_sint32: -1001
165opt_sint64: -65535
166opt_fixed64: 64
167opt_sfixed32: -32
Herbie Ong84f09602019-01-17 19:31:47 -0800168opt_float: 1.02
169opt_double: 1.0199999809265137
Herbie Ongcddf8192018-11-28 18:25:20 -0800170opt_bytes: "谷歌"
171opt_string: "谷歌"
172`,
173 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700174 desc: "string with invalid UTF-8",
175 input: &pb3.Scalars{
176 SString: "abc\xff",
177 },
178 want: `s_string: "abc\xff"
179`,
180 wantErr: true,
181 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800182 desc: "float nan",
Herbie Ong800c9902018-12-06 15:28:53 -0800183 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800184 SFloat: float32(math.NaN()),
Herbie Ong800c9902018-12-06 15:28:53 -0800185 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800186 want: "s_float: nan\n",
187 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800188 desc: "float positive infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800189 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800190 SFloat: float32(math.Inf(1)),
Herbie Ong800c9902018-12-06 15:28:53 -0800191 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800192 want: "s_float: inf\n",
193 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800194 desc: "float negative infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800195 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800196 SFloat: float32(math.Inf(-1)),
Herbie Ong800c9902018-12-06 15:28:53 -0800197 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800198 want: "s_float: -inf\n",
199 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800200 desc: "double nan",
Herbie Ong800c9902018-12-06 15:28:53 -0800201 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800202 SDouble: math.NaN(),
Herbie Ong800c9902018-12-06 15:28:53 -0800203 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800204 want: "s_double: nan\n",
205 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800206 desc: "double positive infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800207 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800208 SDouble: math.Inf(1),
Herbie Ong800c9902018-12-06 15:28:53 -0800209 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800210 want: "s_double: inf\n",
211 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800212 desc: "double negative infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800213 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800214 SDouble: math.Inf(-1),
Herbie Ong800c9902018-12-06 15:28:53 -0800215 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800216 want: "s_double: -inf\n",
217 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800218 desc: "proto2 enum not set",
219 input: &pb2.Enums{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800220 want: "\n",
221 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800222 desc: "proto2 enum set to zero value",
223 input: &pb2.Enums{
Herbie Ong8170d692019-02-13 14:13:21 -0800224 OptEnum: pb2Enum(0),
Herbie Ong800c9902018-12-06 15:28:53 -0800225 OptNestedEnum: pb2Enums_NestedEnum(0),
226 },
Herbie Ong8170d692019-02-13 14:13:21 -0800227 want: `opt_enum: 0
Herbie Ong800c9902018-12-06 15:28:53 -0800228opt_nested_enum: 0
229`,
230 }, {
231 desc: "proto2 enum",
232 input: &pb2.Enums{
Herbie Ong8170d692019-02-13 14:13:21 -0800233 OptEnum: pb2.Enum_ONE.Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800234 OptNestedEnum: pb2.Enums_UNO.Enum(),
235 },
Herbie Ong8170d692019-02-13 14:13:21 -0800236 want: `opt_enum: ONE
Herbie Ong800c9902018-12-06 15:28:53 -0800237opt_nested_enum: UNO
238`,
239 }, {
240 desc: "proto2 enum set to numeric values",
241 input: &pb2.Enums{
Herbie Ong8170d692019-02-13 14:13:21 -0800242 OptEnum: pb2Enum(2),
Herbie Ong800c9902018-12-06 15:28:53 -0800243 OptNestedEnum: pb2Enums_NestedEnum(2),
244 },
Herbie Ong8170d692019-02-13 14:13:21 -0800245 want: `opt_enum: TWO
Herbie Ong800c9902018-12-06 15:28:53 -0800246opt_nested_enum: DOS
247`,
248 }, {
249 desc: "proto2 enum set to unnamed numeric values",
250 input: &pb2.Enums{
251 OptEnum: pb2Enum(101),
252 OptNestedEnum: pb2Enums_NestedEnum(-101),
253 },
254 want: `opt_enum: 101
255opt_nested_enum: -101
256`,
257 }, {
258 desc: "proto3 enum not set",
259 input: &pb3.Enums{},
260 want: "\n",
261 }, {
262 desc: "proto3 enum set to zero value",
263 input: &pb3.Enums{
264 SEnum: pb3.Enum_ZERO,
265 SNestedEnum: pb3.Enums_CERO,
266 },
267 want: "\n",
268 }, {
269 desc: "proto3 enum",
270 input: &pb3.Enums{
271 SEnum: pb3.Enum_ONE,
Herbie Ong8170d692019-02-13 14:13:21 -0800272 SNestedEnum: pb3.Enums_UNO,
Herbie Ong800c9902018-12-06 15:28:53 -0800273 },
274 want: `s_enum: ONE
Herbie Ong8170d692019-02-13 14:13:21 -0800275s_nested_enum: UNO
Herbie Ong800c9902018-12-06 15:28:53 -0800276`,
277 }, {
278 desc: "proto3 enum set to numeric values",
279 input: &pb3.Enums{
280 SEnum: 2,
Herbie Ong8170d692019-02-13 14:13:21 -0800281 SNestedEnum: 2,
Herbie Ong800c9902018-12-06 15:28:53 -0800282 },
283 want: `s_enum: TWO
Herbie Ong8170d692019-02-13 14:13:21 -0800284s_nested_enum: DOS
Herbie Ong800c9902018-12-06 15:28:53 -0800285`,
286 }, {
287 desc: "proto3 enum set to unnamed numeric values",
288 input: &pb3.Enums{
289 SEnum: -47,
290 SNestedEnum: 47,
291 },
292 want: `s_enum: -47
293s_nested_enum: 47
294`,
295 }, {
296 desc: "proto2 nested message not set",
297 input: &pb2.Nests{},
298 want: "\n",
299 }, {
300 desc: "proto2 nested message set to empty",
301 input: &pb2.Nests{
302 OptNested: &pb2.Nested{},
303 Optgroup: &pb2.Nests_OptGroup{},
304 },
305 want: `opt_nested: {}
Herbie Ong0dcfb9a2019-01-14 15:32:26 -0800306OptGroup: {}
Herbie Ong800c9902018-12-06 15:28:53 -0800307`,
308 }, {
309 desc: "proto2 nested messages",
310 input: &pb2.Nests{
311 OptNested: &pb2.Nested{
312 OptString: scalar.String("nested message"),
313 OptNested: &pb2.Nested{
314 OptString: scalar.String("another nested message"),
315 },
316 },
317 },
318 want: `opt_nested: {
319 opt_string: "nested message"
320 opt_nested: {
321 opt_string: "another nested message"
322 }
323}
324`,
325 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800326 desc: "proto2 groups",
Herbie Ong800c9902018-12-06 15:28:53 -0800327 input: &pb2.Nests{
328 Optgroup: &pb2.Nests_OptGroup{
Herbie Ong800c9902018-12-06 15:28:53 -0800329 OptString: scalar.String("inside a group"),
330 OptNested: &pb2.Nested{
331 OptString: scalar.String("nested message inside a group"),
332 },
333 Optnestedgroup: &pb2.Nests_OptGroup_OptNestedGroup{
Herbie Ong8170d692019-02-13 14:13:21 -0800334 OptFixed32: scalar.Uint32(47),
Herbie Ong800c9902018-12-06 15:28:53 -0800335 },
336 },
337 },
Herbie Ong0dcfb9a2019-01-14 15:32:26 -0800338 want: `OptGroup: {
Herbie Ong800c9902018-12-06 15:28:53 -0800339 opt_string: "inside a group"
340 opt_nested: {
341 opt_string: "nested message inside a group"
342 }
Herbie Ong0dcfb9a2019-01-14 15:32:26 -0800343 OptNestedGroup: {
Herbie Ong8170d692019-02-13 14:13:21 -0800344 opt_fixed32: 47
Herbie Ong800c9902018-12-06 15:28:53 -0800345 }
346}
347`,
348 }, {
349 desc: "proto3 nested message not set",
350 input: &pb3.Nests{},
351 want: "\n",
352 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800353 desc: "proto3 nested message set to empty",
354 input: &pb3.Nests{
355 SNested: &pb3.Nested{},
356 },
357 want: "s_nested: {}\n",
358 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800359 desc: "proto3 nested message",
360 input: &pb3.Nests{
361 SNested: &pb3.Nested{
362 SString: "nested message",
363 SNested: &pb3.Nested{
364 SString: "another nested message",
365 },
366 },
367 },
368 want: `s_nested: {
369 s_string: "nested message"
370 s_nested: {
371 s_string: "another nested message"
372 }
373}
374`,
375 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700376 desc: "proto3 nested message contains invalid UTF-8",
377 input: &pb3.Nests{
378 SNested: &pb3.Nested{
379 SString: "abc\xff",
380 },
381 },
382 want: `s_nested: {
383 s_string: "abc\xff"
384}
385`,
386 wantErr: true,
387 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800388 desc: "oneof not set",
389 input: &pb3.Oneofs{},
Herbie Ong800c9902018-12-06 15:28:53 -0800390 want: "\n",
391 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800392 desc: "oneof set to empty string",
393 input: &pb3.Oneofs{
394 Union: &pb3.Oneofs_OneofString{},
Herbie Ong800c9902018-12-06 15:28:53 -0800395 },
Herbie Ong8170d692019-02-13 14:13:21 -0800396 want: `oneof_string: ""
397`,
Herbie Ong800c9902018-12-06 15:28:53 -0800398 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800399 desc: "oneof set to string",
400 input: &pb3.Oneofs{
401 Union: &pb3.Oneofs_OneofString{
402 OneofString: "hello",
Herbie Ong800c9902018-12-06 15:28:53 -0800403 },
404 },
Herbie Ong8170d692019-02-13 14:13:21 -0800405 want: `oneof_string: "hello"
406`,
Herbie Ong800c9902018-12-06 15:28:53 -0800407 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800408 desc: "oneof set to enum",
409 input: &pb3.Oneofs{
410 Union: &pb3.Oneofs_OneofEnum{
411 OneofEnum: pb3.Enum_ZERO,
Herbie Ong800c9902018-12-06 15:28:53 -0800412 },
413 },
Herbie Ong8170d692019-02-13 14:13:21 -0800414 want: `oneof_enum: ZERO
415`,
Herbie Ong800c9902018-12-06 15:28:53 -0800416 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800417 desc: "oneof set to empty message",
418 input: &pb3.Oneofs{
419 Union: &pb3.Oneofs_OneofNested{
420 OneofNested: &pb3.Nested{},
421 },
422 },
423 want: "oneof_nested: {}\n",
424 }, {
425 desc: "oneof set to message",
426 input: &pb3.Oneofs{
427 Union: &pb3.Oneofs_OneofNested{
428 OneofNested: &pb3.Nested{
429 SString: "nested message",
Herbie Ong800c9902018-12-06 15:28:53 -0800430 },
431 },
432 },
Herbie Ong8170d692019-02-13 14:13:21 -0800433 want: `oneof_nested: {
434 s_string: "nested message"
Herbie Ong800c9902018-12-06 15:28:53 -0800435}
436`,
437 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800438 desc: "repeated fields not set",
Herbie Ong800c9902018-12-06 15:28:53 -0800439 input: &pb2.Repeats{},
440 want: "\n",
441 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800442 desc: "repeated fields set to empty slices",
Herbie Ong800c9902018-12-06 15:28:53 -0800443 input: &pb2.Repeats{
Herbie Ongcddf8192018-11-28 18:25:20 -0800444 RptBool: []bool{},
445 RptInt32: []int32{},
446 RptInt64: []int64{},
447 RptUint32: []uint32{},
448 RptUint64: []uint64{},
449 RptFloat: []float32{},
450 RptDouble: []float64{},
451 RptBytes: [][]byte{},
Herbie Ong800c9902018-12-06 15:28:53 -0800452 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800453 want: "\n",
454 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800455 desc: "repeated fields set to some values",
Herbie Ong800c9902018-12-06 15:28:53 -0800456 input: &pb2.Repeats{
Herbie Ongcddf8192018-11-28 18:25:20 -0800457 RptBool: []bool{true, false, true, true},
458 RptInt32: []int32{1, 6, 0, 0},
459 RptInt64: []int64{-64, 47},
460 RptUint32: []uint32{0xff, 0xffff},
461 RptUint64: []uint64{0xdeadbeef},
Herbie Ong84f09602019-01-17 19:31:47 -0800462 RptFloat: []float32{float32(math.NaN()), float32(math.Inf(1)), float32(math.Inf(-1)), 1.034},
Herbie Ongcddf8192018-11-28 18:25:20 -0800463 RptDouble: []float64{math.NaN(), math.Inf(1), math.Inf(-1), 1.23e-308},
464 RptString: []string{"hello", "世界"},
465 RptBytes: [][]byte{
466 []byte("hello"),
467 []byte("\xe4\xb8\x96\xe7\x95\x8c"),
468 },
Herbie Ong800c9902018-12-06 15:28:53 -0800469 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800470 want: `rpt_bool: true
471rpt_bool: false
472rpt_bool: true
473rpt_bool: true
474rpt_int32: 1
475rpt_int32: 6
476rpt_int32: 0
477rpt_int32: 0
478rpt_int64: -64
479rpt_int64: 47
480rpt_uint32: 255
481rpt_uint32: 65535
482rpt_uint64: 3735928559
Herbie Ong84f09602019-01-17 19:31:47 -0800483rpt_float: nan
484rpt_float: inf
485rpt_float: -inf
486rpt_float: 1.034
Herbie Ongcddf8192018-11-28 18:25:20 -0800487rpt_double: nan
488rpt_double: inf
489rpt_double: -inf
490rpt_double: 1.23e-308
491rpt_string: "hello"
492rpt_string: "世界"
493rpt_bytes: "hello"
494rpt_bytes: "世界"
495`,
496 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700497 desc: "repeated contains invalid UTF-8",
498 input: &pb2.Repeats{
499 RptString: []string{"abc\xff"},
500 },
501 want: `rpt_string: "abc\xff"
502`,
503 wantErr: true,
504 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800505 desc: "repeated enums",
Herbie Ong800c9902018-12-06 15:28:53 -0800506 input: &pb2.Enums{
Herbie Ong8170d692019-02-13 14:13:21 -0800507 RptEnum: []pb2.Enum{pb2.Enum_ONE, 2, pb2.Enum_TEN, 42},
Herbie Ongcddf8192018-11-28 18:25:20 -0800508 RptNestedEnum: []pb2.Enums_NestedEnum{2, 47, 10},
Herbie Ong800c9902018-12-06 15:28:53 -0800509 },
Herbie Ong8170d692019-02-13 14:13:21 -0800510 want: `rpt_enum: ONE
511rpt_enum: TWO
512rpt_enum: TEN
Herbie Ongcddf8192018-11-28 18:25:20 -0800513rpt_enum: 42
Herbie Ongcddf8192018-11-28 18:25:20 -0800514rpt_nested_enum: DOS
515rpt_nested_enum: 47
516rpt_nested_enum: DIEZ
517`,
518 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800519 desc: "repeated messages set to empty",
Herbie Ong800c9902018-12-06 15:28:53 -0800520 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800521 RptNested: []*pb2.Nested{},
522 Rptgroup: []*pb2.Nests_RptGroup{},
Herbie Ong800c9902018-12-06 15:28:53 -0800523 },
524 want: "\n",
Herbie Ongcddf8192018-11-28 18:25:20 -0800525 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800526 desc: "repeated messages",
Herbie Ong800c9902018-12-06 15:28:53 -0800527 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800528 RptNested: []*pb2.Nested{
529 {
530 OptString: scalar.String("repeat nested one"),
531 },
532 {
533 OptString: scalar.String("repeat nested two"),
534 OptNested: &pb2.Nested{
535 OptString: scalar.String("inside repeat nested two"),
536 },
537 },
538 {},
539 },
Herbie Ong800c9902018-12-06 15:28:53 -0800540 },
541 want: `rpt_nested: {
Herbie Ongcddf8192018-11-28 18:25:20 -0800542 opt_string: "repeat nested one"
543}
544rpt_nested: {
545 opt_string: "repeat nested two"
546 opt_nested: {
547 opt_string: "inside repeat nested two"
548 }
549}
550rpt_nested: {}
551`,
552 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800553 desc: "repeated messages contains nil value",
Herbie Ongf5db2df2019-02-07 20:17:45 -0800554 input: &pb2.Nests{
555 RptNested: []*pb2.Nested{nil, {}},
556 },
557 want: `rpt_nested: {}
558rpt_nested: {}
559`,
560 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800561 desc: "repeated groups",
Herbie Ong800c9902018-12-06 15:28:53 -0800562 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800563 Rptgroup: []*pb2.Nests_RptGroup{
564 {
Herbie Ong8170d692019-02-13 14:13:21 -0800565 RptString: []string{"hello", "world"},
Herbie Ongcddf8192018-11-28 18:25:20 -0800566 },
567 {},
Herbie Ong8170d692019-02-13 14:13:21 -0800568 nil,
Herbie Ongcddf8192018-11-28 18:25:20 -0800569 },
Herbie Ong800c9902018-12-06 15:28:53 -0800570 },
Herbie Ongde7313b2019-01-14 19:26:50 -0800571 want: `RptGroup: {
Herbie Ong8170d692019-02-13 14:13:21 -0800572 rpt_string: "hello"
573 rpt_string: "world"
Herbie Ongcddf8192018-11-28 18:25:20 -0800574}
Herbie Ongde7313b2019-01-14 19:26:50 -0800575RptGroup: {}
Herbie Ong8170d692019-02-13 14:13:21 -0800576RptGroup: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800577`,
578 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800579 desc: "map fields not set",
580 input: &pb3.Maps{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800581 want: "\n",
582 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800583 desc: "map fields set to empty",
584 input: &pb3.Maps{
585 Int32ToStr: map[int32]string{},
586 BoolToUint32: map[bool]uint32{},
587 Uint64ToEnum: map[uint64]pb3.Enum{},
588 StrToNested: map[string]*pb3.Nested{},
589 StrToOneofs: map[string]*pb3.Oneofs{},
Herbie Ong800c9902018-12-06 15:28:53 -0800590 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800591 want: "\n",
592 }, {
593 desc: "map fields 1",
Herbie Ong8170d692019-02-13 14:13:21 -0800594 input: &pb3.Maps{
Herbie Ongcddf8192018-11-28 18:25:20 -0800595 Int32ToStr: map[int32]string{
596 -101: "-101",
597 0xff: "0xff",
598 0: "zero",
599 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800600 BoolToUint32: map[bool]uint32{
601 true: 42,
602 false: 101,
603 },
Herbie Ong800c9902018-12-06 15:28:53 -0800604 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800605 want: `int32_to_str: {
606 key: -101
607 value: "-101"
608}
609int32_to_str: {
610 key: 0
611 value: "zero"
612}
613int32_to_str: {
614 key: 255
615 value: "0xff"
616}
Herbie Ongcddf8192018-11-28 18:25:20 -0800617bool_to_uint32: {
618 key: false
619 value: 101
620}
621bool_to_uint32: {
622 key: true
623 value: 42
624}
625`,
626 }, {
627 desc: "map fields 2",
Herbie Ong8170d692019-02-13 14:13:21 -0800628 input: &pb3.Maps{
629 Uint64ToEnum: map[uint64]pb3.Enum{
630 1: pb3.Enum_ONE,
631 2: pb3.Enum_TWO,
632 10: pb3.Enum_TEN,
633 47: 47,
Herbie Ongcddf8192018-11-28 18:25:20 -0800634 },
Herbie Ong800c9902018-12-06 15:28:53 -0800635 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800636 want: `uint64_to_enum: {
637 key: 1
Herbie Ong8170d692019-02-13 14:13:21 -0800638 value: ONE
Herbie Ongcddf8192018-11-28 18:25:20 -0800639}
640uint64_to_enum: {
641 key: 2
Herbie Ong8170d692019-02-13 14:13:21 -0800642 value: TWO
Herbie Ongcddf8192018-11-28 18:25:20 -0800643}
644uint64_to_enum: {
645 key: 10
Herbie Ong8170d692019-02-13 14:13:21 -0800646 value: TEN
647}
648uint64_to_enum: {
649 key: 47
650 value: 47
Herbie Ongcddf8192018-11-28 18:25:20 -0800651}
652`,
653 }, {
654 desc: "map fields 3",
Herbie Ong8170d692019-02-13 14:13:21 -0800655 input: &pb3.Maps{
656 StrToNested: map[string]*pb3.Nested{
657 "nested": &pb3.Nested{
658 SString: "nested in a map",
Herbie Ongcddf8192018-11-28 18:25:20 -0800659 },
660 },
Herbie Ong800c9902018-12-06 15:28:53 -0800661 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800662 want: `str_to_nested: {
Herbie Ong8170d692019-02-13 14:13:21 -0800663 key: "nested"
Herbie Ongcddf8192018-11-28 18:25:20 -0800664 value: {
Herbie Ong8170d692019-02-13 14:13:21 -0800665 s_string: "nested in a map"
Herbie Ongcddf8192018-11-28 18:25:20 -0800666 }
667}
668`,
669 }, {
670 desc: "map fields 4",
Herbie Ong8170d692019-02-13 14:13:21 -0800671 input: &pb3.Maps{
672 StrToOneofs: map[string]*pb3.Oneofs{
673 "string": &pb3.Oneofs{
674 Union: &pb3.Oneofs_OneofString{
675 OneofString: "hello",
Herbie Ongcddf8192018-11-28 18:25:20 -0800676 },
677 },
Herbie Ong8170d692019-02-13 14:13:21 -0800678 "nested": &pb3.Oneofs{
679 Union: &pb3.Oneofs_OneofNested{
680 OneofNested: &pb3.Nested{
681 SString: "nested oneof in map field value",
Herbie Ongcddf8192018-11-28 18:25:20 -0800682 },
683 },
684 },
685 },
Herbie Ong800c9902018-12-06 15:28:53 -0800686 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800687 want: `str_to_oneofs: {
688 key: "nested"
689 value: {
Herbie Ong8170d692019-02-13 14:13:21 -0800690 oneof_nested: {
691 s_string: "nested oneof in map field value"
Herbie Ongcddf8192018-11-28 18:25:20 -0800692 }
693 }
694}
695str_to_oneofs: {
696 key: "string"
697 value: {
Herbie Ong8170d692019-02-13 14:13:21 -0800698 oneof_string: "hello"
Herbie Ongcddf8192018-11-28 18:25:20 -0800699 }
700}
701`,
702 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700703 desc: "map field value contains invalid UTF-8",
704 input: &pb3.Maps{
705 Int32ToStr: map[int32]string{
706 101: "abc\xff",
707 },
708 },
709 want: `int32_to_str: {
710 key: 101
711 value: "abc\xff"
712}
713`,
714 wantErr: true,
715 }, {
716 desc: "map field key contains invalid UTF-8",
717 input: &pb3.Maps{
718 StrToNested: map[string]*pb3.Nested{
719 "abc\xff": {},
720 },
721 },
722 want: `str_to_nested: {
723 key: "abc\xff"
724 value: {}
725}
726`,
727 wantErr: true,
728 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800729 desc: "map field contains nil value",
730 input: &pb3.Maps{
731 StrToNested: map[string]*pb3.Nested{
Herbie Ongf5db2df2019-02-07 20:17:45 -0800732 "nil": nil,
733 },
734 },
735 want: `str_to_nested: {
736 key: "nil"
737 value: {}
738}
739`,
740 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700741 desc: "required fields not set",
Herbie Ong800c9902018-12-06 15:28:53 -0800742 input: &pb2.Requireds{},
743 want: "\n",
744 wantErr: true,
Herbie Ongcddf8192018-11-28 18:25:20 -0800745 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700746 desc: "required fields partially 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(0xbeefcafe),
750 ReqDouble: scalar.Float64(math.NaN()),
751 ReqString: scalar.String("hello"),
Herbie Ong8170d692019-02-13 14:13:21 -0800752 ReqEnum: pb2.Enum_ONE.Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800753 },
754 want: `req_bool: false
Herbie Ong800c9902018-12-06 15:28:53 -0800755req_sfixed64: 3203386110
756req_double: nan
757req_string: "hello"
Herbie Ong8170d692019-02-13 14:13:21 -0800758req_enum: ONE
Herbie Ong800c9902018-12-06 15:28:53 -0800759`,
760 wantErr: true,
761 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700762 desc: "required fields not set with AllowPartial",
763 mo: textpb.MarshalOptions{AllowPartial: true},
764 input: &pb2.Requireds{
765 ReqBool: scalar.Bool(false),
766 ReqSfixed64: scalar.Int64(0xbeefcafe),
767 ReqDouble: scalar.Float64(math.NaN()),
768 ReqString: scalar.String("hello"),
769 ReqEnum: pb2.Enum_ONE.Enum(),
770 },
771 want: `req_bool: false
772req_sfixed64: 3203386110
773req_double: nan
774req_string: "hello"
775req_enum: ONE
776`,
777 }, {
778 desc: "required fields all set",
Herbie Ong800c9902018-12-06 15:28:53 -0800779 input: &pb2.Requireds{
780 ReqBool: scalar.Bool(false),
Herbie Ong800c9902018-12-06 15:28:53 -0800781 ReqSfixed64: scalar.Int64(0),
Herbie Ong8170d692019-02-13 14:13:21 -0800782 ReqDouble: scalar.Float64(1.23),
Herbie Ong800c9902018-12-06 15:28:53 -0800783 ReqString: scalar.String(""),
Herbie Ong8170d692019-02-13 14:13:21 -0800784 ReqEnum: pb2.Enum_ONE.Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800785 ReqNested: &pb2.Nested{},
786 },
787 want: `req_bool: false
Herbie Ong800c9902018-12-06 15:28:53 -0800788req_sfixed64: 0
Herbie Ong8170d692019-02-13 14:13:21 -0800789req_double: 1.23
Herbie Ong800c9902018-12-06 15:28:53 -0800790req_string: ""
Herbie Ong8170d692019-02-13 14:13:21 -0800791req_enum: ONE
Herbie Ong800c9902018-12-06 15:28:53 -0800792req_nested: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800793`,
794 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800795 desc: "indirect required field",
796 input: &pb2.IndirectRequired{
797 OptNested: &pb2.NestedWithRequired{},
798 },
799 want: "opt_nested: {}\n",
800 wantErr: true,
Herbie Ongcddf8192018-11-28 18:25:20 -0800801 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700802 desc: "indirect required field with AllowPartial",
803 mo: textpb.MarshalOptions{AllowPartial: true},
804 input: &pb2.IndirectRequired{
805 OptNested: &pb2.NestedWithRequired{},
806 },
807 want: "opt_nested: {}\n",
808 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800809 desc: "indirect required field in empty repeated",
810 input: &pb2.IndirectRequired{
811 RptNested: []*pb2.NestedWithRequired{},
812 },
813 want: "\n",
Herbie Ongcddf8192018-11-28 18:25:20 -0800814 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800815 desc: "indirect required field in repeated",
816 input: &pb2.IndirectRequired{
817 RptNested: []*pb2.NestedWithRequired{
818 &pb2.NestedWithRequired{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800819 },
Herbie Ong800c9902018-12-06 15:28:53 -0800820 },
821 want: "rpt_nested: {}\n",
822 wantErr: true,
823 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700824 desc: "indirect required field in repeated with AllowPartial",
825 mo: textpb.MarshalOptions{AllowPartial: true},
826 input: &pb2.IndirectRequired{
827 RptNested: []*pb2.NestedWithRequired{
828 &pb2.NestedWithRequired{},
829 },
830 },
831 want: "rpt_nested: {}\n",
832 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800833 desc: "indirect required field in empty map",
834 input: &pb2.IndirectRequired{
835 StrToNested: map[string]*pb2.NestedWithRequired{},
836 },
837 want: "\n",
838 }, {
839 desc: "indirect required field in map",
840 input: &pb2.IndirectRequired{
841 StrToNested: map[string]*pb2.NestedWithRequired{
842 "fail": &pb2.NestedWithRequired{},
843 },
844 },
845 want: `str_to_nested: {
846 key: "fail"
847 value: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800848}
849`,
Herbie Ong800c9902018-12-06 15:28:53 -0800850 wantErr: true,
Herbie Ong20a1d312018-12-11 21:08:58 -0800851 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700852 desc: "indirect required field in map with AllowPartial",
853 mo: textpb.MarshalOptions{AllowPartial: true},
854 input: &pb2.IndirectRequired{
855 StrToNested: map[string]*pb2.NestedWithRequired{
856 "fail": &pb2.NestedWithRequired{},
857 },
858 },
859 want: `str_to_nested: {
860 key: "fail"
861 value: {}
862}
863`,
864 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800865 desc: "indirect required field in oneof",
866 input: &pb2.IndirectRequired{
867 Union: &pb2.IndirectRequired_OneofNested{
868 OneofNested: &pb2.NestedWithRequired{},
869 },
870 },
871 want: "oneof_nested: {}\n",
872 wantErr: true,
873 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700874 desc: "indirect required field in oneof with AllowPartial",
875 mo: textpb.MarshalOptions{AllowPartial: true},
876 input: &pb2.IndirectRequired{
877 Union: &pb2.IndirectRequired_OneofNested{
878 OneofNested: &pb2.NestedWithRequired{},
879 },
880 },
881 want: "oneof_nested: {}\n",
882 }, {
Herbie Ong20a1d312018-12-11 21:08:58 -0800883 desc: "unknown varint and fixed types",
884 input: &pb2.Scalars{
885 OptString: scalar.String("this message contains unknown fields"),
886 XXX_unrecognized: pack.Message{
887 pack.Tag{101, pack.VarintType}, pack.Bool(true),
888 pack.Tag{102, pack.VarintType}, pack.Varint(0xff),
889 pack.Tag{103, pack.Fixed32Type}, pack.Uint32(47),
890 pack.Tag{104, pack.Fixed64Type}, pack.Int64(0xdeadbeef),
891 }.Marshal(),
892 },
893 want: `opt_string: "this message contains unknown fields"
894101: 1
895102: 255
896103: 47
897104: 3735928559
898`,
899 }, {
900 desc: "unknown length-delimited",
901 input: &pb2.Scalars{
902 XXX_unrecognized: pack.Message{
903 pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false)},
904 pack.Tag{102, pack.BytesType}, pack.String("hello world"),
905 pack.Tag{103, pack.BytesType}, pack.Bytes("\xe4\xb8\x96\xe7\x95\x8c"),
906 }.Marshal(),
907 },
908 want: `101: "\x01\x00"
909102: "hello world"
910103: "世界"
911`,
912 }, {
913 desc: "unknown group type",
914 input: &pb2.Scalars{
915 XXX_unrecognized: pack.Message{
916 pack.Tag{101, pack.StartGroupType}, pack.Tag{101, pack.EndGroupType},
917 pack.Tag{102, pack.StartGroupType},
918 pack.Tag{101, pack.VarintType}, pack.Bool(false),
919 pack.Tag{102, pack.BytesType}, pack.String("inside a group"),
920 pack.Tag{102, pack.EndGroupType},
921 }.Marshal(),
922 },
923 want: `101: {}
924102: {
925 101: 0
926 102: "inside a group"
927}
928`,
929 }, {
930 desc: "unknown unpack repeated field",
931 input: &pb2.Scalars{
932 XXX_unrecognized: pack.Message{
933 pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false), pack.Bool(true)},
934 pack.Tag{102, pack.BytesType}, pack.String("hello"),
935 pack.Tag{101, pack.VarintType}, pack.Bool(true),
936 pack.Tag{102, pack.BytesType}, pack.String("世界"),
937 }.Marshal(),
938 },
939 want: `101: "\x01\x00\x01"
940101: 1
941102: "hello"
942102: "世界"
943`,
Herbie Ongcf253082018-12-17 17:13:07 -0800944 }, {
945 desc: "extensions of non-repeated fields",
946 input: func() proto.Message {
947 m := &pb2.Extensions{
948 OptString: scalar.String("non-extension field"),
949 OptBool: scalar.Bool(true),
950 OptInt32: scalar.Int32(42),
951 }
952 setExtension(m, pb2.E_OptExtBool, true)
953 setExtension(m, pb2.E_OptExtString, "extension field")
Herbie Ong8170d692019-02-13 14:13:21 -0800954 setExtension(m, pb2.E_OptExtEnum, pb2.Enum_TEN)
Herbie Ongcf253082018-12-17 17:13:07 -0800955 setExtension(m, pb2.E_OptExtNested, &pb2.Nested{
956 OptString: scalar.String("nested in an extension"),
957 OptNested: &pb2.Nested{
958 OptString: scalar.String("another nested in an extension"),
959 },
960 })
961 return m
962 }(),
963 want: `opt_string: "non-extension field"
964opt_bool: true
965opt_int32: 42
966[pb2.opt_ext_bool]: true
Herbie Ong8170d692019-02-13 14:13:21 -0800967[pb2.opt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -0800968[pb2.opt_ext_nested]: {
969 opt_string: "nested in an extension"
970 opt_nested: {
971 opt_string: "another nested in an extension"
972 }
973}
974[pb2.opt_ext_string]: "extension field"
975`,
976 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700977 desc: "extension field contains invalid UTF-8",
978 input: func() proto.Message {
979 m := &pb2.Extensions{}
980 setExtension(m, pb2.E_OptExtString, "abc\xff")
981 return m
982 }(),
983 want: `[pb2.opt_ext_string]: "abc\xff"
984`,
985 wantErr: true,
986 }, {
Herbie Ong09b28a92019-04-03 15:42:41 -0700987 desc: "extension partial returns error",
988 input: func() proto.Message {
989 m := &pb2.Extensions{}
990 setExtension(m, pb2.E_OptExtPartial, &pb2.PartialRequired{
991 OptString: scalar.String("partial1"),
992 })
993 setExtension(m, pb2.E_ExtensionsContainer_OptExtPartial, &pb2.PartialRequired{
994 OptString: scalar.String("partial2"),
995 })
996 return m
997 }(),
998 want: `[pb2.ExtensionsContainer.opt_ext_partial]: {
999 opt_string: "partial2"
1000}
1001[pb2.opt_ext_partial]: {
1002 opt_string: "partial1"
1003}
1004`,
1005 wantErr: true,
1006 }, {
1007 desc: "extension partial with AllowPartial",
1008 mo: textpb.MarshalOptions{AllowPartial: true},
1009 input: func() proto.Message {
1010 m := &pb2.Extensions{}
1011 setExtension(m, pb2.E_OptExtPartial, &pb2.PartialRequired{
1012 OptString: scalar.String("partial1"),
1013 })
1014 return m
1015 }(),
1016 want: `[pb2.opt_ext_partial]: {
1017 opt_string: "partial1"
1018}
1019`,
1020 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001021 desc: "extension message field set to nil",
Herbie Ongcf253082018-12-17 17:13:07 -08001022 input: func() proto.Message {
1023 m := &pb2.Extensions{}
1024 setExtension(m, pb2.E_OptExtNested, nil)
1025 return m
1026 }(),
1027 want: "\n",
1028 }, {
1029 desc: "extensions of repeated fields",
1030 input: func() proto.Message {
1031 m := &pb2.Extensions{}
Herbie Ong8170d692019-02-13 14:13:21 -08001032 setExtension(m, pb2.E_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
Herbie Ongcf253082018-12-17 17:13:07 -08001033 setExtension(m, pb2.E_RptExtFixed32, &[]uint32{42, 47})
1034 setExtension(m, pb2.E_RptExtNested, &[]*pb2.Nested{
1035 &pb2.Nested{OptString: scalar.String("one")},
1036 &pb2.Nested{OptString: scalar.String("two")},
1037 &pb2.Nested{OptString: scalar.String("three")},
1038 })
1039 return m
1040 }(),
Herbie Ong8170d692019-02-13 14:13:21 -08001041 want: `[pb2.rpt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -08001042[pb2.rpt_ext_enum]: 101
Herbie Ong8170d692019-02-13 14:13:21 -08001043[pb2.rpt_ext_enum]: ONE
Herbie Ongcf253082018-12-17 17:13:07 -08001044[pb2.rpt_ext_fixed32]: 42
1045[pb2.rpt_ext_fixed32]: 47
1046[pb2.rpt_ext_nested]: {
1047 opt_string: "one"
1048}
1049[pb2.rpt_ext_nested]: {
1050 opt_string: "two"
1051}
1052[pb2.rpt_ext_nested]: {
1053 opt_string: "three"
1054}
1055`,
1056 }, {
1057 desc: "extensions of non-repeated fields in another message",
1058 input: func() proto.Message {
1059 m := &pb2.Extensions{}
1060 setExtension(m, pb2.E_ExtensionsContainer_OptExtBool, true)
1061 setExtension(m, pb2.E_ExtensionsContainer_OptExtString, "extension field")
Herbie Ong8170d692019-02-13 14:13:21 -08001062 setExtension(m, pb2.E_ExtensionsContainer_OptExtEnum, pb2.Enum_TEN)
Herbie Ongcf253082018-12-17 17:13:07 -08001063 setExtension(m, pb2.E_ExtensionsContainer_OptExtNested, &pb2.Nested{
1064 OptString: scalar.String("nested in an extension"),
1065 OptNested: &pb2.Nested{
1066 OptString: scalar.String("another nested in an extension"),
1067 },
1068 })
1069 return m
1070 }(),
1071 want: `[pb2.ExtensionsContainer.opt_ext_bool]: true
Herbie Ong8170d692019-02-13 14:13:21 -08001072[pb2.ExtensionsContainer.opt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -08001073[pb2.ExtensionsContainer.opt_ext_nested]: {
1074 opt_string: "nested in an extension"
1075 opt_nested: {
1076 opt_string: "another nested in an extension"
1077 }
1078}
1079[pb2.ExtensionsContainer.opt_ext_string]: "extension field"
1080`,
1081 }, {
1082 desc: "extensions of repeated fields in another message",
1083 input: func() proto.Message {
1084 m := &pb2.Extensions{
1085 OptString: scalar.String("non-extension field"),
1086 OptBool: scalar.Bool(true),
1087 OptInt32: scalar.Int32(42),
1088 }
Herbie Ong8170d692019-02-13 14:13:21 -08001089 setExtension(m, pb2.E_ExtensionsContainer_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
Herbie Ongcf253082018-12-17 17:13:07 -08001090 setExtension(m, pb2.E_ExtensionsContainer_RptExtString, &[]string{"hello", "world"})
1091 setExtension(m, pb2.E_ExtensionsContainer_RptExtNested, &[]*pb2.Nested{
1092 &pb2.Nested{OptString: scalar.String("one")},
1093 &pb2.Nested{OptString: scalar.String("two")},
1094 &pb2.Nested{OptString: scalar.String("three")},
1095 })
1096 return m
1097 }(),
1098 want: `opt_string: "non-extension field"
1099opt_bool: true
1100opt_int32: 42
Herbie Ong8170d692019-02-13 14:13:21 -08001101[pb2.ExtensionsContainer.rpt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -08001102[pb2.ExtensionsContainer.rpt_ext_enum]: 101
Herbie Ong8170d692019-02-13 14:13:21 -08001103[pb2.ExtensionsContainer.rpt_ext_enum]: ONE
Herbie Ongcf253082018-12-17 17:13:07 -08001104[pb2.ExtensionsContainer.rpt_ext_nested]: {
1105 opt_string: "one"
1106}
1107[pb2.ExtensionsContainer.rpt_ext_nested]: {
1108 opt_string: "two"
1109}
1110[pb2.ExtensionsContainer.rpt_ext_nested]: {
1111 opt_string: "three"
1112}
1113[pb2.ExtensionsContainer.rpt_ext_string]: "hello"
1114[pb2.ExtensionsContainer.rpt_ext_string]: "world"
1115`,
Herbie Ong6470ea62019-01-07 18:56:57 -08001116 }, {
1117 desc: "MessageSet",
1118 input: func() proto.Message {
1119 m := &pb2.MessageSet{}
1120 setExtension(m, pb2.E_MessageSetExtension_MessageSetExtension, &pb2.MessageSetExtension{
1121 OptString: scalar.String("a messageset extension"),
1122 })
1123 setExtension(m, pb2.E_MessageSetExtension_NotMessageSetExtension, &pb2.MessageSetExtension{
1124 OptString: scalar.String("not a messageset extension"),
1125 })
1126 setExtension(m, pb2.E_MessageSetExtension_ExtNested, &pb2.Nested{
1127 OptString: scalar.String("just a regular extension"),
1128 })
1129 return m
1130 }(),
1131 want: `[pb2.MessageSetExtension]: {
1132 opt_string: "a messageset extension"
1133}
1134[pb2.MessageSetExtension.ext_nested]: {
1135 opt_string: "just a regular extension"
1136}
1137[pb2.MessageSetExtension.not_message_set_extension]: {
1138 opt_string: "not a messageset extension"
1139}
1140`,
1141 }, {
1142 desc: "not real MessageSet 1",
1143 input: func() proto.Message {
1144 m := &pb2.FakeMessageSet{}
1145 setExtension(m, pb2.E_FakeMessageSetExtension_MessageSetExtension, &pb2.FakeMessageSetExtension{
1146 OptString: scalar.String("not a messageset extension"),
1147 })
1148 return m
1149 }(),
1150 want: `[pb2.FakeMessageSetExtension.message_set_extension]: {
1151 opt_string: "not a messageset extension"
1152}
1153`,
1154 }, {
1155 desc: "not real MessageSet 2",
1156 input: func() proto.Message {
1157 m := &pb2.MessageSet{}
1158 setExtension(m, pb2.E_MessageSetExtension, &pb2.FakeMessageSetExtension{
1159 OptString: scalar.String("another not a messageset extension"),
1160 })
1161 return m
1162 }(),
1163 want: `[pb2.message_set_extension]: {
1164 opt_string: "another not a messageset extension"
1165}
1166`,
Herbie Ongf42b55f2019-01-02 15:46:07 -08001167 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001168 desc: "Any not expanded",
Herbie Ong66c365c2019-01-04 14:08:41 -08001169 mo: textpb.MarshalOptions{
1170 Resolver: preg.NewTypes(),
1171 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001172 input: func() proto.Message {
1173 m := &pb2.Nested{
1174 OptString: scalar.String("embedded inside Any"),
1175 OptNested: &pb2.Nested{
1176 OptString: scalar.String("inception"),
1177 },
1178 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -07001179 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ongf42b55f2019-01-02 15:46:07 -08001180 if err != nil {
1181 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1182 }
Herbie Ong300cff02019-03-20 18:05:16 -07001183 return &knownpb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001184 TypeUrl: "pb2.Nested",
Herbie Ongf42b55f2019-01-02 15:46:07 -08001185 Value: b,
Herbie Ong300cff02019-03-20 18:05:16 -07001186 }
Herbie Ongf42b55f2019-01-02 15:46:07 -08001187 }(),
1188 want: `type_url: "pb2.Nested"
1189value: "\n\x13embedded inside Any\x12\x0b\n\tinception"
1190`,
1191 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001192 desc: "Any expanded",
Herbie Ong66c365c2019-01-04 14:08:41 -08001193 mo: textpb.MarshalOptions{
1194 Resolver: preg.NewTypes((&pb2.Nested{}).ProtoReflect().Type()),
1195 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001196 input: func() proto.Message {
1197 m := &pb2.Nested{
1198 OptString: scalar.String("embedded inside Any"),
1199 OptNested: &pb2.Nested{
1200 OptString: scalar.String("inception"),
1201 },
1202 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -07001203 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ongf42b55f2019-01-02 15:46:07 -08001204 if err != nil {
1205 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1206 }
Herbie Ong300cff02019-03-20 18:05:16 -07001207 return &knownpb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001208 TypeUrl: "foo/pb2.Nested",
Herbie Ongf42b55f2019-01-02 15:46:07 -08001209 Value: b,
Herbie Ong300cff02019-03-20 18:05:16 -07001210 }
Herbie Ongf42b55f2019-01-02 15:46:07 -08001211 }(),
Herbie Ong66c365c2019-01-04 14:08:41 -08001212 want: `[foo/pb2.Nested]: {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001213 opt_string: "embedded inside Any"
1214 opt_nested: {
1215 opt_string: "inception"
1216 }
1217}
1218`,
1219 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001220 desc: "Any expanded with missing required error",
Herbie Ong66c365c2019-01-04 14:08:41 -08001221 mo: textpb.MarshalOptions{
1222 Resolver: preg.NewTypes((&pb2.PartialRequired{}).ProtoReflect().Type()),
1223 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001224 input: func() proto.Message {
1225 m := &pb2.PartialRequired{
1226 OptString: scalar.String("embedded inside Any"),
1227 }
Damien Neil96c229a2019-04-03 12:17:24 -07001228 b, err := proto.MarshalOptions{
1229 AllowPartial: true,
1230 Deterministic: true,
1231 }.Marshal(m)
Herbie Ong300cff02019-03-20 18:05:16 -07001232 if err != nil {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001233 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1234 }
Herbie Ong300cff02019-03-20 18:05:16 -07001235 return &knownpb.Any{
Herbie Ongf42b55f2019-01-02 15:46:07 -08001236 TypeUrl: string(m.ProtoReflect().Type().FullName()),
1237 Value: b,
Herbie Ong300cff02019-03-20 18:05:16 -07001238 }
Herbie Ongf42b55f2019-01-02 15:46:07 -08001239 }(),
1240 want: `[pb2.PartialRequired]: {
1241 opt_string: "embedded inside Any"
1242}
1243`,
1244 wantErr: true,
1245 }, {
Herbie Ong21a39742019-04-08 17:32:44 -07001246 desc: "Any with invalid UTF-8",
1247 mo: textpb.MarshalOptions{
1248 Resolver: preg.NewTypes((&pb3.Nested{}).ProtoReflect().Type()),
1249 },
1250 input: func() proto.Message {
1251 m := &pb3.Nested{
Damien Neilbc310b52019-04-11 11:46:55 -07001252 SString: "abcd",
Herbie Ong21a39742019-04-08 17:32:44 -07001253 }
1254 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
1255 if err != nil {
1256 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1257 }
1258 return &knownpb.Any{
1259 TypeUrl: string(m.ProtoReflect().Type().FullName()),
Damien Neilbc310b52019-04-11 11:46:55 -07001260 Value: bytes.Replace(b, []byte("abcd"), []byte("abc\xff"), -1),
Herbie Ong21a39742019-04-08 17:32:44 -07001261 }
1262 }(),
1263 want: `[pb3.Nested]: {
1264 s_string: "abc\xff"
1265}
1266`,
1267 wantErr: true,
1268 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001269 desc: "Any with invalid value",
Herbie Ong66c365c2019-01-04 14:08:41 -08001270 mo: textpb.MarshalOptions{
1271 Resolver: preg.NewTypes((&pb2.Nested{}).ProtoReflect().Type()),
1272 },
Herbie Ong300cff02019-03-20 18:05:16 -07001273 input: &knownpb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001274 TypeUrl: "foo/pb2.Nested",
1275 Value: dhex("80"),
Herbie Ong300cff02019-03-20 18:05:16 -07001276 },
Herbie Ong66c365c2019-01-04 14:08:41 -08001277 want: `type_url: "foo/pb2.Nested"
Herbie Onga94f78c2019-01-03 15:39:58 -08001278value: "\x80"
1279`,
Herbie Ongcddf8192018-11-28 18:25:20 -08001280 }}
1281
1282 for _, tt := range tests {
1283 tt := tt
1284 t.Run(tt.desc, func(t *testing.T) {
Herbie Ong3a385912019-03-20 14:04:24 -07001285 // Use 2-space indentation on all MarshalOptions.
1286 tt.mo.Indent = " "
Herbie Ongf42b55f2019-01-02 15:46:07 -08001287 b, err := tt.mo.Marshal(tt.input)
Herbie Ongcddf8192018-11-28 18:25:20 -08001288 if err != nil && !tt.wantErr {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001289 t.Errorf("Marshal() returned error: %v\n", err)
Herbie Ongcddf8192018-11-28 18:25:20 -08001290 }
Herbie Ong800c9902018-12-06 15:28:53 -08001291 if err == nil && tt.wantErr {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001292 t.Error("Marshal() got nil error, want error\n")
Herbie Ongcddf8192018-11-28 18:25:20 -08001293 }
Herbie Ong800c9902018-12-06 15:28:53 -08001294 got := string(b)
1295 if tt.want != "" && got != tt.want {
1296 t.Errorf("Marshal()\n<got>\n%v\n<want>\n%v\n", got, tt.want)
1297 if diff := cmp.Diff(tt.want, got, splitLines); diff != "" {
Herbie Ongcddf8192018-11-28 18:25:20 -08001298 t.Errorf("Marshal() diff -want +got\n%v\n", diff)
1299 }
1300 }
1301 })
1302 }
1303}