github.com/cbroglie/terraform@v0.7.0-rc3.0.20170410193827-735dfc416d46/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 UnknownPendingStateRefreshFunc() StateRefreshFunc { 74 sequence := []string{ 75 "unknown1", "unknown2", "done", 76 } 77 78 r := NewStateGenerator(sequence) 79 80 return func() (interface{}, string, error) { 81 idx, s, err := r.NextState() 82 if err != nil { 83 return nil, "", err 84 } 85 86 return idx, s, nil 87 } 88 } 89 90 func TestWaitForState_inconsistent_positive(t *testing.T) { 91 conf := &StateChangeConf{ 92 Pending: []string{"replicating"}, 93 Target: []string{"done"}, 94 Refresh: InconsistentStateRefreshFunc(), 95 Timeout: 90 * time.Millisecond, 96 PollInterval: 10 * time.Millisecond, 97 ContinuousTargetOccurence: 3, 98 } 99 100 idx, err := conf.WaitForState() 101 102 if err != nil { 103 t.Fatalf("err: %s", err) 104 } 105 106 if idx != 4 { 107 t.Fatalf("Expected index 4, given %d", idx.(int)) 108 } 109 } 110 111 func TestWaitForState_inconsistent_negative(t *testing.T) { 112 conf := &StateChangeConf{ 113 Pending: []string{"replicating"}, 114 Target: []string{"done"}, 115 Refresh: InconsistentStateRefreshFunc(), 116 Timeout: 90 * time.Millisecond, 117 PollInterval: 10 * time.Millisecond, 118 ContinuousTargetOccurence: 4, 119 } 120 121 _, err := conf.WaitForState() 122 123 if err == nil { 124 t.Fatal("Expected timeout error. No error returned.") 125 } 126 expectedErr := "timeout while waiting for state to become 'done' (last state: 'done', timeout: 90ms)" 127 if err.Error() != expectedErr { 128 t.Fatalf("Errors don't match.\nExpected: %q\nGiven: %q\n", expectedErr, err.Error()) 129 } 130 } 131 132 func TestWaitForState_timeout(t *testing.T) { 133 conf := &StateChangeConf{ 134 Pending: []string{"pending", "incomplete"}, 135 Target: []string{"running"}, 136 Refresh: TimeoutStateRefreshFunc(), 137 Timeout: 1 * time.Millisecond, 138 } 139 140 obj, err := conf.WaitForState() 141 142 if err == nil { 143 t.Fatal("Expected timeout error. No error returned.") 144 } 145 146 expectedErr := "timeout while waiting for state to become 'running' (timeout: 1ms)" 147 if err.Error() != expectedErr { 148 t.Fatalf("Errors don't match.\nExpected: %q\nGiven: %q\n", expectedErr, err.Error()) 149 } 150 151 if obj != nil { 152 t.Fatalf("should not return obj") 153 } 154 155 } 156 157 func TestWaitForState_success(t *testing.T) { 158 conf := &StateChangeConf{ 159 Pending: []string{"pending", "incomplete"}, 160 Target: []string{"running"}, 161 Refresh: SuccessfulStateRefreshFunc(), 162 Timeout: 200 * time.Second, 163 } 164 165 obj, err := conf.WaitForState() 166 if err != nil { 167 t.Fatalf("err: %s", err) 168 } 169 if obj == nil { 170 t.Fatalf("should return obj") 171 } 172 } 173 174 func TestWaitForState_successUnknownPending(t *testing.T) { 175 conf := &StateChangeConf{ 176 Target: []string{"done"}, 177 Refresh: UnknownPendingStateRefreshFunc(), 178 Timeout: 200 * time.Second, 179 } 180 181 obj, err := conf.WaitForState() 182 if err != nil { 183 t.Fatalf("err: %s", err) 184 } 185 if obj == nil { 186 t.Fatalf("should return obj") 187 } 188 } 189 190 func TestWaitForState_successEmpty(t *testing.T) { 191 conf := &StateChangeConf{ 192 Pending: []string{"pending", "incomplete"}, 193 Target: []string{}, 194 Refresh: func() (interface{}, string, error) { 195 return nil, "", nil 196 }, 197 Timeout: 200 * time.Second, 198 } 199 200 obj, err := conf.WaitForState() 201 if err != nil { 202 t.Fatalf("err: %s", err) 203 } 204 if obj != nil { 205 t.Fatalf("obj should be nil") 206 } 207 } 208 209 func TestWaitForState_failureEmpty(t *testing.T) { 210 conf := &StateChangeConf{ 211 Pending: []string{"pending", "incomplete"}, 212 Target: []string{}, 213 NotFoundChecks: 1, 214 Refresh: func() (interface{}, string, error) { 215 return 42, "pending", nil 216 }, 217 PollInterval: 10 * time.Millisecond, 218 Timeout: 100 * time.Millisecond, 219 } 220 221 _, err := conf.WaitForState() 222 if err == nil { 223 t.Fatal("Expected timeout error. Got none.") 224 } 225 expectedErr := "timeout while waiting for resource to be gone (last state: 'pending', timeout: 100ms)" 226 if err.Error() != expectedErr { 227 t.Fatalf("Errors don't match.\nExpected: %q\nGiven: %q\n", expectedErr, err.Error()) 228 } 229 } 230 231 func TestWaitForState_failure(t *testing.T) { 232 conf := &StateChangeConf{ 233 Pending: []string{"pending", "incomplete"}, 234 Target: []string{"running"}, 235 Refresh: FailedStateRefreshFunc(), 236 Timeout: 200 * time.Second, 237 } 238 239 obj, err := conf.WaitForState() 240 if err == nil { 241 t.Fatal("Expected error. No error returned.") 242 } 243 expectedErr := "failed" 244 if err.Error() != expectedErr { 245 t.Fatalf("Errors don't match.\nExpected: %q\nGiven: %q\n", expectedErr, err.Error()) 246 } 247 if obj != nil { 248 t.Fatalf("should not return obj") 249 } 250 }