github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/golang/protobuf/proto/clone_test.go (about) 1 // Go support for Protocol Buffers - Google's data interchange format 2 // 3 // Copyright 2011 The Go Authors. All rights reserved. 4 // https://yougam/libraries/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/insionng/yougam/libraries/golang/protobuf/proto" 38 39 proto3pb "github.com/insionng/yougam/libraries/golang/protobuf/proto/proto3_proto" 40 pb "github.com/insionng/yougam/libraries/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 }, 199 ByteMapping: map[bool][]byte{true: []byte("wowsa")}, 200 }, 201 dst: &pb.MessageWithMap{ 202 NameMapping: map[int32]string{ 203 6: "Bruce", // should be overwritten 204 7: "Andrew", 205 }, 206 }, 207 want: &pb.MessageWithMap{ 208 NameMapping: map[int32]string{ 209 6: "Nigel", 210 7: "Andrew", 211 }, 212 MsgMapping: map[int64]*pb.FloatingPoint{ 213 0x4001: &pb.FloatingPoint{F: proto.Float64(2.0)}, 214 }, 215 ByteMapping: map[bool][]byte{true: []byte("wowsa")}, 216 }, 217 }, 218 // proto3 shouldn't merge zero values, 219 // in the same way that proto2 shouldn't merge nils. 220 { 221 src: &proto3pb.Message{ 222 Name: "Aaron", 223 Data: []byte(""), // zero value, but not nil 224 }, 225 dst: &proto3pb.Message{ 226 HeightInCm: 176, 227 Data: []byte("texas!"), 228 }, 229 want: &proto3pb.Message{ 230 Name: "Aaron", 231 HeightInCm: 176, 232 Data: []byte("texas!"), 233 }, 234 }, 235 // Oneof fields should merge by assignment. 236 { 237 src: &pb.Communique{ 238 Union: &pb.Communique_Number{41}, 239 }, 240 dst: &pb.Communique{ 241 Union: &pb.Communique_Name{"Bobby Tables"}, 242 }, 243 want: &pb.Communique{ 244 Union: &pb.Communique_Number{41}, 245 }, 246 }, 247 // Oneof nil is the same as not set. 248 { 249 src: &pb.Communique{}, 250 dst: &pb.Communique{ 251 Union: &pb.Communique_Name{"Bobby Tables"}, 252 }, 253 want: &pb.Communique{ 254 Union: &pb.Communique_Name{"Bobby Tables"}, 255 }, 256 }, 257 } 258 259 func TestMerge(t *testing.T) { 260 for _, m := range mergeTests { 261 got := proto.Clone(m.dst) 262 proto.Merge(got, m.src) 263 if !proto.Equal(got, m.want) { 264 t.Errorf("Merge(%v, %v)\n got %v\nwant %v\n", m.dst, m.src, got, m.want) 265 } 266 } 267 }