blob: 1bbf7f8eb37ff2140f4a5973c19e6be8e9e58d0e [file] [log] [blame]
Herbie Ongcddf8192018-11-28 18:25:20 -08001// Copyright 2018 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
Damien Neil5c5b5312019-05-14 12:44:37 -07005package prototext_test
Herbie Ongcddf8192018-11-28 18:25:20 -08006
7import (
8 "math"
Herbie Ongcddf8192018-11-28 18:25:20 -08009 "testing"
10
Herbie Ongcddf8192018-11-28 18:25:20 -080011 "github.com/google/go-cmp/cmp"
Damien Neil5c5b5312019-05-14 12:44:37 -070012 "google.golang.org/protobuf/encoding/prototext"
Damien Neile89e6242019-05-13 23:55:40 -070013 "google.golang.org/protobuf/internal/detrand"
14 "google.golang.org/protobuf/internal/encoding/pack"
Damien Neile89e6242019-05-13 23:55:40 -070015 pimpl "google.golang.org/protobuf/internal/impl"
16 "google.golang.org/protobuf/internal/scalar"
17 "google.golang.org/protobuf/proto"
18 preg "google.golang.org/protobuf/reflect/protoregistry"
19 "google.golang.org/protobuf/runtime/protoiface"
Herbie Ongcddf8192018-11-28 18:25:20 -080020
Damien Neile89e6242019-05-13 23:55:40 -070021 "google.golang.org/protobuf/encoding/testprotos/pb2"
22 "google.golang.org/protobuf/encoding/testprotos/pb3"
Joe Tsaia95b29f2019-05-16 12:47:20 -070023 "google.golang.org/protobuf/types/known/anypb"
Herbie Ongcddf8192018-11-28 18:25:20 -080024)
25
26func init() {
27 // Disable detrand to enable direct comparisons on outputs.
28 detrand.Disable()
29}
30
Joe Tsai378c1322019-04-25 23:48:08 -070031// TODO: Use proto.SetExtension when available.
Joe Tsai4fddeba2019-03-20 18:29:32 -070032func setExtension(m proto.Message, xd *protoiface.ExtensionDescV1, val interface{}) {
Joe Tsai378c1322019-04-25 23:48:08 -070033 m.ProtoReflect().Set(xd.Type, xd.Type.ValueOf(val))
Herbie Ongcf253082018-12-17 17:13:07 -080034}
35
Herbie Ongcddf8192018-11-28 18:25:20 -080036func TestMarshal(t *testing.T) {
37 tests := []struct {
38 desc string
Damien Neil5c5b5312019-05-14 12:44:37 -070039 mo prototext.MarshalOptions
Herbie Ong70651952018-12-13 14:19:50 -080040 input proto.Message
Herbie Ongcddf8192018-11-28 18:25:20 -080041 want string
Herbie Ong300cff02019-03-20 18:05:16 -070042 wantErr bool // TODO: Verify error message content.
Herbie Ongcddf8192018-11-28 18:25:20 -080043 }{{
Herbie Ong8170d692019-02-13 14:13:21 -080044 desc: "proto2 optional scalars not set",
Herbie Ong800c9902018-12-06 15:28:53 -080045 input: &pb2.Scalars{},
Herbie Ongcddf8192018-11-28 18:25:20 -080046 want: "\n",
47 }, {
Herbie Ong8170d692019-02-13 14:13:21 -080048 desc: "proto3 scalars not set",
Herbie Ong800c9902018-12-06 15:28:53 -080049 input: &pb3.Scalars{},
Herbie Ongcddf8192018-11-28 18:25:20 -080050 want: "\n",
51 }, {
Herbie Ong8170d692019-02-13 14:13:21 -080052 desc: "proto2 optional scalars set to zero values",
Herbie Ong800c9902018-12-06 15:28:53 -080053 input: &pb2.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -080054 OptBool: scalar.Bool(false),
55 OptInt32: scalar.Int32(0),
56 OptInt64: scalar.Int64(0),
57 OptUint32: scalar.Uint32(0),
58 OptUint64: scalar.Uint64(0),
59 OptSint32: scalar.Int32(0),
60 OptSint64: scalar.Int64(0),
61 OptFixed32: scalar.Uint32(0),
62 OptFixed64: scalar.Uint64(0),
63 OptSfixed32: scalar.Int32(0),
64 OptSfixed64: scalar.Int64(0),
65 OptFloat: scalar.Float32(0),
66 OptDouble: scalar.Float64(0),
67 OptBytes: []byte{},
68 OptString: scalar.String(""),
Herbie Ong800c9902018-12-06 15:28:53 -080069 },
Herbie Ongcddf8192018-11-28 18:25:20 -080070 want: `opt_bool: false
71opt_int32: 0
72opt_int64: 0
73opt_uint32: 0
74opt_uint64: 0
75opt_sint32: 0
76opt_sint64: 0
77opt_fixed32: 0
78opt_fixed64: 0
79opt_sfixed32: 0
80opt_sfixed64: 0
81opt_float: 0
82opt_double: 0
83opt_bytes: ""
84opt_string: ""
85`,
86 }, {
Herbie Ong8170d692019-02-13 14:13:21 -080087 desc: "proto3 scalars set to zero values",
Herbie Ong800c9902018-12-06 15:28:53 -080088 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -080089 SBool: false,
90 SInt32: 0,
91 SInt64: 0,
92 SUint32: 0,
93 SUint64: 0,
94 SSint32: 0,
95 SSint64: 0,
96 SFixed32: 0,
97 SFixed64: 0,
98 SSfixed32: 0,
99 SSfixed64: 0,
100 SFloat: 0,
101 SDouble: 0,
102 SBytes: []byte{},
103 SString: "",
Herbie Ong800c9902018-12-06 15:28:53 -0800104 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800105 want: "\n",
106 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800107 desc: "proto2 optional scalars set to some values",
Herbie Ong800c9902018-12-06 15:28:53 -0800108 input: &pb2.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800109 OptBool: scalar.Bool(true),
110 OptInt32: scalar.Int32(0xff),
111 OptInt64: scalar.Int64(0xdeadbeef),
112 OptUint32: scalar.Uint32(47),
113 OptUint64: scalar.Uint64(0xdeadbeef),
114 OptSint32: scalar.Int32(-1001),
115 OptSint64: scalar.Int64(-0xffff),
116 OptFixed64: scalar.Uint64(64),
117 OptSfixed32: scalar.Int32(-32),
Herbie Ong84f09602019-01-17 19:31:47 -0800118 OptFloat: scalar.Float32(1.02),
119 OptDouble: scalar.Float64(1.0199999809265137),
Herbie Ong8170d692019-02-13 14:13:21 -0800120 OptBytes: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
121 OptString: scalar.String("谷歌"),
Herbie Ong800c9902018-12-06 15:28:53 -0800122 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800123 want: `opt_bool: true
124opt_int32: 255
125opt_int64: 3735928559
126opt_uint32: 47
127opt_uint64: 3735928559
128opt_sint32: -1001
129opt_sint64: -65535
130opt_fixed64: 64
131opt_sfixed32: -32
Herbie Ong84f09602019-01-17 19:31:47 -0800132opt_float: 1.02
133opt_double: 1.0199999809265137
Herbie Ongcddf8192018-11-28 18:25:20 -0800134opt_bytes: "谷歌"
135opt_string: "谷歌"
136`,
137 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700138 desc: "string with invalid UTF-8",
139 input: &pb3.Scalars{
140 SString: "abc\xff",
141 },
Herbie Ong21a39742019-04-08 17:32:44 -0700142 wantErr: true,
143 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800144 desc: "float nan",
Herbie Ong800c9902018-12-06 15:28:53 -0800145 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800146 SFloat: float32(math.NaN()),
Herbie Ong800c9902018-12-06 15:28:53 -0800147 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800148 want: "s_float: nan\n",
149 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800150 desc: "float positive infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800151 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800152 SFloat: float32(math.Inf(1)),
Herbie Ong800c9902018-12-06 15:28:53 -0800153 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800154 want: "s_float: inf\n",
155 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800156 desc: "float negative infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800157 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800158 SFloat: float32(math.Inf(-1)),
Herbie Ong800c9902018-12-06 15:28:53 -0800159 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800160 want: "s_float: -inf\n",
161 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800162 desc: "double nan",
Herbie Ong800c9902018-12-06 15:28:53 -0800163 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800164 SDouble: math.NaN(),
Herbie Ong800c9902018-12-06 15:28:53 -0800165 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800166 want: "s_double: nan\n",
167 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800168 desc: "double positive infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800169 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800170 SDouble: math.Inf(1),
Herbie Ong800c9902018-12-06 15:28:53 -0800171 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800172 want: "s_double: inf\n",
173 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800174 desc: "double negative infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800175 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800176 SDouble: math.Inf(-1),
Herbie Ong800c9902018-12-06 15:28:53 -0800177 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800178 want: "s_double: -inf\n",
179 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800180 desc: "proto2 enum not set",
181 input: &pb2.Enums{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800182 want: "\n",
183 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800184 desc: "proto2 enum set to zero value",
185 input: &pb2.Enums{
Joe Tsai6dc168e2019-07-09 23:11:13 -0700186 OptEnum: pb2.Enum(0).Enum(),
187 OptNestedEnum: pb2.Enums_NestedEnum(0).Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800188 },
Herbie Ong8170d692019-02-13 14:13:21 -0800189 want: `opt_enum: 0
Herbie Ong800c9902018-12-06 15:28:53 -0800190opt_nested_enum: 0
191`,
192 }, {
193 desc: "proto2 enum",
194 input: &pb2.Enums{
Herbie Ong8170d692019-02-13 14:13:21 -0800195 OptEnum: pb2.Enum_ONE.Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800196 OptNestedEnum: pb2.Enums_UNO.Enum(),
197 },
Herbie Ong8170d692019-02-13 14:13:21 -0800198 want: `opt_enum: ONE
Herbie Ong800c9902018-12-06 15:28:53 -0800199opt_nested_enum: UNO
200`,
201 }, {
202 desc: "proto2 enum set to numeric values",
203 input: &pb2.Enums{
Joe Tsai6dc168e2019-07-09 23:11:13 -0700204 OptEnum: pb2.Enum(2).Enum(),
205 OptNestedEnum: pb2.Enums_NestedEnum(2).Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800206 },
Herbie Ong8170d692019-02-13 14:13:21 -0800207 want: `opt_enum: TWO
Herbie Ong800c9902018-12-06 15:28:53 -0800208opt_nested_enum: DOS
209`,
210 }, {
211 desc: "proto2 enum set to unnamed numeric values",
212 input: &pb2.Enums{
Joe Tsai6dc168e2019-07-09 23:11:13 -0700213 OptEnum: pb2.Enum(101).Enum(),
214 OptNestedEnum: pb2.Enums_NestedEnum(-101).Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800215 },
216 want: `opt_enum: 101
217opt_nested_enum: -101
218`,
219 }, {
220 desc: "proto3 enum not set",
221 input: &pb3.Enums{},
222 want: "\n",
223 }, {
224 desc: "proto3 enum set to zero value",
225 input: &pb3.Enums{
226 SEnum: pb3.Enum_ZERO,
227 SNestedEnum: pb3.Enums_CERO,
228 },
229 want: "\n",
230 }, {
231 desc: "proto3 enum",
232 input: &pb3.Enums{
233 SEnum: pb3.Enum_ONE,
Herbie Ong8170d692019-02-13 14:13:21 -0800234 SNestedEnum: pb3.Enums_UNO,
Herbie Ong800c9902018-12-06 15:28:53 -0800235 },
236 want: `s_enum: ONE
Herbie Ong8170d692019-02-13 14:13:21 -0800237s_nested_enum: UNO
Herbie Ong800c9902018-12-06 15:28:53 -0800238`,
239 }, {
240 desc: "proto3 enum set to numeric values",
241 input: &pb3.Enums{
242 SEnum: 2,
Herbie Ong8170d692019-02-13 14:13:21 -0800243 SNestedEnum: 2,
Herbie Ong800c9902018-12-06 15:28:53 -0800244 },
245 want: `s_enum: TWO
Herbie Ong8170d692019-02-13 14:13:21 -0800246s_nested_enum: DOS
Herbie Ong800c9902018-12-06 15:28:53 -0800247`,
248 }, {
249 desc: "proto3 enum set to unnamed numeric values",
250 input: &pb3.Enums{
251 SEnum: -47,
252 SNestedEnum: 47,
253 },
254 want: `s_enum: -47
255s_nested_enum: 47
256`,
257 }, {
258 desc: "proto2 nested message not set",
259 input: &pb2.Nests{},
260 want: "\n",
261 }, {
262 desc: "proto2 nested message set to empty",
263 input: &pb2.Nests{
264 OptNested: &pb2.Nested{},
265 Optgroup: &pb2.Nests_OptGroup{},
266 },
267 want: `opt_nested: {}
Herbie Ong0dcfb9a2019-01-14 15:32:26 -0800268OptGroup: {}
Herbie Ong800c9902018-12-06 15:28:53 -0800269`,
270 }, {
271 desc: "proto2 nested messages",
272 input: &pb2.Nests{
273 OptNested: &pb2.Nested{
274 OptString: scalar.String("nested message"),
275 OptNested: &pb2.Nested{
276 OptString: scalar.String("another nested message"),
277 },
278 },
279 },
280 want: `opt_nested: {
281 opt_string: "nested message"
282 opt_nested: {
283 opt_string: "another nested message"
284 }
285}
286`,
287 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800288 desc: "proto2 groups",
Herbie Ong800c9902018-12-06 15:28:53 -0800289 input: &pb2.Nests{
290 Optgroup: &pb2.Nests_OptGroup{
Herbie Ong800c9902018-12-06 15:28:53 -0800291 OptString: scalar.String("inside a group"),
292 OptNested: &pb2.Nested{
293 OptString: scalar.String("nested message inside a group"),
294 },
295 Optnestedgroup: &pb2.Nests_OptGroup_OptNestedGroup{
Herbie Ong8170d692019-02-13 14:13:21 -0800296 OptFixed32: scalar.Uint32(47),
Herbie Ong800c9902018-12-06 15:28:53 -0800297 },
298 },
299 },
Herbie Ong0dcfb9a2019-01-14 15:32:26 -0800300 want: `OptGroup: {
Herbie Ong800c9902018-12-06 15:28:53 -0800301 opt_string: "inside a group"
302 opt_nested: {
303 opt_string: "nested message inside a group"
304 }
Herbie Ong0dcfb9a2019-01-14 15:32:26 -0800305 OptNestedGroup: {
Herbie Ong8170d692019-02-13 14:13:21 -0800306 opt_fixed32: 47
Herbie Ong800c9902018-12-06 15:28:53 -0800307 }
308}
309`,
310 }, {
311 desc: "proto3 nested message not set",
312 input: &pb3.Nests{},
313 want: "\n",
314 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800315 desc: "proto3 nested message set to empty",
316 input: &pb3.Nests{
317 SNested: &pb3.Nested{},
318 },
319 want: "s_nested: {}\n",
320 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800321 desc: "proto3 nested message",
322 input: &pb3.Nests{
323 SNested: &pb3.Nested{
324 SString: "nested message",
325 SNested: &pb3.Nested{
326 SString: "another nested message",
327 },
328 },
329 },
330 want: `s_nested: {
331 s_string: "nested message"
332 s_nested: {
333 s_string: "another nested message"
334 }
335}
336`,
337 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700338 desc: "proto3 nested message contains invalid UTF-8",
339 input: &pb3.Nests{
340 SNested: &pb3.Nested{
341 SString: "abc\xff",
342 },
343 },
Herbie Ong21a39742019-04-08 17:32:44 -0700344 wantErr: true,
345 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800346 desc: "oneof not set",
347 input: &pb3.Oneofs{},
Herbie Ong800c9902018-12-06 15:28:53 -0800348 want: "\n",
349 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800350 desc: "oneof set to empty string",
351 input: &pb3.Oneofs{
352 Union: &pb3.Oneofs_OneofString{},
Herbie Ong800c9902018-12-06 15:28:53 -0800353 },
Herbie Ong8170d692019-02-13 14:13:21 -0800354 want: `oneof_string: ""
355`,
Herbie Ong800c9902018-12-06 15:28:53 -0800356 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800357 desc: "oneof set to string",
358 input: &pb3.Oneofs{
359 Union: &pb3.Oneofs_OneofString{
360 OneofString: "hello",
Herbie Ong800c9902018-12-06 15:28:53 -0800361 },
362 },
Herbie Ong8170d692019-02-13 14:13:21 -0800363 want: `oneof_string: "hello"
364`,
Herbie Ong800c9902018-12-06 15:28:53 -0800365 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800366 desc: "oneof set to enum",
367 input: &pb3.Oneofs{
368 Union: &pb3.Oneofs_OneofEnum{
369 OneofEnum: pb3.Enum_ZERO,
Herbie Ong800c9902018-12-06 15:28:53 -0800370 },
371 },
Herbie Ong8170d692019-02-13 14:13:21 -0800372 want: `oneof_enum: ZERO
373`,
Herbie Ong800c9902018-12-06 15:28:53 -0800374 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800375 desc: "oneof set to empty message",
376 input: &pb3.Oneofs{
377 Union: &pb3.Oneofs_OneofNested{
378 OneofNested: &pb3.Nested{},
379 },
380 },
381 want: "oneof_nested: {}\n",
382 }, {
383 desc: "oneof set to message",
384 input: &pb3.Oneofs{
385 Union: &pb3.Oneofs_OneofNested{
386 OneofNested: &pb3.Nested{
387 SString: "nested message",
Herbie Ong800c9902018-12-06 15:28:53 -0800388 },
389 },
390 },
Herbie Ong8170d692019-02-13 14:13:21 -0800391 want: `oneof_nested: {
392 s_string: "nested message"
Herbie Ong800c9902018-12-06 15:28:53 -0800393}
394`,
395 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800396 desc: "repeated fields not set",
Herbie Ong800c9902018-12-06 15:28:53 -0800397 input: &pb2.Repeats{},
398 want: "\n",
399 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800400 desc: "repeated fields set to empty slices",
Herbie Ong800c9902018-12-06 15:28:53 -0800401 input: &pb2.Repeats{
Herbie Ongcddf8192018-11-28 18:25:20 -0800402 RptBool: []bool{},
403 RptInt32: []int32{},
404 RptInt64: []int64{},
405 RptUint32: []uint32{},
406 RptUint64: []uint64{},
407 RptFloat: []float32{},
408 RptDouble: []float64{},
409 RptBytes: [][]byte{},
Herbie Ong800c9902018-12-06 15:28:53 -0800410 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800411 want: "\n",
412 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800413 desc: "repeated fields set to some values",
Herbie Ong800c9902018-12-06 15:28:53 -0800414 input: &pb2.Repeats{
Herbie Ongcddf8192018-11-28 18:25:20 -0800415 RptBool: []bool{true, false, true, true},
416 RptInt32: []int32{1, 6, 0, 0},
417 RptInt64: []int64{-64, 47},
418 RptUint32: []uint32{0xff, 0xffff},
419 RptUint64: []uint64{0xdeadbeef},
Herbie Ong84f09602019-01-17 19:31:47 -0800420 RptFloat: []float32{float32(math.NaN()), float32(math.Inf(1)), float32(math.Inf(-1)), 1.034},
Herbie Ongcddf8192018-11-28 18:25:20 -0800421 RptDouble: []float64{math.NaN(), math.Inf(1), math.Inf(-1), 1.23e-308},
422 RptString: []string{"hello", "世界"},
423 RptBytes: [][]byte{
424 []byte("hello"),
425 []byte("\xe4\xb8\x96\xe7\x95\x8c"),
426 },
Herbie Ong800c9902018-12-06 15:28:53 -0800427 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800428 want: `rpt_bool: true
429rpt_bool: false
430rpt_bool: true
431rpt_bool: true
432rpt_int32: 1
433rpt_int32: 6
434rpt_int32: 0
435rpt_int32: 0
436rpt_int64: -64
437rpt_int64: 47
438rpt_uint32: 255
439rpt_uint32: 65535
440rpt_uint64: 3735928559
Herbie Ong84f09602019-01-17 19:31:47 -0800441rpt_float: nan
442rpt_float: inf
443rpt_float: -inf
444rpt_float: 1.034
Herbie Ongcddf8192018-11-28 18:25:20 -0800445rpt_double: nan
446rpt_double: inf
447rpt_double: -inf
448rpt_double: 1.23e-308
449rpt_string: "hello"
450rpt_string: "世界"
451rpt_bytes: "hello"
452rpt_bytes: "世界"
453`,
454 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700455 desc: "repeated contains invalid UTF-8",
456 input: &pb2.Repeats{
457 RptString: []string{"abc\xff"},
458 },
Herbie Ong21a39742019-04-08 17:32:44 -0700459 wantErr: true,
460 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800461 desc: "repeated enums",
Herbie Ong800c9902018-12-06 15:28:53 -0800462 input: &pb2.Enums{
Herbie Ong8170d692019-02-13 14:13:21 -0800463 RptEnum: []pb2.Enum{pb2.Enum_ONE, 2, pb2.Enum_TEN, 42},
Herbie Ongcddf8192018-11-28 18:25:20 -0800464 RptNestedEnum: []pb2.Enums_NestedEnum{2, 47, 10},
Herbie Ong800c9902018-12-06 15:28:53 -0800465 },
Herbie Ong8170d692019-02-13 14:13:21 -0800466 want: `rpt_enum: ONE
467rpt_enum: TWO
468rpt_enum: TEN
Herbie Ongcddf8192018-11-28 18:25:20 -0800469rpt_enum: 42
Herbie Ongcddf8192018-11-28 18:25:20 -0800470rpt_nested_enum: DOS
471rpt_nested_enum: 47
472rpt_nested_enum: DIEZ
473`,
474 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800475 desc: "repeated messages set to empty",
Herbie Ong800c9902018-12-06 15:28:53 -0800476 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800477 RptNested: []*pb2.Nested{},
478 Rptgroup: []*pb2.Nests_RptGroup{},
Herbie Ong800c9902018-12-06 15:28:53 -0800479 },
480 want: "\n",
Herbie Ongcddf8192018-11-28 18:25:20 -0800481 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800482 desc: "repeated messages",
Herbie Ong800c9902018-12-06 15:28:53 -0800483 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800484 RptNested: []*pb2.Nested{
485 {
486 OptString: scalar.String("repeat nested one"),
487 },
488 {
489 OptString: scalar.String("repeat nested two"),
490 OptNested: &pb2.Nested{
491 OptString: scalar.String("inside repeat nested two"),
492 },
493 },
494 {},
495 },
Herbie Ong800c9902018-12-06 15:28:53 -0800496 },
497 want: `rpt_nested: {
Herbie Ongcddf8192018-11-28 18:25:20 -0800498 opt_string: "repeat nested one"
499}
500rpt_nested: {
501 opt_string: "repeat nested two"
502 opt_nested: {
503 opt_string: "inside repeat nested two"
504 }
505}
506rpt_nested: {}
507`,
508 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800509 desc: "repeated messages contains nil value",
Herbie Ongf5db2df2019-02-07 20:17:45 -0800510 input: &pb2.Nests{
511 RptNested: []*pb2.Nested{nil, {}},
512 },
513 want: `rpt_nested: {}
514rpt_nested: {}
515`,
516 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800517 desc: "repeated groups",
Herbie Ong800c9902018-12-06 15:28:53 -0800518 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800519 Rptgroup: []*pb2.Nests_RptGroup{
520 {
Herbie Ong8170d692019-02-13 14:13:21 -0800521 RptString: []string{"hello", "world"},
Herbie Ongcddf8192018-11-28 18:25:20 -0800522 },
523 {},
Herbie Ong8170d692019-02-13 14:13:21 -0800524 nil,
Herbie Ongcddf8192018-11-28 18:25:20 -0800525 },
Herbie Ong800c9902018-12-06 15:28:53 -0800526 },
Herbie Ongde7313b2019-01-14 19:26:50 -0800527 want: `RptGroup: {
Herbie Ong8170d692019-02-13 14:13:21 -0800528 rpt_string: "hello"
529 rpt_string: "world"
Herbie Ongcddf8192018-11-28 18:25:20 -0800530}
Herbie Ongde7313b2019-01-14 19:26:50 -0800531RptGroup: {}
Herbie Ong8170d692019-02-13 14:13:21 -0800532RptGroup: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800533`,
534 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800535 desc: "map fields not set",
536 input: &pb3.Maps{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800537 want: "\n",
538 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800539 desc: "map fields set to empty",
540 input: &pb3.Maps{
541 Int32ToStr: map[int32]string{},
542 BoolToUint32: map[bool]uint32{},
543 Uint64ToEnum: map[uint64]pb3.Enum{},
544 StrToNested: map[string]*pb3.Nested{},
545 StrToOneofs: map[string]*pb3.Oneofs{},
Herbie Ong800c9902018-12-06 15:28:53 -0800546 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800547 want: "\n",
548 }, {
549 desc: "map fields 1",
Herbie Ong8170d692019-02-13 14:13:21 -0800550 input: &pb3.Maps{
Herbie Ongcddf8192018-11-28 18:25:20 -0800551 Int32ToStr: map[int32]string{
552 -101: "-101",
553 0xff: "0xff",
554 0: "zero",
555 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800556 BoolToUint32: map[bool]uint32{
557 true: 42,
558 false: 101,
559 },
Herbie Ong800c9902018-12-06 15:28:53 -0800560 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800561 want: `int32_to_str: {
562 key: -101
563 value: "-101"
564}
565int32_to_str: {
566 key: 0
567 value: "zero"
568}
569int32_to_str: {
570 key: 255
571 value: "0xff"
572}
Herbie Ongcddf8192018-11-28 18:25:20 -0800573bool_to_uint32: {
574 key: false
575 value: 101
576}
577bool_to_uint32: {
578 key: true
579 value: 42
580}
581`,
582 }, {
583 desc: "map fields 2",
Herbie Ong8170d692019-02-13 14:13:21 -0800584 input: &pb3.Maps{
585 Uint64ToEnum: map[uint64]pb3.Enum{
586 1: pb3.Enum_ONE,
587 2: pb3.Enum_TWO,
588 10: pb3.Enum_TEN,
589 47: 47,
Herbie Ongcddf8192018-11-28 18:25:20 -0800590 },
Herbie Ong800c9902018-12-06 15:28:53 -0800591 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800592 want: `uint64_to_enum: {
593 key: 1
Herbie Ong8170d692019-02-13 14:13:21 -0800594 value: ONE
Herbie Ongcddf8192018-11-28 18:25:20 -0800595}
596uint64_to_enum: {
597 key: 2
Herbie Ong8170d692019-02-13 14:13:21 -0800598 value: TWO
Herbie Ongcddf8192018-11-28 18:25:20 -0800599}
600uint64_to_enum: {
601 key: 10
Herbie Ong8170d692019-02-13 14:13:21 -0800602 value: TEN
603}
604uint64_to_enum: {
605 key: 47
606 value: 47
Herbie Ongcddf8192018-11-28 18:25:20 -0800607}
608`,
609 }, {
610 desc: "map fields 3",
Herbie Ong8170d692019-02-13 14:13:21 -0800611 input: &pb3.Maps{
612 StrToNested: map[string]*pb3.Nested{
613 "nested": &pb3.Nested{
614 SString: "nested in a map",
Herbie Ongcddf8192018-11-28 18:25:20 -0800615 },
616 },
Herbie Ong800c9902018-12-06 15:28:53 -0800617 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800618 want: `str_to_nested: {
Herbie Ong8170d692019-02-13 14:13:21 -0800619 key: "nested"
Herbie Ongcddf8192018-11-28 18:25:20 -0800620 value: {
Herbie Ong8170d692019-02-13 14:13:21 -0800621 s_string: "nested in a map"
Herbie Ongcddf8192018-11-28 18:25:20 -0800622 }
623}
624`,
625 }, {
626 desc: "map fields 4",
Herbie Ong8170d692019-02-13 14:13:21 -0800627 input: &pb3.Maps{
628 StrToOneofs: map[string]*pb3.Oneofs{
629 "string": &pb3.Oneofs{
630 Union: &pb3.Oneofs_OneofString{
631 OneofString: "hello",
Herbie Ongcddf8192018-11-28 18:25:20 -0800632 },
633 },
Herbie Ong8170d692019-02-13 14:13:21 -0800634 "nested": &pb3.Oneofs{
635 Union: &pb3.Oneofs_OneofNested{
636 OneofNested: &pb3.Nested{
637 SString: "nested oneof in map field value",
Herbie Ongcddf8192018-11-28 18:25:20 -0800638 },
639 },
640 },
641 },
Herbie Ong800c9902018-12-06 15:28:53 -0800642 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800643 want: `str_to_oneofs: {
644 key: "nested"
645 value: {
Herbie Ong8170d692019-02-13 14:13:21 -0800646 oneof_nested: {
647 s_string: "nested oneof in map field value"
Herbie Ongcddf8192018-11-28 18:25:20 -0800648 }
649 }
650}
651str_to_oneofs: {
652 key: "string"
653 value: {
Herbie Ong8170d692019-02-13 14:13:21 -0800654 oneof_string: "hello"
Herbie Ongcddf8192018-11-28 18:25:20 -0800655 }
656}
657`,
658 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700659 desc: "map field value contains invalid UTF-8",
660 input: &pb3.Maps{
661 Int32ToStr: map[int32]string{
662 101: "abc\xff",
663 },
664 },
Herbie Ong21a39742019-04-08 17:32:44 -0700665 wantErr: true,
666 }, {
667 desc: "map field key contains invalid UTF-8",
668 input: &pb3.Maps{
669 StrToNested: map[string]*pb3.Nested{
670 "abc\xff": {},
671 },
672 },
Herbie Ong21a39742019-04-08 17:32:44 -0700673 wantErr: true,
674 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800675 desc: "map field contains nil value",
676 input: &pb3.Maps{
677 StrToNested: map[string]*pb3.Nested{
Herbie Ongf5db2df2019-02-07 20:17:45 -0800678 "nil": nil,
679 },
680 },
681 want: `str_to_nested: {
682 key: "nil"
683 value: {}
684}
685`,
686 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700687 desc: "required fields not set",
Herbie Ong800c9902018-12-06 15:28:53 -0800688 input: &pb2.Requireds{},
689 want: "\n",
690 wantErr: true,
Herbie Ongcddf8192018-11-28 18:25:20 -0800691 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700692 desc: "required fields partially set",
Herbie Ong800c9902018-12-06 15:28:53 -0800693 input: &pb2.Requireds{
694 ReqBool: scalar.Bool(false),
Herbie Ong800c9902018-12-06 15:28:53 -0800695 ReqSfixed64: scalar.Int64(0xbeefcafe),
696 ReqDouble: scalar.Float64(math.NaN()),
697 ReqString: scalar.String("hello"),
Herbie Ong8170d692019-02-13 14:13:21 -0800698 ReqEnum: pb2.Enum_ONE.Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800699 },
700 want: `req_bool: false
Herbie Ong800c9902018-12-06 15:28:53 -0800701req_sfixed64: 3203386110
702req_double: nan
703req_string: "hello"
Herbie Ong8170d692019-02-13 14:13:21 -0800704req_enum: ONE
Herbie Ong800c9902018-12-06 15:28:53 -0800705`,
706 wantErr: true,
707 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700708 desc: "required fields not set with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700709 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong42577ea2019-03-26 16:26:22 -0700710 input: &pb2.Requireds{
711 ReqBool: scalar.Bool(false),
712 ReqSfixed64: scalar.Int64(0xbeefcafe),
713 ReqDouble: scalar.Float64(math.NaN()),
714 ReqString: scalar.String("hello"),
715 ReqEnum: pb2.Enum_ONE.Enum(),
716 },
717 want: `req_bool: false
718req_sfixed64: 3203386110
719req_double: nan
720req_string: "hello"
721req_enum: ONE
722`,
723 }, {
724 desc: "required fields all set",
Herbie Ong800c9902018-12-06 15:28:53 -0800725 input: &pb2.Requireds{
726 ReqBool: scalar.Bool(false),
Herbie Ong800c9902018-12-06 15:28:53 -0800727 ReqSfixed64: scalar.Int64(0),
Herbie Ong8170d692019-02-13 14:13:21 -0800728 ReqDouble: scalar.Float64(1.23),
Herbie Ong800c9902018-12-06 15:28:53 -0800729 ReqString: scalar.String(""),
Herbie Ong8170d692019-02-13 14:13:21 -0800730 ReqEnum: pb2.Enum_ONE.Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800731 ReqNested: &pb2.Nested{},
732 },
733 want: `req_bool: false
Herbie Ong800c9902018-12-06 15:28:53 -0800734req_sfixed64: 0
Herbie Ong8170d692019-02-13 14:13:21 -0800735req_double: 1.23
Herbie Ong800c9902018-12-06 15:28:53 -0800736req_string: ""
Herbie Ong8170d692019-02-13 14:13:21 -0800737req_enum: ONE
Herbie Ong800c9902018-12-06 15:28:53 -0800738req_nested: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800739`,
740 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800741 desc: "indirect required field",
742 input: &pb2.IndirectRequired{
743 OptNested: &pb2.NestedWithRequired{},
744 },
745 want: "opt_nested: {}\n",
746 wantErr: true,
Herbie Ongcddf8192018-11-28 18:25:20 -0800747 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700748 desc: "indirect required field with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700749 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong42577ea2019-03-26 16:26:22 -0700750 input: &pb2.IndirectRequired{
751 OptNested: &pb2.NestedWithRequired{},
752 },
753 want: "opt_nested: {}\n",
754 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800755 desc: "indirect required field in empty repeated",
756 input: &pb2.IndirectRequired{
757 RptNested: []*pb2.NestedWithRequired{},
758 },
759 want: "\n",
Herbie Ongcddf8192018-11-28 18:25:20 -0800760 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800761 desc: "indirect required field in repeated",
762 input: &pb2.IndirectRequired{
763 RptNested: []*pb2.NestedWithRequired{
764 &pb2.NestedWithRequired{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800765 },
Herbie Ong800c9902018-12-06 15:28:53 -0800766 },
767 want: "rpt_nested: {}\n",
768 wantErr: true,
769 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700770 desc: "indirect required field in repeated with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700771 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong42577ea2019-03-26 16:26:22 -0700772 input: &pb2.IndirectRequired{
773 RptNested: []*pb2.NestedWithRequired{
774 &pb2.NestedWithRequired{},
775 },
776 },
777 want: "rpt_nested: {}\n",
778 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800779 desc: "indirect required field in empty map",
780 input: &pb2.IndirectRequired{
781 StrToNested: map[string]*pb2.NestedWithRequired{},
782 },
783 want: "\n",
784 }, {
785 desc: "indirect required field in map",
786 input: &pb2.IndirectRequired{
787 StrToNested: map[string]*pb2.NestedWithRequired{
788 "fail": &pb2.NestedWithRequired{},
789 },
790 },
791 want: `str_to_nested: {
792 key: "fail"
793 value: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800794}
795`,
Herbie Ong800c9902018-12-06 15:28:53 -0800796 wantErr: true,
Herbie Ong20a1d312018-12-11 21:08:58 -0800797 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700798 desc: "indirect required field in map with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700799 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong42577ea2019-03-26 16:26:22 -0700800 input: &pb2.IndirectRequired{
801 StrToNested: map[string]*pb2.NestedWithRequired{
802 "fail": &pb2.NestedWithRequired{},
803 },
804 },
805 want: `str_to_nested: {
806 key: "fail"
807 value: {}
808}
809`,
810 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800811 desc: "indirect required field in oneof",
812 input: &pb2.IndirectRequired{
813 Union: &pb2.IndirectRequired_OneofNested{
814 OneofNested: &pb2.NestedWithRequired{},
815 },
816 },
817 want: "oneof_nested: {}\n",
818 wantErr: true,
819 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700820 desc: "indirect required field in oneof with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700821 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong42577ea2019-03-26 16:26:22 -0700822 input: &pb2.IndirectRequired{
823 Union: &pb2.IndirectRequired_OneofNested{
824 OneofNested: &pb2.NestedWithRequired{},
825 },
826 },
827 want: "oneof_nested: {}\n",
828 }, {
Herbie Ong20a1d312018-12-11 21:08:58 -0800829 desc: "unknown varint and fixed types",
Joe Tsai28216c72019-06-22 13:20:09 -0700830 input: func() proto.Message {
831 m := &pb2.Scalars{
832 OptString: scalar.String("this message contains unknown fields"),
833 }
834 m.ProtoReflect().SetUnknown(pack.Message{
Herbie Ong20a1d312018-12-11 21:08:58 -0800835 pack.Tag{101, pack.VarintType}, pack.Bool(true),
836 pack.Tag{102, pack.VarintType}, pack.Varint(0xff),
837 pack.Tag{103, pack.Fixed32Type}, pack.Uint32(47),
838 pack.Tag{104, pack.Fixed64Type}, pack.Int64(0xdeadbeef),
Joe Tsai28216c72019-06-22 13:20:09 -0700839 }.Marshal())
840 return m
841 }(),
Herbie Ong20a1d312018-12-11 21:08:58 -0800842 want: `opt_string: "this message contains unknown fields"
843101: 1
844102: 255
845103: 47
846104: 3735928559
847`,
848 }, {
849 desc: "unknown length-delimited",
Joe Tsai28216c72019-06-22 13:20:09 -0700850 input: func() proto.Message {
851 m := new(pb2.Scalars)
852 m.ProtoReflect().SetUnknown(pack.Message{
Herbie Ong20a1d312018-12-11 21:08:58 -0800853 pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false)},
854 pack.Tag{102, pack.BytesType}, pack.String("hello world"),
855 pack.Tag{103, pack.BytesType}, pack.Bytes("\xe4\xb8\x96\xe7\x95\x8c"),
Joe Tsai28216c72019-06-22 13:20:09 -0700856 }.Marshal())
857 return m
858 }(),
Herbie Ong20a1d312018-12-11 21:08:58 -0800859 want: `101: "\x01\x00"
860102: "hello world"
861103: "世界"
862`,
863 }, {
864 desc: "unknown group type",
Joe Tsai28216c72019-06-22 13:20:09 -0700865 input: func() proto.Message {
866 m := new(pb2.Scalars)
867 m.ProtoReflect().SetUnknown(pack.Message{
Herbie Ong20a1d312018-12-11 21:08:58 -0800868 pack.Tag{101, pack.StartGroupType}, pack.Tag{101, pack.EndGroupType},
869 pack.Tag{102, pack.StartGroupType},
870 pack.Tag{101, pack.VarintType}, pack.Bool(false),
871 pack.Tag{102, pack.BytesType}, pack.String("inside a group"),
872 pack.Tag{102, pack.EndGroupType},
Joe Tsai28216c72019-06-22 13:20:09 -0700873 }.Marshal())
874 return m
875 }(),
Herbie Ong20a1d312018-12-11 21:08:58 -0800876 want: `101: {}
877102: {
878 101: 0
879 102: "inside a group"
880}
881`,
882 }, {
883 desc: "unknown unpack repeated field",
Joe Tsai28216c72019-06-22 13:20:09 -0700884 input: func() proto.Message {
885 m := new(pb2.Scalars)
886 m.ProtoReflect().SetUnknown(pack.Message{
Herbie Ong20a1d312018-12-11 21:08:58 -0800887 pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false), pack.Bool(true)},
888 pack.Tag{102, pack.BytesType}, pack.String("hello"),
889 pack.Tag{101, pack.VarintType}, pack.Bool(true),
890 pack.Tag{102, pack.BytesType}, pack.String("世界"),
Joe Tsai28216c72019-06-22 13:20:09 -0700891 }.Marshal())
892 return m
893 }(),
Herbie Ong20a1d312018-12-11 21:08:58 -0800894 want: `101: "\x01\x00\x01"
Herbie Ong20a1d312018-12-11 21:08:58 -0800895102: "hello"
Joe Tsai378c1322019-04-25 23:48:08 -0700896101: 1
Herbie Ong20a1d312018-12-11 21:08:58 -0800897102: "世界"
898`,
Herbie Ongcf253082018-12-17 17:13:07 -0800899 }, {
900 desc: "extensions of non-repeated fields",
901 input: func() proto.Message {
902 m := &pb2.Extensions{
903 OptString: scalar.String("non-extension field"),
904 OptBool: scalar.Bool(true),
905 OptInt32: scalar.Int32(42),
906 }
907 setExtension(m, pb2.E_OptExtBool, true)
908 setExtension(m, pb2.E_OptExtString, "extension field")
Herbie Ong8170d692019-02-13 14:13:21 -0800909 setExtension(m, pb2.E_OptExtEnum, pb2.Enum_TEN)
Herbie Ongcf253082018-12-17 17:13:07 -0800910 setExtension(m, pb2.E_OptExtNested, &pb2.Nested{
911 OptString: scalar.String("nested in an extension"),
912 OptNested: &pb2.Nested{
913 OptString: scalar.String("another nested in an extension"),
914 },
915 })
916 return m
917 }(),
918 want: `opt_string: "non-extension field"
919opt_bool: true
920opt_int32: 42
921[pb2.opt_ext_bool]: true
Herbie Ong8170d692019-02-13 14:13:21 -0800922[pb2.opt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -0800923[pb2.opt_ext_nested]: {
924 opt_string: "nested in an extension"
925 opt_nested: {
926 opt_string: "another nested in an extension"
927 }
928}
929[pb2.opt_ext_string]: "extension field"
930`,
931 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700932 desc: "extension field contains invalid UTF-8",
933 input: func() proto.Message {
934 m := &pb2.Extensions{}
935 setExtension(m, pb2.E_OptExtString, "abc\xff")
936 return m
937 }(),
Herbie Ong21a39742019-04-08 17:32:44 -0700938 wantErr: true,
939 }, {
Herbie Ong09b28a92019-04-03 15:42:41 -0700940 desc: "extension partial returns error",
941 input: func() proto.Message {
942 m := &pb2.Extensions{}
943 setExtension(m, pb2.E_OptExtPartial, &pb2.PartialRequired{
944 OptString: scalar.String("partial1"),
945 })
946 setExtension(m, pb2.E_ExtensionsContainer_OptExtPartial, &pb2.PartialRequired{
947 OptString: scalar.String("partial2"),
948 })
949 return m
950 }(),
951 want: `[pb2.ExtensionsContainer.opt_ext_partial]: {
952 opt_string: "partial2"
953}
954[pb2.opt_ext_partial]: {
955 opt_string: "partial1"
956}
957`,
958 wantErr: true,
959 }, {
960 desc: "extension partial with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700961 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong09b28a92019-04-03 15:42:41 -0700962 input: func() proto.Message {
963 m := &pb2.Extensions{}
964 setExtension(m, pb2.E_OptExtPartial, &pb2.PartialRequired{
965 OptString: scalar.String("partial1"),
966 })
967 return m
968 }(),
969 want: `[pb2.opt_ext_partial]: {
970 opt_string: "partial1"
971}
972`,
973 }, {
Herbie Ongcf253082018-12-17 17:13:07 -0800974 desc: "extensions of repeated fields",
975 input: func() proto.Message {
976 m := &pb2.Extensions{}
Herbie Ong8170d692019-02-13 14:13:21 -0800977 setExtension(m, pb2.E_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
Herbie Ongcf253082018-12-17 17:13:07 -0800978 setExtension(m, pb2.E_RptExtFixed32, &[]uint32{42, 47})
979 setExtension(m, pb2.E_RptExtNested, &[]*pb2.Nested{
980 &pb2.Nested{OptString: scalar.String("one")},
981 &pb2.Nested{OptString: scalar.String("two")},
982 &pb2.Nested{OptString: scalar.String("three")},
983 })
984 return m
985 }(),
Herbie Ong8170d692019-02-13 14:13:21 -0800986 want: `[pb2.rpt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -0800987[pb2.rpt_ext_enum]: 101
Herbie Ong8170d692019-02-13 14:13:21 -0800988[pb2.rpt_ext_enum]: ONE
Herbie Ongcf253082018-12-17 17:13:07 -0800989[pb2.rpt_ext_fixed32]: 42
990[pb2.rpt_ext_fixed32]: 47
991[pb2.rpt_ext_nested]: {
992 opt_string: "one"
993}
994[pb2.rpt_ext_nested]: {
995 opt_string: "two"
996}
997[pb2.rpt_ext_nested]: {
998 opt_string: "three"
999}
1000`,
1001 }, {
1002 desc: "extensions of non-repeated fields in another message",
1003 input: func() proto.Message {
1004 m := &pb2.Extensions{}
1005 setExtension(m, pb2.E_ExtensionsContainer_OptExtBool, true)
1006 setExtension(m, pb2.E_ExtensionsContainer_OptExtString, "extension field")
Herbie Ong8170d692019-02-13 14:13:21 -08001007 setExtension(m, pb2.E_ExtensionsContainer_OptExtEnum, pb2.Enum_TEN)
Herbie Ongcf253082018-12-17 17:13:07 -08001008 setExtension(m, pb2.E_ExtensionsContainer_OptExtNested, &pb2.Nested{
1009 OptString: scalar.String("nested in an extension"),
1010 OptNested: &pb2.Nested{
1011 OptString: scalar.String("another nested in an extension"),
1012 },
1013 })
1014 return m
1015 }(),
1016 want: `[pb2.ExtensionsContainer.opt_ext_bool]: true
Herbie Ong8170d692019-02-13 14:13:21 -08001017[pb2.ExtensionsContainer.opt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -08001018[pb2.ExtensionsContainer.opt_ext_nested]: {
1019 opt_string: "nested in an extension"
1020 opt_nested: {
1021 opt_string: "another nested in an extension"
1022 }
1023}
1024[pb2.ExtensionsContainer.opt_ext_string]: "extension field"
1025`,
1026 }, {
1027 desc: "extensions of repeated fields in another message",
1028 input: func() proto.Message {
1029 m := &pb2.Extensions{
1030 OptString: scalar.String("non-extension field"),
1031 OptBool: scalar.Bool(true),
1032 OptInt32: scalar.Int32(42),
1033 }
Herbie Ong8170d692019-02-13 14:13:21 -08001034 setExtension(m, pb2.E_ExtensionsContainer_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
Herbie Ongcf253082018-12-17 17:13:07 -08001035 setExtension(m, pb2.E_ExtensionsContainer_RptExtString, &[]string{"hello", "world"})
1036 setExtension(m, pb2.E_ExtensionsContainer_RptExtNested, &[]*pb2.Nested{
1037 &pb2.Nested{OptString: scalar.String("one")},
1038 &pb2.Nested{OptString: scalar.String("two")},
1039 &pb2.Nested{OptString: scalar.String("three")},
1040 })
1041 return m
1042 }(),
1043 want: `opt_string: "non-extension field"
1044opt_bool: true
1045opt_int32: 42
Herbie Ong8170d692019-02-13 14:13:21 -08001046[pb2.ExtensionsContainer.rpt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -08001047[pb2.ExtensionsContainer.rpt_ext_enum]: 101
Herbie Ong8170d692019-02-13 14:13:21 -08001048[pb2.ExtensionsContainer.rpt_ext_enum]: ONE
Herbie Ongcf253082018-12-17 17:13:07 -08001049[pb2.ExtensionsContainer.rpt_ext_nested]: {
1050 opt_string: "one"
1051}
1052[pb2.ExtensionsContainer.rpt_ext_nested]: {
1053 opt_string: "two"
1054}
1055[pb2.ExtensionsContainer.rpt_ext_nested]: {
1056 opt_string: "three"
1057}
1058[pb2.ExtensionsContainer.rpt_ext_string]: "hello"
1059[pb2.ExtensionsContainer.rpt_ext_string]: "world"
1060`,
Herbie Ong6470ea62019-01-07 18:56:57 -08001061 }, {
1062 desc: "MessageSet",
1063 input: func() proto.Message {
1064 m := &pb2.MessageSet{}
1065 setExtension(m, pb2.E_MessageSetExtension_MessageSetExtension, &pb2.MessageSetExtension{
1066 OptString: scalar.String("a messageset extension"),
1067 })
1068 setExtension(m, pb2.E_MessageSetExtension_NotMessageSetExtension, &pb2.MessageSetExtension{
1069 OptString: scalar.String("not a messageset extension"),
1070 })
1071 setExtension(m, pb2.E_MessageSetExtension_ExtNested, &pb2.Nested{
1072 OptString: scalar.String("just a regular extension"),
1073 })
1074 return m
1075 }(),
1076 want: `[pb2.MessageSetExtension]: {
1077 opt_string: "a messageset extension"
1078}
1079[pb2.MessageSetExtension.ext_nested]: {
1080 opt_string: "just a regular extension"
1081}
1082[pb2.MessageSetExtension.not_message_set_extension]: {
1083 opt_string: "not a messageset extension"
1084}
1085`,
1086 }, {
1087 desc: "not real MessageSet 1",
1088 input: func() proto.Message {
1089 m := &pb2.FakeMessageSet{}
1090 setExtension(m, pb2.E_FakeMessageSetExtension_MessageSetExtension, &pb2.FakeMessageSetExtension{
1091 OptString: scalar.String("not a messageset extension"),
1092 })
1093 return m
1094 }(),
1095 want: `[pb2.FakeMessageSetExtension.message_set_extension]: {
1096 opt_string: "not a messageset extension"
1097}
1098`,
1099 }, {
1100 desc: "not real MessageSet 2",
1101 input: func() proto.Message {
1102 m := &pb2.MessageSet{}
1103 setExtension(m, pb2.E_MessageSetExtension, &pb2.FakeMessageSetExtension{
1104 OptString: scalar.String("another not a messageset extension"),
1105 })
1106 return m
1107 }(),
1108 want: `[pb2.message_set_extension]: {
1109 opt_string: "another not a messageset extension"
1110}
1111`,
Herbie Ongf42b55f2019-01-02 15:46:07 -08001112 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001113 desc: "Any not expanded",
Damien Neil5c5b5312019-05-14 12:44:37 -07001114 mo: prototext.MarshalOptions{
Herbie Ong66c365c2019-01-04 14:08:41 -08001115 Resolver: preg.NewTypes(),
1116 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001117 input: func() proto.Message {
1118 m := &pb2.Nested{
1119 OptString: scalar.String("embedded inside Any"),
1120 OptNested: &pb2.Nested{
1121 OptString: scalar.String("inception"),
1122 },
1123 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -07001124 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ongf42b55f2019-01-02 15:46:07 -08001125 if err != nil {
1126 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1127 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07001128 return &anypb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001129 TypeUrl: "pb2.Nested",
Herbie Ongf42b55f2019-01-02 15:46:07 -08001130 Value: b,
Herbie Ong300cff02019-03-20 18:05:16 -07001131 }
Herbie Ongf42b55f2019-01-02 15:46:07 -08001132 }(),
1133 want: `type_url: "pb2.Nested"
1134value: "\n\x13embedded inside Any\x12\x0b\n\tinception"
1135`,
1136 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001137 desc: "Any expanded",
Damien Neil5c5b5312019-05-14 12:44:37 -07001138 mo: prototext.MarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001139 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
Herbie Ong66c365c2019-01-04 14:08:41 -08001140 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001141 input: func() proto.Message {
1142 m := &pb2.Nested{
1143 OptString: scalar.String("embedded inside Any"),
1144 OptNested: &pb2.Nested{
1145 OptString: scalar.String("inception"),
1146 },
1147 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -07001148 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ongf42b55f2019-01-02 15:46:07 -08001149 if err != nil {
1150 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1151 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07001152 return &anypb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001153 TypeUrl: "foo/pb2.Nested",
Herbie Ongf42b55f2019-01-02 15:46:07 -08001154 Value: b,
Herbie Ong300cff02019-03-20 18:05:16 -07001155 }
Herbie Ongf42b55f2019-01-02 15:46:07 -08001156 }(),
Herbie Ong66c365c2019-01-04 14:08:41 -08001157 want: `[foo/pb2.Nested]: {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001158 opt_string: "embedded inside Any"
1159 opt_nested: {
1160 opt_string: "inception"
1161 }
1162}
1163`,
1164 }, {
Damien Neil0c9f0a92019-06-19 10:41:09 -07001165 desc: "Any expanded with missing required",
Damien Neil5c5b5312019-05-14 12:44:37 -07001166 mo: prototext.MarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001167 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.PartialRequired{})),
Herbie Ong66c365c2019-01-04 14:08:41 -08001168 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001169 input: func() proto.Message {
1170 m := &pb2.PartialRequired{
1171 OptString: scalar.String("embedded inside Any"),
1172 }
Damien Neil96c229a2019-04-03 12:17:24 -07001173 b, err := proto.MarshalOptions{
1174 AllowPartial: true,
1175 Deterministic: true,
1176 }.Marshal(m)
Herbie Ong300cff02019-03-20 18:05:16 -07001177 if err != nil {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001178 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1179 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07001180 return &anypb.Any{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001181 TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
Herbie Ongf42b55f2019-01-02 15:46:07 -08001182 Value: b,
Herbie Ong300cff02019-03-20 18:05:16 -07001183 }
Herbie Ongf42b55f2019-01-02 15:46:07 -08001184 }(),
1185 want: `[pb2.PartialRequired]: {
1186 opt_string: "embedded inside Any"
1187}
1188`,
Herbie Ongf42b55f2019-01-02 15:46:07 -08001189 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001190 desc: "Any with invalid value",
Damien Neil5c5b5312019-05-14 12:44:37 -07001191 mo: prototext.MarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001192 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
Herbie Ong66c365c2019-01-04 14:08:41 -08001193 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07001194 input: &anypb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001195 TypeUrl: "foo/pb2.Nested",
Joe Tsai6dc168e2019-07-09 23:11:13 -07001196 Value: []byte("\x80"),
Herbie Ong300cff02019-03-20 18:05:16 -07001197 },
Herbie Ong66c365c2019-01-04 14:08:41 -08001198 want: `type_url: "foo/pb2.Nested"
Herbie Onga94f78c2019-01-03 15:39:58 -08001199value: "\x80"
1200`,
Herbie Ongcddf8192018-11-28 18:25:20 -08001201 }}
1202
1203 for _, tt := range tests {
1204 tt := tt
1205 t.Run(tt.desc, func(t *testing.T) {
Herbie Ong3a385912019-03-20 14:04:24 -07001206 // Use 2-space indentation on all MarshalOptions.
1207 tt.mo.Indent = " "
Herbie Ongf42b55f2019-01-02 15:46:07 -08001208 b, err := tt.mo.Marshal(tt.input)
Herbie Ongcddf8192018-11-28 18:25:20 -08001209 if err != nil && !tt.wantErr {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001210 t.Errorf("Marshal() returned error: %v\n", err)
Herbie Ongcddf8192018-11-28 18:25:20 -08001211 }
Herbie Ong800c9902018-12-06 15:28:53 -08001212 if err == nil && tt.wantErr {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001213 t.Error("Marshal() got nil error, want error\n")
Herbie Ongcddf8192018-11-28 18:25:20 -08001214 }
Herbie Ong800c9902018-12-06 15:28:53 -08001215 got := string(b)
1216 if tt.want != "" && got != tt.want {
1217 t.Errorf("Marshal()\n<got>\n%v\n<want>\n%v\n", got, tt.want)
Joe Tsai378c1322019-04-25 23:48:08 -07001218 if diff := cmp.Diff(tt.want, got); diff != "" {
Herbie Ongcddf8192018-11-28 18:25:20 -08001219 t.Errorf("Marshal() diff -want +got\n%v\n", diff)
1220 }
1221 }
1222 })
1223 }
1224}