github.com/acm1/terraform@v0.6.2-0.20150729164239-1f314444f45c/helper/resource/testing_test.go (about) 1 package resource 2 3 import ( 4 "fmt" 5 "os" 6 "sync/atomic" 7 "testing" 8 9 "github.com/hashicorp/terraform/terraform" 10 ) 11 12 func init() { 13 testTesting = true 14 15 if err := os.Setenv(TestEnvVar, "1"); err != nil { 16 panic(err) 17 } 18 } 19 20 func TestTest(t *testing.T) { 21 mp := testProvider() 22 mp.DiffReturn = nil 23 24 mp.ApplyReturn = &terraform.InstanceState{ 25 ID: "foo", 26 } 27 var refreshCount int32 28 mp.RefreshFn = func(*terraform.InstanceInfo, *terraform.InstanceState) (*terraform.InstanceState, error) { 29 atomic.AddInt32(&refreshCount, 1) 30 if atomic.LoadInt32(&refreshCount) == 1 { 31 return &terraform.InstanceState{ID: "foo"}, nil 32 } else { 33 return nil, nil 34 } 35 } 36 37 checkDestroy := false 38 checkStep := false 39 40 checkDestroyFn := func(*terraform.State) error { 41 checkDestroy = true 42 return nil 43 } 44 45 checkStepFn := func(s *terraform.State) error { 46 checkStep = true 47 48 rs, ok := s.RootModule().Resources["test_instance.foo"] 49 if !ok { 50 t.Error("test_instance.foo is not present") 51 return nil 52 } 53 is := rs.Primary 54 if is.ID != "foo" { 55 t.Errorf("bad check ID: %s", is.ID) 56 } 57 58 return nil 59 } 60 61 mt := new(mockT) 62 Test(mt, TestCase{ 63 Providers: map[string]terraform.ResourceProvider{ 64 "test": mp, 65 }, 66 CheckDestroy: checkDestroyFn, 67 Steps: []TestStep{ 68 TestStep{ 69 Config: testConfigStr, 70 Check: checkStepFn, 71 }, 72 }, 73 }) 74 75 if mt.failed() { 76 t.Fatalf("test failed: %s", mt.failMessage()) 77 } 78 if !checkStep { 79 t.Fatal("didn't call check for step") 80 } 81 if !checkDestroy { 82 t.Fatal("didn't call check for destroy") 83 } 84 } 85 86 func TestTest_empty(t *testing.T) { 87 destroyCalled := false 88 checkDestroyFn := func(*terraform.State) error { 89 destroyCalled = true 90 return nil 91 } 92 93 mt := new(mockT) 94 Test(mt, TestCase{ 95 CheckDestroy: checkDestroyFn, 96 }) 97 98 if mt.failed() { 99 t.Fatal("test failed") 100 } 101 if destroyCalled { 102 t.Fatal("should not call check destroy if there is no steps") 103 } 104 } 105 106 func TestTest_noEnv(t *testing.T) { 107 // Unset the variable 108 if err := os.Setenv(TestEnvVar, ""); err != nil { 109 t.Fatalf("err: %s", err) 110 } 111 defer os.Setenv(TestEnvVar, "1") 112 113 mt := new(mockT) 114 Test(mt, TestCase{}) 115 116 if !mt.SkipCalled { 117 t.Fatal("skip not called") 118 } 119 } 120 121 func TestTest_preCheck(t *testing.T) { 122 called := false 123 124 mt := new(mockT) 125 Test(mt, TestCase{ 126 PreCheck: func() { called = true }, 127 }) 128 129 if !called { 130 t.Fatal("precheck should be called") 131 } 132 } 133 134 func TestTest_stepError(t *testing.T) { 135 mp := testProvider() 136 mp.ApplyReturn = &terraform.InstanceState{ 137 ID: "foo", 138 } 139 140 checkDestroy := false 141 142 checkDestroyFn := func(*terraform.State) error { 143 checkDestroy = true 144 return nil 145 } 146 147 checkStepFn := func(*terraform.State) error { 148 return fmt.Errorf("error") 149 } 150 151 mt := new(mockT) 152 Test(mt, TestCase{ 153 Providers: map[string]terraform.ResourceProvider{ 154 "test": mp, 155 }, 156 CheckDestroy: checkDestroyFn, 157 Steps: []TestStep{ 158 TestStep{ 159 Config: testConfigStr, 160 Check: checkStepFn, 161 }, 162 }, 163 }) 164 165 if !mt.failed() { 166 t.Fatal("test should've failed") 167 } 168 expected := "Step 0 error: Check failed: error" 169 if mt.failMessage() != expected { 170 t.Fatalf("Expected message: %s\n\ngot:\n\n%s", expected, mt.failMessage()) 171 } 172 173 if !checkDestroy { 174 t.Fatal("didn't call check for destroy") 175 } 176 } 177 178 func TestComposeTestCheckFunc(t *testing.T) { 179 cases := []struct { 180 F []TestCheckFunc 181 Result string 182 }{ 183 { 184 F: []TestCheckFunc{ 185 func(*terraform.State) error { return nil }, 186 }, 187 Result: "", 188 }, 189 190 { 191 F: []TestCheckFunc{ 192 func(*terraform.State) error { 193 return fmt.Errorf("error") 194 }, 195 func(*terraform.State) error { return nil }, 196 }, 197 Result: "error", 198 }, 199 200 { 201 F: []TestCheckFunc{ 202 func(*terraform.State) error { return nil }, 203 func(*terraform.State) error { 204 return fmt.Errorf("error") 205 }, 206 }, 207 Result: "error", 208 }, 209 210 { 211 F: []TestCheckFunc{ 212 func(*terraform.State) error { return nil }, 213 func(*terraform.State) error { return nil }, 214 }, 215 Result: "", 216 }, 217 } 218 219 for i, tc := range cases { 220 f := ComposeTestCheckFunc(tc.F...) 221 err := f(nil) 222 if err == nil { 223 err = fmt.Errorf("") 224 } 225 if tc.Result != err.Error() { 226 t.Fatalf("Case %d bad: %s", i, err) 227 } 228 } 229 } 230 231 // mockT implements TestT for testing 232 type mockT struct { 233 ErrorCalled bool 234 ErrorArgs []interface{} 235 FatalCalled bool 236 FatalArgs []interface{} 237 SkipCalled bool 238 SkipArgs []interface{} 239 240 f bool 241 } 242 243 func (t *mockT) Error(args ...interface{}) { 244 t.ErrorCalled = true 245 t.ErrorArgs = args 246 t.f = true 247 } 248 249 func (t *mockT) Fatal(args ...interface{}) { 250 t.FatalCalled = true 251 t.FatalArgs = args 252 t.f = true 253 } 254 255 func (t *mockT) Skip(args ...interface{}) { 256 t.SkipCalled = true 257 t.SkipArgs = args 258 t.f = true 259 } 260 261 func (t *mockT) failed() bool { 262 return t.f 263 } 264 265 func (t *mockT) failMessage() string { 266 if t.FatalCalled { 267 return t.FatalArgs[0].(string) 268 } else if t.ErrorCalled { 269 return t.ErrorArgs[0].(string) 270 } else if t.SkipCalled { 271 return t.SkipArgs[0].(string) 272 } 273 274 return "unknown" 275 } 276 277 func testProvider() *terraform.MockResourceProvider { 278 mp := new(terraform.MockResourceProvider) 279 mp.DiffReturn = &terraform.InstanceDiff{ 280 Attributes: map[string]*terraform.ResourceAttrDiff{ 281 "foo": &terraform.ResourceAttrDiff{ 282 New: "bar", 283 }, 284 }, 285 } 286 mp.ResourcesReturn = []terraform.ResourceType{ 287 terraform.ResourceType{Name: "test_instance"}, 288 } 289 290 return mp 291 } 292 293 const testConfigStr = ` 294 resource "test_instance" "foo" {} 295 `