blob: d9118a736ebc8fe6918e94aba243925c62df9618 [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 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -0700154 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ong66c365c2019-01-04 14:08:41 -0800155 if err != nil {
156 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
157 }
158 return &pb2.KnownTypes{
Joe Tsai19058432019-02-27 21:46:29 -0800159 OptAny: &knownpb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -0800160 TypeUrl: string(m.ProtoReflect().Type().FullName()),
161 Value: b,
162 },
163 }
164 }(),
165 }, {
166 desc: "Any field with registered type",
167 resolver: preg.NewTypes((&pb2.Nested{}).ProtoReflect().Type()),
168 message: func() proto.Message {
169 m := &pb2.Nested{
170 OptString: scalar.String("embedded inside Any"),
171 OptNested: &pb2.Nested{
172 OptString: scalar.String("inception"),
173 },
174 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -0700175 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ong66c365c2019-01-04 14:08:41 -0800176 if err != nil {
177 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
178 }
179 return &pb2.KnownTypes{
Joe Tsai19058432019-02-27 21:46:29 -0800180 OptAny: &knownpb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -0800181 TypeUrl: string(m.ProtoReflect().Type().FullName()),
182 Value: b,
183 },
184 }
185 }(),
186 }, {
187 desc: "Any field containing Any message",
188 resolver: func() *preg.Types {
189 mt1 := (&pb2.Nested{}).ProtoReflect().Type()
Joe Tsai19058432019-02-27 21:46:29 -0800190 mt2 := impl.Export{}.MessageTypeOf(&knownpb.Any{})
Herbie Ong66c365c2019-01-04 14:08:41 -0800191 return preg.NewTypes(mt1, mt2)
192 }(),
193 message: func() proto.Message {
194 m1 := &pb2.Nested{
195 OptString: scalar.String("message inside Any of another Any field"),
196 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -0700197 b1, err := proto.MarshalOptions{Deterministic: true}.Marshal(m1)
Herbie Ong66c365c2019-01-04 14:08:41 -0800198 if err != nil {
199 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
200 }
Joe Tsai19058432019-02-27 21:46:29 -0800201 m2 := &knownpb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -0800202 TypeUrl: "pb2.Nested",
203 Value: b1,
204 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -0700205 b2, err := proto.MarshalOptions{Deterministic: true}.Marshal(m2)
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 }
209 return &pb2.KnownTypes{
Joe Tsai19058432019-02-27 21:46:29 -0800210 OptAny: &knownpb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -0800211 TypeUrl: "google.protobuf.Any",
212 Value: b2,
213 },
214 }
215 }(),
Herbie Ong800c9902018-12-06 15:28:53 -0800216 }}
217
218 for _, tt := range tests {
219 tt := tt
220 t.Run(tt.desc, func(t *testing.T) {
221 t.Parallel()
Herbie Ong66c365c2019-01-04 14:08:41 -0800222 mo := textpb.MarshalOptions{Resolver: tt.resolver}
223 umo := textpb.UnmarshalOptions{Resolver: tt.resolver}
224
225 b, err := mo.Marshal(tt.message)
Herbie Ong800c9902018-12-06 15:28:53 -0800226 if err != nil {
227 t.Errorf("Marshal() returned error: %v\n\n", err)
228 }
Joe Tsai3bc7d6f2019-01-09 02:57:13 -0800229 gotMessage := tt.message.ProtoReflect().Type().New().Interface()
Herbie Ong66c365c2019-01-04 14:08:41 -0800230 err = umo.Unmarshal(gotMessage, b)
Herbie Ong800c9902018-12-06 15:28:53 -0800231 if err != nil {
232 t.Errorf("Unmarshal() returned error: %v\n\n", err)
233 }
Herbie Ong66c365c2019-01-04 14:08:41 -0800234
Herbie Ong70651952018-12-13 14:19:50 -0800235 if !protoV1.Equal(gotMessage.(protoV1.Message), tt.message.(protoV1.Message)) {
236 t.Errorf("Unmarshal()\n<got>\n%v\n<want>\n%v\n", gotMessage, tt.message)
237 }
Herbie Ong800c9902018-12-06 15:28:53 -0800238 })
239 }
240}