-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Plugin Framework bridge cross tests (#2592)
This is a test-only PR - it adds cross-tests for Diff for the plugin framework for the existing behaviour. Each test defines a set of schemas and a set of scenarios and the full matrix of schemas X scenarios is run in cross-tests. For each of these test cases both pulumi and TF are run with the initial input then a preview is run with the second set of inputs and the outcome of the preview is compared. We also record the stdout for both pulumi and TF for manual comparison of the preview output. The recordings also contain the inputs in order to make spot-checking them easier. The full test plan is available in #2597 fixes #2297 fixes #2597
- Loading branch information
1 parent
77577d0
commit 317d4b8
Showing
507 changed files
with
19,210 additions
and
5 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,233 @@ | ||
package tfbridgetests | ||
|
||
import ( | ||
"testing" | ||
|
||
rschema "github.com/hashicorp/terraform-plugin-framework/resource/schema" | ||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier" | ||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" | ||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" | ||
"github.com/hashicorp/terraform-plugin-framework/types" | ||
"github.com/hexops/autogold/v2" | ||
crosstests "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/pf/tests/internal/cross-tests" | ||
"github.com/zclconf/go-cty/cty" | ||
) | ||
|
||
func TestDetailedDiffList(t *testing.T) { | ||
t.Parallel() | ||
|
||
attributeSchema := rschema.Schema{ | ||
Attributes: map[string]rschema.Attribute{ | ||
"key": rschema.ListAttribute{ | ||
Optional: true, | ||
ElementType: types.StringType, | ||
}, | ||
}, | ||
} | ||
|
||
attributeReplaceSchema := rschema.Schema{ | ||
Attributes: map[string]rschema.Attribute{ | ||
"key": rschema.ListAttribute{ | ||
Optional: true, | ||
ElementType: types.StringType, | ||
PlanModifiers: []planmodifier.List{ | ||
listplanmodifier.RequiresReplace(), | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
nestedAttributeSchema := rschema.Schema{ | ||
Attributes: map[string]rschema.Attribute{ | ||
"key": rschema.ListNestedAttribute{ | ||
Optional: true, | ||
NestedObject: rschema.NestedAttributeObject{ | ||
Attributes: map[string]rschema.Attribute{ | ||
"nested": rschema.StringAttribute{Optional: true}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
nestedAttributeReplaceSchema := rschema.Schema{ | ||
Attributes: map[string]rschema.Attribute{ | ||
"key": rschema.ListNestedAttribute{ | ||
Optional: true, | ||
NestedObject: rschema.NestedAttributeObject{ | ||
Attributes: map[string]rschema.Attribute{ | ||
"nested": rschema.StringAttribute{ | ||
Optional: true, | ||
}, | ||
}, | ||
}, | ||
PlanModifiers: []planmodifier.List{ | ||
listplanmodifier.RequiresReplace(), | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
nestedAttributeNestedReplaceSchema := rschema.Schema{ | ||
Attributes: map[string]rschema.Attribute{ | ||
"key": rschema.ListNestedAttribute{ | ||
Optional: true, | ||
NestedObject: rschema.NestedAttributeObject{ | ||
Attributes: map[string]rschema.Attribute{ | ||
"nested": rschema.StringAttribute{ | ||
Optional: true, | ||
PlanModifiers: []planmodifier.String{ | ||
stringplanmodifier.RequiresReplace(), | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
blockSchema := rschema.Schema{ | ||
Blocks: map[string]rschema.Block{ | ||
"key": rschema.ListNestedBlock{ | ||
NestedObject: rschema.NestedBlockObject{ | ||
Attributes: map[string]rschema.Attribute{ | ||
"nested": rschema.StringAttribute{Optional: true}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
blockReplaceSchema := rschema.Schema{ | ||
Blocks: map[string]rschema.Block{ | ||
"key": rschema.ListNestedBlock{ | ||
NestedObject: rschema.NestedBlockObject{ | ||
Attributes: map[string]rschema.Attribute{ | ||
"nested": rschema.StringAttribute{Optional: true}, | ||
}, | ||
}, | ||
PlanModifiers: []planmodifier.List{ | ||
listplanmodifier.RequiresReplace(), | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
blockNestedReplaceSchema := rschema.Schema{ | ||
Blocks: map[string]rschema.Block{ | ||
"key": rschema.ListNestedBlock{ | ||
NestedObject: rschema.NestedBlockObject{ | ||
Attributes: map[string]rschema.Attribute{ | ||
"nested": rschema.StringAttribute{ | ||
Optional: true, | ||
PlanModifiers: []planmodifier.String{ | ||
stringplanmodifier.RequiresReplace(), | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
attrList := func(arr *[]string) cty.Value { | ||
if arr == nil { | ||
return cty.NullVal(cty.DynamicPseudoType) | ||
} | ||
slice := make([]cty.Value, len(*arr)) | ||
for i, v := range *arr { | ||
slice[i] = cty.StringVal(v) | ||
} | ||
if len(slice) == 0 { | ||
return cty.ListValEmpty(cty.String) | ||
} | ||
return cty.ListVal(slice) | ||
} | ||
|
||
nestedAttrList := func(arr *[]string) cty.Value { | ||
if arr == nil { | ||
return cty.NullVal(cty.DynamicPseudoType) | ||
} | ||
slice := make([]cty.Value, len(*arr)) | ||
for i, v := range *arr { | ||
slice[i] = cty.ObjectVal( | ||
map[string]cty.Value{ | ||
"nested": cty.StringVal(v), | ||
}, | ||
) | ||
} | ||
if len(slice) == 0 { | ||
return cty.ListValEmpty(cty.Object(map[string]cty.Type{"nested": cty.String})) | ||
} | ||
return cty.ListVal(slice) | ||
} | ||
|
||
schemaValueMakerPairs := []struct { | ||
name string | ||
schema rschema.Schema | ||
valueMaker func(*[]string) cty.Value | ||
}{ | ||
{"attribute no replace", attributeSchema, attrList}, | ||
{"attribute requires replace", attributeReplaceSchema, attrList}, | ||
{"nested attribute no replace", nestedAttributeSchema, nestedAttrList}, | ||
{"nested attribute requires replace", nestedAttributeReplaceSchema, nestedAttrList}, | ||
{"nested attribute nested requires replace", nestedAttributeNestedReplaceSchema, nestedAttrList}, | ||
{"block no replace", blockSchema, nestedAttrList}, | ||
{"block requires replace", blockReplaceSchema, nestedAttrList}, | ||
{"block nested requires replace", blockNestedReplaceSchema, nestedAttrList}, | ||
} | ||
|
||
scenarios := []struct { | ||
name string | ||
initialValue *[]string | ||
changeValue *[]string | ||
}{ | ||
{"unchanged non-empty", &[]string{"value"}, &[]string{"value"}}, | ||
{"changed non-empty", &[]string{"value"}, &[]string{"value1"}}, | ||
{"added", &[]string{}, &[]string{"value"}}, | ||
{"removed", &[]string{"value"}, &[]string{}}, | ||
{"null unchanged", nil, nil}, | ||
{"null to non-null", nil, &[]string{"value"}}, | ||
{"non-null to null", &[]string{"value"}, nil}, | ||
{"changed null to empty", nil, &[]string{}}, | ||
{"changed empty to null", &[]string{}, nil}, | ||
{"element added", &[]string{"value"}, &[]string{"value", "value1"}}, | ||
{"element removed", &[]string{"value", "value1"}, &[]string{"value"}}, | ||
{"removed front", &[]string{"val1", "val2", "val3"}, &[]string{"val2", "val3"}}, | ||
{"removed middle", &[]string{"val1", "val2", "val3"}, &[]string{"val1", "val3"}}, | ||
{"removed end", &[]string{"val1", "val2", "val3"}, &[]string{"val1", "val2"}}, | ||
{"added front", &[]string{"val2", "val3"}, &[]string{"val1", "val2", "val3"}}, | ||
{"added middle", &[]string{"val1", "val3"}, &[]string{"val1", "val2", "val3"}}, | ||
{"added end", &[]string{"val1", "val2"}, &[]string{"val1", "val2", "val3"}}, | ||
} | ||
|
||
type testOutput struct { | ||
initialValue *[]string | ||
changeValue *[]string | ||
tfOut string | ||
pulumiOut string | ||
} | ||
|
||
for _, schemaValueMakerPair := range schemaValueMakerPairs { | ||
t.Run(schemaValueMakerPair.name, func(t *testing.T) { | ||
t.Parallel() | ||
for _, scenario := range scenarios { | ||
t.Run(scenario.name, func(t *testing.T) { | ||
t.Parallel() | ||
initialValue := schemaValueMakerPair.valueMaker(scenario.initialValue) | ||
changeValue := schemaValueMakerPair.valueMaker(scenario.changeValue) | ||
|
||
diff := crosstests.Diff( | ||
t, schemaValueMakerPair.schema, map[string]cty.Value{"key": initialValue}, map[string]cty.Value{"key": changeValue}) | ||
|
||
autogold.ExpectFile(t, testOutput{ | ||
initialValue: scenario.initialValue, | ||
changeValue: scenario.changeValue, | ||
tfOut: diff.TFOut, | ||
pulumiOut: diff.PulumiOut, | ||
}) | ||
}) | ||
} | ||
}) | ||
} | ||
} |
Oops, something went wrong.