1// Go support for Protocol Buffers - Google's data interchange format 2// 3// Copyright 2010 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// Test that we can use protocol buffers that use extensions. 33 34package testdata 35 36import ( 37 "bytes" 38 "regexp" 39 "testing" 40 41 "github.com/golang/protobuf/proto" 42 base "github.com/golang/protobuf/protoc-gen-go/testdata/extension_base" 43 user "github.com/golang/protobuf/protoc-gen-go/testdata/extension_user" 44) 45 46func TestSingleFieldExtension(t *testing.T) { 47 bm := &base.BaseMessage{ 48 Height: proto.Int32(178), 49 } 50 51 // Use extension within scope of another type. 52 vol := proto.Uint32(11) 53 err := proto.SetExtension(bm, user.E_LoudMessage_Volume, vol) 54 if err != nil { 55 t.Fatal("Failed setting extension:", err) 56 } 57 buf, err := proto.Marshal(bm) 58 if err != nil { 59 t.Fatal("Failed encoding message with extension:", err) 60 } 61 bm_new := new(base.BaseMessage) 62 if err := proto.Unmarshal(buf, bm_new); err != nil { 63 t.Fatal("Failed decoding message with extension:", err) 64 } 65 if !proto.HasExtension(bm_new, user.E_LoudMessage_Volume) { 66 t.Fatal("Decoded message didn't contain extension.") 67 } 68 vol_out, err := proto.GetExtension(bm_new, user.E_LoudMessage_Volume) 69 if err != nil { 70 t.Fatal("Failed getting extension:", err) 71 } 72 if v := vol_out.(*uint32); *v != *vol { 73 t.Errorf("vol_out = %v, expected %v", *v, *vol) 74 } 75 proto.ClearExtension(bm_new, user.E_LoudMessage_Volume) 76 if proto.HasExtension(bm_new, user.E_LoudMessage_Volume) { 77 t.Fatal("Failed clearing extension.") 78 } 79} 80 81func TestMessageExtension(t *testing.T) { 82 bm := &base.BaseMessage{ 83 Height: proto.Int32(179), 84 } 85 86 // Use extension that is itself a message. 87 um := &user.UserMessage{ 88 Name: proto.String("Dave"), 89 Rank: proto.String("Major"), 90 } 91 err := proto.SetExtension(bm, user.E_LoginMessage_UserMessage, um) 92 if err != nil { 93 t.Fatal("Failed setting extension:", err) 94 } 95 buf, err := proto.Marshal(bm) 96 if err != nil { 97 t.Fatal("Failed encoding message with extension:", err) 98 } 99 bm_new := new(base.BaseMessage) 100 if err := proto.Unmarshal(buf, bm_new); err != nil { 101 t.Fatal("Failed decoding message with extension:", err) 102 } 103 if !proto.HasExtension(bm_new, user.E_LoginMessage_UserMessage) { 104 t.Fatal("Decoded message didn't contain extension.") 105 } 106 um_out, err := proto.GetExtension(bm_new, user.E_LoginMessage_UserMessage) 107 if err != nil { 108 t.Fatal("Failed getting extension:", err) 109 } 110 if n := um_out.(*user.UserMessage).Name; *n != *um.Name { 111 t.Errorf("um_out.Name = %q, expected %q", *n, *um.Name) 112 } 113 if r := um_out.(*user.UserMessage).Rank; *r != *um.Rank { 114 t.Errorf("um_out.Rank = %q, expected %q", *r, *um.Rank) 115 } 116 proto.ClearExtension(bm_new, user.E_LoginMessage_UserMessage) 117 if proto.HasExtension(bm_new, user.E_LoginMessage_UserMessage) { 118 t.Fatal("Failed clearing extension.") 119 } 120} 121 122func TestTopLevelExtension(t *testing.T) { 123 bm := &base.BaseMessage{ 124 Height: proto.Int32(179), 125 } 126 127 width := proto.Int32(17) 128 err := proto.SetExtension(bm, user.E_Width, width) 129 if err != nil { 130 t.Fatal("Failed setting extension:", err) 131 } 132 buf, err := proto.Marshal(bm) 133 if err != nil { 134 t.Fatal("Failed encoding message with extension:", err) 135 } 136 bm_new := new(base.BaseMessage) 137 if err := proto.Unmarshal(buf, bm_new); err != nil { 138 t.Fatal("Failed decoding message with extension:", err) 139 } 140 if !proto.HasExtension(bm_new, user.E_Width) { 141 t.Fatal("Decoded message didn't contain extension.") 142 } 143 width_out, err := proto.GetExtension(bm_new, user.E_Width) 144 if err != nil { 145 t.Fatal("Failed getting extension:", err) 146 } 147 if w := width_out.(*int32); *w != *width { 148 t.Errorf("width_out = %v, expected %v", *w, *width) 149 } 150 proto.ClearExtension(bm_new, user.E_Width) 151 if proto.HasExtension(bm_new, user.E_Width) { 152 t.Fatal("Failed clearing extension.") 153 } 154} 155 156func TestMessageSetWireFormat(t *testing.T) { 157 osm := new(base.OldStyleMessage) 158 osp := &user.OldStyleParcel{ 159 Name: proto.String("Dave"), 160 Height: proto.Int32(178), 161 } 162 163 err := proto.SetExtension(osm, user.E_OldStyleParcel_MessageSetExtension, osp) 164 if err != nil { 165 t.Fatal("Failed setting extension:", err) 166 } 167 168 buf, err := proto.Marshal(osm) 169 if err != nil { 170 t.Fatal("Failed encoding message:", err) 171 } 172 173 // Data generated from Python implementation. 174 expected := []byte{ 175 11, 16, 209, 15, 26, 9, 10, 4, 68, 97, 118, 101, 16, 178, 1, 12, 176 } 177 178 if !bytes.Equal(expected, buf) { 179 t.Errorf("Encoding mismatch.\nwant %+v\n got %+v", expected, buf) 180 } 181 182 // Check that it is restored correctly. 183 osm = new(base.OldStyleMessage) 184 if err := proto.Unmarshal(buf, osm); err != nil { 185 t.Fatal("Failed decoding message:", err) 186 } 187 osp_out, err := proto.GetExtension(osm, user.E_OldStyleParcel_MessageSetExtension) 188 if err != nil { 189 t.Fatal("Failed getting extension:", err) 190 } 191 osp = osp_out.(*user.OldStyleParcel) 192 if *osp.Name != "Dave" || *osp.Height != 178 { 193 t.Errorf("Retrieved extension from decoded message is not correct: %+v", osp) 194 } 195} 196 197func main() { 198 // simpler than rigging up gotest 199 testing.Main(regexp.MatchString, []testing.InternalTest{ 200 {"TestSingleFieldExtension", TestSingleFieldExtension}, 201 {"TestMessageExtension", TestMessageExtension}, 202 {"TestTopLevelExtension", TestTopLevelExtension}, 203 }, 204 []testing.InternalBenchmark{}, 205 []testing.InternalExample{}) 206} 207