blob: c29169b40e75402ae79eed1218cb916e418aeba9 [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"
Joe Tsai5ae10aa2019-07-11 18:23:08 -070015 "google.golang.org/protobuf/internal/flags"
Damien Neile89e6242019-05-13 23:55:40 -070016 pimpl "google.golang.org/protobuf/internal/impl"
Damien Neile89e6242019-05-13 23:55:40 -070017 "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.
Joe Tsai5ae10aa2019-07-11 18:23:08 -070043 skip bool
Herbie Ongcddf8192018-11-28 18:25:20 -080044 }{{
Herbie Ong8170d692019-02-13 14:13:21 -080045 desc: "proto2 optional scalars not set",
Herbie Ong800c9902018-12-06 15:28:53 -080046 input: &pb2.Scalars{},
Herbie Ongcddf8192018-11-28 18:25:20 -080047 want: "\n",
48 }, {
Herbie Ong8170d692019-02-13 14:13:21 -080049 desc: "proto3 scalars not set",
Herbie Ong800c9902018-12-06 15:28:53 -080050 input: &pb3.Scalars{},
Herbie Ongcddf8192018-11-28 18:25:20 -080051 want: "\n",
52 }, {
Herbie Ong8170d692019-02-13 14:13:21 -080053 desc: "proto2 optional scalars set to zero values",
Herbie Ong800c9902018-12-06 15:28:53 -080054 input: &pb2.Scalars{
Damien Neila8a2cea2019-07-10 16:17:16 -070055 OptBool: proto.Bool(false),
56 OptInt32: proto.Int32(0),
57 OptInt64: proto.Int64(0),
58 OptUint32: proto.Uint32(0),
59 OptUint64: proto.Uint64(0),
60 OptSint32: proto.Int32(0),
61 OptSint64: proto.Int64(0),
62 OptFixed32: proto.Uint32(0),
63 OptFixed64: proto.Uint64(0),
64 OptSfixed32: proto.Int32(0),
65 OptSfixed64: proto.Int64(0),
66 OptFloat: proto.Float32(0),
67 OptDouble: proto.Float64(0),
Herbie Ongcddf8192018-11-28 18:25:20 -080068 OptBytes: []byte{},
Damien Neila8a2cea2019-07-10 16:17:16 -070069 OptString: proto.String(""),
Herbie Ong800c9902018-12-06 15:28:53 -080070 },
Herbie Ongcddf8192018-11-28 18:25:20 -080071 want: `opt_bool: false
72opt_int32: 0
73opt_int64: 0
74opt_uint32: 0
75opt_uint64: 0
76opt_sint32: 0
77opt_sint64: 0
78opt_fixed32: 0
79opt_fixed64: 0
80opt_sfixed32: 0
81opt_sfixed64: 0
82opt_float: 0
83opt_double: 0
84opt_bytes: ""
85opt_string: ""
86`,
87 }, {
Herbie Ong8170d692019-02-13 14:13:21 -080088 desc: "proto3 scalars set to zero values",
Herbie Ong800c9902018-12-06 15:28:53 -080089 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -080090 SBool: false,
91 SInt32: 0,
92 SInt64: 0,
93 SUint32: 0,
94 SUint64: 0,
95 SSint32: 0,
96 SSint64: 0,
97 SFixed32: 0,
98 SFixed64: 0,
99 SSfixed32: 0,
100 SSfixed64: 0,
101 SFloat: 0,
102 SDouble: 0,
103 SBytes: []byte{},
104 SString: "",
Herbie Ong800c9902018-12-06 15:28:53 -0800105 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800106 want: "\n",
107 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800108 desc: "proto2 optional scalars set to some values",
Herbie Ong800c9902018-12-06 15:28:53 -0800109 input: &pb2.Scalars{
Damien Neila8a2cea2019-07-10 16:17:16 -0700110 OptBool: proto.Bool(true),
111 OptInt32: proto.Int32(0xff),
112 OptInt64: proto.Int64(0xdeadbeef),
113 OptUint32: proto.Uint32(47),
114 OptUint64: proto.Uint64(0xdeadbeef),
115 OptSint32: proto.Int32(-1001),
116 OptSint64: proto.Int64(-0xffff),
117 OptFixed64: proto.Uint64(64),
118 OptSfixed32: proto.Int32(-32),
119 OptFloat: proto.Float32(1.02),
120 OptDouble: proto.Float64(1.0199999809265137),
Herbie Ong8170d692019-02-13 14:13:21 -0800121 OptBytes: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
Damien Neila8a2cea2019-07-10 16:17:16 -0700122 OptString: proto.String("谷歌"),
Herbie Ong800c9902018-12-06 15:28:53 -0800123 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800124 want: `opt_bool: true
125opt_int32: 255
126opt_int64: 3735928559
127opt_uint32: 47
128opt_uint64: 3735928559
129opt_sint32: -1001
130opt_sint64: -65535
131opt_fixed64: 64
132opt_sfixed32: -32
Herbie Ong84f09602019-01-17 19:31:47 -0800133opt_float: 1.02
134opt_double: 1.0199999809265137
Herbie Ongcddf8192018-11-28 18:25:20 -0800135opt_bytes: "谷歌"
136opt_string: "谷歌"
137`,
138 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700139 desc: "string with invalid UTF-8",
140 input: &pb3.Scalars{
141 SString: "abc\xff",
142 },
Herbie Ong21a39742019-04-08 17:32:44 -0700143 wantErr: true,
144 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800145 desc: "float nan",
Herbie Ong800c9902018-12-06 15:28:53 -0800146 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800147 SFloat: float32(math.NaN()),
Herbie Ong800c9902018-12-06 15:28:53 -0800148 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800149 want: "s_float: nan\n",
150 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800151 desc: "float positive infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800152 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800153 SFloat: float32(math.Inf(1)),
Herbie Ong800c9902018-12-06 15:28:53 -0800154 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800155 want: "s_float: inf\n",
156 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800157 desc: "float negative infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800158 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800159 SFloat: float32(math.Inf(-1)),
Herbie Ong800c9902018-12-06 15:28:53 -0800160 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800161 want: "s_float: -inf\n",
162 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800163 desc: "double nan",
Herbie Ong800c9902018-12-06 15:28:53 -0800164 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800165 SDouble: math.NaN(),
Herbie Ong800c9902018-12-06 15:28:53 -0800166 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800167 want: "s_double: nan\n",
168 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800169 desc: "double positive infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800170 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800171 SDouble: math.Inf(1),
Herbie Ong800c9902018-12-06 15:28:53 -0800172 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800173 want: "s_double: inf\n",
174 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800175 desc: "double negative infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800176 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800177 SDouble: math.Inf(-1),
Herbie Ong800c9902018-12-06 15:28:53 -0800178 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800179 want: "s_double: -inf\n",
180 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800181 desc: "proto2 enum not set",
182 input: &pb2.Enums{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800183 want: "\n",
184 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800185 desc: "proto2 enum set to zero value",
186 input: &pb2.Enums{
Joe Tsai6dc168e2019-07-09 23:11:13 -0700187 OptEnum: pb2.Enum(0).Enum(),
188 OptNestedEnum: pb2.Enums_NestedEnum(0).Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800189 },
Herbie Ong8170d692019-02-13 14:13:21 -0800190 want: `opt_enum: 0
Herbie Ong800c9902018-12-06 15:28:53 -0800191opt_nested_enum: 0
192`,
193 }, {
194 desc: "proto2 enum",
195 input: &pb2.Enums{
Herbie Ong8170d692019-02-13 14:13:21 -0800196 OptEnum: pb2.Enum_ONE.Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800197 OptNestedEnum: pb2.Enums_UNO.Enum(),
198 },
Herbie Ong8170d692019-02-13 14:13:21 -0800199 want: `opt_enum: ONE
Herbie Ong800c9902018-12-06 15:28:53 -0800200opt_nested_enum: UNO
201`,
202 }, {
203 desc: "proto2 enum set to numeric values",
204 input: &pb2.Enums{
Joe Tsai6dc168e2019-07-09 23:11:13 -0700205 OptEnum: pb2.Enum(2).Enum(),
206 OptNestedEnum: pb2.Enums_NestedEnum(2).Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800207 },
Herbie Ong8170d692019-02-13 14:13:21 -0800208 want: `opt_enum: TWO
Herbie Ong800c9902018-12-06 15:28:53 -0800209opt_nested_enum: DOS
210`,
211 }, {
212 desc: "proto2 enum set to unnamed numeric values",
213 input: &pb2.Enums{
Joe Tsai6dc168e2019-07-09 23:11:13 -0700214 OptEnum: pb2.Enum(101).Enum(),
215 OptNestedEnum: pb2.Enums_NestedEnum(-101).Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800216 },
217 want: `opt_enum: 101
218opt_nested_enum: -101
219`,
220 }, {
221 desc: "proto3 enum not set",
222 input: &pb3.Enums{},
223 want: "\n",
224 }, {
225 desc: "proto3 enum set to zero value",
226 input: &pb3.Enums{
227 SEnum: pb3.Enum_ZERO,
228 SNestedEnum: pb3.Enums_CERO,
229 },
230 want: "\n",
231 }, {
232 desc: "proto3 enum",
233 input: &pb3.Enums{
234 SEnum: pb3.Enum_ONE,
Herbie Ong8170d692019-02-13 14:13:21 -0800235 SNestedEnum: pb3.Enums_UNO,
Herbie Ong800c9902018-12-06 15:28:53 -0800236 },
237 want: `s_enum: ONE
Herbie Ong8170d692019-02-13 14:13:21 -0800238s_nested_enum: UNO
Herbie Ong800c9902018-12-06 15:28:53 -0800239`,
240 }, {
241 desc: "proto3 enum set to numeric values",
242 input: &pb3.Enums{
243 SEnum: 2,
Herbie Ong8170d692019-02-13 14:13:21 -0800244 SNestedEnum: 2,
Herbie Ong800c9902018-12-06 15:28:53 -0800245 },
246 want: `s_enum: TWO
Herbie Ong8170d692019-02-13 14:13:21 -0800247s_nested_enum: DOS
Herbie Ong800c9902018-12-06 15:28:53 -0800248`,
249 }, {
250 desc: "proto3 enum set to unnamed numeric values",
251 input: &pb3.Enums{
252 SEnum: -47,
253 SNestedEnum: 47,
254 },
255 want: `s_enum: -47
256s_nested_enum: 47
257`,
258 }, {
259 desc: "proto2 nested message not set",
260 input: &pb2.Nests{},
261 want: "\n",
262 }, {
263 desc: "proto2 nested message set to empty",
264 input: &pb2.Nests{
265 OptNested: &pb2.Nested{},
266 Optgroup: &pb2.Nests_OptGroup{},
267 },
268 want: `opt_nested: {}
Herbie Ong0dcfb9a2019-01-14 15:32:26 -0800269OptGroup: {}
Herbie Ong800c9902018-12-06 15:28:53 -0800270`,
271 }, {
272 desc: "proto2 nested messages",
273 input: &pb2.Nests{
274 OptNested: &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -0700275 OptString: proto.String("nested message"),
Herbie Ong800c9902018-12-06 15:28:53 -0800276 OptNested: &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -0700277 OptString: proto.String("another nested message"),
Herbie Ong800c9902018-12-06 15:28:53 -0800278 },
279 },
280 },
281 want: `opt_nested: {
282 opt_string: "nested message"
283 opt_nested: {
284 opt_string: "another nested message"
285 }
286}
287`,
288 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800289 desc: "proto2 groups",
Herbie Ong800c9902018-12-06 15:28:53 -0800290 input: &pb2.Nests{
291 Optgroup: &pb2.Nests_OptGroup{
Damien Neila8a2cea2019-07-10 16:17:16 -0700292 OptString: proto.String("inside a group"),
Herbie Ong800c9902018-12-06 15:28:53 -0800293 OptNested: &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -0700294 OptString: proto.String("nested message inside a group"),
Herbie Ong800c9902018-12-06 15:28:53 -0800295 },
296 Optnestedgroup: &pb2.Nests_OptGroup_OptNestedGroup{
Damien Neila8a2cea2019-07-10 16:17:16 -0700297 OptFixed32: proto.Uint32(47),
Herbie Ong800c9902018-12-06 15:28:53 -0800298 },
299 },
300 },
Herbie Ong0dcfb9a2019-01-14 15:32:26 -0800301 want: `OptGroup: {
Herbie Ong800c9902018-12-06 15:28:53 -0800302 opt_string: "inside a group"
303 opt_nested: {
304 opt_string: "nested message inside a group"
305 }
Herbie Ong0dcfb9a2019-01-14 15:32:26 -0800306 OptNestedGroup: {
Herbie Ong8170d692019-02-13 14:13:21 -0800307 opt_fixed32: 47
Herbie Ong800c9902018-12-06 15:28:53 -0800308 }
309}
310`,
311 }, {
312 desc: "proto3 nested message not set",
313 input: &pb3.Nests{},
314 want: "\n",
315 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800316 desc: "proto3 nested message set to empty",
317 input: &pb3.Nests{
318 SNested: &pb3.Nested{},
319 },
320 want: "s_nested: {}\n",
321 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800322 desc: "proto3 nested message",
323 input: &pb3.Nests{
324 SNested: &pb3.Nested{
325 SString: "nested message",
326 SNested: &pb3.Nested{
327 SString: "another nested message",
328 },
329 },
330 },
331 want: `s_nested: {
332 s_string: "nested message"
333 s_nested: {
334 s_string: "another nested message"
335 }
336}
337`,
338 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700339 desc: "proto3 nested message contains invalid UTF-8",
340 input: &pb3.Nests{
341 SNested: &pb3.Nested{
342 SString: "abc\xff",
343 },
344 },
Herbie Ong21a39742019-04-08 17:32:44 -0700345 wantErr: true,
346 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800347 desc: "oneof not set",
348 input: &pb3.Oneofs{},
Herbie Ong800c9902018-12-06 15:28:53 -0800349 want: "\n",
350 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800351 desc: "oneof set to empty string",
352 input: &pb3.Oneofs{
353 Union: &pb3.Oneofs_OneofString{},
Herbie Ong800c9902018-12-06 15:28:53 -0800354 },
Herbie Ong8170d692019-02-13 14:13:21 -0800355 want: `oneof_string: ""
356`,
Herbie Ong800c9902018-12-06 15:28:53 -0800357 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800358 desc: "oneof set to string",
359 input: &pb3.Oneofs{
360 Union: &pb3.Oneofs_OneofString{
361 OneofString: "hello",
Herbie Ong800c9902018-12-06 15:28:53 -0800362 },
363 },
Herbie Ong8170d692019-02-13 14:13:21 -0800364 want: `oneof_string: "hello"
365`,
Herbie Ong800c9902018-12-06 15:28:53 -0800366 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800367 desc: "oneof set to enum",
368 input: &pb3.Oneofs{
369 Union: &pb3.Oneofs_OneofEnum{
370 OneofEnum: pb3.Enum_ZERO,
Herbie Ong800c9902018-12-06 15:28:53 -0800371 },
372 },
Herbie Ong8170d692019-02-13 14:13:21 -0800373 want: `oneof_enum: ZERO
374`,
Herbie Ong800c9902018-12-06 15:28:53 -0800375 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800376 desc: "oneof set to empty message",
377 input: &pb3.Oneofs{
378 Union: &pb3.Oneofs_OneofNested{
379 OneofNested: &pb3.Nested{},
380 },
381 },
382 want: "oneof_nested: {}\n",
383 }, {
384 desc: "oneof set to message",
385 input: &pb3.Oneofs{
386 Union: &pb3.Oneofs_OneofNested{
387 OneofNested: &pb3.Nested{
388 SString: "nested message",
Herbie Ong800c9902018-12-06 15:28:53 -0800389 },
390 },
391 },
Herbie Ong8170d692019-02-13 14:13:21 -0800392 want: `oneof_nested: {
393 s_string: "nested message"
Herbie Ong800c9902018-12-06 15:28:53 -0800394}
395`,
396 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800397 desc: "repeated fields not set",
Herbie Ong800c9902018-12-06 15:28:53 -0800398 input: &pb2.Repeats{},
399 want: "\n",
400 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800401 desc: "repeated fields set to empty slices",
Herbie Ong800c9902018-12-06 15:28:53 -0800402 input: &pb2.Repeats{
Herbie Ongcddf8192018-11-28 18:25:20 -0800403 RptBool: []bool{},
404 RptInt32: []int32{},
405 RptInt64: []int64{},
406 RptUint32: []uint32{},
407 RptUint64: []uint64{},
408 RptFloat: []float32{},
409 RptDouble: []float64{},
410 RptBytes: [][]byte{},
Herbie Ong800c9902018-12-06 15:28:53 -0800411 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800412 want: "\n",
413 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800414 desc: "repeated fields set to some values",
Herbie Ong800c9902018-12-06 15:28:53 -0800415 input: &pb2.Repeats{
Herbie Ongcddf8192018-11-28 18:25:20 -0800416 RptBool: []bool{true, false, true, true},
417 RptInt32: []int32{1, 6, 0, 0},
418 RptInt64: []int64{-64, 47},
419 RptUint32: []uint32{0xff, 0xffff},
420 RptUint64: []uint64{0xdeadbeef},
Herbie Ong84f09602019-01-17 19:31:47 -0800421 RptFloat: []float32{float32(math.NaN()), float32(math.Inf(1)), float32(math.Inf(-1)), 1.034},
Herbie Ongcddf8192018-11-28 18:25:20 -0800422 RptDouble: []float64{math.NaN(), math.Inf(1), math.Inf(-1), 1.23e-308},
423 RptString: []string{"hello", "世界"},
424 RptBytes: [][]byte{
425 []byte("hello"),
426 []byte("\xe4\xb8\x96\xe7\x95\x8c"),
427 },
Herbie Ong800c9902018-12-06 15:28:53 -0800428 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800429 want: `rpt_bool: true
430rpt_bool: false
431rpt_bool: true
432rpt_bool: true
433rpt_int32: 1
434rpt_int32: 6
435rpt_int32: 0
436rpt_int32: 0
437rpt_int64: -64
438rpt_int64: 47
439rpt_uint32: 255
440rpt_uint32: 65535
441rpt_uint64: 3735928559
Herbie Ong84f09602019-01-17 19:31:47 -0800442rpt_float: nan
443rpt_float: inf
444rpt_float: -inf
445rpt_float: 1.034
Herbie Ongcddf8192018-11-28 18:25:20 -0800446rpt_double: nan
447rpt_double: inf
448rpt_double: -inf
449rpt_double: 1.23e-308
450rpt_string: "hello"
451rpt_string: "世界"
452rpt_bytes: "hello"
453rpt_bytes: "世界"
454`,
455 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700456 desc: "repeated contains invalid UTF-8",
457 input: &pb2.Repeats{
458 RptString: []string{"abc\xff"},
459 },
Herbie Ong21a39742019-04-08 17:32:44 -0700460 wantErr: true,
461 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800462 desc: "repeated enums",
Herbie Ong800c9902018-12-06 15:28:53 -0800463 input: &pb2.Enums{
Herbie Ong8170d692019-02-13 14:13:21 -0800464 RptEnum: []pb2.Enum{pb2.Enum_ONE, 2, pb2.Enum_TEN, 42},
Herbie Ongcddf8192018-11-28 18:25:20 -0800465 RptNestedEnum: []pb2.Enums_NestedEnum{2, 47, 10},
Herbie Ong800c9902018-12-06 15:28:53 -0800466 },
Herbie Ong8170d692019-02-13 14:13:21 -0800467 want: `rpt_enum: ONE
468rpt_enum: TWO
469rpt_enum: TEN
Herbie Ongcddf8192018-11-28 18:25:20 -0800470rpt_enum: 42
Herbie Ongcddf8192018-11-28 18:25:20 -0800471rpt_nested_enum: DOS
472rpt_nested_enum: 47
473rpt_nested_enum: DIEZ
474`,
475 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800476 desc: "repeated messages set to empty",
Herbie Ong800c9902018-12-06 15:28:53 -0800477 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800478 RptNested: []*pb2.Nested{},
479 Rptgroup: []*pb2.Nests_RptGroup{},
Herbie Ong800c9902018-12-06 15:28:53 -0800480 },
481 want: "\n",
Herbie Ongcddf8192018-11-28 18:25:20 -0800482 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800483 desc: "repeated messages",
Herbie Ong800c9902018-12-06 15:28:53 -0800484 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800485 RptNested: []*pb2.Nested{
486 {
Damien Neila8a2cea2019-07-10 16:17:16 -0700487 OptString: proto.String("repeat nested one"),
Herbie Ongcddf8192018-11-28 18:25:20 -0800488 },
489 {
Damien Neila8a2cea2019-07-10 16:17:16 -0700490 OptString: proto.String("repeat nested two"),
Herbie Ongcddf8192018-11-28 18:25:20 -0800491 OptNested: &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -0700492 OptString: proto.String("inside repeat nested two"),
Herbie Ongcddf8192018-11-28 18:25:20 -0800493 },
494 },
495 {},
496 },
Herbie Ong800c9902018-12-06 15:28:53 -0800497 },
498 want: `rpt_nested: {
Herbie Ongcddf8192018-11-28 18:25:20 -0800499 opt_string: "repeat nested one"
500}
501rpt_nested: {
502 opt_string: "repeat nested two"
503 opt_nested: {
504 opt_string: "inside repeat nested two"
505 }
506}
507rpt_nested: {}
508`,
509 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800510 desc: "repeated messages contains nil value",
Herbie Ongf5db2df2019-02-07 20:17:45 -0800511 input: &pb2.Nests{
512 RptNested: []*pb2.Nested{nil, {}},
513 },
514 want: `rpt_nested: {}
515rpt_nested: {}
516`,
517 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800518 desc: "repeated groups",
Herbie Ong800c9902018-12-06 15:28:53 -0800519 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800520 Rptgroup: []*pb2.Nests_RptGroup{
521 {
Herbie Ong8170d692019-02-13 14:13:21 -0800522 RptString: []string{"hello", "world"},
Herbie Ongcddf8192018-11-28 18:25:20 -0800523 },
524 {},
Herbie Ong8170d692019-02-13 14:13:21 -0800525 nil,
Herbie Ongcddf8192018-11-28 18:25:20 -0800526 },
Herbie Ong800c9902018-12-06 15:28:53 -0800527 },
Herbie Ongde7313b2019-01-14 19:26:50 -0800528 want: `RptGroup: {
Herbie Ong8170d692019-02-13 14:13:21 -0800529 rpt_string: "hello"
530 rpt_string: "world"
Herbie Ongcddf8192018-11-28 18:25:20 -0800531}
Herbie Ongde7313b2019-01-14 19:26:50 -0800532RptGroup: {}
Herbie Ong8170d692019-02-13 14:13:21 -0800533RptGroup: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800534`,
535 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800536 desc: "map fields not set",
537 input: &pb3.Maps{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800538 want: "\n",
539 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800540 desc: "map fields set to empty",
541 input: &pb3.Maps{
542 Int32ToStr: map[int32]string{},
543 BoolToUint32: map[bool]uint32{},
544 Uint64ToEnum: map[uint64]pb3.Enum{},
545 StrToNested: map[string]*pb3.Nested{},
546 StrToOneofs: map[string]*pb3.Oneofs{},
Herbie Ong800c9902018-12-06 15:28:53 -0800547 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800548 want: "\n",
549 }, {
550 desc: "map fields 1",
Herbie Ong8170d692019-02-13 14:13:21 -0800551 input: &pb3.Maps{
Herbie Ongcddf8192018-11-28 18:25:20 -0800552 Int32ToStr: map[int32]string{
553 -101: "-101",
554 0xff: "0xff",
555 0: "zero",
556 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800557 BoolToUint32: map[bool]uint32{
558 true: 42,
559 false: 101,
560 },
Herbie Ong800c9902018-12-06 15:28:53 -0800561 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800562 want: `int32_to_str: {
563 key: -101
564 value: "-101"
565}
566int32_to_str: {
567 key: 0
568 value: "zero"
569}
570int32_to_str: {
571 key: 255
572 value: "0xff"
573}
Herbie Ongcddf8192018-11-28 18:25:20 -0800574bool_to_uint32: {
575 key: false
576 value: 101
577}
578bool_to_uint32: {
579 key: true
580 value: 42
581}
582`,
583 }, {
584 desc: "map fields 2",
Herbie Ong8170d692019-02-13 14:13:21 -0800585 input: &pb3.Maps{
586 Uint64ToEnum: map[uint64]pb3.Enum{
587 1: pb3.Enum_ONE,
588 2: pb3.Enum_TWO,
589 10: pb3.Enum_TEN,
590 47: 47,
Herbie Ongcddf8192018-11-28 18:25:20 -0800591 },
Herbie Ong800c9902018-12-06 15:28:53 -0800592 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800593 want: `uint64_to_enum: {
594 key: 1
Herbie Ong8170d692019-02-13 14:13:21 -0800595 value: ONE
Herbie Ongcddf8192018-11-28 18:25:20 -0800596}
597uint64_to_enum: {
598 key: 2
Herbie Ong8170d692019-02-13 14:13:21 -0800599 value: TWO
Herbie Ongcddf8192018-11-28 18:25:20 -0800600}
601uint64_to_enum: {
602 key: 10
Herbie Ong8170d692019-02-13 14:13:21 -0800603 value: TEN
604}
605uint64_to_enum: {
606 key: 47
607 value: 47
Herbie Ongcddf8192018-11-28 18:25:20 -0800608}
609`,
610 }, {
611 desc: "map fields 3",
Herbie Ong8170d692019-02-13 14:13:21 -0800612 input: &pb3.Maps{
613 StrToNested: map[string]*pb3.Nested{
614 "nested": &pb3.Nested{
615 SString: "nested in a map",
Herbie Ongcddf8192018-11-28 18:25:20 -0800616 },
617 },
Herbie Ong800c9902018-12-06 15:28:53 -0800618 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800619 want: `str_to_nested: {
Herbie Ong8170d692019-02-13 14:13:21 -0800620 key: "nested"
Herbie Ongcddf8192018-11-28 18:25:20 -0800621 value: {
Herbie Ong8170d692019-02-13 14:13:21 -0800622 s_string: "nested in a map"
Herbie Ongcddf8192018-11-28 18:25:20 -0800623 }
624}
625`,
626 }, {
627 desc: "map fields 4",
Herbie Ong8170d692019-02-13 14:13:21 -0800628 input: &pb3.Maps{
629 StrToOneofs: map[string]*pb3.Oneofs{
630 "string": &pb3.Oneofs{
631 Union: &pb3.Oneofs_OneofString{
632 OneofString: "hello",
Herbie Ongcddf8192018-11-28 18:25:20 -0800633 },
634 },
Herbie Ong8170d692019-02-13 14:13:21 -0800635 "nested": &pb3.Oneofs{
636 Union: &pb3.Oneofs_OneofNested{
637 OneofNested: &pb3.Nested{
638 SString: "nested oneof in map field value",
Herbie Ongcddf8192018-11-28 18:25:20 -0800639 },
640 },
641 },
642 },
Herbie Ong800c9902018-12-06 15:28:53 -0800643 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800644 want: `str_to_oneofs: {
645 key: "nested"
646 value: {
Herbie Ong8170d692019-02-13 14:13:21 -0800647 oneof_nested: {
648 s_string: "nested oneof in map field value"
Herbie Ongcddf8192018-11-28 18:25:20 -0800649 }
650 }
651}
652str_to_oneofs: {
653 key: "string"
654 value: {
Herbie Ong8170d692019-02-13 14:13:21 -0800655 oneof_string: "hello"
Herbie Ongcddf8192018-11-28 18:25:20 -0800656 }
657}
658`,
659 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700660 desc: "map field value contains invalid UTF-8",
661 input: &pb3.Maps{
662 Int32ToStr: map[int32]string{
663 101: "abc\xff",
664 },
665 },
Herbie Ong21a39742019-04-08 17:32:44 -0700666 wantErr: true,
667 }, {
668 desc: "map field key contains invalid UTF-8",
669 input: &pb3.Maps{
670 StrToNested: map[string]*pb3.Nested{
671 "abc\xff": {},
672 },
673 },
Herbie Ong21a39742019-04-08 17:32:44 -0700674 wantErr: true,
675 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800676 desc: "map field contains nil value",
677 input: &pb3.Maps{
678 StrToNested: map[string]*pb3.Nested{
Herbie Ongf5db2df2019-02-07 20:17:45 -0800679 "nil": nil,
680 },
681 },
682 want: `str_to_nested: {
683 key: "nil"
684 value: {}
685}
686`,
687 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700688 desc: "required fields not set",
Herbie Ong800c9902018-12-06 15:28:53 -0800689 input: &pb2.Requireds{},
690 want: "\n",
691 wantErr: true,
Herbie Ongcddf8192018-11-28 18:25:20 -0800692 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700693 desc: "required fields partially set",
Herbie Ong800c9902018-12-06 15:28:53 -0800694 input: &pb2.Requireds{
Damien Neila8a2cea2019-07-10 16:17:16 -0700695 ReqBool: proto.Bool(false),
696 ReqSfixed64: proto.Int64(0xbeefcafe),
697 ReqDouble: proto.Float64(math.NaN()),
698 ReqString: proto.String("hello"),
Herbie Ong8170d692019-02-13 14:13:21 -0800699 ReqEnum: pb2.Enum_ONE.Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800700 },
701 want: `req_bool: false
Herbie Ong800c9902018-12-06 15:28:53 -0800702req_sfixed64: 3203386110
703req_double: nan
704req_string: "hello"
Herbie Ong8170d692019-02-13 14:13:21 -0800705req_enum: ONE
Herbie Ong800c9902018-12-06 15:28:53 -0800706`,
707 wantErr: true,
708 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700709 desc: "required fields not set with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700710 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong42577ea2019-03-26 16:26:22 -0700711 input: &pb2.Requireds{
Damien Neila8a2cea2019-07-10 16:17:16 -0700712 ReqBool: proto.Bool(false),
713 ReqSfixed64: proto.Int64(0xbeefcafe),
714 ReqDouble: proto.Float64(math.NaN()),
715 ReqString: proto.String("hello"),
Herbie Ong42577ea2019-03-26 16:26:22 -0700716 ReqEnum: pb2.Enum_ONE.Enum(),
717 },
718 want: `req_bool: false
719req_sfixed64: 3203386110
720req_double: nan
721req_string: "hello"
722req_enum: ONE
723`,
724 }, {
725 desc: "required fields all set",
Herbie Ong800c9902018-12-06 15:28:53 -0800726 input: &pb2.Requireds{
Damien Neila8a2cea2019-07-10 16:17:16 -0700727 ReqBool: proto.Bool(false),
728 ReqSfixed64: proto.Int64(0),
729 ReqDouble: proto.Float64(1.23),
730 ReqString: proto.String(""),
Herbie Ong8170d692019-02-13 14:13:21 -0800731 ReqEnum: pb2.Enum_ONE.Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800732 ReqNested: &pb2.Nested{},
733 },
734 want: `req_bool: false
Herbie Ong800c9902018-12-06 15:28:53 -0800735req_sfixed64: 0
Herbie Ong8170d692019-02-13 14:13:21 -0800736req_double: 1.23
Herbie Ong800c9902018-12-06 15:28:53 -0800737req_string: ""
Herbie Ong8170d692019-02-13 14:13:21 -0800738req_enum: ONE
Herbie Ong800c9902018-12-06 15:28:53 -0800739req_nested: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800740`,
741 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800742 desc: "indirect required field",
743 input: &pb2.IndirectRequired{
744 OptNested: &pb2.NestedWithRequired{},
745 },
746 want: "opt_nested: {}\n",
747 wantErr: true,
Herbie Ongcddf8192018-11-28 18:25:20 -0800748 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700749 desc: "indirect required field with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700750 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong42577ea2019-03-26 16:26:22 -0700751 input: &pb2.IndirectRequired{
752 OptNested: &pb2.NestedWithRequired{},
753 },
754 want: "opt_nested: {}\n",
755 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800756 desc: "indirect required field in empty repeated",
757 input: &pb2.IndirectRequired{
758 RptNested: []*pb2.NestedWithRequired{},
759 },
760 want: "\n",
Herbie Ongcddf8192018-11-28 18:25:20 -0800761 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800762 desc: "indirect required field in repeated",
763 input: &pb2.IndirectRequired{
764 RptNested: []*pb2.NestedWithRequired{
765 &pb2.NestedWithRequired{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800766 },
Herbie Ong800c9902018-12-06 15:28:53 -0800767 },
768 want: "rpt_nested: {}\n",
769 wantErr: true,
770 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700771 desc: "indirect required field in repeated with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700772 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong42577ea2019-03-26 16:26:22 -0700773 input: &pb2.IndirectRequired{
774 RptNested: []*pb2.NestedWithRequired{
775 &pb2.NestedWithRequired{},
776 },
777 },
778 want: "rpt_nested: {}\n",
779 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800780 desc: "indirect required field in empty map",
781 input: &pb2.IndirectRequired{
782 StrToNested: map[string]*pb2.NestedWithRequired{},
783 },
784 want: "\n",
785 }, {
786 desc: "indirect required field in map",
787 input: &pb2.IndirectRequired{
788 StrToNested: map[string]*pb2.NestedWithRequired{
789 "fail": &pb2.NestedWithRequired{},
790 },
791 },
792 want: `str_to_nested: {
793 key: "fail"
794 value: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800795}
796`,
Herbie Ong800c9902018-12-06 15:28:53 -0800797 wantErr: true,
Herbie Ong20a1d312018-12-11 21:08:58 -0800798 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700799 desc: "indirect required field in map with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700800 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong42577ea2019-03-26 16:26:22 -0700801 input: &pb2.IndirectRequired{
802 StrToNested: map[string]*pb2.NestedWithRequired{
803 "fail": &pb2.NestedWithRequired{},
804 },
805 },
806 want: `str_to_nested: {
807 key: "fail"
808 value: {}
809}
810`,
811 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800812 desc: "indirect required field in oneof",
813 input: &pb2.IndirectRequired{
814 Union: &pb2.IndirectRequired_OneofNested{
815 OneofNested: &pb2.NestedWithRequired{},
816 },
817 },
818 want: "oneof_nested: {}\n",
819 wantErr: true,
820 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700821 desc: "indirect required field in oneof with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700822 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong42577ea2019-03-26 16:26:22 -0700823 input: &pb2.IndirectRequired{
824 Union: &pb2.IndirectRequired_OneofNested{
825 OneofNested: &pb2.NestedWithRequired{},
826 },
827 },
828 want: "oneof_nested: {}\n",
829 }, {
Herbie Ong20a1d312018-12-11 21:08:58 -0800830 desc: "unknown varint and fixed types",
Joe Tsai28216c72019-06-22 13:20:09 -0700831 input: func() proto.Message {
832 m := &pb2.Scalars{
Damien Neila8a2cea2019-07-10 16:17:16 -0700833 OptString: proto.String("this message contains unknown fields"),
Joe Tsai28216c72019-06-22 13:20:09 -0700834 }
835 m.ProtoReflect().SetUnknown(pack.Message{
Herbie Ong20a1d312018-12-11 21:08:58 -0800836 pack.Tag{101, pack.VarintType}, pack.Bool(true),
837 pack.Tag{102, pack.VarintType}, pack.Varint(0xff),
838 pack.Tag{103, pack.Fixed32Type}, pack.Uint32(47),
839 pack.Tag{104, pack.Fixed64Type}, pack.Int64(0xdeadbeef),
Joe Tsai28216c72019-06-22 13:20:09 -0700840 }.Marshal())
841 return m
842 }(),
Herbie Ong20a1d312018-12-11 21:08:58 -0800843 want: `opt_string: "this message contains unknown fields"
844101: 1
845102: 255
846103: 47
847104: 3735928559
848`,
849 }, {
850 desc: "unknown length-delimited",
Joe Tsai28216c72019-06-22 13:20:09 -0700851 input: func() proto.Message {
852 m := new(pb2.Scalars)
853 m.ProtoReflect().SetUnknown(pack.Message{
Herbie Ong20a1d312018-12-11 21:08:58 -0800854 pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false)},
855 pack.Tag{102, pack.BytesType}, pack.String("hello world"),
856 pack.Tag{103, pack.BytesType}, pack.Bytes("\xe4\xb8\x96\xe7\x95\x8c"),
Joe Tsai28216c72019-06-22 13:20:09 -0700857 }.Marshal())
858 return m
859 }(),
Herbie Ong20a1d312018-12-11 21:08:58 -0800860 want: `101: "\x01\x00"
861102: "hello world"
862103: "世界"
863`,
864 }, {
865 desc: "unknown group type",
Joe Tsai28216c72019-06-22 13:20:09 -0700866 input: func() proto.Message {
867 m := new(pb2.Scalars)
868 m.ProtoReflect().SetUnknown(pack.Message{
Herbie Ong20a1d312018-12-11 21:08:58 -0800869 pack.Tag{101, pack.StartGroupType}, pack.Tag{101, pack.EndGroupType},
870 pack.Tag{102, pack.StartGroupType},
871 pack.Tag{101, pack.VarintType}, pack.Bool(false),
872 pack.Tag{102, pack.BytesType}, pack.String("inside a group"),
873 pack.Tag{102, pack.EndGroupType},
Joe Tsai28216c72019-06-22 13:20:09 -0700874 }.Marshal())
875 return m
876 }(),
Herbie Ong20a1d312018-12-11 21:08:58 -0800877 want: `101: {}
878102: {
879 101: 0
880 102: "inside a group"
881}
882`,
883 }, {
884 desc: "unknown unpack repeated field",
Joe Tsai28216c72019-06-22 13:20:09 -0700885 input: func() proto.Message {
886 m := new(pb2.Scalars)
887 m.ProtoReflect().SetUnknown(pack.Message{
Herbie Ong20a1d312018-12-11 21:08:58 -0800888 pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false), pack.Bool(true)},
889 pack.Tag{102, pack.BytesType}, pack.String("hello"),
890 pack.Tag{101, pack.VarintType}, pack.Bool(true),
891 pack.Tag{102, pack.BytesType}, pack.String("世界"),
Joe Tsai28216c72019-06-22 13:20:09 -0700892 }.Marshal())
893 return m
894 }(),
Herbie Ong20a1d312018-12-11 21:08:58 -0800895 want: `101: "\x01\x00\x01"
Herbie Ong20a1d312018-12-11 21:08:58 -0800896102: "hello"
Joe Tsai378c1322019-04-25 23:48:08 -0700897101: 1
Herbie Ong20a1d312018-12-11 21:08:58 -0800898102: "世界"
899`,
Herbie Ongcf253082018-12-17 17:13:07 -0800900 }, {
901 desc: "extensions of non-repeated fields",
902 input: func() proto.Message {
903 m := &pb2.Extensions{
Damien Neila8a2cea2019-07-10 16:17:16 -0700904 OptString: proto.String("non-extension field"),
905 OptBool: proto.Bool(true),
906 OptInt32: proto.Int32(42),
Herbie Ongcf253082018-12-17 17:13:07 -0800907 }
908 setExtension(m, pb2.E_OptExtBool, true)
909 setExtension(m, pb2.E_OptExtString, "extension field")
Herbie Ong8170d692019-02-13 14:13:21 -0800910 setExtension(m, pb2.E_OptExtEnum, pb2.Enum_TEN)
Herbie Ongcf253082018-12-17 17:13:07 -0800911 setExtension(m, pb2.E_OptExtNested, &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -0700912 OptString: proto.String("nested in an extension"),
Herbie Ongcf253082018-12-17 17:13:07 -0800913 OptNested: &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -0700914 OptString: proto.String("another nested in an extension"),
Herbie Ongcf253082018-12-17 17:13:07 -0800915 },
916 })
917 return m
918 }(),
919 want: `opt_string: "non-extension field"
920opt_bool: true
921opt_int32: 42
922[pb2.opt_ext_bool]: true
Herbie Ong8170d692019-02-13 14:13:21 -0800923[pb2.opt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -0800924[pb2.opt_ext_nested]: {
925 opt_string: "nested in an extension"
926 opt_nested: {
927 opt_string: "another nested in an extension"
928 }
929}
930[pb2.opt_ext_string]: "extension field"
931`,
932 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700933 desc: "extension field contains invalid UTF-8",
934 input: func() proto.Message {
935 m := &pb2.Extensions{}
936 setExtension(m, pb2.E_OptExtString, "abc\xff")
937 return m
938 }(),
Herbie Ong21a39742019-04-08 17:32:44 -0700939 wantErr: true,
940 }, {
Herbie Ong09b28a92019-04-03 15:42:41 -0700941 desc: "extension partial returns error",
942 input: func() proto.Message {
943 m := &pb2.Extensions{}
944 setExtension(m, pb2.E_OptExtPartial, &pb2.PartialRequired{
Damien Neila8a2cea2019-07-10 16:17:16 -0700945 OptString: proto.String("partial1"),
Herbie Ong09b28a92019-04-03 15:42:41 -0700946 })
947 setExtension(m, pb2.E_ExtensionsContainer_OptExtPartial, &pb2.PartialRequired{
Damien Neila8a2cea2019-07-10 16:17:16 -0700948 OptString: proto.String("partial2"),
Herbie Ong09b28a92019-04-03 15:42:41 -0700949 })
950 return m
951 }(),
952 want: `[pb2.ExtensionsContainer.opt_ext_partial]: {
953 opt_string: "partial2"
954}
955[pb2.opt_ext_partial]: {
956 opt_string: "partial1"
957}
958`,
959 wantErr: true,
960 }, {
961 desc: "extension partial with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700962 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong09b28a92019-04-03 15:42:41 -0700963 input: func() proto.Message {
964 m := &pb2.Extensions{}
965 setExtension(m, pb2.E_OptExtPartial, &pb2.PartialRequired{
Damien Neila8a2cea2019-07-10 16:17:16 -0700966 OptString: proto.String("partial1"),
Herbie Ong09b28a92019-04-03 15:42:41 -0700967 })
968 return m
969 }(),
970 want: `[pb2.opt_ext_partial]: {
971 opt_string: "partial1"
972}
973`,
974 }, {
Herbie Ongcf253082018-12-17 17:13:07 -0800975 desc: "extensions of repeated fields",
976 input: func() proto.Message {
977 m := &pb2.Extensions{}
Herbie Ong8170d692019-02-13 14:13:21 -0800978 setExtension(m, pb2.E_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
Herbie Ongcf253082018-12-17 17:13:07 -0800979 setExtension(m, pb2.E_RptExtFixed32, &[]uint32{42, 47})
980 setExtension(m, pb2.E_RptExtNested, &[]*pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -0700981 &pb2.Nested{OptString: proto.String("one")},
982 &pb2.Nested{OptString: proto.String("two")},
983 &pb2.Nested{OptString: proto.String("three")},
Herbie Ongcf253082018-12-17 17:13:07 -0800984 })
985 return m
986 }(),
Herbie Ong8170d692019-02-13 14:13:21 -0800987 want: `[pb2.rpt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -0800988[pb2.rpt_ext_enum]: 101
Herbie Ong8170d692019-02-13 14:13:21 -0800989[pb2.rpt_ext_enum]: ONE
Herbie Ongcf253082018-12-17 17:13:07 -0800990[pb2.rpt_ext_fixed32]: 42
991[pb2.rpt_ext_fixed32]: 47
992[pb2.rpt_ext_nested]: {
993 opt_string: "one"
994}
995[pb2.rpt_ext_nested]: {
996 opt_string: "two"
997}
998[pb2.rpt_ext_nested]: {
999 opt_string: "three"
1000}
1001`,
1002 }, {
1003 desc: "extensions of non-repeated fields in another message",
1004 input: func() proto.Message {
1005 m := &pb2.Extensions{}
1006 setExtension(m, pb2.E_ExtensionsContainer_OptExtBool, true)
1007 setExtension(m, pb2.E_ExtensionsContainer_OptExtString, "extension field")
Herbie Ong8170d692019-02-13 14:13:21 -08001008 setExtension(m, pb2.E_ExtensionsContainer_OptExtEnum, pb2.Enum_TEN)
Herbie Ongcf253082018-12-17 17:13:07 -08001009 setExtension(m, pb2.E_ExtensionsContainer_OptExtNested, &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -07001010 OptString: proto.String("nested in an extension"),
Herbie Ongcf253082018-12-17 17:13:07 -08001011 OptNested: &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -07001012 OptString: proto.String("another nested in an extension"),
Herbie Ongcf253082018-12-17 17:13:07 -08001013 },
1014 })
1015 return m
1016 }(),
1017 want: `[pb2.ExtensionsContainer.opt_ext_bool]: true
Herbie Ong8170d692019-02-13 14:13:21 -08001018[pb2.ExtensionsContainer.opt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -08001019[pb2.ExtensionsContainer.opt_ext_nested]: {
1020 opt_string: "nested in an extension"
1021 opt_nested: {
1022 opt_string: "another nested in an extension"
1023 }
1024}
1025[pb2.ExtensionsContainer.opt_ext_string]: "extension field"
1026`,
1027 }, {
1028 desc: "extensions of repeated fields in another message",
1029 input: func() proto.Message {
1030 m := &pb2.Extensions{
Damien Neila8a2cea2019-07-10 16:17:16 -07001031 OptString: proto.String("non-extension field"),
1032 OptBool: proto.Bool(true),
1033 OptInt32: proto.Int32(42),
Herbie Ongcf253082018-12-17 17:13:07 -08001034 }
Herbie Ong8170d692019-02-13 14:13:21 -08001035 setExtension(m, pb2.E_ExtensionsContainer_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
Herbie Ongcf253082018-12-17 17:13:07 -08001036 setExtension(m, pb2.E_ExtensionsContainer_RptExtString, &[]string{"hello", "world"})
1037 setExtension(m, pb2.E_ExtensionsContainer_RptExtNested, &[]*pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -07001038 &pb2.Nested{OptString: proto.String("one")},
1039 &pb2.Nested{OptString: proto.String("two")},
1040 &pb2.Nested{OptString: proto.String("three")},
Herbie Ongcf253082018-12-17 17:13:07 -08001041 })
1042 return m
1043 }(),
1044 want: `opt_string: "non-extension field"
1045opt_bool: true
1046opt_int32: 42
Herbie Ong8170d692019-02-13 14:13:21 -08001047[pb2.ExtensionsContainer.rpt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -08001048[pb2.ExtensionsContainer.rpt_ext_enum]: 101
Herbie Ong8170d692019-02-13 14:13:21 -08001049[pb2.ExtensionsContainer.rpt_ext_enum]: ONE
Herbie Ongcf253082018-12-17 17:13:07 -08001050[pb2.ExtensionsContainer.rpt_ext_nested]: {
1051 opt_string: "one"
1052}
1053[pb2.ExtensionsContainer.rpt_ext_nested]: {
1054 opt_string: "two"
1055}
1056[pb2.ExtensionsContainer.rpt_ext_nested]: {
1057 opt_string: "three"
1058}
1059[pb2.ExtensionsContainer.rpt_ext_string]: "hello"
1060[pb2.ExtensionsContainer.rpt_ext_string]: "world"
1061`,
Herbie Ong6470ea62019-01-07 18:56:57 -08001062 }, {
1063 desc: "MessageSet",
1064 input: func() proto.Message {
1065 m := &pb2.MessageSet{}
1066 setExtension(m, pb2.E_MessageSetExtension_MessageSetExtension, &pb2.MessageSetExtension{
Damien Neila8a2cea2019-07-10 16:17:16 -07001067 OptString: proto.String("a messageset extension"),
Herbie Ong6470ea62019-01-07 18:56:57 -08001068 })
1069 setExtension(m, pb2.E_MessageSetExtension_NotMessageSetExtension, &pb2.MessageSetExtension{
Damien Neila8a2cea2019-07-10 16:17:16 -07001070 OptString: proto.String("not a messageset extension"),
Herbie Ong6470ea62019-01-07 18:56:57 -08001071 })
1072 setExtension(m, pb2.E_MessageSetExtension_ExtNested, &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -07001073 OptString: proto.String("just a regular extension"),
Herbie Ong6470ea62019-01-07 18:56:57 -08001074 })
1075 return m
1076 }(),
1077 want: `[pb2.MessageSetExtension]: {
1078 opt_string: "a messageset extension"
1079}
1080[pb2.MessageSetExtension.ext_nested]: {
1081 opt_string: "just a regular extension"
1082}
1083[pb2.MessageSetExtension.not_message_set_extension]: {
1084 opt_string: "not a messageset extension"
1085}
1086`,
Joe Tsai5ae10aa2019-07-11 18:23:08 -07001087 skip: !flags.Proto1Legacy,
Herbie Ong6470ea62019-01-07 18:56:57 -08001088 }, {
1089 desc: "not real MessageSet 1",
1090 input: func() proto.Message {
1091 m := &pb2.FakeMessageSet{}
1092 setExtension(m, pb2.E_FakeMessageSetExtension_MessageSetExtension, &pb2.FakeMessageSetExtension{
Damien Neila8a2cea2019-07-10 16:17:16 -07001093 OptString: proto.String("not a messageset extension"),
Herbie Ong6470ea62019-01-07 18:56:57 -08001094 })
1095 return m
1096 }(),
1097 want: `[pb2.FakeMessageSetExtension.message_set_extension]: {
1098 opt_string: "not a messageset extension"
1099}
1100`,
Joe Tsai5ae10aa2019-07-11 18:23:08 -07001101 skip: !flags.Proto1Legacy,
Herbie Ong6470ea62019-01-07 18:56:57 -08001102 }, {
1103 desc: "not real MessageSet 2",
1104 input: func() proto.Message {
1105 m := &pb2.MessageSet{}
1106 setExtension(m, pb2.E_MessageSetExtension, &pb2.FakeMessageSetExtension{
Damien Neila8a2cea2019-07-10 16:17:16 -07001107 OptString: proto.String("another not a messageset extension"),
Herbie Ong6470ea62019-01-07 18:56:57 -08001108 })
1109 return m
1110 }(),
1111 want: `[pb2.message_set_extension]: {
1112 opt_string: "another not a messageset extension"
1113}
1114`,
Joe Tsai5ae10aa2019-07-11 18:23:08 -07001115 skip: !flags.Proto1Legacy,
Herbie Ongf42b55f2019-01-02 15:46:07 -08001116 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001117 desc: "Any not expanded",
Damien Neil5c5b5312019-05-14 12:44:37 -07001118 mo: prototext.MarshalOptions{
Herbie Ong66c365c2019-01-04 14:08:41 -08001119 Resolver: preg.NewTypes(),
1120 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001121 input: func() proto.Message {
1122 m := &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -07001123 OptString: proto.String("embedded inside Any"),
Herbie Ongf42b55f2019-01-02 15:46:07 -08001124 OptNested: &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -07001125 OptString: proto.String("inception"),
Herbie Ongf42b55f2019-01-02 15:46:07 -08001126 },
1127 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -07001128 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ongf42b55f2019-01-02 15:46:07 -08001129 if err != nil {
1130 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1131 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07001132 return &anypb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001133 TypeUrl: "pb2.Nested",
Herbie Ongf42b55f2019-01-02 15:46:07 -08001134 Value: b,
Herbie Ong300cff02019-03-20 18:05:16 -07001135 }
Herbie Ongf42b55f2019-01-02 15:46:07 -08001136 }(),
1137 want: `type_url: "pb2.Nested"
1138value: "\n\x13embedded inside Any\x12\x0b\n\tinception"
1139`,
1140 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001141 desc: "Any expanded",
Damien Neil5c5b5312019-05-14 12:44:37 -07001142 mo: prototext.MarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001143 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
Herbie Ong66c365c2019-01-04 14:08:41 -08001144 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001145 input: func() proto.Message {
1146 m := &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -07001147 OptString: proto.String("embedded inside Any"),
Herbie Ongf42b55f2019-01-02 15:46:07 -08001148 OptNested: &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -07001149 OptString: proto.String("inception"),
Herbie Ongf42b55f2019-01-02 15:46:07 -08001150 },
1151 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -07001152 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ongf42b55f2019-01-02 15:46:07 -08001153 if err != nil {
1154 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1155 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07001156 return &anypb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001157 TypeUrl: "foo/pb2.Nested",
Herbie Ongf42b55f2019-01-02 15:46:07 -08001158 Value: b,
Herbie Ong300cff02019-03-20 18:05:16 -07001159 }
Herbie Ongf42b55f2019-01-02 15:46:07 -08001160 }(),
Herbie Ong66c365c2019-01-04 14:08:41 -08001161 want: `[foo/pb2.Nested]: {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001162 opt_string: "embedded inside Any"
1163 opt_nested: {
1164 opt_string: "inception"
1165 }
1166}
1167`,
1168 }, {
Damien Neil0c9f0a92019-06-19 10:41:09 -07001169 desc: "Any expanded with missing required",
Damien Neil5c5b5312019-05-14 12:44:37 -07001170 mo: prototext.MarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001171 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.PartialRequired{})),
Herbie Ong66c365c2019-01-04 14:08:41 -08001172 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001173 input: func() proto.Message {
1174 m := &pb2.PartialRequired{
Damien Neila8a2cea2019-07-10 16:17:16 -07001175 OptString: proto.String("embedded inside Any"),
Herbie Ongf42b55f2019-01-02 15:46:07 -08001176 }
Damien Neil96c229a2019-04-03 12:17:24 -07001177 b, err := proto.MarshalOptions{
1178 AllowPartial: true,
1179 Deterministic: true,
1180 }.Marshal(m)
Herbie Ong300cff02019-03-20 18:05:16 -07001181 if err != nil {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001182 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1183 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07001184 return &anypb.Any{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001185 TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
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: `[pb2.PartialRequired]: {
1190 opt_string: "embedded inside Any"
1191}
1192`,
Herbie Ongf42b55f2019-01-02 15:46:07 -08001193 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001194 desc: "Any with invalid value",
Damien Neil5c5b5312019-05-14 12:44:37 -07001195 mo: prototext.MarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001196 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
Herbie Ong66c365c2019-01-04 14:08:41 -08001197 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07001198 input: &anypb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001199 TypeUrl: "foo/pb2.Nested",
Joe Tsai6dc168e2019-07-09 23:11:13 -07001200 Value: []byte("\x80"),
Herbie Ong300cff02019-03-20 18:05:16 -07001201 },
Herbie Ong66c365c2019-01-04 14:08:41 -08001202 want: `type_url: "foo/pb2.Nested"
Herbie Onga94f78c2019-01-03 15:39:58 -08001203value: "\x80"
1204`,
Herbie Ongcddf8192018-11-28 18:25:20 -08001205 }}
1206
1207 for _, tt := range tests {
1208 tt := tt
Joe Tsai5ae10aa2019-07-11 18:23:08 -07001209 if tt.skip {
1210 continue
1211 }
Herbie Ongcddf8192018-11-28 18:25:20 -08001212 t.Run(tt.desc, func(t *testing.T) {
Herbie Ong3a385912019-03-20 14:04:24 -07001213 // Use 2-space indentation on all MarshalOptions.
1214 tt.mo.Indent = " "
Herbie Ongf42b55f2019-01-02 15:46:07 -08001215 b, err := tt.mo.Marshal(tt.input)
Herbie Ongcddf8192018-11-28 18:25:20 -08001216 if err != nil && !tt.wantErr {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001217 t.Errorf("Marshal() returned error: %v\n", err)
Herbie Ongcddf8192018-11-28 18:25:20 -08001218 }
Herbie Ong800c9902018-12-06 15:28:53 -08001219 if err == nil && tt.wantErr {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001220 t.Error("Marshal() got nil error, want error\n")
Herbie Ongcddf8192018-11-28 18:25:20 -08001221 }
Herbie Ong800c9902018-12-06 15:28:53 -08001222 got := string(b)
1223 if tt.want != "" && got != tt.want {
1224 t.Errorf("Marshal()\n<got>\n%v\n<want>\n%v\n", got, tt.want)
Joe Tsai378c1322019-04-25 23:48:08 -07001225 if diff := cmp.Diff(tt.want, got); diff != "" {
Herbie Ongcddf8192018-11-28 18:25:20 -08001226 t.Errorf("Marshal() diff -want +got\n%v\n", diff)
1227 }
1228 }
1229 })
1230 }
1231}