blob: ec1842f38fbf9df4f33c26343ddeb3a16b9a94f5 [file] [log] [blame]
Joe Tsaid8881392019-06-06 13:01:53 -07001// Copyright 2019 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
Damien Neil5c5b5312019-05-14 12:44:37 -07005package prototext_test
Herbie Ong800c9902018-12-06 15:28:53 -08006
7import (
8 "testing"
9
10 protoV1 "github.com/golang/protobuf/proto"
Damien Neil5c5b5312019-05-14 12:44:37 -070011 "google.golang.org/protobuf/encoding/prototext"
Damien Neile89e6242019-05-13 23:55:40 -070012 "google.golang.org/protobuf/internal/impl"
13 pimpl "google.golang.org/protobuf/internal/impl"
14 "google.golang.org/protobuf/internal/scalar"
15 "google.golang.org/protobuf/proto"
16 preg "google.golang.org/protobuf/reflect/protoregistry"
Herbie Ong800c9902018-12-06 15:28:53 -080017
Damien Neile89e6242019-05-13 23:55:40 -070018 "google.golang.org/protobuf/encoding/testprotos/pb2"
Joe Tsaia95b29f2019-05-16 12:47:20 -070019 "google.golang.org/protobuf/types/known/anypb"
20 "google.golang.org/protobuf/types/known/durationpb"
21 "google.golang.org/protobuf/types/known/emptypb"
22 "google.golang.org/protobuf/types/known/structpb"
23 "google.golang.org/protobuf/types/known/timestamppb"
24 "google.golang.org/protobuf/types/known/wrapperspb"
Herbie Ong800c9902018-12-06 15:28:53 -080025)
26
27func TestRoundTrip(t *testing.T) {
28 tests := []struct {
Herbie Ong66c365c2019-01-04 14:08:41 -080029 desc string
30 resolver *preg.Types
31 message proto.Message
Herbie Ong800c9902018-12-06 15:28:53 -080032 }{{
33 desc: "well-known type fields set to empty messages",
34 message: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -070035 OptBool: &wrapperspb.BoolValue{},
36 OptInt32: &wrapperspb.Int32Value{},
37 OptInt64: &wrapperspb.Int64Value{},
38 OptUint32: &wrapperspb.UInt32Value{},
39 OptUint64: &wrapperspb.UInt64Value{},
40 OptFloat: &wrapperspb.FloatValue{},
41 OptDouble: &wrapperspb.DoubleValue{},
42 OptString: &wrapperspb.StringValue{},
43 OptBytes: &wrapperspb.BytesValue{},
44 OptDuration: &durationpb.Duration{},
45 OptTimestamp: &timestamppb.Timestamp{},
46 OptStruct: &structpb.Struct{},
47 OptList: &structpb.ListValue{},
48 OptValue: &structpb.Value{},
49 OptEmpty: &emptypb.Empty{},
50 OptAny: &anypb.Any{},
Herbie Ong800c9902018-12-06 15:28:53 -080051 },
52 }, {
53 desc: "well-known type scalar fields",
54 message: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -070055 OptBool: &wrapperspb.BoolValue{
Herbie Ong800c9902018-12-06 15:28:53 -080056 Value: true,
57 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070058 OptInt32: &wrapperspb.Int32Value{
Herbie Ong800c9902018-12-06 15:28:53 -080059 Value: -42,
60 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070061 OptInt64: &wrapperspb.Int64Value{
Herbie Ong800c9902018-12-06 15:28:53 -080062 Value: -42,
63 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070064 OptUint32: &wrapperspb.UInt32Value{
Herbie Ong800c9902018-12-06 15:28:53 -080065 Value: 0xff,
66 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070067 OptUint64: &wrapperspb.UInt64Value{
Herbie Ong800c9902018-12-06 15:28:53 -080068 Value: 0xffff,
69 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070070 OptFloat: &wrapperspb.FloatValue{
Herbie Ong800c9902018-12-06 15:28:53 -080071 Value: 1.234,
72 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070073 OptDouble: &wrapperspb.DoubleValue{
Herbie Ong800c9902018-12-06 15:28:53 -080074 Value: 1.23e308,
75 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070076 OptString: &wrapperspb.StringValue{
Herbie Ong800c9902018-12-06 15:28:53 -080077 Value: "谷歌",
78 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070079 OptBytes: &wrapperspb.BytesValue{
Herbie Ong800c9902018-12-06 15:28:53 -080080 Value: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
81 },
82 },
83 }, {
84 desc: "well-known type time-related fields",
85 message: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -070086 OptDuration: &durationpb.Duration{
Herbie Ong800c9902018-12-06 15:28:53 -080087 Seconds: -3600,
88 Nanos: -123,
89 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070090 OptTimestamp: &timestamppb.Timestamp{
Herbie Ong800c9902018-12-06 15:28:53 -080091 Seconds: 1257894000,
92 Nanos: 123,
93 },
94 },
95 }, {
Herbie Ong66c365c2019-01-04 14:08:41 -080096 desc: "Struct field and different Value types",
Herbie Ong800c9902018-12-06 15:28:53 -080097 message: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -070098 OptStruct: &structpb.Struct{
99 Fields: map[string]*structpb.Value{
100 "bool": &structpb.Value{
101 Kind: &structpb.Value_BoolValue{
Herbie Ong800c9902018-12-06 15:28:53 -0800102 BoolValue: true,
103 },
104 },
Joe Tsaia95b29f2019-05-16 12:47:20 -0700105 "double": &structpb.Value{
106 Kind: &structpb.Value_NumberValue{
Herbie Ong800c9902018-12-06 15:28:53 -0800107 NumberValue: 3.1415,
108 },
109 },
Joe Tsaia95b29f2019-05-16 12:47:20 -0700110 "null": &structpb.Value{
111 Kind: &structpb.Value_NullValue{
112 NullValue: structpb.NullValue_NULL_VALUE,
Herbie Ong800c9902018-12-06 15:28:53 -0800113 },
114 },
Joe Tsaia95b29f2019-05-16 12:47:20 -0700115 "string": &structpb.Value{
116 Kind: &structpb.Value_StringValue{
Herbie Ong800c9902018-12-06 15:28:53 -0800117 StringValue: "string",
118 },
119 },
Joe Tsaia95b29f2019-05-16 12:47:20 -0700120 "struct": &structpb.Value{
121 Kind: &structpb.Value_StructValue{
122 StructValue: &structpb.Struct{
123 Fields: map[string]*structpb.Value{
124 "bool": &structpb.Value{
125 Kind: &structpb.Value_BoolValue{
Herbie Ong800c9902018-12-06 15:28:53 -0800126 BoolValue: false,
127 },
128 },
129 },
130 },
131 },
132 },
Joe Tsaia95b29f2019-05-16 12:47:20 -0700133 "list": &structpb.Value{
134 Kind: &structpb.Value_ListValue{
135 ListValue: &structpb.ListValue{
136 Values: []*structpb.Value{
Herbie Ong800c9902018-12-06 15:28:53 -0800137 {
Joe Tsaia95b29f2019-05-16 12:47:20 -0700138 Kind: &structpb.Value_BoolValue{
Herbie Ong800c9902018-12-06 15:28:53 -0800139 BoolValue: false,
140 },
141 },
142 {
Joe Tsaia95b29f2019-05-16 12:47:20 -0700143 Kind: &structpb.Value_StringValue{
Herbie Ong800c9902018-12-06 15:28:53 -0800144 StringValue: "hello",
145 },
146 },
147 },
148 },
149 },
150 },
151 },
152 },
153 },
Herbie Ong66c365c2019-01-04 14:08:41 -0800154 }, {
155 desc: "Any field without registered type",
156 resolver: preg.NewTypes(),
157 message: func() proto.Message {
158 m := &pb2.Nested{
159 OptString: scalar.String("embedded inside Any"),
160 OptNested: &pb2.Nested{
161 OptString: scalar.String("inception"),
162 },
163 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -0700164 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ong66c365c2019-01-04 14:08:41 -0800165 if err != nil {
166 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
167 }
168 return &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -0700169 OptAny: &anypb.Any{
Joe Tsai0fc49f82019-05-01 12:29:25 -0700170 TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
Herbie Ong66c365c2019-01-04 14:08:41 -0800171 Value: b,
172 },
173 }
174 }(),
175 }, {
176 desc: "Any field with registered type",
Joe Tsai0fc49f82019-05-01 12:29:25 -0700177 resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
178 message: func() *pb2.KnownTypes {
Herbie Ong66c365c2019-01-04 14:08:41 -0800179 m := &pb2.Nested{
180 OptString: scalar.String("embedded inside Any"),
181 OptNested: &pb2.Nested{
182 OptString: scalar.String("inception"),
183 },
184 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -0700185 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ong66c365c2019-01-04 14:08:41 -0800186 if err != nil {
187 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
188 }
189 return &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -0700190 OptAny: &anypb.Any{
Joe Tsai0fc49f82019-05-01 12:29:25 -0700191 TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
Herbie Ong66c365c2019-01-04 14:08:41 -0800192 Value: b,
193 },
194 }
195 }(),
196 }, {
197 desc: "Any field containing Any message",
198 resolver: func() *preg.Types {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700199 mt1 := impl.Export{}.MessageTypeOf(&pb2.Nested{})
Joe Tsaia95b29f2019-05-16 12:47:20 -0700200 mt2 := impl.Export{}.MessageTypeOf(&anypb.Any{})
Herbie Ong66c365c2019-01-04 14:08:41 -0800201 return preg.NewTypes(mt1, mt2)
202 }(),
Joe Tsai0fc49f82019-05-01 12:29:25 -0700203 message: func() *pb2.KnownTypes {
Herbie Ong66c365c2019-01-04 14:08:41 -0800204 m1 := &pb2.Nested{
205 OptString: scalar.String("message inside Any of another Any field"),
206 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -0700207 b1, err := proto.MarshalOptions{Deterministic: true}.Marshal(m1)
Herbie Ong66c365c2019-01-04 14:08:41 -0800208 if err != nil {
209 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
210 }
Joe Tsaia95b29f2019-05-16 12:47:20 -0700211 m2 := &anypb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -0800212 TypeUrl: "pb2.Nested",
213 Value: b1,
214 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -0700215 b2, err := proto.MarshalOptions{Deterministic: true}.Marshal(m2)
Herbie Ong66c365c2019-01-04 14:08:41 -0800216 if err != nil {
217 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
218 }
219 return &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -0700220 OptAny: &anypb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -0800221 TypeUrl: "google.protobuf.Any",
222 Value: b2,
223 },
224 }
225 }(),
Herbie Ong800c9902018-12-06 15:28:53 -0800226 }}
227
228 for _, tt := range tests {
229 tt := tt
230 t.Run(tt.desc, func(t *testing.T) {
231 t.Parallel()
Damien Neil5c5b5312019-05-14 12:44:37 -0700232 b, err := prototext.MarshalOptions{Resolver: tt.resolver}.Marshal(tt.message)
Herbie Ong800c9902018-12-06 15:28:53 -0800233 if err != nil {
234 t.Errorf("Marshal() returned error: %v\n\n", err)
235 }
Joe Tsai0fc49f82019-05-01 12:29:25 -0700236
237 gotMessage := new(pb2.KnownTypes)
Joe Tsaicdb77732019-05-14 16:05:06 -0700238 err = prototext.UnmarshalOptions{Resolver: tt.resolver}.Unmarshal(b, gotMessage)
Herbie Ong800c9902018-12-06 15:28:53 -0800239 if err != nil {
240 t.Errorf("Unmarshal() returned error: %v\n\n", err)
241 }
Herbie Ong66c365c2019-01-04 14:08:41 -0800242
Joe Tsai0fc49f82019-05-01 12:29:25 -0700243 if !protoV1.Equal(gotMessage, tt.message.(protoV1.Message)) {
Herbie Ong70651952018-12-13 14:19:50 -0800244 t.Errorf("Unmarshal()\n<got>\n%v\n<want>\n%v\n", gotMessage, tt.message)
245 }
Herbie Ong800c9902018-12-06 15:28:53 -0800246 })
247 }
248}