blob: 008c0901c778d18d0569dba663ec462a67bc61e2 [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"
Damien Neile89e6242019-05-13 23:55:40 -07007 "google.golang.org/protobuf/encoding/textpb"
8 "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"
15 knownpb "google.golang.org/protobuf/types/known"
Herbie Ong800c9902018-12-06 15:28:53 -080016)
17
18func TestRoundTrip(t *testing.T) {
19 tests := []struct {
Herbie Ong66c365c2019-01-04 14:08:41 -080020 desc string
21 resolver *preg.Types
22 message proto.Message
Herbie Ong800c9902018-12-06 15:28:53 -080023 }{{
24 desc: "well-known type fields set to empty messages",
25 message: &pb2.KnownTypes{
Joe Tsai19058432019-02-27 21:46:29 -080026 OptBool: &knownpb.BoolValue{},
27 OptInt32: &knownpb.Int32Value{},
28 OptInt64: &knownpb.Int64Value{},
29 OptUint32: &knownpb.UInt32Value{},
30 OptUint64: &knownpb.UInt64Value{},
31 OptFloat: &knownpb.FloatValue{},
32 OptDouble: &knownpb.DoubleValue{},
33 OptString: &knownpb.StringValue{},
34 OptBytes: &knownpb.BytesValue{},
35 OptDuration: &knownpb.Duration{},
36 OptTimestamp: &knownpb.Timestamp{},
37 OptStruct: &knownpb.Struct{},
38 OptList: &knownpb.ListValue{},
39 OptValue: &knownpb.Value{},
40 OptEmpty: &knownpb.Empty{},
41 OptAny: &knownpb.Any{},
Herbie Ong800c9902018-12-06 15:28:53 -080042 },
43 }, {
44 desc: "well-known type scalar fields",
45 message: &pb2.KnownTypes{
Joe Tsai19058432019-02-27 21:46:29 -080046 OptBool: &knownpb.BoolValue{
Herbie Ong800c9902018-12-06 15:28:53 -080047 Value: true,
48 },
Joe Tsai19058432019-02-27 21:46:29 -080049 OptInt32: &knownpb.Int32Value{
Herbie Ong800c9902018-12-06 15:28:53 -080050 Value: -42,
51 },
Joe Tsai19058432019-02-27 21:46:29 -080052 OptInt64: &knownpb.Int64Value{
Herbie Ong800c9902018-12-06 15:28:53 -080053 Value: -42,
54 },
Joe Tsai19058432019-02-27 21:46:29 -080055 OptUint32: &knownpb.UInt32Value{
Herbie Ong800c9902018-12-06 15:28:53 -080056 Value: 0xff,
57 },
Joe Tsai19058432019-02-27 21:46:29 -080058 OptUint64: &knownpb.UInt64Value{
Herbie Ong800c9902018-12-06 15:28:53 -080059 Value: 0xffff,
60 },
Joe Tsai19058432019-02-27 21:46:29 -080061 OptFloat: &knownpb.FloatValue{
Herbie Ong800c9902018-12-06 15:28:53 -080062 Value: 1.234,
63 },
Joe Tsai19058432019-02-27 21:46:29 -080064 OptDouble: &knownpb.DoubleValue{
Herbie Ong800c9902018-12-06 15:28:53 -080065 Value: 1.23e308,
66 },
Joe Tsai19058432019-02-27 21:46:29 -080067 OptString: &knownpb.StringValue{
Herbie Ong800c9902018-12-06 15:28:53 -080068 Value: "谷歌",
69 },
Joe Tsai19058432019-02-27 21:46:29 -080070 OptBytes: &knownpb.BytesValue{
Herbie Ong800c9902018-12-06 15:28:53 -080071 Value: []byte("\xe8\xb0\xb7\xe6\xad\x8c"),
72 },
73 },
74 }, {
75 desc: "well-known type time-related fields",
76 message: &pb2.KnownTypes{
Joe Tsai19058432019-02-27 21:46:29 -080077 OptDuration: &knownpb.Duration{
Herbie Ong800c9902018-12-06 15:28:53 -080078 Seconds: -3600,
79 Nanos: -123,
80 },
Joe Tsai19058432019-02-27 21:46:29 -080081 OptTimestamp: &knownpb.Timestamp{
Herbie Ong800c9902018-12-06 15:28:53 -080082 Seconds: 1257894000,
83 Nanos: 123,
84 },
85 },
86 }, {
Herbie Ong66c365c2019-01-04 14:08:41 -080087 desc: "Struct field and different Value types",
Herbie Ong800c9902018-12-06 15:28:53 -080088 message: &pb2.KnownTypes{
Joe Tsai19058432019-02-27 21:46:29 -080089 OptStruct: &knownpb.Struct{
90 Fields: map[string]*knownpb.Value{
91 "bool": &knownpb.Value{
92 Kind: &knownpb.Value_BoolValue{
Herbie Ong800c9902018-12-06 15:28:53 -080093 BoolValue: true,
94 },
95 },
Joe Tsai19058432019-02-27 21:46:29 -080096 "double": &knownpb.Value{
97 Kind: &knownpb.Value_NumberValue{
Herbie Ong800c9902018-12-06 15:28:53 -080098 NumberValue: 3.1415,
99 },
100 },
Joe Tsai19058432019-02-27 21:46:29 -0800101 "null": &knownpb.Value{
102 Kind: &knownpb.Value_NullValue{
103 NullValue: knownpb.NullValue_NULL_VALUE,
Herbie Ong800c9902018-12-06 15:28:53 -0800104 },
105 },
Joe Tsai19058432019-02-27 21:46:29 -0800106 "string": &knownpb.Value{
107 Kind: &knownpb.Value_StringValue{
Herbie Ong800c9902018-12-06 15:28:53 -0800108 StringValue: "string",
109 },
110 },
Joe Tsai19058432019-02-27 21:46:29 -0800111 "struct": &knownpb.Value{
112 Kind: &knownpb.Value_StructValue{
113 StructValue: &knownpb.Struct{
114 Fields: map[string]*knownpb.Value{
115 "bool": &knownpb.Value{
116 Kind: &knownpb.Value_BoolValue{
Herbie Ong800c9902018-12-06 15:28:53 -0800117 BoolValue: false,
118 },
119 },
120 },
121 },
122 },
123 },
Joe Tsai19058432019-02-27 21:46:29 -0800124 "list": &knownpb.Value{
125 Kind: &knownpb.Value_ListValue{
126 ListValue: &knownpb.ListValue{
127 Values: []*knownpb.Value{
Herbie Ong800c9902018-12-06 15:28:53 -0800128 {
Joe Tsai19058432019-02-27 21:46:29 -0800129 Kind: &knownpb.Value_BoolValue{
Herbie Ong800c9902018-12-06 15:28:53 -0800130 BoolValue: false,
131 },
132 },
133 {
Joe Tsai19058432019-02-27 21:46:29 -0800134 Kind: &knownpb.Value_StringValue{
Herbie Ong800c9902018-12-06 15:28:53 -0800135 StringValue: "hello",
136 },
137 },
138 },
139 },
140 },
141 },
142 },
143 },
144 },
Herbie Ong66c365c2019-01-04 14:08:41 -0800145 }, {
146 desc: "Any field without registered type",
147 resolver: preg.NewTypes(),
148 message: func() proto.Message {
149 m := &pb2.Nested{
150 OptString: scalar.String("embedded inside Any"),
151 OptNested: &pb2.Nested{
152 OptString: scalar.String("inception"),
153 },
154 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -0700155 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ong66c365c2019-01-04 14:08:41 -0800156 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{
Joe Tsai0fc49f82019-05-01 12:29:25 -0700161 TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
Herbie Ong66c365c2019-01-04 14:08:41 -0800162 Value: b,
163 },
164 }
165 }(),
166 }, {
167 desc: "Any field with registered type",
Joe Tsai0fc49f82019-05-01 12:29:25 -0700168 resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
169 message: func() *pb2.KnownTypes {
Herbie Ong66c365c2019-01-04 14:08:41 -0800170 m := &pb2.Nested{
171 OptString: scalar.String("embedded inside Any"),
172 OptNested: &pb2.Nested{
173 OptString: scalar.String("inception"),
174 },
175 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -0700176 b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
Herbie Ong66c365c2019-01-04 14:08:41 -0800177 if err != nil {
178 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
179 }
180 return &pb2.KnownTypes{
Joe Tsai19058432019-02-27 21:46:29 -0800181 OptAny: &knownpb.Any{
Joe Tsai0fc49f82019-05-01 12:29:25 -0700182 TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
Herbie Ong66c365c2019-01-04 14:08:41 -0800183 Value: b,
184 },
185 }
186 }(),
187 }, {
188 desc: "Any field containing Any message",
189 resolver: func() *preg.Types {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700190 mt1 := impl.Export{}.MessageTypeOf(&pb2.Nested{})
Joe Tsai19058432019-02-27 21:46:29 -0800191 mt2 := impl.Export{}.MessageTypeOf(&knownpb.Any{})
Herbie Ong66c365c2019-01-04 14:08:41 -0800192 return preg.NewTypes(mt1, mt2)
193 }(),
Joe Tsai0fc49f82019-05-01 12:29:25 -0700194 message: func() *pb2.KnownTypes {
Herbie Ong66c365c2019-01-04 14:08:41 -0800195 m1 := &pb2.Nested{
196 OptString: scalar.String("message inside Any of another Any field"),
197 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -0700198 b1, err := proto.MarshalOptions{Deterministic: true}.Marshal(m1)
Herbie Ong66c365c2019-01-04 14:08:41 -0800199 if err != nil {
200 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
201 }
Joe Tsai19058432019-02-27 21:46:29 -0800202 m2 := &knownpb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -0800203 TypeUrl: "pb2.Nested",
204 Value: b1,
205 }
Herbie Ong4d1c3be2019-03-15 18:22:36 -0700206 b2, err := proto.MarshalOptions{Deterministic: true}.Marshal(m2)
Herbie Ong66c365c2019-01-04 14:08:41 -0800207 if err != nil {
208 t.Fatalf("error in binary marshaling message for Any.value: %v", err)
209 }
210 return &pb2.KnownTypes{
Joe Tsai19058432019-02-27 21:46:29 -0800211 OptAny: &knownpb.Any{
Herbie Ong66c365c2019-01-04 14:08:41 -0800212 TypeUrl: "google.protobuf.Any",
213 Value: b2,
214 },
215 }
216 }(),
Herbie Ong800c9902018-12-06 15:28:53 -0800217 }}
218
219 for _, tt := range tests {
220 tt := tt
221 t.Run(tt.desc, func(t *testing.T) {
222 t.Parallel()
Joe Tsai0fc49f82019-05-01 12:29:25 -0700223 b, err := textpb.MarshalOptions{Resolver: tt.resolver}.Marshal(tt.message)
Herbie Ong800c9902018-12-06 15:28:53 -0800224 if err != nil {
225 t.Errorf("Marshal() returned error: %v\n\n", err)
226 }
Joe Tsai0fc49f82019-05-01 12:29:25 -0700227
228 gotMessage := new(pb2.KnownTypes)
229 err = textpb.UnmarshalOptions{Resolver: tt.resolver}.Unmarshal(gotMessage, b)
Herbie Ong800c9902018-12-06 15:28:53 -0800230 if err != nil {
231 t.Errorf("Unmarshal() returned error: %v\n\n", err)
232 }
Herbie Ong66c365c2019-01-04 14:08:41 -0800233
Joe Tsai0fc49f82019-05-01 12:29:25 -0700234 if !protoV1.Equal(gotMessage, tt.message.(protoV1.Message)) {
Herbie Ong70651952018-12-13 14:19:50 -0800235 t.Errorf("Unmarshal()\n<got>\n%v\n<want>\n%v\n", gotMessage, tt.message)
236 }
Herbie Ong800c9902018-12-06 15:28:53 -0800237 })
238 }
239}