OSDN Git Service

Merge pull request #41 from Bytom/dev
[bytom/vapor.git] / vendor / github.com / gogo / protobuf / proto / any_test.go
1 // Go support for Protocol Buffers - Google's data interchange format
2 //
3 // Copyright 2016 The Go Authors.  All rights reserved.
4 // https://github.com/golang/protobuf
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are
8 // met:
9 //
10 //     * Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 //     * Redistributions in binary form must reproduce the above
13 // copyright notice, this list of conditions and the following disclaimer
14 // in the documentation and/or other materials provided with the
15 // distribution.
16 //     * Neither the name of Google Inc. nor the names of its
17 // contributors may be used to endorse or promote products derived from
18 // this software without specific prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32 package proto_test
33
34 import (
35         "strings"
36         "testing"
37
38         "github.com/gogo/protobuf/proto"
39
40         pb "github.com/gogo/protobuf/proto/proto3_proto"
41         testpb "github.com/gogo/protobuf/proto/test_proto"
42         "github.com/gogo/protobuf/types"
43 )
44
45 var (
46         expandedMarshaler        = proto.TextMarshaler{ExpandAny: true}
47         expandedCompactMarshaler = proto.TextMarshaler{Compact: true, ExpandAny: true}
48 )
49
50 // anyEqual reports whether two messages which may be google.protobuf.Any or may
51 // contain google.protobuf.Any fields are equal. We can't use proto.Equal for
52 // comparison, because semantically equivalent messages may be marshaled to
53 // binary in different tag order. Instead, trust that TextMarshaler with
54 // ExpandAny option works and compare the text marshaling results.
55 func anyEqual(got, want proto.Message) bool {
56         // if messages are proto.Equal, no need to marshal.
57         if proto.Equal(got, want) {
58                 return true
59         }
60         g := expandedMarshaler.Text(got)
61         w := expandedMarshaler.Text(want)
62         return g == w
63 }
64
65 type golden struct {
66         m    proto.Message
67         t, c string
68 }
69
70 var goldenMessages = makeGolden()
71
72 func makeGolden() []golden {
73         nested := &pb.Nested{Bunny: "Monty"}
74         nb, err := proto.Marshal(nested)
75         if err != nil {
76                 panic(err)
77         }
78         m1 := &pb.Message{
79                 Name:        "David",
80                 ResultCount: 47,
81                 Anything:    &types.Any{TypeUrl: "type.googleapis.com/" + proto.MessageName(nested), Value: nb},
82         }
83         m2 := &pb.Message{
84                 Name:        "David",
85                 ResultCount: 47,
86                 Anything:    &types.Any{TypeUrl: "http://[::1]/type.googleapis.com/" + proto.MessageName(nested), Value: nb},
87         }
88         m3 := &pb.Message{
89                 Name:        "David",
90                 ResultCount: 47,
91                 Anything:    &types.Any{TypeUrl: `type.googleapis.com/"/` + proto.MessageName(nested), Value: nb},
92         }
93         m4 := &pb.Message{
94                 Name:        "David",
95                 ResultCount: 47,
96                 Anything:    &types.Any{TypeUrl: "type.googleapis.com/a/path/" + proto.MessageName(nested), Value: nb},
97         }
98         m5 := &types.Any{TypeUrl: "type.googleapis.com/" + proto.MessageName(nested), Value: nb}
99
100         any1 := &testpb.MyMessage{Count: proto.Int32(47), Name: proto.String("David")}
101         proto.SetExtension(any1, testpb.E_Ext_More, &testpb.Ext{Data: proto.String("foo")})
102         proto.SetExtension(any1, testpb.E_Ext_Text, proto.String("bar"))
103         any1b, err := proto.Marshal(any1)
104         if err != nil {
105                 panic(err)
106         }
107         any2 := &testpb.MyMessage{Count: proto.Int32(42), Bikeshed: testpb.MyMessage_GREEN.Enum(), RepBytes: [][]byte{[]byte("roboto")}}
108         proto.SetExtension(any2, testpb.E_Ext_More, &testpb.Ext{Data: proto.String("baz")})
109         any2b, err := proto.Marshal(any2)
110         if err != nil {
111                 panic(err)
112         }
113         m6 := &pb.Message{
114                 Name:        "David",
115                 ResultCount: 47,
116                 Anything:    &types.Any{TypeUrl: "type.googleapis.com/" + proto.MessageName(any1), Value: any1b},
117                 ManyThings: []*types.Any{
118                         {TypeUrl: "type.googleapis.com/" + proto.MessageName(any2), Value: any2b},
119                         {TypeUrl: "type.googleapis.com/" + proto.MessageName(any1), Value: any1b},
120                 },
121         }
122
123         const (
124                 m1Golden = `
125 name: "David"
126 result_count: 47
127 anything: <
128   [type.googleapis.com/proto3_proto.Nested]: <
129     bunny: "Monty"
130   >
131 >
132 `
133                 m2Golden = `
134 name: "David"
135 result_count: 47
136 anything: <
137   ["http://[::1]/type.googleapis.com/proto3_proto.Nested"]: <
138     bunny: "Monty"
139   >
140 >
141 `
142                 m3Golden = `
143 name: "David"
144 result_count: 47
145 anything: <
146   ["type.googleapis.com/\"/proto3_proto.Nested"]: <
147     bunny: "Monty"
148   >
149 >
150 `
151                 m4Golden = `
152 name: "David"
153 result_count: 47
154 anything: <
155   [type.googleapis.com/a/path/proto3_proto.Nested]: <
156     bunny: "Monty"
157   >
158 >
159 `
160                 m5Golden = `
161 [type.googleapis.com/proto3_proto.Nested]: <
162   bunny: "Monty"
163 >
164 `
165                 m6Golden = `
166 name: "David"
167 result_count: 47
168 anything: <
169   [type.googleapis.com/test_proto.MyMessage]: <
170     count: 47
171     name: "David"
172     [test_proto.Ext.more]: <
173       data: "foo"
174     >
175     [test_proto.Ext.text]: "bar"
176   >
177 >
178 many_things: <
179   [type.googleapis.com/test_proto.MyMessage]: <
180     count: 42
181     bikeshed: GREEN
182     rep_bytes: "roboto"
183     [test_proto.Ext.more]: <
184       data: "baz"
185     >
186   >
187 >
188 many_things: <
189   [type.googleapis.com/test_proto.MyMessage]: <
190     count: 47
191     name: "David"
192     [test_proto.Ext.more]: <
193       data: "foo"
194     >
195     [test_proto.Ext.text]: "bar"
196   >
197 >
198 `
199         )
200         return []golden{
201                 {m1, strings.TrimSpace(m1Golden) + "\n", strings.TrimSpace(compact(m1Golden)) + " "},
202                 {m2, strings.TrimSpace(m2Golden) + "\n", strings.TrimSpace(compact(m2Golden)) + " "},
203                 {m3, strings.TrimSpace(m3Golden) + "\n", strings.TrimSpace(compact(m3Golden)) + " "},
204                 {m4, strings.TrimSpace(m4Golden) + "\n", strings.TrimSpace(compact(m4Golden)) + " "},
205                 {m5, strings.TrimSpace(m5Golden) + "\n", strings.TrimSpace(compact(m5Golden)) + " "},
206                 {m6, strings.TrimSpace(m6Golden) + "\n", strings.TrimSpace(compact(m6Golden)) + " "},
207         }
208 }
209
210 func TestMarshalGolden(t *testing.T) {
211         for _, tt := range goldenMessages {
212                 if got, want := expandedMarshaler.Text(tt.m), tt.t; got != want {
213                         t.Errorf("message %v: got:\n%s\nwant:\n%s", tt.m, got, want)
214                 }
215                 if got, want := expandedCompactMarshaler.Text(tt.m), tt.c; got != want {
216                         t.Errorf("message %v: got:\n`%s`\nwant:\n`%s`", tt.m, got, want)
217                 }
218         }
219 }
220
221 func TestUnmarshalGolden(t *testing.T) {
222         for _, tt := range goldenMessages {
223                 want := tt.m
224                 got := proto.Clone(tt.m)
225                 got.Reset()
226                 if err := proto.UnmarshalText(tt.t, got); err != nil {
227                         t.Errorf("failed to unmarshal\n%s\nerror: %v", tt.t, err)
228                 }
229                 if !anyEqual(got, want) {
230                         t.Errorf("message:\n%s\ngot:\n%s\nwant:\n%s", tt.t, got, want)
231                 }
232                 got.Reset()
233                 if err := proto.UnmarshalText(tt.c, got); err != nil {
234                         t.Errorf("failed to unmarshal\n%s\nerror: %v", tt.c, err)
235                 }
236                 if !anyEqual(got, want) {
237                         t.Errorf("message:\n%s\ngot:\n%s\nwant:\n%s", tt.c, got, want)
238                 }
239         }
240 }
241
242 func TestMarshalUnknownAny(t *testing.T) {
243         m := &pb.Message{
244                 Anything: &types.Any{
245                         TypeUrl: "foo",
246                         Value:   []byte("bar"),
247                 },
248         }
249         want := `anything: <
250   type_url: "foo"
251   value: "bar"
252 >
253 `
254         got := expandedMarshaler.Text(m)
255         if got != want {
256                 t.Errorf("got\n`%s`\nwant\n`%s`", got, want)
257         }
258 }
259
260 func TestAmbiguousAny(t *testing.T) {
261         pb := &types.Any{}
262         err := proto.UnmarshalText(`
263         type_url: "ttt/proto3_proto.Nested"
264         value: "\n\x05Monty"
265         `, pb)
266         t.Logf("result: %v (error: %v)", expandedMarshaler.Text(pb), err)
267         if err != nil {
268                 t.Errorf("failed to parse ambiguous Any message: %v", err)
269         }
270 }
271
272 func TestUnmarshalOverwriteAny(t *testing.T) {
273         pb := &types.Any{}
274         err := proto.UnmarshalText(`
275   [type.googleapis.com/a/path/proto3_proto.Nested]: <
276     bunny: "Monty"
277   >
278   [type.googleapis.com/a/path/proto3_proto.Nested]: <
279     bunny: "Rabbit of Caerbannog"
280   >
281         `, pb)
282         want := `line 7: Any message unpacked multiple times, or "type_url" already set`
283         if err.Error() != want {
284                 t.Errorf("incorrect error.\nHave: %v\nWant: %v", err.Error(), want)
285         }
286 }
287
288 func TestUnmarshalAnyMixAndMatch(t *testing.T) {
289         pb := &types.Any{}
290         err := proto.UnmarshalText(`
291         value: "\n\x05Monty"
292   [type.googleapis.com/a/path/proto3_proto.Nested]: <
293     bunny: "Rabbit of Caerbannog"
294   >
295         `, pb)
296         want := `line 5: Any message unpacked multiple times, or "value" already set`
297         if err.Error() != want {
298                 t.Errorf("incorrect error.\nHave: %v\nWant: %v", err.Error(), want)
299         }
300 }