-
Notifications
You must be signed in to change notification settings - Fork 232
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
helper/resource: Support TestStep provider handling
Reference: #253 Reference: #628 Reference: #779 Provider developers can now select whether to configure providers for acceptance testing at the `TestCase` or `TestStep` level. Only one level may be used in this current implementation, however it may be possible to allow merged `TestCase` and `TestStep` configuration with additional validation logic to ensure a single provider is not specified multiple times across the merge result of all fields. This change also introduces some upfront `TestCase` and `TestStep` configuration validation when calling any of the `Test` functions, failing the test early if a problem is detected. There are other validations that are possible, however these are considered out of scope.
- Loading branch information
Showing
17 changed files
with
1,965 additions
and
221 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
```release-note:note | ||
helper/resource: Provider references or external installation can now be handled at either the `TestCase` or `TestStep` level. Using the `TestStep` handling, advanced use cases are now enabled such as state upgrade acceptance testing. | ||
``` | ||
|
||
```release-note:enhancement | ||
helper/resource: Added `TestStep` type `ExternalProviders`, `ProtoV5ProviderFactories`, `ProtoV6ProviderFactories`, and `ProviderFactories` fields | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,236 @@ | ||
package resource | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/google/go-cmp/cmp" | ||
"github.com/hashicorp/terraform-plugin-go/tfprotov5" | ||
"github.com/hashicorp/terraform-plugin-go/tfprotov6" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
) | ||
|
||
func TestProtoV5ProviderFactoriesMerge(t *testing.T) { | ||
t.Parallel() | ||
|
||
testProviderFactory1 := func() (tfprotov5.ProviderServer, error) { | ||
return nil, nil | ||
} | ||
testProviderFactory2 := func() (tfprotov5.ProviderServer, error) { | ||
return nil, nil | ||
} | ||
|
||
// Function pointers do not play well with go-cmp, so convert these | ||
// into their stringified address for comparison. | ||
transformer := cmp.Transformer( | ||
"protov5ProviderFactory", | ||
func(pf protov5ProviderFactory) string { | ||
return fmt.Sprintf("%v", pf) | ||
}, | ||
) | ||
|
||
testCases := map[string]struct { | ||
pf protov5ProviderFactories | ||
others []protov5ProviderFactories | ||
expected protov5ProviderFactories | ||
}{ | ||
"no-overlap": { | ||
pf: protov5ProviderFactories{ | ||
"test1": testProviderFactory1, | ||
}, | ||
others: []protov5ProviderFactories{ | ||
{ | ||
"test2": testProviderFactory1, | ||
}, | ||
{ | ||
"test3": testProviderFactory1, | ||
}, | ||
}, | ||
expected: protov5ProviderFactories{ | ||
"test1": testProviderFactory1, | ||
"test2": testProviderFactory1, | ||
"test3": testProviderFactory1, | ||
}, | ||
}, | ||
"overlap": { | ||
pf: protov5ProviderFactories{ | ||
"test": testProviderFactory1, | ||
}, | ||
others: []protov5ProviderFactories{ | ||
{ | ||
"test": testProviderFactory1, | ||
}, | ||
{ | ||
"test": testProviderFactory2, | ||
}, | ||
}, | ||
expected: protov5ProviderFactories{ | ||
"test": testProviderFactory2, | ||
}, | ||
}, | ||
} | ||
|
||
for name, testCase := range testCases { | ||
name, testCase := name, testCase | ||
|
||
t.Run(name, func(t *testing.T) { | ||
t.Parallel() | ||
|
||
got := testCase.pf.merge(testCase.others...) | ||
|
||
if diff := cmp.Diff(got, testCase.expected, transformer); diff != "" { | ||
t.Errorf("unexpected difference: %s", diff) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestProtoV6ProviderFactoriesMerge(t *testing.T) { | ||
t.Parallel() | ||
|
||
testProviderFactory1 := func() (tfprotov6.ProviderServer, error) { | ||
return nil, nil | ||
} | ||
testProviderFactory2 := func() (tfprotov6.ProviderServer, error) { | ||
return nil, nil | ||
} | ||
|
||
// Function pointers do not play well with go-cmp, so convert these | ||
// into their stringified address for comparison. | ||
transformer := cmp.Transformer( | ||
"protov6ProviderFactory", | ||
func(pf protov6ProviderFactory) string { | ||
return fmt.Sprintf("%v", pf) | ||
}, | ||
) | ||
|
||
testCases := map[string]struct { | ||
pf protov6ProviderFactories | ||
others []protov6ProviderFactories | ||
expected protov6ProviderFactories | ||
}{ | ||
"no-overlap": { | ||
pf: protov6ProviderFactories{ | ||
"test1": testProviderFactory1, | ||
}, | ||
others: []protov6ProviderFactories{ | ||
{ | ||
"test2": testProviderFactory1, | ||
}, | ||
{ | ||
"test3": testProviderFactory1, | ||
}, | ||
}, | ||
expected: protov6ProviderFactories{ | ||
"test1": testProviderFactory1, | ||
"test2": testProviderFactory1, | ||
"test3": testProviderFactory1, | ||
}, | ||
}, | ||
"overlap": { | ||
pf: protov6ProviderFactories{ | ||
"test": testProviderFactory1, | ||
}, | ||
others: []protov6ProviderFactories{ | ||
{ | ||
"test": testProviderFactory1, | ||
}, | ||
{ | ||
"test": testProviderFactory2, | ||
}, | ||
}, | ||
expected: protov6ProviderFactories{ | ||
"test": testProviderFactory2, | ||
}, | ||
}, | ||
} | ||
|
||
for name, testCase := range testCases { | ||
name, testCase := name, testCase | ||
|
||
t.Run(name, func(t *testing.T) { | ||
t.Parallel() | ||
|
||
got := testCase.pf.merge(testCase.others...) | ||
|
||
if diff := cmp.Diff(got, testCase.expected, transformer); diff != "" { | ||
t.Errorf("unexpected difference: %s", diff) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestSdkProviderFactoriesMerge(t *testing.T) { | ||
t.Parallel() | ||
|
||
testProviderFactory1 := func() (*schema.Provider, error) { | ||
return nil, nil | ||
} | ||
testProviderFactory2 := func() (*schema.Provider, error) { | ||
return nil, nil | ||
} | ||
|
||
// Function pointers do not play well with go-cmp, so convert these | ||
// into their stringified address for comparison. | ||
transformer := cmp.Transformer( | ||
"sdkProviderFactory", | ||
func(pf sdkProviderFactory) string { | ||
return fmt.Sprintf("%v", pf) | ||
}, | ||
) | ||
|
||
testCases := map[string]struct { | ||
pf sdkProviderFactories | ||
others []sdkProviderFactories | ||
expected sdkProviderFactories | ||
}{ | ||
"no-overlap": { | ||
pf: sdkProviderFactories{ | ||
"test1": testProviderFactory1, | ||
}, | ||
others: []sdkProviderFactories{ | ||
{ | ||
"test2": testProviderFactory1, | ||
}, | ||
{ | ||
"test3": testProviderFactory1, | ||
}, | ||
}, | ||
expected: sdkProviderFactories{ | ||
"test1": testProviderFactory1, | ||
"test2": testProviderFactory1, | ||
"test3": testProviderFactory1, | ||
}, | ||
}, | ||
"overlap": { | ||
pf: sdkProviderFactories{ | ||
"test": testProviderFactory1, | ||
}, | ||
others: []sdkProviderFactories{ | ||
{ | ||
"test": testProviderFactory1, | ||
}, | ||
{ | ||
"test": testProviderFactory2, | ||
}, | ||
}, | ||
expected: sdkProviderFactories{ | ||
"test": testProviderFactory2, | ||
}, | ||
}, | ||
} | ||
|
||
for name, testCase := range testCases { | ||
name, testCase := name, testCase | ||
|
||
t.Run(name, func(t *testing.T) { | ||
t.Parallel() | ||
|
||
got := testCase.pf.merge(testCase.others...) | ||
|
||
if diff := cmp.Diff(got, testCase.expected, transformer); diff != "" { | ||
t.Errorf("unexpected difference: %s", diff) | ||
} | ||
}) | ||
} | ||
} |
Oops, something went wrong.