Skip to content

Commit

Permalink
Add Int32 and Float32 type testing (#258)
Browse files Browse the repository at this point in the history
* Add Int32 and Float32 type testing

* Add overflow and underflow tests for Float32

* Add `MaxFloat32` precision tests for `float64_precision_resource` and create separate tests for Terraform `v1.9.0` and above

* Fix tfversioncheck constraints

* Fix tfversioncheck constraints

* Update tfversioncheck constraints and comments to use major release versions.

* Add Int32 and Float32 type tests for schema_resource
  • Loading branch information
SBGoods authored Jul 10, 2024
1 parent 701ad28 commit c7c3613
Show file tree
Hide file tree
Showing 21 changed files with 1,977 additions and 1 deletion.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ toolchain go1.21.6

require (
github.com/hashicorp/go-memdb v1.3.4
github.com/hashicorp/go-version v1.7.0
github.com/hashicorp/terraform-json v0.22.1
github.com/hashicorp/terraform-plugin-framework v1.10.0
github.com/hashicorp/terraform-plugin-framework-timeouts v0.4.1
Expand Down Expand Up @@ -34,7 +35,6 @@ require (
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-plugin v1.6.0 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/hashicorp/go-version v1.7.0 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/hashicorp/hc-install v0.7.0 // indirect
github.com/hashicorp/hcl/v2 v2.21.0 // indirect
Expand Down
41 changes: 41 additions & 0 deletions internal/framework5provider/float32_function.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package framework

import (
"context"

"github.com/hashicorp/terraform-plugin-framework/function"
)

var _ function.Function = Float32Function{}

func NewFloat32Function() function.Function {
return &Float32Function{}
}

type Float32Function struct{}

func (f Float32Function) Metadata(ctx context.Context, req function.MetadataRequest, resp *function.MetadataResponse) {
resp.Name = "float32"
}

func (f Float32Function) Definition(ctx context.Context, req function.DefinitionRequest, resp *function.DefinitionResponse) {
resp.Definition = function.Definition{
Parameters: []function.Parameter{
function.Float32Parameter{
Name: "float32_param",
},
},
Return: function.Float32Return{},
}
}

func (f Float32Function) Run(ctx context.Context, req function.RunRequest, resp *function.RunResponse) {
var arg float32

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

resp.Error = function.ConcatFuncErrors(resp.Error, resp.Result.Set(ctx, arg))
}
135 changes: 135 additions & 0 deletions internal/framework5provider/float32_function_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package framework

import (
"regexp"
"testing"

"github.com/hashicorp/terraform-plugin-framework/providerserver"
"github.com/hashicorp/terraform-plugin-go/tfprotov5"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/plancheck"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
"github.com/hashicorp/terraform-plugin-testing/tfversion"
)

func TestFloat32Function_known(t *testing.T) {
resource.UnitTest(t, resource.TestCase{
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
tfversion.SkipBelow(tfversion.Version1_8_0),
},
ProtoV5ProviderFactories: map[string]func() (tfprotov5.ProviderServer, error){
"framework": providerserver.NewProtocol5WithError(New()),
},
Steps: []resource.TestStep{
{
Config: `
output "test" {
value = provider::framework::float32(1.23)
}`,
ConfigStateChecks: []statecheck.StateCheck{
statecheck.ExpectKnownOutputValue("test", knownvalue.Float32Exact(1.23)),
},
},
},
})
}

func TestFloat32Function_null(t *testing.T) {
resource.UnitTest(t, resource.TestCase{
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
tfversion.SkipBelow(tfversion.Version1_8_0),
},
ProtoV5ProviderFactories: map[string]func() (tfprotov5.ProviderServer, error){
"framework": providerserver.NewProtocol5WithError(New()),
},
Steps: []resource.TestStep{
{
Config: `
output "test" {
value = provider::framework::float32(null)
}`,
ExpectError: regexp.MustCompile("Invalid function argument"),
},
},
})
}

func TestFloat32Function_unknown(t *testing.T) {
resource.UnitTest(t, resource.TestCase{
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
tfversion.SkipBelow(tfversion.Version1_8_0),
},
ProtoV5ProviderFactories: map[string]func() (tfprotov5.ProviderServer, error){
"framework": providerserver.NewProtocol5WithError(New()),
},
Steps: []resource.TestStep{
{
Config: `
resource "terraform_data" "test" {
input = provider::framework::float32(1.23)
}
output "test" {
value = terraform_data.test.output
}`,
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{
plancheck.ExpectUnknownOutputValue("test"),
},
},
ConfigStateChecks: []statecheck.StateCheck{
statecheck.ExpectKnownOutputValue("test", knownvalue.Float32Exact(1.23)),
},
},
},
})
}

func TestFloat32Function_overflow_underflow(t *testing.T) {
resource.UnitTest(t, resource.TestCase{
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
tfversion.SkipBelow(tfversion.Version1_8_0),
},
ProtoV5ProviderFactories: map[string]func() (tfprotov5.ProviderServer, error){
"framework": providerserver.NewProtocol5WithError(New()),
},
Steps: []resource.TestStep{
// float32 overflow
{
Config: `
output "test" {
value = provider::framework::float32(3.40282346638528859811704183484516925440e+39)
}`,
ExpectError: regexp.MustCompile("Invalid function argument"),
},
// float32 negative overflow
{
Config: `
output "test" {
value = provider::framework::float32(-3.40282346638528859811704183484516925440e+39)
}`,
ExpectError: regexp.MustCompile("Invalid function argument"),
},
// float32 underflow
{
Config: `
output "test" {
value = provider::framework::float32(1.401298464324817070923729583289916131280e-46)
}`,
ExpectError: regexp.MustCompile("Invalid function argument"),
},
// float32 negative underflow
{
Config: `
output "test" {
value = provider::framework::float32(-1.401298464324817070923729583289916131280e-46)
}`,
ExpectError: regexp.MustCompile("Invalid function argument"),
},
},
})
}
86 changes: 86 additions & 0 deletions internal/framework5provider/float32_precision_resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package framework

import (
"context"

"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
)

var _ resource.Resource = Float32PrecisionResource{}

func NewFloat32PrecisionResource() resource.Resource {
return &Float32PrecisionResource{}
}

// Float32PrecisionResource is for testing Float32/cty.Number quirks
// https://github.com/hashicorp/terraform-plugin-framework/issues/815
type Float32PrecisionResource struct{}

func (r Float32PrecisionResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_float32_precision"
}

func (r Float32PrecisionResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"float32_attribute": schema.Float32Attribute{
Optional: true,
Computed: true,
},
},
}
}

func (r Float32PrecisionResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var data Float32PrecisionResourceModel

resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

// Test semantic equality by losing the precision of the initial *big.Float
data.Float32Attribute = types.Float32Value(data.Float32Attribute.ValueFloat32())

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

func (r Float32PrecisionResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
var data Float32PrecisionResourceModel

resp.Diagnostics.Append(req.State.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

func (r Float32PrecisionResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
var data Float32PrecisionResourceModel

resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

// Test semantic equality by losing the precision of the initial *big.Float
data.Float32Attribute = types.Float32Value(data.Float32Attribute.ValueFloat32())

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

func (r Float32PrecisionResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
}

type Float32PrecisionResourceModel struct {
Float32Attribute types.Float32 `tfsdk:"float32_attribute"`
}
Loading

0 comments on commit c7c3613

Please sign in to comment.