mirror of
				https://github.com/golang/go.git
				synced 2025-10-31 16:50:58 +00:00 
			
		
		
		
	net: detect changes to /etc/resolv.conf.
Implement the changes as suggested by rsc. Fixes #6670. LGTM=josharian, iant R=golang-codereviews, iant, josharian, mikioh.mikioh, alex, gobot CC=golang-codereviews, rsc https://golang.org/cl/83690045
This commit is contained in:
		
							parent
							
								
									79fb16d32c
								
							
						
					
					
						commit
						bf1d400d1c
					
				
					 2 changed files with 203 additions and 29 deletions
				
			
		|  | @ -7,7 +7,13 @@ | |||
| package net | ||||
| 
 | ||||
| import ( | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"path" | ||||
| 	"reflect" | ||||
| 	"testing" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| func TestTCPLookup(t *testing.T) { | ||||
|  | @ -25,3 +31,129 @@ func TestTCPLookup(t *testing.T) { | |||
| 		t.Fatalf("exchange failed: %v", err) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 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]"}) | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Guillaume J. Charmes
						Guillaume J. Charmes