github.com/bradfeehan/terraform@v0.7.0-rc3.0.20170529055808-34b45c5ad841/backend/local/hook_state_test.go (about) 1 package local 2 3 import ( 4 "sync" 5 "testing" 6 "time" 7 8 "github.com/hashicorp/terraform/state" 9 "github.com/hashicorp/terraform/terraform" 10 ) 11 12 func TestStateHook_impl(t *testing.T) { 13 var _ terraform.Hook = new(StateHook) 14 } 15 16 func TestStateHook(t *testing.T) { 17 is := &state.InmemState{} 18 var hook terraform.Hook = &StateHook{State: is} 19 20 s := state.TestStateInitial() 21 action, err := hook.PostStateUpdate(s) 22 if err != nil { 23 t.Fatalf("err: %s", err) 24 } 25 if action != terraform.HookActionContinue { 26 t.Fatalf("bad: %v", action) 27 } 28 if !is.State().Equal(s) { 29 t.Fatalf("bad state: %#v", is.State()) 30 } 31 } 32 33 // testPersistState stores the state on WriteState, and 34 type testPersistState struct { 35 *state.InmemState 36 37 mu sync.Mutex 38 persisted bool 39 } 40 41 func (s *testPersistState) WriteState(state *terraform.State) error { 42 s.mu.Lock() 43 defer s.mu.Unlock() 44 45 s.persisted = false 46 return s.InmemState.WriteState(state) 47 } 48 49 func (s *testPersistState) PersistState() error { 50 s.mu.Lock() 51 defer s.mu.Unlock() 52 53 s.persisted = true 54 return nil 55 } 56 57 // verify that StateHook calls PersistState if the last call was more than 58 // persistStateHookInterval 59 func TestStateHookPersist(t *testing.T) { 60 is := &testPersistState{ 61 InmemState: &state.InmemState{}, 62 } 63 hook := &StateHook{State: is} 64 65 s := state.TestStateInitial() 66 hook.PostStateUpdate(s) 67 68 // the first call should persist, since the last time was zero 69 if !is.persisted { 70 t.Fatal("PersistState not called") 71 } 72 73 s.Serial++ 74 hook.PostStateUpdate(s) 75 76 // this call should not have persisted 77 if is.persisted { 78 t.Fatal("PostStateUpdate called PersistState early") 79 } 80 81 if !is.State().Equal(s) { 82 t.Fatalf("bad state: %#v", is.State()) 83 } 84 85 // set the last call back to before our interval 86 hook.lastPersist = time.Now().Add(-2 * persistStateHookInterval) 87 88 s.Serial++ 89 hook.PostStateUpdate(s) 90 91 if !is.persisted { 92 t.Fatal("PersistState not called") 93 } 94 95 if !is.State().Equal(s) { 96 t.Fatalf("bad state: %#v", is.State()) 97 } 98 } 99 100 // verify that the satet hook is safe for concurrent use 101 func TestStateHookRace(t *testing.T) { 102 is := &state.InmemState{} 103 var hook terraform.Hook = &StateHook{State: is} 104 105 s := state.TestStateInitial() 106 107 var wg sync.WaitGroup 108 109 for i := 0; i < 100; i++ { 110 wg.Add(1) 111 go func() { 112 defer wg.Done() 113 action, err := hook.PostStateUpdate(s) 114 if err != nil { 115 t.Fatalf("err: %s", err) 116 } 117 if action != terraform.HookActionContinue { 118 t.Fatalf("bad: %v", action) 119 } 120 if !is.State().Equal(s) { 121 t.Fatalf("bad state: %#v", is.State()) 122 } 123 }() 124 } 125 wg.Wait() 126 }