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