dnsclient_unix_test.go 3.71 KB
Newer Older
1 2 3 4
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

5
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
6 7 8 9

package net

import (
10 11 12 13 14
	"io"
	"io/ioutil"
	"os"
	"path"
	"reflect"
15
	"testing"
16
	"time"
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
)

func TestTCPLookup(t *testing.T) {
	if testing.Short() || !*testExternal {
		t.Skip("skipping test to avoid external network")
	}
	c, err := Dial("tcp", "8.8.8.8:53")
	if err != nil {
		t.Fatalf("Dial failed: %v", err)
	}
	defer c.Close()
	cfg := &dnsConfig{timeout: 10, attempts: 3}
	_, err = exchange(cfg, c, "com.", dnsTypeALL)
	if err != nil {
		t.Fatalf("exchange failed: %v", err)
	}
}
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159

type resolvConfTest struct {
	*testing.T
	dir     string
	path    string
	started bool
	quitc   chan chan struct{}
}

func newResolvConfTest(t *testing.T) *resolvConfTest {
	dir, err := ioutil.TempDir("", "resolvConfTest")
	if err != nil {
		t.Fatalf("could not create temp dir: %v", err)
	}

	// Disable the default loadConfig
	onceLoadConfig.Do(func() {})

	r := &resolvConfTest{
		T:     t,
		dir:   dir,
		path:  path.Join(dir, "resolv.conf"),
		quitc: make(chan chan struct{}),
	}

	return r
}

func (r *resolvConfTest) Start() {
	loadConfig(r.path, 100*time.Millisecond, r.quitc)
	r.started = true
}

func (r *resolvConfTest) SetConf(s string) {
	// Make sure the file mtime will be different once we're done here,
	// even on systems with coarse (1s) mtime resolution.
	time.Sleep(time.Second)

	f, err := os.OpenFile(r.path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
	if err != nil {
		r.Fatalf("failed to create temp file %s: %v", r.path, err)
	}
	if _, err := io.WriteString(f, s); err != nil {
		f.Close()
		r.Fatalf("failed to write temp file: %v", err)
	}
	f.Close()

	if r.started {
		cfg.ch <- struct{}{} // fill buffer
		cfg.ch <- struct{}{} // wait for reload to begin
		cfg.ch <- struct{}{} // wait for reload to complete
	}
}

func (r *resolvConfTest) WantServers(want []string) {
	cfg.mu.RLock()
	defer cfg.mu.RUnlock()
	if got := cfg.dnsConfig.servers; !reflect.DeepEqual(got, want) {
		r.Fatalf("Unexpected dns server loaded, got %v want %v", got, want)
	}
}

func (r *resolvConfTest) Close() {
	resp := make(chan struct{})
	r.quitc <- resp
	<-resp
	if err := os.RemoveAll(r.dir); err != nil {
		r.Logf("failed to remove temp dir %s: %v", r.dir, err)
	}
}

func TestReloadResolvConfFail(t *testing.T) {
	if testing.Short() || !*testExternal {
		t.Skip("skipping test to avoid external network")
	}

	r := newResolvConfTest(t)
	defer r.Close()

	// resolv.conf.tmp does not exist yet
	r.Start()
	if _, err := goLookupIP("golang.org"); err == nil {
		t.Fatal("goLookupIP(missing) succeeded")
	}

	r.SetConf("nameserver 8.8.8.8")
	if _, err := goLookupIP("golang.org"); err != nil {
		t.Fatalf("goLookupIP(missing; good) failed: %v", err)
	}

	// Using a bad resolv.conf while we had a good
	// one before should not update the config
	r.SetConf("")
	if _, err := goLookupIP("golang.org"); err != nil {
		t.Fatalf("goLookupIP(missing; good; bad) failed: %v", err)
	}
}

func TestReloadResolvConfChange(t *testing.T) {
	if testing.Short() || !*testExternal {
		t.Skip("skipping test to avoid external network")
	}

	r := newResolvConfTest(t)
	defer r.Close()

	r.SetConf("nameserver 8.8.8.8")
	r.Start()

	if _, err := goLookupIP("golang.org"); err != nil {
		t.Fatalf("goLookupIP(good) failed: %v", err)
	}
	r.WantServers([]string{"[8.8.8.8]"})

	// Using a bad resolv.conf when we had a good one
	// before should not update the config
	r.SetConf("")
	if _, err := goLookupIP("golang.org"); err != nil {
		t.Fatalf("goLookupIP(good; bad) failed: %v", err)
	}

	// A new good config should get picked up
	r.SetConf("nameserver 8.8.4.4")
	r.WantServers([]string{"[8.8.4.4]"})
}