blob: 978a3585dfbb371fdfbb858abec0f6b54d8f500e [file] [log] [blame]
Damien Neil5c5b5312019-05-14 12:44:37 -07001package prototext_test
Herbie Ong800c9902018-12-06 15:28:53 -08002
3import (
4 "testing"
5
6 protoV1 "github.com/golang/protobuf/proto"
Damien Neil5c5b5312019-05-14 12:44:37 -07007 "google.golang.org/protobuf/encoding/prototext"
Damien Neile89e6242019-05-13 23:55:40 -07008 "google.golang.org/protobuf/internal/impl"
9 pimpl "google.golang.org/protobuf/internal/impl"
10 "google.golang.org/protobuf/internal/scalar"
11 "google.golang.org/protobuf/proto"
12 preg "google.golang.org/protobuf/reflect/protoregistry"
Herbie Ong800c9902018-12-06 15:28:53 -080013
Damien Neile89e6242019-05-13 23:55:40 -070014 "google.golang.org/protobuf/encoding/testprotos/pb2"
Joe Tsaia95b29f2019-05-16 12:47:20 -070015 "google.golang.org/protobuf/types/known/anypb"
16 "google.golang.org/protobuf/types/known/durationpb"
17 "google.golang.org/protobuf/types/known/emptypb"
18 "google.golang.org/protobuf/types/known/structpb"
19 "google.golang.org/protobuf/types/known/timestamppb"
20 "google.golang.org/protobuf/types/known/wrapperspb"
Herbie Ong800c9902018-12-06 15:28:53 -080021)
22
23func TestRoundTrip(t *testing.T) {
24 tests := []struct {
Herbie Ong66c365c2019-01-04 14:08:41 -080025 desc string
26 resolver *preg.Types
27 message proto.Message
Herbie Ong800c9902018-12-06 15:28:53 -080028 }{{
29 desc: "well-known type fields set to empty messages",
30 message: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -070031 OptBool: &wrapperspb.BoolValue{},
32 OptInt32: &wrapperspb.Int32Value{},
33 OptInt64: &wrapperspb.Int64Value{},
34 OptUint32: &wrapperspb.UInt32Value{},
35 OptUint64: &wrapperspb.UInt64Value{},
36 OptFloat: &wrapperspb.FloatValue{},
37 OptDouble: &wrapperspb.DoubleValue{},
38 OptString: &wrapperspb.StringValue{},
39 OptBytes: &wrapperspb.BytesValue{},
40 OptDuration: &durationpb.Duration{},
41 OptTimestamp: &timestamppb.Timestamp{},
42 OptStruct: &structpb.Struct{},
43 OptList: &structpb.ListValue{},
44 OptValue: &structpb.Value{},
45 OptEmpty: &emptypb.Empty{},
46 OptAny: &anypb.Any{},
Herbie Ong800c9902018-12-06 15:28:53 -080047 },
48 }, {
49 desc: "well-known type scalar fields",
50 message: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -070051 OptBool: &wrapperspb.BoolValue{
Herbie Ong800c9902018-12-06 15:28:53 -080052 Value: true,
53 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070054 OptInt32: &wrapperspb.Int32Value{
Herbie Ong800c9902018-12-06 15:28:53 -080055 Value: -42,
56 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070057 OptInt64: &wrapperspb.Int64Value{
Herbie Ong800c9902018-12-06 15:28:53 -080058 Value: -42,
59 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070060 OptUint32: &wrapperspb.UInt32Value{
Herbie Ong800c9902018-12-06 15:28:53 -080061 Value: 0xff,
62 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070063 OptUint64: &wrapperspb.UInt64Value{
Herbie Ong800c9902018-12-06 15:28:53 -080064 Value: 0xffff,
65 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070066 OptFloat: &wrapperspb.FloatValue{
Herbie Ong800c9902018-12-06 15:28:53 -080067 Value: 1.234,
68 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070069 OptDouble: &wrapperspb.DoubleValue{
Herbie Ong800c9902018-12-06 15:28:53 -080070 Value: 1.23e308,
71 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070072 OptString: &wrapperspb.StringValue{
Herbie Ong800c9902018-12-06 15:28:53 -080073 Value: "谷歌",
74 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070075 OptBytes: &wrapperspb.BytesValue{
Herbie Ong800c9902018-12-06 15:28:53 -080076 Value: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
77 },
78 },
79 }, {
80 desc: "well-known type time-related fields",
81 message: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -070082 OptDuration: &durationpb.Duration{
Herbie Ong800c9902018-12-06 15:28:53 -080083 Seconds: -3600,
84 Nanos: -123,
85 },
Joe Tsaia95b29f2019-05-16 12:47:20 -070086 OptTimestamp: &timestamppb.Timestamp{
Herbie Ong800c9902018-12-06 15:28:53 -080087 Seconds: 1257894000,
88 Nanos: 123,
89 },
90 },
91 }, {
Herbie Ong66c365c2019-01-04 14:08:41 -080092 desc: "Struct field and different Value types",
Herbie Ong800c9902018-12-06 15:28:53 -080093 message: &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -070094 OptStruct: &structpb.Struct{
95 Fields: map[string]*structpb.Value{
96 "bool": &structpb.Value{
97 Kind: &structpb.Value_BoolValue{
Herbie Ong800c9902018-12-06 15:28:53 -080098 BoolValue: true,
99 },
100 },
Joe Tsaia95b29f2019-05-16 12:47:20 -0700101 "double": &structpb.Value{
102 Kind: &structpb.Value_NumberValue{
Herbie Ong800c9902018-12-06 15:28:53 -0800103 NumberValue: 3.1415,
104 },
105 },
Joe Tsaia95b29f2019-05-16 12:47:20 -0700106 "null": &structpb.Value{
107 Kind: &structpb.Value_NullValue{
108 NullValue: structpb.NullValue_NULL_VALUE,
Herbie Ong800c9902018-12-06 15:28:53 -0800109 },
110 },
Joe Tsaia95b29f2019-05-16 12:47:20 -0700111 "string": &structpb.Value{
112 Kind: &structpb.Value_StringValue{
Herbie Ong800c9902018-12-06 15:28:53 -0800113 StringValue: "string",
114 },
115 },
Joe Tsaia95b29f2019-05-16 12:47:20 -0700116 "struct": &structpb.Value{
117 Kind: &structpb.Value_StructValue{
118 StructValue: &structpb.Struct{
119 Fields: map[string]*structpb.Value{
120 "bool": &structpb.Value{
121 Kind: &structpb.Value_BoolValue{
Herbie Ong800c9902018-12-06 15:28:53 -0800122 BoolValue: false,
123 },
124 },
125 },
126 },
127 },
128 },
Joe Tsaia95b29f2019-05-16 12:47:20 -0700129 "list": &structpb.Value{
130 Kind: &structpb.Value_ListValue{
131 ListValue: &structpb.ListValue{
132 Values: []*structpb.Value{
Herbie Ong800c9902018-12-06 15:28:53 -0800133 {
Joe Tsaia95b29f2019-05-16 12:47:20 -0700134 Kind: &structpb.Value_BoolValue{
Herbie Ong800c9902018-12-06 15:28:53 -0800135 BoolValue: false,
136 },
137 },
138 {
Joe Tsaia95b29f2019-05-16 12:47:20 -0700139 Kind: &structpb.Value_StringValue{
Herbie Ong800c9902018-12-06 15:28:53 -0800140 StringValue: "hello",
141 },
142 },
143 },
144 },
145 },
146 },
147 },
148 },
149 },
Herbie Ong66c365c2019-01-04 14:08:41 -0800150 }, {
151 desc: "Any field without registered type",
152 resolver: preg.NewTypes(),
153 message: func() proto.Message {
154 m := &pb2.Nested{
155 OptString: scalar.String("embedded inside Any"),
156 OptNested: &pb2.Nested{
157 OptString: scalar.String("inception"),
158 },
159 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -0700160 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ong66c365c2019-01-04 14:08:41 -0800161 if err != nil {
162 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
163 }
164 return &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -0700165 OptAny: &anypb.Any{
Joe Tsai0fc49f82019-05-01 12:29:25 -0700166 TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
Herbie Ong66c365c2019-01-04 14:08:41 -0800167 Value: b,
168 },
169 }
170 }(),
171 }, {
172 desc: "Any field with registered type",
Joe Tsai0fc49f82019-05-01 12:29:25 -0700173 resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
174 message: func() *pb2.KnownTypes {
Herbie Ong66c365c2019-01-04 14:08:41 -0800175 m := &pb2.Nested{
176 OptString: scalar.String("embedded inside Any"),
177 OptNested: &pb2.Nested{
178 OptString: scalar.String("inception"),
179 },
180 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -0700181 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ong66c365c2019-01-04 14:08:41 -0800182 if err != nil {
183 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
184 }
185 return &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -0700186 OptAny: &anypb.Any{
Joe Tsai0fc49f82019-05-01 12:29:25 -0700187 TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
Herbie Ong66c365c2019-01-04 14:08:41 -0800188 Value: b,
189 },
190 }
191 }(),
192 }, {
193 desc: "Any field containing Any message",
194 resolver: func() *preg.Types {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700195 mt1 := impl.Export{}.MessageTypeOf(&pb2.Nested{})
Joe Tsaia95b29f2019-05-16 12:47:20 -0700196 mt2 := impl.Export{}.MessageTypeOf(&anypb.Any{})
Herbie Ong66c365c2019-01-04 14:08:41 -0800197 return preg.NewTypes(mt1, mt2)
198 }(),
Joe Tsai0fc49f82019-05-01 12:29:25 -0700199 message: func() *pb2.KnownTypes {
Herbie Ong66c365c2019-01-04 14:08:41 -0800200 m1 := &pb2.Nested{
201 OptString: scalar.String("message inside Any of another Any field"),
202 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -0700203 b1, err := proto.MarshalOptions{Deterministic: true}.Marshal(m1)
Herbie Ong66c365c2019-01-04 14:08:41 -0800204 if err != nil {
205 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
206 }
Joe Tsaia95b29f2019-05-16 12:47:20 -0700207 m2 := &anypb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -0800208 TypeUrl: "pb2.Nested",
209 Value: b1,
210 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -0700211 b2, err := proto.MarshalOptions{Deterministic: true}.Marshal(m2)
Herbie Ong66c365c2019-01-04 14:08:41 -0800212 if err != nil {
213 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
214 }
215 return &pb2.KnownTypes{
Joe Tsaia95b29f2019-05-16 12:47:20 -0700216 OptAny: &anypb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -0800217 TypeUrl: "google.protobuf.Any",
218 Value: b2,
219 },
220 }
221 }(),
Herbie Ong800c9902018-12-06 15:28:53 -0800222 }}
223
224 for _, tt := range tests {
225 tt := tt
226 t.Run(tt.desc, func(t *testing.T) {
227 t.Parallel()
Damien Neil5c5b5312019-05-14 12:44:37 -0700228 b, err := prototext.MarshalOptions{Resolver: tt.resolver}.Marshal(tt.message)
Herbie Ong800c9902018-12-06 15:28:53 -0800229 if err != nil {
230 t.Errorf("Marshal() returned error: %v\n\n", err)
231 }
Joe Tsai0fc49f82019-05-01 12:29:25 -0700232
233 gotMessage := new(pb2.KnownTypes)
Joe Tsaicdb77732019-05-14 16:05:06 -0700234 err = prototext.UnmarshalOptions{Resolver: tt.resolver}.Unmarshal(b, gotMessage)
Herbie Ong800c9902018-12-06 15:28:53 -0800235 if err != nil {
236 t.Errorf("Unmarshal() returned error: %v\n\n", err)
237 }
Herbie Ong66c365c2019-01-04 14:08:41 -0800238
Joe Tsai0fc49f82019-05-01 12:29:25 -0700239 if !protoV1.Equal(gotMessage, tt.message.(protoV1.Message)) {
Herbie Ong70651952018-12-13 14:19:50 -0800240 t.Errorf("Unmarshal()\n<got>\n%v\n<want>\n%v\n", gotMessage, tt.message)
241 }
Herbie Ong800c9902018-12-06 15:28:53 -0800242 })
243 }
244}