mirror of
https://github.com/protocolbuffers/protobuf-go.git
synced 2024-12-29 12:17:48 +00:00
cdb7773569
While it is general convention that the receiver being mutated is the first argument, the standard library specifically goes against this convention when it comes to the Unmarshal function. Switch the ordering of the Unmarshal function to match the Go stdlib. Change-Id: I893346680233ef9fec7104415a54a0a7ae353378 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/177258 Reviewed-by: Damien Neil <dneil@google.com>
240 lines
6.2 KiB
Go
240 lines
6.2 KiB
Go
package prototext_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
protoV1 "github.com/golang/protobuf/proto"
|
|
"google.golang.org/protobuf/encoding/prototext"
|
|
"google.golang.org/protobuf/internal/impl"
|
|
pimpl "google.golang.org/protobuf/internal/impl"
|
|
"google.golang.org/protobuf/internal/scalar"
|
|
"google.golang.org/protobuf/proto"
|
|
preg "google.golang.org/protobuf/reflect/protoregistry"
|
|
|
|
"google.golang.org/protobuf/encoding/testprotos/pb2"
|
|
knownpb "google.golang.org/protobuf/types/known"
|
|
)
|
|
|
|
func TestRoundTrip(t *testing.T) {
|
|
tests := []struct {
|
|
desc string
|
|
resolver *preg.Types
|
|
message proto.Message
|
|
}{{
|
|
desc: "well-known type fields set to empty messages",
|
|
message: &pb2.KnownTypes{
|
|
OptBool: &knownpb.BoolValue{},
|
|
OptInt32: &knownpb.Int32Value{},
|
|
OptInt64: &knownpb.Int64Value{},
|
|
OptUint32: &knownpb.UInt32Value{},
|
|
OptUint64: &knownpb.UInt64Value{},
|
|
OptFloat: &knownpb.FloatValue{},
|
|
OptDouble: &knownpb.DoubleValue{},
|
|
OptString: &knownpb.StringValue{},
|
|
OptBytes: &knownpb.BytesValue{},
|
|
OptDuration: &knownpb.Duration{},
|
|
OptTimestamp: &knownpb.Timestamp{},
|
|
OptStruct: &knownpb.Struct{},
|
|
OptList: &knownpb.ListValue{},
|
|
OptValue: &knownpb.Value{},
|
|
OptEmpty: &knownpb.Empty{},
|
|
OptAny: &knownpb.Any{},
|
|
},
|
|
}, {
|
|
desc: "well-known type scalar fields",
|
|
message: &pb2.KnownTypes{
|
|
OptBool: &knownpb.BoolValue{
|
|
Value: true,
|
|
},
|
|
OptInt32: &knownpb.Int32Value{
|
|
Value: -42,
|
|
},
|
|
OptInt64: &knownpb.Int64Value{
|
|
Value: -42,
|
|
},
|
|
OptUint32: &knownpb.UInt32Value{
|
|
Value: 0xff,
|
|
},
|
|
OptUint64: &knownpb.UInt64Value{
|
|
Value: 0xffff,
|
|
},
|
|
OptFloat: &knownpb.FloatValue{
|
|
Value: 1.234,
|
|
},
|
|
OptDouble: &knownpb.DoubleValue{
|
|
Value: 1.23e308,
|
|
},
|
|
OptString: &knownpb.StringValue{
|
|
Value: "谷歌",
|
|
},
|
|
OptBytes: &knownpb.BytesValue{
|
|
Value: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
|
|
},
|
|
},
|
|
}, {
|
|
desc: "well-known type time-related fields",
|
|
message: &pb2.KnownTypes{
|
|
OptDuration: &knownpb.Duration{
|
|
Seconds: -3600,
|
|
Nanos: -123,
|
|
},
|
|
OptTimestamp: &knownpb.Timestamp{
|
|
Seconds: 1257894000,
|
|
Nanos: 123,
|
|
},
|
|
},
|
|
}, {
|
|
desc: "Struct field and different Value types",
|
|
message: &pb2.KnownTypes{
|
|
OptStruct: &knownpb.Struct{
|
|
Fields: map[string]*knownpb.Value{
|
|
"bool": &knownpb.Value{
|
|
Kind: &knownpb.Value_BoolValue{
|
|
BoolValue: true,
|
|
},
|
|
},
|
|
"double": &knownpb.Value{
|
|
Kind: &knownpb.Value_NumberValue{
|
|
NumberValue: 3.1415,
|
|
},
|
|
},
|
|
"null": &knownpb.Value{
|
|
Kind: &knownpb.Value_NullValue{
|
|
NullValue: knownpb.NullValue_NULL_VALUE,
|
|
},
|
|
},
|
|
"string": &knownpb.Value{
|
|
Kind: &knownpb.Value_StringValue{
|
|
StringValue: "string",
|
|
},
|
|
},
|
|
"struct": &knownpb.Value{
|
|
Kind: &knownpb.Value_StructValue{
|
|
StructValue: &knownpb.Struct{
|
|
Fields: map[string]*knownpb.Value{
|
|
"bool": &knownpb.Value{
|
|
Kind: &knownpb.Value_BoolValue{
|
|
BoolValue: false,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
"list": &knownpb.Value{
|
|
Kind: &knownpb.Value_ListValue{
|
|
ListValue: &knownpb.ListValue{
|
|
Values: []*knownpb.Value{
|
|
{
|
|
Kind: &knownpb.Value_BoolValue{
|
|
BoolValue: false,
|
|
},
|
|
},
|
|
{
|
|
Kind: &knownpb.Value_StringValue{
|
|
StringValue: "hello",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}, {
|
|
desc: "Any field without registered type",
|
|
resolver: preg.NewTypes(),
|
|
message: func() proto.Message {
|
|
m := &pb2.Nested{
|
|
OptString: scalar.String("embedded inside Any"),
|
|
OptNested: &pb2.Nested{
|
|
OptString: scalar.String("inception"),
|
|
},
|
|
}
|
|
b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
|
|
if err != nil {
|
|
t.Fatalf("error in binary marshaling message for Any.value: %v", err)
|
|
}
|
|
return &pb2.KnownTypes{
|
|
OptAny: &knownpb.Any{
|
|
TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
|
|
Value: b,
|
|
},
|
|
}
|
|
}(),
|
|
}, {
|
|
desc: "Any field with registered type",
|
|
resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
|
|
message: func() *pb2.KnownTypes {
|
|
m := &pb2.Nested{
|
|
OptString: scalar.String("embedded inside Any"),
|
|
OptNested: &pb2.Nested{
|
|
OptString: scalar.String("inception"),
|
|
},
|
|
}
|
|
b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
|
|
if err != nil {
|
|
t.Fatalf("error in binary marshaling message for Any.value: %v", err)
|
|
}
|
|
return &pb2.KnownTypes{
|
|
OptAny: &knownpb.Any{
|
|
TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
|
|
Value: b,
|
|
},
|
|
}
|
|
}(),
|
|
}, {
|
|
desc: "Any field containing Any message",
|
|
resolver: func() *preg.Types {
|
|
mt1 := impl.Export{}.MessageTypeOf(&pb2.Nested{})
|
|
mt2 := impl.Export{}.MessageTypeOf(&knownpb.Any{})
|
|
return preg.NewTypes(mt1, mt2)
|
|
}(),
|
|
message: func() *pb2.KnownTypes {
|
|
m1 := &pb2.Nested{
|
|
OptString: scalar.String("message inside Any of another Any field"),
|
|
}
|
|
b1, err := proto.MarshalOptions{Deterministic: true}.Marshal(m1)
|
|
if err != nil {
|
|
t.Fatalf("error in binary marshaling message for Any.value: %v", err)
|
|
}
|
|
m2 := &knownpb.Any{
|
|
TypeUrl: "pb2.Nested",
|
|
Value: b1,
|
|
}
|
|
b2, err := proto.MarshalOptions{Deterministic: true}.Marshal(m2)
|
|
if err != nil {
|
|
t.Fatalf("error in binary marshaling message for Any.value: %v", err)
|
|
}
|
|
return &pb2.KnownTypes{
|
|
OptAny: &knownpb.Any{
|
|
TypeUrl: "google.protobuf.Any",
|
|
Value: b2,
|
|
},
|
|
}
|
|
}(),
|
|
}}
|
|
|
|
for _, tt := range tests {
|
|
tt := tt
|
|
t.Run(tt.desc, func(t *testing.T) {
|
|
t.Parallel()
|
|
b, err := prototext.MarshalOptions{Resolver: tt.resolver}.Marshal(tt.message)
|
|
if err != nil {
|
|
t.Errorf("Marshal() returned error: %v\n\n", err)
|
|
}
|
|
|
|
gotMessage := new(pb2.KnownTypes)
|
|
err = prototext.UnmarshalOptions{Resolver: tt.resolver}.Unmarshal(b, gotMessage)
|
|
if err != nil {
|
|
t.Errorf("Unmarshal() returned error: %v\n\n", err)
|
|
}
|
|
|
|
if !protoV1.Equal(gotMessage, tt.message.(protoV1.Message)) {
|
|
t.Errorf("Unmarshal()\n<got>\n%v\n<want>\n%v\n", gotMessage, tt.message)
|
|
}
|
|
})
|
|
}
|
|
}
|