From 28c46d1a90da500d5406f93c3b62b77941a9d7c7 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Wed, 28 Mar 2018 10:54:08 -0400 Subject: [PATCH 1/3] cleanup temp files from backend tests --- backend/local/backend_apply_test.go | 17 ++++++++++++----- backend/local/backend_plan_test.go | 21 ++++++++++++++------- backend/local/backend_refresh_test.go | 16 +++++++++++----- backend/local/testing.go | 12 ++++++++++-- 4 files changed, 47 insertions(+), 19 deletions(-) diff --git a/backend/local/backend_apply_test.go b/backend/local/backend_apply_test.go index 3e692ea24..19cc1140a 100644 --- a/backend/local/backend_apply_test.go +++ b/backend/local/backend_apply_test.go @@ -18,7 +18,8 @@ import ( ) func TestLocal_applyBasic(t *testing.T) { - b := TestLocal(t) + b, cleanup := TestLocal(t) + defer cleanup() p := TestLocalProvider(t, b, "test") p.ApplyReturn = &terraform.InstanceState{ID: "yes"} @@ -58,7 +59,9 @@ test_instance.foo: } func TestLocal_applyEmptyDir(t *testing.T) { - b := TestLocal(t) + b, cleanup := TestLocal(t) + defer cleanup() + p := TestLocalProvider(t, b, "test") p.ApplyReturn = &terraform.InstanceState{ID: "yes"} @@ -85,7 +88,8 @@ func TestLocal_applyEmptyDir(t *testing.T) { } func TestLocal_applyEmptyDirDestroy(t *testing.T) { - b := TestLocal(t) + b, cleanup := TestLocal(t) + defer cleanup() p := TestLocalProvider(t, b, "test") p.ApplyReturn = nil @@ -111,7 +115,8 @@ func TestLocal_applyEmptyDirDestroy(t *testing.T) { } func TestLocal_applyError(t *testing.T) { - b := TestLocal(t) + b, cleanup := TestLocal(t) + defer cleanup() p := TestLocalProvider(t, b, "test") var lock sync.Mutex @@ -169,7 +174,9 @@ func TestLocal_applyBackendFail(t *testing.T) { mod, modCleanup := module.TestTree(t, "./test-fixtures/apply") defer modCleanup() - b := TestLocal(t) + b, cleanup := TestLocal(t) + defer cleanup() + wd, err := os.Getwd() if err != nil { t.Fatalf("failed to get current working directory") diff --git a/backend/local/backend_plan_test.go b/backend/local/backend_plan_test.go index de71555a7..33832a9ec 100644 --- a/backend/local/backend_plan_test.go +++ b/backend/local/backend_plan_test.go @@ -15,7 +15,8 @@ import ( ) func TestLocal_planBasic(t *testing.T) { - b := TestLocal(t) + b, cleanup := TestLocal(t) + defer cleanup() p := TestLocalProvider(t, b, "test") mod, modCleanup := module.TestTree(t, "./test-fixtures/plan") @@ -40,7 +41,8 @@ func TestLocal_planBasic(t *testing.T) { } func TestLocal_planInAutomation(t *testing.T) { - b := TestLocal(t) + b, cleanup := TestLocal(t) + defer cleanup() TestLocalProvider(t, b, "test") mod, modCleanup := module.TestTree(t, "./test-fixtures/plan") @@ -103,7 +105,8 @@ func TestLocal_planInAutomation(t *testing.T) { } func TestLocal_planNoConfig(t *testing.T) { - b := TestLocal(t) + b, cleanup := TestLocal(t) + defer cleanup() TestLocalProvider(t, b, "test") op := testOperationPlan() @@ -126,7 +129,8 @@ func TestLocal_planNoConfig(t *testing.T) { } func TestLocal_planRefreshFalse(t *testing.T) { - b := TestLocal(t) + b, cleanup := TestLocal(t) + defer cleanup() p := TestLocalProvider(t, b, "test") terraform.TestStateFile(t, b.StatePath, testPlanState()) @@ -155,7 +159,8 @@ func TestLocal_planRefreshFalse(t *testing.T) { } func TestLocal_planDestroy(t *testing.T) { - b := TestLocal(t) + b, cleanup := TestLocal(t) + defer cleanup() p := TestLocalProvider(t, b, "test") terraform.TestStateFile(t, b.StatePath, testPlanState()) @@ -200,7 +205,8 @@ func TestLocal_planDestroy(t *testing.T) { } func TestLocal_planOutPathNoChange(t *testing.T) { - b := TestLocal(t) + b, cleanup := TestLocal(t) + defer cleanup() TestLocalProvider(t, b, "test") terraform.TestStateFile(t, b.StatePath, testPlanState()) @@ -237,7 +243,8 @@ func TestLocal_planOutPathNoChange(t *testing.T) { // checks to make sure the correct resource count is ultimately given to the // UI. func TestLocal_planScaleOutNoDupeCount(t *testing.T) { - b := TestLocal(t) + b, cleanup := TestLocal(t) + defer cleanup() TestLocalProvider(t, b, "test") state := &terraform.State{ Version: 2, diff --git a/backend/local/backend_refresh_test.go b/backend/local/backend_refresh_test.go index 1d7a6f1cc..b28009bd2 100644 --- a/backend/local/backend_refresh_test.go +++ b/backend/local/backend_refresh_test.go @@ -11,7 +11,9 @@ import ( ) func TestLocal_refresh(t *testing.T) { - b := TestLocal(t) + b, cleanup := TestLocal(t) + defer cleanup() + p := TestLocalProvider(t, b, "test") terraform.TestStateFile(t, b.StatePath, testRefreshState()) @@ -42,7 +44,8 @@ test_instance.foo: } func TestLocal_refreshNilModule(t *testing.T) { - b := TestLocal(t) + b, cleanup := TestLocal(t) + defer cleanup() p := TestLocalProvider(t, b, "test") terraform.TestStateFile(t, b.StatePath, testRefreshState()) @@ -71,7 +74,8 @@ test_instance.foo: // GH-12174 func TestLocal_refreshNilModuleWithInput(t *testing.T) { - b := TestLocal(t) + b, cleanup := TestLocal(t) + defer cleanup() p := TestLocalProvider(t, b, "test") terraform.TestStateFile(t, b.StatePath, testRefreshState()) @@ -101,7 +105,8 @@ test_instance.foo: } func TestLocal_refreshInput(t *testing.T) { - b := TestLocal(t) + b, cleanup := TestLocal(t) + defer cleanup() p := TestLocalProvider(t, b, "test") terraform.TestStateFile(t, b.StatePath, testRefreshState()) @@ -145,7 +150,8 @@ test_instance.foo: } func TestLocal_refreshValidate(t *testing.T) { - b := TestLocal(t) + b, cleanup := TestLocal(t) + defer cleanup() p := TestLocalProvider(t, b, "test") terraform.TestStateFile(t, b.StatePath, testRefreshState()) diff --git a/backend/local/testing.go b/backend/local/testing.go index beb88508e..4d480f6d7 100644 --- a/backend/local/testing.go +++ b/backend/local/testing.go @@ -2,6 +2,7 @@ package local import ( "io/ioutil" + "os" "path/filepath" "testing" @@ -15,15 +16,22 @@ import ( // // No operations will be called on the returned value, so you can still set // public fields without any locks. -func TestLocal(t *testing.T) *Local { +func TestLocal(t *testing.T) (*Local, func()) { tempDir := testTempDir(t) - return &Local{ + local := &Local{ StatePath: filepath.Join(tempDir, "state.tfstate"), StateOutPath: filepath.Join(tempDir, "state.tfstate"), StateBackupPath: filepath.Join(tempDir, "state.tfstate.bak"), StateWorkspaceDir: filepath.Join(tempDir, "state.tfstate.d"), ContextOpts: &terraform.ContextOpts{}, } + cleanup := func() { + if err := os.RemoveAll(tempDir); err != nil { + t.Fatal("error clecanup up test:", err) + } + } + + return local, cleanup } // TestLocalProvider modifies the ContextOpts of the *Local parameter to From 15dc75720e324a2bdd9b4a8566651fa010c10d51 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Wed, 28 Mar 2018 11:33:42 -0400 Subject: [PATCH 2/3] don't re-use a TempDir path Rather than creating and immediately removing a temp directory to get a random path name, fetch files into a subdirectory. --- config/module/get.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/config/module/get.go b/config/module/get.go index 58515ab36..5073d0d27 100644 --- a/config/module/get.go +++ b/config/module/get.go @@ -3,6 +3,7 @@ package module import ( "io/ioutil" "os" + "path/filepath" "github.com/hashicorp/go-getter" ) @@ -37,13 +38,10 @@ func GetCopy(dst, src string) error { if err != nil { return err } - // FIXME: This isn't completely safe. Creating and removing our temp path - // exposes where to race to inject files. - if err := os.RemoveAll(tmpDir); err != nil { - return err - } defer os.RemoveAll(tmpDir) + tmpDir = filepath.Join(tmpDir, "module") + // Get to that temporary dir if err := getter.Get(tmpDir, src); err != nil { return err From e9801564517097db415bd5d6eaa2513896bf34ef Mon Sep 17 00:00:00 2001 From: James Bardin Date: Wed, 28 Mar 2018 13:08:38 -0400 Subject: [PATCH 3/3] cleanup temp files from command tests Rather than try to modify all the hundreds of calls to the temp helper functions, and cleanup the temp files at every call site, have all tests work within a single temp directory that is removed at the end of TestMain. --- command/apply_test.go | 10 ++----- command/command_test.go | 18 +++++++++--- command/debug_json2dot_test.go | 2 +- command/fmt_test.go | 46 ++++++++----------------------- command/init_test.go | 6 +--- command/output_test.go | 6 +--- command/plan_test.go | 50 +++++----------------------------- command/plugins_lock_test.go | 2 +- command/plugins_test.go | 7 +---- command/refresh_test.go | 23 ++++++++-------- command/show_test.go | 46 +++---------------------------- 11 files changed, 55 insertions(+), 161 deletions(-) diff --git a/command/apply_test.go b/command/apply_test.go index 6eda227f0..19862257b 100644 --- a/command/apply_test.go +++ b/command/apply_test.go @@ -252,10 +252,7 @@ func TestApply_configInvalid(t *testing.T) { } func TestApply_defaultState(t *testing.T) { - td, err := ioutil.TempDir("", "tf") - if err != nil { - t.Fatalf("err: %s", err) - } + td := testTempDir(t) statePath := filepath.Join(td, DefaultStateFilename) // Change to the temporary directory @@ -735,10 +732,7 @@ func TestApply_planVars(t *testing.T) { // we should be able to apply a plan file with no other file dependencies func TestApply_planNoModuleFiles(t *testing.T) { // temporary data directory which we can remove between commands - td, err := ioutil.TempDir("", "tf") - if err != nil { - t.Fatal(err) - } + td := testTempDir(t) defer os.RemoveAll(td) defer testChdir(t, td)() diff --git a/command/command_test.go b/command/command_test.go index bf6fee7c2..12d48761b 100644 --- a/command/command_test.go +++ b/command/command_test.go @@ -27,6 +27,9 @@ import ( // This is the directory where our test fixtures are. var fixtureDir = "./test-fixtures" +// a top level temp directory which will be cleaned after all tests +var testingDir string + func init() { test = true @@ -37,9 +40,16 @@ func init() { if err != nil { panic(err) } + + testingDir, err = ioutil.TempDir(testingDir, "tf") + if err != nil { + panic(err) + } } func TestMain(m *testing.M) { + defer os.RemoveAll(testingDir) + flag.Parse() if testing.Verbose() { // if we're verbose, use the logging requested by TF_LOG @@ -55,7 +65,7 @@ func TestMain(m *testing.M) { func tempDir(t *testing.T) string { t.Helper() - dir, err := ioutil.TempDir("", "tf") + dir, err := ioutil.TempDir(testingDir, "tf") if err != nil { t.Fatalf("err: %s", err) } @@ -305,7 +315,7 @@ func testTempFile(t *testing.T) string { func testTempDir(t *testing.T) string { t.Helper() - d, err := ioutil.TempDir("", "tf") + d, err := ioutil.TempDir(testingDir, "tf") if err != nil { t.Fatalf("err: %s", err) } @@ -358,7 +368,7 @@ func testChdir(t *testing.T, new string) func() { func testCwd(t *testing.T) (string, string) { t.Helper() - tmp, err := ioutil.TempDir("", "tf") + tmp, err := ioutil.TempDir(testingDir, "tf") if err != nil { t.Fatalf("err: %v", err) } @@ -595,7 +605,7 @@ func testRemoteState(t *testing.T, s *terraform.State, c int) (*terraform.Remote // supplied to locate the statelocker.go source. func testLockState(sourceDir, path string) (func(), error) { // build and run the binary ourselves so we can quickly terminate it for cleanup - buildDir, err := ioutil.TempDir("", "locker") + buildDir, err := ioutil.TempDir(testingDir, "locker") if err != nil { return nil, err } diff --git a/command/debug_json2dot_test.go b/command/debug_json2dot_test.go index 75c1a60bd..3e72048ae 100644 --- a/command/debug_json2dot_test.go +++ b/command/debug_json2dot_test.go @@ -12,7 +12,7 @@ import ( func TestDebugJSON2Dot(t *testing.T) { // create the graph JSON output - logFile, err := ioutil.TempFile("", "tf") + logFile, err := ioutil.TempFile(testingDir, "tf") if err != nil { t.Fatal(err) } diff --git a/command/fmt_test.go b/command/fmt_test.go index ffaaa7a99..454f1de70 100644 --- a/command/fmt_test.go +++ b/command/fmt_test.go @@ -13,11 +13,7 @@ import ( ) func TestFmt_errorReporting(t *testing.T) { - tempDir, err := fmtFixtureWriteDir() - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.RemoveAll(tempDir) + tempDir := fmtFixtureWriteDir(t) ui := new(cli.MockUi) c := &FmtCommand{ @@ -63,11 +59,7 @@ func TestFmt_tooManyArgs(t *testing.T) { } func TestFmt_workingDirectory(t *testing.T) { - tempDir, err := fmtFixtureWriteDir() - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.RemoveAll(tempDir) + tempDir := fmtFixtureWriteDir(t) cwd, err := os.Getwd() if err != nil { @@ -99,11 +91,7 @@ func TestFmt_workingDirectory(t *testing.T) { } func TestFmt_directoryArg(t *testing.T) { - tempDir, err := fmtFixtureWriteDir() - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.RemoveAll(tempDir) + tempDir := fmtFixtureWriteDir(t) ui := new(cli.MockUi) c := &FmtCommand{ @@ -149,11 +137,7 @@ func TestFmt_stdinArg(t *testing.T) { } func TestFmt_nonDefaultOptions(t *testing.T) { - tempDir, err := fmtFixtureWriteDir() - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.RemoveAll(tempDir) + tempDir := fmtFixtureWriteDir(t) ui := new(cli.MockUi) c := &FmtCommand{ @@ -180,11 +164,7 @@ func TestFmt_nonDefaultOptions(t *testing.T) { } func TestFmt_check(t *testing.T) { - tempDir, err := fmtFixtureWriteDir() - if err != nil { - t.Fatalf("err: %s", err) - } - defer os.RemoveAll(tempDir) + tempDir := fmtFixtureWriteDir(t) ui := new(cli.MockUi) c := &FmtCommand{ @@ -244,17 +224,13 @@ var fmtFixture = struct { `), } -func fmtFixtureWriteDir() (string, error) { - dir, err := ioutil.TempDir("", "tf") +func fmtFixtureWriteDir(t *testing.T) string { + dir := testTempDir(t) + + err := ioutil.WriteFile(filepath.Join(dir, fmtFixture.filename), fmtFixture.input, 0644) if err != nil { - return "", err + t.Fatal(err) } - err = ioutil.WriteFile(filepath.Join(dir, fmtFixture.filename), fmtFixture.input, 0644) - if err != nil { - os.RemoveAll(dir) - return "", err - } - - return dir, nil + return dir } diff --git a/command/init_test.go b/command/init_test.go index 1e95e1241..32118b486 100644 --- a/command/init_test.go +++ b/command/init_test.go @@ -998,11 +998,7 @@ func TestInit_providerLockFile(t *testing.T) { } func TestInit_pluginDirReset(t *testing.T) { - td, err := ioutil.TempDir("", "tf") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(td) + td := testTempDir(t) defer testChdir(t, td)() ui := new(cli.MockUi) diff --git a/command/output_test.go b/command/output_test.go index 298cd8444..e4b536448 100644 --- a/command/output_test.go +++ b/command/output_test.go @@ -1,7 +1,6 @@ package command import ( - "io/ioutil" "os" "path/filepath" "strings" @@ -451,10 +450,7 @@ func TestOutput_stateDefault(t *testing.T) { // Write the state file in a temporary directory with the // default filename. - td, err := ioutil.TempDir("", "tf") - if err != nil { - t.Fatalf("err: %s", err) - } + td := testTempDir(t) statePath := filepath.Join(td, DefaultStateFilename) f, err := os.Create(statePath) diff --git a/command/plan_test.go b/command/plan_test.go index b78de9b8e..2da48ae00 100644 --- a/command/plan_test.go +++ b/command/plan_test.go @@ -196,12 +196,8 @@ func TestPlan_outPath(t *testing.T) { tmp, cwd := testCwd(t) defer testFixCwd(t, tmp, cwd) - tf, err := ioutil.TempFile("", "tf") - if err != nil { - t.Fatalf("err: %s", err) - } - outPath := tf.Name() - os.Remove(tf.Name()) + td := testTempDir(t) + outPath := filepath.Join(td, "test.plan") p := testProvider() ui := new(cli.MockUi) @@ -253,12 +249,8 @@ func TestPlan_outPathNoChange(t *testing.T) { } statePath := testStateFile(t, originalState) - tf, err := ioutil.TempFile("", "tf") - if err != nil { - t.Fatalf("err: %s", err) - } - outPath := tf.Name() - os.Remove(tf.Name()) + td := testTempDir(t) + outPath := filepath.Join(td, "test.plan") p := testProvider() ui := new(cli.MockUi) @@ -433,20 +425,8 @@ func TestPlan_refresh(t *testing.T) { } func TestPlan_state(t *testing.T) { - // Write out some prior state - tf, err := ioutil.TempFile("", "tf") - if err != nil { - t.Fatalf("err: %s", err) - } - statePath := tf.Name() - defer os.Remove(tf.Name()) - originalState := testState() - err = terraform.WriteState(originalState, tf) - tf.Close() - if err != nil { - t.Fatalf("err: %s", err) - } + statePath := testStateFile(t, originalState) p := testProvider() ui := new(cli.MockUi) @@ -475,24 +455,7 @@ func TestPlan_state(t *testing.T) { func TestPlan_stateDefault(t *testing.T) { originalState := testState() - - // Write the state file in a temporary directory with the - // default filename. - td, err := ioutil.TempDir("", "tf") - if err != nil { - t.Fatalf("err: %s", err) - } - statePath := filepath.Join(td, DefaultStateFilename) - - f, err := os.Create(statePath) - if err != nil { - t.Fatalf("err: %s", err) - } - err = terraform.WriteState(originalState, f) - f.Close() - if err != nil { - t.Fatalf("err: %s", err) - } + statePath := testStateFile(t, originalState) // Change to that directory cwd, err := os.Getwd() @@ -514,6 +477,7 @@ func TestPlan_stateDefault(t *testing.T) { } args := []string{ + "-state", statePath, testFixturePath("plan"), } if code := c.Run(args); code != 0 { diff --git a/command/plugins_lock_test.go b/command/plugins_lock_test.go index b954c127b..946ccab02 100644 --- a/command/plugins_lock_test.go +++ b/command/plugins_lock_test.go @@ -7,7 +7,7 @@ import ( ) func TestPluginSHA256LockFile(t *testing.T) { - f, err := ioutil.TempFile("", "tf-pluginsha1lockfile-test-") + f, err := ioutil.TempFile(testingDir, "tf-pluginsha1lockfile-test-") if err != nil { t.Fatalf("failed to create temporary file: %s", err) } diff --git a/command/plugins_test.go b/command/plugins_test.go index fb7ee16e0..086a30d9c 100644 --- a/command/plugins_test.go +++ b/command/plugins_test.go @@ -2,7 +2,6 @@ package command import ( "fmt" - "io/ioutil" "os" "path/filepath" "reflect" @@ -95,11 +94,7 @@ func TestMultiVersionProviderResolver(t *testing.T) { } func TestPluginPath(t *testing.T) { - td, err := ioutil.TempDir("", "tf") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(td) + td := testTempDir(t) defer testChdir(t, td)() pluginPath := []string{"a", "b", "c"} diff --git a/command/refresh_test.go b/command/refresh_test.go index bb04f39f5..a083849f3 100644 --- a/command/refresh_test.go +++ b/command/refresh_test.go @@ -189,17 +189,17 @@ func TestRefresh_defaultState(t *testing.T) { // Write the state file in a temporary directory with the // default filename. - td, err := ioutil.TempDir("", "tf") - if err != nil { - t.Fatalf("err: %s", err) - } - statePath := filepath.Join(td, DefaultStateFilename) + statePath := testStateFile(t, originalState) localState := &state.LocalState{Path: statePath} - if err := localState.WriteState(originalState); err != nil { + if err := localState.RefreshState(); err != nil { t.Fatal(err) } - serial := localState.State().Serial + s := localState.State() + if s == nil { + t.Fatal("empty test state") + } + serial := s.Serial // Change to that directory cwd, err := os.Getwd() @@ -224,6 +224,7 @@ func TestRefresh_defaultState(t *testing.T) { p.RefreshReturn = newInstanceState("yes") args := []string{ + "-state", statePath, testFixturePath("refresh"), } if code := c.Run(args); code != 0 { @@ -364,7 +365,7 @@ func TestRefresh_outPath(t *testing.T) { statePath := testStateFile(t, state) // Output path - outf, err := ioutil.TempFile("", "tf") + outf, err := ioutil.TempFile(testingDir, "tf") if err != nil { t.Fatalf("err: %s", err) } @@ -585,7 +586,7 @@ func TestRefresh_backup(t *testing.T) { statePath := testStateFile(t, state) // Output path - outf, err := ioutil.TempFile("", "tf") + outf, err := ioutil.TempFile(testingDir, "tf") if err != nil { t.Fatalf("err: %s", err) } @@ -594,7 +595,7 @@ func TestRefresh_backup(t *testing.T) { os.Remove(outPath) // Backup path - backupf, err := ioutil.TempFile("", "tf") + backupf, err := ioutil.TempFile(testingDir, "tf") if err != nil { t.Fatalf("err: %s", err) } @@ -679,7 +680,7 @@ func TestRefresh_disableBackup(t *testing.T) { statePath := testStateFile(t, state) // Output path - outf, err := ioutil.TempFile("", "tf") + outf, err := ioutil.TempFile(testingDir, "tf") if err != nil { t.Fatalf("err: %s", err) } diff --git a/command/show_test.go b/command/show_test.go index dfcb4ac7c..53c2cdcaa 100644 --- a/command/show_test.go +++ b/command/show_test.go @@ -1,8 +1,6 @@ package command import ( - "io/ioutil" - "os" "path/filepath" "strings" "testing" @@ -32,31 +30,8 @@ func TestShow(t *testing.T) { func TestShow_noArgs(t *testing.T) { // Create the default state - td, err := ioutil.TempDir("", "tf") - if err != nil { - t.Fatalf("err: %s", err) - } - statePath := filepath.Join(td, DefaultStateFilename) - - f, err := os.Create(statePath) - if err != nil { - t.Fatalf("err: %s", err) - } - err = terraform.WriteState(testState(), f) - f.Close() - if err != nil { - t.Fatalf("err: %s", err) - } - - // Change to the temporary directory - cwd, err := os.Getwd() - if err != nil { - t.Fatalf("err: %s", err) - } - if err := os.Chdir(filepath.Dir(statePath)); err != nil { - t.Fatalf("err: %s", err) - } - defer os.Chdir(cwd) + statePath := testStateFile(t, testState()) + defer testChdir(t, filepath.Dir(statePath))() ui := new(cli.MockUi) c := &ShowCommand{ @@ -74,21 +49,8 @@ func TestShow_noArgs(t *testing.T) { func TestShow_noArgsNoState(t *testing.T) { // Create the default state - td, err := ioutil.TempDir("", "tf") - if err != nil { - t.Fatalf("err: %s", err) - } - statePath := filepath.Join(td, DefaultStateFilename) - - // Change to the temporary directory - cwd, err := os.Getwd() - if err != nil { - t.Fatalf("err: %s", err) - } - if err := os.Chdir(filepath.Dir(statePath)); err != nil { - t.Fatalf("err: %s", err) - } - defer os.Chdir(cwd) + statePath := testStateFile(t, testState()) + defer testChdir(t, filepath.Dir(statePath))() ui := new(cli.MockUi) c := &ShowCommand{