Skip to content

Commit

Permalink
knownvalue: Add Int32Exact and Float32Exact checks (#356)
Browse files Browse the repository at this point in the history
* Add `float32exact` and `int32exact` types

* Update website documentation

* Add changelog entries

* Update changelog wording
  • Loading branch information
SBGoods authored Jul 1, 2024
1 parent 1589250 commit ac2ce0a
Show file tree
Hide file tree
Showing 13 changed files with 361 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changes/unreleased/ENHANCEMENTS-20240626-163240.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
kind: ENHANCEMENTS
body: 'knownvalue: Add `Int32Exact` check for int32 value testing.'
time: 2024-06-26T16:32:40.387821-04:00
custom:
Issue: "356"
5 changes: 5 additions & 0 deletions .changes/unreleased/ENHANCEMENTS-20240626-163311.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
kind: ENHANCEMENTS
body: 'knownvalue: Add `Float32Exact` check for float32 value testing.'
time: 2024-06-26T16:33:11.495969-04:00
custom:
Issue: "356"
51 changes: 51 additions & 0 deletions knownvalue/float32.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package knownvalue

import (
"encoding/json"
"fmt"
"strconv"
)

var _ Check = float32Exact{}

type float32Exact struct {
value float32
}

// CheckValue determines whether the passed value is of type float32, and
// contains a matching float32 value.
func (v float32Exact) CheckValue(other any) error {
jsonNum, ok := other.(json.Number)

if !ok {
return fmt.Errorf("expected json.Number value for Float32Exact check, got: %T", other)
}

otherVal, err := strconv.ParseFloat(string(jsonNum), 32)

if err != nil {
return fmt.Errorf("expected json.Number to be parseable as float32 value for Float32Exact check: %s", err)
}

if float32(otherVal) != v.value {
return fmt.Errorf("expected value %s for Float32Exact check, got: %s", v.String(), strconv.FormatFloat(otherVal, 'f', -1, 32))
}

return nil
}

// String returns the string representation of the float32 value.
func (v float32Exact) String() string {
return strconv.FormatFloat(float64(v.value), 'f', -1, 32)
}

// Float32Exact returns a Check for asserting equality between the
// supplied float32 and the value passed to the CheckValue method.
func Float32Exact(value float32) float32Exact {
return float32Exact{
value: value,
}
}
75 changes: 75 additions & 0 deletions knownvalue/float32_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package knownvalue_test

import (
"encoding/json"
"fmt"
"testing"

"github.com/google/go-cmp/cmp"

"github.com/hashicorp/terraform-plugin-testing/knownvalue"
)

func TestFloat32Value_CheckValue(t *testing.T) {
t.Parallel()

testCases := map[string]struct {
self knownvalue.Check
other any
expectedError error
}{
"zero-nil": {
self: knownvalue.Float32Exact(0),
expectedError: fmt.Errorf("expected json.Number value for Float32Exact check, got: <nil>"),
},
"zero-other": {
self: knownvalue.Float32Exact(0),
other: json.Number("0.0"), // checking against the underlying value field zero-value
},
"nil": {
self: knownvalue.Float32Exact(1.234),
expectedError: fmt.Errorf("expected json.Number value for Float32Exact check, got: <nil>"),
},
"wrong-type": {
self: knownvalue.Float32Exact(1.234),
other: json.Number("str"),
expectedError: fmt.Errorf("expected json.Number to be parseable as float32 value for Float32Exact check: strconv.ParseFloat: parsing \"str\": invalid syntax"),
},
"not-equal": {
self: knownvalue.Float32Exact(1.234),
other: json.Number("4.321"),
expectedError: fmt.Errorf("expected value 1.234 for Float32Exact check, got: 4.321"),
},
"equal": {
self: knownvalue.Float32Exact(1.234),
other: json.Number("1.234"),
},
}

for name, testCase := range testCases {
name, testCase := name, testCase

t.Run(name, func(t *testing.T) {
t.Parallel()

got := testCase.self.CheckValue(testCase.other)

if diff := cmp.Diff(got, testCase.expectedError, equateErrorMessage); diff != "" {
t.Errorf("unexpected difference: %s", diff)
}
})
}
}

func TestFloat32Value_String(t *testing.T) {
t.Parallel()

got := knownvalue.Float32Exact(1.234567890123e+03).String()

if diff := cmp.Diff(got, "1234.5679"); diff != "" {
t.Errorf("unexpected difference: %s", diff)
}
}
51 changes: 51 additions & 0 deletions knownvalue/int32.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package knownvalue

import (
"encoding/json"
"fmt"
"strconv"
)

var _ Check = int32Exact{}

type int32Exact struct {
value int32
}

// CheckValue determines whether the passed value is of type int32, and
// contains a matching int32 value.
func (v int32Exact) CheckValue(other any) error {
jsonNum, ok := other.(json.Number)

if !ok {
return fmt.Errorf("expected json.Number value for Int32Exact check, got: %T", other)
}

otherVal, err := strconv.ParseInt(string(jsonNum), 10, 32)

if err != nil {
return fmt.Errorf("expected json.Number to be parseable as int32 value for Int32Exact check: %s", err)
}

if int32(otherVal) != v.value {
return fmt.Errorf("expected value %d for Int32Exact check, got: %d", v.value, otherVal)
}

return nil
}

// String returns the string representation of the int32 value.
func (v int32Exact) String() string {
return strconv.FormatInt(int64(v.value), 10)
}

// Int32Exact returns a Check for asserting equality between the
// supplied int32 and the value passed to the CheckValue method.
func Int32Exact(value int32) int32Exact {
return int32Exact{
value: value,
}
}
75 changes: 75 additions & 0 deletions knownvalue/int32_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package knownvalue_test

import (
"encoding/json"
"fmt"
"testing"

"github.com/google/go-cmp/cmp"

"github.com/hashicorp/terraform-plugin-testing/knownvalue"
)

func TestInt32Value_CheckValue(t *testing.T) {
t.Parallel()

testCases := map[string]struct {
self knownvalue.Check
other any
expectedError error
}{
"zero-nil": {
self: knownvalue.Int32Exact(0),
expectedError: fmt.Errorf("expected json.Number value for Int32Exact check, got: <nil>"),
},
"zero-other": {
self: knownvalue.Int32Exact(0),
other: json.Number("0"), // checking against the underlying value field zero-value
},
"nil": {
self: knownvalue.Int32Exact(1234),
expectedError: fmt.Errorf("expected json.Number value for Int32Exact check, got: <nil>"),
},
"wrong-type": {
self: knownvalue.Int32Exact(1234),
other: json.Number("str"),
expectedError: fmt.Errorf("expected json.Number to be parseable as int32 value for Int32Exact check: strconv.ParseInt: parsing \"str\": invalid syntax"),
},
"not-equal": {
self: knownvalue.Int32Exact(1234),
other: json.Number("4321"),
expectedError: fmt.Errorf("expected value 1234 for Int32Exact check, got: 4321"),
},
"equal": {
self: knownvalue.Int32Exact(1234),
other: json.Number("1234"),
},
}

for name, testCase := range testCases {
name, testCase := name, testCase

t.Run(name, func(t *testing.T) {
t.Parallel()

got := testCase.self.CheckValue(testCase.other)

if diff := cmp.Diff(got, testCase.expectedError, equateErrorMessage); diff != "" {
t.Errorf("unexpected difference: %s", diff)
}
})
}
}

func TestInt32Value_String(t *testing.T) {
t.Parallel()

got := knownvalue.Int32Exact(123456789).String()

if diff := cmp.Diff(got, "123456789"); diff != "" {
t.Errorf("unexpected difference: %s", diff)
}
}
8 changes: 8 additions & 0 deletions website/data/plugin-testing-nav-data.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,18 @@
"title": "Custom",
"path": "acceptance-tests/known-value-checks/custom"
},
{
"title": "Float32",
"path": "acceptance-tests/known-value-checks/float32"
},
{
"title": "Float64",
"path": "acceptance-tests/known-value-checks/float64"
},
{
"title": "Int32",
"path": "acceptance-tests/known-value-checks/int32"
},
{
"title": "Int64",
"path": "acceptance-tests/known-value-checks/int64"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ The `other` parameter passed to the `CheckValue` method is one of the following
Refer to the following built-in known value checks for implementations that handle the different types that can be passed to the `CheckValue` method in the `other` parameter:

* [Bool](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Bool)
* [Float32Exact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Float32Exact)
* [Float64Exact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Float64Exact)
* [Int32Exact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Int32Exact)
* [Int64Exact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Int64Exact)
* [ListExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ListExact)
* [MapExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#MapExact)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
page_title: 'Plugin Development - Acceptance Testing: Known Values'
description: >-
Float32 Value Checks for use with Plan Checks.
---

# Float32 Known Value Checks

The known value checks that are available for float32 values are:

* [Float32Exact](/terraform/plugin/testing/acceptance-tests/known-value-checks/float32#float32exact-check)

## `Float32Exact` Check

The [Float32Exact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Float32Exact) check tests that a resource attribute, or output value has an exactly matching float32 value.

Example usage of [Float32Exact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Float32Exact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check.

```go
func TestExpectKnownValue_CheckPlan_Float32(t *testing.T) {
t.Parallel()

resource.Test(t, resource.TestCase{
// Provider definition omitted.
Steps: []resource.TestStep{
{
// Example resource containing a computed float32 attribute named "computed_attribute"
Config: `resource "test_resource" "one" {}`,
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{
plancheck.ExpectKnownValue(
"test_resource.one",
tfjsonpath.New("computed_attribute"),
knownvalue.Float32Exact(1.23),
),
},
},
},
},
})
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ The following table shows the correspondence between [knownvalue.Check](https://
| Known Value Check Type | Framework Attribute Type | SDKv2 Attribute Type |
|------------------------------------------------------------------------------------------------------|---------------------------|----------------------|
| [Bool Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks/bool) | `schema.BoolAttribute` | `schema.TypeBool` |
| [Float32 Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks/float32) | `schema.Float32Attribute` | `schema.TypeFloat` |
| [Float64 Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks/float64) | `schema.Float64Attribute` | `schema.TypeFloat` |
| [Int32 Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks/int32) | `schema.Int32Attribute` | `schema.TypeInt` |
| [Int64 Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks/int64) | `schema.Int64Attribute` | `schema.TypeInt` |
| [List Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks/list) | `schema.ListAttribute` | `schema.TypeList` |
| [Map Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks/map) | `schema.MapAttribute` | `schema.TypeMap` |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
page_title: 'Plugin Development - Acceptance Testing: Known Values'
description: >-
Int32 Value Checks for use with Plan Checks.
---

# Int32 Known Value Checks

The known value checks that are available for int32 values are:

* [Int32Exact](/terraform/plugin/testing/acceptance-tests/known-value-checks/int32#int32exact-check)

## `Int32Exact` Check

The [Int32Exact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Int32Exact) check tests that a resource attribute, or output value has an exactly matching int32 value.

Example usage of [Int32Exact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Int32Exact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check.

```go
func TestExpectKnownValue_CheckPlan_Int32(t *testing.T) {
t.Parallel()

resource.Test(t, resource.TestCase{
// Provider definition omitted.
Steps: []resource.TestStep{
{
// Example resource containing a computed int32 attribute named "computed_attribute"
Config: `resource "test_resource" "one" {}`,
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{
plancheck.ExpectKnownValue(
"test_resource.one",
tfjsonpath.New("computed_attribute"),
knownvalue.Int32Exact(123),
),
},
},
},
},
})
}
```
Loading

0 comments on commit ac2ce0a

Please sign in to comment.