Skip to content

Commit

Permalink
update to using tuple exact + new testing fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
austinvalle committed Mar 25, 2024
1 parent 71512e3 commit f203251
Show file tree
Hide file tree
Showing 9 changed files with 182 additions and 128 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ require (
github.com/hashicorp/terraform-plugin-go v0.22.1
github.com/hashicorp/terraform-plugin-mux v0.15.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0
github.com/hashicorp/terraform-plugin-testing v1.7.0
github.com/hashicorp/terraform-plugin-testing v1.7.1-0.20240325220100-c294752cca7f
github.com/zclconf/go-cty v1.14.3
)

Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ github.com/hashicorp/terraform-plugin-mux v0.15.0 h1:+/+lDx0WUsIOpkAmdwBIoFU8UP9
github.com/hashicorp/terraform-plugin-mux v0.15.0/go.mod h1:9ezplb1Dyq394zQ+ldB0nvy/qbNAz3mMoHHseMTMaKo=
github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 h1:qHprzXy/As0rxedphECBEQAh3R4yp6pKksKHcqZx5G8=
github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0/go.mod h1:H+8tjs9TjV2w57QFVSMBQacf8k/E1XwLXGCARgViC6A=
github.com/hashicorp/terraform-plugin-testing v1.7.0 h1:I6aeCyZ30z4NiI3tzyDoO6fS7YxP5xSL1ceOon3gTe8=
github.com/hashicorp/terraform-plugin-testing v1.7.0/go.mod h1:sbAreCleJNOCz+y5vVHV8EJkIWZKi/t4ndKiUjM9vao=
github.com/hashicorp/terraform-plugin-testing v1.7.1-0.20240325220100-c294752cca7f h1:KANyvm9GwKRS1xkaYge+6a9NUhLwlR5kUz5kOT9mw00=
github.com/hashicorp/terraform-plugin-testing v1.7.1-0.20240325220100-c294752cca7f/go.mod h1:Vf0AwgzPP6M/yopLkHMdIT4aG3V66hS14Emv2UvRsNs=
github.com/hashicorp/terraform-registry-address v0.2.3 h1:2TAiKJ1A3MAkZlH1YI/aTVcLZRu7JseiXNRHbOAyoTI=
github.com/hashicorp/terraform-registry-address v0.2.3/go.mod h1:lFHA76T8jfQteVfT7caREqguFrW3c4MFSPhZB7HHgUM=
github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S52uzrw4x0jKQ=
Expand Down
2 changes: 1 addition & 1 deletion internal/cornertesting/expect_output_type_state_check.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func (e expectOutputType) CheckState(ctx context.Context, req statecheck.CheckSt
}

if !output.Type.Equals(e.expectedType) {
resp.Error = fmt.Errorf("expected %q output type to be %q, got %q", e.outputAddress, output.Type.FriendlyName(), e.expectedType.FriendlyName())
resp.Error = fmt.Errorf("expected %q output type to be %q, got %q", e.outputAddress, e.expectedType.FriendlyName(), output.Type.FriendlyName())
}
}

