ALL

For reading and verification only. You may not copy, use, modify or redistribute this code. Full notice on the main page.

tunnel/hints_test.go

SHA-256: a3aabc10caa5401d1eccd7109354c8ad2822d2349e3dd37797549a36c424a6f9
93 lines · 2674 bytes · View on GitHub

1package main
2
3import (
4 "fmt"
5 "net/netip"
6 "testing"
7 "time"
8)
9
10func newTestHints(ttl time.Duration, perLabel int) (*hintTable, *fakeClock) {
11 fc := newFakeClock()
12 return newHintTable(newClock(fc.Now, fc.AfterFunc), ttl, perLabel), fc
13}
14
15func addrs(texts ...string) []netip.Addr {
16 var out []netip.Addr
17 for _, t := range texts {
18 out = append(out, netip.MustParseAddr(t))
19 }
20 return out
21}
22
23func TestHints_AMarkLastsItsTTLFromTheLastHintAndBelongsToOneHost(t *testing.T) {
24 h, fc := newTestHints(15*time.Minute, 64)
25 a := netip.MustParseAddr("203.0.113.5")
26 h.mark("one.example", addrs("203.0.113.5"))
27 if !h.good("one.example", a) {
28 t.Fatal("not good right after the HINT")
29 }
30 if h.good("two.example", a) {
31 t.Fatal("a mark for one host counts for another")
32 }
33 fc.Advance(14 * time.Minute)
34 if !h.good("one.example", a) {
35 t.Fatal("expired early")
36 }
37 h.mark("one.example", addrs("203.0.113.5")) // the device says it again: the clock starts over
38 fc.Advance(14 * time.Minute)
39 if !h.good("one.example", a) {
40 t.Fatal("a repeated HINT did not renew the mark")
41 }
42 fc.Advance(2 * time.Minute)
43 if h.good("one.example", a) {
44 t.Fatal("outlived its TTL")
45 }
46 h.Sweep()
47 if h.size() != 0 {
48 t.Fatalf("%d left after the sweep", h.size())
49 }
50}
51
52func TestHints_AddressesAreCompared_AsTheyAre_WithoutZoneOrMapping(t *testing.T) {
53 h, _ := newTestHints(time.Hour, 64)
54 h.mark("h", addrs("::ffff:203.0.113.9", "fe80::1%eth0"))
55 if !h.good("h", netip.MustParseAddr("203.0.113.9")) {
56 t.Fatal("an IPv4-mapped mark is the IPv4 address")
57 }
58 if !h.good("h", netip.MustParseAddr("fe80::1")) {
59 t.Fatal("a zone is not part of an address")
60 }
61 if h.good("h", netip.MustParseAddr("203.0.113.10")) {
62 t.Fatal("the neighbouring address is good too")
63 }
64}
65
66func TestHints_ADeviceCanMarkOnlyAFixedNumberAndTheOldestGoFirst(t *testing.T) {
67 h, fc := newTestHints(time.Hour, 5)
68 for i := 0; i < 5; i++ {
69 h.mark("h", addrs(fmt.Sprintf("203.0.113.%d", i+1)))
70 fc.Advance(time.Second)
71 }
72 h.mark("h", addrs("203.0.113.100", "203.0.113.101"))
73 if h.size() != 5 {
74 t.Fatalf("%d addresses, cap 5", h.size())
75 }
76 for _, gone := range []string{"203.0.113.1", "203.0.113.2"} {
77 if h.good("h", netip.MustParseAddr(gone)) {
78 t.Fatalf("%s kept although it is the oldest", gone)
79 }
80 }
81 for _, kept := range []string{"203.0.113.3", "203.0.113.5", "203.0.113.100", "203.0.113.101"} {
82 if !h.good("h", netip.MustParseAddr(kept)) {
83 t.Fatalf("%s lost", kept)
84 }
85 }
86 // a flood of hints cannot grow the table without bound
87 for i := 0; i < 1000; i++ {
88 h.mark("h", addrs(fmt.Sprintf("198.51.100.%d", i%250)))
89 }
90 if h.size() > 5 {
91 t.Fatalf("%d addresses after a flood", h.size())
92 }
93}