From eedf0f3ac5e638df3e77de255c53b2cac5147b20 Mon Sep 17 00:00:00 2001 From: Frank Schroeder Date: Fri, 12 May 2017 15:41:13 +0200 Subject: [PATCH] test: add helper for ioutil.TempDir/TempFile This creates a simplified helper for temporary directories and files. All path names are prefixed with the name of the current test. All files and directories are stored either in /tmp/consul-test or /tmp if the former could not be created. Using the system temp dir breaks some tests on macOS where the unix socket path becomes too long. --- api/agent_test.go | 7 +- api/api_test.go | 8 +- command/agent/acl_test.go | 7 +- command/agent/agent_endpoint_test.go | 13 +-- command/agent/agent_test.go | 11 +-- command/agent/command_test.go | 39 ++------ command/agent/config_test.go | 13 +-- command/agent/http_test.go | 15 ++-- command/agent/keyring_test.go | 6 +- command/agent/ui_endpoint_test.go | 6 +- command/agent/util_test.go | 8 +- command/configtest_test.go | 32 ++----- command/keygen_test.go | 3 +- command/kv_put_test.go | 7 +- command/members_test.go | 5 +- command/snapshot_inspect_test.go | 7 +- command/snapshot_restore_test.go | 7 +- command/snapshot_save_test.go | 7 +- command/util_test.go | 7 +- command/validate_test.go | 37 +++----- consul/client_test.go | 3 +- consul/server_test.go | 12 +-- snapshot/snapshot_test.go | 12 +-- testutil/io.go | 59 ++++++++++++ testutil/server.go | 129 +++++++++++++-------------- 25 files changed, 198 insertions(+), 262 deletions(-) create mode 100644 testutil/io.go diff --git a/api/agent_test.go b/api/agent_test.go index 89b797e9e..c0997e58b 100644 --- a/api/agent_test.go +++ b/api/agent_test.go @@ -32,10 +32,7 @@ func TestAgent_Reload(t *testing.T) { t.Parallel() // Create our initial empty config file, to be overwritten later - configFile, err := ioutil.TempFile("", t.Name()+"-reload") - if err != nil { - t.Fatalf("err: %s", err) - } + configFile := testutil.TempFile(t, "reload") if _, err := configFile.Write([]byte("{}")); err != nil { t.Fatalf("err: %s", err) } @@ -50,7 +47,7 @@ func TestAgent_Reload(t *testing.T) { // Update the config file with a service definition config := `{"service":{"name":"redis", "port":1234}}` - err = ioutil.WriteFile(configFile.Name(), []byte(config), 0644) + err := ioutil.WriteFile(configFile.Name(), []byte(config), 0644) if err != nil { t.Fatalf("err: %v", err) } diff --git a/api/api_test.go b/api/api_test.go index 79f812590..a7a9445ca 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -4,7 +4,6 @@ import ( crand "crypto/rand" "crypto/tls" "fmt" - "io/ioutil" "net/http" "os" "path/filepath" @@ -44,7 +43,7 @@ func makeClientWithConfig( cb1(conf) } // Create server - server, err := testutil.NewTestServerConfig(t.Name(), cb2) + server, err := testutil.NewTestServerConfigT(t, cb2) if err != nil { t.Fatal(err) } @@ -481,10 +480,7 @@ func TestAPI_UnixSocket(t *testing.T) { t.SkipNow() } - tempDir, err := ioutil.TempDir("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %s", err) - } + tempDir := testutil.TempDir(t, "consul") defer os.RemoveAll(tempDir) socket := filepath.Join(tempDir, "test.sock") diff --git a/command/agent/acl_test.go b/command/agent/acl_test.go index 5399e8ca5..7f7c77001 100644 --- a/command/agent/acl_test.go +++ b/command/agent/acl_test.go @@ -3,7 +3,6 @@ package agent import ( "errors" "fmt" - "io/ioutil" "os" "strings" "testing" @@ -12,6 +11,7 @@ import ( rawacl "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/consul/structs" "github.com/hashicorp/consul/testrpc" + "github.com/hashicorp/consul/testutil" "github.com/hashicorp/consul/types" "github.com/hashicorp/serf/serf" ) @@ -21,10 +21,7 @@ func TestACL_Bad_Config(t *testing.T) { config.ACLDownPolicy = "nope" var err error - config.DataDir, err = ioutil.TempDir("", t.Name()+"-agent") - if err != nil { - t.Fatalf("err: %v", err) - } + config.DataDir = testutil.TempDir(t, "agent") defer os.RemoveAll(config.DataDir) _, err = Create(config, nil, nil, nil) diff --git a/command/agent/agent_endpoint_test.go b/command/agent/agent_endpoint_test.go index 487c3af88..edf47a47f 100644 --- a/command/agent/agent_endpoint_test.go +++ b/command/agent/agent_endpoint_test.go @@ -17,6 +17,7 @@ import ( "github.com/hashicorp/consul/command/base" "github.com/hashicorp/consul/consul/structs" "github.com/hashicorp/consul/logger" + "github.com/hashicorp/consul/testutil" "github.com/hashicorp/consul/testutil/retry" "github.com/hashicorp/consul/types" "github.com/hashicorp/serf/serf" @@ -243,18 +244,12 @@ func TestAgent_Self_ACLDeny(t *testing.T) { func TestAgent_Reload(t *testing.T) { conf := nextConfig() - tmpDir, err := ioutil.TempDir("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %s", err) - } + tmpDir := testutil.TempDir(t, "consul") defer os.RemoveAll(tmpDir) // Write initial config, to be reloaded later - tmpFile, err := ioutil.TempFile(tmpDir, "config") - if err != nil { - t.Fatalf("err: %s", err) - } - _, err = tmpFile.WriteString(`{"acl_enforce_version_8": false, "service":{"name":"redis"}}`) + tmpFile := testutil.TempFile(t, "config") + _, err := tmpFile.WriteString(`{"acl_enforce_version_8": false, "service":{"name":"redis"}}`) if err != nil { t.Fatalf("err: %s", err) } diff --git a/command/agent/agent_test.go b/command/agent/agent_test.go index 63b1f117e..8425773a1 100644 --- a/command/agent/agent_test.go +++ b/command/agent/agent_test.go @@ -21,6 +21,7 @@ import ( "github.com/hashicorp/consul/consul/structs" "github.com/hashicorp/consul/logger" "github.com/hashicorp/consul/testrpc" + "github.com/hashicorp/consul/testutil" "github.com/hashicorp/consul/types" "github.com/hashicorp/consul/version" "github.com/hashicorp/go-uuid" @@ -96,10 +97,7 @@ func nextConfig() *Config { } func makeAgentLog(t *testing.T, conf *Config, l io.Writer, writer *logger.LogWriter) (string, *Agent) { - dir, err := ioutil.TempDir("", t.Name()+"-agent") - if err != nil { - t.Fatalf(fmt.Sprintf("err: %v", err)) - } + dir := testutil.TempDir(t, "agent") conf.DataDir = dir agent, err := Create(conf, l, writer, nil) @@ -112,10 +110,7 @@ func makeAgentLog(t *testing.T, conf *Config, l io.Writer, writer *logger.LogWri } func makeAgentKeyring(t *testing.T, conf *Config, key string) (string, *Agent) { - dir, err := ioutil.TempDir("", t.Name()+"-agent") - if err != nil { - t.Fatalf("err: %v", err) - } + dir := testutil.TempDir(t, "agent") conf.DataDir = dir diff --git a/command/agent/command_test.go b/command/agent/command_test.go index dbc874875..16fede875 100644 --- a/command/agent/command_test.go +++ b/command/agent/command_test.go @@ -2,7 +2,6 @@ package agent import ( "fmt" - "io/ioutil" "log" "os" "os/exec" @@ -12,6 +11,7 @@ import ( "testing" "github.com/hashicorp/consul/command/base" + "github.com/hashicorp/consul/testutil" "github.com/hashicorp/consul/testutil/retry" "github.com/hashicorp/consul/version" "github.com/mitchellh/cli" @@ -103,10 +103,7 @@ func TestRetryJoin(t *testing.T) { defer agent.Shutdown() conf2 := nextConfig() - tmpDir, err := ioutil.TempDir("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %s", err) - } + tmpDir := testutil.TempDir(t, "consul") defer os.RemoveAll(tmpDir) doneCh := make(chan struct{}) @@ -162,10 +159,7 @@ func TestRetryJoin(t *testing.T) { } func TestReadCliConfig(t *testing.T) { - tmpDir, err := ioutil.TempDir("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %s", err) - } + tmpDir := testutil.TempDir(t, "consul") defer os.RemoveAll(tmpDir) shutdownCh := make(chan struct{}) @@ -294,10 +288,7 @@ func TestReadCliConfig(t *testing.T) { func TestRetryJoinFail(t *testing.T) { conf := nextConfig() - tmpDir, err := ioutil.TempDir("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %s", err) - } + tmpDir := testutil.TempDir(t, "consul") defer os.RemoveAll(tmpDir) shutdownCh := make(chan struct{}) @@ -325,10 +316,7 @@ func TestRetryJoinFail(t *testing.T) { func TestRetryJoinWanFail(t *testing.T) { conf := nextConfig() - tmpDir, err := ioutil.TempDir("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %s", err) - } + tmpDir := testutil.TempDir(t, "consul") defer os.RemoveAll(tmpDir) shutdownCh := make(chan struct{}) @@ -413,24 +401,18 @@ func TestDiscoverGCEHosts(t *testing.T) { } func TestProtectDataDir(t *testing.T) { - dir, err := ioutil.TempDir("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %v", err) - } + dir := testutil.TempDir(t, "consul") defer os.RemoveAll(dir) if err := os.MkdirAll(filepath.Join(dir, "mdb"), 0700); err != nil { t.Fatalf("err: %v", err) } - cfgFile, err := ioutil.TempFile("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %v", err) - } + cfgFile := testutil.TempFile(t, "consul") defer os.Remove(cfgFile.Name()) content := fmt.Sprintf(`{"server": true, "data_dir": "%s"}`, dir) - _, err = cfgFile.Write([]byte(content)) + _, err := cfgFile.Write([]byte(content)) if err != nil { t.Fatalf("err: %v", err) } @@ -449,10 +431,7 @@ func TestProtectDataDir(t *testing.T) { } func TestBadDataDirPermissions(t *testing.T) { - dir, err := ioutil.TempDir("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %v", err) - } + dir := testutil.TempDir(t, "consul") defer os.RemoveAll(dir) dataDir := filepath.Join(dir, "mdb") diff --git a/command/agent/config_test.go b/command/agent/config_test.go index 726494adb..170fbdbc4 100644 --- a/command/agent/config_test.go +++ b/command/agent/config_test.go @@ -14,6 +14,7 @@ import ( "time" "github.com/hashicorp/consul/lib" + "github.com/hashicorp/consul/testutil" ) func TestConfigEncryptBytes(t *testing.T) { @@ -1797,10 +1798,7 @@ func TestReadConfigPaths_badPath(t *testing.T) { } func TestReadConfigPaths_file(t *testing.T) { - tf, err := ioutil.TempFile("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %s", err) - } + tf := testutil.TempFile(t, "consul") tf.Write([]byte(`{"node_name":"bar"}`)) tf.Close() defer os.Remove(tf.Name()) @@ -1816,13 +1814,10 @@ func TestReadConfigPaths_file(t *testing.T) { } func TestReadConfigPaths_dir(t *testing.T) { - td, err := ioutil.TempDir("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %s", err) - } + td := testutil.TempDir(t, "consul") defer os.RemoveAll(td) - err = ioutil.WriteFile(filepath.Join(td, "a.json"), + err := ioutil.WriteFile(filepath.Join(td, "a.json"), []byte(`{"node_name": "bar"}`), 0644) if err != nil { t.Fatalf("err: %s", err) diff --git a/command/agent/http_test.go b/command/agent/http_test.go index 135b77121..6eacd2137 100644 --- a/command/agent/http_test.go +++ b/command/agent/http_test.go @@ -22,6 +22,7 @@ import ( "github.com/hashicorp/consul/consul/structs" "github.com/hashicorp/consul/logger" "github.com/hashicorp/consul/testrpc" + "github.com/hashicorp/consul/testutil" "github.com/hashicorp/go-cleanhttp" ) @@ -77,12 +78,9 @@ func TestHTTPServer_UnixSocket(t *testing.T) { t.SkipNow() } - tempDir, err := ioutil.TempDir("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %s", err) - } + tempDir := testutil.TempDir(t, "consul") defer os.RemoveAll(tempDir) - socket := filepath.Join(tempDir, t.Name()+".sock") + socket := filepath.Join(tempDir, "test.sock") dir, srv := makeHTTPServerWithConfig(t, func(c *Config) { c.Addresses.HTTP = "unix://" + socket @@ -139,12 +137,9 @@ func TestHTTPServer_UnixSocket_FileExists(t *testing.T) { t.SkipNow() } - tempDir, err := ioutil.TempDir("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %s", err) - } + tempDir := testutil.TempDir(t, "consul") defer os.RemoveAll(tempDir) - socket := filepath.Join(tempDir, t.Name()+".sock") + socket := filepath.Join(tempDir, "test.sock") // Create a regular file at the socket path if err := ioutil.WriteFile(socket, []byte("hello world"), 0644); err != nil { diff --git a/command/agent/keyring_test.go b/command/agent/keyring_test.go index 689e3c50b..193975ca0 100644 --- a/command/agent/keyring_test.go +++ b/command/agent/keyring_test.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/hashicorp/consul/testrpc" + "github.com/hashicorp/consul/testutil" ) func TestAgent_LoadKeyrings(t *testing.T) { @@ -81,10 +82,7 @@ func TestAgent_InitKeyring(t *testing.T) { key2 := "4leC33rgtXKIVUr9Nr0snQ==" expected := fmt.Sprintf(`["%s"]`, key1) - dir, err := ioutil.TempDir("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %s", err) - } + dir := testutil.TempDir(t, "consul") defer os.RemoveAll(dir) file := filepath.Join(dir, "keyring") diff --git a/command/agent/ui_endpoint_test.go b/command/agent/ui_endpoint_test.go index e23ffae14..dab65f99e 100644 --- a/command/agent/ui_endpoint_test.go +++ b/command/agent/ui_endpoint_test.go @@ -15,15 +15,13 @@ import ( "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/consul/structs" "github.com/hashicorp/consul/testrpc" + "github.com/hashicorp/consul/testutil" "github.com/hashicorp/go-cleanhttp" ) func TestUiIndex(t *testing.T) { // Make a test dir to serve UI files - uiDir, err := ioutil.TempDir("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %v", err) - } + uiDir := testutil.TempDir(t, "consul") defer os.RemoveAll(uiDir) // Make the server diff --git a/command/agent/util_test.go b/command/agent/util_test.go index 4f016f7b6..a97297242 100644 --- a/command/agent/util_test.go +++ b/command/agent/util_test.go @@ -1,11 +1,12 @@ package agent import ( - "io/ioutil" "os" "runtime" "testing" "time" + + "github.com/hashicorp/consul/testutil" ) func TestAEScale(t *testing.T) { @@ -37,10 +38,7 @@ func TestSetFilePermissions(t *testing.T) { if runtime.GOOS == "windows" { t.SkipNow() } - tempFile, err := ioutil.TempFile("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %s", err) - } + tempFile := testutil.TempFile(t, "consul") path := tempFile.Name() defer os.Remove(path) diff --git a/command/configtest_test.go b/command/configtest_test.go index 43a9a4bd0..22b8cfd32 100644 --- a/command/configtest_test.go +++ b/command/configtest_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/hashicorp/consul/command/base" + "github.com/hashicorp/consul/testutil" "github.com/mitchellh/cli" ) @@ -25,10 +26,7 @@ func TestConfigTestCommand_implements(t *testing.T) { } func TestConfigTestCommandFailOnEmptyFile(t *testing.T) { - tmpFile, err := ioutil.TempFile("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %s", err) - } + tmpFile := testutil.TempFile(t, "consul") defer os.RemoveAll(tmpFile.Name()) _, cmd := testConfigTestCommand(t) @@ -43,10 +41,7 @@ func TestConfigTestCommandFailOnEmptyFile(t *testing.T) { } func TestConfigTestCommandSucceedOnEmptyDir(t *testing.T) { - td, err := ioutil.TempDir("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %s", err) - } + td := testutil.TempDir(t, "consul") defer os.RemoveAll(td) ui, cmd := testConfigTestCommand(t) @@ -61,14 +56,11 @@ func TestConfigTestCommandSucceedOnEmptyDir(t *testing.T) { } func TestConfigTestCommandSucceedOnMinimalConfigFile(t *testing.T) { - td, err := ioutil.TempDir("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %s", err) - } + td := testutil.TempDir(t, "consul") defer os.RemoveAll(td) fp := filepath.Join(td, "config.json") - err = ioutil.WriteFile(fp, []byte(`{}`), 0644) + err := ioutil.WriteFile(fp, []byte(`{}`), 0644) if err != nil { t.Fatalf("err: %s", err) } @@ -85,13 +77,10 @@ func TestConfigTestCommandSucceedOnMinimalConfigFile(t *testing.T) { } func TestConfigTestCommandSucceedOnMinimalConfigDir(t *testing.T) { - td, err := ioutil.TempDir("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %s", err) - } + td := testutil.TempDir(t, "consul") defer os.RemoveAll(td) - err = ioutil.WriteFile(filepath.Join(td, "config.json"), []byte(`{}`), 0644) + err := ioutil.WriteFile(filepath.Join(td, "config.json"), []byte(`{}`), 0644) if err != nil { t.Fatalf("err: %s", err) } @@ -108,13 +97,10 @@ func TestConfigTestCommandSucceedOnMinimalConfigDir(t *testing.T) { } func TestConfigTestCommandSucceedOnConfigDirWithEmptyFile(t *testing.T) { - td, err := ioutil.TempDir("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %s", err) - } + td := testutil.TempDir(t, "consul") defer os.RemoveAll(td) - err = ioutil.WriteFile(filepath.Join(td, "config.json"), []byte{}, 0644) + err := ioutil.WriteFile(filepath.Join(td, "config.json"), []byte{}, 0644) if err != nil { t.Fatalf("err: %s", err) } diff --git a/command/keygen_test.go b/command/keygen_test.go index db1af3a06..b131802f6 100644 --- a/command/keygen_test.go +++ b/command/keygen_test.go @@ -2,9 +2,10 @@ package command import ( "encoding/base64" + "testing" + "github.com/hashicorp/consul/command/base" "github.com/mitchellh/cli" - "testing" ) func TestKeygenCommand_implements(t *testing.T) { diff --git a/command/kv_put_test.go b/command/kv_put_test.go index f4609d25a..48b4212d3 100644 --- a/command/kv_put_test.go +++ b/command/kv_put_test.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/base64" "io" - "io/ioutil" "os" "strconv" "strings" @@ -12,6 +11,7 @@ import ( "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/command/base" + "github.com/hashicorp/consul/testutil" "github.com/mitchellh/cli" ) @@ -179,10 +179,7 @@ func TestKVPutCommand_File(t *testing.T) { ui, c := testKVPutCommand(t) - f, err := ioutil.TempFile("", t.Name()+"-kv-put-command-file") - if err != nil { - t.Fatalf("err: %#v", err) - } + f := testutil.TempFile(t, "kv-put-command-file") defer os.Remove(f.Name()) if _, err := f.WriteString("bar"); err != nil { t.Fatalf("err: %#v", err) diff --git a/command/members_test.go b/command/members_test.go index eca541200..8c653896b 100644 --- a/command/members_test.go +++ b/command/members_test.go @@ -2,10 +2,11 @@ package command import ( "fmt" - "github.com/hashicorp/consul/command/base" - "github.com/mitchellh/cli" "strings" "testing" + + "github.com/hashicorp/consul/command/base" + "github.com/mitchellh/cli" ) func testMembersCommand(t *testing.T) (*cli.MockUi, *MembersCommand) { diff --git a/command/snapshot_inspect_test.go b/command/snapshot_inspect_test.go index 851200a8f..09f718d3d 100644 --- a/command/snapshot_inspect_test.go +++ b/command/snapshot_inspect_test.go @@ -2,13 +2,13 @@ package command import ( "io" - "io/ioutil" "os" "path" "strings" "testing" "github.com/hashicorp/consul/command/base" + "github.com/hashicorp/consul/testutil" "github.com/mitchellh/cli" ) @@ -73,10 +73,7 @@ func TestSnapshotInspectCommand_Run(t *testing.T) { defer srv.Shutdown() waitForLeader(t, srv.httpAddr) - dir, err := ioutil.TempDir("", t.Name()+"-snapshot") - if err != nil { - t.Fatalf("err: %v", err) - } + dir := testutil.TempDir(t, "snapshot") defer os.RemoveAll(dir) file := path.Join(dir, "backup.tgz") diff --git a/command/snapshot_restore_test.go b/command/snapshot_restore_test.go index ad65c188a..0856aea84 100644 --- a/command/snapshot_restore_test.go +++ b/command/snapshot_restore_test.go @@ -2,13 +2,13 @@ package command import ( "io" - "io/ioutil" "os" "path" "strings" "testing" "github.com/hashicorp/consul/command/base" + "github.com/hashicorp/consul/testutil" "github.com/mitchellh/cli" ) @@ -75,10 +75,7 @@ func TestSnapshotRestoreCommand_Run(t *testing.T) { ui, c := testSnapshotRestoreCommand(t) - dir, err := ioutil.TempDir("", t.Name()+"-snapshot") - if err != nil { - t.Fatalf("err: %v", err) - } + dir := testutil.TempDir(t, "snapshot") defer os.RemoveAll(dir) file := path.Join(dir, "backup.tgz") diff --git a/command/snapshot_save_test.go b/command/snapshot_save_test.go index 239e07c18..09fd661d5 100644 --- a/command/snapshot_save_test.go +++ b/command/snapshot_save_test.go @@ -1,13 +1,13 @@ package command import ( - "io/ioutil" "os" "path" "strings" "testing" "github.com/hashicorp/consul/command/base" + "github.com/hashicorp/consul/testutil" "github.com/mitchellh/cli" ) @@ -74,10 +74,7 @@ func TestSnapshotSaveCommand_Run(t *testing.T) { ui, c := testSnapshotSaveCommand(t) - dir, err := ioutil.TempDir("", t.Name()+"-snapshot") - if err != nil { - t.Fatalf("err: %v", err) - } + dir := testutil.TempDir(t, "snapshot") defer os.RemoveAll(dir) file := path.Join(dir, "backup.tgz") diff --git a/command/util_test.go b/command/util_test.go index 66c441427..e72814faa 100644 --- a/command/util_test.go +++ b/command/util_test.go @@ -2,7 +2,6 @@ package command import ( "fmt" - "io/ioutil" "math/rand" "os" "strings" @@ -14,6 +13,7 @@ import ( "github.com/hashicorp/consul/command/agent" "github.com/hashicorp/consul/consul" "github.com/hashicorp/consul/logger" + "github.com/hashicorp/consul/testutil" "github.com/hashicorp/consul/types" "github.com/hashicorp/consul/version" "github.com/hashicorp/go-uuid" @@ -67,10 +67,7 @@ func testAgentWithConfigReload(t *testing.T, cb func(c *agent.Config), reloadCh cb(conf) } - dir, err := ioutil.TempDir("", t.Name()+"-agent") - if err != nil { - t.Fatalf(fmt.Sprintf("err: %v", err)) - } + dir := testutil.TempDir(t, "agent") conf.DataDir = dir a, err := agent.Create(conf, lw, nil, reloadCh) diff --git a/command/validate_test.go b/command/validate_test.go index a58ac51be..f44f32139 100644 --- a/command/validate_test.go +++ b/command/validate_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/hashicorp/consul/command/base" + "github.com/hashicorp/consul/testutil" "github.com/mitchellh/cli" ) @@ -25,10 +26,7 @@ func TestValidateCommand_implements(t *testing.T) { } func TestValidateCommandFailOnEmptyFile(t *testing.T) { - tmpFile, err := ioutil.TempFile("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %s", err) - } + tmpFile := testutil.TempFile(t, "consul") defer os.RemoveAll(tmpFile.Name()) _, cmd := testValidateCommand(t) @@ -41,10 +39,7 @@ func TestValidateCommandFailOnEmptyFile(t *testing.T) { } func TestValidateCommandSucceedOnEmptyDir(t *testing.T) { - td, err := ioutil.TempDir("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %s", err) - } + td := testutil.TempDir(t, "consul") defer os.RemoveAll(td) ui, cmd := testValidateCommand(t) @@ -57,14 +52,11 @@ func TestValidateCommandSucceedOnEmptyDir(t *testing.T) { } func TestValidateCommandSucceedOnMinimalConfigFile(t *testing.T) { - td, err := ioutil.TempDir("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %s", err) - } + td := testutil.TempDir(t, "consul") defer os.RemoveAll(td) fp := filepath.Join(td, "config.json") - err = ioutil.WriteFile(fp, []byte(`{}`), 0644) + err := ioutil.WriteFile(fp, []byte(`{}`), 0644) if err != nil { t.Fatalf("err: %s", err) } @@ -79,13 +71,10 @@ func TestValidateCommandSucceedOnMinimalConfigFile(t *testing.T) { } func TestValidateCommandSucceedOnMinimalConfigDir(t *testing.T) { - td, err := ioutil.TempDir("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %s", err) - } + td := testutil.TempDir(t, "consul") defer os.RemoveAll(td) - err = ioutil.WriteFile(filepath.Join(td, "config.json"), []byte(`{}`), 0644) + err := ioutil.WriteFile(filepath.Join(td, "config.json"), []byte(`{}`), 0644) if err != nil { t.Fatalf("err: %s", err) } @@ -100,13 +89,10 @@ func TestValidateCommandSucceedOnMinimalConfigDir(t *testing.T) { } func TestValidateCommandSucceedOnConfigDirWithEmptyFile(t *testing.T) { - td, err := ioutil.TempDir("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %s", err) - } + td := testutil.TempDir(t, "consul") defer os.RemoveAll(td) - err = ioutil.WriteFile(filepath.Join(td, "config.json"), []byte{}, 0644) + err := ioutil.WriteFile(filepath.Join(td, "config.json"), []byte{}, 0644) if err != nil { t.Fatalf("err: %s", err) } @@ -121,10 +107,7 @@ func TestValidateCommandSucceedOnConfigDirWithEmptyFile(t *testing.T) { } func TestValidateCommandQuiet(t *testing.T) { - td, err := ioutil.TempDir("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %s", err) - } + td := testutil.TempDir(t, "consul") defer os.RemoveAll(td) ui, cmd := testValidateCommand(t) diff --git a/consul/client_test.go b/consul/client_test.go index 730721346..af0dc81b4 100644 --- a/consul/client_test.go +++ b/consul/client_test.go @@ -11,13 +11,14 @@ import ( "github.com/hashicorp/consul/consul/structs" "github.com/hashicorp/consul/testrpc" + "github.com/hashicorp/consul/testutil" "github.com/hashicorp/consul/testutil/retry" "github.com/hashicorp/net-rpc-msgpackrpc" "github.com/hashicorp/serf/serf" ) func testClientConfig(t *testing.T, NodeName string) (string, *Config) { - dir := tmpDir(t) + dir := testutil.TempDir(t, "consul") config := DefaultConfig() config.Datacenter = "dc1" config.DataDir = dir diff --git a/consul/server_test.go b/consul/server_test.go index e79762fb3..8d1ebeaf6 100644 --- a/consul/server_test.go +++ b/consul/server_test.go @@ -2,7 +2,6 @@ package consul import ( "fmt" - "io/ioutil" "net" "os" "strings" @@ -12,6 +11,7 @@ import ( "github.com/hashicorp/consul/consul/agent" "github.com/hashicorp/consul/testrpc" + "github.com/hashicorp/consul/testutil" "github.com/hashicorp/consul/testutil/retry" "github.com/hashicorp/consul/types" "github.com/hashicorp/go-uuid" @@ -23,14 +23,6 @@ func getPort() int { return int(atomic.AddInt32(&nextPort, 1)) } -func tmpDir(t *testing.T) string { - dir, err := ioutil.TempDir("", t.Name()+"-consul") - if err != nil { - t.Fatalf("err: %v", err) - } - return dir -} - func configureTLS(config *Config) { config.CAFile = "../test/ca/root.cer" config.CertFile = "../test/key/ourdomain.cer" @@ -38,7 +30,7 @@ func configureTLS(config *Config) { } func testServerConfig(t *testing.T, NodeName string) (string, *Config) { - dir := tmpDir(t) + dir := testutil.TempDir(t, "consul") config := DefaultConfig() config.NodeName = NodeName diff --git a/snapshot/snapshot_test.go b/snapshot/snapshot_test.go index 1883c0f84..b9a24e526 100644 --- a/snapshot/snapshot_test.go +++ b/snapshot/snapshot_test.go @@ -5,7 +5,6 @@ import ( "crypto/rand" "fmt" "io" - "io/ioutil" "log" "os" "path" @@ -14,6 +13,7 @@ import ( "testing" "time" + "github.com/hashicorp/consul/testutil" "github.com/hashicorp/go-msgpack/codec" "github.com/hashicorp/raft" ) @@ -126,10 +126,7 @@ func makeRaft(t *testing.T, dir string) (*raft.Raft, *MockFSM) { } func TestSnapshot(t *testing.T) { - dir, err := ioutil.TempDir("", t.Name()+"-snapshot") - if err != nil { - t.Fatalf("err: %v", err) - } + dir := testutil.TempDir(t, "snapshot") defer os.RemoveAll(dir) // Make a Raft and populate it with some data. We tee everything we @@ -238,10 +235,7 @@ func TestSnapshot_BadVerify(t *testing.T) { } func TestSnapshot_BadRestore(t *testing.T) { - dir, err := ioutil.TempDir("", t.Name()+"-snapshot") - if err != nil { - t.Fatalf("err: %v", err) - } + dir := testutil.TempDir(t, "snapshot") defer os.RemoveAll(dir) // Make a Raft and populate it with some data. diff --git a/testutil/io.go b/testutil/io.go new file mode 100644 index 000000000..faf72ac66 --- /dev/null +++ b/testutil/io.go @@ -0,0 +1,59 @@ +package testutil + +import ( + "fmt" + "io/ioutil" + "os" + "testing" +) + +// tmpdir is the base directory for all temporary directories +// and files created with TempDir and TempFile. This could be +// achieved by setting a system environment variable but then +// the test execution would depend on whether or not the +// environment variable is set. +// +// On macOS the temp base directory is quite long and that +// triggers a problem with some tests that bind to UNIX sockets +// where the filename seems to be too long. Using a shorter name +// fixes this and makes the paths more readable. +// +// It also provides a single base directory for cleanup. +var tmpdir = "/tmp/consul-test" + +func init() { + if err := os.MkdirAll(tmpdir, 0755); err != nil { + fmt.Println("Cannot create %s. Reverting to /tmp", tmpdir) + tmpdir = "/tmp" + } +} + +// TempDir creates a temporary directory within tmpdir +// with the name 'testname-name'. If the directory cannot +// be created t.Fatal is called. +func TempDir(t *testing.T, name string) string { + if t != nil && t.Name() != "" { + name = t.Name() + "-" + name + } + d, err := ioutil.TempDir(tmpdir, name) + if err != nil { + t.Fatalf("err: %s", err) + } + return d +} + +// TempFile creates a temporary file within tmpdir +// with the name 'testname-name'. If the file cannot +// be created t.Fatal is called. If a temporary directory +// has been created before consider storing the file +// inside this directory to avoid double cleanup. +func TempFile(t *testing.T, name string) *os.File { + if t != nil && t.Name() != "" { + name = t.Name() + "-" + name + } + f, err := ioutil.TempFile(tmpdir, name) + if err != nil { + t.Fatalf("err: %s", err) + } + return f +} diff --git a/testutil/server.go b/testutil/server.go index 2eb4395c6..0f7e216f5 100644 --- a/testutil/server.go +++ b/testutil/server.go @@ -21,8 +21,10 @@ import ( "net/http" "os" "os/exec" + "path/filepath" "strconv" "strings" + "testing" "time" "github.com/hashicorp/consul/testutil/retry" @@ -169,67 +171,61 @@ type TestServer struct { WANAddr string HTTPClient *http.Client + + tmpdir string } // NewTestServer is an easy helper method to create a new Consul // test server with the most basic configuration. -func NewTestServer(name string) (*TestServer, error) { - return NewTestServerConfig(name, nil) +func NewTestServer() (*TestServer, error) { + return NewTestServerConfigT(nil, nil) +} + +func NewTestServerConfig(cb ServerConfigCallback) (*TestServer, error) { + return NewTestServerConfigT(nil, cb) } // NewTestServerConfig creates a new TestServer, and makes a call to an optional // callback function to modify the configuration. If there is an error // configuring or starting the server, the server will NOT be running when the // function returns (thus you do not need to stop it). -func NewTestServerConfig(name string, cb ServerConfigCallback) (*TestServer, error) { - if path, err := exec.LookPath("consul"); err != nil || path == "" { +func NewTestServerConfigT(t *testing.T, cb ServerConfigCallback) (*TestServer, error) { + path, err := exec.LookPath("consul") + if err != nil || path == "" { return nil, fmt.Errorf("consul not found on $PATH - download and install " + "consul or skip this test") } - dataDir, err := ioutil.TempDir("", name+"-consul") - if err != nil { - return nil, errors.Wrap(err, "failed creating tempdir") - } - - configFile, err := ioutil.TempFile(dataDir, name+"-config") - if err != nil { - defer os.RemoveAll(dataDir) - return nil, errors.Wrap(err, "failed creating temp config") - } - - consulConfig := defaultServerConfig() - consulConfig.DataDir = dataDir - + tmpdir := TempDir(t, "consul") + cfg := defaultServerConfig() + cfg.DataDir = filepath.Join(tmpdir, "data") if cb != nil { - cb(consulConfig) + cb(cfg) } - configContent, err := json.Marshal(consulConfig) + b, err := json.Marshal(cfg) if err != nil { return nil, errors.Wrap(err, "failed marshaling json") } - if _, err := configFile.Write(configContent); err != nil { - defer configFile.Close() - defer os.RemoveAll(dataDir) + configFile := filepath.Join(tmpdir, "config.json") + if err := ioutil.WriteFile(configFile, b, 0644); err != nil { + defer os.RemoveAll(tmpdir) return nil, errors.Wrap(err, "failed writing config content") } - configFile.Close() stdout := io.Writer(os.Stdout) - if consulConfig.Stdout != nil { - stdout = consulConfig.Stdout + if cfg.Stdout != nil { + stdout = cfg.Stdout } - stderr := io.Writer(os.Stderr) - if consulConfig.Stderr != nil { - stderr = consulConfig.Stderr + if cfg.Stderr != nil { + stderr = cfg.Stderr } // Start the server - args := []string{"agent", "-config-file", configFile.Name()} - args = append(args, consulConfig.Args...) + args := []string{"agent", "-config-file", configFile} + args = append(args, cfg.Args...) cmd := exec.Command("consul", args...) cmd.Stdout = stdout cmd.Stderr = stderr @@ -237,68 +233,63 @@ func NewTestServerConfig(name string, cb ServerConfigCallback) (*TestServer, err return nil, errors.Wrap(err, "failed starting command") } - var httpAddr string - var client *http.Client - if strings.HasPrefix(consulConfig.Addresses.HTTP, "unix://") { - httpAddr = consulConfig.Addresses.HTTP - trans := cleanhttp.DefaultTransport() - trans.DialContext = func(_ context.Context, _, _ string) (net.Conn, error) { - return net.Dial("unix", httpAddr[7:]) + httpAddr := fmt.Sprintf("127.0.0.1:%d", cfg.Ports.HTTP) + client := cleanhttp.DefaultClient() + if strings.HasPrefix(cfg.Addresses.HTTP, "unix://") { + httpAddr = cfg.Addresses.HTTP + tr := cleanhttp.DefaultTransport() + tr.DialContext = func(_ context.Context, _, _ string) (net.Conn, error) { + return net.Dial("unix", httpAddr[len("unix://"):]) } - client = &http.Client{ - Transport: trans, - } - } else { - httpAddr = fmt.Sprintf("127.0.0.1:%d", consulConfig.Ports.HTTP) - client = cleanhttp.DefaultClient() + client = &http.Client{Transport: tr} } server := &TestServer{ - Config: consulConfig, + Config: cfg, cmd: cmd, HTTPAddr: httpAddr, - HTTPSAddr: fmt.Sprintf("127.0.0.1:%d", consulConfig.Ports.HTTPS), - LANAddr: fmt.Sprintf("127.0.0.1:%d", consulConfig.Ports.SerfLan), - WANAddr: fmt.Sprintf("127.0.0.1:%d", consulConfig.Ports.SerfWan), + HTTPSAddr: fmt.Sprintf("127.0.0.1:%d", cfg.Ports.HTTPS), + LANAddr: fmt.Sprintf("127.0.0.1:%d", cfg.Ports.SerfLan), + WANAddr: fmt.Sprintf("127.0.0.1:%d", cfg.Ports.SerfWan), HTTPClient: client, + + tmpdir: tmpdir, } // Wait for the server to be ready - var startErr error - if consulConfig.Bootstrap { - startErr = server.waitForLeader() + if cfg.Bootstrap { + err = server.waitForLeader() } else { - startErr = server.waitForAPI() + err = server.waitForAPI() } - if startErr != nil { + if err != nil { defer server.Stop() - return nil, errors.Wrap(startErr, "failed waiting for server to start") + return nil, errors.Wrap(err, "failed waiting for server to start") } - return server, nil } // Stop stops the test Consul server, and removes the Consul data // directory once we are done. func (s *TestServer) Stop() error { - defer os.RemoveAll(s.Config.DataDir) - - if s.cmd != nil { - if s.cmd.Process != nil { - if err := s.cmd.Process.Kill(); err != nil { - return errors.Wrap(err, "failed to kill consul server") - } - } - - // wait for the process to exit to be sure that the data dir can be - // deleted on all platforms. - return s.cmd.Wait() - } + defer os.RemoveAll(s.tmpdir) // There was no process - return nil + if s.cmd == nil { + return nil + } + + if s.cmd.Process != nil { + if err := s.cmd.Process.Kill(); err != nil { + return errors.Wrap(err, "failed to kill consul server") + } + } + + // wait for the process to exit to be sure that the data dir can be + // deleted on all platforms. + return s.cmd.Wait() } type failer struct {