mirror of
https://github.com/protocolbuffers/protobuf-go.git
synced 2025-01-18 13:11:16 +00:00
724 lines
14 KiB
Go
724 lines
14 KiB
Go
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style
|
||
|
// license that can be found in the LICENSE file.
|
||
|
|
||
|
package jsonpb_test
|
||
|
|
||
|
import (
|
||
|
"math"
|
||
|
"strings"
|
||
|
"testing"
|
||
|
|
||
|
"github.com/golang/protobuf/v2/encoding/jsonpb"
|
||
|
"github.com/golang/protobuf/v2/internal/encoding/pack"
|
||
|
"github.com/golang/protobuf/v2/internal/scalar"
|
||
|
"github.com/golang/protobuf/v2/proto"
|
||
|
"github.com/google/go-cmp/cmp"
|
||
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||
|
|
||
|
"github.com/golang/protobuf/v2/encoding/testprotos/pb2"
|
||
|
"github.com/golang/protobuf/v2/encoding/testprotos/pb3"
|
||
|
)
|
||
|
|
||
|
// splitLines is a cmpopts.Option for comparing strings with line breaks.
|
||
|
var splitLines = cmpopts.AcyclicTransformer("SplitLines", func(s string) []string {
|
||
|
return strings.Split(s, "\n")
|
||
|
})
|
||
|
|
||
|
func pb2Enum(i int32) *pb2.Enum {
|
||
|
p := new(pb2.Enum)
|
||
|
*p = pb2.Enum(i)
|
||
|
return p
|
||
|
}
|
||
|
|
||
|
func pb2Enums_NestedEnum(i int32) *pb2.Enums_NestedEnum {
|
||
|
p := new(pb2.Enums_NestedEnum)
|
||
|
*p = pb2.Enums_NestedEnum(i)
|
||
|
return p
|
||
|
}
|
||
|
|
||
|
func TestMarshal(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
desc string
|
||
|
mo jsonpb.MarshalOptions
|
||
|
input proto.Message
|
||
|
want string
|
||
|
}{{
|
||
|
desc: "proto2 optional scalars not set",
|
||
|
input: &pb2.Scalars{},
|
||
|
want: "{}",
|
||
|
}, {
|
||
|
desc: "proto3 scalars not set",
|
||
|
input: &pb3.Scalars{},
|
||
|
want: "{}",
|
||
|
}, {
|
||
|
desc: "proto2 optional scalars set to zero values",
|
||
|
input: &pb2.Scalars{
|
||
|
OptBool: scalar.Bool(false),
|
||
|
OptInt32: scalar.Int32(0),
|
||
|
OptInt64: scalar.Int64(0),
|
||
|
OptUint32: scalar.Uint32(0),
|
||
|
OptUint64: scalar.Uint64(0),
|
||
|
OptSint32: scalar.Int32(0),
|
||
|
OptSint64: scalar.Int64(0),
|
||
|
OptFixed32: scalar.Uint32(0),
|
||
|
OptFixed64: scalar.Uint64(0),
|
||
|
OptSfixed32: scalar.Int32(0),
|
||
|
OptSfixed64: scalar.Int64(0),
|
||
|
OptFloat: scalar.Float32(0),
|
||
|
OptDouble: scalar.Float64(0),
|
||
|
OptBytes: []byte{},
|
||
|
OptString: scalar.String(""),
|
||
|
},
|
||
|
want: `{
|
||
|
"optBool": false,
|
||
|
"optInt32": 0,
|
||
|
"optInt64": "0",
|
||
|
"optUint32": 0,
|
||
|
"optUint64": "0",
|
||
|
"optSint32": 0,
|
||
|
"optSint64": "0",
|
||
|
"optFixed32": 0,
|
||
|
"optFixed64": "0",
|
||
|
"optSfixed32": 0,
|
||
|
"optSfixed64": "0",
|
||
|
"optFloat": 0,
|
||
|
"optDouble": 0,
|
||
|
"optBytes": "",
|
||
|
"optString": ""
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "proto2 optional scalars set to some values",
|
||
|
input: &pb2.Scalars{
|
||
|
OptBool: scalar.Bool(true),
|
||
|
OptInt32: scalar.Int32(0xff),
|
||
|
OptInt64: scalar.Int64(0xdeadbeef),
|
||
|
OptUint32: scalar.Uint32(47),
|
||
|
OptUint64: scalar.Uint64(0xdeadbeef),
|
||
|
OptSint32: scalar.Int32(-1001),
|
||
|
OptSint64: scalar.Int64(-0xffff),
|
||
|
OptFixed64: scalar.Uint64(64),
|
||
|
OptSfixed32: scalar.Int32(-32),
|
||
|
OptFloat: scalar.Float32(1.02),
|
||
|
OptDouble: scalar.Float64(1.234),
|
||
|
OptBytes: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
|
||
|
OptString: scalar.String("谷歌"),
|
||
|
},
|
||
|
want: `{
|
||
|
"optBool": true,
|
||
|
"optInt32": 255,
|
||
|
"optInt64": "3735928559",
|
||
|
"optUint32": 47,
|
||
|
"optUint64": "3735928559",
|
||
|
"optSint32": -1001,
|
||
|
"optSint64": "-65535",
|
||
|
"optFixed64": "64",
|
||
|
"optSfixed32": -32,
|
||
|
"optFloat": 1.02,
|
||
|
"optDouble": 1.234,
|
||
|
"optBytes": "6LC35q2M",
|
||
|
"optString": "谷歌"
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "float nan",
|
||
|
input: &pb3.Scalars{
|
||
|
SFloat: float32(math.NaN()),
|
||
|
},
|
||
|
want: `{
|
||
|
"sFloat": "NaN"
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "float positive infinity",
|
||
|
input: &pb3.Scalars{
|
||
|
SFloat: float32(math.Inf(1)),
|
||
|
},
|
||
|
want: `{
|
||
|
"sFloat": "Infinity"
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "float negative infinity",
|
||
|
input: &pb3.Scalars{
|
||
|
SFloat: float32(math.Inf(-1)),
|
||
|
},
|
||
|
want: `{
|
||
|
"sFloat": "-Infinity"
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "double nan",
|
||
|
input: &pb3.Scalars{
|
||
|
SDouble: math.NaN(),
|
||
|
},
|
||
|
want: `{
|
||
|
"sDouble": "NaN"
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "double positive infinity",
|
||
|
input: &pb3.Scalars{
|
||
|
SDouble: math.Inf(1),
|
||
|
},
|
||
|
want: `{
|
||
|
"sDouble": "Infinity"
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "double negative infinity",
|
||
|
input: &pb3.Scalars{
|
||
|
SDouble: math.Inf(-1),
|
||
|
},
|
||
|
want: `{
|
||
|
"sDouble": "-Infinity"
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "proto2 enum not set",
|
||
|
input: &pb2.Enums{},
|
||
|
want: "{}",
|
||
|
}, {
|
||
|
desc: "proto2 enum set to zero value",
|
||
|
input: &pb2.Enums{
|
||
|
OptEnum: pb2Enum(0),
|
||
|
OptNestedEnum: pb2Enums_NestedEnum(0),
|
||
|
},
|
||
|
want: `{
|
||
|
"optEnum": 0,
|
||
|
"optNestedEnum": 0
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "proto2 enum",
|
||
|
input: &pb2.Enums{
|
||
|
OptEnum: pb2.Enum_ONE.Enum(),
|
||
|
OptNestedEnum: pb2.Enums_UNO.Enum(),
|
||
|
},
|
||
|
want: `{
|
||
|
"optEnum": "ONE",
|
||
|
"optNestedEnum": "UNO"
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "proto2 enum set to numeric values",
|
||
|
input: &pb2.Enums{
|
||
|
OptEnum: pb2Enum(2),
|
||
|
OptNestedEnum: pb2Enums_NestedEnum(2),
|
||
|
},
|
||
|
want: `{
|
||
|
"optEnum": "TWO",
|
||
|
"optNestedEnum": "DOS"
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "proto2 enum set to unnamed numeric values",
|
||
|
input: &pb2.Enums{
|
||
|
OptEnum: pb2Enum(101),
|
||
|
OptNestedEnum: pb2Enums_NestedEnum(-101),
|
||
|
},
|
||
|
want: `{
|
||
|
"optEnum": 101,
|
||
|
"optNestedEnum": -101
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "proto3 enum not set",
|
||
|
input: &pb3.Enums{},
|
||
|
want: "{}",
|
||
|
}, {
|
||
|
desc: "proto3 enum set to zero value",
|
||
|
input: &pb3.Enums{
|
||
|
SEnum: pb3.Enum_ZERO,
|
||
|
SNestedEnum: pb3.Enums_CERO,
|
||
|
},
|
||
|
want: "{}",
|
||
|
}, {
|
||
|
desc: "proto3 enum",
|
||
|
input: &pb3.Enums{
|
||
|
SEnum: pb3.Enum_ONE,
|
||
|
SNestedEnum: pb3.Enums_UNO,
|
||
|
},
|
||
|
want: `{
|
||
|
"sEnum": "ONE",
|
||
|
"sNestedEnum": "UNO"
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "proto3 enum set to numeric values",
|
||
|
input: &pb3.Enums{
|
||
|
SEnum: 2,
|
||
|
SNestedEnum: 2,
|
||
|
},
|
||
|
want: `{
|
||
|
"sEnum": "TWO",
|
||
|
"sNestedEnum": "DOS"
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "proto3 enum set to unnamed numeric values",
|
||
|
input: &pb3.Enums{
|
||
|
SEnum: -47,
|
||
|
SNestedEnum: 47,
|
||
|
},
|
||
|
want: `{
|
||
|
"sEnum": -47,
|
||
|
"sNestedEnum": 47
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "proto2 nested message not set",
|
||
|
input: &pb2.Nests{},
|
||
|
want: "{}",
|
||
|
}, {
|
||
|
desc: "proto2 nested message set to empty",
|
||
|
input: &pb2.Nests{
|
||
|
OptNested: &pb2.Nested{},
|
||
|
Optgroup: &pb2.Nests_OptGroup{},
|
||
|
},
|
||
|
want: `{
|
||
|
"optNested": {},
|
||
|
"optgroup": {}
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "proto2 nested messages",
|
||
|
input: &pb2.Nests{
|
||
|
OptNested: &pb2.Nested{
|
||
|
OptString: scalar.String("nested message"),
|
||
|
OptNested: &pb2.Nested{
|
||
|
OptString: scalar.String("another nested message"),
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
want: `{
|
||
|
"optNested": {
|
||
|
"optString": "nested message",
|
||
|
"optNested": {
|
||
|
"optString": "another nested message"
|
||
|
}
|
||
|
}
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "proto2 groups",
|
||
|
input: &pb2.Nests{
|
||
|
Optgroup: &pb2.Nests_OptGroup{
|
||
|
OptString: scalar.String("inside a group"),
|
||
|
OptNested: &pb2.Nested{
|
||
|
OptString: scalar.String("nested message inside a group"),
|
||
|
},
|
||
|
Optnestedgroup: &pb2.Nests_OptGroup_OptNestedGroup{
|
||
|
OptFixed32: scalar.Uint32(47),
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
want: `{
|
||
|
"optgroup": {
|
||
|
"optString": "inside a group",
|
||
|
"optNested": {
|
||
|
"optString": "nested message inside a group"
|
||
|
},
|
||
|
"optnestedgroup": {
|
||
|
"optFixed32": 47
|
||
|
}
|
||
|
}
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "proto3 nested message not set",
|
||
|
input: &pb3.Nests{},
|
||
|
want: "{}",
|
||
|
}, {
|
||
|
desc: "proto3 nested message set to empty",
|
||
|
input: &pb3.Nests{
|
||
|
SNested: &pb3.Nested{},
|
||
|
},
|
||
|
want: `{
|
||
|
"sNested": {}
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "proto3 nested message",
|
||
|
input: &pb3.Nests{
|
||
|
SNested: &pb3.Nested{
|
||
|
SString: "nested message",
|
||
|
SNested: &pb3.Nested{
|
||
|
SString: "another nested message",
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
want: `{
|
||
|
"sNested": {
|
||
|
"sString": "nested message",
|
||
|
"sNested": {
|
||
|
"sString": "another nested message"
|
||
|
}
|
||
|
}
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "oneof not set",
|
||
|
input: &pb3.Oneofs{},
|
||
|
want: "{}",
|
||
|
}, {
|
||
|
desc: "oneof set to empty string",
|
||
|
input: &pb3.Oneofs{
|
||
|
Union: &pb3.Oneofs_OneofString{},
|
||
|
},
|
||
|
want: `{
|
||
|
"oneofString": ""
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "oneof set to string",
|
||
|
input: &pb3.Oneofs{
|
||
|
Union: &pb3.Oneofs_OneofString{
|
||
|
OneofString: "hello",
|
||
|
},
|
||
|
},
|
||
|
want: `{
|
||
|
"oneofString": "hello"
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "oneof set to enum",
|
||
|
input: &pb3.Oneofs{
|
||
|
Union: &pb3.Oneofs_OneofEnum{
|
||
|
OneofEnum: pb3.Enum_ZERO,
|
||
|
},
|
||
|
},
|
||
|
want: `{
|
||
|
"oneofEnum": "ZERO"
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "oneof set to empty message",
|
||
|
input: &pb3.Oneofs{
|
||
|
Union: &pb3.Oneofs_OneofNested{
|
||
|
OneofNested: &pb3.Nested{},
|
||
|
},
|
||
|
},
|
||
|
want: `{
|
||
|
"oneofNested": {}
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "oneof set to message",
|
||
|
input: &pb3.Oneofs{
|
||
|
Union: &pb3.Oneofs_OneofNested{
|
||
|
OneofNested: &pb3.Nested{
|
||
|
SString: "nested message",
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
want: `{
|
||
|
"oneofNested": {
|
||
|
"sString": "nested message"
|
||
|
}
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "repeated fields not set",
|
||
|
input: &pb2.Repeats{},
|
||
|
want: "{}",
|
||
|
}, {
|
||
|
desc: "repeated fields set to empty slices",
|
||
|
input: &pb2.Repeats{
|
||
|
RptBool: []bool{},
|
||
|
RptInt32: []int32{},
|
||
|
RptInt64: []int64{},
|
||
|
RptUint32: []uint32{},
|
||
|
RptUint64: []uint64{},
|
||
|
RptFloat: []float32{},
|
||
|
RptDouble: []float64{},
|
||
|
RptBytes: [][]byte{},
|
||
|
},
|
||
|
want: "{}",
|
||
|
}, {
|
||
|
desc: "repeated fields set to some values",
|
||
|
input: &pb2.Repeats{
|
||
|
RptBool: []bool{true, false, true, true},
|
||
|
RptInt32: []int32{1, 6, 0, 0},
|
||
|
RptInt64: []int64{-64, 47},
|
||
|
RptUint32: []uint32{0xff, 0xffff},
|
||
|
RptUint64: []uint64{0xdeadbeef},
|
||
|
RptFloat: []float32{float32(math.NaN()), float32(math.Inf(1)), float32(math.Inf(-1)), 1.034},
|
||
|
RptDouble: []float64{math.NaN(), math.Inf(1), math.Inf(-1), 1.23e-308},
|
||
|
RptString: []string{"hello", "世界"},
|
||
|
RptBytes: [][]byte{
|
||
|
[]byte("hello"),
|
||
|
[]byte("\xe4\xb8\x96\xe7\x95\x8c"),
|
||
|
},
|
||
|
},
|
||
|
want: `{
|
||
|
"rptBool": [
|
||
|
true,
|
||
|
false,
|
||
|
true,
|
||
|
true
|
||
|
],
|
||
|
"rptInt32": [
|
||
|
1,
|
||
|
6,
|
||
|
0,
|
||
|
0
|
||
|
],
|
||
|
"rptInt64": [
|
||
|
"-64",
|
||
|
"47"
|
||
|
],
|
||
|
"rptUint32": [
|
||
|
255,
|
||
|
65535
|
||
|
],
|
||
|
"rptUint64": [
|
||
|
"3735928559"
|
||
|
],
|
||
|
"rptFloat": [
|
||
|
"NaN",
|
||
|
"Infinity",
|
||
|
"-Infinity",
|
||
|
1.034
|
||
|
],
|
||
|
"rptDouble": [
|
||
|
"NaN",
|
||
|
"Infinity",
|
||
|
"-Infinity",
|
||
|
1.23e-308
|
||
|
],
|
||
|
"rptString": [
|
||
|
"hello",
|
||
|
"世界"
|
||
|
],
|
||
|
"rptBytes": [
|
||
|
"aGVsbG8=",
|
||
|
"5LiW55WM"
|
||
|
]
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "repeated enums",
|
||
|
input: &pb2.Enums{
|
||
|
RptEnum: []pb2.Enum{pb2.Enum_ONE, 2, pb2.Enum_TEN, 42},
|
||
|
RptNestedEnum: []pb2.Enums_NestedEnum{2, 47, 10},
|
||
|
},
|
||
|
want: `{
|
||
|
"rptEnum": [
|
||
|
"ONE",
|
||
|
"TWO",
|
||
|
"TEN",
|
||
|
42
|
||
|
],
|
||
|
"rptNestedEnum": [
|
||
|
"DOS",
|
||
|
47,
|
||
|
"DIEZ"
|
||
|
]
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "repeated messages set to empty",
|
||
|
input: &pb2.Nests{
|
||
|
RptNested: []*pb2.Nested{},
|
||
|
Rptgroup: []*pb2.Nests_RptGroup{},
|
||
|
},
|
||
|
want: "{}",
|
||
|
}, {
|
||
|
desc: "repeated messages",
|
||
|
input: &pb2.Nests{
|
||
|
RptNested: []*pb2.Nested{
|
||
|
{
|
||
|
OptString: scalar.String("repeat nested one"),
|
||
|
},
|
||
|
{
|
||
|
OptString: scalar.String("repeat nested two"),
|
||
|
OptNested: &pb2.Nested{
|
||
|
OptString: scalar.String("inside repeat nested two"),
|
||
|
},
|
||
|
},
|
||
|
{},
|
||
|
},
|
||
|
},
|
||
|
want: `{
|
||
|
"rptNested": [
|
||
|
{
|
||
|
"optString": "repeat nested one"
|
||
|
},
|
||
|
{
|
||
|
"optString": "repeat nested two",
|
||
|
"optNested": {
|
||
|
"optString": "inside repeat nested two"
|
||
|
}
|
||
|
},
|
||
|
{}
|
||
|
]
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "repeated messages contains nil value",
|
||
|
input: &pb2.Nests{
|
||
|
RptNested: []*pb2.Nested{nil, {}},
|
||
|
},
|
||
|
want: `{
|
||
|
"rptNested": [
|
||
|
{},
|
||
|
{}
|
||
|
]
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "repeated groups",
|
||
|
input: &pb2.Nests{
|
||
|
Rptgroup: []*pb2.Nests_RptGroup{
|
||
|
{
|
||
|
RptString: []string{"hello", "world"},
|
||
|
},
|
||
|
{},
|
||
|
nil,
|
||
|
},
|
||
|
},
|
||
|
want: `{
|
||
|
"rptgroup": [
|
||
|
{
|
||
|
"rptString": [
|
||
|
"hello",
|
||
|
"world"
|
||
|
]
|
||
|
},
|
||
|
{},
|
||
|
{}
|
||
|
]
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "map fields not set",
|
||
|
input: &pb3.Maps{},
|
||
|
want: "{}",
|
||
|
}, {
|
||
|
desc: "map fields set to empty",
|
||
|
input: &pb3.Maps{
|
||
|
Int32ToStr: map[int32]string{},
|
||
|
BoolToUint32: map[bool]uint32{},
|
||
|
Uint64ToEnum: map[uint64]pb3.Enum{},
|
||
|
StrToNested: map[string]*pb3.Nested{},
|
||
|
StrToOneofs: map[string]*pb3.Oneofs{},
|
||
|
},
|
||
|
want: "{}",
|
||
|
}, {
|
||
|
desc: "map fields 1",
|
||
|
input: &pb3.Maps{
|
||
|
BoolToUint32: map[bool]uint32{
|
||
|
true: 42,
|
||
|
false: 101,
|
||
|
},
|
||
|
},
|
||
|
want: `{
|
||
|
"boolToUint32": {
|
||
|
"false": 101,
|
||
|
"true": 42
|
||
|
}
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "map fields 2",
|
||
|
input: &pb3.Maps{
|
||
|
Int32ToStr: map[int32]string{
|
||
|
-101: "-101",
|
||
|
0xff: "0xff",
|
||
|
0: "zero",
|
||
|
},
|
||
|
},
|
||
|
want: `{
|
||
|
"int32ToStr": {
|
||
|
"-101": "-101",
|
||
|
"0": "zero",
|
||
|
"255": "0xff"
|
||
|
}
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "map fields 3",
|
||
|
input: &pb3.Maps{
|
||
|
Uint64ToEnum: map[uint64]pb3.Enum{
|
||
|
1: pb3.Enum_ONE,
|
||
|
2: pb3.Enum_TWO,
|
||
|
10: pb3.Enum_TEN,
|
||
|
47: 47,
|
||
|
},
|
||
|
},
|
||
|
want: `{
|
||
|
"uint64ToEnum": {
|
||
|
"1": "ONE",
|
||
|
"2": "TWO",
|
||
|
"10": "TEN",
|
||
|
"47": 47
|
||
|
}
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "map fields 4",
|
||
|
input: &pb3.Maps{
|
||
|
StrToNested: map[string]*pb3.Nested{
|
||
|
"nested": &pb3.Nested{
|
||
|
SString: "nested in a map",
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
want: `{
|
||
|
"strToNested": {
|
||
|
"nested": {
|
||
|
"sString": "nested in a map"
|
||
|
}
|
||
|
}
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "map fields 5",
|
||
|
input: &pb3.Maps{
|
||
|
StrToOneofs: map[string]*pb3.Oneofs{
|
||
|
"string": &pb3.Oneofs{
|
||
|
Union: &pb3.Oneofs_OneofString{
|
||
|
OneofString: "hello",
|
||
|
},
|
||
|
},
|
||
|
"nested": &pb3.Oneofs{
|
||
|
Union: &pb3.Oneofs_OneofNested{
|
||
|
OneofNested: &pb3.Nested{
|
||
|
SString: "nested oneof in map field value",
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
want: `{
|
||
|
"strToOneofs": {
|
||
|
"nested": {
|
||
|
"oneofNested": {
|
||
|
"sString": "nested oneof in map field value"
|
||
|
}
|
||
|
},
|
||
|
"string": {
|
||
|
"oneofString": "hello"
|
||
|
}
|
||
|
}
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "map field contains nil value",
|
||
|
input: &pb3.Maps{
|
||
|
StrToNested: map[string]*pb3.Nested{
|
||
|
"nil": nil,
|
||
|
},
|
||
|
},
|
||
|
want: `{
|
||
|
"strToNested": {
|
||
|
"nil": {}
|
||
|
}
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "unknown fields are ignored",
|
||
|
input: &pb2.Scalars{
|
||
|
OptString: scalar.String("no unknowns"),
|
||
|
XXX_unrecognized: pack.Message{
|
||
|
pack.Tag{101, pack.BytesType}, pack.String("hello world"),
|
||
|
}.Marshal(),
|
||
|
},
|
||
|
want: `{
|
||
|
"optString": "no unknowns"
|
||
|
}`,
|
||
|
}, {
|
||
|
desc: "json_name",
|
||
|
input: &pb3.JSONNames{
|
||
|
SString: "json_name",
|
||
|
},
|
||
|
want: `{
|
||
|
"foo_bar": "json_name"
|
||
|
}`,
|
||
|
}}
|
||
|
|
||
|
for _, tt := range tests {
|
||
|
tt := tt
|
||
|
t.Run(tt.desc, func(t *testing.T) {
|
||
|
t.Parallel()
|
||
|
b, err := tt.mo.Marshal(tt.input)
|
||
|
if err != nil {
|
||
|
t.Errorf("Marshal() returned error: %v\n", err)
|
||
|
}
|
||
|
got := string(b)
|
||
|
if got != tt.want {
|
||
|
t.Errorf("Marshal()\n<got>\n%v\n<want>\n%v\n", got, tt.want)
|
||
|
if diff := cmp.Diff(tt.want, got, splitLines); diff != "" {
|
||
|
t.Errorf("Marshal() diff -want +got\n%v\n", diff)
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|