mirror of https://github.com/tailscale/tailscale/
Merge 8085324449 into f8cd07fb8a
commit
c0a80d6c4e
@ -0,0 +1,109 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build linux
|
||||
|
||||
package dns
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"testing/synctest"
|
||||
|
||||
"github.com/illarion/gonotify/v3"
|
||||
|
||||
"tailscale.com/util/dnsname"
|
||||
"tailscale.com/util/eventbus/eventbustest"
|
||||
)
|
||||
|
||||
func TestDNSTrampleRecovery(t *testing.T) {
|
||||
HookWatchFile.Set(watchFile)
|
||||
synctest.Test(t, func(t *testing.T) {
|
||||
tmp := t.TempDir()
|
||||
if err := os.MkdirAll(filepath.Join(tmp, "etc"), 0700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
resolvPath := "/etc/resolv.conf"
|
||||
fs := directFS{prefix: tmp}
|
||||
readFile := func(t *testing.T, path string) string {
|
||||
t.Helper()
|
||||
b, err := fs.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
bus := eventbustest.NewBus(t)
|
||||
eventbustest.LogAllEvents(t, bus)
|
||||
m := newDirectManagerOnFS(t.Logf, nil, bus, fs)
|
||||
defer m.Close()
|
||||
|
||||
if err := m.SetDNS(OSConfig{
|
||||
Nameservers: []netip.Addr{netip.MustParseAddr("8.8.8.8"), netip.MustParseAddr("8.8.4.4")},
|
||||
SearchDomains: []dnsname.FQDN{"ts.net.", "ts-dns.test."},
|
||||
MatchDomains: []dnsname.FQDN{"ignored."},
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
want := `# resolv.conf(5) file generated by tailscale
|
||||
# For more info, see https://tailscale.com/s/resolvconf-overwrite
|
||||
# DO NOT EDIT THIS FILE BY HAND -- CHANGES WILL BE OVERWRITTEN
|
||||
|
||||
nameserver 8.8.8.8
|
||||
nameserver 8.8.4.4
|
||||
search ts.net ts-dns.test
|
||||
`
|
||||
if got := readFile(t, resolvPath); got != want {
|
||||
t.Fatalf("resolv.conf:\n%s, want:\n%s", got, want)
|
||||
}
|
||||
|
||||
tw := eventbustest.NewWatcher(t, bus)
|
||||
|
||||
trample := "Hvem er det som tramper på min bro?"
|
||||
if err := fs.WriteFile(resolvPath, []byte(trample), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
synctest.Wait()
|
||||
|
||||
if err := eventbustest.Expect(tw, eventbustest.Type[TrampleDNS]()); err != nil {
|
||||
t.Errorf("did not see trample event: %s", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// watchFile is generally copied from linuxtrample, but cancels the context
|
||||
// after one trample to end the test.
|
||||
func watchFile(ctx context.Context, dir, filename string, cb func()) error {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
|
||||
const events = gonotify.IN_ATTRIB |
|
||||
gonotify.IN_CLOSE_WRITE |
|
||||
gonotify.IN_CREATE |
|
||||
gonotify.IN_DELETE |
|
||||
gonotify.IN_MODIFY |
|
||||
gonotify.IN_MOVE
|
||||
|
||||
watcher, err := gonotify.NewDirWatcher(ctx, events, dir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("NewDirWatcher: %w", err)
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case event := <-watcher.C:
|
||||
if event.Name == filename {
|
||||
cb()
|
||||
cancel()
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue