github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/terraform/shadow_resource_provider_test.go (about) 1 package terraform 2 3 import ( 4 "fmt" 5 "reflect" 6 "testing" 7 "time" 8 ) 9 10 func TestShadowResourceProvider_impl(t *testing.T) { 11 var _ Shadow = new(shadowResourceProviderShadow) 12 } 13 14 func TestShadowResourceProvider_cachedValues(t *testing.T) { 15 mock := new(MockResourceProvider) 16 real, shadow := newShadowResourceProvider(mock) 17 18 // Resources 19 { 20 actual := shadow.Resources() 21 expected := real.Resources() 22 if !reflect.DeepEqual(actual, expected) { 23 t.Fatalf("bad:\n\n%#v\n\n%#v", actual, expected) 24 } 25 } 26 27 // DataSources 28 { 29 actual := shadow.DataSources() 30 expected := real.DataSources() 31 if !reflect.DeepEqual(actual, expected) { 32 t.Fatalf("bad:\n\n%#v\n\n%#v", actual, expected) 33 } 34 } 35 } 36 37 func TestShadowResourceProviderInput(t *testing.T) { 38 mock := new(MockResourceProvider) 39 real, shadow := newShadowResourceProvider(mock) 40 41 // Test values 42 ui := new(MockUIInput) 43 config := testResourceConfig(t, map[string]interface{}{ 44 "foo": "bar", 45 }) 46 returnConfig := testResourceConfig(t, map[string]interface{}{ 47 "bar": "baz", 48 }) 49 50 // Configure the mock 51 mock.InputReturnConfig = returnConfig 52 53 // Verify that it blocks until the real input is called 54 var actual *ResourceConfig 55 var err error 56 doneCh := make(chan struct{}) 57 go func() { 58 defer close(doneCh) 59 actual, err = shadow.Input(ui, config) 60 }() 61 62 select { 63 case <-doneCh: 64 t.Fatal("should block until finished") 65 case <-time.After(10 * time.Millisecond): 66 } 67 68 // Call the real input 69 realResult, realErr := real.Input(ui, config) 70 if !realResult.Equal(returnConfig) { 71 t.Fatalf("bad: %#v", realResult) 72 } 73 if realErr != nil { 74 t.Fatalf("bad: %s", realErr) 75 } 76 77 // The shadow should finish now 78 <-doneCh 79 80 // Verify the shadow returned the same values 81 if !actual.Equal(returnConfig) { 82 t.Fatalf("bad: %#v", actual) 83 } 84 if err != nil { 85 t.Fatalf("bad: %s", err) 86 } 87 88 // Verify we have no errors 89 if err := shadow.CloseShadow(); err != nil { 90 t.Fatalf("bad: %s", err) 91 } 92 } 93 94 func TestShadowResourceProviderInput_badInput(t *testing.T) { 95 mock := new(MockResourceProvider) 96 real, shadow := newShadowResourceProvider(mock) 97 98 // Test values 99 ui := new(MockUIInput) 100 config := testResourceConfig(t, map[string]interface{}{ 101 "foo": "bar", 102 }) 103 configBad := testResourceConfig(t, map[string]interface{}{ 104 "foo": "nope", 105 }) 106 107 // Call the real with one 108 real.Input(ui, config) 109 110 // Call the shadow with another 111 _, err := shadow.Input(ui, configBad) 112 if err != nil { 113 t.Fatalf("bad: %s", err) 114 } 115 116 // Verify we have an error 117 if err := shadow.CloseShadow(); err != nil { 118 t.Fatalf("bad: %s", err) 119 } 120 if err := shadow.ShadowError(); err == nil { 121 t.Fatal("should error") 122 } 123 } 124 125 func TestShadowResourceProviderValidate(t *testing.T) { 126 mock := new(MockResourceProvider) 127 real, shadow := newShadowResourceProvider(mock) 128 129 // Test values 130 config := testResourceConfig(t, map[string]interface{}{ 131 "foo": "bar", 132 }) 133 returnWarns := []string{"foo"} 134 returnErrs := []error{fmt.Errorf("bar")} 135 136 // Configure the mock 137 mock.ValidateReturnWarns = returnWarns 138 mock.ValidateReturnErrors = returnErrs 139 140 // Verify that it blocks until the real func is called 141 var warns []string 142 var errs []error 143 doneCh := make(chan struct{}) 144 go func() { 145 defer close(doneCh) 146 warns, errs = shadow.Validate(config) 147 }() 148 149 select { 150 case <-doneCh: 151 t.Fatal("should block until finished") 152 case <-time.After(10 * time.Millisecond): 153 } 154 155 // Call the real func 156 realWarns, realErrs := real.Validate(config) 157 if !reflect.DeepEqual(realWarns, returnWarns) { 158 t.Fatalf("bad: %#v", realWarns) 159 } 160 if !reflect.DeepEqual(realErrs, returnErrs) { 161 t.Fatalf("bad: %#v", realWarns) 162 } 163 164 // The shadow should finish now 165 <-doneCh 166 167 // Verify the shadow returned the same values 168 if !reflect.DeepEqual(warns, returnWarns) { 169 t.Fatalf("bad: %#v", warns) 170 } 171 if !reflect.DeepEqual(errs, returnErrs) { 172 t.Fatalf("bad: %#v", errs) 173 } 174 175 // Verify we have no errors 176 if err := shadow.CloseShadow(); err != nil { 177 t.Fatalf("bad: %s", err) 178 } 179 } 180 181 func TestShadowResourceProviderValidate_badInput(t *testing.T) { 182 mock := new(MockResourceProvider) 183 real, shadow := newShadowResourceProvider(mock) 184 185 // Test values 186 config := testResourceConfig(t, map[string]interface{}{ 187 "foo": "bar", 188 }) 189 configBad := testResourceConfig(t, map[string]interface{}{ 190 "foo": "nope", 191 }) 192 193 // Call the real with one 194 real.Validate(config) 195 196 // Call the shadow with another 197 shadow.Validate(configBad) 198 199 // Verify we have an error 200 if err := shadow.CloseShadow(); err != nil { 201 t.Fatalf("bad: %s", err) 202 } 203 if err := shadow.ShadowError(); err == nil { 204 t.Fatal("should error") 205 } 206 } 207 208 func TestShadowResourceProviderConfigure(t *testing.T) { 209 mock := new(MockResourceProvider) 210 real, shadow := newShadowResourceProvider(mock) 211 212 // Test values 213 config := testResourceConfig(t, map[string]interface{}{ 214 "foo": "bar", 215 }) 216 returnErr := fmt.Errorf("bar") 217 218 // Configure the mock 219 mock.ConfigureReturnError = returnErr 220 221 // Verify that it blocks until the real func is called 222 var err error 223 doneCh := make(chan struct{}) 224 go func() { 225 defer close(doneCh) 226 err = shadow.Configure(config) 227 }() 228 229 select { 230 case <-doneCh: 231 t.Fatal("should block until finished") 232 case <-time.After(10 * time.Millisecond): 233 } 234 235 // Call the real func 236 realErr := real.Configure(config) 237 if !reflect.DeepEqual(realErr, returnErr) { 238 t.Fatalf("bad: %#v", realErr) 239 } 240 241 // The shadow should finish now 242 <-doneCh 243 244 // Verify the shadow returned the same values 245 if !reflect.DeepEqual(err, returnErr) { 246 t.Fatalf("bad: %#v", err) 247 } 248 249 // Verify we have no errors 250 if err := shadow.CloseShadow(); err != nil { 251 t.Fatalf("bad: %s", err) 252 } 253 } 254 255 func TestShadowResourceProviderConfigure_badInput(t *testing.T) { 256 mock := new(MockResourceProvider) 257 real, shadow := newShadowResourceProvider(mock) 258 259 // Test values 260 config := testResourceConfig(t, map[string]interface{}{ 261 "foo": "bar", 262 }) 263 configBad := testResourceConfig(t, map[string]interface{}{ 264 "foo": "nope", 265 }) 266 267 // Call the real with one 268 real.Configure(config) 269 270 // Call the shadow with another 271 shadow.Configure(configBad) 272 273 // Verify we have an error 274 if err := shadow.CloseShadow(); err != nil { 275 t.Fatalf("bad: %s", err) 276 } 277 if err := shadow.ShadowError(); err == nil { 278 t.Fatal("should error") 279 } 280 } 281 282 func TestShadowResourceProviderApply(t *testing.T) { 283 mock := new(MockResourceProvider) 284 real, shadow := newShadowResourceProvider(mock) 285 286 // Test values 287 info := &InstanceInfo{Id: "foo"} 288 state := &InstanceState{ID: "foo"} 289 diff := &InstanceDiff{Destroy: true} 290 mockResult := &InstanceState{ID: "bar"} 291 292 // Configure the mock 293 mock.ApplyReturn = mockResult 294 295 // Verify that it blocks until the real func is called 296 var result *InstanceState 297 var err error 298 doneCh := make(chan struct{}) 299 go func() { 300 defer close(doneCh) 301 result, err = shadow.Apply(info, state, diff) 302 }() 303 304 select { 305 case <-doneCh: 306 t.Fatal("should block until finished") 307 case <-time.After(10 * time.Millisecond): 308 } 309 310 // Call the real func 311 realResult, realErr := real.Apply(info, state, diff) 312 if !realResult.Equal(mockResult) { 313 t.Fatalf("bad: %#v", realResult) 314 } 315 if realErr != nil { 316 t.Fatalf("bad: %#v", realErr) 317 } 318 319 // The shadow should finish now 320 <-doneCh 321 322 // Verify the shadow returned the same values 323 if !result.Equal(mockResult) { 324 t.Fatalf("bad: %#v", result) 325 } 326 if err != nil { 327 t.Fatalf("bad: %#v", err) 328 } 329 330 // Verify we have no errors 331 if err := shadow.CloseShadow(); err != nil { 332 t.Fatalf("bad: %s", err) 333 } 334 } 335 336 func TestShadowResourceProviderApply_modifyDiff(t *testing.T) { 337 mock := new(MockResourceProvider) 338 real, shadow := newShadowResourceProvider(mock) 339 340 // Test values 341 info := &InstanceInfo{Id: "foo"} 342 state := &InstanceState{ID: "foo"} 343 diff := &InstanceDiff{} 344 mockResult := &InstanceState{ID: "foo"} 345 346 // Configure the mock 347 mock.ApplyFn = func( 348 info *InstanceInfo, 349 s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 350 d.Destroy = true 351 return s, nil 352 } 353 354 // Call the real func 355 realResult, realErr := real.Apply(info, state.DeepCopy(), diff.DeepCopy()) 356 if !realResult.Equal(mockResult) { 357 t.Fatalf("bad: %#v", realResult) 358 } 359 if realErr != nil { 360 t.Fatalf("bad: %#v", realErr) 361 } 362 363 // Verify the shadow returned the same values 364 result, err := shadow.Apply(info, state.DeepCopy(), diff.DeepCopy()) 365 if !result.Equal(mockResult) { 366 t.Fatalf("bad: %#v", result) 367 } 368 if err != nil { 369 t.Fatalf("bad: %#v", err) 370 } 371 372 // Verify we have no errors 373 if err := shadow.CloseShadow(); err != nil { 374 t.Fatalf("bad: %s", err) 375 } 376 if err := shadow.ShadowError(); err != nil { 377 t.Fatalf("bad: %s", err) 378 } 379 } 380 381 func TestShadowResourceProviderApply_modifyState(t *testing.T) { 382 mock := new(MockResourceProvider) 383 real, shadow := newShadowResourceProvider(mock) 384 385 // Test values 386 info := &InstanceInfo{Id: "foo"} 387 state := &InstanceState{ID: ""} 388 diff := &InstanceDiff{} 389 mockResult := &InstanceState{ID: "foo"} 390 391 // Configure the mock 392 mock.ApplyFn = func( 393 info *InstanceInfo, 394 s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 395 s.ID = "foo" 396 return s, nil 397 } 398 399 // Call the real func 400 realResult, realErr := real.Apply(info, state.DeepCopy(), diff) 401 if !realResult.Equal(mockResult) { 402 t.Fatalf("bad: %#v", realResult) 403 } 404 if realErr != nil { 405 t.Fatalf("bad: %#v", realErr) 406 } 407 408 // Verify the shadow returned the same values 409 result, err := shadow.Apply(info, state.DeepCopy(), diff) 410 if !result.Equal(mockResult) { 411 t.Fatalf("bad: %#v", result) 412 } 413 if err != nil { 414 t.Fatalf("bad: %#v", err) 415 } 416 417 // Verify we have no errors 418 if err := shadow.CloseShadow(); err != nil { 419 t.Fatalf("bad: %s", err) 420 } 421 if err := shadow.ShadowError(); err != nil { 422 t.Fatalf("bad: %s", err) 423 } 424 } 425 426 func TestShadowResourceProviderDiff(t *testing.T) { 427 mock := new(MockResourceProvider) 428 real, shadow := newShadowResourceProvider(mock) 429 430 // Test values 431 info := &InstanceInfo{Id: "foo"} 432 state := &InstanceState{ID: "foo"} 433 desired := testResourceConfig(t, map[string]interface{}{"foo": "bar"}) 434 mockResult := &InstanceDiff{Destroy: true} 435 436 // Configure the mock 437 mock.DiffReturn = mockResult 438 439 // Verify that it blocks until the real func is called 440 var result *InstanceDiff 441 var err error 442 doneCh := make(chan struct{}) 443 go func() { 444 defer close(doneCh) 445 result, err = shadow.Diff(info, state, desired) 446 }() 447 448 select { 449 case <-doneCh: 450 t.Fatal("should block until finished") 451 case <-time.After(10 * time.Millisecond): 452 } 453 454 // Call the real func 455 realResult, realErr := real.Diff(info, state, desired) 456 if !reflect.DeepEqual(realResult, mockResult) { 457 t.Fatalf("bad: %#v", realResult) 458 } 459 if realErr != nil { 460 t.Fatalf("bad: %#v", realErr) 461 } 462 463 // The shadow should finish now 464 <-doneCh 465 466 // Verify the shadow returned the same values 467 if !reflect.DeepEqual(result, mockResult) { 468 t.Fatalf("bad: %#v", result) 469 } 470 if err != nil { 471 t.Fatalf("bad: %#v", err) 472 } 473 474 // Verify we have no errors 475 if err := shadow.CloseShadow(); err != nil { 476 t.Fatalf("bad: %s", err) 477 } 478 } 479 480 func TestShadowResourceProviderRefresh(t *testing.T) { 481 mock := new(MockResourceProvider) 482 real, shadow := newShadowResourceProvider(mock) 483 484 // Test values 485 info := &InstanceInfo{Id: "foo"} 486 state := &InstanceState{ID: "foo"} 487 mockResult := &InstanceState{ID: "bar"} 488 489 // Configure the mock 490 mock.RefreshReturn = mockResult 491 492 // Verify that it blocks until the real func is called 493 var result *InstanceState 494 var err error 495 doneCh := make(chan struct{}) 496 go func() { 497 defer close(doneCh) 498 result, err = shadow.Refresh(info, state) 499 }() 500 501 select { 502 case <-doneCh: 503 t.Fatal("should block until finished") 504 case <-time.After(10 * time.Millisecond): 505 } 506 507 // Call the real func 508 realResult, realErr := real.Refresh(info, state) 509 if !realResult.Equal(mockResult) { 510 t.Fatalf("bad: %#v", realResult) 511 } 512 if realErr != nil { 513 t.Fatalf("bad: %#v", realErr) 514 } 515 516 // The shadow should finish now 517 <-doneCh 518 519 // Verify the shadow returned the same values 520 if !result.Equal(mockResult) { 521 t.Fatalf("bad: %#v", result) 522 } 523 if err != nil { 524 t.Fatalf("bad: %#v", err) 525 } 526 527 // Verify we have no errors 528 if err := shadow.CloseShadow(); err != nil { 529 t.Fatalf("bad: %s", err) 530 } 531 }