1// Go support for Protocol Buffers - Google's data interchange format 2// 3// Copyright 2011 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 32package proto_test 33 34import ( 35 "testing" 36 37 . "github.com/golang/protobuf/proto" 38 proto3pb "github.com/golang/protobuf/proto/proto3_proto" 39 pb "github.com/golang/protobuf/proto/test_proto" 40) 41 42// Four identical base messages. 43// The init function adds extensions to some of them. 44var messageWithoutExtension = &pb.MyMessage{Count: Int32(7)} 45var messageWithExtension1a = &pb.MyMessage{Count: Int32(7)} 46var messageWithExtension1b = &pb.MyMessage{Count: Int32(7)} 47var messageWithExtension2 = &pb.MyMessage{Count: Int32(7)} 48var messageWithExtension3a = &pb.MyMessage{Count: Int32(7)} 49var messageWithExtension3b = &pb.MyMessage{Count: Int32(7)} 50var messageWithExtension3c = &pb.MyMessage{Count: Int32(7)} 51 52// Two messages with non-message extensions. 53var messageWithInt32Extension1 = &pb.MyMessage{Count: Int32(8)} 54var messageWithInt32Extension2 = &pb.MyMessage{Count: Int32(8)} 55 56func init() { 57 ext1 := &pb.Ext{Data: String("Kirk")} 58 ext2 := &pb.Ext{Data: String("Picard")} 59 60 // messageWithExtension1a has ext1, but never marshals it. 61 if err := SetExtension(messageWithExtension1a, pb.E_Ext_More, ext1); err != nil { 62 panic("SetExtension on 1a failed: " + err.Error()) 63 } 64 65 // messageWithExtension1b is the unmarshaled form of messageWithExtension1a. 66 if err := SetExtension(messageWithExtension1b, pb.E_Ext_More, ext1); err != nil { 67 panic("SetExtension on 1b failed: " + err.Error()) 68 } 69 buf, err := Marshal(messageWithExtension1b) 70 if err != nil { 71 panic("Marshal of 1b failed: " + err.Error()) 72 } 73 messageWithExtension1b.Reset() 74 if err := Unmarshal(buf, messageWithExtension1b); err != nil { 75 panic("Unmarshal of 1b failed: " + err.Error()) 76 } 77 78 // messageWithExtension2 has ext2. 79 if err := SetExtension(messageWithExtension2, pb.E_Ext_More, ext2); err != nil { 80 panic("SetExtension on 2 failed: " + err.Error()) 81 } 82 83 if err := SetExtension(messageWithInt32Extension1, pb.E_Ext_Number, Int32(23)); err != nil { 84 panic("SetExtension on Int32-1 failed: " + err.Error()) 85 } 86 if err := SetExtension(messageWithInt32Extension1, pb.E_Ext_Number, Int32(24)); err != nil { 87 panic("SetExtension on Int32-2 failed: " + err.Error()) 88 } 89 90 // messageWithExtension3{a,b,c} has unregistered extension. 91 if RegisteredExtensions(messageWithExtension3a)[200] != nil { 92 panic("expect extension 200 unregistered") 93 } 94 bytes := []byte{ 95 0xc0, 0x0c, 0x01, // id=200, wiretype=0 (varint), data=1 96 } 97 bytes2 := []byte{ 98 0xc0, 0x0c, 0x02, // id=200, wiretype=0 (varint), data=2 99 } 100 SetRawExtension(messageWithExtension3a, 200, bytes) 101 SetRawExtension(messageWithExtension3b, 200, bytes) 102 SetRawExtension(messageWithExtension3c, 200, bytes2) 103} 104 105var EqualTests = []struct { 106 desc string 107 a, b Message 108 exp bool 109}{ 110 {"different types", &pb.GoEnum{}, &pb.GoTestField{}, false}, 111 {"equal empty", &pb.GoEnum{}, &pb.GoEnum{}, true}, 112 {"nil vs nil", nil, nil, true}, 113 {"typed nil vs typed nil", (*pb.GoEnum)(nil), (*pb.GoEnum)(nil), true}, 114 {"typed nil vs empty", (*pb.GoEnum)(nil), &pb.GoEnum{}, false}, 115 {"different typed nil", (*pb.GoEnum)(nil), (*pb.GoTestField)(nil), false}, 116 117 {"one set field, one unset field", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{}, false}, 118 {"one set field zero, one unset field", &pb.GoTest{Param: Int32(0)}, &pb.GoTest{}, false}, 119 {"different set fields", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{Label: String("bar")}, false}, 120 {"equal set", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{Label: String("foo")}, true}, 121 122 {"repeated, one set", &pb.GoTest{F_Int32Repeated: []int32{2, 3}}, &pb.GoTest{}, false}, 123 {"repeated, different length", &pb.GoTest{F_Int32Repeated: []int32{2, 3}}, &pb.GoTest{F_Int32Repeated: []int32{2}}, false}, 124 {"repeated, different value", &pb.GoTest{F_Int32Repeated: []int32{2}}, &pb.GoTest{F_Int32Repeated: []int32{3}}, false}, 125 {"repeated, equal", &pb.GoTest{F_Int32Repeated: []int32{2, 4}}, &pb.GoTest{F_Int32Repeated: []int32{2, 4}}, true}, 126 {"repeated, nil equal nil", &pb.GoTest{F_Int32Repeated: nil}, &pb.GoTest{F_Int32Repeated: nil}, true}, 127 {"repeated, nil equal empty", &pb.GoTest{F_Int32Repeated: nil}, &pb.GoTest{F_Int32Repeated: []int32{}}, true}, 128 {"repeated, empty equal nil", &pb.GoTest{F_Int32Repeated: []int32{}}, &pb.GoTest{F_Int32Repeated: nil}, true}, 129 130 { 131 "nested, different", 132 &pb.GoTest{RequiredField: &pb.GoTestField{Label: String("foo")}}, 133 &pb.GoTest{RequiredField: &pb.GoTestField{Label: String("bar")}}, 134 false, 135 }, 136 { 137 "nested, equal", 138 &pb.GoTest{RequiredField: &pb.GoTestField{Label: String("wow")}}, 139 &pb.GoTest{RequiredField: &pb.GoTestField{Label: String("wow")}}, 140 true, 141 }, 142 143 {"bytes", &pb.OtherMessage{Value: []byte("foo")}, &pb.OtherMessage{Value: []byte("foo")}, true}, 144 {"bytes, empty", &pb.OtherMessage{Value: []byte{}}, &pb.OtherMessage{Value: []byte{}}, true}, 145 {"bytes, empty vs nil", &pb.OtherMessage{Value: []byte{}}, &pb.OtherMessage{Value: nil}, false}, 146 { 147 "repeated bytes", 148 &pb.MyMessage{RepBytes: [][]byte{[]byte("sham"), []byte("wow")}}, 149 &pb.MyMessage{RepBytes: [][]byte{[]byte("sham"), []byte("wow")}}, 150 true, 151 }, 152 // In proto3, []byte{} and []byte(nil) are equal. 153 {"proto3 bytes, empty vs nil", &proto3pb.Message{Data: []byte{}}, &proto3pb.Message{Data: nil}, true}, 154 155 {"extension vs. no extension", messageWithoutExtension, messageWithExtension1a, false}, 156 {"extension vs. same extension", messageWithExtension1a, messageWithExtension1b, true}, 157 {"extension vs. different extension", messageWithExtension1a, messageWithExtension2, false}, 158 159 {"int32 extension vs. itself", messageWithInt32Extension1, messageWithInt32Extension1, true}, 160 {"int32 extension vs. a different int32", messageWithInt32Extension1, messageWithInt32Extension2, false}, 161 162 {"unregistered extension same", messageWithExtension3a, messageWithExtension3b, true}, 163 {"unregistered extension different", messageWithExtension3a, messageWithExtension3c, false}, 164 165 { 166 "message with group", 167 &pb.MyMessage{ 168 Count: Int32(1), 169 Somegroup: &pb.MyMessage_SomeGroup{ 170 GroupField: Int32(5), 171 }, 172 }, 173 &pb.MyMessage{ 174 Count: Int32(1), 175 Somegroup: &pb.MyMessage_SomeGroup{ 176 GroupField: Int32(5), 177 }, 178 }, 179 true, 180 }, 181 182 { 183 "map same", 184 &pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}}, 185 &pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}}, 186 true, 187 }, 188 { 189 "map different entry", 190 &pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}}, 191 &pb.MessageWithMap{NameMapping: map[int32]string{2: "Rob"}}, 192 false, 193 }, 194 { 195 "map different key only", 196 &pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}}, 197 &pb.MessageWithMap{NameMapping: map[int32]string{2: "Ken"}}, 198 false, 199 }, 200 { 201 "map different value only", 202 &pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}}, 203 &pb.MessageWithMap{NameMapping: map[int32]string{1: "Rob"}}, 204 false, 205 }, 206 { 207 "zero-length maps same", 208 &pb.MessageWithMap{NameMapping: map[int32]string{}}, 209 &pb.MessageWithMap{NameMapping: nil}, 210 true, 211 }, 212 { 213 "orders in map don't matter", 214 &pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken", 2: "Rob"}}, 215 &pb.MessageWithMap{NameMapping: map[int32]string{2: "Rob", 1: "Ken"}}, 216 true, 217 }, 218 { 219 "oneof same", 220 &pb.Communique{Union: &pb.Communique_Number{41}}, 221 &pb.Communique{Union: &pb.Communique_Number{41}}, 222 true, 223 }, 224 { 225 "oneof one nil", 226 &pb.Communique{Union: &pb.Communique_Number{41}}, 227 &pb.Communique{}, 228 false, 229 }, 230 { 231 "oneof different", 232 &pb.Communique{Union: &pb.Communique_Number{41}}, 233 &pb.Communique{Union: &pb.Communique_Name{"Bobby Tables"}}, 234 false, 235 }, 236} 237 238func TestEqual(t *testing.T) { 239 for _, tc := range EqualTests { 240 if res := Equal(tc.a, tc.b); res != tc.exp { 241 t.Errorf("%v: Equal(%v, %v) = %v, want %v", tc.desc, tc.a, tc.b, res, tc.exp) 242 } 243 } 244} 245