mirror of
https://github.com/protocolbuffers/protobuf-go.git
synced 2024-12-28 00:19:55 +00:00
784c482554
Change-Id: I62ec79419354a2c65ac69e4bcc1cc864a6a40a1a Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/407934 Reviewed-by: Lasse Folger <lassefolger@google.com> Reviewed-by: Damien Neil <dneil@google.com>
239 lines
6.2 KiB
Go
239 lines
6.2 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 prototext_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"google.golang.org/protobuf/encoding/prototext"
|
|
"google.golang.org/protobuf/proto"
|
|
"google.golang.org/protobuf/reflect/protoregistry"
|
|
|
|
pb2 "google.golang.org/protobuf/internal/testprotos/textpb2"
|
|
"google.golang.org/protobuf/types/known/anypb"
|
|
"google.golang.org/protobuf/types/known/durationpb"
|
|
"google.golang.org/protobuf/types/known/emptypb"
|
|
"google.golang.org/protobuf/types/known/structpb"
|
|
"google.golang.org/protobuf/types/known/timestamppb"
|
|
"google.golang.org/protobuf/types/known/wrapperspb"
|
|
)
|
|
|
|
func TestRoundTrip(t *testing.T) {
|
|
tests := []struct {
|
|
desc string
|
|
resolver *protoregistry.Types
|
|
message proto.Message
|
|
}{{
|
|
desc: "well-known type fields set to empty messages",
|
|
message: &pb2.KnownTypes{
|
|
OptBool: &wrapperspb.BoolValue{},
|
|
OptInt32: &wrapperspb.Int32Value{},
|
|
OptInt64: &wrapperspb.Int64Value{},
|
|
OptUint32: &wrapperspb.UInt32Value{},
|
|
OptUint64: &wrapperspb.UInt64Value{},
|
|
OptFloat: &wrapperspb.FloatValue{},
|
|
OptDouble: &wrapperspb.DoubleValue{},
|
|
OptString: &wrapperspb.StringValue{},
|
|
OptBytes: &wrapperspb.BytesValue{},
|
|
OptDuration: &durationpb.Duration{},
|
|
OptTimestamp: ×tamppb.Timestamp{},
|
|
OptStruct: &structpb.Struct{},
|
|
OptList: &structpb.ListValue{},
|
|
OptValue: &structpb.Value{},
|
|
OptEmpty: &emptypb.Empty{},
|
|
OptAny: &anypb.Any{},
|
|
},
|
|
}, {
|
|
desc: "well-known type scalar fields",
|
|
message: &pb2.KnownTypes{
|
|
OptBool: &wrapperspb.BoolValue{
|
|
Value: true,
|
|
},
|
|
OptInt32: &wrapperspb.Int32Value{
|
|
Value: -42,
|
|
},
|
|
OptInt64: &wrapperspb.Int64Value{
|
|
Value: -42,
|
|
},
|
|
OptUint32: &wrapperspb.UInt32Value{
|
|
Value: 0xff,
|
|
},
|
|
OptUint64: &wrapperspb.UInt64Value{
|
|
Value: 0xffff,
|
|
},
|
|
OptFloat: &wrapperspb.FloatValue{
|
|
Value: 1.234,
|
|
},
|
|
OptDouble: &wrapperspb.DoubleValue{
|
|
Value: 1.23e308,
|
|
},
|
|
OptString: &wrapperspb.StringValue{
|
|
Value: "谷歌",
|
|
},
|
|
OptBytes: &wrapperspb.BytesValue{
|
|
Value: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
|
|
},
|
|
},
|
|
}, {
|
|
desc: "well-known type time-related fields",
|
|
message: &pb2.KnownTypes{
|
|
OptDuration: &durationpb.Duration{
|
|
Seconds: -3600,
|
|
Nanos: -123,
|
|
},
|
|
OptTimestamp: ×tamppb.Timestamp{
|
|
Seconds: 1257894000,
|
|
Nanos: 123,
|
|
},
|
|
},
|
|
}, {
|
|
desc: "Struct field and different Value types",
|
|
message: &pb2.KnownTypes{
|
|
OptStruct: &structpb.Struct{
|
|
Fields: map[string]*structpb.Value{
|
|
"bool": &structpb.Value{
|
|
Kind: &structpb.Value_BoolValue{
|
|
BoolValue: true,
|
|
},
|
|
},
|
|
"double": &structpb.Value{
|
|
Kind: &structpb.Value_NumberValue{
|
|
NumberValue: 3.1415,
|
|
},
|
|
},
|
|
"null": &structpb.Value{
|
|
Kind: &structpb.Value_NullValue{
|
|
NullValue: structpb.NullValue_NULL_VALUE,
|
|
},
|
|
},
|
|
"string": &structpb.Value{
|
|
Kind: &structpb.Value_StringValue{
|
|
StringValue: "string",
|
|
},
|
|
},
|
|
"struct": &structpb.Value{
|
|
Kind: &structpb.Value_StructValue{
|
|
StructValue: &structpb.Struct{
|
|
Fields: map[string]*structpb.Value{
|
|
"bool": &structpb.Value{
|
|
Kind: &structpb.Value_BoolValue{
|
|
BoolValue: false,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
"list": &structpb.Value{
|
|
Kind: &structpb.Value_ListValue{
|
|
ListValue: &structpb.ListValue{
|
|
Values: []*structpb.Value{
|
|
{
|
|
Kind: &structpb.Value_BoolValue{
|
|
BoolValue: false,
|
|
},
|
|
},
|
|
{
|
|
Kind: &structpb.Value_StringValue{
|
|
StringValue: "hello",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}, {
|
|
desc: "Any field without registered type",
|
|
resolver: new(protoregistry.Types),
|
|
message: func() proto.Message {
|
|
m := &pb2.Nested{
|
|
OptString: proto.String("embedded inside Any"),
|
|
OptNested: &pb2.Nested{
|
|
OptString: proto.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: &anypb.Any{
|
|
TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
|
|
Value: b,
|
|
},
|
|
}
|
|
}(),
|
|
}, {
|
|
desc: "Any field with registered type",
|
|
message: func() *pb2.KnownTypes {
|
|
m := &pb2.Nested{
|
|
OptString: proto.String("embedded inside Any"),
|
|
OptNested: &pb2.Nested{
|
|
OptString: proto.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: &anypb.Any{
|
|
TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
|
|
Value: b,
|
|
},
|
|
}
|
|
}(),
|
|
}, {
|
|
desc: "Any field containing Any message",
|
|
message: func() *pb2.KnownTypes {
|
|
m1 := &pb2.Nested{
|
|
OptString: proto.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 := &anypb.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: &anypb.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 !proto.Equal(gotMessage, tt.message) {
|
|
t.Errorf("Unmarshal()\n<got>\n%v\n<want>\n%v\n", gotMessage, tt.message)
|
|
}
|
|
})
|
|
}
|
|
}
|