github.com/paybyphone/terraform@v0.9.5-0.20170613192930-9706042ddd51/config/module/tree_test.go (about) 1 package module 2 3 import ( 4 "fmt" 5 "os" 6 "reflect" 7 "strings" 8 "testing" 9 10 "github.com/hashicorp/go-getter" 11 "github.com/hashicorp/terraform/config" 12 "github.com/hashicorp/terraform/helper/copy" 13 ) 14 15 func TestTreeChild(t *testing.T) { 16 var nilTree *Tree 17 if nilTree.Child(nil) != nil { 18 t.Fatal("child should be nil") 19 } 20 21 storage := testStorage(t) 22 tree := NewTree("", testConfig(t, "child")) 23 if err := tree.Load(storage, GetModeGet); err != nil { 24 t.Fatalf("err: %s", err) 25 } 26 27 // Should be able to get the root child 28 if c := tree.Child([]string{}); c == nil { 29 t.Fatal("should not be nil") 30 } else if c.Name() != "root" { 31 t.Fatalf("bad: %#v", c.Name()) 32 } else if !reflect.DeepEqual(c.Path(), []string(nil)) { 33 t.Fatalf("bad: %#v", c.Path()) 34 } 35 36 // Should be able to get the root child 37 if c := tree.Child(nil); c == nil { 38 t.Fatal("should not be nil") 39 } else if c.Name() != "root" { 40 t.Fatalf("bad: %#v", c.Name()) 41 } else if !reflect.DeepEqual(c.Path(), []string(nil)) { 42 t.Fatalf("bad: %#v", c.Path()) 43 } 44 45 // Should be able to get the foo child 46 if c := tree.Child([]string{"foo"}); c == nil { 47 t.Fatal("should not be nil") 48 } else if c.Name() != "foo" { 49 t.Fatalf("bad: %#v", c.Name()) 50 } else if !reflect.DeepEqual(c.Path(), []string{"foo"}) { 51 t.Fatalf("bad: %#v", c.Path()) 52 } 53 54 // Should be able to get the nested child 55 if c := tree.Child([]string{"foo", "bar"}); c == nil { 56 t.Fatal("should not be nil") 57 } else if c.Name() != "bar" { 58 t.Fatalf("bad: %#v", c.Name()) 59 } else if !reflect.DeepEqual(c.Path(), []string{"foo", "bar"}) { 60 t.Fatalf("bad: %#v", c.Path()) 61 } 62 } 63 64 func TestTreeLoad(t *testing.T) { 65 storage := testStorage(t) 66 tree := NewTree("", testConfig(t, "basic")) 67 68 if tree.Loaded() { 69 t.Fatal("should not be loaded") 70 } 71 72 // This should error because we haven't gotten things yet 73 if err := tree.Load(storage, GetModeNone); err == nil { 74 t.Fatal("should error") 75 } 76 77 if tree.Loaded() { 78 t.Fatal("should not be loaded") 79 } 80 81 // This should get things 82 if err := tree.Load(storage, GetModeGet); err != nil { 83 t.Fatalf("err: %s", err) 84 } 85 86 if !tree.Loaded() { 87 t.Fatal("should be loaded") 88 } 89 90 // This should no longer error 91 if err := tree.Load(storage, GetModeNone); err != nil { 92 t.Fatalf("err: %s", err) 93 } 94 95 actual := strings.TrimSpace(tree.String()) 96 expected := strings.TrimSpace(treeLoadStr) 97 if actual != expected { 98 t.Fatalf("bad: \n\n%s", actual) 99 } 100 } 101 102 func TestTreeLoad_duplicate(t *testing.T) { 103 storage := testStorage(t) 104 tree := NewTree("", testConfig(t, "dup")) 105 106 if tree.Loaded() { 107 t.Fatal("should not be loaded") 108 } 109 110 // This should get things 111 if err := tree.Load(storage, GetModeGet); err == nil { 112 t.Fatalf("should error") 113 } 114 } 115 116 func TestTreeLoad_copyable(t *testing.T) { 117 dir := tempDir(t) 118 storage := &getter.FolderStorage{StorageDir: dir} 119 cfg := testConfig(t, "basic") 120 tree := NewTree("", cfg) 121 122 // This should get things 123 if err := tree.Load(storage, GetModeGet); err != nil { 124 t.Fatalf("err: %s", err) 125 } 126 127 if !tree.Loaded() { 128 t.Fatal("should be loaded") 129 } 130 131 // This should no longer error 132 if err := tree.Load(storage, GetModeNone); err != nil { 133 t.Fatalf("err: %s", err) 134 } 135 136 // Now we copy the directory, this COPIES symlink values, and 137 // doesn't create symlinks themselves. That is important. 138 dir2 := tempDir(t) 139 os.RemoveAll(dir2) 140 defer os.RemoveAll(dir2) 141 if err := copy.CopyDir(dir, dir2); err != nil { 142 t.Fatalf("err: %s", err) 143 } 144 145 // Now copy the configuration 146 cfgDir := tempDir(t) 147 os.RemoveAll(cfgDir) 148 defer os.RemoveAll(cfgDir) 149 if err := copy.CopyDir(cfg.Dir, cfgDir); err != nil { 150 t.Fatalf("err: %s", err) 151 } 152 153 { 154 cfg, err := config.LoadDir(cfgDir) 155 if err != nil { 156 t.Fatalf("err: %s", err) 157 } 158 159 tree := NewTree("", cfg) 160 storage := &getter.FolderStorage{StorageDir: dir2} 161 162 // This should not error since we already got it! 163 if err := tree.Load(storage, GetModeNone); err != nil { 164 t.Fatalf("err: %s", err) 165 } 166 167 if !tree.Loaded() { 168 t.Fatal("should be loaded") 169 } 170 } 171 } 172 173 func TestTreeLoad_parentRef(t *testing.T) { 174 storage := testStorage(t) 175 tree := NewTree("", testConfig(t, "basic-parent")) 176 177 if tree.Loaded() { 178 t.Fatal("should not be loaded") 179 } 180 181 // This should error because we haven't gotten things yet 182 if err := tree.Load(storage, GetModeNone); err == nil { 183 t.Fatal("should error") 184 } 185 186 if tree.Loaded() { 187 t.Fatal("should not be loaded") 188 } 189 190 // This should get things 191 if err := tree.Load(storage, GetModeGet); err != nil { 192 t.Fatalf("err: %s", err) 193 } 194 195 if !tree.Loaded() { 196 t.Fatal("should be loaded") 197 } 198 199 // This should no longer error 200 if err := tree.Load(storage, GetModeNone); err != nil { 201 t.Fatalf("err: %s", err) 202 } 203 204 actual := strings.TrimSpace(tree.String()) 205 expected := strings.TrimSpace(treeLoadParentStr) 206 if actual != expected { 207 t.Fatalf("bad: \n\n%s", actual) 208 } 209 } 210 211 func TestTreeLoad_subdir(t *testing.T) { 212 storage := testStorage(t) 213 tree := NewTree("", testConfig(t, "basic-subdir")) 214 215 if tree.Loaded() { 216 t.Fatal("should not be loaded") 217 } 218 219 // This should error because we haven't gotten things yet 220 if err := tree.Load(storage, GetModeNone); err == nil { 221 t.Fatal("should error") 222 } 223 224 if tree.Loaded() { 225 t.Fatal("should not be loaded") 226 } 227 228 // This should get things 229 if err := tree.Load(storage, GetModeGet); err != nil { 230 t.Fatalf("err: %s", err) 231 } 232 233 if !tree.Loaded() { 234 t.Fatal("should be loaded") 235 } 236 237 // This should no longer error 238 if err := tree.Load(storage, GetModeNone); err != nil { 239 t.Fatalf("err: %s", err) 240 } 241 242 actual := strings.TrimSpace(tree.String()) 243 expected := strings.TrimSpace(treeLoadSubdirStr) 244 if actual != expected { 245 t.Fatalf("bad: \n\n%s", actual) 246 } 247 } 248 249 func TestTreeModules(t *testing.T) { 250 tree := NewTree("", testConfig(t, "basic")) 251 actual := tree.Modules() 252 253 expected := []*Module{ 254 &Module{Name: "foo", Source: "./foo"}, 255 } 256 257 if !reflect.DeepEqual(actual, expected) { 258 t.Fatalf("bad: %#v", actual) 259 } 260 } 261 262 func TestTreeName(t *testing.T) { 263 tree := NewTree("", testConfig(t, "basic")) 264 actual := tree.Name() 265 266 if actual != RootName { 267 t.Fatalf("bad: %#v", actual) 268 } 269 } 270 271 // This is a table-driven test for tree validation. This is the preferred 272 // way to test Validate. Non table-driven tests exist historically but 273 // that style shouldn't be done anymore. 274 func TestTreeValidate_table(t *testing.T) { 275 cases := []struct { 276 Name string 277 Fixture string 278 Err string 279 }{ 280 { 281 "provider alias in child", 282 "validate-alias-good", 283 "", 284 }, 285 286 { 287 "undefined provider alias in child", 288 "validate-alias-bad", 289 "alias must be defined", 290 }, 291 292 { 293 "root module named root", 294 "validate-module-root", 295 "cannot contain module", 296 }, 297 298 { 299 "grandchild module named root", 300 "validate-module-root-grandchild", 301 "", 302 }, 303 } 304 305 for i, tc := range cases { 306 t.Run(fmt.Sprintf("%d-%s", i, tc.Name), func(t *testing.T) { 307 tree := NewTree("", testConfig(t, tc.Fixture)) 308 if err := tree.Load(testStorage(t), GetModeGet); err != nil { 309 t.Fatalf("err: %s", err) 310 } 311 312 err := tree.Validate() 313 if (err != nil) != (tc.Err != "") { 314 t.Fatalf("err: %s", err) 315 } 316 if err == nil { 317 return 318 } 319 if !strings.Contains(err.Error(), tc.Err) { 320 t.Fatalf("err should contain %q: %s", tc.Err, err) 321 } 322 }) 323 } 324 } 325 326 func TestTreeValidate_badChild(t *testing.T) { 327 tree := NewTree("", testConfig(t, "validate-child-bad")) 328 329 if err := tree.Load(testStorage(t), GetModeGet); err != nil { 330 t.Fatalf("err: %s", err) 331 } 332 333 if err := tree.Validate(); err == nil { 334 t.Fatal("should error") 335 } 336 } 337 338 func TestTreeValidate_badChildOutput(t *testing.T) { 339 tree := NewTree("", testConfig(t, "validate-bad-output")) 340 341 if err := tree.Load(testStorage(t), GetModeGet); err != nil { 342 t.Fatalf("err: %s", err) 343 } 344 345 if err := tree.Validate(); err == nil { 346 t.Fatal("should error") 347 } 348 } 349 350 func TestTreeValidate_badChildOutputToModule(t *testing.T) { 351 tree := NewTree("", testConfig(t, "validate-bad-output-to-module")) 352 353 if err := tree.Load(testStorage(t), GetModeGet); err != nil { 354 t.Fatalf("err: %s", err) 355 } 356 357 if err := tree.Validate(); err == nil { 358 t.Fatal("should error") 359 } 360 } 361 362 func TestTreeValidate_badChildVar(t *testing.T) { 363 tree := NewTree("", testConfig(t, "validate-bad-var")) 364 365 if err := tree.Load(testStorage(t), GetModeGet); err != nil { 366 t.Fatalf("err: %s", err) 367 } 368 369 if err := tree.Validate(); err == nil { 370 t.Fatal("should error") 371 } 372 } 373 374 func TestTreeValidate_badRoot(t *testing.T) { 375 tree := NewTree("", testConfig(t, "validate-root-bad")) 376 377 if err := tree.Load(testStorage(t), GetModeGet); err != nil { 378 t.Fatalf("err: %s", err) 379 } 380 381 if err := tree.Validate(); err == nil { 382 t.Fatal("should error") 383 } 384 } 385 386 func TestTreeValidate_good(t *testing.T) { 387 tree := NewTree("", testConfig(t, "validate-child-good")) 388 389 if err := tree.Load(testStorage(t), GetModeGet); err != nil { 390 t.Fatalf("err: %s", err) 391 } 392 393 if err := tree.Validate(); err != nil { 394 t.Fatalf("err: %s", err) 395 } 396 } 397 398 func TestTreeValidate_notLoaded(t *testing.T) { 399 tree := NewTree("", testConfig(t, "basic")) 400 401 if err := tree.Validate(); err == nil { 402 t.Fatal("should error") 403 } 404 } 405 406 func TestTreeValidate_requiredChildVar(t *testing.T) { 407 tree := NewTree("", testConfig(t, "validate-required-var")) 408 409 if err := tree.Load(testStorage(t), GetModeGet); err != nil { 410 t.Fatalf("err: %s", err) 411 } 412 413 err := tree.Validate() 414 if err == nil { 415 t.Fatal("should error") 416 } 417 418 // ensure both variables are mentioned in the output 419 errMsg := err.Error() 420 for _, v := range []string{"feature", "memory"} { 421 if !strings.Contains(errMsg, v) { 422 t.Fatalf("no mention of missing variable %q", v) 423 } 424 } 425 } 426 427 func TestTreeValidate_unknownModule(t *testing.T) { 428 tree := NewTree("", testConfig(t, "validate-module-unknown")) 429 430 if err := tree.Load(testStorage(t), GetModeNone); err != nil { 431 t.Fatalf("err: %s", err) 432 } 433 434 if err := tree.Validate(); err == nil { 435 t.Fatal("should error") 436 } 437 } 438 439 const treeLoadStr = ` 440 root 441 foo (path: foo) 442 ` 443 444 const treeLoadParentStr = ` 445 root 446 a (path: a) 447 b (path: a, b) 448 ` 449 const treeLoadSubdirStr = ` 450 root 451 foo (path: foo) 452 bar (path: foo, bar) 453 `