blob: 003d490b56c91252b50fe08ae3fd8d683071f2e7 [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"
Damien Neile89e6242019-05-13 23:55:40 -070016 "google.golang.org/protobuf/proto"
17 preg "google.golang.org/protobuf/reflect/protoregistry"
18 "google.golang.org/protobuf/runtime/protoiface"
Herbie Ongcddf8192018-11-28 18:25:20 -080019
Damien Neile89e6242019-05-13 23:55:40 -070020 "google.golang.org/protobuf/encoding/testprotos/pb2"
21 "google.golang.org/protobuf/encoding/testprotos/pb3"
Joe Tsaia95b29f2019-05-16 12:47:20 -070022 "google.golang.org/protobuf/types/known/anypb"
Herbie Ongcddf8192018-11-28 18:25:20 -080023)
24
25func init() {
26 // Disable detrand to enable direct comparisons on outputs.
27 detrand.Disable()
28}
29
Joe Tsai378c1322019-04-25 23:48:08 -070030// TODO: Use proto.SetExtension when available.
Joe Tsai4fddeba2019-03-20 18:29:32 -070031func setExtension(m proto.Message, xd *protoiface.ExtensionDescV1, val interface{}) {
Joe Tsai378c1322019-04-25 23:48:08 -070032 m.ProtoReflect().Set(xd.Type, xd.Type.ValueOf(val))
Herbie Ongcf253082018-12-17 17:13:07 -080033}
34
Herbie Ongcddf8192018-11-28 18:25:20 -080035func TestMarshal(t *testing.T) {
36 tests := []struct {
37 desc string
Damien Neil5c5b5312019-05-14 12:44:37 -070038 mo prototext.MarshalOptions
Herbie Ong70651952018-12-13 14:19:50 -080039 input proto.Message
Herbie Ongcddf8192018-11-28 18:25:20 -080040 want string
Herbie Ong300cff02019-03-20 18:05:16 -070041 wantErr bool // TODO: Verify error message content.
Herbie Ongcddf8192018-11-28 18:25:20 -080042 }{{
Herbie Ong8170d692019-02-13 14:13:21 -080043 desc: "proto2 optional scalars not set",
Herbie Ong800c9902018-12-06 15:28:53 -080044 input: &pb2.Scalars{},
Herbie Ongcddf8192018-11-28 18:25:20 -080045 want: "\n",
46 }, {
Herbie Ong8170d692019-02-13 14:13:21 -080047 desc: "proto3 scalars not set",
Herbie Ong800c9902018-12-06 15:28:53 -080048 input: &pb3.Scalars{},
Herbie Ongcddf8192018-11-28 18:25:20 -080049 want: "\n",
50 }, {
Herbie Ong8170d692019-02-13 14:13:21 -080051 desc: "proto2 optional scalars set to zero values",
Herbie Ong800c9902018-12-06 15:28:53 -080052 input: &pb2.Scalars{
Damien Neila8a2cea2019-07-10 16:17:16 -070053 OptBool: proto.Bool(false),
54 OptInt32: proto.Int32(0),
55 OptInt64: proto.Int64(0),
56 OptUint32: proto.Uint32(0),
57 OptUint64: proto.Uint64(0),
58 OptSint32: proto.Int32(0),
59 OptSint64: proto.Int64(0),
60 OptFixed32: proto.Uint32(0),
61 OptFixed64: proto.Uint64(0),
62 OptSfixed32: proto.Int32(0),
63 OptSfixed64: proto.Int64(0),
64 OptFloat: proto.Float32(0),
65 OptDouble: proto.Float64(0),
Herbie Ongcddf8192018-11-28 18:25:20 -080066 OptBytes: []byte{},
Damien Neila8a2cea2019-07-10 16:17:16 -070067 OptString: proto.String(""),
Herbie Ong800c9902018-12-06 15:28:53 -080068 },
Herbie Ongcddf8192018-11-28 18:25:20 -080069 want: `opt_bool: false
70opt_int32: 0
71opt_int64: 0
72opt_uint32: 0
73opt_uint64: 0
74opt_sint32: 0
75opt_sint64: 0
76opt_fixed32: 0
77opt_fixed64: 0
78opt_sfixed32: 0
79opt_sfixed64: 0
80opt_float: 0
81opt_double: 0
82opt_bytes: ""
83opt_string: ""
84`,
85 }, {
Herbie Ong8170d692019-02-13 14:13:21 -080086 desc: "proto3 scalars set to zero values",
Herbie Ong800c9902018-12-06 15:28:53 -080087 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -080088 SBool: false,
89 SInt32: 0,
90 SInt64: 0,
91 SUint32: 0,
92 SUint64: 0,
93 SSint32: 0,
94 SSint64: 0,
95 SFixed32: 0,
96 SFixed64: 0,
97 SSfixed32: 0,
98 SSfixed64: 0,
99 SFloat: 0,
100 SDouble: 0,
101 SBytes: []byte{},
102 SString: "",
Herbie Ong800c9902018-12-06 15:28:53 -0800103 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800104 want: "\n",
105 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800106 desc: "proto2 optional scalars set to some values",
Herbie Ong800c9902018-12-06 15:28:53 -0800107 input: &pb2.Scalars{
Damien Neila8a2cea2019-07-10 16:17:16 -0700108 OptBool: proto.Bool(true),
109 OptInt32: proto.Int32(0xff),
110 OptInt64: proto.Int64(0xdeadbeef),
111 OptUint32: proto.Uint32(47),
112 OptUint64: proto.Uint64(0xdeadbeef),
113 OptSint32: proto.Int32(-1001),
114 OptSint64: proto.Int64(-0xffff),
115 OptFixed64: proto.Uint64(64),
116 OptSfixed32: proto.Int32(-32),
117 OptFloat: proto.Float32(1.02),
118 OptDouble: proto.Float64(1.0199999809265137),
Herbie Ong8170d692019-02-13 14:13:21 -0800119 OptBytes: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
Damien Neila8a2cea2019-07-10 16:17:16 -0700120 OptString: proto.String("谷歌"),
Herbie Ong800c9902018-12-06 15:28:53 -0800121 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800122 want: `opt_bool: true
123opt_int32: 255
124opt_int64: 3735928559
125opt_uint32: 47
126opt_uint64: 3735928559
127opt_sint32: -1001
128opt_sint64: -65535
129opt_fixed64: 64
130opt_sfixed32: -32
Herbie Ong84f09602019-01-17 19:31:47 -0800131opt_float: 1.02
132opt_double: 1.0199999809265137
Herbie Ongcddf8192018-11-28 18:25:20 -0800133opt_bytes: "谷歌"
134opt_string: "谷歌"
135`,
136 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700137 desc: "string with invalid UTF-8",
138 input: &pb3.Scalars{
139 SString: "abc\xff",
140 },
Herbie Ong21a39742019-04-08 17:32:44 -0700141 wantErr: true,
142 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800143 desc: "float nan",
Herbie Ong800c9902018-12-06 15:28:53 -0800144 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800145 SFloat: float32(math.NaN()),
Herbie Ong800c9902018-12-06 15:28:53 -0800146 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800147 want: "s_float: nan\n",
148 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800149 desc: "float positive infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800150 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800151 SFloat: float32(math.Inf(1)),
Herbie Ong800c9902018-12-06 15:28:53 -0800152 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800153 want: "s_float: inf\n",
154 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800155 desc: "float negative infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800156 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800157 SFloat: float32(math.Inf(-1)),
Herbie Ong800c9902018-12-06 15:28:53 -0800158 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800159 want: "s_float: -inf\n",
160 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800161 desc: "double nan",
Herbie Ong800c9902018-12-06 15:28:53 -0800162 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800163 SDouble: math.NaN(),
Herbie Ong800c9902018-12-06 15:28:53 -0800164 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800165 want: "s_double: nan\n",
166 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800167 desc: "double positive infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800168 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800169 SDouble: math.Inf(1),
Herbie Ong800c9902018-12-06 15:28:53 -0800170 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800171 want: "s_double: inf\n",
172 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800173 desc: "double negative infinity",
Herbie Ong800c9902018-12-06 15:28:53 -0800174 input: &pb3.Scalars{
Herbie Ongcddf8192018-11-28 18:25:20 -0800175 SDouble: math.Inf(-1),
Herbie Ong800c9902018-12-06 15:28:53 -0800176 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800177 want: "s_double: -inf\n",
178 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800179 desc: "proto2 enum not set",
180 input: &pb2.Enums{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800181 want: "\n",
182 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800183 desc: "proto2 enum set to zero value",
184 input: &pb2.Enums{
Joe Tsai6dc168e2019-07-09 23:11:13 -0700185 OptEnum: pb2.Enum(0).Enum(),
186 OptNestedEnum: pb2.Enums_NestedEnum(0).Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800187 },
Herbie Ong8170d692019-02-13 14:13:21 -0800188 want: `opt_enum: 0
Herbie Ong800c9902018-12-06 15:28:53 -0800189opt_nested_enum: 0
190`,
191 }, {
192 desc: "proto2 enum",
193 input: &pb2.Enums{
Herbie Ong8170d692019-02-13 14:13:21 -0800194 OptEnum: pb2.Enum_ONE.Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800195 OptNestedEnum: pb2.Enums_UNO.Enum(),
196 },
Herbie Ong8170d692019-02-13 14:13:21 -0800197 want: `opt_enum: ONE
Herbie Ong800c9902018-12-06 15:28:53 -0800198opt_nested_enum: UNO
199`,
200 }, {
201 desc: "proto2 enum set to numeric values",
202 input: &pb2.Enums{
Joe Tsai6dc168e2019-07-09 23:11:13 -0700203 OptEnum: pb2.Enum(2).Enum(),
204 OptNestedEnum: pb2.Enums_NestedEnum(2).Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800205 },
Herbie Ong8170d692019-02-13 14:13:21 -0800206 want: `opt_enum: TWO
Herbie Ong800c9902018-12-06 15:28:53 -0800207opt_nested_enum: DOS
208`,
209 }, {
210 desc: "proto2 enum set to unnamed numeric values",
211 input: &pb2.Enums{
Joe Tsai6dc168e2019-07-09 23:11:13 -0700212 OptEnum: pb2.Enum(101).Enum(),
213 OptNestedEnum: pb2.Enums_NestedEnum(-101).Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800214 },
215 want: `opt_enum: 101
216opt_nested_enum: -101
217`,
218 }, {
219 desc: "proto3 enum not set",
220 input: &pb3.Enums{},
221 want: "\n",
222 }, {
223 desc: "proto3 enum set to zero value",
224 input: &pb3.Enums{
225 SEnum: pb3.Enum_ZERO,
226 SNestedEnum: pb3.Enums_CERO,
227 },
228 want: "\n",
229 }, {
230 desc: "proto3 enum",
231 input: &pb3.Enums{
232 SEnum: pb3.Enum_ONE,
Herbie Ong8170d692019-02-13 14:13:21 -0800233 SNestedEnum: pb3.Enums_UNO,
Herbie Ong800c9902018-12-06 15:28:53 -0800234 },
235 want: `s_enum: ONE
Herbie Ong8170d692019-02-13 14:13:21 -0800236s_nested_enum: UNO
Herbie Ong800c9902018-12-06 15:28:53 -0800237`,
238 }, {
239 desc: "proto3 enum set to numeric values",
240 input: &pb3.Enums{
241 SEnum: 2,
Herbie Ong8170d692019-02-13 14:13:21 -0800242 SNestedEnum: 2,
Herbie Ong800c9902018-12-06 15:28:53 -0800243 },
244 want: `s_enum: TWO
Herbie Ong8170d692019-02-13 14:13:21 -0800245s_nested_enum: DOS
Herbie Ong800c9902018-12-06 15:28:53 -0800246`,
247 }, {
248 desc: "proto3 enum set to unnamed numeric values",
249 input: &pb3.Enums{
250 SEnum: -47,
251 SNestedEnum: 47,
252 },
253 want: `s_enum: -47
254s_nested_enum: 47
255`,
256 }, {
257 desc: "proto2 nested message not set",
258 input: &pb2.Nests{},
259 want: "\n",
260 }, {
261 desc: "proto2 nested message set to empty",
262 input: &pb2.Nests{
263 OptNested: &pb2.Nested{},
264 Optgroup: &pb2.Nests_OptGroup{},
265 },
266 want: `opt_nested: {}
Herbie Ong0dcfb9a2019-01-14 15:32:26 -0800267OptGroup: {}
Herbie Ong800c9902018-12-06 15:28:53 -0800268`,
269 }, {
270 desc: "proto2 nested messages",
271 input: &pb2.Nests{
272 OptNested: &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -0700273 OptString: proto.String("nested message"),
Herbie Ong800c9902018-12-06 15:28:53 -0800274 OptNested: &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -0700275 OptString: proto.String("another nested message"),
Herbie Ong800c9902018-12-06 15:28:53 -0800276 },
277 },
278 },
279 want: `opt_nested: {
280 opt_string: "nested message"
281 opt_nested: {
282 opt_string: "another nested message"
283 }
284}
285`,
286 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800287 desc: "proto2 groups",
Herbie Ong800c9902018-12-06 15:28:53 -0800288 input: &pb2.Nests{
289 Optgroup: &pb2.Nests_OptGroup{
Damien Neila8a2cea2019-07-10 16:17:16 -0700290 OptString: proto.String("inside a group"),
Herbie Ong800c9902018-12-06 15:28:53 -0800291 OptNested: &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -0700292 OptString: proto.String("nested message inside a group"),
Herbie Ong800c9902018-12-06 15:28:53 -0800293 },
294 Optnestedgroup: &pb2.Nests_OptGroup_OptNestedGroup{
Damien Neila8a2cea2019-07-10 16:17:16 -0700295 OptFixed32: proto.Uint32(47),
Herbie Ong800c9902018-12-06 15:28:53 -0800296 },
297 },
298 },
Herbie Ong0dcfb9a2019-01-14 15:32:26 -0800299 want: `OptGroup: {
Herbie Ong800c9902018-12-06 15:28:53 -0800300 opt_string: "inside a group"
301 opt_nested: {
302 opt_string: "nested message inside a group"
303 }
Herbie Ong0dcfb9a2019-01-14 15:32:26 -0800304 OptNestedGroup: {
Herbie Ong8170d692019-02-13 14:13:21 -0800305 opt_fixed32: 47
Herbie Ong800c9902018-12-06 15:28:53 -0800306 }
307}
308`,
309 }, {
310 desc: "proto3 nested message not set",
311 input: &pb3.Nests{},
312 want: "\n",
313 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800314 desc: "proto3 nested message set to empty",
315 input: &pb3.Nests{
316 SNested: &pb3.Nested{},
317 },
318 want: "s_nested: {}\n",
319 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800320 desc: "proto3 nested message",
321 input: &pb3.Nests{
322 SNested: &pb3.Nested{
323 SString: "nested message",
324 SNested: &pb3.Nested{
325 SString: "another nested message",
326 },
327 },
328 },
329 want: `s_nested: {
330 s_string: "nested message"
331 s_nested: {
332 s_string: "another nested message"
333 }
334}
335`,
336 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700337 desc: "proto3 nested message contains invalid UTF-8",
338 input: &pb3.Nests{
339 SNested: &pb3.Nested{
340 SString: "abc\xff",
341 },
342 },
Herbie Ong21a39742019-04-08 17:32:44 -0700343 wantErr: true,
344 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800345 desc: "oneof not set",
346 input: &pb3.Oneofs{},
Herbie Ong800c9902018-12-06 15:28:53 -0800347 want: "\n",
348 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800349 desc: "oneof set to empty string",
350 input: &pb3.Oneofs{
351 Union: &pb3.Oneofs_OneofString{},
Herbie Ong800c9902018-12-06 15:28:53 -0800352 },
Herbie Ong8170d692019-02-13 14:13:21 -0800353 want: `oneof_string: ""
354`,
Herbie Ong800c9902018-12-06 15:28:53 -0800355 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800356 desc: "oneof set to string",
357 input: &pb3.Oneofs{
358 Union: &pb3.Oneofs_OneofString{
359 OneofString: "hello",
Herbie Ong800c9902018-12-06 15:28:53 -0800360 },
361 },
Herbie Ong8170d692019-02-13 14:13:21 -0800362 want: `oneof_string: "hello"
363`,
Herbie Ong800c9902018-12-06 15:28:53 -0800364 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800365 desc: "oneof set to enum",
366 input: &pb3.Oneofs{
367 Union: &pb3.Oneofs_OneofEnum{
368 OneofEnum: pb3.Enum_ZERO,
Herbie Ong800c9902018-12-06 15:28:53 -0800369 },
370 },
Herbie Ong8170d692019-02-13 14:13:21 -0800371 want: `oneof_enum: ZERO
372`,
Herbie Ong800c9902018-12-06 15:28:53 -0800373 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800374 desc: "oneof set to empty message",
375 input: &pb3.Oneofs{
376 Union: &pb3.Oneofs_OneofNested{
377 OneofNested: &pb3.Nested{},
378 },
379 },
380 want: "oneof_nested: {}\n",
381 }, {
382 desc: "oneof set to message",
383 input: &pb3.Oneofs{
384 Union: &pb3.Oneofs_OneofNested{
385 OneofNested: &pb3.Nested{
386 SString: "nested message",
Herbie Ong800c9902018-12-06 15:28:53 -0800387 },
388 },
389 },
Herbie Ong8170d692019-02-13 14:13:21 -0800390 want: `oneof_nested: {
391 s_string: "nested message"
Herbie Ong800c9902018-12-06 15:28:53 -0800392}
393`,
394 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800395 desc: "repeated fields not set",
Herbie Ong800c9902018-12-06 15:28:53 -0800396 input: &pb2.Repeats{},
397 want: "\n",
398 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800399 desc: "repeated fields set to empty slices",
Herbie Ong800c9902018-12-06 15:28:53 -0800400 input: &pb2.Repeats{
Herbie Ongcddf8192018-11-28 18:25:20 -0800401 RptBool: []bool{},
402 RptInt32: []int32{},
403 RptInt64: []int64{},
404 RptUint32: []uint32{},
405 RptUint64: []uint64{},
406 RptFloat: []float32{},
407 RptDouble: []float64{},
408 RptBytes: [][]byte{},
Herbie Ong800c9902018-12-06 15:28:53 -0800409 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800410 want: "\n",
411 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800412 desc: "repeated fields set to some values",
Herbie Ong800c9902018-12-06 15:28:53 -0800413 input: &pb2.Repeats{
Herbie Ongcddf8192018-11-28 18:25:20 -0800414 RptBool: []bool{true, false, true, true},
415 RptInt32: []int32{1, 6, 0, 0},
416 RptInt64: []int64{-64, 47},
417 RptUint32: []uint32{0xff, 0xffff},
418 RptUint64: []uint64{0xdeadbeef},
Herbie Ong84f09602019-01-17 19:31:47 -0800419 RptFloat: []float32{float32(math.NaN()), float32(math.Inf(1)), float32(math.Inf(-1)), 1.034},
Herbie Ongcddf8192018-11-28 18:25:20 -0800420 RptDouble: []float64{math.NaN(), math.Inf(1), math.Inf(-1), 1.23e-308},
421 RptString: []string{"hello", "世界"},
422 RptBytes: [][]byte{
423 []byte("hello"),
424 []byte("\xe4\xb8\x96\xe7\x95\x8c"),
425 },
Herbie Ong800c9902018-12-06 15:28:53 -0800426 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800427 want: `rpt_bool: true
428rpt_bool: false
429rpt_bool: true
430rpt_bool: true
431rpt_int32: 1
432rpt_int32: 6
433rpt_int32: 0
434rpt_int32: 0
435rpt_int64: -64
436rpt_int64: 47
437rpt_uint32: 255
438rpt_uint32: 65535
439rpt_uint64: 3735928559
Herbie Ong84f09602019-01-17 19:31:47 -0800440rpt_float: nan
441rpt_float: inf
442rpt_float: -inf
443rpt_float: 1.034
Herbie Ongcddf8192018-11-28 18:25:20 -0800444rpt_double: nan
445rpt_double: inf
446rpt_double: -inf
447rpt_double: 1.23e-308
448rpt_string: "hello"
449rpt_string: "世界"
450rpt_bytes: "hello"
451rpt_bytes: "世界"
452`,
453 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700454 desc: "repeated contains invalid UTF-8",
455 input: &pb2.Repeats{
456 RptString: []string{"abc\xff"},
457 },
Herbie Ong21a39742019-04-08 17:32:44 -0700458 wantErr: true,
459 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800460 desc: "repeated enums",
Herbie Ong800c9902018-12-06 15:28:53 -0800461 input: &pb2.Enums{
Herbie Ong8170d692019-02-13 14:13:21 -0800462 RptEnum: []pb2.Enum{pb2.Enum_ONE, 2, pb2.Enum_TEN, 42},
Herbie Ongcddf8192018-11-28 18:25:20 -0800463 RptNestedEnum: []pb2.Enums_NestedEnum{2, 47, 10},
Herbie Ong800c9902018-12-06 15:28:53 -0800464 },
Herbie Ong8170d692019-02-13 14:13:21 -0800465 want: `rpt_enum: ONE
466rpt_enum: TWO
467rpt_enum: TEN
Herbie Ongcddf8192018-11-28 18:25:20 -0800468rpt_enum: 42
Herbie Ongcddf8192018-11-28 18:25:20 -0800469rpt_nested_enum: DOS
470rpt_nested_enum: 47
471rpt_nested_enum: DIEZ
472`,
473 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800474 desc: "repeated messages set to empty",
Herbie Ong800c9902018-12-06 15:28:53 -0800475 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800476 RptNested: []*pb2.Nested{},
477 Rptgroup: []*pb2.Nests_RptGroup{},
Herbie Ong800c9902018-12-06 15:28:53 -0800478 },
479 want: "\n",
Herbie Ongcddf8192018-11-28 18:25:20 -0800480 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800481 desc: "repeated messages",
Herbie Ong800c9902018-12-06 15:28:53 -0800482 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800483 RptNested: []*pb2.Nested{
484 {
Damien Neila8a2cea2019-07-10 16:17:16 -0700485 OptString: proto.String("repeat nested one"),
Herbie Ongcddf8192018-11-28 18:25:20 -0800486 },
487 {
Damien Neila8a2cea2019-07-10 16:17:16 -0700488 OptString: proto.String("repeat nested two"),
Herbie Ongcddf8192018-11-28 18:25:20 -0800489 OptNested: &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -0700490 OptString: proto.String("inside repeat nested two"),
Herbie Ongcddf8192018-11-28 18:25:20 -0800491 },
492 },
493 {},
494 },
Herbie Ong800c9902018-12-06 15:28:53 -0800495 },
496 want: `rpt_nested: {
Herbie Ongcddf8192018-11-28 18:25:20 -0800497 opt_string: "repeat nested one"
498}
499rpt_nested: {
500 opt_string: "repeat nested two"
501 opt_nested: {
502 opt_string: "inside repeat nested two"
503 }
504}
505rpt_nested: {}
506`,
507 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800508 desc: "repeated messages contains nil value",
Herbie Ongf5db2df2019-02-07 20:17:45 -0800509 input: &pb2.Nests{
510 RptNested: []*pb2.Nested{nil, {}},
511 },
512 want: `rpt_nested: {}
513rpt_nested: {}
514`,
515 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800516 desc: "repeated groups",
Herbie Ong800c9902018-12-06 15:28:53 -0800517 input: &pb2.Nests{
Herbie Ongcddf8192018-11-28 18:25:20 -0800518 Rptgroup: []*pb2.Nests_RptGroup{
519 {
Herbie Ong8170d692019-02-13 14:13:21 -0800520 RptString: []string{"hello", "world"},
Herbie Ongcddf8192018-11-28 18:25:20 -0800521 },
522 {},
Herbie Ong8170d692019-02-13 14:13:21 -0800523 nil,
Herbie Ongcddf8192018-11-28 18:25:20 -0800524 },
Herbie Ong800c9902018-12-06 15:28:53 -0800525 },
Herbie Ongde7313b2019-01-14 19:26:50 -0800526 want: `RptGroup: {
Herbie Ong8170d692019-02-13 14:13:21 -0800527 rpt_string: "hello"
528 rpt_string: "world"
Herbie Ongcddf8192018-11-28 18:25:20 -0800529}
Herbie Ongde7313b2019-01-14 19:26:50 -0800530RptGroup: {}
Herbie Ong8170d692019-02-13 14:13:21 -0800531RptGroup: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800532`,
533 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800534 desc: "map fields not set",
535 input: &pb3.Maps{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800536 want: "\n",
537 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800538 desc: "map fields set to empty",
539 input: &pb3.Maps{
540 Int32ToStr: map[int32]string{},
541 BoolToUint32: map[bool]uint32{},
542 Uint64ToEnum: map[uint64]pb3.Enum{},
543 StrToNested: map[string]*pb3.Nested{},
544 StrToOneofs: map[string]*pb3.Oneofs{},
Herbie Ong800c9902018-12-06 15:28:53 -0800545 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800546 want: "\n",
547 }, {
548 desc: "map fields 1",
Herbie Ong8170d692019-02-13 14:13:21 -0800549 input: &pb3.Maps{
Herbie Ongcddf8192018-11-28 18:25:20 -0800550 Int32ToStr: map[int32]string{
551 -101: "-101",
552 0xff: "0xff",
553 0: "zero",
554 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800555 BoolToUint32: map[bool]uint32{
556 true: 42,
557 false: 101,
558 },
Herbie Ong800c9902018-12-06 15:28:53 -0800559 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800560 want: `int32_to_str: {
561 key: -101
562 value: "-101"
563}
564int32_to_str: {
565 key: 0
566 value: "zero"
567}
568int32_to_str: {
569 key: 255
570 value: "0xff"
571}
Herbie Ongcddf8192018-11-28 18:25:20 -0800572bool_to_uint32: {
573 key: false
574 value: 101
575}
576bool_to_uint32: {
577 key: true
578 value: 42
579}
580`,
581 }, {
582 desc: "map fields 2",
Herbie Ong8170d692019-02-13 14:13:21 -0800583 input: &pb3.Maps{
584 Uint64ToEnum: map[uint64]pb3.Enum{
585 1: pb3.Enum_ONE,
586 2: pb3.Enum_TWO,
587 10: pb3.Enum_TEN,
588 47: 47,
Herbie Ongcddf8192018-11-28 18:25:20 -0800589 },
Herbie Ong800c9902018-12-06 15:28:53 -0800590 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800591 want: `uint64_to_enum: {
592 key: 1
Herbie Ong8170d692019-02-13 14:13:21 -0800593 value: ONE
Herbie Ongcddf8192018-11-28 18:25:20 -0800594}
595uint64_to_enum: {
596 key: 2
Herbie Ong8170d692019-02-13 14:13:21 -0800597 value: TWO
Herbie Ongcddf8192018-11-28 18:25:20 -0800598}
599uint64_to_enum: {
600 key: 10
Herbie Ong8170d692019-02-13 14:13:21 -0800601 value: TEN
602}
603uint64_to_enum: {
604 key: 47
605 value: 47
Herbie Ongcddf8192018-11-28 18:25:20 -0800606}
607`,
608 }, {
609 desc: "map fields 3",
Herbie Ong8170d692019-02-13 14:13:21 -0800610 input: &pb3.Maps{
611 StrToNested: map[string]*pb3.Nested{
612 "nested": &pb3.Nested{
613 SString: "nested in a map",
Herbie Ongcddf8192018-11-28 18:25:20 -0800614 },
615 },
Herbie Ong800c9902018-12-06 15:28:53 -0800616 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800617 want: `str_to_nested: {
Herbie Ong8170d692019-02-13 14:13:21 -0800618 key: "nested"
Herbie Ongcddf8192018-11-28 18:25:20 -0800619 value: {
Herbie Ong8170d692019-02-13 14:13:21 -0800620 s_string: "nested in a map"
Herbie Ongcddf8192018-11-28 18:25:20 -0800621 }
622}
623`,
624 }, {
625 desc: "map fields 4",
Herbie Ong8170d692019-02-13 14:13:21 -0800626 input: &pb3.Maps{
627 StrToOneofs: map[string]*pb3.Oneofs{
628 "string": &pb3.Oneofs{
629 Union: &pb3.Oneofs_OneofString{
630 OneofString: "hello",
Herbie Ongcddf8192018-11-28 18:25:20 -0800631 },
632 },
Herbie Ong8170d692019-02-13 14:13:21 -0800633 "nested": &pb3.Oneofs{
634 Union: &pb3.Oneofs_OneofNested{
635 OneofNested: &pb3.Nested{
636 SString: "nested oneof in map field value",
Herbie Ongcddf8192018-11-28 18:25:20 -0800637 },
638 },
639 },
640 },
Herbie Ong800c9902018-12-06 15:28:53 -0800641 },
Herbie Ongcddf8192018-11-28 18:25:20 -0800642 want: `str_to_oneofs: {
643 key: "nested"
644 value: {
Herbie Ong8170d692019-02-13 14:13:21 -0800645 oneof_nested: {
646 s_string: "nested oneof in map field value"
Herbie Ongcddf8192018-11-28 18:25:20 -0800647 }
648 }
649}
650str_to_oneofs: {
651 key: "string"
652 value: {
Herbie Ong8170d692019-02-13 14:13:21 -0800653 oneof_string: "hello"
Herbie Ongcddf8192018-11-28 18:25:20 -0800654 }
655}
656`,
657 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700658 desc: "map field value contains invalid UTF-8",
659 input: &pb3.Maps{
660 Int32ToStr: map[int32]string{
661 101: "abc\xff",
662 },
663 },
Herbie Ong21a39742019-04-08 17:32:44 -0700664 wantErr: true,
665 }, {
666 desc: "map field key contains invalid UTF-8",
667 input: &pb3.Maps{
668 StrToNested: map[string]*pb3.Nested{
669 "abc\xff": {},
670 },
671 },
Herbie Ong21a39742019-04-08 17:32:44 -0700672 wantErr: true,
673 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800674 desc: "map field contains nil value",
675 input: &pb3.Maps{
676 StrToNested: map[string]*pb3.Nested{
Herbie Ongf5db2df2019-02-07 20:17:45 -0800677 "nil": nil,
678 },
679 },
680 want: `str_to_nested: {
681 key: "nil"
682 value: {}
683}
684`,
685 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700686 desc: "required fields not set",
Herbie Ong800c9902018-12-06 15:28:53 -0800687 input: &pb2.Requireds{},
688 want: "\n",
689 wantErr: true,
Herbie Ongcddf8192018-11-28 18:25:20 -0800690 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700691 desc: "required fields partially set",
Herbie Ong800c9902018-12-06 15:28:53 -0800692 input: &pb2.Requireds{
Damien Neila8a2cea2019-07-10 16:17:16 -0700693 ReqBool: proto.Bool(false),
694 ReqSfixed64: proto.Int64(0xbeefcafe),
695 ReqDouble: proto.Float64(math.NaN()),
696 ReqString: proto.String("hello"),
Herbie Ong8170d692019-02-13 14:13:21 -0800697 ReqEnum: pb2.Enum_ONE.Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800698 },
699 want: `req_bool: false
Herbie Ong800c9902018-12-06 15:28:53 -0800700req_sfixed64: 3203386110
701req_double: nan
702req_string: "hello"
Herbie Ong8170d692019-02-13 14:13:21 -0800703req_enum: ONE
Herbie Ong800c9902018-12-06 15:28:53 -0800704`,
705 wantErr: true,
706 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700707 desc: "required fields not set with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700708 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong42577ea2019-03-26 16:26:22 -0700709 input: &pb2.Requireds{
Damien Neila8a2cea2019-07-10 16:17:16 -0700710 ReqBool: proto.Bool(false),
711 ReqSfixed64: proto.Int64(0xbeefcafe),
712 ReqDouble: proto.Float64(math.NaN()),
713 ReqString: proto.String("hello"),
Herbie Ong42577ea2019-03-26 16:26:22 -0700714 ReqEnum: pb2.Enum_ONE.Enum(),
715 },
716 want: `req_bool: false
717req_sfixed64: 3203386110
718req_double: nan
719req_string: "hello"
720req_enum: ONE
721`,
722 }, {
723 desc: "required fields all set",
Herbie Ong800c9902018-12-06 15:28:53 -0800724 input: &pb2.Requireds{
Damien Neila8a2cea2019-07-10 16:17:16 -0700725 ReqBool: proto.Bool(false),
726 ReqSfixed64: proto.Int64(0),
727 ReqDouble: proto.Float64(1.23),
728 ReqString: proto.String(""),
Herbie Ong8170d692019-02-13 14:13:21 -0800729 ReqEnum: pb2.Enum_ONE.Enum(),
Herbie Ong800c9902018-12-06 15:28:53 -0800730 ReqNested: &pb2.Nested{},
731 },
732 want: `req_bool: false
Herbie Ong800c9902018-12-06 15:28:53 -0800733req_sfixed64: 0
Herbie Ong8170d692019-02-13 14:13:21 -0800734req_double: 1.23
Herbie Ong800c9902018-12-06 15:28:53 -0800735req_string: ""
Herbie Ong8170d692019-02-13 14:13:21 -0800736req_enum: ONE
Herbie Ong800c9902018-12-06 15:28:53 -0800737req_nested: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800738`,
739 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800740 desc: "indirect required field",
741 input: &pb2.IndirectRequired{
742 OptNested: &pb2.NestedWithRequired{},
743 },
744 want: "opt_nested: {}\n",
745 wantErr: true,
Herbie Ongcddf8192018-11-28 18:25:20 -0800746 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700747 desc: "indirect required field with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700748 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong42577ea2019-03-26 16:26:22 -0700749 input: &pb2.IndirectRequired{
750 OptNested: &pb2.NestedWithRequired{},
751 },
752 want: "opt_nested: {}\n",
753 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800754 desc: "indirect required field in empty repeated",
755 input: &pb2.IndirectRequired{
756 RptNested: []*pb2.NestedWithRequired{},
757 },
758 want: "\n",
Herbie Ongcddf8192018-11-28 18:25:20 -0800759 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800760 desc: "indirect required field in repeated",
761 input: &pb2.IndirectRequired{
762 RptNested: []*pb2.NestedWithRequired{
763 &pb2.NestedWithRequired{},
Herbie Ongcddf8192018-11-28 18:25:20 -0800764 },
Herbie Ong800c9902018-12-06 15:28:53 -0800765 },
766 want: "rpt_nested: {}\n",
767 wantErr: true,
768 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700769 desc: "indirect required field in repeated with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700770 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong42577ea2019-03-26 16:26:22 -0700771 input: &pb2.IndirectRequired{
772 RptNested: []*pb2.NestedWithRequired{
773 &pb2.NestedWithRequired{},
774 },
775 },
776 want: "rpt_nested: {}\n",
777 }, {
Herbie Ong800c9902018-12-06 15:28:53 -0800778 desc: "indirect required field in empty map",
779 input: &pb2.IndirectRequired{
780 StrToNested: map[string]*pb2.NestedWithRequired{},
781 },
782 want: "\n",
783 }, {
784 desc: "indirect required field in map",
785 input: &pb2.IndirectRequired{
786 StrToNested: map[string]*pb2.NestedWithRequired{
787 "fail": &pb2.NestedWithRequired{},
788 },
789 },
790 want: `str_to_nested: {
791 key: "fail"
792 value: {}
Herbie Ongcddf8192018-11-28 18:25:20 -0800793}
794`,
Herbie Ong800c9902018-12-06 15:28:53 -0800795 wantErr: true,
Herbie Ong20a1d312018-12-11 21:08:58 -0800796 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700797 desc: "indirect required field in map with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700798 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong42577ea2019-03-26 16:26:22 -0700799 input: &pb2.IndirectRequired{
800 StrToNested: map[string]*pb2.NestedWithRequired{
801 "fail": &pb2.NestedWithRequired{},
802 },
803 },
804 want: `str_to_nested: {
805 key: "fail"
806 value: {}
807}
808`,
809 }, {
Herbie Ong8170d692019-02-13 14:13:21 -0800810 desc: "indirect required field in oneof",
811 input: &pb2.IndirectRequired{
812 Union: &pb2.IndirectRequired_OneofNested{
813 OneofNested: &pb2.NestedWithRequired{},
814 },
815 },
816 want: "oneof_nested: {}\n",
817 wantErr: true,
818 }, {
Herbie Ong42577ea2019-03-26 16:26:22 -0700819 desc: "indirect required field in oneof with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700820 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong42577ea2019-03-26 16:26:22 -0700821 input: &pb2.IndirectRequired{
822 Union: &pb2.IndirectRequired_OneofNested{
823 OneofNested: &pb2.NestedWithRequired{},
824 },
825 },
826 want: "oneof_nested: {}\n",
827 }, {
Herbie Ong20a1d312018-12-11 21:08:58 -0800828 desc: "unknown varint and fixed types",
Joe Tsai28216c72019-06-22 13:20:09 -0700829 input: func() proto.Message {
830 m := &pb2.Scalars{
Damien Neila8a2cea2019-07-10 16:17:16 -0700831 OptString: proto.String("this message contains unknown fields"),
Joe Tsai28216c72019-06-22 13:20:09 -0700832 }
833 m.ProtoReflect().SetUnknown(pack.Message{
Herbie Ong20a1d312018-12-11 21:08:58 -0800834 pack.Tag{101, pack.VarintType}, pack.Bool(true),
835 pack.Tag{102, pack.VarintType}, pack.Varint(0xff),
836 pack.Tag{103, pack.Fixed32Type}, pack.Uint32(47),
837 pack.Tag{104, pack.Fixed64Type}, pack.Int64(0xdeadbeef),
Joe Tsai28216c72019-06-22 13:20:09 -0700838 }.Marshal())
839 return m
840 }(),
Herbie Ong20a1d312018-12-11 21:08:58 -0800841 want: `opt_string: "this message contains unknown fields"
842101: 1
843102: 255
844103: 47
845104: 3735928559
846`,
847 }, {
848 desc: "unknown length-delimited",
Joe Tsai28216c72019-06-22 13:20:09 -0700849 input: func() proto.Message {
850 m := new(pb2.Scalars)
851 m.ProtoReflect().SetUnknown(pack.Message{
Herbie Ong20a1d312018-12-11 21:08:58 -0800852 pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false)},
853 pack.Tag{102, pack.BytesType}, pack.String("hello world"),
854 pack.Tag{103, pack.BytesType}, pack.Bytes("\xe4\xb8\x96\xe7\x95\x8c"),
Joe Tsai28216c72019-06-22 13:20:09 -0700855 }.Marshal())
856 return m
857 }(),
Herbie Ong20a1d312018-12-11 21:08:58 -0800858 want: `101: "\x01\x00"
859102: "hello world"
860103: "世界"
861`,
862 }, {
863 desc: "unknown group type",
Joe Tsai28216c72019-06-22 13:20:09 -0700864 input: func() proto.Message {
865 m := new(pb2.Scalars)
866 m.ProtoReflect().SetUnknown(pack.Message{
Herbie Ong20a1d312018-12-11 21:08:58 -0800867 pack.Tag{101, pack.StartGroupType}, pack.Tag{101, pack.EndGroupType},
868 pack.Tag{102, pack.StartGroupType},
869 pack.Tag{101, pack.VarintType}, pack.Bool(false),
870 pack.Tag{102, pack.BytesType}, pack.String("inside a group"),
871 pack.Tag{102, pack.EndGroupType},
Joe Tsai28216c72019-06-22 13:20:09 -0700872 }.Marshal())
873 return m
874 }(),
Herbie Ong20a1d312018-12-11 21:08:58 -0800875 want: `101: {}
876102: {
877 101: 0
878 102: "inside a group"
879}
880`,
881 }, {
882 desc: "unknown unpack repeated field",
Joe Tsai28216c72019-06-22 13:20:09 -0700883 input: func() proto.Message {
884 m := new(pb2.Scalars)
885 m.ProtoReflect().SetUnknown(pack.Message{
Herbie Ong20a1d312018-12-11 21:08:58 -0800886 pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false), pack.Bool(true)},
887 pack.Tag{102, pack.BytesType}, pack.String("hello"),
888 pack.Tag{101, pack.VarintType}, pack.Bool(true),
889 pack.Tag{102, pack.BytesType}, pack.String("世界"),
Joe Tsai28216c72019-06-22 13:20:09 -0700890 }.Marshal())
891 return m
892 }(),
Herbie Ong20a1d312018-12-11 21:08:58 -0800893 want: `101: "\x01\x00\x01"
Herbie Ong20a1d312018-12-11 21:08:58 -0800894102: "hello"
Joe Tsai378c1322019-04-25 23:48:08 -0700895101: 1
Herbie Ong20a1d312018-12-11 21:08:58 -0800896102: "世界"
897`,
Herbie Ongcf253082018-12-17 17:13:07 -0800898 }, {
899 desc: "extensions of non-repeated fields",
900 input: func() proto.Message {
901 m := &pb2.Extensions{
Damien Neila8a2cea2019-07-10 16:17:16 -0700902 OptString: proto.String("non-extension field"),
903 OptBool: proto.Bool(true),
904 OptInt32: proto.Int32(42),
Herbie Ongcf253082018-12-17 17:13:07 -0800905 }
906 setExtension(m, pb2.E_OptExtBool, true)
907 setExtension(m, pb2.E_OptExtString, "extension field")
Herbie Ong8170d692019-02-13 14:13:21 -0800908 setExtension(m, pb2.E_OptExtEnum, pb2.Enum_TEN)
Herbie Ongcf253082018-12-17 17:13:07 -0800909 setExtension(m, pb2.E_OptExtNested, &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -0700910 OptString: proto.String("nested in an extension"),
Herbie Ongcf253082018-12-17 17:13:07 -0800911 OptNested: &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -0700912 OptString: proto.String("another nested in an extension"),
Herbie Ongcf253082018-12-17 17:13:07 -0800913 },
914 })
915 return m
916 }(),
917 want: `opt_string: "non-extension field"
918opt_bool: true
919opt_int32: 42
920[pb2.opt_ext_bool]: true
Herbie Ong8170d692019-02-13 14:13:21 -0800921[pb2.opt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -0800922[pb2.opt_ext_nested]: {
923 opt_string: "nested in an extension"
924 opt_nested: {
925 opt_string: "another nested in an extension"
926 }
927}
928[pb2.opt_ext_string]: "extension field"
929`,
930 }, {
Herbie Ong21a39742019-04-08 17:32:44 -0700931 desc: "extension field contains invalid UTF-8",
932 input: func() proto.Message {
933 m := &pb2.Extensions{}
934 setExtension(m, pb2.E_OptExtString, "abc\xff")
935 return m
936 }(),
Herbie Ong21a39742019-04-08 17:32:44 -0700937 wantErr: true,
938 }, {
Herbie Ong09b28a92019-04-03 15:42:41 -0700939 desc: "extension partial returns error",
940 input: func() proto.Message {
941 m := &pb2.Extensions{}
942 setExtension(m, pb2.E_OptExtPartial, &pb2.PartialRequired{
Damien Neila8a2cea2019-07-10 16:17:16 -0700943 OptString: proto.String("partial1"),
Herbie Ong09b28a92019-04-03 15:42:41 -0700944 })
945 setExtension(m, pb2.E_ExtensionsContainer_OptExtPartial, &pb2.PartialRequired{
Damien Neila8a2cea2019-07-10 16:17:16 -0700946 OptString: proto.String("partial2"),
Herbie Ong09b28a92019-04-03 15:42:41 -0700947 })
948 return m
949 }(),
950 want: `[pb2.ExtensionsContainer.opt_ext_partial]: {
951 opt_string: "partial2"
952}
953[pb2.opt_ext_partial]: {
954 opt_string: "partial1"
955}
956`,
957 wantErr: true,
958 }, {
959 desc: "extension partial with AllowPartial",
Damien Neil5c5b5312019-05-14 12:44:37 -0700960 mo: prototext.MarshalOptions{AllowPartial: true},
Herbie Ong09b28a92019-04-03 15:42:41 -0700961 input: func() proto.Message {
962 m := &pb2.Extensions{}
963 setExtension(m, pb2.E_OptExtPartial, &pb2.PartialRequired{
Damien Neila8a2cea2019-07-10 16:17:16 -0700964 OptString: proto.String("partial1"),
Herbie Ong09b28a92019-04-03 15:42:41 -0700965 })
966 return m
967 }(),
968 want: `[pb2.opt_ext_partial]: {
969 opt_string: "partial1"
970}
971`,
972 }, {
Herbie Ongcf253082018-12-17 17:13:07 -0800973 desc: "extensions of repeated fields",
974 input: func() proto.Message {
975 m := &pb2.Extensions{}
Herbie Ong8170d692019-02-13 14:13:21 -0800976 setExtension(m, pb2.E_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
Herbie Ongcf253082018-12-17 17:13:07 -0800977 setExtension(m, pb2.E_RptExtFixed32, &[]uint32{42, 47})
978 setExtension(m, pb2.E_RptExtNested, &[]*pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -0700979 &pb2.Nested{OptString: proto.String("one")},
980 &pb2.Nested{OptString: proto.String("two")},
981 &pb2.Nested{OptString: proto.String("three")},
Herbie Ongcf253082018-12-17 17:13:07 -0800982 })
983 return m
984 }(),
Herbie Ong8170d692019-02-13 14:13:21 -0800985 want: `[pb2.rpt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -0800986[pb2.rpt_ext_enum]: 101
Herbie Ong8170d692019-02-13 14:13:21 -0800987[pb2.rpt_ext_enum]: ONE
Herbie Ongcf253082018-12-17 17:13:07 -0800988[pb2.rpt_ext_fixed32]: 42
989[pb2.rpt_ext_fixed32]: 47
990[pb2.rpt_ext_nested]: {
991 opt_string: "one"
992}
993[pb2.rpt_ext_nested]: {
994 opt_string: "two"
995}
996[pb2.rpt_ext_nested]: {
997 opt_string: "three"
998}
999`,
1000 }, {
1001 desc: "extensions of non-repeated fields in another message",
1002 input: func() proto.Message {
1003 m := &pb2.Extensions{}
1004 setExtension(m, pb2.E_ExtensionsContainer_OptExtBool, true)
1005 setExtension(m, pb2.E_ExtensionsContainer_OptExtString, "extension field")
Herbie Ong8170d692019-02-13 14:13:21 -08001006 setExtension(m, pb2.E_ExtensionsContainer_OptExtEnum, pb2.Enum_TEN)
Herbie Ongcf253082018-12-17 17:13:07 -08001007 setExtension(m, pb2.E_ExtensionsContainer_OptExtNested, &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -07001008 OptString: proto.String("nested in an extension"),
Herbie Ongcf253082018-12-17 17:13:07 -08001009 OptNested: &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -07001010 OptString: proto.String("another nested in an extension"),
Herbie Ongcf253082018-12-17 17:13:07 -08001011 },
1012 })
1013 return m
1014 }(),
1015 want: `[pb2.ExtensionsContainer.opt_ext_bool]: true
Herbie Ong8170d692019-02-13 14:13:21 -08001016[pb2.ExtensionsContainer.opt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -08001017[pb2.ExtensionsContainer.opt_ext_nested]: {
1018 opt_string: "nested in an extension"
1019 opt_nested: {
1020 opt_string: "another nested in an extension"
1021 }
1022}
1023[pb2.ExtensionsContainer.opt_ext_string]: "extension field"
1024`,
1025 }, {
1026 desc: "extensions of repeated fields in another message",
1027 input: func() proto.Message {
1028 m := &pb2.Extensions{
Damien Neila8a2cea2019-07-10 16:17:16 -07001029 OptString: proto.String("non-extension field"),
1030 OptBool: proto.Bool(true),
1031 OptInt32: proto.Int32(42),
Herbie Ongcf253082018-12-17 17:13:07 -08001032 }
Herbie Ong8170d692019-02-13 14:13:21 -08001033 setExtension(m, pb2.E_ExtensionsContainer_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
Herbie Ongcf253082018-12-17 17:13:07 -08001034 setExtension(m, pb2.E_ExtensionsContainer_RptExtString, &[]string{"hello", "world"})
1035 setExtension(m, pb2.E_ExtensionsContainer_RptExtNested, &[]*pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -07001036 &pb2.Nested{OptString: proto.String("one")},
1037 &pb2.Nested{OptString: proto.String("two")},
1038 &pb2.Nested{OptString: proto.String("three")},
Herbie Ongcf253082018-12-17 17:13:07 -08001039 })
1040 return m
1041 }(),
1042 want: `opt_string: "non-extension field"
1043opt_bool: true
1044opt_int32: 42
Herbie Ong8170d692019-02-13 14:13:21 -08001045[pb2.ExtensionsContainer.rpt_ext_enum]: TEN
Herbie Ongcf253082018-12-17 17:13:07 -08001046[pb2.ExtensionsContainer.rpt_ext_enum]: 101
Herbie Ong8170d692019-02-13 14:13:21 -08001047[pb2.ExtensionsContainer.rpt_ext_enum]: ONE
Herbie Ongcf253082018-12-17 17:13:07 -08001048[pb2.ExtensionsContainer.rpt_ext_nested]: {
1049 opt_string: "one"
1050}
1051[pb2.ExtensionsContainer.rpt_ext_nested]: {
1052 opt_string: "two"
1053}
1054[pb2.ExtensionsContainer.rpt_ext_nested]: {
1055 opt_string: "three"
1056}
1057[pb2.ExtensionsContainer.rpt_ext_string]: "hello"
1058[pb2.ExtensionsContainer.rpt_ext_string]: "world"
1059`,
Herbie Ong6470ea62019-01-07 18:56:57 -08001060 }, {
1061 desc: "MessageSet",
1062 input: func() proto.Message {
1063 m := &pb2.MessageSet{}
1064 setExtension(m, pb2.E_MessageSetExtension_MessageSetExtension, &pb2.MessageSetExtension{
Damien Neila8a2cea2019-07-10 16:17:16 -07001065 OptString: proto.String("a messageset extension"),
Herbie Ong6470ea62019-01-07 18:56:57 -08001066 })
1067 setExtension(m, pb2.E_MessageSetExtension_NotMessageSetExtension, &pb2.MessageSetExtension{
Damien Neila8a2cea2019-07-10 16:17:16 -07001068 OptString: proto.String("not a messageset extension"),
Herbie Ong6470ea62019-01-07 18:56:57 -08001069 })
1070 setExtension(m, pb2.E_MessageSetExtension_ExtNested, &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -07001071 OptString: proto.String("just a regular extension"),
Herbie Ong6470ea62019-01-07 18:56:57 -08001072 })
1073 return m
1074 }(),
1075 want: `[pb2.MessageSetExtension]: {
1076 opt_string: "a messageset extension"
1077}
1078[pb2.MessageSetExtension.ext_nested]: {
1079 opt_string: "just a regular extension"
1080}
1081[pb2.MessageSetExtension.not_message_set_extension]: {
1082 opt_string: "not a messageset extension"
1083}
1084`,
1085 }, {
1086 desc: "not real MessageSet 1",
1087 input: func() proto.Message {
1088 m := &pb2.FakeMessageSet{}
1089 setExtension(m, pb2.E_FakeMessageSetExtension_MessageSetExtension, &pb2.FakeMessageSetExtension{
Damien Neila8a2cea2019-07-10 16:17:16 -07001090 OptString: proto.String("not a messageset extension"),
Herbie Ong6470ea62019-01-07 18:56:57 -08001091 })
1092 return m
1093 }(),
1094 want: `[pb2.FakeMessageSetExtension.message_set_extension]: {
1095 opt_string: "not a messageset extension"
1096}
1097`,
1098 }, {
1099 desc: "not real MessageSet 2",
1100 input: func() proto.Message {
1101 m := &pb2.MessageSet{}
1102 setExtension(m, pb2.E_MessageSetExtension, &pb2.FakeMessageSetExtension{
Damien Neila8a2cea2019-07-10 16:17:16 -07001103 OptString: proto.String("another not a messageset extension"),
Herbie Ong6470ea62019-01-07 18:56:57 -08001104 })
1105 return m
1106 }(),
1107 want: `[pb2.message_set_extension]: {
1108 opt_string: "another not a messageset extension"
1109}
1110`,
Herbie Ongf42b55f2019-01-02 15:46:07 -08001111 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001112 desc: "Any not expanded",
Damien Neil5c5b5312019-05-14 12:44:37 -07001113 mo: prototext.MarshalOptions{
Herbie Ong66c365c2019-01-04 14:08:41 -08001114 Resolver: preg.NewTypes(),
1115 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001116 input: func() proto.Message {
1117 m := &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -07001118 OptString: proto.String("embedded inside Any"),
Herbie Ongf42b55f2019-01-02 15:46:07 -08001119 OptNested: &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -07001120 OptString: proto.String("inception"),
Herbie Ongf42b55f2019-01-02 15:46:07 -08001121 },
1122 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -07001123 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ongf42b55f2019-01-02 15:46:07 -08001124 if err != nil {
1125 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1126 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07001127 return &anypb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001128 TypeUrl: "pb2.Nested",
Herbie Ongf42b55f2019-01-02 15:46:07 -08001129 Value: b,
Herbie Ong300cff02019-03-20 18:05:16 -07001130 }
Herbie Ongf42b55f2019-01-02 15:46:07 -08001131 }(),
1132 want: `type_url: "pb2.Nested"
1133value: "\n\x13embedded inside Any\x12\x0b\n\tinception"
1134`,
1135 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001136 desc: "Any expanded",
Damien Neil5c5b5312019-05-14 12:44:37 -07001137 mo: prototext.MarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001138 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
Herbie Ong66c365c2019-01-04 14:08:41 -08001139 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001140 input: func() proto.Message {
1141 m := &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -07001142 OptString: proto.String("embedded inside Any"),
Herbie Ongf42b55f2019-01-02 15:46:07 -08001143 OptNested: &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -07001144 OptString: proto.String("inception"),
Herbie Ongf42b55f2019-01-02 15:46:07 -08001145 },
1146 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -07001147 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ongf42b55f2019-01-02 15:46:07 -08001148 if err != nil {
1149 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1150 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07001151 return &anypb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001152 TypeUrl: "foo/pb2.Nested",
Herbie Ongf42b55f2019-01-02 15:46:07 -08001153 Value: b,
Herbie Ong300cff02019-03-20 18:05:16 -07001154 }
Herbie Ongf42b55f2019-01-02 15:46:07 -08001155 }(),
Herbie Ong66c365c2019-01-04 14:08:41 -08001156 want: `[foo/pb2.Nested]: {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001157 opt_string: "embedded inside Any"
1158 opt_nested: {
1159 opt_string: "inception"
1160 }
1161}
1162`,
1163 }, {
Damien Neil0c9f0a92019-06-19 10:41:09 -07001164 desc: "Any expanded with missing required",
Damien Neil5c5b5312019-05-14 12:44:37 -07001165 mo: prototext.MarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001166 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.PartialRequired{})),
Herbie Ong66c365c2019-01-04 14:08:41 -08001167 },
Herbie Ongf42b55f2019-01-02 15:46:07 -08001168 input: func() proto.Message {
1169 m := &pb2.PartialRequired{
Damien Neila8a2cea2019-07-10 16:17:16 -07001170 OptString: proto.String("embedded inside Any"),
Herbie Ongf42b55f2019-01-02 15:46:07 -08001171 }
Damien Neil96c229a2019-04-03 12:17:24 -07001172 b, err := proto.MarshalOptions{
1173 AllowPartial: true,
1174 Deterministic: true,
1175 }.Marshal(m)
Herbie Ong300cff02019-03-20 18:05:16 -07001176 if err != nil {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001177 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1178 }
Joe Tsaia95b29f2019-05-16 12:47:20 -07001179 return &anypb.Any{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001180 TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
Herbie Ongf42b55f2019-01-02 15:46:07 -08001181 Value: b,
Herbie Ong300cff02019-03-20 18:05:16 -07001182 }
Herbie Ongf42b55f2019-01-02 15:46:07 -08001183 }(),
1184 want: `[pb2.PartialRequired]: {
1185 opt_string: "embedded inside Any"
1186}
1187`,
Herbie Ongf42b55f2019-01-02 15:46:07 -08001188 }, {
Herbie Ong8170d692019-02-13 14:13:21 -08001189 desc: "Any with invalid value",
Damien Neil5c5b5312019-05-14 12:44:37 -07001190 mo: prototext.MarshalOptions{
Joe Tsai0fc49f82019-05-01 12:29:25 -07001191 Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
Herbie Ong66c365c2019-01-04 14:08:41 -08001192 },
Joe Tsaia95b29f2019-05-16 12:47:20 -07001193 input: &anypb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -08001194 TypeUrl: "foo/pb2.Nested",
Joe Tsai6dc168e2019-07-09 23:11:13 -07001195 Value: []byte("\x80"),
Herbie Ong300cff02019-03-20 18:05:16 -07001196 },
Herbie Ong66c365c2019-01-04 14:08:41 -08001197 want: `type_url: "foo/pb2.Nested"
Herbie Onga94f78c2019-01-03 15:39:58 -08001198value: "\x80"
1199`,
Herbie Ongcddf8192018-11-28 18:25:20 -08001200 }}
1201
1202 for _, tt := range tests {
1203 tt := tt
1204 t.Run(tt.desc, func(t *testing.T) {
Herbie Ong3a385912019-03-20 14:04:24 -07001205 // Use 2-space indentation on all MarshalOptions.
1206 tt.mo.Indent = " "
Herbie Ongf42b55f2019-01-02 15:46:07 -08001207 b, err := tt.mo.Marshal(tt.input)
Herbie Ongcddf8192018-11-28 18:25:20 -08001208 if err != nil && !tt.wantErr {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001209 t.Errorf("Marshal() returned error: %v\n", err)
Herbie Ongcddf8192018-11-28 18:25:20 -08001210 }
Herbie Ong800c9902018-12-06 15:28:53 -08001211 if err == nil && tt.wantErr {
Herbie Ongf42b55f2019-01-02 15:46:07 -08001212 t.Error("Marshal() got nil error, want error\n")
Herbie Ongcddf8192018-11-28 18:25:20 -08001213 }
Herbie Ong800c9902018-12-06 15:28:53 -08001214 got := string(b)
1215 if tt.want != "" && got != tt.want {
1216 t.Errorf("Marshal()\n<got>\n%v\n<want>\n%v\n", got, tt.want)
Joe Tsai378c1322019-04-25 23:48:08 -07001217 if diff := cmp.Diff(tt.want, got); diff != "" {
Herbie Ongcddf8192018-11-28 18:25:20 -08001218 t.Errorf("Marshal() diff -want +got\n%v\n", diff)
1219 }
1220 }
1221 })
1222 }
1223}