github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/golang/protobuf/proto/extensions_test.go (about) 1 // Go support for Protocol Buffers - Google's data interchange format 2 // 3 // Copyright 2014 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 "bytes" 36 "fmt" 37 "reflect" 38 "testing" 39 40 "github.com/insionng/yougam/libraries/golang/protobuf/proto" 41 pb "github.com/insionng/yougam/libraries/golang/protobuf/proto/testdata" 42 ) 43 44 func TestGetExtensionsWithMissingExtensions(t *testing.T) { 45 msg := &pb.MyMessage{} 46 ext1 := &pb.Ext{} 47 if err := proto.SetExtension(msg, pb.E_Ext_More, ext1); err != nil { 48 t.Fatalf("Could not set ext1: %s", ext1) 49 } 50 exts, err := proto.GetExtensions(msg, []*proto.ExtensionDesc{ 51 pb.E_Ext_More, 52 pb.E_Ext_Text, 53 }) 54 if err != nil { 55 t.Fatalf("GetExtensions() failed: %s", err) 56 } 57 if exts[0] != ext1 { 58 t.Errorf("ext1 not in returned extensions: %T %v", exts[0], exts[0]) 59 } 60 if exts[1] != nil { 61 t.Errorf("ext2 in returned extensions: %T %v", exts[1], exts[1]) 62 } 63 } 64 65 func TestGetExtensionStability(t *testing.T) { 66 check := func(m *pb.MyMessage) bool { 67 ext1, err := proto.GetExtension(m, pb.E_Ext_More) 68 if err != nil { 69 t.Fatalf("GetExtension() failed: %s", err) 70 } 71 ext2, err := proto.GetExtension(m, pb.E_Ext_More) 72 if err != nil { 73 t.Fatalf("GetExtension() failed: %s", err) 74 } 75 return ext1 == ext2 76 } 77 msg := &pb.MyMessage{Count: proto.Int32(4)} 78 ext0 := &pb.Ext{} 79 if err := proto.SetExtension(msg, pb.E_Ext_More, ext0); err != nil { 80 t.Fatalf("Could not set ext1: %s", ext0) 81 } 82 if !check(msg) { 83 t.Errorf("GetExtension() not stable before marshaling") 84 } 85 bb, err := proto.Marshal(msg) 86 if err != nil { 87 t.Fatalf("Marshal() failed: %s", err) 88 } 89 msg1 := &pb.MyMessage{} 90 err = proto.Unmarshal(bb, msg1) 91 if err != nil { 92 t.Fatalf("Unmarshal() failed: %s", err) 93 } 94 if !check(msg1) { 95 t.Errorf("GetExtension() not stable after unmarshaling") 96 } 97 } 98 99 func TestGetExtensionDefaults(t *testing.T) { 100 var setFloat64 float64 = 1 101 var setFloat32 float32 = 2 102 var setInt32 int32 = 3 103 var setInt64 int64 = 4 104 var setUint32 uint32 = 5 105 var setUint64 uint64 = 6 106 var setBool = true 107 var setBool2 = false 108 var setString = "Goodnight string" 109 var setBytes = []byte("Goodnight bytes") 110 var setEnum = pb.DefaultsMessage_TWO 111 112 type testcase struct { 113 ext *proto.ExtensionDesc // Extension we are testing. 114 want interface{} // Expected value of extension, or nil (meaning that GetExtension will fail). 115 def interface{} // Expected value of extension after ClearExtension(). 116 } 117 tests := []testcase{ 118 {pb.E_NoDefaultDouble, setFloat64, nil}, 119 {pb.E_NoDefaultFloat, setFloat32, nil}, 120 {pb.E_NoDefaultInt32, setInt32, nil}, 121 {pb.E_NoDefaultInt64, setInt64, nil}, 122 {pb.E_NoDefaultUint32, setUint32, nil}, 123 {pb.E_NoDefaultUint64, setUint64, nil}, 124 {pb.E_NoDefaultSint32, setInt32, nil}, 125 {pb.E_NoDefaultSint64, setInt64, nil}, 126 {pb.E_NoDefaultFixed32, setUint32, nil}, 127 {pb.E_NoDefaultFixed64, setUint64, nil}, 128 {pb.E_NoDefaultSfixed32, setInt32, nil}, 129 {pb.E_NoDefaultSfixed64, setInt64, nil}, 130 {pb.E_NoDefaultBool, setBool, nil}, 131 {pb.E_NoDefaultBool, setBool2, nil}, 132 {pb.E_NoDefaultString, setString, nil}, 133 {pb.E_NoDefaultBytes, setBytes, nil}, 134 {pb.E_NoDefaultEnum, setEnum, nil}, 135 {pb.E_DefaultDouble, setFloat64, float64(3.1415)}, 136 {pb.E_DefaultFloat, setFloat32, float32(3.14)}, 137 {pb.E_DefaultInt32, setInt32, int32(42)}, 138 {pb.E_DefaultInt64, setInt64, int64(43)}, 139 {pb.E_DefaultUint32, setUint32, uint32(44)}, 140 {pb.E_DefaultUint64, setUint64, uint64(45)}, 141 {pb.E_DefaultSint32, setInt32, int32(46)}, 142 {pb.E_DefaultSint64, setInt64, int64(47)}, 143 {pb.E_DefaultFixed32, setUint32, uint32(48)}, 144 {pb.E_DefaultFixed64, setUint64, uint64(49)}, 145 {pb.E_DefaultSfixed32, setInt32, int32(50)}, 146 {pb.E_DefaultSfixed64, setInt64, int64(51)}, 147 {pb.E_DefaultBool, setBool, true}, 148 {pb.E_DefaultBool, setBool2, true}, 149 {pb.E_DefaultString, setString, "Hello, string"}, 150 {pb.E_DefaultBytes, setBytes, []byte("Hello, bytes")}, 151 {pb.E_DefaultEnum, setEnum, pb.DefaultsMessage_ONE}, 152 } 153 154 checkVal := func(test testcase, msg *pb.DefaultsMessage, valWant interface{}) error { 155 val, err := proto.GetExtension(msg, test.ext) 156 if err != nil { 157 if valWant != nil { 158 return fmt.Errorf("GetExtension(): %s", err) 159 } 160 if want := proto.ErrMissingExtension; err != want { 161 return fmt.Errorf("Unexpected error: got %v, want %v", err, want) 162 } 163 return nil 164 } 165 166 // All proto2 extension values are either a pointer to a value or a slice of values. 167 ty := reflect.TypeOf(val) 168 tyWant := reflect.TypeOf(test.ext.ExtensionType) 169 if got, want := ty, tyWant; got != want { 170 return fmt.Errorf("unexpected reflect.TypeOf(): got %v want %v", got, want) 171 } 172 tye := ty.Elem() 173 tyeWant := tyWant.Elem() 174 if got, want := tye, tyeWant; got != want { 175 return fmt.Errorf("unexpected reflect.TypeOf().Elem(): got %v want %v", got, want) 176 } 177 178 // Check the name of the type of the value. 179 // If it is an enum it will be type int32 with the name of the enum. 180 if got, want := tye.Name(), tye.Name(); got != want { 181 return fmt.Errorf("unexpected reflect.TypeOf().Elem().Name(): got %v want %v", got, want) 182 } 183 184 // Check that value is what we expect. 185 // If we have a pointer in val, get the value it points to. 186 valExp := val 187 if ty.Kind() == reflect.Ptr { 188 valExp = reflect.ValueOf(val).Elem().Interface() 189 } 190 if got, want := valExp, valWant; !reflect.DeepEqual(got, want) { 191 return fmt.Errorf("unexpected reflect.DeepEqual(): got %v want %v", got, want) 192 } 193 194 return nil 195 } 196 197 setTo := func(test testcase) interface{} { 198 setTo := reflect.ValueOf(test.want) 199 if typ := reflect.TypeOf(test.ext.ExtensionType); typ.Kind() == reflect.Ptr { 200 setTo = reflect.New(typ).Elem() 201 setTo.Set(reflect.New(setTo.Type().Elem())) 202 setTo.Elem().Set(reflect.ValueOf(test.want)) 203 } 204 return setTo.Interface() 205 } 206 207 for _, test := range tests { 208 msg := &pb.DefaultsMessage{} 209 name := test.ext.Name 210 211 // Check the initial value. 212 if err := checkVal(test, msg, test.def); err != nil { 213 t.Errorf("%s: %v", name, err) 214 } 215 216 // Set the per-type value and check value. 217 name = fmt.Sprintf("%s (set to %T %v)", name, test.want, test.want) 218 if err := proto.SetExtension(msg, test.ext, setTo(test)); err != nil { 219 t.Errorf("%s: SetExtension(): %v", name, err) 220 continue 221 } 222 if err := checkVal(test, msg, test.want); err != nil { 223 t.Errorf("%s: %v", name, err) 224 continue 225 } 226 227 // Set and check the value. 228 name += " (cleared)" 229 proto.ClearExtension(msg, test.ext) 230 if err := checkVal(test, msg, test.def); err != nil { 231 t.Errorf("%s: %v", name, err) 232 } 233 } 234 } 235 236 func TestExtensionsRoundTrip(t *testing.T) { 237 msg := &pb.MyMessage{} 238 ext1 := &pb.Ext{ 239 Data: proto.String("hi"), 240 } 241 ext2 := &pb.Ext{ 242 Data: proto.String("there"), 243 } 244 exists := proto.HasExtension(msg, pb.E_Ext_More) 245 if exists { 246 t.Error("Extension More present unexpectedly") 247 } 248 if err := proto.SetExtension(msg, pb.E_Ext_More, ext1); err != nil { 249 t.Error(err) 250 } 251 if err := proto.SetExtension(msg, pb.E_Ext_More, ext2); err != nil { 252 t.Error(err) 253 } 254 e, err := proto.GetExtension(msg, pb.E_Ext_More) 255 if err != nil { 256 t.Error(err) 257 } 258 x, ok := e.(*pb.Ext) 259 if !ok { 260 t.Errorf("e has type %T, expected testdata.Ext", e) 261 } else if *x.Data != "there" { 262 t.Errorf("SetExtension failed to overwrite, got %+v, not 'there'", x) 263 } 264 proto.ClearExtension(msg, pb.E_Ext_More) 265 if _, err = proto.GetExtension(msg, pb.E_Ext_More); err != proto.ErrMissingExtension { 266 t.Errorf("got %v, expected ErrMissingExtension", e) 267 } 268 if _, err := proto.GetExtension(msg, pb.E_X215); err == nil { 269 t.Error("expected bad extension error, got nil") 270 } 271 if err := proto.SetExtension(msg, pb.E_X215, 12); err == nil { 272 t.Error("expected extension err") 273 } 274 if err := proto.SetExtension(msg, pb.E_Ext_More, 12); err == nil { 275 t.Error("expected some sort of type mismatch error, got nil") 276 } 277 } 278 279 func TestNilExtension(t *testing.T) { 280 msg := &pb.MyMessage{ 281 Count: proto.Int32(1), 282 } 283 if err := proto.SetExtension(msg, pb.E_Ext_Text, proto.String("hello")); err != nil { 284 t.Fatal(err) 285 } 286 if err := proto.SetExtension(msg, pb.E_Ext_More, (*pb.Ext)(nil)); err == nil { 287 t.Error("expected SetExtension to fail due to a nil extension") 288 } else if want := "proto: SetExtension called with nil value of type *testdata.Ext"; err.Error() != want { 289 t.Errorf("expected error %v, got %v", want, err) 290 } 291 // Note: if the behavior of Marshal is ever changed to ignore nil extensions, update 292 // this test to verify that E_Ext_Text is properly propagated through marshal->unmarshal. 293 } 294 295 func TestMarshalUnmarshalRepeatedExtension(t *testing.T) { 296 // Add a repeated extension to the result. 297 tests := []struct { 298 name string 299 ext []*pb.ComplexExtension 300 }{ 301 { 302 "two fields", 303 []*pb.ComplexExtension{ 304 {First: proto.Int32(7)}, 305 {Second: proto.Int32(11)}, 306 }, 307 }, 308 { 309 "repeated field", 310 []*pb.ComplexExtension{ 311 {Third: []int32{1000}}, 312 {Third: []int32{2000}}, 313 }, 314 }, 315 { 316 "two fields and repeated field", 317 []*pb.ComplexExtension{ 318 {Third: []int32{1000}}, 319 {First: proto.Int32(9)}, 320 {Second: proto.Int32(21)}, 321 {Third: []int32{2000}}, 322 }, 323 }, 324 } 325 for _, test := range tests { 326 // Marshal message with a repeated extension. 327 msg1 := new(pb.OtherMessage) 328 err := proto.SetExtension(msg1, pb.E_RComplex, test.ext) 329 if err != nil { 330 t.Fatalf("[%s] Error setting extension: %v", test.name, err) 331 } 332 b, err := proto.Marshal(msg1) 333 if err != nil { 334 t.Fatalf("[%s] Error marshaling message: %v", test.name, err) 335 } 336 337 // Unmarshal and read the merged proto. 338 msg2 := new(pb.OtherMessage) 339 err = proto.Unmarshal(b, msg2) 340 if err != nil { 341 t.Fatalf("[%s] Error unmarshaling message: %v", test.name, err) 342 } 343 e, err := proto.GetExtension(msg2, pb.E_RComplex) 344 if err != nil { 345 t.Fatalf("[%s] Error getting extension: %v", test.name, err) 346 } 347 ext := e.([]*pb.ComplexExtension) 348 if ext == nil { 349 t.Fatalf("[%s] Invalid extension", test.name) 350 } 351 if !reflect.DeepEqual(ext, test.ext) { 352 t.Errorf("[%s] Wrong value for ComplexExtension: got: %v want: %v\n", test.name, ext, test.ext) 353 } 354 } 355 } 356 357 func TestUnmarshalRepeatingNonRepeatedExtension(t *testing.T) { 358 // We may see multiple instances of the same extension in the wire 359 // format. For example, the proto compiler may encode custom options in 360 // this way. Here, we verify that we merge the extensions together. 361 tests := []struct { 362 name string 363 ext []*pb.ComplexExtension 364 }{ 365 { 366 "two fields", 367 []*pb.ComplexExtension{ 368 {First: proto.Int32(7)}, 369 {Second: proto.Int32(11)}, 370 }, 371 }, 372 { 373 "repeated field", 374 []*pb.ComplexExtension{ 375 {Third: []int32{1000}}, 376 {Third: []int32{2000}}, 377 }, 378 }, 379 { 380 "two fields and repeated field", 381 []*pb.ComplexExtension{ 382 {Third: []int32{1000}}, 383 {First: proto.Int32(9)}, 384 {Second: proto.Int32(21)}, 385 {Third: []int32{2000}}, 386 }, 387 }, 388 } 389 for _, test := range tests { 390 var buf bytes.Buffer 391 var want pb.ComplexExtension 392 393 // Generate a serialized representation of a repeated extension 394 // by catenating bytes together. 395 for i, e := range test.ext { 396 // Merge to create the wanted proto. 397 proto.Merge(&want, e) 398 399 // serialize the message 400 msg := new(pb.OtherMessage) 401 err := proto.SetExtension(msg, pb.E_Complex, e) 402 if err != nil { 403 t.Fatalf("[%s] Error setting extension %d: %v", test.name, i, err) 404 } 405 b, err := proto.Marshal(msg) 406 if err != nil { 407 t.Fatalf("[%s] Error marshaling message %d: %v", test.name, i, err) 408 } 409 buf.Write(b) 410 } 411 412 // Unmarshal and read the merged proto. 413 msg2 := new(pb.OtherMessage) 414 err := proto.Unmarshal(buf.Bytes(), msg2) 415 if err != nil { 416 t.Fatalf("[%s] Error unmarshaling message: %v", test.name, err) 417 } 418 e, err := proto.GetExtension(msg2, pb.E_Complex) 419 if err != nil { 420 t.Fatalf("[%s] Error getting extension: %v", test.name, err) 421 } 422 ext := e.(*pb.ComplexExtension) 423 if ext == nil { 424 t.Fatalf("[%s] Invalid extension", test.name) 425 } 426 if !reflect.DeepEqual(*ext, want) { 427 t.Errorf("[%s] Wrong value for ComplexExtension: got: %s want: %s\n", test.name, ext, want) 428 } 429 } 430 }