diff --git a/helper/resource/testing.go b/helper/resource/testing.go index 40acfbf3d..00da8a92e 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -635,9 +635,9 @@ func testProviderConfig(c TestCase) string { // Any errors are stored so that they can be returned by the factory in // terraform to match non-test behavior. func testProviderResolver(c TestCase) (providers.Resolver, error) { - ctxProviders := c.ProviderFactories - if ctxProviders == nil { - ctxProviders = make(map[string]terraform.ResourceProviderFactory) + ctxProviders := make(map[string]terraform.ResourceProviderFactory) + for k, pf := range c.ProviderFactories { + ctxProviders[k] = pf } // add any fixed providers @@ -650,8 +650,9 @@ func testProviderResolver(c TestCase) (providers.Resolver, error) { newProviders := make(map[string]providers.Factory) for k, pf := range ctxProviders { + factory := pf // must copy to ensure each closure sees its own value newProviders[k] = func() (providers.Interface, error) { - p, err := pf() + p, err := factory() if err != nil { return nil, err } diff --git a/helper/resource/testing_test.go b/helper/resource/testing_test.go index 448c2abb3..59d2f17b4 100644 --- a/helper/resource/testing_test.go +++ b/helper/resource/testing_test.go @@ -14,6 +14,8 @@ import ( "testing" "github.com/hashicorp/go-multierror" + "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/plugin/discovery" "github.com/hashicorp/terraform/terraform" ) @@ -1033,6 +1035,77 @@ func TestTest_Taint(t *testing.T) { } } +func TestTestProviderResolver(t *testing.T) { + stubProvider := func(name string) terraform.ResourceProvider { + return &schema.Provider{ + Schema: map[string]*schema.Schema{ + name: &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + }, + } + } + + c := TestCase{ + ProviderFactories: map[string]terraform.ResourceProviderFactory{ + "foo": terraform.ResourceProviderFactoryFixed(stubProvider("foo")), + "bar": terraform.ResourceProviderFactoryFixed(stubProvider("bar")), + }, + Providers: map[string]terraform.ResourceProvider{ + "baz": stubProvider("baz"), + "bop": stubProvider("bop"), + }, + } + + resolver, err := testProviderResolver(c) + if err != nil { + t.Fatal(err) + } + + reqd := discovery.PluginRequirements{ + "foo": &discovery.PluginConstraints{}, + "bar": &discovery.PluginConstraints{}, + "baz": &discovery.PluginConstraints{}, + "bop": &discovery.PluginConstraints{}, + } + + factories, errs := resolver.ResolveProviders(reqd) + if len(errs) != 0 { + for _, err := range errs { + t.Error(err) + } + t.Fatal("unexpected errors") + } + + for name := range reqd { + t.Run(name, func(t *testing.T) { + pf, ok := factories[name] + if !ok { + t.Fatalf("no factory for %q", name) + } + p, err := pf() + if err != nil { + t.Fatal(err) + } + resp := p.GetSchema() + _, ok = resp.Provider.Block.Attributes[name] + if !ok { + var has string + for k := range resp.Provider.Block.Attributes { + has = k + break + } + if has != "" { + t.Errorf("provider %q does not have the expected schema attribute %q (but has %q)", name, name, has) + } else { + t.Errorf("provider %q does not have the expected schema attribute %q", name, name) + } + } + }) + } +} + const testConfigStr = ` resource "test_instance" "foo" {} `