blob: 3397d660d359a0ded20f9e4902e8c44ea91aaecb [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 (
Herbie Onga94f78c2019-01-03 15:39:58 -08008 "encoding/hex"
Herbie Ongcddf8192018-11-28 18:25:20 -08009 "math"
10 "strings"
11 "testing"
12
13 "github.com/golang/protobuf/v2/encoding/textpb"
Herbie Ongcddf8192018-11-28 18:25:20 -080014 "github.com/golang/protobuf/v2/internal/detrand"
Herbie Ong20a1d312018-12-11 21:08:58 -080015 "github.com/golang/protobuf/v2/internal/encoding/pack"
Herbie Ongcf253082018-12-17 17:13:07 -080016 "github.com/golang/protobuf/v2/internal/encoding/wire"
Herbie Ongcddf8192018-11-28 18:25:20 -080017 "github.com/golang/protobuf/v2/internal/scalar"
18 "github.com/golang/protobuf/v2/proto"
Herbie Ongf42b55f2019-01-02 15:46:07 -080019 preg "github.com/golang/protobuf/v2/reflect/protoregistry"
Joe Tsai4fddeba2019-03-20 18:29:32 -070020 "github.com/golang/protobuf/v2/runtime/protoiface"
Herbie Ongcddf8192018-11-28 18:25:20 -080021 "github.com/google/go-cmp/cmp"
22 "github.com/google/go-cmp/cmp/cmpopts"
23
Herbie Ong8170d692019-02-13 14:13:21 -080024 "github.com/golang/protobuf/v2/encoding/testprotos/pb2"
25 "github.com/golang/protobuf/v2/encoding/testprotos/pb3"
Joe Tsai19058432019-02-27 21:46:29 -080026 knownpb "github.com/golang/protobuf/v2/types/known"
Herbie Ongcddf8192018-11-28 18:25:20 -080027)
28
29func init() {
30 // Disable detrand to enable direct comparisons on outputs.
31 detrand.Disable()
32}
33
Herbie Ongcddf8192018-11-28 18:25:20 -080034// splitLines is a cmpopts.Option for comparing strings with line breaks.
35var splitLines = cmpopts.AcyclicTransformer("SplitLines", func(s string) []string {
36 return strings.Split(s, "\n")
37})
38
Herbie Ong800c9902018-12-06 15:28:53 -080039func pb2Enum(i int32) *pb2.Enum {
40 p := new(pb2.Enum)
41 *p = pb2.Enum(i)
42 return p
43}
44
45func pb2Enums_NestedEnum(i int32) *pb2.Enums_NestedEnum {
46 p := new(pb2.Enums_NestedEnum)
47 *p = pb2.Enums_NestedEnum(i)
48 return p
49}
50
Joe Tsai4fddeba2019-03-20 18:29:32 -070051func setExtension(m proto.Message, xd *protoiface.ExtensionDescV1, val interface{}) {
Herbie Ongcf253082018-12-17 17:13:07 -080052 knownFields := m.ProtoReflect().KnownFields()
53 extTypes := knownFields.ExtensionTypes()
Joe Tsaiafb455e2019-03-14 16:08:22 -070054 extTypes.Register(xd.Type)
Herbie Ongcf253082018-12-17 17:13:07 -080055 if val == nil {
56 return
57 }
Joe Tsaiafb455e2019-03-14 16:08:22 -070058 pval := xd.Type.ValueOf(val)
Herbie Ongcf253082018-12-17 17:13:07 -080059 knownFields.Set(wire.Number(xd.Field), pval)
60}
61
Herbie Onga94f78c2019-01-03 15:39:58 -080062// dhex decodes a hex-string and returns the bytes and panics if s is invalid.
63func dhex(s string) []byte {
64 b, err := hex.DecodeString(s)
65 if err != nil {
66 panic(err)
67 }
68 return b
69}
70
Herbie Ongcddf8192018-11-28 18:25:20 -080071func TestMarshal(t *testing.T) {
72 tests := []struct {
73 desc string
Herbie Ongf42b55f2019-01-02 15:46:07 -080074 mo textpb.MarshalOptions
Herbie Ong70651952018-12-13 14:19:50 -080075 input proto.Message
Herbie Ongcddf8192018-11-28 18:25:20 -080076 want string
Herbie Ong300cff02019-03-20 18:05:16 -070077 wantErr bool // TODO: Verify error message content.
Herbie Ongcddf8192018-11-28 18:25:20 -080078 }{{
Herbie Ong8170d692019-02-13 14:13:21 -080079 desc: "proto2 optional scalars not set",
Herbie Ong800c9902018-12-06 15:28:53 -080080 input: &pb2.Scalars{},
Herbie Ongcddf8192018-11-28 18:25:20 -080081 want: "\n",
82 }, {
Herbie Ong8170d692019-02-13 14:13:21 -080083 desc: "proto3 scalars not set",
Herbie Ong800c9902018-12-06 15:28:53 -080084 input: &pb3.Scalars{},
Herbie Ongcddf8192018-11-28 18:25:20 -080085 want: "\n",
86 }, {
Herbie Ong8170d692019-02-13 14:13:21 -080087 desc: "proto2 optional scalars set to zero values",
Herbie Ong800c9902018-12-06 15:28:53 -080088 input: &pb2.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -080089 OptBool: scalar.Bool(false),
90 OptInt32: scalar.Int32(0),
91 OptInt64: scalar.Int64(0),
92 OptUint32: scalar.Uint32(0),
93 OptUint64: scalar.Uint64(0),
94 OptSint32: scalar.Int32(0),
95 OptSint64: scalar.Int64(0),
96 OptFixed32: scalar.Uint32(0),
97 OptFixed64: scalar.Uint64(0),
98 OptSfixed32: scalar.Int32(0),
99 OptSfixed64: scalar.Int64(0),
100 OptFloat: scalar.Float32(0),
101 OptDouble: scalar.Float64(0),
102 OptBytes: []byte{},
103 OptString: scalar.String(""),
Herbie Ong800c9902018-12-06 15:28:53 -0800104 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800105 want: `opt_bool: false
106opt_int32: 0
107opt_int64: 0
108opt_uint32: 0
109opt_uint64: 0
110opt_sint32: 0
111opt_sint64: 0
112opt_fixed32: 0
113opt_fixed64: 0
114opt_sfixed32: 0
115opt_sfixed64: 0
116opt_float: 0
117opt_double: 0
118opt_bytes: ""
119opt_string: ""
120`,
121 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800122 desc: "proto3 scalars set to zero values",
Herbie Ong800c9902018-12-06 15:28:53 -0800123 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800124 SBool: false,
125 SInt32: 0,
126 SInt64: 0,
127 SUint32: 0,
128 SUint64: 0,
129 SSint32: 0,
130 SSint64: 0,
131 SFixed32: 0,
132 SFixed64: 0,
133 SSfixed32: 0,
134 SSfixed64: 0,
135 SFloat: 0,
136 SDouble: 0,
137 SBytes: []byte{},
138 SString: "",
Herbie Ong800c9902018-12-06 15:28:53 -0800139 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800140 want: "\n",
141 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800142 desc: "proto2 optional scalars set to some values",
Herbie Ong800c9902018-12-06 15:28:53 -0800143 input: &pb2.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800144 OptBool: scalar.Bool(true),
145 OptInt32: scalar.Int32(0xff),
146 OptInt64: scalar.Int64(0xdeadbeef),
147 OptUint32: scalar.Uint32(47),
148 OptUint64: scalar.Uint64(0xdeadbeef),
149 OptSint32: scalar.Int32(-1001),
150 OptSint64: scalar.Int64(-0xffff),
151 OptFixed64: scalar.Uint64(64),
152 OptSfixed32: scalar.Int32(-32),
Herbie Ong84f09602019-01-17 19:31:47 -0800153 OptFloat: scalar.Float32(1.02),
154 OptDouble: scalar.Float64(1.0199999809265137),
Herbie Ong8170d692019-02-13 14:13:21 -0800155 OptBytes: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
156 OptString: scalar.String("谷歌"),
Herbie Ong800c9902018-12-06 15:28:53 -0800157 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800158 want: `opt_bool: true
159opt_int32: 255
160opt_int64: 3735928559
161opt_uint32: 47
162opt_uint64: 3735928559
163opt_sint32: -1001
164opt_sint64: -65535
165opt_fixed64: 64
166opt_sfixed32: -32
Herbie Ong84f09602019-01-17 19:31:47 -0800167opt_float: 1.02
168opt_double: 1.0199999809265137
Herbie Ongcddf8192018-11-28 18:25:20 -0800169opt_bytes: "谷歌"
170opt_string: "谷歌"
171`,
172 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700173 desc: "string with invalid UTF-8",
174 input: &pb3.Scalars{
175 SString: "abc\xff",
176 },
177 want: `s_string: "abc\xff"
178`,
179 wantErr: true,
180 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800181 desc: "float nan",
Herbie Ong800c9902018-12-06 15:28:53 -0800182 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800183 SFloat: float32(math.NaN()),
Herbie Ong800c9902018-12-06 15:28:53 -0800184 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800185 want: "s_float: nan\n",
186 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800187 desc: "float positive infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800188 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800189 SFloat: float32(math.Inf(1)),
Herbie Ong800c9902018-12-06 15:28:53 -0800190 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800191 want: "s_float: inf\n",
192 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800193 desc: "float negative infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800194 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800195 SFloat: float32(math.Inf(-1)),
Herbie Ong800c9902018-12-06 15:28:53 -0800196 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800197 want: "s_float: -inf\n",
198 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800199 desc: "double nan",
Herbie Ong800c9902018-12-06 15:28:53 -0800200 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800201 SDouble: math.NaN(),
Herbie Ong800c9902018-12-06 15:28:53 -0800202 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800203 want: "s_double: nan\n",
204 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800205 desc: "double positive infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800206 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800207 SDouble: math.Inf(1),
Herbie Ong800c9902018-12-06 15:28:53 -0800208 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800209 want: "s_double: inf\n",
210 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800211 desc: "double negative infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800212 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800213 SDouble: math.Inf(-1),
Herbie Ong800c9902018-12-06 15:28:53 -0800214 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800215 want: "s_double: -inf\n",
216 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800217 desc: "proto2 enum not set",
218 input: &pb2.Enums{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800219 want: "\n",
220 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800221 desc: "proto2 enum set to zero value",
222 input: &pb2.Enums{
Herbie Ong8170d692019-02-13 14:13:21 -0800223 OptEnum: pb2Enum(0),
Herbie Ong800c9902018-12-06 15:28:53 -0800224 OptNestedEnum: pb2Enums_NestedEnum(0),
225 },
Herbie Ong8170d692019-02-13 14:13:21 -0800226 want: `opt_enum: 0
Herbie Ong800c9902018-12-06 15:28:53 -0800227opt_nested_enum: 0
228`,
229 }, {
230 desc: "proto2 enum",
231 input: &pb2.Enums{
Herbie Ong8170d692019-02-13 14:13:21 -0800232 OptEnum: pb2.Enum_ONE.Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800233 OptNestedEnum: pb2.Enums_UNO.Enum(),
234 },
Herbie Ong8170d692019-02-13 14:13:21 -0800235 want: `opt_enum: ONE
Herbie Ong800c9902018-12-06 15:28:53 -0800236opt_nested_enum: UNO
237`,
238 }, {
239 desc: "proto2 enum set to numeric values",
240 input: &pb2.Enums{
Herbie Ong8170d692019-02-13 14:13:21 -0800241 OptEnum: pb2Enum(2),
Herbie Ong800c9902018-12-06 15:28:53 -0800242 OptNestedEnum: pb2Enums_NestedEnum(2),
243 },
Herbie Ong8170d692019-02-13 14:13:21 -0800244 want: `opt_enum: TWO
Herbie Ong800c9902018-12-06 15:28:53 -0800245opt_nested_enum: DOS
246`,
247 }, {
248 desc: "proto2 enum set to unnamed numeric values",
249 input: &pb2.Enums{
250 OptEnum: pb2Enum(101),
251 OptNestedEnum: pb2Enums_NestedEnum(-101),
252 },
253 want: `opt_enum: 101
254opt_nested_enum: -101
255`,
256 }, {
257 desc: "proto3 enum not set",
258 input: &pb3.Enums{},
259 want: "\n",
260 }, {
261 desc: "proto3 enum set to zero value",
262 input: &pb3.Enums{
263 SEnum: pb3.Enum_ZERO,
264 SNestedEnum: pb3.Enums_CERO,
265 },
266 want: "\n",
267 }, {
268 desc: "proto3 enum",
269 input: &pb3.Enums{
270 SEnum: pb3.Enum_ONE,
Herbie Ong8170d692019-02-13 14:13:21 -0800271 SNestedEnum: pb3.Enums_UNO,
Herbie Ong800c9902018-12-06 15:28:53 -0800272 },
273 want: `s_enum: ONE
Herbie Ong8170d692019-02-13 14:13:21 -0800274s_nested_enum: UNO
Herbie Ong800c9902018-12-06 15:28:53 -0800275`,
276 }, {
277 desc: "proto3 enum set to numeric values",
278 input: &pb3.Enums{
279 SEnum: 2,
Herbie Ong8170d692019-02-13 14:13:21 -0800280 SNestedEnum: 2,
Herbie Ong800c9902018-12-06 15:28:53 -0800281 },
282 want: `s_enum: TWO
Herbie Ong8170d692019-02-13 14:13:21 -0800283s_nested_enum: DOS
Herbie Ong800c9902018-12-06 15:28:53 -0800284`,
285 }, {
286 desc: "proto3 enum set to unnamed numeric values",
287 input: &pb3.Enums{
288 SEnum: -47,
289 SNestedEnum: 47,
290 },
291 want: `s_enum: -47
292s_nested_enum: 47
293`,
294 }, {
295 desc: "proto2 nested message not set",
296 input: &pb2.Nests{},
297 want: "\n",
298 }, {
299 desc: "proto2 nested message set to empty",
300 input: &pb2.Nests{
301 OptNested: &pb2.Nested{},
302 Optgroup: &pb2.Nests_OptGroup{},
303 },
304 want: `opt_nested: {}
Herbie Ong0dcfb9a2019-01-14 15:32:26 -0800305OptGroup: {}
Herbie Ong800c9902018-12-06 15:28:53 -0800306`,
307 }, {
308 desc: "proto2 nested messages",
309 input: &pb2.Nests{
310 OptNested: &pb2.Nested{
311 OptString: scalar.String("nested message"),
312 OptNested: &pb2.Nested{
313 OptString: scalar.String("another nested message"),
314 },
315 },
316 },
317 want: `opt_nested: {
318 opt_string: "nested message"
319 opt_nested: {
320 opt_string: "another nested message"
321 }
322}
323`,
324 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800325 desc: "proto2 groups",
Herbie Ong800c9902018-12-06 15:28:53 -0800326 input: &pb2.Nests{
327 Optgroup: &pb2.Nests_OptGroup{
Herbie Ong800c9902018-12-06 15:28:53 -0800328 OptString: scalar.String("inside a group"),
329 OptNested: &pb2.Nested{
330 OptString: scalar.String("nested message inside a group"),
331 },
332 Optnestedgroup: &pb2.Nests_OptGroup_OptNestedGroup{
Herbie Ong8170d692019-02-13 14:13:21 -0800333 OptFixed32: scalar.Uint32(47),
Herbie Ong800c9902018-12-06 15:28:53 -0800334 },
335 },
336 },
Herbie Ong0dcfb9a2019-01-14 15:32:26 -0800337 want: `OptGroup: {
Herbie Ong800c9902018-12-06 15:28:53 -0800338 opt_string: "inside a group"
339 opt_nested: {
340 opt_string: "nested message inside a group"
341 }
Herbie Ong0dcfb9a2019-01-14 15:32:26 -0800342 OptNestedGroup: {
Herbie Ong8170d692019-02-13 14:13:21 -0800343 opt_fixed32: 47
Herbie Ong800c9902018-12-06 15:28:53 -0800344 }
345}
346`,
347 }, {
348 desc: "proto3 nested message not set",
349 input: &pb3.Nests{},
350 want: "\n",
351 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800352 desc: "proto3 nested message set to empty",
353 input: &pb3.Nests{
354 SNested: &pb3.Nested{},
355 },
356 want: "s_nested: {}\n",
357 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800358 desc: "proto3 nested message",
359 input: &pb3.Nests{
360 SNested: &pb3.Nested{
361 SString: "nested message",
362 SNested: &pb3.Nested{
363 SString: "another nested message",
364 },
365 },
366 },
367 want: `s_nested: {
368 s_string: "nested message"
369 s_nested: {
370 s_string: "another nested message"
371 }
372}
373`,
374 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700375 desc: "proto3 nested message contains invalid UTF-8",
376 input: &pb3.Nests{
377 SNested: &pb3.Nested{
378 SString: "abc\xff",
379 },
380 },
381 want: `s_nested: {
382 s_string: "abc\xff"
383}
384`,
385 wantErr: true,
386 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800387 desc: "oneof not set",
388 input: &pb3.Oneofs{},
Herbie Ong800c9902018-12-06 15:28:53 -0800389 want: "\n",
390 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800391 desc: "oneof set to empty string",
392 input: &pb3.Oneofs{
393 Union: &pb3.Oneofs_OneofString{},
Herbie Ong800c9902018-12-06 15:28:53 -0800394 },
Herbie Ong8170d692019-02-13 14:13:21 -0800395 want: `oneof_string: ""
396`,
Herbie Ong800c9902018-12-06 15:28:53 -0800397 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800398 desc: "oneof set to string",
399 input: &pb3.Oneofs{
400 Union: &pb3.Oneofs_OneofString{
401 OneofString: "hello",
Herbie Ong800c9902018-12-06 15:28:53 -0800402 },
403 },
Herbie Ong8170d692019-02-13 14:13:21 -0800404 want: `oneof_string: "hello"
405`,
Herbie Ong800c9902018-12-06 15:28:53 -0800406 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800407 desc: "oneof set to enum",
408 input: &pb3.Oneofs{
409 Union: &pb3.Oneofs_OneofEnum{
410 OneofEnum: pb3.Enum_ZERO,
Herbie Ong800c9902018-12-06 15:28:53 -0800411 },
412 },
Herbie Ong8170d692019-02-13 14:13:21 -0800413 want: `oneof_enum: ZERO
414`,
Herbie Ong800c9902018-12-06 15:28:53 -0800415 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800416 desc: "oneof set to empty message",
417 input: &pb3.Oneofs{
418 Union: &pb3.Oneofs_OneofNested{
419 OneofNested: &pb3.Nested{},
420 },
421 },
422 want: "oneof_nested: {}\n",
423 }, {
424 desc: "oneof set to message",
425 input: &pb3.Oneofs{
426 Union: &pb3.Oneofs_OneofNested{
427 OneofNested: &pb3.Nested{
428 SString: "nested message",
Herbie Ong800c9902018-12-06 15:28:53 -0800429 },
430 },
431 },
Herbie Ong8170d692019-02-13 14:13:21 -0800432 want: `oneof_nested: {
433 s_string: "nested message"
Herbie Ong800c9902018-12-06 15:28:53 -0800434}
435`,
436 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800437 desc: "repeated fields not set",
Herbie Ong800c9902018-12-06 15:28:53 -0800438 input: &pb2.Repeats{},
439 want: "\n",
440 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800441 desc: "repeated fields set to empty slices",
Herbie Ong800c9902018-12-06 15:28:53 -0800442 input: &pb2.Repeats{
Herbie Ongcddf8192018-11-28 18:25:20 -0800443 RptBool: []bool{},
444 RptInt32: []int32{},
445 RptInt64: []int64{},
446 RptUint32: []uint32{},
447 RptUint64: []uint64{},
448 RptFloat: []float32{},
449 RptDouble: []float64{},
450 RptBytes: [][]byte{},
Herbie Ong800c9902018-12-06 15:28:53 -0800451 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800452 want: "\n",
453 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800454 desc: "repeated fields set to some values",
Herbie Ong800c9902018-12-06 15:28:53 -0800455 input: &pb2.Repeats{
Herbie Ongcddf8192018-11-28 18:25:20 -0800456 RptBool: []bool{true, false, true, true},
457 RptInt32: []int32{1, 6, 0, 0},
458 RptInt64: []int64{-64, 47},
459 RptUint32: []uint32{0xff, 0xffff},
460 RptUint64: []uint64{0xdeadbeef},
Herbie Ong84f09602019-01-17 19:31:47 -0800461 RptFloat: []float32{float32(math.NaN()), float32(math.Inf(1)), float32(math.Inf(-1)), 1.034},
Herbie Ongcddf8192018-11-28 18:25:20 -0800462 RptDouble: []float64{math.NaN(), math.Inf(1), math.Inf(-1), 1.23e-308},
463 RptString: []string{"hello", "世界"},
464 RptBytes: [][]byte{
465 []byte("hello"),
466 []byte("\xe4\xb8\x96\xe7\x95\x8c"),
467 },
Herbie Ong800c9902018-12-06 15:28:53 -0800468 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800469 want: `rpt_bool: true
470rpt_bool: false
471rpt_bool: true
472rpt_bool: true
473rpt_int32: 1
474rpt_int32: 6
475rpt_int32: 0
476rpt_int32: 0
477rpt_int64: -64
478rpt_int64: 47
479rpt_uint32: 255
480rpt_uint32: 65535
481rpt_uint64: 3735928559
Herbie Ong84f09602019-01-17 19:31:47 -0800482rpt_float: nan
483rpt_float: inf
484rpt_float: -inf
485rpt_float: 1.034
Herbie Ongcddf8192018-11-28 18:25:20 -0800486rpt_double: nan
487rpt_double: inf
488rpt_double: -inf
489rpt_double: 1.23e-308
490rpt_string: "hello"
491rpt_string: "世界"
492rpt_bytes: "hello"
493rpt_bytes: "世界"
494`,
495 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700496 desc: "repeated contains invalid UTF-8",
497 input: &pb2.Repeats{
498 RptString: []string{"abc\xff"},
499 },
500 want: `rpt_string: "abc\xff"
501`,
502 wantErr: true,
503 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800504 desc: "repeated enums",
Herbie Ong800c9902018-12-06 15:28:53 -0800505 input: &pb2.Enums{
Herbie Ong8170d692019-02-13 14:13:21 -0800506 RptEnum: []pb2.Enum{pb2.Enum_ONE, 2, pb2.Enum_TEN, 42},
Herbie Ongcddf8192018-11-28 18:25:20 -0800507 RptNestedEnum: []pb2.Enums_NestedEnum{2, 47, 10},
Herbie Ong800c9902018-12-06 15:28:53 -0800508 },
Herbie Ong8170d692019-02-13 14:13:21 -0800509 want: `rpt_enum: ONE
510rpt_enum: TWO
511rpt_enum: TEN
Herbie Ongcddf8192018-11-28 18:25:20 -0800512rpt_enum: 42
Herbie Ongcddf8192018-11-28 18:25:20 -0800513rpt_nested_enum: DOS
514rpt_nested_enum: 47
515rpt_nested_enum: DIEZ
516`,
517 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800518 desc: "repeated messages set to empty",
Herbie Ong800c9902018-12-06 15:28:53 -0800519 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800520 RptNested: []*pb2.Nested{},
521 Rptgroup: []*pb2.Nests_RptGroup{},
Herbie Ong800c9902018-12-06 15:28:53 -0800522 },
523 want: "\n",
Herbie Ongcddf8192018-11-28 18:25:20 -0800524 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800525 desc: "repeated messages",
Herbie Ong800c9902018-12-06 15:28:53 -0800526 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800527 RptNested: []*pb2.Nested{
528 {
529 OptString: scalar.String("repeat nested one"),
530 },
531 {
532 OptString: scalar.String("repeat nested two"),
533 OptNested: &pb2.Nested{
534 OptString: scalar.String("inside repeat nested two"),
535 },
536 },
537 {},
538 },
Herbie Ong800c9902018-12-06 15:28:53 -0800539 },
540 want: `rpt_nested: {
Herbie Ongcddf8192018-11-28 18:25:20 -0800541 opt_string: "repeat nested one"
542}
543rpt_nested: {
544 opt_string: "repeat nested two"
545 opt_nested: {
546 opt_string: "inside repeat nested two"
547 }
548}
549rpt_nested: {}
550`,
551 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800552 desc: "repeated messages contains nil value",
Herbie Ongf5db2df2019-02-07 20:17:45 -0800553 input: &pb2.Nests{
554 RptNested: []*pb2.Nested{nil, {}},
555 },
556 want: `rpt_nested: {}
557rpt_nested: {}
558`,
559 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800560 desc: "repeated groups",
Herbie Ong800c9902018-12-06 15:28:53 -0800561 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800562 Rptgroup: []*pb2.Nests_RptGroup{
563 {
Herbie Ong8170d692019-02-13 14:13:21 -0800564 RptString: []string{"hello", "world"},
Herbie Ongcddf8192018-11-28 18:25:20 -0800565 },
566 {},
Herbie Ong8170d692019-02-13 14:13:21 -0800567 nil,
Herbie Ongcddf8192018-11-28 18:25:20 -0800568 },
Herbie Ong800c9902018-12-06 15:28:53 -0800569 },
Herbie Ongde7313b2019-01-14 19:26:50 -0800570 want: `RptGroup: {
Herbie Ong8170d692019-02-13 14:13:21 -0800571 rpt_string: "hello"
572 rpt_string: "world"
Herbie Ongcddf8192018-11-28 18:25:20 -0800573}
Herbie Ongde7313b2019-01-14 19:26:50 -0800574RptGroup: {}
Herbie Ong8170d692019-02-13 14:13:21 -0800575RptGroup: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800576`,
577 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800578 desc: "map fields not set",
579 input: &pb3.Maps{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800580 want: "\n",
581 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800582 desc: "map fields set to empty",
583 input: &pb3.Maps{
584 Int32ToStr: map[int32]string{},
585 BoolToUint32: map[bool]uint32{},
586 Uint64ToEnum: map[uint64]pb3.Enum{},
587 StrToNested: map[string]*pb3.Nested{},
588 StrToOneofs: map[string]*pb3.Oneofs{},
Herbie Ong800c9902018-12-06 15:28:53 -0800589 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800590 want: "\n",
591 }, {
592 desc: "map fields 1",
Herbie Ong8170d692019-02-13 14:13:21 -0800593 input: &pb3.Maps{
Herbie Ongcddf8192018-11-28 18:25:20 -0800594 Int32ToStr: map[int32]string{
595 -101: "-101",
596 0xff: "0xff",
597 0: "zero",
598 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800599 BoolToUint32: map[bool]uint32{
600 true: 42,
601 false: 101,
602 },
Herbie Ong800c9902018-12-06 15:28:53 -0800603 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800604 want: `int32_to_str: {
605 key: -101
606 value: "-101"
607}
608int32_to_str: {
609 key: 0
610 value: "zero"
611}
612int32_to_str: {
613 key: 255
614 value: "0xff"
615}
Herbie Ongcddf8192018-11-28 18:25:20 -0800616bool_to_uint32: {
617 key: false
618 value: 101
619}
620bool_to_uint32: {
621 key: true
622 value: 42
623}
624`,
625 }, {
626 desc: "map fields 2",
Herbie Ong8170d692019-02-13 14:13:21 -0800627 input: &pb3.Maps{
628 Uint64ToEnum: map[uint64]pb3.Enum{
629 1: pb3.Enum_ONE,
630 2: pb3.Enum_TWO,
631 10: pb3.Enum_TEN,
632 47: 47,
Herbie Ongcddf8192018-11-28 18:25:20 -0800633 },
Herbie Ong800c9902018-12-06 15:28:53 -0800634 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800635 want: `uint64_to_enum: {
636 key: 1
Herbie Ong8170d692019-02-13 14:13:21 -0800637 value: ONE
Herbie Ongcddf8192018-11-28 18:25:20 -0800638}
639uint64_to_enum: {
640 key: 2
Herbie Ong8170d692019-02-13 14:13:21 -0800641 value: TWO
Herbie Ongcddf8192018-11-28 18:25:20 -0800642}
643uint64_to_enum: {
644 key: 10
Herbie Ong8170d692019-02-13 14:13:21 -0800645 value: TEN
646}
647uint64_to_enum: {
648 key: 47
649 value: 47
Herbie Ongcddf8192018-11-28 18:25:20 -0800650}
651`,
652 }, {
653 desc: "map fields 3",
Herbie Ong8170d692019-02-13 14:13:21 -0800654 input: &pb3.Maps{
655 StrToNested: map[string]*pb3.Nested{
656 "nested": &pb3.Nested{
657 SString: "nested in a map",
Herbie Ongcddf8192018-11-28 18:25:20 -0800658 },
659 },
Herbie Ong800c9902018-12-06 15:28:53 -0800660 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800661 want: `str_to_nested: {
Herbie Ong8170d692019-02-13 14:13:21 -0800662 key: "nested"
Herbie Ongcddf8192018-11-28 18:25:20 -0800663 value: {
Herbie Ong8170d692019-02-13 14:13:21 -0800664 s_string: "nested in a map"
Herbie Ongcddf8192018-11-28 18:25:20 -0800665 }
666}
667`,
668 }, {
669 desc: "map fields 4",
Herbie Ong8170d692019-02-13 14:13:21 -0800670 input: &pb3.Maps{
671 StrToOneofs: map[string]*pb3.Oneofs{
672 "string": &pb3.Oneofs{
673 Union: &pb3.Oneofs_OneofString{
674 OneofString: "hello",
Herbie Ongcddf8192018-11-28 18:25:20 -0800675 },
676 },
Herbie Ong8170d692019-02-13 14:13:21 -0800677 "nested": &pb3.Oneofs{
678 Union: &pb3.Oneofs_OneofNested{
679 OneofNested: &pb3.Nested{
680 SString: "nested oneof in map field value",
Herbie Ongcddf8192018-11-28 18:25:20 -0800681 },
682 },
683 },
684 },
Herbie Ong800c9902018-12-06 15:28:53 -0800685 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800686 want: `str_to_oneofs: {
687 key: "nested"
688 value: {
Herbie Ong8170d692019-02-13 14:13:21 -0800689 oneof_nested: {
690 s_string: "nested oneof in map field value"
Herbie Ongcddf8192018-11-28 18:25:20 -0800691 }
692 }
693}
694str_to_oneofs: {
695 key: "string"
696 value: {
Herbie Ong8170d692019-02-13 14:13:21 -0800697 oneof_string: "hello"
Herbie Ongcddf8192018-11-28 18:25:20 -0800698 }
699}
700`,
701 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700702 desc: "map field value contains invalid UTF-8",
703 input: &pb3.Maps{
704 Int32ToStr: map[int32]string{
705 101: "abc\xff",
706 },
707 },
708 want: `int32_to_str: {
709 key: 101
710 value: "abc\xff"
711}
712`,
713 wantErr: true,
714 }, {
715 desc: "map field key contains invalid UTF-8",
716 input: &pb3.Maps{
717 StrToNested: map[string]*pb3.Nested{
718 "abc\xff": {},
719 },
720 },
721 want: `str_to_nested: {
722 key: "abc\xff"
723 value: {}
724}
725`,
726 wantErr: true,
727 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800728 desc: "map field contains nil value",
729 input: &pb3.Maps{
730 StrToNested: map[string]*pb3.Nested{
Herbie Ongf5db2df2019-02-07 20:17:45 -0800731 "nil": nil,
732 },
733 },
734 want: `str_to_nested: {
735 key: "nil"
736 value: {}
737}
738`,
739 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700740 desc: "required fields not set",
Herbie Ong800c9902018-12-06 15:28:53 -0800741 input: &pb2.Requireds{},
742 want: "\n",
743 wantErr: true,
Herbie Ongcddf8192018-11-28 18:25:20 -0800744 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700745 desc: "required fields partially set",
Herbie Ong800c9902018-12-06 15:28:53 -0800746 input: &pb2.Requireds{
747 ReqBool: scalar.Bool(false),
Herbie Ong800c9902018-12-06 15:28:53 -0800748 ReqSfixed64: scalar.Int64(0xbeefcafe),
749 ReqDouble: scalar.Float64(math.NaN()),
750 ReqString: scalar.String("hello"),
Herbie Ong8170d692019-02-13 14:13:21 -0800751 ReqEnum: pb2.Enum_ONE.Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800752 },
753 want: `req_bool: false
Herbie Ong800c9902018-12-06 15:28:53 -0800754req_sfixed64: 3203386110
755req_double: nan
756req_string: "hello"
Herbie Ong8170d692019-02-13 14:13:21 -0800757req_enum: ONE
Herbie Ong800c9902018-12-06 15:28:53 -0800758`,
759 wantErr: true,
760 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700761 desc: "required fields not set with AllowPartial",
762 mo: textpb.MarshalOptions{AllowPartial: true},
763 input: &pb2.Requireds{
764 ReqBool: scalar.Bool(false),
765 ReqSfixed64: scalar.Int64(0xbeefcafe),
766 ReqDouble: scalar.Float64(math.NaN()),
767 ReqString: scalar.String("hello"),
768 ReqEnum: pb2.Enum_ONE.Enum(),
769 },
770 want: `req_bool: false
771req_sfixed64: 3203386110
772req_double: nan
773req_string: "hello"
774req_enum: ONE
775`,
776 }, {
777 desc: "required fields all set",
Herbie Ong800c9902018-12-06 15:28:53 -0800778 input: &pb2.Requireds{
779 ReqBool: scalar.Bool(false),
Herbie Ong800c9902018-12-06 15:28:53 -0800780 ReqSfixed64: scalar.Int64(0),
Herbie Ong8170d692019-02-13 14:13:21 -0800781 ReqDouble: scalar.Float64(1.23),
Herbie Ong800c9902018-12-06 15:28:53 -0800782 ReqString: scalar.String(""),
Herbie Ong8170d692019-02-13 14:13:21 -0800783 ReqEnum: pb2.Enum_ONE.Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800784 ReqNested: &pb2.Nested{},
785 },
786 want: `req_bool: false
Herbie Ong800c9902018-12-06 15:28:53 -0800787req_sfixed64: 0
Herbie Ong8170d692019-02-13 14:13:21 -0800788req_double: 1.23
Herbie Ong800c9902018-12-06 15:28:53 -0800789req_string: ""
Herbie Ong8170d692019-02-13 14:13:21 -0800790req_enum: ONE
Herbie Ong800c9902018-12-06 15:28:53 -0800791req_nested: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800792`,
793 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800794 desc: "indirect required field",
795 input: &pb2.IndirectRequired{
796 OptNested: &pb2.NestedWithRequired{},
797 },
798 want: "opt_nested: {}\n",
799 wantErr: true,
Herbie Ongcddf8192018-11-28 18:25:20 -0800800 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700801 desc: "indirect required field with AllowPartial",
802 mo: textpb.MarshalOptions{AllowPartial: true},
803 input: &pb2.IndirectRequired{
804 OptNested: &pb2.NestedWithRequired{},
805 },
806 want: "opt_nested: {}\n",
807 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800808 desc: "indirect required field in empty repeated",
809 input: &pb2.IndirectRequired{
810 RptNested: []*pb2.NestedWithRequired{},
811 },
812 want: "\n",
Herbie Ongcddf8192018-11-28 18:25:20 -0800813 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800814 desc: "indirect required field in repeated",
815 input: &pb2.IndirectRequired{
816 RptNested: []*pb2.NestedWithRequired{
817 &pb2.NestedWithRequired{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800818 },
Herbie Ong800c9902018-12-06 15:28:53 -0800819 },
820 want: "rpt_nested: {}\n",
821 wantErr: true,
822 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700823 desc: "indirect required field in repeated with AllowPartial",
824 mo: textpb.MarshalOptions{AllowPartial: true},
825 input: &pb2.IndirectRequired{
826 RptNested: []*pb2.NestedWithRequired{
827 &pb2.NestedWithRequired{},
828 },
829 },
830 want: "rpt_nested: {}\n",
831 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800832 desc: "indirect required field in empty map",
833 input: &pb2.IndirectRequired{
834 StrToNested: map[string]*pb2.NestedWithRequired{},
835 },
836 want: "\n",
837 }, {
838 desc: "indirect required field in map",
839 input: &pb2.IndirectRequired{
840 StrToNested: map[string]*pb2.NestedWithRequired{
841 "fail": &pb2.NestedWithRequired{},
842 },
843 },
844 want: `str_to_nested: {
845 key: "fail"
846 value: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800847}
848`,
Herbie Ong800c9902018-12-06 15:28:53 -0800849 wantErr: true,
Herbie Ong20a1d312018-12-11 21:08:58 -0800850 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700851 desc: "indirect required field in map with AllowPartial",
852 mo: textpb.MarshalOptions{AllowPartial: true},
853 input: &pb2.IndirectRequired{
854 StrToNested: map[string]*pb2.NestedWithRequired{
855 "fail": &pb2.NestedWithRequired{},
856 },
857 },
858 want: `str_to_nested: {
859 key: "fail"
860 value: {}
861}
862`,
863 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800864 desc: "indirect required field in oneof",
865 input: &pb2.IndirectRequired{
866 Union: &pb2.IndirectRequired_OneofNested{
867 OneofNested: &pb2.NestedWithRequired{},
868 },
869 },
870 want: "oneof_nested: {}\n",
871 wantErr: true,
872 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700873 desc: "indirect required field in oneof with AllowPartial",
874 mo: textpb.MarshalOptions{AllowPartial: true},
875 input: &pb2.IndirectRequired{
876 Union: &pb2.IndirectRequired_OneofNested{
877 OneofNested: &pb2.NestedWithRequired{},
878 },
879 },
880 want: "oneof_nested: {}\n",
881 }, {
Herbie Ong20a1d312018-12-11 21:08:58 -0800882 desc: "unknown varint and fixed types",
883 input: &pb2.Scalars{
884 OptString: scalar.String("this message contains unknown fields"),
885 XXX_unrecognized: pack.Message{
886 pack.Tag{101, pack.VarintType}, pack.Bool(true),
887 pack.Tag{102, pack.VarintType}, pack.Varint(0xff),
888 pack.Tag{103, pack.Fixed32Type}, pack.Uint32(47),
889 pack.Tag{104, pack.Fixed64Type}, pack.Int64(0xdeadbeef),
890 }.Marshal(),
891 },
892 want: `opt_string: "this message contains unknown fields"
893101: 1
894102: 255
895103: 47
896104: 3735928559
897`,
898 }, {
899 desc: "unknown length-delimited",
900 input: &pb2.Scalars{
901 XXX_unrecognized: pack.Message{
902 pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false)},
903 pack.Tag{102, pack.BytesType}, pack.String("hello world"),
904 pack.Tag{103, pack.BytesType}, pack.Bytes("\xe4\xb8\x96\xe7\x95\x8c"),
905 }.Marshal(),
906 },
907 want: `101: "\x01\x00"
908102: "hello world"
909103: "世界"
910`,
911 }, {
912 desc: "unknown group type",
913 input: &pb2.Scalars{
914 XXX_unrecognized: pack.Message{
915 pack.Tag{101, pack.StartGroupType}, pack.Tag{101, pack.EndGroupType},
916 pack.Tag{102, pack.StartGroupType},
917 pack.Tag{101, pack.VarintType}, pack.Bool(false),
918 pack.Tag{102, pack.BytesType}, pack.String("inside a group"),
919 pack.Tag{102, pack.EndGroupType},
920 }.Marshal(),
921 },
922 want: `101: {}
923102: {
924 101: 0
925 102: "inside a group"
926}
927`,
928 }, {
929 desc: "unknown unpack repeated field",
930 input: &pb2.Scalars{
931 XXX_unrecognized: pack.Message{
932 pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false), pack.Bool(true)},
933 pack.Tag{102, pack.BytesType}, pack.String("hello"),
934 pack.Tag{101, pack.VarintType}, pack.Bool(true),
935 pack.Tag{102, pack.BytesType}, pack.String("世界"),
936 }.Marshal(),
937 },
938 want: `101: "\x01\x00\x01"
939101: 1
940102: "hello"
941102: "世界"
942`,
Herbie Ongcf253082018-12-17 17:13:07 -0800943 }, {
944 desc: "extensions of non-repeated fields",
945 input: func() proto.Message {
946 m := &pb2.Extensions{
947 OptString: scalar.String("non-extension field"),
948 OptBool: scalar.Bool(true),
949 OptInt32: scalar.Int32(42),
950 }
951 setExtension(m, pb2.E_OptExtBool, true)
952 setExtension(m, pb2.E_OptExtString, "extension field")
Herbie Ong8170d692019-02-13 14:13:21 -0800953 setExtension(m, pb2.E_OptExtEnum, pb2.Enum_TEN)
Herbie Ongcf253082018-12-17 17:13:07 -0800954 setExtension(m, pb2.E_OptExtNested, &pb2.Nested{
955 OptString: scalar.String("nested in an extension"),
956 OptNested: &pb2.Nested{
957 OptString: scalar.String("another nested in an extension"),
958 },
959 })
960 return m
961 }(),
962 want: `opt_string: "non-extension field"
963opt_bool: true
964opt_int32: 42
965[pb2.opt_ext_bool]: true
Herbie Ong8170d692019-02-13 14:13:21 -0800966[pb2.opt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -0800967[pb2.opt_ext_nested]: {
968 opt_string: "nested in an extension"
969 opt_nested: {
970 opt_string: "another nested in an extension"
971 }
972}
973[pb2.opt_ext_string]: "extension field"
974`,
975 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700976 desc: "extension field contains invalid UTF-8",
977 input: func() proto.Message {
978 m := &pb2.Extensions{}
979 setExtension(m, pb2.E_OptExtString, "abc\xff")
980 return m
981 }(),
982 want: `[pb2.opt_ext_string]: "abc\xff"
983`,
984 wantErr: true,
985 }, {
Herbie Ong09b28a92019-04-03 15:42:41 -0700986 desc: "extension partial returns error",
987 input: func() proto.Message {
988 m := &pb2.Extensions{}
989 setExtension(m, pb2.E_OptExtPartial, &pb2.PartialRequired{
990 OptString: scalar.String("partial1"),
991 })
992 setExtension(m, pb2.E_ExtensionsContainer_OptExtPartial, &pb2.PartialRequired{
993 OptString: scalar.String("partial2"),
994 })
995 return m
996 }(),
997 want: `[pb2.ExtensionsContainer.opt_ext_partial]: {
998 opt_string: "partial2"
999}
1000[pb2.opt_ext_partial]: {
1001 opt_string: "partial1"
1002}
1003`,
1004 wantErr: true,
1005 }, {
1006 desc: "extension partial with AllowPartial",
1007 mo: textpb.MarshalOptions{AllowPartial: true},
1008 input: func() proto.Message {
1009 m := &pb2.Extensions{}
1010 setExtension(m, pb2.E_OptExtPartial, &pb2.PartialRequired{
1011 OptString: scalar.String("partial1"),
1012 })
1013 return m
1014 }(),
1015 want: `[pb2.opt_ext_partial]: {
1016 opt_string: "partial1"
1017}
1018`,
1019 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001020 desc: "extension message field set to nil",
Herbie Ongcf253082018-12-17 17:13:07 -08001021 input: func() proto.Message {
1022 m := &pb2.Extensions{}
1023 setExtension(m, pb2.E_OptExtNested, nil)
1024 return m
1025 }(),
1026 want: "\n",
1027 }, {
1028 desc: "extensions of repeated fields",
1029 input: func() proto.Message {
1030 m := &pb2.Extensions{}
Herbie Ong8170d692019-02-13 14:13:21 -08001031 setExtension(m, pb2.E_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
Herbie Ongcf253082018-12-17 17:13:07 -08001032 setExtension(m, pb2.E_RptExtFixed32, &[]uint32{42, 47})
1033 setExtension(m, pb2.E_RptExtNested, &[]*pb2.Nested{
1034 &pb2.Nested{OptString: scalar.String("one")},
1035 &pb2.Nested{OptString: scalar.String("two")},
1036 &pb2.Nested{OptString: scalar.String("three")},
1037 })
1038 return m
1039 }(),
Herbie Ong8170d692019-02-13 14:13:21 -08001040 want: `[pb2.rpt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -08001041[pb2.rpt_ext_enum]: 101
Herbie Ong8170d692019-02-13 14:13:21 -08001042[pb2.rpt_ext_enum]: ONE
Herbie Ongcf253082018-12-17 17:13:07 -08001043[pb2.rpt_ext_fixed32]: 42
1044[pb2.rpt_ext_fixed32]: 47
1045[pb2.rpt_ext_nested]: {
1046 opt_string: "one"
1047}
1048[pb2.rpt_ext_nested]: {
1049 opt_string: "two"
1050}
1051[pb2.rpt_ext_nested]: {
1052 opt_string: "three"
1053}
1054`,
1055 }, {
1056 desc: "extensions of non-repeated fields in another message",
1057 input: func() proto.Message {
1058 m := &pb2.Extensions{}
1059 setExtension(m, pb2.E_ExtensionsContainer_OptExtBool, true)
1060 setExtension(m, pb2.E_ExtensionsContainer_OptExtString, "extension field")
Herbie Ong8170d692019-02-13 14:13:21 -08001061 setExtension(m, pb2.E_ExtensionsContainer_OptExtEnum, pb2.Enum_TEN)
Herbie Ongcf253082018-12-17 17:13:07 -08001062 setExtension(m, pb2.E_ExtensionsContainer_OptExtNested, &pb2.Nested{
1063 OptString: scalar.String("nested in an extension"),
1064 OptNested: &pb2.Nested{
1065 OptString: scalar.String("another nested in an extension"),
1066 },
1067 })
1068 return m
1069 }(),
1070 want: `[pb2.ExtensionsContainer.opt_ext_bool]: true
Herbie Ong8170d692019-02-13 14:13:21 -08001071[pb2.ExtensionsContainer.opt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -08001072[pb2.ExtensionsContainer.opt_ext_nested]: {
1073 opt_string: "nested in an extension"
1074 opt_nested: {
1075 opt_string: "another nested in an extension"
1076 }
1077}
1078[pb2.ExtensionsContainer.opt_ext_string]: "extension field"
1079`,
1080 }, {
1081 desc: "extensions of repeated fields in another message",
1082 input: func() proto.Message {
1083 m := &pb2.Extensions{
1084 OptString: scalar.String("non-extension field"),
1085 OptBool: scalar.Bool(true),
1086 OptInt32: scalar.Int32(42),
1087 }
Herbie Ong8170d692019-02-13 14:13:21 -08001088 setExtension(m, pb2.E_ExtensionsContainer_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
Herbie Ongcf253082018-12-17 17:13:07 -08001089 setExtension(m, pb2.E_ExtensionsContainer_RptExtString, &[]string{"hello", "world"})
1090 setExtension(m, pb2.E_ExtensionsContainer_RptExtNested, &[]*pb2.Nested{
1091 &pb2.Nested{OptString: scalar.String("one")},
1092 &pb2.Nested{OptString: scalar.String("two")},
1093 &pb2.Nested{OptString: scalar.String("three")},
1094 })
1095 return m
1096 }(),
1097 want: `opt_string: "non-extension field"
1098opt_bool: true
1099opt_int32: 42
Herbie Ong8170d692019-02-13 14:13:21 -08001100[pb2.ExtensionsContainer.rpt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -08001101[pb2.ExtensionsContainer.rpt_ext_enum]: 101
Herbie Ong8170d692019-02-13 14:13:21 -08001102[pb2.ExtensionsContainer.rpt_ext_enum]: ONE
Herbie Ongcf253082018-12-17 17:13:07 -08001103[pb2.ExtensionsContainer.rpt_ext_nested]: {
1104 opt_string: "one"
1105}
1106[pb2.ExtensionsContainer.rpt_ext_nested]: {
1107 opt_string: "two"
1108}
1109[pb2.ExtensionsContainer.rpt_ext_nested]: {
1110 opt_string: "three"
1111}
1112[pb2.ExtensionsContainer.rpt_ext_string]: "hello"
1113[pb2.ExtensionsContainer.rpt_ext_string]: "world"
1114`,
Herbie Ong6470ea62019-01-07 18:56:57 -08001115 }, {
1116 desc: "MessageSet",
1117 input: func() proto.Message {
1118 m := &pb2.MessageSet{}
1119 setExtension(m, pb2.E_MessageSetExtension_MessageSetExtension, &pb2.MessageSetExtension{
1120 OptString: scalar.String("a messageset extension"),
1121 })
1122 setExtension(m, pb2.E_MessageSetExtension_NotMessageSetExtension, &pb2.MessageSetExtension{
1123 OptString: scalar.String("not a messageset extension"),
1124 })
1125 setExtension(m, pb2.E_MessageSetExtension_ExtNested, &pb2.Nested{
1126 OptString: scalar.String("just a regular extension"),
1127 })
1128 return m
1129 }(),
1130 want: `[pb2.MessageSetExtension]: {
1131 opt_string: "a messageset extension"
1132}
1133[pb2.MessageSetExtension.ext_nested]: {
1134 opt_string: "just a regular extension"
1135}
1136[pb2.MessageSetExtension.not_message_set_extension]: {
1137 opt_string: "not a messageset extension"
1138}
1139`,
1140 }, {
1141 desc: "not real MessageSet 1",
1142 input: func() proto.Message {
1143 m := &pb2.FakeMessageSet{}
1144 setExtension(m, pb2.E_FakeMessageSetExtension_MessageSetExtension, &pb2.FakeMessageSetExtension{
1145 OptString: scalar.String("not a messageset extension"),
1146 })
1147 return m
1148 }(),
1149 want: `[pb2.FakeMessageSetExtension.message_set_extension]: {
1150 opt_string: "not a messageset extension"
1151}
1152`,
1153 }, {
1154 desc: "not real MessageSet 2",
1155 input: func() proto.Message {
1156 m := &pb2.MessageSet{}
1157 setExtension(m, pb2.E_MessageSetExtension, &pb2.FakeMessageSetExtension{
1158 OptString: scalar.String("another not a messageset extension"),
1159 })
1160 return m
1161 }(),
1162 want: `[pb2.message_set_extension]: {
1163 opt_string: "another not a messageset extension"
1164}
1165`,
Herbie Ongf42b55f2019-01-02 15:46:07 -08001166 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001167 desc: "Any not expanded",
Herbie Ong66c365c2019-01-04 14:08:41 -08001168 mo: textpb.MarshalOptions{
1169 Resolver: preg.NewTypes(),
1170 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001171 input: func() proto.Message {
1172 m := &pb2.Nested{
1173 OptString: scalar.String("embedded inside Any"),
1174 OptNested: &pb2.Nested{
1175 OptString: scalar.String("inception"),
1176 },
1177 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -07001178 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ongf42b55f2019-01-02 15:46:07 -08001179 if err != nil {
1180 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1181 }
Herbie Ong300cff02019-03-20 18:05:16 -07001182 return &knownpb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001183 TypeUrl: "pb2.Nested",
Herbie Ongf42b55f2019-01-02 15:46:07 -08001184 Value: b,
Herbie Ong300cff02019-03-20 18:05:16 -07001185 }
Herbie Ongf42b55f2019-01-02 15:46:07 -08001186 }(),
1187 want: `type_url: "pb2.Nested"
1188value: "\n\x13embedded inside Any\x12\x0b\n\tinception"
1189`,
1190 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001191 desc: "Any expanded",
Herbie Ong66c365c2019-01-04 14:08:41 -08001192 mo: textpb.MarshalOptions{
1193 Resolver: preg.NewTypes((&pb2.Nested{}).ProtoReflect().Type()),
1194 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001195 input: func() proto.Message {
1196 m := &pb2.Nested{
1197 OptString: scalar.String("embedded inside Any"),
1198 OptNested: &pb2.Nested{
1199 OptString: scalar.String("inception"),
1200 },
1201 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -07001202 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ongf42b55f2019-01-02 15:46:07 -08001203 if err != nil {
1204 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1205 }
Herbie Ong300cff02019-03-20 18:05:16 -07001206 return &knownpb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001207 TypeUrl: "foo/pb2.Nested",
Herbie Ongf42b55f2019-01-02 15:46:07 -08001208 Value: b,
Herbie Ong300cff02019-03-20 18:05:16 -07001209 }
Herbie Ongf42b55f2019-01-02 15:46:07 -08001210 }(),
Herbie Ong66c365c2019-01-04 14:08:41 -08001211 want: `[foo/pb2.Nested]: {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001212 opt_string: "embedded inside Any"
1213 opt_nested: {
1214 opt_string: "inception"
1215 }
1216}
1217`,
1218 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001219 desc: "Any expanded with missing required error",
Herbie Ong66c365c2019-01-04 14:08:41 -08001220 mo: textpb.MarshalOptions{
1221 Resolver: preg.NewTypes((&pb2.PartialRequired{}).ProtoReflect().Type()),
1222 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001223 input: func() proto.Message {
1224 m := &pb2.PartialRequired{
1225 OptString: scalar.String("embedded inside Any"),
1226 }
Damien Neil96c229a2019-04-03 12:17:24 -07001227 b, err := proto.MarshalOptions{
1228 AllowPartial: true,
1229 Deterministic: true,
1230 }.Marshal(m)
Herbie Ong300cff02019-03-20 18:05:16 -07001231 if err != nil {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001232 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1233 }
Herbie Ong300cff02019-03-20 18:05:16 -07001234 return &knownpb.Any{
Herbie Ongf42b55f2019-01-02 15:46:07 -08001235 TypeUrl: string(m.ProtoReflect().Type().FullName()),
1236 Value: b,
Herbie Ong300cff02019-03-20 18:05:16 -07001237 }
Herbie Ongf42b55f2019-01-02 15:46:07 -08001238 }(),
1239 want: `[pb2.PartialRequired]: {
1240 opt_string: "embedded inside Any"
1241}
1242`,
1243 wantErr: true,
1244 }, {
Herbie Ong21a39742019-04-08 17:32:44 -07001245 desc: "Any with invalid UTF-8",
1246 mo: textpb.MarshalOptions{
1247 Resolver: preg.NewTypes((&pb3.Nested{}).ProtoReflect().Type()),
1248 },
1249 input: func() proto.Message {
1250 m := &pb3.Nested{
1251 SString: "abc\xff",
1252 }
1253 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
1254 if err != nil {
1255 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1256 }
1257 return &knownpb.Any{
1258 TypeUrl: string(m.ProtoReflect().Type().FullName()),
1259 Value: b,
1260 }
1261 }(),
1262 want: `[pb3.Nested]: {
1263 s_string: "abc\xff"
1264}
1265`,
1266 wantErr: true,
1267 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001268 desc: "Any with invalid value",
Herbie Ong66c365c2019-01-04 14:08:41 -08001269 mo: textpb.MarshalOptions{
1270 Resolver: preg.NewTypes((&pb2.Nested{}).ProtoReflect().Type()),
1271 },
Herbie Ong300cff02019-03-20 18:05:16 -07001272 input: &knownpb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001273 TypeUrl: "foo/pb2.Nested",
1274 Value: dhex("80"),
Herbie Ong300cff02019-03-20 18:05:16 -07001275 },
Herbie Ong66c365c2019-01-04 14:08:41 -08001276 want: `type_url: "foo/pb2.Nested"
Herbie Onga94f78c2019-01-03 15:39:58 -08001277value: "\x80"
1278`,
Herbie Ongcddf8192018-11-28 18:25:20 -08001279 }}
1280
1281 for _, tt := range tests {
1282 tt := tt
1283 t.Run(tt.desc, func(t *testing.T) {
Herbie Ong3a385912019-03-20 14:04:24 -07001284 // Use 2-space indentation on all MarshalOptions.
1285 tt.mo.Indent = " "
Herbie Ongf42b55f2019-01-02 15:46:07 -08001286 b, err := tt.mo.Marshal(tt.input)
Herbie Ongcddf8192018-11-28 18:25:20 -08001287 if err != nil && !tt.wantErr {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001288 t.Errorf("Marshal() returned error: %v\n", err)
Herbie Ongcddf8192018-11-28 18:25:20 -08001289 }
Herbie Ong800c9902018-12-06 15:28:53 -08001290 if err == nil && tt.wantErr {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001291 t.Error("Marshal() got nil error, want error\n")
Herbie Ongcddf8192018-11-28 18:25:20 -08001292 }
Herbie Ong800c9902018-12-06 15:28:53 -08001293 got := string(b)
1294 if tt.want != "" && got != tt.want {
1295 t.Errorf("Marshal()\n<got>\n%v\n<want>\n%v\n", got, tt.want)
1296 if diff := cmp.Diff(tt.want, got, splitLines); diff != "" {
Herbie Ongcddf8192018-11-28 18:25:20 -08001297 t.Errorf("Marshal() diff -want +got\n%v\n", diff)
1298 }
1299 }
1300 })
1301 }
1302}