github.com/okex/exchain@v1.8.0/libs/tendermint/p2p/pex/addrbook_test.go (about) 1 package pex 2 3 import ( 4 "encoding/hex" 5 "fmt" 6 "io/ioutil" 7 "math" 8 "net" 9 "os" 10 "testing" 11 "time" 12 13 "github.com/stretchr/testify/assert" 14 "github.com/stretchr/testify/require" 15 16 "github.com/okex/exchain/libs/tendermint/libs/log" 17 tmmath "github.com/okex/exchain/libs/tendermint/libs/math" 18 tmrand "github.com/okex/exchain/libs/tendermint/libs/rand" 19 "github.com/okex/exchain/libs/tendermint/p2p" 20 ) 21 22 // FIXME These tests should not rely on .(*addrBook) assertions 23 24 func TestAddrBookPickAddress(t *testing.T) { 25 fname := createTempFileName("addrbook_test") 26 defer deleteTempFile(fname) 27 28 // 0 addresses 29 book := NewAddrBook(fname, true) 30 book.SetLogger(log.TestingLogger()) 31 assert.Zero(t, book.Size()) 32 33 addr := book.PickAddress(50) 34 assert.Nil(t, addr, "expected no address") 35 36 randAddrs := randNetAddressPairs(t, 1) 37 addrSrc := randAddrs[0] 38 book.AddAddress(addrSrc.addr, addrSrc.src) 39 40 // pick an address when we only have new address 41 addr = book.PickAddress(0) 42 assert.NotNil(t, addr, "expected an address") 43 addr = book.PickAddress(50) 44 assert.NotNil(t, addr, "expected an address") 45 addr = book.PickAddress(100) 46 assert.NotNil(t, addr, "expected an address") 47 48 // pick an address when we only have old address 49 book.MarkGood(addrSrc.addr.ID) 50 addr = book.PickAddress(0) 51 assert.NotNil(t, addr, "expected an address") 52 addr = book.PickAddress(50) 53 assert.NotNil(t, addr, "expected an address") 54 55 // in this case, nNew==0 but we biased 100% to new, so we return nil 56 addr = book.PickAddress(100) 57 assert.Nil(t, addr, "did not expected an address") 58 } 59 60 func TestAddrBookSaveLoad(t *testing.T) { 61 fname := createTempFileName("addrbook_test") 62 defer deleteTempFile(fname) 63 64 // 0 addresses 65 book := NewAddrBook(fname, true) 66 book.SetLogger(log.TestingLogger()) 67 book.Save() 68 69 book = NewAddrBook(fname, true) 70 book.SetLogger(log.TestingLogger()) 71 book.Start() 72 73 assert.True(t, book.Empty()) 74 75 // 100 addresses 76 randAddrs := randNetAddressPairs(t, 100) 77 78 for _, addrSrc := range randAddrs { 79 book.AddAddress(addrSrc.addr, addrSrc.src) 80 } 81 82 assert.Equal(t, 100, book.Size()) 83 book.Save() 84 85 book = NewAddrBook(fname, true) 86 book.SetLogger(log.TestingLogger()) 87 book.Start() 88 89 assert.Equal(t, 100, book.Size()) 90 } 91 92 func TestAddrBookLookup(t *testing.T) { 93 fname := createTempFileName("addrbook_test") 94 defer deleteTempFile(fname) 95 96 randAddrs := randNetAddressPairs(t, 100) 97 98 book := NewAddrBook(fname, true) 99 book.SetLogger(log.TestingLogger()) 100 for _, addrSrc := range randAddrs { 101 addr := addrSrc.addr 102 src := addrSrc.src 103 book.AddAddress(addr, src) 104 105 ka := book.HasAddress(addr) 106 assert.True(t, ka, "Expected to find KnownAddress %v but wasn't there.", addr) 107 } 108 } 109 110 func TestAddrBookPromoteToOld(t *testing.T) { 111 fname := createTempFileName("addrbook_test") 112 defer deleteTempFile(fname) 113 114 randAddrs := randNetAddressPairs(t, 100) 115 116 book := NewAddrBook(fname, true) 117 book.SetLogger(log.TestingLogger()) 118 for _, addrSrc := range randAddrs { 119 book.AddAddress(addrSrc.addr, addrSrc.src) 120 } 121 122 // Attempt all addresses. 123 for _, addrSrc := range randAddrs { 124 book.MarkAttempt(addrSrc.addr) 125 } 126 127 // Promote half of them 128 for i, addrSrc := range randAddrs { 129 if i%2 == 0 { 130 book.MarkGood(addrSrc.addr.ID) 131 } 132 } 133 134 // TODO: do more testing :) 135 136 selection := book.GetSelection() 137 t.Logf("selection: %v", selection) 138 139 if len(selection) > book.Size() { 140 t.Errorf("selection could not be bigger than the book") 141 } 142 143 selection = book.GetSelectionWithBias(30) 144 t.Logf("selection: %v", selection) 145 146 if len(selection) > book.Size() { 147 t.Errorf("selection with bias could not be bigger than the book") 148 } 149 150 assert.Equal(t, book.Size(), 100, "expecting book size to be 100") 151 } 152 153 func TestAddrBookHandlesDuplicates(t *testing.T) { 154 fname := createTempFileName("addrbook_test") 155 defer deleteTempFile(fname) 156 157 book := NewAddrBook(fname, true) 158 book.SetLogger(log.TestingLogger()) 159 160 randAddrs := randNetAddressPairs(t, 100) 161 162 differentSrc := randIPv4Address(t) 163 for _, addrSrc := range randAddrs { 164 book.AddAddress(addrSrc.addr, addrSrc.src) 165 book.AddAddress(addrSrc.addr, addrSrc.src) // duplicate 166 book.AddAddress(addrSrc.addr, differentSrc) // different src 167 } 168 169 assert.Equal(t, 100, book.Size()) 170 } 171 172 type netAddressPair struct { 173 addr *p2p.NetAddress 174 src *p2p.NetAddress 175 } 176 177 func randNetAddressPairs(t *testing.T, n int) []netAddressPair { 178 randAddrs := make([]netAddressPair, n) 179 for i := 0; i < n; i++ { 180 randAddrs[i] = netAddressPair{addr: randIPv4Address(t), src: randIPv4Address(t)} 181 } 182 return randAddrs 183 } 184 185 func randIPv4Address(t *testing.T) *p2p.NetAddress { 186 for { 187 ip := fmt.Sprintf("%v.%v.%v.%v", 188 tmrand.Intn(254)+1, 189 tmrand.Intn(255), 190 tmrand.Intn(255), 191 tmrand.Intn(255), 192 ) 193 port := tmrand.Intn(65535-1) + 1 194 id := p2p.ID(hex.EncodeToString(tmrand.Bytes(p2p.IDByteLength))) 195 idAddr := p2p.IDAddressString(id, fmt.Sprintf("%v:%v", ip, port)) 196 addr, err := p2p.NewNetAddressString(idAddr) 197 assert.Nil(t, err, "error generating rand network address") 198 if addr.Routable() { 199 return addr 200 } 201 } 202 } 203 204 func TestAddrBookRemoveAddress(t *testing.T) { 205 fname := createTempFileName("addrbook_test") 206 defer deleteTempFile(fname) 207 208 book := NewAddrBook(fname, true) 209 book.SetLogger(log.TestingLogger()) 210 211 addr := randIPv4Address(t) 212 book.AddAddress(addr, addr) 213 assert.Equal(t, 1, book.Size()) 214 215 book.RemoveAddress(addr) 216 assert.Equal(t, 0, book.Size()) 217 218 nonExistingAddr := randIPv4Address(t) 219 book.RemoveAddress(nonExistingAddr) 220 assert.Equal(t, 0, book.Size()) 221 } 222 223 func TestAddrBookGetSelectionWithOneMarkedGood(t *testing.T) { 224 // create a book with 10 addresses, 1 good/old and 9 new 225 book, fname := createAddrBookWithMOldAndNNewAddrs(t, 1, 9) 226 defer deleteTempFile(fname) 227 228 addrs := book.GetSelectionWithBias(biasToSelectNewPeers) 229 assert.NotNil(t, addrs) 230 assertMOldAndNNewAddrsInSelection(t, 1, 9, addrs, book) 231 } 232 233 func TestAddrBookGetSelectionWithOneNotMarkedGood(t *testing.T) { 234 // create a book with 10 addresses, 9 good/old and 1 new 235 book, fname := createAddrBookWithMOldAndNNewAddrs(t, 9, 1) 236 defer deleteTempFile(fname) 237 238 addrs := book.GetSelectionWithBias(biasToSelectNewPeers) 239 assert.NotNil(t, addrs) 240 assertMOldAndNNewAddrsInSelection(t, 9, 1, addrs, book) 241 } 242 243 func TestAddrBookGetSelectionReturnsNilWhenAddrBookIsEmpty(t *testing.T) { 244 book, fname := createAddrBookWithMOldAndNNewAddrs(t, 0, 0) 245 defer deleteTempFile(fname) 246 247 addrs := book.GetSelectionWithBias(biasToSelectNewPeers) 248 assert.Nil(t, addrs) 249 } 250 251 func TestAddrBookGetSelection(t *testing.T) { 252 fname := createTempFileName("addrbook_test") 253 defer deleteTempFile(fname) 254 255 book := NewAddrBook(fname, true) 256 book.SetLogger(log.TestingLogger()) 257 258 // 1) empty book 259 assert.Empty(t, book.GetSelection()) 260 261 // 2) add one address 262 addr := randIPv4Address(t) 263 book.AddAddress(addr, addr) 264 265 assert.Equal(t, 1, len(book.GetSelection())) 266 assert.Equal(t, addr, book.GetSelection()[0]) 267 268 // 3) add a bunch of addresses 269 randAddrs := randNetAddressPairs(t, 100) 270 for _, addrSrc := range randAddrs { 271 book.AddAddress(addrSrc.addr, addrSrc.src) 272 } 273 274 // check there is no duplicates 275 addrs := make(map[string]*p2p.NetAddress) 276 selection := book.GetSelection() 277 for _, addr := range selection { 278 if dup, ok := addrs[addr.String()]; ok { 279 t.Fatalf("selection %v contains duplicates %v", selection, dup) 280 } 281 addrs[addr.String()] = addr 282 } 283 284 if len(selection) > book.Size() { 285 t.Errorf("selection %v could not be bigger than the book", selection) 286 } 287 } 288 289 func TestAddrBookGetSelectionWithBias(t *testing.T) { 290 const biasTowardsNewAddrs = 30 291 292 fname := createTempFileName("addrbook_test") 293 defer deleteTempFile(fname) 294 295 book := NewAddrBook(fname, true) 296 book.SetLogger(log.TestingLogger()) 297 298 // 1) empty book 299 selection := book.GetSelectionWithBias(biasTowardsNewAddrs) 300 assert.Empty(t, selection) 301 302 // 2) add one address 303 addr := randIPv4Address(t) 304 book.AddAddress(addr, addr) 305 306 selection = book.GetSelectionWithBias(biasTowardsNewAddrs) 307 assert.Equal(t, 1, len(selection)) 308 assert.Equal(t, addr, selection[0]) 309 310 // 3) add a bunch of addresses 311 randAddrs := randNetAddressPairs(t, 100) 312 for _, addrSrc := range randAddrs { 313 book.AddAddress(addrSrc.addr, addrSrc.src) 314 } 315 316 // check there is no duplicates 317 addrs := make(map[string]*p2p.NetAddress) 318 selection = book.GetSelectionWithBias(biasTowardsNewAddrs) 319 for _, addr := range selection { 320 if dup, ok := addrs[addr.String()]; ok { 321 t.Fatalf("selection %v contains duplicates %v", selection, dup) 322 } 323 addrs[addr.String()] = addr 324 } 325 326 if len(selection) > book.Size() { 327 t.Fatalf("selection %v could not be bigger than the book", selection) 328 } 329 330 // 4) mark 80% of the addresses as good 331 randAddrsLen := len(randAddrs) 332 for i, addrSrc := range randAddrs { 333 if int((float64(i)/float64(randAddrsLen))*100) >= 20 { 334 book.MarkGood(addrSrc.addr.ID) 335 } 336 } 337 338 selection = book.GetSelectionWithBias(biasTowardsNewAddrs) 339 340 // check that ~70% of addresses returned are good 341 good := 0 342 for _, addr := range selection { 343 if book.IsGood(addr) { 344 good++ 345 } 346 } 347 348 got, expected := int((float64(good)/float64(len(selection)))*100), 100-biasTowardsNewAddrs 349 350 // compute some slack to protect against small differences due to rounding: 351 slack := int(math.Round(float64(100) / float64(len(selection)))) 352 if got > expected+slack { 353 t.Fatalf( 354 "got more good peers (%% got: %d, %% expected: %d, number of good addrs: %d, total: %d)", 355 got, 356 expected, 357 good, 358 len(selection), 359 ) 360 } 361 if got < expected-slack { 362 t.Fatalf( 363 "got fewer good peers (%% got: %d, %% expected: %d, number of good addrs: %d, total: %d)", 364 got, 365 expected, 366 good, 367 len(selection), 368 ) 369 } 370 } 371 372 func TestAddrBookHasAddress(t *testing.T) { 373 fname := createTempFileName("addrbook_test") 374 defer deleteTempFile(fname) 375 376 book := NewAddrBook(fname, true) 377 book.SetLogger(log.TestingLogger()) 378 addr := randIPv4Address(t) 379 book.AddAddress(addr, addr) 380 381 assert.True(t, book.HasAddress(addr)) 382 383 book.RemoveAddress(addr) 384 385 assert.False(t, book.HasAddress(addr)) 386 } 387 388 func testCreatePrivateAddrs(t *testing.T, numAddrs int) ([]*p2p.NetAddress, []string) { 389 addrs := make([]*p2p.NetAddress, numAddrs) 390 for i := 0; i < numAddrs; i++ { 391 addrs[i] = randIPv4Address(t) 392 } 393 394 private := make([]string, numAddrs) 395 for i, addr := range addrs { 396 private[i] = string(addr.ID) 397 } 398 return addrs, private 399 } 400 401 func TestBanBadPeers(t *testing.T) { 402 fname := createTempFileName("addrbook_test") 403 defer deleteTempFile(fname) 404 405 book := NewAddrBook(fname, true) 406 book.SetLogger(log.TestingLogger()) 407 408 addr := randIPv4Address(t) 409 _ = book.AddAddress(addr, addr) 410 411 book.MarkBad(addr, 1*time.Second) 412 // addr should not reachable 413 assert.False(t, book.HasAddress(addr)) 414 assert.True(t, book.IsBanned(addr)) 415 416 err := book.AddAddress(addr, addr) 417 // book should not add address from the blacklist 418 assert.Error(t, err) 419 420 time.Sleep(1 * time.Second) 421 book.ReinstateBadPeers() 422 // address should be reinstated in the new bucket 423 assert.EqualValues(t, 1, book.Size()) 424 assert.True(t, book.HasAddress(addr)) 425 assert.False(t, book.IsGood(addr)) 426 } 427 428 func TestAddrBookEmpty(t *testing.T) { 429 fname := createTempFileName("addrbook_test") 430 defer deleteTempFile(fname) 431 432 book := NewAddrBook(fname, true) 433 book.SetLogger(log.TestingLogger()) 434 // Check that empty book is empty 435 require.True(t, book.Empty()) 436 // Check that book with our address is empty 437 book.AddOurAddress(randIPv4Address(t)) 438 require.True(t, book.Empty()) 439 // Check that book with private addrs is empty 440 _, privateIds := testCreatePrivateAddrs(t, 5) 441 book.AddPrivateIDs(privateIds) 442 require.True(t, book.Empty()) 443 444 // Check that book with address is not empty 445 book.AddAddress(randIPv4Address(t), randIPv4Address(t)) 446 require.False(t, book.Empty()) 447 } 448 449 func TestPrivatePeers(t *testing.T) { 450 fname := createTempFileName("addrbook_test") 451 defer deleteTempFile(fname) 452 453 book := NewAddrBook(fname, true) 454 book.SetLogger(log.TestingLogger()) 455 456 addrs, private := testCreatePrivateAddrs(t, 10) 457 book.AddPrivateIDs(private) 458 459 // private addrs must not be added 460 for _, addr := range addrs { 461 err := book.AddAddress(addr, addr) 462 if assert.Error(t, err) { 463 _, ok := err.(ErrAddrBookPrivate) 464 assert.True(t, ok) 465 } 466 } 467 468 // addrs coming from private peers must not be added 469 err := book.AddAddress(randIPv4Address(t), addrs[0]) 470 if assert.Error(t, err) { 471 _, ok := err.(ErrAddrBookPrivateSrc) 472 assert.True(t, ok) 473 } 474 } 475 476 func testAddrBookAddressSelection(t *testing.T, bookSize int) { 477 // generate all combinations of old (m) and new addresses 478 for nBookOld := 0; nBookOld <= bookSize; nBookOld++ { 479 nBookNew := bookSize - nBookOld 480 dbgStr := fmt.Sprintf("book of size %d (new %d, old %d)", bookSize, nBookNew, nBookOld) 481 482 // create book and get selection 483 book, fname := createAddrBookWithMOldAndNNewAddrs(t, nBookOld, nBookNew) 484 defer deleteTempFile(fname) 485 addrs := book.GetSelectionWithBias(biasToSelectNewPeers) 486 assert.NotNil(t, addrs, "%s - expected a non-nil selection", dbgStr) 487 nAddrs := len(addrs) 488 assert.NotZero(t, nAddrs, "%s - expected at least one address in selection", dbgStr) 489 490 // check there's no nil addresses 491 for _, addr := range addrs { 492 if addr == nil { 493 t.Fatalf("%s - got nil address in selection %v", dbgStr, addrs) 494 } 495 } 496 497 // XXX: shadowing 498 nOld, nNew := countOldAndNewAddrsInSelection(addrs, book) 499 500 // Given: 501 // n - num new addrs, m - num old addrs 502 // k - num new addrs expected in the beginning (based on bias %) 503 // i=min(n, max(k,r-m)), aka expNew 504 // j=min(m, r-i), aka expOld 505 // 506 // We expect this layout: 507 // indices: 0...i-1 i...i+j-1 508 // addresses: N0..Ni-1 O0..Oj-1 509 // 510 // There is at least one partition and at most three. 511 var ( 512 k = percentageOfNum(biasToSelectNewPeers, nAddrs) 513 expNew = tmmath.MinInt(nNew, tmmath.MaxInt(k, nAddrs-nBookOld)) 514 expOld = tmmath.MinInt(nOld, nAddrs-expNew) 515 ) 516 517 // Verify that the number of old and new addresses are as expected 518 if nNew != expNew { 519 t.Fatalf("%s - expected new addrs %d, got %d", dbgStr, expNew, nNew) 520 } 521 if nOld != expOld { 522 t.Fatalf("%s - expected old addrs %d, got %d", dbgStr, expOld, nOld) 523 } 524 525 // Verify that the order of addresses is as expected 526 // Get the sequence types and lengths of the selection 527 seqLens, seqTypes, err := analyseSelectionLayout(book, addrs) 528 assert.NoError(t, err, "%s", dbgStr) 529 530 // Build a list with the expected lengths of partitions and another with the expected types, e.g.: 531 // expSeqLens = [10, 22], expSeqTypes = [1, 2] 532 // means we expect 10 new (type 1) addresses followed by 22 old (type 2) addresses. 533 var expSeqLens []int 534 var expSeqTypes []int 535 536 switch { 537 case expOld == 0: // all new addresses 538 expSeqLens = []int{nAddrs} 539 expSeqTypes = []int{1} 540 case expNew == 0: // all old addresses 541 expSeqLens = []int{nAddrs} 542 expSeqTypes = []int{2} 543 case nAddrs-expNew-expOld == 0: // new addresses, old addresses 544 expSeqLens = []int{expNew, expOld} 545 expSeqTypes = []int{1, 2} 546 } 547 548 assert.Equal(t, expSeqLens, seqLens, 549 "%s - expected sequence lengths of old/new %v, got %v", 550 dbgStr, expSeqLens, seqLens) 551 assert.Equal(t, expSeqTypes, seqTypes, 552 "%s - expected sequence types (1-new, 2-old) was %v, got %v", 553 dbgStr, expSeqTypes, seqTypes) 554 } 555 } 556 557 func TestMultipleAddrBookAddressSelection(t *testing.T) { 558 // test books with smaller size, < N 559 const N = 32 560 for bookSize := 1; bookSize < N; bookSize++ { 561 testAddrBookAddressSelection(t, bookSize) 562 } 563 564 // Test for two books with sizes from following ranges 565 ranges := [...][]int{{33, 100}, {100, 175}} 566 bookSizes := make([]int, 0, len(ranges)) 567 for _, r := range ranges { 568 bookSizes = append(bookSizes, tmrand.Intn(r[1]-r[0])+r[0]) 569 } 570 t.Logf("Testing address selection for the following book sizes %v\n", bookSizes) 571 for _, bookSize := range bookSizes { 572 testAddrBookAddressSelection(t, bookSize) 573 } 574 } 575 576 func TestAddrBookGroupKey(t *testing.T) { 577 // non-strict routability 578 testCases := []struct { 579 name string 580 ip string 581 expKey string 582 }{ 583 // IPv4 normal. 584 {"ipv4 normal class a", "12.1.2.3", "12.1.0.0"}, 585 {"ipv4 normal class b", "173.1.2.3", "173.1.0.0"}, 586 {"ipv4 normal class c", "196.1.2.3", "196.1.0.0"}, 587 588 // IPv6/IPv4 translations. 589 {"ipv6 rfc3964 with ipv4 encap", "2002:0c01:0203::", "12.1.0.0"}, 590 {"ipv6 rfc4380 toredo ipv4", "2001:0:1234::f3fe:fdfc", "12.1.0.0"}, 591 {"ipv6 rfc6052 well-known prefix with ipv4", "64:ff9b::0c01:0203", "12.1.0.0"}, 592 {"ipv6 rfc6145 translated ipv4", "::ffff:0:0c01:0203", "12.1.0.0"}, 593 594 // Tor. 595 {"ipv6 tor onioncat", "fd87:d87e:eb43:1234::5678", "tor:2"}, 596 {"ipv6 tor onioncat 2", "fd87:d87e:eb43:1245::6789", "tor:2"}, 597 {"ipv6 tor onioncat 3", "fd87:d87e:eb43:1345::6789", "tor:3"}, 598 599 // IPv6 normal. 600 {"ipv6 normal", "2602:100::1", "2602:100::"}, 601 {"ipv6 normal 2", "2602:0100::1234", "2602:100::"}, 602 {"ipv6 hurricane electric", "2001:470:1f10:a1::2", "2001:470:1000::"}, 603 {"ipv6 hurricane electric 2", "2001:0470:1f10:a1::2", "2001:470:1000::"}, 604 } 605 606 for i, tc := range testCases { 607 nip := net.ParseIP(tc.ip) 608 key := groupKeyFor(p2p.NewNetAddressIPPort(nip, 26656), false) 609 assert.Equal(t, tc.expKey, key, "#%d", i) 610 } 611 612 // strict routability 613 testCases = []struct { 614 name string 615 ip string 616 expKey string 617 }{ 618 // Local addresses. 619 {"ipv4 localhost", "127.0.0.1", "local"}, 620 {"ipv6 localhost", "::1", "local"}, 621 {"ipv4 zero", "0.0.0.0", "local"}, 622 {"ipv4 first octet zero", "0.1.2.3", "local"}, 623 624 // Unroutable addresses. 625 {"ipv4 invalid bcast", "255.255.255.255", "unroutable"}, 626 {"ipv4 rfc1918 10/8", "10.1.2.3", "unroutable"}, 627 {"ipv4 rfc1918 172.16/12", "172.16.1.2", "unroutable"}, 628 {"ipv4 rfc1918 192.168/16", "192.168.1.2", "unroutable"}, 629 {"ipv6 rfc3849 2001:db8::/32", "2001:db8::1234", "unroutable"}, 630 {"ipv4 rfc3927 169.254/16", "169.254.1.2", "unroutable"}, 631 {"ipv6 rfc4193 fc00::/7", "fc00::1234", "unroutable"}, 632 {"ipv6 rfc4843 2001:10::/28", "2001:10::1234", "unroutable"}, 633 {"ipv6 rfc4862 fe80::/64", "fe80::1234", "unroutable"}, 634 } 635 636 for i, tc := range testCases { 637 nip := net.ParseIP(tc.ip) 638 key := groupKeyFor(p2p.NewNetAddressIPPort(nip, 26656), true) 639 assert.Equal(t, tc.expKey, key, "#%d", i) 640 } 641 } 642 643 func assertMOldAndNNewAddrsInSelection(t *testing.T, m, n int, addrs []*p2p.NetAddress, book *addrBook) { 644 nOld, nNew := countOldAndNewAddrsInSelection(addrs, book) 645 assert.Equal(t, m, nOld, "old addresses") 646 assert.Equal(t, n, nNew, "new addresses") 647 } 648 649 func createTempFileName(prefix string) string { 650 f, err := ioutil.TempFile("", prefix) 651 if err != nil { 652 panic(err) 653 } 654 fname := f.Name() 655 err = f.Close() 656 if err != nil { 657 panic(err) 658 } 659 return fname 660 } 661 662 func deleteTempFile(fname string) { 663 err := os.Remove(fname) 664 if err != nil { 665 panic(err) 666 } 667 } 668 669 func createAddrBookWithMOldAndNNewAddrs(t *testing.T, nOld, nNew int) (book *addrBook, fname string) { 670 fname = createTempFileName("addrbook_test") 671 672 book = NewAddrBook(fname, true).(*addrBook) 673 book.SetLogger(log.TestingLogger()) 674 assert.Zero(t, book.Size()) 675 676 randAddrs := randNetAddressPairs(t, nOld) 677 for _, addr := range randAddrs { 678 book.AddAddress(addr.addr, addr.src) 679 book.MarkGood(addr.addr.ID) 680 } 681 682 randAddrs = randNetAddressPairs(t, nNew) 683 for _, addr := range randAddrs { 684 book.AddAddress(addr.addr, addr.src) 685 } 686 687 return 688 } 689 690 func countOldAndNewAddrsInSelection(addrs []*p2p.NetAddress, book *addrBook) (nOld, nNew int) { 691 for _, addr := range addrs { 692 if book.IsGood(addr) { 693 nOld++ 694 } else { 695 nNew++ 696 } 697 } 698 return 699 } 700 701 // Analyse the layout of the selection specified by 'addrs' 702 // Returns: 703 // - seqLens - the lengths of the sequences of addresses of same type 704 // - seqTypes - the types of sequences in selection 705 func analyseSelectionLayout(book *addrBook, addrs []*p2p.NetAddress) (seqLens, seqTypes []int, err error) { 706 // address types are: 0 - nil, 1 - new, 2 - old 707 var ( 708 prevType = 0 709 currentSeqLen = 0 710 ) 711 712 for _, addr := range addrs { 713 addrType := 0 714 if book.IsGood(addr) { 715 addrType = 2 716 } else { 717 addrType = 1 718 } 719 if addrType != prevType && prevType != 0 { 720 seqLens = append(seqLens, currentSeqLen) 721 seqTypes = append(seqTypes, prevType) 722 currentSeqLen = 0 723 } 724 currentSeqLen++ 725 prevType = addrType 726 } 727 728 seqLens = append(seqLens, currentSeqLen) 729 seqTypes = append(seqTypes, prevType) 730 731 return 732 } 733 734 func BenchmarkAddrBook_hash(b *testing.B) { 735 book := &addrBook{ 736 ourAddrs: make(map[string]struct{}), 737 privateIDs: make(map[p2p.ID]struct{}), 738 addrLookup: make(map[p2p.ID]*knownAddress), 739 badPeers: make(map[p2p.ID]*knownAddress), 740 filePath: "", 741 routabilityStrict: true, 742 } 743 book.init() 744 msg := []byte(`foobar`) 745 b.ResetTimer() 746 for i := 0; i < b.N; i++ { 747 _, _ = book.hash(msg) 748 } 749 }