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