1// Protocol Buffers for Go with Gadgets 2// 3// Copyright (c) 2013, The GoGo Authors. All rights reserved. 4// http://github.com/gogo/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// 17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29package test 30 31import ( 32 "github.com/gogo/protobuf/proto" 33 "math" 34 math_rand "math/rand" 35 "testing" 36 "time" 37) 38 39//func SetRawExtension(base extendableProto, id int32, b []byte) { 40//func HasExtension(pb extendableProto, extension *ExtensionDesc) bool { 41//func ClearExtension(pb extendableProto, extension *ExtensionDesc) { 42//func GetExtension(pb extendableProto, extension *ExtensionDesc) (interface{}, error) { 43//func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) { 44//func SetExtension(pb extendableProto, extension *ExtensionDesc, value interface{}) error { 45 46type extendable interface { 47 proto.Message 48 ExtensionRangeArray() []proto.ExtensionRange 49} 50 51func check(t *testing.T, m extendable, fieldA float64, ext *proto.ExtensionDesc) { 52 if !proto.HasExtension(m, ext) { 53 t.Fatalf("expected extension to be set") 54 } 55 fieldA2Interface, err := proto.GetExtension(m, ext) 56 if err != nil { 57 panic(err) 58 } 59 fieldA2 := fieldA2Interface.(*float64) 60 if fieldA != *fieldA2 { 61 t.Fatalf("Expected %f got %f", fieldA, *fieldA2) 62 } 63 fieldA3Interface, err := proto.GetUnsafeExtension(m, ext.Field) 64 if err != nil { 65 panic(err) 66 } 67 fieldA3 := fieldA3Interface.(*float64) 68 if fieldA != *fieldA3 { 69 t.Fatalf("Expected %f got %f", fieldA, *fieldA3) 70 } 71 proto.ClearExtension(m, ext) 72 if proto.HasExtension(m, ext) { 73 t.Fatalf("expected extension to be cleared") 74 } 75} 76 77var fieldA float64 78var fieldABytes []byte 79var extr = math_rand.New(math_rand.NewSource(time.Now().UnixNano())) 80 81func init() { 82 fieldA = float64(1.1) 83 fieldABits := math.Float64bits(fieldA) 84 x := uint64(uint32(100)<<3 | uint32(proto.WireFixed64)) 85 fieldABytes = encodeVarintPopulateThetest(nil, x) 86 fieldABytes = append(fieldABytes, uint8(fieldABits)) 87 fieldABytes = append(fieldABytes, uint8(fieldABits>>8)) 88 fieldABytes = append(fieldABytes, uint8(fieldABits>>16)) 89 fieldABytes = append(fieldABytes, uint8(fieldABits>>24)) 90 fieldABytes = append(fieldABytes, uint8(fieldABits>>32)) 91 fieldABytes = append(fieldABytes, uint8(fieldABits>>40)) 92 fieldABytes = append(fieldABytes, uint8(fieldABits>>48)) 93 fieldABytes = append(fieldABytes, uint8(fieldABits>>56)) 94} 95 96func TestExtensionsMyExtendable(t *testing.T) { 97 m := NewPopulatedMyExtendable(extr, false) 98 err := proto.SetExtension(m, E_FieldA, &fieldA) 99 if err != nil { 100 panic(err) 101 } 102 check(t, m, fieldA, E_FieldA) 103 proto.SetRawExtension(m, 100, fieldABytes) 104 check(t, m, fieldA, E_FieldA) 105} 106 107func TestExtensionsNoExtensionsMapSetExtension(t *testing.T) { 108 m := NewPopulatedNoExtensionsMap(extr, false) 109 err := proto.SetExtension(m, E_FieldA1, &fieldA) 110 if err != nil { 111 panic(err) 112 } 113 check(t, m, fieldA, E_FieldA1) 114} 115 116func TestExtensionsNoExtensionsMapSetRawExtension(t *testing.T) { 117 m := NewPopulatedNoExtensionsMap(extr, false) 118 proto.SetRawExtension(m, 100, fieldABytes) 119 check(t, m, fieldA, E_FieldA1) 120} 121 122func TestUnsafeExtension(t *testing.T) { 123 m := NewPopulatedMyExtendable(extr, false) 124 err := proto.SetUnsafeExtension(m, E_FieldA.Field, &fieldA) 125 if err != nil { 126 panic(err) 127 } 128 check(t, m, fieldA, E_FieldA) 129} 130 131//See another version of this test in proto/extensions_test.go 132func TestGetExtensionStability(t *testing.T) { 133 check := func(m *NoExtensionsMap) bool { 134 ext1, err := proto.GetExtension(m, E_FieldB1) 135 if err != nil { 136 t.Fatalf("GetExtension() failed: %s", err) 137 } 138 ext2, err := proto.GetExtension(m, E_FieldB1) 139 if err != nil { 140 t.Fatalf("GetExtension() failed: %s", err) 141 } 142 return ext1.(*NinOptNative).Equal(ext2) 143 } 144 msg := &NoExtensionsMap{Field1: proto.Int64(2)} 145 ext0 := &NinOptNative{Field1: proto.Float64(1)} 146 if err := proto.SetExtension(msg, E_FieldB1, ext0); err != nil { 147 t.Fatalf("Could not set ext1: %s", ext0) 148 } 149 if !check(msg) { 150 t.Errorf("GetExtension() not stable before marshaling") 151 } 152 bb, err := proto.Marshal(msg) 153 if err != nil { 154 t.Fatalf("Marshal() failed: %s", err) 155 } 156 msg1 := &NoExtensionsMap{} 157 err = proto.Unmarshal(bb, msg1) 158 if err != nil { 159 t.Fatalf("Unmarshal() failed: %s", err) 160 } 161 if !check(msg1) { 162 t.Errorf("GetExtension() not stable after unmarshaling") 163 } 164} 165