From 065c4ffc2c6ac3d4d28a30a2b3ef06d55fea19b8 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Mon, 30 Aug 2021 14:16:12 -0700 Subject: [PATCH] net/dns: add start of Linux newOSConfigurator tests Only one test case so far. Signed-off-by: Brad Fitzpatrick --- net/dns/manager_linux.go | 6 +-- net/dns/manager_linux_test.go | 84 +++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 net/dns/manager_linux_test.go diff --git a/net/dns/manager_linux.go b/net/dns/manager_linux.go index a439571b6..99e170495 100644 --- a/net/dns/manager_linux.go +++ b/net/dns/manager_linux.go @@ -29,7 +29,6 @@ func (kv kv) String() string { func NewOSConfigurator(logf logger.Logf, interfaceName string) (ret OSConfigurator, err error) { return newOSConfigurator(logf, interfaceName, newOSConfigEnv{ fs: directFS{}, - ReadFile: os.ReadFile, resolvOwner: resolvOwner, resolvedIsActuallyResolver: resolvedIsActuallyResolver, dbusPing: dbusPing, @@ -42,8 +41,7 @@ func NewOSConfigurator(logf logger.Logf, interfaceName string) (ret OSConfigurat // newOSConfigEnv are the funcs newOSConfigurator needs, pulled out for testing. type newOSConfigEnv struct { fs wholeFileFS - ReadFile func(name string) ([]byte, error) - resolvOwner func(resolvConfContnets []byte) string + resolvOwner func(resolvConfContents []byte) string resolvedIsActuallyResolver func(wholeFileFS) error dbusPing func(string, string) error nmIsUsingResolved func() error @@ -63,7 +61,7 @@ func newOSConfigurator(logf logger.Logf, interfaceName string, env newOSConfigEn logf("dns: %v", debug) }() - bs, err := env.ReadFile("/etc/resolv.conf") + bs, err := env.fs.ReadFile(resolvConf) if os.IsNotExist(err) { dbg("rc", "missing") return newDirectManager(), nil diff --git a/net/dns/manager_linux_test.go b/net/dns/manager_linux_test.go new file mode 100644 index 000000000..62034f4e2 --- /dev/null +++ b/net/dns/manager_linux_test.go @@ -0,0 +1,84 @@ +// Copyright (c) 2021 Tailscale Inc & AUTHORS All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package dns + +import ( + "bytes" + "fmt" + "io/fs" + "os" + "testing" +) + +func TestLinuxNewOSConfigurator(t *testing.T) { + tests := []struct { + name string + env newOSConfigEnv + wantLog string + want string // reflect type string + }{ + { + name: "no_obvious_resolv.conf_owner", + env: newOSConfigEnv{ + fs: memFS{ + "/etc/resolv.conf": "nameserver 10.0.0.1\n", + }, + resolvOwner: resolvOwner, + }, + wantLog: "dns: [rc=unknown ret=dns.directManager]\n", + want: "dns.directManager", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var logBuf bytes.Buffer + logf := func(format string, a ...interface{}) { + fmt.Fprintf(&logBuf, format, a...) + logBuf.WriteByte('\n') + } + osc, err := newOSConfigurator(logf, "unused_if_name0", tt.env) + if err != nil { + t.Fatal(err) + } + if got := fmt.Sprintf("%T", osc); got != tt.want { + t.Errorf("got %s; want %s", got, tt.want) + } + if tt.wantLog != string(logBuf.Bytes()) { + t.Errorf("log output mismatch:\n got: %q\nwant: %q\n", logBuf.Bytes(), tt.wantLog) + } + }) + } +} + +type memFS map[string]interface{} // full path => string for regular files + +func (m memFS) Stat(name string) (isRegular bool, err error) { + v, ok := m[name] + if !ok { + return false, fs.ErrNotExist + } + if _, ok := v.(string); ok { + return true, nil + } + return false, nil +} + +func (m memFS) Rename(oldName, newName string) error { panic("TODO") } +func (m memFS) Remove(name string) error { panic("TODO") } +func (m memFS) ReadFile(name string) ([]byte, error) { + v, ok := m[name] + if !ok { + return nil, fs.ErrNotExist + } + if s, ok := v.(string); ok { + return []byte(s), nil + } + panic("TODO") +} + +func (fs memFS) WriteFile(name string, contents []byte, perm os.FileMode) error { + fs[name] = string(contents) + return nil +}