github.com/meteor/terraform@v0.6.15-0.20210412225145-79ec4bc057c6/state/local_test.go (about) 1 package state 2 3 import ( 4 "io/ioutil" 5 "os" 6 "os/exec" 7 "testing" 8 9 "github.com/hashicorp/terraform/terraform" 10 ) 11 12 func TestLocalState(t *testing.T) { 13 ls := testLocalState(t) 14 defer os.Remove(ls.Path) 15 TestState(t, ls) 16 } 17 18 func TestLocalStateLocks(t *testing.T) { 19 s := testLocalState(t) 20 defer os.Remove(s.Path) 21 22 // lock first 23 info := NewLockInfo() 24 info.Operation = "test" 25 lockID, err := s.Lock(info) 26 if err != nil { 27 t.Fatal(err) 28 } 29 30 out, err := exec.Command("go", "run", "testdata/lockstate.go", s.Path).CombinedOutput() 31 if err != nil { 32 t.Fatal("unexpected lock failure", err, string(out)) 33 } 34 35 if string(out) != "lock failed" { 36 t.Fatal("expected 'locked failed', got", string(out)) 37 } 38 39 // check our lock info 40 lockInfo, err := s.lockInfo() 41 if err != nil { 42 t.Fatal(err) 43 } 44 45 if lockInfo.Operation != "test" { 46 t.Fatalf("invalid lock info %#v\n", lockInfo) 47 } 48 49 // a noop, since we unlock on exit 50 if err := s.Unlock(lockID); err != nil { 51 t.Fatal(err) 52 } 53 54 // local locks can re-lock 55 lockID, err = s.Lock(info) 56 if err != nil { 57 t.Fatal(err) 58 } 59 60 if err := s.Unlock(lockID); err != nil { 61 t.Fatal(err) 62 } 63 64 // we should not be able to unlock the same lock twice 65 if err := s.Unlock(lockID); err == nil { 66 t.Fatal("unlocking an unlocked state should fail") 67 } 68 69 // make sure lock info is gone 70 lockInfoPath := s.lockInfoPath() 71 if _, err := os.Stat(lockInfoPath); !os.IsNotExist(err) { 72 t.Fatal("lock info not removed") 73 } 74 } 75 76 // Verify that we can write to the state file, as Windows' mandatory locking 77 // will prevent writing to a handle different than the one that hold the lock. 78 func TestLocalState_writeWhileLocked(t *testing.T) { 79 s := testLocalState(t) 80 defer os.Remove(s.Path) 81 82 // lock first 83 info := NewLockInfo() 84 info.Operation = "test" 85 lockID, err := s.Lock(info) 86 if err != nil { 87 t.Fatal(err) 88 } 89 defer func() { 90 if err := s.Unlock(lockID); err != nil { 91 t.Fatal(err) 92 } 93 }() 94 95 if err := s.WriteState(TestStateInitial()); err != nil { 96 t.Fatal(err) 97 } 98 } 99 100 func TestLocalState_pathOut(t *testing.T) { 101 f, err := ioutil.TempFile("", "tf") 102 if err != nil { 103 t.Fatalf("err: %s", err) 104 } 105 f.Close() 106 defer os.Remove(f.Name()) 107 108 ls := testLocalState(t) 109 ls.PathOut = f.Name() 110 defer os.Remove(ls.Path) 111 112 TestState(t, ls) 113 } 114 115 func TestLocalState_nonExist(t *testing.T) { 116 ls := &LocalState{Path: "ishouldntexist"} 117 if err := ls.RefreshState(); err != nil { 118 t.Fatalf("err: %s", err) 119 } 120 121 if state := ls.State(); state != nil { 122 t.Fatalf("bad: %#v", state) 123 } 124 } 125 126 func TestLocalState_impl(t *testing.T) { 127 var _ StateReader = new(LocalState) 128 var _ StateWriter = new(LocalState) 129 var _ StatePersister = new(LocalState) 130 var _ StateRefresher = new(LocalState) 131 } 132 133 func testLocalState(t *testing.T) *LocalState { 134 f, err := ioutil.TempFile("", "tf") 135 if err != nil { 136 t.Fatalf("err: %s", err) 137 } 138 139 err = terraform.WriteState(TestStateInitial(), f) 140 f.Close() 141 if err != nil { 142 t.Fatalf("err: %s", err) 143 } 144 145 ls := &LocalState{Path: f.Name()} 146 if err := ls.RefreshState(); err != nil { 147 t.Fatalf("bad: %s", err) 148 } 149 150 return ls 151 }