OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / golang / protobuf / proto / clone_test.go
1 // Go support for Protocol Buffers - Google's data interchange format
2 //
3 // Copyright 2011 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         "testing"
36
37         "github.com/golang/protobuf/proto"
38
39         proto3pb "github.com/golang/protobuf/proto/proto3_proto"
40         pb "github.com/golang/protobuf/proto/testdata"
41 )
42
43 var cloneTestMessage = &pb.MyMessage{
44         Count: proto.Int32(42),
45         Name:  proto.String("Dave"),
46         Pet:   []string{"bunny", "kitty", "horsey"},
47         Inner: &pb.InnerMessage{
48                 Host:      proto.String("niles"),
49                 Port:      proto.Int32(9099),
50                 Connected: proto.Bool(true),
51         },
52         Others: []*pb.OtherMessage{
53                 {
54                         Value: []byte("some bytes"),
55                 },
56         },
57         Somegroup: &pb.MyMessage_SomeGroup{
58                 GroupField: proto.Int32(6),
59         },
60         RepBytes: [][]byte{[]byte("sham"), []byte("wow")},
61 }
62
63 func init() {
64         ext := &pb.Ext{
65                 Data: proto.String("extension"),
66         }
67         if err := proto.SetExtension(cloneTestMessage, pb.E_Ext_More, ext); err != nil {
68                 panic("SetExtension: " + err.Error())
69         }
70 }
71
72 func TestClone(t *testing.T) {
73         m := proto.Clone(cloneTestMessage).(*pb.MyMessage)
74         if !proto.Equal(m, cloneTestMessage) {
75                 t.Errorf("Clone(%v) = %v", cloneTestMessage, m)
76         }
77
78         // Verify it was a deep copy.
79         *m.Inner.Port++
80         if proto.Equal(m, cloneTestMessage) {
81                 t.Error("Mutating clone changed the original")
82         }
83         // Byte fields and repeated fields should be copied.
84         if &m.Pet[0] == &cloneTestMessage.Pet[0] {
85                 t.Error("Pet: repeated field not copied")
86         }
87         if &m.Others[0] == &cloneTestMessage.Others[0] {
88                 t.Error("Others: repeated field not copied")
89         }
90         if &m.Others[0].Value[0] == &cloneTestMessage.Others[0].Value[0] {
91                 t.Error("Others[0].Value: bytes field not copied")
92         }
93         if &m.RepBytes[0] == &cloneTestMessage.RepBytes[0] {
94                 t.Error("RepBytes: repeated field not copied")
95         }
96         if &m.RepBytes[0][0] == &cloneTestMessage.RepBytes[0][0] {
97                 t.Error("RepBytes[0]: bytes field not copied")
98         }
99 }
100
101 func TestCloneNil(t *testing.T) {
102         var m *pb.MyMessage
103         if c := proto.Clone(m); !proto.Equal(m, c) {
104                 t.Errorf("Clone(%v) = %v", m, c)
105         }
106 }
107
108 var mergeTests = []struct {
109         src, dst, want proto.Message
110 }{
111         {
112                 src: &pb.MyMessage{
113                         Count: proto.Int32(42),
114                 },
115                 dst: &pb.MyMessage{
116                         Name: proto.String("Dave"),
117                 },
118                 want: &pb.MyMessage{
119                         Count: proto.Int32(42),
120                         Name:  proto.String("Dave"),
121                 },
122         },
123         {
124                 src: &pb.MyMessage{
125                         Inner: &pb.InnerMessage{
126                                 Host:      proto.String("hey"),
127                                 Connected: proto.Bool(true),
128                         },
129                         Pet: []string{"horsey"},
130                         Others: []*pb.OtherMessage{
131                                 {
132                                         Value: []byte("some bytes"),
133                                 },
134                         },
135                 },
136                 dst: &pb.MyMessage{
137                         Inner: &pb.InnerMessage{
138                                 Host: proto.String("niles"),
139                                 Port: proto.Int32(9099),
140                         },
141                         Pet: []string{"bunny", "kitty"},
142                         Others: []*pb.OtherMessage{
143                                 {
144                                         Key: proto.Int64(31415926535),
145                                 },
146                                 {
147                                         // Explicitly test a src=nil field
148                                         Inner: nil,
149                                 },
150                         },
151                 },
152                 want: &pb.MyMessage{
153                         Inner: &pb.InnerMessage{
154                                 Host:      proto.String("hey"),
155                                 Connected: proto.Bool(true),
156                                 Port:      proto.Int32(9099),
157                         },
158                         Pet: []string{"bunny", "kitty", "horsey"},
159                         Others: []*pb.OtherMessage{
160                                 {
161                                         Key: proto.Int64(31415926535),
162                                 },
163                                 {},
164                                 {
165                                         Value: []byte("some bytes"),
166                                 },
167                         },
168                 },
169         },
170         {
171                 src: &pb.MyMessage{
172                         RepBytes: [][]byte{[]byte("wow")},
173                 },
174                 dst: &pb.MyMessage{
175                         Somegroup: &pb.MyMessage_SomeGroup{
176                                 GroupField: proto.Int32(6),
177                         },
178                         RepBytes: [][]byte{[]byte("sham")},
179                 },
180                 want: &pb.MyMessage{
181                         Somegroup: &pb.MyMessage_SomeGroup{
182                                 GroupField: proto.Int32(6),
183                         },
184                         RepBytes: [][]byte{[]byte("sham"), []byte("wow")},
185                 },
186         },
187         // Check that a scalar bytes field replaces rather than appends.
188         {
189                 src:  &pb.OtherMessage{Value: []byte("foo")},
190                 dst:  &pb.OtherMessage{Value: []byte("bar")},
191                 want: &pb.OtherMessage{Value: []byte("foo")},
192         },
193         {
194                 src: &pb.MessageWithMap{
195                         NameMapping: map[int32]string{6: "Nigel"},
196                         MsgMapping: map[int64]*pb.FloatingPoint{
197                                 0x4001: &pb.FloatingPoint{F: proto.Float64(2.0)},
198                                 0x4002: &pb.FloatingPoint{
199                                         F: proto.Float64(2.0),
200                                 },
201                         },
202                         ByteMapping: map[bool][]byte{true: []byte("wowsa")},
203                 },
204                 dst: &pb.MessageWithMap{
205                         NameMapping: map[int32]string{
206                                 6: "Bruce", // should be overwritten
207                                 7: "Andrew",
208                         },
209                         MsgMapping: map[int64]*pb.FloatingPoint{
210                                 0x4002: &pb.FloatingPoint{
211                                         F:     proto.Float64(3.0),
212                                         Exact: proto.Bool(true),
213                                 }, // the entire message should be overwritten
214                         },
215                 },
216                 want: &pb.MessageWithMap{
217                         NameMapping: map[int32]string{
218                                 6: "Nigel",
219                                 7: "Andrew",
220                         },
221                         MsgMapping: map[int64]*pb.FloatingPoint{
222                                 0x4001: &pb.FloatingPoint{F: proto.Float64(2.0)},
223                                 0x4002: &pb.FloatingPoint{
224                                         F: proto.Float64(2.0),
225                                 },
226                         },
227                         ByteMapping: map[bool][]byte{true: []byte("wowsa")},
228                 },
229         },
230         // proto3 shouldn't merge zero values,
231         // in the same way that proto2 shouldn't merge nils.
232         {
233                 src: &proto3pb.Message{
234                         Name: "Aaron",
235                         Data: []byte(""), // zero value, but not nil
236                 },
237                 dst: &proto3pb.Message{
238                         HeightInCm: 176,
239                         Data:       []byte("texas!"),
240                 },
241                 want: &proto3pb.Message{
242                         Name:       "Aaron",
243                         HeightInCm: 176,
244                         Data:       []byte("texas!"),
245                 },
246         },
247         // Oneof fields should merge by assignment.
248         {
249                 src: &pb.Communique{
250                         Union: &pb.Communique_Number{41},
251                 },
252                 dst: &pb.Communique{
253                         Union: &pb.Communique_Name{"Bobby Tables"},
254                 },
255                 want: &pb.Communique{
256                         Union: &pb.Communique_Number{41},
257                 },
258         },
259         // Oneof nil is the same as not set.
260         {
261                 src: &pb.Communique{},
262                 dst: &pb.Communique{
263                         Union: &pb.Communique_Name{"Bobby Tables"},
264                 },
265                 want: &pb.Communique{
266                         Union: &pb.Communique_Name{"Bobby Tables"},
267                 },
268         },
269         {
270                 src: &proto3pb.Message{
271                         Terrain: map[string]*proto3pb.Nested{
272                                 "kay_a": &proto3pb.Nested{Cute: true},      // replace
273                                 "kay_b": &proto3pb.Nested{Bunny: "rabbit"}, // insert
274                         },
275                 },
276                 dst: &proto3pb.Message{
277                         Terrain: map[string]*proto3pb.Nested{
278                                 "kay_a": &proto3pb.Nested{Bunny: "lost"},  // replaced
279                                 "kay_c": &proto3pb.Nested{Bunny: "bunny"}, // keep
280                         },
281                 },
282                 want: &proto3pb.Message{
283                         Terrain: map[string]*proto3pb.Nested{
284                                 "kay_a": &proto3pb.Nested{Cute: true},
285                                 "kay_b": &proto3pb.Nested{Bunny: "rabbit"},
286                                 "kay_c": &proto3pb.Nested{Bunny: "bunny"},
287                         },
288                 },
289         },
290 }
291
292 func TestMerge(t *testing.T) {
293         for _, m := range mergeTests {
294                 got := proto.Clone(m.dst)
295                 proto.Merge(got, m.src)
296                 if !proto.Equal(got, m.want) {
297                         t.Errorf("Merge(%v, %v)\n got %v\nwant %v\n", m.dst, m.src, got, m.want)
298                 }
299         }
300 }