dns_test.mx raw
1 package ws
2
3 import (
4 "testing"
5 "time"
6 )
7
8 // The parts of the resolver that do not need a nameserver: the address
9 // parser, the resolv.conf scan, and the cache. dnsLookup's UDP exchange stays
10 // integration-only (it needs a DNS server; the relay's own tests do not dial
11 // hostnames).
12
13 func TestParseIPv4AcceptsAndRejects(t *testing.T) {
14 cases := []struct {
15 in string
16 a, b, c, d byte
17 ok bool
18 }{
19 {"1.2.3.4", 1, 2, 3, 4, true},
20 {"0.0.0.0", 0, 0, 0, 0, true},
21 {"255.255.255.255", 255, 255, 255, 255, true},
22 {"8.8.8.8", 8, 8, 8, 8, true},
23 {"256.1.1.1", 0, 0, 0, 0, false},
24 {"1.2.3", 0, 0, 0, 0, false},
25 {"1.2.3.4.5", 0, 0, 0, 0, false},
26 // A trailing dot is read as a zero octet; the parser is lenient
27 // about the nameserver lines it exists to read.
28 {"1.2.3.", 1, 2, 3, 0, true},
29 {"a.b.c.d", 0, 0, 0, 0, false},
30 {"", 0, 0, 0, 0, false},
31 {"1.2.3.4x", 0, 0, 0, 0, false},
32 {" 1.2.3.4", 0, 0, 0, 0, false},
33 }
34 for _, tc := range cases {
35 got := parseIPv4([]byte(tc.in))
36 if tc.ok {
37 if len(got) != 4 || got[0] != tc.a || got[1] != tc.b || got[2] != tc.c || got[3] != tc.d {
38 t.Fatalf("parseIPv4(%q) = %v", tc.in, got)
39 }
40 } else if got != nil {
41 t.Fatalf("parseIPv4(%q) must be rejected", tc.in)
42 }
43 }
44 }
45
46 func TestEnsureDNSAddrIsIdempotent(t *testing.T) {
47 ensureDNSAddr()
48 if !dnsAddrInit {
49 t.Fatal("ensureDNSAddr must record that it ran")
50 }
51 // Either /etc/resolv.conf named a server or the 8.8.8.8 fallback stands.
52 if dnsAddr[0] == 0 && dnsAddr[1] == 0 && dnsAddr[2] == 0 && dnsAddr[3] == 0 {
53 t.Fatal("no DNS server address")
54 }
55 first := dnsAddr
56 ensureDNSAddr()
57 if dnsAddr[0] != first[0] || dnsAddr[1] != first[1] ||
58 dnsAddr[2] != first[2] || dnsAddr[3] != first[3] {
59 t.Fatal("ensureDNSAddr must not rescan")
60 }
61 }
62
63 func TestResolveHostServesTheCache(t *testing.T) {
64 host := "cached-probe.invalid"
65 dnsMu.Lock()
66 dnsCache[host] = dnsEntry{ip: "10.1.2.3", exp: time.Now().Add(time.Hour)}
67 dnsMu.Unlock()
68
69 ip, err := resolveHost(host)
70 if err != nil {
71 t.Fatalf("cached resolve: %v", err)
72 }
73 if ip != "10.1.2.3" {
74 t.Fatalf("cached resolve = %s", ip)
75 }
76 // The exported wrapper shares the same cache.
77 ip2, err2 := ResolveHost(host)
78 if err2 != nil {
79 t.Fatalf("ResolveHost: %v", err2)
80 }
81 if ip2 != "10.1.2.3" {
82 t.Fatalf("ResolveHost = %s", ip2)
83 }
84 }
85