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