github.com/ndarilek/terraform@v0.3.8-0.20150320140257-d3135c1b2bac/terraform/diff_test.go (about) 1 package terraform 2 3 import ( 4 "reflect" 5 "strings" 6 "testing" 7 ) 8 9 func TestDiffEmpty(t *testing.T) { 10 diff := new(Diff) 11 if !diff.Empty() { 12 t.Fatal("should be empty") 13 } 14 15 mod := diff.AddModule(rootModulePath) 16 mod.Resources["nodeA"] = &InstanceDiff{ 17 Attributes: map[string]*ResourceAttrDiff{ 18 "foo": &ResourceAttrDiff{ 19 Old: "foo", 20 New: "bar", 21 }, 22 }, 23 } 24 25 if diff.Empty() { 26 t.Fatal("should not be empty") 27 } 28 } 29 30 func TestModuleDiff_ChangeType(t *testing.T) { 31 cases := []struct { 32 Diff *ModuleDiff 33 Result DiffChangeType 34 }{ 35 { 36 &ModuleDiff{}, 37 DiffNone, 38 }, 39 { 40 &ModuleDiff{ 41 Resources: map[string]*InstanceDiff{ 42 "foo": &InstanceDiff{Destroy: true}, 43 }, 44 }, 45 DiffDestroy, 46 }, 47 { 48 &ModuleDiff{ 49 Resources: map[string]*InstanceDiff{ 50 "foo": &InstanceDiff{ 51 Attributes: map[string]*ResourceAttrDiff{ 52 "foo": &ResourceAttrDiff{ 53 Old: "", 54 New: "bar", 55 }, 56 }, 57 }, 58 }, 59 }, 60 DiffUpdate, 61 }, 62 { 63 &ModuleDiff{ 64 Resources: map[string]*InstanceDiff{ 65 "foo": &InstanceDiff{ 66 Attributes: map[string]*ResourceAttrDiff{ 67 "foo": &ResourceAttrDiff{ 68 Old: "", 69 New: "bar", 70 RequiresNew: true, 71 }, 72 }, 73 }, 74 }, 75 }, 76 DiffCreate, 77 }, 78 { 79 &ModuleDiff{ 80 Resources: map[string]*InstanceDiff{ 81 "foo": &InstanceDiff{ 82 Destroy: true, 83 Attributes: map[string]*ResourceAttrDiff{ 84 "foo": &ResourceAttrDiff{ 85 Old: "", 86 New: "bar", 87 RequiresNew: true, 88 }, 89 }, 90 }, 91 }, 92 }, 93 DiffUpdate, 94 }, 95 } 96 97 for i, tc := range cases { 98 actual := tc.Diff.ChangeType() 99 if actual != tc.Result { 100 t.Fatalf("%d: %#v", i, actual) 101 } 102 } 103 } 104 105 func TestModuleDiff_Empty(t *testing.T) { 106 diff := new(ModuleDiff) 107 if !diff.Empty() { 108 t.Fatal("should be empty") 109 } 110 111 diff.Resources = map[string]*InstanceDiff{ 112 "nodeA": &InstanceDiff{}, 113 } 114 115 if !diff.Empty() { 116 t.Fatal("should be empty") 117 } 118 119 diff.Resources["nodeA"].Attributes = map[string]*ResourceAttrDiff{ 120 "foo": &ResourceAttrDiff{ 121 Old: "foo", 122 New: "bar", 123 }, 124 } 125 126 if diff.Empty() { 127 t.Fatal("should not be empty") 128 } 129 130 diff.Resources["nodeA"].Attributes = nil 131 diff.Resources["nodeA"].Destroy = true 132 133 if diff.Empty() { 134 t.Fatal("should not be empty") 135 } 136 } 137 138 func TestModuleDiff_String(t *testing.T) { 139 diff := &ModuleDiff{ 140 Resources: map[string]*InstanceDiff{ 141 "nodeA": &InstanceDiff{ 142 Attributes: map[string]*ResourceAttrDiff{ 143 "foo": &ResourceAttrDiff{ 144 Old: "foo", 145 New: "bar", 146 }, 147 "bar": &ResourceAttrDiff{ 148 Old: "foo", 149 NewComputed: true, 150 }, 151 "longfoo": &ResourceAttrDiff{ 152 Old: "foo", 153 New: "bar", 154 RequiresNew: true, 155 }, 156 }, 157 }, 158 }, 159 } 160 161 actual := strings.TrimSpace(diff.String()) 162 expected := strings.TrimSpace(moduleDiffStrBasic) 163 if actual != expected { 164 t.Fatalf("bad:\n%s", actual) 165 } 166 } 167 168 func TestInstanceDiff_ChangeType(t *testing.T) { 169 cases := []struct { 170 Diff *InstanceDiff 171 Result DiffChangeType 172 }{ 173 { 174 &InstanceDiff{}, 175 DiffNone, 176 }, 177 { 178 &InstanceDiff{Destroy: true}, 179 DiffDestroy, 180 }, 181 { 182 &InstanceDiff{ 183 Attributes: map[string]*ResourceAttrDiff{ 184 "foo": &ResourceAttrDiff{ 185 Old: "", 186 New: "bar", 187 }, 188 }, 189 }, 190 DiffUpdate, 191 }, 192 { 193 &InstanceDiff{ 194 Attributes: map[string]*ResourceAttrDiff{ 195 "foo": &ResourceAttrDiff{ 196 Old: "", 197 New: "bar", 198 RequiresNew: true, 199 }, 200 }, 201 }, 202 DiffCreate, 203 }, 204 { 205 &InstanceDiff{ 206 Destroy: true, 207 Attributes: map[string]*ResourceAttrDiff{ 208 "foo": &ResourceAttrDiff{ 209 Old: "", 210 New: "bar", 211 RequiresNew: true, 212 }, 213 }, 214 }, 215 DiffDestroyCreate, 216 }, 217 { 218 &InstanceDiff{ 219 DestroyTainted: true, 220 Attributes: map[string]*ResourceAttrDiff{ 221 "foo": &ResourceAttrDiff{ 222 Old: "", 223 New: "bar", 224 RequiresNew: true, 225 }, 226 }, 227 }, 228 DiffDestroyCreate, 229 }, 230 } 231 232 for i, tc := range cases { 233 actual := tc.Diff.ChangeType() 234 if actual != tc.Result { 235 t.Fatalf("%d: %#v", i, actual) 236 } 237 } 238 } 239 240 func TestInstanceDiff_Empty(t *testing.T) { 241 var rd *InstanceDiff 242 243 if !rd.Empty() { 244 t.Fatal("should be empty") 245 } 246 247 rd = new(InstanceDiff) 248 249 if !rd.Empty() { 250 t.Fatal("should be empty") 251 } 252 253 rd = &InstanceDiff{Destroy: true} 254 255 if rd.Empty() { 256 t.Fatal("should not be empty") 257 } 258 259 rd = &InstanceDiff{ 260 Attributes: map[string]*ResourceAttrDiff{ 261 "foo": &ResourceAttrDiff{ 262 New: "bar", 263 }, 264 }, 265 } 266 267 if rd.Empty() { 268 t.Fatal("should not be empty") 269 } 270 } 271 272 func TestModuleDiff_Instances(t *testing.T) { 273 yesDiff := &InstanceDiff{Destroy: true} 274 noDiff := &InstanceDiff{Destroy: true, DestroyTainted: true} 275 276 cases := []struct { 277 Diff *ModuleDiff 278 Id string 279 Result []*InstanceDiff 280 }{ 281 { 282 &ModuleDiff{ 283 Resources: map[string]*InstanceDiff{ 284 "foo": yesDiff, 285 "bar": noDiff, 286 }, 287 }, 288 "foo", 289 []*InstanceDiff{ 290 yesDiff, 291 }, 292 }, 293 294 { 295 &ModuleDiff{ 296 Resources: map[string]*InstanceDiff{ 297 "foo": yesDiff, 298 "foo.0": yesDiff, 299 "bar": noDiff, 300 }, 301 }, 302 "foo", 303 []*InstanceDiff{ 304 yesDiff, 305 yesDiff, 306 }, 307 }, 308 309 { 310 &ModuleDiff{ 311 Resources: map[string]*InstanceDiff{ 312 "foo": yesDiff, 313 "foo.0": yesDiff, 314 "foo_bar": noDiff, 315 "bar": noDiff, 316 }, 317 }, 318 "foo", 319 []*InstanceDiff{ 320 yesDiff, 321 yesDiff, 322 }, 323 }, 324 } 325 326 for i, tc := range cases { 327 actual := tc.Diff.Instances(tc.Id) 328 if !reflect.DeepEqual(actual, tc.Result) { 329 t.Fatalf("%d: %#v", i, actual) 330 } 331 } 332 } 333 334 func TestInstanceDiff_RequiresNew(t *testing.T) { 335 rd := &InstanceDiff{ 336 Attributes: map[string]*ResourceAttrDiff{ 337 "foo": &ResourceAttrDiff{}, 338 }, 339 } 340 341 if rd.RequiresNew() { 342 t.Fatal("should not require new") 343 } 344 345 rd.Attributes["foo"].RequiresNew = true 346 347 if !rd.RequiresNew() { 348 t.Fatal("should require new") 349 } 350 } 351 352 func TestInstanceDiff_RequiresNew_nil(t *testing.T) { 353 var rd *InstanceDiff 354 355 if rd.RequiresNew() { 356 t.Fatal("should not require new") 357 } 358 } 359 360 func TestInstanceDiffSame(t *testing.T) { 361 cases := []struct { 362 One, Two *InstanceDiff 363 Same bool 364 }{ 365 { 366 &InstanceDiff{}, 367 &InstanceDiff{}, 368 true, 369 }, 370 371 { 372 nil, 373 nil, 374 true, 375 }, 376 377 { 378 &InstanceDiff{Destroy: false}, 379 &InstanceDiff{Destroy: true}, 380 false, 381 }, 382 383 { 384 &InstanceDiff{Destroy: true}, 385 &InstanceDiff{Destroy: true}, 386 true, 387 }, 388 389 { 390 &InstanceDiff{ 391 Attributes: map[string]*ResourceAttrDiff{ 392 "foo": &ResourceAttrDiff{}, 393 }, 394 }, 395 &InstanceDiff{ 396 Attributes: map[string]*ResourceAttrDiff{ 397 "foo": &ResourceAttrDiff{}, 398 }, 399 }, 400 true, 401 }, 402 403 { 404 &InstanceDiff{ 405 Attributes: map[string]*ResourceAttrDiff{ 406 "bar": &ResourceAttrDiff{}, 407 }, 408 }, 409 &InstanceDiff{ 410 Attributes: map[string]*ResourceAttrDiff{ 411 "foo": &ResourceAttrDiff{}, 412 }, 413 }, 414 false, 415 }, 416 417 // Extra attributes 418 { 419 &InstanceDiff{ 420 Attributes: map[string]*ResourceAttrDiff{ 421 "foo": &ResourceAttrDiff{}, 422 }, 423 }, 424 &InstanceDiff{ 425 Attributes: map[string]*ResourceAttrDiff{ 426 "foo": &ResourceAttrDiff{}, 427 "bar": &ResourceAttrDiff{}, 428 }, 429 }, 430 false, 431 }, 432 433 { 434 &InstanceDiff{ 435 Attributes: map[string]*ResourceAttrDiff{ 436 "foo": &ResourceAttrDiff{RequiresNew: true}, 437 }, 438 }, 439 &InstanceDiff{ 440 Attributes: map[string]*ResourceAttrDiff{ 441 "foo": &ResourceAttrDiff{RequiresNew: false}, 442 }, 443 }, 444 false, 445 }, 446 447 { 448 &InstanceDiff{ 449 Attributes: map[string]*ResourceAttrDiff{ 450 "foo.#": &ResourceAttrDiff{NewComputed: true}, 451 }, 452 }, 453 &InstanceDiff{ 454 Attributes: map[string]*ResourceAttrDiff{ 455 "foo.#": &ResourceAttrDiff{ 456 Old: "0", 457 New: "1", 458 }, 459 "foo.0": &ResourceAttrDiff{ 460 Old: "", 461 New: "12", 462 }, 463 }, 464 }, 465 true, 466 }, 467 468 { 469 &InstanceDiff{ 470 Attributes: map[string]*ResourceAttrDiff{ 471 "foo.#": &ResourceAttrDiff{ 472 Old: "0", 473 New: "1", 474 }, 475 "foo.~35964334.bar": &ResourceAttrDiff{ 476 Old: "", 477 New: "${var.foo}", 478 }, 479 }, 480 }, 481 &InstanceDiff{ 482 Attributes: map[string]*ResourceAttrDiff{ 483 "foo.#": &ResourceAttrDiff{ 484 Old: "0", 485 New: "1", 486 }, 487 "foo.87654323.bar": &ResourceAttrDiff{ 488 Old: "", 489 New: "12", 490 }, 491 }, 492 }, 493 true, 494 }, 495 496 { 497 &InstanceDiff{ 498 Attributes: map[string]*ResourceAttrDiff{ 499 "foo.#": &ResourceAttrDiff{ 500 Old: "0", 501 NewComputed: true, 502 }, 503 }, 504 }, 505 &InstanceDiff{ 506 Attributes: map[string]*ResourceAttrDiff{}, 507 }, 508 true, 509 }, 510 } 511 512 for i, tc := range cases { 513 actual := tc.One.Same(tc.Two) 514 if actual != tc.Same { 515 t.Fatalf("%d:\n\n%#v\n\n%#v", i, tc.One, tc.Two) 516 } 517 } 518 } 519 520 const moduleDiffStrBasic = ` 521 CREATE: nodeA 522 bar: "foo" => "<computed>" 523 foo: "foo" => "bar" 524 longfoo: "foo" => "bar" (forces new resource) 525 `