github.com/codingfuture/orig-energi3@v0.8.4/les/freeclient_test.go (about) 1 // Copyright 2018 The Energi Core Authors 2 // Copyright 2018 The go-ethereum Authors 3 // This file is part of the Energi Core library. 4 // 5 // The Energi Core 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 Energi Core 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 Energi Core library. If not, see <http://www.gnu.org/licenses/>. 17 18 // Package light implements on-demand retrieval capable state and chain objects 19 // for the Ethereum Light Client. 20 package les 21 22 import ( 23 "fmt" 24 "math/rand" 25 "testing" 26 "time" 27 28 "github.com/ethereum/go-ethereum/common/mclock" 29 "github.com/ethereum/go-ethereum/ethdb" 30 ) 31 32 func TestFreeClientPoolL10C100(t *testing.T) { 33 testFreeClientPool(t, 10, 100) 34 } 35 36 func TestFreeClientPoolL40C200(t *testing.T) { 37 testFreeClientPool(t, 40, 200) 38 } 39 40 func TestFreeClientPoolL100C300(t *testing.T) { 41 testFreeClientPool(t, 100, 300) 42 } 43 44 const testFreeClientPoolTicks = 500000 45 46 func testFreeClientPool(t *testing.T, connLimit, clientCount int) { 47 var ( 48 clock mclock.Simulated 49 db = ethdb.NewMemDatabase() 50 pool = newFreeClientPool(db, connLimit, 10000, &clock) 51 connected = make([]bool, clientCount) 52 connTicks = make([]int, clientCount) 53 disconnCh = make(chan int, clientCount) 54 ) 55 peerId := func(i int) string { 56 return fmt.Sprintf("test peer #%d", i) 57 } 58 disconnFn := func(i int) func() { 59 return func() { 60 disconnCh <- i 61 } 62 } 63 64 // pool should accept new peers up to its connected limit 65 for i := 0; i < connLimit; i++ { 66 if pool.connect(peerId(i), disconnFn(i)) { 67 connected[i] = true 68 } else { 69 t.Fatalf("Test peer #%d rejected", i) 70 } 71 } 72 // since all accepted peers are new and should not be kicked out, the next one should be rejected 73 if pool.connect(peerId(connLimit), disconnFn(connLimit)) { 74 connected[connLimit] = true 75 t.Fatalf("Peer accepted over connected limit") 76 } 77 78 // randomly connect and disconnect peers, expect to have a similar total connection time at the end 79 for tickCounter := 0; tickCounter < testFreeClientPoolTicks; tickCounter++ { 80 clock.Run(1 * time.Second) 81 82 i := rand.Intn(clientCount) 83 if connected[i] { 84 pool.disconnect(peerId(i)) 85 connected[i] = false 86 connTicks[i] += tickCounter 87 } else { 88 if pool.connect(peerId(i), disconnFn(i)) { 89 connected[i] = true 90 connTicks[i] -= tickCounter 91 } 92 } 93 pollDisconnects: 94 for { 95 select { 96 case i := <-disconnCh: 97 pool.disconnect(peerId(i)) 98 if connected[i] { 99 connTicks[i] += tickCounter 100 connected[i] = false 101 } 102 default: 103 break pollDisconnects 104 } 105 } 106 } 107 108 expTicks := testFreeClientPoolTicks * connLimit / clientCount 109 expMin := expTicks - expTicks/10 110 expMax := expTicks + expTicks/10 111 112 // check if the total connected time of peers are all in the expected range 113 for i, c := range connected { 114 if c { 115 connTicks[i] += testFreeClientPoolTicks 116 } 117 if connTicks[i] < expMin || connTicks[i] > expMax { 118 t.Errorf("Total connected time of test node #%d (%d) outside expected range (%d to %d)", i, connTicks[i], expMin, expMax) 119 } 120 } 121 122 // a previously unknown peer should be accepted now 123 if !pool.connect("newPeer", func() {}) { 124 t.Fatalf("Previously unknown peer rejected") 125 } 126 127 // close and restart pool 128 pool.stop() 129 pool = newFreeClientPool(db, connLimit, 10000, &clock) 130 131 // try connecting all known peers (connLimit should be filled up) 132 for i := 0; i < clientCount; i++ { 133 pool.connect(peerId(i), func() {}) 134 } 135 // expect pool to remember known nodes and kick out one of them to accept a new one 136 if !pool.connect("newPeer2", func() {}) { 137 t.Errorf("Previously unknown peer rejected after restarting pool") 138 } 139 pool.stop() 140 }