xref: /aosp_15_r20/external/golang-protobuf/encoding/protojson/encode_test.go (revision 1c12ee1efe575feb122dbf939ff15148a3b3e8f2)
1*1c12ee1eSDan Willemsen// Copyright 2019 The Go Authors. All rights reserved.
2*1c12ee1eSDan Willemsen// Use of this source code is governed by a BSD-style
3*1c12ee1eSDan Willemsen// license that can be found in the LICENSE file.
4*1c12ee1eSDan Willemsen
5*1c12ee1eSDan Willemsenpackage protojson_test
6*1c12ee1eSDan Willemsen
7*1c12ee1eSDan Willemsenimport (
8*1c12ee1eSDan Willemsen	"bytes"
9*1c12ee1eSDan Willemsen	"math"
10*1c12ee1eSDan Willemsen	"testing"
11*1c12ee1eSDan Willemsen
12*1c12ee1eSDan Willemsen	"github.com/google/go-cmp/cmp"
13*1c12ee1eSDan Willemsen
14*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/encoding/protojson"
15*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/detrand"
16*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/flags"
17*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/proto"
18*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/reflect/protoregistry"
19*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/testing/protopack"
20*1c12ee1eSDan Willemsen
21*1c12ee1eSDan Willemsen	pb2 "google.golang.org/protobuf/internal/testprotos/textpb2"
22*1c12ee1eSDan Willemsen	pb3 "google.golang.org/protobuf/internal/testprotos/textpb3"
23*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/types/known/anypb"
24*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/types/known/durationpb"
25*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/types/known/emptypb"
26*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/types/known/fieldmaskpb"
27*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/types/known/structpb"
28*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/types/known/timestamppb"
29*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/types/known/wrapperspb"
30*1c12ee1eSDan Willemsen)
31*1c12ee1eSDan Willemsen
32*1c12ee1eSDan Willemsen// Disable detrand to enable direct comparisons on outputs.
33*1c12ee1eSDan Willemsenfunc init() { detrand.Disable() }
34*1c12ee1eSDan Willemsen
35*1c12ee1eSDan Willemsenfunc TestMarshal(t *testing.T) {
36*1c12ee1eSDan Willemsen	tests := []struct {
37*1c12ee1eSDan Willemsen		desc    string
38*1c12ee1eSDan Willemsen		mo      protojson.MarshalOptions
39*1c12ee1eSDan Willemsen		input   proto.Message
40*1c12ee1eSDan Willemsen		want    string
41*1c12ee1eSDan Willemsen		wantErr bool // TODO: Verify error message substring.
42*1c12ee1eSDan Willemsen		skip    bool
43*1c12ee1eSDan Willemsen	}{{
44*1c12ee1eSDan Willemsen		desc:  "proto2 optional scalars not set",
45*1c12ee1eSDan Willemsen		input: &pb2.Scalars{},
46*1c12ee1eSDan Willemsen		want:  "{}",
47*1c12ee1eSDan Willemsen	}, {
48*1c12ee1eSDan Willemsen		desc:  "proto3 scalars not set",
49*1c12ee1eSDan Willemsen		input: &pb3.Scalars{},
50*1c12ee1eSDan Willemsen		want:  "{}",
51*1c12ee1eSDan Willemsen	}, {
52*1c12ee1eSDan Willemsen		desc:  "proto3 optional not set",
53*1c12ee1eSDan Willemsen		input: &pb3.Proto3Optional{},
54*1c12ee1eSDan Willemsen		want:  "{}",
55*1c12ee1eSDan Willemsen	}, {
56*1c12ee1eSDan Willemsen		desc: "proto2 optional scalars set to zero values",
57*1c12ee1eSDan Willemsen		input: &pb2.Scalars{
58*1c12ee1eSDan Willemsen			OptBool:     proto.Bool(false),
59*1c12ee1eSDan Willemsen			OptInt32:    proto.Int32(0),
60*1c12ee1eSDan Willemsen			OptInt64:    proto.Int64(0),
61*1c12ee1eSDan Willemsen			OptUint32:   proto.Uint32(0),
62*1c12ee1eSDan Willemsen			OptUint64:   proto.Uint64(0),
63*1c12ee1eSDan Willemsen			OptSint32:   proto.Int32(0),
64*1c12ee1eSDan Willemsen			OptSint64:   proto.Int64(0),
65*1c12ee1eSDan Willemsen			OptFixed32:  proto.Uint32(0),
66*1c12ee1eSDan Willemsen			OptFixed64:  proto.Uint64(0),
67*1c12ee1eSDan Willemsen			OptSfixed32: proto.Int32(0),
68*1c12ee1eSDan Willemsen			OptSfixed64: proto.Int64(0),
69*1c12ee1eSDan Willemsen			OptFloat:    proto.Float32(0),
70*1c12ee1eSDan Willemsen			OptDouble:   proto.Float64(0),
71*1c12ee1eSDan Willemsen			OptBytes:    []byte{},
72*1c12ee1eSDan Willemsen			OptString:   proto.String(""),
73*1c12ee1eSDan Willemsen		},
74*1c12ee1eSDan Willemsen		want: `{
75*1c12ee1eSDan Willemsen  "optBool": false,
76*1c12ee1eSDan Willemsen  "optInt32": 0,
77*1c12ee1eSDan Willemsen  "optInt64": "0",
78*1c12ee1eSDan Willemsen  "optUint32": 0,
79*1c12ee1eSDan Willemsen  "optUint64": "0",
80*1c12ee1eSDan Willemsen  "optSint32": 0,
81*1c12ee1eSDan Willemsen  "optSint64": "0",
82*1c12ee1eSDan Willemsen  "optFixed32": 0,
83*1c12ee1eSDan Willemsen  "optFixed64": "0",
84*1c12ee1eSDan Willemsen  "optSfixed32": 0,
85*1c12ee1eSDan Willemsen  "optSfixed64": "0",
86*1c12ee1eSDan Willemsen  "optFloat": 0,
87*1c12ee1eSDan Willemsen  "optDouble": 0,
88*1c12ee1eSDan Willemsen  "optBytes": "",
89*1c12ee1eSDan Willemsen  "optString": ""
90*1c12ee1eSDan Willemsen}`,
91*1c12ee1eSDan Willemsen	}, {
92*1c12ee1eSDan Willemsen		desc: "proto3 optional set to zero values",
93*1c12ee1eSDan Willemsen		input: &pb3.Proto3Optional{
94*1c12ee1eSDan Willemsen			OptBool:    proto.Bool(false),
95*1c12ee1eSDan Willemsen			OptInt32:   proto.Int32(0),
96*1c12ee1eSDan Willemsen			OptInt64:   proto.Int64(0),
97*1c12ee1eSDan Willemsen			OptUint32:  proto.Uint32(0),
98*1c12ee1eSDan Willemsen			OptUint64:  proto.Uint64(0),
99*1c12ee1eSDan Willemsen			OptFloat:   proto.Float32(0),
100*1c12ee1eSDan Willemsen			OptDouble:  proto.Float64(0),
101*1c12ee1eSDan Willemsen			OptString:  proto.String(""),
102*1c12ee1eSDan Willemsen			OptBytes:   []byte{},
103*1c12ee1eSDan Willemsen			OptEnum:    pb3.Enum_ZERO.Enum(),
104*1c12ee1eSDan Willemsen			OptMessage: &pb3.Nested{},
105*1c12ee1eSDan Willemsen		},
106*1c12ee1eSDan Willemsen		want: `{
107*1c12ee1eSDan Willemsen  "optBool": false,
108*1c12ee1eSDan Willemsen  "optInt32": 0,
109*1c12ee1eSDan Willemsen  "optInt64": "0",
110*1c12ee1eSDan Willemsen  "optUint32": 0,
111*1c12ee1eSDan Willemsen  "optUint64": "0",
112*1c12ee1eSDan Willemsen  "optFloat": 0,
113*1c12ee1eSDan Willemsen  "optDouble": 0,
114*1c12ee1eSDan Willemsen  "optString": "",
115*1c12ee1eSDan Willemsen  "optBytes": "",
116*1c12ee1eSDan Willemsen  "optEnum": "ZERO",
117*1c12ee1eSDan Willemsen  "optMessage": {}
118*1c12ee1eSDan Willemsen}`,
119*1c12ee1eSDan Willemsen	}, {
120*1c12ee1eSDan Willemsen		desc: "proto2 optional scalars set to some values",
121*1c12ee1eSDan Willemsen		input: &pb2.Scalars{
122*1c12ee1eSDan Willemsen			OptBool:     proto.Bool(true),
123*1c12ee1eSDan Willemsen			OptInt32:    proto.Int32(0xff),
124*1c12ee1eSDan Willemsen			OptInt64:    proto.Int64(0xdeadbeef),
125*1c12ee1eSDan Willemsen			OptUint32:   proto.Uint32(47),
126*1c12ee1eSDan Willemsen			OptUint64:   proto.Uint64(0xdeadbeef),
127*1c12ee1eSDan Willemsen			OptSint32:   proto.Int32(-1001),
128*1c12ee1eSDan Willemsen			OptSint64:   proto.Int64(-0xffff),
129*1c12ee1eSDan Willemsen			OptFixed64:  proto.Uint64(64),
130*1c12ee1eSDan Willemsen			OptSfixed32: proto.Int32(-32),
131*1c12ee1eSDan Willemsen			OptFloat:    proto.Float32(1.02),
132*1c12ee1eSDan Willemsen			OptDouble:   proto.Float64(1.234),
133*1c12ee1eSDan Willemsen			OptBytes:    []byte("谷歌"),
134*1c12ee1eSDan Willemsen			OptString:   proto.String("谷歌"),
135*1c12ee1eSDan Willemsen		},
136*1c12ee1eSDan Willemsen		want: `{
137*1c12ee1eSDan Willemsen  "optBool": true,
138*1c12ee1eSDan Willemsen  "optInt32": 255,
139*1c12ee1eSDan Willemsen  "optInt64": "3735928559",
140*1c12ee1eSDan Willemsen  "optUint32": 47,
141*1c12ee1eSDan Willemsen  "optUint64": "3735928559",
142*1c12ee1eSDan Willemsen  "optSint32": -1001,
143*1c12ee1eSDan Willemsen  "optSint64": "-65535",
144*1c12ee1eSDan Willemsen  "optFixed64": "64",
145*1c12ee1eSDan Willemsen  "optSfixed32": -32,
146*1c12ee1eSDan Willemsen  "optFloat": 1.02,
147*1c12ee1eSDan Willemsen  "optDouble": 1.234,
148*1c12ee1eSDan Willemsen  "optBytes": "6LC35q2M",
149*1c12ee1eSDan Willemsen  "optString": "谷歌"
150*1c12ee1eSDan Willemsen}`,
151*1c12ee1eSDan Willemsen	}, {
152*1c12ee1eSDan Willemsen		desc: "string",
153*1c12ee1eSDan Willemsen		input: &pb3.Scalars{
154*1c12ee1eSDan Willemsen			SString: "谷歌",
155*1c12ee1eSDan Willemsen		},
156*1c12ee1eSDan Willemsen		want: `{
157*1c12ee1eSDan Willemsen  "sString": "谷歌"
158*1c12ee1eSDan Willemsen}`,
159*1c12ee1eSDan Willemsen	}, {
160*1c12ee1eSDan Willemsen		desc: "string with invalid UTF8",
161*1c12ee1eSDan Willemsen		input: &pb3.Scalars{
162*1c12ee1eSDan Willemsen			SString: "abc\xff",
163*1c12ee1eSDan Willemsen		},
164*1c12ee1eSDan Willemsen		wantErr: true,
165*1c12ee1eSDan Willemsen	}, {
166*1c12ee1eSDan Willemsen		desc: "float nan",
167*1c12ee1eSDan Willemsen		input: &pb3.Scalars{
168*1c12ee1eSDan Willemsen			SFloat: float32(math.NaN()),
169*1c12ee1eSDan Willemsen		},
170*1c12ee1eSDan Willemsen		want: `{
171*1c12ee1eSDan Willemsen  "sFloat": "NaN"
172*1c12ee1eSDan Willemsen}`,
173*1c12ee1eSDan Willemsen	}, {
174*1c12ee1eSDan Willemsen		desc: "float positive infinity",
175*1c12ee1eSDan Willemsen		input: &pb3.Scalars{
176*1c12ee1eSDan Willemsen			SFloat: float32(math.Inf(1)),
177*1c12ee1eSDan Willemsen		},
178*1c12ee1eSDan Willemsen		want: `{
179*1c12ee1eSDan Willemsen  "sFloat": "Infinity"
180*1c12ee1eSDan Willemsen}`,
181*1c12ee1eSDan Willemsen	}, {
182*1c12ee1eSDan Willemsen		desc: "float negative infinity",
183*1c12ee1eSDan Willemsen		input: &pb3.Scalars{
184*1c12ee1eSDan Willemsen			SFloat: float32(math.Inf(-1)),
185*1c12ee1eSDan Willemsen		},
186*1c12ee1eSDan Willemsen		want: `{
187*1c12ee1eSDan Willemsen  "sFloat": "-Infinity"
188*1c12ee1eSDan Willemsen}`,
189*1c12ee1eSDan Willemsen	}, {
190*1c12ee1eSDan Willemsen		desc: "double nan",
191*1c12ee1eSDan Willemsen		input: &pb3.Scalars{
192*1c12ee1eSDan Willemsen			SDouble: math.NaN(),
193*1c12ee1eSDan Willemsen		},
194*1c12ee1eSDan Willemsen		want: `{
195*1c12ee1eSDan Willemsen  "sDouble": "NaN"
196*1c12ee1eSDan Willemsen}`,
197*1c12ee1eSDan Willemsen	}, {
198*1c12ee1eSDan Willemsen		desc: "double positive infinity",
199*1c12ee1eSDan Willemsen		input: &pb3.Scalars{
200*1c12ee1eSDan Willemsen			SDouble: math.Inf(1),
201*1c12ee1eSDan Willemsen		},
202*1c12ee1eSDan Willemsen		want: `{
203*1c12ee1eSDan Willemsen  "sDouble": "Infinity"
204*1c12ee1eSDan Willemsen}`,
205*1c12ee1eSDan Willemsen	}, {
206*1c12ee1eSDan Willemsen		desc: "double negative infinity",
207*1c12ee1eSDan Willemsen		input: &pb3.Scalars{
208*1c12ee1eSDan Willemsen			SDouble: math.Inf(-1),
209*1c12ee1eSDan Willemsen		},
210*1c12ee1eSDan Willemsen		want: `{
211*1c12ee1eSDan Willemsen  "sDouble": "-Infinity"
212*1c12ee1eSDan Willemsen}`,
213*1c12ee1eSDan Willemsen	}, {
214*1c12ee1eSDan Willemsen		desc:  "proto2 enum not set",
215*1c12ee1eSDan Willemsen		input: &pb2.Enums{},
216*1c12ee1eSDan Willemsen		want:  "{}",
217*1c12ee1eSDan Willemsen	}, {
218*1c12ee1eSDan Willemsen		desc: "proto2 enum set to zero value",
219*1c12ee1eSDan Willemsen		input: &pb2.Enums{
220*1c12ee1eSDan Willemsen			OptEnum:       pb2.Enum(0).Enum(),
221*1c12ee1eSDan Willemsen			OptNestedEnum: pb2.Enums_NestedEnum(0).Enum(),
222*1c12ee1eSDan Willemsen		},
223*1c12ee1eSDan Willemsen		want: `{
224*1c12ee1eSDan Willemsen  "optEnum": 0,
225*1c12ee1eSDan Willemsen  "optNestedEnum": 0
226*1c12ee1eSDan Willemsen}`,
227*1c12ee1eSDan Willemsen	}, {
228*1c12ee1eSDan Willemsen		desc: "proto2 enum",
229*1c12ee1eSDan Willemsen		input: &pb2.Enums{
230*1c12ee1eSDan Willemsen			OptEnum:       pb2.Enum_ONE.Enum(),
231*1c12ee1eSDan Willemsen			OptNestedEnum: pb2.Enums_UNO.Enum(),
232*1c12ee1eSDan Willemsen		},
233*1c12ee1eSDan Willemsen		want: `{
234*1c12ee1eSDan Willemsen  "optEnum": "ONE",
235*1c12ee1eSDan Willemsen  "optNestedEnum": "UNO"
236*1c12ee1eSDan Willemsen}`,
237*1c12ee1eSDan Willemsen	}, {
238*1c12ee1eSDan Willemsen		desc: "proto2 enum set to numeric values",
239*1c12ee1eSDan Willemsen		input: &pb2.Enums{
240*1c12ee1eSDan Willemsen			OptEnum:       pb2.Enum(2).Enum(),
241*1c12ee1eSDan Willemsen			OptNestedEnum: pb2.Enums_NestedEnum(2).Enum(),
242*1c12ee1eSDan Willemsen		},
243*1c12ee1eSDan Willemsen		want: `{
244*1c12ee1eSDan Willemsen  "optEnum": "TWO",
245*1c12ee1eSDan Willemsen  "optNestedEnum": "DOS"
246*1c12ee1eSDan Willemsen}`,
247*1c12ee1eSDan Willemsen	}, {
248*1c12ee1eSDan Willemsen		desc: "proto2 enum set to unnamed numeric values",
249*1c12ee1eSDan Willemsen		input: &pb2.Enums{
250*1c12ee1eSDan Willemsen			OptEnum:       pb2.Enum(101).Enum(),
251*1c12ee1eSDan Willemsen			OptNestedEnum: pb2.Enums_NestedEnum(-101).Enum(),
252*1c12ee1eSDan Willemsen		},
253*1c12ee1eSDan Willemsen		want: `{
254*1c12ee1eSDan Willemsen  "optEnum": 101,
255*1c12ee1eSDan Willemsen  "optNestedEnum": -101
256*1c12ee1eSDan Willemsen}`,
257*1c12ee1eSDan Willemsen	}, {
258*1c12ee1eSDan Willemsen		desc:  "proto3 enum not set",
259*1c12ee1eSDan Willemsen		input: &pb3.Enums{},
260*1c12ee1eSDan Willemsen		want:  "{}",
261*1c12ee1eSDan Willemsen	}, {
262*1c12ee1eSDan Willemsen		desc: "proto3 enum set to zero value",
263*1c12ee1eSDan Willemsen		input: &pb3.Enums{
264*1c12ee1eSDan Willemsen			SEnum:       pb3.Enum_ZERO,
265*1c12ee1eSDan Willemsen			SNestedEnum: pb3.Enums_CERO,
266*1c12ee1eSDan Willemsen		},
267*1c12ee1eSDan Willemsen		want: "{}",
268*1c12ee1eSDan Willemsen	}, {
269*1c12ee1eSDan Willemsen		desc: "proto3 enum",
270*1c12ee1eSDan Willemsen		input: &pb3.Enums{
271*1c12ee1eSDan Willemsen			SEnum:       pb3.Enum_ONE,
272*1c12ee1eSDan Willemsen			SNestedEnum: pb3.Enums_UNO,
273*1c12ee1eSDan Willemsen		},
274*1c12ee1eSDan Willemsen		want: `{
275*1c12ee1eSDan Willemsen  "sEnum": "ONE",
276*1c12ee1eSDan Willemsen  "sNestedEnum": "UNO"
277*1c12ee1eSDan Willemsen}`,
278*1c12ee1eSDan Willemsen	}, {
279*1c12ee1eSDan Willemsen		desc: "proto3 enum set to numeric values",
280*1c12ee1eSDan Willemsen		input: &pb3.Enums{
281*1c12ee1eSDan Willemsen			SEnum:       2,
282*1c12ee1eSDan Willemsen			SNestedEnum: 2,
283*1c12ee1eSDan Willemsen		},
284*1c12ee1eSDan Willemsen		want: `{
285*1c12ee1eSDan Willemsen  "sEnum": "TWO",
286*1c12ee1eSDan Willemsen  "sNestedEnum": "DOS"
287*1c12ee1eSDan Willemsen}`,
288*1c12ee1eSDan Willemsen	}, {
289*1c12ee1eSDan Willemsen		desc: "proto3 enum set to unnamed numeric values",
290*1c12ee1eSDan Willemsen		input: &pb3.Enums{
291*1c12ee1eSDan Willemsen			SEnum:       -47,
292*1c12ee1eSDan Willemsen			SNestedEnum: 47,
293*1c12ee1eSDan Willemsen		},
294*1c12ee1eSDan Willemsen		want: `{
295*1c12ee1eSDan Willemsen  "sEnum": -47,
296*1c12ee1eSDan Willemsen  "sNestedEnum": 47
297*1c12ee1eSDan Willemsen}`,
298*1c12ee1eSDan Willemsen	}, {
299*1c12ee1eSDan Willemsen		desc:  "proto2 nested message not set",
300*1c12ee1eSDan Willemsen		input: &pb2.Nests{},
301*1c12ee1eSDan Willemsen		want:  "{}",
302*1c12ee1eSDan Willemsen	}, {
303*1c12ee1eSDan Willemsen		desc: "proto2 nested message set to empty",
304*1c12ee1eSDan Willemsen		input: &pb2.Nests{
305*1c12ee1eSDan Willemsen			OptNested: &pb2.Nested{},
306*1c12ee1eSDan Willemsen			Optgroup:  &pb2.Nests_OptGroup{},
307*1c12ee1eSDan Willemsen		},
308*1c12ee1eSDan Willemsen		want: `{
309*1c12ee1eSDan Willemsen  "optNested": {},
310*1c12ee1eSDan Willemsen  "optgroup": {}
311*1c12ee1eSDan Willemsen}`,
312*1c12ee1eSDan Willemsen	}, {
313*1c12ee1eSDan Willemsen		desc: "proto2 nested messages",
314*1c12ee1eSDan Willemsen		input: &pb2.Nests{
315*1c12ee1eSDan Willemsen			OptNested: &pb2.Nested{
316*1c12ee1eSDan Willemsen				OptString: proto.String("nested message"),
317*1c12ee1eSDan Willemsen				OptNested: &pb2.Nested{
318*1c12ee1eSDan Willemsen					OptString: proto.String("another nested message"),
319*1c12ee1eSDan Willemsen				},
320*1c12ee1eSDan Willemsen			},
321*1c12ee1eSDan Willemsen		},
322*1c12ee1eSDan Willemsen		want: `{
323*1c12ee1eSDan Willemsen  "optNested": {
324*1c12ee1eSDan Willemsen    "optString": "nested message",
325*1c12ee1eSDan Willemsen    "optNested": {
326*1c12ee1eSDan Willemsen      "optString": "another nested message"
327*1c12ee1eSDan Willemsen    }
328*1c12ee1eSDan Willemsen  }
329*1c12ee1eSDan Willemsen}`,
330*1c12ee1eSDan Willemsen	}, {
331*1c12ee1eSDan Willemsen		desc: "proto2 groups",
332*1c12ee1eSDan Willemsen		input: &pb2.Nests{
333*1c12ee1eSDan Willemsen			Optgroup: &pb2.Nests_OptGroup{
334*1c12ee1eSDan Willemsen				OptString: proto.String("inside a group"),
335*1c12ee1eSDan Willemsen				OptNested: &pb2.Nested{
336*1c12ee1eSDan Willemsen					OptString: proto.String("nested message inside a group"),
337*1c12ee1eSDan Willemsen				},
338*1c12ee1eSDan Willemsen				Optnestedgroup: &pb2.Nests_OptGroup_OptNestedGroup{
339*1c12ee1eSDan Willemsen					OptFixed32: proto.Uint32(47),
340*1c12ee1eSDan Willemsen				},
341*1c12ee1eSDan Willemsen			},
342*1c12ee1eSDan Willemsen		},
343*1c12ee1eSDan Willemsen		want: `{
344*1c12ee1eSDan Willemsen  "optgroup": {
345*1c12ee1eSDan Willemsen    "optString": "inside a group",
346*1c12ee1eSDan Willemsen    "optNested": {
347*1c12ee1eSDan Willemsen      "optString": "nested message inside a group"
348*1c12ee1eSDan Willemsen    },
349*1c12ee1eSDan Willemsen    "optnestedgroup": {
350*1c12ee1eSDan Willemsen      "optFixed32": 47
351*1c12ee1eSDan Willemsen    }
352*1c12ee1eSDan Willemsen  }
353*1c12ee1eSDan Willemsen}`,
354*1c12ee1eSDan Willemsen	}, {
355*1c12ee1eSDan Willemsen		desc:  "proto3 nested message not set",
356*1c12ee1eSDan Willemsen		input: &pb3.Nests{},
357*1c12ee1eSDan Willemsen		want:  "{}",
358*1c12ee1eSDan Willemsen	}, {
359*1c12ee1eSDan Willemsen		desc: "proto3 nested message set to empty",
360*1c12ee1eSDan Willemsen		input: &pb3.Nests{
361*1c12ee1eSDan Willemsen			SNested: &pb3.Nested{},
362*1c12ee1eSDan Willemsen		},
363*1c12ee1eSDan Willemsen		want: `{
364*1c12ee1eSDan Willemsen  "sNested": {}
365*1c12ee1eSDan Willemsen}`,
366*1c12ee1eSDan Willemsen	}, {
367*1c12ee1eSDan Willemsen		desc: "proto3 nested message",
368*1c12ee1eSDan Willemsen		input: &pb3.Nests{
369*1c12ee1eSDan Willemsen			SNested: &pb3.Nested{
370*1c12ee1eSDan Willemsen				SString: "nested message",
371*1c12ee1eSDan Willemsen				SNested: &pb3.Nested{
372*1c12ee1eSDan Willemsen					SString: "another nested message",
373*1c12ee1eSDan Willemsen				},
374*1c12ee1eSDan Willemsen			},
375*1c12ee1eSDan Willemsen		},
376*1c12ee1eSDan Willemsen		want: `{
377*1c12ee1eSDan Willemsen  "sNested": {
378*1c12ee1eSDan Willemsen    "sString": "nested message",
379*1c12ee1eSDan Willemsen    "sNested": {
380*1c12ee1eSDan Willemsen      "sString": "another nested message"
381*1c12ee1eSDan Willemsen    }
382*1c12ee1eSDan Willemsen  }
383*1c12ee1eSDan Willemsen}`,
384*1c12ee1eSDan Willemsen	}, {
385*1c12ee1eSDan Willemsen		desc:  "oneof not set",
386*1c12ee1eSDan Willemsen		input: &pb3.Oneofs{},
387*1c12ee1eSDan Willemsen		want:  "{}",
388*1c12ee1eSDan Willemsen	}, {
389*1c12ee1eSDan Willemsen		desc: "oneof set to empty string",
390*1c12ee1eSDan Willemsen		input: &pb3.Oneofs{
391*1c12ee1eSDan Willemsen			Union: &pb3.Oneofs_OneofString{},
392*1c12ee1eSDan Willemsen		},
393*1c12ee1eSDan Willemsen		want: `{
394*1c12ee1eSDan Willemsen  "oneofString": ""
395*1c12ee1eSDan Willemsen}`,
396*1c12ee1eSDan Willemsen	}, {
397*1c12ee1eSDan Willemsen		desc: "oneof set to string",
398*1c12ee1eSDan Willemsen		input: &pb3.Oneofs{
399*1c12ee1eSDan Willemsen			Union: &pb3.Oneofs_OneofString{
400*1c12ee1eSDan Willemsen				OneofString: "hello",
401*1c12ee1eSDan Willemsen			},
402*1c12ee1eSDan Willemsen		},
403*1c12ee1eSDan Willemsen		want: `{
404*1c12ee1eSDan Willemsen  "oneofString": "hello"
405*1c12ee1eSDan Willemsen}`,
406*1c12ee1eSDan Willemsen	}, {
407*1c12ee1eSDan Willemsen		desc: "oneof set to enum",
408*1c12ee1eSDan Willemsen		input: &pb3.Oneofs{
409*1c12ee1eSDan Willemsen			Union: &pb3.Oneofs_OneofEnum{
410*1c12ee1eSDan Willemsen				OneofEnum: pb3.Enum_ZERO,
411*1c12ee1eSDan Willemsen			},
412*1c12ee1eSDan Willemsen		},
413*1c12ee1eSDan Willemsen		want: `{
414*1c12ee1eSDan Willemsen  "oneofEnum": "ZERO"
415*1c12ee1eSDan Willemsen}`,
416*1c12ee1eSDan Willemsen	}, {
417*1c12ee1eSDan Willemsen		desc: "oneof set to empty message",
418*1c12ee1eSDan Willemsen		input: &pb3.Oneofs{
419*1c12ee1eSDan Willemsen			Union: &pb3.Oneofs_OneofNested{
420*1c12ee1eSDan Willemsen				OneofNested: &pb3.Nested{},
421*1c12ee1eSDan Willemsen			},
422*1c12ee1eSDan Willemsen		},
423*1c12ee1eSDan Willemsen		want: `{
424*1c12ee1eSDan Willemsen  "oneofNested": {}
425*1c12ee1eSDan Willemsen}`,
426*1c12ee1eSDan Willemsen	}, {
427*1c12ee1eSDan Willemsen		desc: "oneof set to message",
428*1c12ee1eSDan Willemsen		input: &pb3.Oneofs{
429*1c12ee1eSDan Willemsen			Union: &pb3.Oneofs_OneofNested{
430*1c12ee1eSDan Willemsen				OneofNested: &pb3.Nested{
431*1c12ee1eSDan Willemsen					SString: "nested message",
432*1c12ee1eSDan Willemsen				},
433*1c12ee1eSDan Willemsen			},
434*1c12ee1eSDan Willemsen		},
435*1c12ee1eSDan Willemsen		want: `{
436*1c12ee1eSDan Willemsen  "oneofNested": {
437*1c12ee1eSDan Willemsen    "sString": "nested message"
438*1c12ee1eSDan Willemsen  }
439*1c12ee1eSDan Willemsen}`,
440*1c12ee1eSDan Willemsen	}, {
441*1c12ee1eSDan Willemsen		desc:  "repeated fields not set",
442*1c12ee1eSDan Willemsen		input: &pb2.Repeats{},
443*1c12ee1eSDan Willemsen		want:  "{}",
444*1c12ee1eSDan Willemsen	}, {
445*1c12ee1eSDan Willemsen		desc: "repeated fields set to empty slices",
446*1c12ee1eSDan Willemsen		input: &pb2.Repeats{
447*1c12ee1eSDan Willemsen			RptBool:   []bool{},
448*1c12ee1eSDan Willemsen			RptInt32:  []int32{},
449*1c12ee1eSDan Willemsen			RptInt64:  []int64{},
450*1c12ee1eSDan Willemsen			RptUint32: []uint32{},
451*1c12ee1eSDan Willemsen			RptUint64: []uint64{},
452*1c12ee1eSDan Willemsen			RptFloat:  []float32{},
453*1c12ee1eSDan Willemsen			RptDouble: []float64{},
454*1c12ee1eSDan Willemsen			RptBytes:  [][]byte{},
455*1c12ee1eSDan Willemsen		},
456*1c12ee1eSDan Willemsen		want: "{}",
457*1c12ee1eSDan Willemsen	}, {
458*1c12ee1eSDan Willemsen		desc: "repeated fields set to some values",
459*1c12ee1eSDan Willemsen		input: &pb2.Repeats{
460*1c12ee1eSDan Willemsen			RptBool:   []bool{true, false, true, true},
461*1c12ee1eSDan Willemsen			RptInt32:  []int32{1, 6, 0, 0},
462*1c12ee1eSDan Willemsen			RptInt64:  []int64{-64, 47},
463*1c12ee1eSDan Willemsen			RptUint32: []uint32{0xff, 0xffff},
464*1c12ee1eSDan Willemsen			RptUint64: []uint64{0xdeadbeef},
465*1c12ee1eSDan Willemsen			RptFloat:  []float32{float32(math.NaN()), float32(math.Inf(1)), float32(math.Inf(-1)), 1.034},
466*1c12ee1eSDan Willemsen			RptDouble: []float64{math.NaN(), math.Inf(1), math.Inf(-1), 1.23e-308},
467*1c12ee1eSDan Willemsen			RptString: []string{"hello", "世界"},
468*1c12ee1eSDan Willemsen			RptBytes: [][]byte{
469*1c12ee1eSDan Willemsen				[]byte("hello"),
470*1c12ee1eSDan Willemsen				[]byte("\xe4\xb8\x96\xe7\x95\x8c"),
471*1c12ee1eSDan Willemsen			},
472*1c12ee1eSDan Willemsen		},
473*1c12ee1eSDan Willemsen		want: `{
474*1c12ee1eSDan Willemsen  "rptBool": [
475*1c12ee1eSDan Willemsen    true,
476*1c12ee1eSDan Willemsen    false,
477*1c12ee1eSDan Willemsen    true,
478*1c12ee1eSDan Willemsen    true
479*1c12ee1eSDan Willemsen  ],
480*1c12ee1eSDan Willemsen  "rptInt32": [
481*1c12ee1eSDan Willemsen    1,
482*1c12ee1eSDan Willemsen    6,
483*1c12ee1eSDan Willemsen    0,
484*1c12ee1eSDan Willemsen    0
485*1c12ee1eSDan Willemsen  ],
486*1c12ee1eSDan Willemsen  "rptInt64": [
487*1c12ee1eSDan Willemsen    "-64",
488*1c12ee1eSDan Willemsen    "47"
489*1c12ee1eSDan Willemsen  ],
490*1c12ee1eSDan Willemsen  "rptUint32": [
491*1c12ee1eSDan Willemsen    255,
492*1c12ee1eSDan Willemsen    65535
493*1c12ee1eSDan Willemsen  ],
494*1c12ee1eSDan Willemsen  "rptUint64": [
495*1c12ee1eSDan Willemsen    "3735928559"
496*1c12ee1eSDan Willemsen  ],
497*1c12ee1eSDan Willemsen  "rptFloat": [
498*1c12ee1eSDan Willemsen    "NaN",
499*1c12ee1eSDan Willemsen    "Infinity",
500*1c12ee1eSDan Willemsen    "-Infinity",
501*1c12ee1eSDan Willemsen    1.034
502*1c12ee1eSDan Willemsen  ],
503*1c12ee1eSDan Willemsen  "rptDouble": [
504*1c12ee1eSDan Willemsen    "NaN",
505*1c12ee1eSDan Willemsen    "Infinity",
506*1c12ee1eSDan Willemsen    "-Infinity",
507*1c12ee1eSDan Willemsen    1.23e-308
508*1c12ee1eSDan Willemsen  ],
509*1c12ee1eSDan Willemsen  "rptString": [
510*1c12ee1eSDan Willemsen    "hello",
511*1c12ee1eSDan Willemsen    "世界"
512*1c12ee1eSDan Willemsen  ],
513*1c12ee1eSDan Willemsen  "rptBytes": [
514*1c12ee1eSDan Willemsen    "aGVsbG8=",
515*1c12ee1eSDan Willemsen    "5LiW55WM"
516*1c12ee1eSDan Willemsen  ]
517*1c12ee1eSDan Willemsen}`,
518*1c12ee1eSDan Willemsen	}, {
519*1c12ee1eSDan Willemsen		desc: "repeated enums",
520*1c12ee1eSDan Willemsen		input: &pb2.Enums{
521*1c12ee1eSDan Willemsen			RptEnum:       []pb2.Enum{pb2.Enum_ONE, 2, pb2.Enum_TEN, 42},
522*1c12ee1eSDan Willemsen			RptNestedEnum: []pb2.Enums_NestedEnum{2, 47, 10},
523*1c12ee1eSDan Willemsen		},
524*1c12ee1eSDan Willemsen		want: `{
525*1c12ee1eSDan Willemsen  "rptEnum": [
526*1c12ee1eSDan Willemsen    "ONE",
527*1c12ee1eSDan Willemsen    "TWO",
528*1c12ee1eSDan Willemsen    "TEN",
529*1c12ee1eSDan Willemsen    42
530*1c12ee1eSDan Willemsen  ],
531*1c12ee1eSDan Willemsen  "rptNestedEnum": [
532*1c12ee1eSDan Willemsen    "DOS",
533*1c12ee1eSDan Willemsen    47,
534*1c12ee1eSDan Willemsen    "DIEZ"
535*1c12ee1eSDan Willemsen  ]
536*1c12ee1eSDan Willemsen}`,
537*1c12ee1eSDan Willemsen	}, {
538*1c12ee1eSDan Willemsen		desc: "repeated messages set to empty",
539*1c12ee1eSDan Willemsen		input: &pb2.Nests{
540*1c12ee1eSDan Willemsen			RptNested: []*pb2.Nested{},
541*1c12ee1eSDan Willemsen			Rptgroup:  []*pb2.Nests_RptGroup{},
542*1c12ee1eSDan Willemsen		},
543*1c12ee1eSDan Willemsen		want: "{}",
544*1c12ee1eSDan Willemsen	}, {
545*1c12ee1eSDan Willemsen		desc: "repeated messages",
546*1c12ee1eSDan Willemsen		input: &pb2.Nests{
547*1c12ee1eSDan Willemsen			RptNested: []*pb2.Nested{
548*1c12ee1eSDan Willemsen				{
549*1c12ee1eSDan Willemsen					OptString: proto.String("repeat nested one"),
550*1c12ee1eSDan Willemsen				},
551*1c12ee1eSDan Willemsen				{
552*1c12ee1eSDan Willemsen					OptString: proto.String("repeat nested two"),
553*1c12ee1eSDan Willemsen					OptNested: &pb2.Nested{
554*1c12ee1eSDan Willemsen						OptString: proto.String("inside repeat nested two"),
555*1c12ee1eSDan Willemsen					},
556*1c12ee1eSDan Willemsen				},
557*1c12ee1eSDan Willemsen				{},
558*1c12ee1eSDan Willemsen			},
559*1c12ee1eSDan Willemsen		},
560*1c12ee1eSDan Willemsen		want: `{
561*1c12ee1eSDan Willemsen  "rptNested": [
562*1c12ee1eSDan Willemsen    {
563*1c12ee1eSDan Willemsen      "optString": "repeat nested one"
564*1c12ee1eSDan Willemsen    },
565*1c12ee1eSDan Willemsen    {
566*1c12ee1eSDan Willemsen      "optString": "repeat nested two",
567*1c12ee1eSDan Willemsen      "optNested": {
568*1c12ee1eSDan Willemsen        "optString": "inside repeat nested two"
569*1c12ee1eSDan Willemsen      }
570*1c12ee1eSDan Willemsen    },
571*1c12ee1eSDan Willemsen    {}
572*1c12ee1eSDan Willemsen  ]
573*1c12ee1eSDan Willemsen}`,
574*1c12ee1eSDan Willemsen	}, {
575*1c12ee1eSDan Willemsen		desc: "repeated messages contains nil value",
576*1c12ee1eSDan Willemsen		input: &pb2.Nests{
577*1c12ee1eSDan Willemsen			RptNested: []*pb2.Nested{nil, {}},
578*1c12ee1eSDan Willemsen		},
579*1c12ee1eSDan Willemsen		want: `{
580*1c12ee1eSDan Willemsen  "rptNested": [
581*1c12ee1eSDan Willemsen    {},
582*1c12ee1eSDan Willemsen    {}
583*1c12ee1eSDan Willemsen  ]
584*1c12ee1eSDan Willemsen}`,
585*1c12ee1eSDan Willemsen	}, {
586*1c12ee1eSDan Willemsen		desc: "repeated groups",
587*1c12ee1eSDan Willemsen		input: &pb2.Nests{
588*1c12ee1eSDan Willemsen			Rptgroup: []*pb2.Nests_RptGroup{
589*1c12ee1eSDan Willemsen				{
590*1c12ee1eSDan Willemsen					RptString: []string{"hello", "world"},
591*1c12ee1eSDan Willemsen				},
592*1c12ee1eSDan Willemsen				{},
593*1c12ee1eSDan Willemsen				nil,
594*1c12ee1eSDan Willemsen			},
595*1c12ee1eSDan Willemsen		},
596*1c12ee1eSDan Willemsen		want: `{
597*1c12ee1eSDan Willemsen  "rptgroup": [
598*1c12ee1eSDan Willemsen    {
599*1c12ee1eSDan Willemsen      "rptString": [
600*1c12ee1eSDan Willemsen        "hello",
601*1c12ee1eSDan Willemsen        "world"
602*1c12ee1eSDan Willemsen      ]
603*1c12ee1eSDan Willemsen    },
604*1c12ee1eSDan Willemsen    {},
605*1c12ee1eSDan Willemsen    {}
606*1c12ee1eSDan Willemsen  ]
607*1c12ee1eSDan Willemsen}`,
608*1c12ee1eSDan Willemsen	}, {
609*1c12ee1eSDan Willemsen		desc:  "map fields not set",
610*1c12ee1eSDan Willemsen		input: &pb3.Maps{},
611*1c12ee1eSDan Willemsen		want:  "{}",
612*1c12ee1eSDan Willemsen	}, {
613*1c12ee1eSDan Willemsen		desc: "map fields set to empty",
614*1c12ee1eSDan Willemsen		input: &pb3.Maps{
615*1c12ee1eSDan Willemsen			Int32ToStr:   map[int32]string{},
616*1c12ee1eSDan Willemsen			BoolToUint32: map[bool]uint32{},
617*1c12ee1eSDan Willemsen			Uint64ToEnum: map[uint64]pb3.Enum{},
618*1c12ee1eSDan Willemsen			StrToNested:  map[string]*pb3.Nested{},
619*1c12ee1eSDan Willemsen			StrToOneofs:  map[string]*pb3.Oneofs{},
620*1c12ee1eSDan Willemsen		},
621*1c12ee1eSDan Willemsen		want: "{}",
622*1c12ee1eSDan Willemsen	}, {
623*1c12ee1eSDan Willemsen		desc: "map fields 1",
624*1c12ee1eSDan Willemsen		input: &pb3.Maps{
625*1c12ee1eSDan Willemsen			BoolToUint32: map[bool]uint32{
626*1c12ee1eSDan Willemsen				true:  42,
627*1c12ee1eSDan Willemsen				false: 101,
628*1c12ee1eSDan Willemsen			},
629*1c12ee1eSDan Willemsen		},
630*1c12ee1eSDan Willemsen		want: `{
631*1c12ee1eSDan Willemsen  "boolToUint32": {
632*1c12ee1eSDan Willemsen    "false": 101,
633*1c12ee1eSDan Willemsen    "true": 42
634*1c12ee1eSDan Willemsen  }
635*1c12ee1eSDan Willemsen}`,
636*1c12ee1eSDan Willemsen	}, {
637*1c12ee1eSDan Willemsen		desc: "map fields 2",
638*1c12ee1eSDan Willemsen		input: &pb3.Maps{
639*1c12ee1eSDan Willemsen			Int32ToStr: map[int32]string{
640*1c12ee1eSDan Willemsen				-101: "-101",
641*1c12ee1eSDan Willemsen				0xff: "0xff",
642*1c12ee1eSDan Willemsen				0:    "zero",
643*1c12ee1eSDan Willemsen			},
644*1c12ee1eSDan Willemsen		},
645*1c12ee1eSDan Willemsen		want: `{
646*1c12ee1eSDan Willemsen  "int32ToStr": {
647*1c12ee1eSDan Willemsen    "-101": "-101",
648*1c12ee1eSDan Willemsen    "0": "zero",
649*1c12ee1eSDan Willemsen    "255": "0xff"
650*1c12ee1eSDan Willemsen  }
651*1c12ee1eSDan Willemsen}`,
652*1c12ee1eSDan Willemsen	}, {
653*1c12ee1eSDan Willemsen		desc: "map fields 3",
654*1c12ee1eSDan Willemsen		input: &pb3.Maps{
655*1c12ee1eSDan Willemsen			Uint64ToEnum: map[uint64]pb3.Enum{
656*1c12ee1eSDan Willemsen				1:  pb3.Enum_ONE,
657*1c12ee1eSDan Willemsen				2:  pb3.Enum_TWO,
658*1c12ee1eSDan Willemsen				10: pb3.Enum_TEN,
659*1c12ee1eSDan Willemsen				47: 47,
660*1c12ee1eSDan Willemsen			},
661*1c12ee1eSDan Willemsen		},
662*1c12ee1eSDan Willemsen		want: `{
663*1c12ee1eSDan Willemsen  "uint64ToEnum": {
664*1c12ee1eSDan Willemsen    "1": "ONE",
665*1c12ee1eSDan Willemsen    "2": "TWO",
666*1c12ee1eSDan Willemsen    "10": "TEN",
667*1c12ee1eSDan Willemsen    "47": 47
668*1c12ee1eSDan Willemsen  }
669*1c12ee1eSDan Willemsen}`,
670*1c12ee1eSDan Willemsen	}, {
671*1c12ee1eSDan Willemsen		desc: "map fields 4",
672*1c12ee1eSDan Willemsen		input: &pb3.Maps{
673*1c12ee1eSDan Willemsen			StrToNested: map[string]*pb3.Nested{
674*1c12ee1eSDan Willemsen				"nested": &pb3.Nested{
675*1c12ee1eSDan Willemsen					SString: "nested in a map",
676*1c12ee1eSDan Willemsen				},
677*1c12ee1eSDan Willemsen			},
678*1c12ee1eSDan Willemsen		},
679*1c12ee1eSDan Willemsen		want: `{
680*1c12ee1eSDan Willemsen  "strToNested": {
681*1c12ee1eSDan Willemsen    "nested": {
682*1c12ee1eSDan Willemsen      "sString": "nested in a map"
683*1c12ee1eSDan Willemsen    }
684*1c12ee1eSDan Willemsen  }
685*1c12ee1eSDan Willemsen}`,
686*1c12ee1eSDan Willemsen	}, {
687*1c12ee1eSDan Willemsen		desc: "map fields 5",
688*1c12ee1eSDan Willemsen		input: &pb3.Maps{
689*1c12ee1eSDan Willemsen			StrToOneofs: map[string]*pb3.Oneofs{
690*1c12ee1eSDan Willemsen				"string": &pb3.Oneofs{
691*1c12ee1eSDan Willemsen					Union: &pb3.Oneofs_OneofString{
692*1c12ee1eSDan Willemsen						OneofString: "hello",
693*1c12ee1eSDan Willemsen					},
694*1c12ee1eSDan Willemsen				},
695*1c12ee1eSDan Willemsen				"nested": &pb3.Oneofs{
696*1c12ee1eSDan Willemsen					Union: &pb3.Oneofs_OneofNested{
697*1c12ee1eSDan Willemsen						OneofNested: &pb3.Nested{
698*1c12ee1eSDan Willemsen							SString: "nested oneof in map field value",
699*1c12ee1eSDan Willemsen						},
700*1c12ee1eSDan Willemsen					},
701*1c12ee1eSDan Willemsen				},
702*1c12ee1eSDan Willemsen			},
703*1c12ee1eSDan Willemsen		},
704*1c12ee1eSDan Willemsen		want: `{
705*1c12ee1eSDan Willemsen  "strToOneofs": {
706*1c12ee1eSDan Willemsen    "nested": {
707*1c12ee1eSDan Willemsen      "oneofNested": {
708*1c12ee1eSDan Willemsen        "sString": "nested oneof in map field value"
709*1c12ee1eSDan Willemsen      }
710*1c12ee1eSDan Willemsen    },
711*1c12ee1eSDan Willemsen    "string": {
712*1c12ee1eSDan Willemsen      "oneofString": "hello"
713*1c12ee1eSDan Willemsen    }
714*1c12ee1eSDan Willemsen  }
715*1c12ee1eSDan Willemsen}`,
716*1c12ee1eSDan Willemsen	}, {
717*1c12ee1eSDan Willemsen		desc: "map field contains nil value",
718*1c12ee1eSDan Willemsen		input: &pb3.Maps{
719*1c12ee1eSDan Willemsen			StrToNested: map[string]*pb3.Nested{
720*1c12ee1eSDan Willemsen				"nil": nil,
721*1c12ee1eSDan Willemsen			},
722*1c12ee1eSDan Willemsen		},
723*1c12ee1eSDan Willemsen		want: `{
724*1c12ee1eSDan Willemsen  "strToNested": {
725*1c12ee1eSDan Willemsen    "nil": {}
726*1c12ee1eSDan Willemsen  }
727*1c12ee1eSDan Willemsen}`,
728*1c12ee1eSDan Willemsen	}, {
729*1c12ee1eSDan Willemsen		desc:    "required fields not set",
730*1c12ee1eSDan Willemsen		input:   &pb2.Requireds{},
731*1c12ee1eSDan Willemsen		want:    `{}`,
732*1c12ee1eSDan Willemsen		wantErr: true,
733*1c12ee1eSDan Willemsen	}, {
734*1c12ee1eSDan Willemsen		desc: "required fields partially set",
735*1c12ee1eSDan Willemsen		input: &pb2.Requireds{
736*1c12ee1eSDan Willemsen			ReqBool:     proto.Bool(false),
737*1c12ee1eSDan Willemsen			ReqSfixed64: proto.Int64(0),
738*1c12ee1eSDan Willemsen			ReqDouble:   proto.Float64(1.23),
739*1c12ee1eSDan Willemsen			ReqString:   proto.String("hello"),
740*1c12ee1eSDan Willemsen			ReqEnum:     pb2.Enum_ONE.Enum(),
741*1c12ee1eSDan Willemsen		},
742*1c12ee1eSDan Willemsen		want: `{
743*1c12ee1eSDan Willemsen  "reqBool": false,
744*1c12ee1eSDan Willemsen  "reqSfixed64": "0",
745*1c12ee1eSDan Willemsen  "reqDouble": 1.23,
746*1c12ee1eSDan Willemsen  "reqString": "hello",
747*1c12ee1eSDan Willemsen  "reqEnum": "ONE"
748*1c12ee1eSDan Willemsen}`,
749*1c12ee1eSDan Willemsen		wantErr: true,
750*1c12ee1eSDan Willemsen	}, {
751*1c12ee1eSDan Willemsen		desc: "required fields not set with AllowPartial",
752*1c12ee1eSDan Willemsen		mo:   protojson.MarshalOptions{AllowPartial: true},
753*1c12ee1eSDan Willemsen		input: &pb2.Requireds{
754*1c12ee1eSDan Willemsen			ReqBool:     proto.Bool(false),
755*1c12ee1eSDan Willemsen			ReqSfixed64: proto.Int64(0),
756*1c12ee1eSDan Willemsen			ReqDouble:   proto.Float64(1.23),
757*1c12ee1eSDan Willemsen			ReqString:   proto.String("hello"),
758*1c12ee1eSDan Willemsen			ReqEnum:     pb2.Enum_ONE.Enum(),
759*1c12ee1eSDan Willemsen		},
760*1c12ee1eSDan Willemsen		want: `{
761*1c12ee1eSDan Willemsen  "reqBool": false,
762*1c12ee1eSDan Willemsen  "reqSfixed64": "0",
763*1c12ee1eSDan Willemsen  "reqDouble": 1.23,
764*1c12ee1eSDan Willemsen  "reqString": "hello",
765*1c12ee1eSDan Willemsen  "reqEnum": "ONE"
766*1c12ee1eSDan Willemsen}`,
767*1c12ee1eSDan Willemsen	}, {
768*1c12ee1eSDan Willemsen		desc: "required fields all set",
769*1c12ee1eSDan Willemsen		input: &pb2.Requireds{
770*1c12ee1eSDan Willemsen			ReqBool:     proto.Bool(false),
771*1c12ee1eSDan Willemsen			ReqSfixed64: proto.Int64(0),
772*1c12ee1eSDan Willemsen			ReqDouble:   proto.Float64(1.23),
773*1c12ee1eSDan Willemsen			ReqString:   proto.String("hello"),
774*1c12ee1eSDan Willemsen			ReqEnum:     pb2.Enum_ONE.Enum(),
775*1c12ee1eSDan Willemsen			ReqNested:   &pb2.Nested{},
776*1c12ee1eSDan Willemsen		},
777*1c12ee1eSDan Willemsen		want: `{
778*1c12ee1eSDan Willemsen  "reqBool": false,
779*1c12ee1eSDan Willemsen  "reqSfixed64": "0",
780*1c12ee1eSDan Willemsen  "reqDouble": 1.23,
781*1c12ee1eSDan Willemsen  "reqString": "hello",
782*1c12ee1eSDan Willemsen  "reqEnum": "ONE",
783*1c12ee1eSDan Willemsen  "reqNested": {}
784*1c12ee1eSDan Willemsen}`,
785*1c12ee1eSDan Willemsen	}, {
786*1c12ee1eSDan Willemsen		desc: "indirect required field",
787*1c12ee1eSDan Willemsen		input: &pb2.IndirectRequired{
788*1c12ee1eSDan Willemsen			OptNested: &pb2.NestedWithRequired{},
789*1c12ee1eSDan Willemsen		},
790*1c12ee1eSDan Willemsen		want: `{
791*1c12ee1eSDan Willemsen  "optNested": {}
792*1c12ee1eSDan Willemsen}`,
793*1c12ee1eSDan Willemsen		wantErr: true,
794*1c12ee1eSDan Willemsen	}, {
795*1c12ee1eSDan Willemsen		desc: "indirect required field with AllowPartial",
796*1c12ee1eSDan Willemsen		mo:   protojson.MarshalOptions{AllowPartial: true},
797*1c12ee1eSDan Willemsen		input: &pb2.IndirectRequired{
798*1c12ee1eSDan Willemsen			OptNested: &pb2.NestedWithRequired{},
799*1c12ee1eSDan Willemsen		},
800*1c12ee1eSDan Willemsen		want: `{
801*1c12ee1eSDan Willemsen  "optNested": {}
802*1c12ee1eSDan Willemsen}`,
803*1c12ee1eSDan Willemsen	}, {
804*1c12ee1eSDan Willemsen		desc: "indirect required field in empty repeated",
805*1c12ee1eSDan Willemsen		input: &pb2.IndirectRequired{
806*1c12ee1eSDan Willemsen			RptNested: []*pb2.NestedWithRequired{},
807*1c12ee1eSDan Willemsen		},
808*1c12ee1eSDan Willemsen		want: `{}`,
809*1c12ee1eSDan Willemsen	}, {
810*1c12ee1eSDan Willemsen		desc: "indirect required field in repeated",
811*1c12ee1eSDan Willemsen		input: &pb2.IndirectRequired{
812*1c12ee1eSDan Willemsen			RptNested: []*pb2.NestedWithRequired{
813*1c12ee1eSDan Willemsen				&pb2.NestedWithRequired{},
814*1c12ee1eSDan Willemsen			},
815*1c12ee1eSDan Willemsen		},
816*1c12ee1eSDan Willemsen		want: `{
817*1c12ee1eSDan Willemsen  "rptNested": [
818*1c12ee1eSDan Willemsen    {}
819*1c12ee1eSDan Willemsen  ]
820*1c12ee1eSDan Willemsen}`,
821*1c12ee1eSDan Willemsen		wantErr: true,
822*1c12ee1eSDan Willemsen	}, {
823*1c12ee1eSDan Willemsen		desc: "indirect required field in repeated with AllowPartial",
824*1c12ee1eSDan Willemsen		mo:   protojson.MarshalOptions{AllowPartial: true},
825*1c12ee1eSDan Willemsen		input: &pb2.IndirectRequired{
826*1c12ee1eSDan Willemsen			RptNested: []*pb2.NestedWithRequired{
827*1c12ee1eSDan Willemsen				&pb2.NestedWithRequired{},
828*1c12ee1eSDan Willemsen			},
829*1c12ee1eSDan Willemsen		},
830*1c12ee1eSDan Willemsen		want: `{
831*1c12ee1eSDan Willemsen  "rptNested": [
832*1c12ee1eSDan Willemsen    {}
833*1c12ee1eSDan Willemsen  ]
834*1c12ee1eSDan Willemsen}`,
835*1c12ee1eSDan Willemsen	}, {
836*1c12ee1eSDan Willemsen		desc: "indirect required field in empty map",
837*1c12ee1eSDan Willemsen		input: &pb2.IndirectRequired{
838*1c12ee1eSDan Willemsen			StrToNested: map[string]*pb2.NestedWithRequired{},
839*1c12ee1eSDan Willemsen		},
840*1c12ee1eSDan Willemsen		want: "{}",
841*1c12ee1eSDan Willemsen	}, {
842*1c12ee1eSDan Willemsen		desc: "indirect required field in map",
843*1c12ee1eSDan Willemsen		input: &pb2.IndirectRequired{
844*1c12ee1eSDan Willemsen			StrToNested: map[string]*pb2.NestedWithRequired{
845*1c12ee1eSDan Willemsen				"fail": &pb2.NestedWithRequired{},
846*1c12ee1eSDan Willemsen			},
847*1c12ee1eSDan Willemsen		},
848*1c12ee1eSDan Willemsen		want: `{
849*1c12ee1eSDan Willemsen  "strToNested": {
850*1c12ee1eSDan Willemsen    "fail": {}
851*1c12ee1eSDan Willemsen  }
852*1c12ee1eSDan Willemsen}`,
853*1c12ee1eSDan Willemsen		wantErr: true,
854*1c12ee1eSDan Willemsen	}, {
855*1c12ee1eSDan Willemsen		desc: "indirect required field in map with AllowPartial",
856*1c12ee1eSDan Willemsen		mo:   protojson.MarshalOptions{AllowPartial: true},
857*1c12ee1eSDan Willemsen		input: &pb2.IndirectRequired{
858*1c12ee1eSDan Willemsen			StrToNested: map[string]*pb2.NestedWithRequired{
859*1c12ee1eSDan Willemsen				"fail": &pb2.NestedWithRequired{},
860*1c12ee1eSDan Willemsen			},
861*1c12ee1eSDan Willemsen		},
862*1c12ee1eSDan Willemsen		want: `{
863*1c12ee1eSDan Willemsen  "strToNested": {
864*1c12ee1eSDan Willemsen    "fail": {}
865*1c12ee1eSDan Willemsen  }
866*1c12ee1eSDan Willemsen}`,
867*1c12ee1eSDan Willemsen	}, {
868*1c12ee1eSDan Willemsen		desc: "indirect required field in oneof",
869*1c12ee1eSDan Willemsen		input: &pb2.IndirectRequired{
870*1c12ee1eSDan Willemsen			Union: &pb2.IndirectRequired_OneofNested{
871*1c12ee1eSDan Willemsen				OneofNested: &pb2.NestedWithRequired{},
872*1c12ee1eSDan Willemsen			},
873*1c12ee1eSDan Willemsen		},
874*1c12ee1eSDan Willemsen		want: `{
875*1c12ee1eSDan Willemsen  "oneofNested": {}
876*1c12ee1eSDan Willemsen}`,
877*1c12ee1eSDan Willemsen		wantErr: true,
878*1c12ee1eSDan Willemsen	}, {
879*1c12ee1eSDan Willemsen		desc: "indirect required field in oneof with AllowPartial",
880*1c12ee1eSDan Willemsen		mo:   protojson.MarshalOptions{AllowPartial: true},
881*1c12ee1eSDan Willemsen		input: &pb2.IndirectRequired{
882*1c12ee1eSDan Willemsen			Union: &pb2.IndirectRequired_OneofNested{
883*1c12ee1eSDan Willemsen				OneofNested: &pb2.NestedWithRequired{},
884*1c12ee1eSDan Willemsen			},
885*1c12ee1eSDan Willemsen		},
886*1c12ee1eSDan Willemsen		want: `{
887*1c12ee1eSDan Willemsen  "oneofNested": {}
888*1c12ee1eSDan Willemsen}`,
889*1c12ee1eSDan Willemsen	}, {
890*1c12ee1eSDan Willemsen		desc: "unknown fields are ignored",
891*1c12ee1eSDan Willemsen		input: func() proto.Message {
892*1c12ee1eSDan Willemsen			m := &pb2.Scalars{
893*1c12ee1eSDan Willemsen				OptString: proto.String("no unknowns"),
894*1c12ee1eSDan Willemsen			}
895*1c12ee1eSDan Willemsen			m.ProtoReflect().SetUnknown(protopack.Message{
896*1c12ee1eSDan Willemsen				protopack.Tag{101, protopack.BytesType}, protopack.String("hello world"),
897*1c12ee1eSDan Willemsen			}.Marshal())
898*1c12ee1eSDan Willemsen			return m
899*1c12ee1eSDan Willemsen		}(),
900*1c12ee1eSDan Willemsen		want: `{
901*1c12ee1eSDan Willemsen  "optString": "no unknowns"
902*1c12ee1eSDan Willemsen}`,
903*1c12ee1eSDan Willemsen	}, {
904*1c12ee1eSDan Willemsen		desc: "json_name",
905*1c12ee1eSDan Willemsen		input: &pb3.JSONNames{
906*1c12ee1eSDan Willemsen			SString: "json_name",
907*1c12ee1eSDan Willemsen		},
908*1c12ee1eSDan Willemsen		want: `{
909*1c12ee1eSDan Willemsen  "foo_bar": "json_name"
910*1c12ee1eSDan Willemsen}`,
911*1c12ee1eSDan Willemsen	}, {
912*1c12ee1eSDan Willemsen		desc: "extensions of non-repeated fields",
913*1c12ee1eSDan Willemsen		input: func() proto.Message {
914*1c12ee1eSDan Willemsen			m := &pb2.Extensions{
915*1c12ee1eSDan Willemsen				OptString: proto.String("non-extension field"),
916*1c12ee1eSDan Willemsen				OptBool:   proto.Bool(true),
917*1c12ee1eSDan Willemsen				OptInt32:  proto.Int32(42),
918*1c12ee1eSDan Willemsen			}
919*1c12ee1eSDan Willemsen			proto.SetExtension(m, pb2.E_OptExtBool, true)
920*1c12ee1eSDan Willemsen			proto.SetExtension(m, pb2.E_OptExtString, "extension field")
921*1c12ee1eSDan Willemsen			proto.SetExtension(m, pb2.E_OptExtEnum, pb2.Enum_TEN)
922*1c12ee1eSDan Willemsen			proto.SetExtension(m, pb2.E_OptExtNested, &pb2.Nested{
923*1c12ee1eSDan Willemsen				OptString: proto.String("nested in an extension"),
924*1c12ee1eSDan Willemsen				OptNested: &pb2.Nested{
925*1c12ee1eSDan Willemsen					OptString: proto.String("another nested in an extension"),
926*1c12ee1eSDan Willemsen				},
927*1c12ee1eSDan Willemsen			})
928*1c12ee1eSDan Willemsen			return m
929*1c12ee1eSDan Willemsen		}(),
930*1c12ee1eSDan Willemsen		want: `{
931*1c12ee1eSDan Willemsen  "optString": "non-extension field",
932*1c12ee1eSDan Willemsen  "optBool": true,
933*1c12ee1eSDan Willemsen  "optInt32": 42,
934*1c12ee1eSDan Willemsen  "[pb2.opt_ext_bool]": true,
935*1c12ee1eSDan Willemsen  "[pb2.opt_ext_enum]": "TEN",
936*1c12ee1eSDan Willemsen  "[pb2.opt_ext_nested]": {
937*1c12ee1eSDan Willemsen    "optString": "nested in an extension",
938*1c12ee1eSDan Willemsen    "optNested": {
939*1c12ee1eSDan Willemsen      "optString": "another nested in an extension"
940*1c12ee1eSDan Willemsen    }
941*1c12ee1eSDan Willemsen  },
942*1c12ee1eSDan Willemsen  "[pb2.opt_ext_string]": "extension field"
943*1c12ee1eSDan Willemsen}`,
944*1c12ee1eSDan Willemsen	}, {
945*1c12ee1eSDan Willemsen		desc: "extensions of repeated fields",
946*1c12ee1eSDan Willemsen		input: func() proto.Message {
947*1c12ee1eSDan Willemsen			m := &pb2.Extensions{}
948*1c12ee1eSDan Willemsen			proto.SetExtension(m, pb2.E_RptExtEnum, []pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
949*1c12ee1eSDan Willemsen			proto.SetExtension(m, pb2.E_RptExtFixed32, []uint32{42, 47})
950*1c12ee1eSDan Willemsen			proto.SetExtension(m, pb2.E_RptExtNested, []*pb2.Nested{
951*1c12ee1eSDan Willemsen				&pb2.Nested{OptString: proto.String("one")},
952*1c12ee1eSDan Willemsen				&pb2.Nested{OptString: proto.String("two")},
953*1c12ee1eSDan Willemsen				&pb2.Nested{OptString: proto.String("three")},
954*1c12ee1eSDan Willemsen			})
955*1c12ee1eSDan Willemsen			return m
956*1c12ee1eSDan Willemsen		}(),
957*1c12ee1eSDan Willemsen		want: `{
958*1c12ee1eSDan Willemsen  "[pb2.rpt_ext_enum]": [
959*1c12ee1eSDan Willemsen    "TEN",
960*1c12ee1eSDan Willemsen    101,
961*1c12ee1eSDan Willemsen    "ONE"
962*1c12ee1eSDan Willemsen  ],
963*1c12ee1eSDan Willemsen  "[pb2.rpt_ext_fixed32]": [
964*1c12ee1eSDan Willemsen    42,
965*1c12ee1eSDan Willemsen    47
966*1c12ee1eSDan Willemsen  ],
967*1c12ee1eSDan Willemsen  "[pb2.rpt_ext_nested]": [
968*1c12ee1eSDan Willemsen    {
969*1c12ee1eSDan Willemsen      "optString": "one"
970*1c12ee1eSDan Willemsen    },
971*1c12ee1eSDan Willemsen    {
972*1c12ee1eSDan Willemsen      "optString": "two"
973*1c12ee1eSDan Willemsen    },
974*1c12ee1eSDan Willemsen    {
975*1c12ee1eSDan Willemsen      "optString": "three"
976*1c12ee1eSDan Willemsen    }
977*1c12ee1eSDan Willemsen  ]
978*1c12ee1eSDan Willemsen}`,
979*1c12ee1eSDan Willemsen	}, {
980*1c12ee1eSDan Willemsen		desc: "extensions of non-repeated fields in another message",
981*1c12ee1eSDan Willemsen		input: func() proto.Message {
982*1c12ee1eSDan Willemsen			m := &pb2.Extensions{}
983*1c12ee1eSDan Willemsen			proto.SetExtension(m, pb2.E_ExtensionsContainer_OptExtBool, true)
984*1c12ee1eSDan Willemsen			proto.SetExtension(m, pb2.E_ExtensionsContainer_OptExtString, "extension field")
985*1c12ee1eSDan Willemsen			proto.SetExtension(m, pb2.E_ExtensionsContainer_OptExtEnum, pb2.Enum_TEN)
986*1c12ee1eSDan Willemsen			proto.SetExtension(m, pb2.E_ExtensionsContainer_OptExtNested, &pb2.Nested{
987*1c12ee1eSDan Willemsen				OptString: proto.String("nested in an extension"),
988*1c12ee1eSDan Willemsen				OptNested: &pb2.Nested{
989*1c12ee1eSDan Willemsen					OptString: proto.String("another nested in an extension"),
990*1c12ee1eSDan Willemsen				},
991*1c12ee1eSDan Willemsen			})
992*1c12ee1eSDan Willemsen			return m
993*1c12ee1eSDan Willemsen		}(),
994*1c12ee1eSDan Willemsen		want: `{
995*1c12ee1eSDan Willemsen  "[pb2.ExtensionsContainer.opt_ext_bool]": true,
996*1c12ee1eSDan Willemsen  "[pb2.ExtensionsContainer.opt_ext_enum]": "TEN",
997*1c12ee1eSDan Willemsen  "[pb2.ExtensionsContainer.opt_ext_nested]": {
998*1c12ee1eSDan Willemsen    "optString": "nested in an extension",
999*1c12ee1eSDan Willemsen    "optNested": {
1000*1c12ee1eSDan Willemsen      "optString": "another nested in an extension"
1001*1c12ee1eSDan Willemsen    }
1002*1c12ee1eSDan Willemsen  },
1003*1c12ee1eSDan Willemsen  "[pb2.ExtensionsContainer.opt_ext_string]": "extension field"
1004*1c12ee1eSDan Willemsen}`,
1005*1c12ee1eSDan Willemsen	}, {
1006*1c12ee1eSDan Willemsen		desc: "extensions of repeated fields in another message",
1007*1c12ee1eSDan Willemsen		input: func() proto.Message {
1008*1c12ee1eSDan Willemsen			m := &pb2.Extensions{
1009*1c12ee1eSDan Willemsen				OptString: proto.String("non-extension field"),
1010*1c12ee1eSDan Willemsen				OptBool:   proto.Bool(true),
1011*1c12ee1eSDan Willemsen				OptInt32:  proto.Int32(42),
1012*1c12ee1eSDan Willemsen			}
1013*1c12ee1eSDan Willemsen			proto.SetExtension(m, pb2.E_ExtensionsContainer_RptExtEnum, []pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
1014*1c12ee1eSDan Willemsen			proto.SetExtension(m, pb2.E_ExtensionsContainer_RptExtString, []string{"hello", "world"})
1015*1c12ee1eSDan Willemsen			proto.SetExtension(m, pb2.E_ExtensionsContainer_RptExtNested, []*pb2.Nested{
1016*1c12ee1eSDan Willemsen				&pb2.Nested{OptString: proto.String("one")},
1017*1c12ee1eSDan Willemsen				&pb2.Nested{OptString: proto.String("two")},
1018*1c12ee1eSDan Willemsen				&pb2.Nested{OptString: proto.String("three")},
1019*1c12ee1eSDan Willemsen			})
1020*1c12ee1eSDan Willemsen			return m
1021*1c12ee1eSDan Willemsen		}(),
1022*1c12ee1eSDan Willemsen		want: `{
1023*1c12ee1eSDan Willemsen  "optString": "non-extension field",
1024*1c12ee1eSDan Willemsen  "optBool": true,
1025*1c12ee1eSDan Willemsen  "optInt32": 42,
1026*1c12ee1eSDan Willemsen  "[pb2.ExtensionsContainer.rpt_ext_enum]": [
1027*1c12ee1eSDan Willemsen    "TEN",
1028*1c12ee1eSDan Willemsen    101,
1029*1c12ee1eSDan Willemsen    "ONE"
1030*1c12ee1eSDan Willemsen  ],
1031*1c12ee1eSDan Willemsen  "[pb2.ExtensionsContainer.rpt_ext_nested]": [
1032*1c12ee1eSDan Willemsen    {
1033*1c12ee1eSDan Willemsen      "optString": "one"
1034*1c12ee1eSDan Willemsen    },
1035*1c12ee1eSDan Willemsen    {
1036*1c12ee1eSDan Willemsen      "optString": "two"
1037*1c12ee1eSDan Willemsen    },
1038*1c12ee1eSDan Willemsen    {
1039*1c12ee1eSDan Willemsen      "optString": "three"
1040*1c12ee1eSDan Willemsen    }
1041*1c12ee1eSDan Willemsen  ],
1042*1c12ee1eSDan Willemsen  "[pb2.ExtensionsContainer.rpt_ext_string]": [
1043*1c12ee1eSDan Willemsen    "hello",
1044*1c12ee1eSDan Willemsen    "world"
1045*1c12ee1eSDan Willemsen  ]
1046*1c12ee1eSDan Willemsen}`,
1047*1c12ee1eSDan Willemsen	}, {
1048*1c12ee1eSDan Willemsen		desc: "MessageSet",
1049*1c12ee1eSDan Willemsen		input: func() proto.Message {
1050*1c12ee1eSDan Willemsen			m := &pb2.MessageSet{}
1051*1c12ee1eSDan Willemsen			proto.SetExtension(m, pb2.E_MessageSetExtension_MessageSetExtension, &pb2.MessageSetExtension{
1052*1c12ee1eSDan Willemsen				OptString: proto.String("a messageset extension"),
1053*1c12ee1eSDan Willemsen			})
1054*1c12ee1eSDan Willemsen			proto.SetExtension(m, pb2.E_MessageSetExtension_NotMessageSetExtension, &pb2.MessageSetExtension{
1055*1c12ee1eSDan Willemsen				OptString: proto.String("not a messageset extension"),
1056*1c12ee1eSDan Willemsen			})
1057*1c12ee1eSDan Willemsen			proto.SetExtension(m, pb2.E_MessageSetExtension_ExtNested, &pb2.Nested{
1058*1c12ee1eSDan Willemsen				OptString: proto.String("just a regular extension"),
1059*1c12ee1eSDan Willemsen			})
1060*1c12ee1eSDan Willemsen			return m
1061*1c12ee1eSDan Willemsen		}(),
1062*1c12ee1eSDan Willemsen		want: `{
1063*1c12ee1eSDan Willemsen  "[pb2.MessageSetExtension.ext_nested]": {
1064*1c12ee1eSDan Willemsen    "optString": "just a regular extension"
1065*1c12ee1eSDan Willemsen  },
1066*1c12ee1eSDan Willemsen  "[pb2.MessageSetExtension]": {
1067*1c12ee1eSDan Willemsen    "optString": "a messageset extension"
1068*1c12ee1eSDan Willemsen  },
1069*1c12ee1eSDan Willemsen  "[pb2.MessageSetExtension.not_message_set_extension]": {
1070*1c12ee1eSDan Willemsen    "optString": "not a messageset extension"
1071*1c12ee1eSDan Willemsen  }
1072*1c12ee1eSDan Willemsen}`,
1073*1c12ee1eSDan Willemsen		skip: !flags.ProtoLegacy,
1074*1c12ee1eSDan Willemsen	}, {
1075*1c12ee1eSDan Willemsen		desc: "not real MessageSet 1",
1076*1c12ee1eSDan Willemsen		input: func() proto.Message {
1077*1c12ee1eSDan Willemsen			m := &pb2.FakeMessageSet{}
1078*1c12ee1eSDan Willemsen			proto.SetExtension(m, pb2.E_FakeMessageSetExtension_MessageSetExtension, &pb2.FakeMessageSetExtension{
1079*1c12ee1eSDan Willemsen				OptString: proto.String("not a messageset extension"),
1080*1c12ee1eSDan Willemsen			})
1081*1c12ee1eSDan Willemsen			return m
1082*1c12ee1eSDan Willemsen		}(),
1083*1c12ee1eSDan Willemsen		want: `{
1084*1c12ee1eSDan Willemsen  "[pb2.FakeMessageSetExtension.message_set_extension]": {
1085*1c12ee1eSDan Willemsen    "optString": "not a messageset extension"
1086*1c12ee1eSDan Willemsen  }
1087*1c12ee1eSDan Willemsen}`,
1088*1c12ee1eSDan Willemsen		skip: !flags.ProtoLegacy,
1089*1c12ee1eSDan Willemsen	}, {
1090*1c12ee1eSDan Willemsen		desc: "not real MessageSet 2",
1091*1c12ee1eSDan Willemsen		input: func() proto.Message {
1092*1c12ee1eSDan Willemsen			m := &pb2.MessageSet{}
1093*1c12ee1eSDan Willemsen			proto.SetExtension(m, pb2.E_MessageSetExtension, &pb2.FakeMessageSetExtension{
1094*1c12ee1eSDan Willemsen				OptString: proto.String("another not a messageset extension"),
1095*1c12ee1eSDan Willemsen			})
1096*1c12ee1eSDan Willemsen			return m
1097*1c12ee1eSDan Willemsen		}(),
1098*1c12ee1eSDan Willemsen		want: `{
1099*1c12ee1eSDan Willemsen  "[pb2.message_set_extension]": {
1100*1c12ee1eSDan Willemsen    "optString": "another not a messageset extension"
1101*1c12ee1eSDan Willemsen  }
1102*1c12ee1eSDan Willemsen}`,
1103*1c12ee1eSDan Willemsen		skip: !flags.ProtoLegacy,
1104*1c12ee1eSDan Willemsen	}, {
1105*1c12ee1eSDan Willemsen		desc:  "BoolValue empty",
1106*1c12ee1eSDan Willemsen		input: &wrapperspb.BoolValue{},
1107*1c12ee1eSDan Willemsen		want:  `false`,
1108*1c12ee1eSDan Willemsen	}, {
1109*1c12ee1eSDan Willemsen		desc:  "BoolValue",
1110*1c12ee1eSDan Willemsen		input: &wrapperspb.BoolValue{Value: true},
1111*1c12ee1eSDan Willemsen		want:  `true`,
1112*1c12ee1eSDan Willemsen	}, {
1113*1c12ee1eSDan Willemsen		desc:  "Int32Value empty",
1114*1c12ee1eSDan Willemsen		input: &wrapperspb.Int32Value{},
1115*1c12ee1eSDan Willemsen		want:  `0`,
1116*1c12ee1eSDan Willemsen	}, {
1117*1c12ee1eSDan Willemsen		desc:  "Int32Value",
1118*1c12ee1eSDan Willemsen		input: &wrapperspb.Int32Value{Value: 42},
1119*1c12ee1eSDan Willemsen		want:  `42`,
1120*1c12ee1eSDan Willemsen	}, {
1121*1c12ee1eSDan Willemsen		desc:  "Int64Value",
1122*1c12ee1eSDan Willemsen		input: &wrapperspb.Int64Value{Value: 42},
1123*1c12ee1eSDan Willemsen		want:  `"42"`,
1124*1c12ee1eSDan Willemsen	}, {
1125*1c12ee1eSDan Willemsen		desc:  "UInt32Value",
1126*1c12ee1eSDan Willemsen		input: &wrapperspb.UInt32Value{Value: 42},
1127*1c12ee1eSDan Willemsen		want:  `42`,
1128*1c12ee1eSDan Willemsen	}, {
1129*1c12ee1eSDan Willemsen		desc:  "UInt64Value",
1130*1c12ee1eSDan Willemsen		input: &wrapperspb.UInt64Value{Value: 42},
1131*1c12ee1eSDan Willemsen		want:  `"42"`,
1132*1c12ee1eSDan Willemsen	}, {
1133*1c12ee1eSDan Willemsen		desc:  "FloatValue",
1134*1c12ee1eSDan Willemsen		input: &wrapperspb.FloatValue{Value: 1.02},
1135*1c12ee1eSDan Willemsen		want:  `1.02`,
1136*1c12ee1eSDan Willemsen	}, {
1137*1c12ee1eSDan Willemsen		desc:  "FloatValue Infinity",
1138*1c12ee1eSDan Willemsen		input: &wrapperspb.FloatValue{Value: float32(math.Inf(-1))},
1139*1c12ee1eSDan Willemsen		want:  `"-Infinity"`,
1140*1c12ee1eSDan Willemsen	}, {
1141*1c12ee1eSDan Willemsen		desc:  "DoubleValue",
1142*1c12ee1eSDan Willemsen		input: &wrapperspb.DoubleValue{Value: 1.02},
1143*1c12ee1eSDan Willemsen		want:  `1.02`,
1144*1c12ee1eSDan Willemsen	}, {
1145*1c12ee1eSDan Willemsen		desc:  "DoubleValue NaN",
1146*1c12ee1eSDan Willemsen		input: &wrapperspb.DoubleValue{Value: math.NaN()},
1147*1c12ee1eSDan Willemsen		want:  `"NaN"`,
1148*1c12ee1eSDan Willemsen	}, {
1149*1c12ee1eSDan Willemsen		desc:  "StringValue empty",
1150*1c12ee1eSDan Willemsen		input: &wrapperspb.StringValue{},
1151*1c12ee1eSDan Willemsen		want:  `""`,
1152*1c12ee1eSDan Willemsen	}, {
1153*1c12ee1eSDan Willemsen		desc:  "StringValue",
1154*1c12ee1eSDan Willemsen		input: &wrapperspb.StringValue{Value: "谷歌"},
1155*1c12ee1eSDan Willemsen		want:  `"谷歌"`,
1156*1c12ee1eSDan Willemsen	}, {
1157*1c12ee1eSDan Willemsen		desc:    "StringValue with invalid UTF8 error",
1158*1c12ee1eSDan Willemsen		input:   &wrapperspb.StringValue{Value: "abc\xff"},
1159*1c12ee1eSDan Willemsen		wantErr: true,
1160*1c12ee1eSDan Willemsen	}, {
1161*1c12ee1eSDan Willemsen		desc: "StringValue field with invalid UTF8 error",
1162*1c12ee1eSDan Willemsen		input: &pb2.KnownTypes{
1163*1c12ee1eSDan Willemsen			OptString: &wrapperspb.StringValue{Value: "abc\xff"},
1164*1c12ee1eSDan Willemsen		},
1165*1c12ee1eSDan Willemsen		wantErr: true,
1166*1c12ee1eSDan Willemsen	}, {
1167*1c12ee1eSDan Willemsen		desc:  "BytesValue",
1168*1c12ee1eSDan Willemsen		input: &wrapperspb.BytesValue{Value: []byte("hello")},
1169*1c12ee1eSDan Willemsen		want:  `"aGVsbG8="`,
1170*1c12ee1eSDan Willemsen	}, {
1171*1c12ee1eSDan Willemsen		desc:  "Empty",
1172*1c12ee1eSDan Willemsen		input: &emptypb.Empty{},
1173*1c12ee1eSDan Willemsen		want:  `{}`,
1174*1c12ee1eSDan Willemsen	}, {
1175*1c12ee1eSDan Willemsen		desc:  "NullValue field",
1176*1c12ee1eSDan Willemsen		input: &pb2.KnownTypes{OptNull: new(structpb.NullValue)},
1177*1c12ee1eSDan Willemsen		want: `{
1178*1c12ee1eSDan Willemsen  "optNull": null
1179*1c12ee1eSDan Willemsen}`,
1180*1c12ee1eSDan Willemsen	}, {
1181*1c12ee1eSDan Willemsen		desc:    "Value empty",
1182*1c12ee1eSDan Willemsen		input:   &structpb.Value{},
1183*1c12ee1eSDan Willemsen		wantErr: true,
1184*1c12ee1eSDan Willemsen	}, {
1185*1c12ee1eSDan Willemsen		desc: "Value empty field",
1186*1c12ee1eSDan Willemsen		input: &pb2.KnownTypes{
1187*1c12ee1eSDan Willemsen			OptValue: &structpb.Value{},
1188*1c12ee1eSDan Willemsen		},
1189*1c12ee1eSDan Willemsen		wantErr: true,
1190*1c12ee1eSDan Willemsen	}, {
1191*1c12ee1eSDan Willemsen		desc:  "Value contains NullValue",
1192*1c12ee1eSDan Willemsen		input: &structpb.Value{Kind: &structpb.Value_NullValue{}},
1193*1c12ee1eSDan Willemsen		want:  `null`,
1194*1c12ee1eSDan Willemsen	}, {
1195*1c12ee1eSDan Willemsen		desc:  "Value contains BoolValue",
1196*1c12ee1eSDan Willemsen		input: &structpb.Value{Kind: &structpb.Value_BoolValue{}},
1197*1c12ee1eSDan Willemsen		want:  `false`,
1198*1c12ee1eSDan Willemsen	}, {
1199*1c12ee1eSDan Willemsen		desc:  "Value contains NumberValue",
1200*1c12ee1eSDan Willemsen		input: &structpb.Value{Kind: &structpb.Value_NumberValue{1.02}},
1201*1c12ee1eSDan Willemsen		want:  `1.02`,
1202*1c12ee1eSDan Willemsen	}, {
1203*1c12ee1eSDan Willemsen		desc:  "Value contains StringValue",
1204*1c12ee1eSDan Willemsen		input: &structpb.Value{Kind: &structpb.Value_StringValue{"hello"}},
1205*1c12ee1eSDan Willemsen		want:  `"hello"`,
1206*1c12ee1eSDan Willemsen	}, {
1207*1c12ee1eSDan Willemsen		desc:    "Value contains StringValue with invalid UTF8",
1208*1c12ee1eSDan Willemsen		input:   &structpb.Value{Kind: &structpb.Value_StringValue{"\xff"}},
1209*1c12ee1eSDan Willemsen		wantErr: true,
1210*1c12ee1eSDan Willemsen	}, {
1211*1c12ee1eSDan Willemsen		desc: "Value contains Struct",
1212*1c12ee1eSDan Willemsen		input: &structpb.Value{
1213*1c12ee1eSDan Willemsen			Kind: &structpb.Value_StructValue{
1214*1c12ee1eSDan Willemsen				&structpb.Struct{
1215*1c12ee1eSDan Willemsen					Fields: map[string]*structpb.Value{
1216*1c12ee1eSDan Willemsen						"null":   {Kind: &structpb.Value_NullValue{}},
1217*1c12ee1eSDan Willemsen						"number": {Kind: &structpb.Value_NumberValue{}},
1218*1c12ee1eSDan Willemsen						"string": {Kind: &structpb.Value_StringValue{}},
1219*1c12ee1eSDan Willemsen						"struct": {Kind: &structpb.Value_StructValue{}},
1220*1c12ee1eSDan Willemsen						"list":   {Kind: &structpb.Value_ListValue{}},
1221*1c12ee1eSDan Willemsen						"bool":   {Kind: &structpb.Value_BoolValue{}},
1222*1c12ee1eSDan Willemsen					},
1223*1c12ee1eSDan Willemsen				},
1224*1c12ee1eSDan Willemsen			},
1225*1c12ee1eSDan Willemsen		},
1226*1c12ee1eSDan Willemsen		want: `{
1227*1c12ee1eSDan Willemsen  "bool": false,
1228*1c12ee1eSDan Willemsen  "list": [],
1229*1c12ee1eSDan Willemsen  "null": null,
1230*1c12ee1eSDan Willemsen  "number": 0,
1231*1c12ee1eSDan Willemsen  "string": "",
1232*1c12ee1eSDan Willemsen  "struct": {}
1233*1c12ee1eSDan Willemsen}`,
1234*1c12ee1eSDan Willemsen	}, {
1235*1c12ee1eSDan Willemsen		desc: "Value contains ListValue",
1236*1c12ee1eSDan Willemsen		input: &structpb.Value{
1237*1c12ee1eSDan Willemsen			Kind: &structpb.Value_ListValue{
1238*1c12ee1eSDan Willemsen				&structpb.ListValue{
1239*1c12ee1eSDan Willemsen					Values: []*structpb.Value{
1240*1c12ee1eSDan Willemsen						{Kind: &structpb.Value_BoolValue{}},
1241*1c12ee1eSDan Willemsen						{Kind: &structpb.Value_NullValue{}},
1242*1c12ee1eSDan Willemsen						{Kind: &structpb.Value_NumberValue{}},
1243*1c12ee1eSDan Willemsen						{Kind: &structpb.Value_StringValue{}},
1244*1c12ee1eSDan Willemsen						{Kind: &structpb.Value_StructValue{}},
1245*1c12ee1eSDan Willemsen						{Kind: &structpb.Value_ListValue{}},
1246*1c12ee1eSDan Willemsen					},
1247*1c12ee1eSDan Willemsen				},
1248*1c12ee1eSDan Willemsen			},
1249*1c12ee1eSDan Willemsen		},
1250*1c12ee1eSDan Willemsen		want: `[
1251*1c12ee1eSDan Willemsen  false,
1252*1c12ee1eSDan Willemsen  null,
1253*1c12ee1eSDan Willemsen  0,
1254*1c12ee1eSDan Willemsen  "",
1255*1c12ee1eSDan Willemsen  {},
1256*1c12ee1eSDan Willemsen  []
1257*1c12ee1eSDan Willemsen]`,
1258*1c12ee1eSDan Willemsen	}, {
1259*1c12ee1eSDan Willemsen		desc:    "Value with NaN",
1260*1c12ee1eSDan Willemsen		input:   structpb.NewNumberValue(math.NaN()),
1261*1c12ee1eSDan Willemsen		wantErr: true,
1262*1c12ee1eSDan Willemsen	}, {
1263*1c12ee1eSDan Willemsen		desc:    "Value with -Inf",
1264*1c12ee1eSDan Willemsen		input:   structpb.NewNumberValue(math.Inf(-1)),
1265*1c12ee1eSDan Willemsen		wantErr: true,
1266*1c12ee1eSDan Willemsen	}, {
1267*1c12ee1eSDan Willemsen		desc:    "Value with +Inf",
1268*1c12ee1eSDan Willemsen		input:   structpb.NewNumberValue(math.Inf(+1)),
1269*1c12ee1eSDan Willemsen		wantErr: true,
1270*1c12ee1eSDan Willemsen	}, {
1271*1c12ee1eSDan Willemsen		desc:  "Struct with nil map",
1272*1c12ee1eSDan Willemsen		input: &structpb.Struct{},
1273*1c12ee1eSDan Willemsen		want:  `{}`,
1274*1c12ee1eSDan Willemsen	}, {
1275*1c12ee1eSDan Willemsen		desc: "Struct with empty map",
1276*1c12ee1eSDan Willemsen		input: &structpb.Struct{
1277*1c12ee1eSDan Willemsen			Fields: map[string]*structpb.Value{},
1278*1c12ee1eSDan Willemsen		},
1279*1c12ee1eSDan Willemsen		want: `{}`,
1280*1c12ee1eSDan Willemsen	}, {
1281*1c12ee1eSDan Willemsen		desc: "Struct",
1282*1c12ee1eSDan Willemsen		input: &structpb.Struct{
1283*1c12ee1eSDan Willemsen			Fields: map[string]*structpb.Value{
1284*1c12ee1eSDan Willemsen				"bool":   {Kind: &structpb.Value_BoolValue{true}},
1285*1c12ee1eSDan Willemsen				"null":   {Kind: &structpb.Value_NullValue{}},
1286*1c12ee1eSDan Willemsen				"number": {Kind: &structpb.Value_NumberValue{3.1415}},
1287*1c12ee1eSDan Willemsen				"string": {Kind: &structpb.Value_StringValue{"hello"}},
1288*1c12ee1eSDan Willemsen				"struct": {
1289*1c12ee1eSDan Willemsen					Kind: &structpb.Value_StructValue{
1290*1c12ee1eSDan Willemsen						&structpb.Struct{
1291*1c12ee1eSDan Willemsen							Fields: map[string]*structpb.Value{
1292*1c12ee1eSDan Willemsen								"string": {Kind: &structpb.Value_StringValue{"world"}},
1293*1c12ee1eSDan Willemsen							},
1294*1c12ee1eSDan Willemsen						},
1295*1c12ee1eSDan Willemsen					},
1296*1c12ee1eSDan Willemsen				},
1297*1c12ee1eSDan Willemsen				"list": {
1298*1c12ee1eSDan Willemsen					Kind: &structpb.Value_ListValue{
1299*1c12ee1eSDan Willemsen						&structpb.ListValue{
1300*1c12ee1eSDan Willemsen							Values: []*structpb.Value{
1301*1c12ee1eSDan Willemsen								{Kind: &structpb.Value_BoolValue{}},
1302*1c12ee1eSDan Willemsen								{Kind: &structpb.Value_NullValue{}},
1303*1c12ee1eSDan Willemsen								{Kind: &structpb.Value_NumberValue{}},
1304*1c12ee1eSDan Willemsen							},
1305*1c12ee1eSDan Willemsen						},
1306*1c12ee1eSDan Willemsen					},
1307*1c12ee1eSDan Willemsen				},
1308*1c12ee1eSDan Willemsen			},
1309*1c12ee1eSDan Willemsen		},
1310*1c12ee1eSDan Willemsen		want: `{
1311*1c12ee1eSDan Willemsen  "bool": true,
1312*1c12ee1eSDan Willemsen  "list": [
1313*1c12ee1eSDan Willemsen    false,
1314*1c12ee1eSDan Willemsen    null,
1315*1c12ee1eSDan Willemsen    0
1316*1c12ee1eSDan Willemsen  ],
1317*1c12ee1eSDan Willemsen  "null": null,
1318*1c12ee1eSDan Willemsen  "number": 3.1415,
1319*1c12ee1eSDan Willemsen  "string": "hello",
1320*1c12ee1eSDan Willemsen  "struct": {
1321*1c12ee1eSDan Willemsen    "string": "world"
1322*1c12ee1eSDan Willemsen  }
1323*1c12ee1eSDan Willemsen}`,
1324*1c12ee1eSDan Willemsen	}, {
1325*1c12ee1eSDan Willemsen		desc: "Struct message with invalid UTF8 string",
1326*1c12ee1eSDan Willemsen		input: &structpb.Struct{
1327*1c12ee1eSDan Willemsen			Fields: map[string]*structpb.Value{
1328*1c12ee1eSDan Willemsen				"string": {Kind: &structpb.Value_StringValue{"\xff"}},
1329*1c12ee1eSDan Willemsen			},
1330*1c12ee1eSDan Willemsen		},
1331*1c12ee1eSDan Willemsen		wantErr: true,
1332*1c12ee1eSDan Willemsen	}, {
1333*1c12ee1eSDan Willemsen		desc:  "ListValue with nil values",
1334*1c12ee1eSDan Willemsen		input: &structpb.ListValue{},
1335*1c12ee1eSDan Willemsen		want:  `[]`,
1336*1c12ee1eSDan Willemsen	}, {
1337*1c12ee1eSDan Willemsen		desc: "ListValue with empty values",
1338*1c12ee1eSDan Willemsen		input: &structpb.ListValue{
1339*1c12ee1eSDan Willemsen			Values: []*structpb.Value{},
1340*1c12ee1eSDan Willemsen		},
1341*1c12ee1eSDan Willemsen		want: `[]`,
1342*1c12ee1eSDan Willemsen	}, {
1343*1c12ee1eSDan Willemsen		desc: "ListValue",
1344*1c12ee1eSDan Willemsen		input: &structpb.ListValue{
1345*1c12ee1eSDan Willemsen			Values: []*structpb.Value{
1346*1c12ee1eSDan Willemsen				{Kind: &structpb.Value_BoolValue{true}},
1347*1c12ee1eSDan Willemsen				{Kind: &structpb.Value_NullValue{}},
1348*1c12ee1eSDan Willemsen				{Kind: &structpb.Value_NumberValue{3.1415}},
1349*1c12ee1eSDan Willemsen				{Kind: &structpb.Value_StringValue{"hello"}},
1350*1c12ee1eSDan Willemsen				{
1351*1c12ee1eSDan Willemsen					Kind: &structpb.Value_ListValue{
1352*1c12ee1eSDan Willemsen						&structpb.ListValue{
1353*1c12ee1eSDan Willemsen							Values: []*structpb.Value{
1354*1c12ee1eSDan Willemsen								{Kind: &structpb.Value_BoolValue{}},
1355*1c12ee1eSDan Willemsen								{Kind: &structpb.Value_NullValue{}},
1356*1c12ee1eSDan Willemsen								{Kind: &structpb.Value_NumberValue{}},
1357*1c12ee1eSDan Willemsen							},
1358*1c12ee1eSDan Willemsen						},
1359*1c12ee1eSDan Willemsen					},
1360*1c12ee1eSDan Willemsen				},
1361*1c12ee1eSDan Willemsen				{
1362*1c12ee1eSDan Willemsen					Kind: &structpb.Value_StructValue{
1363*1c12ee1eSDan Willemsen						&structpb.Struct{
1364*1c12ee1eSDan Willemsen							Fields: map[string]*structpb.Value{
1365*1c12ee1eSDan Willemsen								"string": {Kind: &structpb.Value_StringValue{"world"}},
1366*1c12ee1eSDan Willemsen							},
1367*1c12ee1eSDan Willemsen						},
1368*1c12ee1eSDan Willemsen					},
1369*1c12ee1eSDan Willemsen				},
1370*1c12ee1eSDan Willemsen			},
1371*1c12ee1eSDan Willemsen		},
1372*1c12ee1eSDan Willemsen		want: `[
1373*1c12ee1eSDan Willemsen  true,
1374*1c12ee1eSDan Willemsen  null,
1375*1c12ee1eSDan Willemsen  3.1415,
1376*1c12ee1eSDan Willemsen  "hello",
1377*1c12ee1eSDan Willemsen  [
1378*1c12ee1eSDan Willemsen    false,
1379*1c12ee1eSDan Willemsen    null,
1380*1c12ee1eSDan Willemsen    0
1381*1c12ee1eSDan Willemsen  ],
1382*1c12ee1eSDan Willemsen  {
1383*1c12ee1eSDan Willemsen    "string": "world"
1384*1c12ee1eSDan Willemsen  }
1385*1c12ee1eSDan Willemsen]`,
1386*1c12ee1eSDan Willemsen	}, {
1387*1c12ee1eSDan Willemsen		desc: "ListValue with invalid UTF8 string",
1388*1c12ee1eSDan Willemsen		input: &structpb.ListValue{
1389*1c12ee1eSDan Willemsen			Values: []*structpb.Value{
1390*1c12ee1eSDan Willemsen				{Kind: &structpb.Value_StringValue{"\xff"}},
1391*1c12ee1eSDan Willemsen			},
1392*1c12ee1eSDan Willemsen		},
1393*1c12ee1eSDan Willemsen		wantErr: true,
1394*1c12ee1eSDan Willemsen	}, {
1395*1c12ee1eSDan Willemsen		desc:  "Duration empty",
1396*1c12ee1eSDan Willemsen		input: &durationpb.Duration{},
1397*1c12ee1eSDan Willemsen		want:  `"0s"`,
1398*1c12ee1eSDan Willemsen	}, {
1399*1c12ee1eSDan Willemsen		desc:  "Duration with secs",
1400*1c12ee1eSDan Willemsen		input: &durationpb.Duration{Seconds: 3},
1401*1c12ee1eSDan Willemsen		want:  `"3s"`,
1402*1c12ee1eSDan Willemsen	}, {
1403*1c12ee1eSDan Willemsen		desc:  "Duration with -secs",
1404*1c12ee1eSDan Willemsen		input: &durationpb.Duration{Seconds: -3},
1405*1c12ee1eSDan Willemsen		want:  `"-3s"`,
1406*1c12ee1eSDan Willemsen	}, {
1407*1c12ee1eSDan Willemsen		desc:  "Duration with nanos",
1408*1c12ee1eSDan Willemsen		input: &durationpb.Duration{Nanos: 1e6},
1409*1c12ee1eSDan Willemsen		want:  `"0.001s"`,
1410*1c12ee1eSDan Willemsen	}, {
1411*1c12ee1eSDan Willemsen		desc:  "Duration with -nanos",
1412*1c12ee1eSDan Willemsen		input: &durationpb.Duration{Nanos: -1e6},
1413*1c12ee1eSDan Willemsen		want:  `"-0.001s"`,
1414*1c12ee1eSDan Willemsen	}, {
1415*1c12ee1eSDan Willemsen		desc:  "Duration with large secs",
1416*1c12ee1eSDan Willemsen		input: &durationpb.Duration{Seconds: 1e10, Nanos: 1},
1417*1c12ee1eSDan Willemsen		want:  `"10000000000.000000001s"`,
1418*1c12ee1eSDan Willemsen	}, {
1419*1c12ee1eSDan Willemsen		desc:  "Duration with 6-digit nanos",
1420*1c12ee1eSDan Willemsen		input: &durationpb.Duration{Nanos: 1e4},
1421*1c12ee1eSDan Willemsen		want:  `"0.000010s"`,
1422*1c12ee1eSDan Willemsen	}, {
1423*1c12ee1eSDan Willemsen		desc:  "Duration with 3-digit nanos",
1424*1c12ee1eSDan Willemsen		input: &durationpb.Duration{Nanos: 1e6},
1425*1c12ee1eSDan Willemsen		want:  `"0.001s"`,
1426*1c12ee1eSDan Willemsen	}, {
1427*1c12ee1eSDan Willemsen		desc:  "Duration with -secs -nanos",
1428*1c12ee1eSDan Willemsen		input: &durationpb.Duration{Seconds: -123, Nanos: -450},
1429*1c12ee1eSDan Willemsen		want:  `"-123.000000450s"`,
1430*1c12ee1eSDan Willemsen	}, {
1431*1c12ee1eSDan Willemsen		desc:  "Duration max value",
1432*1c12ee1eSDan Willemsen		input: &durationpb.Duration{Seconds: 315576000000, Nanos: 999999999},
1433*1c12ee1eSDan Willemsen		want:  `"315576000000.999999999s"`,
1434*1c12ee1eSDan Willemsen	}, {
1435*1c12ee1eSDan Willemsen		desc:  "Duration min value",
1436*1c12ee1eSDan Willemsen		input: &durationpb.Duration{Seconds: -315576000000, Nanos: -999999999},
1437*1c12ee1eSDan Willemsen		want:  `"-315576000000.999999999s"`,
1438*1c12ee1eSDan Willemsen	}, {
1439*1c12ee1eSDan Willemsen		desc:    "Duration with +secs -nanos",
1440*1c12ee1eSDan Willemsen		input:   &durationpb.Duration{Seconds: 1, Nanos: -1},
1441*1c12ee1eSDan Willemsen		wantErr: true,
1442*1c12ee1eSDan Willemsen	}, {
1443*1c12ee1eSDan Willemsen		desc:    "Duration with -secs +nanos",
1444*1c12ee1eSDan Willemsen		input:   &durationpb.Duration{Seconds: -1, Nanos: 1},
1445*1c12ee1eSDan Willemsen		wantErr: true,
1446*1c12ee1eSDan Willemsen	}, {
1447*1c12ee1eSDan Willemsen		desc:    "Duration with +secs out of range",
1448*1c12ee1eSDan Willemsen		input:   &durationpb.Duration{Seconds: 315576000001},
1449*1c12ee1eSDan Willemsen		wantErr: true,
1450*1c12ee1eSDan Willemsen	}, {
1451*1c12ee1eSDan Willemsen		desc:    "Duration with -secs out of range",
1452*1c12ee1eSDan Willemsen		input:   &durationpb.Duration{Seconds: -315576000001},
1453*1c12ee1eSDan Willemsen		wantErr: true,
1454*1c12ee1eSDan Willemsen	}, {
1455*1c12ee1eSDan Willemsen		desc:    "Duration with +nanos out of range",
1456*1c12ee1eSDan Willemsen		input:   &durationpb.Duration{Seconds: 0, Nanos: 1e9},
1457*1c12ee1eSDan Willemsen		wantErr: true,
1458*1c12ee1eSDan Willemsen	}, {
1459*1c12ee1eSDan Willemsen		desc:    "Duration with -nanos out of range",
1460*1c12ee1eSDan Willemsen		input:   &durationpb.Duration{Seconds: 0, Nanos: -1e9},
1461*1c12ee1eSDan Willemsen		wantErr: true,
1462*1c12ee1eSDan Willemsen	}, {
1463*1c12ee1eSDan Willemsen		desc:  "Timestamp zero",
1464*1c12ee1eSDan Willemsen		input: &timestamppb.Timestamp{},
1465*1c12ee1eSDan Willemsen		want:  `"1970-01-01T00:00:00Z"`,
1466*1c12ee1eSDan Willemsen	}, {
1467*1c12ee1eSDan Willemsen		desc:  "Timestamp",
1468*1c12ee1eSDan Willemsen		input: &timestamppb.Timestamp{Seconds: 1553036601},
1469*1c12ee1eSDan Willemsen		want:  `"2019-03-19T23:03:21Z"`,
1470*1c12ee1eSDan Willemsen	}, {
1471*1c12ee1eSDan Willemsen		desc:  "Timestamp with nanos",
1472*1c12ee1eSDan Willemsen		input: &timestamppb.Timestamp{Seconds: 1553036601, Nanos: 1},
1473*1c12ee1eSDan Willemsen		want:  `"2019-03-19T23:03:21.000000001Z"`,
1474*1c12ee1eSDan Willemsen	}, {
1475*1c12ee1eSDan Willemsen		desc:  "Timestamp with 6-digit nanos",
1476*1c12ee1eSDan Willemsen		input: &timestamppb.Timestamp{Nanos: 1e3},
1477*1c12ee1eSDan Willemsen		want:  `"1970-01-01T00:00:00.000001Z"`,
1478*1c12ee1eSDan Willemsen	}, {
1479*1c12ee1eSDan Willemsen		desc:  "Timestamp with 3-digit nanos",
1480*1c12ee1eSDan Willemsen		input: &timestamppb.Timestamp{Nanos: 1e7},
1481*1c12ee1eSDan Willemsen		want:  `"1970-01-01T00:00:00.010Z"`,
1482*1c12ee1eSDan Willemsen	}, {
1483*1c12ee1eSDan Willemsen		desc:  "Timestamp max value",
1484*1c12ee1eSDan Willemsen		input: &timestamppb.Timestamp{Seconds: 253402300799, Nanos: 999999999},
1485*1c12ee1eSDan Willemsen		want:  `"9999-12-31T23:59:59.999999999Z"`,
1486*1c12ee1eSDan Willemsen	}, {
1487*1c12ee1eSDan Willemsen		desc:  "Timestamp min value",
1488*1c12ee1eSDan Willemsen		input: &timestamppb.Timestamp{Seconds: -62135596800},
1489*1c12ee1eSDan Willemsen		want:  `"0001-01-01T00:00:00Z"`,
1490*1c12ee1eSDan Willemsen	}, {
1491*1c12ee1eSDan Willemsen		desc:    "Timestamp with +secs out of range",
1492*1c12ee1eSDan Willemsen		input:   &timestamppb.Timestamp{Seconds: 253402300800},
1493*1c12ee1eSDan Willemsen		wantErr: true,
1494*1c12ee1eSDan Willemsen	}, {
1495*1c12ee1eSDan Willemsen		desc:    "Timestamp with -secs out of range",
1496*1c12ee1eSDan Willemsen		input:   &timestamppb.Timestamp{Seconds: -62135596801},
1497*1c12ee1eSDan Willemsen		wantErr: true,
1498*1c12ee1eSDan Willemsen	}, {
1499*1c12ee1eSDan Willemsen		desc:    "Timestamp with -nanos",
1500*1c12ee1eSDan Willemsen		input:   &timestamppb.Timestamp{Nanos: -1},
1501*1c12ee1eSDan Willemsen		wantErr: true,
1502*1c12ee1eSDan Willemsen	}, {
1503*1c12ee1eSDan Willemsen		desc:    "Timestamp with +nanos out of range",
1504*1c12ee1eSDan Willemsen		input:   &timestamppb.Timestamp{Nanos: 1e9},
1505*1c12ee1eSDan Willemsen		wantErr: true,
1506*1c12ee1eSDan Willemsen	}, {
1507*1c12ee1eSDan Willemsen		desc:  "FieldMask empty",
1508*1c12ee1eSDan Willemsen		input: &fieldmaskpb.FieldMask{},
1509*1c12ee1eSDan Willemsen		want:  `""`,
1510*1c12ee1eSDan Willemsen	}, {
1511*1c12ee1eSDan Willemsen		desc: "FieldMask",
1512*1c12ee1eSDan Willemsen		input: &fieldmaskpb.FieldMask{
1513*1c12ee1eSDan Willemsen			Paths: []string{
1514*1c12ee1eSDan Willemsen				"foo",
1515*1c12ee1eSDan Willemsen				"foo_bar",
1516*1c12ee1eSDan Willemsen				"foo.bar_qux",
1517*1c12ee1eSDan Willemsen				"_foo",
1518*1c12ee1eSDan Willemsen			},
1519*1c12ee1eSDan Willemsen		},
1520*1c12ee1eSDan Willemsen		want: `"foo,fooBar,foo.barQux,Foo"`,
1521*1c12ee1eSDan Willemsen	}, {
1522*1c12ee1eSDan Willemsen		desc: "FieldMask empty string path",
1523*1c12ee1eSDan Willemsen		input: &fieldmaskpb.FieldMask{
1524*1c12ee1eSDan Willemsen			Paths: []string{""},
1525*1c12ee1eSDan Willemsen		},
1526*1c12ee1eSDan Willemsen		wantErr: true,
1527*1c12ee1eSDan Willemsen	}, {
1528*1c12ee1eSDan Willemsen		desc: "FieldMask path contains spaces only",
1529*1c12ee1eSDan Willemsen		input: &fieldmaskpb.FieldMask{
1530*1c12ee1eSDan Willemsen			Paths: []string{"  "},
1531*1c12ee1eSDan Willemsen		},
1532*1c12ee1eSDan Willemsen		wantErr: true,
1533*1c12ee1eSDan Willemsen	}, {
1534*1c12ee1eSDan Willemsen		desc: "FieldMask irreversible error 1",
1535*1c12ee1eSDan Willemsen		input: &fieldmaskpb.FieldMask{
1536*1c12ee1eSDan Willemsen			Paths: []string{"foo_"},
1537*1c12ee1eSDan Willemsen		},
1538*1c12ee1eSDan Willemsen		wantErr: true,
1539*1c12ee1eSDan Willemsen	}, {
1540*1c12ee1eSDan Willemsen		desc: "FieldMask irreversible error 2",
1541*1c12ee1eSDan Willemsen		input: &fieldmaskpb.FieldMask{
1542*1c12ee1eSDan Willemsen			Paths: []string{"foo__bar"},
1543*1c12ee1eSDan Willemsen		},
1544*1c12ee1eSDan Willemsen		wantErr: true,
1545*1c12ee1eSDan Willemsen	}, {
1546*1c12ee1eSDan Willemsen		desc: "FieldMask invalid char",
1547*1c12ee1eSDan Willemsen		input: &fieldmaskpb.FieldMask{
1548*1c12ee1eSDan Willemsen			Paths: []string{"foo@bar"},
1549*1c12ee1eSDan Willemsen		},
1550*1c12ee1eSDan Willemsen		wantErr: true,
1551*1c12ee1eSDan Willemsen	}, {
1552*1c12ee1eSDan Willemsen		desc:  "Any empty",
1553*1c12ee1eSDan Willemsen		input: &anypb.Any{},
1554*1c12ee1eSDan Willemsen		want:  `{}`,
1555*1c12ee1eSDan Willemsen	}, {
1556*1c12ee1eSDan Willemsen		desc: "Any with non-custom message",
1557*1c12ee1eSDan Willemsen		input: func() proto.Message {
1558*1c12ee1eSDan Willemsen			m := &pb2.Nested{
1559*1c12ee1eSDan Willemsen				OptString: proto.String("embedded inside Any"),
1560*1c12ee1eSDan Willemsen				OptNested: &pb2.Nested{
1561*1c12ee1eSDan Willemsen					OptString: proto.String("inception"),
1562*1c12ee1eSDan Willemsen				},
1563*1c12ee1eSDan Willemsen			}
1564*1c12ee1eSDan Willemsen			b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
1565*1c12ee1eSDan Willemsen			if err != nil {
1566*1c12ee1eSDan Willemsen				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1567*1c12ee1eSDan Willemsen			}
1568*1c12ee1eSDan Willemsen			return &anypb.Any{
1569*1c12ee1eSDan Willemsen				TypeUrl: "foo/pb2.Nested",
1570*1c12ee1eSDan Willemsen				Value:   b,
1571*1c12ee1eSDan Willemsen			}
1572*1c12ee1eSDan Willemsen		}(),
1573*1c12ee1eSDan Willemsen		want: `{
1574*1c12ee1eSDan Willemsen  "@type": "foo/pb2.Nested",
1575*1c12ee1eSDan Willemsen  "optString": "embedded inside Any",
1576*1c12ee1eSDan Willemsen  "optNested": {
1577*1c12ee1eSDan Willemsen    "optString": "inception"
1578*1c12ee1eSDan Willemsen  }
1579*1c12ee1eSDan Willemsen}`,
1580*1c12ee1eSDan Willemsen	}, {
1581*1c12ee1eSDan Willemsen		desc:  "Any with empty embedded message",
1582*1c12ee1eSDan Willemsen		input: &anypb.Any{TypeUrl: "foo/pb2.Nested"},
1583*1c12ee1eSDan Willemsen		want: `{
1584*1c12ee1eSDan Willemsen  "@type": "foo/pb2.Nested"
1585*1c12ee1eSDan Willemsen}`,
1586*1c12ee1eSDan Willemsen	}, {
1587*1c12ee1eSDan Willemsen		desc:    "Any without registered type",
1588*1c12ee1eSDan Willemsen		mo:      protojson.MarshalOptions{Resolver: new(protoregistry.Types)},
1589*1c12ee1eSDan Willemsen		input:   &anypb.Any{TypeUrl: "foo/pb2.Nested"},
1590*1c12ee1eSDan Willemsen		wantErr: true,
1591*1c12ee1eSDan Willemsen	}, {
1592*1c12ee1eSDan Willemsen		desc: "Any with missing required",
1593*1c12ee1eSDan Willemsen		input: func() proto.Message {
1594*1c12ee1eSDan Willemsen			m := &pb2.PartialRequired{
1595*1c12ee1eSDan Willemsen				OptString: proto.String("embedded inside Any"),
1596*1c12ee1eSDan Willemsen			}
1597*1c12ee1eSDan Willemsen			b, err := proto.MarshalOptions{
1598*1c12ee1eSDan Willemsen				AllowPartial:  true,
1599*1c12ee1eSDan Willemsen				Deterministic: true,
1600*1c12ee1eSDan Willemsen			}.Marshal(m)
1601*1c12ee1eSDan Willemsen			if err != nil {
1602*1c12ee1eSDan Willemsen				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1603*1c12ee1eSDan Willemsen			}
1604*1c12ee1eSDan Willemsen			return &anypb.Any{
1605*1c12ee1eSDan Willemsen				TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
1606*1c12ee1eSDan Willemsen				Value:   b,
1607*1c12ee1eSDan Willemsen			}
1608*1c12ee1eSDan Willemsen		}(),
1609*1c12ee1eSDan Willemsen		want: `{
1610*1c12ee1eSDan Willemsen  "@type": "pb2.PartialRequired",
1611*1c12ee1eSDan Willemsen  "optString": "embedded inside Any"
1612*1c12ee1eSDan Willemsen}`,
1613*1c12ee1eSDan Willemsen	}, {
1614*1c12ee1eSDan Willemsen		desc: "Any with partial required and AllowPartial",
1615*1c12ee1eSDan Willemsen		mo: protojson.MarshalOptions{
1616*1c12ee1eSDan Willemsen			AllowPartial: true,
1617*1c12ee1eSDan Willemsen		},
1618*1c12ee1eSDan Willemsen		input: func() proto.Message {
1619*1c12ee1eSDan Willemsen			m := &pb2.PartialRequired{
1620*1c12ee1eSDan Willemsen				OptString: proto.String("embedded inside Any"),
1621*1c12ee1eSDan Willemsen			}
1622*1c12ee1eSDan Willemsen			b, err := proto.MarshalOptions{
1623*1c12ee1eSDan Willemsen				AllowPartial:  true,
1624*1c12ee1eSDan Willemsen				Deterministic: true,
1625*1c12ee1eSDan Willemsen			}.Marshal(m)
1626*1c12ee1eSDan Willemsen			if err != nil {
1627*1c12ee1eSDan Willemsen				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1628*1c12ee1eSDan Willemsen			}
1629*1c12ee1eSDan Willemsen			return &anypb.Any{
1630*1c12ee1eSDan Willemsen				TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
1631*1c12ee1eSDan Willemsen				Value:   b,
1632*1c12ee1eSDan Willemsen			}
1633*1c12ee1eSDan Willemsen		}(),
1634*1c12ee1eSDan Willemsen		want: `{
1635*1c12ee1eSDan Willemsen  "@type": "pb2.PartialRequired",
1636*1c12ee1eSDan Willemsen  "optString": "embedded inside Any"
1637*1c12ee1eSDan Willemsen}`,
1638*1c12ee1eSDan Willemsen	}, {
1639*1c12ee1eSDan Willemsen		desc: "Any with EmitUnpopulated",
1640*1c12ee1eSDan Willemsen		mo: protojson.MarshalOptions{
1641*1c12ee1eSDan Willemsen			EmitUnpopulated: true,
1642*1c12ee1eSDan Willemsen		},
1643*1c12ee1eSDan Willemsen		input: func() proto.Message {
1644*1c12ee1eSDan Willemsen			return &anypb.Any{
1645*1c12ee1eSDan Willemsen				TypeUrl: string(new(pb3.Scalars).ProtoReflect().Descriptor().FullName()),
1646*1c12ee1eSDan Willemsen			}
1647*1c12ee1eSDan Willemsen		}(),
1648*1c12ee1eSDan Willemsen		want: `{
1649*1c12ee1eSDan Willemsen  "@type": "pb3.Scalars",
1650*1c12ee1eSDan Willemsen  "sBool": false,
1651*1c12ee1eSDan Willemsen  "sInt32": 0,
1652*1c12ee1eSDan Willemsen  "sInt64": "0",
1653*1c12ee1eSDan Willemsen  "sUint32": 0,
1654*1c12ee1eSDan Willemsen  "sUint64": "0",
1655*1c12ee1eSDan Willemsen  "sSint32": 0,
1656*1c12ee1eSDan Willemsen  "sSint64": "0",
1657*1c12ee1eSDan Willemsen  "sFixed32": 0,
1658*1c12ee1eSDan Willemsen  "sFixed64": "0",
1659*1c12ee1eSDan Willemsen  "sSfixed32": 0,
1660*1c12ee1eSDan Willemsen  "sSfixed64": "0",
1661*1c12ee1eSDan Willemsen  "sFloat": 0,
1662*1c12ee1eSDan Willemsen  "sDouble": 0,
1663*1c12ee1eSDan Willemsen  "sBytes": "",
1664*1c12ee1eSDan Willemsen  "sString": ""
1665*1c12ee1eSDan Willemsen}`,
1666*1c12ee1eSDan Willemsen	}, {
1667*1c12ee1eSDan Willemsen		desc: "Any with invalid UTF8",
1668*1c12ee1eSDan Willemsen		input: func() proto.Message {
1669*1c12ee1eSDan Willemsen			m := &pb2.Nested{
1670*1c12ee1eSDan Willemsen				OptString: proto.String("abc\xff"),
1671*1c12ee1eSDan Willemsen			}
1672*1c12ee1eSDan Willemsen			b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
1673*1c12ee1eSDan Willemsen			if err != nil {
1674*1c12ee1eSDan Willemsen				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1675*1c12ee1eSDan Willemsen			}
1676*1c12ee1eSDan Willemsen			return &anypb.Any{
1677*1c12ee1eSDan Willemsen				TypeUrl: "foo/pb2.Nested",
1678*1c12ee1eSDan Willemsen				Value:   b,
1679*1c12ee1eSDan Willemsen			}
1680*1c12ee1eSDan Willemsen		}(),
1681*1c12ee1eSDan Willemsen		wantErr: true,
1682*1c12ee1eSDan Willemsen	}, {
1683*1c12ee1eSDan Willemsen		desc: "Any with invalid value",
1684*1c12ee1eSDan Willemsen		input: &anypb.Any{
1685*1c12ee1eSDan Willemsen			TypeUrl: "foo/pb2.Nested",
1686*1c12ee1eSDan Willemsen			Value:   []byte("\x80"),
1687*1c12ee1eSDan Willemsen		},
1688*1c12ee1eSDan Willemsen		wantErr: true,
1689*1c12ee1eSDan Willemsen	}, {
1690*1c12ee1eSDan Willemsen		desc: "Any with BoolValue",
1691*1c12ee1eSDan Willemsen		input: func() proto.Message {
1692*1c12ee1eSDan Willemsen			m := &wrapperspb.BoolValue{Value: true}
1693*1c12ee1eSDan Willemsen			b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
1694*1c12ee1eSDan Willemsen			if err != nil {
1695*1c12ee1eSDan Willemsen				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1696*1c12ee1eSDan Willemsen			}
1697*1c12ee1eSDan Willemsen			return &anypb.Any{
1698*1c12ee1eSDan Willemsen				TypeUrl: "type.googleapis.com/google.protobuf.BoolValue",
1699*1c12ee1eSDan Willemsen				Value:   b,
1700*1c12ee1eSDan Willemsen			}
1701*1c12ee1eSDan Willemsen		}(),
1702*1c12ee1eSDan Willemsen		want: `{
1703*1c12ee1eSDan Willemsen  "@type": "type.googleapis.com/google.protobuf.BoolValue",
1704*1c12ee1eSDan Willemsen  "value": true
1705*1c12ee1eSDan Willemsen}`,
1706*1c12ee1eSDan Willemsen	}, {
1707*1c12ee1eSDan Willemsen		desc: "Any with Empty",
1708*1c12ee1eSDan Willemsen		input: func() proto.Message {
1709*1c12ee1eSDan Willemsen			m := &emptypb.Empty{}
1710*1c12ee1eSDan Willemsen			b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
1711*1c12ee1eSDan Willemsen			if err != nil {
1712*1c12ee1eSDan Willemsen				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1713*1c12ee1eSDan Willemsen			}
1714*1c12ee1eSDan Willemsen			return &anypb.Any{
1715*1c12ee1eSDan Willemsen				TypeUrl: "type.googleapis.com/google.protobuf.Empty",
1716*1c12ee1eSDan Willemsen				Value:   b,
1717*1c12ee1eSDan Willemsen			}
1718*1c12ee1eSDan Willemsen		}(),
1719*1c12ee1eSDan Willemsen		want: `{
1720*1c12ee1eSDan Willemsen  "@type": "type.googleapis.com/google.protobuf.Empty",
1721*1c12ee1eSDan Willemsen  "value": {}
1722*1c12ee1eSDan Willemsen}`,
1723*1c12ee1eSDan Willemsen	}, {
1724*1c12ee1eSDan Willemsen		desc: "Any with StringValue containing invalid UTF8",
1725*1c12ee1eSDan Willemsen		input: func() proto.Message {
1726*1c12ee1eSDan Willemsen			m := &wrapperspb.StringValue{Value: "abcd"}
1727*1c12ee1eSDan Willemsen			b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
1728*1c12ee1eSDan Willemsen			if err != nil {
1729*1c12ee1eSDan Willemsen				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1730*1c12ee1eSDan Willemsen			}
1731*1c12ee1eSDan Willemsen			return &anypb.Any{
1732*1c12ee1eSDan Willemsen				TypeUrl: "google.protobuf.StringValue",
1733*1c12ee1eSDan Willemsen				Value:   bytes.Replace(b, []byte("abcd"), []byte("abc\xff"), -1),
1734*1c12ee1eSDan Willemsen			}
1735*1c12ee1eSDan Willemsen		}(),
1736*1c12ee1eSDan Willemsen		wantErr: true,
1737*1c12ee1eSDan Willemsen	}, {
1738*1c12ee1eSDan Willemsen		desc: "Any with Int64Value",
1739*1c12ee1eSDan Willemsen		input: func() proto.Message {
1740*1c12ee1eSDan Willemsen			m := &wrapperspb.Int64Value{Value: 42}
1741*1c12ee1eSDan Willemsen			b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
1742*1c12ee1eSDan Willemsen			if err != nil {
1743*1c12ee1eSDan Willemsen				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1744*1c12ee1eSDan Willemsen			}
1745*1c12ee1eSDan Willemsen			return &anypb.Any{
1746*1c12ee1eSDan Willemsen				TypeUrl: "google.protobuf.Int64Value",
1747*1c12ee1eSDan Willemsen				Value:   b,
1748*1c12ee1eSDan Willemsen			}
1749*1c12ee1eSDan Willemsen		}(),
1750*1c12ee1eSDan Willemsen		want: `{
1751*1c12ee1eSDan Willemsen  "@type": "google.protobuf.Int64Value",
1752*1c12ee1eSDan Willemsen  "value": "42"
1753*1c12ee1eSDan Willemsen}`,
1754*1c12ee1eSDan Willemsen	}, {
1755*1c12ee1eSDan Willemsen		desc: "Any with Duration",
1756*1c12ee1eSDan Willemsen		input: func() proto.Message {
1757*1c12ee1eSDan Willemsen			m := &durationpb.Duration{}
1758*1c12ee1eSDan Willemsen			b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
1759*1c12ee1eSDan Willemsen			if err != nil {
1760*1c12ee1eSDan Willemsen				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1761*1c12ee1eSDan Willemsen			}
1762*1c12ee1eSDan Willemsen			return &anypb.Any{
1763*1c12ee1eSDan Willemsen				TypeUrl: "type.googleapis.com/google.protobuf.Duration",
1764*1c12ee1eSDan Willemsen				Value:   b,
1765*1c12ee1eSDan Willemsen			}
1766*1c12ee1eSDan Willemsen		}(),
1767*1c12ee1eSDan Willemsen		want: `{
1768*1c12ee1eSDan Willemsen  "@type": "type.googleapis.com/google.protobuf.Duration",
1769*1c12ee1eSDan Willemsen  "value": "0s"
1770*1c12ee1eSDan Willemsen}`,
1771*1c12ee1eSDan Willemsen	}, {
1772*1c12ee1eSDan Willemsen		desc: "Any with empty Value",
1773*1c12ee1eSDan Willemsen		input: func() proto.Message {
1774*1c12ee1eSDan Willemsen			m := &structpb.Value{}
1775*1c12ee1eSDan Willemsen			b, err := proto.Marshal(m)
1776*1c12ee1eSDan Willemsen			if err != nil {
1777*1c12ee1eSDan Willemsen				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1778*1c12ee1eSDan Willemsen			}
1779*1c12ee1eSDan Willemsen			return &anypb.Any{
1780*1c12ee1eSDan Willemsen				TypeUrl: "type.googleapis.com/google.protobuf.Value",
1781*1c12ee1eSDan Willemsen				Value:   b,
1782*1c12ee1eSDan Willemsen			}
1783*1c12ee1eSDan Willemsen		}(),
1784*1c12ee1eSDan Willemsen		wantErr: true,
1785*1c12ee1eSDan Willemsen	}, {
1786*1c12ee1eSDan Willemsen		desc: "Any with Value of StringValue",
1787*1c12ee1eSDan Willemsen		input: func() proto.Message {
1788*1c12ee1eSDan Willemsen			m := &structpb.Value{Kind: &structpb.Value_StringValue{"abcd"}}
1789*1c12ee1eSDan Willemsen			b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
1790*1c12ee1eSDan Willemsen			if err != nil {
1791*1c12ee1eSDan Willemsen				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1792*1c12ee1eSDan Willemsen			}
1793*1c12ee1eSDan Willemsen			return &anypb.Any{
1794*1c12ee1eSDan Willemsen				TypeUrl: "type.googleapis.com/google.protobuf.Value",
1795*1c12ee1eSDan Willemsen				Value:   bytes.Replace(b, []byte("abcd"), []byte("abc\xff"), -1),
1796*1c12ee1eSDan Willemsen			}
1797*1c12ee1eSDan Willemsen		}(),
1798*1c12ee1eSDan Willemsen		wantErr: true,
1799*1c12ee1eSDan Willemsen	}, {
1800*1c12ee1eSDan Willemsen		desc: "Any with Value of NullValue",
1801*1c12ee1eSDan Willemsen		input: func() proto.Message {
1802*1c12ee1eSDan Willemsen			m := &structpb.Value{Kind: &structpb.Value_NullValue{}}
1803*1c12ee1eSDan Willemsen			b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
1804*1c12ee1eSDan Willemsen			if err != nil {
1805*1c12ee1eSDan Willemsen				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1806*1c12ee1eSDan Willemsen			}
1807*1c12ee1eSDan Willemsen			return &anypb.Any{
1808*1c12ee1eSDan Willemsen				TypeUrl: "type.googleapis.com/google.protobuf.Value",
1809*1c12ee1eSDan Willemsen				Value:   b,
1810*1c12ee1eSDan Willemsen			}
1811*1c12ee1eSDan Willemsen		}(),
1812*1c12ee1eSDan Willemsen		want: `{
1813*1c12ee1eSDan Willemsen  "@type": "type.googleapis.com/google.protobuf.Value",
1814*1c12ee1eSDan Willemsen  "value": null
1815*1c12ee1eSDan Willemsen}`,
1816*1c12ee1eSDan Willemsen	}, {
1817*1c12ee1eSDan Willemsen		desc: "Any with Struct",
1818*1c12ee1eSDan Willemsen		input: func() proto.Message {
1819*1c12ee1eSDan Willemsen			m := &structpb.Struct{
1820*1c12ee1eSDan Willemsen				Fields: map[string]*structpb.Value{
1821*1c12ee1eSDan Willemsen					"bool":   {Kind: &structpb.Value_BoolValue{true}},
1822*1c12ee1eSDan Willemsen					"null":   {Kind: &structpb.Value_NullValue{}},
1823*1c12ee1eSDan Willemsen					"string": {Kind: &structpb.Value_StringValue{"hello"}},
1824*1c12ee1eSDan Willemsen					"struct": {
1825*1c12ee1eSDan Willemsen						Kind: &structpb.Value_StructValue{
1826*1c12ee1eSDan Willemsen							&structpb.Struct{
1827*1c12ee1eSDan Willemsen								Fields: map[string]*structpb.Value{
1828*1c12ee1eSDan Willemsen									"string": {Kind: &structpb.Value_StringValue{"world"}},
1829*1c12ee1eSDan Willemsen								},
1830*1c12ee1eSDan Willemsen							},
1831*1c12ee1eSDan Willemsen						},
1832*1c12ee1eSDan Willemsen					},
1833*1c12ee1eSDan Willemsen				},
1834*1c12ee1eSDan Willemsen			}
1835*1c12ee1eSDan Willemsen			b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
1836*1c12ee1eSDan Willemsen			if err != nil {
1837*1c12ee1eSDan Willemsen				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1838*1c12ee1eSDan Willemsen			}
1839*1c12ee1eSDan Willemsen			return &anypb.Any{
1840*1c12ee1eSDan Willemsen				TypeUrl: "google.protobuf.Struct",
1841*1c12ee1eSDan Willemsen				Value:   b,
1842*1c12ee1eSDan Willemsen			}
1843*1c12ee1eSDan Willemsen		}(),
1844*1c12ee1eSDan Willemsen		want: `{
1845*1c12ee1eSDan Willemsen  "@type": "google.protobuf.Struct",
1846*1c12ee1eSDan Willemsen  "value": {
1847*1c12ee1eSDan Willemsen    "bool": true,
1848*1c12ee1eSDan Willemsen    "null": null,
1849*1c12ee1eSDan Willemsen    "string": "hello",
1850*1c12ee1eSDan Willemsen    "struct": {
1851*1c12ee1eSDan Willemsen      "string": "world"
1852*1c12ee1eSDan Willemsen    }
1853*1c12ee1eSDan Willemsen  }
1854*1c12ee1eSDan Willemsen}`,
1855*1c12ee1eSDan Willemsen	}, {
1856*1c12ee1eSDan Willemsen		desc: "Any with missing type_url",
1857*1c12ee1eSDan Willemsen		input: func() proto.Message {
1858*1c12ee1eSDan Willemsen			m := &wrapperspb.BoolValue{Value: true}
1859*1c12ee1eSDan Willemsen			b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
1860*1c12ee1eSDan Willemsen			if err != nil {
1861*1c12ee1eSDan Willemsen				t.Fatalf("error in binary marshaling message for Any.value: %v", err)
1862*1c12ee1eSDan Willemsen			}
1863*1c12ee1eSDan Willemsen			return &anypb.Any{
1864*1c12ee1eSDan Willemsen				Value: b,
1865*1c12ee1eSDan Willemsen			}
1866*1c12ee1eSDan Willemsen		}(),
1867*1c12ee1eSDan Willemsen		wantErr: true,
1868*1c12ee1eSDan Willemsen	}, {
1869*1c12ee1eSDan Willemsen		desc: "well known types as field values",
1870*1c12ee1eSDan Willemsen		input: &pb2.KnownTypes{
1871*1c12ee1eSDan Willemsen			OptBool:      &wrapperspb.BoolValue{Value: false},
1872*1c12ee1eSDan Willemsen			OptInt32:     &wrapperspb.Int32Value{Value: 42},
1873*1c12ee1eSDan Willemsen			OptInt64:     &wrapperspb.Int64Value{Value: 42},
1874*1c12ee1eSDan Willemsen			OptUint32:    &wrapperspb.UInt32Value{Value: 42},
1875*1c12ee1eSDan Willemsen			OptUint64:    &wrapperspb.UInt64Value{Value: 42},
1876*1c12ee1eSDan Willemsen			OptFloat:     &wrapperspb.FloatValue{Value: 1.23},
1877*1c12ee1eSDan Willemsen			OptDouble:    &wrapperspb.DoubleValue{Value: 3.1415},
1878*1c12ee1eSDan Willemsen			OptString:    &wrapperspb.StringValue{Value: "hello"},
1879*1c12ee1eSDan Willemsen			OptBytes:     &wrapperspb.BytesValue{Value: []byte("hello")},
1880*1c12ee1eSDan Willemsen			OptDuration:  &durationpb.Duration{Seconds: 123},
1881*1c12ee1eSDan Willemsen			OptTimestamp: &timestamppb.Timestamp{Seconds: 1553036601},
1882*1c12ee1eSDan Willemsen			OptStruct: &structpb.Struct{
1883*1c12ee1eSDan Willemsen				Fields: map[string]*structpb.Value{
1884*1c12ee1eSDan Willemsen					"string": {Kind: &structpb.Value_StringValue{"hello"}},
1885*1c12ee1eSDan Willemsen				},
1886*1c12ee1eSDan Willemsen			},
1887*1c12ee1eSDan Willemsen			OptList: &structpb.ListValue{
1888*1c12ee1eSDan Willemsen				Values: []*structpb.Value{
1889*1c12ee1eSDan Willemsen					{Kind: &structpb.Value_NullValue{}},
1890*1c12ee1eSDan Willemsen					{Kind: &structpb.Value_StringValue{}},
1891*1c12ee1eSDan Willemsen					{Kind: &structpb.Value_StructValue{}},
1892*1c12ee1eSDan Willemsen					{Kind: &structpb.Value_ListValue{}},
1893*1c12ee1eSDan Willemsen				},
1894*1c12ee1eSDan Willemsen			},
1895*1c12ee1eSDan Willemsen			OptValue: &structpb.Value{
1896*1c12ee1eSDan Willemsen				Kind: &structpb.Value_StringValue{"world"},
1897*1c12ee1eSDan Willemsen			},
1898*1c12ee1eSDan Willemsen			OptEmpty: &emptypb.Empty{},
1899*1c12ee1eSDan Willemsen			OptAny: &anypb.Any{
1900*1c12ee1eSDan Willemsen				TypeUrl: "google.protobuf.Empty",
1901*1c12ee1eSDan Willemsen			},
1902*1c12ee1eSDan Willemsen			OptFieldmask: &fieldmaskpb.FieldMask{
1903*1c12ee1eSDan Willemsen				Paths: []string{"foo_bar", "bar_foo"},
1904*1c12ee1eSDan Willemsen			},
1905*1c12ee1eSDan Willemsen		},
1906*1c12ee1eSDan Willemsen		want: `{
1907*1c12ee1eSDan Willemsen  "optBool": false,
1908*1c12ee1eSDan Willemsen  "optInt32": 42,
1909*1c12ee1eSDan Willemsen  "optInt64": "42",
1910*1c12ee1eSDan Willemsen  "optUint32": 42,
1911*1c12ee1eSDan Willemsen  "optUint64": "42",
1912*1c12ee1eSDan Willemsen  "optFloat": 1.23,
1913*1c12ee1eSDan Willemsen  "optDouble": 3.1415,
1914*1c12ee1eSDan Willemsen  "optString": "hello",
1915*1c12ee1eSDan Willemsen  "optBytes": "aGVsbG8=",
1916*1c12ee1eSDan Willemsen  "optDuration": "123s",
1917*1c12ee1eSDan Willemsen  "optTimestamp": "2019-03-19T23:03:21Z",
1918*1c12ee1eSDan Willemsen  "optStruct": {
1919*1c12ee1eSDan Willemsen    "string": "hello"
1920*1c12ee1eSDan Willemsen  },
1921*1c12ee1eSDan Willemsen  "optList": [
1922*1c12ee1eSDan Willemsen    null,
1923*1c12ee1eSDan Willemsen    "",
1924*1c12ee1eSDan Willemsen    {},
1925*1c12ee1eSDan Willemsen    []
1926*1c12ee1eSDan Willemsen  ],
1927*1c12ee1eSDan Willemsen  "optValue": "world",
1928*1c12ee1eSDan Willemsen  "optEmpty": {},
1929*1c12ee1eSDan Willemsen  "optAny": {
1930*1c12ee1eSDan Willemsen    "@type": "google.protobuf.Empty",
1931*1c12ee1eSDan Willemsen    "value": {}
1932*1c12ee1eSDan Willemsen  },
1933*1c12ee1eSDan Willemsen  "optFieldmask": "fooBar,barFoo"
1934*1c12ee1eSDan Willemsen}`,
1935*1c12ee1eSDan Willemsen	}, {
1936*1c12ee1eSDan Willemsen		desc:  "EmitUnpopulated: proto2 optional scalars",
1937*1c12ee1eSDan Willemsen		mo:    protojson.MarshalOptions{EmitUnpopulated: true},
1938*1c12ee1eSDan Willemsen		input: &pb2.Scalars{},
1939*1c12ee1eSDan Willemsen		want: `{
1940*1c12ee1eSDan Willemsen  "optBool": null,
1941*1c12ee1eSDan Willemsen  "optInt32": null,
1942*1c12ee1eSDan Willemsen  "optInt64": null,
1943*1c12ee1eSDan Willemsen  "optUint32": null,
1944*1c12ee1eSDan Willemsen  "optUint64": null,
1945*1c12ee1eSDan Willemsen  "optSint32": null,
1946*1c12ee1eSDan Willemsen  "optSint64": null,
1947*1c12ee1eSDan Willemsen  "optFixed32": null,
1948*1c12ee1eSDan Willemsen  "optFixed64": null,
1949*1c12ee1eSDan Willemsen  "optSfixed32": null,
1950*1c12ee1eSDan Willemsen  "optSfixed64": null,
1951*1c12ee1eSDan Willemsen  "optFloat": null,
1952*1c12ee1eSDan Willemsen  "optDouble": null,
1953*1c12ee1eSDan Willemsen  "optBytes": null,
1954*1c12ee1eSDan Willemsen  "optString": null
1955*1c12ee1eSDan Willemsen}`,
1956*1c12ee1eSDan Willemsen	}, {
1957*1c12ee1eSDan Willemsen		desc:  "EmitUnpopulated: proto3 scalars",
1958*1c12ee1eSDan Willemsen		mo:    protojson.MarshalOptions{EmitUnpopulated: true},
1959*1c12ee1eSDan Willemsen		input: &pb3.Scalars{},
1960*1c12ee1eSDan Willemsen		want: `{
1961*1c12ee1eSDan Willemsen  "sBool": false,
1962*1c12ee1eSDan Willemsen  "sInt32": 0,
1963*1c12ee1eSDan Willemsen  "sInt64": "0",
1964*1c12ee1eSDan Willemsen  "sUint32": 0,
1965*1c12ee1eSDan Willemsen  "sUint64": "0",
1966*1c12ee1eSDan Willemsen  "sSint32": 0,
1967*1c12ee1eSDan Willemsen  "sSint64": "0",
1968*1c12ee1eSDan Willemsen  "sFixed32": 0,
1969*1c12ee1eSDan Willemsen  "sFixed64": "0",
1970*1c12ee1eSDan Willemsen  "sSfixed32": 0,
1971*1c12ee1eSDan Willemsen  "sSfixed64": "0",
1972*1c12ee1eSDan Willemsen  "sFloat": 0,
1973*1c12ee1eSDan Willemsen  "sDouble": 0,
1974*1c12ee1eSDan Willemsen  "sBytes": "",
1975*1c12ee1eSDan Willemsen  "sString": ""
1976*1c12ee1eSDan Willemsen}`,
1977*1c12ee1eSDan Willemsen	}, {
1978*1c12ee1eSDan Willemsen		desc:  "EmitUnpopulated: proto2 enum",
1979*1c12ee1eSDan Willemsen		mo:    protojson.MarshalOptions{EmitUnpopulated: true},
1980*1c12ee1eSDan Willemsen		input: &pb2.Enums{},
1981*1c12ee1eSDan Willemsen		want: `{
1982*1c12ee1eSDan Willemsen  "optEnum": null,
1983*1c12ee1eSDan Willemsen  "rptEnum": [],
1984*1c12ee1eSDan Willemsen  "optNestedEnum": null,
1985*1c12ee1eSDan Willemsen  "rptNestedEnum": []
1986*1c12ee1eSDan Willemsen}`,
1987*1c12ee1eSDan Willemsen	}, {
1988*1c12ee1eSDan Willemsen		desc:  "EmitUnpopulated: proto3 enum",
1989*1c12ee1eSDan Willemsen		mo:    protojson.MarshalOptions{EmitUnpopulated: true},
1990*1c12ee1eSDan Willemsen		input: &pb3.Enums{},
1991*1c12ee1eSDan Willemsen		want: `{
1992*1c12ee1eSDan Willemsen  "sEnum": "ZERO",
1993*1c12ee1eSDan Willemsen  "sNestedEnum": "CERO"
1994*1c12ee1eSDan Willemsen}`,
1995*1c12ee1eSDan Willemsen	}, {
1996*1c12ee1eSDan Willemsen		desc:  "EmitUnpopulated: proto2 message and group fields",
1997*1c12ee1eSDan Willemsen		mo:    protojson.MarshalOptions{EmitUnpopulated: true},
1998*1c12ee1eSDan Willemsen		input: &pb2.Nests{},
1999*1c12ee1eSDan Willemsen		want: `{
2000*1c12ee1eSDan Willemsen  "optNested": null,
2001*1c12ee1eSDan Willemsen  "optgroup": null,
2002*1c12ee1eSDan Willemsen  "rptNested": [],
2003*1c12ee1eSDan Willemsen  "rptgroup": []
2004*1c12ee1eSDan Willemsen}`,
2005*1c12ee1eSDan Willemsen	}, {
2006*1c12ee1eSDan Willemsen		desc:  "EmitUnpopulated: proto3 message field",
2007*1c12ee1eSDan Willemsen		mo:    protojson.MarshalOptions{EmitUnpopulated: true},
2008*1c12ee1eSDan Willemsen		input: &pb3.Nests{},
2009*1c12ee1eSDan Willemsen		want: `{
2010*1c12ee1eSDan Willemsen  "sNested": null
2011*1c12ee1eSDan Willemsen}`,
2012*1c12ee1eSDan Willemsen	}, {
2013*1c12ee1eSDan Willemsen		desc: "EmitUnpopulated: proto2 empty message and group fields",
2014*1c12ee1eSDan Willemsen		mo:   protojson.MarshalOptions{EmitUnpopulated: true},
2015*1c12ee1eSDan Willemsen		input: &pb2.Nests{
2016*1c12ee1eSDan Willemsen			OptNested: &pb2.Nested{},
2017*1c12ee1eSDan Willemsen			Optgroup:  &pb2.Nests_OptGroup{},
2018*1c12ee1eSDan Willemsen		},
2019*1c12ee1eSDan Willemsen		want: `{
2020*1c12ee1eSDan Willemsen  "optNested": {
2021*1c12ee1eSDan Willemsen    "optString": null,
2022*1c12ee1eSDan Willemsen    "optNested": null
2023*1c12ee1eSDan Willemsen  },
2024*1c12ee1eSDan Willemsen  "optgroup": {
2025*1c12ee1eSDan Willemsen    "optString": null,
2026*1c12ee1eSDan Willemsen    "optNested": null,
2027*1c12ee1eSDan Willemsen    "optnestedgroup": null
2028*1c12ee1eSDan Willemsen  },
2029*1c12ee1eSDan Willemsen  "rptNested": [],
2030*1c12ee1eSDan Willemsen  "rptgroup": []
2031*1c12ee1eSDan Willemsen}`,
2032*1c12ee1eSDan Willemsen	}, {
2033*1c12ee1eSDan Willemsen		desc: "EmitUnpopulated: proto3 empty message field",
2034*1c12ee1eSDan Willemsen		mo:   protojson.MarshalOptions{EmitUnpopulated: true},
2035*1c12ee1eSDan Willemsen		input: &pb3.Nests{
2036*1c12ee1eSDan Willemsen			SNested: &pb3.Nested{},
2037*1c12ee1eSDan Willemsen		},
2038*1c12ee1eSDan Willemsen		want: `{
2039*1c12ee1eSDan Willemsen  "sNested": {
2040*1c12ee1eSDan Willemsen    "sString": "",
2041*1c12ee1eSDan Willemsen    "sNested": null
2042*1c12ee1eSDan Willemsen  }
2043*1c12ee1eSDan Willemsen}`,
2044*1c12ee1eSDan Willemsen	}, {
2045*1c12ee1eSDan Willemsen		desc: "EmitUnpopulated: proto2 required fields",
2046*1c12ee1eSDan Willemsen		mo: protojson.MarshalOptions{
2047*1c12ee1eSDan Willemsen			AllowPartial:    true,
2048*1c12ee1eSDan Willemsen			EmitUnpopulated: true,
2049*1c12ee1eSDan Willemsen		},
2050*1c12ee1eSDan Willemsen		input: &pb2.Requireds{},
2051*1c12ee1eSDan Willemsen		want: `{
2052*1c12ee1eSDan Willemsen  "reqBool": null,
2053*1c12ee1eSDan Willemsen  "reqSfixed64": null,
2054*1c12ee1eSDan Willemsen  "reqDouble": null,
2055*1c12ee1eSDan Willemsen  "reqString": null,
2056*1c12ee1eSDan Willemsen  "reqEnum": null,
2057*1c12ee1eSDan Willemsen  "reqNested": null
2058*1c12ee1eSDan Willemsen}`,
2059*1c12ee1eSDan Willemsen	}, {
2060*1c12ee1eSDan Willemsen		desc:  "EmitUnpopulated: repeated fields",
2061*1c12ee1eSDan Willemsen		mo:    protojson.MarshalOptions{EmitUnpopulated: true},
2062*1c12ee1eSDan Willemsen		input: &pb2.Repeats{},
2063*1c12ee1eSDan Willemsen		want: `{
2064*1c12ee1eSDan Willemsen  "rptBool": [],
2065*1c12ee1eSDan Willemsen  "rptInt32": [],
2066*1c12ee1eSDan Willemsen  "rptInt64": [],
2067*1c12ee1eSDan Willemsen  "rptUint32": [],
2068*1c12ee1eSDan Willemsen  "rptUint64": [],
2069*1c12ee1eSDan Willemsen  "rptFloat": [],
2070*1c12ee1eSDan Willemsen  "rptDouble": [],
2071*1c12ee1eSDan Willemsen  "rptString": [],
2072*1c12ee1eSDan Willemsen  "rptBytes": []
2073*1c12ee1eSDan Willemsen}`,
2074*1c12ee1eSDan Willemsen	}, {
2075*1c12ee1eSDan Willemsen		desc: "EmitUnpopulated: repeated containing empty message",
2076*1c12ee1eSDan Willemsen		mo:   protojson.MarshalOptions{EmitUnpopulated: true},
2077*1c12ee1eSDan Willemsen		input: &pb2.Nests{
2078*1c12ee1eSDan Willemsen			RptNested: []*pb2.Nested{nil, {}},
2079*1c12ee1eSDan Willemsen		},
2080*1c12ee1eSDan Willemsen		want: `{
2081*1c12ee1eSDan Willemsen  "optNested": null,
2082*1c12ee1eSDan Willemsen  "optgroup": null,
2083*1c12ee1eSDan Willemsen  "rptNested": [
2084*1c12ee1eSDan Willemsen    {
2085*1c12ee1eSDan Willemsen      "optString": null,
2086*1c12ee1eSDan Willemsen      "optNested": null
2087*1c12ee1eSDan Willemsen    },
2088*1c12ee1eSDan Willemsen    {
2089*1c12ee1eSDan Willemsen      "optString": null,
2090*1c12ee1eSDan Willemsen      "optNested": null
2091*1c12ee1eSDan Willemsen    }
2092*1c12ee1eSDan Willemsen  ],
2093*1c12ee1eSDan Willemsen  "rptgroup": []
2094*1c12ee1eSDan Willemsen}`,
2095*1c12ee1eSDan Willemsen	}, {
2096*1c12ee1eSDan Willemsen		desc:  "EmitUnpopulated: map fields",
2097*1c12ee1eSDan Willemsen		mo:    protojson.MarshalOptions{EmitUnpopulated: true},
2098*1c12ee1eSDan Willemsen		input: &pb3.Maps{},
2099*1c12ee1eSDan Willemsen		want: `{
2100*1c12ee1eSDan Willemsen  "int32ToStr": {},
2101*1c12ee1eSDan Willemsen  "boolToUint32": {},
2102*1c12ee1eSDan Willemsen  "uint64ToEnum": {},
2103*1c12ee1eSDan Willemsen  "strToNested": {},
2104*1c12ee1eSDan Willemsen  "strToOneofs": {}
2105*1c12ee1eSDan Willemsen}`,
2106*1c12ee1eSDan Willemsen	}, {
2107*1c12ee1eSDan Willemsen		desc: "EmitUnpopulated: map containing empty message",
2108*1c12ee1eSDan Willemsen		mo:   protojson.MarshalOptions{EmitUnpopulated: true},
2109*1c12ee1eSDan Willemsen		input: &pb3.Maps{
2110*1c12ee1eSDan Willemsen			StrToNested: map[string]*pb3.Nested{
2111*1c12ee1eSDan Willemsen				"nested": &pb3.Nested{},
2112*1c12ee1eSDan Willemsen			},
2113*1c12ee1eSDan Willemsen			StrToOneofs: map[string]*pb3.Oneofs{
2114*1c12ee1eSDan Willemsen				"nested": &pb3.Oneofs{},
2115*1c12ee1eSDan Willemsen			},
2116*1c12ee1eSDan Willemsen		},
2117*1c12ee1eSDan Willemsen		want: `{
2118*1c12ee1eSDan Willemsen  "int32ToStr": {},
2119*1c12ee1eSDan Willemsen  "boolToUint32": {},
2120*1c12ee1eSDan Willemsen  "uint64ToEnum": {},
2121*1c12ee1eSDan Willemsen  "strToNested": {
2122*1c12ee1eSDan Willemsen    "nested": {
2123*1c12ee1eSDan Willemsen      "sString": "",
2124*1c12ee1eSDan Willemsen      "sNested": null
2125*1c12ee1eSDan Willemsen    }
2126*1c12ee1eSDan Willemsen  },
2127*1c12ee1eSDan Willemsen  "strToOneofs": {
2128*1c12ee1eSDan Willemsen    "nested": {}
2129*1c12ee1eSDan Willemsen  }
2130*1c12ee1eSDan Willemsen}`,
2131*1c12ee1eSDan Willemsen	}, {
2132*1c12ee1eSDan Willemsen		desc:  "EmitUnpopulated: oneof fields",
2133*1c12ee1eSDan Willemsen		mo:    protojson.MarshalOptions{EmitUnpopulated: true},
2134*1c12ee1eSDan Willemsen		input: &pb3.Oneofs{},
2135*1c12ee1eSDan Willemsen		want:  `{}`,
2136*1c12ee1eSDan Willemsen	}, {
2137*1c12ee1eSDan Willemsen		desc: "EmitUnpopulated: extensions",
2138*1c12ee1eSDan Willemsen		mo:   protojson.MarshalOptions{EmitUnpopulated: true},
2139*1c12ee1eSDan Willemsen		input: func() proto.Message {
2140*1c12ee1eSDan Willemsen			m := &pb2.Extensions{}
2141*1c12ee1eSDan Willemsen			proto.SetExtension(m, pb2.E_OptExtNested, &pb2.Nested{})
2142*1c12ee1eSDan Willemsen			proto.SetExtension(m, pb2.E_RptExtNested, []*pb2.Nested{
2143*1c12ee1eSDan Willemsen				nil,
2144*1c12ee1eSDan Willemsen				{},
2145*1c12ee1eSDan Willemsen			})
2146*1c12ee1eSDan Willemsen			return m
2147*1c12ee1eSDan Willemsen		}(),
2148*1c12ee1eSDan Willemsen		want: `{
2149*1c12ee1eSDan Willemsen  "optString": null,
2150*1c12ee1eSDan Willemsen  "optBool": null,
2151*1c12ee1eSDan Willemsen  "optInt32": null,
2152*1c12ee1eSDan Willemsen  "[pb2.opt_ext_nested]": {
2153*1c12ee1eSDan Willemsen    "optString": null,
2154*1c12ee1eSDan Willemsen    "optNested": null
2155*1c12ee1eSDan Willemsen  },
2156*1c12ee1eSDan Willemsen  "[pb2.rpt_ext_nested]": [
2157*1c12ee1eSDan Willemsen    {
2158*1c12ee1eSDan Willemsen      "optString": null,
2159*1c12ee1eSDan Willemsen      "optNested": null
2160*1c12ee1eSDan Willemsen    },
2161*1c12ee1eSDan Willemsen    {
2162*1c12ee1eSDan Willemsen      "optString": null,
2163*1c12ee1eSDan Willemsen      "optNested": null
2164*1c12ee1eSDan Willemsen    }
2165*1c12ee1eSDan Willemsen  ]
2166*1c12ee1eSDan Willemsen}`,
2167*1c12ee1eSDan Willemsen	}, {
2168*1c12ee1eSDan Willemsen		desc: "EmitUnpopulated: with populated fields",
2169*1c12ee1eSDan Willemsen		mo:   protojson.MarshalOptions{EmitUnpopulated: true},
2170*1c12ee1eSDan Willemsen		input: &pb2.Scalars{
2171*1c12ee1eSDan Willemsen			OptInt32:    proto.Int32(0xff),
2172*1c12ee1eSDan Willemsen			OptUint32:   proto.Uint32(47),
2173*1c12ee1eSDan Willemsen			OptSint32:   proto.Int32(-1001),
2174*1c12ee1eSDan Willemsen			OptFixed32:  proto.Uint32(32),
2175*1c12ee1eSDan Willemsen			OptSfixed32: proto.Int32(-32),
2176*1c12ee1eSDan Willemsen			OptFloat:    proto.Float32(1.02),
2177*1c12ee1eSDan Willemsen			OptBytes:    []byte("谷歌"),
2178*1c12ee1eSDan Willemsen		},
2179*1c12ee1eSDan Willemsen		want: `{
2180*1c12ee1eSDan Willemsen  "optBool": null,
2181*1c12ee1eSDan Willemsen  "optInt32": 255,
2182*1c12ee1eSDan Willemsen  "optInt64": null,
2183*1c12ee1eSDan Willemsen  "optUint32": 47,
2184*1c12ee1eSDan Willemsen  "optUint64": null,
2185*1c12ee1eSDan Willemsen  "optSint32": -1001,
2186*1c12ee1eSDan Willemsen  "optSint64": null,
2187*1c12ee1eSDan Willemsen  "optFixed32": 32,
2188*1c12ee1eSDan Willemsen  "optFixed64": null,
2189*1c12ee1eSDan Willemsen  "optSfixed32": -32,
2190*1c12ee1eSDan Willemsen  "optSfixed64": null,
2191*1c12ee1eSDan Willemsen  "optFloat": 1.02,
2192*1c12ee1eSDan Willemsen  "optDouble": null,
2193*1c12ee1eSDan Willemsen  "optBytes": "6LC35q2M",
2194*1c12ee1eSDan Willemsen  "optString": null
2195*1c12ee1eSDan Willemsen}`,
2196*1c12ee1eSDan Willemsen	}, {
2197*1c12ee1eSDan Willemsen		desc: "UseEnumNumbers in singular field",
2198*1c12ee1eSDan Willemsen		mo:   protojson.MarshalOptions{UseEnumNumbers: true},
2199*1c12ee1eSDan Willemsen		input: &pb2.Enums{
2200*1c12ee1eSDan Willemsen			OptEnum:       pb2.Enum_ONE.Enum(),
2201*1c12ee1eSDan Willemsen			OptNestedEnum: pb2.Enums_UNO.Enum(),
2202*1c12ee1eSDan Willemsen		},
2203*1c12ee1eSDan Willemsen		want: `{
2204*1c12ee1eSDan Willemsen  "optEnum": 1,
2205*1c12ee1eSDan Willemsen  "optNestedEnum": 1
2206*1c12ee1eSDan Willemsen}`,
2207*1c12ee1eSDan Willemsen	}, {
2208*1c12ee1eSDan Willemsen		desc: "UseEnumNumbers in repeated field",
2209*1c12ee1eSDan Willemsen		mo:   protojson.MarshalOptions{UseEnumNumbers: true},
2210*1c12ee1eSDan Willemsen		input: &pb2.Enums{
2211*1c12ee1eSDan Willemsen			RptEnum:       []pb2.Enum{pb2.Enum_ONE, 2, pb2.Enum_TEN, 42},
2212*1c12ee1eSDan Willemsen			RptNestedEnum: []pb2.Enums_NestedEnum{pb2.Enums_UNO, pb2.Enums_DOS, 47},
2213*1c12ee1eSDan Willemsen		},
2214*1c12ee1eSDan Willemsen		want: `{
2215*1c12ee1eSDan Willemsen  "rptEnum": [
2216*1c12ee1eSDan Willemsen    1,
2217*1c12ee1eSDan Willemsen    2,
2218*1c12ee1eSDan Willemsen    10,
2219*1c12ee1eSDan Willemsen    42
2220*1c12ee1eSDan Willemsen  ],
2221*1c12ee1eSDan Willemsen  "rptNestedEnum": [
2222*1c12ee1eSDan Willemsen    1,
2223*1c12ee1eSDan Willemsen    2,
2224*1c12ee1eSDan Willemsen    47
2225*1c12ee1eSDan Willemsen  ]
2226*1c12ee1eSDan Willemsen}`,
2227*1c12ee1eSDan Willemsen	}, {
2228*1c12ee1eSDan Willemsen		desc: "UseEnumNumbers in map field",
2229*1c12ee1eSDan Willemsen		mo:   protojson.MarshalOptions{UseEnumNumbers: true},
2230*1c12ee1eSDan Willemsen		input: &pb3.Maps{
2231*1c12ee1eSDan Willemsen			Uint64ToEnum: map[uint64]pb3.Enum{
2232*1c12ee1eSDan Willemsen				1:  pb3.Enum_ONE,
2233*1c12ee1eSDan Willemsen				2:  pb3.Enum_TWO,
2234*1c12ee1eSDan Willemsen				10: pb3.Enum_TEN,
2235*1c12ee1eSDan Willemsen				47: 47,
2236*1c12ee1eSDan Willemsen			},
2237*1c12ee1eSDan Willemsen		},
2238*1c12ee1eSDan Willemsen		want: `{
2239*1c12ee1eSDan Willemsen  "uint64ToEnum": {
2240*1c12ee1eSDan Willemsen    "1": 1,
2241*1c12ee1eSDan Willemsen    "2": 2,
2242*1c12ee1eSDan Willemsen    "10": 10,
2243*1c12ee1eSDan Willemsen    "47": 47
2244*1c12ee1eSDan Willemsen  }
2245*1c12ee1eSDan Willemsen}`,
2246*1c12ee1eSDan Willemsen	}, {
2247*1c12ee1eSDan Willemsen		desc: "UseProtoNames",
2248*1c12ee1eSDan Willemsen		mo:   protojson.MarshalOptions{UseProtoNames: true},
2249*1c12ee1eSDan Willemsen		input: &pb2.Nests{
2250*1c12ee1eSDan Willemsen			OptNested: &pb2.Nested{},
2251*1c12ee1eSDan Willemsen			Optgroup: &pb2.Nests_OptGroup{
2252*1c12ee1eSDan Willemsen				OptString: proto.String("inside a group"),
2253*1c12ee1eSDan Willemsen				OptNested: &pb2.Nested{
2254*1c12ee1eSDan Willemsen					OptString: proto.String("nested message inside a group"),
2255*1c12ee1eSDan Willemsen				},
2256*1c12ee1eSDan Willemsen				Optnestedgroup: &pb2.Nests_OptGroup_OptNestedGroup{
2257*1c12ee1eSDan Willemsen					OptFixed32: proto.Uint32(47),
2258*1c12ee1eSDan Willemsen				},
2259*1c12ee1eSDan Willemsen			},
2260*1c12ee1eSDan Willemsen			Rptgroup: []*pb2.Nests_RptGroup{
2261*1c12ee1eSDan Willemsen				{
2262*1c12ee1eSDan Willemsen					RptString: []string{"hello", "world"},
2263*1c12ee1eSDan Willemsen				},
2264*1c12ee1eSDan Willemsen			},
2265*1c12ee1eSDan Willemsen		},
2266*1c12ee1eSDan Willemsen		want: `{
2267*1c12ee1eSDan Willemsen  "opt_nested": {},
2268*1c12ee1eSDan Willemsen  "OptGroup": {
2269*1c12ee1eSDan Willemsen    "opt_string": "inside a group",
2270*1c12ee1eSDan Willemsen    "opt_nested": {
2271*1c12ee1eSDan Willemsen      "opt_string": "nested message inside a group"
2272*1c12ee1eSDan Willemsen    },
2273*1c12ee1eSDan Willemsen    "OptNestedGroup": {
2274*1c12ee1eSDan Willemsen      "opt_fixed32": 47
2275*1c12ee1eSDan Willemsen    }
2276*1c12ee1eSDan Willemsen  },
2277*1c12ee1eSDan Willemsen  "RptGroup": [
2278*1c12ee1eSDan Willemsen    {
2279*1c12ee1eSDan Willemsen      "rpt_string": [
2280*1c12ee1eSDan Willemsen        "hello",
2281*1c12ee1eSDan Willemsen        "world"
2282*1c12ee1eSDan Willemsen      ]
2283*1c12ee1eSDan Willemsen    }
2284*1c12ee1eSDan Willemsen  ]
2285*1c12ee1eSDan Willemsen}`,
2286*1c12ee1eSDan Willemsen	}}
2287*1c12ee1eSDan Willemsen
2288*1c12ee1eSDan Willemsen	for _, tt := range tests {
2289*1c12ee1eSDan Willemsen		tt := tt
2290*1c12ee1eSDan Willemsen		if tt.skip {
2291*1c12ee1eSDan Willemsen			continue
2292*1c12ee1eSDan Willemsen		}
2293*1c12ee1eSDan Willemsen		t.Run(tt.desc, func(t *testing.T) {
2294*1c12ee1eSDan Willemsen			// Use 2-space indentation on all MarshalOptions.
2295*1c12ee1eSDan Willemsen			tt.mo.Indent = "  "
2296*1c12ee1eSDan Willemsen			b, err := tt.mo.Marshal(tt.input)
2297*1c12ee1eSDan Willemsen			if err != nil && !tt.wantErr {
2298*1c12ee1eSDan Willemsen				t.Errorf("Marshal() returned error: %v\n", err)
2299*1c12ee1eSDan Willemsen			}
2300*1c12ee1eSDan Willemsen			if err == nil && tt.wantErr {
2301*1c12ee1eSDan Willemsen				t.Errorf("Marshal() got nil error, want error\n")
2302*1c12ee1eSDan Willemsen			}
2303*1c12ee1eSDan Willemsen			got := string(b)
2304*1c12ee1eSDan Willemsen			if got != tt.want {
2305*1c12ee1eSDan Willemsen				t.Errorf("Marshal()\n<got>\n%v\n<want>\n%v\n", got, tt.want)
2306*1c12ee1eSDan Willemsen				if diff := cmp.Diff(tt.want, got); diff != "" {
2307*1c12ee1eSDan Willemsen					t.Errorf("Marshal() diff -want +got\n%v\n", diff)
2308*1c12ee1eSDan Willemsen				}
2309*1c12ee1eSDan Willemsen			}
2310*1c12ee1eSDan Willemsen		})
2311*1c12ee1eSDan Willemsen	}
2312*1c12ee1eSDan Willemsen}
2313