github.com/blocknative/go-ethereum@v1.9.7/p2p/netutil/iptrack_test.go (about) 1 // Copyright 2018 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 netutil 18 19 import ( 20 "fmt" 21 mrand "math/rand" 22 "testing" 23 "time" 24 25 "github.com/ethereum/go-ethereum/common/mclock" 26 ) 27 28 const ( 29 opStatement = iota 30 opContact 31 opPredict 32 opCheckFullCone 33 ) 34 35 type iptrackTestEvent struct { 36 op int 37 time int // absolute, in milliseconds 38 ip, from string 39 } 40 41 func TestIPTracker(t *testing.T) { 42 tests := map[string][]iptrackTestEvent{ 43 "minStatements": { 44 {opPredict, 0, "", ""}, 45 {opStatement, 0, "127.0.0.1", "127.0.0.2"}, 46 {opPredict, 1000, "", ""}, 47 {opStatement, 1000, "127.0.0.1", "127.0.0.3"}, 48 {opPredict, 1000, "", ""}, 49 {opStatement, 1000, "127.0.0.1", "127.0.0.4"}, 50 {opPredict, 1000, "127.0.0.1", ""}, 51 }, 52 "window": { 53 {opStatement, 0, "127.0.0.1", "127.0.0.2"}, 54 {opStatement, 2000, "127.0.0.1", "127.0.0.3"}, 55 {opStatement, 3000, "127.0.0.1", "127.0.0.4"}, 56 {opPredict, 10000, "127.0.0.1", ""}, 57 {opPredict, 10001, "", ""}, // first statement expired 58 {opStatement, 10100, "127.0.0.1", "127.0.0.2"}, 59 {opPredict, 10200, "127.0.0.1", ""}, 60 }, 61 "fullcone": { 62 {opContact, 0, "", "127.0.0.2"}, 63 {opStatement, 10, "127.0.0.1", "127.0.0.2"}, 64 {opContact, 2000, "", "127.0.0.3"}, 65 {opStatement, 2010, "127.0.0.1", "127.0.0.3"}, 66 {opContact, 3000, "", "127.0.0.4"}, 67 {opStatement, 3010, "127.0.0.1", "127.0.0.4"}, 68 {opCheckFullCone, 3500, "false", ""}, 69 }, 70 "fullcone_2": { 71 {opContact, 0, "", "127.0.0.2"}, 72 {opStatement, 10, "127.0.0.1", "127.0.0.2"}, 73 {opContact, 2000, "", "127.0.0.3"}, 74 {opStatement, 2010, "127.0.0.1", "127.0.0.3"}, 75 {opStatement, 3000, "127.0.0.1", "127.0.0.4"}, 76 {opContact, 3010, "", "127.0.0.4"}, 77 {opCheckFullCone, 3500, "true", ""}, 78 }, 79 } 80 for name, test := range tests { 81 t.Run(name, func(t *testing.T) { runIPTrackerTest(t, test) }) 82 } 83 } 84 85 func runIPTrackerTest(t *testing.T, evs []iptrackTestEvent) { 86 var ( 87 clock mclock.Simulated 88 it = NewIPTracker(10*time.Second, 10*time.Second, 3) 89 ) 90 it.clock = &clock 91 for i, ev := range evs { 92 evtime := time.Duration(ev.time) * time.Millisecond 93 clock.Run(evtime - time.Duration(clock.Now())) 94 switch ev.op { 95 case opStatement: 96 it.AddStatement(ev.from, ev.ip) 97 case opContact: 98 it.AddContact(ev.from) 99 case opPredict: 100 if pred := it.PredictEndpoint(); pred != ev.ip { 101 t.Errorf("op %d: wrong prediction %q, want %q", i, pred, ev.ip) 102 } 103 case opCheckFullCone: 104 pred := fmt.Sprintf("%t", it.PredictFullConeNAT()) 105 if pred != ev.ip { 106 t.Errorf("op %d: wrong prediction %s, want %s", i, pred, ev.ip) 107 } 108 } 109 } 110 } 111 112 // This checks that old statements and contacts are GCed even if Predict* isn't called. 113 func TestIPTrackerForceGC(t *testing.T) { 114 var ( 115 clock mclock.Simulated 116 window = 10 * time.Second 117 rate = 50 * time.Millisecond 118 max = int(window/rate) + 1 119 it = NewIPTracker(window, window, 3) 120 ) 121 it.clock = &clock 122 123 for i := 0; i < 5*max; i++ { 124 e1 := make([]byte, 4) 125 e2 := make([]byte, 4) 126 mrand.Read(e1) 127 mrand.Read(e2) 128 it.AddStatement(string(e1), string(e2)) 129 it.AddContact(string(e1)) 130 clock.Run(rate) 131 } 132 if len(it.contact) > 2*max { 133 t.Errorf("contacts not GCed, have %d", len(it.contact)) 134 } 135 if len(it.statements) > 2*max { 136 t.Errorf("statements not GCed, have %d", len(it.statements)) 137 } 138 }