github.com/richardbowden/terraform@v0.6.12-0.20160901200758-30ea22c25211/helper/resource/state_test.go (about) 1 package resource 2 3 import ( 4 "errors" 5 "testing" 6 "time" 7 ) 8 9 func FailedStateRefreshFunc() StateRefreshFunc { 10 return func() (interface{}, string, error) { 11 return nil, "", errors.New("failed") 12 } 13 } 14 15 func TimeoutStateRefreshFunc() StateRefreshFunc { 16 return func() (interface{}, string, error) { 17 time.Sleep(100 * time.Second) 18 return nil, "", errors.New("failed") 19 } 20 } 21 22 func SuccessfulStateRefreshFunc() StateRefreshFunc { 23 return func() (interface{}, string, error) { 24 return struct{}{}, "running", nil 25 } 26 } 27 28 type StateGenerator struct { 29 position int 30 stateSequence []string 31 } 32 33 func (r *StateGenerator) NextState() (int, string, error) { 34 p, v := r.position, "" 35 if len(r.stateSequence)-1 >= p { 36 v = r.stateSequence[p] 37 } else { 38 return -1, "", errors.New("No more states available") 39 } 40 41 r.position += 1 42 43 return p, v, nil 44 } 45 46 func NewStateGenerator(sequence []string) *StateGenerator { 47 r := &StateGenerator{} 48 r.stateSequence = sequence 49 50 return r 51 } 52 53 func InconsistentStateRefreshFunc() StateRefreshFunc { 54 sequence := []string{ 55 "done", "replicating", 56 "done", "done", "done", 57 "replicating", 58 "done", "done", "done", 59 } 60 61 r := NewStateGenerator(sequence) 62 63 return func() (interface{}, string, error) { 64 idx, s, err := r.NextState() 65 if err != nil { 66 return nil, "", err 67 } 68 69 return idx, s, nil 70 } 71 } 72 73 func TestWaitForState_inconsistent_positive(t *testing.T) { 74 conf := &StateChangeConf{ 75 Pending: []string{"replicating"}, 76 Target: []string{"done"}, 77 Refresh: InconsistentStateRefreshFunc(), 78 Timeout: 90 * time.Millisecond, 79 PollInterval: 10 * time.Millisecond, 80 ContinuousTargetOccurence: 3, 81 } 82 83 idx, err := conf.WaitForState() 84 85 if err != nil { 86 t.Fatalf("err: %s", err) 87 } 88 89 if idx != 4 { 90 t.Fatalf("Expected index 4, given %d", idx.(int)) 91 } 92 } 93 94 func TestWaitForState_inconsistent_negative(t *testing.T) { 95 conf := &StateChangeConf{ 96 Pending: []string{"replicating"}, 97 Target: []string{"done"}, 98 Refresh: InconsistentStateRefreshFunc(), 99 Timeout: 90 * time.Millisecond, 100 PollInterval: 10 * time.Millisecond, 101 ContinuousTargetOccurence: 4, 102 } 103 104 _, err := conf.WaitForState() 105 106 if err == nil { 107 t.Fatal("Expected timeout error. No error returned.") 108 } 109 expectedErr := "timeout while waiting for state to become 'done' (last state: 'done')" 110 if err.Error() != expectedErr { 111 t.Fatalf("Errors don't match.\nExpected: %q\nGiven: %q\n", expectedErr, err.Error()) 112 } 113 } 114 115 func TestWaitForState_timeout(t *testing.T) { 116 conf := &StateChangeConf{ 117 Pending: []string{"pending", "incomplete"}, 118 Target: []string{"running"}, 119 Refresh: TimeoutStateRefreshFunc(), 120 Timeout: 1 * time.Millisecond, 121 } 122 123 obj, err := conf.WaitForState() 124 125 if err == nil { 126 t.Fatal("Expected timeout error. No error returned.") 127 } 128 129 expectedErr := "timeout while waiting for state to become 'running'" 130 if err.Error() != expectedErr { 131 t.Fatalf("Errors don't match.\nExpected: %q\nGiven: %q\n", expectedErr, err.Error()) 132 } 133 134 if obj != nil { 135 t.Fatalf("should not return obj") 136 } 137 138 } 139 140 func TestWaitForState_success(t *testing.T) { 141 conf := &StateChangeConf{ 142 Pending: []string{"pending", "incomplete"}, 143 Target: []string{"running"}, 144 Refresh: SuccessfulStateRefreshFunc(), 145 Timeout: 200 * time.Second, 146 } 147 148 obj, err := conf.WaitForState() 149 if err != nil { 150 t.Fatalf("err: %s", err) 151 } 152 if obj == nil { 153 t.Fatalf("should return obj") 154 } 155 } 156 157 func TestWaitForState_successEmpty(t *testing.T) { 158 conf := &StateChangeConf{ 159 Pending: []string{"pending", "incomplete"}, 160 Target: []string{}, 161 Refresh: func() (interface{}, string, error) { 162 return nil, "", nil 163 }, 164 Timeout: 200 * time.Second, 165 } 166 167 obj, err := conf.WaitForState() 168 if err != nil { 169 t.Fatalf("err: %s", err) 170 } 171 if obj != nil { 172 t.Fatalf("obj should be nil") 173 } 174 } 175 176 func TestWaitForState_failureEmpty(t *testing.T) { 177 conf := &StateChangeConf{ 178 Pending: []string{"pending", "incomplete"}, 179 Target: []string{}, 180 NotFoundChecks: 1, 181 Refresh: func() (interface{}, string, error) { 182 return 42, "pending", nil 183 }, 184 PollInterval: 10 * time.Millisecond, 185 Timeout: 100 * time.Millisecond, 186 } 187 188 _, err := conf.WaitForState() 189 if err == nil { 190 t.Fatal("Expected timeout error. Got none.") 191 } 192 expectedErr := "timeout while waiting for resource to be gone (last state: 'pending')" 193 if err.Error() != expectedErr { 194 t.Fatalf("Errors don't match.\nExpected: %q\nGiven: %q\n", expectedErr, err.Error()) 195 } 196 } 197 198 func TestWaitForState_failure(t *testing.T) { 199 conf := &StateChangeConf{ 200 Pending: []string{"pending", "incomplete"}, 201 Target: []string{"running"}, 202 Refresh: FailedStateRefreshFunc(), 203 Timeout: 200 * time.Second, 204 } 205 206 obj, err := conf.WaitForState() 207 if err == nil { 208 t.Fatal("Expected error. No error returned.") 209 } 210 expectedErr := "failed" 211 if err.Error() != expectedErr { 212 t.Fatalf("Errors don't match.\nExpected: %q\nGiven: %q\n", expectedErr, err.Error()) 213 } 214 if obj != nil { 215 t.Fatalf("should not return obj") 216 } 217 }