123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- // 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"
- preg "google.golang.org/protobuf/reflect/protoregistry"
- "google.golang.org/protobuf/encoding/testprotos/pb2"
- "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 *preg.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(preg.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)
- }
- })
- }
- }
|