github.com/klaytn/klaytn@v1.12.1/networks/p2p/discover/node_test.go (about) 1 // Modifications Copyright 2018 The klaytn Authors 2 // Copyright 2015 The go-ethereum Authors 3 // This file is part of the go-ethereum library. 4 // 5 // The go-ethereum library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-ethereum library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // This file is derived from p2p/discover/node_test.go (2018/06/04). 19 // Modified and improved for the klaytn development. 20 21 package discover 22 23 import ( 24 "bytes" 25 "errors" 26 "fmt" 27 "math/big" 28 "math/rand" 29 "net" 30 "reflect" 31 "strings" 32 "testing" 33 "testing/quick" 34 "time" 35 36 "github.com/klaytn/klaytn/common" 37 "github.com/klaytn/klaytn/crypto" 38 ) 39 40 func init() { 41 lookupIPFunc = func(name string) ([]net.IP, error) { 42 if name == "node.example.org" { 43 return []net.IP{{33, 44, 55, 66}}, nil 44 } 45 if name == "1234.com" { 46 return []net.IP{{11, 22, 33, 44}}, nil 47 } 48 return nil, errors.New("no such host") 49 } 50 } 51 52 func ExampleNewNode() { 53 id := MustHexID("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439") 54 55 // Complete nodes contain UDP and TCP endpoints: 56 n1 := NewNode(id, net.ParseIP("2001:db8:3c4d:15::abcd:ef12"), 52150, 30303, nil, NodeTypeUnknown) 57 fmt.Println("n1:", n1) 58 fmt.Println("n1.Incomplete() ->", n1.Incomplete()) 59 60 // An incomplete node can be created by passing zero values 61 // for all parameters except id. 62 n2 := NewNode(id, nil, 0, 0, nil, NodeTypeUnknown) 63 fmt.Println("n2:", n2) 64 fmt.Println("n2.Incomplete() ->", n2.Incomplete()) 65 66 // Output: 67 // n1: kni://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[2001:db8:3c4d:15::abcd:ef12]:30303?discport=52150 68 // n1.Incomplete() -> false 69 // n2: kni://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439 70 // n2.Incomplete() -> true 71 } 72 73 var parseNodeTests = []struct { 74 rawurl string 75 wantError string 76 wantResult *Node 77 wantNodeString string 78 }{ 79 { 80 rawurl: "http://foobar", 81 wantError: `invalid URL scheme, want "kni"`, 82 }, 83 { 84 rawurl: "enode://01010101@123.124.125.126:3", 85 wantError: `invalid node ID (wrong length, want 128 hex chars)`, 86 }, 87 { 88 rawurl: "kni://01010101@123.124.125.126:3", 89 wantError: `invalid node ID (wrong length, want 128 hex chars)`, 90 }, 91 // Complete nodes with IP address. 92 { 93 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@hostname:3", 94 wantError: `no such host`, 95 }, 96 { 97 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:foo", 98 wantError: `invalid port`, 99 }, 100 { 101 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:3?discport=foo", 102 wantError: `invalid discport in query`, 103 }, 104 { 105 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150", 106 wantResult: NewNode( 107 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 108 net.IP{127, 0, 0, 1}, 109 52150, 110 52150, 111 nil, 112 NodeTypeUnknown, 113 ), 114 }, 115 { 116 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@node.example.org:52150", 117 wantNodeString: "kni://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@33.44.55.66:52150", 118 wantResult: NewNode( 119 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 120 net.IP{33, 44, 55, 66}, 121 52150, 122 52150, 123 nil, 124 NodeTypeUnknown, 125 ), 126 }, 127 { 128 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@1234.com:52150", 129 wantNodeString: "kni://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@11.22.33.44:52150", 130 wantResult: NewNode( 131 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 132 net.IP{11, 22, 33, 44}, 133 52150, 134 52150, 135 nil, 136 NodeTypeUnknown, 137 ), 138 }, 139 { 140 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[::]:52150", 141 wantResult: NewNode( 142 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 143 net.ParseIP("::"), 144 52150, 145 52150, 146 nil, 147 NodeTypeUnknown, 148 ), 149 }, 150 { 151 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[2001:db8:3c4d:15::abcd:ef12]:52150", 152 wantResult: NewNode( 153 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 154 net.ParseIP("2001:db8:3c4d:15::abcd:ef12"), 155 52150, 156 52150, 157 nil, 158 NodeTypeUnknown, 159 ), 160 }, 161 { 162 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150?discport=22334", 163 wantResult: NewNode( 164 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 165 net.IP{0x7f, 0x0, 0x0, 0x1}, 166 22334, 167 52150, 168 nil, 169 NodeTypeUnknown, 170 ), 171 }, 172 { 173 rawurl: "kni://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@hostname:3", 174 wantError: `no such host`, 175 }, 176 { 177 rawurl: "kni://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:foo", 178 wantError: `invalid port`, 179 }, 180 { 181 rawurl: "kni://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:3?discport=foo", 182 wantError: `invalid discport in query`, 183 }, 184 { 185 rawurl: "kni://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150", 186 wantResult: NewNode( 187 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 188 net.IP{0x7f, 0x0, 0x0, 0x1}, 189 52150, 190 52150, 191 nil, 192 NodeTypeUnknown, 193 ), 194 }, 195 { 196 rawurl: "kni://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[::]:52150", 197 wantResult: NewNode( 198 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 199 net.ParseIP("::"), 200 52150, 201 52150, 202 nil, 203 NodeTypeUnknown, 204 ), 205 }, 206 { 207 rawurl: "kni://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[2001:db8:3c4d:15::abcd:ef12]:52150", 208 wantResult: NewNode( 209 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 210 net.ParseIP("2001:db8:3c4d:15::abcd:ef12"), 211 52150, 212 52150, 213 nil, 214 NodeTypeUnknown, 215 ), 216 }, 217 { 218 rawurl: "kni://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150?discport=22334", 219 wantResult: NewNode( 220 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 221 net.IP{0x7f, 0x0, 0x0, 0x1}, 222 22334, 223 52150, 224 nil, 225 NodeTypeUnknown, 226 ), 227 }, 228 // Incomplete nodes with no address. 229 { 230 rawurl: "1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439", 231 wantResult: NewNode( 232 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 233 nil, 0, 0, nil, 234 NodeTypeUnknown, 235 ), 236 }, 237 { 238 rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439", 239 wantResult: NewNode( 240 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 241 nil, 0, 0, nil, 242 NodeTypeUnknown, 243 ), 244 }, 245 { 246 rawurl: "kni://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439", 247 wantResult: NewNode( 248 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 249 nil, 0, 0, nil, 250 NodeTypeUnknown, 251 ), 252 }, 253 { 254 rawurl: "kni://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150?subport=1", 255 wantResult: NewNode( 256 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 257 net.IP{0x7f, 0x0, 0x0, 0x1}, 258 52150, 259 52150, 260 []uint16{1, 52150}, 261 NodeTypeUnknown, 262 ), 263 }, 264 { 265 rawurl: "kni://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150?discport=123&subport=1&subport=2", 266 wantResult: NewNode( 267 MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), 268 net.IP{0x7f, 0x0, 0x0, 0x1}, 269 123, 270 52150, 271 []uint16{1, 2, 52150}, 272 NodeTypeUnknown, 273 ), 274 }, 275 // Invalid URLs 276 { 277 rawurl: "01010101", 278 wantError: `invalid node ID (wrong length, want 128 hex chars)`, 279 }, 280 { 281 rawurl: "enode://01010101", 282 wantError: `invalid node ID (wrong length, want 128 hex chars)`, 283 }, 284 { 285 rawurl: "kni://01010101", 286 wantError: `invalid node ID (wrong length, want 128 hex chars)`, 287 }, 288 { 289 // This test checks that errors from url.Parse are handled. 290 rawurl: "://foo", 291 wantError: `missing protocol scheme`, 292 }, 293 } 294 295 func convertNodeScheme(rawstr string) string { 296 converted := rawstr 297 if strings.HasPrefix(rawstr, "enode://") { 298 converted = "kni://" + rawstr[len("enode://"):] 299 } 300 return converted 301 } 302 303 func TestParseNode(t *testing.T) { 304 for _, test := range parseNodeTests { 305 n, err := ParseNode(test.rawurl) 306 if test.wantError != "" { 307 if err == nil { 308 t.Errorf("test %q:\n got nil error, expected %#q", test.rawurl, test.wantError) 309 continue 310 } else if !strings.Contains(err.Error(), test.wantError) { 311 t.Errorf("test %q:\n got error %#q, expected %#q", test.rawurl, err.Error(), test.wantError) 312 continue 313 } 314 } else { 315 if err != nil { 316 t.Errorf("test %q:\n unexpected error: %v", test.rawurl, err) 317 continue 318 } 319 if !reflect.DeepEqual(n, test.wantResult) { 320 t.Errorf("test %q:\n result mismatch:\ngot: %#v, want: %#v", test.rawurl, n, test.wantResult) 321 } 322 } 323 } 324 } 325 326 func TestNodeString(t *testing.T) { 327 for i, test := range parseNodeTests { 328 rawUrl := test.rawurl 329 if strings.HasPrefix(test.rawurl, "enode://") { 330 rawUrl = convertNodeScheme(test.rawurl) 331 } 332 if test.wantError == "" && strings.HasPrefix(rawUrl, "kni://") { 333 str := test.wantResult.String() 334 if str != rawUrl && str != test.wantNodeString && test.wantNodeString != "" { 335 t.Errorf("test %d: Node.String() mismatch:\ngot: %s\nwant: %s", i, str, rawUrl) 336 } 337 } 338 } 339 } 340 341 func TestHexID(t *testing.T) { 342 ref := NodeID{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 106, 217, 182, 31, 165, 174, 1, 67, 7, 235, 220, 150, 66, 83, 173, 205, 159, 44, 10, 57, 42, 161, 26, 188} 343 id1 := MustHexID("0x000000000000000000000000000000000000000000000000000000000000000000000000000000806ad9b61fa5ae014307ebdc964253adcd9f2c0a392aa11abc") 344 id2 := MustHexID("000000000000000000000000000000000000000000000000000000000000000000000000000000806ad9b61fa5ae014307ebdc964253adcd9f2c0a392aa11abc") 345 346 if id1 != ref { 347 t.Errorf("wrong id1\ngot %v\nwant %v", id1[:], ref[:]) 348 } 349 if id2 != ref { 350 t.Errorf("wrong id2\ngot %v\nwant %v", id2[:], ref[:]) 351 } 352 } 353 354 func TestNodeID_textEncoding(t *testing.T) { 355 ref := NodeID{ 356 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 357 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 358 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 359 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x40, 360 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x50, 361 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x60, 362 0x61, 0x62, 0x63, 0x64, 363 } 364 hex := "01020304050607080910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364" 365 366 text, err := ref.MarshalText() 367 if err != nil { 368 t.Fatal(err) 369 } 370 if !bytes.Equal(text, []byte(hex)) { 371 t.Fatalf("text encoding did not match\nexpected: %s\ngot: %s", hex, text) 372 } 373 374 id := new(NodeID) 375 if err := id.UnmarshalText(text); err != nil { 376 t.Fatal(err) 377 } 378 if *id != ref { 379 t.Fatalf("text decoding did not match\nexpected: %s\ngot: %s", ref, id) 380 } 381 } 382 383 func TestNodeID_recover(t *testing.T) { 384 prv := newkey() 385 hash := make([]byte, 32) 386 sig, err := crypto.Sign(hash, prv) 387 if err != nil { 388 t.Fatalf("signing error: %v", err) 389 } 390 391 pub := PubkeyID(&prv.PublicKey) 392 recpub, err := recoverNodeID(hash, sig) 393 if err != nil { 394 t.Fatalf("recovery error: %v", err) 395 } 396 if pub != recpub { 397 t.Errorf("recovered wrong pubkey:\ngot: %v\nwant: %v", recpub, pub) 398 } 399 400 ecdsa, err := pub.Pubkey() 401 if err != nil { 402 t.Errorf("Pubkey error: %v", err) 403 } 404 if !reflect.DeepEqual(ecdsa, &prv.PublicKey) { 405 t.Errorf("Pubkey mismatch:\n got: %#v\n want: %#v", ecdsa, &prv.PublicKey) 406 } 407 } 408 409 func TestNodeID_pubkeyBad(t *testing.T) { 410 ecdsa, err := NodeID{}.Pubkey() 411 if err == nil { 412 t.Error("expected error for zero ID") 413 } 414 if ecdsa != nil { 415 t.Error("expected nil result") 416 } 417 } 418 419 func TestNodeID_distcmp(t *testing.T) { 420 distcmpBig := func(target, a, b common.Hash) int { 421 tbig := new(big.Int).SetBytes(target[:]) 422 abig := new(big.Int).SetBytes(a[:]) 423 bbig := new(big.Int).SetBytes(b[:]) 424 return new(big.Int).Xor(tbig, abig).Cmp(new(big.Int).Xor(tbig, bbig)) 425 } 426 if err := quick.CheckEqual(distcmp, distcmpBig, quickcfg()); err != nil { 427 t.Error(err) 428 } 429 } 430 431 // the random tests is likely to miss the case where they're equal. 432 func TestNodeID_distcmpEqual(t *testing.T) { 433 base := common.Hash{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} 434 x := common.Hash{15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} 435 if distcmp(base, x, x) != 0 { 436 t.Errorf("distcmp(base, x, x) != 0") 437 } 438 } 439 440 func TestNodeID_logdist(t *testing.T) { 441 logdistBig := func(a, b common.Hash) int { 442 abig, bbig := new(big.Int).SetBytes(a[:]), new(big.Int).SetBytes(b[:]) 443 return new(big.Int).Xor(abig, bbig).BitLen() 444 } 445 if err := quick.CheckEqual(logdist, logdistBig, quickcfg()); err != nil { 446 t.Error(err) 447 } 448 } 449 450 // the random tests is likely to miss the case where they're equal. 451 func TestNodeID_logdistEqual(t *testing.T) { 452 x := common.Hash{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} 453 if logdist(x, x) != 0 { 454 t.Errorf("logdist(x, x) != 0") 455 } 456 } 457 458 func TestNodeID_hashAtDistance(t *testing.T) { 459 // we don't use quick.Check here because its output isn't 460 // very helpful when the test fails. 461 cfg := quickcfg() 462 for i := 0; i < cfg.MaxCount; i++ { 463 a := gen(common.Hash{}, cfg.Rand).(common.Hash) 464 dist := cfg.Rand.Intn(len(common.Hash{}) * 8) 465 result := hashAtDistance(a, dist) 466 actualdist := logdist(result, a) 467 468 if dist != actualdist { 469 t.Log("a: ", a) 470 t.Log("result:", result) 471 t.Fatalf("#%d: distance of result is %d, want %d", i, actualdist, dist) 472 } 473 } 474 } 475 476 func quickcfg() *quick.Config { 477 return &quick.Config{ 478 MaxCount: 5000, 479 Rand: rand.New(rand.NewSource(time.Now().Unix())), 480 } 481 } 482 483 // TODO: The Generate method can be dropped when we require Go >= 1.5 484 // because testing/quick learned to generate arrays in 1.5. 485 486 func (NodeID) Generate(rand *rand.Rand, size int) reflect.Value { 487 var id NodeID 488 m := rand.Intn(len(id)) 489 for i := len(id) - 1; i > m; i-- { 490 id[i] = byte(rand.Uint32()) 491 } 492 return reflect.ValueOf(id) 493 }