github.com/turtlemonvh/terraform@v0.6.9-0.20151204001754-8e40b6b855e8/terraform/context_refresh_test.go (about) 1 package terraform 2 3 import ( 4 "reflect" 5 "sort" 6 "strings" 7 "sync" 8 "testing" 9 ) 10 11 func TestContext2Refresh(t *testing.T) { 12 p := testProvider("aws") 13 m := testModule(t, "refresh-basic") 14 ctx := testContext2(t, &ContextOpts{ 15 Module: m, 16 Providers: map[string]ResourceProviderFactory{ 17 "aws": testProviderFuncFixed(p), 18 }, 19 State: &State{ 20 Modules: []*ModuleState{ 21 &ModuleState{ 22 Path: rootModulePath, 23 Resources: map[string]*ResourceState{ 24 "aws_instance.web": &ResourceState{ 25 Type: "aws_instance", 26 Primary: &InstanceState{ 27 ID: "foo", 28 }, 29 }, 30 }, 31 }, 32 }, 33 }, 34 }) 35 36 p.RefreshFn = nil 37 p.RefreshReturn = &InstanceState{ 38 ID: "foo", 39 } 40 41 s, err := ctx.Refresh() 42 mod := s.RootModule() 43 if err != nil { 44 t.Fatalf("err: %s", err) 45 } 46 if !p.RefreshCalled { 47 t.Fatal("refresh should be called") 48 } 49 if p.RefreshState.ID != "foo" { 50 t.Fatalf("bad: %#v", p.RefreshState) 51 } 52 if !reflect.DeepEqual(mod.Resources["aws_instance.web"].Primary, p.RefreshReturn) { 53 t.Fatalf("bad: %#v %#v", mod.Resources["aws_instance.web"], p.RefreshReturn) 54 } 55 56 for _, r := range mod.Resources { 57 if r.Type == "" { 58 t.Fatalf("no type: %#v", r) 59 } 60 } 61 } 62 63 func TestContext2Refresh_targeted(t *testing.T) { 64 p := testProvider("aws") 65 m := testModule(t, "refresh-targeted") 66 ctx := testContext2(t, &ContextOpts{ 67 Module: m, 68 Providers: map[string]ResourceProviderFactory{ 69 "aws": testProviderFuncFixed(p), 70 }, 71 State: &State{ 72 Modules: []*ModuleState{ 73 &ModuleState{ 74 Path: rootModulePath, 75 Resources: map[string]*ResourceState{ 76 "aws_vpc.metoo": resourceState("aws_vpc", "vpc-abc123"), 77 "aws_instance.notme": resourceState("aws_instance", "i-bcd345"), 78 "aws_instance.me": resourceState("aws_instance", "i-abc123"), 79 "aws_elb.meneither": resourceState("aws_elb", "lb-abc123"), 80 }, 81 }, 82 }, 83 }, 84 Targets: []string{"aws_instance.me"}, 85 }) 86 87 refreshedResources := make([]string, 0, 2) 88 p.RefreshFn = func(i *InstanceInfo, is *InstanceState) (*InstanceState, error) { 89 refreshedResources = append(refreshedResources, i.Id) 90 return is, nil 91 } 92 93 _, err := ctx.Refresh() 94 if err != nil { 95 t.Fatalf("err: %s", err) 96 } 97 98 expected := []string{"aws_vpc.metoo", "aws_instance.me"} 99 if !reflect.DeepEqual(refreshedResources, expected) { 100 t.Fatalf("expected: %#v, got: %#v", expected, refreshedResources) 101 } 102 } 103 104 func TestContext2Refresh_targetedCount(t *testing.T) { 105 p := testProvider("aws") 106 m := testModule(t, "refresh-targeted-count") 107 ctx := testContext2(t, &ContextOpts{ 108 Module: m, 109 Providers: map[string]ResourceProviderFactory{ 110 "aws": testProviderFuncFixed(p), 111 }, 112 State: &State{ 113 Modules: []*ModuleState{ 114 &ModuleState{ 115 Path: rootModulePath, 116 Resources: map[string]*ResourceState{ 117 "aws_vpc.metoo": resourceState("aws_vpc", "vpc-abc123"), 118 "aws_instance.notme": resourceState("aws_instance", "i-bcd345"), 119 "aws_instance.me.0": resourceState("aws_instance", "i-abc123"), 120 "aws_instance.me.1": resourceState("aws_instance", "i-cde567"), 121 "aws_instance.me.2": resourceState("aws_instance", "i-cde789"), 122 "aws_elb.meneither": resourceState("aws_elb", "lb-abc123"), 123 }, 124 }, 125 }, 126 }, 127 Targets: []string{"aws_instance.me"}, 128 }) 129 130 refreshedResources := make([]string, 0, 2) 131 p.RefreshFn = func(i *InstanceInfo, is *InstanceState) (*InstanceState, error) { 132 refreshedResources = append(refreshedResources, i.Id) 133 return is, nil 134 } 135 136 _, err := ctx.Refresh() 137 if err != nil { 138 t.Fatalf("err: %s", err) 139 } 140 141 // Target didn't specify index, so we should get all our instances 142 expected := []string{ 143 "aws_vpc.metoo", 144 "aws_instance.me.0", 145 "aws_instance.me.1", 146 "aws_instance.me.2", 147 } 148 sort.Strings(expected) 149 sort.Strings(refreshedResources) 150 if !reflect.DeepEqual(refreshedResources, expected) { 151 t.Fatalf("expected: %#v, got: %#v", expected, refreshedResources) 152 } 153 } 154 155 func TestContext2Refresh_targetedCountIndex(t *testing.T) { 156 p := testProvider("aws") 157 m := testModule(t, "refresh-targeted-count") 158 ctx := testContext2(t, &ContextOpts{ 159 Module: m, 160 Providers: map[string]ResourceProviderFactory{ 161 "aws": testProviderFuncFixed(p), 162 }, 163 State: &State{ 164 Modules: []*ModuleState{ 165 &ModuleState{ 166 Path: rootModulePath, 167 Resources: map[string]*ResourceState{ 168 "aws_vpc.metoo": resourceState("aws_vpc", "vpc-abc123"), 169 "aws_instance.notme": resourceState("aws_instance", "i-bcd345"), 170 "aws_instance.me.0": resourceState("aws_instance", "i-abc123"), 171 "aws_instance.me.1": resourceState("aws_instance", "i-cde567"), 172 "aws_instance.me.2": resourceState("aws_instance", "i-cde789"), 173 "aws_elb.meneither": resourceState("aws_elb", "lb-abc123"), 174 }, 175 }, 176 }, 177 }, 178 Targets: []string{"aws_instance.me[0]"}, 179 }) 180 181 refreshedResources := make([]string, 0, 2) 182 p.RefreshFn = func(i *InstanceInfo, is *InstanceState) (*InstanceState, error) { 183 refreshedResources = append(refreshedResources, i.Id) 184 return is, nil 185 } 186 187 _, err := ctx.Refresh() 188 if err != nil { 189 t.Fatalf("err: %s", err) 190 } 191 192 expected := []string{"aws_vpc.metoo", "aws_instance.me.0"} 193 if !reflect.DeepEqual(refreshedResources, expected) { 194 t.Fatalf("expected: %#v, got: %#v", expected, refreshedResources) 195 } 196 } 197 198 func TestContext2Refresh_moduleComputedVar(t *testing.T) { 199 p := testProvider("aws") 200 m := testModule(t, "refresh-module-computed-var") 201 ctx := testContext2(t, &ContextOpts{ 202 Module: m, 203 Providers: map[string]ResourceProviderFactory{ 204 "aws": testProviderFuncFixed(p), 205 }, 206 }) 207 208 // This was failing (see GH-2188) at some point, so this test just 209 // verifies that the failure goes away. 210 if _, err := ctx.Refresh(); err != nil { 211 t.Fatalf("err: %s", err) 212 } 213 } 214 215 func TestContext2Refresh_delete(t *testing.T) { 216 p := testProvider("aws") 217 m := testModule(t, "refresh-basic") 218 ctx := testContext2(t, &ContextOpts{ 219 Module: m, 220 Providers: map[string]ResourceProviderFactory{ 221 "aws": testProviderFuncFixed(p), 222 }, 223 State: &State{ 224 Modules: []*ModuleState{ 225 &ModuleState{ 226 Path: rootModulePath, 227 Resources: map[string]*ResourceState{ 228 "aws_instance.web": &ResourceState{ 229 Type: "aws_instance", 230 Primary: &InstanceState{ 231 ID: "foo", 232 }, 233 }, 234 }, 235 }, 236 }, 237 }, 238 }) 239 240 p.RefreshFn = nil 241 p.RefreshReturn = nil 242 243 s, err := ctx.Refresh() 244 if err != nil { 245 t.Fatalf("err: %s", err) 246 } 247 248 mod := s.RootModule() 249 if len(mod.Resources) > 0 { 250 t.Fatal("resources should be empty") 251 } 252 } 253 254 func TestContext2Refresh_ignoreUncreated(t *testing.T) { 255 p := testProvider("aws") 256 m := testModule(t, "refresh-basic") 257 ctx := testContext2(t, &ContextOpts{ 258 Module: m, 259 Providers: map[string]ResourceProviderFactory{ 260 "aws": testProviderFuncFixed(p), 261 }, 262 State: nil, 263 }) 264 265 p.RefreshFn = nil 266 p.RefreshReturn = &InstanceState{ 267 ID: "foo", 268 } 269 270 _, err := ctx.Refresh() 271 if err != nil { 272 t.Fatalf("err: %s", err) 273 } 274 if p.RefreshCalled { 275 t.Fatal("refresh should not be called") 276 } 277 } 278 279 func TestContext2Refresh_hook(t *testing.T) { 280 h := new(MockHook) 281 p := testProvider("aws") 282 m := testModule(t, "refresh-basic") 283 ctx := testContext2(t, &ContextOpts{ 284 Module: m, 285 Hooks: []Hook{h}, 286 Providers: map[string]ResourceProviderFactory{ 287 "aws": testProviderFuncFixed(p), 288 }, 289 State: &State{ 290 Modules: []*ModuleState{ 291 &ModuleState{ 292 Path: rootModulePath, 293 Resources: map[string]*ResourceState{ 294 "aws_instance.web": &ResourceState{ 295 Type: "aws_instance", 296 Primary: &InstanceState{ 297 ID: "foo", 298 }, 299 }, 300 }, 301 }, 302 }, 303 }, 304 }) 305 306 if _, err := ctx.Refresh(); err != nil { 307 t.Fatalf("err: %s", err) 308 } 309 if !h.PreRefreshCalled { 310 t.Fatal("should be called") 311 } 312 if !h.PostRefreshCalled { 313 t.Fatal("should be called") 314 } 315 } 316 317 func TestContext2Refresh_modules(t *testing.T) { 318 p := testProvider("aws") 319 m := testModule(t, "refresh-modules") 320 state := &State{ 321 Modules: []*ModuleState{ 322 &ModuleState{ 323 Path: rootModulePath, 324 Resources: map[string]*ResourceState{ 325 "aws_instance.web": &ResourceState{ 326 Type: "aws_instance", 327 Tainted: []*InstanceState{ 328 &InstanceState{ 329 ID: "bar", 330 }, 331 }, 332 }, 333 }, 334 }, 335 336 &ModuleState{ 337 Path: []string{"root", "child"}, 338 Resources: map[string]*ResourceState{ 339 "aws_instance.web": &ResourceState{ 340 Type: "aws_instance", 341 Primary: &InstanceState{ 342 ID: "baz", 343 }, 344 }, 345 }, 346 }, 347 }, 348 } 349 ctx := testContext2(t, &ContextOpts{ 350 Module: m, 351 Providers: map[string]ResourceProviderFactory{ 352 "aws": testProviderFuncFixed(p), 353 }, 354 State: state, 355 }) 356 357 p.RefreshFn = func(info *InstanceInfo, s *InstanceState) (*InstanceState, error) { 358 if s.ID != "baz" { 359 return s, nil 360 } 361 362 s.ID = "new" 363 return s, nil 364 } 365 366 s, err := ctx.Refresh() 367 if err != nil { 368 t.Fatalf("err: %s", err) 369 } 370 371 actual := strings.TrimSpace(s.String()) 372 expected := strings.TrimSpace(testContextRefreshModuleStr) 373 if actual != expected { 374 t.Fatalf("bad:\n\n%s\n\n%s", actual, expected) 375 } 376 } 377 378 func TestContext2Refresh_moduleInputComputedOutput(t *testing.T) { 379 m := testModule(t, "refresh-module-input-computed-output") 380 p := testProvider("aws") 381 p.DiffFn = testDiffFn 382 ctx := testContext2(t, &ContextOpts{ 383 Module: m, 384 Providers: map[string]ResourceProviderFactory{ 385 "aws": testProviderFuncFixed(p), 386 }, 387 }) 388 389 if _, err := ctx.Refresh(); err != nil { 390 t.Fatalf("err: %s", err) 391 } 392 } 393 394 func TestContext2Refresh_moduleVarModule(t *testing.T) { 395 m := testModule(t, "refresh-module-var-module") 396 p := testProvider("aws") 397 p.DiffFn = testDiffFn 398 ctx := testContext2(t, &ContextOpts{ 399 Module: m, 400 Providers: map[string]ResourceProviderFactory{ 401 "aws": testProviderFuncFixed(p), 402 }, 403 }) 404 405 if _, err := ctx.Refresh(); err != nil { 406 t.Fatalf("err: %s", err) 407 } 408 } 409 410 // GH-70 411 func TestContext2Refresh_noState(t *testing.T) { 412 p := testProvider("aws") 413 m := testModule(t, "refresh-no-state") 414 ctx := testContext2(t, &ContextOpts{ 415 Module: m, 416 Providers: map[string]ResourceProviderFactory{ 417 "aws": testProviderFuncFixed(p), 418 }, 419 }) 420 421 p.RefreshFn = nil 422 p.RefreshReturn = &InstanceState{ 423 ID: "foo", 424 } 425 426 if _, err := ctx.Refresh(); err != nil { 427 t.Fatalf("err: %s", err) 428 } 429 } 430 431 func TestContext2Refresh_output(t *testing.T) { 432 p := testProvider("aws") 433 m := testModule(t, "refresh-output") 434 ctx := testContext2(t, &ContextOpts{ 435 Module: m, 436 Providers: map[string]ResourceProviderFactory{ 437 "aws": testProviderFuncFixed(p), 438 }, 439 State: &State{ 440 Modules: []*ModuleState{ 441 &ModuleState{ 442 Path: rootModulePath, 443 Resources: map[string]*ResourceState{ 444 "aws_instance.web": &ResourceState{ 445 Type: "aws_instance", 446 Primary: &InstanceState{ 447 ID: "foo", 448 Attributes: map[string]string{ 449 "foo": "bar", 450 }, 451 }, 452 }, 453 }, 454 455 Outputs: map[string]string{ 456 "foo": "foo", 457 }, 458 }, 459 }, 460 }, 461 }) 462 463 p.RefreshFn = func(info *InstanceInfo, s *InstanceState) (*InstanceState, error) { 464 return s, nil 465 } 466 467 s, err := ctx.Refresh() 468 if err != nil { 469 t.Fatalf("err: %s", err) 470 } 471 472 actual := strings.TrimSpace(s.String()) 473 expected := strings.TrimSpace(testContextRefreshOutputStr) 474 if actual != expected { 475 t.Fatalf("bad:\n\n%s\n\n%s", actual, expected) 476 } 477 } 478 479 func TestContext2Refresh_outputPartial(t *testing.T) { 480 p := testProvider("aws") 481 m := testModule(t, "refresh-output-partial") 482 ctx := testContext2(t, &ContextOpts{ 483 Module: m, 484 Providers: map[string]ResourceProviderFactory{ 485 "aws": testProviderFuncFixed(p), 486 }, 487 State: &State{ 488 Modules: []*ModuleState{ 489 &ModuleState{ 490 Path: rootModulePath, 491 Resources: map[string]*ResourceState{ 492 "aws_instance.foo": &ResourceState{ 493 Type: "aws_instance", 494 Primary: &InstanceState{ 495 ID: "foo", 496 }, 497 }, 498 }, 499 }, 500 }, 501 }, 502 }) 503 504 p.RefreshFn = nil 505 p.RefreshReturn = nil 506 507 s, err := ctx.Refresh() 508 if err != nil { 509 t.Fatalf("err: %s", err) 510 } 511 512 actual := strings.TrimSpace(s.String()) 513 expected := strings.TrimSpace(testContextRefreshOutputPartialStr) 514 if actual != expected { 515 t.Fatalf("bad:\n\n%s\n\n%s", actual, expected) 516 } 517 } 518 519 func TestContext2Refresh_state(t *testing.T) { 520 p := testProvider("aws") 521 m := testModule(t, "refresh-basic") 522 state := &State{ 523 Modules: []*ModuleState{ 524 &ModuleState{ 525 Path: rootModulePath, 526 Resources: map[string]*ResourceState{ 527 "aws_instance.web": &ResourceState{ 528 Primary: &InstanceState{ 529 ID: "bar", 530 }, 531 }, 532 }, 533 }, 534 }, 535 } 536 ctx := testContext2(t, &ContextOpts{ 537 Module: m, 538 Providers: map[string]ResourceProviderFactory{ 539 "aws": testProviderFuncFixed(p), 540 }, 541 State: state, 542 }) 543 544 p.RefreshFn = nil 545 p.RefreshReturn = &InstanceState{ 546 ID: "foo", 547 } 548 549 s, err := ctx.Refresh() 550 if err != nil { 551 t.Fatalf("err: %s", err) 552 } 553 originalMod := state.RootModule() 554 mod := s.RootModule() 555 if !p.RefreshCalled { 556 t.Fatal("refresh should be called") 557 } 558 if !reflect.DeepEqual(p.RefreshState, originalMod.Resources["aws_instance.web"].Primary) { 559 t.Fatalf( 560 "bad:\n\n%#v\n\n%#v", 561 p.RefreshState, 562 originalMod.Resources["aws_instance.web"].Primary) 563 } 564 if !reflect.DeepEqual(mod.Resources["aws_instance.web"].Primary, p.RefreshReturn) { 565 t.Fatalf("bad: %#v", mod.Resources) 566 } 567 } 568 569 func TestContext2Refresh_tainted(t *testing.T) { 570 p := testProvider("aws") 571 m := testModule(t, "refresh-basic") 572 state := &State{ 573 Modules: []*ModuleState{ 574 &ModuleState{ 575 Path: rootModulePath, 576 Resources: map[string]*ResourceState{ 577 "aws_instance.web": &ResourceState{ 578 Type: "aws_instance", 579 Tainted: []*InstanceState{ 580 &InstanceState{ 581 ID: "bar", 582 }, 583 }, 584 }, 585 }, 586 }, 587 }, 588 } 589 ctx := testContext2(t, &ContextOpts{ 590 Module: m, 591 Providers: map[string]ResourceProviderFactory{ 592 "aws": testProviderFuncFixed(p), 593 }, 594 State: state, 595 }) 596 597 p.RefreshFn = nil 598 p.RefreshReturn = &InstanceState{ 599 ID: "foo", 600 } 601 602 s, err := ctx.Refresh() 603 if err != nil { 604 t.Fatalf("err: %s", err) 605 } 606 if !p.RefreshCalled { 607 t.Fatal("refresh should be called") 608 } 609 610 actual := strings.TrimSpace(s.String()) 611 expected := strings.TrimSpace(testContextRefreshTaintedStr) 612 if actual != expected { 613 t.Fatalf("bad:\n\n%s\n\n%s", actual, expected) 614 } 615 } 616 617 // Doing a Refresh (or any operation really, but Refresh usually 618 // happens first) with a config with an unknown provider should result in 619 // an error. The key bug this found was that this wasn't happening if 620 // Providers was _empty_. 621 func TestContext2Refresh_unknownProvider(t *testing.T) { 622 m := testModule(t, "refresh-unknown-provider") 623 p := testProvider("aws") 624 p.ApplyFn = testApplyFn 625 p.DiffFn = testDiffFn 626 ctx := testContext2(t, &ContextOpts{ 627 Module: m, 628 Providers: map[string]ResourceProviderFactory{}, 629 }) 630 631 if _, err := ctx.Refresh(); err == nil { 632 t.Fatal("should error") 633 } 634 } 635 636 func TestContext2Refresh_vars(t *testing.T) { 637 p := testProvider("aws") 638 m := testModule(t, "refresh-vars") 639 ctx := testContext2(t, &ContextOpts{ 640 Module: m, 641 Providers: map[string]ResourceProviderFactory{ 642 "aws": testProviderFuncFixed(p), 643 }, 644 State: &State{ 645 646 Modules: []*ModuleState{ 647 &ModuleState{ 648 Path: rootModulePath, 649 Resources: map[string]*ResourceState{ 650 "aws_instance.web": &ResourceState{ 651 Type: "aws_instance", 652 Primary: &InstanceState{ 653 ID: "foo", 654 }, 655 }, 656 }, 657 }, 658 }, 659 }, 660 }) 661 662 p.RefreshFn = nil 663 p.RefreshReturn = &InstanceState{ 664 ID: "foo", 665 } 666 667 s, err := ctx.Refresh() 668 if err != nil { 669 t.Fatalf("err: %s", err) 670 } 671 mod := s.RootModule() 672 if !p.RefreshCalled { 673 t.Fatal("refresh should be called") 674 } 675 if p.RefreshState.ID != "foo" { 676 t.Fatalf("bad: %#v", p.RefreshState) 677 } 678 if !reflect.DeepEqual(mod.Resources["aws_instance.web"].Primary, p.RefreshReturn) { 679 t.Fatalf("bad: %#v", mod.Resources["aws_instance.web"]) 680 } 681 682 for _, r := range mod.Resources { 683 if r.Type == "" { 684 t.Fatalf("no type: %#v", r) 685 } 686 } 687 } 688 689 func TestContext2Refresh_orphanModule(t *testing.T) { 690 p := testProvider("aws") 691 m := testModule(t, "refresh-module-orphan") 692 693 // Create a custom refresh function to track the order they were visited 694 var order []string 695 var orderLock sync.Mutex 696 p.RefreshFn = func( 697 info *InstanceInfo, 698 is *InstanceState) (*InstanceState, error) { 699 orderLock.Lock() 700 defer orderLock.Unlock() 701 702 order = append(order, is.ID) 703 return is, nil 704 } 705 706 state := &State{ 707 Modules: []*ModuleState{ 708 &ModuleState{ 709 Path: rootModulePath, 710 Resources: map[string]*ResourceState{ 711 "aws_instance.foo": &ResourceState{ 712 Primary: &InstanceState{ 713 ID: "i-abc123", 714 Attributes: map[string]string{ 715 "childid": "i-bcd234", 716 "grandchildid": "i-cde345", 717 }, 718 }, 719 Dependencies: []string{ 720 "module.child", 721 "module.child", 722 }, 723 }, 724 }, 725 }, 726 &ModuleState{ 727 Path: append(rootModulePath, "child"), 728 Resources: map[string]*ResourceState{ 729 "aws_instance.bar": &ResourceState{ 730 Primary: &InstanceState{ 731 ID: "i-bcd234", 732 Attributes: map[string]string{ 733 "grandchildid": "i-cde345", 734 }, 735 }, 736 Dependencies: []string{ 737 "module.grandchild", 738 }, 739 }, 740 }, 741 Outputs: map[string]string{ 742 "id": "i-bcd234", 743 "grandchild_id": "i-cde345", 744 }, 745 }, 746 &ModuleState{ 747 Path: append(rootModulePath, "child", "grandchild"), 748 Resources: map[string]*ResourceState{ 749 "aws_instance.baz": &ResourceState{ 750 Primary: &InstanceState{ 751 ID: "i-cde345", 752 }, 753 }, 754 }, 755 Outputs: map[string]string{ 756 "id": "i-cde345", 757 }, 758 }, 759 }, 760 } 761 ctx := testContext2(t, &ContextOpts{ 762 Module: m, 763 Providers: map[string]ResourceProviderFactory{ 764 "aws": testProviderFuncFixed(p), 765 }, 766 State: state, 767 }) 768 769 testCheckDeadlock(t, func() { 770 _, err := ctx.Refresh() 771 if err != nil { 772 t.Fatalf("err: %s", err) 773 } 774 775 // TODO: handle order properly for orphaned modules / resources 776 // expected := []string{"i-abc123", "i-bcd234", "i-cde345"} 777 // if !reflect.DeepEqual(order, expected) { 778 // t.Fatalf("expected: %#v, got: %#v", expected, order) 779 // } 780 }) 781 } 782 783 func TestContext2Validate(t *testing.T) { 784 p := testProvider("aws") 785 m := testModule(t, "validate-good") 786 c := testContext2(t, &ContextOpts{ 787 Module: m, 788 Providers: map[string]ResourceProviderFactory{ 789 "aws": testProviderFuncFixed(p), 790 }, 791 }) 792 793 w, e := c.Validate() 794 if len(w) > 0 { 795 t.Fatalf("bad: %#v", w) 796 } 797 if len(e) > 0 { 798 t.Fatalf("bad: %s", e) 799 } 800 }