Skip to content

Adding AtLeastSumOf, AtMostSumOf, EqualToSumOf Validators #29

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Jul 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/29.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
int64validator: Added `AtLeastSumOf()`, `AtMostSumOf()` and `EqualToSumOf()` validation functions
```
14 changes: 7 additions & 7 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,22 @@ go 1.17

require (
github.com/google/go-cmp v0.5.8
github.com/hashicorp/terraform-plugin-framework v0.9.1-0.20220711170800-89baaa204707
github.com/hashicorp/terraform-plugin-go v0.11.0
github.com/hashicorp/terraform-plugin-framework v0.10.0
github.com/hashicorp/terraform-plugin-go v0.12.0
)

require (
github.com/fatih/color v1.13.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/hashicorp/go-hclog v1.2.1 // indirect
github.com/hashicorp/terraform-plugin-log v0.4.1 // indirect
github.com/hashicorp/terraform-plugin-log v0.6.0 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect
github.com/vmihailenco/tagparser v0.1.1 // indirect
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 // indirect
google.golang.org/appengine v1.6.5 // indirect
github.com/vmihailenco/tagparser v0.1.2 // indirect
golang.org/x/net v0.0.0-20220708220712-1185a9018129 // indirect
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.28.0 // indirect
)
22 changes: 15 additions & 7 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,12 @@ github.com/hashicorp/go-hclog v1.2.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVH
github.com/hashicorp/go-plugin v1.4.4/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s=
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/terraform-plugin-framework v0.9.1-0.20220711170800-89baaa204707 h1:4wAdubsgZ/eAbCjW2At8w6UDeVCel76jWDHsWvbc8Pk=
github.com/hashicorp/terraform-plugin-framework v0.9.1-0.20220711170800-89baaa204707/go.mod h1:+H4ieVu7X4bfYlLB/zytek48e4CjcG+gjKdVOjVY1PU=
github.com/hashicorp/terraform-plugin-go v0.11.0 h1:YXsvSCx7GbQO5jIUQd77FesqmIBxgSvYAtAX1NqErTk=
github.com/hashicorp/terraform-plugin-go v0.11.0/go.mod h1:aphXBG8qtQH0yF1waMRlaw/3G+ZFlR/6Artnvt1QEDE=
github.com/hashicorp/terraform-plugin-log v0.4.1 h1:xpbmVhvuU3mgHzLetOmx9pkOL2rmgpu302XxddON6eo=
github.com/hashicorp/terraform-plugin-log v0.4.1/go.mod h1:p4R1jWBXRTvL4odmEkFfDdhUjHf9zcs/BCoNHAc7IK4=
github.com/hashicorp/terraform-plugin-framework v0.10.0 h1:LGYcnvNdVaZA1ZHe53BHLVjaaGs7HTiq6+9Js29stL4=
github.com/hashicorp/terraform-plugin-framework v0.10.0/go.mod h1:CK7Opzukfu/2CPJs+HzUdfHrFlp+ZIQeSxjF0x8k464=
github.com/hashicorp/terraform-plugin-go v0.12.0 h1:6wW9mT1dSs0Xq4LR6HXj1heQ5ovr5GxXNJwkErZzpJw=
github.com/hashicorp/terraform-plugin-go v0.12.0/go.mod h1:kwhmaWHNDvT1B3QiSJdAtrB/D4RaKSY/v3r2BuoWK4M=
github.com/hashicorp/terraform-plugin-log v0.6.0 h1:/Vq78uSIdUSZ3iqDc9PESKtwt8YqNKN6u+khD+lLjuw=
github.com/hashicorp/terraform-plugin-log v0.6.0/go.mod h1:p4R1jWBXRTvL4odmEkFfDdhUjHf9zcs/BCoNHAc7IK4=
github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c/go.mod h1:Wn3Na71knbXc1G8Lh+yu/dQWWJeFQEpDeJMtWMtlmNI=
github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734/go.mod h1:kNDNcF7sN4DocDLBkQYz73HGKwN1ANB1blq4lIYLYvg=
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
Expand Down Expand Up @@ -110,6 +110,8 @@ github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvC
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
github.com/vmihailenco/tagparser v0.1.1 h1:quXMXlA39OCbd2wAdTsGDlK9RkOk6Wuw+x37wVyIuWY=
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
github.com/vmihailenco/tagparser v0.1.2 h1:gnjoVuB/kljJ5wICEEOpx98oXMWPLj22G67Vbd1qPqc=
github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
Expand All @@ -134,6 +136,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220708220712-1185a9018129 h1:vucSRfWwTsoXro7P+3Cjlr6flUMtzCwzlvkxEQtHHB0=
golang.org/x/net v0.0.0-20220708220712-1185a9018129/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
Expand All @@ -157,6 +161,8 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAglgQfVnM9ZC6MmNLMR60=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
Expand All @@ -174,6 +180,8 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
Expand All @@ -187,7 +195,7 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0/go.mod h1:DNq5QpG7LJqD2AamLZ7zvKE0DEpVl2BSEVjFycAAjRY=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
Expand Down
115 changes: 115 additions & 0 deletions int64validator/at_least_sum_of.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package int64validator

import (
"context"
"fmt"
"strings"

"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
"github.com/hashicorp/terraform-plugin-framework/types"

"github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag"
)

var _ tfsdk.AttributeValidator = atLeastSumOfValidator{}

// atLeastSumOfValidator validates that an integer Attribute's value is at least the sum of one
// or more integer Attributes retrieved via the given path expressions.
type atLeastSumOfValidator struct {
attributesToSumPathExpressions path.Expressions
}

// Description describes the validation in plain text formatting.
func (av atLeastSumOfValidator) Description(_ context.Context) string {
var attributePaths []string
for _, p := range av.attributesToSumPathExpressions {
attributePaths = append(attributePaths, p.String())
}

return fmt.Sprintf("value must be at least sum of %s", strings.Join(attributePaths, " + "))
}

// MarkdownDescription describes the validation in Markdown formatting.
func (av atLeastSumOfValidator) MarkdownDescription(ctx context.Context) string {
return av.Description(ctx)
}

// Validate performs the validation.
func (av atLeastSumOfValidator) Validate(ctx context.Context, request tfsdk.ValidateAttributeRequest, response *tfsdk.ValidateAttributeResponse) {
i, ok := validateInt(ctx, request, response)
if !ok {
return
}

// Ensure input path expressions resolution against the current attribute
expressions := request.AttributePathExpression.MergeExpressions(av.attributesToSumPathExpressions...)

// Sum the value of all the attributes involved, but only if they are all known.
var sumOfAttribs int64
for _, expression := range expressions {
matchedPaths, diags := request.Config.PathMatches(ctx, expression)
response.Diagnostics.Append(diags...)

// Collect all errors
if diags.HasError() {
continue
}

for _, mp := range matchedPaths {
// If the user specifies the same attribute this validator is applied to,
// also as part of the input, skip it
if mp.Equal(request.AttributePath) {
continue
}

// Get the value
var matchedValue attr.Value
diags := request.Config.GetAttribute(ctx, mp, &matchedValue)
response.Diagnostics.Append(diags...)
if diags.HasError() {
continue
}

if matchedValue.IsUnknown() {
return
}

if matchedValue.IsNull() {
continue
}

// We know there is a value, convert it to the expected type
var attribToSum types.Int64
diags = tfsdk.ValueAs(ctx, matchedValue, &attribToSum)
response.Diagnostics.Append(diags...)
if diags.HasError() {
continue
}

sumOfAttribs += attribToSum.Value
}
}

if i < sumOfAttribs {
response.Diagnostics.Append(validatordiag.InvalidAttributeValueDiagnostic(
request.AttributePath,
av.Description(ctx),
fmt.Sprintf("%d", i),
))

return
}
}

// AtLeastSumOf returns an AttributeValidator which ensures that any configured
// attribute value:
//
// - Is a number, which can be represented by a 64-bit integer.
// - Is at least the sum of the attributes retrieved via the given path expression(s).
//
// Null (unconfigured) and unknown (known after apply) values are skipped.
func AtLeastSumOf(attributesToSumPathExpressions ...path.Expression) tfsdk.AttributeValidator {
return atLeastSumOfValidator{attributesToSumPathExpressions}
}
181 changes: 181 additions & 0 deletions int64validator/at_least_sum_of_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
package int64validator

import (
"context"
"testing"

"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-go/tftypes"
)

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

type testCase struct {
val attr.Value
attributesToSumExpressions path.Expressions
requestConfigRaw map[string]tftypes.Value
expectError bool
}
tests := map[string]testCase{
"not an Int64": {
val: types.Bool{Value: true},
expectError: true,
},
"unknown Int64": {
val: types.Int64{Unknown: true},
},
"null Int64": {
val: types.Int64{Null: true},
},
"valid integer as Int64 less than sum of attributes": {
val: types.Int64{Value: 10},
attributesToSumExpressions: path.Expressions{
path.MatchRoot("one"),
path.MatchRoot("two"),
},
requestConfigRaw: map[string]tftypes.Value{
"one": tftypes.NewValue(tftypes.Number, 15),
"two": tftypes.NewValue(tftypes.Number, 15),
},
Comment on lines +40 to +43
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Drive-by note: It'd be great to ensure there are unit tests covering when the one/two attributes are null and/or unknown as well. Or all three are null/unknown.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have added some additional tests.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These look great! Another good test case might be verifying that giving a path to an unexpected type (e.g. boolean attribute) always returns an error diagnostic. It appears the code should already be doing this, but it might be good to cover this for future code changes. Seems like it should be popping an additional attribute into the test schema, then referencing it in a new test case. 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have added a test case for attributePath(s) referencing unexpected types in at_least|at_most|equal_to_sum_of_test.

expectError: true,
},
"valid integer as Int64 equal to sum of attributes": {
val: types.Int64{Value: 10},
attributesToSumExpressions: path.Expressions{
path.MatchRoot("one"),
path.MatchRoot("two"),
},
requestConfigRaw: map[string]tftypes.Value{
"one": tftypes.NewValue(tftypes.Number, 5),
"two": tftypes.NewValue(tftypes.Number, 5),
},
},
"valid integer as Int64 greater than sum of attributes": {
val: types.Int64{Value: 10},
attributesToSumExpressions: path.Expressions{
path.MatchRoot("one"),
path.MatchRoot("two"),
},
requestConfigRaw: map[string]tftypes.Value{
"one": tftypes.NewValue(tftypes.Number, 4),
"two": tftypes.NewValue(tftypes.Number, 4),
},
},
"valid integer as Int64 greater than sum of attributes, when one summed attribute is null": {
val: types.Int64{Value: 10},
attributesToSumExpressions: path.Expressions{
path.MatchRoot("one"),
path.MatchRoot("two"),
},
requestConfigRaw: map[string]tftypes.Value{
"one": tftypes.NewValue(tftypes.Number, nil),
"two": tftypes.NewValue(tftypes.Number, 9),
},
},
"valid integer as Int64 does not return error when all attributes are null": {
val: types.Int64{Null: true},
attributesToSumExpressions: path.Expressions{
path.MatchRoot("one"),
path.MatchRoot("two"),
},
requestConfigRaw: map[string]tftypes.Value{
"one": tftypes.NewValue(tftypes.Number, nil),
"two": tftypes.NewValue(tftypes.Number, nil),
},
},
"valid integer as Int64 returns error when all attributes to sum are null": {
val: types.Int64{Value: -1},
attributesToSumExpressions: path.Expressions{
path.MatchRoot("one"),
path.MatchRoot("two"),
},
requestConfigRaw: map[string]tftypes.Value{
"one": tftypes.NewValue(tftypes.Number, nil),
"two": tftypes.NewValue(tftypes.Number, nil),
},
expectError: true,
},
"valid integer as Int64 greater than sum of attributes, when one summed attribute is unknown": {
val: types.Int64{Value: 10},
attributesToSumExpressions: path.Expressions{
path.MatchRoot("one"),
path.MatchRoot("two"),
},
requestConfigRaw: map[string]tftypes.Value{
"one": tftypes.NewValue(tftypes.Number, tftypes.UnknownValue),
"two": tftypes.NewValue(tftypes.Number, 9),
},
},
"valid integer as Int64 does not return error when all attributes are unknown": {
val: types.Int64{Unknown: true},
attributesToSumExpressions: path.Expressions{
path.MatchRoot("one"),
path.MatchRoot("two"),
},
requestConfigRaw: map[string]tftypes.Value{
"one": tftypes.NewValue(tftypes.Number, tftypes.UnknownValue),
"two": tftypes.NewValue(tftypes.Number, tftypes.UnknownValue),
},
},
"valid integer as Int64 does not return error when all attributes to sum are unknown": {
val: types.Int64{Value: -1},
attributesToSumExpressions: path.Expressions{
path.MatchRoot("one"),
path.MatchRoot("two"),
},
requestConfigRaw: map[string]tftypes.Value{
"one": tftypes.NewValue(tftypes.Number, tftypes.UnknownValue),
"two": tftypes.NewValue(tftypes.Number, tftypes.UnknownValue),
},
},
"error when attribute to sum is not Number": {
val: types.Int64{Value: 9},
attributesToSumExpressions: path.Expressions{
path.MatchRoot("one"),
path.MatchRoot("two"),
},
requestConfigRaw: map[string]tftypes.Value{
"one": tftypes.NewValue(tftypes.Bool, true),
"two": tftypes.NewValue(tftypes.Number, 9),
},
expectError: true,
},
}

for name, test := range tests {
name, test := name, test
t.Run(name, func(t *testing.T) {
request := tfsdk.ValidateAttributeRequest{
AttributePath: path.Root("test"),
AttributePathExpression: path.MatchRoot("test"),
AttributeConfig: test.val,
Config: tfsdk.Config{
Raw: tftypes.NewValue(tftypes.Object{}, test.requestConfigRaw),
Schema: tfsdk.Schema{
Attributes: map[string]tfsdk.Attribute{
"test": {Type: types.Int64Type},
"one": {Type: types.Int64Type},
"two": {Type: types.Int64Type},
},
},
},
}

response := tfsdk.ValidateAttributeResponse{}

AtLeastSumOf(test.attributesToSumExpressions...).Validate(context.Background(), request, &response)

if !response.Diagnostics.HasError() && test.expectError {
t.Fatal("expected error, got no error")
}

if response.Diagnostics.HasError() && !test.expectError {
t.Fatalf("got unexpected error: %s", response.Diagnostics)
}
})
}
}
Loading