diff --git a/internal/reflect/number.go b/internal/reflect/number.go index 1960d7e12..168ff7bb9 100644 --- a/internal/reflect/number.go +++ b/internal/reflect/number.go @@ -11,11 +11,12 @@ import ( "reflect" "strconv" + "github.com/hashicorp/terraform-plugin-go/tftypes" + "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/attr/xattr" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/path" - "github.com/hashicorp/terraform-plugin-go/tftypes" ) // Number creates a *big.Float and populates it with the data in `val`. It then @@ -168,65 +169,28 @@ func Number(ctx context.Context, typ attr.Type, val tftypes.Value, target reflec return reflect.ValueOf(uintResult), diags } case reflect.Float32: - floatResult, acc := result.Float32() - if acc != big.Exact && !opts.AllowRoundingNumbers { - return target, append(diags, roundingErrorDiag) - } else if acc == big.Above { - floatResult = math.MaxFloat32 - } else if acc == big.Below { - floatResult = math.SmallestNonzeroFloat32 - } else if acc != big.Exact { - err := fmt.Errorf("unsure how to round %s and %f", acc, floatResult) - diags.AddAttributeError( - path, - "Value Conversion Error", - "An unexpected error was encountered trying to convert to number. This is always an error in the provider. Please report the following to the provider developer:\n\n"+err.Error(), - ) + floatResult, _ := result.Float32() + + bf := big.NewFloat(float64(floatResult)) + + if result.Text('f', -1) != bf.Text('f', -1) { + diags.Append(roundingErrorDiag) + return target, diags } + return reflect.ValueOf(floatResult), diags case reflect.Float64: - floatResult, acc := result.Float64() - if acc != big.Exact && !opts.AllowRoundingNumbers { - return target, append(diags, roundingErrorDiag) - } - if acc == big.Above { - if floatResult == math.Inf(1) || floatResult == math.MaxFloat64 { - floatResult = math.MaxFloat64 - } else if floatResult == 0.0 || floatResult == math.SmallestNonzeroFloat64 { - floatResult = -math.SmallestNonzeroFloat64 - } else { - err := fmt.Errorf("not sure how to round %s and %f", acc, floatResult) - diags.AddAttributeError( - path, - "Value Conversion Error", - "An unexpected error was encountered trying to convert to number. This is always an error in the provider. Please report the following to the provider developer:\n\n"+err.Error(), - ) - return target, diags - } - } else if acc == big.Below { - if floatResult == math.Inf(-1) || floatResult == -math.MaxFloat64 { - floatResult = -math.MaxFloat64 - } else if floatResult == -0.0 || floatResult == -math.SmallestNonzeroFloat64 { //nolint:staticcheck - floatResult = math.SmallestNonzeroFloat64 - } else { - err := fmt.Errorf("not sure how to round %s and %f", acc, floatResult) - diags.AddAttributeError( - path, - "Value Conversion Error", - "An unexpected error was encountered trying to convert to number. This is always an error in the provider. Please report the following to the provider developer:\n\n"+err.Error(), - ) - return target, diags - } - } else if acc != big.Exact { - err := fmt.Errorf("not sure how to round %s and %f", acc, floatResult) - diags.AddAttributeError( - path, - "Value Conversion Error", - "An unexpected error was encountered trying to convert to number. This is always an error in the provider. Please report the following to the provider developer:\n\n"+err.Error(), - ) + floatResult, _ := result.Float64() + + bf := big.NewFloat(floatResult) + + if result.Text('f', -1) != bf.Text('f', -1) { + diags.Append(roundingErrorDiag) + return target, diags } + return reflect.ValueOf(floatResult), diags } err = fmt.Errorf("cannot convert number to %s", target.Type()) diff --git a/internal/reflect/number_test.go b/internal/reflect/number_test.go index 209347998..e52631701 100644 --- a/internal/reflect/number_test.go +++ b/internal/reflect/number_test.go @@ -12,13 +12,14 @@ import ( "testing" "github.com/google/go-cmp/cmp" + "github.com/hashicorp/terraform-plugin-go/tftypes" + "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/diag" refl "github.com/hashicorp/terraform-plugin-framework/internal/reflect" "github.com/hashicorp/terraform-plugin-framework/internal/testing/testtypes" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/hashicorp/terraform-plugin-go/tftypes" ) var ( @@ -945,23 +946,6 @@ func TestNumber_float32(t *testing.T) { t.Parallel() } -func TestNumber_float32Overflow(t *testing.T) { - t.Parallel() - - var n float32 - - result, diags := refl.Number(context.Background(), types.NumberType, tftypes.NewValue(tftypes.Number, math.MaxFloat64), reflect.ValueOf(n), refl.Options{ - AllowRoundingNumbers: true, - }, path.Empty()) - if diags.HasError() { - t.Errorf("Unexpected error: %v", diags) - } - reflect.ValueOf(&n).Elem().Set(result) - if n != math.MaxFloat32 { - t.Errorf("Expected %v, got %v", math.MaxFloat32, n) - } -} - func TestNumber_float32OverflowError(t *testing.T) { t.Parallel() @@ -981,23 +965,6 @@ func TestNumber_float32OverflowError(t *testing.T) { } } -func TestNumber_float32Underflow(t *testing.T) { - t.Parallel() - - var n float32 - - result, diags := refl.Number(context.Background(), types.NumberType, tftypes.NewValue(tftypes.Number, math.SmallestNonzeroFloat64), reflect.ValueOf(n), refl.Options{ - AllowRoundingNumbers: true, - }, path.Empty()) - if diags.HasError() { - t.Errorf("Unexpected error: %v", diags) - } - reflect.ValueOf(&n).Elem().Set(result) - if n != math.SmallestNonzeroFloat32 { - t.Errorf("Expected %v, got %v", math.SmallestNonzeroFloat32, n) - } -} - func TestNumber_float32UnderflowError(t *testing.T) { t.Parallel() @@ -1032,23 +999,6 @@ func TestNumber_float64(t *testing.T) { } } -func TestNumber_float64Overflow(t *testing.T) { - t.Parallel() - - var n float64 - - result, diags := refl.Number(context.Background(), types.NumberType, tftypes.NewValue(tftypes.Number, overflowFloat), reflect.ValueOf(n), refl.Options{ - AllowRoundingNumbers: true, - }, path.Empty()) - if diags.HasError() { - t.Errorf("Unexpected error: %v", diags) - } - reflect.ValueOf(&n).Elem().Set(result) - if n != math.MaxFloat64 { - t.Errorf("Expected %v, got %v", math.MaxFloat64, n) - } -} - func TestNumber_float64OverflowError(t *testing.T) { t.Parallel() @@ -1068,23 +1018,6 @@ func TestNumber_float64OverflowError(t *testing.T) { } } -func TestNumber_float64OverflowNegative(t *testing.T) { - t.Parallel() - - var n float64 - - result, diags := refl.Number(context.Background(), types.NumberType, tftypes.NewValue(tftypes.Number, overflowNegativeFloat), reflect.ValueOf(n), refl.Options{ - AllowRoundingNumbers: true, - }, path.Empty()) - if diags.HasError() { - t.Errorf("Unexpected error: %v", diags) - } - reflect.ValueOf(&n).Elem().Set(result) - if n != -math.MaxFloat64 { - t.Errorf("Expected %v, got %v", -math.MaxFloat64, n) - } -} - func TestNumber_float64OverflowNegativeError(t *testing.T) { t.Parallel() @@ -1104,23 +1037,6 @@ func TestNumber_float64OverflowNegativeError(t *testing.T) { } } -func TestNumber_float64Underflow(t *testing.T) { - t.Parallel() - - var n float64 - - result, diags := refl.Number(context.Background(), types.NumberType, tftypes.NewValue(tftypes.Number, underflowFloat), reflect.ValueOf(n), refl.Options{ - AllowRoundingNumbers: true, - }, path.Empty()) - if diags.HasError() { - t.Errorf("Unexpected error: %v", diags) - } - reflect.ValueOf(&n).Elem().Set(result) - if n != math.SmallestNonzeroFloat64 { - t.Errorf("Expected %v, got %v", math.SmallestNonzeroFloat64, n) - } -} - func TestNumber_float64UnderflowError(t *testing.T) { t.Parallel() @@ -1140,23 +1056,6 @@ func TestNumber_float64UnderflowError(t *testing.T) { } } -func TestNumber_float64UnderflowNegative(t *testing.T) { - t.Parallel() - - var n float64 - - result, diags := refl.Number(context.Background(), types.NumberType, tftypes.NewValue(tftypes.Number, underflowNegativeFloat), reflect.ValueOf(n), refl.Options{ - AllowRoundingNumbers: true, - }, path.Empty()) - if diags.HasError() { - t.Errorf("Unexpected error: %v", diags) - } - reflect.ValueOf(&n).Elem().Set(result) - if n != -math.SmallestNonzeroFloat64 { - t.Errorf("Expected %v, got %v", -math.SmallestNonzeroFloat64, n) - } -} - func TestNumber_float64UnderflowNegativeError(t *testing.T) { t.Parallel()