Expand Down
3 changes: 1 addition & 2 deletions internal/framework5provider/dynamic_schema_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,7 @@ func TestDynamicSchemaResource_DynamicAttribute(t *testing.T) {
"attribute_one": knownvalue.StringExact("value1"),
"attribute_two": knownvalue.Bool(false),
"attribute_three": knownvalue.NumberExact(big.NewFloat(1234.5)),
// ListExact can be used despite the underlying type being a tuple[bool, number]
"attribute_four": knownvalue.ListExact(
"attribute_four": knownvalue.TupleExact(
[]knownvalue.Check{
knownvalue.Bool(true),
knownvalue.NumberExact(big.NewFloat(1234.5)),
Expand Down
15 changes: 6 additions & 9 deletions internal/framework5provider/dynamic_variadic_function.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,19 @@ func (f DynamicVariadicFunction) Run(ctx context.Context, req function.RunReques

resp.Error = req.Arguments.Get(ctx, &varg)

dynVals := make([]attr.Value, 0)
tupleTypes := make([]attr.Type, 0)
tupleValues := make([]attr.Value, 0)

for _, arg := range varg {
dynVals = append(dynVals, types.DynamicValue(arg.UnderlyingValue()))
tupleTypes = append(tupleTypes, arg.UnderlyingValue().Type(ctx))
tupleValues = append(tupleValues, arg.UnderlyingValue())
}

// Despite types.List not fully supporting dynamic types, in this restricted scenario it will work fine
// as long as all the dynamic types coming in are the same.
//
// TODO: Switch this to a tuple once `terraform-plugin-testing` bug has been fixed with Tuple output:
// - https://github.com/hashicorp/terraform-plugin-testing/issues/310
listReturn, diags := types.ListValue(types.DynamicType, dynVals)
tupleReturn, diags := types.TupleValue(tupleTypes, tupleValues)
if diags.HasError() {
resp.Error = function.FuncErrorFromDiags(ctx, diags)
return
}

resp.Error = function.ConcatFuncErrors(resp.Error, resp.Result.Set(ctx, types.DynamicValue(listReturn)))
resp.Error = function.ConcatFuncErrors(resp.Error, resp.Result.Set(ctx, types.DynamicValue(tupleReturn)))
}
133 changes: 82 additions & 51 deletions internal/framework5provider/dynamic_variadic_function_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,8 @@ func TestDynamicVariadicFunction_value_zero(t *testing.T) {
value = provider::framework::dynamic_variadic()
}`,
ConfigStateChecks: []statecheck.StateCheck{
// Since no arguments were passed in to determine the type, the list will be dynamic
cornertesting.ExpectOutputType("test", cty.List(cty.DynamicPseudoType)),
statecheck.ExpectKnownOutputValue("test", knownvalue.ListExact([]knownvalue.Check{})),
cornertesting.ExpectOutputType("test", cty.Tuple([]cty.Type{})),
statecheck.ExpectKnownOutputValue("test", knownvalue.TupleExact([]knownvalue.Check{})),
},
},
},
Expand All @@ -61,9 +60,15 @@ func TestDynamicVariadicFunction_value_one(t *testing.T) {
value = provider::framework::dynamic_variadic("one")
}`,
ConfigStateChecks: []statecheck.StateCheck{
cornertesting.ExpectOutputType("test", cty.List(cty.String)),
cornertesting.ExpectOutputType("test",
cty.Tuple(
[]cty.Type{
cty.String,
},
),
),
statecheck.ExpectKnownOutputValue("test",
knownvalue.ListExact(
knownvalue.TupleExact(
[]knownvalue.Check{
knownvalue.StringExact("one"),
},
Expand Down Expand Up @@ -91,9 +96,16 @@ func TestDynamicVariadicFunction_value_multiple_same_type_primitive(t *testing.T
value = provider::framework::dynamic_variadic("one", "two")
}`,
ConfigStateChecks: []statecheck.StateCheck{
cornertesting.ExpectOutputType("test", cty.List(cty.String)),
cornertesting.ExpectOutputType("test",
cty.Tuple(
[]cty.Type{
cty.String,
cty.String,
},
),
),
statecheck.ExpectKnownOutputValue("test",
knownvalue.ListExact(
knownvalue.TupleExact(
[]knownvalue.Check{
knownvalue.StringExact("one"),
knownvalue.StringExact("two"),
Expand Down Expand Up @@ -125,18 +137,24 @@ func TestDynamicVariadicFunction_value_multiple_same_type_complex(t *testing.T)
)
}`,
ConfigStateChecks: []statecheck.StateCheck{
cornertesting.ExpectOutputType(
"test",
cty.List(
cty.Object(map[string]cty.Type{
"a": cty.Number,
"b": cty.Bool,
"c": cty.String,
}),
cornertesting.ExpectOutputType("test",
cty.Tuple(
[]cty.Type{
cty.Object(map[string]cty.Type{
"a": cty.Number,
"b": cty.Bool,
"c": cty.String,
}),
cty.Object(map[string]cty.Type{
"a": cty.Number,
"b": cty.Bool,
"c": cty.String,
}),
},
),
),
statecheck.ExpectKnownOutputValue("test",
knownvalue.ListExact(
knownvalue.TupleExact(
[]knownvalue.Check{
knownvalue.ObjectExact(
map[string]knownvalue.Check{
Expand All @@ -161,40 +179,46 @@ func TestDynamicVariadicFunction_value_multiple_same_type_complex(t *testing.T)
})
}

// This test can't be completed until the `dynamic_variadic` function implementation uses a tuple return.
// A `terraform-plugin-testing` bug is causing a panic when an output value is a tuple.
// - https://github.com/hashicorp/terraform-plugin-testing/issues/310
//
// TODO: Uncomment this test when the upstream tuple bug is fixed and the function implementation switches to using a tuple.
//
// func TestDynamicVariadicFunction_value_multiple_different_type(t *testing.T) {
// resource.UnitTest(t, resource.TestCase{
// TerraformVersionChecks: []tfversion.TerraformVersionCheck{
// // TODO: Replace with the stable v1.8.0 release when available
// tfversion.SkipBelow(version.Must(version.NewVersion("v1.8.0-rc1"))),
// },
// ProtoV5ProviderFactories: map[string]func() (tfprotov5.ProviderServer, error){
// "framework": providerserver.NewProtocol5WithError(New()),
// },
// Steps: []resource.TestStep{
// {
// Config: `
// output "test" {
// value = provider::framework::dynamic_variadic(true, "string", 1234.5)
// }`,
// ConfigStateChecks: []statecheck.StateCheck{
// cornertesting.ExpectOutputType("test", cty.Tuple([]cty.Type{cty.Bool, cty.String, cty.Number})),
// // ListExact can be used despite the underlying type being a tuple[bool, string, number]
// statecheck.ExpectKnownOutputValue("test", knownvalue.ListExact([]knownvalue.Check{
// knownvalue.Bool(true),
// knownvalue.StringExact("string"),
// knownvalue.NumberExact(big.NewFloat(1234.5)),
// })),
// },
// },
// },
// })
// }
func TestDynamicVariadicFunction_value_multiple_different_type(t *testing.T) {
resource.UnitTest(t, resource.TestCase{
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
// TODO: Replace with the stable v1.8.0 release when available
tfversion.SkipBelow(version.Must(version.NewVersion("v1.8.0-rc1"))),
},
ProtoV5ProviderFactories: map[string]func() (tfprotov5.ProviderServer, error){
"framework": providerserver.NewProtocol5WithError(New()),
},
Steps: []resource.TestStep{
{
Config: `
output "test" {
value = provider::framework::dynamic_variadic(true, "string", 1234.5)
}`,
ConfigStateChecks: []statecheck.StateCheck{
cornertesting.ExpectOutputType(
"test",
cty.Tuple(
[]cty.Type{
cty.Bool,
cty.String,
cty.Number,
},
),
),
statecheck.ExpectKnownOutputValue("test",
knownvalue.TupleExact(
[]knownvalue.Check{
knownvalue.Bool(true),
knownvalue.StringExact("string"),
knownvalue.NumberExact(big.NewFloat(1234.5)),
},
),
),
},
},
},
})
}

func TestDynamicVariadicFunction_null(t *testing.T) {
resource.UnitTest(t, resource.TestCase{
Expand Down Expand Up @@ -268,8 +292,15 @@ func TestDynamicVariadicFunction_unknown(t *testing.T) {
},
},
ConfigStateChecks: []statecheck.StateCheck{
cornertesting.ExpectOutputType("test",
cty.Tuple(
[]cty.Type{
cty.String,
},
),
),
statecheck.ExpectKnownOutputValue("test",
knownvalue.ListExact(
knownvalue.TupleExact(
[]knownvalue.Check{
knownvalue.StringExact("test-value"),
},
Expand Down
15 changes: 6 additions & 9 deletions internal/framework6provider/dynamic_variadic_function.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,19 @@ func (f DynamicVariadicFunction) Run(ctx context.Context, req function.RunReques

resp.Error = req.Arguments.Get(ctx, &varg)

dynVals := make([]attr.Value, 0)
tupleTypes := make([]attr.Type, 0)
tupleValues := make([]attr.Value, 0)

for _, arg := range varg {
dynVals = append(dynVals, types.DynamicValue(arg.UnderlyingValue()))
tupleTypes = append(tupleTypes, arg.UnderlyingValue().Type(ctx))
tupleValues = append(tupleValues, arg.UnderlyingValue())
}

// Despite types.List not fully supporting dynamic types, in this restricted scenario it will work fine
// as long as all the dynamic types coming in are the same.
//
// TODO: Switch this to a tuple once `terraform-plugin-testing` bug has been fixed with Tuple output:
// - https://github.com/hashicorp/terraform-plugin-testing/issues/310
listReturn, diags := types.ListValue(types.DynamicType, dynVals)
tupleReturn, diags := types.TupleValue(tupleTypes, tupleValues)
if diags.HasError() {
resp.Error = function.FuncErrorFromDiags(ctx, diags)
return
}

resp.Error = function.ConcatFuncErrors(resp.Error, resp.Result.Set(ctx, types.DynamicValue(listReturn)))
resp.Error = function.ConcatFuncErrors(resp.Error, resp.Result.Set(ctx, types.DynamicValue(tupleReturn)))
}
Loading

0 comments on commit f203251

Please sign in to comment.