1 // Go support for Protocol Buffers - Google's data interchange format
3 // Copyright 2011 The Go Authors. All rights reserved.
4 // https://github.com/golang/protobuf
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are
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
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.
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.
37 "github.com/golang/protobuf/proto"
39 proto3pb "github.com/golang/protobuf/proto/proto3_proto"
40 pb "github.com/golang/protobuf/proto/testdata"
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),
52 Others: []*pb.OtherMessage{
54 Value: []byte("some bytes"),
57 Somegroup: &pb.MyMessage_SomeGroup{
58 GroupField: proto.Int32(6),
60 RepBytes: [][]byte{[]byte("sham"), []byte("wow")},
65 Data: proto.String("extension"),
67 if err := proto.SetExtension(cloneTestMessage, pb.E_Ext_More, ext); err != nil {
68 panic("SetExtension: " + err.Error())
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)
78 // Verify it was a deep copy.
80 if proto.Equal(m, cloneTestMessage) {
81 t.Error("Mutating clone changed the original")
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")
87 if &m.Others[0] == &cloneTestMessage.Others[0] {
88 t.Error("Others: repeated field not copied")
90 if &m.Others[0].Value[0] == &cloneTestMessage.Others[0].Value[0] {
91 t.Error("Others[0].Value: bytes field not copied")
93 if &m.RepBytes[0] == &cloneTestMessage.RepBytes[0] {
94 t.Error("RepBytes: repeated field not copied")
96 if &m.RepBytes[0][0] == &cloneTestMessage.RepBytes[0][0] {
97 t.Error("RepBytes[0]: bytes field not copied")
101 func TestCloneNil(t *testing.T) {
103 if c := proto.Clone(m); !proto.Equal(m, c) {
104 t.Errorf("Clone(%v) = %v", m, c)
108 var mergeTests = []struct {
109 src, dst, want proto.Message
113 Count: proto.Int32(42),
116 Name: proto.String("Dave"),
119 Count: proto.Int32(42),
120 Name: proto.String("Dave"),
125 Inner: &pb.InnerMessage{
126 Host: proto.String("hey"),
127 Connected: proto.Bool(true),
129 Pet: []string{"horsey"},
130 Others: []*pb.OtherMessage{
132 Value: []byte("some bytes"),
137 Inner: &pb.InnerMessage{
138 Host: proto.String("niles"),
139 Port: proto.Int32(9099),
141 Pet: []string{"bunny", "kitty"},
142 Others: []*pb.OtherMessage{
144 Key: proto.Int64(31415926535),
147 // Explicitly test a src=nil field
153 Inner: &pb.InnerMessage{
154 Host: proto.String("hey"),
155 Connected: proto.Bool(true),
156 Port: proto.Int32(9099),
158 Pet: []string{"bunny", "kitty", "horsey"},
159 Others: []*pb.OtherMessage{
161 Key: proto.Int64(31415926535),
165 Value: []byte("some bytes"),
172 RepBytes: [][]byte{[]byte("wow")},
175 Somegroup: &pb.MyMessage_SomeGroup{
176 GroupField: proto.Int32(6),
178 RepBytes: [][]byte{[]byte("sham")},
181 Somegroup: &pb.MyMessage_SomeGroup{
182 GroupField: proto.Int32(6),
184 RepBytes: [][]byte{[]byte("sham"), []byte("wow")},
187 // Check that a scalar bytes field replaces rather than appends.
189 src: &pb.OtherMessage{Value: []byte("foo")},
190 dst: &pb.OtherMessage{Value: []byte("bar")},
191 want: &pb.OtherMessage{Value: []byte("foo")},
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),
202 ByteMapping: map[bool][]byte{true: []byte("wowsa")},
204 dst: &pb.MessageWithMap{
205 NameMapping: map[int32]string{
206 6: "Bruce", // should be overwritten
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
216 want: &pb.MessageWithMap{
217 NameMapping: map[int32]string{
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),
227 ByteMapping: map[bool][]byte{true: []byte("wowsa")},
230 // proto3 shouldn't merge zero values,
231 // in the same way that proto2 shouldn't merge nils.
233 src: &proto3pb.Message{
235 Data: []byte(""), // zero value, but not nil
237 dst: &proto3pb.Message{
239 Data: []byte("texas!"),
241 want: &proto3pb.Message{
244 Data: []byte("texas!"),
247 // Oneof fields should merge by assignment.
250 Union: &pb.Communique_Number{41},
253 Union: &pb.Communique_Name{"Bobby Tables"},
255 want: &pb.Communique{
256 Union: &pb.Communique_Number{41},
259 // Oneof nil is the same as not set.
261 src: &pb.Communique{},
263 Union: &pb.Communique_Name{"Bobby Tables"},
265 want: &pb.Communique{
266 Union: &pb.Communique_Name{"Bobby Tables"},
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
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
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"},
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)