blob: e4ca9666d1639088163c73f3133f5677382c1ca1 [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"
Joe Tsai0fc49f82019-05-01 12:29:25 -070018 pimpl "github.com/golang/protobuf/v2/internal/impl"
Herbie Ongcddf8192018-11-28 18:25:20 -080019 "github.com/golang/protobuf/v2/internal/scalar"
20 "github.com/golang/protobuf/v2/proto"
Herbie Ongf42b55f2019-01-02 15:46:07 -080021 preg "github.com/golang/protobuf/v2/reflect/protoregistry"
Joe Tsai4fddeba2019-03-20 18:29:32 -070022 "github.com/golang/protobuf/v2/runtime/protoiface"
Herbie Ongcddf8192018-11-28 18:25:20 -080023 "github.com/google/go-cmp/cmp"
24 "github.com/google/go-cmp/cmp/cmpopts"
25
Herbie Ong8170d692019-02-13 14:13:21 -080026 "github.com/golang/protobuf/v2/encoding/testprotos/pb2"
27 "github.com/golang/protobuf/v2/encoding/testprotos/pb3"
Joe Tsai19058432019-02-27 21:46:29 -080028 knownpb "github.com/golang/protobuf/v2/types/known"
Herbie Ongcddf8192018-11-28 18:25:20 -080029)
30
31func init() {
32 // Disable detrand to enable direct comparisons on outputs.
33 detrand.Disable()
34}
35
Herbie Ongcddf8192018-11-28 18:25:20 -080036// splitLines is a cmpopts.Option for comparing strings with line breaks.
37var splitLines = cmpopts.AcyclicTransformer("SplitLines", func(s string) []string {
38 return strings.Split(s, "\n")
39})
40
Herbie Ong800c9902018-12-06 15:28:53 -080041func pb2Enum(i int32) *pb2.Enum {
42 p := new(pb2.Enum)
43 *p = pb2.Enum(i)
44 return p
45}
46
47func pb2Enums_NestedEnum(i int32) *pb2.Enums_NestedEnum {
48 p := new(pb2.Enums_NestedEnum)
49 *p = pb2.Enums_NestedEnum(i)
50 return p
51}
52
Joe Tsai4fddeba2019-03-20 18:29:32 -070053func setExtension(m proto.Message, xd *protoiface.ExtensionDescV1, val interface{}) {
Herbie Ongcf253082018-12-17 17:13:07 -080054 knownFields := m.ProtoReflect().KnownFields()
55 extTypes := knownFields.ExtensionTypes()
Joe Tsaiafb455e2019-03-14 16:08:22 -070056 extTypes.Register(xd.Type)
Herbie Ongcf253082018-12-17 17:13:07 -080057 if val == nil {
58 return
59 }
Joe Tsaiafb455e2019-03-14 16:08:22 -070060 pval := xd.Type.ValueOf(val)
Herbie Ongcf253082018-12-17 17:13:07 -080061 knownFields.Set(wire.Number(xd.Field), pval)
62}
63
Herbie Onga94f78c2019-01-03 15:39:58 -080064// dhex decodes a hex-string and returns the bytes and panics if s is invalid.
65func dhex(s string) []byte {
66 b, err := hex.DecodeString(s)
67 if err != nil {
68 panic(err)
69 }
70 return b
71}
72
Herbie Ongcddf8192018-11-28 18:25:20 -080073func TestMarshal(t *testing.T) {
74 tests := []struct {
75 desc string
Herbie Ongf42b55f2019-01-02 15:46:07 -080076 mo textpb.MarshalOptions
Herbie Ong70651952018-12-13 14:19:50 -080077 input proto.Message
Herbie Ongcddf8192018-11-28 18:25:20 -080078 want string
Herbie Ong300cff02019-03-20 18:05:16 -070079 wantErr bool // TODO: Verify error message content.
Herbie Ongcddf8192018-11-28 18:25:20 -080080 }{{
Herbie Ong8170d692019-02-13 14:13:21 -080081 desc: "proto2 optional scalars not set",
Herbie Ong800c9902018-12-06 15:28:53 -080082 input: &pb2.Scalars{},
Herbie Ongcddf8192018-11-28 18:25:20 -080083 want: "\n",
84 }, {
Herbie Ong8170d692019-02-13 14:13:21 -080085 desc: "proto3 scalars not set",
Herbie Ong800c9902018-12-06 15:28:53 -080086 input: &pb3.Scalars{},
Herbie Ongcddf8192018-11-28 18:25:20 -080087 want: "\n",
88 }, {
Herbie Ong8170d692019-02-13 14:13:21 -080089 desc: "proto2 optional scalars set to zero values",
Herbie Ong800c9902018-12-06 15:28:53 -080090 input: &pb2.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -080091 OptBool: scalar.Bool(false),
92 OptInt32: scalar.Int32(0),
93 OptInt64: scalar.Int64(0),
94 OptUint32: scalar.Uint32(0),
95 OptUint64: scalar.Uint64(0),
96 OptSint32: scalar.Int32(0),
97 OptSint64: scalar.Int64(0),
98 OptFixed32: scalar.Uint32(0),
99 OptFixed64: scalar.Uint64(0),
100 OptSfixed32: scalar.Int32(0),
101 OptSfixed64: scalar.Int64(0),
102 OptFloat: scalar.Float32(0),
103 OptDouble: scalar.Float64(0),
104 OptBytes: []byte{},
105 OptString: scalar.String(""),
Herbie Ong800c9902018-12-06 15:28:53 -0800106 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800107 want: `opt_bool: false
108opt_int32: 0
109opt_int64: 0
110opt_uint32: 0
111opt_uint64: 0
112opt_sint32: 0
113opt_sint64: 0
114opt_fixed32: 0
115opt_fixed64: 0
116opt_sfixed32: 0
117opt_sfixed64: 0
118opt_float: 0
119opt_double: 0
120opt_bytes: ""
121opt_string: ""
122`,
123 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800124 desc: "proto3 scalars set to zero values",
Herbie Ong800c9902018-12-06 15:28:53 -0800125 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800126 SBool: false,
127 SInt32: 0,
128 SInt64: 0,
129 SUint32: 0,
130 SUint64: 0,
131 SSint32: 0,
132 SSint64: 0,
133 SFixed32: 0,
134 SFixed64: 0,
135 SSfixed32: 0,
136 SSfixed64: 0,
137 SFloat: 0,
138 SDouble: 0,
139 SBytes: []byte{},
140 SString: "",
Herbie Ong800c9902018-12-06 15:28:53 -0800141 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800142 want: "\n",
143 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800144 desc: "proto2 optional scalars set to some values",
Herbie Ong800c9902018-12-06 15:28:53 -0800145 input: &pb2.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800146 OptBool: scalar.Bool(true),
147 OptInt32: scalar.Int32(0xff),
148 OptInt64: scalar.Int64(0xdeadbeef),
149 OptUint32: scalar.Uint32(47),
150 OptUint64: scalar.Uint64(0xdeadbeef),
151 OptSint32: scalar.Int32(-1001),
152 OptSint64: scalar.Int64(-0xffff),
153 OptFixed64: scalar.Uint64(64),
154 OptSfixed32: scalar.Int32(-32),
Herbie Ong84f09602019-01-17 19:31:47 -0800155 OptFloat: scalar.Float32(1.02),
156 OptDouble: scalar.Float64(1.0199999809265137),
Herbie Ong8170d692019-02-13 14:13:21 -0800157 OptBytes: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
158 OptString: scalar.String("谷歌"),
Herbie Ong800c9902018-12-06 15:28:53 -0800159 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800160 want: `opt_bool: true
161opt_int32: 255
162opt_int64: 3735928559
163opt_uint32: 47
164opt_uint64: 3735928559
165opt_sint32: -1001
166opt_sint64: -65535
167opt_fixed64: 64
168opt_sfixed32: -32
Herbie Ong84f09602019-01-17 19:31:47 -0800169opt_float: 1.02
170opt_double: 1.0199999809265137
Herbie Ongcddf8192018-11-28 18:25:20 -0800171opt_bytes: "谷歌"
172opt_string: "谷歌"
173`,
174 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700175 desc: "string with invalid UTF-8",
176 input: &pb3.Scalars{
177 SString: "abc\xff",
178 },
179 want: `s_string: "abc\xff"
180`,
181 wantErr: true,
182 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800183 desc: "float nan",
Herbie Ong800c9902018-12-06 15:28:53 -0800184 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800185 SFloat: float32(math.NaN()),
Herbie Ong800c9902018-12-06 15:28:53 -0800186 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800187 want: "s_float: nan\n",
188 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800189 desc: "float positive infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800190 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800191 SFloat: float32(math.Inf(1)),
Herbie Ong800c9902018-12-06 15:28:53 -0800192 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800193 want: "s_float: inf\n",
194 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800195 desc: "float negative infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800196 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800197 SFloat: float32(math.Inf(-1)),
Herbie Ong800c9902018-12-06 15:28:53 -0800198 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800199 want: "s_float: -inf\n",
200 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800201 desc: "double nan",
Herbie Ong800c9902018-12-06 15:28:53 -0800202 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800203 SDouble: math.NaN(),
Herbie Ong800c9902018-12-06 15:28:53 -0800204 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800205 want: "s_double: nan\n",
206 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800207 desc: "double positive infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800208 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800209 SDouble: math.Inf(1),
Herbie Ong800c9902018-12-06 15:28:53 -0800210 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800211 want: "s_double: inf\n",
212 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800213 desc: "double negative infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800214 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800215 SDouble: math.Inf(-1),
Herbie Ong800c9902018-12-06 15:28:53 -0800216 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800217 want: "s_double: -inf\n",
218 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800219 desc: "proto2 enum not set",
220 input: &pb2.Enums{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800221 want: "\n",
222 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800223 desc: "proto2 enum set to zero value",
224 input: &pb2.Enums{
Herbie Ong8170d692019-02-13 14:13:21 -0800225 OptEnum: pb2Enum(0),
Herbie Ong800c9902018-12-06 15:28:53 -0800226 OptNestedEnum: pb2Enums_NestedEnum(0),
227 },
Herbie Ong8170d692019-02-13 14:13:21 -0800228 want: `opt_enum: 0
Herbie Ong800c9902018-12-06 15:28:53 -0800229opt_nested_enum: 0
230`,
231 }, {
232 desc: "proto2 enum",
233 input: &pb2.Enums{
Herbie Ong8170d692019-02-13 14:13:21 -0800234 OptEnum: pb2.Enum_ONE.Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800235 OptNestedEnum: pb2.Enums_UNO.Enum(),
236 },
Herbie Ong8170d692019-02-13 14:13:21 -0800237 want: `opt_enum: ONE
Herbie Ong800c9902018-12-06 15:28:53 -0800238opt_nested_enum: UNO
239`,
240 }, {
241 desc: "proto2 enum set to numeric values",
242 input: &pb2.Enums{
Herbie Ong8170d692019-02-13 14:13:21 -0800243 OptEnum: pb2Enum(2),
Herbie Ong800c9902018-12-06 15:28:53 -0800244 OptNestedEnum: pb2Enums_NestedEnum(2),
245 },
Herbie Ong8170d692019-02-13 14:13:21 -0800246 want: `opt_enum: TWO
Herbie Ong800c9902018-12-06 15:28:53 -0800247opt_nested_enum: DOS
248`,
249 }, {
250 desc: "proto2 enum set to unnamed numeric values",
251 input: &pb2.Enums{
252 OptEnum: pb2Enum(101),
253 OptNestedEnum: pb2Enums_NestedEnum(-101),
254 },
255 want: `opt_enum: 101
256opt_nested_enum: -101
257`,
258 }, {
259 desc: "proto3 enum not set",
260 input: &pb3.Enums{},
261 want: "\n",
262 }, {
263 desc: "proto3 enum set to zero value",
264 input: &pb3.Enums{
265 SEnum: pb3.Enum_ZERO,
266 SNestedEnum: pb3.Enums_CERO,
267 },
268 want: "\n",
269 }, {
270 desc: "proto3 enum",
271 input: &pb3.Enums{
272 SEnum: pb3.Enum_ONE,
Herbie Ong8170d692019-02-13 14:13:21 -0800273 SNestedEnum: pb3.Enums_UNO,
Herbie Ong800c9902018-12-06 15:28:53 -0800274 },
275 want: `s_enum: ONE
Herbie Ong8170d692019-02-13 14:13:21 -0800276s_nested_enum: UNO
Herbie Ong800c9902018-12-06 15:28:53 -0800277`,
278 }, {
279 desc: "proto3 enum set to numeric values",
280 input: &pb3.Enums{
281 SEnum: 2,
Herbie Ong8170d692019-02-13 14:13:21 -0800282 SNestedEnum: 2,
Herbie Ong800c9902018-12-06 15:28:53 -0800283 },
284 want: `s_enum: TWO
Herbie Ong8170d692019-02-13 14:13:21 -0800285s_nested_enum: DOS
Herbie Ong800c9902018-12-06 15:28:53 -0800286`,
287 }, {
288 desc: "proto3 enum set to unnamed numeric values",
289 input: &pb3.Enums{
290 SEnum: -47,
291 SNestedEnum: 47,
292 },
293 want: `s_enum: -47
294s_nested_enum: 47
295`,
296 }, {
297 desc: "proto2 nested message not set",
298 input: &pb2.Nests{},
299 want: "\n",
300 }, {
301 desc: "proto2 nested message set to empty",
302 input: &pb2.Nests{
303 OptNested: &pb2.Nested{},
304 Optgroup: &pb2.Nests_OptGroup{},
305 },
306 want: `opt_nested: {}
Herbie Ong0dcfb9a2019-01-14 15:32:26 -0800307OptGroup: {}
Herbie Ong800c9902018-12-06 15:28:53 -0800308`,
309 }, {
310 desc: "proto2 nested messages",
311 input: &pb2.Nests{
312 OptNested: &pb2.Nested{
313 OptString: scalar.String("nested message"),
314 OptNested: &pb2.Nested{
315 OptString: scalar.String("another nested message"),
316 },
317 },
318 },
319 want: `opt_nested: {
320 opt_string: "nested message"
321 opt_nested: {
322 opt_string: "another nested message"
323 }
324}
325`,
326 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800327 desc: "proto2 groups",
Herbie Ong800c9902018-12-06 15:28:53 -0800328 input: &pb2.Nests{
329 Optgroup: &pb2.Nests_OptGroup{
Herbie Ong800c9902018-12-06 15:28:53 -0800330 OptString: scalar.String("inside a group"),
331 OptNested: &pb2.Nested{
332 OptString: scalar.String("nested message inside a group"),
333 },
334 Optnestedgroup: &pb2.Nests_OptGroup_OptNestedGroup{
Herbie Ong8170d692019-02-13 14:13:21 -0800335 OptFixed32: scalar.Uint32(47),
Herbie Ong800c9902018-12-06 15:28:53 -0800336 },
337 },
338 },
Herbie Ong0dcfb9a2019-01-14 15:32:26 -0800339 want: `OptGroup: {
Herbie Ong800c9902018-12-06 15:28:53 -0800340 opt_string: "inside a group"
341 opt_nested: {
342 opt_string: "nested message inside a group"
343 }
Herbie Ong0dcfb9a2019-01-14 15:32:26 -0800344 OptNestedGroup: {
Herbie Ong8170d692019-02-13 14:13:21 -0800345 opt_fixed32: 47
Herbie Ong800c9902018-12-06 15:28:53 -0800346 }
347}
348`,
349 }, {
350 desc: "proto3 nested message not set",
351 input: &pb3.Nests{},
352 want: "\n",
353 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800354 desc: "proto3 nested message set to empty",
355 input: &pb3.Nests{
356 SNested: &pb3.Nested{},
357 },
358 want: "s_nested: {}\n",
359 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800360 desc: "proto3 nested message",
361 input: &pb3.Nests{
362 SNested: &pb3.Nested{
363 SString: "nested message",
364 SNested: &pb3.Nested{
365 SString: "another nested message",
366 },
367 },
368 },
369 want: `s_nested: {
370 s_string: "nested message"
371 s_nested: {
372 s_string: "another nested message"
373 }
374}
375`,
376 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700377 desc: "proto3 nested message contains invalid UTF-8",
378 input: &pb3.Nests{
379 SNested: &pb3.Nested{
380 SString: "abc\xff",
381 },
382 },
383 want: `s_nested: {
384 s_string: "abc\xff"
385}
386`,
387 wantErr: true,
388 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800389 desc: "oneof not set",
390 input: &pb3.Oneofs{},
Herbie Ong800c9902018-12-06 15:28:53 -0800391 want: "\n",
392 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800393 desc: "oneof set to empty string",
394 input: &pb3.Oneofs{
395 Union: &pb3.Oneofs_OneofString{},
Herbie Ong800c9902018-12-06 15:28:53 -0800396 },
Herbie Ong8170d692019-02-13 14:13:21 -0800397 want: `oneof_string: ""
398`,
Herbie Ong800c9902018-12-06 15:28:53 -0800399 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800400 desc: "oneof set to string",
401 input: &pb3.Oneofs{
402 Union: &pb3.Oneofs_OneofString{
403 OneofString: "hello",
Herbie Ong800c9902018-12-06 15:28:53 -0800404 },
405 },
Herbie Ong8170d692019-02-13 14:13:21 -0800406 want: `oneof_string: "hello"
407`,
Herbie Ong800c9902018-12-06 15:28:53 -0800408 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800409 desc: "oneof set to enum",
410 input: &pb3.Oneofs{
411 Union: &pb3.Oneofs_OneofEnum{
412 OneofEnum: pb3.Enum_ZERO,
Herbie Ong800c9902018-12-06 15:28:53 -0800413 },
414 },
Herbie Ong8170d692019-02-13 14:13:21 -0800415 want: `oneof_enum: ZERO
416`,
Herbie Ong800c9902018-12-06 15:28:53 -0800417 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800418 desc: "oneof set to empty message",
419 input: &pb3.Oneofs{
420 Union: &pb3.Oneofs_OneofNested{
421 OneofNested: &pb3.Nested{},
422 },
423 },
424 want: "oneof_nested: {}\n",
425 }, {
426 desc: "oneof set to message",
427 input: &pb3.Oneofs{
428 Union: &pb3.Oneofs_OneofNested{
429 OneofNested: &pb3.Nested{
430 SString: "nested message",
Herbie Ong800c9902018-12-06 15:28:53 -0800431 },
432 },
433 },
Herbie Ong8170d692019-02-13 14:13:21 -0800434 want: `oneof_nested: {
435 s_string: "nested message"
Herbie Ong800c9902018-12-06 15:28:53 -0800436}
437`,
438 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800439 desc: "repeated fields not set",
Herbie Ong800c9902018-12-06 15:28:53 -0800440 input: &pb2.Repeats{},
441 want: "\n",
442 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800443 desc: "repeated fields set to empty slices",
Herbie Ong800c9902018-12-06 15:28:53 -0800444 input: &pb2.Repeats{
Herbie Ongcddf8192018-11-28 18:25:20 -0800445 RptBool: []bool{},
446 RptInt32: []int32{},
447 RptInt64: []int64{},
448 RptUint32: []uint32{},
449 RptUint64: []uint64{},
450 RptFloat: []float32{},
451 RptDouble: []float64{},
452 RptBytes: [][]byte{},
Herbie Ong800c9902018-12-06 15:28:53 -0800453 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800454 want: "\n",
455 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800456 desc: "repeated fields set to some values",
Herbie Ong800c9902018-12-06 15:28:53 -0800457 input: &pb2.Repeats{
Herbie Ongcddf8192018-11-28 18:25:20 -0800458 RptBool: []bool{true, false, true, true},
459 RptInt32: []int32{1, 6, 0, 0},
460 RptInt64: []int64{-64, 47},
461 RptUint32: []uint32{0xff, 0xffff},
462 RptUint64: []uint64{0xdeadbeef},
Herbie Ong84f09602019-01-17 19:31:47 -0800463 RptFloat: []float32{float32(math.NaN()), float32(math.Inf(1)), float32(math.Inf(-1)), 1.034},
Herbie Ongcddf8192018-11-28 18:25:20 -0800464 RptDouble: []float64{math.NaN(), math.Inf(1), math.Inf(-1), 1.23e-308},
465 RptString: []string{"hello", "世界"},
466 RptBytes: [][]byte{
467 []byte("hello"),
468 []byte("\xe4\xb8\x96\xe7\x95\x8c"),
469 },
Herbie Ong800c9902018-12-06 15:28:53 -0800470 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800471 want: `rpt_bool: true
472rpt_bool: false
473rpt_bool: true
474rpt_bool: true
475rpt_int32: 1
476rpt_int32: 6
477rpt_int32: 0
478rpt_int32: 0
479rpt_int64: -64
480rpt_int64: 47
481rpt_uint32: 255
482rpt_uint32: 65535
483rpt_uint64: 3735928559
Herbie Ong84f09602019-01-17 19:31:47 -0800484rpt_float: nan
485rpt_float: inf
486rpt_float: -inf
487rpt_float: 1.034
Herbie Ongcddf8192018-11-28 18:25:20 -0800488rpt_double: nan
489rpt_double: inf
490rpt_double: -inf
491rpt_double: 1.23e-308
492rpt_string: "hello"
493rpt_string: "世界"
494rpt_bytes: "hello"
495rpt_bytes: "世界"
496`,
497 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700498 desc: "repeated contains invalid UTF-8",
499 input: &pb2.Repeats{
500 RptString: []string{"abc\xff"},
501 },
502 want: `rpt_string: "abc\xff"
503`,
504 wantErr: true,
505 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800506 desc: "repeated enums",
Herbie Ong800c9902018-12-06 15:28:53 -0800507 input: &pb2.Enums{
Herbie Ong8170d692019-02-13 14:13:21 -0800508 RptEnum: []pb2.Enum{pb2.Enum_ONE, 2, pb2.Enum_TEN, 42},
Herbie Ongcddf8192018-11-28 18:25:20 -0800509 RptNestedEnum: []pb2.Enums_NestedEnum{2, 47, 10},
Herbie Ong800c9902018-12-06 15:28:53 -0800510 },
Herbie Ong8170d692019-02-13 14:13:21 -0800511 want: `rpt_enum: ONE
512rpt_enum: TWO
513rpt_enum: TEN
Herbie Ongcddf8192018-11-28 18:25:20 -0800514rpt_enum: 42
Herbie Ongcddf8192018-11-28 18:25:20 -0800515rpt_nested_enum: DOS
516rpt_nested_enum: 47
517rpt_nested_enum: DIEZ
518`,
519 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800520 desc: "repeated messages set to empty",
Herbie Ong800c9902018-12-06 15:28:53 -0800521 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800522 RptNested: []*pb2.Nested{},
523 Rptgroup: []*pb2.Nests_RptGroup{},
Herbie Ong800c9902018-12-06 15:28:53 -0800524 },
525 want: "\n",
Herbie Ongcddf8192018-11-28 18:25:20 -0800526 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800527 desc: "repeated messages",
Herbie Ong800c9902018-12-06 15:28:53 -0800528 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800529 RptNested: []*pb2.Nested{
530 {
531 OptString: scalar.String("repeat nested one"),
532 },
533 {
534 OptString: scalar.String("repeat nested two"),
535 OptNested: &pb2.Nested{
536 OptString: scalar.String("inside repeat nested two"),
537 },
538 },
539 {},
540 },
Herbie Ong800c9902018-12-06 15:28:53 -0800541 },
542 want: `rpt_nested: {
Herbie Ongcddf8192018-11-28 18:25:20 -0800543 opt_string: "repeat nested one"
544}
545rpt_nested: {
546 opt_string: "repeat nested two"
547 opt_nested: {
548 opt_string: "inside repeat nested two"
549 }
550}
551rpt_nested: {}
552`,
553 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800554 desc: "repeated messages contains nil value",
Herbie Ongf5db2df2019-02-07 20:17:45 -0800555 input: &pb2.Nests{
556 RptNested: []*pb2.Nested{nil, {}},
557 },
558 want: `rpt_nested: {}
559rpt_nested: {}
560`,
561 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800562 desc: "repeated groups",
Herbie Ong800c9902018-12-06 15:28:53 -0800563 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800564 Rptgroup: []*pb2.Nests_RptGroup{
565 {
Herbie Ong8170d692019-02-13 14:13:21 -0800566 RptString: []string{"hello", "world"},
Herbie Ongcddf8192018-11-28 18:25:20 -0800567 },
568 {},
Herbie Ong8170d692019-02-13 14:13:21 -0800569 nil,
Herbie Ongcddf8192018-11-28 18:25:20 -0800570 },
Herbie Ong800c9902018-12-06 15:28:53 -0800571 },
Herbie Ongde7313b2019-01-14 19:26:50 -0800572 want: `RptGroup: {
Herbie Ong8170d692019-02-13 14:13:21 -0800573 rpt_string: "hello"
574 rpt_string: "world"
Herbie Ongcddf8192018-11-28 18:25:20 -0800575}
Herbie Ongde7313b2019-01-14 19:26:50 -0800576RptGroup: {}
Herbie Ong8170d692019-02-13 14:13:21 -0800577RptGroup: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800578`,
579 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800580 desc: "map fields not set",
581 input: &pb3.Maps{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800582 want: "\n",
583 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800584 desc: "map fields set to empty",
585 input: &pb3.Maps{
586 Int32ToStr: map[int32]string{},
587 BoolToUint32: map[bool]uint32{},
588 Uint64ToEnum: map[uint64]pb3.Enum{},
589 StrToNested: map[string]*pb3.Nested{},
590 StrToOneofs: map[string]*pb3.Oneofs{},
Herbie Ong800c9902018-12-06 15:28:53 -0800591 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800592 want: "\n",
593 }, {
594 desc: "map fields 1",
Herbie Ong8170d692019-02-13 14:13:21 -0800595 input: &pb3.Maps{
Herbie Ongcddf8192018-11-28 18:25:20 -0800596 Int32ToStr: map[int32]string{
597 -101: "-101",
598 0xff: "0xff",
599 0: "zero",
600 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800601 BoolToUint32: map[bool]uint32{
602 true: 42,
603 false: 101,
604 },
Herbie Ong800c9902018-12-06 15:28:53 -0800605 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800606 want: `int32_to_str: {
607 key: -101
608 value: "-101"
609}
610int32_to_str: {
611 key: 0
612 value: "zero"
613}
614int32_to_str: {
615 key: 255
616 value: "0xff"
617}
Herbie Ongcddf8192018-11-28 18:25:20 -0800618bool_to_uint32: {
619 key: false
620 value: 101
621}
622bool_to_uint32: {
623 key: true
624 value: 42
625}
626`,
627 }, {
628 desc: "map fields 2",
Herbie Ong8170d692019-02-13 14:13:21 -0800629 input: &pb3.Maps{
630 Uint64ToEnum: map[uint64]pb3.Enum{
631 1: pb3.Enum_ONE,
632 2: pb3.Enum_TWO,
633 10: pb3.Enum_TEN,
634 47: 47,
Herbie Ongcddf8192018-11-28 18:25:20 -0800635 },
Herbie Ong800c9902018-12-06 15:28:53 -0800636 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800637 want: `uint64_to_enum: {
638 key: 1
Herbie Ong8170d692019-02-13 14:13:21 -0800639 value: ONE
Herbie Ongcddf8192018-11-28 18:25:20 -0800640}
641uint64_to_enum: {
642 key: 2
Herbie Ong8170d692019-02-13 14:13:21 -0800643 value: TWO
Herbie Ongcddf8192018-11-28 18:25:20 -0800644}
645uint64_to_enum: {
646 key: 10
Herbie Ong8170d692019-02-13 14:13:21 -0800647 value: TEN
648}
649uint64_to_enum: {
650 key: 47
651 value: 47
Herbie Ongcddf8192018-11-28 18:25:20 -0800652}
653`,
654 }, {
655 desc: "map fields 3",
Herbie Ong8170d692019-02-13 14:13:21 -0800656 input: &pb3.Maps{
657 StrToNested: map[string]*pb3.Nested{
658 "nested": &pb3.Nested{
659 SString: "nested in a map",
Herbie Ongcddf8192018-11-28 18:25:20 -0800660 },
661 },
Herbie Ong800c9902018-12-06 15:28:53 -0800662 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800663 want: `str_to_nested: {
Herbie Ong8170d692019-02-13 14:13:21 -0800664 key: "nested"
Herbie Ongcddf8192018-11-28 18:25:20 -0800665 value: {
Herbie Ong8170d692019-02-13 14:13:21 -0800666 s_string: "nested in a map"
Herbie Ongcddf8192018-11-28 18:25:20 -0800667 }
668}
669`,
670 }, {
671 desc: "map fields 4",
Herbie Ong8170d692019-02-13 14:13:21 -0800672 input: &pb3.Maps{
673 StrToOneofs: map[string]*pb3.Oneofs{
674 "string": &pb3.Oneofs{
675 Union: &pb3.Oneofs_OneofString{
676 OneofString: "hello",
Herbie Ongcddf8192018-11-28 18:25:20 -0800677 },
678 },
Herbie Ong8170d692019-02-13 14:13:21 -0800679 "nested": &pb3.Oneofs{
680 Union: &pb3.Oneofs_OneofNested{
681 OneofNested: &pb3.Nested{
682 SString: "nested oneof in map field value",
Herbie Ongcddf8192018-11-28 18:25:20 -0800683 },
684 },
685 },
686 },
Herbie Ong800c9902018-12-06 15:28:53 -0800687 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800688 want: `str_to_oneofs: {
689 key: "nested"
690 value: {
Herbie Ong8170d692019-02-13 14:13:21 -0800691 oneof_nested: {
692 s_string: "nested oneof in map field value"
Herbie Ongcddf8192018-11-28 18:25:20 -0800693 }
694 }
695}
696str_to_oneofs: {
697 key: "string"
698 value: {
Herbie Ong8170d692019-02-13 14:13:21 -0800699 oneof_string: "hello"
Herbie Ongcddf8192018-11-28 18:25:20 -0800700 }
701}
702`,
703 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700704 desc: "map field value contains invalid UTF-8",
705 input: &pb3.Maps{
706 Int32ToStr: map[int32]string{
707 101: "abc\xff",
708 },
709 },
710 want: `int32_to_str: {
711 key: 101
712 value: "abc\xff"
713}
714`,
715 wantErr: true,
716 }, {
717 desc: "map field key contains invalid UTF-8",
718 input: &pb3.Maps{
719 StrToNested: map[string]*pb3.Nested{
720 "abc\xff": {},
721 },
722 },
723 want: `str_to_nested: {
724 key: "abc\xff"
725 value: {}
726}
727`,
728 wantErr: true,
729 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800730 desc: "map field contains nil value",
731 input: &pb3.Maps{
732 StrToNested: map[string]*pb3.Nested{
Herbie Ongf5db2df2019-02-07 20:17:45 -0800733 "nil": nil,
734 },
735 },
736 want: `str_to_nested: {
737 key: "nil"
738 value: {}
739}
740`,
741 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700742 desc: "required fields not set",
Herbie Ong800c9902018-12-06 15:28:53 -0800743 input: &pb2.Requireds{},
744 want: "\n",
745 wantErr: true,
Herbie Ongcddf8192018-11-28 18:25:20 -0800746 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700747 desc: "required fields partially set",
Herbie Ong800c9902018-12-06 15:28:53 -0800748 input: &pb2.Requireds{
749 ReqBool: scalar.Bool(false),
Herbie Ong800c9902018-12-06 15:28:53 -0800750 ReqSfixed64: scalar.Int64(0xbeefcafe),
751 ReqDouble: scalar.Float64(math.NaN()),
752 ReqString: scalar.String("hello"),
Herbie Ong8170d692019-02-13 14:13:21 -0800753 ReqEnum: pb2.Enum_ONE.Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800754 },
755 want: `req_bool: false
Herbie Ong800c9902018-12-06 15:28:53 -0800756req_sfixed64: 3203386110
757req_double: nan
758req_string: "hello"
Herbie Ong8170d692019-02-13 14:13:21 -0800759req_enum: ONE
Herbie Ong800c9902018-12-06 15:28:53 -0800760`,
761 wantErr: true,
762 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700763 desc: "required fields not set with AllowPartial",
764 mo: textpb.MarshalOptions{AllowPartial: true},
765 input: &pb2.Requireds{
766 ReqBool: scalar.Bool(false),
767 ReqSfixed64: scalar.Int64(0xbeefcafe),
768 ReqDouble: scalar.Float64(math.NaN()),
769 ReqString: scalar.String("hello"),
770 ReqEnum: pb2.Enum_ONE.Enum(),
771 },
772 want: `req_bool: false
773req_sfixed64: 3203386110
774req_double: nan
775req_string: "hello"
776req_enum: ONE
777`,
778 }, {
779 desc: "required fields all set",
Herbie Ong800c9902018-12-06 15:28:53 -0800780 input: &pb2.Requireds{
781 ReqBool: scalar.Bool(false),
Herbie Ong800c9902018-12-06 15:28:53 -0800782 ReqSfixed64: scalar.Int64(0),
Herbie Ong8170d692019-02-13 14:13:21 -0800783 ReqDouble: scalar.Float64(1.23),
Herbie Ong800c9902018-12-06 15:28:53 -0800784 ReqString: scalar.String(""),
Herbie Ong8170d692019-02-13 14:13:21 -0800785 ReqEnum: pb2.Enum_ONE.Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800786 ReqNested: &pb2.Nested{},
787 },
788 want: `req_bool: false
Herbie Ong800c9902018-12-06 15:28:53 -0800789req_sfixed64: 0
Herbie Ong8170d692019-02-13 14:13:21 -0800790req_double: 1.23
Herbie Ong800c9902018-12-06 15:28:53 -0800791req_string: ""
Herbie Ong8170d692019-02-13 14:13:21 -0800792req_enum: ONE
Herbie Ong800c9902018-12-06 15:28:53 -0800793req_nested: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800794`,
795 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800796 desc: "indirect required field",
797 input: &pb2.IndirectRequired{
798 OptNested: &pb2.NestedWithRequired{},
799 },
800 want: "opt_nested: {}\n",
801 wantErr: true,
Herbie Ongcddf8192018-11-28 18:25:20 -0800802 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700803 desc: "indirect required field with AllowPartial",
804 mo: textpb.MarshalOptions{AllowPartial: true},
805 input: &pb2.IndirectRequired{
806 OptNested: &pb2.NestedWithRequired{},
807 },
808 want: "opt_nested: {}\n",
809 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800810 desc: "indirect required field in empty repeated",
811 input: &pb2.IndirectRequired{
812 RptNested: []*pb2.NestedWithRequired{},
813 },
814 want: "\n",
Herbie Ongcddf8192018-11-28 18:25:20 -0800815 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800816 desc: "indirect required field in repeated",
817 input: &pb2.IndirectRequired{
818 RptNested: []*pb2.NestedWithRequired{
819 &pb2.NestedWithRequired{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800820 },
Herbie Ong800c9902018-12-06 15:28:53 -0800821 },
822 want: "rpt_nested: {}\n",
823 wantErr: true,
824 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700825 desc: "indirect required field in repeated with AllowPartial",
826 mo: textpb.MarshalOptions{AllowPartial: true},
827 input: &pb2.IndirectRequired{
828 RptNested: []*pb2.NestedWithRequired{
829 &pb2.NestedWithRequired{},
830 },
831 },
832 want: "rpt_nested: {}\n",
833 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800834 desc: "indirect required field in empty map",
835 input: &pb2.IndirectRequired{
836 StrToNested: map[string]*pb2.NestedWithRequired{},
837 },
838 want: "\n",
839 }, {
840 desc: "indirect required field in map",
841 input: &pb2.IndirectRequired{
842 StrToNested: map[string]*pb2.NestedWithRequired{
843 "fail": &pb2.NestedWithRequired{},
844 },
845 },
846 want: `str_to_nested: {
847 key: "fail"
848 value: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800849}
850`,
Herbie Ong800c9902018-12-06 15:28:53 -0800851 wantErr: true,
Herbie Ong20a1d312018-12-11 21:08:58 -0800852 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700853 desc: "indirect required field in map with AllowPartial",
854 mo: textpb.MarshalOptions{AllowPartial: true},
855 input: &pb2.IndirectRequired{
856 StrToNested: map[string]*pb2.NestedWithRequired{
857 "fail": &pb2.NestedWithRequired{},
858 },
859 },
860 want: `str_to_nested: {
861 key: "fail"
862 value: {}
863}
864`,
865 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800866 desc: "indirect required field in oneof",
867 input: &pb2.IndirectRequired{
868 Union: &pb2.IndirectRequired_OneofNested{
869 OneofNested: &pb2.NestedWithRequired{},
870 },
871 },
872 want: "oneof_nested: {}\n",
873 wantErr: true,
874 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700875 desc: "indirect required field in oneof with AllowPartial",
876 mo: textpb.MarshalOptions{AllowPartial: true},
877 input: &pb2.IndirectRequired{
878 Union: &pb2.IndirectRequired_OneofNested{
879 OneofNested: &pb2.NestedWithRequired{},
880 },
881 },
882 want: "oneof_nested: {}\n",
883 }, {
Herbie Ong20a1d312018-12-11 21:08:58 -0800884 desc: "unknown varint and fixed types",
885 input: &pb2.Scalars{
886 OptString: scalar.String("this message contains unknown fields"),
887 XXX_unrecognized: pack.Message{
888 pack.Tag{101, pack.VarintType}, pack.Bool(true),
889 pack.Tag{102, pack.VarintType}, pack.Varint(0xff),
890 pack.Tag{103, pack.Fixed32Type}, pack.Uint32(47),
891 pack.Tag{104, pack.Fixed64Type}, pack.Int64(0xdeadbeef),
892 }.Marshal(),
893 },
894 want: `opt_string: "this message contains unknown fields"
895101: 1
896102: 255
897103: 47
898104: 3735928559
899`,
900 }, {
901 desc: "unknown length-delimited",
902 input: &pb2.Scalars{
903 XXX_unrecognized: pack.Message{
904 pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false)},
905 pack.Tag{102, pack.BytesType}, pack.String("hello world"),
906 pack.Tag{103, pack.BytesType}, pack.Bytes("\xe4\xb8\x96\xe7\x95\x8c"),
907 }.Marshal(),
908 },
909 want: `101: "\x01\x00"
910102: "hello world"
911103: "世界"
912`,
913 }, {
914 desc: "unknown group type",
915 input: &pb2.Scalars{
916 XXX_unrecognized: pack.Message{
917 pack.Tag{101, pack.StartGroupType}, pack.Tag{101, pack.EndGroupType},
918 pack.Tag{102, pack.StartGroupType},
919 pack.Tag{101, pack.VarintType}, pack.Bool(false),
920 pack.Tag{102, pack.BytesType}, pack.String("inside a group"),
921 pack.Tag{102, pack.EndGroupType},
922 }.Marshal(),
923 },
924 want: `101: {}
925102: {
926 101: 0
927 102: "inside a group"
928}
929`,
930 }, {
931 desc: "unknown unpack repeated field",
932 input: &pb2.Scalars{
933 XXX_unrecognized: pack.Message{
934 pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false), pack.Bool(true)},
935 pack.Tag{102, pack.BytesType}, pack.String("hello"),
936 pack.Tag{101, pack.VarintType}, pack.Bool(true),
937 pack.Tag{102, pack.BytesType}, pack.String("世界"),
938 }.Marshal(),
939 },
940 want: `101: "\x01\x00\x01"
941101: 1
942102: "hello"
943102: "世界"
944`,
Herbie Ongcf253082018-12-17 17:13:07 -0800945 }, {
946 desc: "extensions of non-repeated fields",
947 input: func() proto.Message {
948 m := &pb2.Extensions{
949 OptString: scalar.String("non-extension field"),
950 OptBool: scalar.Bool(true),
951 OptInt32: scalar.Int32(42),
952 }
953 setExtension(m, pb2.E_OptExtBool, true)
954 setExtension(m, pb2.E_OptExtString, "extension field")
Herbie Ong8170d692019-02-13 14:13:21 -0800955 setExtension(m, pb2.E_OptExtEnum, pb2.Enum_TEN)
Herbie Ongcf253082018-12-17 17:13:07 -0800956 setExtension(m, pb2.E_OptExtNested, &pb2.Nested{
957 OptString: scalar.String("nested in an extension"),
958 OptNested: &pb2.Nested{
959 OptString: scalar.String("another nested in an extension"),
960 },
961 })
962 return m
963 }(),
964 want: `opt_string: "non-extension field"
965opt_bool: true
966opt_int32: 42
967[pb2.opt_ext_bool]: true
Herbie Ong8170d692019-02-13 14:13:21 -0800968[pb2.opt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -0800969[pb2.opt_ext_nested]: {
970 opt_string: "nested in an extension"
971 opt_nested: {
972 opt_string: "another nested in an extension"
973 }
974}
975[pb2.opt_ext_string]: "extension field"
976`,
977 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700978 desc: "extension field contains invalid UTF-8",
979 input: func() proto.Message {
980 m := &pb2.Extensions{}
981 setExtension(m, pb2.E_OptExtString, "abc\xff")
982 return m
983 }(),
984 want: `[pb2.opt_ext_string]: "abc\xff"
985`,
986 wantErr: true,
987 }, {
Herbie Ong09b28a92019-04-03 15:42:41 -0700988 desc: "extension partial returns error",
989 input: func() proto.Message {
990 m := &pb2.Extensions{}
991 setExtension(m, pb2.E_OptExtPartial, &pb2.PartialRequired{
992 OptString: scalar.String("partial1"),
993 })
994 setExtension(m, pb2.E_ExtensionsContainer_OptExtPartial, &pb2.PartialRequired{
995 OptString: scalar.String("partial2"),
996 })
997 return m
998 }(),
999 want: `[pb2.ExtensionsContainer.opt_ext_partial]: {
1000 opt_string: "partial2"
1001}
1002[pb2.opt_ext_partial]: {
1003 opt_string: "partial1"
1004}
1005`,
1006 wantErr: true,
1007 }, {
1008 desc: "extension partial with AllowPartial",
1009 mo: textpb.MarshalOptions{AllowPartial: true},
1010 input: func() proto.Message {
1011 m := &pb2.Extensions{}
1012 setExtension(m, pb2.E_OptExtPartial, &pb2.PartialRequired{
1013 OptString: scalar.String("partial1"),
1014 })
1015 return m
1016 }(),
1017 want: `[pb2.opt_ext_partial]: {
1018 opt_string: "partial1"
1019}
1020`,
1021 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001022 desc: "extension message field set to nil",
Herbie Ongcf253082018-12-17 17:13:07 -08001023 input: func() proto.Message {
1024 m := &pb2.Extensions{}
1025 setExtension(m, pb2.E_OptExtNested, nil)
1026 return m
1027 }(),
1028 want: "\n",
1029 }, {
1030 desc: "extensions of repeated fields",
1031 input: func() proto.Message {
1032 m := &pb2.Extensions{}
Herbie Ong8170d692019-02-13 14:13:21 -08001033 setExtension(m, pb2.E_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
Herbie Ongcf253082018-12-17 17:13:07 -08001034 setExtension(m, pb2.E_RptExtFixed32, &[]uint32{42, 47})
1035 setExtension(m, pb2.E_RptExtNested, &[]*pb2.Nested{
1036 &pb2.Nested{OptString: scalar.String("one")},
1037 &pb2.Nested{OptString: scalar.String("two")},
1038 &pb2.Nested{OptString: scalar.String("three")},
1039 })
1040 return m
1041 }(),
Herbie Ong8170d692019-02-13 14:13:21 -08001042 want: `[pb2.rpt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -08001043[pb2.rpt_ext_enum]: 101
Herbie Ong8170d692019-02-13 14:13:21 -08001044[pb2.rpt_ext_enum]: ONE
Herbie Ongcf253082018-12-17 17:13:07 -08001045[pb2.rpt_ext_fixed32]: 42
1046[pb2.rpt_ext_fixed32]: 47
1047[pb2.rpt_ext_nested]: {
1048 opt_string: "one"
1049}
1050[pb2.rpt_ext_nested]: {
1051 opt_string: "two"
1052}
1053[pb2.rpt_ext_nested]: {
1054 opt_string: "three"
1055}
1056`,
1057 }, {
1058 desc: "extensions of non-repeated fields in another message",
1059 input: func() proto.Message {
1060 m := &pb2.Extensions{}
1061 setExtension(m, pb2.E_ExtensionsContainer_OptExtBool, true)
1062 setExtension(m, pb2.E_ExtensionsContainer_OptExtString, "extension field")
Herbie Ong8170d692019-02-13 14:13:21 -08001063 setExtension(m, pb2.E_ExtensionsContainer_OptExtEnum, pb2.Enum_TEN)
Herbie Ongcf253082018-12-17 17:13:07 -08001064 setExtension(m, pb2.E_ExtensionsContainer_OptExtNested, &pb2.Nested{
1065 OptString: scalar.String("nested in an extension"),
1066 OptNested: &pb2.Nested{
1067 OptString: scalar.String("another nested in an extension"),
1068 },
1069 })
1070 return m
1071 }(),
1072 want: `[pb2.ExtensionsContainer.opt_ext_bool]: true
Herbie Ong8170d692019-02-13 14:13:21 -08001073[pb2.ExtensionsContainer.opt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -08001074[pb2.ExtensionsContainer.opt_ext_nested]: {
1075 opt_string: "nested in an extension"
1076 opt_nested: {
1077 opt_string: "another nested in an extension"
1078 }
1079}
1080[pb2.ExtensionsContainer.opt_ext_string]: "extension field"
1081`,
1082 }, {
1083 desc: "extensions of repeated fields in another message",
1084 input: func() proto.Message {
1085 m := &pb2.Extensions{
1086 OptString: scalar.String("non-extension field"),
1087 OptBool: scalar.Bool(true),
1088 OptInt32: scalar.Int32(42),
1089 }
Herbie Ong8170d692019-02-13 14:13:21 -08001090 setExtension(m, pb2.E_ExtensionsContainer_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
Herbie Ongcf253082018-12-17 17:13:07 -08001091 setExtension(m, pb2.E_ExtensionsContainer_RptExtString, &[]string{"hello", "world"})
1092 setExtension(m, pb2.E_ExtensionsContainer_RptExtNested, &[]*pb2.Nested{
1093 &pb2.Nested{OptString: scalar.String("one")},
1094 &pb2.Nested{OptString: scalar.String("two")},
1095 &pb2.Nested{OptString: scalar.String("three")},
1096 })
1097 return m
1098 }(),
1099 want: `opt_string: "non-extension field"
1100opt_bool: true
1101opt_int32: 42
Herbie Ong8170d692019-02-13 14:13:21 -08001102[pb2.ExtensionsContainer.rpt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -08001103[pb2.ExtensionsContainer.rpt_ext_enum]: 101
Herbie Ong8170d692019-02-13 14:13:21 -08001104[pb2.ExtensionsContainer.rpt_ext_enum]: ONE
Herbie Ongcf253082018-12-17 17:13:07 -08001105[pb2.ExtensionsContainer.rpt_ext_nested]: {
1106 opt_string: "one"
1107}
1108[pb2.ExtensionsContainer.rpt_ext_nested]: {
1109 opt_string: "two"
1110}
1111[pb2.ExtensionsContainer.rpt_ext_nested]: {
1112 opt_string: "three"
1113}
1114[pb2.ExtensionsContainer.rpt_ext_string]: "hello"
1115[pb2.ExtensionsContainer.rpt_ext_string]: "world"
1116`,
Herbie Ong6470ea62019-01-07 18:56:57 -08001117 }, {
1118 desc: "MessageSet",
1119 input: func() proto.Message {
1120 m := &pb2.MessageSet{}
1121 setExtension(m, pb2.E_MessageSetExtension_MessageSetExtension, &pb2.MessageSetExtension{
1122 OptString: scalar.String("a messageset extension"),
1123 })
1124 setExtension(m, pb2.E_MessageSetExtension_NotMessageSetExtension, &pb2.MessageSetExtension{
1125 OptString: scalar.String("not a messageset extension"),
1126 })
1127 setExtension(m, pb2.E_MessageSetExtension_ExtNested, &pb2.Nested{
1128 OptString: scalar.String("just a regular extension"),
1129 })
1130 return m
1131 }(),
1132 want: `[pb2.MessageSetExtension]: {
1133 opt_string: "a messageset extension"
1134}
1135[pb2.MessageSetExtension.ext_nested]: {
1136 opt_string: "just a regular extension"
1137}
1138[pb2.MessageSetExtension.not_message_set_extension]: {
1139 opt_string: "not a messageset extension"
1140}
1141`,
1142 }, {
1143 desc: "not real MessageSet 1",
1144 input: func() proto.Message {
1145 m := &pb2.FakeMessageSet{}
1146 setExtension(m, pb2.E_FakeMessageSetExtension_MessageSetExtension, &pb2.FakeMessageSetExtension{
1147 OptString: scalar.String("not a messageset extension"),
1148 })
1149 return m
1150 }(),
1151 want: `[pb2.FakeMessageSetExtension.message_set_extension]: {
1152 opt_string: "not a messageset extension"
1153}
1154`,
1155 }, {
1156 desc: "not real MessageSet 2",
1157 input: func() proto.Message {
1158 m := &pb2.MessageSet{}
1159 setExtension(m, pb2.E_MessageSetExtension, &pb2.FakeMessageSetExtension{
1160 OptString: scalar.String("another not a messageset extension"),
1161 })
1162 return m
1163 }(),
1164 want: `[pb2.message_set_extension]: {
1165 opt_string: "another not a messageset extension"
1166}
1167`,
Herbie Ongf42b55f2019-01-02 15:46:07 -08001168 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001169 desc: "Any not expanded",
Herbie Ong66c365c2019-01-04 14:08:41 -08001170 mo: textpb.MarshalOptions{
1171 Resolver: preg.NewTypes(),
1172 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001173 input: func() proto.Message {
1174 m := &pb2.Nested{
1175 OptString: scalar.String("embedded inside Any"),
1176 OptNested: &pb2.Nested{
1177 OptString: scalar.String("inception"),
1178 },
1179 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -07001180 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ongf42b55f2019-01-02 15:46:07 -08001181 if err != nil {
1182 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1183 }
Herbie Ong300cff02019-03-20 18:05:16 -07001184 return &knownpb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001185 TypeUrl: "pb2.Nested",
Herbie Ongf42b55f2019-01-02 15:46:07 -08001186 Value: b,
Herbie Ong300cff02019-03-20 18:05:16 -07001187 }
Herbie Ongf42b55f2019-01-02 15:46:07 -08001188 }(),
1189 want: `type_url: "pb2.Nested"
1190value: "\n\x13embedded inside Any\x12\x0b\n\tinception"
1191`,
1192 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001193 desc: "Any expanded",
Herbie Ong66c365c2019-01-04 14:08:41 -08001194 mo: textpb.MarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001195 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
Herbie Ong66c365c2019-01-04 14:08:41 -08001196 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001197 input: func() proto.Message {
1198 m := &pb2.Nested{
1199 OptString: scalar.String("embedded inside Any"),
1200 OptNested: &pb2.Nested{
1201 OptString: scalar.String("inception"),
1202 },
1203 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -07001204 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ongf42b55f2019-01-02 15:46:07 -08001205 if err != nil {
1206 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1207 }
Herbie Ong300cff02019-03-20 18:05:16 -07001208 return &knownpb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001209 TypeUrl: "foo/pb2.Nested",
Herbie Ongf42b55f2019-01-02 15:46:07 -08001210 Value: b,
Herbie Ong300cff02019-03-20 18:05:16 -07001211 }
Herbie Ongf42b55f2019-01-02 15:46:07 -08001212 }(),
Herbie Ong66c365c2019-01-04 14:08:41 -08001213 want: `[foo/pb2.Nested]: {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001214 opt_string: "embedded inside Any"
1215 opt_nested: {
1216 opt_string: "inception"
1217 }
1218}
1219`,
1220 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001221 desc: "Any expanded with missing required error",
Herbie Ong66c365c2019-01-04 14:08:41 -08001222 mo: textpb.MarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001223 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.PartialRequired{})),
Herbie Ong66c365c2019-01-04 14:08:41 -08001224 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001225 input: func() proto.Message {
1226 m := &pb2.PartialRequired{
1227 OptString: scalar.String("embedded inside Any"),
1228 }
Damien Neil96c229a2019-04-03 12:17:24 -07001229 b, err := proto.MarshalOptions{
1230 AllowPartial: true,
1231 Deterministic: true,
1232 }.Marshal(m)
Herbie Ong300cff02019-03-20 18:05:16 -07001233 if err != nil {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001234 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1235 }
Herbie Ong300cff02019-03-20 18:05:16 -07001236 return &knownpb.Any{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001237 TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
Herbie Ongf42b55f2019-01-02 15:46:07 -08001238 Value: b,
Herbie Ong300cff02019-03-20 18:05:16 -07001239 }
Herbie Ongf42b55f2019-01-02 15:46:07 -08001240 }(),
1241 want: `[pb2.PartialRequired]: {
1242 opt_string: "embedded inside Any"
1243}
1244`,
1245 wantErr: true,
1246 }, {
Herbie Ong21a39742019-04-08 17:32:44 -07001247 desc: "Any with invalid UTF-8",
1248 mo: textpb.MarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001249 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb3.Nested{})),
Herbie Ong21a39742019-04-08 17:32:44 -07001250 },
1251 input: func() proto.Message {
1252 m := &pb3.Nested{
Damien Neilbc310b52019-04-11 11:46:55 -07001253 SString: "abcd",
Herbie Ong21a39742019-04-08 17:32:44 -07001254 }
1255 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
1256 if err != nil {
1257 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1258 }
1259 return &knownpb.Any{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001260 TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
Damien Neilbc310b52019-04-11 11:46:55 -07001261 Value: bytes.Replace(b, []byte("abcd"), []byte("abc\xff"), -1),
Herbie Ong21a39742019-04-08 17:32:44 -07001262 }
1263 }(),
1264 want: `[pb3.Nested]: {
1265 s_string: "abc\xff"
1266}
1267`,
1268 wantErr: true,
1269 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001270 desc: "Any with invalid value",
Herbie Ong66c365c2019-01-04 14:08:41 -08001271 mo: textpb.MarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001272 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
Herbie Ong66c365c2019-01-04 14:08:41 -08001273 },
Herbie Ong300cff02019-03-20 18:05:16 -07001274 input: &knownpb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001275 TypeUrl: "foo/pb2.Nested",
1276 Value: dhex("80"),
Herbie Ong300cff02019-03-20 18:05:16 -07001277 },
Herbie Ong66c365c2019-01-04 14:08:41 -08001278 want: `type_url: "foo/pb2.Nested"
Herbie Onga94f78c2019-01-03 15:39:58 -08001279value: "\x80"
1280`,
Herbie Ongcddf8192018-11-28 18:25:20 -08001281 }}
1282
1283 for _, tt := range tests {
1284 tt := tt
1285 t.Run(tt.desc, func(t *testing.T) {
Herbie Ong3a385912019-03-20 14:04:24 -07001286 // Use 2-space indentation on all MarshalOptions.
1287 tt.mo.Indent = " "
Herbie Ongf42b55f2019-01-02 15:46:07 -08001288 b, err := tt.mo.Marshal(tt.input)
Herbie Ongcddf8192018-11-28 18:25:20 -08001289 if err != nil && !tt.wantErr {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001290 t.Errorf("Marshal() returned error: %v\n", err)
Herbie Ongcddf8192018-11-28 18:25:20 -08001291 }
Herbie Ong800c9902018-12-06 15:28:53 -08001292 if err == nil && tt.wantErr {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001293 t.Error("Marshal() got nil error, want error\n")
Herbie Ongcddf8192018-11-28 18:25:20 -08001294 }
Herbie Ong800c9902018-12-06 15:28:53 -08001295 got := string(b)
1296 if tt.want != "" && got != tt.want {
1297 t.Errorf("Marshal()\n<got>\n%v\n<want>\n%v\n", got, tt.want)
1298 if diff := cmp.Diff(tt.want, got, splitLines); diff != "" {
Herbie Ongcddf8192018-11-28 18:25:20 -08001299 t.Errorf("Marshal() diff -want +got\n%v\n", diff)
1300 }
1301 }
1302 })
1303 }
1304}