diff --git a/state/backup_test.go b/state/backup_test.go deleted file mode 100644 index 8ef0afec6..000000000 --- a/state/backup_test.go +++ /dev/null @@ -1,65 +0,0 @@ -package state - -import ( - "io/ioutil" - "os" - "sync" - "testing" -) - -func TestBackupState_locker(t *testing.T) { - var _ Locker = new(BackupState) -} - -func TestBackupState(t *testing.T) { - f, err := ioutil.TempFile("", "tf") - if err != nil { - t.Fatalf("err: %s", err) - } - f.Close() - defer os.Remove(f.Name()) - - ls := testLocalState(t) - defer os.Remove(ls.Path) - TestState(t, &BackupState{ - Real: ls, - Path: f.Name(), - }) - - if fi, err := os.Stat(f.Name()); err != nil { - t.Fatalf("err: %s", err) - } else if fi.Size() == 0 { - t.Fatalf("bad: %d", fi.Size()) - } -} - -func TestBackupStateRace(t *testing.T) { - f, err := ioutil.TempFile("", "tf") - if err != nil { - t.Fatalf("err: %s", err) - } - f.Close() - defer os.Remove(f.Name()) - - ls := testLocalState(t) - defer os.Remove(ls.Path) - bs := &BackupState{ - Real: ls, - Path: f.Name(), - } - - current := TestStateInitial() - - var wg sync.WaitGroup - for i := 0; i < 100; i++ { - wg.Add(1) - go func() { - defer wg.Done() - bs.WriteState(current) - bs.PersistState() - bs.RefreshState() - }() - } - - wg.Wait() -} diff --git a/state/inmem_test.go b/state/inmem_test.go deleted file mode 100644 index 6ca8a69a5..000000000 --- a/state/inmem_test.go +++ /dev/null @@ -1,52 +0,0 @@ -package state - -import ( - "testing" -) - -func TestInmemState(t *testing.T) { - TestState(t, &InmemState{state: TestStateInitial()}) -} - -func TestInmemState_impl(t *testing.T) { - var _ StateReader = new(InmemState) - var _ StateWriter = new(InmemState) - var _ StatePersister = new(InmemState) - var _ StateRefresher = new(InmemState) -} - -func TestInmemLocker(t *testing.T) { - inmem := &InmemState{state: TestStateInitial()} - // test that it correctly wraps the inmem state - s := &inmemLocker{InmemState: inmem} - TestState(t, s) - - info := NewLockInfo() - - id, err := s.Lock(info) - if err != nil { - t.Fatal(err) - } - - if id == "" { - t.Fatal("no lock id from state lock") - } - - // locking again should fail - _, err = s.Lock(NewLockInfo()) - if err == nil { - t.Fatal("state locked while locked") - } - - if err.(*LockError).Info.ID != id { - t.Fatal("wrong lock id from lock failure") - } - - if err := s.Unlock(id); err != nil { - t.Fatal(err) - } - - if _, err := s.Lock(NewLockInfo()); err != nil { - t.Fatal(err) - } -} diff --git a/state/local_test.go b/state/local_test.go deleted file mode 100644 index 13dcf6eab..000000000 --- a/state/local_test.go +++ /dev/null @@ -1,207 +0,0 @@ -package state - -import ( - "io/ioutil" - "os" - "os/exec" - "sync" - "testing" - - "github.com/hashicorp/terraform/terraform" -) - -func TestLocalState(t *testing.T) { - ls := testLocalState(t) - defer os.Remove(ls.Path) - TestState(t, ls) -} - -func TestLocalStateRace(t *testing.T) { - ls := testLocalState(t) - defer os.Remove(ls.Path) - - current := TestStateInitial() - - var wg sync.WaitGroup - for i := 0; i < 100; i++ { - wg.Add(1) - go func() { - defer wg.Done() - ls.WriteState(current) - }() - } -} - -func TestLocalStateLocks(t *testing.T) { - s := testLocalState(t) - defer os.Remove(s.Path) - - // lock first - info := NewLockInfo() - info.Operation = "test" - lockID, err := s.Lock(info) - if err != nil { - t.Fatal(err) - } - - out, err := exec.Command("go", "run", "testdata/lockstate.go", s.Path).CombinedOutput() - if err != nil { - t.Fatal("unexpected lock failure", err, string(out)) - } - - if string(out) != "lock failed" { - t.Fatal("expected 'locked failed', got", string(out)) - } - - // check our lock info - lockInfo, err := s.lockInfo() - if err != nil { - t.Fatal(err) - } - - if lockInfo.Operation != "test" { - t.Fatalf("invalid lock info %#v\n", lockInfo) - } - - // a noop, since we unlock on exit - if err := s.Unlock(lockID); err != nil { - t.Fatal(err) - } - - // local locks can re-lock - lockID, err = s.Lock(info) - if err != nil { - t.Fatal(err) - } - - if err := s.Unlock(lockID); err != nil { - t.Fatal(err) - } - - // we should not be able to unlock the same lock twice - if err := s.Unlock(lockID); err == nil { - t.Fatal("unlocking an unlocked state should fail") - } - - // make sure lock info is gone - lockInfoPath := s.lockInfoPath() - if _, err := os.Stat(lockInfoPath); !os.IsNotExist(err) { - t.Fatal("lock info not removed") - } -} - -// Verify that we can write to the state file, as Windows' mandatory locking -// will prevent writing to a handle different than the one that hold the lock. -func TestLocalState_writeWhileLocked(t *testing.T) { - s := testLocalState(t) - defer os.Remove(s.Path) - - // lock first - info := NewLockInfo() - info.Operation = "test" - lockID, err := s.Lock(info) - if err != nil { - t.Fatal(err) - } - defer func() { - if err := s.Unlock(lockID); err != nil { - t.Fatal(err) - } - }() - - if err := s.WriteState(TestStateInitial()); err != nil { - t.Fatal(err) - } -} - -func TestLocalState_pathOut(t *testing.T) { - f, err := ioutil.TempFile("", "tf") - if err != nil { - t.Fatalf("err: %s", err) - } - f.Close() - defer os.Remove(f.Name()) - - ls := testLocalState(t) - ls.PathOut = f.Name() - defer os.Remove(ls.Path) - - TestState(t, ls) -} - -func TestLocalState_nonExist(t *testing.T) { - ls := &LocalState{Path: "ishouldntexist"} - if err := ls.RefreshState(); err != nil { - t.Fatalf("err: %s", err) - } - - if state := ls.State(); state != nil { - t.Fatalf("bad: %#v", state) - } -} - -func TestLocalState_impl(t *testing.T) { - var _ StateReader = new(LocalState) - var _ StateWriter = new(LocalState) - var _ StatePersister = new(LocalState) - var _ StateRefresher = new(LocalState) -} - -func testLocalState(t *testing.T) *LocalState { - f, err := ioutil.TempFile("", "tf") - if err != nil { - t.Fatalf("err: %s", err) - } - - err = terraform.WriteState(TestStateInitial(), f) - f.Close() - if err != nil { - t.Fatalf("err: %s", err) - } - - ls := &LocalState{Path: f.Name()} - if err := ls.RefreshState(); err != nil { - t.Fatalf("bad: %s", err) - } - - return ls -} - -// Make sure we can refresh while the state is locked -func TestLocalState_refreshWhileLocked(t *testing.T) { - f, err := ioutil.TempFile("", "tf") - if err != nil { - t.Fatalf("err: %s", err) - } - - err = terraform.WriteState(TestStateInitial(), f) - f.Close() - if err != nil { - t.Fatalf("err: %s", err) - } - - s := &LocalState{Path: f.Name()} - defer os.Remove(s.Path) - - // lock first - info := NewLockInfo() - info.Operation = "test" - lockID, err := s.Lock(info) - if err != nil { - t.Fatal(err) - } - defer func() { - if err := s.Unlock(lockID); err != nil { - t.Fatal(err) - } - }() - - if err := s.RefreshState(); err != nil { - t.Fatal(err) - } - - readState := s.State() - if readState == nil || readState.Lineage == "" { - t.Fatal("missing state") - } -} diff --git a/state/state_test.go b/state/state_test.go index a8fdec6ab..e93f5680a 100644 --- a/state/state_test.go +++ b/state/state_test.go @@ -1,14 +1,12 @@ package state import ( - "context" "encoding/json" "flag" "io/ioutil" "log" "os" "testing" - "time" "github.com/hashicorp/terraform/helper/logging" ) @@ -52,59 +50,3 @@ func TestNewLockInfo(t *testing.T) { t.Fatal(err) } } - -func TestLockWithContext(t *testing.T) { - inmem := &InmemState{state: TestStateInitial()} - // test that it correctly wraps the inmem state - s := &inmemLocker{InmemState: inmem} - - id, err := s.Lock(NewLockInfo()) - if err != nil { - t.Fatal(err) - } - - // use a cancelled context for an immediate timeout - ctx, cancel := context.WithCancel(context.Background()) - cancel() - - info := NewLockInfo() - info.Info = "lock with context" - _, err = LockWithContext(ctx, s, info) - if err == nil { - t.Fatal("lock should have failed immediately") - } - - // block until LockwithContext has made a first attempt - attempted := make(chan struct{}) - postLockHook = func() { - close(attempted) - postLockHook = nil - } - - // unlock the state during LockWithContext - unlocked := make(chan struct{}) - go func() { - defer close(unlocked) - <-attempted - if err := s.Unlock(id); err != nil { - t.Fatal(err) - } - }() - - ctx, cancel = context.WithTimeout(context.Background(), 2*time.Second) - defer cancel() - - id, err = LockWithContext(ctx, s, info) - if err != nil { - t.Fatal("lock should have completed within 2s:", err) - } - - // ensure the goruotine completes - <-unlocked - - // Lock should have been called a total of 4 times. - // 1 initial lock, 1 failure, 1 failure + 1 retry - if s.lockCounter != 4 { - t.Fatalf("lock only called %d times", s.lockCounter) - } -}