blob: e20e005ab6d7b9b75938ccb450ea200e3d8ed28a [file] [log] [blame]
Herbie Ong800c9902018-12-06 15:28:53 -08001package textpb_test
2
3import (
4 "testing"
5
6 protoV1 "github.com/golang/protobuf/proto"
7 "github.com/golang/protobuf/v2/encoding/textpb"
Herbie Ong8170d692019-02-13 14:13:21 -08008 "github.com/golang/protobuf/v2/internal/impl"
9 "github.com/golang/protobuf/v2/internal/scalar"
Herbie Ong70651952018-12-13 14:19:50 -080010 "github.com/golang/protobuf/v2/proto"
Herbie Ong66c365c2019-01-04 14:08:41 -080011 preg "github.com/golang/protobuf/v2/reflect/protoregistry"
Herbie Ong800c9902018-12-06 15:28:53 -080012
Herbie Ong8170d692019-02-13 14:13:21 -080013 "github.com/golang/protobuf/v2/encoding/testprotos/pb2"
Joe Tsai19058432019-02-27 21:46:29 -080014 knownpb "github.com/golang/protobuf/v2/types/known"
Herbie Ong800c9902018-12-06 15:28:53 -080015)
16
17func TestRoundTrip(t *testing.T) {
18 tests := []struct {
Herbie Ong66c365c2019-01-04 14:08:41 -080019 desc string
20 resolver *preg.Types
21 message proto.Message
Herbie Ong800c9902018-12-06 15:28:53 -080022 }{{
23 desc: "well-known type fields set to empty messages",
24 message: &pb2.KnownTypes{
Joe Tsai19058432019-02-27 21:46:29 -080025 OptBool: &knownpb.BoolValue{},
26 OptInt32: &knownpb.Int32Value{},
27 OptInt64: &knownpb.Int64Value{},
28 OptUint32: &knownpb.UInt32Value{},
29 OptUint64: &knownpb.UInt64Value{},
30 OptFloat: &knownpb.FloatValue{},
31 OptDouble: &knownpb.DoubleValue{},
32 OptString: &knownpb.StringValue{},
33 OptBytes: &knownpb.BytesValue{},
34 OptDuration: &knownpb.Duration{},
35 OptTimestamp: &knownpb.Timestamp{},
36 OptStruct: &knownpb.Struct{},
37 OptList: &knownpb.ListValue{},
38 OptValue: &knownpb.Value{},
39 OptEmpty: &knownpb.Empty{},
40 OptAny: &knownpb.Any{},
Herbie Ong800c9902018-12-06 15:28:53 -080041 },
42 }, {
43 desc: "well-known type scalar fields",
44 message: &pb2.KnownTypes{
Joe Tsai19058432019-02-27 21:46:29 -080045 OptBool: &knownpb.BoolValue{
Herbie Ong800c9902018-12-06 15:28:53 -080046 Value: true,
47 },
Joe Tsai19058432019-02-27 21:46:29 -080048 OptInt32: &knownpb.Int32Value{
Herbie Ong800c9902018-12-06 15:28:53 -080049 Value: -42,
50 },
Joe Tsai19058432019-02-27 21:46:29 -080051 OptInt64: &knownpb.Int64Value{
Herbie Ong800c9902018-12-06 15:28:53 -080052 Value: -42,
53 },
Joe Tsai19058432019-02-27 21:46:29 -080054 OptUint32: &knownpb.UInt32Value{
Herbie Ong800c9902018-12-06 15:28:53 -080055 Value: 0xff,
56 },
Joe Tsai19058432019-02-27 21:46:29 -080057 OptUint64: &knownpb.UInt64Value{
Herbie Ong800c9902018-12-06 15:28:53 -080058 Value: 0xffff,
59 },
Joe Tsai19058432019-02-27 21:46:29 -080060 OptFloat: &knownpb.FloatValue{
Herbie Ong800c9902018-12-06 15:28:53 -080061 Value: 1.234,
62 },
Joe Tsai19058432019-02-27 21:46:29 -080063 OptDouble: &knownpb.DoubleValue{
Herbie Ong800c9902018-12-06 15:28:53 -080064 Value: 1.23e308,
65 },
Joe Tsai19058432019-02-27 21:46:29 -080066 OptString: &knownpb.StringValue{
Herbie Ong800c9902018-12-06 15:28:53 -080067 Value: "谷歌",
68 },
Joe Tsai19058432019-02-27 21:46:29 -080069 OptBytes: &knownpb.BytesValue{
Herbie Ong800c9902018-12-06 15:28:53 -080070 Value: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
71 },
72 },
73 }, {
74 desc: "well-known type time-related fields",
75 message: &pb2.KnownTypes{
Joe Tsai19058432019-02-27 21:46:29 -080076 OptDuration: &knownpb.Duration{
Herbie Ong800c9902018-12-06 15:28:53 -080077 Seconds: -3600,
78 Nanos: -123,
79 },
Joe Tsai19058432019-02-27 21:46:29 -080080 OptTimestamp: &knownpb.Timestamp{
Herbie Ong800c9902018-12-06 15:28:53 -080081 Seconds: 1257894000,
82 Nanos: 123,
83 },
84 },
85 }, {
Herbie Ong66c365c2019-01-04 14:08:41 -080086 desc: "Struct field and different Value types",
Herbie Ong800c9902018-12-06 15:28:53 -080087 message: &pb2.KnownTypes{
Joe Tsai19058432019-02-27 21:46:29 -080088 OptStruct: &knownpb.Struct{
89 Fields: map[string]*knownpb.Value{
90 "bool": &knownpb.Value{
91 Kind: &knownpb.Value_BoolValue{
Herbie Ong800c9902018-12-06 15:28:53 -080092 BoolValue: true,
93 },
94 },
Joe Tsai19058432019-02-27 21:46:29 -080095 "double": &knownpb.Value{
96 Kind: &knownpb.Value_NumberValue{
Herbie Ong800c9902018-12-06 15:28:53 -080097 NumberValue: 3.1415,
98 },
99 },
Joe Tsai19058432019-02-27 21:46:29 -0800100 "null": &knownpb.Value{
101 Kind: &knownpb.Value_NullValue{
102 NullValue: knownpb.NullValue_NULL_VALUE,
Herbie Ong800c9902018-12-06 15:28:53 -0800103 },
104 },
Joe Tsai19058432019-02-27 21:46:29 -0800105 "string": &knownpb.Value{
106 Kind: &knownpb.Value_StringValue{
Herbie Ong800c9902018-12-06 15:28:53 -0800107 StringValue: "string",
108 },
109 },
Joe Tsai19058432019-02-27 21:46:29 -0800110 "struct": &knownpb.Value{
111 Kind: &knownpb.Value_StructValue{
112 StructValue: &knownpb.Struct{
113 Fields: map[string]*knownpb.Value{
114 "bool": &knownpb.Value{
115 Kind: &knownpb.Value_BoolValue{
Herbie Ong800c9902018-12-06 15:28:53 -0800116 BoolValue: false,
117 },
118 },
119 },
120 },
121 },
122 },
Joe Tsai19058432019-02-27 21:46:29 -0800123 "list": &knownpb.Value{
124 Kind: &knownpb.Value_ListValue{
125 ListValue: &knownpb.ListValue{
126 Values: []*knownpb.Value{
Herbie Ong800c9902018-12-06 15:28:53 -0800127 {
Joe Tsai19058432019-02-27 21:46:29 -0800128 Kind: &knownpb.Value_BoolValue{
Herbie Ong800c9902018-12-06 15:28:53 -0800129 BoolValue: false,
130 },
131 },
132 {
Joe Tsai19058432019-02-27 21:46:29 -0800133 Kind: &knownpb.Value_StringValue{
Herbie Ong800c9902018-12-06 15:28:53 -0800134 StringValue: "hello",
135 },
136 },
137 },
138 },
139 },
140 },
141 },
142 },
143 },
Herbie Ong66c365c2019-01-04 14:08:41 -0800144 }, {
145 desc: "Any field without registered type",
146 resolver: preg.NewTypes(),
147 message: func() proto.Message {
148 m := &pb2.Nested{
149 OptString: scalar.String("embedded inside Any"),
150 OptNested: &pb2.Nested{
151 OptString: scalar.String("inception"),
152 },
153 }
154 // TODO: Switch to V2 marshal when ready.
155 b, err := protoV1.Marshal(m)
156 if err != nil {
157 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
158 }
159 return &pb2.KnownTypes{
Joe Tsai19058432019-02-27 21:46:29 -0800160 OptAny: &knownpb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -0800161 TypeUrl: string(m.ProtoReflect().Type().FullName()),
162 Value: b,
163 },
164 }
165 }(),
166 }, {
167 desc: "Any field with registered type",
168 resolver: preg.NewTypes((&pb2.Nested{}).ProtoReflect().Type()),
169 message: func() proto.Message {
170 m := &pb2.Nested{
171 OptString: scalar.String("embedded inside Any"),
172 OptNested: &pb2.Nested{
173 OptString: scalar.String("inception"),
174 },
175 }
176 // TODO: Switch to V2 marshal when ready.
177 b, err := protoV1.Marshal(m)
178 if err != nil {
179 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
180 }
181 return &pb2.KnownTypes{
Joe Tsai19058432019-02-27 21:46:29 -0800182 OptAny: &knownpb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -0800183 TypeUrl: string(m.ProtoReflect().Type().FullName()),
184 Value: b,
185 },
186 }
187 }(),
188 }, {
189 desc: "Any field containing Any message",
190 resolver: func() *preg.Types {
191 mt1 := (&pb2.Nested{}).ProtoReflect().Type()
Joe Tsai19058432019-02-27 21:46:29 -0800192 mt2 := impl.Export{}.MessageTypeOf(&knownpb.Any{})
Herbie Ong66c365c2019-01-04 14:08:41 -0800193 return preg.NewTypes(mt1, mt2)
194 }(),
195 message: func() proto.Message {
196 m1 := &pb2.Nested{
197 OptString: scalar.String("message inside Any of another Any field"),
198 }
199 // TODO: Switch to V2 marshal when ready.
200 b1, err := protoV1.Marshal(m1)
201 if err != nil {
202 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
203 }
Joe Tsai19058432019-02-27 21:46:29 -0800204 m2 := &knownpb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -0800205 TypeUrl: "pb2.Nested",
206 Value: b1,
207 }
208 // TODO: Switch to V2 marshal when ready.
209 b2, err := protoV1.Marshal(m2)
210 if err != nil {
211 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
212 }
213 return &pb2.KnownTypes{
Joe Tsai19058432019-02-27 21:46:29 -0800214 OptAny: &knownpb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -0800215 TypeUrl: "google.protobuf.Any",
216 Value: b2,
217 },
218 }
219 }(),
Herbie Ong800c9902018-12-06 15:28:53 -0800220 }}
221
222 for _, tt := range tests {
223 tt := tt
224 t.Run(tt.desc, func(t *testing.T) {
225 t.Parallel()
Herbie Ong66c365c2019-01-04 14:08:41 -0800226 mo := textpb.MarshalOptions{Resolver: tt.resolver}
227 umo := textpb.UnmarshalOptions{Resolver: tt.resolver}
228
229 b, err := mo.Marshal(tt.message)
Herbie Ong800c9902018-12-06 15:28:53 -0800230 if err != nil {
231 t.Errorf("Marshal() returned error: %v\n\n", err)
232 }
Joe Tsai3bc7d6f2019-01-09 02:57:13 -0800233 gotMessage := tt.message.ProtoReflect().Type().New().Interface()
Herbie Ong66c365c2019-01-04 14:08:41 -0800234 err = umo.Unmarshal(gotMessage, b)
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
Herbie Ong70651952018-12-13 14:19:50 -0800239 if !protoV1.Equal(gotMessage.(protoV1.Message), tt.message.(protoV1.Message)) {
240 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}