iptrack_test.go 3.9 KB

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