123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- // Copyright 2018 The go-ethereum Authors
- // This file is part of the go-ethereum library.
- //
- // The go-ethereum library is free software: you can redistribute it and/or modify
- // it under the terms of the GNU Lesser General Public License as published by
- // the Free Software Foundation, either version 3 of the License, or
- // (at your option) any later version.
- //
- // The go-ethereum library is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU Lesser General Public License for more details.
- //
- // You should have received a copy of the GNU Lesser General Public License
- // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
- package netutil
- import (
- "fmt"
- mrand "math/rand"
- "testing"
- "time"
- "github.com/ethereum/go-ethereum/common/mclock"
- )
- const (
- opStatement = iota
- opContact
- opPredict
- opCheckFullCone
- )
- type iptrackTestEvent struct {
- op int
- time int // absolute, in milliseconds
- ip, from string
- }
- func TestIPTracker(t *testing.T) {
- tests := map[string][]iptrackTestEvent{
- "minStatements": {
- {opPredict, 0, "", ""},
- {opStatement, 0, "127.0.0.1", "127.0.0.2"},
- {opPredict, 1000, "", ""},
- {opStatement, 1000, "127.0.0.1", "127.0.0.3"},
- {opPredict, 1000, "", ""},
- {opStatement, 1000, "127.0.0.1", "127.0.0.4"},
- {opPredict, 1000, "127.0.0.1", ""},
- },
- "window": {
- {opStatement, 0, "127.0.0.1", "127.0.0.2"},
- {opStatement, 2000, "127.0.0.1", "127.0.0.3"},
- {opStatement, 3000, "127.0.0.1", "127.0.0.4"},
- {opPredict, 10000, "127.0.0.1", ""},
- {opPredict, 10001, "", ""}, // first statement expired
- {opStatement, 10100, "127.0.0.1", "127.0.0.2"},
- {opPredict, 10200, "127.0.0.1", ""},
- },
- "fullcone": {
- {opContact, 0, "", "127.0.0.2"},
- {opStatement, 10, "127.0.0.1", "127.0.0.2"},
- {opContact, 2000, "", "127.0.0.3"},
- {opStatement, 2010, "127.0.0.1", "127.0.0.3"},
- {opContact, 3000, "", "127.0.0.4"},
- {opStatement, 3010, "127.0.0.1", "127.0.0.4"},
- {opCheckFullCone, 3500, "false", ""},
- },
- "fullcone_2": {
- {opContact, 0, "", "127.0.0.2"},
- {opStatement, 10, "127.0.0.1", "127.0.0.2"},
- {opContact, 2000, "", "127.0.0.3"},
- {opStatement, 2010, "127.0.0.1", "127.0.0.3"},
- {opStatement, 3000, "127.0.0.1", "127.0.0.4"},
- {opContact, 3010, "", "127.0.0.4"},
- {opCheckFullCone, 3500, "true", ""},
- },
- }
- for name, test := range tests {
- t.Run(name, func(t *testing.T) { runIPTrackerTest(t, test) })
- }
- }
- func runIPTrackerTest(t *testing.T, evs []iptrackTestEvent) {
- var (
- clock mclock.Simulated
- it = NewIPTracker(10*time.Second, 10*time.Second, 3)
- )
- it.clock = &clock
- for i, ev := range evs {
- evtime := time.Duration(ev.time) * time.Millisecond
- clock.Run(evtime - time.Duration(clock.Now()))
- switch ev.op {
- case opStatement:
- it.AddStatement(ev.from, ev.ip)
- case opContact:
- it.AddContact(ev.from)
- case opPredict:
- if pred := it.PredictEndpoint(); pred != ev.ip {
- t.Errorf("op %d: wrong prediction %q, want %q", i, pred, ev.ip)
- }
- case opCheckFullCone:
- pred := fmt.Sprintf("%t", it.PredictFullConeNAT())
- if pred != ev.ip {
- t.Errorf("op %d: wrong prediction %s, want %s", i, pred, ev.ip)
- }
- }
- }
- }
- // This checks that old statements and contacts are GCed even if Predict* isn't called.
- func TestIPTrackerForceGC(t *testing.T) {
- var (
- clock mclock.Simulated
- window = 10 * time.Second
- rate = 50 * time.Millisecond
- max = int(window/rate) + 1
- it = NewIPTracker(window, window, 3)
- )
- it.clock = &clock
- for i := 0; i < 5*max; i++ {
- e1 := make([]byte, 4)
- e2 := make([]byte, 4)
- mrand.Read(e1)
- mrand.Read(e2)
- it.AddStatement(string(e1), string(e2))
- it.AddContact(string(e1))
- clock.Run(rate)
- }
- if len(it.contact) > 2*max {
- t.Errorf("contacts not GCed, have %d", len(it.contact))
- }
- if len(it.statements) > 2*max {
- t.Errorf("statements not GCed, have %d", len(it.statements))
- }
- }
|