github.com/bloxroute-labs/bor@v0.1.4/les/freeclient_test.go (about) 1 // Copyright 2017 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package les 18 19 import ( 20 "fmt" 21 "math/rand" 22 "strconv" 23 "testing" 24 "time" 25 26 "github.com/maticnetwork/bor/common/mclock" 27 "github.com/maticnetwork/bor/core/rawdb" 28 ) 29 30 func TestFreeClientPoolL10C100(t *testing.T) { 31 testFreeClientPool(t, 10, 100) 32 } 33 34 func TestFreeClientPoolL40C200(t *testing.T) { 35 testFreeClientPool(t, 40, 200) 36 } 37 38 func TestFreeClientPoolL100C300(t *testing.T) { 39 testFreeClientPool(t, 100, 300) 40 } 41 42 const testFreeClientPoolTicks = 500000 43 44 func testFreeClientPool(t *testing.T, connLimit, clientCount int) { 45 var ( 46 clock mclock.Simulated 47 db = rawdb.NewMemoryDatabase() 48 connected = make([]bool, clientCount) 49 connTicks = make([]int, clientCount) 50 disconnCh = make(chan int, clientCount) 51 peerAddress = func(i int) string { 52 return fmt.Sprintf("addr #%d", i) 53 } 54 peerId = func(i int) string { 55 return fmt.Sprintf("id #%d", i) 56 } 57 disconnFn = func(id string) { 58 i, err := strconv.Atoi(id[4:]) 59 if err != nil { 60 panic(err) 61 } 62 disconnCh <- i 63 } 64 pool = newFreeClientPool(db, 1, 10000, &clock, disconnFn) 65 ) 66 pool.setLimits(connLimit, uint64(connLimit)) 67 68 // pool should accept new peers up to its connected limit 69 for i := 0; i < connLimit; i++ { 70 if pool.connect(peerAddress(i), peerId(i)) { 71 connected[i] = true 72 } else { 73 t.Fatalf("Test peer #%d rejected", i) 74 } 75 } 76 // since all accepted peers are new and should not be kicked out, the next one should be rejected 77 if pool.connect(peerAddress(connLimit), peerId(connLimit)) { 78 connected[connLimit] = true 79 t.Fatalf("Peer accepted over connected limit") 80 } 81 82 // randomly connect and disconnect peers, expect to have a similar total connection time at the end 83 for tickCounter := 0; tickCounter < testFreeClientPoolTicks; tickCounter++ { 84 clock.Run(1 * time.Second) 85 86 i := rand.Intn(clientCount) 87 if connected[i] { 88 pool.disconnect(peerAddress(i)) 89 connected[i] = false 90 connTicks[i] += tickCounter 91 } else { 92 if pool.connect(peerAddress(i), peerId(i)) { 93 connected[i] = true 94 connTicks[i] -= tickCounter 95 } 96 } 97 pollDisconnects: 98 for { 99 select { 100 case i := <-disconnCh: 101 pool.disconnect(peerAddress(i)) 102 if connected[i] { 103 connTicks[i] += tickCounter 104 connected[i] = false 105 } 106 default: 107 break pollDisconnects 108 } 109 } 110 } 111 112 expTicks := testFreeClientPoolTicks * connLimit / clientCount 113 expMin := expTicks - expTicks/10 114 expMax := expTicks + expTicks/10 115 116 // check if the total connected time of peers are all in the expected range 117 for i, c := range connected { 118 if c { 119 connTicks[i] += testFreeClientPoolTicks 120 } 121 if connTicks[i] < expMin || connTicks[i] > expMax { 122 t.Errorf("Total connected time of test node #%d (%d) outside expected range (%d to %d)", i, connTicks[i], expMin, expMax) 123 } 124 } 125 126 // a previously unknown peer should be accepted now 127 if !pool.connect("newAddr", "newId") { 128 t.Fatalf("Previously unknown peer rejected") 129 } 130 131 // close and restart pool 132 pool.stop() 133 pool = newFreeClientPool(db, 1, 10000, &clock, disconnFn) 134 pool.setLimits(connLimit, uint64(connLimit)) 135 136 // try connecting all known peers (connLimit should be filled up) 137 for i := 0; i < clientCount; i++ { 138 pool.connect(peerAddress(i), peerId(i)) 139 } 140 // expect pool to remember known nodes and kick out one of them to accept a new one 141 if !pool.connect("newAddr2", "newId2") { 142 t.Errorf("Previously unknown peer rejected after restarting pool") 143 } 144 pool.stop() 145 }