blob: 3ffa071ed830dae05eaa319ffabe250ec1ca7214 [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
Damien Neil5c5b5312019-05-14 12:44:37 -070010 "google.golang.org/protobuf/encoding/prototext"
Damien Neile89e6242019-05-13 23:55:40 -070011 "google.golang.org/protobuf/internal/impl"
12 pimpl "google.golang.org/protobuf/internal/impl"
Damien Neile89e6242019-05-13 23:55:40 -070013 "google.golang.org/protobuf/proto"
14 preg "google.golang.org/protobuf/reflect/protoregistry"
Herbie Ong800c9902018-12-06 15:28:53 -080015
Damien Neile89e6242019-05-13 23:55:40 -070016 "google.golang.org/protobuf/encoding/testprotos/pb2"
Joe Tsaia95b29f2019-05-16 12:47:20 -070017 "google.golang.org/protobuf/types/known/anypb"
18 "google.golang.org/protobuf/types/known/durationpb"
19 "google.golang.org/protobuf/types/known/emptypb"
20 "google.golang.org/protobuf/types/known/structpb"
21 "google.golang.org/protobuf/types/known/timestamppb"
22 "google.golang.org/protobuf/types/known/wrapperspb"
Herbie Ong800c9902018-12-06 15:28:53 -080023)
24
25func TestRoundTrip(t *testing.T) {
26 tests := []struct {
Herbie Ong66c365c2019-01-04 14:08:41 -080027 desc string
28 resolver *preg.Types
29 message proto.Message
Herbie Ong800c9902018-12-06 15:28:53 -080030 }{{
31 desc: "well-known type fields set to empty messages",
32 message: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -070033 OptBool: &wrapperspb.BoolValue{},
34 OptInt32: &wrapperspb.Int32Value{},
35 OptInt64: &wrapperspb.Int64Value{},
36 OptUint32: &wrapperspb.UInt32Value{},
37 OptUint64: &wrapperspb.UInt64Value{},
38 OptFloat: &wrapperspb.FloatValue{},
39 OptDouble: &wrapperspb.DoubleValue{},
40 OptString: &wrapperspb.StringValue{},
41 OptBytes: &wrapperspb.BytesValue{},
42 OptDuration: &durationpb.Duration{},
43 OptTimestamp: &timestamppb.Timestamp{},
44 OptStruct: &structpb.Struct{},
45 OptList: &structpb.ListValue{},
46 OptValue: &structpb.Value{},
47 OptEmpty: &emptypb.Empty{},
48 OptAny: &anypb.Any{},
Herbie Ong800c9902018-12-06 15:28:53 -080049 },
50 }, {
51 desc: "well-known type scalar fields",
52 message: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -070053 OptBool: &wrapperspb.BoolValue{
Herbie Ong800c9902018-12-06 15:28:53 -080054 Value: true,
55 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070056 OptInt32: &wrapperspb.Int32Value{
Herbie Ong800c9902018-12-06 15:28:53 -080057 Value: -42,
58 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070059 OptInt64: &wrapperspb.Int64Value{
Herbie Ong800c9902018-12-06 15:28:53 -080060 Value: -42,
61 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070062 OptUint32: &wrapperspb.UInt32Value{
Herbie Ong800c9902018-12-06 15:28:53 -080063 Value: 0xff,
64 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070065 OptUint64: &wrapperspb.UInt64Value{
Herbie Ong800c9902018-12-06 15:28:53 -080066 Value: 0xffff,
67 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070068 OptFloat: &wrapperspb.FloatValue{
Herbie Ong800c9902018-12-06 15:28:53 -080069 Value: 1.234,
70 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070071 OptDouble: &wrapperspb.DoubleValue{
Herbie Ong800c9902018-12-06 15:28:53 -080072 Value: 1.23e308,
73 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070074 OptString: &wrapperspb.StringValue{
Herbie Ong800c9902018-12-06 15:28:53 -080075 Value: "谷歌",
76 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070077 OptBytes: &wrapperspb.BytesValue{
Herbie Ong800c9902018-12-06 15:28:53 -080078 Value: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
79 },
80 },
81 }, {
82 desc: "well-known type time-related fields",
83 message: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -070084 OptDuration: &durationpb.Duration{
Herbie Ong800c9902018-12-06 15:28:53 -080085 Seconds: -3600,
86 Nanos: -123,
87 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070088 OptTimestamp: &timestamppb.Timestamp{
Herbie Ong800c9902018-12-06 15:28:53 -080089 Seconds: 1257894000,
90 Nanos: 123,
91 },
92 },
93 }, {
Herbie Ong66c365c2019-01-04 14:08:41 -080094 desc: "Struct field and different Value types",
Herbie Ong800c9902018-12-06 15:28:53 -080095 message: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -070096 OptStruct: &structpb.Struct{
97 Fields: map[string]*structpb.Value{
98 "bool": &structpb.Value{
99 Kind: &structpb.Value_BoolValue{
Herbie Ong800c9902018-12-06 15:28:53 -0800100 BoolValue: true,
101 },
102 },
Joe Tsaia95b29f2019-05-16 12:47:20 -0700103 "double": &structpb.Value{
104 Kind: &structpb.Value_NumberValue{
Herbie Ong800c9902018-12-06 15:28:53 -0800105 NumberValue: 3.1415,
106 },
107 },
Joe Tsaia95b29f2019-05-16 12:47:20 -0700108 "null": &structpb.Value{
109 Kind: &structpb.Value_NullValue{
110 NullValue: structpb.NullValue_NULL_VALUE,
Herbie Ong800c9902018-12-06 15:28:53 -0800111 },
112 },
Joe Tsaia95b29f2019-05-16 12:47:20 -0700113 "string": &structpb.Value{
114 Kind: &structpb.Value_StringValue{
Herbie Ong800c9902018-12-06 15:28:53 -0800115 StringValue: "string",
116 },
117 },
Joe Tsaia95b29f2019-05-16 12:47:20 -0700118 "struct": &structpb.Value{
119 Kind: &structpb.Value_StructValue{
120 StructValue: &structpb.Struct{
121 Fields: map[string]*structpb.Value{
122 "bool": &structpb.Value{
123 Kind: &structpb.Value_BoolValue{
Herbie Ong800c9902018-12-06 15:28:53 -0800124 BoolValue: false,
125 },
126 },
127 },
128 },
129 },
130 },
Joe Tsaia95b29f2019-05-16 12:47:20 -0700131 "list": &structpb.Value{
132 Kind: &structpb.Value_ListValue{
133 ListValue: &structpb.ListValue{
134 Values: []*structpb.Value{
Herbie Ong800c9902018-12-06 15:28:53 -0800135 {
Joe Tsaia95b29f2019-05-16 12:47:20 -0700136 Kind: &structpb.Value_BoolValue{
Herbie Ong800c9902018-12-06 15:28:53 -0800137 BoolValue: false,
138 },
139 },
140 {
Joe Tsaia95b29f2019-05-16 12:47:20 -0700141 Kind: &structpb.Value_StringValue{
Herbie Ong800c9902018-12-06 15:28:53 -0800142 StringValue: "hello",
143 },
144 },
145 },
146 },
147 },
148 },
149 },
150 },
151 },
Herbie Ong66c365c2019-01-04 14:08:41 -0800152 }, {
153 desc: "Any field without registered type",
154 resolver: preg.NewTypes(),
155 message: func() proto.Message {
156 m := &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -0700157 OptString: proto.String("embedded inside Any"),
Herbie Ong66c365c2019-01-04 14:08:41 -0800158 OptNested: &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -0700159 OptString: proto.String("inception"),
Herbie Ong66c365c2019-01-04 14:08:41 -0800160 },
161 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -0700162 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ong66c365c2019-01-04 14:08:41 -0800163 if err != nil {
164 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
165 }
166 return &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -0700167 OptAny: &anypb.Any{
Joe Tsai0fc49f82019-05-01 12:29:25 -0700168 TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
Herbie Ong66c365c2019-01-04 14:08:41 -0800169 Value: b,
170 },
171 }
172 }(),
173 }, {
174 desc: "Any field with registered type",
Joe Tsai0fc49f82019-05-01 12:29:25 -0700175 resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
176 message: func() *pb2.KnownTypes {
Herbie Ong66c365c2019-01-04 14:08:41 -0800177 m := &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -0700178 OptString: proto.String("embedded inside Any"),
Herbie Ong66c365c2019-01-04 14:08:41 -0800179 OptNested: &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -0700180 OptString: proto.String("inception"),
Herbie Ong66c365c2019-01-04 14:08:41 -0800181 },
182 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -0700183 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ong66c365c2019-01-04 14:08:41 -0800184 if err != nil {
185 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
186 }
187 return &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -0700188 OptAny: &anypb.Any{
Joe Tsai0fc49f82019-05-01 12:29:25 -0700189 TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
Herbie Ong66c365c2019-01-04 14:08:41 -0800190 Value: b,
191 },
192 }
193 }(),
194 }, {
195 desc: "Any field containing Any message",
196 resolver: func() *preg.Types {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700197 mt1 := impl.Export{}.MessageTypeOf(&pb2.Nested{})
Joe Tsaia95b29f2019-05-16 12:47:20 -0700198 mt2 := impl.Export{}.MessageTypeOf(&anypb.Any{})
Herbie Ong66c365c2019-01-04 14:08:41 -0800199 return preg.NewTypes(mt1, mt2)
200 }(),
Joe Tsai0fc49f82019-05-01 12:29:25 -0700201 message: func() *pb2.KnownTypes {
Herbie Ong66c365c2019-01-04 14:08:41 -0800202 m1 := &pb2.Nested{
Damien Neila8a2cea2019-07-10 16:17:16 -0700203 OptString: proto.String("message inside Any of another Any field"),
Herbie Ong66c365c2019-01-04 14:08:41 -0800204 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -0700205 b1, err := proto.MarshalOptions{Deterministic: true}.Marshal(m1)
Herbie Ong66c365c2019-01-04 14:08:41 -0800206 if err != nil {
207 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
208 }
Joe Tsaia95b29f2019-05-16 12:47:20 -0700209 m2 := &anypb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -0800210 TypeUrl: "pb2.Nested",
211 Value: b1,
212 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -0700213 b2, err := proto.MarshalOptions{Deterministic: true}.Marshal(m2)
Herbie Ong66c365c2019-01-04 14:08:41 -0800214 if err != nil {
215 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
216 }
217 return &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -0700218 OptAny: &anypb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -0800219 TypeUrl: "google.protobuf.Any",
220 Value: b2,
221 },
222 }
223 }(),
Herbie Ong800c9902018-12-06 15:28:53 -0800224 }}
225
226 for _, tt := range tests {
227 tt := tt
228 t.Run(tt.desc, func(t *testing.T) {
229 t.Parallel()
Damien Neil5c5b5312019-05-14 12:44:37 -0700230 b, err := prototext.MarshalOptions{Resolver: tt.resolver}.Marshal(tt.message)
Herbie Ong800c9902018-12-06 15:28:53 -0800231 if err != nil {
232 t.Errorf("Marshal() returned error: %v\n\n", err)
233 }
Joe Tsai0fc49f82019-05-01 12:29:25 -0700234
235 gotMessage := new(pb2.KnownTypes)
Joe Tsaicdb77732019-05-14 16:05:06 -0700236 err = prototext.UnmarshalOptions{Resolver: tt.resolver}.Unmarshal(b, gotMessage)
Herbie Ong800c9902018-12-06 15:28:53 -0800237 if err != nil {
238 t.Errorf("Unmarshal() returned error: %v\n\n", err)
239 }
Herbie Ong66c365c2019-01-04 14:08:41 -0800240
Joe Tsai8d30bbe2019-05-16 15:53:25 -0700241 if !proto.Equal(gotMessage, tt.message) {
Herbie Ong70651952018-12-13 14:19:50 -0800242 t.Errorf("Unmarshal()\n<got>\n%v\n<want>\n%v\n", gotMessage, tt.message)
243 }
Herbie Ong800c9902018-12-06 15:28:53 -0800244 })
245 }
246}