blob: 4092976c0d13267642b9726fa068a8743ffed7c3 [file] [log] [blame]
package textpb_test
import (
"testing"
protoV1 "github.com/golang/protobuf/proto"
"github.com/golang/protobuf/v2/encoding/textpb"
"github.com/golang/protobuf/v2/encoding/textpb/testprotos/pb2"
"github.com/golang/protobuf/v2/proto"
// The legacy package must be imported prior to use of any legacy messages.
// TODO: Remove this when protoV1 registers these hooks for you.
_ "github.com/golang/protobuf/v2/internal/legacy"
anypb "github.com/golang/protobuf/ptypes/any"
durpb "github.com/golang/protobuf/ptypes/duration"
emptypb "github.com/golang/protobuf/ptypes/empty"
stpb "github.com/golang/protobuf/ptypes/struct"
tspb "github.com/golang/protobuf/ptypes/timestamp"
wpb "github.com/golang/protobuf/ptypes/wrappers"
)
func TestRoundTrip(t *testing.T) {
tests := []struct {
desc string
message proto.Message
}{{
desc: "well-known type fields set to empty messages",
message: &pb2.KnownTypes{
OptBool: &wpb.BoolValue{},
OptInt32: &wpb.Int32Value{},
OptInt64: &wpb.Int64Value{},
OptUint32: &wpb.UInt32Value{},
OptUint64: &wpb.UInt64Value{},
OptFloat: &wpb.FloatValue{},
OptDouble: &wpb.DoubleValue{},
OptString: &wpb.StringValue{},
OptBytes: &wpb.BytesValue{},
OptDuration: &durpb.Duration{},
OptTimestamp: &tspb.Timestamp{},
OptStruct: &stpb.Struct{},
OptList: &stpb.ListValue{},
OptValue: &stpb.Value{},
OptEmpty: &emptypb.Empty{},
OptAny: &anypb.Any{},
},
}, {
desc: "well-known type scalar fields",
message: &pb2.KnownTypes{
OptBool: &wpb.BoolValue{
Value: true,
},
OptInt32: &wpb.Int32Value{
Value: -42,
},
OptInt64: &wpb.Int64Value{
Value: -42,
},
OptUint32: &wpb.UInt32Value{
Value: 0xff,
},
OptUint64: &wpb.UInt64Value{
Value: 0xffff,
},
OptFloat: &wpb.FloatValue{
Value: 1.234,
},
OptDouble: &wpb.DoubleValue{
Value: 1.23e308,
},
OptString: &wpb.StringValue{
Value: "谷歌",
},
OptBytes: &wpb.BytesValue{
Value: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
},
},
}, {
desc: "well-known type time-related fields",
message: &pb2.KnownTypes{
OptDuration: &durpb.Duration{
Seconds: -3600,
Nanos: -123,
},
OptTimestamp: &tspb.Timestamp{
Seconds: 1257894000,
Nanos: 123,
},
},
}, {
desc: "well-known type struct field and different Value types",
message: &pb2.KnownTypes{
OptStruct: &stpb.Struct{
Fields: map[string]*stpb.Value{
"bool": &stpb.Value{
Kind: &stpb.Value_BoolValue{
BoolValue: true,
},
},
"double": &stpb.Value{
Kind: &stpb.Value_NumberValue{
NumberValue: 3.1415,
},
},
"null": &stpb.Value{
Kind: &stpb.Value_NullValue{
NullValue: stpb.NullValue_NULL_VALUE,
},
},
"string": &stpb.Value{
Kind: &stpb.Value_StringValue{
StringValue: "string",
},
},
"struct": &stpb.Value{
Kind: &stpb.Value_StructValue{
StructValue: &stpb.Struct{
Fields: map[string]*stpb.Value{
"bool": &stpb.Value{
Kind: &stpb.Value_BoolValue{
BoolValue: false,
},
},
},
},
},
},
"list": &stpb.Value{
Kind: &stpb.Value_ListValue{
ListValue: &stpb.ListValue{
Values: []*stpb.Value{
{
Kind: &stpb.Value_BoolValue{
BoolValue: false,
},
},
{
Kind: &stpb.Value_StringValue{
StringValue: "hello",
},
},
},
},
},
},
},
},
},
}}
for _, tt := range tests {
tt := tt
t.Run(tt.desc, func(t *testing.T) {
t.Parallel()
b, err := textpb.Marshal(tt.message)
if err != nil {
t.Errorf("Marshal() returned error: %v\n\n", err)
}
gotMessage := tt.message.ProtoReflect().Type().New().Interface()
err = textpb.Unmarshal(gotMessage, b)
if err != nil {
t.Errorf("Unmarshal() returned error: %v\n\n", err)
}
if !protoV1.Equal(gotMessage.(protoV1.Message), tt.message.(protoV1.Message)) {
t.Errorf("Unmarshal()\n<got>\n%v\n<want>\n%v\n", gotMessage, tt.message)
}
})
}
}