From f67b3e766436ba2b070be8c29d66f7e72d0e1bbb Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Tue, 9 Jan 2024 11:19:37 +0000 Subject: [PATCH 01/73] Adding StateCheck interface (#266) * Configuring when state checks are executed. * Testing that state checks are executed. --- helper/resource/state_checks.go | 29 +++++ helper/resource/state_checks_test.go | 22 ++++ helper/resource/testing.go | 12 ++ helper/resource/testing_new_config.go | 20 ++++ helper/resource/testing_new_config_test.go | 124 +++++++++++++++++++++ statecheck/doc.go | 5 + statecheck/state_check.go | 30 +++++ 7 files changed, 242 insertions(+) create mode 100644 helper/resource/state_checks.go create mode 100644 helper/resource/state_checks_test.go create mode 100644 statecheck/doc.go create mode 100644 statecheck/state_check.go diff --git a/helper/resource/state_checks.go b/helper/resource/state_checks.go new file mode 100644 index 000000000..66c850eae --- /dev/null +++ b/helper/resource/state_checks.go @@ -0,0 +1,29 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package resource + +import ( + "context" + "errors" + + tfjson "github.com/hashicorp/terraform-json" + "github.com/mitchellh/go-testing-interface" + + "github.com/hashicorp/terraform-plugin-testing/statecheck" +) + +func runStateChecks(ctx context.Context, t testing.T, state *tfjson.State, stateChecks []statecheck.StateCheck) error { + t.Helper() + + var result []error + + for _, stateCheck := range stateChecks { + resp := statecheck.CheckStateResponse{} + stateCheck.CheckState(ctx, statecheck.CheckStateRequest{State: state}, &resp) + + result = append(result, resp.Error) + } + + return errors.Join(result...) +} diff --git a/helper/resource/state_checks_test.go b/helper/resource/state_checks_test.go new file mode 100644 index 000000000..e8ab33753 --- /dev/null +++ b/helper/resource/state_checks_test.go @@ -0,0 +1,22 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package resource + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-testing/statecheck" +) + +var _ statecheck.StateCheck = &stateCheckSpy{} + +type stateCheckSpy struct { + err error + called bool +} + +func (s *stateCheckSpy) CheckState(ctx context.Context, req statecheck.CheckStateRequest, resp *statecheck.CheckStateResponse) { + s.called = true + resp.Error = s.err +} diff --git a/helper/resource/testing.go b/helper/resource/testing.go index 581152f72..5abda4eaa 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -24,6 +24,7 @@ import ( "github.com/hashicorp/terraform-plugin-testing/config" "github.com/hashicorp/terraform-plugin-testing/plancheck" + "github.com/hashicorp/terraform-plugin-testing/statecheck" "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/hashicorp/terraform-plugin-testing/tfversion" @@ -590,6 +591,13 @@ type TestStep struct { // [plancheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck RefreshPlanChecks RefreshPlanChecks + // ConfigStateChecks allow assertions to be made against the state file at different points of a Config (apply) test using a state check. + // Custom state checks can be created by implementing the [StateCheck] interface, or by using a StateCheck implementation from the provided [statecheck] package + // + // [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck + // [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck + ConfigStateChecks ConfigStateChecks + // PlanOnly can be set to only run `plan` with this configuration, and not // actually apply it. This is useful for ensuring config changes result in // no-op plans @@ -795,6 +803,10 @@ type RefreshPlanChecks struct { PostRefresh []plancheck.PlanCheck } +// ConfigStateChecks runs all state checks in the slice. This occurs after the apply and refresh of a Config test are run. +// All errors by state checks in this slice are aggregated, reported, and will result in a test failure. +type ConfigStateChecks []statecheck.StateCheck + // ParallelTest performs an acceptance test on a resource, allowing concurrency // with other ParallelTest. The number of concurrent tests is controlled by the // "go test" command -parallel flag. diff --git a/helper/resource/testing_new_config.go b/helper/resource/testing_new_config.go index 35e605c1d..17d3745fa 100644 --- a/helper/resource/testing_new_config.go +++ b/helper/resource/testing_new_config.go @@ -313,6 +313,26 @@ func testStepNewConfig(ctx context.Context, t testing.T, c TestCase, wd *plugint } } + // Run post-apply, post-refresh state checks + if len(step.ConfigStateChecks) > 0 { + var state *tfjson.State + + err = runProviderCommand(ctx, t, func() error { + var err error + state, err = wd.State(ctx) + return err + }, wd, providers) + + if err != nil { + return fmt.Errorf("Error retrieving post-apply, post-refresh state: %w", err) + } + + err = runStateChecks(ctx, t, state, step.ConfigStateChecks) + if err != nil { + return fmt.Errorf("Post-apply refresh state check(s) failed:\n%w", err) + } + } + // check if plan is empty if !planIsEmpty(plan, helper.TerraformVersion()) && !step.ExpectNonEmptyPlan { var stdout string diff --git a/helper/resource/testing_new_config_test.go b/helper/resource/testing_new_config_test.go index b54eb4282..fe0eb707e 100644 --- a/helper/resource/testing_new_config_test.go +++ b/helper/resource/testing_new_config_test.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/terraform-plugin-go/tfprotov6" "github.com/hashicorp/terraform-plugin-go/tftypes" + "github.com/hashicorp/terraform-plugin-testing/internal/testing/testprovider" "github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/providerserver" "github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/resource" @@ -717,3 +718,126 @@ func Test_ConfigPlanChecks_PostApplyPostRefresh_Errors(t *testing.T) { }, }) } + +func Test_ConfigStateChecks_Called(t *testing.T) { + t.Parallel() + + spy1 := &stateCheckSpy{} + spy2 := &stateCheckSpy{} + UnitTest(t, TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_0_0), // ProtoV6ProviderFactories + }, + ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ + "test": providerserver.NewProviderServer(testprovider.Provider{ + Resources: map[string]testprovider.Resource{ + "test_resource": { + CreateResponse: &resource.CreateResponse{ + NewState: tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "id": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "id": tftypes.NewValue(tftypes.String, "test"), + }, + ), + }, + SchemaResponse: &resource.SchemaResponse{ + Schema: &tfprotov6.Schema{ + Block: &tfprotov6.SchemaBlock{ + Attributes: []*tfprotov6.SchemaAttribute{ + { + Name: "id", + Type: tftypes.String, + Computed: true, + }, + }, + }, + }, + }, + }, + }, + }), + }, + Steps: []TestStep{ + { + Config: `resource "test_resource" "test" {}`, + ConfigStateChecks: ConfigStateChecks{ + spy1, + spy2, + }, + }, + }, + }) + + if !spy1.called { + t.Error("expected ConfigStateChecks spy1 to be called at least once") + } + + if !spy2.called { + t.Error("expected ConfigStateChecks spy2 to be called at least once") + } +} + +func Test_ConfigStateChecks_Errors(t *testing.T) { + t.Parallel() + + spy1 := &stateCheckSpy{} + spy2 := &stateCheckSpy{ + err: errors.New("spy2 check failed"), + } + spy3 := &stateCheckSpy{ + err: errors.New("spy3 check failed"), + } + UnitTest(t, TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_0_0), // ProtoV6ProviderFactories + }, + ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ + "test": providerserver.NewProviderServer(testprovider.Provider{ + Resources: map[string]testprovider.Resource{ + "test_resource": { + CreateResponse: &resource.CreateResponse{ + NewState: tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "id": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "id": tftypes.NewValue(tftypes.String, "test"), + }, + ), + }, + SchemaResponse: &resource.SchemaResponse{ + Schema: &tfprotov6.Schema{ + Block: &tfprotov6.SchemaBlock{ + Attributes: []*tfprotov6.SchemaAttribute{ + { + Name: "id", + Type: tftypes.String, + Computed: true, + }, + }, + }, + }, + }, + }, + }, + }), + }, + Steps: []TestStep{ + { + Config: `resource "test_resource" "test" {}`, + ConfigStateChecks: ConfigStateChecks{ + spy1, + spy2, + spy3, + }, + ExpectError: regexp.MustCompile(`.*?(spy2 check failed)\n.*?(spy3 check failed)`), + }, + }, + }) +} diff --git a/statecheck/doc.go b/statecheck/doc.go new file mode 100644 index 000000000..eba32447d --- /dev/null +++ b/statecheck/doc.go @@ -0,0 +1,5 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// Package statecheck contains the state check interface, request/response structs, and common state check implementations. +package statecheck diff --git a/statecheck/state_check.go b/statecheck/state_check.go new file mode 100644 index 000000000..cfd2da6b1 --- /dev/null +++ b/statecheck/state_check.go @@ -0,0 +1,30 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package statecheck + +import ( + "context" + + tfjson "github.com/hashicorp/terraform-json" +) + +// StateCheck defines an interface for implementing test logic that checks a state file and then returns an error +// if the state file does not match what is expected. +type StateCheck interface { + // CheckState should perform the state check. + CheckState(context.Context, CheckStateRequest, *CheckStateResponse) +} + +// CheckStateRequest is a request for an invoke of the CheckState function. +type CheckStateRequest struct { + // State represents a parsed state file, retrieved via the `terraform show -json` command. + State *tfjson.State +} + +// CheckStateResponse is a response to an invoke of the CheckState function. +type CheckStateResponse struct { + // Error is used to report the failure of a state check assertion and is combined with other StateCheck errors + // to be reported as a test failure. + Error error +} From eed2a1287574bd92cae6e1b601a70f030a8e9186 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Tue, 9 Jan 2024 11:29:11 +0000 Subject: [PATCH 02/73] Adding validation to ensure state checks are only defined for config (apply) tests (#266) --- helper/resource/teststep_validate.go | 8 +++++++- helper/resource/teststep_validate_test.go | 10 ++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/helper/resource/teststep_validate.go b/helper/resource/teststep_validate.go index d63db4dc8..8590ca466 100644 --- a/helper/resource/teststep_validate.go +++ b/helper/resource/teststep_validate.go @@ -15,7 +15,7 @@ import ( // testStepValidateRequest contains data for the (TestStep).validate() method. type testStepValidateRequest struct { // StepConfiguration contains the TestStep configuration derived from - // TestStep.Config or TestStep.ConfigDirectory. + // TestStep.Config, TestStep.ConfigDirectory, or TestStep.ConfigFile. StepConfiguration teststep.Config // StepNumber is the index of the TestStep in the TestCase.Steps. @@ -235,5 +235,11 @@ func (s TestStep) validate(ctx context.Context, req testStepValidateRequest) err return err } + if len(s.ConfigStateChecks) > 0 && req.StepConfiguration == nil { + err := fmt.Errorf("TestStep ConfigStateChecks must only be specified with Config, ConfigDirectory or ConfigFile") + logging.HelperResourceError(ctx, "TestStep validation error", map[string]interface{}{logging.KeyError: err}) + return err + } + return nil } diff --git a/helper/resource/teststep_validate_test.go b/helper/resource/teststep_validate_test.go index c5f19a60e..6a326e003 100644 --- a/helper/resource/teststep_validate_test.go +++ b/helper/resource/teststep_validate_test.go @@ -466,6 +466,16 @@ func TestTestStepValidate(t *testing.T) { testStepValidateRequest: testStepValidateRequest{TestCaseHasProviders: true}, expectedError: errors.New("TestStep ConfigPlanChecks.PostApplyPostRefresh must only be specified with Config"), }, + "configstatechecks-not-config-mode": { + testStep: TestStep{ + ConfigStateChecks: ConfigStateChecks{ + &stateCheckSpy{}, + }, + RefreshState: true, + }, + testStepValidateRequest: testStepValidateRequest{TestCaseHasProviders: true}, + expectedError: errors.New("TestStep ConfigStateChecks must only be specified with Config"), + }, "refreshplanchecks-postrefresh-not-refresh-mode": { testStep: TestStep{ RefreshPlanChecks: RefreshPlanChecks{ From d4e31d3babd2d9cb019b343bf2c99b6d4906abf4 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Tue, 9 Jan 2024 11:58:57 +0000 Subject: [PATCH 03/73] Adding ExpectKnownValue state check (#266) --- statecheck/expect_known_value.go | 94 ++ statecheck/expect_known_value_test.go | 1412 +++++++++++++++++++++++++ 2 files changed, 1506 insertions(+) create mode 100644 statecheck/expect_known_value.go create mode 100644 statecheck/expect_known_value_test.go diff --git a/statecheck/expect_known_value.go b/statecheck/expect_known_value.go new file mode 100644 index 000000000..2f073f15c --- /dev/null +++ b/statecheck/expect_known_value.go @@ -0,0 +1,94 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package statecheck + +import ( + "context" + "fmt" + "reflect" + + tfjson "github.com/hashicorp/terraform-json" + + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + +// Resource State Check +var _ StateCheck = expectKnownValue{} + +type expectKnownValue struct { + resourceAddress string + attributePath tfjsonpath.Path + knownValue knownvalue.Check +} + +// CheckState implements the state check logic. +func (e expectKnownValue) CheckState(ctx context.Context, req CheckStateRequest, resp *CheckStateResponse) { + var rc *tfjson.StateResource + + if req.State.Values == nil { + resp.Error = fmt.Errorf("state does not contain any state values") + } + + if req.State.Values.RootModule == nil { + resp.Error = fmt.Errorf("state does not contain a root module") + } + + for _, resourceChange := range req.State.Values.RootModule.Resources { + if e.resourceAddress == resourceChange.Address { + rc = resourceChange + + break + } + } + + if rc == nil { + resp.Error = fmt.Errorf("%s - Resource not found in state", e.resourceAddress) + + return + } + + result, err := tfjsonpath.Traverse(rc.AttributeValues, e.attributePath) + + if err != nil { + resp.Error = err + + return + } + + if result == nil { + resp.Error = fmt.Errorf("value is null") + + return + } + + switch reflect.TypeOf(result).Kind() { + case reflect.Bool, + reflect.Map, + reflect.Slice, + reflect.String: + if err := e.knownValue.CheckValue(result); err != nil { + resp.Error = err + + return + } + default: + errorStr := fmt.Sprintf("unrecognised attribute type: %T, known value type is %T", result, e.knownValue) + errorStr += "\n\nThis is an error in statecheck.ExpectKnownValue.\nPlease report this to the maintainers." + + resp.Error = fmt.Errorf(errorStr) + + return + } +} + +// ExpectKnownValue returns a state check that asserts that the specified attribute at the given resource +// has a known type and value. +func ExpectKnownValue(resourceAddress string, attributePath tfjsonpath.Path, knownValue knownvalue.Check) StateCheck { + return expectKnownValue{ + resourceAddress: resourceAddress, + attributePath: attributePath, + knownValue: knownValue, + } +} diff --git a/statecheck/expect_known_value_test.go b/statecheck/expect_known_value_test.go new file mode 100644 index 000000000..bd1024891 --- /dev/null +++ b/statecheck/expect_known_value_test.go @@ -0,0 +1,1412 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package statecheck_test + +import ( + "context" + "fmt" + "math/big" + "regexp" + "testing" + + "github.com/google/go-cmp/cmp" + tfjson "github.com/hashicorp/terraform-json" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + r "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + +func TestExpectKnownValue_CheckState_ResourceNotFound(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.two", + tfjsonpath.New("bool_attribute"), + knownvalue.BoolValueExact(true), + ), + }, + ExpectError: regexp.MustCompile("test_resource.two - Resource not found in state"), + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_AttributeValueNull(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" {}`, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + knownvalue.BoolValueExact(true), + ), + }, + ExpectError: regexp.MustCompile("value is null"), + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_Bool(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + knownvalue.BoolValueExact(true), + ), + }, + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_Bool_KnownValueWrongType(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + knownvalue.Float64ValueExact(1.23), + ), + }, + ExpectError: regexp.MustCompile(`expected json\.Number value for Float64Value check, got: bool`), + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_Bool_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + knownvalue.BoolValueExact(false), + ), + }, + ExpectError: regexp.MustCompile("expected value false for BoolValue check, got: true"), + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_Float64(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + float_attribute = 1.23 + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("float_attribute"), + knownvalue.Float64ValueExact(1.23), + ), + }, + }, + }, + }) +} + +// We do not need equivalent tests for Int64 and Number as they all test the same logic. +func TestExpectKnownValue_CheckState_Float64_KnownValueWrongType(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + float_attribute = 1.23 + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("float_attribute"), + knownvalue.StringValueExact("str"), + ), + }, + ExpectError: regexp.MustCompile(`expected string value for StringValue check, got: json\.Number`), + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_Float64_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + float_attribute = 1.23 + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("float_attribute"), + knownvalue.Float64ValueExact(3.21), + ), + }, + ExpectError: regexp.MustCompile("expected value 3.21 for Float64Value check, got: 1.23"), + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_Int64(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + int_attribute = 123 + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("int_attribute"), + knownvalue.Int64ValueExact(123), + ), + }, + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_Int64_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + int_attribute = 123 + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("int_attribute"), + knownvalue.Int64ValueExact(321), + ), + }, + ExpectError: regexp.MustCompile("expected value 321 for Int64Value check, got: 123"), + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_List(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_attribute = [ + "value1", + "value2" + ] + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("list_attribute"), + knownvalue.ListValueExact([]knownvalue.Check{ + knownvalue.StringValueExact("value1"), + knownvalue.StringValueExact("value2"), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_List_KnownValueWrongType(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_attribute = [ + "value1", + "value2" + ] + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("list_attribute"), + knownvalue.MapValueExact(map[string]knownvalue.Check{}), + ), + }, + ExpectError: regexp.MustCompile(`expected map\[string\]any value for MapValue check, got: \[\]interface {}`), + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_List_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_attribute = [ + "value1", + "value2" + ] + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("list_attribute"), + knownvalue.ListValueExact([]knownvalue.Check{ + knownvalue.StringValueExact("value3"), + knownvalue.StringValueExact("value4"), + }), + ), + }, + ExpectError: regexp.MustCompile(`list element index 0: expected value value3 for StringValue check, got: value1`), + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_ListPartial(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_attribute = [ + "value1", + "value2" + ] + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("list_attribute"), + knownvalue.ListValuePartialMatch(map[int]knownvalue.Check{ + 0: knownvalue.StringValueExact("value1"), + }), + ), + }, + }, + }, + }) +} + +// No need to check KnownValueWrongType for ListPartial as all lists, and sets are []any in +// tfjson.State. +func TestExpectKnownValue_CheckState_ListPartial_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_attribute = [ + "value1", + "value2" + ] + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("list_attribute"), + knownvalue.ListValuePartialMatch(map[int]knownvalue.Check{ + 0: knownvalue.StringValueExact("value3"), + }), + ), + }, + ExpectError: regexp.MustCompile(`list element 0: expected value value3 for StringValue check, got: value1`), + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_ListElements(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_attribute = [ + "value1", + "value2" + ] + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("list_attribute"), + knownvalue.ListElementsExact(2), + ), + }, + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_ListElements_WrongNum(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_attribute = [ + "value1", + "value2" + ] + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("list_attribute"), + knownvalue.ListElementsExact(3), + ), + }, + ExpectError: regexp.MustCompile("expected 3 elements for ListElements check, got 2 elements"), + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_ListNestedBlock(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_nested_block { + list_nested_block_attribute = "str" + } + list_nested_block { + list_nested_block_attribute = "rts" + } + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("list_nested_block"), + knownvalue.ListValueExact([]knownvalue.Check{ + knownvalue.MapValueExact(map[string]knownvalue.Check{ + "list_nested_block_attribute": knownvalue.StringValueExact("str"), + }), + knownvalue.MapValueExact(map[string]knownvalue.Check{ + "list_nested_block_attribute": knownvalue.StringValueExact("rts"), + }), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_ListNestedBlockPartial(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_nested_block { + list_nested_block_attribute = "str" + } + list_nested_block { + list_nested_block_attribute = "rts" + } + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("list_nested_block"), + knownvalue.ListValuePartialMatch(map[int]knownvalue.Check{ + 1: knownvalue.MapValueExact(map[string]knownvalue.Check{ + "list_nested_block_attribute": knownvalue.StringValueExact("rts"), + }), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_ListNestedBlockElements(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_nested_block { + list_nested_block_attribute = "str" + } + list_nested_block { + list_nested_block_attribute = "rts" + } + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("list_nested_block"), + knownvalue.ListElementsExact(2), + ), + }, + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_Map(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + map_attribute = { + key1 = "value1" + key2 = "value2" + } + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("map_attribute"), + knownvalue.MapValueExact(map[string]knownvalue.Check{ + "key1": knownvalue.StringValueExact("value1"), + "key2": knownvalue.StringValueExact("value2"), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_Map_KnownValueWrongType(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + map_attribute = { + key1 = "value1" + key2 = "value2" + } + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("map_attribute"), + knownvalue.ListValueExact([]knownvalue.Check{}), + ), + }, + ExpectError: regexp.MustCompile(`expected \[\]any value for ListValue check, got: map\[string\]interface {}`), + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_Map_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + map_attribute = { + key1 = "value1" + key2 = "value2" + } + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("map_attribute"), + knownvalue.MapValueExact(map[string]knownvalue.Check{ + "key3": knownvalue.StringValueExact("value3"), + "key4": knownvalue.StringValueExact("value4"), + }), + ), + }, + ExpectError: regexp.MustCompile(`missing element key3 for MapValue check`), + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_MapPartial(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + map_attribute = { + key1 = "value1" + key2 = "value2" + } + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("map_attribute"), + knownvalue.MapValuePartialMatch(map[string]knownvalue.Check{ + "key1": knownvalue.StringValueExact("value1"), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_MapPartial_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + map_attribute = { + key1 = "value1" + key2 = "value2" + } + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("map_attribute"), + knownvalue.MapValuePartialMatch(map[string]knownvalue.Check{ + "key3": knownvalue.StringValueExact("value1"), + }), + ), + }, + ExpectError: regexp.MustCompile(`missing element key3 for MapValuePartial check`), + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_MapElements(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + map_attribute = { + key1 = "value1" + key2 = "value2" + } + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("map_attribute"), + knownvalue.MapElementsExact(2), + ), + }, + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_MapElements_WrongNum(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + map_attribute = { + key1 = "value1" + key2 = "value2" + } + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("map_attribute"), + knownvalue.MapElementsExact(3), + ), + }, + ExpectError: regexp.MustCompile("expected 3 elements for MapElements check, got 2 elements"), + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_Number(t *testing.T) { + t.Parallel() + + f, _, err := big.ParseFloat("123", 10, 512, big.ToNearestEven) + + if err != nil { + t.Errorf("%s", err) + } + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + int_attribute = 123 + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("int_attribute"), + knownvalue.NumberValueExact(f), + ), + }, + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_Number_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + f, _, err := big.ParseFloat("321", 10, 512, big.ToNearestEven) + + if err != nil { + t.Errorf("%s", err) + } + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + int_attribute = 123 + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("int_attribute"), + knownvalue.NumberValueExact(f), + ), + }, + ExpectError: regexp.MustCompile("expected value 321 for NumberValue check, got: 123"), + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_Set(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + set_attribute = [ + "value1", + "value2" + ] + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("set_attribute"), + knownvalue.SetValueExact([]knownvalue.Check{ + knownvalue.StringValueExact("value2"), + knownvalue.StringValueExact("value1"), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_Set_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + set_attribute = [ + "value1", + "value2" + ] + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("set_attribute"), + knownvalue.SetValueExact([]knownvalue.Check{ + knownvalue.StringValueExact("value1"), + knownvalue.StringValueExact("value3"), + }), + ), + }, + ExpectError: regexp.MustCompile(`missing value value3 for SetValue check`), + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_SetPartial(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + set_attribute = [ + "value1", + "value2" + ] + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("set_attribute"), + knownvalue.SetValuePartialMatch([]knownvalue.Check{ + knownvalue.StringValueExact("value2"), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_SetPartial_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + set_attribute = [ + "value1", + "value2" + ] + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("set_attribute"), + knownvalue.SetValuePartialMatch([]knownvalue.Check{ + knownvalue.StringValueExact("value3"), + }), + ), + }, + ExpectError: regexp.MustCompile(`missing value value3 for SetValuePartial check`), + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_SetElements(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + set_attribute = [ + "value1", + "value2" + ] + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("set_attribute"), + knownvalue.SetElementsExact(2), + ), + }, + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_SetNestedBlock(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + set_nested_block { + set_nested_block_attribute = "str" + } + set_nested_block { + set_nested_block_attribute = "rts" + } + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("set_nested_block"), + knownvalue.SetValueExact([]knownvalue.Check{ + knownvalue.MapValueExact(map[string]knownvalue.Check{ + "set_nested_block_attribute": knownvalue.StringValueExact("str"), + }), + knownvalue.MapValueExact(map[string]knownvalue.Check{ + "set_nested_block_attribute": knownvalue.StringValueExact("rts"), + }), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_SetNestedBlockPartial(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + set_nested_block { + set_nested_block_attribute = "str" + } + set_nested_block { + set_nested_block_attribute = "rts" + } + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("set_nested_block"), + knownvalue.SetValuePartialMatch([]knownvalue.Check{ + knownvalue.MapValueExact(map[string]knownvalue.Check{ + "set_nested_block_attribute": knownvalue.StringValueExact("rts"), + }), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_SetNestedBlockElements(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + set_nested_block { + set_nested_block_attribute = "str" + } + set_nested_block { + set_nested_block_attribute = "rts" + } + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("set_nested_block"), + knownvalue.SetElementsExact(2), + ), + }, + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_String(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + string_attribute = "str" + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("string_attribute"), + knownvalue.StringValueExact("str")), + }, + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_String_KnownValueWrongType(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + string_attribute = "str" + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("string_attribute"), + knownvalue.BoolValueExact(true)), + }, + ExpectError: regexp.MustCompile("expected bool value for BoolValue check, got: string"), + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_String_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + string_attribute = "str" + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("string_attribute"), + knownvalue.StringValueExact("rts")), + }, + ExpectError: regexp.MustCompile("expected value rts for StringValue check, got: str"), + }, + }, + }) +} + +func TestExpectKnownValue_CheckState_UnknownAttributeType(t *testing.T) { + t.Parallel() + + testCases := map[string]struct { + knownValue knownvalue.Check + req statecheck.CheckStateRequest + expectedErr error + }{ + "unrecognised-type": { + knownValue: knownvalue.Int64ValueExact(123), + req: statecheck.CheckStateRequest{ + State: &tfjson.State{ + Values: &tfjson.StateValues{ + RootModule: &tfjson.StateModule{ + Resources: []*tfjson.StateResource{ + { + Address: "example_resource.test", + AttributeValues: map[string]any{ + "attribute": float32(123), + }, + }, + }, + }, + }, + }, + }, + expectedErr: fmt.Errorf("unrecognised attribute type: float32, known value type is knownvalue.Int64Value\n\nThis is an error in statecheck.ExpectKnownValue.\nPlease report this to the maintainers."), + }, + } + + for name, testCase := range testCases { + name, testCase := name, testCase + + t.Run(name, func(t *testing.T) { + t.Parallel() + + e := statecheck.ExpectKnownValue("example_resource.test", tfjsonpath.New("attribute"), testCase.knownValue) + + resp := statecheck.CheckStateResponse{} + + e.CheckState(context.Background(), testCase.req, &resp) + + if diff := cmp.Diff(resp.Error, testCase.expectedErr, equateErrorMessage); diff != "" { + t.Errorf("unexpected difference: %s", diff) + } + }) + } +} + +var equateErrorMessage = cmp.Comparer(func(x, y error) bool { + if x == nil || y == nil { + return x == nil && y == nil + } + + return x.Error() == y.Error() +}) + +func testProvider() *schema.Provider { + return &schema.Provider{ + ResourcesMap: map[string]*schema.Resource{ + "test_resource": { + CreateContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + d.SetId("test") + return nil + }, + UpdateContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + return nil + }, + DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + return nil + }, + ReadContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + return nil + }, + Schema: map[string]*schema.Schema{ + "bool_attribute": { + Optional: true, + Type: schema.TypeBool, + }, + "float_attribute": { + Optional: true, + Type: schema.TypeFloat, + }, + "int_attribute": { + Optional: true, + Type: schema.TypeInt, + }, + "list_attribute": { + Type: schema.TypeList, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Optional: true, + }, + "list_nested_block": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "list_nested_block_attribute": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + "map_attribute": { + Type: schema.TypeMap, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Optional: true, + }, + "set_attribute": { + Type: schema.TypeSet, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Optional: true, + }, + "set_nested_block": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "set_nested_block_attribute": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + "string_attribute": { + Optional: true, + Type: schema.TypeString, + }, + }, + }, + }, + } +} From 4e3ca3ab02664ef0c018688994ad2b92acd810de Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Tue, 9 Jan 2024 13:34:14 +0000 Subject: [PATCH 04/73] Adding ExpectKnownOutputValue state check (#266) --- statecheck/expect_known_output_value.go | 92 ++ statecheck/expect_known_output_value_test.go | 1432 ++++++++++++++++++ statecheck/expect_known_value.go | 4 + 3 files changed, 1528 insertions(+) create mode 100644 statecheck/expect_known_output_value.go create mode 100644 statecheck/expect_known_output_value_test.go diff --git a/statecheck/expect_known_output_value.go b/statecheck/expect_known_output_value.go new file mode 100644 index 000000000..2809dff46 --- /dev/null +++ b/statecheck/expect_known_output_value.go @@ -0,0 +1,92 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package statecheck + +import ( + "context" + "fmt" + "reflect" + + tfjson "github.com/hashicorp/terraform-json" + + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + +// Resource State Check +var _ StateCheck = expectKnownOutputValue{} + +type expectKnownOutputValue struct { + outputAddress string + knownValue knownvalue.Check +} + +// CheckState implements the state check logic. +func (e expectKnownOutputValue) CheckState(ctx context.Context, req CheckStateRequest, resp *CheckStateResponse) { + var output *tfjson.StateOutput + + if req.State == nil { + resp.Error = fmt.Errorf("state is nil") + } + + if req.State.Values == nil { + resp.Error = fmt.Errorf("state does not contain any state values") + } + + for address, oc := range req.State.Values.Outputs { + if e.outputAddress == address { + output = oc + + break + } + } + + if output == nil { + resp.Error = fmt.Errorf("%s - Output not found in state", e.outputAddress) + + return + } + + result, err := tfjsonpath.Traverse(output.Value, tfjsonpath.Path{}) + + if err != nil { + resp.Error = err + + return + } + + if result == nil { + resp.Error = fmt.Errorf("value is null") + + return + } + + switch reflect.TypeOf(result).Kind() { + case reflect.Bool, + reflect.Map, + reflect.Slice, + reflect.String: + if err := e.knownValue.CheckValue(result); err != nil { + resp.Error = err + + return + } + default: + errorStr := fmt.Sprintf("unrecognised output type: %T, known value type is %T", result, e.knownValue) + errorStr += "\n\nThis is an error in statecheck.ExpectKnownOutputValue.\nPlease report this to the maintainers." + + resp.Error = fmt.Errorf(errorStr) + + return + } +} + +// ExpectKnownOutputValue returns a state check that asserts that the specified value +// has a known type, and value. +func ExpectKnownOutputValue(outputAddress string, knownValue knownvalue.Check) StateCheck { + return expectKnownOutputValue{ + outputAddress: outputAddress, + knownValue: knownValue, + } +} diff --git a/statecheck/expect_known_output_value_test.go b/statecheck/expect_known_output_value_test.go new file mode 100644 index 000000000..1c1cfcaa7 --- /dev/null +++ b/statecheck/expect_known_output_value_test.go @@ -0,0 +1,1432 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package statecheck_test + +import ( + "context" + "fmt" + "math/big" + "regexp" + "testing" + + "github.com/google/go-cmp/cmp" + tfjson "github.com/hashicorp/terraform-json" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + r "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/statecheck" +) + +func TestExpectKnownOutputValue_CheckState_OutputNotFound(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + + output bool_output { + value = test_resource.one.bool_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "bool_not_found", + knownvalue.BoolValueExact(true), + ), + }, + ExpectError: regexp.MustCompile("bool_not_found - Output not found in state"), + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_AttributeValueNull(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" {} + output bool_output { + value = test_resource.one.bool_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "bool_output", + knownvalue.BoolValueExact(true), + ), + }, + ExpectError: regexp.MustCompile("bool_output - Output not found in state"), + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_Bool(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + + output bool_output { + value = test_resource.one.bool_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "bool_output", + knownvalue.BoolValueExact(true), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_Bool_KnownValueWrongType(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + + output bool_output { + value = test_resource.one.bool_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "bool_output", + knownvalue.Float64ValueExact(1.23), + ), + }, + ExpectError: regexp.MustCompile(`expected json\.Number value for Float64Value check, got: bool`), + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_Bool_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + + output bool_output { + value = test_resource.one.bool_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "bool_output", + knownvalue.BoolValueExact(false), + ), + }, + ExpectError: regexp.MustCompile("expected value false for BoolValue check, got: true"), + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_Float64(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + float_attribute = 1.23 + } + + output float64_output { + value = test_resource.one.float_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "float64_output", + knownvalue.Float64ValueExact(1.23), + ), + }, + }, + }, + }) +} + +// We do not need equivalent tests for Int64 and Number as they all test the same logic. +func TestExpectKnownOutputValue_CheckState_Float64_KnownValueWrongType(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + float_attribute = 1.23 + } + + output float64_output { + value = test_resource.one.float_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "float64_output", + knownvalue.StringValueExact("str"), + ), + }, + ExpectError: regexp.MustCompile(`expected string value for StringValue check, got: json\.Number`), + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_Float64_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + float_attribute = 1.23 + } + + output float64_output { + value = test_resource.one.float_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "float64_output", + knownvalue.Float64ValueExact(3.21), + ), + }, + ExpectError: regexp.MustCompile("expected value 3.21 for Float64Value check, got: 1.23"), + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_Int64(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + int_attribute = 123 + } + + output int64_output { + value = test_resource.one.int_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "int64_output", + knownvalue.Int64ValueExact(123), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_Int64_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + int_attribute = 123 + } + + output int64_output { + value = test_resource.one.int_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "int64_output", + knownvalue.Int64ValueExact(321), + ), + }, + ExpectError: regexp.MustCompile("expected value 321 for Int64Value check, got: 123"), + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_List(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_attribute = [ + "value1", + "value2" + ] + } + + output list_output { + value = test_resource.one.list_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "list_output", + knownvalue.ListValueExact([]knownvalue.Check{ + knownvalue.StringValueExact("value1"), + knownvalue.StringValueExact("value2"), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_List_KnownValueWrongType(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_attribute = [ + "value1", + "value2" + ] + } + + output list_output { + value = test_resource.one.list_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "list_output", + knownvalue.MapValueExact(map[string]knownvalue.Check{}), + ), + }, + ExpectError: regexp.MustCompile(`expected map\[string\]any value for MapValue check, got: \[\]interface {}`), + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_List_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_attribute = [ + "value1", + "value2" + ] + } + + output list_output { + value = test_resource.one.list_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "list_output", + knownvalue.ListValueExact([]knownvalue.Check{ + knownvalue.StringValueExact("value3"), + knownvalue.StringValueExact("value4"), + }), + ), + }, + ExpectError: regexp.MustCompile(`list element index 0: expected value value3 for StringValue check, got: value1`), + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_ListPartial(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_attribute = [ + "value1", + "value2" + ] + } + + output list_output { + value = test_resource.one.list_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "list_output", + knownvalue.ListValuePartialMatch(map[int]knownvalue.Check{ + 0: knownvalue.StringValueExact("value1"), + }), + ), + }, + }, + }, + }) +} + +// No need to check KnownValueWrongType for ListPartial as all lists, and sets are []any in +// tfjson.State. +func TestExpectKnownOutputValue_CheckState_ListPartial_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_attribute = [ + "value1", + "value2" + ] + } + + output list_output { + value = test_resource.one.list_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "list_output", + knownvalue.ListValuePartialMatch(map[int]knownvalue.Check{ + 0: knownvalue.StringValueExact("value3"), + }), + ), + }, + ExpectError: regexp.MustCompile(`list element 0: expected value value3 for StringValue check, got: value1`), + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_ListElements(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_attribute = [ + "value1", + "value2" + ] + } + + output list_output { + value = test_resource.one.list_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "list_output", + knownvalue.ListElementsExact(2), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_ListElements_WrongNum(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_attribute = [ + "value1", + "value2" + ] + } + + output list_output { + value = test_resource.one.list_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "list_output", + knownvalue.ListElementsExact(3), + ), + }, + ExpectError: regexp.MustCompile("expected 3 elements for ListElements check, got 2 elements"), + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_ListNestedBlock(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_nested_block { + list_nested_block_attribute = "str" + } + list_nested_block { + list_nested_block_attribute = "rts" + } + } + + output list_nested_block_output { + value = test_resource.one.list_nested_block + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "list_nested_block_output", + knownvalue.ListValueExact([]knownvalue.Check{ + knownvalue.MapValueExact(map[string]knownvalue.Check{ + "list_nested_block_attribute": knownvalue.StringValueExact("str"), + }), + knownvalue.MapValueExact(map[string]knownvalue.Check{ + "list_nested_block_attribute": knownvalue.StringValueExact("rts"), + }), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_ListNestedBlockPartial(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_nested_block { + list_nested_block_attribute = "str" + } + list_nested_block { + list_nested_block_attribute = "rts" + } + } + + output list_nested_block_output { + value = test_resource.one.list_nested_block + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "list_nested_block_output", + knownvalue.ListValuePartialMatch(map[int]knownvalue.Check{ + 1: knownvalue.MapValueExact(map[string]knownvalue.Check{ + "list_nested_block_attribute": knownvalue.StringValueExact("rts"), + }), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_ListNestedBlockElements(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_nested_block { + list_nested_block_attribute = "str" + } + list_nested_block { + list_nested_block_attribute = "rts" + } + } + + output list_nested_block_output { + value = test_resource.one.list_nested_block + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "list_nested_block_output", + knownvalue.ListElementsExact(2), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_Map(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + map_attribute = { + key1 = "value1" + key2 = "value2" + } + } + + output map_output { + value = test_resource.one.map_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "map_output", + knownvalue.MapValueExact(map[string]knownvalue.Check{ + "key1": knownvalue.StringValueExact("value1"), + "key2": knownvalue.StringValueExact("value2"), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_Map_KnownValueWrongType(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + map_attribute = { + key1 = "value1" + key2 = "value2" + } + } + + output map_output { + value = test_resource.one.map_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "map_output", + knownvalue.ListValueExact([]knownvalue.Check{}), + ), + }, + ExpectError: regexp.MustCompile(`expected \[\]any value for ListValue check, got: map\[string\]interface {}`), + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_Map_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + map_attribute = { + key1 = "value1" + key2 = "value2" + } + } + + output map_output { + value = test_resource.one.map_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "map_output", + knownvalue.MapValueExact(map[string]knownvalue.Check{ + "key3": knownvalue.StringValueExact("value3"), + "key4": knownvalue.StringValueExact("value4"), + }), + ), + }, + ExpectError: regexp.MustCompile(`missing element key3 for MapValue check`), + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_MapPartial(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + map_attribute = { + key1 = "value1" + key2 = "value2" + } + } + + output map_output { + value = test_resource.one.map_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "map_output", + knownvalue.MapValuePartialMatch(map[string]knownvalue.Check{ + "key1": knownvalue.StringValueExact("value1"), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_MapPartial_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + map_attribute = { + key1 = "value1" + key2 = "value2" + } + } + + output map_output { + value = test_resource.one.map_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "map_output", + knownvalue.MapValuePartialMatch(map[string]knownvalue.Check{ + "key3": knownvalue.StringValueExact("value1"), + }), + ), + }, + ExpectError: regexp.MustCompile(`missing element key3 for MapValuePartial check`), + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_MapElements(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + map_attribute = { + key1 = "value1" + key2 = "value2" + } + } + + output map_output { + value = test_resource.one.map_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "map_output", + knownvalue.MapElementsExact(2), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_MapElements_WrongNum(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + map_attribute = { + key1 = "value1" + key2 = "value2" + } + } + + output map_output { + value = test_resource.one.map_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "map_output", + knownvalue.MapElementsExact(3), + ), + }, + ExpectError: regexp.MustCompile("expected 3 elements for MapElements check, got 2 elements"), + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_Number(t *testing.T) { + t.Parallel() + + f, _, err := big.ParseFloat("123", 10, 512, big.ToNearestEven) + + if err != nil { + t.Errorf("%s", err) + } + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + int_attribute = 123 + } + + output int64_output { + value = test_resource.one.int_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "int64_output", + knownvalue.NumberValueExact(f), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_Number_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + f, _, err := big.ParseFloat("321", 10, 512, big.ToNearestEven) + + if err != nil { + t.Errorf("%s", err) + } + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + int_attribute = 123 + } + + output int64_output { + value = test_resource.one.int_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "int64_output", + knownvalue.NumberValueExact(f), + ), + }, + ExpectError: regexp.MustCompile("expected value 321 for NumberValue check, got: 123"), + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_Set(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + set_attribute = [ + "value1", + "value2" + ] + } + + output set_output { + value = test_resource.one.set_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "set_output", + knownvalue.SetValueExact([]knownvalue.Check{ + knownvalue.StringValueExact("value1"), + knownvalue.StringValueExact("value2"), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_Set_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + set_attribute = [ + "value1", + "value2" + ] + } + + output set_output { + value = test_resource.one.set_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "set_output", + knownvalue.SetValueExact([]knownvalue.Check{ + knownvalue.StringValueExact("value1"), + knownvalue.StringValueExact("value3"), + }), + ), + }, + ExpectError: regexp.MustCompile(`missing value value3 for SetValue check`), + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_SetPartial(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + set_attribute = [ + "value1", + "value2" + ] + } + + output set_output { + value = test_resource.one.set_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "set_output", + knownvalue.SetValuePartialMatch([]knownvalue.Check{ + knownvalue.StringValueExact("value2"), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_SetPartial_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + set_attribute = [ + "value1", + "value2" + ] + } + + output set_output { + value = test_resource.one.set_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "set_output", + knownvalue.SetValuePartialMatch([]knownvalue.Check{ + knownvalue.StringValueExact("value3"), + }), + ), + }, + ExpectError: regexp.MustCompile(`missing value value3 for SetValuePartial check`), + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_SetElements(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + set_attribute = [ + "value1", + "value2" + ] + } + + output set_output { + value = test_resource.one.set_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "set_output", + knownvalue.SetElementsExact(2), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_SetNestedBlock(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + set_nested_block { + set_nested_block_attribute = "str" + } + set_nested_block { + set_nested_block_attribute = "rts" + } + } + + output set_nested_block_output { + value = test_resource.one.set_nested_block + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "set_nested_block_output", + knownvalue.SetValueExact([]knownvalue.Check{ + knownvalue.MapValueExact(map[string]knownvalue.Check{ + "set_nested_block_attribute": knownvalue.StringValueExact("str"), + }), + knownvalue.MapValueExact(map[string]knownvalue.Check{ + "set_nested_block_attribute": knownvalue.StringValueExact("rts"), + }), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_SetNestedBlockPartial(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + set_nested_block { + set_nested_block_attribute = "str" + } + set_nested_block { + set_nested_block_attribute = "rts" + } + } + + output set_nested_block_output { + value = test_resource.one.set_nested_block + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "set_nested_block_output", + knownvalue.SetValuePartialMatch([]knownvalue.Check{ + knownvalue.MapValueExact(map[string]knownvalue.Check{ + "set_nested_block_attribute": knownvalue.StringValueExact("rts"), + }), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_SetNestedBlockElements(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + set_nested_block { + set_nested_block_attribute = "str" + } + set_nested_block { + set_nested_block_attribute = "rts" + } + } + + output set_nested_block_output { + value = test_resource.one.set_nested_block + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "set_nested_block_output", + knownvalue.SetElementsExact(2), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_String(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + string_attribute = "str" + } + + output string_output { + value = test_resource.one.string_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "string_output", + knownvalue.StringValueExact("str")), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_String_KnownValueWrongType(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + string_attribute = "str" + } + + output string_output { + value = test_resource.one.string_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "string_output", + knownvalue.BoolValueExact(true)), + }, + ExpectError: regexp.MustCompile("expected bool value for BoolValue check, got: string"), + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_String_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + string_attribute = "str" + } + + output string_output { + value = test_resource.one.string_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "string_output", + knownvalue.StringValueExact("rts")), + }, + ExpectError: regexp.MustCompile("expected value rts for StringValue check, got: str"), + }, + }, + }) +} + +func TestExpectKnownOutputValue_CheckState_UnknownAttributeType(t *testing.T) { + t.Parallel() + + testCases := map[string]struct { + knownValue knownvalue.Check + req statecheck.CheckStateRequest + expectedErr error + }{ + "unrecognised-type": { + knownValue: knownvalue.Int64ValueExact(123), + req: statecheck.CheckStateRequest{ + State: &tfjson.State{ + Values: &tfjson.StateValues{ + Outputs: map[string]*tfjson.StateOutput{ + "float32_output": { + Value: float32(123), + }, + }, + }, + }, + }, + expectedErr: fmt.Errorf("unrecognised output type: float32, known value type is knownvalue.Int64Value\n\nThis is an error in statecheck.ExpectKnownOutputValue.\nPlease report this to the maintainers."), + }, + } + + for name, testCase := range testCases { + name, testCase := name, testCase + + t.Run(name, func(t *testing.T) { + t.Parallel() + + e := statecheck.ExpectKnownOutputValue("float32_output", testCase.knownValue) + + resp := statecheck.CheckStateResponse{} + + e.CheckState(context.Background(), testCase.req, &resp) + + if diff := cmp.Diff(resp.Error, testCase.expectedErr, equateErrorMessage); diff != "" { + t.Errorf("unexpected difference: %s", diff) + } + }) + } +} diff --git a/statecheck/expect_known_value.go b/statecheck/expect_known_value.go index 2f073f15c..b8d5a6157 100644 --- a/statecheck/expect_known_value.go +++ b/statecheck/expect_known_value.go @@ -27,6 +27,10 @@ type expectKnownValue struct { func (e expectKnownValue) CheckState(ctx context.Context, req CheckStateRequest, resp *CheckStateResponse) { var rc *tfjson.StateResource + if req.State == nil { + resp.Error = fmt.Errorf("state is nil") + } + if req.State.Values == nil { resp.Error = fmt.Errorf("state does not contain any state values") } From d93aa8209edf3836a627e8dfbcf432bf9263e2e8 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Tue, 9 Jan 2024 13:48:21 +0000 Subject: [PATCH 05/73] Adding ExpectKnownOutputValueAtPath state check (#266) --- .../expect_known_output_value_at_path.go | 94 + .../expect_known_output_value_at_path_test.go | 1755 +++++++++++++++++ 2 files changed, 1849 insertions(+) create mode 100644 statecheck/expect_known_output_value_at_path.go create mode 100644 statecheck/expect_known_output_value_at_path_test.go diff --git a/statecheck/expect_known_output_value_at_path.go b/statecheck/expect_known_output_value_at_path.go new file mode 100644 index 000000000..31d4516b1 --- /dev/null +++ b/statecheck/expect_known_output_value_at_path.go @@ -0,0 +1,94 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package statecheck + +import ( + "context" + "fmt" + "reflect" + + tfjson "github.com/hashicorp/terraform-json" + + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + +// Resource State Check +var _ StateCheck = expectKnownOutputValueAtPath{} + +type expectKnownOutputValueAtPath struct { + outputAddress string + outputPath tfjsonpath.Path + knownValue knownvalue.Check +} + +// CheckState implements the state check logic. +func (e expectKnownOutputValueAtPath) CheckState(ctx context.Context, req CheckStateRequest, resp *CheckStateResponse) { + var output *tfjson.StateOutput + + if req.State == nil { + resp.Error = fmt.Errorf("state is nil") + } + + if req.State.Values == nil { + resp.Error = fmt.Errorf("state does not contain any state values") + } + + for address, oc := range req.State.Values.Outputs { + if e.outputAddress == address { + output = oc + + break + } + } + + if output == nil { + resp.Error = fmt.Errorf("%s - Output not found in state", e.outputAddress) + + return + } + + result, err := tfjsonpath.Traverse(output.Value, e.outputPath) + + if err != nil { + resp.Error = err + + return + } + + if result == nil { + resp.Error = fmt.Errorf("value is null") + + return + } + + switch reflect.TypeOf(result).Kind() { + case reflect.Bool, + reflect.Map, + reflect.Slice, + reflect.String: + if err := e.knownValue.CheckValue(result); err != nil { + resp.Error = err + + return + } + default: + errorStr := fmt.Sprintf("unrecognised output type: %T, known value type is %T", result, e.knownValue) + errorStr += "\n\nThis is an error in statecheck.ExpectKnownOutputValueAtPath.\nPlease report this to the maintainers." + + resp.Error = fmt.Errorf(errorStr) + + return + } +} + +// ExpectKnownOutputValueAtPath returns a state check that asserts that the specified output at the given path +// has a known type and value. +func ExpectKnownOutputValueAtPath(outputAddress string, outputPath tfjsonpath.Path, knownValue knownvalue.Check) StateCheck { + return expectKnownOutputValueAtPath{ + outputAddress: outputAddress, + outputPath: outputPath, + knownValue: knownValue, + } +} diff --git a/statecheck/expect_known_output_value_at_path_test.go b/statecheck/expect_known_output_value_at_path_test.go new file mode 100644 index 000000000..6b9795f90 --- /dev/null +++ b/statecheck/expect_known_output_value_at_path_test.go @@ -0,0 +1,1755 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package statecheck_test + +import ( + "context" + "fmt" + "math/big" + "regexp" + "testing" + + "github.com/google/go-cmp/cmp" + tfjson "github.com/hashicorp/terraform-json" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + r "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" + "github.com/hashicorp/terraform-plugin-testing/tfversion" +) + +func TestExpectKnownOutputValueAtPath_CheckState_ResourceNotFound(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_two_output", + tfjsonpath.New("bool_attribute"), + knownvalue.BoolValueExact(true), + ), + }, + ExpectError: regexp.MustCompile("test_resource_two_output - Output not found in state"), + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_AttributeValueNull(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" {} + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("bool_attribute"), + knownvalue.BoolValueExact(true), + ), + }, + ExpectError: regexp.MustCompile("value is null"), + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_Bool(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("bool_attribute"), + knownvalue.BoolValueExact(true), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_Bool_KnownValueWrongType(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("bool_attribute"), + knownvalue.Float64ValueExact(1.23), + ), + }, + ExpectError: regexp.MustCompile(`expected json\.Number value for Float64Value check, got: bool`), + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_Bool_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("bool_attribute"), + knownvalue.BoolValueExact(false), + ), + }, + ExpectError: regexp.MustCompile("expected value false for BoolValue check, got: true"), + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_Float64(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + float_attribute = 1.23 + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("float_attribute"), + knownvalue.Float64ValueExact(1.23), + ), + }, + }, + }, + }) +} + +// We do not need equivalent tests for Int64 and Number as they all test the same logic. +func TestExpectKnownOutputValueAtPath_CheckState_Float64_KnownValueWrongType(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + float_attribute = 1.23 + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("float_attribute"), + knownvalue.StringValueExact("str"), + ), + }, + ExpectError: regexp.MustCompile(`expected string value for StringValue check, got: json\.Number`), + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_Float64_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + float_attribute = 1.23 + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("float_attribute"), + knownvalue.Float64ValueExact(3.21), + ), + }, + ExpectError: regexp.MustCompile("expected value 3.21 for Float64Value check, got: 1.23"), + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_Int64(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + int_attribute = 123 + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("int_attribute"), + knownvalue.Int64ValueExact(123), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_Int64_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + int_attribute = 123 + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("int_attribute"), + knownvalue.Int64ValueExact(321), + ), + }, + ExpectError: regexp.MustCompile("expected value 321 for Int64Value check, got: 123"), + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_List(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_attribute = [ + "value1", + "value2" + ] + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("list_attribute"), + knownvalue.ListValueExact([]knownvalue.Check{ + knownvalue.StringValueExact("value1"), + knownvalue.StringValueExact("value2"), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_List_KnownValueWrongType(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_attribute = [ + "value1", + "value2" + ] + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("list_attribute"), + knownvalue.MapValueExact(map[string]knownvalue.Check{}), + ), + }, + ExpectError: regexp.MustCompile(`expected map\[string\]any value for MapValue check, got: \[\]interface {}`), + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_List_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_attribute = [ + "value1", + "value2" + ] + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("list_attribute"), + knownvalue.ListValueExact([]knownvalue.Check{ + knownvalue.StringValueExact("value3"), + knownvalue.StringValueExact("value4"), + }), + ), + }, + ExpectError: regexp.MustCompile(`list element index 0: expected value value3 for StringValue check, got: value1`), + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_ListPartial(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_attribute = [ + "value1", + "value2" + ] + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("list_attribute"), + knownvalue.ListValuePartialMatch(map[int]knownvalue.Check{ + 0: knownvalue.StringValueExact("value1"), + }), + ), + }, + }, + }, + }) +} + +// No need to check KnownValueWrongType for ListPartial as all lists, and sets are []any in +// tfjson.State. +func TestExpectKnownOutputValueAtPath_CheckState_ListPartial_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_attribute = [ + "value1", + "value2" + ] + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("list_attribute"), + knownvalue.ListValuePartialMatch(map[int]knownvalue.Check{ + 0: knownvalue.StringValueExact("value3"), + }), + ), + }, + ExpectError: regexp.MustCompile(`list element 0: expected value value3 for StringValue check, got: value1`), + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_ListElements(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_attribute = [ + "value1", + "value2" + ] + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("list_attribute"), + knownvalue.ListElementsExact(2), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_ListElements_WrongNum(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_attribute = [ + "value1", + "value2" + ] + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("list_attribute"), + knownvalue.ListElementsExact(3), + ), + }, + ExpectError: regexp.MustCompile("expected 3 elements for ListElements check, got 2 elements"), + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_ListNestedBlock(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_nested_block { + list_nested_block_attribute = "str" + } + list_nested_block { + list_nested_block_attribute = "rts" + } + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("list_nested_block"), + knownvalue.ListValueExact([]knownvalue.Check{ + knownvalue.MapValueExact(map[string]knownvalue.Check{ + "list_nested_block_attribute": knownvalue.StringValueExact("str"), + }), + knownvalue.MapValueExact(map[string]knownvalue.Check{ + "list_nested_block_attribute": knownvalue.StringValueExact("rts"), + }), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_ListNestedBlockPartial(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_nested_block { + list_nested_block_attribute = "str" + } + list_nested_block { + list_nested_block_attribute = "rts" + } + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("list_nested_block"), + knownvalue.ListValuePartialMatch(map[int]knownvalue.Check{ + 1: knownvalue.MapValueExact(map[string]knownvalue.Check{ + "list_nested_block_attribute": knownvalue.StringValueExact("rts"), + }), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_ListNestedBlockElements(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_nested_block { + list_nested_block_attribute = "str" + } + list_nested_block { + list_nested_block_attribute = "rts" + } + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("list_nested_block"), + knownvalue.ListElementsExact(2), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_Map(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + map_attribute = { + key1 = "value1" + key2 = "value2" + } + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("map_attribute"), + knownvalue.MapValueExact(map[string]knownvalue.Check{ + "key1": knownvalue.StringValueExact("value1"), + "key2": knownvalue.StringValueExact("value2"), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_Map_KnownValueWrongType(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + map_attribute = { + key1 = "value1" + key2 = "value2" + } + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("map_attribute"), + knownvalue.ListValueExact([]knownvalue.Check{}), + ), + }, + ExpectError: regexp.MustCompile(`expected \[\]any value for ListValue check, got: map\[string\]interface {}`), + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_Map_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + map_attribute = { + key1 = "value1" + key2 = "value2" + } + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("map_attribute"), + knownvalue.MapValueExact(map[string]knownvalue.Check{ + "key3": knownvalue.StringValueExact("value3"), + "key4": knownvalue.StringValueExact("value4"), + }), + ), + }, + ExpectError: regexp.MustCompile(`missing element key3 for MapValue check`), + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_MapPartial(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + map_attribute = { + key1 = "value1" + key2 = "value2" + } + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("map_attribute"), + knownvalue.MapValuePartialMatch(map[string]knownvalue.Check{ + "key1": knownvalue.StringValueExact("value1"), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_MapPartial_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + map_attribute = { + key1 = "value1" + key2 = "value2" + } + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("map_attribute"), + knownvalue.MapValuePartialMatch(map[string]knownvalue.Check{ + "key3": knownvalue.StringValueExact("value1"), + }), + ), + }, + ExpectError: regexp.MustCompile(`missing element key3 for MapValuePartial check`), + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_MapElements(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + map_attribute = { + key1 = "value1" + key2 = "value2" + } + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("map_attribute"), + knownvalue.MapElementsExact(2), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_MapElements_WrongNum(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + map_attribute = { + key1 = "value1" + key2 = "value2" + } + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("map_attribute"), + knownvalue.MapElementsExact(3), + ), + }, + ExpectError: regexp.MustCompile("expected 3 elements for MapElements check, got 2 elements"), + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_Number(t *testing.T) { + t.Parallel() + + f, _, err := big.ParseFloat("123", 10, 512, big.ToNearestEven) + + if err != nil { + t.Errorf("%s", err) + } + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + int_attribute = 123 + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("int_attribute"), + knownvalue.NumberValueExact(f), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_Number_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + f, _, err := big.ParseFloat("321", 10, 512, big.ToNearestEven) + + if err != nil { + t.Errorf("%s", err) + } + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + int_attribute = 123 + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("int_attribute"), + knownvalue.NumberValueExact(f), + ), + }, + ExpectError: regexp.MustCompile("expected value 321 for NumberValue check, got: 123"), + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_Set(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + set_attribute = [ + "value1", + "value2" + ] + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("set_attribute"), + knownvalue.SetValueExact([]knownvalue.Check{ + knownvalue.StringValueExact("value1"), + knownvalue.StringValueExact("value2"), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_Set_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + set_attribute = [ + "value1", + "value2" + ] + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("set_attribute"), + knownvalue.SetValueExact([]knownvalue.Check{ + knownvalue.StringValueExact("value1"), + knownvalue.StringValueExact("value3"), + }), + ), + }, + ExpectError: regexp.MustCompile(`missing value value3 for SetValue check`), + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_SetPartial(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + set_attribute = [ + "value1", + "value2" + ] + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("set_attribute"), + knownvalue.SetValuePartialMatch([]knownvalue.Check{ + knownvalue.StringValueExact("value2"), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_SetPartial_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + set_attribute = [ + "value1", + "value2" + ] + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("set_attribute"), + knownvalue.SetValuePartialMatch([]knownvalue.Check{ + knownvalue.StringValueExact("value3"), + }), + ), + }, + ExpectError: regexp.MustCompile(`missing value value3 for SetValuePartial check`), + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_SetElements(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + set_attribute = [ + "value1", + "value2" + ] + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("set_attribute"), + knownvalue.SetElementsExact(2), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_SetNestedBlock(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + set_nested_block { + set_nested_block_attribute = "str" + } + set_nested_block { + set_nested_block_attribute = "rts" + } + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("set_nested_block"), + knownvalue.SetValueExact([]knownvalue.Check{ + knownvalue.MapValueExact(map[string]knownvalue.Check{ + "set_nested_block_attribute": knownvalue.StringValueExact("str"), + }), + knownvalue.MapValueExact(map[string]knownvalue.Check{ + "set_nested_block_attribute": knownvalue.StringValueExact("rts"), + }), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_SetNestedBlockPartial(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + set_nested_block { + set_nested_block_attribute = "str" + } + set_nested_block { + set_nested_block_attribute = "rts" + } + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("set_nested_block"), + knownvalue.SetValuePartialMatch([]knownvalue.Check{ + knownvalue.MapValueExact(map[string]knownvalue.Check{ + "set_nested_block_attribute": knownvalue.StringValueExact("rts"), + }), + }), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_SetNestedBlockElements(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + set_nested_block { + set_nested_block_attribute = "str" + } + set_nested_block { + set_nested_block_attribute = "rts" + } + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("set_nested_block"), + knownvalue.SetElementsExact(2), + ), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_String(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + string_attribute = "str" + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("string_attribute"), + knownvalue.StringValueExact("str")), + }, + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_String_KnownValueWrongType(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + string_attribute = "str" + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("string_attribute"), + knownvalue.BoolValueExact(true)), + }, + ExpectError: regexp.MustCompile("expected bool value for BoolValue check, got: string"), + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_String_KnownValueWrongValue(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + // Prior to Terraform v1.3.0 a statened output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + string_attribute = "str" + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("string_attribute"), + knownvalue.StringValueExact("rts")), + }, + ExpectError: regexp.MustCompile("expected value rts for StringValue check, got: str"), + }, + }, + }) +} + +func TestExpectKnownOutputValueAtPath_CheckState_UnknownAttributeType(t *testing.T) { + t.Parallel() + + testCases := map[string]struct { + knownValue knownvalue.Check + req statecheck.CheckStateRequest + expectedErr error + }{ + "unrecognised-type": { + knownValue: knownvalue.Int64ValueExact(123), + req: statecheck.CheckStateRequest{ + State: &tfjson.State{ + Values: &tfjson.StateValues{ + Outputs: map[string]*tfjson.StateOutput{ + "float32_output": { + Value: float32(123), + }, + }, + }, + }, + }, + expectedErr: fmt.Errorf("unrecognised output type: float32, known value type is knownvalue.Int64Value\n\nThis is an error in statecheck.ExpectKnownOutputValueAtPath.\nPlease report this to the maintainers."), + }, + } + + for name, testCase := range testCases { + name, testCase := name, testCase + + t.Run(name, func(t *testing.T) { + t.Parallel() + + e := statecheck.ExpectKnownOutputValueAtPath("float32_output", tfjsonpath.Path{}, testCase.knownValue) + + resp := statecheck.CheckStateResponse{} + + e.CheckState(context.Background(), testCase.req, &resp) + + if diff := cmp.Diff(resp.Error, testCase.expectedErr, equateErrorMessage); diff != "" { + t.Errorf("unexpected difference: %s", diff) + } + }) + } +} From 598dac8246003c5c0aef3714f345493cfec3fc25 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Wed, 10 Jan 2024 10:45:42 +0000 Subject: [PATCH 06/73] Modifying ExpectKnown to allow for checking of null values (#266) --- knownvalue/null.go | 34 +++ knownvalue/null_test.go | 61 ++++ statecheck/expect_known_output_value.go | 24 +- .../expect_known_output_value_at_path.go | 24 +- .../expect_known_output_value_at_path_test.go | 286 +----------------- statecheck/expect_known_output_value_test.go | 6 +- statecheck/expect_known_value.go | 26 +- statecheck/expect_known_value_test.go | 5 +- 8 files changed, 110 insertions(+), 356 deletions(-) create mode 100644 knownvalue/null.go create mode 100644 knownvalue/null_test.go diff --git a/knownvalue/null.go b/knownvalue/null.go new file mode 100644 index 000000000..93e773cb0 --- /dev/null +++ b/knownvalue/null.go @@ -0,0 +1,34 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package knownvalue + +import ( + "fmt" +) + +var _ Check = NullValue{} + +// NullValue is a Check for asserting equality between the value supplied +// to NullValueExact and the value passed to the CheckValue method. +type NullValue struct{} + +// CheckValue determines whether the passed value is of nil. +func (v NullValue) CheckValue(other any) error { + if other != nil { + return fmt.Errorf("expected value nil for NullValue check, got: %T", other) + } + + return nil +} + +// String returns the string representation of nil. +func (v NullValue) String() string { + return "nil" +} + +// NullValueExact returns a Check for asserting equality nil +// and the value passed to the CheckValue method. +func NullValueExact() NullValue { + return NullValue{} +} diff --git a/knownvalue/null_test.go b/knownvalue/null_test.go new file mode 100644 index 000000000..b185ca220 --- /dev/null +++ b/knownvalue/null_test.go @@ -0,0 +1,61 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package knownvalue_test + +import ( + "fmt" + "testing" + + "github.com/google/go-cmp/cmp" + + "github.com/hashicorp/terraform-plugin-testing/knownvalue" +) + +func TestNullValue_CheckValue(t *testing.T) { + t.Parallel() + + testCases := map[string]struct { + self knownvalue.NullValue + other any + expectedError error + }{ + "zero-nil": {}, + "zero-other": { + other: nil, // checking against the underlying value field zero-value + }, + "not-nil": { + self: knownvalue.NullValueExact(), + other: false, + expectedError: fmt.Errorf("expected value nil for NullValue check, got: bool"), + }, + "equal": { + self: knownvalue.NullValueExact(), + other: nil, + }, + } + + 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 TestNullValue_String(t *testing.T) { + t.Parallel() + + got := knownvalue.NullValueExact().String() + + if diff := cmp.Diff(got, "nil"); diff != "" { + t.Errorf("unexpected difference: %s", diff) + } +} diff --git a/statecheck/expect_known_output_value.go b/statecheck/expect_known_output_value.go index 2809dff46..1cf6b69e8 100644 --- a/statecheck/expect_known_output_value.go +++ b/statecheck/expect_known_output_value.go @@ -6,7 +6,6 @@ package statecheck import ( "context" "fmt" - "reflect" tfjson "github.com/hashicorp/terraform-json" @@ -56,27 +55,8 @@ func (e expectKnownOutputValue) CheckState(ctx context.Context, req CheckStateRe return } - if result == nil { - resp.Error = fmt.Errorf("value is null") - - return - } - - switch reflect.TypeOf(result).Kind() { - case reflect.Bool, - reflect.Map, - reflect.Slice, - reflect.String: - if err := e.knownValue.CheckValue(result); err != nil { - resp.Error = err - - return - } - default: - errorStr := fmt.Sprintf("unrecognised output type: %T, known value type is %T", result, e.knownValue) - errorStr += "\n\nThis is an error in statecheck.ExpectKnownOutputValue.\nPlease report this to the maintainers." - - resp.Error = fmt.Errorf(errorStr) + if err := e.knownValue.CheckValue(result); err != nil { + resp.Error = err return } diff --git a/statecheck/expect_known_output_value_at_path.go b/statecheck/expect_known_output_value_at_path.go index 31d4516b1..7ff704b06 100644 --- a/statecheck/expect_known_output_value_at_path.go +++ b/statecheck/expect_known_output_value_at_path.go @@ -6,7 +6,6 @@ package statecheck import ( "context" "fmt" - "reflect" tfjson "github.com/hashicorp/terraform-json" @@ -57,27 +56,8 @@ func (e expectKnownOutputValueAtPath) CheckState(ctx context.Context, req CheckS return } - if result == nil { - resp.Error = fmt.Errorf("value is null") - - return - } - - switch reflect.TypeOf(result).Kind() { - case reflect.Bool, - reflect.Map, - reflect.Slice, - reflect.String: - if err := e.knownValue.CheckValue(result); err != nil { - resp.Error = err - - return - } - default: - errorStr := fmt.Sprintf("unrecognised output type: %T, known value type is %T", result, e.knownValue) - errorStr += "\n\nThis is an error in statecheck.ExpectKnownOutputValueAtPath.\nPlease report this to the maintainers." - - resp.Error = fmt.Errorf(errorStr) + if err := e.knownValue.CheckValue(result); err != nil { + resp.Error = err return } diff --git a/statecheck/expect_known_output_value_at_path_test.go b/statecheck/expect_known_output_value_at_path_test.go index 6b9795f90..371847b69 100644 --- a/statecheck/expect_known_output_value_at_path_test.go +++ b/statecheck/expect_known_output_value_at_path_test.go @@ -18,7 +18,6 @@ import ( "github.com/hashicorp/terraform-plugin-testing/knownvalue" "github.com/hashicorp/terraform-plugin-testing/statecheck" "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" - "github.com/hashicorp/terraform-plugin-testing/tfversion" ) func TestExpectKnownOutputValueAtPath_CheckState_ResourceNotFound(t *testing.T) { @@ -30,13 +29,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_ResourceNotFound(t *testing.T) return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -69,13 +61,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_AttributeValueNull(t *testing.T return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" {} @@ -88,10 +73,9 @@ func TestExpectKnownOutputValueAtPath_CheckState_AttributeValueNull(t *testing.T statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("bool_attribute"), - knownvalue.BoolValueExact(true), + knownvalue.NullValueExact(), ), }, - ExpectError: regexp.MustCompile("value is null"), }, }, }) @@ -106,13 +90,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_Bool(t *testing.T) { return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -144,13 +121,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_Bool_KnownValueWrongType(t *tes return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -183,13 +153,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_Bool_KnownValueWrongValue(t *te return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -222,13 +185,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_Float64(t *testing.T) { return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -261,13 +217,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_Float64_KnownValueWrongType(t * return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -300,13 +249,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_Float64_KnownValueWrongValue(t return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -339,13 +281,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_Int64(t *testing.T) { return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -377,13 +312,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_Int64_KnownValueWrongValue(t *t return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -416,13 +344,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_List(t *testing.T) { return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -460,13 +381,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_List_KnownValueWrongType(t *tes return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -502,13 +416,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_List_KnownValueWrongValue(t *te return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -547,13 +454,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_ListPartial(t *testing.T) { return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -592,13 +492,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_ListPartial_KnownValueWrongValu return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -636,13 +529,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_ListElements(t *testing.T) { return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -677,13 +563,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_ListElements_WrongNum(t *testin return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -719,13 +598,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_ListNestedBlock(t *testing.T) { return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -769,13 +641,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_ListNestedBlockPartial(t *testi return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -816,13 +681,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_ListNestedBlockElements(t *test return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -859,13 +717,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_Map(t *testing.T) { return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -903,13 +754,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_Map_KnownValueWrongType(t *test return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -945,13 +789,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_Map_KnownValueWrongValue(t *tes return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -990,13 +827,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_MapPartial(t *testing.T) { return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -1033,13 +863,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_MapPartial_KnownValueWrongValue return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -1077,13 +900,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_MapElements(t *testing.T) { return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -1118,13 +934,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_MapElements_WrongNum(t *testing return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -1166,13 +975,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_Number(t *testing.T) { return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -1210,13 +1012,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_Number_KnownValueWrongValue(t * return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -1249,13 +1044,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_Set(t *testing.T) { return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -1293,13 +1081,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_Set_KnownValueWrongValue(t *tes return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -1338,13 +1119,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_SetPartial(t *testing.T) { return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -1381,13 +1155,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_SetPartial_KnownValueWrongValue return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -1425,13 +1192,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_SetElements(t *testing.T) { return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -1466,13 +1226,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_SetNestedBlock(t *testing.T) { return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -1516,13 +1269,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_SetNestedBlockPartial(t *testin return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -1563,13 +1309,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_SetNestedBlockElements(t *testi return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -1606,13 +1345,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_String(t *testing.T) { return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -1643,13 +1375,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_String_KnownValueWrongType(t *t return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -1681,13 +1406,6 @@ func TestExpectKnownOutputValueAtPath_CheckState_String_KnownValueWrongValue(t * return testProvider(), nil }, }, - // Prior to Terraform v1.3.0 a statened output is marked as fully unknown - // if any attribute is unknown. The id attribute within the test provider - // is unknown. - // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 - TerraformVersionChecks: []tfversion.TerraformVersionCheck{ - tfversion.SkipBelow(tfversion.Version1_3_0), - }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { @@ -1731,7 +1449,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_UnknownAttributeType(t *testing }, }, }, - expectedErr: fmt.Errorf("unrecognised output type: float32, known value type is knownvalue.Int64Value\n\nThis is an error in statecheck.ExpectKnownOutputValueAtPath.\nPlease report this to the maintainers."), + expectedErr: fmt.Errorf("expected json.Number value for Int64Value check, got: float32"), }, } diff --git a/statecheck/expect_known_output_value_test.go b/statecheck/expect_known_output_value_test.go index 1c1cfcaa7..e081b0716 100644 --- a/statecheck/expect_known_output_value_test.go +++ b/statecheck/expect_known_output_value_test.go @@ -50,6 +50,10 @@ func TestExpectKnownOutputValue_CheckState_OutputNotFound(t *testing.T) { }) } +// TestExpectKnownOutputValue_CheckState_AttributeValueNull shows that outputs that reference +// null values do not appear in state. Indicating that there is no way to discriminate +// between null outputs and non-existent outputs. +// Reference: https://github.com/hashicorp/terraform/issues/34080 func TestExpectKnownOutputValue_CheckState_AttributeValueNull(t *testing.T) { t.Parallel() @@ -1408,7 +1412,7 @@ func TestExpectKnownOutputValue_CheckState_UnknownAttributeType(t *testing.T) { }, }, }, - expectedErr: fmt.Errorf("unrecognised output type: float32, known value type is knownvalue.Int64Value\n\nThis is an error in statecheck.ExpectKnownOutputValue.\nPlease report this to the maintainers."), + expectedErr: fmt.Errorf("expected json.Number value for Int64Value check, got: float32"), }, } diff --git a/statecheck/expect_known_value.go b/statecheck/expect_known_value.go index b8d5a6157..096699cba 100644 --- a/statecheck/expect_known_value.go +++ b/statecheck/expect_known_value.go @@ -6,7 +6,6 @@ package statecheck import ( "context" "fmt" - "reflect" tfjson "github.com/hashicorp/terraform-json" @@ -61,29 +60,8 @@ func (e expectKnownValue) CheckState(ctx context.Context, req CheckStateRequest, return } - if result == nil { - resp.Error = fmt.Errorf("value is null") - - return - } - - switch reflect.TypeOf(result).Kind() { - case reflect.Bool, - reflect.Map, - reflect.Slice, - reflect.String: - if err := e.knownValue.CheckValue(result); err != nil { - resp.Error = err - - return - } - default: - errorStr := fmt.Sprintf("unrecognised attribute type: %T, known value type is %T", result, e.knownValue) - errorStr += "\n\nThis is an error in statecheck.ExpectKnownValue.\nPlease report this to the maintainers." - - resp.Error = fmt.Errorf(errorStr) - - return + if err := e.knownValue.CheckValue(result); err != nil { + resp.Error = err } } diff --git a/statecheck/expect_known_value_test.go b/statecheck/expect_known_value_test.go index bd1024891..ce2d0a5c9 100644 --- a/statecheck/expect_known_value_test.go +++ b/statecheck/expect_known_value_test.go @@ -65,10 +65,9 @@ func TestExpectKnownValue_CheckState_AttributeValueNull(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), - knownvalue.BoolValueExact(true), + knownvalue.NullValueExact(), ), }, - ExpectError: regexp.MustCompile("value is null"), }, }, }) @@ -1295,7 +1294,7 @@ func TestExpectKnownValue_CheckState_UnknownAttributeType(t *testing.T) { }, }, }, - expectedErr: fmt.Errorf("unrecognised attribute type: float32, known value type is knownvalue.Int64Value\n\nThis is an error in statecheck.ExpectKnownValue.\nPlease report this to the maintainers."), + expectedErr: fmt.Errorf("expected json.Number value for Int64Value check, got: float32"), }, } From c78e3e8743c621bb8155edcacbc98989b4b0f828 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Wed, 10 Jan 2024 12:07:10 +0000 Subject: [PATCH 07/73] Adding ExpectSensitiveValue state check (#266) --- statecheck/expect_sensitive_value.go | 95 +++++++ statecheck/expect_sensitive_value_test.go | 308 ++++++++++++++++++++++ tfversion/versions.go | 1 + 3 files changed, 404 insertions(+) create mode 100644 statecheck/expect_sensitive_value.go create mode 100644 statecheck/expect_sensitive_value_test.go diff --git a/statecheck/expect_sensitive_value.go b/statecheck/expect_sensitive_value.go new file mode 100644 index 000000000..7e8ec7325 --- /dev/null +++ b/statecheck/expect_sensitive_value.go @@ -0,0 +1,95 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package statecheck + +import ( + "context" + "encoding/json" + "fmt" + + tfjson "github.com/hashicorp/terraform-json" + + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + +var _ StateCheck = expectSensitiveValue{} + +type expectSensitiveValue struct { + resourceAddress string + attributePath tfjsonpath.Path +} + +// CheckState implements the state check logic. +func (e expectSensitiveValue) CheckState(ctx context.Context, req CheckStateRequest, resp *CheckStateResponse) { + var rc *tfjson.StateResource + + if req.State == nil { + resp.Error = fmt.Errorf("state is nil") + } + + if req.State.Values == nil { + resp.Error = fmt.Errorf("state does not contain any state values") + } + + if req.State.Values.RootModule == nil { + resp.Error = fmt.Errorf("state does not contain a root module") + } + + for _, resourceChange := range req.State.Values.RootModule.Resources { + if e.resourceAddress == resourceChange.Address { + rc = resourceChange + + break + } + } + + if rc == nil { + resp.Error = fmt.Errorf("%s - Resource not found in state", e.resourceAddress) + + return + } + + var data map[string]any + + err := json.Unmarshal(rc.SensitiveValues, &data) + + if err != nil { + resp.Error = fmt.Errorf("could not unmarshal SensitiveValues: %s", err) + + return + } + + result, err := tfjsonpath.Traverse(data, e.attributePath) + + if err != nil { + resp.Error = err + + return + } + + isSensitive, ok := result.(bool) + if !ok { + resp.Error = fmt.Errorf("invalid path: the path value cannot be asserted as bool") + return + } + + if !isSensitive { + resp.Error = fmt.Errorf("attribute at path is not sensitive") + return + } + + return +} + +// ExpectSensitiveValue returns a state check that asserts that the specified attribute at the given resource has a sensitive value. +// +// Due to implementation differences between the terraform-plugin-sdk and the terraform-plugin-framework, representation of sensitive +// values may differ. For example, terraform-plugin-sdk based providers may have less precise representations of sensitive values, such +// as marking whole maps as sensitive rather than individual element values. +func ExpectSensitiveValue(resourceAddress string, attributePath tfjsonpath.Path) StateCheck { + return expectSensitiveValue{ + resourceAddress: resourceAddress, + attributePath: attributePath, + } +} diff --git a/statecheck/expect_sensitive_value_test.go b/statecheck/expect_sensitive_value_test.go new file mode 100644 index 000000000..5723d73b4 --- /dev/null +++ b/statecheck/expect_sensitive_value_test.go @@ -0,0 +1,308 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package statecheck_test + +import ( + "context" + "regexp" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + r "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" + "github.com/hashicorp/terraform-plugin-testing/tfversion" +) + +func Test_ExpectSensitiveValue_SensitiveStringAttribute(t *testing.T) { + t.Parallel() + + r.UnitTest(t, r.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_4_6), // StateResource.SensitiveValues + }, + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProviderSensitive(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: ` + resource "test_resource" "one" { + sensitive_string_attribute = "test" + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectSensitiveValue("test_resource.one", + tfjsonpath.New("sensitive_string_attribute")), + }, + }, + }, + }) +} + +func Test_ExpectSensitiveValue_SensitiveListAttribute(t *testing.T) { + t.Parallel() + + r.UnitTest(t, r.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_4_6), // StateResource.SensitiveValues + }, + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProviderSensitive(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: ` + resource "test_resource" "one" { + sensitive_list_attribute = ["value1"] + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectSensitiveValue("test_resource.one", + tfjsonpath.New("sensitive_list_attribute")), + }, + }, + }, + }) +} + +func Test_ExpectSensitiveValue_SensitiveSetAttribute(t *testing.T) { + t.Parallel() + + r.UnitTest(t, r.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_4_6), // StateResource.SensitiveValues + }, + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProviderSensitive(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: ` + resource "test_resource" "one" { + sensitive_set_attribute = ["value1"] + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectSensitiveValue("test_resource.one", + tfjsonpath.New("sensitive_set_attribute")), + }, + }, + }, + }) +} + +func Test_ExpectSensitiveValue_SensitiveMapAttribute(t *testing.T) { + t.Parallel() + + r.UnitTest(t, r.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_4_6), // StateResource.SensitiveValues + }, + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProviderSensitive(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: ` + resource "test_resource" "one" { + sensitive_map_attribute = { + key1 = "value1", + } + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectSensitiveValue("test_resource.one", + tfjsonpath.New("sensitive_map_attribute")), + }, + }, + }, + }) +} + +func Test_ExpectSensitiveValue_ListNestedBlock_SensitiveAttribute(t *testing.T) { + t.Parallel() + + r.UnitTest(t, r.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_4_6), // StateResource.SensitiveValues + }, + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProviderSensitive(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: ` + resource "test_resource" "one" { + list_nested_block_sensitive_attribute { + sensitive_list_nested_block_attribute = "sensitive-test" + list_nested_block_attribute = "test" + } + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectSensitiveValue("test_resource.one", + tfjsonpath.New("list_nested_block_sensitive_attribute").AtSliceIndex(0). + AtMapKey("sensitive_list_nested_block_attribute")), + }, + }, + }, + }) +} + +func Test_ExpectSensitiveValue_SetNestedBlock_SensitiveAttribute(t *testing.T) { + t.Parallel() + + r.UnitTest(t, r.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_4_6), // StateResource.SensitiveValues + }, + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProviderSensitive(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: ` + resource "test_resource" "one" { + set_nested_block_sensitive_attribute { + sensitive_set_nested_block_attribute = "sensitive-test" + set_nested_block_attribute = "test" + } + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectSensitiveValue("test_resource.one", + tfjsonpath.New("set_nested_block_sensitive_attribute")), + }, + }, + }, + }) +} + +func Test_ExpectSensitiveValue_ExpectError_ResourceNotFound(t *testing.T) { + t.Parallel() + + r.UnitTest(t, r.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_4_6), // StateResource.SensitiveValues + }, + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProviderSensitive(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: ` + resource "test_resource" "one" {} + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectSensitiveValue("test_resource.two", tfjsonpath.New("set_attribute")), + }, + ExpectError: regexp.MustCompile(`test_resource.two - Resource not found in state`), + }, + }, + }) +} + +func testProviderSensitive() *schema.Provider { + return &schema.Provider{ + ResourcesMap: map[string]*schema.Resource{ + "test_resource": { + CreateContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + d.SetId("test") + return nil + }, + UpdateContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + return nil + }, + DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + return nil + }, + ReadContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + return nil + }, + Schema: map[string]*schema.Schema{ + "sensitive_string_attribute": { + Sensitive: true, + Optional: true, + Type: schema.TypeString, + }, + "sensitive_list_attribute": { + Sensitive: true, + Type: schema.TypeList, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Optional: true, + }, + "sensitive_set_attribute": { + Sensitive: true, + Type: schema.TypeSet, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Optional: true, + }, + "sensitive_map_attribute": { + Sensitive: true, + Type: schema.TypeMap, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Optional: true, + }, + "list_nested_block_sensitive_attribute": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "list_nested_block_attribute": { + Type: schema.TypeString, + Optional: true, + }, + "sensitive_list_nested_block_attribute": { + Sensitive: true, + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + "set_nested_block_sensitive_attribute": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "set_nested_block_attribute": { + Type: schema.TypeString, + Optional: true, + }, + "sensitive_set_nested_block_attribute": { + Sensitive: true, + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + }, + }, + }, + } +} diff --git a/tfversion/versions.go b/tfversion/versions.go index 77f384b5e..f405bd766 100644 --- a/tfversion/versions.go +++ b/tfversion/versions.go @@ -28,6 +28,7 @@ var ( Version1_2_0 *version.Version = version.Must(version.NewVersion("1.2.0")) Version1_3_0 *version.Version = version.Must(version.NewVersion("1.3.0")) Version1_4_0 *version.Version = version.Must(version.NewVersion("1.4.0")) + Version1_4_6 *version.Version = version.Must(version.NewVersion("1.4.6")) Version1_5_0 *version.Version = version.Must(version.NewVersion("1.5.0")) Version1_6_0 *version.Version = version.Must(version.NewVersion("1.6.0")) Version1_7_0 *version.Version = version.Must(version.NewVersion("1.7.0")) From 1e516931f719d54ab6a84fc7f42c019b8a86b2aa Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Wed, 10 Jan 2024 17:03:54 +0000 Subject: [PATCH 08/73] Adding documentation for state checks and null known value check type (#266) --- website/data/plugin-testing-nav-data.json | 25 ++++ .../known-value-checks/null.mdx | 39 ++++++ .../acceptance-tests/state-checks/custom.mdx | 119 ++++++++++++++++++ .../acceptance-tests/state-checks/index.mdx | 20 +++ .../acceptance-tests/state-checks/output.mdx | 84 +++++++++++++ .../state-checks/resource.mdx | 78 ++++++++++++ 6 files changed, 365 insertions(+) create mode 100644 website/docs/plugin/testing/acceptance-tests/known-value-checks/null.mdx create mode 100644 website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx create mode 100644 website/docs/plugin/testing/acceptance-tests/state-checks/index.mdx create mode 100644 website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx create mode 100644 website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx diff --git a/website/data/plugin-testing-nav-data.json b/website/data/plugin-testing-nav-data.json index 7e581b6c3..40fc85629 100644 --- a/website/data/plugin-testing-nav-data.json +++ b/website/data/plugin-testing-nav-data.json @@ -50,6 +50,27 @@ } ] }, + { + "title": "State Checks", + "routes": [ + { + "title": "Overview", + "path": "acceptance-tests/state-checks" + }, + { + "title": "Resource State Checks", + "path": "acceptance-tests/state-checks/resource" + }, + { + "title": "Output State Checks", + "path": "acceptance-tests/state-checks/output" + }, + { + "title": "Custom State Checks", + "path": "acceptance-tests/state-checks/custom" + } + ] + }, { "title": "Known Value Checks", "routes": [ @@ -85,6 +106,10 @@ "title": "Number", "path": "acceptance-tests/known-value-checks/number" }, + { + "title": "Null ", + "path": "acceptance-tests/known-value-checks/null" + }, { "title": "Object", "path": "acceptance-tests/known-value-checks/object" diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/null.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/null.mdx new file mode 100644 index 000000000..9d50ee65e --- /dev/null +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/null.mdx @@ -0,0 +1,39 @@ +--- +page_title: 'Plugin Development - Acceptance Testing: Known Values' +description: >- + Null Value Checks for use with Plan Checks or State Checks. +--- + +# Null Known Value Checks + +The known value checks that are available for null values are: + +* [NullValueExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/null#nullvalueexact-check) + +## `NullValueExact` Check + +The [NullValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NullValueExact) check tests that a resource attribute, or output value has an exactly matching null value. + +Example usage of [NullValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NullValueExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/state-checks/resource) state check. + +```go +func TestExpectKnownValue_CheckState_AttributeValueNull(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + // Provider definition omitted. + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" {}`, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + knownvalue.NullValueExact(), + ), + }, + }, + }, + }) +} +``` diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx new file mode 100644 index 000000000..f3b3461b0 --- /dev/null +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx @@ -0,0 +1,119 @@ +--- +page_title: 'Plugin Development - Acceptance Testing: State Checks' +description: >- + State Checks are test assertions that can inspect state during a TestStep. Custom State Checks can be implemented. +--- + +# Custom State Checks + +The package [`statecheck`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck) also provides the [`StateCheck`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck) interface, which can be implemented for a custom state check. + +The [`statecheck.CheckStateRequest`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#CheckStateRequest) contains the current state file, parsed by the [terraform-json package](https://pkg.go.dev/github.com/hashicorp/terraform-json#State). + +Here is an example implementation of a state check that asserts that a specific resource attribute has a known type and value: + +```go +package example_test + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-testing/statecheck" +) + +var _ StateCheck = expectKnownValue{} + +type expectKnownValue struct { + resourceAddress string + attributePath tfjsonpath.Path + knownValue knownvalue.Check +} + +func (e expectKnownValue) CheckState(ctx context.Context, req CheckStateRequest, resp *CheckStateResponse) { + var rc *tfjson.StateResource + + if req.State == nil { + resp.Error = fmt.Errorf("state is nil") + } + + if req.State.Values == nil { + resp.Error = fmt.Errorf("state does not contain any state values") + } + + if req.State.Values.RootModule == nil { + resp.Error = fmt.Errorf("state does not contain a root module") + } + + for _, resourceChange := range req.State.Values.RootModule.Resources { + if e.resourceAddress == resourceChange.Address { + rc = resourceChange + + break + } + } + + if rc == nil { + resp.Error = fmt.Errorf("%s - Resource not found in state", e.resourceAddress) + + return + } + + result, err := tfjsonpath.Traverse(rc.AttributeValues, e.attributePath) + + if err != nil { + resp.Error = err + + return + } + + if err := e.knownValue.CheckValue(result); err != nil { + resp.Error = err + } +} + +func ExpectKnownValue(resourceAddress string, attributePath tfjsonpath.Path, knownValue knownvalue.Check) StateCheck { + return expectKnownValue{ + resourceAddress: resourceAddress, + attributePath: attributePath, + knownValue: knownValue, + } +} +``` + +And example usage: +```go +package example_test + +import ( + "testing" + + r "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + +func TestExpectKnownValue_CheckState_Bool(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + // Provider definition omitted. + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + knownvalue.BoolValueExact(true), + ), + }, + }, + }, + }) +} +``` diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/index.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/index.mdx new file mode 100644 index 000000000..36304e388 --- /dev/null +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/index.mdx @@ -0,0 +1,20 @@ +--- +page_title: 'Plugin Development - Acceptance Testing: State Checks' +description: >- + State Checks are test assertions that can inspect state during a TestStep. The testing module + provides built-in State Checks for common use-cases, and custom State Checks can also be implemented. +--- + +# State Checks + +During the **Lifecycle (config)** [mode](/terraform/plugin/testing/acceptance-tests/teststep#test-modes) of a `TestStep`, the testing framework will run `terraform apply`. + +The execution of `terraform apply` results in a [state file](/terraform/language/state), and can be represented by this [JSON format](/terraform/internals/json-format#state-representation). + +A **state check** is a test assertion that inspects the state file. Multiple state checks can be run, all assertion errors returned are aggregated, reported as a test failure, and all test cleanup logic is executed. + +Refer to: + +- [Resource State Checks](/terraform/plugin/testing/acceptance-tests/state-checks/resource) for built-in managed resource and data source state checks. +- [Output State Checks](/terraform/plugin/testing/acceptance-tests/state-checks/output) for built-in output-related state checks. +- [Custom State Checks](/terraform/plugin/testing/acceptance-tests/state-checks/custom) for defining bespoke state checks. diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx new file mode 100644 index 000000000..01caccdae --- /dev/null +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx @@ -0,0 +1,84 @@ +--- +page_title: 'Plugin Development - Acceptance Testing: State Checks' +description: >- + State Checks are test assertions that can inspect state during a TestStep. The testing module + provides built-in Output Value State Checks for common use-cases. +--- + +# Output State Checks + +The `terraform-plugin-testing` module provides a package [`statecheck`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck) with built-in output value state checks for common use-cases: + +| Check | Description | +|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------| +| [`statecheck.ExpectKnownOutputValue(address, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValue) | Asserts the output at the specified address has the specified type, and value. | +| [`statecheck.ExpectKnownOutputValueAtPath(address, path, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValueAtPath) | Asserts the output at the specified address, and path has the specified type, and value. | + +## Example using `statecheck.ExpectKnownOutputValue` + +The [`statecheck.ExpectKnownOutputValue(address, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValue) state check verifies that a specific output value has a known type, and value. + +Refer to [Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks) for details, and examples of the available [knownvalue.Check](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check) types that can be used with the `ExpectKnownOutputValue` state check. + +```go +func TestExpectKnownOutputValue_CheckState_Bool(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + // Provider definition omitted. + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + + output bool_output { + value = test_resource.one.bool_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "bool_output", + knownvalue.BoolValueExact(true), + ), + }, + }, + }, + }) +} +``` + +## Example using `statecheck.ExpectKnownOutputValueAtPath` + +The [`statecheck.ExpectKnownOutputValueAtPath(address, path, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValueAtPath) state check verifies that a specific output value at a defined path has a known type, and value. + +Refer to [Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks) for details, and examples of the available [knownvalue.Check](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check) types that can be used with the `ExpectKnownOutputValueAtPath` state check. + +```go +func TestExpectKnownOutputValueAtPath_CheckState_Bool(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + // Provider definition omitted. + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("bool_attribute"), + knownvalue.BoolValueExact(true), + ), + }, + }, + }, + }) +} +``` \ No newline at end of file diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx new file mode 100644 index 000000000..990fd828b --- /dev/null +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx @@ -0,0 +1,78 @@ +--- +page_title: 'Plugin Development - Acceptance Testing: State Checks' +description: >- + State Checks are test assertions that can inspect state during a TestStep. The testing module + provides built-in Managed Resource and Data Source State Checks for common use-cases. +--- + +# Resource State Checks + +The `terraform-plugin-testing` module provides a package [`statecheck`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck) with built-in managed resource, and data source state checks for common use-cases: + +| Check | Description | +|------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------| +| [`statecheck.ExpectKnownValue(address, path, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue) | Asserts the specified attribute at the given managed resource, or data source, has the specified type, and value. | +| [`statecheck.ExpectSensitiveValue(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectSensitiveValue) | Asserts the specified attribute at the given managed resource, or data source, has a sensitive value. | + +## Example using `statecheck.ExpectKnownValue` + +The [`statecheck.ExpectKnownValue(address, path, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue) state check provides a basis for asserting that a specific resource attribute has a known type, and value. + +Refer to [Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks) for details, and examples of the available [knownvalue.Check](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check) types that can be used with the `ExpectKnownValue` state check. + +```go +func TestExpectKnownValue_CheckState_Bool(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + // Provider definition omitted. + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + knownvalue.BoolValueExact(true), + ), + }, + }, + }, + }) +} +``` + +## Example using `statecheck.ExpectSensitiveValue` + +The [`statecheck.ExpectSensitiveValue(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectSensitiveValue) state check provides a basis for asserting that a specific resource attribute is marked as sensitive. + +-> **Note:** In this example, a [TerraformVersionCheck](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/tfversion#TerraformVersionCheck) is being used to prevent execution of this test prior to Terraform version `1.4.6` (refer to the release notes for Terraform [v1.4.6](https://github.com/hashicorp/terraform/releases/tag/v1.4.6)). + +```go +func Test_ExpectSensitiveValue_SensitiveStringAttribute(t *testing.T) { + t.Parallel() + + r.UnitTest(t, r.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_4_6), // StateResource.SensitiveValues + }, + // Provider definition omitted. + Steps: []r.TestStep{ + { + Config: ` + resource "test_resource" "one" { + sensitive_string_attribute = "test" + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectSensitiveValue("test_resource.one", + tfjsonpath.New("sensitive_string_attribute")), + }, + }, + }, + }) +} +``` From 3d4acf4ff30976989935bbdad88fb716a8c8d22b Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Thu, 11 Jan 2024 08:11:23 +0000 Subject: [PATCH 09/73] Adding to the documentation for the custom known value check (#266) --- .../known-value-checks/custom.mdx | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/custom.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/custom.mdx index ee48caa62..b9f69de1e 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/custom.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/custom.mdx @@ -48,3 +48,26 @@ func StringValueMatch(value string) StringValue { } } ``` + +## `CheckValue` Method Implementation + +The `other` parameter passed to the `CheckValue` method is one of the following types: + +* bool +* map[string]any +* []any +* string + +-> **Note:** Numerical values will be of type `json.Number`, with an underlying type of `string`. + +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: + +* [BoolValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#BoolValueExact) +* [Float64ValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Float64ValueExact) +* [Int64ValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Int64ValueExact) +* [ListValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ListValueExact) +* [MapValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#MapValueExact) +* [NumberValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NumberValueExact) +* [ObjectValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ObjectValueExact) +* [SetValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetValueExact) +* [StringValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#StringValueExact) From 01fe9a9bc5ce887a2709b4dbc495e4e8a9b48eeb Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Thu, 11 Jan 2024 14:29:54 +0000 Subject: [PATCH 10/73] Adding changelog entries (#266) --- .changes/unreleased/FEATURES-20240111-142126.yaml | 6 ++++++ .changes/unreleased/FEATURES-20240111-142223.yaml | 6 ++++++ .changes/unreleased/FEATURES-20240111-142314.yaml | 6 ++++++ .changes/unreleased/FEATURES-20240111-142353.yaml | 6 ++++++ .changes/unreleased/FEATURES-20240111-142544.yaml | 6 ++++++ 5 files changed, 30 insertions(+) create mode 100644 .changes/unreleased/FEATURES-20240111-142126.yaml create mode 100644 .changes/unreleased/FEATURES-20240111-142223.yaml create mode 100644 .changes/unreleased/FEATURES-20240111-142314.yaml create mode 100644 .changes/unreleased/FEATURES-20240111-142353.yaml create mode 100644 .changes/unreleased/FEATURES-20240111-142544.yaml diff --git a/.changes/unreleased/FEATURES-20240111-142126.yaml b/.changes/unreleased/FEATURES-20240111-142126.yaml new file mode 100644 index 000000000..99c271b7c --- /dev/null +++ b/.changes/unreleased/FEATURES-20240111-142126.yaml @@ -0,0 +1,6 @@ +kind: FEATURES +body: 'statecheck: Introduced new `statecheck` package with interface and built-in + state check functionality' +time: 2024-01-11T14:21:26.261094Z +custom: + Issue: "273" diff --git a/.changes/unreleased/FEATURES-20240111-142223.yaml b/.changes/unreleased/FEATURES-20240111-142223.yaml new file mode 100644 index 000000000..ca6a2a386 --- /dev/null +++ b/.changes/unreleased/FEATURES-20240111-142223.yaml @@ -0,0 +1,6 @@ +kind: FEATURES +body: 'statecheck: Added `ExpectKnownValue` state check, which asserts that a given + resource attribute has a defined type, and value' +time: 2024-01-11T14:22:23.072321Z +custom: + Issue: "273" diff --git a/.changes/unreleased/FEATURES-20240111-142314.yaml b/.changes/unreleased/FEATURES-20240111-142314.yaml new file mode 100644 index 000000000..3d683c564 --- /dev/null +++ b/.changes/unreleased/FEATURES-20240111-142314.yaml @@ -0,0 +1,6 @@ +kind: FEATURES +body: 'statecheck: Added `ExpectKnownOutputValue` state check, which asserts that + a given output value has a defined type, and value' +time: 2024-01-11T14:23:14.025585Z +custom: + Issue: "273" diff --git a/.changes/unreleased/FEATURES-20240111-142353.yaml b/.changes/unreleased/FEATURES-20240111-142353.yaml new file mode 100644 index 000000000..eaa67ae05 --- /dev/null +++ b/.changes/unreleased/FEATURES-20240111-142353.yaml @@ -0,0 +1,6 @@ +kind: FEATURES +body: 'statecheck: Added `ExpectKnownOutputValueAtPath` plan check, which asserts + that a given output value at a specified path has a defined type, and value' +time: 2024-01-11T14:23:53.633255Z +custom: + Issue: "273" diff --git a/.changes/unreleased/FEATURES-20240111-142544.yaml b/.changes/unreleased/FEATURES-20240111-142544.yaml new file mode 100644 index 000000000..42bf8aa03 --- /dev/null +++ b/.changes/unreleased/FEATURES-20240111-142544.yaml @@ -0,0 +1,6 @@ +kind: FEATURES +body: 'statecheck: Added `ExpectSensitiveValue` built-in state check, which asserts + that a given attribute has a sensitive value' +time: 2024-01-11T14:25:44.598583Z +custom: + Issue: "273" From fb9fed8fc9649aec0047ed57fe6d45082e1834e5 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Thu, 11 Jan 2024 14:40:05 +0000 Subject: [PATCH 11/73] Refactoring to use updated known value check types (#266) --- .../expect_known_output_value_at_path_test.go | 50 +++++++++---------- statecheck/expect_known_output_value_test.go | 50 +++++++++---------- statecheck/expect_known_value_test.go | 50 +++++++++---------- statecheck/expect_sensitive_value.go | 2 - 4 files changed, 75 insertions(+), 77 deletions(-) diff --git a/statecheck/expect_known_output_value_at_path_test.go b/statecheck/expect_known_output_value_at_path_test.go index 371847b69..3fcd64637 100644 --- a/statecheck/expect_known_output_value_at_path_test.go +++ b/statecheck/expect_known_output_value_at_path_test.go @@ -138,7 +138,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Bool_KnownValueWrongType(t *tes knownvalue.Float64ValueExact(1.23), ), }, - ExpectError: regexp.MustCompile(`expected json\.Number value for Float64Value check, got: bool`), + ExpectError: regexp.MustCompile(`expected json\.Number value for Float64ValueExact check, got: bool`), }, }, }) @@ -170,7 +170,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Bool_KnownValueWrongValue(t *te knownvalue.BoolValueExact(false), ), }, - ExpectError: regexp.MustCompile("expected value false for BoolValue check, got: true"), + ExpectError: regexp.MustCompile("expected value false for BoolValueExact check, got: true"), }, }, }) @@ -234,7 +234,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Float64_KnownValueWrongType(t * knownvalue.StringValueExact("str"), ), }, - ExpectError: regexp.MustCompile(`expected string value for StringValue check, got: json\.Number`), + ExpectError: regexp.MustCompile(`expected string value for StringValueExact check, got: json\.Number`), }, }, }) @@ -266,7 +266,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Float64_KnownValueWrongValue(t knownvalue.Float64ValueExact(3.21), ), }, - ExpectError: regexp.MustCompile("expected value 3.21 for Float64Value check, got: 1.23"), + ExpectError: regexp.MustCompile("expected value 3.21 for Float64ValueExact check, got: 1.23"), }, }, }) @@ -329,7 +329,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Int64_KnownValueWrongValue(t *t knownvalue.Int64ValueExact(321), ), }, - ExpectError: regexp.MustCompile("expected value 321 for Int64Value check, got: 123"), + ExpectError: regexp.MustCompile("expected value 321 for Int64ValueExact check, got: 123"), }, }, }) @@ -401,7 +401,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_List_KnownValueWrongType(t *tes knownvalue.MapValueExact(map[string]knownvalue.Check{}), ), }, - ExpectError: regexp.MustCompile(`expected map\[string\]any value for MapValue check, got: \[\]interface {}`), + ExpectError: regexp.MustCompile(`expected map\[string\]any value for MapValueExact check, got: \[\]interface {}`), }, }, }) @@ -439,7 +439,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_List_KnownValueWrongValue(t *te }), ), }, - ExpectError: regexp.MustCompile(`list element index 0: expected value value3 for StringValue check, got: value1`), + ExpectError: regexp.MustCompile(`list element index 0: expected value value3 for StringValueExact check, got: value1`), }, }, }) @@ -471,7 +471,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_ListPartial(t *testing.T) { statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("list_attribute"), - knownvalue.ListValuePartialMatch(map[int]knownvalue.Check{ + knownvalue.ListValuePartial(map[int]knownvalue.Check{ 0: knownvalue.StringValueExact("value1"), }), ), @@ -509,12 +509,12 @@ func TestExpectKnownOutputValueAtPath_CheckState_ListPartial_KnownValueWrongValu statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("list_attribute"), - knownvalue.ListValuePartialMatch(map[int]knownvalue.Check{ + knownvalue.ListValuePartial(map[int]knownvalue.Check{ 0: knownvalue.StringValueExact("value3"), }), ), }, - ExpectError: regexp.MustCompile(`list element 0: expected value value3 for StringValue check, got: value1`), + ExpectError: regexp.MustCompile(`list element 0: expected value value3 for StringValueExact check, got: value1`), }, }, }) @@ -583,7 +583,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_ListElements_WrongNum(t *testin knownvalue.ListElementsExact(3), ), }, - ExpectError: regexp.MustCompile("expected 3 elements for ListElements check, got 2 elements"), + ExpectError: regexp.MustCompile("expected 3 elements for ListElementsExact check, got 2 elements"), }, }, }) @@ -660,7 +660,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_ListNestedBlockPartial(t *testi statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("list_nested_block"), - knownvalue.ListValuePartialMatch(map[int]knownvalue.Check{ + knownvalue.ListValuePartial(map[int]knownvalue.Check{ 1: knownvalue.MapValueExact(map[string]knownvalue.Check{ "list_nested_block_attribute": knownvalue.StringValueExact("rts"), }), @@ -774,7 +774,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Map_KnownValueWrongType(t *test knownvalue.ListValueExact([]knownvalue.Check{}), ), }, - ExpectError: regexp.MustCompile(`expected \[\]any value for ListValue check, got: map\[string\]interface {}`), + ExpectError: regexp.MustCompile(`expected \[\]any value for ListValueExact check, got: map\[string\]interface {}`), }, }, }) @@ -812,7 +812,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Map_KnownValueWrongValue(t *tes }), ), }, - ExpectError: regexp.MustCompile(`missing element key3 for MapValue check`), + ExpectError: regexp.MustCompile(`missing element key3 for MapValueExact check`), }, }, }) @@ -844,7 +844,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_MapPartial(t *testing.T) { statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("map_attribute"), - knownvalue.MapValuePartialMatch(map[string]knownvalue.Check{ + knownvalue.MapValuePartial(map[string]knownvalue.Check{ "key1": knownvalue.StringValueExact("value1"), }), ), @@ -880,7 +880,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_MapPartial_KnownValueWrongValue statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("map_attribute"), - knownvalue.MapValuePartialMatch(map[string]knownvalue.Check{ + knownvalue.MapValuePartial(map[string]knownvalue.Check{ "key3": knownvalue.StringValueExact("value1"), }), ), @@ -954,7 +954,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_MapElements_WrongNum(t *testing knownvalue.MapElementsExact(3), ), }, - ExpectError: regexp.MustCompile("expected 3 elements for MapElements check, got 2 elements"), + ExpectError: regexp.MustCompile("expected 3 elements for MapElementsExact check, got 2 elements"), }, }, }) @@ -1029,7 +1029,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Number_KnownValueWrongValue(t * knownvalue.NumberValueExact(f), ), }, - ExpectError: regexp.MustCompile("expected value 321 for NumberValue check, got: 123"), + ExpectError: regexp.MustCompile("expected value 321 for NumberValueExact check, got: 123"), }, }, }) @@ -1104,7 +1104,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Set_KnownValueWrongValue(t *tes }), ), }, - ExpectError: regexp.MustCompile(`missing value value3 for SetValue check`), + ExpectError: regexp.MustCompile(`missing value value3 for SetValueExact check`), }, }, }) @@ -1136,7 +1136,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_SetPartial(t *testing.T) { statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("set_attribute"), - knownvalue.SetValuePartialMatch([]knownvalue.Check{ + knownvalue.SetValuePartial([]knownvalue.Check{ knownvalue.StringValueExact("value2"), }), ), @@ -1172,7 +1172,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_SetPartial_KnownValueWrongValue statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("set_attribute"), - knownvalue.SetValuePartialMatch([]knownvalue.Check{ + knownvalue.SetValuePartial([]knownvalue.Check{ knownvalue.StringValueExact("value3"), }), ), @@ -1288,7 +1288,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_SetNestedBlockPartial(t *testin statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("set_nested_block"), - knownvalue.SetValuePartialMatch([]knownvalue.Check{ + knownvalue.SetValuePartial([]knownvalue.Check{ knownvalue.MapValueExact(map[string]knownvalue.Check{ "set_nested_block_attribute": knownvalue.StringValueExact("rts"), }), @@ -1391,7 +1391,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_String_KnownValueWrongType(t *t tfjsonpath.New("string_attribute"), knownvalue.BoolValueExact(true)), }, - ExpectError: regexp.MustCompile("expected bool value for BoolValue check, got: string"), + ExpectError: regexp.MustCompile("expected bool value for BoolValueExact check, got: string"), }, }, }) @@ -1422,7 +1422,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_String_KnownValueWrongValue(t * tfjsonpath.New("string_attribute"), knownvalue.StringValueExact("rts")), }, - ExpectError: regexp.MustCompile("expected value rts for StringValue check, got: str"), + ExpectError: regexp.MustCompile("expected value rts for StringValueExact check, got: str"), }, }, }) @@ -1449,7 +1449,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_UnknownAttributeType(t *testing }, }, }, - expectedErr: fmt.Errorf("expected json.Number value for Int64Value check, got: float32"), + expectedErr: fmt.Errorf("expected json.Number value for Int64ValueExact check, got: float32"), }, } diff --git a/statecheck/expect_known_output_value_test.go b/statecheck/expect_known_output_value_test.go index e081b0716..e4af792d5 100644 --- a/statecheck/expect_known_output_value_test.go +++ b/statecheck/expect_known_output_value_test.go @@ -137,7 +137,7 @@ func TestExpectKnownOutputValue_CheckState_Bool_KnownValueWrongType(t *testing.T knownvalue.Float64ValueExact(1.23), ), }, - ExpectError: regexp.MustCompile(`expected json\.Number value for Float64Value check, got: bool`), + ExpectError: regexp.MustCompile(`expected json\.Number value for Float64ValueExact check, got: bool`), }, }, }) @@ -168,7 +168,7 @@ func TestExpectKnownOutputValue_CheckState_Bool_KnownValueWrongValue(t *testing. knownvalue.BoolValueExact(false), ), }, - ExpectError: regexp.MustCompile("expected value false for BoolValue check, got: true"), + ExpectError: regexp.MustCompile("expected value false for BoolValueExact check, got: true"), }, }, }) @@ -230,7 +230,7 @@ func TestExpectKnownOutputValue_CheckState_Float64_KnownValueWrongType(t *testin knownvalue.StringValueExact("str"), ), }, - ExpectError: regexp.MustCompile(`expected string value for StringValue check, got: json\.Number`), + ExpectError: regexp.MustCompile(`expected string value for StringValueExact check, got: json\.Number`), }, }, }) @@ -261,7 +261,7 @@ func TestExpectKnownOutputValue_CheckState_Float64_KnownValueWrongValue(t *testi knownvalue.Float64ValueExact(3.21), ), }, - ExpectError: regexp.MustCompile("expected value 3.21 for Float64Value check, got: 1.23"), + ExpectError: regexp.MustCompile("expected value 3.21 for Float64ValueExact check, got: 1.23"), }, }, }) @@ -322,7 +322,7 @@ func TestExpectKnownOutputValue_CheckState_Int64_KnownValueWrongValue(t *testing knownvalue.Int64ValueExact(321), ), }, - ExpectError: regexp.MustCompile("expected value 321 for Int64Value check, got: 123"), + ExpectError: regexp.MustCompile("expected value 321 for Int64ValueExact check, got: 123"), }, }, }) @@ -392,7 +392,7 @@ func TestExpectKnownOutputValue_CheckState_List_KnownValueWrongType(t *testing.T knownvalue.MapValueExact(map[string]knownvalue.Check{}), ), }, - ExpectError: regexp.MustCompile(`expected map\[string\]any value for MapValue check, got: \[\]interface {}`), + ExpectError: regexp.MustCompile(`expected map\[string\]any value for MapValueExact check, got: \[\]interface {}`), }, }, }) @@ -429,7 +429,7 @@ func TestExpectKnownOutputValue_CheckState_List_KnownValueWrongValue(t *testing. }), ), }, - ExpectError: regexp.MustCompile(`list element index 0: expected value value3 for StringValue check, got: value1`), + ExpectError: regexp.MustCompile(`list element index 0: expected value value3 for StringValueExact check, got: value1`), }, }, }) @@ -460,7 +460,7 @@ func TestExpectKnownOutputValue_CheckState_ListPartial(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "list_output", - knownvalue.ListValuePartialMatch(map[int]knownvalue.Check{ + knownvalue.ListValuePartial(map[int]knownvalue.Check{ 0: knownvalue.StringValueExact("value1"), }), ), @@ -497,12 +497,12 @@ func TestExpectKnownOutputValue_CheckState_ListPartial_KnownValueWrongValue(t *t ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "list_output", - knownvalue.ListValuePartialMatch(map[int]knownvalue.Check{ + knownvalue.ListValuePartial(map[int]knownvalue.Check{ 0: knownvalue.StringValueExact("value3"), }), ), }, - ExpectError: regexp.MustCompile(`list element 0: expected value value3 for StringValue check, got: value1`), + ExpectError: regexp.MustCompile(`list element 0: expected value value3 for StringValueExact check, got: value1`), }, }, }) @@ -569,7 +569,7 @@ func TestExpectKnownOutputValue_CheckState_ListElements_WrongNum(t *testing.T) { knownvalue.ListElementsExact(3), ), }, - ExpectError: regexp.MustCompile("expected 3 elements for ListElements check, got 2 elements"), + ExpectError: regexp.MustCompile("expected 3 elements for ListElementsExact check, got 2 elements"), }, }, }) @@ -644,7 +644,7 @@ func TestExpectKnownOutputValue_CheckState_ListNestedBlockPartial(t *testing.T) ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "list_nested_block_output", - knownvalue.ListValuePartialMatch(map[int]knownvalue.Check{ + knownvalue.ListValuePartial(map[int]knownvalue.Check{ 1: knownvalue.MapValueExact(map[string]knownvalue.Check{ "list_nested_block_attribute": knownvalue.StringValueExact("rts"), }), @@ -755,7 +755,7 @@ func TestExpectKnownOutputValue_CheckState_Map_KnownValueWrongType(t *testing.T) knownvalue.ListValueExact([]knownvalue.Check{}), ), }, - ExpectError: regexp.MustCompile(`expected \[\]any value for ListValue check, got: map\[string\]interface {}`), + ExpectError: regexp.MustCompile(`expected \[\]any value for ListValueExact check, got: map\[string\]interface {}`), }, }, }) @@ -792,7 +792,7 @@ func TestExpectKnownOutputValue_CheckState_Map_KnownValueWrongValue(t *testing.T }), ), }, - ExpectError: regexp.MustCompile(`missing element key3 for MapValue check`), + ExpectError: regexp.MustCompile(`missing element key3 for MapValueExact check`), }, }, }) @@ -823,7 +823,7 @@ func TestExpectKnownOutputValue_CheckState_MapPartial(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "map_output", - knownvalue.MapValuePartialMatch(map[string]knownvalue.Check{ + knownvalue.MapValuePartial(map[string]knownvalue.Check{ "key1": knownvalue.StringValueExact("value1"), }), ), @@ -858,7 +858,7 @@ func TestExpectKnownOutputValue_CheckState_MapPartial_KnownValueWrongValue(t *te ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "map_output", - knownvalue.MapValuePartialMatch(map[string]knownvalue.Check{ + knownvalue.MapValuePartial(map[string]knownvalue.Check{ "key3": knownvalue.StringValueExact("value1"), }), ), @@ -930,7 +930,7 @@ func TestExpectKnownOutputValue_CheckState_MapElements_WrongNum(t *testing.T) { knownvalue.MapElementsExact(3), ), }, - ExpectError: regexp.MustCompile("expected 3 elements for MapElements check, got 2 elements"), + ExpectError: regexp.MustCompile("expected 3 elements for MapElementsExact check, got 2 elements"), }, }, }) @@ -1003,7 +1003,7 @@ func TestExpectKnownOutputValue_CheckState_Number_KnownValueWrongValue(t *testin knownvalue.NumberValueExact(f), ), }, - ExpectError: regexp.MustCompile("expected value 321 for NumberValue check, got: 123"), + ExpectError: regexp.MustCompile("expected value 321 for NumberValueExact check, got: 123"), }, }, }) @@ -1076,7 +1076,7 @@ func TestExpectKnownOutputValue_CheckState_Set_KnownValueWrongValue(t *testing.T }), ), }, - ExpectError: regexp.MustCompile(`missing value value3 for SetValue check`), + ExpectError: regexp.MustCompile(`missing value value3 for SetValueExact check`), }, }, }) @@ -1107,7 +1107,7 @@ func TestExpectKnownOutputValue_CheckState_SetPartial(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "set_output", - knownvalue.SetValuePartialMatch([]knownvalue.Check{ + knownvalue.SetValuePartial([]knownvalue.Check{ knownvalue.StringValueExact("value2"), }), ), @@ -1142,7 +1142,7 @@ func TestExpectKnownOutputValue_CheckState_SetPartial_KnownValueWrongValue(t *te ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "set_output", - knownvalue.SetValuePartialMatch([]knownvalue.Check{ + knownvalue.SetValuePartial([]knownvalue.Check{ knownvalue.StringValueExact("value3"), }), ), @@ -1255,7 +1255,7 @@ func TestExpectKnownOutputValue_CheckState_SetNestedBlockPartial(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "set_nested_block_output", - knownvalue.SetValuePartialMatch([]knownvalue.Check{ + knownvalue.SetValuePartial([]knownvalue.Check{ knownvalue.MapValueExact(map[string]knownvalue.Check{ "set_nested_block_attribute": knownvalue.StringValueExact("rts"), }), @@ -1355,7 +1355,7 @@ func TestExpectKnownOutputValue_CheckState_String_KnownValueWrongType(t *testing "string_output", knownvalue.BoolValueExact(true)), }, - ExpectError: regexp.MustCompile("expected bool value for BoolValue check, got: string"), + ExpectError: regexp.MustCompile("expected bool value for BoolValueExact check, got: string"), }, }, }) @@ -1385,7 +1385,7 @@ func TestExpectKnownOutputValue_CheckState_String_KnownValueWrongValue(t *testin "string_output", knownvalue.StringValueExact("rts")), }, - ExpectError: regexp.MustCompile("expected value rts for StringValue check, got: str"), + ExpectError: regexp.MustCompile("expected value rts for StringValueExact check, got: str"), }, }, }) @@ -1412,7 +1412,7 @@ func TestExpectKnownOutputValue_CheckState_UnknownAttributeType(t *testing.T) { }, }, }, - expectedErr: fmt.Errorf("expected json.Number value for Int64Value check, got: float32"), + expectedErr: fmt.Errorf("expected json.Number value for Int64ValueExact check, got: float32"), }, } diff --git a/statecheck/expect_known_value_test.go b/statecheck/expect_known_value_test.go index ce2d0a5c9..c95086d4b 100644 --- a/statecheck/expect_known_value_test.go +++ b/statecheck/expect_known_value_test.go @@ -122,7 +122,7 @@ func TestExpectKnownValue_CheckState_Bool_KnownValueWrongType(t *testing.T) { knownvalue.Float64ValueExact(1.23), ), }, - ExpectError: regexp.MustCompile(`expected json\.Number value for Float64Value check, got: bool`), + ExpectError: regexp.MustCompile(`expected json\.Number value for Float64ValueExact check, got: bool`), }, }, }) @@ -150,7 +150,7 @@ func TestExpectKnownValue_CheckState_Bool_KnownValueWrongValue(t *testing.T) { knownvalue.BoolValueExact(false), ), }, - ExpectError: regexp.MustCompile("expected value false for BoolValue check, got: true"), + ExpectError: regexp.MustCompile("expected value false for BoolValueExact check, got: true"), }, }, }) @@ -206,7 +206,7 @@ func TestExpectKnownValue_CheckState_Float64_KnownValueWrongType(t *testing.T) { knownvalue.StringValueExact("str"), ), }, - ExpectError: regexp.MustCompile(`expected string value for StringValue check, got: json\.Number`), + ExpectError: regexp.MustCompile(`expected string value for StringValueExact check, got: json\.Number`), }, }, }) @@ -234,7 +234,7 @@ func TestExpectKnownValue_CheckState_Float64_KnownValueWrongValue(t *testing.T) knownvalue.Float64ValueExact(3.21), ), }, - ExpectError: regexp.MustCompile("expected value 3.21 for Float64Value check, got: 1.23"), + ExpectError: regexp.MustCompile("expected value 3.21 for Float64ValueExact check, got: 1.23"), }, }, }) @@ -289,7 +289,7 @@ func TestExpectKnownValue_CheckState_Int64_KnownValueWrongValue(t *testing.T) { knownvalue.Int64ValueExact(321), ), }, - ExpectError: regexp.MustCompile("expected value 321 for Int64Value check, got: 123"), + ExpectError: regexp.MustCompile("expected value 321 for Int64ValueExact check, got: 123"), }, }, }) @@ -353,7 +353,7 @@ func TestExpectKnownValue_CheckState_List_KnownValueWrongType(t *testing.T) { knownvalue.MapValueExact(map[string]knownvalue.Check{}), ), }, - ExpectError: regexp.MustCompile(`expected map\[string\]any value for MapValue check, got: \[\]interface {}`), + ExpectError: regexp.MustCompile(`expected map\[string\]any value for MapValueExact check, got: \[\]interface {}`), }, }, }) @@ -387,7 +387,7 @@ func TestExpectKnownValue_CheckState_List_KnownValueWrongValue(t *testing.T) { }), ), }, - ExpectError: regexp.MustCompile(`list element index 0: expected value value3 for StringValue check, got: value1`), + ExpectError: regexp.MustCompile(`list element index 0: expected value value3 for StringValueExact check, got: value1`), }, }, }) @@ -415,7 +415,7 @@ func TestExpectKnownValue_CheckState_ListPartial(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_attribute"), - knownvalue.ListValuePartialMatch(map[int]knownvalue.Check{ + knownvalue.ListValuePartial(map[int]knownvalue.Check{ 0: knownvalue.StringValueExact("value1"), }), ), @@ -449,12 +449,12 @@ func TestExpectKnownValue_CheckState_ListPartial_KnownValueWrongValue(t *testing statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_attribute"), - knownvalue.ListValuePartialMatch(map[int]knownvalue.Check{ + knownvalue.ListValuePartial(map[int]knownvalue.Check{ 0: knownvalue.StringValueExact("value3"), }), ), }, - ExpectError: regexp.MustCompile(`list element 0: expected value value3 for StringValue check, got: value1`), + ExpectError: regexp.MustCompile(`list element 0: expected value value3 for StringValueExact check, got: value1`), }, }, }) @@ -515,7 +515,7 @@ func TestExpectKnownValue_CheckState_ListElements_WrongNum(t *testing.T) { knownvalue.ListElementsExact(3), ), }, - ExpectError: regexp.MustCompile("expected 3 elements for ListElements check, got 2 elements"), + ExpectError: regexp.MustCompile("expected 3 elements for ListElementsExact check, got 2 elements"), }, }, }) @@ -584,7 +584,7 @@ func TestExpectKnownValue_CheckState_ListNestedBlockPartial(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_nested_block"), - knownvalue.ListValuePartialMatch(map[int]knownvalue.Check{ + knownvalue.ListValuePartial(map[int]knownvalue.Check{ 1: knownvalue.MapValueExact(map[string]knownvalue.Check{ "list_nested_block_attribute": knownvalue.StringValueExact("rts"), }), @@ -686,7 +686,7 @@ func TestExpectKnownValue_CheckState_Map_KnownValueWrongType(t *testing.T) { knownvalue.ListValueExact([]knownvalue.Check{}), ), }, - ExpectError: regexp.MustCompile(`expected \[\]any value for ListValue check, got: map\[string\]interface {}`), + ExpectError: regexp.MustCompile(`expected \[\]any value for ListValueExact check, got: map\[string\]interface {}`), }, }, }) @@ -720,7 +720,7 @@ func TestExpectKnownValue_CheckState_Map_KnownValueWrongValue(t *testing.T) { }), ), }, - ExpectError: regexp.MustCompile(`missing element key3 for MapValue check`), + ExpectError: regexp.MustCompile(`missing element key3 for MapValueExact check`), }, }, }) @@ -748,7 +748,7 @@ func TestExpectKnownValue_CheckState_MapPartial(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("map_attribute"), - knownvalue.MapValuePartialMatch(map[string]knownvalue.Check{ + knownvalue.MapValuePartial(map[string]knownvalue.Check{ "key1": knownvalue.StringValueExact("value1"), }), ), @@ -780,7 +780,7 @@ func TestExpectKnownValue_CheckState_MapPartial_KnownValueWrongValue(t *testing. statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("map_attribute"), - knownvalue.MapValuePartialMatch(map[string]knownvalue.Check{ + knownvalue.MapValuePartial(map[string]knownvalue.Check{ "key3": knownvalue.StringValueExact("value1"), }), ), @@ -846,7 +846,7 @@ func TestExpectKnownValue_CheckState_MapElements_WrongNum(t *testing.T) { knownvalue.MapElementsExact(3), ), }, - ExpectError: regexp.MustCompile("expected 3 elements for MapElements check, got 2 elements"), + ExpectError: regexp.MustCompile("expected 3 elements for MapElementsExact check, got 2 elements"), }, }, }) @@ -913,7 +913,7 @@ func TestExpectKnownValue_CheckState_Number_KnownValueWrongValue(t *testing.T) { knownvalue.NumberValueExact(f), ), }, - ExpectError: regexp.MustCompile("expected value 321 for NumberValue check, got: 123"), + ExpectError: regexp.MustCompile("expected value 321 for NumberValueExact check, got: 123"), }, }, }) @@ -980,7 +980,7 @@ func TestExpectKnownValue_CheckState_Set_KnownValueWrongValue(t *testing.T) { }), ), }, - ExpectError: regexp.MustCompile(`missing value value3 for SetValue check`), + ExpectError: regexp.MustCompile(`missing value value3 for SetValueExact check`), }, }, }) @@ -1008,7 +1008,7 @@ func TestExpectKnownValue_CheckState_SetPartial(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("set_attribute"), - knownvalue.SetValuePartialMatch([]knownvalue.Check{ + knownvalue.SetValuePartial([]knownvalue.Check{ knownvalue.StringValueExact("value2"), }), ), @@ -1040,7 +1040,7 @@ func TestExpectKnownValue_CheckState_SetPartial_KnownValueWrongValue(t *testing. statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("set_attribute"), - knownvalue.SetValuePartialMatch([]knownvalue.Check{ + knownvalue.SetValuePartial([]knownvalue.Check{ knownvalue.StringValueExact("value3"), }), ), @@ -1144,7 +1144,7 @@ func TestExpectKnownValue_CheckState_SetNestedBlockPartial(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("set_nested_block"), - knownvalue.SetValuePartialMatch([]knownvalue.Check{ + knownvalue.SetValuePartial([]knownvalue.Check{ knownvalue.MapValueExact(map[string]knownvalue.Check{ "set_nested_block_attribute": knownvalue.StringValueExact("rts"), }), @@ -1235,7 +1235,7 @@ func TestExpectKnownValue_CheckState_String_KnownValueWrongType(t *testing.T) { tfjsonpath.New("string_attribute"), knownvalue.BoolValueExact(true)), }, - ExpectError: regexp.MustCompile("expected bool value for BoolValue check, got: string"), + ExpectError: regexp.MustCompile("expected bool value for BoolValueExact check, got: string"), }, }, }) @@ -1262,7 +1262,7 @@ func TestExpectKnownValue_CheckState_String_KnownValueWrongValue(t *testing.T) { tfjsonpath.New("string_attribute"), knownvalue.StringValueExact("rts")), }, - ExpectError: regexp.MustCompile("expected value rts for StringValue check, got: str"), + ExpectError: regexp.MustCompile("expected value rts for StringValueExact check, got: str"), }, }, }) @@ -1294,7 +1294,7 @@ func TestExpectKnownValue_CheckState_UnknownAttributeType(t *testing.T) { }, }, }, - expectedErr: fmt.Errorf("expected json.Number value for Int64Value check, got: float32"), + expectedErr: fmt.Errorf("expected json.Number value for Int64ValueExact check, got: float32"), }, } diff --git a/statecheck/expect_sensitive_value.go b/statecheck/expect_sensitive_value.go index 7e8ec7325..447a2cb27 100644 --- a/statecheck/expect_sensitive_value.go +++ b/statecheck/expect_sensitive_value.go @@ -78,8 +78,6 @@ func (e expectSensitiveValue) CheckState(ctx context.Context, req CheckStateRequ resp.Error = fmt.Errorf("attribute at path is not sensitive") return } - - return } // ExpectSensitiveValue returns a state check that asserts that the specified attribute at the given resource has a sensitive value. From 7ff68bcef229ef769020cb8f3bd983e7f6cc58ab Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Mon, 15 Jan 2024 15:24:13 +0000 Subject: [PATCH 12/73] Correcting documentation for revised naming of known value check types (#266) --- website/data/plugin-testing-nav-data.json | 4 ++ .../known-value-checks/bool.mdx | 10 +-- .../known-value-checks/float64.mdx | 10 +-- .../known-value-checks/index.mdx | 8 +-- .../known-value-checks/int64.mdx | 10 +-- .../known-value-checks/list.mdx | 48 +++++++------- .../known-value-checks/map.mdx | 50 +++++++-------- .../known-value-checks/null.mdx | 10 +-- .../known-value-checks/number.mdx | 10 +-- .../known-value-checks/object.mdx | 63 ++++--------------- .../known-value-checks/set.mdx | 48 +++++++------- .../known-value-checks/string.mdx | 10 +-- .../acceptance-tests/plan-checks/output.mdx | 4 +- .../acceptance-tests/plan-checks/resource.mdx | 2 +- .../acceptance-tests/state-checks/custom.mdx | 2 +- .../acceptance-tests/state-checks/output.mdx | 4 +- .../state-checks/resource.mdx | 2 +- 17 files changed, 131 insertions(+), 164 deletions(-) diff --git a/website/data/plugin-testing-nav-data.json b/website/data/plugin-testing-nav-data.json index 40fc85629..dce49a74f 100644 --- a/website/data/plugin-testing-nav-data.json +++ b/website/data/plugin-testing-nav-data.json @@ -102,6 +102,10 @@ "title": "Map", "path": "acceptance-tests/known-value-checks/map" }, + { + "title": "Null", + "path": "acceptance-tests/known-value-checks/null" + }, { "title": "Number", "path": "acceptance-tests/known-value-checks/number" diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/bool.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/bool.mdx index 039bc347b..1a5c09a53 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/bool.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/bool.mdx @@ -8,13 +8,13 @@ description: >- The known value checks that are available for bool values are: -* [BoolValueExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/bool#boolvalueexact-check) +* [BoolExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/bool#boolexact-check) -## `BoolValueExact` Check +## `BoolExact` Check -The [BoolValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#BoolValueExact) check tests that a resource attribute, or output value has an exactly matching bool value. +The [BoolExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#BoolExact) check tests that a resource attribute, or output value has an exactly matching bool value. -Example usage of [BoolValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#BoolValueExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. +Example usage of [BoolExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#BoolExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. ```go func TestExpectKnownValue_CheckPlan_Bool(t *testing.T) { @@ -33,7 +33,7 @@ func TestExpectKnownValue_CheckPlan_Bool(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), - knownvalue.BoolValueExact(true), + knownvalue.BoolExact(true), ), }, }, diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/float64.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/float64.mdx index d4bacb127..ebaa17d39 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/float64.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/float64.mdx @@ -8,13 +8,13 @@ description: >- The known value checks that are available for float64 values are: -* [Float64ValueExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/float64#float64valueexact-check) +* [Float64Exact](/terraform/plugin/testing/acceptance-tests/known-value-checks/float64#float64exact-check) -## `Float64ValueExact` Check +## `Float64Exact` Check -The [Float64ValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Float64ValueExact) check tests that a resource attribute, or output value has an exactly matching float64 value. +The [Float64Exact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Float64Exact) check tests that a resource attribute, or output value has an exactly matching float64 value. -Example usage of [Float64ValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Float64ValueExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. +Example usage of [Float64Exact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Float64Exact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. ```go func TestExpectKnownValue_CheckPlan_Float64(t *testing.T) { @@ -33,7 +33,7 @@ func TestExpectKnownValue_CheckPlan_Float64(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("float_attribute"), - knownvalue.Float64ValueExact(1.23), + knownvalue.Float64Exact(1.23), ), }, }, diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/index.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/index.mdx index dae04a89d..bc22d96e5 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/index.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/index.mdx @@ -20,15 +20,15 @@ Example uses in the testing module include: The known value check types are implemented within the `terraform-plugin-testing` module in the [`knownvalue` package](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue). Known value checks are instantiated by calling the relevant constructor function. ```go -knownvalue.BoolValueExact(true) +knownvalue.BoolExact(true) ``` For known value checks that represent collections, or objects, nesting of known value checks can be used to define a "composite" known value check for use in asserting against a resource attribute, or output value that contains other values. ```go -knownvalue.ListValueExact([]knownvalue.Check{ - knownvalue.StringValueExact("value1"), - knownvalue.StringValueExact("value2"), +knownvalue.ListExact([]knownvalue.Check{ + knownvalue.StringExact("value1"), + knownvalue.StringExact("value2"), }) ``` diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/int64.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/int64.mdx index 9954cd7ec..214fcef25 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/int64.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/int64.mdx @@ -8,13 +8,13 @@ description: >- The known value checks that are available for int64 values are: -* [Int64ValueExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/float64#int64valueexact-check) +* [Int64Exact](/terraform/plugin/testing/acceptance-tests/known-value-checks/float64#int64exact-check) -## `Int64ValueExact` Check +## `Int64Exact` Check -The [Int64ValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Int64ValueExact) check tests that a resource attribute, or output value has an exactly matching int64 value. +The [Int64Exact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Int64Exact) check tests that a resource attribute, or output value has an exactly matching int64 value. -Example usage of [Int64ValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Int64ValueExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. +Example usage of [Int64Exact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Int64Exact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. ```go func TestExpectKnownValue_CheckPlan_Int64(t *testing.T) { @@ -33,7 +33,7 @@ func TestExpectKnownValue_CheckPlan_Int64(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("int_attribute"), - knownvalue.Int64ValueExact(123), + knownvalue.Int64Exact(123), ), }, }, diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/list.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/list.mdx index 774cedc02..e491e58b6 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/list.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/list.mdx @@ -8,22 +8,22 @@ description: >- The known value checks that are available for list values are: -* [ListElementsExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/list#listelementsexact-check) -* [ListValueExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/list#listvalueexact-check) -* [ListValuePartialMatch](/terraform/plugin/testing/acceptance-tests/known-value-checks/list#listvaluepartialmatch-check) +* [ListExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/list#listexact-check) +* [ListPartial](/terraform/plugin/testing/acceptance-tests/known-value-checks/list#listpartial-check) +* [ListSizeExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/list#listsizeexact-check) -## `ListElementsExact` Check +## `ListExact` Check -The [ListElementsExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ListElementsExact) check tests that a resource attribute, or output value contains the specified number of elements. +The [ListExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ListExact) check tests that a resource attribute, or output value has an order-dependent, matching collection of element values. -Example usage of [ListElementsExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ListElementsExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. +Example usage of [ListExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ListExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. ```go -func TestExpectKnownValue_CheckPlan_ListElements(t *testing.T) { +func TestExpectKnownValue_CheckPlan_List(t *testing.T) { t.Parallel() resource.Test(t, resource.TestCase{ - // Provider definition omitted. + // Provider definition omitted. Steps: []resource.TestStep{ { Config: `resource "test_resource" "one" { @@ -38,7 +38,10 @@ func TestExpectKnownValue_CheckPlan_ListElements(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_attribute"), - knownvalue.ListElementsExact(2), + knownvalue.ListExact([]knownvalue.Check{ + knownvalue.StringExact("value1"), + knownvalue.StringExact("value2"), + }), ), }, }, @@ -48,18 +51,18 @@ func TestExpectKnownValue_CheckPlan_ListElements(t *testing.T) { } ``` -## `ListValueExact` Check +## `ListPartial` Check -The [ListValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ListValueExact) check tests that a resource attribute, or output value has an order-dependent, matching collection of element values. +The [ListPartial](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ListPartial) check tests that a resource attribute, or output value has matching element values for the specified collection indices. -Example usage of [ListValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ListValueExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. +Example usage of [ListPartial](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ListPartial) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. In this example, only the first element within the list, the element defined at index `0`, is checked. ```go -func TestExpectKnownValue_CheckPlan_List(t *testing.T) { +func TestExpectKnownValue_CheckPlan_ListPartial(t *testing.T) { t.Parallel() resource.Test(t, resource.TestCase{ - // Provider definition omitted. + // Provider definition omitted. Steps: []resource.TestStep{ { Config: `resource "test_resource" "one" { @@ -74,9 +77,8 @@ func TestExpectKnownValue_CheckPlan_List(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_attribute"), - knownvalue.ListValueExact([]knownvalue.Check{ - knownvalue.StringValueExact("value1"), - knownvalue.StringValueExact("value2"), + knownvalue.ListPartial(map[int]knownvalue.Check{ + 0: knownvalue.StringExact("value1"), }), ), }, @@ -87,14 +89,14 @@ func TestExpectKnownValue_CheckPlan_List(t *testing.T) { } ``` -## `ListValuePartialMatch` Check +## `ListSizeExact` Check -The [ListValuePartialMatch](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ListValuePartialMatch) check tests that a resource attribute, or output value has matching element values for the specified collection indices. +The [ListSizeExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ListSizeExact) check tests that a resource attribute, or output value contains the specified number of elements. -Example usage of [ListValuePartialMatch](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ListValuePartialMatch) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. In this example, only the first element within the list, the element defined at index `0`, is checked. +Example usage of [ListSizeExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ListSizeExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. ```go -func TestExpectKnownValue_CheckPlan_ListPartial(t *testing.T) { +func TestExpectKnownValue_CheckPlan_ListElements(t *testing.T) { t.Parallel() resource.Test(t, resource.TestCase{ @@ -113,9 +115,7 @@ func TestExpectKnownValue_CheckPlan_ListPartial(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_attribute"), - knownvalue.ListValuePartialMatch(map[int]knownvalue.Check{ - 0: knownvalue.StringValueExact("value1"), - }), + knownvalue.ListSizeExact(2), ), }, }, diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/map.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/map.mdx index ea1a5c252..fc04c2f80 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/map.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/map.mdx @@ -8,18 +8,18 @@ description: >- The known value checks that are available for map values are: -* [MapElementsExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/map#mapelementsexact-check) -* [MapValueExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/map#mapvalueexact-check) -* [MapValuePartialMatch](/terraform/plugin/testing/acceptance-tests/known-value-checks/map#mapvaluepartialmatch-check) +* [MapExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/map#mapexact-check) +* [MapPartial](/terraform/plugin/testing/acceptance-tests/known-value-checks/map#mappartial-check) +* [MapSizeExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/map#mapsizeexact-check) -## `MapElementsExact` Check +## `MapExact` Check -The [MapElementsExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#MapElementsExact) check tests that a resource attribute, or output value contains the specified number of elements. +The [MapExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#MapExact) check tests that a resource attribute, or output value has a key-specified, matching collection of element values. -Example usage of [MapElementsExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#MapElementsExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. +Example usage of [MapExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#MapExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. ```go -func TestExpectKnownValue_CheckPlan_MapElements(t *testing.T) { +func TestExpectKnownValue_CheckPlan_Map(t *testing.T) { t.Parallel() resource.Test(t, resource.TestCase{ @@ -38,7 +38,10 @@ func TestExpectKnownValue_CheckPlan_MapElements(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("map_attribute"), - knownvalue.MapElementsExact(2), + knownvalue.MapExact(map[string]knownvalue.Check{ + "key1": knownvalue.StringExact("value1"), + "key2": knownvalue.StringExact("value2"), + }), ), }, }, @@ -48,14 +51,16 @@ func TestExpectKnownValue_CheckPlan_MapElements(t *testing.T) { } ``` -## `MapValueExact` Check +## `MapPartial` Check -The [MapValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#MapValueExact) check tests that a resource attribute, or output value has a key-specified, matching collection of element values. +The [MapPartial](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#MapPartial) check tests that a resource attribute, or output value has matching element values for the specified keys. -Example usage of [MapValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#MapValueExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. +Example usage of [MapPartial](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#MapPartial) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. + +In this example, only the element associated with `key1` within the map is checked. ```go -func TestExpectKnownValue_CheckPlan_Map(t *testing.T) { +func TestExpectKnownValue_CheckPlan_MapPartial(t *testing.T) { t.Parallel() resource.Test(t, resource.TestCase{ @@ -74,9 +79,8 @@ func TestExpectKnownValue_CheckPlan_Map(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("map_attribute"), - knownvalue.MapValueExact(map[string]knownvalue.Check{ - "key1": knownvalue.StringValueExact("value1"), - "key2": knownvalue.StringValueExact("value2"), + knownvalue.MapPartial(map[string]knownvalue.Check{ + "key1": knownvalue.StringExact("value1"), }), ), }, @@ -87,16 +91,14 @@ func TestExpectKnownValue_CheckPlan_Map(t *testing.T) { } ``` -## `MapValuePartialMatch` Check +## `MapSizeExact` Check -The [MapValuePartialMatch](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#MapValuePartialMatch) check tests that a resource attribute, or output value has matching element values for the specified keys. +The [MapSizeExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#MapSizeExact) check tests that a resource attribute, or output value contains the specified number of elements. -Example usage of [MapValuePartialMatch](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#MapValuePartialMatch) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. - -In this example, only the element associated with `key1` within the map is checked. +Example usage of [MapSizeExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#MapSizeExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. ```go -func TestExpectKnownValue_CheckPlan_MapPartial(t *testing.T) { +func TestExpectKnownValue_CheckPlan_MapElements(t *testing.T) { t.Parallel() resource.Test(t, resource.TestCase{ @@ -115,9 +117,7 @@ func TestExpectKnownValue_CheckPlan_MapPartial(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("map_attribute"), - knownvalue.MapValuePartialMatch(map[string]knownvalue.Check{ - "key1": knownvalue.StringValueExact("value1"), - }), + knownvalue.MapSizeExact(2), ), }, }, @@ -125,4 +125,4 @@ func TestExpectKnownValue_CheckPlan_MapPartial(t *testing.T) { }, }) } -``` +``` \ No newline at end of file diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/null.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/null.mdx index 9d50ee65e..58d95ce8d 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/null.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/null.mdx @@ -8,13 +8,13 @@ description: >- The known value checks that are available for null values are: -* [NullValueExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/null#nullvalueexact-check) +* [NullExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/null#nullexact-check) -## `NullValueExact` Check +## `NullExact` Check -The [NullValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NullValueExact) check tests that a resource attribute, or output value has an exactly matching null value. +The [NullExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NullExact) check tests that a resource attribute, or output value has an exactly matching null value. -Example usage of [NullValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NullValueExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/state-checks/resource) state check. +Example usage of [NullExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NullExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/state-checks/resource) state check. ```go func TestExpectKnownValue_CheckState_AttributeValueNull(t *testing.T) { @@ -29,7 +29,7 @@ func TestExpectKnownValue_CheckState_AttributeValueNull(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), - knownvalue.NullValueExact(), + knownvalue.NullExact(), ), }, }, diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/number.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/number.mdx index 784146c06..fe5345727 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/number.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/number.mdx @@ -8,13 +8,13 @@ description: >- The known value checks that are available for number values are: -* [NumberValueExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/number#numbervalueexact-check) +* [NumberExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/number#numberexact-check) -## `NumberValueExact` Check +## `NumberExact` Check -The [NumberValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NumberValueExact) check tests that a resource attribute, or output value has an exactly matching number value. +The [NumberExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NumberExact) check tests that a resource attribute, or output value has an exactly matching number value. -Example usage of [NumberValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NumberValueExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. +Example usage of [NumberExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NumberExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. ```go func TestExpectKnownValue_CheckPlan_Number(t *testing.T) { @@ -39,7 +39,7 @@ func TestExpectKnownValue_CheckPlan_Number(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("number_attribute"), - knownvalue.NumberValueExact(num), + knownvalue.NumberExact(num), ), }, }, diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/object.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/object.mdx index 55e4b923b..86e62a786 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/object.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/object.mdx @@ -8,51 +8,14 @@ description: >- The known value checks that are available for object values are: -* [ObjectElementsExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/object#objectelementsexact-check) -* [ObjectValueExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/object#objectvalueexact-check) -* [ObjectValuePartialMatch](/terraform/plugin/testing/acceptance-tests/known-value-checks/object#objectvaluepartialmatch-check) +* [ObjectExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/object#objectexact-check) +* [ObjectPartial](/terraform/plugin/testing/acceptance-tests/known-value-checks/object#objectpartial-check) -## `ObjectElementsExact` Check +## `ObjectExact` Check -The [ObjectElementsExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ObjectElementsExact) check tests that a resource attribute, or output value contains the specified number of attributes. +The [ObjectExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ObjectExact) check tests that a resource attribute, or output value has a matching collection of attribute name, and attribute values. -Example usage of [ObjectElementsExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ObjectElementsExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. - -```go -func TestExpectKnownValue_CheckPlan_ObjectElements(t *testing.T) { - t.Parallel() - - resource.Test(t, resource.TestCase{ - // Provider definition omitted. - Steps: []resource.TestStep{ - { - Config: `resource "test_resource" "one" { - object_attribute = { - key1 = "value1" - key2 = "value2" - } - } - `, - ConfigPlanChecks: resource.ConfigPlanChecks{ - PreApply: []plancheck.PlanCheck{ - plancheck.ExpectKnownValue( - "test_resource.one", - tfjsonpath.New("object_attribute"), - knownvalue.ObjectElementsExact(2), - ), - }, - }, - }, - }, - }) -} -``` - -## `ObjectValueExact` Check - -The [ObjectValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ObjectValueExact) check tests that a resource attribute, or output value has a matching collection of attribute name, and attribute values. - -Example usage of [ObjectValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ObjectValueExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. +Example usage of [ObjectExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ObjectExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. ```go func TestExpectKnownValue_CheckPlan_Object(t *testing.T) { @@ -74,9 +37,9 @@ func TestExpectKnownValue_CheckPlan_Object(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("object_attribute"), - knownvalue.ObjectValueExact(map[string]knownvalue.Check{ - "attr1": knownvalue.StringValueExact("value1"), - "attr2": knownvalue.StringValueExact("value2"), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "attr1": knownvalue.StringExact("value1"), + "attr2": knownvalue.StringExact("value2"), }), ), }, @@ -87,11 +50,11 @@ func TestExpectKnownValue_CheckPlan_Object(t *testing.T) { } ``` -## `ObjectValuePartialMatch` Check +## `ObjectPartial` Check -The [ObjectValuePartialMatch](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ObjectValuePartialMatch) check tests that a resource attribute, or output value has matching attribute values for the specified attribute names. +The [ObjectPartial](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ObjectPartial) check tests that a resource attribute, or output value has matching attribute values for the specified attribute names. -Example usage of [ObjectValuePartialMatch](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ObjectValuePartialMatch) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. +Example usage of [ObjectPartial](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ObjectPartial) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. In this example, only the attribute value associated with the attribute name `attr1` within the object is checked. @@ -115,8 +78,8 @@ func TestExpectKnownValue_CheckPlan_ObjectPartial(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("object_attribute"), - knownvalue.ObjectValuePartialMatch(map[string]knownvalue.Check{ - "attr1": knownvalue.StringValueExact("value1"), + knownvalue.ObjectPartial(map[string]knownvalue.Check{ + "attr1": knownvalue.StringExact("value1"), }), ), }, diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/set.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/set.mdx index 64d646a2b..f4bf5730f 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/set.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/set.mdx @@ -8,22 +8,22 @@ description: >- The known value checks that are available for set values are: -* [SetElementsExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/set#setelementsexact-check) -* [SetValueExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/set#setvalueexact-check) -* [SetValuePartialMatch](/terraform/plugin/testing/acceptance-tests/known-value-checks/set#setvaluepartialmatch-check) +* [SetExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/set#setexact-check) +* [SetPartial](/terraform/plugin/testing/acceptance-tests/known-value-checks/set#setpartial-check) +* [SetSizeExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/set#setsizeexact-check) -## `SetElementsExact` Check +## `SetExact` Check -The [SetElementsExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetElementsExact) check tests that a resource attribute, or output value contains the specified number of elements. +The [SetExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetExact) check tests that a resource attribute, or output value has an order-independent, matching collection of element values. -Example usage of [SetElementsExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetElementsExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. +Example usage of [SetExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. ```go -func TestExpectKnownValue_CheckPlan_SetElements(t *testing.T) { +func TestExpectKnownValue_CheckPlan_Set(t *testing.T) { t.Parallel() resource.Test(t, resource.TestCase{ - // Provider definition omitted. + // Provider definition omitted. Steps: []resource.TestStep{ { Config: `resource "test_resource" "one" { @@ -38,7 +38,10 @@ func TestExpectKnownValue_CheckPlan_SetElements(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("set_attribute"), - knownvalue.SetElementsExact(2), + knownvalue.SetExact([]knownvalue.Check{ + knownvalue.StringExact("value2"), + knownvalue.StringExact("value1"), + }), ), }, }, @@ -48,18 +51,18 @@ func TestExpectKnownValue_CheckPlan_SetElements(t *testing.T) { } ``` -## `SetValueExact` Check +## `SetPartial` Check -The [SetValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetValueExact) check tests that a resource attribute, or output value has an order-independent, matching collection of element values. +The [SetPartial](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetPartial) check tests that a resource attribute, or output value contains matching element values. -Example usage of [SetValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetValueExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. +Example usage of [SetPartial](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetPartial) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. In this example, only the one element within the set is checked. ```go -func TestExpectKnownValue_CheckPlan_Set(t *testing.T) { +func TestExpectKnownValue_CheckPlan_SetPartial(t *testing.T) { t.Parallel() resource.Test(t, resource.TestCase{ - // Provider definition omitted. + // Provider definition omitted. Steps: []resource.TestStep{ { Config: `resource "test_resource" "one" { @@ -74,9 +77,8 @@ func TestExpectKnownValue_CheckPlan_Set(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("set_attribute"), - knownvalue.SetValueExact([]knownvalue.Check{ - knownvalue.StringValueExact("value2"), - knownvalue.StringValueExact("value1"), + knownvalue.SetPartial([]knownvalue.Check{ + knownvalue.StringExact("value2"), }), ), }, @@ -87,14 +89,14 @@ func TestExpectKnownValue_CheckPlan_Set(t *testing.T) { } ``` -## `SetValuePartialMatch` Check +## `SetSizeExact` Check -The [SetValuePartialMatch](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetValuePartialMatch) check tests that a resource attribute, or output value contains matching element values. +The [SetSizeExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetSizeExact) check tests that a resource attribute, or output value contains the specified number of elements. -Example usage of [SetValuePartialMatch](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetValuePartialMatch) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. In this example, only the one element within the set is checked. +Example usage of [SetSizeExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetSizeExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. ```go -func TestExpectKnownValue_CheckPlan_SetPartial(t *testing.T) { +func TestExpectKnownValue_CheckPlan_SetElements(t *testing.T) { t.Parallel() resource.Test(t, resource.TestCase{ @@ -113,9 +115,7 @@ func TestExpectKnownValue_CheckPlan_SetPartial(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("set_attribute"), - knownvalue.SetValuePartialMatch([]knownvalue.Check{ - knownvalue.StringValueExact("value2"), - }), + knownvalue.SetSizeExact(2), ), }, }, diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/string.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/string.mdx index 2d771964b..f25a66907 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/string.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/string.mdx @@ -8,13 +8,13 @@ description: >- The known value checks that are available for string values are: -* [StringValueExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/string#stringvalueexact-check) +* [StringExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/string#stringexact-check) -## `StringValueExact` Check +## `StringExact` Check -The [StringValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#StringValueExact) check tests that a resource attribute, or output value has an exactly matching string value. +The [StringExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#StringExact) check tests that a resource attribute, or output value has an exactly matching string value. -Example usage of [StringValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#StringValueExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. +Example usage of [StringExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#StringExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. ```go func TestExpectKnownValue_CheckPlan_String(t *testing.T) { @@ -33,7 +33,7 @@ func TestExpectKnownValue_CheckPlan_String(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("string_attribute"), - knownvalue.StringValueExact("str")), + knownvalue.StringExact("str")), }, }, }, diff --git a/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx b/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx index 146ea2de7..6dd2121cd 100644 --- a/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx +++ b/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx @@ -44,7 +44,7 @@ func TestExpectKnownOutputValue_CheckPlan_Bool(t *testing.T) { PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownOutputValue( "bool_output", - knownvalue.BoolValueExact(true), + knownvalue.BoolExact(true), ), }, }, @@ -80,7 +80,7 @@ func TestExpectKnownOutputValue_CheckPlan_Bool(t *testing.T) { PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownOutputValue( "bool_output", - knownvalue.BoolValueExact(true), + knownvalue.BoolExact(true), ), }, }, diff --git a/website/docs/plugin/testing/acceptance-tests/plan-checks/resource.mdx b/website/docs/plugin/testing/acceptance-tests/plan-checks/resource.mdx index c0f93b6e7..2ef10e073 100644 --- a/website/docs/plugin/testing/acceptance-tests/plan-checks/resource.mdx +++ b/website/docs/plugin/testing/acceptance-tests/plan-checks/resource.mdx @@ -39,7 +39,7 @@ func TestExpectKnownValue_CheckPlan_String(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("string_attribute"), - knownvalue.StringValueExact("str")), + knownvalue.StringExact("str")), }, }, }, diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx index f3b3461b0..817be30fb 100644 --- a/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx @@ -109,7 +109,7 @@ func TestExpectKnownValue_CheckState_Bool(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), - knownvalue.BoolValueExact(true), + knownvalue.BoolExact(true), ), }, }, diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx index 01caccdae..b1e02da1f 100644 --- a/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx @@ -39,7 +39,7 @@ func TestExpectKnownOutputValue_CheckState_Bool(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "bool_output", - knownvalue.BoolValueExact(true), + knownvalue.BoolExact(true), ), }, }, @@ -74,7 +74,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Bool(t *testing.T) { statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("bool_attribute"), - knownvalue.BoolValueExact(true), + knownvalue.BoolExact(true), ), }, }, diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx index 990fd828b..582afbcdf 100644 --- a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx @@ -36,7 +36,7 @@ func TestExpectKnownValue_CheckState_Bool(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), - knownvalue.BoolValueExact(true), + knownvalue.BoolExact(true), ), }, }, From 5d0485957b026bb9e9adbf514adca914d0520779 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Mon, 15 Jan 2024 15:35:29 +0000 Subject: [PATCH 13/73] Renaming nul known value check (#266) --- knownvalue/null.go | 18 ++++++++---------- knownvalue/null_test.go | 15 +++++++++------ 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/knownvalue/null.go b/knownvalue/null.go index 93e773cb0..f10c5a3f5 100644 --- a/knownvalue/null.go +++ b/knownvalue/null.go @@ -7,28 +7,26 @@ import ( "fmt" ) -var _ Check = NullValue{} +var _ Check = nullExact{} -// NullValue is a Check for asserting equality between the value supplied -// to NullValueExact and the value passed to the CheckValue method. -type NullValue struct{} +type nullExact struct{} // CheckValue determines whether the passed value is of nil. -func (v NullValue) CheckValue(other any) error { +func (v nullExact) CheckValue(other any) error { if other != nil { - return fmt.Errorf("expected value nil for NullValue check, got: %T", other) + return fmt.Errorf("expected value nil for NullExact check, got: %T", other) } return nil } // String returns the string representation of nil. -func (v NullValue) String() string { +func (v nullExact) String() string { return "nil" } -// NullValueExact returns a Check for asserting equality nil +// NullExact returns a Check for asserting equality nil // and the value passed to the CheckValue method. -func NullValueExact() NullValue { - return NullValue{} +func NullExact() nullExact { + return nullExact{} } diff --git a/knownvalue/null_test.go b/knownvalue/null_test.go index b185ca220..94682ed7b 100644 --- a/knownvalue/null_test.go +++ b/knownvalue/null_test.go @@ -16,21 +16,24 @@ func TestNullValue_CheckValue(t *testing.T) { t.Parallel() testCases := map[string]struct { - self knownvalue.NullValue + self knownvalue.Check other any expectedError error }{ - "zero-nil": {}, + "zero-nil": { + self: knownvalue.NullExact(), + }, "zero-other": { + self: knownvalue.NullExact(), other: nil, // checking against the underlying value field zero-value }, "not-nil": { - self: knownvalue.NullValueExact(), + self: knownvalue.NullExact(), other: false, - expectedError: fmt.Errorf("expected value nil for NullValue check, got: bool"), + expectedError: fmt.Errorf("expected value nil for NullExact check, got: bool"), }, "equal": { - self: knownvalue.NullValueExact(), + self: knownvalue.NullExact(), other: nil, }, } @@ -53,7 +56,7 @@ func TestNullValue_CheckValue(t *testing.T) { func TestNullValue_String(t *testing.T) { t.Parallel() - got := knownvalue.NullValueExact().String() + got := knownvalue.NullExact().String() if diff := cmp.Diff(got, "nil"); diff != "" { t.Errorf("unexpected difference: %s", diff) From a79aea8a152fdebd6d7699d709a073a16413e9ae Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Mon, 15 Jan 2024 15:35:38 +0000 Subject: [PATCH 14/73] Fixing tests (#266) --- .../expect_known_output_value_at_path_test.go | 180 +++++++++--------- statecheck/expect_known_output_value_test.go | 180 +++++++++--------- statecheck/expect_known_value_test.go | 180 +++++++++--------- 3 files changed, 270 insertions(+), 270 deletions(-) diff --git a/statecheck/expect_known_output_value_at_path_test.go b/statecheck/expect_known_output_value_at_path_test.go index 3fcd64637..018deb31b 100644 --- a/statecheck/expect_known_output_value_at_path_test.go +++ b/statecheck/expect_known_output_value_at_path_test.go @@ -43,7 +43,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_ResourceNotFound(t *testing.T) statecheck.ExpectKnownOutputValueAtPath( "test_resource_two_output", tfjsonpath.New("bool_attribute"), - knownvalue.BoolValueExact(true), + knownvalue.BoolExact(true), ), }, ExpectError: regexp.MustCompile("test_resource_two_output - Output not found in state"), @@ -73,7 +73,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_AttributeValueNull(t *testing.T statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("bool_attribute"), - knownvalue.NullValueExact(), + knownvalue.NullExact(), ), }, }, @@ -104,7 +104,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Bool(t *testing.T) { statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("bool_attribute"), - knownvalue.BoolValueExact(true), + knownvalue.BoolExact(true), ), }, }, @@ -135,10 +135,10 @@ func TestExpectKnownOutputValueAtPath_CheckState_Bool_KnownValueWrongType(t *tes statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("bool_attribute"), - knownvalue.Float64ValueExact(1.23), + knownvalue.Float64Exact(1.23), ), }, - ExpectError: regexp.MustCompile(`expected json\.Number value for Float64ValueExact check, got: bool`), + ExpectError: regexp.MustCompile(`expected json\.Number value for Float64Exact check, got: bool`), }, }, }) @@ -167,10 +167,10 @@ func TestExpectKnownOutputValueAtPath_CheckState_Bool_KnownValueWrongValue(t *te statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("bool_attribute"), - knownvalue.BoolValueExact(false), + knownvalue.BoolExact(false), ), }, - ExpectError: regexp.MustCompile("expected value false for BoolValueExact check, got: true"), + ExpectError: regexp.MustCompile("expected value false for BoolExact check, got: true"), }, }, }) @@ -199,7 +199,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Float64(t *testing.T) { statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("float_attribute"), - knownvalue.Float64ValueExact(1.23), + knownvalue.Float64Exact(1.23), ), }, }, @@ -231,10 +231,10 @@ func TestExpectKnownOutputValueAtPath_CheckState_Float64_KnownValueWrongType(t * statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("float_attribute"), - knownvalue.StringValueExact("str"), + knownvalue.StringExact("str"), ), }, - ExpectError: regexp.MustCompile(`expected string value for StringValueExact check, got: json\.Number`), + ExpectError: regexp.MustCompile(`expected string value for StringExact check, got: json\.Number`), }, }, }) @@ -263,10 +263,10 @@ func TestExpectKnownOutputValueAtPath_CheckState_Float64_KnownValueWrongValue(t statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("float_attribute"), - knownvalue.Float64ValueExact(3.21), + knownvalue.Float64Exact(3.21), ), }, - ExpectError: regexp.MustCompile("expected value 3.21 for Float64ValueExact check, got: 1.23"), + ExpectError: regexp.MustCompile("expected value 3.21 for Float64Exact check, got: 1.23"), }, }, }) @@ -295,7 +295,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Int64(t *testing.T) { statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("int_attribute"), - knownvalue.Int64ValueExact(123), + knownvalue.Int64Exact(123), ), }, }, @@ -326,10 +326,10 @@ func TestExpectKnownOutputValueAtPath_CheckState_Int64_KnownValueWrongValue(t *t statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("int_attribute"), - knownvalue.Int64ValueExact(321), + knownvalue.Int64Exact(321), ), }, - ExpectError: regexp.MustCompile("expected value 321 for Int64ValueExact check, got: 123"), + ExpectError: regexp.MustCompile("expected value 321 for Int64Exact check, got: 123"), }, }, }) @@ -361,9 +361,9 @@ func TestExpectKnownOutputValueAtPath_CheckState_List(t *testing.T) { statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("list_attribute"), - knownvalue.ListValueExact([]knownvalue.Check{ - knownvalue.StringValueExact("value1"), - knownvalue.StringValueExact("value2"), + knownvalue.ListExact([]knownvalue.Check{ + knownvalue.StringExact("value1"), + knownvalue.StringExact("value2"), }), ), }, @@ -398,10 +398,10 @@ func TestExpectKnownOutputValueAtPath_CheckState_List_KnownValueWrongType(t *tes statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("list_attribute"), - knownvalue.MapValueExact(map[string]knownvalue.Check{}), + knownvalue.MapExact(map[string]knownvalue.Check{}), ), }, - ExpectError: regexp.MustCompile(`expected map\[string\]any value for MapValueExact check, got: \[\]interface {}`), + ExpectError: regexp.MustCompile(`expected map\[string\]any value for MapExact check, got: \[\]interface {}`), }, }, }) @@ -433,13 +433,13 @@ func TestExpectKnownOutputValueAtPath_CheckState_List_KnownValueWrongValue(t *te statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("list_attribute"), - knownvalue.ListValueExact([]knownvalue.Check{ - knownvalue.StringValueExact("value3"), - knownvalue.StringValueExact("value4"), + knownvalue.ListExact([]knownvalue.Check{ + knownvalue.StringExact("value3"), + knownvalue.StringExact("value4"), }), ), }, - ExpectError: regexp.MustCompile(`list element index 0: expected value value3 for StringValueExact check, got: value1`), + ExpectError: regexp.MustCompile(`list element index 0: expected value value3 for StringExact check, got: value1`), }, }, }) @@ -471,8 +471,8 @@ func TestExpectKnownOutputValueAtPath_CheckState_ListPartial(t *testing.T) { statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("list_attribute"), - knownvalue.ListValuePartial(map[int]knownvalue.Check{ - 0: knownvalue.StringValueExact("value1"), + knownvalue.ListPartial(map[int]knownvalue.Check{ + 0: knownvalue.StringExact("value1"), }), ), }, @@ -509,12 +509,12 @@ func TestExpectKnownOutputValueAtPath_CheckState_ListPartial_KnownValueWrongValu statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("list_attribute"), - knownvalue.ListValuePartial(map[int]knownvalue.Check{ - 0: knownvalue.StringValueExact("value3"), + knownvalue.ListPartial(map[int]knownvalue.Check{ + 0: knownvalue.StringExact("value3"), }), ), }, - ExpectError: regexp.MustCompile(`list element 0: expected value value3 for StringValueExact check, got: value1`), + ExpectError: regexp.MustCompile(`list element 0: expected value value3 for StringExact check, got: value1`), }, }, }) @@ -546,7 +546,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_ListElements(t *testing.T) { statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("list_attribute"), - knownvalue.ListElementsExact(2), + knownvalue.ListSizeExact(2), ), }, }, @@ -580,10 +580,10 @@ func TestExpectKnownOutputValueAtPath_CheckState_ListElements_WrongNum(t *testin statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("list_attribute"), - knownvalue.ListElementsExact(3), + knownvalue.ListSizeExact(3), ), }, - ExpectError: regexp.MustCompile("expected 3 elements for ListElementsExact check, got 2 elements"), + ExpectError: regexp.MustCompile("expected 3 elements for ListSizeExact check, got 2 elements"), }, }, }) @@ -617,12 +617,12 @@ func TestExpectKnownOutputValueAtPath_CheckState_ListNestedBlock(t *testing.T) { statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("list_nested_block"), - knownvalue.ListValueExact([]knownvalue.Check{ - knownvalue.MapValueExact(map[string]knownvalue.Check{ - "list_nested_block_attribute": knownvalue.StringValueExact("str"), + knownvalue.ListExact([]knownvalue.Check{ + knownvalue.MapExact(map[string]knownvalue.Check{ + "list_nested_block_attribute": knownvalue.StringExact("str"), }), - knownvalue.MapValueExact(map[string]knownvalue.Check{ - "list_nested_block_attribute": knownvalue.StringValueExact("rts"), + knownvalue.MapExact(map[string]knownvalue.Check{ + "list_nested_block_attribute": knownvalue.StringExact("rts"), }), }), ), @@ -660,9 +660,9 @@ func TestExpectKnownOutputValueAtPath_CheckState_ListNestedBlockPartial(t *testi statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("list_nested_block"), - knownvalue.ListValuePartial(map[int]knownvalue.Check{ - 1: knownvalue.MapValueExact(map[string]knownvalue.Check{ - "list_nested_block_attribute": knownvalue.StringValueExact("rts"), + knownvalue.ListPartial(map[int]knownvalue.Check{ + 1: knownvalue.MapExact(map[string]knownvalue.Check{ + "list_nested_block_attribute": knownvalue.StringExact("rts"), }), }), ), @@ -700,7 +700,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_ListNestedBlockElements(t *test statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("list_nested_block"), - knownvalue.ListElementsExact(2), + knownvalue.ListSizeExact(2), ), }, }, @@ -734,9 +734,9 @@ func TestExpectKnownOutputValueAtPath_CheckState_Map(t *testing.T) { statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("map_attribute"), - knownvalue.MapValueExact(map[string]knownvalue.Check{ - "key1": knownvalue.StringValueExact("value1"), - "key2": knownvalue.StringValueExact("value2"), + knownvalue.MapExact(map[string]knownvalue.Check{ + "key1": knownvalue.StringExact("value1"), + "key2": knownvalue.StringExact("value2"), }), ), }, @@ -771,10 +771,10 @@ func TestExpectKnownOutputValueAtPath_CheckState_Map_KnownValueWrongType(t *test statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("map_attribute"), - knownvalue.ListValueExact([]knownvalue.Check{}), + knownvalue.ListExact([]knownvalue.Check{}), ), }, - ExpectError: regexp.MustCompile(`expected \[\]any value for ListValueExact check, got: map\[string\]interface {}`), + ExpectError: regexp.MustCompile(`expected \[\]any value for ListExact check, got: map\[string\]interface {}`), }, }, }) @@ -806,13 +806,13 @@ func TestExpectKnownOutputValueAtPath_CheckState_Map_KnownValueWrongValue(t *tes statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("map_attribute"), - knownvalue.MapValueExact(map[string]knownvalue.Check{ - "key3": knownvalue.StringValueExact("value3"), - "key4": knownvalue.StringValueExact("value4"), + knownvalue.MapExact(map[string]knownvalue.Check{ + "key3": knownvalue.StringExact("value3"), + "key4": knownvalue.StringExact("value4"), }), ), }, - ExpectError: regexp.MustCompile(`missing element key3 for MapValueExact check`), + ExpectError: regexp.MustCompile(`missing element key3 for MapExact check`), }, }, }) @@ -844,8 +844,8 @@ func TestExpectKnownOutputValueAtPath_CheckState_MapPartial(t *testing.T) { statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("map_attribute"), - knownvalue.MapValuePartial(map[string]knownvalue.Check{ - "key1": knownvalue.StringValueExact("value1"), + knownvalue.MapPartial(map[string]knownvalue.Check{ + "key1": knownvalue.StringExact("value1"), }), ), }, @@ -880,12 +880,12 @@ func TestExpectKnownOutputValueAtPath_CheckState_MapPartial_KnownValueWrongValue statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("map_attribute"), - knownvalue.MapValuePartial(map[string]knownvalue.Check{ - "key3": knownvalue.StringValueExact("value1"), + knownvalue.MapPartial(map[string]knownvalue.Check{ + "key3": knownvalue.StringExact("value1"), }), ), }, - ExpectError: regexp.MustCompile(`missing element key3 for MapValuePartial check`), + ExpectError: regexp.MustCompile(`missing element key3 for MapPartial check`), }, }, }) @@ -917,7 +917,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_MapElements(t *testing.T) { statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("map_attribute"), - knownvalue.MapElementsExact(2), + knownvalue.MapSizeExact(2), ), }, }, @@ -951,10 +951,10 @@ func TestExpectKnownOutputValueAtPath_CheckState_MapElements_WrongNum(t *testing statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("map_attribute"), - knownvalue.MapElementsExact(3), + knownvalue.MapSizeExact(3), ), }, - ExpectError: regexp.MustCompile("expected 3 elements for MapElementsExact check, got 2 elements"), + ExpectError: regexp.MustCompile("expected 3 elements for MapSizeExact check, got 2 elements"), }, }, }) @@ -989,7 +989,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Number(t *testing.T) { statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("int_attribute"), - knownvalue.NumberValueExact(f), + knownvalue.NumberExact(f), ), }, }, @@ -1026,10 +1026,10 @@ func TestExpectKnownOutputValueAtPath_CheckState_Number_KnownValueWrongValue(t * statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("int_attribute"), - knownvalue.NumberValueExact(f), + knownvalue.NumberExact(f), ), }, - ExpectError: regexp.MustCompile("expected value 321 for NumberValueExact check, got: 123"), + ExpectError: regexp.MustCompile("expected value 321 for NumberExact check, got: 123"), }, }, }) @@ -1061,9 +1061,9 @@ func TestExpectKnownOutputValueAtPath_CheckState_Set(t *testing.T) { statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("set_attribute"), - knownvalue.SetValueExact([]knownvalue.Check{ - knownvalue.StringValueExact("value1"), - knownvalue.StringValueExact("value2"), + knownvalue.SetExact([]knownvalue.Check{ + knownvalue.StringExact("value1"), + knownvalue.StringExact("value2"), }), ), }, @@ -1098,13 +1098,13 @@ func TestExpectKnownOutputValueAtPath_CheckState_Set_KnownValueWrongValue(t *tes statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("set_attribute"), - knownvalue.SetValueExact([]knownvalue.Check{ - knownvalue.StringValueExact("value1"), - knownvalue.StringValueExact("value3"), + knownvalue.SetExact([]knownvalue.Check{ + knownvalue.StringExact("value1"), + knownvalue.StringExact("value3"), }), ), }, - ExpectError: regexp.MustCompile(`missing value value3 for SetValueExact check`), + ExpectError: regexp.MustCompile(`missing value value3 for SetExact check`), }, }, }) @@ -1136,8 +1136,8 @@ func TestExpectKnownOutputValueAtPath_CheckState_SetPartial(t *testing.T) { statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("set_attribute"), - knownvalue.SetValuePartial([]knownvalue.Check{ - knownvalue.StringValueExact("value2"), + knownvalue.SetPartial([]knownvalue.Check{ + knownvalue.StringExact("value2"), }), ), }, @@ -1172,12 +1172,12 @@ func TestExpectKnownOutputValueAtPath_CheckState_SetPartial_KnownValueWrongValue statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("set_attribute"), - knownvalue.SetValuePartial([]knownvalue.Check{ - knownvalue.StringValueExact("value3"), + knownvalue.SetPartial([]knownvalue.Check{ + knownvalue.StringExact("value3"), }), ), }, - ExpectError: regexp.MustCompile(`missing value value3 for SetValuePartial check`), + ExpectError: regexp.MustCompile(`missing value value3 for SetPartial check`), }, }, }) @@ -1209,7 +1209,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_SetElements(t *testing.T) { statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("set_attribute"), - knownvalue.SetElementsExact(2), + knownvalue.SetSizeExact(2), ), }, }, @@ -1245,12 +1245,12 @@ func TestExpectKnownOutputValueAtPath_CheckState_SetNestedBlock(t *testing.T) { statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("set_nested_block"), - knownvalue.SetValueExact([]knownvalue.Check{ - knownvalue.MapValueExact(map[string]knownvalue.Check{ - "set_nested_block_attribute": knownvalue.StringValueExact("str"), + knownvalue.SetExact([]knownvalue.Check{ + knownvalue.MapExact(map[string]knownvalue.Check{ + "set_nested_block_attribute": knownvalue.StringExact("str"), }), - knownvalue.MapValueExact(map[string]knownvalue.Check{ - "set_nested_block_attribute": knownvalue.StringValueExact("rts"), + knownvalue.MapExact(map[string]knownvalue.Check{ + "set_nested_block_attribute": knownvalue.StringExact("rts"), }), }), ), @@ -1288,9 +1288,9 @@ func TestExpectKnownOutputValueAtPath_CheckState_SetNestedBlockPartial(t *testin statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("set_nested_block"), - knownvalue.SetValuePartial([]knownvalue.Check{ - knownvalue.MapValueExact(map[string]knownvalue.Check{ - "set_nested_block_attribute": knownvalue.StringValueExact("rts"), + knownvalue.SetPartial([]knownvalue.Check{ + knownvalue.MapExact(map[string]knownvalue.Check{ + "set_nested_block_attribute": knownvalue.StringExact("rts"), }), }), ), @@ -1328,7 +1328,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_SetNestedBlockElements(t *testi statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("set_nested_block"), - knownvalue.SetElementsExact(2), + knownvalue.SetSizeExact(2), ), }, }, @@ -1359,7 +1359,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_String(t *testing.T) { statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("string_attribute"), - knownvalue.StringValueExact("str")), + knownvalue.StringExact("str")), }, }, }, @@ -1389,9 +1389,9 @@ func TestExpectKnownOutputValueAtPath_CheckState_String_KnownValueWrongType(t *t statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("string_attribute"), - knownvalue.BoolValueExact(true)), + knownvalue.BoolExact(true)), }, - ExpectError: regexp.MustCompile("expected bool value for BoolValueExact check, got: string"), + ExpectError: regexp.MustCompile("expected bool value for BoolExact check, got: string"), }, }, }) @@ -1420,9 +1420,9 @@ func TestExpectKnownOutputValueAtPath_CheckState_String_KnownValueWrongValue(t * statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("string_attribute"), - knownvalue.StringValueExact("rts")), + knownvalue.StringExact("rts")), }, - ExpectError: regexp.MustCompile("expected value rts for StringValueExact check, got: str"), + ExpectError: regexp.MustCompile("expected value rts for StringExact check, got: str"), }, }, }) @@ -1437,7 +1437,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_UnknownAttributeType(t *testing expectedErr error }{ "unrecognised-type": { - knownValue: knownvalue.Int64ValueExact(123), + knownValue: knownvalue.Int64Exact(123), req: statecheck.CheckStateRequest{ State: &tfjson.State{ Values: &tfjson.StateValues{ @@ -1449,7 +1449,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_UnknownAttributeType(t *testing }, }, }, - expectedErr: fmt.Errorf("expected json.Number value for Int64ValueExact check, got: float32"), + expectedErr: fmt.Errorf("expected json.Number value for Int64Exact check, got: float32"), }, } diff --git a/statecheck/expect_known_output_value_test.go b/statecheck/expect_known_output_value_test.go index e4af792d5..612891f74 100644 --- a/statecheck/expect_known_output_value_test.go +++ b/statecheck/expect_known_output_value_test.go @@ -41,7 +41,7 @@ func TestExpectKnownOutputValue_CheckState_OutputNotFound(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "bool_not_found", - knownvalue.BoolValueExact(true), + knownvalue.BoolExact(true), ), }, ExpectError: regexp.MustCompile("bool_not_found - Output not found in state"), @@ -73,7 +73,7 @@ func TestExpectKnownOutputValue_CheckState_AttributeValueNull(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "bool_output", - knownvalue.BoolValueExact(true), + knownvalue.BoolExact(true), ), }, ExpectError: regexp.MustCompile("bool_output - Output not found in state"), @@ -104,7 +104,7 @@ func TestExpectKnownOutputValue_CheckState_Bool(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "bool_output", - knownvalue.BoolValueExact(true), + knownvalue.BoolExact(true), ), }, }, @@ -134,10 +134,10 @@ func TestExpectKnownOutputValue_CheckState_Bool_KnownValueWrongType(t *testing.T ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "bool_output", - knownvalue.Float64ValueExact(1.23), + knownvalue.Float64Exact(1.23), ), }, - ExpectError: regexp.MustCompile(`expected json\.Number value for Float64ValueExact check, got: bool`), + ExpectError: regexp.MustCompile(`expected json\.Number value for Float64Exact check, got: bool`), }, }, }) @@ -165,10 +165,10 @@ func TestExpectKnownOutputValue_CheckState_Bool_KnownValueWrongValue(t *testing. ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "bool_output", - knownvalue.BoolValueExact(false), + knownvalue.BoolExact(false), ), }, - ExpectError: regexp.MustCompile("expected value false for BoolValueExact check, got: true"), + ExpectError: regexp.MustCompile("expected value false for BoolExact check, got: true"), }, }, }) @@ -196,7 +196,7 @@ func TestExpectKnownOutputValue_CheckState_Float64(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "float64_output", - knownvalue.Float64ValueExact(1.23), + knownvalue.Float64Exact(1.23), ), }, }, @@ -227,10 +227,10 @@ func TestExpectKnownOutputValue_CheckState_Float64_KnownValueWrongType(t *testin ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "float64_output", - knownvalue.StringValueExact("str"), + knownvalue.StringExact("str"), ), }, - ExpectError: regexp.MustCompile(`expected string value for StringValueExact check, got: json\.Number`), + ExpectError: regexp.MustCompile(`expected string value for StringExact check, got: json\.Number`), }, }, }) @@ -258,10 +258,10 @@ func TestExpectKnownOutputValue_CheckState_Float64_KnownValueWrongValue(t *testi ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "float64_output", - knownvalue.Float64ValueExact(3.21), + knownvalue.Float64Exact(3.21), ), }, - ExpectError: regexp.MustCompile("expected value 3.21 for Float64ValueExact check, got: 1.23"), + ExpectError: regexp.MustCompile("expected value 3.21 for Float64Exact check, got: 1.23"), }, }, }) @@ -289,7 +289,7 @@ func TestExpectKnownOutputValue_CheckState_Int64(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "int64_output", - knownvalue.Int64ValueExact(123), + knownvalue.Int64Exact(123), ), }, }, @@ -319,10 +319,10 @@ func TestExpectKnownOutputValue_CheckState_Int64_KnownValueWrongValue(t *testing ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "int64_output", - knownvalue.Int64ValueExact(321), + knownvalue.Int64Exact(321), ), }, - ExpectError: regexp.MustCompile("expected value 321 for Int64ValueExact check, got: 123"), + ExpectError: regexp.MustCompile("expected value 321 for Int64Exact check, got: 123"), }, }, }) @@ -353,9 +353,9 @@ func TestExpectKnownOutputValue_CheckState_List(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "list_output", - knownvalue.ListValueExact([]knownvalue.Check{ - knownvalue.StringValueExact("value1"), - knownvalue.StringValueExact("value2"), + knownvalue.ListExact([]knownvalue.Check{ + knownvalue.StringExact("value1"), + knownvalue.StringExact("value2"), }), ), }, @@ -389,10 +389,10 @@ func TestExpectKnownOutputValue_CheckState_List_KnownValueWrongType(t *testing.T ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "list_output", - knownvalue.MapValueExact(map[string]knownvalue.Check{}), + knownvalue.MapExact(map[string]knownvalue.Check{}), ), }, - ExpectError: regexp.MustCompile(`expected map\[string\]any value for MapValueExact check, got: \[\]interface {}`), + ExpectError: regexp.MustCompile(`expected map\[string\]any value for MapExact check, got: \[\]interface {}`), }, }, }) @@ -423,13 +423,13 @@ func TestExpectKnownOutputValue_CheckState_List_KnownValueWrongValue(t *testing. ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "list_output", - knownvalue.ListValueExact([]knownvalue.Check{ - knownvalue.StringValueExact("value3"), - knownvalue.StringValueExact("value4"), + knownvalue.ListExact([]knownvalue.Check{ + knownvalue.StringExact("value3"), + knownvalue.StringExact("value4"), }), ), }, - ExpectError: regexp.MustCompile(`list element index 0: expected value value3 for StringValueExact check, got: value1`), + ExpectError: regexp.MustCompile(`list element index 0: expected value value3 for StringExact check, got: value1`), }, }, }) @@ -460,8 +460,8 @@ func TestExpectKnownOutputValue_CheckState_ListPartial(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "list_output", - knownvalue.ListValuePartial(map[int]knownvalue.Check{ - 0: knownvalue.StringValueExact("value1"), + knownvalue.ListPartial(map[int]knownvalue.Check{ + 0: knownvalue.StringExact("value1"), }), ), }, @@ -497,12 +497,12 @@ func TestExpectKnownOutputValue_CheckState_ListPartial_KnownValueWrongValue(t *t ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "list_output", - knownvalue.ListValuePartial(map[int]knownvalue.Check{ - 0: knownvalue.StringValueExact("value3"), + knownvalue.ListPartial(map[int]knownvalue.Check{ + 0: knownvalue.StringExact("value3"), }), ), }, - ExpectError: regexp.MustCompile(`list element 0: expected value value3 for StringValueExact check, got: value1`), + ExpectError: regexp.MustCompile(`list element 0: expected value value3 for StringExact check, got: value1`), }, }, }) @@ -533,7 +533,7 @@ func TestExpectKnownOutputValue_CheckState_ListElements(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "list_output", - knownvalue.ListElementsExact(2), + knownvalue.ListSizeExact(2), ), }, }, @@ -566,10 +566,10 @@ func TestExpectKnownOutputValue_CheckState_ListElements_WrongNum(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "list_output", - knownvalue.ListElementsExact(3), + knownvalue.ListSizeExact(3), ), }, - ExpectError: regexp.MustCompile("expected 3 elements for ListElementsExact check, got 2 elements"), + ExpectError: regexp.MustCompile("expected 3 elements for ListSizeExact check, got 2 elements"), }, }, }) @@ -602,12 +602,12 @@ func TestExpectKnownOutputValue_CheckState_ListNestedBlock(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "list_nested_block_output", - knownvalue.ListValueExact([]knownvalue.Check{ - knownvalue.MapValueExact(map[string]knownvalue.Check{ - "list_nested_block_attribute": knownvalue.StringValueExact("str"), + knownvalue.ListExact([]knownvalue.Check{ + knownvalue.MapExact(map[string]knownvalue.Check{ + "list_nested_block_attribute": knownvalue.StringExact("str"), }), - knownvalue.MapValueExact(map[string]knownvalue.Check{ - "list_nested_block_attribute": knownvalue.StringValueExact("rts"), + knownvalue.MapExact(map[string]knownvalue.Check{ + "list_nested_block_attribute": knownvalue.StringExact("rts"), }), }), ), @@ -644,9 +644,9 @@ func TestExpectKnownOutputValue_CheckState_ListNestedBlockPartial(t *testing.T) ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "list_nested_block_output", - knownvalue.ListValuePartial(map[int]knownvalue.Check{ - 1: knownvalue.MapValueExact(map[string]knownvalue.Check{ - "list_nested_block_attribute": knownvalue.StringValueExact("rts"), + knownvalue.ListPartial(map[int]knownvalue.Check{ + 1: knownvalue.MapExact(map[string]knownvalue.Check{ + "list_nested_block_attribute": knownvalue.StringExact("rts"), }), }), ), @@ -683,7 +683,7 @@ func TestExpectKnownOutputValue_CheckState_ListNestedBlockElements(t *testing.T) ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "list_nested_block_output", - knownvalue.ListElementsExact(2), + knownvalue.ListSizeExact(2), ), }, }, @@ -716,9 +716,9 @@ func TestExpectKnownOutputValue_CheckState_Map(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "map_output", - knownvalue.MapValueExact(map[string]knownvalue.Check{ - "key1": knownvalue.StringValueExact("value1"), - "key2": knownvalue.StringValueExact("value2"), + knownvalue.MapExact(map[string]knownvalue.Check{ + "key1": knownvalue.StringExact("value1"), + "key2": knownvalue.StringExact("value2"), }), ), }, @@ -752,10 +752,10 @@ func TestExpectKnownOutputValue_CheckState_Map_KnownValueWrongType(t *testing.T) ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "map_output", - knownvalue.ListValueExact([]knownvalue.Check{}), + knownvalue.ListExact([]knownvalue.Check{}), ), }, - ExpectError: regexp.MustCompile(`expected \[\]any value for ListValueExact check, got: map\[string\]interface {}`), + ExpectError: regexp.MustCompile(`expected \[\]any value for ListExact check, got: map\[string\]interface {}`), }, }, }) @@ -786,13 +786,13 @@ func TestExpectKnownOutputValue_CheckState_Map_KnownValueWrongValue(t *testing.T ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "map_output", - knownvalue.MapValueExact(map[string]knownvalue.Check{ - "key3": knownvalue.StringValueExact("value3"), - "key4": knownvalue.StringValueExact("value4"), + knownvalue.MapExact(map[string]knownvalue.Check{ + "key3": knownvalue.StringExact("value3"), + "key4": knownvalue.StringExact("value4"), }), ), }, - ExpectError: regexp.MustCompile(`missing element key3 for MapValueExact check`), + ExpectError: regexp.MustCompile(`missing element key3 for MapExact check`), }, }, }) @@ -823,8 +823,8 @@ func TestExpectKnownOutputValue_CheckState_MapPartial(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "map_output", - knownvalue.MapValuePartial(map[string]knownvalue.Check{ - "key1": knownvalue.StringValueExact("value1"), + knownvalue.MapPartial(map[string]knownvalue.Check{ + "key1": knownvalue.StringExact("value1"), }), ), }, @@ -858,12 +858,12 @@ func TestExpectKnownOutputValue_CheckState_MapPartial_KnownValueWrongValue(t *te ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "map_output", - knownvalue.MapValuePartial(map[string]knownvalue.Check{ - "key3": knownvalue.StringValueExact("value1"), + knownvalue.MapPartial(map[string]knownvalue.Check{ + "key3": knownvalue.StringExact("value1"), }), ), }, - ExpectError: regexp.MustCompile(`missing element key3 for MapValuePartial check`), + ExpectError: regexp.MustCompile(`missing element key3 for MapPartial check`), }, }, }) @@ -894,7 +894,7 @@ func TestExpectKnownOutputValue_CheckState_MapElements(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "map_output", - knownvalue.MapElementsExact(2), + knownvalue.MapSizeExact(2), ), }, }, @@ -927,10 +927,10 @@ func TestExpectKnownOutputValue_CheckState_MapElements_WrongNum(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "map_output", - knownvalue.MapElementsExact(3), + knownvalue.MapSizeExact(3), ), }, - ExpectError: regexp.MustCompile("expected 3 elements for MapElementsExact check, got 2 elements"), + ExpectError: regexp.MustCompile("expected 3 elements for MapSizeExact check, got 2 elements"), }, }, }) @@ -964,7 +964,7 @@ func TestExpectKnownOutputValue_CheckState_Number(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "int64_output", - knownvalue.NumberValueExact(f), + knownvalue.NumberExact(f), ), }, }, @@ -1000,10 +1000,10 @@ func TestExpectKnownOutputValue_CheckState_Number_KnownValueWrongValue(t *testin ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "int64_output", - knownvalue.NumberValueExact(f), + knownvalue.NumberExact(f), ), }, - ExpectError: regexp.MustCompile("expected value 321 for NumberValueExact check, got: 123"), + ExpectError: regexp.MustCompile("expected value 321 for NumberExact check, got: 123"), }, }, }) @@ -1034,9 +1034,9 @@ func TestExpectKnownOutputValue_CheckState_Set(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "set_output", - knownvalue.SetValueExact([]knownvalue.Check{ - knownvalue.StringValueExact("value1"), - knownvalue.StringValueExact("value2"), + knownvalue.SetExact([]knownvalue.Check{ + knownvalue.StringExact("value1"), + knownvalue.StringExact("value2"), }), ), }, @@ -1070,13 +1070,13 @@ func TestExpectKnownOutputValue_CheckState_Set_KnownValueWrongValue(t *testing.T ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "set_output", - knownvalue.SetValueExact([]knownvalue.Check{ - knownvalue.StringValueExact("value1"), - knownvalue.StringValueExact("value3"), + knownvalue.SetExact([]knownvalue.Check{ + knownvalue.StringExact("value1"), + knownvalue.StringExact("value3"), }), ), }, - ExpectError: regexp.MustCompile(`missing value value3 for SetValueExact check`), + ExpectError: regexp.MustCompile(`missing value value3 for SetExact check`), }, }, }) @@ -1107,8 +1107,8 @@ func TestExpectKnownOutputValue_CheckState_SetPartial(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "set_output", - knownvalue.SetValuePartial([]knownvalue.Check{ - knownvalue.StringValueExact("value2"), + knownvalue.SetPartial([]knownvalue.Check{ + knownvalue.StringExact("value2"), }), ), }, @@ -1142,12 +1142,12 @@ func TestExpectKnownOutputValue_CheckState_SetPartial_KnownValueWrongValue(t *te ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "set_output", - knownvalue.SetValuePartial([]knownvalue.Check{ - knownvalue.StringValueExact("value3"), + knownvalue.SetPartial([]knownvalue.Check{ + knownvalue.StringExact("value3"), }), ), }, - ExpectError: regexp.MustCompile(`missing value value3 for SetValuePartial check`), + ExpectError: regexp.MustCompile(`missing value value3 for SetPartial check`), }, }, }) @@ -1178,7 +1178,7 @@ func TestExpectKnownOutputValue_CheckState_SetElements(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "set_output", - knownvalue.SetElementsExact(2), + knownvalue.SetSizeExact(2), ), }, }, @@ -1213,12 +1213,12 @@ func TestExpectKnownOutputValue_CheckState_SetNestedBlock(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "set_nested_block_output", - knownvalue.SetValueExact([]knownvalue.Check{ - knownvalue.MapValueExact(map[string]knownvalue.Check{ - "set_nested_block_attribute": knownvalue.StringValueExact("str"), + knownvalue.SetExact([]knownvalue.Check{ + knownvalue.MapExact(map[string]knownvalue.Check{ + "set_nested_block_attribute": knownvalue.StringExact("str"), }), - knownvalue.MapValueExact(map[string]knownvalue.Check{ - "set_nested_block_attribute": knownvalue.StringValueExact("rts"), + knownvalue.MapExact(map[string]knownvalue.Check{ + "set_nested_block_attribute": knownvalue.StringExact("rts"), }), }), ), @@ -1255,9 +1255,9 @@ func TestExpectKnownOutputValue_CheckState_SetNestedBlockPartial(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "set_nested_block_output", - knownvalue.SetValuePartial([]knownvalue.Check{ - knownvalue.MapValueExact(map[string]knownvalue.Check{ - "set_nested_block_attribute": knownvalue.StringValueExact("rts"), + knownvalue.SetPartial([]knownvalue.Check{ + knownvalue.MapExact(map[string]knownvalue.Check{ + "set_nested_block_attribute": knownvalue.StringExact("rts"), }), }), ), @@ -1294,7 +1294,7 @@ func TestExpectKnownOutputValue_CheckState_SetNestedBlockElements(t *testing.T) ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "set_nested_block_output", - knownvalue.SetElementsExact(2), + knownvalue.SetSizeExact(2), ), }, }, @@ -1324,7 +1324,7 @@ func TestExpectKnownOutputValue_CheckState_String(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "string_output", - knownvalue.StringValueExact("str")), + knownvalue.StringExact("str")), }, }, }, @@ -1353,9 +1353,9 @@ func TestExpectKnownOutputValue_CheckState_String_KnownValueWrongType(t *testing ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "string_output", - knownvalue.BoolValueExact(true)), + knownvalue.BoolExact(true)), }, - ExpectError: regexp.MustCompile("expected bool value for BoolValueExact check, got: string"), + ExpectError: regexp.MustCompile("expected bool value for BoolExact check, got: string"), }, }, }) @@ -1383,9 +1383,9 @@ func TestExpectKnownOutputValue_CheckState_String_KnownValueWrongValue(t *testin ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "string_output", - knownvalue.StringValueExact("rts")), + knownvalue.StringExact("rts")), }, - ExpectError: regexp.MustCompile("expected value rts for StringValueExact check, got: str"), + ExpectError: regexp.MustCompile("expected value rts for StringExact check, got: str"), }, }, }) @@ -1400,7 +1400,7 @@ func TestExpectKnownOutputValue_CheckState_UnknownAttributeType(t *testing.T) { expectedErr error }{ "unrecognised-type": { - knownValue: knownvalue.Int64ValueExact(123), + knownValue: knownvalue.Int64Exact(123), req: statecheck.CheckStateRequest{ State: &tfjson.State{ Values: &tfjson.StateValues{ @@ -1412,7 +1412,7 @@ func TestExpectKnownOutputValue_CheckState_UnknownAttributeType(t *testing.T) { }, }, }, - expectedErr: fmt.Errorf("expected json.Number value for Int64ValueExact check, got: float32"), + expectedErr: fmt.Errorf("expected json.Number value for Int64Exact check, got: float32"), }, } diff --git a/statecheck/expect_known_value_test.go b/statecheck/expect_known_value_test.go index c95086d4b..e275212de 100644 --- a/statecheck/expect_known_value_test.go +++ b/statecheck/expect_known_value_test.go @@ -40,7 +40,7 @@ func TestExpectKnownValue_CheckState_ResourceNotFound(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.two", tfjsonpath.New("bool_attribute"), - knownvalue.BoolValueExact(true), + knownvalue.BoolExact(true), ), }, ExpectError: regexp.MustCompile("test_resource.two - Resource not found in state"), @@ -65,7 +65,7 @@ func TestExpectKnownValue_CheckState_AttributeValueNull(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), - knownvalue.NullValueExact(), + knownvalue.NullExact(), ), }, }, @@ -92,7 +92,7 @@ func TestExpectKnownValue_CheckState_Bool(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), - knownvalue.BoolValueExact(true), + knownvalue.BoolExact(true), ), }, }, @@ -119,10 +119,10 @@ func TestExpectKnownValue_CheckState_Bool_KnownValueWrongType(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), - knownvalue.Float64ValueExact(1.23), + knownvalue.Float64Exact(1.23), ), }, - ExpectError: regexp.MustCompile(`expected json\.Number value for Float64ValueExact check, got: bool`), + ExpectError: regexp.MustCompile(`expected json\.Number value for Float64Exact check, got: bool`), }, }, }) @@ -147,10 +147,10 @@ func TestExpectKnownValue_CheckState_Bool_KnownValueWrongValue(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), - knownvalue.BoolValueExact(false), + knownvalue.BoolExact(false), ), }, - ExpectError: regexp.MustCompile("expected value false for BoolValueExact check, got: true"), + ExpectError: regexp.MustCompile("expected value false for BoolExact check, got: true"), }, }, }) @@ -175,7 +175,7 @@ func TestExpectKnownValue_CheckState_Float64(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("float_attribute"), - knownvalue.Float64ValueExact(1.23), + knownvalue.Float64Exact(1.23), ), }, }, @@ -203,10 +203,10 @@ func TestExpectKnownValue_CheckState_Float64_KnownValueWrongType(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("float_attribute"), - knownvalue.StringValueExact("str"), + knownvalue.StringExact("str"), ), }, - ExpectError: regexp.MustCompile(`expected string value for StringValueExact check, got: json\.Number`), + ExpectError: regexp.MustCompile(`expected string value for StringExact check, got: json\.Number`), }, }, }) @@ -231,10 +231,10 @@ func TestExpectKnownValue_CheckState_Float64_KnownValueWrongValue(t *testing.T) statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("float_attribute"), - knownvalue.Float64ValueExact(3.21), + knownvalue.Float64Exact(3.21), ), }, - ExpectError: regexp.MustCompile("expected value 3.21 for Float64ValueExact check, got: 1.23"), + ExpectError: regexp.MustCompile("expected value 3.21 for Float64Exact check, got: 1.23"), }, }, }) @@ -259,7 +259,7 @@ func TestExpectKnownValue_CheckState_Int64(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("int_attribute"), - knownvalue.Int64ValueExact(123), + knownvalue.Int64Exact(123), ), }, }, @@ -286,10 +286,10 @@ func TestExpectKnownValue_CheckState_Int64_KnownValueWrongValue(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("int_attribute"), - knownvalue.Int64ValueExact(321), + knownvalue.Int64Exact(321), ), }, - ExpectError: regexp.MustCompile("expected value 321 for Int64ValueExact check, got: 123"), + ExpectError: regexp.MustCompile("expected value 321 for Int64Exact check, got: 123"), }, }, }) @@ -317,9 +317,9 @@ func TestExpectKnownValue_CheckState_List(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_attribute"), - knownvalue.ListValueExact([]knownvalue.Check{ - knownvalue.StringValueExact("value1"), - knownvalue.StringValueExact("value2"), + knownvalue.ListExact([]knownvalue.Check{ + knownvalue.StringExact("value1"), + knownvalue.StringExact("value2"), }), ), }, @@ -350,10 +350,10 @@ func TestExpectKnownValue_CheckState_List_KnownValueWrongType(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_attribute"), - knownvalue.MapValueExact(map[string]knownvalue.Check{}), + knownvalue.MapExact(map[string]knownvalue.Check{}), ), }, - ExpectError: regexp.MustCompile(`expected map\[string\]any value for MapValueExact check, got: \[\]interface {}`), + ExpectError: regexp.MustCompile(`expected map\[string\]any value for MapExact check, got: \[\]interface {}`), }, }, }) @@ -381,13 +381,13 @@ func TestExpectKnownValue_CheckState_List_KnownValueWrongValue(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_attribute"), - knownvalue.ListValueExact([]knownvalue.Check{ - knownvalue.StringValueExact("value3"), - knownvalue.StringValueExact("value4"), + knownvalue.ListExact([]knownvalue.Check{ + knownvalue.StringExact("value3"), + knownvalue.StringExact("value4"), }), ), }, - ExpectError: regexp.MustCompile(`list element index 0: expected value value3 for StringValueExact check, got: value1`), + ExpectError: regexp.MustCompile(`list element index 0: expected value value3 for StringExact check, got: value1`), }, }, }) @@ -415,8 +415,8 @@ func TestExpectKnownValue_CheckState_ListPartial(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_attribute"), - knownvalue.ListValuePartial(map[int]knownvalue.Check{ - 0: knownvalue.StringValueExact("value1"), + knownvalue.ListPartial(map[int]knownvalue.Check{ + 0: knownvalue.StringExact("value1"), }), ), }, @@ -449,12 +449,12 @@ func TestExpectKnownValue_CheckState_ListPartial_KnownValueWrongValue(t *testing statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_attribute"), - knownvalue.ListValuePartial(map[int]knownvalue.Check{ - 0: knownvalue.StringValueExact("value3"), + knownvalue.ListPartial(map[int]knownvalue.Check{ + 0: knownvalue.StringExact("value3"), }), ), }, - ExpectError: regexp.MustCompile(`list element 0: expected value value3 for StringValueExact check, got: value1`), + ExpectError: regexp.MustCompile(`list element 0: expected value value3 for StringExact check, got: value1`), }, }, }) @@ -482,7 +482,7 @@ func TestExpectKnownValue_CheckState_ListElements(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_attribute"), - knownvalue.ListElementsExact(2), + knownvalue.ListSizeExact(2), ), }, }, @@ -512,10 +512,10 @@ func TestExpectKnownValue_CheckState_ListElements_WrongNum(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_attribute"), - knownvalue.ListElementsExact(3), + knownvalue.ListSizeExact(3), ), }, - ExpectError: regexp.MustCompile("expected 3 elements for ListElementsExact check, got 2 elements"), + ExpectError: regexp.MustCompile("expected 3 elements for ListSizeExact check, got 2 elements"), }, }, }) @@ -545,12 +545,12 @@ func TestExpectKnownValue_CheckState_ListNestedBlock(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_nested_block"), - knownvalue.ListValueExact([]knownvalue.Check{ - knownvalue.MapValueExact(map[string]knownvalue.Check{ - "list_nested_block_attribute": knownvalue.StringValueExact("str"), + knownvalue.ListExact([]knownvalue.Check{ + knownvalue.MapExact(map[string]knownvalue.Check{ + "list_nested_block_attribute": knownvalue.StringExact("str"), }), - knownvalue.MapValueExact(map[string]knownvalue.Check{ - "list_nested_block_attribute": knownvalue.StringValueExact("rts"), + knownvalue.MapExact(map[string]knownvalue.Check{ + "list_nested_block_attribute": knownvalue.StringExact("rts"), }), }), ), @@ -584,9 +584,9 @@ func TestExpectKnownValue_CheckState_ListNestedBlockPartial(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_nested_block"), - knownvalue.ListValuePartial(map[int]knownvalue.Check{ - 1: knownvalue.MapValueExact(map[string]knownvalue.Check{ - "list_nested_block_attribute": knownvalue.StringValueExact("rts"), + knownvalue.ListPartial(map[int]knownvalue.Check{ + 1: knownvalue.MapExact(map[string]knownvalue.Check{ + "list_nested_block_attribute": knownvalue.StringExact("rts"), }), }), ), @@ -620,7 +620,7 @@ func TestExpectKnownValue_CheckState_ListNestedBlockElements(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_nested_block"), - knownvalue.ListElementsExact(2), + knownvalue.ListSizeExact(2), ), }, }, @@ -650,9 +650,9 @@ func TestExpectKnownValue_CheckState_Map(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("map_attribute"), - knownvalue.MapValueExact(map[string]knownvalue.Check{ - "key1": knownvalue.StringValueExact("value1"), - "key2": knownvalue.StringValueExact("value2"), + knownvalue.MapExact(map[string]knownvalue.Check{ + "key1": knownvalue.StringExact("value1"), + "key2": knownvalue.StringExact("value2"), }), ), }, @@ -683,10 +683,10 @@ func TestExpectKnownValue_CheckState_Map_KnownValueWrongType(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("map_attribute"), - knownvalue.ListValueExact([]knownvalue.Check{}), + knownvalue.ListExact([]knownvalue.Check{}), ), }, - ExpectError: regexp.MustCompile(`expected \[\]any value for ListValueExact check, got: map\[string\]interface {}`), + ExpectError: regexp.MustCompile(`expected \[\]any value for ListExact check, got: map\[string\]interface {}`), }, }, }) @@ -714,13 +714,13 @@ func TestExpectKnownValue_CheckState_Map_KnownValueWrongValue(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("map_attribute"), - knownvalue.MapValueExact(map[string]knownvalue.Check{ - "key3": knownvalue.StringValueExact("value3"), - "key4": knownvalue.StringValueExact("value4"), + knownvalue.MapExact(map[string]knownvalue.Check{ + "key3": knownvalue.StringExact("value3"), + "key4": knownvalue.StringExact("value4"), }), ), }, - ExpectError: regexp.MustCompile(`missing element key3 for MapValueExact check`), + ExpectError: regexp.MustCompile(`missing element key3 for MapExact check`), }, }, }) @@ -748,8 +748,8 @@ func TestExpectKnownValue_CheckState_MapPartial(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("map_attribute"), - knownvalue.MapValuePartial(map[string]knownvalue.Check{ - "key1": knownvalue.StringValueExact("value1"), + knownvalue.MapPartial(map[string]knownvalue.Check{ + "key1": knownvalue.StringExact("value1"), }), ), }, @@ -780,12 +780,12 @@ func TestExpectKnownValue_CheckState_MapPartial_KnownValueWrongValue(t *testing. statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("map_attribute"), - knownvalue.MapValuePartial(map[string]knownvalue.Check{ - "key3": knownvalue.StringValueExact("value1"), + knownvalue.MapPartial(map[string]knownvalue.Check{ + "key3": knownvalue.StringExact("value1"), }), ), }, - ExpectError: regexp.MustCompile(`missing element key3 for MapValuePartial check`), + ExpectError: regexp.MustCompile(`missing element key3 for MapPartial check`), }, }, }) @@ -813,7 +813,7 @@ func TestExpectKnownValue_CheckState_MapElements(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("map_attribute"), - knownvalue.MapElementsExact(2), + knownvalue.MapSizeExact(2), ), }, }, @@ -843,10 +843,10 @@ func TestExpectKnownValue_CheckState_MapElements_WrongNum(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("map_attribute"), - knownvalue.MapElementsExact(3), + knownvalue.MapSizeExact(3), ), }, - ExpectError: regexp.MustCompile("expected 3 elements for MapElementsExact check, got 2 elements"), + ExpectError: regexp.MustCompile("expected 3 elements for MapSizeExact check, got 2 elements"), }, }, }) @@ -877,7 +877,7 @@ func TestExpectKnownValue_CheckState_Number(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("int_attribute"), - knownvalue.NumberValueExact(f), + knownvalue.NumberExact(f), ), }, }, @@ -910,10 +910,10 @@ func TestExpectKnownValue_CheckState_Number_KnownValueWrongValue(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("int_attribute"), - knownvalue.NumberValueExact(f), + knownvalue.NumberExact(f), ), }, - ExpectError: regexp.MustCompile("expected value 321 for NumberValueExact check, got: 123"), + ExpectError: regexp.MustCompile("expected value 321 for NumberExact check, got: 123"), }, }, }) @@ -941,9 +941,9 @@ func TestExpectKnownValue_CheckState_Set(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("set_attribute"), - knownvalue.SetValueExact([]knownvalue.Check{ - knownvalue.StringValueExact("value2"), - knownvalue.StringValueExact("value1"), + knownvalue.SetExact([]knownvalue.Check{ + knownvalue.StringExact("value2"), + knownvalue.StringExact("value1"), }), ), }, @@ -974,13 +974,13 @@ func TestExpectKnownValue_CheckState_Set_KnownValueWrongValue(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("set_attribute"), - knownvalue.SetValueExact([]knownvalue.Check{ - knownvalue.StringValueExact("value1"), - knownvalue.StringValueExact("value3"), + knownvalue.SetExact([]knownvalue.Check{ + knownvalue.StringExact("value1"), + knownvalue.StringExact("value3"), }), ), }, - ExpectError: regexp.MustCompile(`missing value value3 for SetValueExact check`), + ExpectError: regexp.MustCompile(`missing value value3 for SetExact check`), }, }, }) @@ -1008,8 +1008,8 @@ func TestExpectKnownValue_CheckState_SetPartial(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("set_attribute"), - knownvalue.SetValuePartial([]knownvalue.Check{ - knownvalue.StringValueExact("value2"), + knownvalue.SetPartial([]knownvalue.Check{ + knownvalue.StringExact("value2"), }), ), }, @@ -1040,12 +1040,12 @@ func TestExpectKnownValue_CheckState_SetPartial_KnownValueWrongValue(t *testing. statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("set_attribute"), - knownvalue.SetValuePartial([]knownvalue.Check{ - knownvalue.StringValueExact("value3"), + knownvalue.SetPartial([]knownvalue.Check{ + knownvalue.StringExact("value3"), }), ), }, - ExpectError: regexp.MustCompile(`missing value value3 for SetValuePartial check`), + ExpectError: regexp.MustCompile(`missing value value3 for SetPartial check`), }, }, }) @@ -1073,7 +1073,7 @@ func TestExpectKnownValue_CheckState_SetElements(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("set_attribute"), - knownvalue.SetElementsExact(2), + knownvalue.SetSizeExact(2), ), }, }, @@ -1105,12 +1105,12 @@ func TestExpectKnownValue_CheckState_SetNestedBlock(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("set_nested_block"), - knownvalue.SetValueExact([]knownvalue.Check{ - knownvalue.MapValueExact(map[string]knownvalue.Check{ - "set_nested_block_attribute": knownvalue.StringValueExact("str"), + knownvalue.SetExact([]knownvalue.Check{ + knownvalue.MapExact(map[string]knownvalue.Check{ + "set_nested_block_attribute": knownvalue.StringExact("str"), }), - knownvalue.MapValueExact(map[string]knownvalue.Check{ - "set_nested_block_attribute": knownvalue.StringValueExact("rts"), + knownvalue.MapExact(map[string]knownvalue.Check{ + "set_nested_block_attribute": knownvalue.StringExact("rts"), }), }), ), @@ -1144,9 +1144,9 @@ func TestExpectKnownValue_CheckState_SetNestedBlockPartial(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("set_nested_block"), - knownvalue.SetValuePartial([]knownvalue.Check{ - knownvalue.MapValueExact(map[string]knownvalue.Check{ - "set_nested_block_attribute": knownvalue.StringValueExact("rts"), + knownvalue.SetPartial([]knownvalue.Check{ + knownvalue.MapExact(map[string]knownvalue.Check{ + "set_nested_block_attribute": knownvalue.StringExact("rts"), }), }), ), @@ -1180,7 +1180,7 @@ func TestExpectKnownValue_CheckState_SetNestedBlockElements(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("set_nested_block"), - knownvalue.SetElementsExact(2), + knownvalue.SetSizeExact(2), ), }, }, @@ -1207,7 +1207,7 @@ func TestExpectKnownValue_CheckState_String(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("string_attribute"), - knownvalue.StringValueExact("str")), + knownvalue.StringExact("str")), }, }, }, @@ -1233,9 +1233,9 @@ func TestExpectKnownValue_CheckState_String_KnownValueWrongType(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("string_attribute"), - knownvalue.BoolValueExact(true)), + knownvalue.BoolExact(true)), }, - ExpectError: regexp.MustCompile("expected bool value for BoolValueExact check, got: string"), + ExpectError: regexp.MustCompile("expected bool value for BoolExact check, got: string"), }, }, }) @@ -1260,9 +1260,9 @@ func TestExpectKnownValue_CheckState_String_KnownValueWrongValue(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("string_attribute"), - knownvalue.StringValueExact("rts")), + knownvalue.StringExact("rts")), }, - ExpectError: regexp.MustCompile("expected value rts for StringValueExact check, got: str"), + ExpectError: regexp.MustCompile("expected value rts for StringExact check, got: str"), }, }, }) @@ -1277,7 +1277,7 @@ func TestExpectKnownValue_CheckState_UnknownAttributeType(t *testing.T) { expectedErr error }{ "unrecognised-type": { - knownValue: knownvalue.Int64ValueExact(123), + knownValue: knownvalue.Int64Exact(123), req: statecheck.CheckStateRequest{ State: &tfjson.State{ Values: &tfjson.StateValues{ @@ -1294,7 +1294,7 @@ func TestExpectKnownValue_CheckState_UnknownAttributeType(t *testing.T) { }, }, }, - expectedErr: fmt.Errorf("expected json.Number value for Int64ValueExact check, got: float32"), + expectedErr: fmt.Errorf("expected json.Number value for Int64Exact check, got: float32"), }, } From f5abf73ec56fbc0f3609758d77985a5d054065a4 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Mon, 15 Jan 2024 16:33:28 +0000 Subject: [PATCH 15/73] Adding address and path to state check errors (#266) --- statecheck/expect_known_output_value.go | 2 +- statecheck/expect_known_output_value_at_path.go | 2 +- statecheck/expect_known_output_value_at_path_test.go | 10 ++++++---- statecheck/expect_known_output_value_test.go | 2 +- statecheck/expect_known_value.go | 2 +- statecheck/expect_known_value_test.go | 2 +- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/statecheck/expect_known_output_value.go b/statecheck/expect_known_output_value.go index 1cf6b69e8..64c47f819 100644 --- a/statecheck/expect_known_output_value.go +++ b/statecheck/expect_known_output_value.go @@ -56,7 +56,7 @@ func (e expectKnownOutputValue) CheckState(ctx context.Context, req CheckStateRe } if err := e.knownValue.CheckValue(result); err != nil { - resp.Error = err + resp.Error = fmt.Errorf("error checking value for output at path: %s, err: %s", e.outputAddress, err) return } diff --git a/statecheck/expect_known_output_value_at_path.go b/statecheck/expect_known_output_value_at_path.go index 7ff704b06..9fb8cc4f1 100644 --- a/statecheck/expect_known_output_value_at_path.go +++ b/statecheck/expect_known_output_value_at_path.go @@ -57,7 +57,7 @@ func (e expectKnownOutputValueAtPath) CheckState(ctx context.Context, req CheckS } if err := e.knownValue.CheckValue(result); err != nil { - resp.Error = err + resp.Error = fmt.Errorf("error checking value for output at path: %s.%s, err: %s", e.outputAddress, e.outputPath.String(), err) return } diff --git a/statecheck/expect_known_output_value_at_path_test.go b/statecheck/expect_known_output_value_at_path_test.go index 018deb31b..078daee04 100644 --- a/statecheck/expect_known_output_value_at_path_test.go +++ b/statecheck/expect_known_output_value_at_path_test.go @@ -1442,14 +1442,16 @@ func TestExpectKnownOutputValueAtPath_CheckState_UnknownAttributeType(t *testing State: &tfjson.State{ Values: &tfjson.StateValues{ Outputs: map[string]*tfjson.StateOutput{ - "float32_output": { - Value: float32(123), + "obj": { + Value: map[string]any{ + "float32_output": float32(123), + }, }, }, }, }, }, - expectedErr: fmt.Errorf("expected json.Number value for Int64Exact check, got: float32"), + expectedErr: fmt.Errorf("error checking value for output at path: obj.float32_output, err: expected json.Number value for Int64Exact check, got: float32"), }, } @@ -1459,7 +1461,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_UnknownAttributeType(t *testing t.Run(name, func(t *testing.T) { t.Parallel() - e := statecheck.ExpectKnownOutputValueAtPath("float32_output", tfjsonpath.Path{}, testCase.knownValue) + e := statecheck.ExpectKnownOutputValueAtPath("obj", tfjsonpath.New("float32_output"), testCase.knownValue) resp := statecheck.CheckStateResponse{} diff --git a/statecheck/expect_known_output_value_test.go b/statecheck/expect_known_output_value_test.go index 612891f74..b3f5e2ccf 100644 --- a/statecheck/expect_known_output_value_test.go +++ b/statecheck/expect_known_output_value_test.go @@ -1412,7 +1412,7 @@ func TestExpectKnownOutputValue_CheckState_UnknownAttributeType(t *testing.T) { }, }, }, - expectedErr: fmt.Errorf("expected json.Number value for Int64Exact check, got: float32"), + expectedErr: fmt.Errorf("error checking value for output at path: float32_output, err: expected json.Number value for Int64Exact check, got: float32"), }, } diff --git a/statecheck/expect_known_value.go b/statecheck/expect_known_value.go index 096699cba..96662c32a 100644 --- a/statecheck/expect_known_value.go +++ b/statecheck/expect_known_value.go @@ -61,7 +61,7 @@ func (e expectKnownValue) CheckState(ctx context.Context, req CheckStateRequest, } if err := e.knownValue.CheckValue(result); err != nil { - resp.Error = err + resp.Error = fmt.Errorf("error checking value for attribute at path: %s.%s, err: %s", e.resourceAddress, e.attributePath.String(), err) } } diff --git a/statecheck/expect_known_value_test.go b/statecheck/expect_known_value_test.go index e275212de..9625ec089 100644 --- a/statecheck/expect_known_value_test.go +++ b/statecheck/expect_known_value_test.go @@ -1294,7 +1294,7 @@ func TestExpectKnownValue_CheckState_UnknownAttributeType(t *testing.T) { }, }, }, - expectedErr: fmt.Errorf("expected json.Number value for Int64Exact check, got: float32"), + expectedErr: fmt.Errorf("error checking value for attribute at path: example_resource.test.attribute, err: expected json.Number value for Int64Exact check, got: float32"), }, } From 648730a4ea8474f51528fb1e8e90c58f0af7413c Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Tue, 16 Jan 2024 08:58:36 +0000 Subject: [PATCH 16/73] Fixing navigation (#266) --- website/data/plugin-testing-nav-data.json | 4 ---- .../known-value-checks/bool.mdx | 3 +-- .../known-value-checks/custom.mdx | 18 +++++++++--------- .../known-value-checks/float64.mdx | 3 +-- .../known-value-checks/int64.mdx | 3 +-- .../known-value-checks/list.mdx | 11 ++++------- .../known-value-checks/map.mdx | 9 +++------ .../known-value-checks/number.mdx | 3 +-- .../known-value-checks/object.mdx | 6 ++---- .../known-value-checks/set.mdx | 11 ++++------- .../known-value-checks/string.mdx | 3 +-- 11 files changed, 27 insertions(+), 47 deletions(-) diff --git a/website/data/plugin-testing-nav-data.json b/website/data/plugin-testing-nav-data.json index dce49a74f..f7ae6d8b5 100644 --- a/website/data/plugin-testing-nav-data.json +++ b/website/data/plugin-testing-nav-data.json @@ -110,10 +110,6 @@ "title": "Number", "path": "acceptance-tests/known-value-checks/number" }, - { - "title": "Null ", - "path": "acceptance-tests/known-value-checks/null" - }, { "title": "Object", "path": "acceptance-tests/known-value-checks/object" diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/bool.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/bool.mdx index 1a5c09a53..dfcb6e06b 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/bool.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/bool.mdx @@ -26,8 +26,7 @@ func TestExpectKnownValue_CheckPlan_Bool(t *testing.T) { { Config: `resource "test_resource" "one" { bool_attribute = true - } - `, + }`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/custom.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/custom.mdx index b9f69de1e..f5ce1d1de 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/custom.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/custom.mdx @@ -62,12 +62,12 @@ 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: -* [BoolValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#BoolValueExact) -* [Float64ValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Float64ValueExact) -* [Int64ValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Int64ValueExact) -* [ListValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ListValueExact) -* [MapValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#MapValueExact) -* [NumberValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NumberValueExact) -* [ObjectValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ObjectValueExact) -* [SetValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetValueExact) -* [StringValueExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#StringValueExact) +* [BoolExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#BoolExact) +* [Float64Exact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Float64Exact) +* [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) +* [NumberExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NumberExact) +* [ObjectExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ObjectExact) +* [SetExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetExact) +* [StringExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#StringExact) diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/float64.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/float64.mdx index ebaa17d39..7a22133ef 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/float64.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/float64.mdx @@ -26,8 +26,7 @@ func TestExpectKnownValue_CheckPlan_Float64(t *testing.T) { { Config: `resource "test_resource" "one" { float_attribute = 1.23 - } - `, + }`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/int64.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/int64.mdx index 214fcef25..ab3b61829 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/int64.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/int64.mdx @@ -26,8 +26,7 @@ func TestExpectKnownValue_CheckPlan_Int64(t *testing.T) { { Config: `resource "test_resource" "one" { int_attribute = 123 - } - `, + }`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/list.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/list.mdx index e491e58b6..fad959b43 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/list.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/list.mdx @@ -23,7 +23,7 @@ func TestExpectKnownValue_CheckPlan_List(t *testing.T) { t.Parallel() resource.Test(t, resource.TestCase{ - // Provider definition omitted. + // Provider definition omitted. Steps: []resource.TestStep{ { Config: `resource "test_resource" "one" { @@ -31,8 +31,7 @@ func TestExpectKnownValue_CheckPlan_List(t *testing.T) { "value1", "value2" ] - } - `, + }`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( @@ -70,8 +69,7 @@ func TestExpectKnownValue_CheckPlan_ListPartial(t *testing.T) { "value1", "value2" ] - } - `, + }`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( @@ -108,8 +106,7 @@ func TestExpectKnownValue_CheckPlan_ListElements(t *testing.T) { "value1", "value2" ] - } - `, + }`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/map.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/map.mdx index fc04c2f80..482686753 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/map.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/map.mdx @@ -31,8 +31,7 @@ func TestExpectKnownValue_CheckPlan_Map(t *testing.T) { key1 = "value1" key2 = "value2" } - } - `, + }`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( @@ -72,8 +71,7 @@ func TestExpectKnownValue_CheckPlan_MapPartial(t *testing.T) { key1 = "value1" key2 = "value2" } - } - `, + }`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( @@ -110,8 +108,7 @@ func TestExpectKnownValue_CheckPlan_MapElements(t *testing.T) { key1 = "value1" key2 = "value2" } - } - `, + }`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/number.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/number.mdx index fe5345727..6aee9e7cc 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/number.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/number.mdx @@ -32,8 +32,7 @@ func TestExpectKnownValue_CheckPlan_Number(t *testing.T) { { Config: `resource "test_resource" "one" { number_attribute = 123 - } - `, + }`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/object.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/object.mdx index 86e62a786..0d7229aed 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/object.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/object.mdx @@ -30,8 +30,7 @@ func TestExpectKnownValue_CheckPlan_Object(t *testing.T) { attr1 = "value1" attr2 = "value2" } - } - `, + }`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( @@ -71,8 +70,7 @@ func TestExpectKnownValue_CheckPlan_ObjectPartial(t *testing.T) { attr1 = "value1" attr2 = "value2" } - } - `, + }`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/set.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/set.mdx index f4bf5730f..23acb33a6 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/set.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/set.mdx @@ -23,7 +23,7 @@ func TestExpectKnownValue_CheckPlan_Set(t *testing.T) { t.Parallel() resource.Test(t, resource.TestCase{ - // Provider definition omitted. + // Provider definition omitted. Steps: []resource.TestStep{ { Config: `resource "test_resource" "one" { @@ -31,8 +31,7 @@ func TestExpectKnownValue_CheckPlan_Set(t *testing.T) { "value1", "value2" ] - } - `, + }`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( @@ -70,8 +69,7 @@ func TestExpectKnownValue_CheckPlan_SetPartial(t *testing.T) { "value1", "value2" ] - } - `, + }`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( @@ -108,8 +106,7 @@ func TestExpectKnownValue_CheckPlan_SetElements(t *testing.T) { "value1", "value2" ] - } - `, + }`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/string.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/string.mdx index f25a66907..bbe2fd80c 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/string.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/string.mdx @@ -26,8 +26,7 @@ func TestExpectKnownValue_CheckPlan_String(t *testing.T) { { Config: `resource "test_resource" "one" { string_attribute = "str" - } - `, + }`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( From a08f279582b19cd403d2858a8f1fae407b1ae4a4 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Tue, 16 Jan 2024 10:14:09 +0000 Subject: [PATCH 17/73] Adding ExpectNoValueExists check to replace TestCheckNoResourceAttr --- statecheck/expect_no_value_exists.go | 68 ++++++++++++++++ statecheck/expect_no_value_exists_test.go | 94 +++++++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 statecheck/expect_no_value_exists.go create mode 100644 statecheck/expect_no_value_exists_test.go diff --git a/statecheck/expect_no_value_exists.go b/statecheck/expect_no_value_exists.go new file mode 100644 index 000000000..b223e5ba8 --- /dev/null +++ b/statecheck/expect_no_value_exists.go @@ -0,0 +1,68 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package statecheck + +import ( + "context" + "fmt" + + tfjson "github.com/hashicorp/terraform-json" + + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + +// Resource State Check +var _ StateCheck = expectNoValueExists{} + +type expectNoValueExists struct { + resourceAddress string + attributePath tfjsonpath.Path +} + +// CheckState implements the state check logic. +func (e expectNoValueExists) CheckState(ctx context.Context, req CheckStateRequest, resp *CheckStateResponse) { + var rc *tfjson.StateResource + + if req.State == nil { + resp.Error = fmt.Errorf("state is nil") + } + + if req.State.Values == nil { + resp.Error = fmt.Errorf("state does not contain any state values") + } + + if req.State.Values.RootModule == nil { + resp.Error = fmt.Errorf("state does not contain a root module") + } + + for _, resourceChange := range req.State.Values.RootModule.Resources { + if e.resourceAddress == resourceChange.Address { + rc = resourceChange + + break + } + } + + // Resource doesn't exist + if rc == nil { + return + } + + _, err := tfjsonpath.Traverse(rc.AttributeValues, e.attributePath) + + if err == nil { + resp.Error = fmt.Errorf("attribute found at path: %s.%s", e.resourceAddress, e.attributePath.String()) + + return + } +} + +// ExpectNoValueExists returns a state check that asserts that the specified attribute at the given resource +// does not exist. +func ExpectNoValueExists(resourceAddress string, attributePath tfjsonpath.Path) StateCheck { + return expectNoValueExists{ + resourceAddress: resourceAddress, + attributePath: attributePath, + } +} diff --git a/statecheck/expect_no_value_exists_test.go b/statecheck/expect_no_value_exists_test.go new file mode 100644 index 000000000..c21e95d81 --- /dev/null +++ b/statecheck/expect_no_value_exists_test.go @@ -0,0 +1,94 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package statecheck_test + +import ( + "regexp" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + r "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + +func TestExpectNoValueExists_CheckState_ResourceNotFound(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectNoValueExists( + "does_not_exist", + tfjsonpath.New("bool_attribute"), + ), + }, + }, + }, + }) +} + +func TestExpectNoValueExists_CheckState_AttributeNotFound(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectNoValueExists( + "test_resource.one", + tfjsonpath.New("does_not_exist"), + ), + }, + }, + }, + }) +} + +func TestExpectNoValueExists_CheckState_AttributeFound(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectNoValueExists( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + ), + }, + ExpectError: regexp.MustCompile(`attribute found at path: test_resource\.one\.bool_attribute`), + }, + }, + }) +} From 22de2d029c0267d8e2faab3cade4821156882e16 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Tue, 16 Jan 2024 10:53:10 +0000 Subject: [PATCH 18/73] Adding ExpectMatchingValues check to replace TestCheckResourceAttrPair --- statecheck/expect_matching_values.go | 102 +++++++++ statecheck/expect_matching_values_test.go | 257 ++++++++++++++++++++++ 2 files changed, 359 insertions(+) create mode 100644 statecheck/expect_matching_values.go create mode 100644 statecheck/expect_matching_values_test.go diff --git a/statecheck/expect_matching_values.go b/statecheck/expect_matching_values.go new file mode 100644 index 000000000..fdcdc6749 --- /dev/null +++ b/statecheck/expect_matching_values.go @@ -0,0 +1,102 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package statecheck + +import ( + "context" + "fmt" + "reflect" + + tfjson "github.com/hashicorp/terraform-json" + + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + +// Resource State Check +var _ StateCheck = expectMatchingValues{} + +type expectMatchingValues struct { + resourceAddressOne string + attributePathOne tfjsonpath.Path + resourceAddressTwo string + attributePathTwo tfjsonpath.Path +} + +// CheckState implements the state check logic. +func (e expectMatchingValues) CheckState(ctx context.Context, req CheckStateRequest, resp *CheckStateResponse) { + var rcOne, rcTwo *tfjson.StateResource + + if req.State == nil { + resp.Error = fmt.Errorf("state is nil") + } + + if req.State.Values == nil { + resp.Error = fmt.Errorf("state does not contain any state values") + } + + if req.State.Values.RootModule == nil { + resp.Error = fmt.Errorf("state does not contain a root module") + } + + for _, resourceChange := range req.State.Values.RootModule.Resources { + if e.resourceAddressOne == resourceChange.Address { + rcOne = resourceChange + + break + } + } + + if rcOne == nil { + resp.Error = fmt.Errorf("%s - Resource not found in state", e.resourceAddressOne) + + return + } + + resultOne, err := tfjsonpath.Traverse(rcOne.AttributeValues, e.attributePathOne) + + if err != nil { + resp.Error = err + + return + } + + for _, resourceChange := range req.State.Values.RootModule.Resources { + if e.resourceAddressTwo == resourceChange.Address { + rcTwo = resourceChange + + break + } + } + + if rcTwo == nil { + resp.Error = fmt.Errorf("%s - Resource not found in state", e.resourceAddressTwo) + + return + } + + resultTwo, err := tfjsonpath.Traverse(rcTwo.AttributeValues, e.attributePathTwo) + + if err != nil { + resp.Error = err + + return + } + + if !reflect.DeepEqual(resultOne, resultTwo) { + resp.Error = fmt.Errorf("values are not equal: %v != %v", resultOne, resultTwo) + + return + } +} + +// ExpectMatchingValues returns a state check that asserts that the specified attributes at the given resources +// have a matching value. +func ExpectMatchingValues(resourceAddressOne string, attributePathOne tfjsonpath.Path, resourceAddressTwo string, attributePathTwo tfjsonpath.Path) StateCheck { + return expectMatchingValues{ + resourceAddressOne: resourceAddressOne, + attributePathOne: attributePathOne, + resourceAddressTwo: resourceAddressTwo, + attributePathTwo: attributePathTwo, + } +} diff --git a/statecheck/expect_matching_values_test.go b/statecheck/expect_matching_values_test.go new file mode 100644 index 000000000..dbc654626 --- /dev/null +++ b/statecheck/expect_matching_values_test.go @@ -0,0 +1,257 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package statecheck_test + +import ( + "regexp" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + r "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + +func TestExpectMatchingValues_CheckState_ResourceOneNotFound(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" {} + + resource "test_resource" "two" {}`, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectMatchingValues( + "does_not_exist_one", + tfjsonpath.New("bool_attribute"), + "test_resource.two", + tfjsonpath.New("bool_attribute"), + ), + }, + ExpectError: regexp.MustCompile("does_not_exist_one - Resource not found in state"), + }, + }, + }) +} + +func TestExpectMatchingValues_CheckState_ResourceTwoNotFound(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" {} + + resource "test_resource" "two" {}`, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectMatchingValues( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + "does_not_exist_two", + tfjsonpath.New("bool_attribute"), + ), + }, + ExpectError: regexp.MustCompile("does_not_exist_two - Resource not found in state"), + }, + }, + }) +} + +func TestExpectMatchingValues_CheckState_AttributeOneNotFound(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" {} + + resource "test_resource" "two" {}`, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectMatchingValues( + "test_resource.one", + tfjsonpath.New("does_not_exist_one"), + "test_resource.two", + tfjsonpath.New("bool_attribute"), + ), + }, + ExpectError: regexp.MustCompile("path not found: specified key does_not_exist_one not found in map at does_not_exist_one"), + }, + }, + }) +} + +func TestExpectMatchingValues_CheckState_AttributeTwoNotFound(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" {} + + resource "test_resource" "two" {}`, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectMatchingValues( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + "test_resource.two", + tfjsonpath.New("does_not_exist_two"), + ), + }, + ExpectError: regexp.MustCompile("path not found: specified key does_not_exist_two not found in map at does_not_exist_two"), + }, + }, + }) +} + +func TestExpectMatchingValues_CheckState_AttributeValuesNotEqualNil(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + + resource "test_resource" "two" {}`, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectMatchingValues( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + "test_resource.two", + tfjsonpath.New("bool_attribute"), + ), + }, + ExpectError: regexp.MustCompile("values are not equal: true != "), + }, + }, + }) +} + +func TestExpectMatchingValues_CheckState_AttributeValuesNotEqual(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + + resource "test_resource" "two" { + bool_attribute = false + }`, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectMatchingValues( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + "test_resource.two", + tfjsonpath.New("bool_attribute"), + ), + }, + ExpectError: regexp.MustCompile("values are not equal: true != false"), + }, + }, + }) +} + +func TestExpectMatchingValues_CheckState_AttributeValuesEqual_Bool(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + + resource "test_resource" "two" { + bool_attribute = true + }`, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectMatchingValues( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + "test_resource.two", + tfjsonpath.New("bool_attribute"), + ), + }, + }, + }, + }) +} + +func TestExpectMatchingValues_CheckState_AttributeValuesEqual_List(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + list_attribute = [ + "value1", + "value2" + ] + } + + resource "test_resource" "two" { + list_attribute = [ + "value1", + "value2" + ] + }`, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectMatchingValues( + "test_resource.one", + tfjsonpath.New("list_attribute"), + "test_resource.two", + tfjsonpath.New("list_attribute"), + ), + }, + }, + }, + }) +} From 41ecdaef7275204167b7b2b58a4e56f6d6fea28c Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Tue, 16 Jan 2024 11:34:38 +0000 Subject: [PATCH 19/73] Adding BoolPointerExact to illustrate a possible replacement for TestCheckResourceAttrPtr --- knownvalue/bool_pointer.go | 52 +++++++++++++++++++++++++++ statecheck/expect_known_value_test.go | 41 +++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 knownvalue/bool_pointer.go diff --git a/knownvalue/bool_pointer.go b/knownvalue/bool_pointer.go new file mode 100644 index 000000000..ccacf7656 --- /dev/null +++ b/knownvalue/bool_pointer.go @@ -0,0 +1,52 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package knownvalue + +import ( + "fmt" + "strconv" +) + +var _ Check = boolPointerExact{} + +type boolPointerExact struct { + value *bool +} + +// CheckValue determines whether the passed value is of type bool, and +// contains a matching bool value. +func (v boolPointerExact) CheckValue(other any) error { + if v.value == nil { + return fmt.Errorf("BoolExact check value is nil") + } + + otherVal, ok := other.(bool) + + if !ok { + return fmt.Errorf("expected bool value for BoolExact check, got: %T", other) + } + + if otherVal != *v.value { + return fmt.Errorf("expected value %t for BoolExact check, got: %t", v.value, otherVal) + } + + return nil +} + +// String returns the string representation of the bool value. +func (v boolPointerExact) String() string { + if v.value == nil { + return "" + } + + return strconv.FormatBool(*v.value) +} + +// BoolPointerExact returns a Check for asserting equality between the +// supplied bool and the value passed to the CheckValue method. +func BoolPointerExact(value *bool) boolPointerExact { + return boolPointerExact{ + value: value, + } +} diff --git a/statecheck/expect_known_value_test.go b/statecheck/expect_known_value_test.go index 9625ec089..87891654f 100644 --- a/statecheck/expect_known_value_test.go +++ b/statecheck/expect_known_value_test.go @@ -100,6 +100,47 @@ func TestExpectKnownValue_CheckState_Bool(t *testing.T) { }) } +func TestExpectKnownValue_CheckState_BoolPointer(t *testing.T) { + t.Parallel() + + var testBool bool + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + AlterValue(&testBool), + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + knownvalue.BoolPointerExact(&testBool), + ), + }, + }, + }, + }) +} + +type mutate struct{} + +func (m mutate) CheckState(context.Context, statecheck.CheckStateRequest, *statecheck.CheckStateResponse) { +} + +func AlterValue(b *bool) mutate { + *b = true + + return mutate{} +} + func TestExpectKnownValue_CheckState_Bool_KnownValueWrongType(t *testing.T) { t.Parallel() From f16ad135c301147e72afec2933526128f9d781ce Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Tue, 16 Jan 2024 13:01:58 +0000 Subject: [PATCH 20/73] Adding ExpectValueExists state check to replace TestCheckResourceAttrSet --- statecheck/expect_value_exists.go | 69 +++++++++++++++++++ statecheck/expect_value_exists_test.go | 95 ++++++++++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 statecheck/expect_value_exists.go create mode 100644 statecheck/expect_value_exists_test.go diff --git a/statecheck/expect_value_exists.go b/statecheck/expect_value_exists.go new file mode 100644 index 000000000..198e55c30 --- /dev/null +++ b/statecheck/expect_value_exists.go @@ -0,0 +1,69 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package statecheck + +import ( + "context" + "fmt" + + tfjson "github.com/hashicorp/terraform-json" + + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + +// Resource State Check +var _ StateCheck = expectValueExists{} + +type expectValueExists struct { + resourceAddress string + attributePath tfjsonpath.Path +} + +// CheckState implements the state check logic. +func (e expectValueExists) CheckState(ctx context.Context, req CheckStateRequest, resp *CheckStateResponse) { + var rc *tfjson.StateResource + + if req.State == nil { + resp.Error = fmt.Errorf("state is nil") + } + + if req.State.Values == nil { + resp.Error = fmt.Errorf("state does not contain any state values") + } + + if req.State.Values.RootModule == nil { + resp.Error = fmt.Errorf("state does not contain a root module") + } + + for _, resourceChange := range req.State.Values.RootModule.Resources { + if e.resourceAddress == resourceChange.Address { + rc = resourceChange + + break + } + } + + if rc == nil { + resp.Error = fmt.Errorf("%s - Resource not found in state", e.resourceAddress) + + return + } + + _, err := tfjsonpath.Traverse(rc.AttributeValues, e.attributePath) + + if err != nil { + resp.Error = err + + return + } +} + +// ExpectValueExists returns a state check that asserts that the specified attribute at the given resource +// does not exist. +func ExpectValueExists(resourceAddress string, attributePath tfjsonpath.Path) StateCheck { + return expectValueExists{ + resourceAddress: resourceAddress, + attributePath: attributePath, + } +} diff --git a/statecheck/expect_value_exists_test.go b/statecheck/expect_value_exists_test.go new file mode 100644 index 000000000..fb1760d59 --- /dev/null +++ b/statecheck/expect_value_exists_test.go @@ -0,0 +1,95 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package statecheck_test + +import ( + "regexp" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + r "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + +func TestExpectValueExists_CheckState_ResourceNotFound(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectValueExists( + "does_not_exist", + tfjsonpath.New("bool_attribute"), + ), + }, + ExpectError: regexp.MustCompile(`does_not_exist - Resource not found in state`), + }, + }, + }) +} + +func TestExpectValueExists_CheckState_AttributeNotFound(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectValueExists( + "test_resource.one", + tfjsonpath.New("does_not_exist"), + ), + }, + ExpectError: regexp.MustCompile(`path not found: specified key does_not_exist not found in map at does_not_exist`), + }, + }, + }) +} + +func TestExpectValueExists_CheckState_AttributeFound(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectValueExists( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + ), + }, + }, + }, + }) +} From ca1fd34599b47dc8ece05ee9d884aae82ac28a65 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Tue, 16 Jan 2024 13:58:00 +0000 Subject: [PATCH 21/73] Fixing bool pointer exact error message --- knownvalue/bool_pointer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/knownvalue/bool_pointer.go b/knownvalue/bool_pointer.go index ccacf7656..9b9459c13 100644 --- a/knownvalue/bool_pointer.go +++ b/knownvalue/bool_pointer.go @@ -28,7 +28,7 @@ func (v boolPointerExact) CheckValue(other any) error { } if otherVal != *v.value { - return fmt.Errorf("expected value %t for BoolExact check, got: %t", v.value, otherVal) + return fmt.Errorf("expected value %t for BoolExact check, got: %t", *v.value, otherVal) } return nil From 72a1193f2c65c0364bc42d0ad69bcd622391fd02 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Tue, 16 Jan 2024 14:00:50 +0000 Subject: [PATCH 22/73] Adding ExpectContains state check to replace TestCheckTypeSetElemAttrPair --- statecheck/expect_contains.go | 112 ++++++++++++++ statecheck/expect_contains_test.go | 227 +++++++++++++++++++++++++++++ 2 files changed, 339 insertions(+) create mode 100644 statecheck/expect_contains.go create mode 100644 statecheck/expect_contains_test.go diff --git a/statecheck/expect_contains.go b/statecheck/expect_contains.go new file mode 100644 index 000000000..237635dc8 --- /dev/null +++ b/statecheck/expect_contains.go @@ -0,0 +1,112 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package statecheck + +import ( + "context" + "fmt" + "reflect" + + tfjson "github.com/hashicorp/terraform-json" + + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + +// Resource State Check +var _ StateCheck = expectContains{} + +type expectContains struct { + resourceAddressOne string + attributePathOne tfjsonpath.Path + resourceAddressTwo string + attributePathTwo tfjsonpath.Path +} + +// CheckState implements the state check logic. +func (e expectContains) CheckState(ctx context.Context, req CheckStateRequest, resp *CheckStateResponse) { + var rcOne, rcTwo *tfjson.StateResource + + if req.State == nil { + resp.Error = fmt.Errorf("state is nil") + } + + if req.State.Values == nil { + resp.Error = fmt.Errorf("state does not contain any state values") + } + + if req.State.Values.RootModule == nil { + resp.Error = fmt.Errorf("state does not contain a root module") + } + + for _, resourceChange := range req.State.Values.RootModule.Resources { + if e.resourceAddressOne == resourceChange.Address { + rcOne = resourceChange + + break + } + } + + if rcOne == nil { + resp.Error = fmt.Errorf("%s - Resource not found in state", e.resourceAddressOne) + + return + } + + resultOne, err := tfjsonpath.Traverse(rcOne.AttributeValues, e.attributePathOne) + + if err != nil { + resp.Error = err + + return + } + + for _, resourceChange := range req.State.Values.RootModule.Resources { + if e.resourceAddressTwo == resourceChange.Address { + rcTwo = resourceChange + + break + } + } + + if rcTwo == nil { + resp.Error = fmt.Errorf("%s - Resource not found in state", e.resourceAddressTwo) + + return + } + + resultTwo, err := tfjsonpath.Traverse(rcTwo.AttributeValues, e.attributePathTwo) + + if err != nil { + resp.Error = err + + return + } + + resultOneCollection, ok := resultOne.([]any) + + if !ok { + resp.Error = fmt.Errorf("%s.%s is not a set", e.resourceAddressOne, e.attributePathOne.String()) + + return + } + + for _, v := range resultOneCollection { + if reflect.DeepEqual(v, resultTwo) { + return + } + } + + resp.Error = fmt.Errorf("value of %s.%s is not found in value of %s.%s", e.resourceAddressTwo, e.attributePathTwo.String(), e.resourceAddressOne, e.attributePathOne.String()) +} + +// ExpectContains returns a state check that asserts that the value of the second attribute is contained within the +// value of the first attribute, allowing checking of whether a set contains a value identified by another attribute. +func ExpectContains(resourceAddressOne string, attributePathOne tfjsonpath.Path, resourceAddressTwo string, attributePathTwo tfjsonpath.Path) StateCheck { + return expectContains{ + resourceAddressOne: resourceAddressOne, + attributePathOne: attributePathOne, + resourceAddressTwo: resourceAddressTwo, + attributePathTwo: attributePathTwo, + } +} diff --git a/statecheck/expect_contains_test.go b/statecheck/expect_contains_test.go new file mode 100644 index 000000000..48eedbe60 --- /dev/null +++ b/statecheck/expect_contains_test.go @@ -0,0 +1,227 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package statecheck_test + +import ( + "regexp" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + r "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + +func TestExpectContains_CheckState_ResourceOneNotFound(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" {} + + resource "test_resource" "two" {}`, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectContains( + "does_not_exist_one", + tfjsonpath.New("bool_attribute"), + "test_resource.two", + tfjsonpath.New("bool_attribute"), + ), + }, + ExpectError: regexp.MustCompile("does_not_exist_one - Resource not found in state"), + }, + }, + }) +} + +func TestExpectContains_CheckState_ResourceTwoNotFound(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" {} + + resource "test_resource" "two" {}`, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectContains( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + "does_not_exist_two", + tfjsonpath.New("bool_attribute"), + ), + }, + ExpectError: regexp.MustCompile("does_not_exist_two - Resource not found in state"), + }, + }, + }) +} + +func TestExpectContains_CheckState_AttributeOneNotFound(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" {} + + resource "test_resource" "two" {}`, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectContains( + "test_resource.one", + tfjsonpath.New("does_not_exist_one"), + "test_resource.two", + tfjsonpath.New("bool_attribute"), + ), + }, + ExpectError: regexp.MustCompile("path not found: specified key does_not_exist_one not found in map at does_not_exist_one"), + }, + }, + }) +} + +func TestExpectContains_CheckState_AttributeTwoNotFound(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" {} + + resource "test_resource" "two" {}`, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectContains( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + "test_resource.two", + tfjsonpath.New("does_not_exist_two"), + ), + }, + ExpectError: regexp.MustCompile("path not found: specified key does_not_exist_two not found in map at does_not_exist_two"), + }, + }, + }) +} + +func TestExpectContains_CheckState_AttributeOneNotSet(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + + resource "test_resource" "two" {}`, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectContains( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + "test_resource.two", + tfjsonpath.New("bool_attribute"), + ), + }, + ExpectError: regexp.MustCompile("test_resource.one.bool_attribute is not a set"), + }, + }, + }) +} + +func TestExpectContains_CheckState_NotFound(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + string_attribute = "value1" + } + + resource "test_resource" "two" { + set_attribute = [ + test_resource.one.string_attribute, + "value2" + ] + }`, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectContains( + "test_resource.two", + tfjsonpath.New("set_attribute"), + "test_resource.one", + tfjsonpath.New("bool_attribute"), + ), + }, + ExpectError: regexp.MustCompile(`value of test_resource\.one\.bool_attribute is not found in value of test_resource\.two\.set_attribute`), + }, + }, + }) +} + +func TestExpectContains_CheckState_Found(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + string_attribute = "value1" + } + + resource "test_resource" "two" { + set_attribute = [ + test_resource.one.string_attribute, + "value2" + ] + }`, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectContains( + "test_resource.two", + tfjsonpath.New("set_attribute"), + "test_resource.one", + tfjsonpath.New("string_attribute"), + ), + }, + }, + }, + }) +} From d56b46d11e7451f891916f730be4eed1fb702868 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Tue, 16 Jan 2024 15:49:22 +0000 Subject: [PATCH 23/73] Removing unneeded bool pointer exact check value type --- knownvalue/bool_pointer.go | 52 --------------------------- statecheck/expect_known_value_test.go | 10 ++++-- 2 files changed, 7 insertions(+), 55 deletions(-) delete mode 100644 knownvalue/bool_pointer.go diff --git a/knownvalue/bool_pointer.go b/knownvalue/bool_pointer.go deleted file mode 100644 index 9b9459c13..000000000 --- a/knownvalue/bool_pointer.go +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package knownvalue - -import ( - "fmt" - "strconv" -) - -var _ Check = boolPointerExact{} - -type boolPointerExact struct { - value *bool -} - -// CheckValue determines whether the passed value is of type bool, and -// contains a matching bool value. -func (v boolPointerExact) CheckValue(other any) error { - if v.value == nil { - return fmt.Errorf("BoolExact check value is nil") - } - - otherVal, ok := other.(bool) - - if !ok { - return fmt.Errorf("expected bool value for BoolExact check, got: %T", other) - } - - if otherVal != *v.value { - return fmt.Errorf("expected value %t for BoolExact check, got: %t", *v.value, otherVal) - } - - return nil -} - -// String returns the string representation of the bool value. -func (v boolPointerExact) String() string { - if v.value == nil { - return "" - } - - return strconv.FormatBool(*v.value) -} - -// BoolPointerExact returns a Check for asserting equality between the -// supplied bool and the value passed to the CheckValue method. -func BoolPointerExact(value *bool) boolPointerExact { - return boolPointerExact{ - value: value, - } -} diff --git a/statecheck/expect_known_value_test.go b/statecheck/expect_known_value_test.go index 87891654f..a2241222f 100644 --- a/statecheck/expect_known_value_test.go +++ b/statecheck/expect_known_value_test.go @@ -103,7 +103,7 @@ func TestExpectKnownValue_CheckState_Bool(t *testing.T) { func TestExpectKnownValue_CheckState_BoolPointer(t *testing.T) { t.Parallel() - var testBool bool + testBool := Pointer(false) r.Test(t, r.TestCase{ ProviderFactories: map[string]func() (*schema.Provider, error){ @@ -118,11 +118,11 @@ func TestExpectKnownValue_CheckState_BoolPointer(t *testing.T) { } `, ConfigStateChecks: r.ConfigStateChecks{ - AlterValue(&testBool), + AlterValue(testBool), statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), - knownvalue.BoolPointerExact(&testBool), + knownvalue.BoolExact(*testBool), ), }, }, @@ -130,6 +130,10 @@ func TestExpectKnownValue_CheckState_BoolPointer(t *testing.T) { }) } +func Pointer[T any](in T) *T { + return &in +} + type mutate struct{} func (m mutate) CheckState(context.Context, statecheck.CheckStateRequest, *statecheck.CheckStateResponse) { From 20d12143f9581be6da237474de73b32b735150bd Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Wed, 17 Jan 2024 11:05:43 +0000 Subject: [PATCH 24/73] Adding docs for new built-in state checks --- .../state-checks/resource.mdx | 138 +++++++++++++++++- 1 file changed, 134 insertions(+), 4 deletions(-) diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx index 582afbcdf..0c522f61e 100644 --- a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx @@ -9,10 +9,50 @@ description: >- The `terraform-plugin-testing` module provides a package [`statecheck`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck) with built-in managed resource, and data source state checks for common use-cases: -| Check | Description | -|------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------| -| [`statecheck.ExpectKnownValue(address, path, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue) | Asserts the specified attribute at the given managed resource, or data source, has the specified type, and value. | -| [`statecheck.ExpectSensitiveValue(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectSensitiveValue) | Asserts the specified attribute at the given managed resource, or data source, has a sensitive value. | +| Check | Description | +|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [`statecheck.ExpectContains(addressOne, pathOne, addressTwo, pathTwo)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectContains) | Asserts the specified attribute at the first given managed resource, or data source, contains the value specified by the attribute in the second given managed resource, or data source. | +| [`statecheck.ExpectKnownValue(address, path, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue) | Asserts the specified attribute at the given managed resource, or data source, has the specified type, and value. | +| [`statecheck.ExpectMatchValues(addressOne, pathOne, addressTwo, pathTwo)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectMatchingValues) | Asserts the specified attributes at the given managed resources have matching values. | +| [`statecheck.ExpectNoValueExists(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectNoValueExists) | Asserts the specified attribute at the given managed resource, or data source, does not exist. | +| [`statecheck.ExpectSensitiveValue(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectSensitiveValue) | Asserts the specified attribute at the given managed resource, or data source, has a sensitive value. | +| [`statecheck.ExpectValueExists(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectValueExists) | Asserts the specified attribute at the given managed resource, or data source, exists. | + +## Example using `statecheck.ExpectContains` + +The [`statecheck.ExpectContains(addressOne, pathOne, addressTwo, pathTwo)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectContains) state check provides a basis for asserting that the first resource attribute contains the value specified by the second resource attribute. + +```go +func TestExpectContains_CheckState_Found(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + // Provider definition omitted. + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + string_attribute = "value1" + } + + resource "test_resource" "two" { + set_attribute = [ + test_resource.one.string_attribute, + "value2" + ] + }`, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectContains( + "test_resource.two", + tfjsonpath.New("set_attribute"), + "test_resource.one", + tfjsonpath.New("string_attribute"), + ), + }, + }, + }, + }) +} +``` ## Example using `statecheck.ExpectKnownValue` @@ -45,6 +85,68 @@ func TestExpectKnownValue_CheckState_Bool(t *testing.T) { } ``` +## Example using `statecheck.ExpectMatchingValues` + +The [`statecheck.ExpectMatchingValues(addressOne, pathOne, addressTwo, pathTwo)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectMatchingValues) state check provides a basis for asserting that the specified resource attributes have matching values. + +```go +func TestExpectMatchingValues_CheckState_AttributeValuesEqual_Bool(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + // Provider definition omitted. + + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + + resource "test_resource" "two" { + bool_attribute = true + }`, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectMatchingValues( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + "test_resource.two", + tfjsonpath.New("bool_attribute"), + ), + }, + }, + }, + }) +} +``` + +## Example using `statecheck.ExpectNoValueExists` + +The [`statecheck.ExpectNoValueExists(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectNoValueExists) state check provides a basis for asserting that a specific resource attribute does not exist. + +```go +func TestExpectNoValueExists_CheckState_AttributeNotFound(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + // Provider definition omitted. + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectNoValueExists( + "test_resource.one", + tfjsonpath.New("does_not_exist"), + ), + }, + }, + }, + }) +} +``` + ## Example using `statecheck.ExpectSensitiveValue` The [`statecheck.ExpectSensitiveValue(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectSensitiveValue) state check provides a basis for asserting that a specific resource attribute is marked as sensitive. @@ -76,3 +178,31 @@ func Test_ExpectSensitiveValue_SensitiveStringAttribute(t *testing.T) { }) } ``` + +## Example using `statecheck.ExpectValueExists` + +The [`statecheck.ExpectValueExists(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectValueExists) state check provides a basis for asserting that a specific resource attribute exists. + +```go +func TestExpectValueExists_CheckState_AttributeFound(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + // Provider definition omitted. + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectValueExists( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + ), + }, + }, + }, + }) +} +``` \ No newline at end of file From d9cd08ac3ba0b7ac97eeefea505d2051ffb04967 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Wed, 17 Jan 2024 16:53:23 +0000 Subject: [PATCH 25/73] Adding deprecations --- helper/resource/testing.go | 107 ++++++++++++++++++++++++++++++++ helper/resource/testing_sets.go | 44 +++++++++++++ 2 files changed, 151 insertions(+) diff --git a/helper/resource/testing.go b/helper/resource/testing.go index 5abda4eaa..32177310a 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -558,6 +558,12 @@ type TestStep struct { // destroy plan will still be attempted. // // If this is nil, no check is done on this step. + // + // Deprecated: State checks have been superseded by ConfigStateChecks. + // This field will be removed in the next major version. + // + // [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck + // [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck Check TestCheckFunc // Destroy will create a destroy plan if set to true. @@ -964,6 +970,12 @@ func testResource(c TestStep, state *terraform.State) (*terraform.ResourceState, // // ComposeTestCheckFunc returns immediately on the first TestCheckFunc error. // To aggregrate all errors, use ComposeAggregateTestCheckFunc instead. +// +// Deprecated: State checks have been superseded by ConfigStateChecks. +// This function will be removed in the next major version. +// +// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck +// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck func ComposeTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc { return func(s *terraform.State) error { for i, f := range fs { @@ -984,6 +996,12 @@ func ComposeTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc { // // Unlike ComposeTestCheckFunc, ComposeAggergateTestCheckFunc runs _all_ of the // TestCheckFuncs and aggregates failures. +// +// Deprecated: State checks have been superseded by ConfigStateChecks. +// This function will be removed in the next major version. +// +// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck +// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck func ComposeAggregateTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc { return func(s *terraform.State) error { var result []error @@ -1040,6 +1058,14 @@ func ComposeAggregateTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc { // attributes using the special key syntax, checking a list, map, or set // attribute directly is not supported. Use TestCheckResourceAttr with // the special .# or .% key syntax for those situations instead. +// +// Deprecated: State checks have been superseded by ConfigStateChecks. +// Use the built-in statecheck.ExpectValueExists state instead. +// TestCheckResourceAttrSet function will be removed in the next major version. +// +// [ExpectValueExists]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectValueExists +// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck +// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck func TestCheckResourceAttrSet(name, key string) TestCheckFunc { return checkIfIndexesIntoTypeSet(key, func(s *terraform.State) error { is, err := primaryInstanceState(s, name) @@ -1139,6 +1165,14 @@ func testCheckResourceAttrSet(is *terraform.InstanceState, name string, key stri // - Boolean: "false" or "true". // - Float/Integer: Stringified number, such as "1.2" or "123". // - String: No conversion necessary. +// +// Deprecated: State checks have been superseded by ConfigStateChecks. +// Use the built-in statecheck.ExpectKnownValue state check instead. +// TestCheckResourceAttr function will be removed in the next major version. +// +// [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue +// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck +// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck func TestCheckResourceAttr(name, key, value string) TestCheckFunc { return checkIfIndexesIntoTypeSet(key, func(s *terraform.State) error { is, err := primaryInstanceState(s, name) @@ -1222,6 +1256,12 @@ func testCheckResourceAttr(is *terraform.InstanceState, name string, key string, // when using TestCheckResourceAttrWith and a value is found for the given name and key. // // When this function returns an error, TestCheckResourceAttrWith will fail the check. +// +// Deprecated: State checks have been superseded by ConfigStateChecks. +// This type will be removed in the next major version. +// +// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck +// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck type CheckResourceAttrWithFunc func(value string) error // TestCheckResourceAttrWith ensures a value stored in state for the @@ -1259,6 +1299,16 @@ type CheckResourceAttrWithFunc func(value string) error // and it's provided with the attribute value to apply a custom checking logic, // if it was found in the state. The function must return an error for the // check to fail, or `nil` to succeed. +// +// Deprecated: State checks have been superseded by ConfigStateChecks. +// Use the built-int statecheck.ExpectKnownValue state check in combination +// with a custom knownvalue.Check instead. +// TestCheckResourceAttrWith function will be removed in the next major version. +// +// [Check]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check +// [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue +// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck +// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck func TestCheckResourceAttrWith(name, key string, checkValueFunc CheckResourceAttrWithFunc) TestCheckFunc { return checkIfIndexesIntoTypeSet(key, func(s *terraform.State) error { is, err := primaryInstanceState(s, name) @@ -1311,6 +1361,14 @@ func TestCheckResourceAttrWith(name, key string, checkValueFunc CheckResourceAtt // attributes using the special key syntax, checking a list, map, or set // attribute directly is not supported. Use TestCheckResourceAttr with // the special .# or .% key syntax for those situations instead. +// +// Deprecated: State checks have been superseded by ConfigStateChecks. +// Use the built-in statecheck.ExpectNoValueExists instead. +// TestCheckNoResourceAttr function will be removed in the next major version. +// +// [ExpectNoValueExists]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectNoValueExists +// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck +// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck func TestCheckNoResourceAttr(name, key string) TestCheckFunc { return checkIfIndexesIntoTypeSet(key, func(s *terraform.State) error { is, err := primaryInstanceState(s, name) @@ -1415,6 +1473,16 @@ func testCheckNoResourceAttr(is *terraform.InstanceState, name string, key strin // using the regexp.MustCompile() function, which will automatically ensure the // regular expression is supported by the Go regular expression handlers during // compilation. +// +// Deprecated: State checks have been superseded by ConfigStateChecks. +// Use the built-in statecheck.ExpectKnownValue state check in combination +// with a custom knownvalue.Check instead. +// TestMatchResourceAttr function will be removed in the next major version. +// +// [Check]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check +// [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue +// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck +// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck func TestMatchResourceAttr(name, key string, r *regexp.Regexp) TestCheckFunc { return checkIfIndexesIntoTypeSet(key, func(s *terraform.State) error { is, err := primaryInstanceState(s, name) @@ -1467,6 +1535,16 @@ func testMatchResourceAttr(is *terraform.InstanceState, name string, key string, // // Refer to the TestCheckResourceAttr documentation for more information about // setting the name, key, and value parameters. +// +// Deprecated: State checks have been superseded by ConfigStateChecks. +// Use the built-in statecheck.ExpectKnownValue state check in combination +// with types implementing knownvalue.Check instead. +// TestCheckResourceAttrPtr function will be removed in the next major version. +// +// [Check]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check +// [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue +// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck +// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck func TestCheckResourceAttrPtr(name string, key string, value *string) TestCheckFunc { return func(s *terraform.State) error { return TestCheckResourceAttr(name, key, *value)(s) @@ -1522,6 +1600,14 @@ func TestCheckModuleResourceAttrPtr(mp []string, name string, key string, value // value. // - .#: Number of elements in list or set. // - .%: Number of elements in map. +// +// Deprecated: State checks have been superseded by ConfigStateChecks. +// Use the built-in statecheck.ExpectMatchingValues state check instead. +// TestCheckResourceAttrPair function will be removed in the next major version. +// +// [ExpectMatchingValues]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectMatchingValues +// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck +// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck func TestCheckResourceAttrPair(nameFirst, keyFirst, nameSecond, keySecond string) TestCheckFunc { return checkIfIndexesIntoTypeSetPair(keyFirst, keySecond, func(s *terraform.State) error { isFirst, err := primaryInstanceState(s, nameFirst) @@ -1616,6 +1702,16 @@ func testCheckResourceAttrPair(isFirst *terraform.InstanceState, nameFirst strin } // TestCheckOutput checks an output in the Terraform configuration +// +// Deprecated: State checks have been superseded by ConfigStateChecks. +// Use the built-in statecheck.ExpectKnownOutputValue, and +// statecheck.ExpectKnownOutputValueAtPath state checks instead. +// TestCheckOutput function will be removed in the next major version. +// +// [ExpectKnownOutputValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValue +// [ExpectKnownOutputValueAtPath]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValueAtPath +// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck +// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck func TestCheckOutput(name, value string) TestCheckFunc { return func(s *terraform.State) error { ms := s.RootModule() @@ -1636,6 +1732,17 @@ func TestCheckOutput(name, value string) TestCheckFunc { } } +// Deprecated: State checks have been superseded by ConfigStateChecks. +// Use the built-in statecheck.ExpectKnownOutputValue, and +// statecheck.ExpectKnownOutputValueAtPath state checks, can be used in +// combination with a custom knownvalue.Check instead. +// TestMatchOutput function will be removed in the next major version. +// +// [Check]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check +// [ExpectKnownOutputValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValue +// [ExpectKnownOutputValueAtPath]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValueAtPath +// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck +// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck func TestMatchOutput(name string, r *regexp.Regexp) TestCheckFunc { return func(s *terraform.State) error { ms := s.RootModule() diff --git a/helper/resource/testing_sets.go b/helper/resource/testing_sets.go index a304bfc4e..abd2c04b7 100644 --- a/helper/resource/testing_sets.go +++ b/helper/resource/testing_sets.go @@ -57,6 +57,17 @@ const ( // If the values map is not granular enough, it is possible to match an element // you were not intending to in the set. Provide the most complete mapping of // attributes possible to be sure the unique element exists. +// +// Deprecated: State checks have been superseded by ConfigStateChecks. +// Use the built-in statecheck.ExpectKnownValue state check in combination +// with knownvalue.SetExact or knownvalue.SetPartial instead. +// TestCheckTypeSetElemNestedAttrs function will be removed in the next major version. +// +// [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue +// [SetExact]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetExact +// [SetPartial]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetPartial +// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck +// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck func TestCheckTypeSetElemNestedAttrs(name, attr string, values map[string]string) TestCheckFunc { return func(s *terraform.State) error { is, err := primaryInstanceState(s, name) @@ -129,6 +140,20 @@ func TestCheckTypeSetElemNestedAttrs(name, attr string, values map[string]string // If the values map is not granular enough, it is possible to match an element // you were not intending to in the set. Provide the most complete mapping of // attributes possible to be sure the unique element exists. +// +// Deprecated: State checks have been superseded by ConfigStateChecks. +// Use the built-in statecheck.ExpectKnownValue state check, can be used in combination +// with knownvalue.ListExact, knownvalue.ListPartial, knownvalue.SetExact, or +// knownvalue.SetPartial, with nested custom knownvalue.Check instead. +// TestMatchTypeSetElemNestedAttrs function will be removed in the next major version. +// +// [ListExact]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ListExact +// [ListPartial]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ListPartial +// [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue +// [SetExact]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetExact +// [SetPartial]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetPartial +// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck +// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck func TestMatchTypeSetElemNestedAttrs(name, attr string, values map[string]*regexp.Regexp) TestCheckFunc { return func(s *terraform.State) error { is, err := primaryInstanceState(s, name) @@ -200,6 +225,17 @@ func TestMatchTypeSetElemNestedAttrs(name, attr string, values map[string]*regex // - Boolean: "false" or "true". // - Float/Integer: Stringified number, such as "1.2" or "123". // - String: No conversion necessary. +// +// Deprecated: State checks have been superseded by ConfigStateChecks. +// Use the built-in statecheck.ExpectKnownValue state check in combination +// with knownvalue.SetExact or knownvalue.SetPartial instead. +// TestCheckTypeSetElemAttr function will be removed in the next major version. +// +// [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue +// [SetExact]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetExact +// [SetPartial]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetPartial +// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck +// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck func TestCheckTypeSetElemAttr(name, attr, value string) TestCheckFunc { return func(s *terraform.State) error { is, err := primaryInstanceState(s, name) @@ -242,6 +278,14 @@ func TestCheckTypeSetElemAttr(name, attr, value string) TestCheckFunc { // attribute. Use the sentinel value '*' to replace the element indexing into // a list or set. The sentinel value can be used for each list or set index, if // there are multiple lists or sets in the attribute path. +// +// Deprecated: State checks have been superseded by ConfigStateChecks. +// Use the built-in statecheck.ExpectContains state check instead. +// TestCheckTypeSetElemAttrPair function will be removed in the next major version. +// +// [ExpectContains]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectContains +// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck +// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck func TestCheckTypeSetElemAttrPair(nameFirst, keyFirst, nameSecond, keySecond string) TestCheckFunc { return func(s *terraform.State) error { isFirst, err := primaryInstanceState(s, nameFirst) From bb63ddd9d54f0a3dd31d10968b8f6e7c30dd1647 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Wed, 17 Jan 2024 17:04:59 +0000 Subject: [PATCH 26/73] Fixing doc --- .../acceptance-tests/state-checks/resource.mdx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx index 0c522f61e..2586e8705 100644 --- a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx @@ -9,14 +9,14 @@ description: >- The `terraform-plugin-testing` module provides a package [`statecheck`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck) with built-in managed resource, and data source state checks for common use-cases: -| Check | Description | -|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [`statecheck.ExpectContains(addressOne, pathOne, addressTwo, pathTwo)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectContains) | Asserts the specified attribute at the first given managed resource, or data source, contains the value specified by the attribute in the second given managed resource, or data source. | -| [`statecheck.ExpectKnownValue(address, path, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue) | Asserts the specified attribute at the given managed resource, or data source, has the specified type, and value. | -| [`statecheck.ExpectMatchValues(addressOne, pathOne, addressTwo, pathTwo)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectMatchingValues) | Asserts the specified attributes at the given managed resources have matching values. | -| [`statecheck.ExpectNoValueExists(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectNoValueExists) | Asserts the specified attribute at the given managed resource, or data source, does not exist. | -| [`statecheck.ExpectSensitiveValue(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectSensitiveValue) | Asserts the specified attribute at the given managed resource, or data source, has a sensitive value. | -| [`statecheck.ExpectValueExists(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectValueExists) | Asserts the specified attribute at the given managed resource, or data source, exists. | +| Check | Description | +|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [`statecheck.ExpectContains(addressOne, pathOne, addressTwo, pathTwo)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectContains) | Asserts the specified attribute at the first given managed resource, or data source, contains the value specified by the attribute in the second given managed resource, or data source. | +| [`statecheck.ExpectKnownValue(address, path, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue) | Asserts the specified attribute at the given managed resource, or data source, has the specified type, and value. | +| [`statecheck.ExpectMatchingValues(addressOne, pathOne, addressTwo, pathTwo)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectMatchingValues) | Asserts the specified attributes at the given managed resources have matching values. | +| [`statecheck.ExpectNoValueExists(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectNoValueExists) | Asserts the specified attribute at the given managed resource, or data source, does not exist. | +| [`statecheck.ExpectSensitiveValue(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectSensitiveValue) | Asserts the specified attribute at the given managed resource, or data source, has a sensitive value. | +| [`statecheck.ExpectValueExists(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectValueExists) | Asserts the specified attribute at the given managed resource, or data source, exists. | ## Example using `statecheck.ExpectContains` From 93a3f263528d9bb4924bf7979caee4c616a4d598 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Wed, 17 Jan 2024 17:05:11 +0000 Subject: [PATCH 27/73] Adding changelog entries --- .changes/unreleased/FEATURES-20240117-165715.yaml | 6 ++++++ .changes/unreleased/FEATURES-20240117-165925.yaml | 6 ++++++ .changes/unreleased/FEATURES-20240117-170016.yaml | 6 ++++++ .changes/unreleased/FEATURES-20240117-170346.yaml | 7 +++++++ 4 files changed, 25 insertions(+) create mode 100644 .changes/unreleased/FEATURES-20240117-165715.yaml create mode 100644 .changes/unreleased/FEATURES-20240117-165925.yaml create mode 100644 .changes/unreleased/FEATURES-20240117-170016.yaml create mode 100644 .changes/unreleased/FEATURES-20240117-170346.yaml diff --git a/.changes/unreleased/FEATURES-20240117-165715.yaml b/.changes/unreleased/FEATURES-20240117-165715.yaml new file mode 100644 index 000000000..3cf34c017 --- /dev/null +++ b/.changes/unreleased/FEATURES-20240117-165715.yaml @@ -0,0 +1,6 @@ +kind: FEATURES +body: 'statecheck: Added `ExpectNoValueExists` built-in state check, which asserts + that a given attribute does not exist' +time: 2024-01-17T16:57:15.53079Z +custom: + Issue: "276" diff --git a/.changes/unreleased/FEATURES-20240117-165925.yaml b/.changes/unreleased/FEATURES-20240117-165925.yaml new file mode 100644 index 000000000..36ef5e40b --- /dev/null +++ b/.changes/unreleased/FEATURES-20240117-165925.yaml @@ -0,0 +1,6 @@ +kind: FEATURES +body: 'statecheck: Added `ExpectMatchingValues built-in state check, which asserts + that the given attributes have matching values' +time: 2024-01-17T16:59:25.504116Z +custom: + Issue: "276" diff --git a/.changes/unreleased/FEATURES-20240117-170016.yaml b/.changes/unreleased/FEATURES-20240117-170016.yaml new file mode 100644 index 000000000..ac83b8291 --- /dev/null +++ b/.changes/unreleased/FEATURES-20240117-170016.yaml @@ -0,0 +1,6 @@ +kind: FEATURES +body: 'statecheck: Added `ExpectValueExists` built-in state check, which asserts that + a given attribute exists' +time: 2024-01-17T17:00:16.411155Z +custom: + Issue: "276" diff --git a/.changes/unreleased/FEATURES-20240117-170346.yaml b/.changes/unreleased/FEATURES-20240117-170346.yaml new file mode 100644 index 000000000..5ff50adb8 --- /dev/null +++ b/.changes/unreleased/FEATURES-20240117-170346.yaml @@ -0,0 +1,7 @@ +kind: FEATURES +body: 'statecheck: Added `ExpectContains` built-in state check, which asserts that + the value of the first given attribute contains the value of the second given + attribute' +time: 2024-01-17T17:03:46.555777Z +custom: + Issue: "276" From c74a9e8bb48edca9e89047b7bde02eb49d0aa520 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Wed, 17 Jan 2024 17:07:15 +0000 Subject: [PATCH 28/73] Fixing changelog entries --- .changes/unreleased/FEATURES-20240111-142126.yaml | 2 +- .changes/unreleased/FEATURES-20240111-142223.yaml | 2 +- .changes/unreleased/FEATURES-20240111-142314.yaml | 2 +- .changes/unreleased/FEATURES-20240111-142353.yaml | 2 +- .changes/unreleased/FEATURES-20240111-142544.yaml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.changes/unreleased/FEATURES-20240111-142126.yaml b/.changes/unreleased/FEATURES-20240111-142126.yaml index 99c271b7c..b89fcbddc 100644 --- a/.changes/unreleased/FEATURES-20240111-142126.yaml +++ b/.changes/unreleased/FEATURES-20240111-142126.yaml @@ -3,4 +3,4 @@ body: 'statecheck: Introduced new `statecheck` package with interface and built- state check functionality' time: 2024-01-11T14:21:26.261094Z custom: - Issue: "273" + Issue: "275" diff --git a/.changes/unreleased/FEATURES-20240111-142223.yaml b/.changes/unreleased/FEATURES-20240111-142223.yaml index ca6a2a386..049bb81f9 100644 --- a/.changes/unreleased/FEATURES-20240111-142223.yaml +++ b/.changes/unreleased/FEATURES-20240111-142223.yaml @@ -3,4 +3,4 @@ body: 'statecheck: Added `ExpectKnownValue` state check, which asserts that a gi resource attribute has a defined type, and value' time: 2024-01-11T14:22:23.072321Z custom: - Issue: "273" + Issue: "275" diff --git a/.changes/unreleased/FEATURES-20240111-142314.yaml b/.changes/unreleased/FEATURES-20240111-142314.yaml index 3d683c564..3b602ef44 100644 --- a/.changes/unreleased/FEATURES-20240111-142314.yaml +++ b/.changes/unreleased/FEATURES-20240111-142314.yaml @@ -3,4 +3,4 @@ body: 'statecheck: Added `ExpectKnownOutputValue` state check, which asserts tha a given output value has a defined type, and value' time: 2024-01-11T14:23:14.025585Z custom: - Issue: "273" + Issue: "275" diff --git a/.changes/unreleased/FEATURES-20240111-142353.yaml b/.changes/unreleased/FEATURES-20240111-142353.yaml index eaa67ae05..2db803bd6 100644 --- a/.changes/unreleased/FEATURES-20240111-142353.yaml +++ b/.changes/unreleased/FEATURES-20240111-142353.yaml @@ -3,4 +3,4 @@ body: 'statecheck: Added `ExpectKnownOutputValueAtPath` plan check, which assert that a given output value at a specified path has a defined type, and value' time: 2024-01-11T14:23:53.633255Z custom: - Issue: "273" + Issue: "275" diff --git a/.changes/unreleased/FEATURES-20240111-142544.yaml b/.changes/unreleased/FEATURES-20240111-142544.yaml index 42bf8aa03..c8a02b9fd 100644 --- a/.changes/unreleased/FEATURES-20240111-142544.yaml +++ b/.changes/unreleased/FEATURES-20240111-142544.yaml @@ -3,4 +3,4 @@ body: 'statecheck: Added `ExpectSensitiveValue` built-in state check, which asse that a given attribute has a sensitive value' time: 2024-01-11T14:25:44.598583Z custom: - Issue: "273" + Issue: "275" From a85156479492731ef74215bcfafa6bc47cd2e4c1 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Wed, 17 Jan 2024 17:13:58 +0000 Subject: [PATCH 29/73] Linting --- internal/plugintest/working_dir_json_test.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/internal/plugintest/working_dir_json_test.go b/internal/plugintest/working_dir_json_test.go index f29c0fed0..05952cddc 100644 --- a/internal/plugintest/working_dir_json_test.go +++ b/internal/plugintest/working_dir_json_test.go @@ -27,13 +27,16 @@ func TestJSONConfig(t *testing.T) { ProviderFactories: providerFactories, Steps: []resource.TestStep{{ Config: `{"resource":{"tst_t":{"r1":{"s":"x1"}}}}`, - Check: resource.TestCheckResourceAttr("tst_t.r1", "s", "x1"), + //nolint + Check: resource.TestCheckResourceAttr("tst_t.r1", "s", "x1"), }, { Config: `resource "tst_t" "r1" { s = "x2" }`, - Check: resource.TestCheckResourceAttr("tst_t.r1", "s", "x2"), + //nolint + Check: resource.TestCheckResourceAttr("tst_t.r1", "s", "x2"), }, { Config: `{"resource":{"tst_t":{"r1":{"s":"x3"}}}}`, - Check: resource.TestCheckResourceAttr("tst_t.r1", "s", "x3"), + //nolint + Check: resource.TestCheckResourceAttr("tst_t.r1", "s", "x3"), }}, }) } From 178c2c47c2bf6d1c0fc14767c286cc4086e74081 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Thu, 18 Jan 2024 11:30:21 +0000 Subject: [PATCH 30/73] Modifying ExpectKnown to handle null checking (#266) --- plancheck/expect_known_output_value.go | 30 +++++-------------- .../expect_known_output_value_at_path.go | 30 +++++-------------- .../expect_known_output_value_at_path_test.go | 7 ++--- plancheck/expect_known_output_value_test.go | 7 ++--- plancheck/expect_known_value.go | 30 +++++-------------- plancheck/expect_known_value_test.go | 7 ++--- 6 files changed, 30 insertions(+), 81 deletions(-) diff --git a/plancheck/expect_known_output_value.go b/plancheck/expect_known_output_value.go index 33a27e2f5..bc954c8ed 100644 --- a/plancheck/expect_known_output_value.go +++ b/plancheck/expect_known_output_value.go @@ -6,7 +6,6 @@ package plancheck import ( "context" "fmt" - "reflect" tfjson "github.com/hashicorp/terraform-json" @@ -26,6 +25,10 @@ type expectKnownOutputValue struct { func (e expectKnownOutputValue) CheckPlan(ctx context.Context, req CheckPlanRequest, resp *CheckPlanResponse) { var change *tfjson.Change + if req.Plan == nil { + resp.Error = fmt.Errorf("plan is nil") + } + for address, oc := range req.Plan.OutputChanges { if e.outputAddress == address { change = oc @@ -35,7 +38,7 @@ func (e expectKnownOutputValue) CheckPlan(ctx context.Context, req CheckPlanRequ } if change == nil { - resp.Error = fmt.Errorf("%s - Output not found in plan OutputChanges", e.outputAddress) + resp.Error = fmt.Errorf("%s - Output not found in plan", e.outputAddress) return } @@ -48,27 +51,8 @@ func (e expectKnownOutputValue) CheckPlan(ctx context.Context, req CheckPlanRequ return } - if result == nil { - resp.Error = fmt.Errorf("value is null for output at path: %s", e.outputAddress) - - return - } - - switch reflect.TypeOf(result).Kind() { - case reflect.Bool, - reflect.Map, - reflect.Slice, - reflect.String: - if err := e.knownValue.CheckValue(result); err != nil { - resp.Error = fmt.Errorf("error checking value for output at path: %s, err: %s", e.outputAddress, err) - - return - } - default: - errorStr := fmt.Sprintf("unrecognised output type: %T, known value type is %T", result, e.knownValue) - errorStr += "\n\nThis is an error in plancheck.ExpectKnownOutputValue.\nPlease report this to the maintainers." - - resp.Error = fmt.Errorf(errorStr) + if err := e.knownValue.CheckValue(result); err != nil { + resp.Error = fmt.Errorf("error checking value for output at path: %s, err: %s", e.outputAddress, err) return } diff --git a/plancheck/expect_known_output_value_at_path.go b/plancheck/expect_known_output_value_at_path.go index 056b7c2f7..ffb8ee334 100644 --- a/plancheck/expect_known_output_value_at_path.go +++ b/plancheck/expect_known_output_value_at_path.go @@ -6,7 +6,6 @@ package plancheck import ( "context" "fmt" - "reflect" tfjson "github.com/hashicorp/terraform-json" @@ -27,6 +26,10 @@ type expectKnownOutputValueAtPath struct { func (e expectKnownOutputValueAtPath) CheckPlan(ctx context.Context, req CheckPlanRequest, resp *CheckPlanResponse) { var change *tfjson.Change + if req.Plan == nil { + resp.Error = fmt.Errorf("plan is nil") + } + for address, oc := range req.Plan.OutputChanges { if e.outputAddress == address { change = oc @@ -36,7 +39,7 @@ func (e expectKnownOutputValueAtPath) CheckPlan(ctx context.Context, req CheckPl } if change == nil { - resp.Error = fmt.Errorf("%s - Output not found in plan OutputChanges", e.outputAddress) + resp.Error = fmt.Errorf("%s - Output not found in plan", e.outputAddress) return } @@ -49,27 +52,8 @@ func (e expectKnownOutputValueAtPath) CheckPlan(ctx context.Context, req CheckPl return } - if result == nil { - resp.Error = fmt.Errorf("value is null for output at path: %s.%s", e.outputAddress, e.outputPath.String()) - - return - } - - switch reflect.TypeOf(result).Kind() { - case reflect.Bool, - reflect.Map, - reflect.Slice, - reflect.String: - if err := e.knownValue.CheckValue(result); err != nil { - resp.Error = fmt.Errorf("error checking value for output at path: %s.%s, err: %s", e.outputAddress, e.outputPath.String(), err) - - return - } - default: - errorStr := fmt.Sprintf("unrecognised output type: %T, known value type is %T", result, e.knownValue) - errorStr += "\n\nThis is an error in plancheck.ExpectKnownOutputValueAtPath.\nPlease report this to the maintainers." - - resp.Error = fmt.Errorf(errorStr) + if err := e.knownValue.CheckValue(result); err != nil { + resp.Error = fmt.Errorf("error checking value for output at path: %s.%s, err: %s", e.outputAddress, e.outputPath.String(), err) return } diff --git a/plancheck/expect_known_output_value_at_path_test.go b/plancheck/expect_known_output_value_at_path_test.go index 564e9c39e..82505f87c 100644 --- a/plancheck/expect_known_output_value_at_path_test.go +++ b/plancheck/expect_known_output_value_at_path_test.go @@ -56,7 +56,7 @@ func TestExpectKnownOutputValueAtPath_CheckPlan_ResourceNotFound(t *testing.T) { ), }, }, - ExpectError: regexp.MustCompile("test_resource_two_output - Output not found in plan OutputChanges"), + ExpectError: regexp.MustCompile("test_resource_two_output - Output not found in plan"), }, }, }) @@ -91,11 +91,10 @@ func TestExpectKnownOutputValueAtPath_CheckPlan_AttributeValueNull(t *testing.T) plancheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("bool_attribute"), - knownvalue.BoolExact(true), + knownvalue.NullExact(), ), }, }, - ExpectError: regexp.MustCompile("value is null for output at path: test_resource_one_output.bool_attribute"), }, }, }) @@ -1809,7 +1808,7 @@ func TestExpectKnownOutputValueAtPath_CheckPlan_UnknownAttributeType(t *testing. }, }, }, - expectedErr: fmt.Errorf("unrecognised output type: float32, known value type is knownvalue.int64Exact\n\nThis is an error in plancheck.ExpectKnownOutputValueAtPath.\nPlease report this to the maintainers."), + expectedErr: fmt.Errorf("error checking value for output at path: float32_output., err: expected json.Number value for Int64Exact check, got: float32"), }, } diff --git a/plancheck/expect_known_output_value_test.go b/plancheck/expect_known_output_value_test.go index bc296a74a..626ecaab2 100644 --- a/plancheck/expect_known_output_value_test.go +++ b/plancheck/expect_known_output_value_test.go @@ -46,7 +46,7 @@ func TestExpectKnownOutputValue_CheckPlan_OutputNotFound(t *testing.T) { ), }, }, - ExpectError: regexp.MustCompile("bool_not_found - Output not found in plan OutputChanges"), + ExpectError: regexp.MustCompile("bool_not_found - Output not found in plan"), }, }, }) @@ -72,11 +72,10 @@ func TestExpectKnownOutputValue_CheckPlan_AttributeValueNull(t *testing.T) { PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownOutputValue( "bool_output", - knownvalue.BoolExact(true), + knownvalue.NullExact(), ), }, }, - ExpectError: regexp.MustCompile("value is null for output at path: bool_output"), }, }, }) @@ -1486,7 +1485,7 @@ func TestExpectKnownOutputValue_CheckPlan_UnknownAttributeType(t *testing.T) { }, }, }, - expectedErr: fmt.Errorf("unrecognised output type: float32, known value type is knownvalue.int64Exact\n\nThis is an error in plancheck.ExpectKnownOutputValue.\nPlease report this to the maintainers."), + expectedErr: fmt.Errorf("error checking value for output at path: float32_output, err: expected json.Number value for Int64Exact check, got: float32"), }, } diff --git a/plancheck/expect_known_value.go b/plancheck/expect_known_value.go index 1118b9a61..ae6ea6d8d 100644 --- a/plancheck/expect_known_value.go +++ b/plancheck/expect_known_value.go @@ -6,7 +6,6 @@ package plancheck import ( "context" "fmt" - "reflect" tfjson "github.com/hashicorp/terraform-json" @@ -27,6 +26,10 @@ type expectKnownValue struct { func (e expectKnownValue) CheckPlan(ctx context.Context, req CheckPlanRequest, resp *CheckPlanResponse) { var rc *tfjson.ResourceChange + if req.Plan == nil { + resp.Error = fmt.Errorf("plan is nil") + } + for _, resourceChange := range req.Plan.ResourceChanges { if e.resourceAddress == resourceChange.Address { rc = resourceChange @@ -36,7 +39,7 @@ func (e expectKnownValue) CheckPlan(ctx context.Context, req CheckPlanRequest, r } if rc == nil { - resp.Error = fmt.Errorf("%s - Resource not found in plan ResourceChanges", e.resourceAddress) + resp.Error = fmt.Errorf("%s - Resource not found in plan", e.resourceAddress) return } @@ -49,27 +52,8 @@ func (e expectKnownValue) CheckPlan(ctx context.Context, req CheckPlanRequest, r return } - if result == nil { - resp.Error = fmt.Errorf("value is null for attribute at path: %s.%s", e.resourceAddress, e.attributePath.String()) - - return - } - - switch reflect.TypeOf(result).Kind() { - case reflect.Bool, - reflect.Map, - reflect.Slice, - reflect.String: - if err := e.knownValue.CheckValue(result); err != nil { - resp.Error = fmt.Errorf("error checking value for attribute at path: %s.%s, err: %s", e.resourceAddress, e.attributePath.String(), err) - - return - } - default: - errorStr := fmt.Sprintf("unrecognised attribute type: %T, known value type is %T", result, e.knownValue) - errorStr += "\n\nThis is an error in plancheck.ExpectKnownValue.\nPlease report this to the maintainers." - - resp.Error = fmt.Errorf(errorStr) + if err := e.knownValue.CheckValue(result); err != nil { + resp.Error = fmt.Errorf("error checking value for attribute at path: %s.%s, err: %s", e.resourceAddress, e.attributePath.String(), err) return } diff --git a/plancheck/expect_known_value_test.go b/plancheck/expect_known_value_test.go index dc061572e..af1618076 100644 --- a/plancheck/expect_known_value_test.go +++ b/plancheck/expect_known_value_test.go @@ -44,7 +44,7 @@ func TestExpectKnownValue_CheckPlan_ResourceNotFound(t *testing.T) { ), }, }, - ExpectError: regexp.MustCompile("test_resource.two - Resource not found in plan ResourceChanges"), + ExpectError: regexp.MustCompile("test_resource.two - Resource not found in plan"), }, }, }) @@ -67,11 +67,10 @@ func TestExpectKnownValue_CheckPlan_AttributeValueNull(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), - knownvalue.BoolExact(true), + knownvalue.NullExact(), ), }, }, - ExpectError: regexp.MustCompile("value is null for attribute at path: test_resource.one.bool_attribute"), }, }, }) @@ -1372,7 +1371,7 @@ func TestExpectKnownValue_CheckPlan_UnknownAttributeType(t *testing.T) { }, }, }, - expectedErr: fmt.Errorf("unrecognised attribute type: float32, known value type is knownvalue.int64Exact\n\nThis is an error in plancheck.ExpectKnownValue.\nPlease report this to the maintainers."), + expectedErr: fmt.Errorf("error checking value for attribute at path: example_resource.test.attribute, err: expected json.Number value for Int64Exact check, got: float32"), }, } From c542a70430a00dc8fb1be3fe9f8a4fb5d5240281 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Thu, 18 Jan 2024 11:41:08 +0000 Subject: [PATCH 31/73] Deprecating ExpectNullOutputValue and ExpectNullOutputValueAtPath plan checks (#266) --- plancheck/expect_null_output_value.go | 6 ++++++ plancheck/expect_null_output_value_at_path.go | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/plancheck/expect_null_output_value.go b/plancheck/expect_null_output_value.go index 540462bf0..1fd27b17e 100644 --- a/plancheck/expect_null_output_value.go +++ b/plancheck/expect_null_output_value.go @@ -64,6 +64,12 @@ func (e expectNullOutputValue) CheckPlan(ctx context.Context, req CheckPlanReque // Due to implementation differences between the terraform-plugin-sdk and the terraform-plugin-framework, representation of null // values may differ. For example, terraform-plugin-sdk based providers may have less precise representations of null values, such // as marking whole maps as null rather than individual element values. +// +// Deprecated: Use ExpectKnownOutputValue with knownvalue.NullExact instead. +// ExpectNullOutputValue will be removed in the next major version release. +// +// [ExpectKnownOutputValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectKnownOutputValue +// [NullExact]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NullExact func ExpectNullOutputValue(outputAddress string) PlanCheck { return expectNullOutputValue{ outputAddress: outputAddress, diff --git a/plancheck/expect_null_output_value_at_path.go b/plancheck/expect_null_output_value_at_path.go index 17366e21a..4929ec64f 100644 --- a/plancheck/expect_null_output_value_at_path.go +++ b/plancheck/expect_null_output_value_at_path.go @@ -65,6 +65,12 @@ func (e expectNullOutputValueAtPath) CheckPlan(ctx context.Context, req CheckPla // Due to implementation differences between the terraform-plugin-sdk and the terraform-plugin-framework, representation of null // values may differ. For example, terraform-plugin-sdk based providers may have less precise representations of null values, such // as marking whole maps as null rather than individual element values. +// +// Deprecated: Use ExpectKnownOutputValueAtPath with knownvalue.NullExact instead. +// ExpectNullOutputValueAtPath will be removed in the next major version release. +// +// [ExpectKnownOutputValueAtPath]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectKnownOutputValueAtPath +// [NullExact]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NullExact func ExpectNullOutputValueAtPath(outputAddress string, valuePath tfjsonpath.Path) PlanCheck { return expectNullOutputValueAtPath{ outputAddress: outputAddress, From 7d3a3c74169ee5c8b3333451f2011d5bebade4ae Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Thu, 18 Jan 2024 14:38:15 +0000 Subject: [PATCH 32/73] Updating docs --- .../acceptance-tests/plan-checks/index.mdx | 77 ++++++-- .../acceptance-tests/plan-checks/output.mdx | 164 ++++++++++++++++-- .../acceptance-tests/plan-checks/resource.mdx | 127 ++++++++++++-- .../acceptance-tests/state-checks/output.mdx | 45 +++-- .../state-checks/resource.mdx | 128 ++++++++++---- 5 files changed, 456 insertions(+), 85 deletions(-) diff --git a/website/docs/plugin/testing/acceptance-tests/plan-checks/index.mdx b/website/docs/plugin/testing/acceptance-tests/plan-checks/index.mdx index b989b786d..9c1960b54 100644 --- a/website/docs/plugin/testing/acceptance-tests/plan-checks/index.mdx +++ b/website/docs/plugin/testing/acceptance-tests/plan-checks/index.mdx @@ -28,28 +28,37 @@ Refer to: The `terraform-plugin-testing` module provides a package [`plancheck`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck) with built-in general plan checks for common use-cases: -| Check | Description | -|-----------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------| -| [`plancheck.ExpectEmptyPlan()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectEmptyPlan) | Asserts the entire plan has no operations for apply. | -| [`plancheck.ExpectNonEmptyPlan()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectNonEmptyPlan) | Asserts the entire plan contains at least one operation for apply. | +| Check | Description | +|--------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------| +| [`ExpectEmptyPlan`](/terraform/plugin/testing/acceptance-tests/plan-checks#expectemptyplan-plan-check) | Asserts the entire plan has no operations for apply. | +| [`ExpectNonEmptyPlan`](/terraform/plugin/testing/acceptance-tests/plan-checks#expectnonemptyplan-plan-check) | Asserts the entire plan contains at least one operation for apply. | -## Examples using `plancheck.ExpectEmptyPlan` +## `ExpectEmptyPlan` Plan Check One of the built-in plan checks, [`plancheck.ExpectEmptyPlan`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectEmptyPlan), is useful for determining a plan is a no-op prior to, for instance, the `terraform apply` phase. -Given the following example with the [random provider](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string), we have written a test that asserts that `random_string.one` will be destroyed and re-created when the `length` attribute is changed: +Given the following example with the [random provider](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string), we have written a test that asserts that there are no planned changes: ```go +package example_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/plancheck" +) + func Test_Random_EmptyPlan(t *testing.T) { t.Parallel() - r.Test(t, r.TestCase{ - ExternalProviders: map[string]r.ExternalProvider{ + resource.Test(t, resource.TestCase{ + ExternalProviders: map[string]resource.ExternalProvider{ "random": { Source: "registry.terraform.io/hashicorp/random", }, }, - Steps: []r.TestStep{ + Steps: []resource.TestStep{ { Config: `resource "random_string" "one" { length = 16 @@ -59,7 +68,7 @@ func Test_Random_EmptyPlan(t *testing.T) { Config: `resource "random_string" "one" { length = 16 }`, - ConfigPlanChecks: r.ConfigPlanChecks{ + ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectEmptyPlan(), }, @@ -68,4 +77,52 @@ func Test_Random_EmptyPlan(t *testing.T) { }, }) } +``` + +## `ExpectNonEmptyPlan` Plan Check + +One of the built-in plan checks, [`plancheck.ExpectNonEmptyPlan`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectNonEmptyPlan), is useful for determining whether a plan contains changes prior to, for instance, the `terraform apply` phase. + +The following example, which uses the built-in [terraform_data resource](https://developer.hashicorp.com/terraform/language/resources/terraform-data), asserts that there are planned changes: + +```go +package example_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/plancheck" + "github.com/hashicorp/terraform-plugin-testing/tfversion" +) + +func Test_ExpectNonEmptyPlan_ResourceChanges(t *testing.T) { + t.Parallel() + + resource.UnitTest(t, resource.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_4_0), + }, + ExternalProviders: map[string]resource.ExternalProvider{ + "terraform": {Source: "terraform.io/builtin/terraform"}, + }, + Steps: []resource.TestStep{ + { + Config: `resource "terraform_data" "one" { + triggers_replace = ["original"] + }`, + }, + { + Config: `resource "terraform_data" "one" { + triggers_replace = ["new"] + }`, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectNonEmptyPlan(), + }, + }, + }, + }, + }) +} ``` \ No newline at end of file diff --git a/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx b/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx index 6dd2121cd..65f406f9a 100644 --- a/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx +++ b/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx @@ -9,28 +9,38 @@ description: >- The `terraform-plugin-testing` module provides a package [`plancheck`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck) with built-in output value plan checks for common use-cases: -| Check | Description | -|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------| -| [`plancheck.ExpectKnownOutputValue(address, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectKnownOutputValue) | Asserts the output at the specified address has the specified type, and value. | -| [`plancheck.ExpectKnownOutputValueAtPath(address, path, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectKnownOutputValueAtPath) | Asserts the output at the specified address, and path has the specified type, and value. | -| [`plancheck.ExpectNullOutputValue(address)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectNullOutputValue) | Asserts the output at the specified address has a null value. | -| [`plancheck.ExpectNullOutputValueAtPath(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectNullOutputValueAtPath) | Asserts the output at the specified address, and path has a null value. | -| [`plancheck.ExpectUnknownOutputValue(address)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectUnknownOutputValue) | Asserts the output at the specified address has an unknown value. | -| [`plancheck.ExpectUnknownOutputValueAtPath(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectUnknownOutputValueAtPath) | Asserts the output at the specified address, and path has an unknown value. | +| Check | Description | +|-------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------| +| [`ExpectKnownOutputValue`](/terraform/plugin/testing/acceptance-tests/plan-checks/output#expectknownoutputvalue-plan-check) | Asserts the output at the specified address has the specified type, and value. | +| [`ExpectKnownOutputValueAtPath`](/terraform/plugin/testing/acceptance-tests/plan-checks/output#expectknownoutputvalueatpath-plan-check) | Asserts the output at the specified address, and path has the specified type, and value. | +| [`ExpectNullOutputValue`](/terraform/plugin/testing/acceptance-tests/plan-checks/output#expectnulloutputvalue-plan-check) | Asserts the output at the specified address has a null value. | +| [`ExpectNullOutputValueAtPath`](/terraform/plugin/testing/acceptance-tests/plan-checks/output#expectnulloutputvalueatpath-plan-check) | Asserts the output at the specified address, and path has a null value. | +| [`ExpectUnknownOutputValue`](/terraform/plugin/testing/acceptance-tests/plan-checks/output#expectunknownoutputvalue-plan-check) | Asserts the output at the specified address has an unknown value. | +| [`ExpectUnknownOutputValueAtPath`](/terraform/plugin/testing/acceptance-tests/plan-checks/output#expectknownoutputvalueatpath-plan-check) | Asserts the output at the specified address, and path has an unknown value. | -## Example using `plancheck.ExpectKnownOutputValue` +## `ExpectKnownOutputValue` Plan Check The [`plancheck.ExpectKnownOutputValue(address, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectKnownOutputValue) plan check verifies that a specific output value has a known type, and value. Refer to [Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks) for details, and examples of the available [knownvalue.Check](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check) types that can be used with the `ExpectKnownOutputValue` plan check. ```go +package example_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/plancheck" +) + func TestExpectKnownOutputValue_CheckPlan_Bool(t *testing.T) { t.Parallel() - r.Test(t, r.TestCase{ + resource.Test(t, resource.TestCase{ // Provider definition omitted. - Steps: []r.TestStep{ + Steps: []resource.TestStep{ { Config: `resource "test_resource" "one" { bool_attribute = true @@ -40,7 +50,7 @@ func TestExpectKnownOutputValue_CheckPlan_Bool(t *testing.T) { value = test_resource.one.bool_attribute } `, - ConfigPlanChecks: r.ConfigPlanChecks{ + ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownOutputValue( "bool_output", @@ -54,19 +64,29 @@ func TestExpectKnownOutputValue_CheckPlan_Bool(t *testing.T) { } ``` -## Example using `plancheck.ExpectKnownOutputValueAtPath` +## `ExpectKnownOutputValueAtPath` Plan Check The [`plancheck.ExpectKnownOutputValueAtPath(address, path, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectKnownOutputValueAtPath) plan check verifies that a specific output value at a defined path has a known type, and value. Refer to [Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks) for details, and examples of the available [knownvalue.Check](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check) types that can be used with the `ExpectKnownOutputValueAtPath` plan check. ```go +package example_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/plancheck" +) + func TestExpectKnownOutputValue_CheckPlan_Bool(t *testing.T) { t.Parallel() - r.Test(t, r.TestCase{ + resource.Test(t, resource.TestCase{ // Provider definition omitted. - Steps: []r.TestStep{ + Steps: []resource.TestStep{ { Config: `resource "test_resource" "one" { bool_attribute = true @@ -76,7 +96,7 @@ func TestExpectKnownOutputValue_CheckPlan_Bool(t *testing.T) { value = test_resource.one.bool_attribute } `, - ConfigPlanChecks: r.ConfigPlanChecks{ + ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownOutputValue( "bool_output", @@ -90,13 +110,111 @@ func TestExpectKnownOutputValue_CheckPlan_Bool(t *testing.T) { } ``` -## Example using `plancheck.ExpectUnknownOutputValue` +## `ExpectNullOutputValue` Plan Check + +The built-in [`plancheck.ExpectNullOutputValue(address)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectNullOutputValue) plan check determines whether an output at the specified address has a null value. + +```go +package example_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/plancheck" +) + +func Test_ExpectNullOutputValue_StringAttribute_NullConfig(t *testing.T) { + t.Parallel() + + resource.Test(t, resource.TestCase{ + // Provider definition omitted. + Steps: []resource.TestStep{ + { + Config: `resource "test_resource" "test" { + string_attribute = null + } + + output "string_attribute" { + value = test_resource.test.string_attribute + } + `, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectNullOutputValue("string_attribute"), + }, + }, + }, + }, + }) +} +``` + +## `ExpectNullOutputValueAtPath` Plan Check + +The built-in [`plancheck.ExpectNullOutputValueAtPath(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectNullOutputValueAtPath) plan check determines whether an output at the specified address, and path has a null value. | + +```go +package example_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/plancheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" + "github.com/hashicorp/terraform-plugin-testing/tfversion" +) + +func Test_ExpectNullOutputValueAtPath_StringAttribute_NullConfig(t *testing.T) { + t.Parallel() + + resource.Test(t, resource.TestCase{ + // Prior to Terraform v1.3.0 a planned output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, + // Provider definition omitted. + Steps: []resource.TestStep{ + { + Config: `resource "test_resource" "test" { + string_attribute = null + } + + output "resource" { + value = test_resource.test + } + `, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectNullOutputValueAtPath("resource", tfjsonpath.New("string_attribute")), + }, + }, + }, + }, + }) +} +``` + +## `ExpectUnknownOutputValue` Plan Check One of the built-in plan checks, [`plancheck.ExpectUnknownOutputValue`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectUnknownOutputValue), determines whether an output value is unknown, for example, prior to the `terraform apply` phase. The following uses the [time_offset](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/offset) resource from the [time provider](https://registry.terraform.io/providers/hashicorp/time/latest), to illustrate usage of the [`plancheck.ExpectUnknownOutputValue`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectUnknownOutputValue), and verifies that `day` is unknown. ```go +package example_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/plancheck" +) + func Test_Time_Unknown(t *testing.T) { t.Parallel() @@ -126,11 +244,21 @@ func Test_Time_Unknown(t *testing.T) { } ``` -## Example using `plancheck.ExpectUnknownOutputValueAtPath` +## `ExpectUnknownOutputValueAtPath` Plan Check Output values can contain objects or collections as well as primitive (e.g., string) values. Output value plan checks provide two forms for the plan checks, for example `ExpectUnknownOutputValue()`, and `ExpectUnknownOutputValueAtPath()`. The `Expect<...>OutputValueAtPath()` form is used to access a value contained within an object or collection, as illustrated in the following example. ```go +package example_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/plancheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + func Test_Time_Unknown(t *testing.T) { t.Parallel() diff --git a/website/docs/plugin/testing/acceptance-tests/plan-checks/resource.mdx b/website/docs/plugin/testing/acceptance-tests/plan-checks/resource.mdx index 2ef10e073..1aabb1281 100644 --- a/website/docs/plugin/testing/acceptance-tests/plan-checks/resource.mdx +++ b/website/docs/plugin/testing/acceptance-tests/plan-checks/resource.mdx @@ -9,32 +9,43 @@ description: >- The `terraform-plugin-testing` module provides a package [`plancheck`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck) with built-in managed resource, and data source plan checks for common use-cases: -| Check | Description | -|---------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------| -| [`plancheck.ExpectKnownValue(address, path, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectKnownValue) | Asserts the specified attribute at the given managed resource, or data source, has the specified type, and value. | -| [`plancheck.ExpectResourceAction(address, operation)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectResourceAction) | Asserts the given managed resource, or data source, has the specified operation for apply. | -| [`plancheck.ExpectSensitiveValue(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectSensitiveValue) | Asserts the specified attribute at the given managed resource, or data source, has a sensitive value. | -| [`plancheck.ExpectUnknownValue(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectUnknownValue) | Asserts the specified attribute at the given managed resource, or data source, has an unknown value. | +| Check | Description | +|---------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------| +| [`ExpectKnownValue`](/terraform/plugin/testing/acceptance-tests/plan-checks/resource#expectknownvalue-plan-check) | Asserts the specified attribute at the given managed resource, or data source, has the specified type, and value. | +| [`ExpectResourceAction`](/terraform/plugin/testing/acceptance-tests/plan-checks/resource#expectresourceaction-plan-check) | Asserts the given managed resource, or data source, has the specified operation for apply. | +| [`ExpectSensitiveValue`](/terraform/plugin/testing/acceptance-tests/plan-checks/resource#expectsensitivevalue-plan-check) | Asserts the specified attribute at the given managed resource, or data source, has a sensitive value. | +| [`ExpectUnknownValue`](/terraform/plugin/testing/acceptance-tests/plan-checks/resource#expectunknownvalue-plan-check) | Asserts the specified attribute at the given managed resource, or data source, has an unknown value. | -## Example using `plancheck.ExpectKnownValue` +## `ExpectKnownValue` Plan Check The [`plancheck.ExpectKnownValue(address, path, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectKnownValue) plan check provides a basis for asserting that a specific resource attribute has a known type, and value. Refer to [Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks) for details, and examples of the available [knownvalue.Check](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check) types that can be used with the `ExpectKnownValue` plan check. ```go +package example_test + +import ( + "testing" + + "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/tfjsonpath" +) + func TestExpectKnownValue_CheckPlan_String(t *testing.T) { t.Parallel() - r.Test(t, r.TestCase{ - // Provider definition omitted. - Steps: []r.TestStep{ + resource.Test(t, resource.TestCase{ + // Provider definition omitted. + Steps: []resource.TestStep{ { Config: `resource "test_resource" "one" { string_attribute = "str" } `, - ConfigPlanChecks: r.ConfigPlanChecks{ + ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( "test_resource.one", @@ -48,7 +59,7 @@ func TestExpectKnownValue_CheckPlan_String(t *testing.T) { } ``` -## Examples using `plancheck.ExpectResourceAction` +## `ExpectResourceAction` Plan Check One of the built-in plan checks, [`plancheck.ExpectResourceAction`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectResourceAction), is useful for determining the exact action type a resource will under-go during, say, the `terraform apply` phase. @@ -137,6 +148,7 @@ func Test_Time_UpdateInPlace(t *testing.T) { ``` Multiple plan checks can be combined if you want to assert multiple resource actions: + ```go package example_test @@ -183,3 +195,94 @@ func Test_Time_UpdateInPlace_and_NoOp(t *testing.T) { }) } ``` + +## `ExpectSensitiveValue` Plan Check + +The built-in [`plancheck.ExpectSensitiveValue(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectSensitiveValue) plan check is used to determine whether the specified attribute at the given managed resource, or data source, has a sensitive value. + +```go +package example_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/plancheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" + "github.com/hashicorp/terraform-plugin-testing/tfversion" +) + +func Test_ExpectSensitiveValue_SensitiveStringAttribute(t *testing.T) { + t.Parallel() + + resource.UnitTest(t, resource.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_0_0), // Change.AfterSensitive + }, + // Provider definition omitted. + Steps: []resource.TestStep{ + { + Config: ` + resource "test_resource" "one" { + sensitive_string_attribute = "test" + } + `, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectSensitiveValue("test_resource.one", + tfjsonpath.New("sensitive_string_attribute")), + }, + }, + }, + }, + }) +} +``` + +## `ExpectUnknownValue` Plan Check + +The built-in [`plancheck.ExpectUnknownValue(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectUnknownValue) plan check is used to determine whether the specified attribute at the given managed resource, or data source, has an unknown value. + +```go +package example_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/plancheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + +func Test_ExpectUnknownValue_StringAttribute(t *testing.T) { + t.Parallel() + + resource.Test(t, resource.TestCase{ + ExternalProviders: map[string]resource.ExternalProvider{ + "time": { + Source: "registry.terraform.io/hashicorp/time", + }, + }, + // Provider definition for `test` omitted. + Steps: []resource.TestStep{ + { + Config: `resource "time_static" "one" {} + + resource "test_resource" "two" { + string_attribute = time_static.one.rfc3339 + } + `, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectUnknownValue("test_resource.two", tfjsonpath.New("string_attribute")), + }, + }, + }, + }, + }) +} +``` \ No newline at end of file diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx index b1e02da1f..d45bc3abd 100644 --- a/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx @@ -9,24 +9,34 @@ description: >- The `terraform-plugin-testing` module provides a package [`statecheck`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck) with built-in output value state checks for common use-cases: -| Check | Description | -|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------| -| [`statecheck.ExpectKnownOutputValue(address, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValue) | Asserts the output at the specified address has the specified type, and value. | -| [`statecheck.ExpectKnownOutputValueAtPath(address, path, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValueAtPath) | Asserts the output at the specified address, and path has the specified type, and value. | +| Check | Description | +|-------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------| +| [`ExpectKnownOutputValue`](/terraform/plugin/testing/acceptance-tests/state-checks/output#expectknownoutputvalue-state-check) | Asserts the output at the specified address has the specified type, and value. | +| [`ExpectKnownOutputValueAtPath`](/terraform/plugin/testing/acceptance-tests/state-checks/output#expectknownoutputvalueatpath-state-check) | Asserts the output at the specified address, and path has the specified type, and value. | -## Example using `statecheck.ExpectKnownOutputValue` +## `ExpectKnownOutputValue` State Check The [`statecheck.ExpectKnownOutputValue(address, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValue) state check verifies that a specific output value has a known type, and value. Refer to [Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks) for details, and examples of the available [knownvalue.Check](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check) types that can be used with the `ExpectKnownOutputValue` state check. ```go +package example_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/statecheck" +) + func TestExpectKnownOutputValue_CheckState_Bool(t *testing.T) { t.Parallel() - r.Test(t, r.TestCase{ + resource.Test(t, resource.TestCase{ // Provider definition omitted. - Steps: []r.TestStep{ + Steps: []resource.TestStep{ { Config: `resource "test_resource" "one" { bool_attribute = true @@ -36,7 +46,7 @@ func TestExpectKnownOutputValue_CheckState_Bool(t *testing.T) { value = test_resource.one.bool_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: resource.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "bool_output", knownvalue.BoolExact(true), @@ -48,19 +58,30 @@ func TestExpectKnownOutputValue_CheckState_Bool(t *testing.T) { } ``` -## Example using `statecheck.ExpectKnownOutputValueAtPath` +## `ExpectKnownOutputValueAtPath` State Check The [`statecheck.ExpectKnownOutputValueAtPath(address, path, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValueAtPath) state check verifies that a specific output value at a defined path has a known type, and value. Refer to [Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks) for details, and examples of the available [knownvalue.Check](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check) types that can be used with the `ExpectKnownOutputValueAtPath` state check. ```go +package example_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + func TestExpectKnownOutputValueAtPath_CheckState_Bool(t *testing.T) { t.Parallel() - r.Test(t, r.TestCase{ + resource.Test(t, resource.TestCase{ // Provider definition omitted. - Steps: []r.TestStep{ + Steps: []resource.TestStep{ { Config: `resource "test_resource" "one" { bool_attribute = true @@ -70,7 +91,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Bool(t *testing.T) { value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: resource.ConfigStateChecks{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("bool_attribute"), diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx index 2586e8705..95dee0822 100644 --- a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx @@ -9,26 +9,36 @@ description: >- The `terraform-plugin-testing` module provides a package [`statecheck`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck) with built-in managed resource, and data source state checks for common use-cases: -| Check | Description | -|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [`statecheck.ExpectContains(addressOne, pathOne, addressTwo, pathTwo)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectContains) | Asserts the specified attribute at the first given managed resource, or data source, contains the value specified by the attribute in the second given managed resource, or data source. | -| [`statecheck.ExpectKnownValue(address, path, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue) | Asserts the specified attribute at the given managed resource, or data source, has the specified type, and value. | -| [`statecheck.ExpectMatchingValues(addressOne, pathOne, addressTwo, pathTwo)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectMatchingValues) | Asserts the specified attributes at the given managed resources have matching values. | -| [`statecheck.ExpectNoValueExists(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectNoValueExists) | Asserts the specified attribute at the given managed resource, or data source, does not exist. | -| [`statecheck.ExpectSensitiveValue(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectSensitiveValue) | Asserts the specified attribute at the given managed resource, or data source, has a sensitive value. | -| [`statecheck.ExpectValueExists(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectValueExists) | Asserts the specified attribute at the given managed resource, or data source, exists. | +| Check | Description | +|-----------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [`ExpectContains`](/terraform/plugin/testing/acceptance-tests/state-checks/resource#expectcontains-state-check) | Asserts the specified attribute at the first given managed resource, or data source, contains the value specified by the attribute in the second given managed resource, or data source. | +| [`ExpectKnownValue`](/terraform/plugin/testing/acceptance-tests/state-checks/resource#expectknownvalue-state-check) | Asserts the specified attribute at the given managed resource, or data source, has the specified type, and value. | +| [`ExpectMatchingValues`](/terraform/plugin/testing/acceptance-tests/state-checks/resource#expectmatchingvalues-state-check) | Asserts the specified attributes at the given managed resources have matching values. | +| [`ExpectNoValueExists`](/terraform/plugin/testing/acceptance-tests/state-checks/resource#expectnovalueexists-state-check) | Asserts the specified attribute at the given managed resource, or data source, does not exist. | +| [`ExpectSensitiveValue`](/terraform/plugin/testing/acceptance-tests/state-checks/resource#expectsensitivevalue-state-check) | Asserts the specified attribute at the given managed resource, or data source, has a sensitive value. | +| [`ExpectValueExists`](/terraform/plugin/testing/acceptance-tests/state-checks/resource#expectvalueexists-state-check) | Asserts the specified attribute at the given managed resource, or data source, exists. | -## Example using `statecheck.ExpectContains` +## `ExpectContains` State Check -The [`statecheck.ExpectContains(addressOne, pathOne, addressTwo, pathTwo)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectContains) state check provides a basis for asserting that the first resource attribute contains the value specified by the second resource attribute. +The [`statecheck.ExpectContains(addressOne, pathOne, addressTwo, pathTwo)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectContains) state check provides a basis for asserting that the first specified resource attribute contains the value specified by the second resource attribute. ```go +package example_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + func TestExpectContains_CheckState_Found(t *testing.T) { t.Parallel() - r.Test(t, r.TestCase{ + resource.Test(t, resource.TestCase{ // Provider definition omitted. - Steps: []r.TestStep{ + Steps: []resource.TestStep{ { Config: `resource "test_resource" "one" { string_attribute = "value1" @@ -40,7 +50,7 @@ func TestExpectContains_CheckState_Found(t *testing.T) { "value2" ] }`, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: resource.ConfigStateChecks{ statecheck.ExpectContains( "test_resource.two", tfjsonpath.New("set_attribute"), @@ -54,25 +64,36 @@ func TestExpectContains_CheckState_Found(t *testing.T) { } ``` -## Example using `statecheck.ExpectKnownValue` +## `ExpectKnownValue` State Check The [`statecheck.ExpectKnownValue(address, path, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue) state check provides a basis for asserting that a specific resource attribute has a known type, and value. Refer to [Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks) for details, and examples of the available [knownvalue.Check](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check) types that can be used with the `ExpectKnownValue` state check. ```go +package example_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + func TestExpectKnownValue_CheckState_Bool(t *testing.T) { t.Parallel() - r.Test(t, r.TestCase{ + resource.Test(t, resource.TestCase{ // Provider definition omitted. - Steps: []r.TestStep{ + Steps: []resource.TestStep{ { Config: `resource "test_resource" "one" { bool_attribute = true } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: resource.ConfigStateChecks{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), @@ -85,18 +106,28 @@ func TestExpectKnownValue_CheckState_Bool(t *testing.T) { } ``` -## Example using `statecheck.ExpectMatchingValues` +## `ExpectMatchingValues` State Check The [`statecheck.ExpectMatchingValues(addressOne, pathOne, addressTwo, pathTwo)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectMatchingValues) state check provides a basis for asserting that the specified resource attributes have matching values. ```go +package example_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + func TestExpectMatchingValues_CheckState_AttributeValuesEqual_Bool(t *testing.T) { t.Parallel() - r.Test(t, r.TestCase{ + resource.Test(t, resource.TestCase{ // Provider definition omitted. - Steps: []r.TestStep{ + Steps: []resource.TestStep{ { Config: `resource "test_resource" "one" { bool_attribute = true @@ -105,7 +136,7 @@ func TestExpectMatchingValues_CheckState_AttributeValuesEqual_Bool(t *testing.T) resource "test_resource" "two" { bool_attribute = true }`, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: resource.ConfigStateChecks{ statecheck.ExpectMatchingValues( "test_resource.one", tfjsonpath.New("bool_attribute"), @@ -119,23 +150,33 @@ func TestExpectMatchingValues_CheckState_AttributeValuesEqual_Bool(t *testing.T) } ``` -## Example using `statecheck.ExpectNoValueExists` +## `ExpectNoValueExists` State Check The [`statecheck.ExpectNoValueExists(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectNoValueExists) state check provides a basis for asserting that a specific resource attribute does not exist. ```go +package example_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + func TestExpectNoValueExists_CheckState_AttributeNotFound(t *testing.T) { t.Parallel() - r.Test(t, r.TestCase{ + resource.Test(t, resource.TestCase{ // Provider definition omitted. - Steps: []r.TestStep{ + Steps: []resource.TestStep{ { Config: `resource "test_resource" "one" { bool_attribute = true } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: resource.ConfigStateChecks{ statecheck.ExpectNoValueExists( "test_resource.one", tfjsonpath.New("does_not_exist"), @@ -147,29 +188,40 @@ func TestExpectNoValueExists_CheckState_AttributeNotFound(t *testing.T) { } ``` -## Example using `statecheck.ExpectSensitiveValue` +## `ExpectSensitiveValue` State Check The [`statecheck.ExpectSensitiveValue(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectSensitiveValue) state check provides a basis for asserting that a specific resource attribute is marked as sensitive. -> **Note:** In this example, a [TerraformVersionCheck](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/tfversion#TerraformVersionCheck) is being used to prevent execution of this test prior to Terraform version `1.4.6` (refer to the release notes for Terraform [v1.4.6](https://github.com/hashicorp/terraform/releases/tag/v1.4.6)). ```go +package example_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" + "github.com/hashicorp/terraform-plugin-testing/tfversion" +) + func Test_ExpectSensitiveValue_SensitiveStringAttribute(t *testing.T) { t.Parallel() - r.UnitTest(t, r.TestCase{ + resource.UnitTest(t, resource.TestCase{ TerraformVersionChecks: []tfversion.TerraformVersionCheck{ tfversion.SkipBelow(tfversion.Version1_4_6), // StateResource.SensitiveValues }, // Provider definition omitted. - Steps: []r.TestStep{ + Steps: []resource.TestStep{ { Config: ` resource "test_resource" "one" { sensitive_string_attribute = "test" } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: resource.ConfigStateChecks{ statecheck.ExpectSensitiveValue("test_resource.one", tfjsonpath.New("sensitive_string_attribute")), }, @@ -179,23 +231,33 @@ func Test_ExpectSensitiveValue_SensitiveStringAttribute(t *testing.T) { } ``` -## Example using `statecheck.ExpectValueExists` +## `ExpectValueExists` State Check The [`statecheck.ExpectValueExists(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectValueExists) state check provides a basis for asserting that a specific resource attribute exists. ```go +package example_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + func TestExpectValueExists_CheckState_AttributeFound(t *testing.T) { t.Parallel() - r.Test(t, r.TestCase{ + resource.Test(t, resource.TestCase{ // Provider definition omitted. - Steps: []r.TestStep{ + Steps: []resource.TestStep{ { Config: `resource "test_resource" "one" { bool_attribute = true } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: resource.ConfigStateChecks{ statecheck.ExpectValueExists( "test_resource.one", tfjsonpath.New("bool_attribute"), From 89d878500190687194af4a2dbe8858d072448290 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Fri, 19 Jan 2024 12:51:41 +0000 Subject: [PATCH 33/73] Adding further Go docs to illustrate migration from built-in TestCheckFunc(s), and include example usage of state checks --- helper/resource/testing.go | 570 +++++++++++++++++- helper/resource/testing_sets.go | 213 ++++++- statecheck/expect_contains.go | 42 ++ statecheck/expect_known_output_value.go | 108 ++++ .../expect_known_output_value_at_path.go | 112 ++++ .../expect_known_output_value_at_path_test.go | 30 + statecheck/expect_known_output_value_test.go | 29 + statecheck/expect_known_value.go | 104 ++++ statecheck/expect_known_value_test.go | 96 +++ statecheck/expect_matching_values.go | 39 ++ statecheck/expect_no_value_exists.go | 34 ++ statecheck/expect_value_exists.go | 38 +- .../known-value-checks/custom.mdx | 20 +- 13 files changed, 1420 insertions(+), 15 deletions(-) diff --git a/helper/resource/testing.go b/helper/resource/testing.go index 32177310a..a1d26a544 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -1060,9 +1060,44 @@ func ComposeAggregateTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc { // the special .# or .% key syntax for those situations instead. // // Deprecated: State checks have been superseded by ConfigStateChecks. -// Use the built-in statecheck.ExpectValueExists state instead. +// Use the built-in statecheck.ExpectValueExists state check instead. // TestCheckResourceAttrSet function will be removed in the next major version. // +// The following is an example of using statecheck.ExpectValueExists +// to replicate the behaviour of TestCheckResourceAttrSet. +// +// package example_test +// +// import ( +// "testing" +// +// "github.com/hashicorp/terraform-plugin-testing/helper/resource" +// "github.com/hashicorp/terraform-plugin-testing/statecheck" +// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +// ) +// +// func TestExpectValueExists_CheckState_AttributeFound(t *testing.T) { +// t.Parallel() +// +// resource.Test(t, resource.TestCase{ +// // Provider definition omitted. +// Steps: []resource.TestStep{ +// { +// Config: `resource "test_resource" "one" { +// bool_attribute = true +// } +// `, +// ConfigStateChecks: resource.ConfigStateChecks{ +// statecheck.ExpectValueExists( +// "test_resource.one", +// tfjsonpath.New("bool_attribute"), +// ), +// }, +// }, +// }, +// }) +// } +// // [ExpectValueExists]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectValueExists // [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck // [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck @@ -1170,6 +1205,43 @@ func testCheckResourceAttrSet(is *terraform.InstanceState, name string, key stri // Use the built-in statecheck.ExpectKnownValue state check instead. // TestCheckResourceAttr function will be removed in the next major version. // +// The following is an example of using statecheck.ExpectKnownValue +// to replicate the behaviour of TestCheckResourceAttr. +// +// package example_test +// +// import ( +// "testing" +// +// "github.com/hashicorp/terraform-plugin-testing/helper/resource" +// "github.com/hashicorp/terraform-plugin-testing/knownvalue" +// "github.com/hashicorp/terraform-plugin-testing/statecheck" +// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +// ) +// +// func TestExpectKnownValue_CheckState_Bool(t *testing.T) { +// t.Parallel() +// +// resource.Test(t, resource.TestCase{ +// // Provider definition omitted. +// Steps: []resource.TestStep{ +// { +// Config: `resource "test_resource" "one" { +// bool_attribute = true +// } +// `, +// ConfigStateChecks: resource.ConfigStateChecks{ +// statecheck.ExpectKnownValue( +// "test_resource.one", +// tfjsonpath.New("bool_attribute"), +// knownvalue.BoolExact(true), +// ), +// }, +// }, +// }, +// }) +// } +// // [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue // [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck // [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck @@ -1258,8 +1330,80 @@ func testCheckResourceAttr(is *terraform.InstanceState, name string, key string, // When this function returns an error, TestCheckResourceAttrWith will fail the check. // // Deprecated: State checks have been superseded by ConfigStateChecks. -// This type will be removed in the next major version. +// Use the built-int statecheck.ExpectKnownValue state check in combination +// with a custom knownvalue.Check instead. +// CheckResourceAttrWithFunc will be removed in the next major version. +// +// The following is an example of using statecheck.ExpectKnownValue in combination +// with a custom knownvalue.Check to replicate the behaviour of TestCheckResourceAttrWith. +// +// package example_test +// +// import ( +// "fmt" +// "strings" +// "testing" +// +// "github.com/hashicorp/terraform-plugin-testing/helper/resource" +// "github.com/hashicorp/terraform-plugin-testing/knownvalue" +// "github.com/hashicorp/terraform-plugin-testing/statecheck" +// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +// ) +// +// func TestExpectKnownValue_CheckState_String_Custom(t *testing.T) { +// t.Parallel() +// +// resource.Test(t, resource.TestCase{ +// // Provider definition omitted. +// Steps: []resource.TestStep{ +// { +// Config: `resource "test_resource" "one" { +// string_attribute = "string" +// } +// `, +// ConfigStateChecks: resource.ConfigStateChecks{ +// statecheck.ExpectKnownValue( +// "test_resource.one", +// tfjsonpath.New("string_attribute"), +// StringContains("tri")), +// }, +// }, +// }, +// }) +// } +// +// var _ knownvalue.Check = stringContains{} +// +// type stringContains struct { +// value string +// } +// +// func (v stringContains) CheckValue(other any) error { +// otherVal, ok := other.(string) +// +// if !ok { +// return fmt.Errorf("expected string value for StringContains check, got: %T", other) +// } +// +// if !strings.Contains(otherVal, v.value) { +// return fmt.Errorf("expected string %q to contain %q for StringContains check", otherVal, v.value) +// } +// +// return nil +// } +// +// func (v stringContains) String() string { +// return v.value +// } +// +// func StringContains(value string) stringContains { +// return stringContains{ +// value: value, +// } +// } // +// [Check]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check +// [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue // [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck // [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck type CheckResourceAttrWithFunc func(value string) error @@ -1305,6 +1449,74 @@ type CheckResourceAttrWithFunc func(value string) error // with a custom knownvalue.Check instead. // TestCheckResourceAttrWith function will be removed in the next major version. // +// The following is an example of using statecheck.ExpectKnownValue in combination +// with a custom knownvalue.Check to replicate the behaviour of TestCheckResourceAttrWith. +// +// package example_test +// +// import ( +// "fmt" +// "strings" +// "testing" +// +// "github.com/hashicorp/terraform-plugin-testing/helper/resource" +// "github.com/hashicorp/terraform-plugin-testing/knownvalue" +// "github.com/hashicorp/terraform-plugin-testing/statecheck" +// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +// ) +// +// func TestExpectKnownValue_CheckState_String_Custom(t *testing.T) { +// t.Parallel() +// +// resource.Test(t, resource.TestCase{ +// // Provider definition omitted. +// Steps: []resource.TestStep{ +// { +// Config: `resource "test_resource" "one" { +// string_attribute = "string" +// } +// `, +// ConfigStateChecks: resource.ConfigStateChecks{ +// statecheck.ExpectKnownValue( +// "test_resource.one", +// tfjsonpath.New("string_attribute"), +// StringContains("tri")), +// }, +// }, +// }, +// }) +// } +// +// var _ knownvalue.Check = stringContains{} +// +// type stringContains struct { +// value string +// } +// +// func (v stringContains) CheckValue(other any) error { +// otherVal, ok := other.(string) +// +// if !ok { +// return fmt.Errorf("expected string value for StringContains check, got: %T", other) +// } +// +// if !strings.Contains(otherVal, v.value) { +// return fmt.Errorf("expected string %q to contain %q for StringContains check", otherVal, v.value) +// } +// +// return nil +// } +// +// func (v stringContains) String() string { +// return v.value +// } +// +// func StringContains(value string) stringContains { +// return stringContains{ +// value: value, +// } +// } +// // [Check]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check // [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue // [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck @@ -1366,6 +1578,41 @@ func TestCheckResourceAttrWith(name, key string, checkValueFunc CheckResourceAtt // Use the built-in statecheck.ExpectNoValueExists instead. // TestCheckNoResourceAttr function will be removed in the next major version. // +// The following is an example of using statecheck.ExpectNoValueExists to +// replicate the behaviour of TestCheckNoResourceAttr. +// +// package example_test +// +// import ( +// "testing" +// +// "github.com/hashicorp/terraform-plugin-testing/helper/resource" +// "github.com/hashicorp/terraform-plugin-testing/statecheck" +// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +// ) +// +// func TestExpectNoValueExists_CheckState_AttributeNotFound(t *testing.T) { +// t.Parallel() +// +// resource.Test(t, resource.TestCase{ +// // Provider definition omitted. +// Steps: []resource.TestStep{ +// { +// Config: `resource "test_resource" "one" { +// bool_attribute = true +// } +// `, +// ConfigStateChecks: resource.ConfigStateChecks{ +// statecheck.ExpectNoValueExists( +// "test_resource.one", +// tfjsonpath.New("does_not_exist"), +// ), +// }, +// }, +// }, +// }) +// } +// // [ExpectNoValueExists]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectNoValueExists // [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck // [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck @@ -1479,6 +1726,75 @@ func testCheckNoResourceAttr(is *terraform.InstanceState, name string, key strin // with a custom knownvalue.Check instead. // TestMatchResourceAttr function will be removed in the next major version. // +// The following is an example of using statecheck.ExpectKnownValue +// in combination with a custom knownvalue.Check to replicate the behaviour of +// TestMatchResourceAttr. +// +// package example_test +// +// import ( +// "fmt" +// "strings" +// "testing" +// +// "github.com/hashicorp/terraform-plugin-testing/helper/resource" +// "github.com/hashicorp/terraform-plugin-testing/knownvalue" +// "github.com/hashicorp/terraform-plugin-testing/statecheck" +// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +// ) +// +// func TestExpectKnownValue_CheckState_String_Custom(t *testing.T) { +// t.Parallel() +// +// resource.Test(t, resource.TestCase{ +// // Provider definition omitted. +// Steps: []resource.TestStep{ +// { +// Config: `resource "test_resource" "one" { +// string_attribute = "string" +// } +// `, +// ConfigStateChecks: resource.ConfigStateChecks{ +// statecheck.ExpectKnownValue( +// "test_resource.one", +// tfjsonpath.New("string_attribute"), +// StringContains("tri")), +// }, +// }, +// }, +// }) +// } +// +// var _ knownvalue.Check = stringContains{} +// +// type stringContains struct { +// value string +// } +// +// func (v stringContains) CheckValue(other any) error { +// otherVal, ok := other.(string) +// +// if !ok { +// return fmt.Errorf("expected string value for StringContains check, got: %T", other) +// } +// +// if !strings.Contains(otherVal, v.value) { +// return fmt.Errorf("expected string %q to contain %q for StringContains check", otherVal, v.value) +// } +// +// return nil +// } +// +// func (v stringContains) String() string { +// return v.value +// } +// +// func StringContains(value string) stringContains { +// return stringContains{ +// value: value, +// } +// } +// // [Check]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check // [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue // [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck @@ -1541,6 +1857,62 @@ func testMatchResourceAttr(is *terraform.InstanceState, name string, key string, // with types implementing knownvalue.Check instead. // TestCheckResourceAttrPtr function will be removed in the next major version. // +// The following is an example of using statecheck.ExpectKnownValue +// to replicate the behaviour of TestCheckResourceAttrPtr. +// +// package example_test +// +// import ( +// "context" +// "testing" +// +// "github.com/hashicorp/terraform-plugin-testing/helper/resource" +// "github.com/hashicorp/terraform-plugin-testing/knownvalue" +// "github.com/hashicorp/terraform-plugin-testing/statecheck" +// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +// ) +// +// func TestExpectKnownValue_CheckState_BoolPointer(t *testing.T) { +// t.Parallel() +// +// testBool := Pointer(false) +// +// resource.Test(t, resource.TestCase{ +// // Provider definition omitted. +// Steps: []resource.TestStep{ +// { +// Config: `resource "test_resource" "one" { +// bool_attribute = true +// } +// `, +// ConfigStateChecks: resource.ConfigStateChecks{ +// AlterValue(testBool), +// statecheck.ExpectKnownValue( +// "test_resource.one", +// tfjsonpath.New("bool_attribute"), +// knownvalue.BoolExact(*testBool), +// ), +// }, +// }, +// }, +// }) +// } +// +// func Pointer[T any](in T) *T { +// return &in +// } +// +// type mutate struct{} +// +// func (m mutate) CheckState(context.Context, statecheck.CheckStateRequest, *statecheck.CheckStateResponse) { +// } +// +// func AlterValue(b *bool) mutate { +// *b = true +// +// return mutate{} +// } +// // [Check]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check // [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue // [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck @@ -1605,6 +1977,47 @@ func TestCheckModuleResourceAttrPtr(mp []string, name string, key string, value // Use the built-in statecheck.ExpectMatchingValues state check instead. // TestCheckResourceAttrPair function will be removed in the next major version. // +// The following is an example of using statecheck.ExpectMatchingValues +// to replicate the behaviour of TestCheckResourceAttrPair. +// +// package example_test +// +// import ( +// "testing" +// +// "github.com/hashicorp/terraform-plugin-testing/helper/resource" +// "github.com/hashicorp/terraform-plugin-testing/statecheck" +// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +// ) +// +// func TestExpectMatchingValues_CheckState_AttributeValuesEqual_Bool(t *testing.T) { +// t.Parallel() +// +// resource.Test(t, resource.TestCase{ +// // Provider definition omitted. +// +// Steps: []resource.TestStep{ +// { +// Config: `resource "test_resource" "one" { +// bool_attribute = true +// } +// +// resource "test_resource" "two" { +// bool_attribute = true +// }`, +// ConfigStateChecks: resource.ConfigStateChecks{ +// statecheck.ExpectMatchingValues( +// "test_resource.one", +// tfjsonpath.New("bool_attribute"), +// "test_resource.two", +// tfjsonpath.New("bool_attribute"), +// ), +// }, +// }, +// }, +// }) +// } +// // [ExpectMatchingValues]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectMatchingValues // [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck // [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck @@ -1708,6 +2121,86 @@ func testCheckResourceAttrPair(isFirst *terraform.InstanceState, nameFirst strin // statecheck.ExpectKnownOutputValueAtPath state checks instead. // TestCheckOutput function will be removed in the next major version. // +// The following is an example of using statecheck.ExpectKnownOutputValue +// to replicate the behaviour of TestCheckOutput. +// +// package example_test +// +// import ( +// "testing" +// +// "github.com/hashicorp/terraform-plugin-testing/helper/resource" +// "github.com/hashicorp/terraform-plugin-testing/knownvalue" +// "github.com/hashicorp/terraform-plugin-testing/statecheck" +// ) +// +// func TestExpectKnownOutputValue_CheckState_Bool(t *testing.T) { +// t.Parallel() +// +// resource.Test(t, resource.TestCase{ +// // Provider definition omitted. +// Steps: []resource.TestStep{ +// { +// Config: `resource "test_resource" "one" { +// bool_attribute = true +// } +// +// output bool_output { +// value = test_resource.one.bool_attribute +// } +// `, +// ConfigStateChecks: resource.ConfigStateChecks{ +// statecheck.ExpectKnownOutputValue( +// "bool_output", +// knownvalue.BoolExact(true), +// ), +// }, +// }, +// }, +// }) +// } +// +// The following is an example of using statecheck.ExpectKnownOutputValueAtPath +// to replicate the behaviour of TestCheckOutput. +// +// package example_test +// +// import ( +// "testing" +// +// "github.com/hashicorp/terraform-plugin-testing/helper/resource" +// "github.com/hashicorp/terraform-plugin-testing/knownvalue" +// "github.com/hashicorp/terraform-plugin-testing/statecheck" +// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +// ) +// +// func TestExpectKnownOutputValueAtPath_CheckState_Bool(t *testing.T) { +// t.Parallel() +// +// resource.Test(t, resource.TestCase{ +// // Provider definition omitted. +// Steps: []resource.TestStep{ +// { +// Config: `resource "test_resource" "one" { +// bool_attribute = true +// } +// +// output test_resource_one_output { +// value = test_resource.one +// } +// `, +// ConfigStateChecks: resource.ConfigStateChecks{ +// statecheck.ExpectKnownOutputValueAtPath( +// "test_resource_one_output", +// tfjsonpath.New("bool_attribute"), +// knownvalue.BoolExact(true), +// ), +// }, +// }, +// }, +// }) +// } +// // [ExpectKnownOutputValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValue // [ExpectKnownOutputValueAtPath]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValueAtPath // [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck @@ -1738,6 +2231,79 @@ func TestCheckOutput(name, value string) TestCheckFunc { // combination with a custom knownvalue.Check instead. // TestMatchOutput function will be removed in the next major version. // +// The following is an example of using statecheck.ExpectKnownOutputValueAtPath +// in combination with a custom knownvalue.Check to replicate the behaviour of +// TestMatchOutput. +// +// package example_test +// +// import ( +// "fmt" +// "strings" +// "testing" +// +// "github.com/hashicorp/terraform-plugin-testing/helper/resource" +// "github.com/hashicorp/terraform-plugin-testing/knownvalue" +// "github.com/hashicorp/terraform-plugin-testing/statecheck" +// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +// ) +// +// func TestExpectKnownOutputValueAtPath_CheckState_String_Custom(t *testing.T) { +// t.Parallel() +// +// resource.Test(t, resource.TestCase{ +// // Provider definition omitted. +// Steps: []resource.TestStep{ +// { +// Config: `resource "test_resource" "one" { +// string_attribute = "string" +// } +// +// output test_resource_one_output { +// value = test_resource.one +// } +// `, +// ConfigStateChecks: resource.ConfigStateChecks{ +// statecheck.ExpectKnownOutputValueAtPath( +// "test_resource_one_output", +// tfjsonpath.New("string_attribute"), +// StringContains("str")), +// }, +// }, +// }, +// }) +// } +// +// var _ knownvalue.Check = stringContains{} +// +// type stringContains struct { +// value string +// } +// +// func (v stringContains) CheckValue(other any) error { +// otherVal, ok := other.(string) +// +// if !ok { +// return fmt.Errorf("expected string value for StringContains check, got: %T", other) +// } +// +// if !strings.Contains(otherVal, v.value) { +// return fmt.Errorf("expected string %q to contain %q for StringContains check", otherVal, v.value) +// } +// +// return nil +// } +// +// func (v stringContains) String() string { +// return v.value +// } +// +// func StringContains(value string) stringContains { +// return stringContains{ +// value: value, +// } +// } +// // [Check]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check // [ExpectKnownOutputValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValue // [ExpectKnownOutputValueAtPath]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValueAtPath diff --git a/helper/resource/testing_sets.go b/helper/resource/testing_sets.go index abd2c04b7..1131e05bb 100644 --- a/helper/resource/testing_sets.go +++ b/helper/resource/testing_sets.go @@ -63,6 +63,48 @@ const ( // with knownvalue.SetExact or knownvalue.SetPartial instead. // TestCheckTypeSetElemNestedAttrs function will be removed in the next major version. // +// The following is an example of using statecheck.ExpectKnownValue in combination +// with knownvalue.SetPartial to replicate the behaviour of TestCheckTypeSetElemNestedAttrs. +// +// package example_test +// +// import ( +// "testing" +// +// "github.com/hashicorp/terraform-plugin-testing/helper/resource" +// "github.com/hashicorp/terraform-plugin-testing/knownvalue" +// "github.com/hashicorp/terraform-plugin-testing/statecheck" +// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +// ) +// +// func TestExpectKnownValue_CheckState_SetPartial(t *testing.T) { +// t.Parallel() +// +// resource.Test(t, resource.TestCase{ +// // Provider definition omitted. +// Steps: []resource.TestStep{ +// { +// Config: `resource "test_resource" "one" { +// set_attribute = [ +// "value1", +// "value2" +// ] +// } +// `, +// ConfigStateChecks: resource.ConfigStateChecks{ +// statecheck.ExpectKnownValue( +// "test_resource.one", +// tfjsonpath.New("set_attribute"), +// knownvalue.SetPartial([]knownvalue.Check{ +// knownvalue.StringExact("value2"), +// }), +// ), +// }, +// }, +// }, +// }) +// } +// // [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue // [SetExact]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetExact // [SetPartial]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetPartial @@ -147,6 +189,88 @@ func TestCheckTypeSetElemNestedAttrs(name, attr string, values map[string]string // knownvalue.SetPartial, with nested custom knownvalue.Check instead. // TestMatchTypeSetElemNestedAttrs function will be removed in the next major version. // +// The following is an example of using statecheck.ExpectKnownValue in combination +// with knownvalue.SetExact, with a nested custom knownvalue.Check to replicate +// the behaviour of TestCheckTypeSetElemAttr. +// +// package example_test +// +// import ( +// "fmt" +// "strings" +// "testing" +// +// "github.com/hashicorp/terraform-plugin-testing/helper/resource" +// "github.com/hashicorp/terraform-plugin-testing/knownvalue" +// "github.com/hashicorp/terraform-plugin-testing/statecheck" +// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +// ) +// +// func TestExpectKnownValue_CheckState_SetNestedBlock_Custom(t *testing.T) { +// t.Parallel() +// +// resource.Test(t, resource.TestCase{ +// // Provider definition omitted. +// Steps: []resource.TestStep{ +// { +// Config: `resource "test_resource" "one" { +// set_nested_block { +// set_nested_block_attribute = "string" +// } +// set_nested_block { +// set_nested_block_attribute = "girts" +// } +// } +// `, +// ConfigStateChecks: resource.ConfigStateChecks{ +// statecheck.ExpectKnownValue( +// "test_resource.one", +// tfjsonpath.New("set_nested_block"), +// knownvalue.SetExact([]knownvalue.Check{ +// knownvalue.MapExact(map[string]knownvalue.Check{ +// "set_nested_block_attribute": StringContains("str"), +// }), +// knownvalue.MapExact(map[string]knownvalue.Check{ +// "set_nested_block_attribute": StringContains("rts"), +// }), +// }), +// ), +// }, +// }, +// }, +// }) +// } +// +// var _ knownvalue.Check = stringContains{} +// +// type stringContains struct { +// value string +// } +// +// func (v stringContains) CheckValue(other any) error { +// otherVal, ok := other.(string) +// +// if !ok { +// return fmt.Errorf("expected string value for StringContains check, got: %T", other) +// } +// +// if !strings.Contains(otherVal, v.value) { +// return fmt.Errorf("expected string %q to contain %q for StringContains check", otherVal, v.value) +// } +// +// return nil +// } +// +// func (v stringContains) String() string { +// return v.value +// } +// +// func StringContains(value string) stringContains { +// return stringContains{ +// value: value, +// } +// } +// // [ListExact]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ListExact // [ListPartial]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ListPartial // [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue @@ -231,6 +355,49 @@ func TestMatchTypeSetElemNestedAttrs(name, attr string, values map[string]*regex // with knownvalue.SetExact or knownvalue.SetPartial instead. // TestCheckTypeSetElemAttr function will be removed in the next major version. // +// The following is an example of using statecheck.ExpectKnownValue in combination +// with knownvalue.SetExact to replicate the behaviour of TestCheckTypeSetElemAttr. +// +// package example_test +// +// import ( +// "testing" +// +// "github.com/hashicorp/terraform-plugin-testing/helper/resource" +// "github.com/hashicorp/terraform-plugin-testing/knownvalue" +// "github.com/hashicorp/terraform-plugin-testing/statecheck" +// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +// ) +// +// func TestExpectKnownValue_CheckState_Set(t *testing.T) { +// t.Parallel() +// +// resource.Test(t, resource.TestCase{ +// // Provider definition omitted. +// Steps: []resource.TestStep{ +// { +// Config: `resource "test_resource" "one" { +// set_attribute = [ +// "value1", +// "value2" +// ] +// } +// `, +// ConfigStateChecks: resource.ConfigStateChecks{ +// statecheck.ExpectKnownValue( +// "test_resource.one", +// tfjsonpath.New("set_attribute"), +// knownvalue.SetExact([]knownvalue.Check{ +// knownvalue.StringExact("value2"), +// knownvalue.StringExact("value1"), +// }), +// ), +// }, +// }, +// }, +// }) +// } +// // [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue // [SetExact]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetExact // [SetPartial]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetPartial @@ -280,9 +447,53 @@ func TestCheckTypeSetElemAttr(name, attr, value string) TestCheckFunc { // there are multiple lists or sets in the attribute path. // // Deprecated: State checks have been superseded by ConfigStateChecks. -// Use the built-in statecheck.ExpectContains state check instead. +// Use the built-in statecheck.ExpectContains, or statecheck.ExpectMatchingValues +// state checks instead. // TestCheckTypeSetElemAttrPair function will be removed in the next major version. // +// The following is an example of using statecheck.ExpectContains to replicate +// the behaviour of TestCheckTypeSetElemAttrPair. +// +// package example_test +// +// import ( +// "testing" +// +// "github.com/hashicorp/terraform-plugin-testing/helper/resource" +// "github.com/hashicorp/terraform-plugin-testing/statecheck" +// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +// ) +// +// func TestExpectContains_CheckState_Found(t *testing.T) { +// t.Parallel() +// +// resource.Test(t, resource.TestCase{ +// // Provider definition omitted. +// Steps: []resource.TestStep{ +// { +// Config: `resource "test_resource" "one" { +// string_attribute = "value1" +// } +// +// resource "test_resource" "two" { +// set_attribute = [ +// test_resource.one.string_attribute, +// "value2" +// ] +// }`, +// ConfigStateChecks: resource.ConfigStateChecks{ +// statecheck.ExpectContains( +// "test_resource.two", +// tfjsonpath.New("set_attribute"), +// "test_resource.one", +// tfjsonpath.New("string_attribute"), +// ), +// }, +// }, +// }, +// }) +// } +// // [ExpectContains]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectContains // [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck // [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck diff --git a/statecheck/expect_contains.go b/statecheck/expect_contains.go index 237635dc8..c37870144 100644 --- a/statecheck/expect_contains.go +++ b/statecheck/expect_contains.go @@ -102,6 +102,48 @@ func (e expectContains) CheckState(ctx context.Context, req CheckStateRequest, r // ExpectContains returns a state check that asserts that the value of the second attribute is contained within the // value of the first attribute, allowing checking of whether a set contains a value identified by another attribute. +// +// The following is an example of using statecheck.ExpectContains. +// +// package example_test +// +// import ( +// "testing" +// +// "github.com/hashicorp/terraform-plugin-testing/helper/resource" +// "github.com/hashicorp/terraform-plugin-testing/statecheck" +// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +// ) +// +// func TestExpectContains_CheckState_Found(t *testing.T) { +// t.Parallel() +// +// resource.Test(t, resource.TestCase{ +// // Provider definition omitted. +// Steps: []resource.TestStep{ +// { +// Config: `resource "test_resource" "one" { +// string_attribute = "value1" +// } +// +// resource "test_resource" "two" { +// set_attribute = [ +// test_resource.one.string_attribute, +// "value2" +// ] +// }`, +// ConfigStateChecks: resource.ConfigStateChecks{ +// statecheck.ExpectContains( +// "test_resource.two", +// tfjsonpath.New("set_attribute"), +// "test_resource.one", +// tfjsonpath.New("string_attribute"), +// ), +// }, +// }, +// }, +// }) +// } func ExpectContains(resourceAddressOne string, attributePathOne tfjsonpath.Path, resourceAddressTwo string, attributePathTwo tfjsonpath.Path) StateCheck { return expectContains{ resourceAddressOne: resourceAddressOne, diff --git a/statecheck/expect_known_output_value.go b/statecheck/expect_known_output_value.go index 64c47f819..b025a212a 100644 --- a/statecheck/expect_known_output_value.go +++ b/statecheck/expect_known_output_value.go @@ -64,6 +64,114 @@ func (e expectKnownOutputValue) CheckState(ctx context.Context, req CheckStateRe // ExpectKnownOutputValue returns a state check that asserts that the specified value // has a known type, and value. +// +// The following is an example of using ExpectKnownOutputValue. +// +// package example_test +// +// import ( +// "testing" +// +// "github.com/hashicorp/terraform-plugin-testing/helper/resource" +// "github.com/hashicorp/terraform-plugin-testing/knownvalue" +// "github.com/hashicorp/terraform-plugin-testing/statecheck" +// ) +// +// func TestExpectKnownOutputValue_CheckState_Bool(t *testing.T) { +// t.Parallel() +// +// resource.Test(t, resource.TestCase{ +// // Provider definition omitted. +// Steps: []resource.TestStep{ +// { +// Config: `resource "test_resource" "one" { +// bool_attribute = true +// } +// +// output bool_output { +// value = test_resource.one.bool_attribute +// } +// `, +// ConfigStateChecks: resource.ConfigStateChecks{ +// statecheck.ExpectKnownOutputValue( +// "bool_output", +// knownvalue.BoolExact(true), +// ), +// }, +// }, +// }, +// }) +// } +// +// The following is an example of using ExpectKnownOutputValue in combination +// with a custom knownvalue.Check. +// +// package example_test +// +// import ( +// "fmt" +// "strings" +// "testing" +// +// "github.com/hashicorp/terraform-plugin-testing/helper/resource" +// "github.com/hashicorp/terraform-plugin-testing/knownvalue" +// "github.com/hashicorp/terraform-plugin-testing/statecheck" +// ) +// +// func TestExpectKnownOutputValue_CheckState_String_Custom(t *testing.T) { +// t.Parallel() +// +// resource.Test(t, resource.TestCase{ +// // Provider definition omitted. +// Steps: []resource.TestStep{ +// { +// Config: `resource "test_resource" "one" { +// string_attribute = "string" +// } +// +// output string_output { +// value = test_resource.one.string_attribute +// } +// `, +// ConfigStateChecks: resource.ConfigStateChecks{ +// statecheck.ExpectKnownOutputValue( +// "string_output", +// StringContains("str")), +// }, +// }, +// }, +// }) +// } +// +// var _ knownvalue.Check = stringContains{} +// +// type stringContains struct { +// value string +// } +// +// func (v stringContains) CheckValue(other any) error { +// otherVal, ok := other.(string) +// +// if !ok { +// return fmt.Errorf("expected string value for StringContains check, got: %T", other) +// } +// +// if !strings.Contains(otherVal, v.value) { +// return fmt.Errorf("expected string %q to contain %q for StringContains check", otherVal, v.value) +// } +// +// return nil +// } +// +// func (v stringContains) String() string { +// return v.value +// } +// +// func StringContains(value string) stringContains { +// return stringContains{ +// value: value, +// } +// } func ExpectKnownOutputValue(outputAddress string, knownValue knownvalue.Check) StateCheck { return expectKnownOutputValue{ outputAddress: outputAddress, diff --git a/statecheck/expect_known_output_value_at_path.go b/statecheck/expect_known_output_value_at_path.go index 9fb8cc4f1..e85c51f94 100644 --- a/statecheck/expect_known_output_value_at_path.go +++ b/statecheck/expect_known_output_value_at_path.go @@ -65,6 +65,118 @@ func (e expectKnownOutputValueAtPath) CheckState(ctx context.Context, req CheckS // ExpectKnownOutputValueAtPath returns a state check that asserts that the specified output at the given path // has a known type and value. +// +// The following is an example of using ExpectKnownOutputValueAtPath. +// +// package example_test +// +// import ( +// "testing" +// +// "github.com/hashicorp/terraform-plugin-testing/helper/resource" +// "github.com/hashicorp/terraform-plugin-testing/knownvalue" +// "github.com/hashicorp/terraform-plugin-testing/statecheck" +// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +// ) +// +// func TestExpectKnownOutputValueAtPath_CheckState_Bool(t *testing.T) { +// t.Parallel() +// +// resource.Test(t, resource.TestCase{ +// // Provider definition omitted. +// Steps: []resource.TestStep{ +// { +// Config: `resource "test_resource" "one" { +// bool_attribute = true +// } +// +// output test_resource_one_output { +// value = test_resource.one +// } +// `, +// ConfigStateChecks: resource.ConfigStateChecks{ +// statecheck.ExpectKnownOutputValueAtPath( +// "test_resource_one_output", +// tfjsonpath.New("bool_attribute"), +// knownvalue.BoolExact(true), +// ), +// }, +// }, +// }, +// }) +// } +// +// The following is an example of using ExpectKnownOutputValueAtPath in combination +// with a custom knownvalue.Check. +// +// package example_test +// +// import ( +// "fmt" +// "strings" +// "testing" +// +// "github.com/hashicorp/terraform-plugin-testing/helper/resource" +// "github.com/hashicorp/terraform-plugin-testing/knownvalue" +// "github.com/hashicorp/terraform-plugin-testing/statecheck" +// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +// ) +// +// func TestExpectKnownOutputValueAtPath_CheckState_String_Custom(t *testing.T) { +// t.Parallel() +// +// resource.Test(t, resource.TestCase{ +// // Provider definition omitted. +// Steps: []resource.TestStep{ +// { +// Config: `resource "test_resource" "one" { +// string_attribute = "string" +// } +// +// output test_resource_one_output { +// value = test_resource.one +// } +// `, +// ConfigStateChecks: resource.ConfigStateChecks{ +// statecheck.ExpectKnownOutputValueAtPath( +// "test_resource_one_output", +// tfjsonpath.New("string_attribute"), +// StringContains("str")), +// }, +// }, +// }, +// }) +// } +// +// var _ knownvalue.Check = stringContains{} +// +// type stringContains struct { +// value string +// } +// +// func (v stringContains) CheckValue(other any) error { +// otherVal, ok := other.(string) +// +// if !ok { +// return fmt.Errorf("expected string value for StringContains check, got: %T", other) +// } +// +// if !strings.Contains(otherVal, v.value) { +// return fmt.Errorf("expected string %q to contain %q for StringContains check", otherVal, v.value) +// } +// +// return nil +// } +// +// func (v stringContains) String() string { +// return v.value +// } +// +// func StringContains(value string) stringContains { +// return stringContains{ +// value: value, +// } +// } func ExpectKnownOutputValueAtPath(outputAddress string, outputPath tfjsonpath.Path, knownValue knownvalue.Check) StateCheck { return expectKnownOutputValueAtPath{ outputAddress: outputAddress, diff --git a/statecheck/expect_known_output_value_at_path_test.go b/statecheck/expect_known_output_value_at_path_test.go index 078daee04..8c369b6ef 100644 --- a/statecheck/expect_known_output_value_at_path_test.go +++ b/statecheck/expect_known_output_value_at_path_test.go @@ -1366,6 +1366,36 @@ func TestExpectKnownOutputValueAtPath_CheckState_String(t *testing.T) { }) } +func TestExpectKnownOutputValueAtPath_CheckState_String_Custom(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + string_attribute = "string" + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("string_attribute"), + StringContains("str")), + }, + }, + }, + }) +} + func TestExpectKnownOutputValueAtPath_CheckState_String_KnownValueWrongType(t *testing.T) { t.Parallel() diff --git a/statecheck/expect_known_output_value_test.go b/statecheck/expect_known_output_value_test.go index b3f5e2ccf..71cfea25c 100644 --- a/statecheck/expect_known_output_value_test.go +++ b/statecheck/expect_known_output_value_test.go @@ -1331,6 +1331,35 @@ func TestExpectKnownOutputValue_CheckState_String(t *testing.T) { }) } +func TestExpectKnownOutputValue_CheckState_String_Custom(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + string_attribute = "string" + } + + output string_output { + value = test_resource.one.string_attribute + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "string_output", + StringContains("str")), + }, + }, + }, + }) +} + func TestExpectKnownOutputValue_CheckState_String_KnownValueWrongType(t *testing.T) { t.Parallel() diff --git a/statecheck/expect_known_value.go b/statecheck/expect_known_value.go index 96662c32a..7441de88c 100644 --- a/statecheck/expect_known_value.go +++ b/statecheck/expect_known_value.go @@ -67,6 +67,110 @@ func (e expectKnownValue) CheckState(ctx context.Context, req CheckStateRequest, // ExpectKnownValue returns a state check that asserts that the specified attribute at the given resource // has a known type and value. +// +// The following is an example of using ExpectKnownValue. +// +// package example_test +// +// import ( +// "testing" +// +// "github.com/hashicorp/terraform-plugin-testing/helper/resource" +// "github.com/hashicorp/terraform-plugin-testing/knownvalue" +// "github.com/hashicorp/terraform-plugin-testing/statecheck" +// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +// ) +// +// func TestExpectKnownValue_CheckState_Bool(t *testing.T) { +// t.Parallel() +// +// resource.Test(t, resource.TestCase{ +// // Provider definition omitted. +// Steps: []resource.TestStep{ +// { +// Config: `resource "test_resource" "one" { +// bool_attribute = true +// } +// `, +// ConfigStateChecks: resource.ConfigStateChecks{ +// statecheck.ExpectKnownValue( +// "test_resource.one", +// tfjsonpath.New("bool_attribute"), +// knownvalue.BoolExact(true), +// ), +// }, +// }, +// }, +// }) +// } +// +// The following is an example of using ExpectKnownValue in combination +// with a custom knownvalue.Check. +// +// package example_test +// +// import ( +// "fmt" +// "strings" +// "testing" +// +// "github.com/hashicorp/terraform-plugin-testing/helper/resource" +// "github.com/hashicorp/terraform-plugin-testing/knownvalue" +// "github.com/hashicorp/terraform-plugin-testing/statecheck" +// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +// ) +// +// func TestExpectKnownValue_CheckState_String_Custom(t *testing.T) { +// t.Parallel() +// +// resource.Test(t, resource.TestCase{ +// // Provider definition omitted. +// Steps: []resource.TestStep{ +// { +// Config: `resource "test_resource" "one" { +// string_attribute = "string" +// } +// `, +// ConfigStateChecks: resource.ConfigStateChecks{ +// statecheck.ExpectKnownValue( +// "test_resource.one", +// tfjsonpath.New("string_attribute"), +// StringContains("tri")), +// }, +// }, +// }, +// }) +// } +// +// var _ knownvalue.Check = stringContains{} +// +// type stringContains struct { +// value string +// } +// +// func (v stringContains) CheckValue(other any) error { +// otherVal, ok := other.(string) +// +// if !ok { +// return fmt.Errorf("expected string value for StringContains check, got: %T", other) +// } +// +// if !strings.Contains(otherVal, v.value) { +// return fmt.Errorf("expected string %q to contain %q for StringContains check", otherVal, v.value) +// } +// +// return nil +// } +// +// func (v stringContains) String() string { +// return v.value +// } +// +// func StringContains(value string) stringContains { +// return stringContains{ +// value: value, +// } +// } func ExpectKnownValue(resourceAddress string, attributePath tfjsonpath.Path, knownValue knownvalue.Check) StateCheck { return expectKnownValue{ resourceAddress: resourceAddress, diff --git a/statecheck/expect_known_value_test.go b/statecheck/expect_known_value_test.go index a2241222f..30a3192d3 100644 --- a/statecheck/expect_known_value_test.go +++ b/statecheck/expect_known_value_test.go @@ -8,6 +8,7 @@ import ( "fmt" "math/big" "regexp" + "strings" "testing" "github.com/google/go-cmp/cmp" @@ -1165,6 +1166,45 @@ func TestExpectKnownValue_CheckState_SetNestedBlock(t *testing.T) { }) } +func TestExpectKnownValue_CheckState_SetNestedBlock_Custom(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + set_nested_block { + set_nested_block_attribute = "string" + } + set_nested_block { + set_nested_block_attribute = "girts" + } + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("set_nested_block"), + knownvalue.SetExact([]knownvalue.Check{ + knownvalue.MapExact(map[string]knownvalue.Check{ + "set_nested_block_attribute": StringContains("str"), + }), + knownvalue.MapExact(map[string]knownvalue.Check{ + "set_nested_block_attribute": StringContains("rts"), + }), + }), + ), + }, + }, + }, + }) +} + func TestExpectKnownValue_CheckState_SetNestedBlockPartial(t *testing.T) { t.Parallel() @@ -1259,6 +1299,62 @@ func TestExpectKnownValue_CheckState_String(t *testing.T) { }) } +func TestExpectKnownValue_CheckState_String_Custom(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + string_attribute = "string" + } + `, + ConfigStateChecks: r.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("string_attribute"), + StringContains("tri")), + }, + }, + }, + }) +} + +var _ knownvalue.Check = stringContains{} + +type stringContains struct { + value string +} + +func (v stringContains) CheckValue(other any) error { + otherVal, ok := other.(string) + + if !ok { + return fmt.Errorf("expected string value for StringContains check, got: %T", other) + } + + if !strings.Contains(otherVal, v.value) { + return fmt.Errorf("expected string %q to contain %q for StringContains check", otherVal, v.value) + } + + return nil +} + +func (v stringContains) String() string { + return v.value +} + +func StringContains(value string) stringContains { + return stringContains{ + value: value, + } +} + func TestExpectKnownValue_CheckState_String_KnownValueWrongType(t *testing.T) { t.Parallel() diff --git a/statecheck/expect_matching_values.go b/statecheck/expect_matching_values.go index fdcdc6749..7609ae01a 100644 --- a/statecheck/expect_matching_values.go +++ b/statecheck/expect_matching_values.go @@ -92,6 +92,45 @@ func (e expectMatchingValues) CheckState(ctx context.Context, req CheckStateRequ // ExpectMatchingValues returns a state check that asserts that the specified attributes at the given resources // have a matching value. +// +// The following is an example of using ExpectMatchingValues. +// +// package example_test +// +// import ( +// "testing" +// +// "github.com/hashicorp/terraform-plugin-testing/helper/resource" +// "github.com/hashicorp/terraform-plugin-testing/statecheck" +// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +// ) +// +// func TestExpectMatchingValues_CheckState_AttributeValuesEqual_Bool(t *testing.T) { +// t.Parallel() +// +// resource.Test(t, resource.TestCase{ +// // Provider definition omitted. +// Steps: []resource.TestStep{ +// { +// Config: `resource "test_resource" "one" { +// bool_attribute = true +// } +// +// resource "test_resource" "two" { +// bool_attribute = true +// }`, +// ConfigStateChecks: resource.ConfigStateChecks{ +// statecheck.ExpectMatchingValues( +// "test_resource.one", +// tfjsonpath.New("bool_attribute"), +// "test_resource.two", +// tfjsonpath.New("bool_attribute"), +// ), +// }, +// }, +// }, +// }) +// } func ExpectMatchingValues(resourceAddressOne string, attributePathOne tfjsonpath.Path, resourceAddressTwo string, attributePathTwo tfjsonpath.Path) StateCheck { return expectMatchingValues{ resourceAddressOne: resourceAddressOne, diff --git a/statecheck/expect_no_value_exists.go b/statecheck/expect_no_value_exists.go index b223e5ba8..feecc93ab 100644 --- a/statecheck/expect_no_value_exists.go +++ b/statecheck/expect_no_value_exists.go @@ -60,6 +60,40 @@ func (e expectNoValueExists) CheckState(ctx context.Context, req CheckStateReque // ExpectNoValueExists returns a state check that asserts that the specified attribute at the given resource // does not exist. +// +// The following is an example of using ExpectNoValueExists. +// +// package example_test +// +// import ( +// "testing" +// +// "github.com/hashicorp/terraform-plugin-testing/helper/resource" +// "github.com/hashicorp/terraform-plugin-testing/statecheck" +// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +// ) +// +// func TestExpectNoValueExists_CheckState_AttributeNotFound(t *testing.T) { +// t.Parallel() +// +// resource.Test(t, resource.TestCase{ +// // Provider definition omitted. +// Steps: []resource.TestStep{ +// { +// Config: `resource "test_resource" "one" { +// bool_attribute = true +// } +// `, +// ConfigStateChecks: resource.ConfigStateChecks{ +// statecheck.ExpectNoValueExists( +// "test_resource.one", +// tfjsonpath.New("does_not_exist"), +// ), +// }, +// }, +// }, +// }) +// } func ExpectNoValueExists(resourceAddress string, attributePath tfjsonpath.Path) StateCheck { return expectNoValueExists{ resourceAddress: resourceAddress, diff --git a/statecheck/expect_value_exists.go b/statecheck/expect_value_exists.go index 198e55c30..1043238bc 100644 --- a/statecheck/expect_value_exists.go +++ b/statecheck/expect_value_exists.go @@ -59,8 +59,42 @@ func (e expectValueExists) CheckState(ctx context.Context, req CheckStateRequest } } -// ExpectValueExists returns a state check that asserts that the specified attribute at the given resource -// does not exist. +// ExpectValueExists returns a state check that asserts that the specified +// attribute at the given resource exists. +// +// The following is an example of using ExpectValueExists. +// +// package example_test +// +// import ( +// "testing" +// +// "github.com/hashicorp/terraform-plugin-testing/helper/resource" +// "github.com/hashicorp/terraform-plugin-testing/statecheck" +// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +// ) +// +// func TestExpectValueExists_CheckState_AttributeFound(t *testing.T) { +// t.Parallel() +// +// resource.Test(t, resource.TestCase{ +// // Provider definition omitted. +// Steps: []resource.TestStep{ +// { +// Config: `resource "test_resource" "one" { +// bool_attribute = true +// } +// `, +// ConfigStateChecks: resource.ConfigStateChecks{ +// statecheck.ExpectValueExists( +// "test_resource.one", +// tfjsonpath.New("bool_attribute"), +// ), +// }, +// }, +// }, +// }) +// } func ExpectValueExists(resourceAddress string, attributePath tfjsonpath.Path) StateCheck { return expectValueExists{ resourceAddress: resourceAddress, diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/custom.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/custom.mdx index f5ce1d1de..5523b1a98 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/custom.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/custom.mdx @@ -15,35 +15,35 @@ type Check interface { } ``` -For example, a `StringValueContains` implementation could look as follows: +For example, a `StringContains` implementation could look as follows: ```go -var _ Check = StringValueContains{} +var _ knownvalue.Check = stringContains{} -type StringValueContains struct { +type stringContains struct { value string } -func (v StringValueContains) CheckValue(other any) error { +func (v stringContains) CheckValue(other any) error { otherVal, ok := other.(string) if !ok { - return fmt.Errorf("expected string value for StringValueContains check, got: %T", other) + return fmt.Errorf("expected string value for StringContains check, got: %T", other) } - if !strings.Contains(v.value, otherVal) { - return fmt.Errorf("expected string %q to contain %q for StringValueContains check", otherVal, v.value) + if !strings.Contains(otherVal, v.value) { + return fmt.Errorf("expected string %q to contain %q for StringContains check", otherVal, v.value) } return nil } -func (v StringValueContains) String() string { +func (v stringContains) String() string { return v.value } -func StringValueMatch(value string) StringValue { - return StringValueContains{ +func StringContains(value string) stringContains { + return stringContains{ value: value, } } From 518c94cd4235a3b0049a491fdffe958145ffe7b6 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Mon, 22 Jan 2024 08:19:46 +0000 Subject: [PATCH 34/73] Adding return statements (#266) --- statecheck/expect_known_output_value.go | 4 ++++ statecheck/expect_known_output_value_at_path.go | 4 ++++ statecheck/expect_known_value.go | 8 ++++++++ statecheck/expect_sensitive_value.go | 8 ++++++++ 4 files changed, 24 insertions(+) diff --git a/statecheck/expect_known_output_value.go b/statecheck/expect_known_output_value.go index 64c47f819..951a36400 100644 --- a/statecheck/expect_known_output_value.go +++ b/statecheck/expect_known_output_value.go @@ -27,10 +27,14 @@ func (e expectKnownOutputValue) CheckState(ctx context.Context, req CheckStateRe if req.State == nil { resp.Error = fmt.Errorf("state is nil") + + return } if req.State.Values == nil { resp.Error = fmt.Errorf("state does not contain any state values") + + return } for address, oc := range req.State.Values.Outputs { diff --git a/statecheck/expect_known_output_value_at_path.go b/statecheck/expect_known_output_value_at_path.go index 9fb8cc4f1..1cdfcea79 100644 --- a/statecheck/expect_known_output_value_at_path.go +++ b/statecheck/expect_known_output_value_at_path.go @@ -28,10 +28,14 @@ func (e expectKnownOutputValueAtPath) CheckState(ctx context.Context, req CheckS if req.State == nil { resp.Error = fmt.Errorf("state is nil") + + return } if req.State.Values == nil { resp.Error = fmt.Errorf("state does not contain any state values") + + return } for address, oc := range req.State.Values.Outputs { diff --git a/statecheck/expect_known_value.go b/statecheck/expect_known_value.go index 96662c32a..86a741417 100644 --- a/statecheck/expect_known_value.go +++ b/statecheck/expect_known_value.go @@ -28,14 +28,20 @@ func (e expectKnownValue) CheckState(ctx context.Context, req CheckStateRequest, if req.State == nil { resp.Error = fmt.Errorf("state is nil") + + return } if req.State.Values == nil { resp.Error = fmt.Errorf("state does not contain any state values") + + return } if req.State.Values.RootModule == nil { resp.Error = fmt.Errorf("state does not contain a root module") + + return } for _, resourceChange := range req.State.Values.RootModule.Resources { @@ -62,6 +68,8 @@ func (e expectKnownValue) CheckState(ctx context.Context, req CheckStateRequest, if err := e.knownValue.CheckValue(result); err != nil { resp.Error = fmt.Errorf("error checking value for attribute at path: %s.%s, err: %s", e.resourceAddress, e.attributePath.String(), err) + + return } } diff --git a/statecheck/expect_sensitive_value.go b/statecheck/expect_sensitive_value.go index 447a2cb27..938238b25 100644 --- a/statecheck/expect_sensitive_value.go +++ b/statecheck/expect_sensitive_value.go @@ -26,14 +26,20 @@ func (e expectSensitiveValue) CheckState(ctx context.Context, req CheckStateRequ if req.State == nil { resp.Error = fmt.Errorf("state is nil") + + return } if req.State.Values == nil { resp.Error = fmt.Errorf("state does not contain any state values") + + return } if req.State.Values.RootModule == nil { resp.Error = fmt.Errorf("state does not contain a root module") + + return } for _, resourceChange := range req.State.Values.RootModule.Resources { @@ -71,11 +77,13 @@ func (e expectSensitiveValue) CheckState(ctx context.Context, req CheckStateRequ isSensitive, ok := result.(bool) if !ok { resp.Error = fmt.Errorf("invalid path: the path value cannot be asserted as bool") + return } if !isSensitive { resp.Error = fmt.Errorf("attribute at path is not sensitive") + return } } From 35ffc45fc5fab0339252775d4802b040ee5ed790 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Mon, 22 Jan 2024 08:29:04 +0000 Subject: [PATCH 35/73] Adding change log entry for deprecation of `ExpectNullOutputValue` and `ExpectNullOutputValueAtPath` plan checks (#266) --- .changes/unreleased/NOTES-20240122-082628.yaml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changes/unreleased/NOTES-20240122-082628.yaml diff --git a/.changes/unreleased/NOTES-20240122-082628.yaml b/.changes/unreleased/NOTES-20240122-082628.yaml new file mode 100644 index 000000000..f05712299 --- /dev/null +++ b/.changes/unreleased/NOTES-20240122-082628.yaml @@ -0,0 +1,7 @@ +kind: NOTES +body: 'plancheck: Deprecated `ExpectNullOutputValue` and `ExpectNullOutputValueAtPath`. + Use `ExpectKnownOutputValue` and `ExpectKnownOutputValueAtPath` with + `knownvalue.NullExact` instead' +time: 2024-01-22T08:26:28.053303Z +custom: + Issue: "275" From 31f8d5e9785d9256279740feb34c94eaca52c09c Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Mon, 22 Jan 2024 08:41:47 +0000 Subject: [PATCH 36/73] Modifying return value of nullExact.String() (#266) --- knownvalue/null.go | 4 ++-- knownvalue/null_test.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/knownvalue/null.go b/knownvalue/null.go index f10c5a3f5..eaad10bef 100644 --- a/knownvalue/null.go +++ b/knownvalue/null.go @@ -20,9 +20,9 @@ func (v nullExact) CheckValue(other any) error { return nil } -// String returns the string representation of nil. +// String returns the string representation of null. func (v nullExact) String() string { - return "nil" + return "null" } // NullExact returns a Check for asserting equality nil diff --git a/knownvalue/null_test.go b/knownvalue/null_test.go index 94682ed7b..ddd688df3 100644 --- a/knownvalue/null_test.go +++ b/knownvalue/null_test.go @@ -58,7 +58,7 @@ func TestNullValue_String(t *testing.T) { got := knownvalue.NullExact().String() - if diff := cmp.Diff(got, "nil"); diff != "" { + if diff := cmp.Diff(got, "null"); diff != "" { t.Errorf("unexpected difference: %s", diff) } } From 031df218fb910365aaa56f2b8d2967390f7d9f71 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Mon, 22 Jan 2024 09:09:08 +0000 Subject: [PATCH 37/73] Renaming variable (#266) --- statecheck/expect_known_value.go | 12 +++---- statecheck/expect_sensitive_value.go | 12 +++---- .../acceptance-tests/state-checks/custom.mdx | 31 +++++++++++-------- 3 files changed, 30 insertions(+), 25 deletions(-) diff --git a/statecheck/expect_known_value.go b/statecheck/expect_known_value.go index 86a741417..aca58c4d2 100644 --- a/statecheck/expect_known_value.go +++ b/statecheck/expect_known_value.go @@ -24,7 +24,7 @@ type expectKnownValue struct { // CheckState implements the state check logic. func (e expectKnownValue) CheckState(ctx context.Context, req CheckStateRequest, resp *CheckStateResponse) { - var rc *tfjson.StateResource + var resource *tfjson.StateResource if req.State == nil { resp.Error = fmt.Errorf("state is nil") @@ -44,21 +44,21 @@ func (e expectKnownValue) CheckState(ctx context.Context, req CheckStateRequest, return } - for _, resourceChange := range req.State.Values.RootModule.Resources { - if e.resourceAddress == resourceChange.Address { - rc = resourceChange + for _, r := range req.State.Values.RootModule.Resources { + if e.resourceAddress == r.Address { + resource = r break } } - if rc == nil { + if resource == nil { resp.Error = fmt.Errorf("%s - Resource not found in state", e.resourceAddress) return } - result, err := tfjsonpath.Traverse(rc.AttributeValues, e.attributePath) + result, err := tfjsonpath.Traverse(resource.AttributeValues, e.attributePath) if err != nil { resp.Error = err diff --git a/statecheck/expect_sensitive_value.go b/statecheck/expect_sensitive_value.go index 938238b25..ea4671119 100644 --- a/statecheck/expect_sensitive_value.go +++ b/statecheck/expect_sensitive_value.go @@ -22,7 +22,7 @@ type expectSensitiveValue struct { // CheckState implements the state check logic. func (e expectSensitiveValue) CheckState(ctx context.Context, req CheckStateRequest, resp *CheckStateResponse) { - var rc *tfjson.StateResource + var resource *tfjson.StateResource if req.State == nil { resp.Error = fmt.Errorf("state is nil") @@ -42,15 +42,15 @@ func (e expectSensitiveValue) CheckState(ctx context.Context, req CheckStateRequ return } - for _, resourceChange := range req.State.Values.RootModule.Resources { - if e.resourceAddress == resourceChange.Address { - rc = resourceChange + for _, r := range req.State.Values.RootModule.Resources { + if e.resourceAddress == r.Address { + resource = r break } } - if rc == nil { + if resource == nil { resp.Error = fmt.Errorf("%s - Resource not found in state", e.resourceAddress) return @@ -58,7 +58,7 @@ func (e expectSensitiveValue) CheckState(ctx context.Context, req CheckStateRequ var data map[string]any - err := json.Unmarshal(rc.SensitiveValues, &data) + err := json.Unmarshal(resource.SensitiveValues, &data) if err != nil { resp.Error = fmt.Errorf("could not unmarshal SensitiveValues: %s", err) diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx index 817be30fb..a71e3d765 100644 --- a/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx @@ -19,10 +19,14 @@ import ( "context" "fmt" + tfjson "github.com/hashicorp/terraform-json" + + "github.com/hashicorp/terraform-plugin-testing/knownvalue" "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" ) -var _ StateCheck = expectKnownValue{} +var _ statecheck.StateCheck = expectKnownValue{} type expectKnownValue struct { resourceAddress string @@ -30,8 +34,8 @@ type expectKnownValue struct { knownValue knownvalue.Check } -func (e expectKnownValue) CheckState(ctx context.Context, req CheckStateRequest, resp *CheckStateResponse) { - var rc *tfjson.StateResource +func (e expectKnownValue) CheckState(ctx context.Context, req statecheck.CheckStateRequest, resp *statecheck.CheckStateResponse) { + var resource *tfjson.StateResource if req.State == nil { resp.Error = fmt.Errorf("state is nil") @@ -45,21 +49,21 @@ func (e expectKnownValue) CheckState(ctx context.Context, req CheckStateRequest, resp.Error = fmt.Errorf("state does not contain a root module") } - for _, resourceChange := range req.State.Values.RootModule.Resources { - if e.resourceAddress == resourceChange.Address { - rc = resourceChange + for _, r := range req.State.Values.RootModule.Resources { + if e.resourceAddress == r.Address { + resource = r break } } - if rc == nil { + if resource == nil { resp.Error = fmt.Errorf("%s - Resource not found in state", e.resourceAddress) return } - result, err := tfjsonpath.Traverse(rc.AttributeValues, e.attributePath) + result, err := tfjsonpath.Traverse(resource.AttributeValues, e.attributePath) if err != nil { resp.Error = err @@ -72,7 +76,7 @@ func (e expectKnownValue) CheckState(ctx context.Context, req CheckStateRequest, } } -func ExpectKnownValue(resourceAddress string, attributePath tfjsonpath.Path, knownValue knownvalue.Check) StateCheck { +func ExpectKnownValue(resourceAddress string, attributePath tfjsonpath.Path, knownValue knownvalue.Check) statecheck.StateCheck { return expectKnownValue{ resourceAddress: resourceAddress, attributePath: attributePath, @@ -82,13 +86,14 @@ func ExpectKnownValue(resourceAddress string, attributePath tfjsonpath.Path, kno ``` And example usage: + ```go package example_test import ( "testing" - r "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/knownvalue" "github.com/hashicorp/terraform-plugin-testing/statecheck" "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" @@ -97,15 +102,15 @@ import ( func TestExpectKnownValue_CheckState_Bool(t *testing.T) { t.Parallel() - r.Test(t, r.TestCase{ + resource.Test(t, resource.TestCase{ // Provider definition omitted. - Steps: []r.TestStep{ + Steps: []resource.TestStep{ { Config: `resource "test_resource" "one" { bool_attribute = true } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: resource.ConfigStateChecks{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), From 6df33b96fb229019fdf3ecf9d7698893c4bd215f Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Mon, 22 Jan 2024 09:23:04 +0000 Subject: [PATCH 38/73] Adding comment for Terraform v1.4.6 (#266) --- tfversion/versions.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tfversion/versions.go b/tfversion/versions.go index f405bd766..690734892 100644 --- a/tfversion/versions.go +++ b/tfversion/versions.go @@ -28,8 +28,10 @@ var ( Version1_2_0 *version.Version = version.Must(version.NewVersion("1.2.0")) Version1_3_0 *version.Version = version.Must(version.NewVersion("1.3.0")) Version1_4_0 *version.Version = version.Must(version.NewVersion("1.4.0")) - Version1_4_6 *version.Version = version.Must(version.NewVersion("1.4.6")) - Version1_5_0 *version.Version = version.Must(version.NewVersion("1.5.0")) - Version1_6_0 *version.Version = version.Must(version.NewVersion("1.6.0")) - Version1_7_0 *version.Version = version.Must(version.NewVersion("1.7.0")) + // Version1_4_6 fixed inclusion of sensitive values in `terraform show -json` output. + // Reference: https://github.com/hashicorp/terraform/releases/tag/v1.4.6 + Version1_4_6 *version.Version = version.Must(version.NewVersion("1.4.6")) + Version1_5_0 *version.Version = version.Must(version.NewVersion("1.5.0")) + Version1_6_0 *version.Version = version.Must(version.NewVersion("1.6.0")) + Version1_7_0 *version.Version = version.Must(version.NewVersion("1.7.0")) ) From 15330e354495c59db4016f3cf9e34430d09b77a8 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Mon, 22 Jan 2024 10:45:29 +0000 Subject: [PATCH 39/73] Adding further tests for null exact known value type check (#266) --- knownvalue/null.go | 2 +- .../expect_known_output_value_at_path_test.go | 40 +++++++++++++ plancheck/expect_known_output_value_test.go | 56 +++++++++++++++++++ plancheck/expect_known_value_test.go | 40 +++++++++++++ .../expect_known_output_value_at_path_test.go | 40 +++++++++++++ statecheck/expect_known_value_test.go | 40 +++++++++++++ 6 files changed, 217 insertions(+), 1 deletion(-) diff --git a/knownvalue/null.go b/knownvalue/null.go index eaad10bef..6b25d1bf4 100644 --- a/knownvalue/null.go +++ b/knownvalue/null.go @@ -11,7 +11,7 @@ var _ Check = nullExact{} type nullExact struct{} -// CheckValue determines whether the passed value is of nil. +// CheckValue determines whether the passed value is nil. func (v nullExact) CheckValue(other any) error { if other != nil { return fmt.Errorf("expected value nil for NullExact check, got: %T", other) diff --git a/plancheck/expect_known_output_value_at_path_test.go b/plancheck/expect_known_output_value_at_path_test.go index 82505f87c..cbcb256bb 100644 --- a/plancheck/expect_known_output_value_at_path_test.go +++ b/plancheck/expect_known_output_value_at_path_test.go @@ -93,6 +93,46 @@ func TestExpectKnownOutputValueAtPath_CheckPlan_AttributeValueNull(t *testing.T) tfjsonpath.New("bool_attribute"), knownvalue.NullExact(), ), + plancheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("float_attribute"), + knownvalue.NullExact(), + ), + plancheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("int_attribute"), + knownvalue.NullExact(), + ), + plancheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("list_attribute"), + knownvalue.NullExact(), + ), + plancheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("list_nested_block"), + knownvalue.ListExact([]knownvalue.Check{}), + ), + plancheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("map_attribute"), + knownvalue.NullExact(), + ), + plancheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("set_attribute"), + knownvalue.NullExact(), + ), + plancheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("set_nested_block"), + knownvalue.SetExact([]knownvalue.Check{}), + ), + plancheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("string_attribute"), + knownvalue.NullExact(), + ), }, }, }, diff --git a/plancheck/expect_known_output_value_test.go b/plancheck/expect_known_output_value_test.go index 626ecaab2..0b5315650 100644 --- a/plancheck/expect_known_output_value_test.go +++ b/plancheck/expect_known_output_value_test.go @@ -67,6 +67,30 @@ func TestExpectKnownOutputValue_CheckPlan_AttributeValueNull(t *testing.T) { output bool_output { value = test_resource.one.bool_attribute } + output float_output { + value = test_resource.one.float_attribute + } + output int_output { + value = test_resource.one.int_attribute + } + output list_output { + value = test_resource.one.list_attribute + } + output list_nested_block_output { + value = test_resource.one.list_nested_block + } + output map_output { + value = test_resource.one.map_attribute + } + output set_output { + value = test_resource.one.set_attribute + } + output set_nested_block_output { + value = test_resource.one.set_nested_block + } + output string_output { + value = test_resource.one.string_attribute + } `, ConfigPlanChecks: r.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ @@ -74,6 +98,38 @@ func TestExpectKnownOutputValue_CheckPlan_AttributeValueNull(t *testing.T) { "bool_output", knownvalue.NullExact(), ), + plancheck.ExpectKnownOutputValue( + "float_output", + knownvalue.NullExact(), + ), + plancheck.ExpectKnownOutputValue( + "int_output", + knownvalue.NullExact(), + ), + plancheck.ExpectKnownOutputValue( + "list_output", + knownvalue.NullExact(), + ), + plancheck.ExpectKnownOutputValue( + "list_nested_block_output", + knownvalue.ListExact([]knownvalue.Check{}), + ), + plancheck.ExpectKnownOutputValue( + "map_output", + knownvalue.NullExact(), + ), + plancheck.ExpectKnownOutputValue( + "set_output", + knownvalue.NullExact(), + ), + plancheck.ExpectKnownOutputValue( + "set_nested_block_output", + knownvalue.SetExact([]knownvalue.Check{}), + ), + plancheck.ExpectKnownOutputValue( + "string_output", + knownvalue.NullExact(), + ), }, }, }, diff --git a/plancheck/expect_known_value_test.go b/plancheck/expect_known_value_test.go index af1618076..c331af94e 100644 --- a/plancheck/expect_known_value_test.go +++ b/plancheck/expect_known_value_test.go @@ -69,6 +69,46 @@ func TestExpectKnownValue_CheckPlan_AttributeValueNull(t *testing.T) { tfjsonpath.New("bool_attribute"), knownvalue.NullExact(), ), + plancheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("float_attribute"), + knownvalue.NullExact(), + ), + plancheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("int_attribute"), + knownvalue.NullExact(), + ), + plancheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("list_attribute"), + knownvalue.NullExact(), + ), + plancheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("list_nested_block"), + knownvalue.ListExact([]knownvalue.Check{}), + ), + plancheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("map_attribute"), + knownvalue.NullExact(), + ), + plancheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("set_attribute"), + knownvalue.NullExact(), + ), + plancheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("set_nested_block"), + knownvalue.SetExact([]knownvalue.Check{}), + ), + plancheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("string_attribute"), + knownvalue.NullExact(), + ), }, }, }, diff --git a/statecheck/expect_known_output_value_at_path_test.go b/statecheck/expect_known_output_value_at_path_test.go index 078daee04..918b53874 100644 --- a/statecheck/expect_known_output_value_at_path_test.go +++ b/statecheck/expect_known_output_value_at_path_test.go @@ -75,6 +75,46 @@ func TestExpectKnownOutputValueAtPath_CheckState_AttributeValueNull(t *testing.T tfjsonpath.New("bool_attribute"), knownvalue.NullExact(), ), + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("float_attribute"), + knownvalue.NullExact(), + ), + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("int_attribute"), + knownvalue.NullExact(), + ), + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("list_attribute"), + knownvalue.NullExact(), + ), + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("list_nested_block"), + knownvalue.ListExact([]knownvalue.Check{}), + ), + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("map_attribute"), + knownvalue.NullExact(), + ), + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("set_attribute"), + knownvalue.NullExact(), + ), + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("set_nested_block"), + knownvalue.SetExact([]knownvalue.Check{}), + ), + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("string_attribute"), + knownvalue.NullExact(), + ), }, }, }, diff --git a/statecheck/expect_known_value_test.go b/statecheck/expect_known_value_test.go index 9625ec089..3be302744 100644 --- a/statecheck/expect_known_value_test.go +++ b/statecheck/expect_known_value_test.go @@ -67,6 +67,46 @@ func TestExpectKnownValue_CheckState_AttributeValueNull(t *testing.T) { tfjsonpath.New("bool_attribute"), knownvalue.NullExact(), ), + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("float_attribute"), + knownvalue.NullExact(), + ), + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("int_attribute"), + knownvalue.NullExact(), + ), + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("list_attribute"), + knownvalue.NullExact(), + ), + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("list_nested_block"), + knownvalue.ListExact([]knownvalue.Check{}), + ), + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("map_attribute"), + knownvalue.NullExact(), + ), + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("set_attribute"), + knownvalue.NullExact(), + ), + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("set_nested_block"), + knownvalue.ListExact([]knownvalue.Check{}), + ), + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("string_attribute"), + knownvalue.NullExact(), + ), }, }, }, From a88a10dfb7c6ed1c1d6d68ca4edb3486052565f3 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Mon, 22 Jan 2024 11:10:21 +0000 Subject: [PATCH 40/73] Linting (#266) --- tfversion/versions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tfversion/versions.go b/tfversion/versions.go index bc4b87158..21f0727a9 100644 --- a/tfversion/versions.go +++ b/tfversion/versions.go @@ -34,5 +34,5 @@ var ( Version1_5_0 *version.Version = version.Must(version.NewVersion("1.5.0")) Version1_6_0 *version.Version = version.Must(version.NewVersion("1.6.0")) Version1_7_0 *version.Version = version.Must(version.NewVersion("1.7.0")) - Version1_8_0 *version.Version = version.Must(version.NewVersion("1.8.0")) + Version1_8_0 *version.Version = version.Must(version.NewVersion("1.8.0")) ) From 404e1e3fe5313dc4aa13fe0643b71a282044ced9 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Mon, 22 Jan 2024 12:07:44 +0000 Subject: [PATCH 41/73] Moving code examples to Go doc example files --- helper/example_test/example.go | 31 +++++ statecheck/expect_contains.go | 42 ------- statecheck/expect_contains_example_test.go | 43 +++++++ statecheck/expect_known_output_value.go | 108 ----------------- .../expect_known_output_value_at_path.go | 112 ------------------ ...known_output_value_at_path_example_test.go | 41 +++++++ .../expect_known_output_value_example_test.go | 39 ++++++ statecheck/expect_known_value.go | 104 ---------------- statecheck/expect_known_value_example_test.go | 37 ++++++ statecheck/expect_matching_values.go | 39 ------ .../expect_matching_values_example_test.go | 40 +++++++ statecheck/expect_no_value_exists.go | 34 ------ .../expect_no_value_exists_example_test.go | 35 ++++++ statecheck/expect_value_exists.go | 34 ------ .../expect_value_exists_example_test.go | 35 ++++++ 15 files changed, 301 insertions(+), 473 deletions(-) create mode 100644 helper/example_test/example.go create mode 100644 statecheck/expect_contains_example_test.go create mode 100644 statecheck/expect_known_output_value_at_path_example_test.go create mode 100644 statecheck/expect_known_output_value_example_test.go create mode 100644 statecheck/expect_known_value_example_test.go create mode 100644 statecheck/expect_matching_values_example_test.go create mode 100644 statecheck/expect_no_value_exists_example_test.go create mode 100644 statecheck/expect_value_exists_example_test.go diff --git a/helper/example_test/example.go b/helper/example_test/example.go new file mode 100644 index 000000000..968726e38 --- /dev/null +++ b/helper/example_test/example.go @@ -0,0 +1,31 @@ +package example_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + +func ExampleExpectValueExists(t *testing.T) { + t.Parallel() + + resource.Test(t, resource.TestCase{ + // Provider definition omitted. + Steps: []resource.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + `, + ConfigStateChecks: resource.ConfigStateChecks{ + statecheck.ExpectValueExists( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + ), + }, + }, + }, + }) +} diff --git a/statecheck/expect_contains.go b/statecheck/expect_contains.go index c37870144..237635dc8 100644 --- a/statecheck/expect_contains.go +++ b/statecheck/expect_contains.go @@ -102,48 +102,6 @@ func (e expectContains) CheckState(ctx context.Context, req CheckStateRequest, r // ExpectContains returns a state check that asserts that the value of the second attribute is contained within the // value of the first attribute, allowing checking of whether a set contains a value identified by another attribute. -// -// The following is an example of using statecheck.ExpectContains. -// -// package example_test -// -// import ( -// "testing" -// -// "github.com/hashicorp/terraform-plugin-testing/helper/resource" -// "github.com/hashicorp/terraform-plugin-testing/statecheck" -// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -// ) -// -// func TestExpectContains_CheckState_Found(t *testing.T) { -// t.Parallel() -// -// resource.Test(t, resource.TestCase{ -// // Provider definition omitted. -// Steps: []resource.TestStep{ -// { -// Config: `resource "test_resource" "one" { -// string_attribute = "value1" -// } -// -// resource "test_resource" "two" { -// set_attribute = [ -// test_resource.one.string_attribute, -// "value2" -// ] -// }`, -// ConfigStateChecks: resource.ConfigStateChecks{ -// statecheck.ExpectContains( -// "test_resource.two", -// tfjsonpath.New("set_attribute"), -// "test_resource.one", -// tfjsonpath.New("string_attribute"), -// ), -// }, -// }, -// }, -// }) -// } func ExpectContains(resourceAddressOne string, attributePathOne tfjsonpath.Path, resourceAddressTwo string, attributePathTwo tfjsonpath.Path) StateCheck { return expectContains{ resourceAddressOne: resourceAddressOne, diff --git a/statecheck/expect_contains_example_test.go b/statecheck/expect_contains_example_test.go new file mode 100644 index 000000000..3f4306226 --- /dev/null +++ b/statecheck/expect_contains_example_test.go @@ -0,0 +1,43 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package statecheck_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + +func ExampleExpectContains() { + t := &testing.T{} + t.Parallel() + + resource.Test(t, resource.TestCase{ + // Provider definition omitted. + Steps: []resource.TestStep{ + { + Config: `resource "test_resource" "one" { + string_attribute = "value1" + } + + resource "test_resource" "two" { + set_attribute = [ + test_resource.one.string_attribute, + "value2" + ] + }`, + ConfigStateChecks: resource.ConfigStateChecks{ + statecheck.ExpectContains( + "test_resource.two", + tfjsonpath.New("set_attribute"), + "test_resource.one", + tfjsonpath.New("string_attribute"), + ), + }, + }, + }, + }) +} diff --git a/statecheck/expect_known_output_value.go b/statecheck/expect_known_output_value.go index 65c3d7ef6..951a36400 100644 --- a/statecheck/expect_known_output_value.go +++ b/statecheck/expect_known_output_value.go @@ -68,114 +68,6 @@ func (e expectKnownOutputValue) CheckState(ctx context.Context, req CheckStateRe // ExpectKnownOutputValue returns a state check that asserts that the specified value // has a known type, and value. -// -// The following is an example of using ExpectKnownOutputValue. -// -// package example_test -// -// import ( -// "testing" -// -// "github.com/hashicorp/terraform-plugin-testing/helper/resource" -// "github.com/hashicorp/terraform-plugin-testing/knownvalue" -// "github.com/hashicorp/terraform-plugin-testing/statecheck" -// ) -// -// func TestExpectKnownOutputValue_CheckState_Bool(t *testing.T) { -// t.Parallel() -// -// resource.Test(t, resource.TestCase{ -// // Provider definition omitted. -// Steps: []resource.TestStep{ -// { -// Config: `resource "test_resource" "one" { -// bool_attribute = true -// } -// -// output bool_output { -// value = test_resource.one.bool_attribute -// } -// `, -// ConfigStateChecks: resource.ConfigStateChecks{ -// statecheck.ExpectKnownOutputValue( -// "bool_output", -// knownvalue.BoolExact(true), -// ), -// }, -// }, -// }, -// }) -// } -// -// The following is an example of using ExpectKnownOutputValue in combination -// with a custom knownvalue.Check. -// -// package example_test -// -// import ( -// "fmt" -// "strings" -// "testing" -// -// "github.com/hashicorp/terraform-plugin-testing/helper/resource" -// "github.com/hashicorp/terraform-plugin-testing/knownvalue" -// "github.com/hashicorp/terraform-plugin-testing/statecheck" -// ) -// -// func TestExpectKnownOutputValue_CheckState_String_Custom(t *testing.T) { -// t.Parallel() -// -// resource.Test(t, resource.TestCase{ -// // Provider definition omitted. -// Steps: []resource.TestStep{ -// { -// Config: `resource "test_resource" "one" { -// string_attribute = "string" -// } -// -// output string_output { -// value = test_resource.one.string_attribute -// } -// `, -// ConfigStateChecks: resource.ConfigStateChecks{ -// statecheck.ExpectKnownOutputValue( -// "string_output", -// StringContains("str")), -// }, -// }, -// }, -// }) -// } -// -// var _ knownvalue.Check = stringContains{} -// -// type stringContains struct { -// value string -// } -// -// func (v stringContains) CheckValue(other any) error { -// otherVal, ok := other.(string) -// -// if !ok { -// return fmt.Errorf("expected string value for StringContains check, got: %T", other) -// } -// -// if !strings.Contains(otherVal, v.value) { -// return fmt.Errorf("expected string %q to contain %q for StringContains check", otherVal, v.value) -// } -// -// return nil -// } -// -// func (v stringContains) String() string { -// return v.value -// } -// -// func StringContains(value string) stringContains { -// return stringContains{ -// value: value, -// } -// } func ExpectKnownOutputValue(outputAddress string, knownValue knownvalue.Check) StateCheck { return expectKnownOutputValue{ outputAddress: outputAddress, diff --git a/statecheck/expect_known_output_value_at_path.go b/statecheck/expect_known_output_value_at_path.go index 8d4faecfd..1cdfcea79 100644 --- a/statecheck/expect_known_output_value_at_path.go +++ b/statecheck/expect_known_output_value_at_path.go @@ -69,118 +69,6 @@ func (e expectKnownOutputValueAtPath) CheckState(ctx context.Context, req CheckS // ExpectKnownOutputValueAtPath returns a state check that asserts that the specified output at the given path // has a known type and value. -// -// The following is an example of using ExpectKnownOutputValueAtPath. -// -// package example_test -// -// import ( -// "testing" -// -// "github.com/hashicorp/terraform-plugin-testing/helper/resource" -// "github.com/hashicorp/terraform-plugin-testing/knownvalue" -// "github.com/hashicorp/terraform-plugin-testing/statecheck" -// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -// ) -// -// func TestExpectKnownOutputValueAtPath_CheckState_Bool(t *testing.T) { -// t.Parallel() -// -// resource.Test(t, resource.TestCase{ -// // Provider definition omitted. -// Steps: []resource.TestStep{ -// { -// Config: `resource "test_resource" "one" { -// bool_attribute = true -// } -// -// output test_resource_one_output { -// value = test_resource.one -// } -// `, -// ConfigStateChecks: resource.ConfigStateChecks{ -// statecheck.ExpectKnownOutputValueAtPath( -// "test_resource_one_output", -// tfjsonpath.New("bool_attribute"), -// knownvalue.BoolExact(true), -// ), -// }, -// }, -// }, -// }) -// } -// -// The following is an example of using ExpectKnownOutputValueAtPath in combination -// with a custom knownvalue.Check. -// -// package example_test -// -// import ( -// "fmt" -// "strings" -// "testing" -// -// "github.com/hashicorp/terraform-plugin-testing/helper/resource" -// "github.com/hashicorp/terraform-plugin-testing/knownvalue" -// "github.com/hashicorp/terraform-plugin-testing/statecheck" -// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -// ) -// -// func TestExpectKnownOutputValueAtPath_CheckState_String_Custom(t *testing.T) { -// t.Parallel() -// -// resource.Test(t, resource.TestCase{ -// // Provider definition omitted. -// Steps: []resource.TestStep{ -// { -// Config: `resource "test_resource" "one" { -// string_attribute = "string" -// } -// -// output test_resource_one_output { -// value = test_resource.one -// } -// `, -// ConfigStateChecks: resource.ConfigStateChecks{ -// statecheck.ExpectKnownOutputValueAtPath( -// "test_resource_one_output", -// tfjsonpath.New("string_attribute"), -// StringContains("str")), -// }, -// }, -// }, -// }) -// } -// -// var _ knownvalue.Check = stringContains{} -// -// type stringContains struct { -// value string -// } -// -// func (v stringContains) CheckValue(other any) error { -// otherVal, ok := other.(string) -// -// if !ok { -// return fmt.Errorf("expected string value for StringContains check, got: %T", other) -// } -// -// if !strings.Contains(otherVal, v.value) { -// return fmt.Errorf("expected string %q to contain %q for StringContains check", otherVal, v.value) -// } -// -// return nil -// } -// -// func (v stringContains) String() string { -// return v.value -// } -// -// func StringContains(value string) stringContains { -// return stringContains{ -// value: value, -// } -// } func ExpectKnownOutputValueAtPath(outputAddress string, outputPath tfjsonpath.Path, knownValue knownvalue.Check) StateCheck { return expectKnownOutputValueAtPath{ outputAddress: outputAddress, diff --git a/statecheck/expect_known_output_value_at_path_example_test.go b/statecheck/expect_known_output_value_at_path_example_test.go new file mode 100644 index 000000000..5dc5944fa --- /dev/null +++ b/statecheck/expect_known_output_value_at_path_example_test.go @@ -0,0 +1,41 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package statecheck_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + +func ExampleExpectKnownOutputValueAtPath() { + t := &testing.T{} + t.Parallel() + + resource.Test(t, resource.TestCase{ + // Provider definition omitted. + Steps: []resource.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: resource.ConfigStateChecks{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("bool_attribute"), + knownvalue.BoolExact(true), + ), + }, + }, + }, + }) +} diff --git a/statecheck/expect_known_output_value_example_test.go b/statecheck/expect_known_output_value_example_test.go new file mode 100644 index 000000000..6335f856e --- /dev/null +++ b/statecheck/expect_known_output_value_example_test.go @@ -0,0 +1,39 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package statecheck_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/statecheck" +) + +func ExampleExpectKnownOutputValue() { + t := &testing.T{} + t.Parallel() + + resource.Test(t, resource.TestCase{ + // Provider definition omitted. + Steps: []resource.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + + output bool_output { + value = test_resource.one.bool_attribute + } + `, + ConfigStateChecks: resource.ConfigStateChecks{ + statecheck.ExpectKnownOutputValue( + "bool_output", + knownvalue.BoolExact(true), + ), + }, + }, + }, + }) +} diff --git a/statecheck/expect_known_value.go b/statecheck/expect_known_value.go index 95ac2ada2..aca58c4d2 100644 --- a/statecheck/expect_known_value.go +++ b/statecheck/expect_known_value.go @@ -75,110 +75,6 @@ func (e expectKnownValue) CheckState(ctx context.Context, req CheckStateRequest, // ExpectKnownValue returns a state check that asserts that the specified attribute at the given resource // has a known type and value. -// -// The following is an example of using ExpectKnownValue. -// -// package example_test -// -// import ( -// "testing" -// -// "github.com/hashicorp/terraform-plugin-testing/helper/resource" -// "github.com/hashicorp/terraform-plugin-testing/knownvalue" -// "github.com/hashicorp/terraform-plugin-testing/statecheck" -// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -// ) -// -// func TestExpectKnownValue_CheckState_Bool(t *testing.T) { -// t.Parallel() -// -// resource.Test(t, resource.TestCase{ -// // Provider definition omitted. -// Steps: []resource.TestStep{ -// { -// Config: `resource "test_resource" "one" { -// bool_attribute = true -// } -// `, -// ConfigStateChecks: resource.ConfigStateChecks{ -// statecheck.ExpectKnownValue( -// "test_resource.one", -// tfjsonpath.New("bool_attribute"), -// knownvalue.BoolExact(true), -// ), -// }, -// }, -// }, -// }) -// } -// -// The following is an example of using ExpectKnownValue in combination -// with a custom knownvalue.Check. -// -// package example_test -// -// import ( -// "fmt" -// "strings" -// "testing" -// -// "github.com/hashicorp/terraform-plugin-testing/helper/resource" -// "github.com/hashicorp/terraform-plugin-testing/knownvalue" -// "github.com/hashicorp/terraform-plugin-testing/statecheck" -// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -// ) -// -// func TestExpectKnownValue_CheckState_String_Custom(t *testing.T) { -// t.Parallel() -// -// resource.Test(t, resource.TestCase{ -// // Provider definition omitted. -// Steps: []resource.TestStep{ -// { -// Config: `resource "test_resource" "one" { -// string_attribute = "string" -// } -// `, -// ConfigStateChecks: resource.ConfigStateChecks{ -// statecheck.ExpectKnownValue( -// "test_resource.one", -// tfjsonpath.New("string_attribute"), -// StringContains("tri")), -// }, -// }, -// }, -// }) -// } -// -// var _ knownvalue.Check = stringContains{} -// -// type stringContains struct { -// value string -// } -// -// func (v stringContains) CheckValue(other any) error { -// otherVal, ok := other.(string) -// -// if !ok { -// return fmt.Errorf("expected string value for StringContains check, got: %T", other) -// } -// -// if !strings.Contains(otherVal, v.value) { -// return fmt.Errorf("expected string %q to contain %q for StringContains check", otherVal, v.value) -// } -// -// return nil -// } -// -// func (v stringContains) String() string { -// return v.value -// } -// -// func StringContains(value string) stringContains { -// return stringContains{ -// value: value, -// } -// } func ExpectKnownValue(resourceAddress string, attributePath tfjsonpath.Path, knownValue knownvalue.Check) StateCheck { return expectKnownValue{ resourceAddress: resourceAddress, diff --git a/statecheck/expect_known_value_example_test.go b/statecheck/expect_known_value_example_test.go new file mode 100644 index 000000000..a54337258 --- /dev/null +++ b/statecheck/expect_known_value_example_test.go @@ -0,0 +1,37 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package statecheck_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + +func ExampleExpectKnownValue() { + t := &testing.T{} + t.Parallel() + + resource.Test(t, resource.TestCase{ + // Provider definition omitted. + Steps: []resource.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + `, + ConfigStateChecks: resource.ConfigStateChecks{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + knownvalue.BoolExact(true), + ), + }, + }, + }, + }) +} diff --git a/statecheck/expect_matching_values.go b/statecheck/expect_matching_values.go index 7609ae01a..fdcdc6749 100644 --- a/statecheck/expect_matching_values.go +++ b/statecheck/expect_matching_values.go @@ -92,45 +92,6 @@ func (e expectMatchingValues) CheckState(ctx context.Context, req CheckStateRequ // ExpectMatchingValues returns a state check that asserts that the specified attributes at the given resources // have a matching value. -// -// The following is an example of using ExpectMatchingValues. -// -// package example_test -// -// import ( -// "testing" -// -// "github.com/hashicorp/terraform-plugin-testing/helper/resource" -// "github.com/hashicorp/terraform-plugin-testing/statecheck" -// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -// ) -// -// func TestExpectMatchingValues_CheckState_AttributeValuesEqual_Bool(t *testing.T) { -// t.Parallel() -// -// resource.Test(t, resource.TestCase{ -// // Provider definition omitted. -// Steps: []resource.TestStep{ -// { -// Config: `resource "test_resource" "one" { -// bool_attribute = true -// } -// -// resource "test_resource" "two" { -// bool_attribute = true -// }`, -// ConfigStateChecks: resource.ConfigStateChecks{ -// statecheck.ExpectMatchingValues( -// "test_resource.one", -// tfjsonpath.New("bool_attribute"), -// "test_resource.two", -// tfjsonpath.New("bool_attribute"), -// ), -// }, -// }, -// }, -// }) -// } func ExpectMatchingValues(resourceAddressOne string, attributePathOne tfjsonpath.Path, resourceAddressTwo string, attributePathTwo tfjsonpath.Path) StateCheck { return expectMatchingValues{ resourceAddressOne: resourceAddressOne, diff --git a/statecheck/expect_matching_values_example_test.go b/statecheck/expect_matching_values_example_test.go new file mode 100644 index 000000000..b75a78091 --- /dev/null +++ b/statecheck/expect_matching_values_example_test.go @@ -0,0 +1,40 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package statecheck_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + +func ExampleExpectMatchingValues() { + t := &testing.T{} + t.Parallel() + + resource.Test(t, resource.TestCase{ + // Provider definition omitted. + Steps: []resource.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + + resource "test_resource" "two" { + bool_attribute = true + }`, + ConfigStateChecks: resource.ConfigStateChecks{ + statecheck.ExpectMatchingValues( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + "test_resource.two", + tfjsonpath.New("bool_attribute"), + ), + }, + }, + }, + }) +} diff --git a/statecheck/expect_no_value_exists.go b/statecheck/expect_no_value_exists.go index feecc93ab..b223e5ba8 100644 --- a/statecheck/expect_no_value_exists.go +++ b/statecheck/expect_no_value_exists.go @@ -60,40 +60,6 @@ func (e expectNoValueExists) CheckState(ctx context.Context, req CheckStateReque // ExpectNoValueExists returns a state check that asserts that the specified attribute at the given resource // does not exist. -// -// The following is an example of using ExpectNoValueExists. -// -// package example_test -// -// import ( -// "testing" -// -// "github.com/hashicorp/terraform-plugin-testing/helper/resource" -// "github.com/hashicorp/terraform-plugin-testing/statecheck" -// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -// ) -// -// func TestExpectNoValueExists_CheckState_AttributeNotFound(t *testing.T) { -// t.Parallel() -// -// resource.Test(t, resource.TestCase{ -// // Provider definition omitted. -// Steps: []resource.TestStep{ -// { -// Config: `resource "test_resource" "one" { -// bool_attribute = true -// } -// `, -// ConfigStateChecks: resource.ConfigStateChecks{ -// statecheck.ExpectNoValueExists( -// "test_resource.one", -// tfjsonpath.New("does_not_exist"), -// ), -// }, -// }, -// }, -// }) -// } func ExpectNoValueExists(resourceAddress string, attributePath tfjsonpath.Path) StateCheck { return expectNoValueExists{ resourceAddress: resourceAddress, diff --git a/statecheck/expect_no_value_exists_example_test.go b/statecheck/expect_no_value_exists_example_test.go new file mode 100644 index 000000000..b8f9b9fa4 --- /dev/null +++ b/statecheck/expect_no_value_exists_example_test.go @@ -0,0 +1,35 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package statecheck_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + +func ExampleExpectNoValueExists() { + t := &testing.T{} + t.Parallel() + + resource.Test(t, resource.TestCase{ + // Provider definition omitted. + Steps: []resource.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + `, + ConfigStateChecks: resource.ConfigStateChecks{ + statecheck.ExpectNoValueExists( + "test_resource.one", + tfjsonpath.New("does_not_exist"), + ), + }, + }, + }, + }) +} diff --git a/statecheck/expect_value_exists.go b/statecheck/expect_value_exists.go index 1043238bc..c2058b9f6 100644 --- a/statecheck/expect_value_exists.go +++ b/statecheck/expect_value_exists.go @@ -61,40 +61,6 @@ func (e expectValueExists) CheckState(ctx context.Context, req CheckStateRequest // ExpectValueExists returns a state check that asserts that the specified // attribute at the given resource exists. -// -// The following is an example of using ExpectValueExists. -// -// package example_test -// -// import ( -// "testing" -// -// "github.com/hashicorp/terraform-plugin-testing/helper/resource" -// "github.com/hashicorp/terraform-plugin-testing/statecheck" -// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -// ) -// -// func TestExpectValueExists_CheckState_AttributeFound(t *testing.T) { -// t.Parallel() -// -// resource.Test(t, resource.TestCase{ -// // Provider definition omitted. -// Steps: []resource.TestStep{ -// { -// Config: `resource "test_resource" "one" { -// bool_attribute = true -// } -// `, -// ConfigStateChecks: resource.ConfigStateChecks{ -// statecheck.ExpectValueExists( -// "test_resource.one", -// tfjsonpath.New("bool_attribute"), -// ), -// }, -// }, -// }, -// }) -// } func ExpectValueExists(resourceAddress string, attributePath tfjsonpath.Path) StateCheck { return expectValueExists{ resourceAddress: resourceAddress, diff --git a/statecheck/expect_value_exists_example_test.go b/statecheck/expect_value_exists_example_test.go new file mode 100644 index 000000000..64ff5346c --- /dev/null +++ b/statecheck/expect_value_exists_example_test.go @@ -0,0 +1,35 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package statecheck_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + +func ExampleExpectValueExists() { + t := &testing.T{} + t.Parallel() + + resource.Test(t, resource.TestCase{ + // Provider definition omitted. + Steps: []resource.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + } + `, + ConfigStateChecks: resource.ConfigStateChecks{ + statecheck.ExpectValueExists( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + ), + }, + }, + }, + }) +} From f4dbadd86b46110e70937394bea1b62bff7508d9 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Mon, 22 Jan 2024 12:14:50 +0000 Subject: [PATCH 42/73] Adding deprecation note to website docs for ExpectNullOutputValue and ExpectNullOutputValueAtPath --- .../plugin/testing/acceptance-tests/plan-checks/output.mdx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx b/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx index 65f406f9a..474867d43 100644 --- a/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx +++ b/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx @@ -112,6 +112,8 @@ func TestExpectKnownOutputValue_CheckPlan_Bool(t *testing.T) { ## `ExpectNullOutputValue` Plan Check +~> **Note**: `ExpectNullOutputValue` is deprecated. Use [`ExpectKnownOutputValue`](/terraform/plugin/testing/acceptance-tests/plan-checks/output#expectknownoutputvalue-plan-check) with [`knownvalue.Null()`](/terraform/plugin/testing/acceptance-tests/known-value-checks#null) instead. + The built-in [`plancheck.ExpectNullOutputValue(address)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectNullOutputValue) plan check determines whether an output at the specified address has a null value. ```go @@ -152,6 +154,8 @@ func Test_ExpectNullOutputValue_StringAttribute_NullConfig(t *testing.T) { ## `ExpectNullOutputValueAtPath` Plan Check +~> **Note**: `ExpectNullOutputValueAtPath` is deprecated. Use [`ExpectKnownOutputValueAtPath`](/terraform/plugin/testing/acceptance-tests/plan-checks/output#expectknownoutputvalueatpath-plan-check) with [`knownvalue.Null()`](/terraform/plugin/testing/acceptance-tests/known-value-checks#null) instead. + The built-in [`plancheck.ExpectNullOutputValueAtPath(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectNullOutputValueAtPath) plan check determines whether an output at the specified address, and path has a null value. | ```go From fcfd1bba97fe7b7d36935a75d5458ce5de875c59 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Mon, 22 Jan 2024 12:28:19 +0000 Subject: [PATCH 43/73] Adding return statements --- helper/resource/testing.go | 124 +-------------------------- helper/resource/testing_sets.go | 31 +------ statecheck/expect_contains.go | 6 ++ statecheck/expect_matching_values.go | 6 ++ statecheck/expect_no_value_exists.go | 6 ++ statecheck/expect_value_exists.go | 6 ++ 6 files changed, 29 insertions(+), 150 deletions(-) diff --git a/helper/resource/testing.go b/helper/resource/testing.go index a1d26a544..6b0843478 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -1372,37 +1372,8 @@ func testCheckResourceAttr(is *terraform.InstanceState, name string, key string, // }) // } // -// var _ knownvalue.Check = stringContains{} -// -// type stringContains struct { -// value string -// } -// -// func (v stringContains) CheckValue(other any) error { -// otherVal, ok := other.(string) -// -// if !ok { -// return fmt.Errorf("expected string value for StringContains check, got: %T", other) -// } -// -// if !strings.Contains(otherVal, v.value) { -// return fmt.Errorf("expected string %q to contain %q for StringContains check", otherVal, v.value) -// } -// -// return nil -// } -// -// func (v stringContains) String() string { -// return v.value -// } -// -// func StringContains(value string) stringContains { -// return stringContains{ -// value: value, -// } -// } -// // [Check]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check +// [Custom Known Value Checks]: https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests/known-value-checks/custom // [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue // [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck // [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck @@ -1487,37 +1458,8 @@ type CheckResourceAttrWithFunc func(value string) error // }) // } // -// var _ knownvalue.Check = stringContains{} -// -// type stringContains struct { -// value string -// } -// -// func (v stringContains) CheckValue(other any) error { -// otherVal, ok := other.(string) -// -// if !ok { -// return fmt.Errorf("expected string value for StringContains check, got: %T", other) -// } -// -// if !strings.Contains(otherVal, v.value) { -// return fmt.Errorf("expected string %q to contain %q for StringContains check", otherVal, v.value) -// } -// -// return nil -// } -// -// func (v stringContains) String() string { -// return v.value -// } -// -// func StringContains(value string) stringContains { -// return stringContains{ -// value: value, -// } -// } -// // [Check]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check +// [Custom Known Value Checks]: https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests/known-value-checks/custom // [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue // [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck // [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck @@ -1765,37 +1707,8 @@ func testCheckNoResourceAttr(is *terraform.InstanceState, name string, key strin // }) // } // -// var _ knownvalue.Check = stringContains{} -// -// type stringContains struct { -// value string -// } -// -// func (v stringContains) CheckValue(other any) error { -// otherVal, ok := other.(string) -// -// if !ok { -// return fmt.Errorf("expected string value for StringContains check, got: %T", other) -// } -// -// if !strings.Contains(otherVal, v.value) { -// return fmt.Errorf("expected string %q to contain %q for StringContains check", otherVal, v.value) -// } -// -// return nil -// } -// -// func (v stringContains) String() string { -// return v.value -// } -// -// func StringContains(value string) stringContains { -// return stringContains{ -// value: value, -// } -// } -// // [Check]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check +// [Custom Known Value Checks]: https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests/known-value-checks/custom // [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue // [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck // [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck @@ -2274,37 +2187,8 @@ func TestCheckOutput(name, value string) TestCheckFunc { // }) // } // -// var _ knownvalue.Check = stringContains{} -// -// type stringContains struct { -// value string -// } -// -// func (v stringContains) CheckValue(other any) error { -// otherVal, ok := other.(string) -// -// if !ok { -// return fmt.Errorf("expected string value for StringContains check, got: %T", other) -// } -// -// if !strings.Contains(otherVal, v.value) { -// return fmt.Errorf("expected string %q to contain %q for StringContains check", otherVal, v.value) -// } -// -// return nil -// } -// -// func (v stringContains) String() string { -// return v.value -// } -// -// func StringContains(value string) stringContains { -// return stringContains{ -// value: value, -// } -// } -// // [Check]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check +// [Custom Known Value Checks]: https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests/known-value-checks/custom // [ExpectKnownOutputValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValue // [ExpectKnownOutputValueAtPath]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValueAtPath // [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck diff --git a/helper/resource/testing_sets.go b/helper/resource/testing_sets.go index 1131e05bb..cab37c8c4 100644 --- a/helper/resource/testing_sets.go +++ b/helper/resource/testing_sets.go @@ -241,36 +241,7 @@ func TestCheckTypeSetElemNestedAttrs(name, attr string, values map[string]string // }) // } // -// var _ knownvalue.Check = stringContains{} -// -// type stringContains struct { -// value string -// } -// -// func (v stringContains) CheckValue(other any) error { -// otherVal, ok := other.(string) -// -// if !ok { -// return fmt.Errorf("expected string value for StringContains check, got: %T", other) -// } -// -// if !strings.Contains(otherVal, v.value) { -// return fmt.Errorf("expected string %q to contain %q for StringContains check", otherVal, v.value) -// } -// -// return nil -// } -// -// func (v stringContains) String() string { -// return v.value -// } -// -// func StringContains(value string) stringContains { -// return stringContains{ -// value: value, -// } -// } -// +// [Custom Known Value Checks]: https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests/known-value-checks/custom // [ListExact]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ListExact // [ListPartial]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ListPartial // [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue diff --git a/statecheck/expect_contains.go b/statecheck/expect_contains.go index 237635dc8..d32f78529 100644 --- a/statecheck/expect_contains.go +++ b/statecheck/expect_contains.go @@ -29,14 +29,20 @@ func (e expectContains) CheckState(ctx context.Context, req CheckStateRequest, r if req.State == nil { resp.Error = fmt.Errorf("state is nil") + + return } if req.State.Values == nil { resp.Error = fmt.Errorf("state does not contain any state values") + + return } if req.State.Values.RootModule == nil { resp.Error = fmt.Errorf("state does not contain a root module") + + return } for _, resourceChange := range req.State.Values.RootModule.Resources { diff --git a/statecheck/expect_matching_values.go b/statecheck/expect_matching_values.go index fdcdc6749..4772aaf0b 100644 --- a/statecheck/expect_matching_values.go +++ b/statecheck/expect_matching_values.go @@ -29,14 +29,20 @@ func (e expectMatchingValues) CheckState(ctx context.Context, req CheckStateRequ if req.State == nil { resp.Error = fmt.Errorf("state is nil") + + return } if req.State.Values == nil { resp.Error = fmt.Errorf("state does not contain any state values") + + return } if req.State.Values.RootModule == nil { resp.Error = fmt.Errorf("state does not contain a root module") + + return } for _, resourceChange := range req.State.Values.RootModule.Resources { diff --git a/statecheck/expect_no_value_exists.go b/statecheck/expect_no_value_exists.go index b223e5ba8..51a1650a1 100644 --- a/statecheck/expect_no_value_exists.go +++ b/statecheck/expect_no_value_exists.go @@ -26,14 +26,20 @@ func (e expectNoValueExists) CheckState(ctx context.Context, req CheckStateReque if req.State == nil { resp.Error = fmt.Errorf("state is nil") + + return } if req.State.Values == nil { resp.Error = fmt.Errorf("state does not contain any state values") + + return } if req.State.Values.RootModule == nil { resp.Error = fmt.Errorf("state does not contain a root module") + + return } for _, resourceChange := range req.State.Values.RootModule.Resources { diff --git a/statecheck/expect_value_exists.go b/statecheck/expect_value_exists.go index c2058b9f6..b0395509e 100644 --- a/statecheck/expect_value_exists.go +++ b/statecheck/expect_value_exists.go @@ -26,14 +26,20 @@ func (e expectValueExists) CheckState(ctx context.Context, req CheckStateRequest if req.State == nil { resp.Error = fmt.Errorf("state is nil") + + return } if req.State.Values == nil { resp.Error = fmt.Errorf("state does not contain any state values") + + return } if req.State.Values.RootModule == nil { resp.Error = fmt.Errorf("state does not contain a root module") + + return } for _, resourceChange := range req.State.Values.RootModule.Resources { From 2e4f316dd840be6837ca79776bcb3ebba84d4b67 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Mon, 22 Jan 2024 12:32:12 +0000 Subject: [PATCH 44/73] Renaming variables --- statecheck/expect_contains.go | 22 +++++++++++----------- statecheck/expect_matching_values.go | 22 +++++++++++----------- statecheck/expect_no_value_exists.go | 12 ++++++------ statecheck/expect_value_exists.go | 12 ++++++------ 4 files changed, 34 insertions(+), 34 deletions(-) diff --git a/statecheck/expect_contains.go b/statecheck/expect_contains.go index d32f78529..0efa63432 100644 --- a/statecheck/expect_contains.go +++ b/statecheck/expect_contains.go @@ -25,7 +25,7 @@ type expectContains struct { // CheckState implements the state check logic. func (e expectContains) CheckState(ctx context.Context, req CheckStateRequest, resp *CheckStateResponse) { - var rcOne, rcTwo *tfjson.StateResource + var resourceOne, resourceTwo *tfjson.StateResource if req.State == nil { resp.Error = fmt.Errorf("state is nil") @@ -45,21 +45,21 @@ func (e expectContains) CheckState(ctx context.Context, req CheckStateRequest, r return } - for _, resourceChange := range req.State.Values.RootModule.Resources { - if e.resourceAddressOne == resourceChange.Address { - rcOne = resourceChange + for _, r := range req.State.Values.RootModule.Resources { + if e.resourceAddressOne == r.Address { + resourceOne = r break } } - if rcOne == nil { + if resourceOne == nil { resp.Error = fmt.Errorf("%s - Resource not found in state", e.resourceAddressOne) return } - resultOne, err := tfjsonpath.Traverse(rcOne.AttributeValues, e.attributePathOne) + resultOne, err := tfjsonpath.Traverse(resourceOne.AttributeValues, e.attributePathOne) if err != nil { resp.Error = err @@ -67,21 +67,21 @@ func (e expectContains) CheckState(ctx context.Context, req CheckStateRequest, r return } - for _, resourceChange := range req.State.Values.RootModule.Resources { - if e.resourceAddressTwo == resourceChange.Address { - rcTwo = resourceChange + for _, r := range req.State.Values.RootModule.Resources { + if e.resourceAddressTwo == r.Address { + resourceTwo = r break } } - if rcTwo == nil { + if resourceTwo == nil { resp.Error = fmt.Errorf("%s - Resource not found in state", e.resourceAddressTwo) return } - resultTwo, err := tfjsonpath.Traverse(rcTwo.AttributeValues, e.attributePathTwo) + resultTwo, err := tfjsonpath.Traverse(resourceTwo.AttributeValues, e.attributePathTwo) if err != nil { resp.Error = err diff --git a/statecheck/expect_matching_values.go b/statecheck/expect_matching_values.go index 4772aaf0b..e7d586b66 100644 --- a/statecheck/expect_matching_values.go +++ b/statecheck/expect_matching_values.go @@ -25,7 +25,7 @@ type expectMatchingValues struct { // CheckState implements the state check logic. func (e expectMatchingValues) CheckState(ctx context.Context, req CheckStateRequest, resp *CheckStateResponse) { - var rcOne, rcTwo *tfjson.StateResource + var resourceOne, resourceTwo *tfjson.StateResource if req.State == nil { resp.Error = fmt.Errorf("state is nil") @@ -45,21 +45,21 @@ func (e expectMatchingValues) CheckState(ctx context.Context, req CheckStateRequ return } - for _, resourceChange := range req.State.Values.RootModule.Resources { - if e.resourceAddressOne == resourceChange.Address { - rcOne = resourceChange + for _, r := range req.State.Values.RootModule.Resources { + if e.resourceAddressOne == r.Address { + resourceOne = r break } } - if rcOne == nil { + if resourceOne == nil { resp.Error = fmt.Errorf("%s - Resource not found in state", e.resourceAddressOne) return } - resultOne, err := tfjsonpath.Traverse(rcOne.AttributeValues, e.attributePathOne) + resultOne, err := tfjsonpath.Traverse(resourceOne.AttributeValues, e.attributePathOne) if err != nil { resp.Error = err @@ -67,21 +67,21 @@ func (e expectMatchingValues) CheckState(ctx context.Context, req CheckStateRequ return } - for _, resourceChange := range req.State.Values.RootModule.Resources { - if e.resourceAddressTwo == resourceChange.Address { - rcTwo = resourceChange + for _, r := range req.State.Values.RootModule.Resources { + if e.resourceAddressTwo == r.Address { + resourceTwo = r break } } - if rcTwo == nil { + if resourceTwo == nil { resp.Error = fmt.Errorf("%s - Resource not found in state", e.resourceAddressTwo) return } - resultTwo, err := tfjsonpath.Traverse(rcTwo.AttributeValues, e.attributePathTwo) + resultTwo, err := tfjsonpath.Traverse(resourceTwo.AttributeValues, e.attributePathTwo) if err != nil { resp.Error = err diff --git a/statecheck/expect_no_value_exists.go b/statecheck/expect_no_value_exists.go index 51a1650a1..45bb736f0 100644 --- a/statecheck/expect_no_value_exists.go +++ b/statecheck/expect_no_value_exists.go @@ -22,7 +22,7 @@ type expectNoValueExists struct { // CheckState implements the state check logic. func (e expectNoValueExists) CheckState(ctx context.Context, req CheckStateRequest, resp *CheckStateResponse) { - var rc *tfjson.StateResource + var resource *tfjson.StateResource if req.State == nil { resp.Error = fmt.Errorf("state is nil") @@ -42,20 +42,20 @@ func (e expectNoValueExists) CheckState(ctx context.Context, req CheckStateReque return } - for _, resourceChange := range req.State.Values.RootModule.Resources { - if e.resourceAddress == resourceChange.Address { - rc = resourceChange + for _, r := range req.State.Values.RootModule.Resources { + if e.resourceAddress == r.Address { + resource = r break } } // Resource doesn't exist - if rc == nil { + if resource == nil { return } - _, err := tfjsonpath.Traverse(rc.AttributeValues, e.attributePath) + _, err := tfjsonpath.Traverse(resource.AttributeValues, e.attributePath) if err == nil { resp.Error = fmt.Errorf("attribute found at path: %s.%s", e.resourceAddress, e.attributePath.String()) diff --git a/statecheck/expect_value_exists.go b/statecheck/expect_value_exists.go index b0395509e..05d443b9f 100644 --- a/statecheck/expect_value_exists.go +++ b/statecheck/expect_value_exists.go @@ -22,7 +22,7 @@ type expectValueExists struct { // CheckState implements the state check logic. func (e expectValueExists) CheckState(ctx context.Context, req CheckStateRequest, resp *CheckStateResponse) { - var rc *tfjson.StateResource + var resource *tfjson.StateResource if req.State == nil { resp.Error = fmt.Errorf("state is nil") @@ -42,21 +42,21 @@ func (e expectValueExists) CheckState(ctx context.Context, req CheckStateRequest return } - for _, resourceChange := range req.State.Values.RootModule.Resources { - if e.resourceAddress == resourceChange.Address { - rc = resourceChange + for _, r := range req.State.Values.RootModule.Resources { + if e.resourceAddress == r.Address { + resource = r break } } - if rc == nil { + if resource == nil { resp.Error = fmt.Errorf("%s - Resource not found in state", e.resourceAddress) return } - _, err := tfjsonpath.Traverse(rc.AttributeValues, e.attributePath) + _, err := tfjsonpath.Traverse(resource.AttributeValues, e.attributePath) if err != nil { resp.Error = err From 4e867206480d09e36547c845a381e31430b58284 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Mon, 22 Jan 2024 12:37:09 +0000 Subject: [PATCH 45/73] Modify wording of error message --- statecheck/expect_contains.go | 2 +- statecheck/expect_contains_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/statecheck/expect_contains.go b/statecheck/expect_contains.go index 0efa63432..b44a3298d 100644 --- a/statecheck/expect_contains.go +++ b/statecheck/expect_contains.go @@ -92,7 +92,7 @@ func (e expectContains) CheckState(ctx context.Context, req CheckStateRequest, r resultOneCollection, ok := resultOne.([]any) if !ok { - resp.Error = fmt.Errorf("%s.%s is not a set", e.resourceAddressOne, e.attributePathOne.String()) + resp.Error = fmt.Errorf("%s.%s is not a collection", e.resourceAddressOne, e.attributePathOne.String()) return } diff --git a/statecheck/expect_contains_test.go b/statecheck/expect_contains_test.go index 48eedbe60..d4aa4a287 100644 --- a/statecheck/expect_contains_test.go +++ b/statecheck/expect_contains_test.go @@ -150,7 +150,7 @@ func TestExpectContains_CheckState_AttributeOneNotSet(t *testing.T) { tfjsonpath.New("bool_attribute"), ), }, - ExpectError: regexp.MustCompile("test_resource.one.bool_attribute is not a set"), + ExpectError: regexp.MustCompile("test_resource.one.bool_attribute is not a collection"), }, }, }) From 532a84c01dc605a5c371dee0e23be6898dd6a708 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Mon, 22 Jan 2024 12:38:55 +0000 Subject: [PATCH 46/73] Remove unneeded file --- helper/example_test/example.go | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 helper/example_test/example.go diff --git a/helper/example_test/example.go b/helper/example_test/example.go deleted file mode 100644 index 968726e38..000000000 --- a/helper/example_test/example.go +++ /dev/null @@ -1,31 +0,0 @@ -package example_test - -import ( - "testing" - - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/statecheck" - "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -) - -func ExampleExpectValueExists(t *testing.T) { - t.Parallel() - - resource.Test(t, resource.TestCase{ - // Provider definition omitted. - Steps: []resource.TestStep{ - { - Config: `resource "test_resource" "one" { - bool_attribute = true - } - `, - ConfigStateChecks: resource.ConfigStateChecks{ - statecheck.ExpectValueExists( - "test_resource.one", - tfjsonpath.New("bool_attribute"), - ), - }, - }, - }, - }) -} From 6d8f1124e0fca467de71d5cd1ca2026ecc246eae Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Tue, 23 Jan 2024 10:41:39 +0000 Subject: [PATCH 47/73] Renaming BoolExact to Bool, and NullExact to Null (#266) --- knownvalue/bool.go | 18 ++++++------- knownvalue/bool_test.go | 22 ++++++++-------- knownvalue/null.go | 16 ++++++------ knownvalue/null_test.go | 12 ++++----- .../expect_known_output_value_at_path_test.go | 26 +++++++++---------- plancheck/expect_known_output_value_test.go | 26 +++++++++---------- plancheck/expect_known_value_test.go | 26 +++++++++---------- .../expect_known_output_value_at_path_test.go | 26 +++++++++---------- statecheck/expect_known_output_value_test.go | 14 +++++----- statecheck/expect_known_value_test.go | 26 +++++++++---------- .../known-value-checks/bool.mdx | 10 +++---- .../known-value-checks/custom.mdx | 2 +- .../known-value-checks/index.mdx | 2 +- .../known-value-checks/null.mdx | 10 +++---- .../acceptance-tests/plan-checks/output.mdx | 4 +-- .../acceptance-tests/state-checks/custom.mdx | 2 +- .../acceptance-tests/state-checks/output.mdx | 4 +-- .../state-checks/resource.mdx | 2 +- 18 files changed, 124 insertions(+), 124 deletions(-) diff --git a/knownvalue/bool.go b/knownvalue/bool.go index 62521f454..fba10ee86 100644 --- a/knownvalue/bool.go +++ b/knownvalue/bool.go @@ -8,37 +8,37 @@ import ( "strconv" ) -var _ Check = boolExact{} +var _ Check = boolValue{} -type boolExact struct { +type boolValue struct { value bool } // CheckValue determines whether the passed value is of type bool, and // contains a matching bool value. -func (v boolExact) CheckValue(other any) error { +func (v boolValue) CheckValue(other any) error { otherVal, ok := other.(bool) if !ok { - return fmt.Errorf("expected bool value for BoolExact check, got: %T", other) + return fmt.Errorf("expected bool value for Bool check, got: %T", other) } if otherVal != v.value { - return fmt.Errorf("expected value %t for BoolExact check, got: %t", v.value, otherVal) + return fmt.Errorf("expected value %t for Bool check, got: %t", v.value, otherVal) } return nil } // String returns the string representation of the bool value. -func (v boolExact) String() string { +func (v boolValue) String() string { return strconv.FormatBool(v.value) } -// BoolExact returns a Check for asserting equality between the +// Bool returns a Check for asserting equality between the // supplied bool and the value passed to the CheckValue method. -func BoolExact(value bool) boolExact { - return boolExact{ +func Bool(value bool) boolValue { + return boolValue{ value: value, } } diff --git a/knownvalue/bool_test.go b/knownvalue/bool_test.go index 3c47d59a9..35ba1d40e 100644 --- a/knownvalue/bool_test.go +++ b/knownvalue/bool_test.go @@ -21,29 +21,29 @@ func TestBoolValue_CheckValue(t *testing.T) { expectedError error }{ "zero-nil": { - self: knownvalue.BoolExact(false), - expectedError: fmt.Errorf("expected bool value for BoolExact check, got: "), + self: knownvalue.Bool(false), + expectedError: fmt.Errorf("expected bool value for Bool check, got: "), }, "zero-other": { - self: knownvalue.BoolExact(false), + self: knownvalue.Bool(false), other: false, // checking against the underlying value field zero-value }, "nil": { - self: knownvalue.BoolExact(false), - expectedError: fmt.Errorf("expected bool value for BoolExact check, got: "), + self: knownvalue.Bool(false), + expectedError: fmt.Errorf("expected bool value for Bool check, got: "), }, "wrong-type": { - self: knownvalue.BoolExact(true), + self: knownvalue.Bool(true), other: 1.23, - expectedError: fmt.Errorf("expected bool value for BoolExact check, got: float64"), + expectedError: fmt.Errorf("expected bool value for Bool check, got: float64"), }, "not-equal": { - self: knownvalue.BoolExact(true), + self: knownvalue.Bool(true), other: false, - expectedError: fmt.Errorf("expected value true for BoolExact check, got: false"), + expectedError: fmt.Errorf("expected value true for Bool check, got: false"), }, "equal": { - self: knownvalue.BoolExact(true), + self: knownvalue.Bool(true), other: true, }, } @@ -66,7 +66,7 @@ func TestBoolValue_CheckValue(t *testing.T) { func TestBoolValue_String(t *testing.T) { t.Parallel() - got := knownvalue.BoolExact(true).String() + got := knownvalue.Bool(true).String() if diff := cmp.Diff(got, "true"); diff != "" { t.Errorf("unexpected difference: %s", diff) diff --git a/knownvalue/null.go b/knownvalue/null.go index 6b25d1bf4..a8bbaee9f 100644 --- a/knownvalue/null.go +++ b/knownvalue/null.go @@ -7,26 +7,26 @@ import ( "fmt" ) -var _ Check = nullExact{} +var _ Check = null{} -type nullExact struct{} +type null struct{} // CheckValue determines whether the passed value is nil. -func (v nullExact) CheckValue(other any) error { +func (v null) CheckValue(other any) error { if other != nil { - return fmt.Errorf("expected value nil for NullExact check, got: %T", other) + return fmt.Errorf("expected value nil for Null check, got: %T", other) } return nil } // String returns the string representation of null. -func (v nullExact) String() string { +func (v null) String() string { return "null" } -// NullExact returns a Check for asserting equality nil +// Null returns a Check for asserting equality nil // and the value passed to the CheckValue method. -func NullExact() nullExact { - return nullExact{} +func Null() null { + return null{} } diff --git a/knownvalue/null_test.go b/knownvalue/null_test.go index ddd688df3..e7bb5531d 100644 --- a/knownvalue/null_test.go +++ b/knownvalue/null_test.go @@ -21,19 +21,19 @@ func TestNullValue_CheckValue(t *testing.T) { expectedError error }{ "zero-nil": { - self: knownvalue.NullExact(), + self: knownvalue.Null(), }, "zero-other": { - self: knownvalue.NullExact(), + self: knownvalue.Null(), other: nil, // checking against the underlying value field zero-value }, "not-nil": { - self: knownvalue.NullExact(), + self: knownvalue.Null(), other: false, - expectedError: fmt.Errorf("expected value nil for NullExact check, got: bool"), + expectedError: fmt.Errorf("expected value nil for Null check, got: bool"), }, "equal": { - self: knownvalue.NullExact(), + self: knownvalue.Null(), other: nil, }, } @@ -56,7 +56,7 @@ func TestNullValue_CheckValue(t *testing.T) { func TestNullValue_String(t *testing.T) { t.Parallel() - got := knownvalue.NullExact().String() + got := knownvalue.Null().String() if diff := cmp.Diff(got, "null"); diff != "" { t.Errorf("unexpected difference: %s", diff) diff --git a/plancheck/expect_known_output_value_at_path_test.go b/plancheck/expect_known_output_value_at_path_test.go index cbcb256bb..fc643523d 100644 --- a/plancheck/expect_known_output_value_at_path_test.go +++ b/plancheck/expect_known_output_value_at_path_test.go @@ -52,7 +52,7 @@ func TestExpectKnownOutputValueAtPath_CheckPlan_ResourceNotFound(t *testing.T) { plancheck.ExpectKnownOutputValueAtPath( "test_resource_two_output", tfjsonpath.New("bool_attribute"), - knownvalue.BoolExact(true), + knownvalue.Bool(true), ), }, }, @@ -91,22 +91,22 @@ func TestExpectKnownOutputValueAtPath_CheckPlan_AttributeValueNull(t *testing.T) plancheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("bool_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), plancheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("float_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), plancheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("int_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), plancheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("list_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), plancheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", @@ -116,12 +116,12 @@ func TestExpectKnownOutputValueAtPath_CheckPlan_AttributeValueNull(t *testing.T) plancheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("map_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), plancheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("set_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), plancheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", @@ -131,7 +131,7 @@ func TestExpectKnownOutputValueAtPath_CheckPlan_AttributeValueNull(t *testing.T) plancheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("string_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), }, }, @@ -171,7 +171,7 @@ func TestExpectKnownOutputValueAtPath_CheckPlan_Bool(t *testing.T) { plancheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("bool_attribute"), - knownvalue.BoolExact(true), + knownvalue.Bool(true), ), }, }, @@ -252,11 +252,11 @@ func TestExpectKnownOutputValueAtPath_CheckPlan_Bool_KnownValueWrongValue(t *tes plancheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("bool_attribute"), - knownvalue.BoolExact(false), + knownvalue.Bool(false), ), }, }, - ExpectError: regexp.MustCompile("error checking value for output at path: test_resource_one_output.bool_attribute, err: expected value false for BoolExact check, got: true"), + ExpectError: regexp.MustCompile("error checking value for output at path: test_resource_one_output.bool_attribute, err: expected value false for Bool check, got: true"), }, }, }) @@ -1780,10 +1780,10 @@ func TestExpectKnownOutputValueAtPath_CheckPlan_String_KnownValueWrongType(t *te plancheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("string_attribute"), - knownvalue.BoolExact(true)), + knownvalue.Bool(true)), }, }, - ExpectError: regexp.MustCompile("error checking value for output at path: test_resource_one_output.string_attribute, err: expected bool value for BoolExact check, got: string"), + ExpectError: regexp.MustCompile("error checking value for output at path: test_resource_one_output.string_attribute, err: expected bool value for Bool check, got: string"), }, }, }) diff --git a/plancheck/expect_known_output_value_test.go b/plancheck/expect_known_output_value_test.go index 0b5315650..da45a00d0 100644 --- a/plancheck/expect_known_output_value_test.go +++ b/plancheck/expect_known_output_value_test.go @@ -42,7 +42,7 @@ func TestExpectKnownOutputValue_CheckPlan_OutputNotFound(t *testing.T) { PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownOutputValue( "bool_not_found", - knownvalue.BoolExact(true), + knownvalue.Bool(true), ), }, }, @@ -96,19 +96,19 @@ func TestExpectKnownOutputValue_CheckPlan_AttributeValueNull(t *testing.T) { PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownOutputValue( "bool_output", - knownvalue.NullExact(), + knownvalue.Null(), ), plancheck.ExpectKnownOutputValue( "float_output", - knownvalue.NullExact(), + knownvalue.Null(), ), plancheck.ExpectKnownOutputValue( "int_output", - knownvalue.NullExact(), + knownvalue.Null(), ), plancheck.ExpectKnownOutputValue( "list_output", - knownvalue.NullExact(), + knownvalue.Null(), ), plancheck.ExpectKnownOutputValue( "list_nested_block_output", @@ -116,11 +116,11 @@ func TestExpectKnownOutputValue_CheckPlan_AttributeValueNull(t *testing.T) { ), plancheck.ExpectKnownOutputValue( "map_output", - knownvalue.NullExact(), + knownvalue.Null(), ), plancheck.ExpectKnownOutputValue( "set_output", - knownvalue.NullExact(), + knownvalue.Null(), ), plancheck.ExpectKnownOutputValue( "set_nested_block_output", @@ -128,7 +128,7 @@ func TestExpectKnownOutputValue_CheckPlan_AttributeValueNull(t *testing.T) { ), plancheck.ExpectKnownOutputValue( "string_output", - knownvalue.NullExact(), + knownvalue.Null(), ), }, }, @@ -160,7 +160,7 @@ func TestExpectKnownOutputValue_CheckPlan_Bool(t *testing.T) { PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownOutputValue( "bool_output", - knownvalue.BoolExact(true), + knownvalue.Bool(true), ), }, }, @@ -225,11 +225,11 @@ func TestExpectKnownOutputValue_CheckPlan_Bool_KnownValueWrongValue(t *testing.T PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownOutputValue( "bool_output", - knownvalue.BoolExact(false), + knownvalue.Bool(false), ), }, }, - ExpectError: regexp.MustCompile("error checking value for output at path: bool_output, err: expected value false for BoolExact check, got: true"), + ExpectError: regexp.MustCompile("error checking value for output at path: bool_output, err: expected value false for Bool check, got: true"), }, }, }) @@ -1481,10 +1481,10 @@ func TestExpectKnownOutputValue_CheckPlan_String_KnownValueWrongType(t *testing. PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownOutputValue( "string_output", - knownvalue.BoolExact(true)), + knownvalue.Bool(true)), }, }, - ExpectError: regexp.MustCompile("error checking value for output at path: string_output, err: expected bool value for BoolExact check, got: string"), + ExpectError: regexp.MustCompile("error checking value for output at path: string_output, err: expected bool value for Bool check, got: string"), }, }, }) diff --git a/plancheck/expect_known_value_test.go b/plancheck/expect_known_value_test.go index c331af94e..85405f1e8 100644 --- a/plancheck/expect_known_value_test.go +++ b/plancheck/expect_known_value_test.go @@ -40,7 +40,7 @@ func TestExpectKnownValue_CheckPlan_ResourceNotFound(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.two", tfjsonpath.New("bool_attribute"), - knownvalue.BoolExact(true), + knownvalue.Bool(true), ), }, }, @@ -67,22 +67,22 @@ func TestExpectKnownValue_CheckPlan_AttributeValueNull(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("float_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("int_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), plancheck.ExpectKnownValue( "test_resource.one", @@ -92,12 +92,12 @@ func TestExpectKnownValue_CheckPlan_AttributeValueNull(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("map_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("set_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), plancheck.ExpectKnownValue( "test_resource.one", @@ -107,7 +107,7 @@ func TestExpectKnownValue_CheckPlan_AttributeValueNull(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("string_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), }, }, @@ -136,7 +136,7 @@ func TestExpectKnownValue_CheckPlan_Bool(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), - knownvalue.BoolExact(true), + knownvalue.Bool(true), ), }, }, @@ -195,11 +195,11 @@ func TestExpectKnownValue_CheckPlan_Bool_KnownValueWrongValue(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), - knownvalue.BoolExact(false), + knownvalue.Bool(false), ), }, }, - ExpectError: regexp.MustCompile("error checking value for attribute at path: test_resource.one.bool_attribute, err: expected value false for BoolExact check, got: true"), + ExpectError: regexp.MustCompile("error checking value for attribute at path: test_resource.one.bool_attribute, err: expected value false for Bool check, got: true"), }, }, }) @@ -1349,10 +1349,10 @@ func TestExpectKnownValue_CheckPlan_String_KnownValueWrongType(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("string_attribute"), - knownvalue.BoolExact(true)), + knownvalue.Bool(true)), }, }, - ExpectError: regexp.MustCompile("error checking value for attribute at path: test_resource.one.string_attribute, err: expected bool value for BoolExact check, got: string"), + ExpectError: regexp.MustCompile("error checking value for attribute at path: test_resource.one.string_attribute, err: expected bool value for Bool check, got: string"), }, }, }) diff --git a/statecheck/expect_known_output_value_at_path_test.go b/statecheck/expect_known_output_value_at_path_test.go index 918b53874..c69c59887 100644 --- a/statecheck/expect_known_output_value_at_path_test.go +++ b/statecheck/expect_known_output_value_at_path_test.go @@ -43,7 +43,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_ResourceNotFound(t *testing.T) statecheck.ExpectKnownOutputValueAtPath( "test_resource_two_output", tfjsonpath.New("bool_attribute"), - knownvalue.BoolExact(true), + knownvalue.Bool(true), ), }, ExpectError: regexp.MustCompile("test_resource_two_output - Output not found in state"), @@ -73,22 +73,22 @@ func TestExpectKnownOutputValueAtPath_CheckState_AttributeValueNull(t *testing.T statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("bool_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("float_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("int_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("list_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", @@ -98,12 +98,12 @@ func TestExpectKnownOutputValueAtPath_CheckState_AttributeValueNull(t *testing.T statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("map_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("set_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", @@ -113,7 +113,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_AttributeValueNull(t *testing.T statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("string_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), }, }, @@ -144,7 +144,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Bool(t *testing.T) { statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("bool_attribute"), - knownvalue.BoolExact(true), + knownvalue.Bool(true), ), }, }, @@ -207,10 +207,10 @@ func TestExpectKnownOutputValueAtPath_CheckState_Bool_KnownValueWrongValue(t *te statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("bool_attribute"), - knownvalue.BoolExact(false), + knownvalue.Bool(false), ), }, - ExpectError: regexp.MustCompile("expected value false for BoolExact check, got: true"), + ExpectError: regexp.MustCompile("expected value false for Bool check, got: true"), }, }, }) @@ -1429,9 +1429,9 @@ func TestExpectKnownOutputValueAtPath_CheckState_String_KnownValueWrongType(t *t statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("string_attribute"), - knownvalue.BoolExact(true)), + knownvalue.Bool(true)), }, - ExpectError: regexp.MustCompile("expected bool value for BoolExact check, got: string"), + ExpectError: regexp.MustCompile("expected bool value for Bool check, got: string"), }, }, }) diff --git a/statecheck/expect_known_output_value_test.go b/statecheck/expect_known_output_value_test.go index b3f5e2ccf..2eb65193e 100644 --- a/statecheck/expect_known_output_value_test.go +++ b/statecheck/expect_known_output_value_test.go @@ -41,7 +41,7 @@ func TestExpectKnownOutputValue_CheckState_OutputNotFound(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "bool_not_found", - knownvalue.BoolExact(true), + knownvalue.Bool(true), ), }, ExpectError: regexp.MustCompile("bool_not_found - Output not found in state"), @@ -73,7 +73,7 @@ func TestExpectKnownOutputValue_CheckState_AttributeValueNull(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "bool_output", - knownvalue.BoolExact(true), + knownvalue.Bool(true), ), }, ExpectError: regexp.MustCompile("bool_output - Output not found in state"), @@ -104,7 +104,7 @@ func TestExpectKnownOutputValue_CheckState_Bool(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "bool_output", - knownvalue.BoolExact(true), + knownvalue.Bool(true), ), }, }, @@ -165,10 +165,10 @@ func TestExpectKnownOutputValue_CheckState_Bool_KnownValueWrongValue(t *testing. ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "bool_output", - knownvalue.BoolExact(false), + knownvalue.Bool(false), ), }, - ExpectError: regexp.MustCompile("expected value false for BoolExact check, got: true"), + ExpectError: regexp.MustCompile("expected value false for Bool check, got: true"), }, }, }) @@ -1353,9 +1353,9 @@ func TestExpectKnownOutputValue_CheckState_String_KnownValueWrongType(t *testing ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "string_output", - knownvalue.BoolExact(true)), + knownvalue.Bool(true)), }, - ExpectError: regexp.MustCompile("expected bool value for BoolExact check, got: string"), + ExpectError: regexp.MustCompile("expected bool value for Bool check, got: string"), }, }, }) diff --git a/statecheck/expect_known_value_test.go b/statecheck/expect_known_value_test.go index 3be302744..eeca817d0 100644 --- a/statecheck/expect_known_value_test.go +++ b/statecheck/expect_known_value_test.go @@ -40,7 +40,7 @@ func TestExpectKnownValue_CheckState_ResourceNotFound(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.two", tfjsonpath.New("bool_attribute"), - knownvalue.BoolExact(true), + knownvalue.Bool(true), ), }, ExpectError: regexp.MustCompile("test_resource.two - Resource not found in state"), @@ -65,22 +65,22 @@ func TestExpectKnownValue_CheckState_AttributeValueNull(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("float_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("int_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), statecheck.ExpectKnownValue( "test_resource.one", @@ -90,12 +90,12 @@ func TestExpectKnownValue_CheckState_AttributeValueNull(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("map_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("set_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), statecheck.ExpectKnownValue( "test_resource.one", @@ -105,7 +105,7 @@ func TestExpectKnownValue_CheckState_AttributeValueNull(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("string_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), }, }, @@ -132,7 +132,7 @@ func TestExpectKnownValue_CheckState_Bool(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), - knownvalue.BoolExact(true), + knownvalue.Bool(true), ), }, }, @@ -187,10 +187,10 @@ func TestExpectKnownValue_CheckState_Bool_KnownValueWrongValue(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), - knownvalue.BoolExact(false), + knownvalue.Bool(false), ), }, - ExpectError: regexp.MustCompile("expected value false for BoolExact check, got: true"), + ExpectError: regexp.MustCompile("expected value false for Bool check, got: true"), }, }, }) @@ -1273,9 +1273,9 @@ func TestExpectKnownValue_CheckState_String_KnownValueWrongType(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("string_attribute"), - knownvalue.BoolExact(true)), + knownvalue.Bool(true)), }, - ExpectError: regexp.MustCompile("expected bool value for BoolExact check, got: string"), + ExpectError: regexp.MustCompile("expected bool value for Bool check, got: string"), }, }, }) diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/bool.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/bool.mdx index dfcb6e06b..a996b569a 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/bool.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/bool.mdx @@ -8,13 +8,13 @@ description: >- The known value checks that are available for bool values are: -* [BoolExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/bool#boolexact-check) +* [Bool](/terraform/plugin/testing/acceptance-tests/known-value-checks/bool#bool-check) -## `BoolExact` Check +## `Bool` Check -The [BoolExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#BoolExact) check tests that a resource attribute, or output value has an exactly matching bool value. +The [Bool](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Bool) check tests that a resource attribute, or output value has an exactly matching bool value. -Example usage of [BoolExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#BoolExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. +Example usage of [Bool](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Bool) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. ```go func TestExpectKnownValue_CheckPlan_Bool(t *testing.T) { @@ -32,7 +32,7 @@ func TestExpectKnownValue_CheckPlan_Bool(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), - knownvalue.BoolExact(true), + knownvalue.Bool(true), ), }, }, diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/custom.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/custom.mdx index f5ce1d1de..892433ea6 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/custom.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/custom.mdx @@ -62,7 +62,7 @@ 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: -* [BoolExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#BoolExact) +* [Bool](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Bool) * [Float64Exact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Float64Exact) * [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) diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/index.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/index.mdx index bc22d96e5..3da43b44c 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/index.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/index.mdx @@ -20,7 +20,7 @@ Example uses in the testing module include: The known value check types are implemented within the `terraform-plugin-testing` module in the [`knownvalue` package](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue). Known value checks are instantiated by calling the relevant constructor function. ```go -knownvalue.BoolExact(true) +knownvalue.Bool(true) ``` For known value checks that represent collections, or objects, nesting of known value checks can be used to define a "composite" known value check for use in asserting against a resource attribute, or output value that contains other values. diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/null.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/null.mdx index 58d95ce8d..69dc32340 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/null.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/null.mdx @@ -8,13 +8,13 @@ description: >- The known value checks that are available for null values are: -* [NullExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/null#nullexact-check) +* [Null](/terraform/plugin/testing/acceptance-tests/known-value-checks/null#null-check) -## `NullExact` Check +## `Null` Check -The [NullExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NullExact) check tests that a resource attribute, or output value has an exactly matching null value. +The [Null](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Null) check tests that a resource attribute, or output value has an exactly matching null value. -Example usage of [NullExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NullExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/state-checks/resource) state check. +Example usage of [Null](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Null) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/state-checks/resource) state check. ```go func TestExpectKnownValue_CheckState_AttributeValueNull(t *testing.T) { @@ -29,7 +29,7 @@ func TestExpectKnownValue_CheckState_AttributeValueNull(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), - knownvalue.NullExact(), + knownvalue.Null(), ), }, }, diff --git a/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx b/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx index 6dd2121cd..ce8c548af 100644 --- a/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx +++ b/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx @@ -44,7 +44,7 @@ func TestExpectKnownOutputValue_CheckPlan_Bool(t *testing.T) { PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownOutputValue( "bool_output", - knownvalue.BoolExact(true), + knownvalue.Bool(true), ), }, }, @@ -80,7 +80,7 @@ func TestExpectKnownOutputValue_CheckPlan_Bool(t *testing.T) { PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownOutputValue( "bool_output", - knownvalue.BoolExact(true), + knownvalue.Bool(true), ), }, }, diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx index a71e3d765..299b18d51 100644 --- a/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx @@ -114,7 +114,7 @@ func TestExpectKnownValue_CheckState_Bool(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), - knownvalue.BoolExact(true), + knownvalue.Bool(true), ), }, }, diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx index b1e02da1f..3d937acb5 100644 --- a/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx @@ -39,7 +39,7 @@ func TestExpectKnownOutputValue_CheckState_Bool(t *testing.T) { ConfigStateChecks: r.ConfigStateChecks{ statecheck.ExpectKnownOutputValue( "bool_output", - knownvalue.BoolExact(true), + knownvalue.Bool(true), ), }, }, @@ -74,7 +74,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Bool(t *testing.T) { statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("bool_attribute"), - knownvalue.BoolExact(true), + knownvalue.Bool(true), ), }, }, diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx index 582afbcdf..9a5acdb0e 100644 --- a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx @@ -36,7 +36,7 @@ func TestExpectKnownValue_CheckState_Bool(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), - knownvalue.BoolExact(true), + knownvalue.Bool(true), ), }, }, From 04cf3c92a288b25e675238810003c5b10ebe361d Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Tue, 23 Jan 2024 11:18:21 +0000 Subject: [PATCH 48/73] Removing ConfigStateChecks type (#266) --- helper/resource/testing.go | 8 +- helper/resource/testing_new_config_test.go | 5 +- helper/resource/teststep_validate_test.go | 3 +- .../expect_known_output_value_at_path_test.go | 80 +++++++++---------- statecheck/expect_known_output_value_test.go | 80 +++++++++---------- statecheck/expect_known_value_test.go | 80 +++++++++---------- statecheck/expect_sensitive_value_test.go | 14 ++-- .../known-value-checks/null.mdx | 2 +- .../acceptance-tests/state-checks/custom.mdx | 2 +- .../acceptance-tests/state-checks/output.mdx | 4 +- .../state-checks/resource.mdx | 4 +- 11 files changed, 140 insertions(+), 142 deletions(-) diff --git a/helper/resource/testing.go b/helper/resource/testing.go index 5abda4eaa..4abdce8d6 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -591,12 +591,12 @@ type TestStep struct { // [plancheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck RefreshPlanChecks RefreshPlanChecks - // ConfigStateChecks allow assertions to be made against the state file at different points of a Config (apply) test using a state check. + // ConfigStateChecks allow assertions to be made against the state file during a Config (apply) test using a state check. // Custom state checks can be created by implementing the [StateCheck] interface, or by using a StateCheck implementation from the provided [statecheck] package // // [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck // [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck - ConfigStateChecks ConfigStateChecks + ConfigStateChecks []statecheck.StateCheck // PlanOnly can be set to only run `plan` with this configuration, and not // actually apply it. This is useful for ensuring config changes result in @@ -803,10 +803,6 @@ type RefreshPlanChecks struct { PostRefresh []plancheck.PlanCheck } -// ConfigStateChecks runs all state checks in the slice. This occurs after the apply and refresh of a Config test are run. -// All errors by state checks in this slice are aggregated, reported, and will result in a test failure. -type ConfigStateChecks []statecheck.StateCheck - // ParallelTest performs an acceptance test on a resource, allowing concurrency // with other ParallelTest. The number of concurrent tests is controlled by the // "go test" command -parallel flag. diff --git a/helper/resource/testing_new_config_test.go b/helper/resource/testing_new_config_test.go index fe0eb707e..147a24dfa 100644 --- a/helper/resource/testing_new_config_test.go +++ b/helper/resource/testing_new_config_test.go @@ -15,6 +15,7 @@ import ( "github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/providerserver" "github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/resource" "github.com/hashicorp/terraform-plugin-testing/plancheck" + "github.com/hashicorp/terraform-plugin-testing/statecheck" "github.com/hashicorp/terraform-plugin-testing/tfversion" ) @@ -764,7 +765,7 @@ func Test_ConfigStateChecks_Called(t *testing.T) { Steps: []TestStep{ { Config: `resource "test_resource" "test" {}`, - ConfigStateChecks: ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ spy1, spy2, }, @@ -831,7 +832,7 @@ func Test_ConfigStateChecks_Errors(t *testing.T) { Steps: []TestStep{ { Config: `resource "test_resource" "test" {}`, - ConfigStateChecks: ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ spy1, spy2, spy3, diff --git a/helper/resource/teststep_validate_test.go b/helper/resource/teststep_validate_test.go index 6a326e003..a4e955b39 100644 --- a/helper/resource/teststep_validate_test.go +++ b/helper/resource/teststep_validate_test.go @@ -16,6 +16,7 @@ import ( "github.com/hashicorp/terraform-plugin-testing/config" "github.com/hashicorp/terraform-plugin-testing/internal/teststep" "github.com/hashicorp/terraform-plugin-testing/plancheck" + "github.com/hashicorp/terraform-plugin-testing/statecheck" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -468,7 +469,7 @@ func TestTestStepValidate(t *testing.T) { }, "configstatechecks-not-config-mode": { testStep: TestStep{ - ConfigStateChecks: ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ &stateCheckSpy{}, }, RefreshState: true, diff --git a/statecheck/expect_known_output_value_at_path_test.go b/statecheck/expect_known_output_value_at_path_test.go index c69c59887..83df97b48 100644 --- a/statecheck/expect_known_output_value_at_path_test.go +++ b/statecheck/expect_known_output_value_at_path_test.go @@ -39,7 +39,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_ResourceNotFound(t *testing.T) value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_two_output", tfjsonpath.New("bool_attribute"), @@ -69,7 +69,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_AttributeValueNull(t *testing.T value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("bool_attribute"), @@ -140,7 +140,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Bool(t *testing.T) { value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("bool_attribute"), @@ -171,7 +171,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Bool_KnownValueWrongType(t *tes value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("bool_attribute"), @@ -203,7 +203,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Bool_KnownValueWrongValue(t *te value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("bool_attribute"), @@ -235,7 +235,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Float64(t *testing.T) { value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("float_attribute"), @@ -267,7 +267,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Float64_KnownValueWrongType(t * value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("float_attribute"), @@ -299,7 +299,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Float64_KnownValueWrongValue(t value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("float_attribute"), @@ -331,7 +331,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Int64(t *testing.T) { value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("int_attribute"), @@ -362,7 +362,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Int64_KnownValueWrongValue(t *t value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("int_attribute"), @@ -397,7 +397,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_List(t *testing.T) { value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("list_attribute"), @@ -434,7 +434,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_List_KnownValueWrongType(t *tes value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("list_attribute"), @@ -469,7 +469,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_List_KnownValueWrongValue(t *te value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("list_attribute"), @@ -507,7 +507,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_ListPartial(t *testing.T) { value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("list_attribute"), @@ -545,7 +545,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_ListPartial_KnownValueWrongValu value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("list_attribute"), @@ -582,7 +582,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_ListElements(t *testing.T) { value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("list_attribute"), @@ -616,7 +616,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_ListElements_WrongNum(t *testin value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("list_attribute"), @@ -653,7 +653,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_ListNestedBlock(t *testing.T) { value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("list_nested_block"), @@ -696,7 +696,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_ListNestedBlockPartial(t *testi value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("list_nested_block"), @@ -736,7 +736,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_ListNestedBlockElements(t *test value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("list_nested_block"), @@ -770,7 +770,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Map(t *testing.T) { value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("map_attribute"), @@ -807,7 +807,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Map_KnownValueWrongType(t *test value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("map_attribute"), @@ -842,7 +842,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Map_KnownValueWrongValue(t *tes value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("map_attribute"), @@ -880,7 +880,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_MapPartial(t *testing.T) { value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("map_attribute"), @@ -916,7 +916,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_MapPartial_KnownValueWrongValue value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("map_attribute"), @@ -953,7 +953,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_MapElements(t *testing.T) { value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("map_attribute"), @@ -987,7 +987,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_MapElements_WrongNum(t *testing value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("map_attribute"), @@ -1025,7 +1025,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Number(t *testing.T) { value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("int_attribute"), @@ -1062,7 +1062,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Number_KnownValueWrongValue(t * value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("int_attribute"), @@ -1097,7 +1097,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Set(t *testing.T) { value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("set_attribute"), @@ -1134,7 +1134,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Set_KnownValueWrongValue(t *tes value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("set_attribute"), @@ -1172,7 +1172,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_SetPartial(t *testing.T) { value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("set_attribute"), @@ -1208,7 +1208,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_SetPartial_KnownValueWrongValue value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("set_attribute"), @@ -1245,7 +1245,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_SetElements(t *testing.T) { value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("set_attribute"), @@ -1281,7 +1281,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_SetNestedBlock(t *testing.T) { value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("set_nested_block"), @@ -1324,7 +1324,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_SetNestedBlockPartial(t *testin value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("set_nested_block"), @@ -1364,7 +1364,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_SetNestedBlockElements(t *testi value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("set_nested_block"), @@ -1395,7 +1395,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_String(t *testing.T) { value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("string_attribute"), @@ -1425,7 +1425,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_String_KnownValueWrongType(t *t value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("string_attribute"), @@ -1456,7 +1456,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_String_KnownValueWrongValue(t * value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("string_attribute"), diff --git a/statecheck/expect_known_output_value_test.go b/statecheck/expect_known_output_value_test.go index 2eb65193e..c1cf98cf3 100644 --- a/statecheck/expect_known_output_value_test.go +++ b/statecheck/expect_known_output_value_test.go @@ -38,7 +38,7 @@ func TestExpectKnownOutputValue_CheckState_OutputNotFound(t *testing.T) { value = test_resource.one.bool_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "bool_not_found", knownvalue.Bool(true), @@ -70,7 +70,7 @@ func TestExpectKnownOutputValue_CheckState_AttributeValueNull(t *testing.T) { value = test_resource.one.bool_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "bool_output", knownvalue.Bool(true), @@ -101,7 +101,7 @@ func TestExpectKnownOutputValue_CheckState_Bool(t *testing.T) { value = test_resource.one.bool_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "bool_output", knownvalue.Bool(true), @@ -131,7 +131,7 @@ func TestExpectKnownOutputValue_CheckState_Bool_KnownValueWrongType(t *testing.T value = test_resource.one.bool_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "bool_output", knownvalue.Float64Exact(1.23), @@ -162,7 +162,7 @@ func TestExpectKnownOutputValue_CheckState_Bool_KnownValueWrongValue(t *testing. value = test_resource.one.bool_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "bool_output", knownvalue.Bool(false), @@ -193,7 +193,7 @@ func TestExpectKnownOutputValue_CheckState_Float64(t *testing.T) { value = test_resource.one.float_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "float64_output", knownvalue.Float64Exact(1.23), @@ -224,7 +224,7 @@ func TestExpectKnownOutputValue_CheckState_Float64_KnownValueWrongType(t *testin value = test_resource.one.float_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "float64_output", knownvalue.StringExact("str"), @@ -255,7 +255,7 @@ func TestExpectKnownOutputValue_CheckState_Float64_KnownValueWrongValue(t *testi value = test_resource.one.float_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "float64_output", knownvalue.Float64Exact(3.21), @@ -286,7 +286,7 @@ func TestExpectKnownOutputValue_CheckState_Int64(t *testing.T) { value = test_resource.one.int_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "int64_output", knownvalue.Int64Exact(123), @@ -316,7 +316,7 @@ func TestExpectKnownOutputValue_CheckState_Int64_KnownValueWrongValue(t *testing value = test_resource.one.int_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "int64_output", knownvalue.Int64Exact(321), @@ -350,7 +350,7 @@ func TestExpectKnownOutputValue_CheckState_List(t *testing.T) { value = test_resource.one.list_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "list_output", knownvalue.ListExact([]knownvalue.Check{ @@ -386,7 +386,7 @@ func TestExpectKnownOutputValue_CheckState_List_KnownValueWrongType(t *testing.T value = test_resource.one.list_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "list_output", knownvalue.MapExact(map[string]knownvalue.Check{}), @@ -420,7 +420,7 @@ func TestExpectKnownOutputValue_CheckState_List_KnownValueWrongValue(t *testing. value = test_resource.one.list_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "list_output", knownvalue.ListExact([]knownvalue.Check{ @@ -457,7 +457,7 @@ func TestExpectKnownOutputValue_CheckState_ListPartial(t *testing.T) { value = test_resource.one.list_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "list_output", knownvalue.ListPartial(map[int]knownvalue.Check{ @@ -494,7 +494,7 @@ func TestExpectKnownOutputValue_CheckState_ListPartial_KnownValueWrongValue(t *t value = test_resource.one.list_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "list_output", knownvalue.ListPartial(map[int]knownvalue.Check{ @@ -530,7 +530,7 @@ func TestExpectKnownOutputValue_CheckState_ListElements(t *testing.T) { value = test_resource.one.list_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "list_output", knownvalue.ListSizeExact(2), @@ -563,7 +563,7 @@ func TestExpectKnownOutputValue_CheckState_ListElements_WrongNum(t *testing.T) { value = test_resource.one.list_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "list_output", knownvalue.ListSizeExact(3), @@ -599,7 +599,7 @@ func TestExpectKnownOutputValue_CheckState_ListNestedBlock(t *testing.T) { value = test_resource.one.list_nested_block } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "list_nested_block_output", knownvalue.ListExact([]knownvalue.Check{ @@ -641,7 +641,7 @@ func TestExpectKnownOutputValue_CheckState_ListNestedBlockPartial(t *testing.T) value = test_resource.one.list_nested_block } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "list_nested_block_output", knownvalue.ListPartial(map[int]knownvalue.Check{ @@ -680,7 +680,7 @@ func TestExpectKnownOutputValue_CheckState_ListNestedBlockElements(t *testing.T) value = test_resource.one.list_nested_block } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "list_nested_block_output", knownvalue.ListSizeExact(2), @@ -713,7 +713,7 @@ func TestExpectKnownOutputValue_CheckState_Map(t *testing.T) { value = test_resource.one.map_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "map_output", knownvalue.MapExact(map[string]knownvalue.Check{ @@ -749,7 +749,7 @@ func TestExpectKnownOutputValue_CheckState_Map_KnownValueWrongType(t *testing.T) value = test_resource.one.map_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "map_output", knownvalue.ListExact([]knownvalue.Check{}), @@ -783,7 +783,7 @@ func TestExpectKnownOutputValue_CheckState_Map_KnownValueWrongValue(t *testing.T value = test_resource.one.map_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "map_output", knownvalue.MapExact(map[string]knownvalue.Check{ @@ -820,7 +820,7 @@ func TestExpectKnownOutputValue_CheckState_MapPartial(t *testing.T) { value = test_resource.one.map_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "map_output", knownvalue.MapPartial(map[string]knownvalue.Check{ @@ -855,7 +855,7 @@ func TestExpectKnownOutputValue_CheckState_MapPartial_KnownValueWrongValue(t *te value = test_resource.one.map_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "map_output", knownvalue.MapPartial(map[string]knownvalue.Check{ @@ -891,7 +891,7 @@ func TestExpectKnownOutputValue_CheckState_MapElements(t *testing.T) { value = test_resource.one.map_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "map_output", knownvalue.MapSizeExact(2), @@ -924,7 +924,7 @@ func TestExpectKnownOutputValue_CheckState_MapElements_WrongNum(t *testing.T) { value = test_resource.one.map_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "map_output", knownvalue.MapSizeExact(3), @@ -961,7 +961,7 @@ func TestExpectKnownOutputValue_CheckState_Number(t *testing.T) { value = test_resource.one.int_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "int64_output", knownvalue.NumberExact(f), @@ -997,7 +997,7 @@ func TestExpectKnownOutputValue_CheckState_Number_KnownValueWrongValue(t *testin value = test_resource.one.int_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "int64_output", knownvalue.NumberExact(f), @@ -1031,7 +1031,7 @@ func TestExpectKnownOutputValue_CheckState_Set(t *testing.T) { value = test_resource.one.set_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "set_output", knownvalue.SetExact([]knownvalue.Check{ @@ -1067,7 +1067,7 @@ func TestExpectKnownOutputValue_CheckState_Set_KnownValueWrongValue(t *testing.T value = test_resource.one.set_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "set_output", knownvalue.SetExact([]knownvalue.Check{ @@ -1104,7 +1104,7 @@ func TestExpectKnownOutputValue_CheckState_SetPartial(t *testing.T) { value = test_resource.one.set_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "set_output", knownvalue.SetPartial([]knownvalue.Check{ @@ -1139,7 +1139,7 @@ func TestExpectKnownOutputValue_CheckState_SetPartial_KnownValueWrongValue(t *te value = test_resource.one.set_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "set_output", knownvalue.SetPartial([]knownvalue.Check{ @@ -1175,7 +1175,7 @@ func TestExpectKnownOutputValue_CheckState_SetElements(t *testing.T) { value = test_resource.one.set_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "set_output", knownvalue.SetSizeExact(2), @@ -1210,7 +1210,7 @@ func TestExpectKnownOutputValue_CheckState_SetNestedBlock(t *testing.T) { value = test_resource.one.set_nested_block } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "set_nested_block_output", knownvalue.SetExact([]knownvalue.Check{ @@ -1252,7 +1252,7 @@ func TestExpectKnownOutputValue_CheckState_SetNestedBlockPartial(t *testing.T) { value = test_resource.one.set_nested_block } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "set_nested_block_output", knownvalue.SetPartial([]knownvalue.Check{ @@ -1291,7 +1291,7 @@ func TestExpectKnownOutputValue_CheckState_SetNestedBlockElements(t *testing.T) value = test_resource.one.set_nested_block } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "set_nested_block_output", knownvalue.SetSizeExact(2), @@ -1321,7 +1321,7 @@ func TestExpectKnownOutputValue_CheckState_String(t *testing.T) { value = test_resource.one.string_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "string_output", knownvalue.StringExact("str")), @@ -1350,7 +1350,7 @@ func TestExpectKnownOutputValue_CheckState_String_KnownValueWrongType(t *testing value = test_resource.one.string_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "string_output", knownvalue.Bool(true)), @@ -1380,7 +1380,7 @@ func TestExpectKnownOutputValue_CheckState_String_KnownValueWrongValue(t *testin value = test_resource.one.string_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "string_output", knownvalue.StringExact("rts")), diff --git a/statecheck/expect_known_value_test.go b/statecheck/expect_known_value_test.go index eeca817d0..f9c89bed0 100644 --- a/statecheck/expect_known_value_test.go +++ b/statecheck/expect_known_value_test.go @@ -36,7 +36,7 @@ func TestExpectKnownValue_CheckState_ResourceNotFound(t *testing.T) { bool_attribute = true } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.two", tfjsonpath.New("bool_attribute"), @@ -61,7 +61,7 @@ func TestExpectKnownValue_CheckState_AttributeValueNull(t *testing.T) { Steps: []r.TestStep{ { Config: `resource "test_resource" "one" {}`, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), @@ -128,7 +128,7 @@ func TestExpectKnownValue_CheckState_Bool(t *testing.T) { bool_attribute = true } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), @@ -155,7 +155,7 @@ func TestExpectKnownValue_CheckState_Bool_KnownValueWrongType(t *testing.T) { bool_attribute = true } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), @@ -183,7 +183,7 @@ func TestExpectKnownValue_CheckState_Bool_KnownValueWrongValue(t *testing.T) { bool_attribute = true } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), @@ -211,7 +211,7 @@ func TestExpectKnownValue_CheckState_Float64(t *testing.T) { float_attribute = 1.23 } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("float_attribute"), @@ -239,7 +239,7 @@ func TestExpectKnownValue_CheckState_Float64_KnownValueWrongType(t *testing.T) { float_attribute = 1.23 } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("float_attribute"), @@ -267,7 +267,7 @@ func TestExpectKnownValue_CheckState_Float64_KnownValueWrongValue(t *testing.T) float_attribute = 1.23 } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("float_attribute"), @@ -295,7 +295,7 @@ func TestExpectKnownValue_CheckState_Int64(t *testing.T) { int_attribute = 123 } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("int_attribute"), @@ -322,7 +322,7 @@ func TestExpectKnownValue_CheckState_Int64_KnownValueWrongValue(t *testing.T) { int_attribute = 123 } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("int_attribute"), @@ -353,7 +353,7 @@ func TestExpectKnownValue_CheckState_List(t *testing.T) { ] } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_attribute"), @@ -386,7 +386,7 @@ func TestExpectKnownValue_CheckState_List_KnownValueWrongType(t *testing.T) { ] } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_attribute"), @@ -417,7 +417,7 @@ func TestExpectKnownValue_CheckState_List_KnownValueWrongValue(t *testing.T) { ] } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_attribute"), @@ -451,7 +451,7 @@ func TestExpectKnownValue_CheckState_ListPartial(t *testing.T) { ] } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_attribute"), @@ -485,7 +485,7 @@ func TestExpectKnownValue_CheckState_ListPartial_KnownValueWrongValue(t *testing ] } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_attribute"), @@ -518,7 +518,7 @@ func TestExpectKnownValue_CheckState_ListElements(t *testing.T) { ] } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_attribute"), @@ -548,7 +548,7 @@ func TestExpectKnownValue_CheckState_ListElements_WrongNum(t *testing.T) { ] } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_attribute"), @@ -581,7 +581,7 @@ func TestExpectKnownValue_CheckState_ListNestedBlock(t *testing.T) { } } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_nested_block"), @@ -620,7 +620,7 @@ func TestExpectKnownValue_CheckState_ListNestedBlockPartial(t *testing.T) { } } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_nested_block"), @@ -656,7 +656,7 @@ func TestExpectKnownValue_CheckState_ListNestedBlockElements(t *testing.T) { } } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("list_nested_block"), @@ -686,7 +686,7 @@ func TestExpectKnownValue_CheckState_Map(t *testing.T) { } } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("map_attribute"), @@ -719,7 +719,7 @@ func TestExpectKnownValue_CheckState_Map_KnownValueWrongType(t *testing.T) { } } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("map_attribute"), @@ -750,7 +750,7 @@ func TestExpectKnownValue_CheckState_Map_KnownValueWrongValue(t *testing.T) { } } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("map_attribute"), @@ -784,7 +784,7 @@ func TestExpectKnownValue_CheckState_MapPartial(t *testing.T) { } } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("map_attribute"), @@ -816,7 +816,7 @@ func TestExpectKnownValue_CheckState_MapPartial_KnownValueWrongValue(t *testing. } } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("map_attribute"), @@ -849,7 +849,7 @@ func TestExpectKnownValue_CheckState_MapElements(t *testing.T) { } } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("map_attribute"), @@ -879,7 +879,7 @@ func TestExpectKnownValue_CheckState_MapElements_WrongNum(t *testing.T) { } } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("map_attribute"), @@ -913,7 +913,7 @@ func TestExpectKnownValue_CheckState_Number(t *testing.T) { int_attribute = 123 } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("int_attribute"), @@ -946,7 +946,7 @@ func TestExpectKnownValue_CheckState_Number_KnownValueWrongValue(t *testing.T) { int_attribute = 123 } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("int_attribute"), @@ -977,7 +977,7 @@ func TestExpectKnownValue_CheckState_Set(t *testing.T) { ] } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("set_attribute"), @@ -1010,7 +1010,7 @@ func TestExpectKnownValue_CheckState_Set_KnownValueWrongValue(t *testing.T) { ] } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("set_attribute"), @@ -1044,7 +1044,7 @@ func TestExpectKnownValue_CheckState_SetPartial(t *testing.T) { ] } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("set_attribute"), @@ -1076,7 +1076,7 @@ func TestExpectKnownValue_CheckState_SetPartial_KnownValueWrongValue(t *testing. ] } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("set_attribute"), @@ -1109,7 +1109,7 @@ func TestExpectKnownValue_CheckState_SetElements(t *testing.T) { ] } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("set_attribute"), @@ -1141,7 +1141,7 @@ func TestExpectKnownValue_CheckState_SetNestedBlock(t *testing.T) { } } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("set_nested_block"), @@ -1180,7 +1180,7 @@ func TestExpectKnownValue_CheckState_SetNestedBlockPartial(t *testing.T) { } } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("set_nested_block"), @@ -1216,7 +1216,7 @@ func TestExpectKnownValue_CheckState_SetNestedBlockElements(t *testing.T) { } } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("set_nested_block"), @@ -1243,7 +1243,7 @@ func TestExpectKnownValue_CheckState_String(t *testing.T) { string_attribute = "str" } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("string_attribute"), @@ -1269,7 +1269,7 @@ func TestExpectKnownValue_CheckState_String_KnownValueWrongType(t *testing.T) { string_attribute = "str" } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("string_attribute"), @@ -1296,7 +1296,7 @@ func TestExpectKnownValue_CheckState_String_KnownValueWrongValue(t *testing.T) { string_attribute = "str" } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("string_attribute"), diff --git a/statecheck/expect_sensitive_value_test.go b/statecheck/expect_sensitive_value_test.go index 5723d73b4..55a44840a 100644 --- a/statecheck/expect_sensitive_value_test.go +++ b/statecheck/expect_sensitive_value_test.go @@ -36,7 +36,7 @@ func Test_ExpectSensitiveValue_SensitiveStringAttribute(t *testing.T) { sensitive_string_attribute = "test" } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectSensitiveValue("test_resource.one", tfjsonpath.New("sensitive_string_attribute")), }, @@ -64,7 +64,7 @@ func Test_ExpectSensitiveValue_SensitiveListAttribute(t *testing.T) { sensitive_list_attribute = ["value1"] } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectSensitiveValue("test_resource.one", tfjsonpath.New("sensitive_list_attribute")), }, @@ -92,7 +92,7 @@ func Test_ExpectSensitiveValue_SensitiveSetAttribute(t *testing.T) { sensitive_set_attribute = ["value1"] } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectSensitiveValue("test_resource.one", tfjsonpath.New("sensitive_set_attribute")), }, @@ -122,7 +122,7 @@ func Test_ExpectSensitiveValue_SensitiveMapAttribute(t *testing.T) { } } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectSensitiveValue("test_resource.one", tfjsonpath.New("sensitive_map_attribute")), }, @@ -153,7 +153,7 @@ func Test_ExpectSensitiveValue_ListNestedBlock_SensitiveAttribute(t *testing.T) } } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectSensitiveValue("test_resource.one", tfjsonpath.New("list_nested_block_sensitive_attribute").AtSliceIndex(0). AtMapKey("sensitive_list_nested_block_attribute")), @@ -185,7 +185,7 @@ func Test_ExpectSensitiveValue_SetNestedBlock_SensitiveAttribute(t *testing.T) { } } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectSensitiveValue("test_resource.one", tfjsonpath.New("set_nested_block_sensitive_attribute")), }, @@ -211,7 +211,7 @@ func Test_ExpectSensitiveValue_ExpectError_ResourceNotFound(t *testing.T) { Config: ` resource "test_resource" "one" {} `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectSensitiveValue("test_resource.two", tfjsonpath.New("set_attribute")), }, ExpectError: regexp.MustCompile(`test_resource.two - Resource not found in state`), diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/null.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/null.mdx index 69dc32340..0ab575e39 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/null.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/null.mdx @@ -25,7 +25,7 @@ func TestExpectKnownValue_CheckState_AttributeValueNull(t *testing.T) { Steps: []r.TestStep{ { Config: `resource "test_resource" "one" {}`, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx index 299b18d51..230923cd2 100644 --- a/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx @@ -110,7 +110,7 @@ func TestExpectKnownValue_CheckState_Bool(t *testing.T) { bool_attribute = true } `, - ConfigStateChecks: resource.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx index 3d937acb5..cad493698 100644 --- a/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx @@ -36,7 +36,7 @@ func TestExpectKnownOutputValue_CheckState_Bool(t *testing.T) { value = test_resource.one.bool_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "bool_output", knownvalue.Bool(true), @@ -70,7 +70,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Bool(t *testing.T) { value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("bool_attribute"), diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx index 9a5acdb0e..18109b54d 100644 --- a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx @@ -32,7 +32,7 @@ func TestExpectKnownValue_CheckState_Bool(t *testing.T) { bool_attribute = true } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), @@ -67,7 +67,7 @@ func Test_ExpectSensitiveValue_SensitiveStringAttribute(t *testing.T) { sensitive_string_attribute = "test" } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectSensitiveValue("test_resource.one", tfjsonpath.New("sensitive_string_attribute")), }, From 173d4b27ea75019e13eeda482a1477725179f6ea Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Tue, 23 Jan 2024 11:26:30 +0000 Subject: [PATCH 49/73] Move execution of ConfigStateChecks (#266) --- helper/resource/testing_new_config.go | 40 +++++++++++++-------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/helper/resource/testing_new_config.go b/helper/resource/testing_new_config.go index 17d3745fa..9747eaf6e 100644 --- a/helper/resource/testing_new_config.go +++ b/helper/resource/testing_new_config.go @@ -205,6 +205,26 @@ func testStepNewConfig(ctx context.Context, t testing.T, c TestCase, wd *plugint } } } + + // Run state checks + if len(step.ConfigStateChecks) > 0 { + var state *tfjson.State + + err = runProviderCommand(ctx, t, func() error { + var err error + state, err = wd.State(ctx) + return err + }, wd, providers) + + if err != nil { + return fmt.Errorf("Error retrieving post-apply, post-refresh state: %w", err) + } + + err = runStateChecks(ctx, t, state, step.ConfigStateChecks) + if err != nil { + return fmt.Errorf("Post-apply refresh state check(s) failed:\n%w", err) + } + } } // Test for perpetual diffs by performing a plan, a refresh, and another plan @@ -313,26 +333,6 @@ func testStepNewConfig(ctx context.Context, t testing.T, c TestCase, wd *plugint } } - // Run post-apply, post-refresh state checks - if len(step.ConfigStateChecks) > 0 { - var state *tfjson.State - - err = runProviderCommand(ctx, t, func() error { - var err error - state, err = wd.State(ctx) - return err - }, wd, providers) - - if err != nil { - return fmt.Errorf("Error retrieving post-apply, post-refresh state: %w", err) - } - - err = runStateChecks(ctx, t, state, step.ConfigStateChecks) - if err != nil { - return fmt.Errorf("Post-apply refresh state check(s) failed:\n%w", err) - } - } - // check if plan is empty if !planIsEmpty(plan, helper.TerraformVersion()) && !step.ExpectNonEmptyPlan { var stdout string From 23ffdb0449bcdf7e1369cd8e70242ea9aa342a99 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Tue, 23 Jan 2024 12:03:47 +0000 Subject: [PATCH 50/73] Replacing usage of ConfigStateChecks, BoolExact and NullExact types --- .../unreleased/NOTES-20240122-082628.yaml | 2 +- helper/resource/testing.go | 30 +++++++++---------- helper/resource/testing_sets.go | 8 ++--- plancheck/expect_null_output_value.go | 4 +-- plancheck/expect_null_output_value_at_path.go | 4 +-- statecheck/expect_contains_example_test.go | 2 +- statecheck/expect_contains_test.go | 14 ++++----- ...known_output_value_at_path_example_test.go | 4 +-- .../expect_known_output_value_at_path_test.go | 2 +- .../expect_known_output_value_example_test.go | 4 +-- statecheck/expect_known_output_value_test.go | 2 +- statecheck/expect_known_value_example_test.go | 4 +-- statecheck/expect_known_value_test.go | 8 ++--- .../expect_matching_values_example_test.go | 2 +- statecheck/expect_matching_values_test.go | 16 +++++----- .../expect_no_value_exists_example_test.go | 2 +- statecheck/expect_no_value_exists_test.go | 6 ++-- .../expect_value_exists_example_test.go | 2 +- statecheck/expect_value_exists_test.go | 6 ++-- .../state-checks/resource.mdx | 8 ++--- 20 files changed, 65 insertions(+), 65 deletions(-) diff --git a/.changes/unreleased/NOTES-20240122-082628.yaml b/.changes/unreleased/NOTES-20240122-082628.yaml index f05712299..09792a709 100644 --- a/.changes/unreleased/NOTES-20240122-082628.yaml +++ b/.changes/unreleased/NOTES-20240122-082628.yaml @@ -1,7 +1,7 @@ kind: NOTES body: 'plancheck: Deprecated `ExpectNullOutputValue` and `ExpectNullOutputValueAtPath`. Use `ExpectKnownOutputValue` and `ExpectKnownOutputValueAtPath` with - `knownvalue.NullExact` instead' + `knownvalue.Null` instead' time: 2024-01-22T08:26:28.053303Z custom: Issue: "275" diff --git a/helper/resource/testing.go b/helper/resource/testing.go index 9bcdf146d..0f6febb63 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -1083,7 +1083,7 @@ func ComposeAggregateTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc { // bool_attribute = true // } // `, -// ConfigStateChecks: resource.ConfigStateChecks{ +// ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectValueExists( // "test_resource.one", // tfjsonpath.New("bool_attribute"), @@ -1226,11 +1226,11 @@ func testCheckResourceAttrSet(is *terraform.InstanceState, name string, key stri // bool_attribute = true // } // `, -// ConfigStateChecks: resource.ConfigStateChecks{ +// ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectKnownValue( // "test_resource.one", // tfjsonpath.New("bool_attribute"), -// knownvalue.BoolExact(true), +// knownvalue.Bool(true), // ), // }, // }, @@ -1357,7 +1357,7 @@ func testCheckResourceAttr(is *terraform.InstanceState, name string, key string, // string_attribute = "string" // } // `, -// ConfigStateChecks: resource.ConfigStateChecks{ +// ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectKnownValue( // "test_resource.one", // tfjsonpath.New("string_attribute"), @@ -1443,7 +1443,7 @@ type CheckResourceAttrWithFunc func(value string) error // string_attribute = "string" // } // `, -// ConfigStateChecks: resource.ConfigStateChecks{ +// ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectKnownValue( // "test_resource.one", // tfjsonpath.New("string_attribute"), @@ -1540,7 +1540,7 @@ func TestCheckResourceAttrWith(name, key string, checkValueFunc CheckResourceAtt // bool_attribute = true // } // `, -// ConfigStateChecks: resource.ConfigStateChecks{ +// ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectNoValueExists( // "test_resource.one", // tfjsonpath.New("does_not_exist"), @@ -1692,7 +1692,7 @@ func testCheckNoResourceAttr(is *terraform.InstanceState, name string, key strin // string_attribute = "string" // } // `, -// ConfigStateChecks: resource.ConfigStateChecks{ +// ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectKnownValue( // "test_resource.one", // tfjsonpath.New("string_attribute"), @@ -1794,12 +1794,12 @@ func testMatchResourceAttr(is *terraform.InstanceState, name string, key string, // bool_attribute = true // } // `, -// ConfigStateChecks: resource.ConfigStateChecks{ +// ConfigStateChecks: []statecheck.StateCheck{ // AlterValue(testBool), // statecheck.ExpectKnownValue( // "test_resource.one", // tfjsonpath.New("bool_attribute"), -// knownvalue.BoolExact(*testBool), +// knownvalue.Bool(*testBool), // ), // }, // }, @@ -1914,7 +1914,7 @@ func TestCheckModuleResourceAttrPtr(mp []string, name string, key string, value // resource "test_resource" "two" { // bool_attribute = true // }`, -// ConfigStateChecks: resource.ConfigStateChecks{ +// ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectMatchingValues( // "test_resource.one", // tfjsonpath.New("bool_attribute"), @@ -2058,10 +2058,10 @@ func testCheckResourceAttrPair(isFirst *terraform.InstanceState, nameFirst strin // value = test_resource.one.bool_attribute // } // `, -// ConfigStateChecks: resource.ConfigStateChecks{ +// ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectKnownOutputValue( // "bool_output", -// knownvalue.BoolExact(true), +// knownvalue.Bool(true), // ), // }, // }, @@ -2098,11 +2098,11 @@ func testCheckResourceAttrPair(isFirst *terraform.InstanceState, nameFirst strin // value = test_resource.one // } // `, -// ConfigStateChecks: resource.ConfigStateChecks{ +// ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectKnownOutputValueAtPath( // "test_resource_one_output", // tfjsonpath.New("bool_attribute"), -// knownvalue.BoolExact(true), +// knownvalue.Bool(true), // ), // }, // }, @@ -2172,7 +2172,7 @@ func TestCheckOutput(name, value string) TestCheckFunc { // value = test_resource.one // } // `, -// ConfigStateChecks: resource.ConfigStateChecks{ +// ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectKnownOutputValueAtPath( // "test_resource_one_output", // tfjsonpath.New("string_attribute"), diff --git a/helper/resource/testing_sets.go b/helper/resource/testing_sets.go index cab37c8c4..eaaec2e7e 100644 --- a/helper/resource/testing_sets.go +++ b/helper/resource/testing_sets.go @@ -91,7 +91,7 @@ const ( // ] // } // `, -// ConfigStateChecks: resource.ConfigStateChecks{ +// ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectKnownValue( // "test_resource.one", // tfjsonpath.New("set_attribute"), @@ -222,7 +222,7 @@ func TestCheckTypeSetElemNestedAttrs(name, attr string, values map[string]string // } // } // `, -// ConfigStateChecks: resource.ConfigStateChecks{ +// ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectKnownValue( // "test_resource.one", // tfjsonpath.New("set_nested_block"), @@ -354,7 +354,7 @@ func TestMatchTypeSetElemNestedAttrs(name, attr string, values map[string]*regex // ] // } // `, -// ConfigStateChecks: resource.ConfigStateChecks{ +// ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectKnownValue( // "test_resource.one", // tfjsonpath.New("set_attribute"), @@ -452,7 +452,7 @@ func TestCheckTypeSetElemAttr(name, attr, value string) TestCheckFunc { // "value2" // ] // }`, -// ConfigStateChecks: resource.ConfigStateChecks{ +// ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectContains( // "test_resource.two", // tfjsonpath.New("set_attribute"), diff --git a/plancheck/expect_null_output_value.go b/plancheck/expect_null_output_value.go index 1fd27b17e..64cbf8483 100644 --- a/plancheck/expect_null_output_value.go +++ b/plancheck/expect_null_output_value.go @@ -65,11 +65,11 @@ func (e expectNullOutputValue) CheckPlan(ctx context.Context, req CheckPlanReque // values may differ. For example, terraform-plugin-sdk based providers may have less precise representations of null values, such // as marking whole maps as null rather than individual element values. // -// Deprecated: Use ExpectKnownOutputValue with knownvalue.NullExact instead. +// Deprecated: Use ExpectKnownOutputValue with knownvalue.Null instead. // ExpectNullOutputValue will be removed in the next major version release. // // [ExpectKnownOutputValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectKnownOutputValue -// [NullExact]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NullExact +// [Null]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Null func ExpectNullOutputValue(outputAddress string) PlanCheck { return expectNullOutputValue{ outputAddress: outputAddress, diff --git a/plancheck/expect_null_output_value_at_path.go b/plancheck/expect_null_output_value_at_path.go index 4929ec64f..deeeda3fb 100644 --- a/plancheck/expect_null_output_value_at_path.go +++ b/plancheck/expect_null_output_value_at_path.go @@ -66,11 +66,11 @@ func (e expectNullOutputValueAtPath) CheckPlan(ctx context.Context, req CheckPla // values may differ. For example, terraform-plugin-sdk based providers may have less precise representations of null values, such // as marking whole maps as null rather than individual element values. // -// Deprecated: Use ExpectKnownOutputValueAtPath with knownvalue.NullExact instead. +// Deprecated: Use ExpectKnownOutputValueAtPath with knownvalue.Null instead. // ExpectNullOutputValueAtPath will be removed in the next major version release. // // [ExpectKnownOutputValueAtPath]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectKnownOutputValueAtPath -// [NullExact]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NullExact +// [Null]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Null func ExpectNullOutputValueAtPath(outputAddress string, valuePath tfjsonpath.Path) PlanCheck { return expectNullOutputValueAtPath{ outputAddress: outputAddress, diff --git a/statecheck/expect_contains_example_test.go b/statecheck/expect_contains_example_test.go index 3f4306226..242368289 100644 --- a/statecheck/expect_contains_example_test.go +++ b/statecheck/expect_contains_example_test.go @@ -29,7 +29,7 @@ func ExampleExpectContains() { "value2" ] }`, - ConfigStateChecks: resource.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectContains( "test_resource.two", tfjsonpath.New("set_attribute"), diff --git a/statecheck/expect_contains_test.go b/statecheck/expect_contains_test.go index d4aa4a287..21442a1fc 100644 --- a/statecheck/expect_contains_test.go +++ b/statecheck/expect_contains_test.go @@ -28,7 +28,7 @@ func TestExpectContains_CheckState_ResourceOneNotFound(t *testing.T) { Config: `resource "test_resource" "one" {} resource "test_resource" "two" {}`, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectContains( "does_not_exist_one", tfjsonpath.New("bool_attribute"), @@ -56,7 +56,7 @@ func TestExpectContains_CheckState_ResourceTwoNotFound(t *testing.T) { Config: `resource "test_resource" "one" {} resource "test_resource" "two" {}`, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectContains( "test_resource.one", tfjsonpath.New("bool_attribute"), @@ -84,7 +84,7 @@ func TestExpectContains_CheckState_AttributeOneNotFound(t *testing.T) { Config: `resource "test_resource" "one" {} resource "test_resource" "two" {}`, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectContains( "test_resource.one", tfjsonpath.New("does_not_exist_one"), @@ -112,7 +112,7 @@ func TestExpectContains_CheckState_AttributeTwoNotFound(t *testing.T) { Config: `resource "test_resource" "one" {} resource "test_resource" "two" {}`, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectContains( "test_resource.one", tfjsonpath.New("bool_attribute"), @@ -142,7 +142,7 @@ func TestExpectContains_CheckState_AttributeOneNotSet(t *testing.T) { } resource "test_resource" "two" {}`, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectContains( "test_resource.one", tfjsonpath.New("bool_attribute"), @@ -178,7 +178,7 @@ func TestExpectContains_CheckState_NotFound(t *testing.T) { "value2" ] }`, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectContains( "test_resource.two", tfjsonpath.New("set_attribute"), @@ -213,7 +213,7 @@ func TestExpectContains_CheckState_Found(t *testing.T) { "value2" ] }`, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectContains( "test_resource.two", tfjsonpath.New("set_attribute"), diff --git a/statecheck/expect_known_output_value_at_path_example_test.go b/statecheck/expect_known_output_value_at_path_example_test.go index 5dc5944fa..692067a16 100644 --- a/statecheck/expect_known_output_value_at_path_example_test.go +++ b/statecheck/expect_known_output_value_at_path_example_test.go @@ -28,11 +28,11 @@ func ExampleExpectKnownOutputValueAtPath() { value = test_resource.one } `, - ConfigStateChecks: resource.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("bool_attribute"), - knownvalue.BoolExact(true), + knownvalue.Bool(true), ), }, }, diff --git a/statecheck/expect_known_output_value_at_path_test.go b/statecheck/expect_known_output_value_at_path_test.go index 1b94031dd..050fd8f67 100644 --- a/statecheck/expect_known_output_value_at_path_test.go +++ b/statecheck/expect_known_output_value_at_path_test.go @@ -1425,7 +1425,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_String_Custom(t *testing.T) { value = test_resource.one } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", tfjsonpath.New("string_attribute"), diff --git a/statecheck/expect_known_output_value_example_test.go b/statecheck/expect_known_output_value_example_test.go index 6335f856e..faeac222e 100644 --- a/statecheck/expect_known_output_value_example_test.go +++ b/statecheck/expect_known_output_value_example_test.go @@ -27,10 +27,10 @@ func ExampleExpectKnownOutputValue() { value = test_resource.one.bool_attribute } `, - ConfigStateChecks: resource.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "bool_output", - knownvalue.BoolExact(true), + knownvalue.Bool(true), ), }, }, diff --git a/statecheck/expect_known_output_value_test.go b/statecheck/expect_known_output_value_test.go index 40524dc85..f3c7d0d2c 100644 --- a/statecheck/expect_known_output_value_test.go +++ b/statecheck/expect_known_output_value_test.go @@ -1350,7 +1350,7 @@ func TestExpectKnownOutputValue_CheckState_String_Custom(t *testing.T) { value = test_resource.one.string_attribute } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( "string_output", StringContains("str")), diff --git a/statecheck/expect_known_value_example_test.go b/statecheck/expect_known_value_example_test.go index a54337258..f3792e8e3 100644 --- a/statecheck/expect_known_value_example_test.go +++ b/statecheck/expect_known_value_example_test.go @@ -24,11 +24,11 @@ func ExampleExpectKnownValue() { bool_attribute = true } `, - ConfigStateChecks: resource.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), - knownvalue.BoolExact(true), + knownvalue.Bool(true), ), }, }, diff --git a/statecheck/expect_known_value_test.go b/statecheck/expect_known_value_test.go index a9063f29d..3beb53cc0 100644 --- a/statecheck/expect_known_value_test.go +++ b/statecheck/expect_known_value_test.go @@ -158,12 +158,12 @@ func TestExpectKnownValue_CheckState_BoolPointer(t *testing.T) { bool_attribute = true } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ AlterValue(testBool), statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("bool_attribute"), - knownvalue.BoolExact(*testBool), + knownvalue.Bool(*testBool), ), }, }, @@ -1226,7 +1226,7 @@ func TestExpectKnownValue_CheckState_SetNestedBlock_Custom(t *testing.T) { } } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("set_nested_block"), @@ -1354,7 +1354,7 @@ func TestExpectKnownValue_CheckState_String_Custom(t *testing.T) { string_attribute = "string" } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("string_attribute"), diff --git a/statecheck/expect_matching_values_example_test.go b/statecheck/expect_matching_values_example_test.go index b75a78091..484bb2af2 100644 --- a/statecheck/expect_matching_values_example_test.go +++ b/statecheck/expect_matching_values_example_test.go @@ -26,7 +26,7 @@ func ExampleExpectMatchingValues() { resource "test_resource" "two" { bool_attribute = true }`, - ConfigStateChecks: resource.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectMatchingValues( "test_resource.one", tfjsonpath.New("bool_attribute"), diff --git a/statecheck/expect_matching_values_test.go b/statecheck/expect_matching_values_test.go index dbc654626..35d86f363 100644 --- a/statecheck/expect_matching_values_test.go +++ b/statecheck/expect_matching_values_test.go @@ -28,7 +28,7 @@ func TestExpectMatchingValues_CheckState_ResourceOneNotFound(t *testing.T) { Config: `resource "test_resource" "one" {} resource "test_resource" "two" {}`, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectMatchingValues( "does_not_exist_one", tfjsonpath.New("bool_attribute"), @@ -56,7 +56,7 @@ func TestExpectMatchingValues_CheckState_ResourceTwoNotFound(t *testing.T) { Config: `resource "test_resource" "one" {} resource "test_resource" "two" {}`, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectMatchingValues( "test_resource.one", tfjsonpath.New("bool_attribute"), @@ -84,7 +84,7 @@ func TestExpectMatchingValues_CheckState_AttributeOneNotFound(t *testing.T) { Config: `resource "test_resource" "one" {} resource "test_resource" "two" {}`, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectMatchingValues( "test_resource.one", tfjsonpath.New("does_not_exist_one"), @@ -112,7 +112,7 @@ func TestExpectMatchingValues_CheckState_AttributeTwoNotFound(t *testing.T) { Config: `resource "test_resource" "one" {} resource "test_resource" "two" {}`, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectMatchingValues( "test_resource.one", tfjsonpath.New("bool_attribute"), @@ -142,7 +142,7 @@ func TestExpectMatchingValues_CheckState_AttributeValuesNotEqualNil(t *testing.T } resource "test_resource" "two" {}`, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectMatchingValues( "test_resource.one", tfjsonpath.New("bool_attribute"), @@ -174,7 +174,7 @@ func TestExpectMatchingValues_CheckState_AttributeValuesNotEqual(t *testing.T) { resource "test_resource" "two" { bool_attribute = false }`, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectMatchingValues( "test_resource.one", tfjsonpath.New("bool_attribute"), @@ -206,7 +206,7 @@ func TestExpectMatchingValues_CheckState_AttributeValuesEqual_Bool(t *testing.T) resource "test_resource" "two" { bool_attribute = true }`, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectMatchingValues( "test_resource.one", tfjsonpath.New("bool_attribute"), @@ -243,7 +243,7 @@ func TestExpectMatchingValues_CheckState_AttributeValuesEqual_List(t *testing.T) "value2" ] }`, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectMatchingValues( "test_resource.one", tfjsonpath.New("list_attribute"), diff --git a/statecheck/expect_no_value_exists_example_test.go b/statecheck/expect_no_value_exists_example_test.go index b8f9b9fa4..14f66a583 100644 --- a/statecheck/expect_no_value_exists_example_test.go +++ b/statecheck/expect_no_value_exists_example_test.go @@ -23,7 +23,7 @@ func ExampleExpectNoValueExists() { bool_attribute = true } `, - ConfigStateChecks: resource.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectNoValueExists( "test_resource.one", tfjsonpath.New("does_not_exist"), diff --git a/statecheck/expect_no_value_exists_test.go b/statecheck/expect_no_value_exists_test.go index c21e95d81..d17d3cf7f 100644 --- a/statecheck/expect_no_value_exists_test.go +++ b/statecheck/expect_no_value_exists_test.go @@ -29,7 +29,7 @@ func TestExpectNoValueExists_CheckState_ResourceNotFound(t *testing.T) { bool_attribute = true } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectNoValueExists( "does_not_exist", tfjsonpath.New("bool_attribute"), @@ -55,7 +55,7 @@ func TestExpectNoValueExists_CheckState_AttributeNotFound(t *testing.T) { bool_attribute = true } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectNoValueExists( "test_resource.one", tfjsonpath.New("does_not_exist"), @@ -81,7 +81,7 @@ func TestExpectNoValueExists_CheckState_AttributeFound(t *testing.T) { bool_attribute = true } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectNoValueExists( "test_resource.one", tfjsonpath.New("bool_attribute"), diff --git a/statecheck/expect_value_exists_example_test.go b/statecheck/expect_value_exists_example_test.go index 64ff5346c..de11b8fd1 100644 --- a/statecheck/expect_value_exists_example_test.go +++ b/statecheck/expect_value_exists_example_test.go @@ -23,7 +23,7 @@ func ExampleExpectValueExists() { bool_attribute = true } `, - ConfigStateChecks: resource.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectValueExists( "test_resource.one", tfjsonpath.New("bool_attribute"), diff --git a/statecheck/expect_value_exists_test.go b/statecheck/expect_value_exists_test.go index fb1760d59..47d7d897b 100644 --- a/statecheck/expect_value_exists_test.go +++ b/statecheck/expect_value_exists_test.go @@ -29,7 +29,7 @@ func TestExpectValueExists_CheckState_ResourceNotFound(t *testing.T) { bool_attribute = true } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectValueExists( "does_not_exist", tfjsonpath.New("bool_attribute"), @@ -56,7 +56,7 @@ func TestExpectValueExists_CheckState_AttributeNotFound(t *testing.T) { bool_attribute = true } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectValueExists( "test_resource.one", tfjsonpath.New("does_not_exist"), @@ -83,7 +83,7 @@ func TestExpectValueExists_CheckState_AttributeFound(t *testing.T) { bool_attribute = true } `, - ConfigStateChecks: r.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectValueExists( "test_resource.one", tfjsonpath.New("bool_attribute"), diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx index e12a468fe..67a796ea3 100644 --- a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx @@ -50,7 +50,7 @@ func TestExpectContains_CheckState_Found(t *testing.T) { "value2" ] }`, - ConfigStateChecks: resource.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectContains( "test_resource.two", tfjsonpath.New("set_attribute"), @@ -136,7 +136,7 @@ func TestExpectMatchingValues_CheckState_AttributeValuesEqual_Bool(t *testing.T) resource "test_resource" "two" { bool_attribute = true }`, - ConfigStateChecks: resource.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectMatchingValues( "test_resource.one", tfjsonpath.New("bool_attribute"), @@ -176,7 +176,7 @@ func TestExpectNoValueExists_CheckState_AttributeNotFound(t *testing.T) { bool_attribute = true } `, - ConfigStateChecks: resource.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectNoValueExists( "test_resource.one", tfjsonpath.New("does_not_exist"), @@ -257,7 +257,7 @@ func TestExpectValueExists_CheckState_AttributeFound(t *testing.T) { bool_attribute = true } `, - ConfigStateChecks: resource.ConfigStateChecks{ + ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectValueExists( "test_resource.one", tfjsonpath.New("bool_attribute"), From bbe401047f8b1edca4f100967395d055d21328ca Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Thu, 25 Jan 2024 13:20:47 +0000 Subject: [PATCH 51/73] Removing ExpectValueExists state check * Adding known value not null check type --- .../unreleased/FEATURES-20240117-170016.yaml | 6 -- helper/resource/testing.go | 12 ++- knownvalue/not_null.go | 32 ++++++ knownvalue/not_null_test.go | 61 +++++++++++ knownvalue/null.go | 6 +- knownvalue/null_test.go | 6 +- .../expect_known_output_value_at_path_test.go | 87 +++++++++++++++ plancheck/expect_known_output_value_test.go | 101 ++++++++++++++++++ plancheck/expect_known_value_test.go | 82 ++++++++++++++ .../expect_known_output_value_at_path_test.go | 85 +++++++++++++++ statecheck/expect_known_output_value_test.go | 99 +++++++++++++++++ statecheck/expect_known_value_test.go | 82 +++++++++++++- statecheck/expect_value_exists.go | 75 ------------- .../expect_value_exists_example_test.go | 35 ------ statecheck/expect_value_exists_test.go | 95 ---------------- website/data/plugin-testing-nav-data.json | 4 + .../known-value-checks/index.mdx | 24 +++-- .../known-value-checks/not-null.mdx | 41 +++++++ .../state-checks/resource.mdx | 39 ------- 19 files changed, 697 insertions(+), 275 deletions(-) delete mode 100644 .changes/unreleased/FEATURES-20240117-170016.yaml create mode 100644 knownvalue/not_null.go create mode 100644 knownvalue/not_null_test.go delete mode 100644 statecheck/expect_value_exists.go delete mode 100644 statecheck/expect_value_exists_example_test.go delete mode 100644 statecheck/expect_value_exists_test.go create mode 100644 website/docs/plugin/testing/acceptance-tests/known-value-checks/not-null.mdx diff --git a/.changes/unreleased/FEATURES-20240117-170016.yaml b/.changes/unreleased/FEATURES-20240117-170016.yaml deleted file mode 100644 index ac83b8291..000000000 --- a/.changes/unreleased/FEATURES-20240117-170016.yaml +++ /dev/null @@ -1,6 +0,0 @@ -kind: FEATURES -body: 'statecheck: Added `ExpectValueExists` built-in state check, which asserts that - a given attribute exists' -time: 2024-01-17T17:00:16.411155Z -custom: - Issue: "276" diff --git a/helper/resource/testing.go b/helper/resource/testing.go index 0f6febb63..b6e3c4bf0 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -1056,10 +1056,10 @@ func ComposeAggregateTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc { // the special .# or .% key syntax for those situations instead. // // Deprecated: State checks have been superseded by ConfigStateChecks. -// Use the built-in statecheck.ExpectValueExists state check instead. +// Use the built-in statecheck.KnownValue state check with knownvalue.NotNull instead. // TestCheckResourceAttrSet function will be removed in the next major version. // -// The following is an example of using statecheck.ExpectValueExists +// The following is an example of using statecheck.ExpectKnownValue with knownvalue.NotNull // to replicate the behaviour of TestCheckResourceAttrSet. // // package example_test @@ -1072,7 +1072,7 @@ func ComposeAggregateTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc { // "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" // ) // -// func TestExpectValueExists_CheckState_AttributeFound(t *testing.T) { +// func TestExpectKnownValue_CheckState_AttributeFound(t *testing.T) { // t.Parallel() // // resource.Test(t, resource.TestCase{ @@ -1084,9 +1084,10 @@ func ComposeAggregateTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc { // } // `, // ConfigStateChecks: []statecheck.StateCheck{ -// statecheck.ExpectValueExists( +// statecheck.ExpectKnownValue( // "test_resource.one", // tfjsonpath.New("bool_attribute"), +// knownvalue.NotNull(), // ), // }, // }, @@ -1094,7 +1095,8 @@ func ComposeAggregateTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc { // }) // } // -// [ExpectValueExists]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectValueExists +// [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue +// [NotNull]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NotNull // [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck // [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck func TestCheckResourceAttrSet(name, key string) TestCheckFunc { diff --git a/knownvalue/not_null.go b/knownvalue/not_null.go new file mode 100644 index 000000000..d7ae68904 --- /dev/null +++ b/knownvalue/not_null.go @@ -0,0 +1,32 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package knownvalue + +import ( + "fmt" +) + +var _ Check = notNull{} + +type notNull struct{} + +// CheckValue determines whether the passed value is nil. +func (v notNull) CheckValue(other any) error { + if other == nil { + return fmt.Errorf("expected non-nil value for NotNull check, got: %T", other) + } + + return nil +} + +// String returns the string representation of notNull. +func (v notNull) String() string { + return "not-null" +} + +// NotNull returns a Check for asserting the value passed +// to the CheckValue method is not nil. +func NotNull() notNull { + return notNull{} +} diff --git a/knownvalue/not_null_test.go b/knownvalue/not_null_test.go new file mode 100644 index 000000000..908c4b769 --- /dev/null +++ b/knownvalue/not_null_test.go @@ -0,0 +1,61 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package knownvalue_test + +import ( + "fmt" + "testing" + + "github.com/google/go-cmp/cmp" + + "github.com/hashicorp/terraform-plugin-testing/knownvalue" +) + +func TestNotNullValue_CheckValue(t *testing.T) { + t.Parallel() + + testCases := map[string]struct { + self knownvalue.Check + other any + expectedError error + }{ + "zero-nil": { + self: knownvalue.NotNull(), + expectedError: fmt.Errorf("expected non-nil value for NotNull check, got: "), + }, + "not-nil": { + self: knownvalue.NotNull(), + other: nil, + expectedError: fmt.Errorf("expected non-nil value for NotNull check, got: "), + }, + "equal": { + self: knownvalue.NotNull(), + other: true, + }, + } + + 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 TestNotNullValue_String(t *testing.T) { + t.Parallel() + + got := knownvalue.NotNull().String() + + if diff := cmp.Diff(got, "not-null"); diff != "" { + t.Errorf("unexpected difference: %s", diff) + } +} diff --git a/knownvalue/null.go b/knownvalue/null.go index a8bbaee9f..24e6b7e2b 100644 --- a/knownvalue/null.go +++ b/knownvalue/null.go @@ -14,7 +14,7 @@ type null struct{} // CheckValue determines whether the passed value is nil. func (v null) CheckValue(other any) error { if other != nil { - return fmt.Errorf("expected value nil for Null check, got: %T", other) + return fmt.Errorf("expected nil value for Null check, got: %T", other) } return nil @@ -25,8 +25,8 @@ func (v null) String() string { return "null" } -// Null returns a Check for asserting equality nil -// and the value passed to the CheckValue method. +// Null returns a Check for asserting the value passed +// to the CheckValue method is nil. func Null() null { return null{} } diff --git a/knownvalue/null_test.go b/knownvalue/null_test.go index e7bb5531d..a9cc33d97 100644 --- a/knownvalue/null_test.go +++ b/knownvalue/null_test.go @@ -23,14 +23,10 @@ func TestNullValue_CheckValue(t *testing.T) { "zero-nil": { self: knownvalue.Null(), }, - "zero-other": { - self: knownvalue.Null(), - other: nil, // checking against the underlying value field zero-value - }, "not-nil": { self: knownvalue.Null(), other: false, - expectedError: fmt.Errorf("expected value nil for Null check, got: bool"), + expectedError: fmt.Errorf("expected nil value for Null check, got: bool"), }, "equal": { self: knownvalue.Null(), diff --git a/plancheck/expect_known_output_value_at_path_test.go b/plancheck/expect_known_output_value_at_path_test.go index fc643523d..5ab769d6d 100644 --- a/plancheck/expect_known_output_value_at_path_test.go +++ b/plancheck/expect_known_output_value_at_path_test.go @@ -140,6 +140,93 @@ func TestExpectKnownOutputValueAtPath_CheckPlan_AttributeValueNull(t *testing.T) }) } +func TestExpectKnownOutputValueAtPath_CheckPlan_AttributeValueNotNull(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + float_attribute = 1.23 + int_attribute = 123 + list_attribute = ["value1", "value2"] + list_nested_block { + list_nested_block_attribute = "str" + } + map_attribute = { + key1 = "value1" + } + set_attribute = ["value1", "value2"] + set_nested_block { + set_nested_block_attribute = "str" + } + string_attribute = "str" + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigPlanChecks: r.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("bool_attribute"), + knownvalue.NotNull(), + ), + plancheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("float_attribute"), + knownvalue.NotNull(), + ), + plancheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("int_attribute"), + knownvalue.NotNull(), + ), + plancheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("list_attribute"), + knownvalue.NotNull(), + ), + plancheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("list_nested_block"), + knownvalue.ListSizeExact(1), + ), + plancheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("map_attribute"), + knownvalue.NotNull(), + ), + plancheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("set_attribute"), + knownvalue.NotNull(), + ), + plancheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("set_nested_block"), + knownvalue.SetSizeExact(1), + ), + plancheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("string_attribute"), + knownvalue.NotNull(), + ), + }, + }, + }, + }, + }) +} + func TestExpectKnownOutputValueAtPath_CheckPlan_Bool(t *testing.T) { t.Parallel() diff --git a/plancheck/expect_known_output_value_test.go b/plancheck/expect_known_output_value_test.go index da45a00d0..0bde45150 100644 --- a/plancheck/expect_known_output_value_test.go +++ b/plancheck/expect_known_output_value_test.go @@ -137,6 +137,107 @@ func TestExpectKnownOutputValue_CheckPlan_AttributeValueNull(t *testing.T) { }) } +func TestExpectKnownOutputValue_CheckPlan_AttributeValueNotNull(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + float_attribute = 1.23 + int_attribute = 123 + list_attribute = ["value1", "value2"] + list_nested_block { + list_nested_block_attribute = "str" + } + map_attribute = { + key1 = "value1" + } + set_attribute = ["value1", "value2"] + set_nested_block { + set_nested_block_attribute = "str" + } + string_attribute = "str" + } + output bool_output { + value = test_resource.one.bool_attribute + } + output float64_output { + value = test_resource.one.float_attribute + } + output int64_output { + value = test_resource.one.int_attribute + } + output list_output { + value = test_resource.one.list_attribute + } + output list_nested_block_output { + value = test_resource.one.list_nested_block + } + output map_output { + value = test_resource.one.map_attribute + } + output set_output { + value = test_resource.one.set_attribute + } + output set_nested_block_output { + value = test_resource.one.set_nested_block + } + output string_output { + value = test_resource.one.string_attribute + } + `, + ConfigPlanChecks: r.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectKnownOutputValue( + "bool_output", + knownvalue.NotNull(), + ), + plancheck.ExpectKnownOutputValue( + "float64_output", + knownvalue.NotNull(), + ), + plancheck.ExpectKnownOutputValue( + "int64_output", + knownvalue.NotNull(), + ), + plancheck.ExpectKnownOutputValue( + "list_output", + knownvalue.NotNull(), + ), + plancheck.ExpectKnownOutputValue( + "list_nested_block_output", + knownvalue.ListSizeExact(1), + ), + plancheck.ExpectKnownOutputValue( + "map_output", + knownvalue.NotNull(), + ), + plancheck.ExpectKnownOutputValue( + "set_output", + knownvalue.NotNull(), + ), + plancheck.ExpectKnownOutputValue( + "set_nested_block_output", + knownvalue.ListSizeExact(1), + ), + plancheck.ExpectKnownOutputValue( + "string_output", + knownvalue.NotNull(), + ), + }, + }, + }, + }, + }) +} + func TestExpectKnownOutputValue_CheckPlan_Bool(t *testing.T) { t.Parallel() diff --git a/plancheck/expect_known_value_test.go b/plancheck/expect_known_value_test.go index 85405f1e8..63a68d7e9 100644 --- a/plancheck/expect_known_value_test.go +++ b/plancheck/expect_known_value_test.go @@ -116,6 +116,88 @@ func TestExpectKnownValue_CheckPlan_AttributeValueNull(t *testing.T) { }) } +func TestExpectKnownValue_CheckPlan_AttributeValueNotNull(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + float_attribute = 1.23 + int_attribute = 123 + list_attribute = ["value1", "value2"] + list_nested_block { + list_nested_block_attribute = "str" + } + map_attribute = { + key1 = "value1" + } + set_attribute = ["value1", "value2"] + set_nested_block { + set_nested_block_attribute = "str" + } + string_attribute = "str" + }`, + ConfigPlanChecks: r.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + knownvalue.NotNull(), + ), + plancheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("float_attribute"), + knownvalue.NotNull(), + ), + plancheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("int_attribute"), + knownvalue.NotNull(), + ), + plancheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("list_attribute"), + knownvalue.NotNull(), + ), + plancheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("list_nested_block"), + knownvalue.ListSizeExact(1), + ), + plancheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("map_attribute"), + knownvalue.NotNull(), + ), + plancheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("set_attribute"), + knownvalue.NotNull(), + ), + plancheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("set_nested_block"), + knownvalue.SetSizeExact(1), + ), + plancheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("string_attribute"), + knownvalue.NotNull(), + ), + }, + }, + }, + }, + }) +} + func TestExpectKnownValue_CheckPlan_Bool(t *testing.T) { t.Parallel() diff --git a/statecheck/expect_known_output_value_at_path_test.go b/statecheck/expect_known_output_value_at_path_test.go index 050fd8f67..0b6013bcd 100644 --- a/statecheck/expect_known_output_value_at_path_test.go +++ b/statecheck/expect_known_output_value_at_path_test.go @@ -121,6 +121,91 @@ func TestExpectKnownOutputValueAtPath_CheckState_AttributeValueNull(t *testing.T }) } +func TestExpectKnownOutputValueAtPath_CheckState_AttributeValueNotNull(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + float_attribute = 1.23 + int_attribute = 123 + list_attribute = ["value1", "value2"] + list_nested_block { + list_nested_block_attribute = "str" + } + map_attribute = { + key1 = "value1" + } + set_attribute = ["value1", "value2"] + set_nested_block { + set_nested_block_attribute = "str" + } + string_attribute = "str" + } + + output test_resource_one_output { + value = test_resource.one + } + `, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("bool_attribute"), + knownvalue.NotNull(), + ), + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("float_attribute"), + knownvalue.NotNull(), + ), + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("int_attribute"), + knownvalue.NotNull(), + ), + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("list_attribute"), + knownvalue.NotNull(), + ), + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("list_nested_block"), + knownvalue.ListSizeExact(1), + ), + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("map_attribute"), + knownvalue.NotNull(), + ), + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("set_attribute"), + knownvalue.NotNull(), + ), + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("set_nested_block"), + knownvalue.SetSizeExact(1), + ), + statecheck.ExpectKnownOutputValueAtPath( + "test_resource_one_output", + tfjsonpath.New("string_attribute"), + knownvalue.NotNull(), + ), + }, + }, + }, + }) +} + func TestExpectKnownOutputValueAtPath_CheckState_Bool(t *testing.T) { t.Parallel() diff --git a/statecheck/expect_known_output_value_test.go b/statecheck/expect_known_output_value_test.go index f3c7d0d2c..8b4dc3293 100644 --- a/statecheck/expect_known_output_value_test.go +++ b/statecheck/expect_known_output_value_test.go @@ -82,6 +82,105 @@ func TestExpectKnownOutputValue_CheckState_AttributeValueNull(t *testing.T) { }) } +func TestExpectKnownOutputValue_CheckState_AttributeValueNotNull(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + float_attribute = 1.23 + int_attribute = 123 + list_attribute = ["value1", "value2"] + list_nested_block { + list_nested_block_attribute = "str" + } + map_attribute = { + key1 = "value1" + } + set_attribute = ["value1", "value2"] + set_nested_block { + set_nested_block_attribute = "str" + } + string_attribute = "str" + } + output bool_output { + value = test_resource.one.bool_attribute + } + output float64_output { + value = test_resource.one.float_attribute + } + output int64_output { + value = test_resource.one.int_attribute + } + output list_output { + value = test_resource.one.list_attribute + } + output list_nested_block_output { + value = test_resource.one.list_nested_block + } + output map_output { + value = test_resource.one.map_attribute + } + output set_output { + value = test_resource.one.set_attribute + } + output set_nested_block_output { + value = test_resource.one.set_nested_block + } + output string_output { + value = test_resource.one.string_attribute + } + `, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownOutputValue( + "bool_output", + knownvalue.NotNull(), + ), + statecheck.ExpectKnownOutputValue( + "float64_output", + knownvalue.NotNull(), + ), + statecheck.ExpectKnownOutputValue( + "int64_output", + knownvalue.NotNull(), + ), + statecheck.ExpectKnownOutputValue( + "list_output", + knownvalue.NotNull(), + ), + statecheck.ExpectKnownOutputValue( + "list_nested_block_output", + knownvalue.ListSizeExact(1), + ), + statecheck.ExpectKnownOutputValue( + "map_output", + knownvalue.NotNull(), + ), + statecheck.ExpectKnownOutputValue( + "set_output", + knownvalue.NotNull(), + ), + statecheck.ExpectKnownOutputValue( + "set_nested_block_output", + knownvalue.ListSizeExact(1), + ), + statecheck.ExpectKnownOutputValue( + "string_output", + knownvalue.NotNull(), + ), + }, + }, + }, + }) +} + func TestExpectKnownOutputValue_CheckState_Bool(t *testing.T) { t.Parallel() diff --git a/statecheck/expect_known_value_test.go b/statecheck/expect_known_value_test.go index 3beb53cc0..eb2bbbffd 100644 --- a/statecheck/expect_known_value_test.go +++ b/statecheck/expect_known_value_test.go @@ -101,7 +101,7 @@ func TestExpectKnownValue_CheckState_AttributeValueNull(t *testing.T) { statecheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("set_nested_block"), - knownvalue.ListExact([]knownvalue.Check{}), + knownvalue.SetExact([]knownvalue.Check{}), ), statecheck.ExpectKnownValue( "test_resource.one", @@ -114,6 +114,86 @@ func TestExpectKnownValue_CheckState_AttributeValueNull(t *testing.T) { }) } +func TestExpectKnownValue_CheckState_AttributeValueNotNull(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + float_attribute = 1.23 + int_attribute = 123 + list_attribute = ["value1", "value2"] + list_nested_block { + list_nested_block_attribute = "str" + } + map_attribute = { + key1 = "value1" + } + set_attribute = ["value1", "value2"] + set_nested_block { + set_nested_block_attribute = "str" + } + string_attribute = "str" + }`, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + knownvalue.NotNull(), + ), + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("float_attribute"), + knownvalue.NotNull(), + ), + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("int_attribute"), + knownvalue.NotNull(), + ), + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("list_attribute"), + knownvalue.NotNull(), + ), + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("list_nested_block"), + knownvalue.ListSizeExact(1), + ), + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("map_attribute"), + knownvalue.NotNull(), + ), + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("set_attribute"), + knownvalue.NotNull(), + ), + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("set_nested_block"), + knownvalue.SetSizeExact(1), + ), + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("string_attribute"), + knownvalue.NotNull(), + ), + }, + }, + }, + }) +} + func TestExpectKnownValue_CheckState_Bool(t *testing.T) { t.Parallel() diff --git a/statecheck/expect_value_exists.go b/statecheck/expect_value_exists.go deleted file mode 100644 index 05d443b9f..000000000 --- a/statecheck/expect_value_exists.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package statecheck - -import ( - "context" - "fmt" - - tfjson "github.com/hashicorp/terraform-json" - - "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -) - -// Resource State Check -var _ StateCheck = expectValueExists{} - -type expectValueExists struct { - resourceAddress string - attributePath tfjsonpath.Path -} - -// CheckState implements the state check logic. -func (e expectValueExists) CheckState(ctx context.Context, req CheckStateRequest, resp *CheckStateResponse) { - var resource *tfjson.StateResource - - if req.State == nil { - resp.Error = fmt.Errorf("state is nil") - - return - } - - if req.State.Values == nil { - resp.Error = fmt.Errorf("state does not contain any state values") - - return - } - - if req.State.Values.RootModule == nil { - resp.Error = fmt.Errorf("state does not contain a root module") - - return - } - - for _, r := range req.State.Values.RootModule.Resources { - if e.resourceAddress == r.Address { - resource = r - - break - } - } - - if resource == nil { - resp.Error = fmt.Errorf("%s - Resource not found in state", e.resourceAddress) - - return - } - - _, err := tfjsonpath.Traverse(resource.AttributeValues, e.attributePath) - - if err != nil { - resp.Error = err - - return - } -} - -// ExpectValueExists returns a state check that asserts that the specified -// attribute at the given resource exists. -func ExpectValueExists(resourceAddress string, attributePath tfjsonpath.Path) StateCheck { - return expectValueExists{ - resourceAddress: resourceAddress, - attributePath: attributePath, - } -} diff --git a/statecheck/expect_value_exists_example_test.go b/statecheck/expect_value_exists_example_test.go deleted file mode 100644 index de11b8fd1..000000000 --- a/statecheck/expect_value_exists_example_test.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package statecheck_test - -import ( - "testing" - - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/statecheck" - "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -) - -func ExampleExpectValueExists() { - t := &testing.T{} - t.Parallel() - - resource.Test(t, resource.TestCase{ - // Provider definition omitted. - Steps: []resource.TestStep{ - { - Config: `resource "test_resource" "one" { - bool_attribute = true - } - `, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectValueExists( - "test_resource.one", - tfjsonpath.New("bool_attribute"), - ), - }, - }, - }, - }) -} diff --git a/statecheck/expect_value_exists_test.go b/statecheck/expect_value_exists_test.go deleted file mode 100644 index 47d7d897b..000000000 --- a/statecheck/expect_value_exists_test.go +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package statecheck_test - -import ( - "regexp" - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - - r "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/statecheck" - "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -) - -func TestExpectValueExists_CheckState_ResourceNotFound(t *testing.T) { - t.Parallel() - - r.Test(t, r.TestCase{ - ProviderFactories: map[string]func() (*schema.Provider, error){ - "test": func() (*schema.Provider, error) { //nolint:unparam // required signature - return testProvider(), nil - }, - }, - Steps: []r.TestStep{ - { - Config: `resource "test_resource" "one" { - bool_attribute = true - } - `, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectValueExists( - "does_not_exist", - tfjsonpath.New("bool_attribute"), - ), - }, - ExpectError: regexp.MustCompile(`does_not_exist - Resource not found in state`), - }, - }, - }) -} - -func TestExpectValueExists_CheckState_AttributeNotFound(t *testing.T) { - t.Parallel() - - r.Test(t, r.TestCase{ - ProviderFactories: map[string]func() (*schema.Provider, error){ - "test": func() (*schema.Provider, error) { //nolint:unparam // required signature - return testProvider(), nil - }, - }, - Steps: []r.TestStep{ - { - Config: `resource "test_resource" "one" { - bool_attribute = true - } - `, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectValueExists( - "test_resource.one", - tfjsonpath.New("does_not_exist"), - ), - }, - ExpectError: regexp.MustCompile(`path not found: specified key does_not_exist not found in map at does_not_exist`), - }, - }, - }) -} - -func TestExpectValueExists_CheckState_AttributeFound(t *testing.T) { - t.Parallel() - - r.Test(t, r.TestCase{ - ProviderFactories: map[string]func() (*schema.Provider, error){ - "test": func() (*schema.Provider, error) { //nolint:unparam // required signature - return testProvider(), nil - }, - }, - Steps: []r.TestStep{ - { - Config: `resource "test_resource" "one" { - bool_attribute = true - } - `, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectValueExists( - "test_resource.one", - tfjsonpath.New("bool_attribute"), - ), - }, - }, - }, - }) -} diff --git a/website/data/plugin-testing-nav-data.json b/website/data/plugin-testing-nav-data.json index f7ae6d8b5..bb9740043 100644 --- a/website/data/plugin-testing-nav-data.json +++ b/website/data/plugin-testing-nav-data.json @@ -102,6 +102,10 @@ "title": "Map", "path": "acceptance-tests/known-value-checks/map" }, + { + "title": "NotNull", + "path": "acceptance-tests/known-value-checks/not-null" + }, { "title": "Null", "path": "acceptance-tests/known-value-checks/null" diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/index.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/index.mdx index 3da43b44c..2d06a3d79 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/index.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/index.mdx @@ -36,15 +36,17 @@ knownvalue.ListExact([]knownvalue.Check{ The following table shows the correspondence between [knownvalue.Check](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check) types, and attributes. -| 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` | -| [Float64 Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks/float64) | `schema.Float64Attribute` | `schema.TypeFloat` | -| [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` | -| [Number Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks/number) | `schema.NumberAttribute` | N/A | -| [Object Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks/object) | `schema.ObjectAttribute` | N/A | -| [Set Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks/set) | `schema.SetAttribute` | `schema.TypeSet` | -| [String Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks/string) | `schema.StringAttribute` | `schema.TypeString` | +| 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` | +| [Float64 Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks/float64) | `schema.Float64Attribute` | `schema.TypeFloat` | +| [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` | +| [NotNull Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks/not-null) | All | All | +| [Null Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks/null) | All | All | +| [Number Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks/number) | `schema.NumberAttribute` | N/A | +| [Object Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks/object) | `schema.ObjectAttribute` | N/A | +| [Set Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks/set) | `schema.SetAttribute` | `schema.TypeSet` | +| [String Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks/string) | `schema.StringAttribute` | `schema.TypeString` | diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/not-null.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/not-null.mdx new file mode 100644 index 000000000..edea7c2b5 --- /dev/null +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/not-null.mdx @@ -0,0 +1,41 @@ +--- +page_title: 'Plugin Development - Acceptance Testing: Known Values' +description: >- + NotNull Value Checks for use with Plan Checks or State Checks. +--- + +# NotNull Known Value Checks + +The known value checks that are available for values that are not null are: + +* [NotNull](/terraform/plugin/testing/acceptance-tests/known-value-checks/null#notnull-check) + +## `NotNull` Check + +The [NotNull](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NotNull) check tests that a resource attribute, or output value is not null. + +Example usage of [NotNull](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NotNull) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/state-checks/resource) state check. + +```go +func TestExpectKnownValue_CheckState_AttributeValueNull(t *testing.T) { + t.Parallel() + + r.Test(t, r.TestCase{ + // Provider definition omitted. + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" { + bool_attribute = true + }`, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("bool_attribute"), + knownvalue.NotNull(), + ), + }, + }, + }, + }) +} +``` diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx index 67a796ea3..0f9099bc5 100644 --- a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx @@ -16,7 +16,6 @@ The `terraform-plugin-testing` module provides a package [`statecheck`](https:// | [`ExpectMatchingValues`](/terraform/plugin/testing/acceptance-tests/state-checks/resource#expectmatchingvalues-state-check) | Asserts the specified attributes at the given managed resources have matching values. | | [`ExpectNoValueExists`](/terraform/plugin/testing/acceptance-tests/state-checks/resource#expectnovalueexists-state-check) | Asserts the specified attribute at the given managed resource, or data source, does not exist. | | [`ExpectSensitiveValue`](/terraform/plugin/testing/acceptance-tests/state-checks/resource#expectsensitivevalue-state-check) | Asserts the specified attribute at the given managed resource, or data source, has a sensitive value. | -| [`ExpectValueExists`](/terraform/plugin/testing/acceptance-tests/state-checks/resource#expectvalueexists-state-check) | Asserts the specified attribute at the given managed resource, or data source, exists. | ## `ExpectContains` State Check @@ -230,41 +229,3 @@ func Test_ExpectSensitiveValue_SensitiveStringAttribute(t *testing.T) { }) } ``` - -## `ExpectValueExists` State Check - -The [`statecheck.ExpectValueExists(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectValueExists) state check provides a basis for asserting that a specific resource attribute exists. - -```go -package example_test - -import ( - "testing" - - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/statecheck" - "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -) - -func TestExpectValueExists_CheckState_AttributeFound(t *testing.T) { - t.Parallel() - - resource.Test(t, resource.TestCase{ - // Provider definition omitted. - Steps: []resource.TestStep{ - { - Config: `resource "test_resource" "one" { - bool_attribute = true - } - `, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectValueExists( - "test_resource.one", - tfjsonpath.New("bool_attribute"), - ), - }, - }, - }, - }) -} -``` \ No newline at end of file From e7bb629843f398ddadb376330558c28ce3c36159 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Thu, 25 Jan 2024 13:50:15 +0000 Subject: [PATCH 52/73] Adding Terraform version check --- plancheck/expect_known_output_value_at_path_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/plancheck/expect_known_output_value_at_path_test.go b/plancheck/expect_known_output_value_at_path_test.go index 5ab769d6d..a6eca3356 100644 --- a/plancheck/expect_known_output_value_at_path_test.go +++ b/plancheck/expect_known_output_value_at_path_test.go @@ -149,6 +149,13 @@ func TestExpectKnownOutputValueAtPath_CheckPlan_AttributeValueNotNull(t *testing return testProvider(), nil }, }, + // Prior to Terraform v1.3.0 a planned output is marked as fully unknown + // if any attribute is unknown. The id attribute within the test provider + // is unknown. + // Reference: https://github.com/hashicorp/terraform/blob/v1.3/CHANGELOG.md#130-september-21-2022 + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_3_0), + }, Steps: []r.TestStep{ { Config: `resource "test_resource" "one" { From 08c363eb2f7674fcde8b554095cfbf7a1bc7407d Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Fri, 26 Jan 2024 10:04:07 +0000 Subject: [PATCH 53/73] Removing ExpectContains state check --- .../unreleased/FEATURES-20240117-170346.yaml | 7 - helper/resource/testing_sets.go | 54 +---- statecheck/expect_contains.go | 118 --------- statecheck/expect_contains_example_test.go | 43 ---- statecheck/expect_contains_test.go | 227 ------------------ .../state-checks/resource.mdx | 47 ---- 6 files changed, 5 insertions(+), 491 deletions(-) delete mode 100644 .changes/unreleased/FEATURES-20240117-170346.yaml delete mode 100644 statecheck/expect_contains.go delete mode 100644 statecheck/expect_contains_example_test.go delete mode 100644 statecheck/expect_contains_test.go diff --git a/.changes/unreleased/FEATURES-20240117-170346.yaml b/.changes/unreleased/FEATURES-20240117-170346.yaml deleted file mode 100644 index 5ff50adb8..000000000 --- a/.changes/unreleased/FEATURES-20240117-170346.yaml +++ /dev/null @@ -1,7 +0,0 @@ -kind: FEATURES -body: 'statecheck: Added `ExpectContains` built-in state check, which asserts that - the value of the first given attribute contains the value of the second given - attribute' -time: 2024-01-17T17:03:46.555777Z -custom: - Issue: "276" diff --git a/helper/resource/testing_sets.go b/helper/resource/testing_sets.go index eaaec2e7e..835ef3741 100644 --- a/helper/resource/testing_sets.go +++ b/helper/resource/testing_sets.go @@ -418,56 +418,12 @@ func TestCheckTypeSetElemAttr(name, attr, value string) TestCheckFunc { // there are multiple lists or sets in the attribute path. // // Deprecated: State checks have been superseded by ConfigStateChecks. -// Use the built-in statecheck.ExpectContains, or statecheck.ExpectMatchingValues -// state checks instead. -// TestCheckTypeSetElemAttrPair function will be removed in the next major version. +// TestCheckTypeSetElemAttrPair has been deprecated without replacement. Please +// use the GitHub issue [Deprecation of Built-In TestCheckFunc Implementations for Checking Pairs of Values] +// to indicate if you have a use-case for a built-in ConfigStateChecks state check +// function that would replicate the behaviour of TestCheckTypeSetElemAttrPair. // -// The following is an example of using statecheck.ExpectContains to replicate -// the behaviour of TestCheckTypeSetElemAttrPair. -// -// package example_test -// -// import ( -// "testing" -// -// "github.com/hashicorp/terraform-plugin-testing/helper/resource" -// "github.com/hashicorp/terraform-plugin-testing/statecheck" -// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -// ) -// -// func TestExpectContains_CheckState_Found(t *testing.T) { -// t.Parallel() -// -// resource.Test(t, resource.TestCase{ -// // Provider definition omitted. -// Steps: []resource.TestStep{ -// { -// Config: `resource "test_resource" "one" { -// string_attribute = "value1" -// } -// -// resource "test_resource" "two" { -// set_attribute = [ -// test_resource.one.string_attribute, -// "value2" -// ] -// }`, -// ConfigStateChecks: []statecheck.StateCheck{ -// statecheck.ExpectContains( -// "test_resource.two", -// tfjsonpath.New("set_attribute"), -// "test_resource.one", -// tfjsonpath.New("string_attribute"), -// ), -// }, -// }, -// }, -// }) -// } -// -// [ExpectContains]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectContains -// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck -// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck +// [Deprecation of Built-In TestCheckFunc Implementations for Checking Pairs of Values](https://github.com/hashicorp/terraform-plugin-testing/issues/282) func TestCheckTypeSetElemAttrPair(nameFirst, keyFirst, nameSecond, keySecond string) TestCheckFunc { return func(s *terraform.State) error { isFirst, err := primaryInstanceState(s, nameFirst) diff --git a/statecheck/expect_contains.go b/statecheck/expect_contains.go deleted file mode 100644 index b44a3298d..000000000 --- a/statecheck/expect_contains.go +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package statecheck - -import ( - "context" - "fmt" - "reflect" - - tfjson "github.com/hashicorp/terraform-json" - - "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -) - -// Resource State Check -var _ StateCheck = expectContains{} - -type expectContains struct { - resourceAddressOne string - attributePathOne tfjsonpath.Path - resourceAddressTwo string - attributePathTwo tfjsonpath.Path -} - -// CheckState implements the state check logic. -func (e expectContains) CheckState(ctx context.Context, req CheckStateRequest, resp *CheckStateResponse) { - var resourceOne, resourceTwo *tfjson.StateResource - - if req.State == nil { - resp.Error = fmt.Errorf("state is nil") - - return - } - - if req.State.Values == nil { - resp.Error = fmt.Errorf("state does not contain any state values") - - return - } - - if req.State.Values.RootModule == nil { - resp.Error = fmt.Errorf("state does not contain a root module") - - return - } - - for _, r := range req.State.Values.RootModule.Resources { - if e.resourceAddressOne == r.Address { - resourceOne = r - - break - } - } - - if resourceOne == nil { - resp.Error = fmt.Errorf("%s - Resource not found in state", e.resourceAddressOne) - - return - } - - resultOne, err := tfjsonpath.Traverse(resourceOne.AttributeValues, e.attributePathOne) - - if err != nil { - resp.Error = err - - return - } - - for _, r := range req.State.Values.RootModule.Resources { - if e.resourceAddressTwo == r.Address { - resourceTwo = r - - break - } - } - - if resourceTwo == nil { - resp.Error = fmt.Errorf("%s - Resource not found in state", e.resourceAddressTwo) - - return - } - - resultTwo, err := tfjsonpath.Traverse(resourceTwo.AttributeValues, e.attributePathTwo) - - if err != nil { - resp.Error = err - - return - } - - resultOneCollection, ok := resultOne.([]any) - - if !ok { - resp.Error = fmt.Errorf("%s.%s is not a collection", e.resourceAddressOne, e.attributePathOne.String()) - - return - } - - for _, v := range resultOneCollection { - if reflect.DeepEqual(v, resultTwo) { - return - } - } - - resp.Error = fmt.Errorf("value of %s.%s is not found in value of %s.%s", e.resourceAddressTwo, e.attributePathTwo.String(), e.resourceAddressOne, e.attributePathOne.String()) -} - -// ExpectContains returns a state check that asserts that the value of the second attribute is contained within the -// value of the first attribute, allowing checking of whether a set contains a value identified by another attribute. -func ExpectContains(resourceAddressOne string, attributePathOne tfjsonpath.Path, resourceAddressTwo string, attributePathTwo tfjsonpath.Path) StateCheck { - return expectContains{ - resourceAddressOne: resourceAddressOne, - attributePathOne: attributePathOne, - resourceAddressTwo: resourceAddressTwo, - attributePathTwo: attributePathTwo, - } -} diff --git a/statecheck/expect_contains_example_test.go b/statecheck/expect_contains_example_test.go deleted file mode 100644 index 242368289..000000000 --- a/statecheck/expect_contains_example_test.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package statecheck_test - -import ( - "testing" - - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/statecheck" - "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -) - -func ExampleExpectContains() { - t := &testing.T{} - t.Parallel() - - resource.Test(t, resource.TestCase{ - // Provider definition omitted. - Steps: []resource.TestStep{ - { - Config: `resource "test_resource" "one" { - string_attribute = "value1" - } - - resource "test_resource" "two" { - set_attribute = [ - test_resource.one.string_attribute, - "value2" - ] - }`, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectContains( - "test_resource.two", - tfjsonpath.New("set_attribute"), - "test_resource.one", - tfjsonpath.New("string_attribute"), - ), - }, - }, - }, - }) -} diff --git a/statecheck/expect_contains_test.go b/statecheck/expect_contains_test.go deleted file mode 100644 index 21442a1fc..000000000 --- a/statecheck/expect_contains_test.go +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package statecheck_test - -import ( - "regexp" - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - - r "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/statecheck" - "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -) - -func TestExpectContains_CheckState_ResourceOneNotFound(t *testing.T) { - t.Parallel() - - r.Test(t, r.TestCase{ - ProviderFactories: map[string]func() (*schema.Provider, error){ - "test": func() (*schema.Provider, error) { //nolint:unparam // required signature - return testProvider(), nil - }, - }, - Steps: []r.TestStep{ - { - Config: `resource "test_resource" "one" {} - - resource "test_resource" "two" {}`, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectContains( - "does_not_exist_one", - tfjsonpath.New("bool_attribute"), - "test_resource.two", - tfjsonpath.New("bool_attribute"), - ), - }, - ExpectError: regexp.MustCompile("does_not_exist_one - Resource not found in state"), - }, - }, - }) -} - -func TestExpectContains_CheckState_ResourceTwoNotFound(t *testing.T) { - t.Parallel() - - r.Test(t, r.TestCase{ - ProviderFactories: map[string]func() (*schema.Provider, error){ - "test": func() (*schema.Provider, error) { //nolint:unparam // required signature - return testProvider(), nil - }, - }, - Steps: []r.TestStep{ - { - Config: `resource "test_resource" "one" {} - - resource "test_resource" "two" {}`, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectContains( - "test_resource.one", - tfjsonpath.New("bool_attribute"), - "does_not_exist_two", - tfjsonpath.New("bool_attribute"), - ), - }, - ExpectError: regexp.MustCompile("does_not_exist_two - Resource not found in state"), - }, - }, - }) -} - -func TestExpectContains_CheckState_AttributeOneNotFound(t *testing.T) { - t.Parallel() - - r.Test(t, r.TestCase{ - ProviderFactories: map[string]func() (*schema.Provider, error){ - "test": func() (*schema.Provider, error) { //nolint:unparam // required signature - return testProvider(), nil - }, - }, - Steps: []r.TestStep{ - { - Config: `resource "test_resource" "one" {} - - resource "test_resource" "two" {}`, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectContains( - "test_resource.one", - tfjsonpath.New("does_not_exist_one"), - "test_resource.two", - tfjsonpath.New("bool_attribute"), - ), - }, - ExpectError: regexp.MustCompile("path not found: specified key does_not_exist_one not found in map at does_not_exist_one"), - }, - }, - }) -} - -func TestExpectContains_CheckState_AttributeTwoNotFound(t *testing.T) { - t.Parallel() - - r.Test(t, r.TestCase{ - ProviderFactories: map[string]func() (*schema.Provider, error){ - "test": func() (*schema.Provider, error) { //nolint:unparam // required signature - return testProvider(), nil - }, - }, - Steps: []r.TestStep{ - { - Config: `resource "test_resource" "one" {} - - resource "test_resource" "two" {}`, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectContains( - "test_resource.one", - tfjsonpath.New("bool_attribute"), - "test_resource.two", - tfjsonpath.New("does_not_exist_two"), - ), - }, - ExpectError: regexp.MustCompile("path not found: specified key does_not_exist_two not found in map at does_not_exist_two"), - }, - }, - }) -} - -func TestExpectContains_CheckState_AttributeOneNotSet(t *testing.T) { - t.Parallel() - - r.Test(t, r.TestCase{ - ProviderFactories: map[string]func() (*schema.Provider, error){ - "test": func() (*schema.Provider, error) { //nolint:unparam // required signature - return testProvider(), nil - }, - }, - Steps: []r.TestStep{ - { - Config: `resource "test_resource" "one" { - bool_attribute = true - } - - resource "test_resource" "two" {}`, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectContains( - "test_resource.one", - tfjsonpath.New("bool_attribute"), - "test_resource.two", - tfjsonpath.New("bool_attribute"), - ), - }, - ExpectError: regexp.MustCompile("test_resource.one.bool_attribute is not a collection"), - }, - }, - }) -} - -func TestExpectContains_CheckState_NotFound(t *testing.T) { - t.Parallel() - - r.Test(t, r.TestCase{ - ProviderFactories: map[string]func() (*schema.Provider, error){ - "test": func() (*schema.Provider, error) { //nolint:unparam // required signature - return testProvider(), nil - }, - }, - Steps: []r.TestStep{ - { - Config: `resource "test_resource" "one" { - bool_attribute = true - string_attribute = "value1" - } - - resource "test_resource" "two" { - set_attribute = [ - test_resource.one.string_attribute, - "value2" - ] - }`, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectContains( - "test_resource.two", - tfjsonpath.New("set_attribute"), - "test_resource.one", - tfjsonpath.New("bool_attribute"), - ), - }, - ExpectError: regexp.MustCompile(`value of test_resource\.one\.bool_attribute is not found in value of test_resource\.two\.set_attribute`), - }, - }, - }) -} - -func TestExpectContains_CheckState_Found(t *testing.T) { - t.Parallel() - - r.Test(t, r.TestCase{ - ProviderFactories: map[string]func() (*schema.Provider, error){ - "test": func() (*schema.Provider, error) { //nolint:unparam // required signature - return testProvider(), nil - }, - }, - Steps: []r.TestStep{ - { - Config: `resource "test_resource" "one" { - string_attribute = "value1" - } - - resource "test_resource" "two" { - set_attribute = [ - test_resource.one.string_attribute, - "value2" - ] - }`, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectContains( - "test_resource.two", - tfjsonpath.New("set_attribute"), - "test_resource.one", - tfjsonpath.New("string_attribute"), - ), - }, - }, - }, - }) -} diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx index 0f9099bc5..1bdd9213f 100644 --- a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx @@ -11,58 +11,11 @@ The `terraform-plugin-testing` module provides a package [`statecheck`](https:// | Check | Description | |-----------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [`ExpectContains`](/terraform/plugin/testing/acceptance-tests/state-checks/resource#expectcontains-state-check) | Asserts the specified attribute at the first given managed resource, or data source, contains the value specified by the attribute in the second given managed resource, or data source. | | [`ExpectKnownValue`](/terraform/plugin/testing/acceptance-tests/state-checks/resource#expectknownvalue-state-check) | Asserts the specified attribute at the given managed resource, or data source, has the specified type, and value. | | [`ExpectMatchingValues`](/terraform/plugin/testing/acceptance-tests/state-checks/resource#expectmatchingvalues-state-check) | Asserts the specified attributes at the given managed resources have matching values. | | [`ExpectNoValueExists`](/terraform/plugin/testing/acceptance-tests/state-checks/resource#expectnovalueexists-state-check) | Asserts the specified attribute at the given managed resource, or data source, does not exist. | | [`ExpectSensitiveValue`](/terraform/plugin/testing/acceptance-tests/state-checks/resource#expectsensitivevalue-state-check) | Asserts the specified attribute at the given managed resource, or data source, has a sensitive value. | -## `ExpectContains` State Check - -The [`statecheck.ExpectContains(addressOne, pathOne, addressTwo, pathTwo)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectContains) state check provides a basis for asserting that the first specified resource attribute contains the value specified by the second resource attribute. - -```go -package example_test - -import ( - "testing" - - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/statecheck" - "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -) - -func TestExpectContains_CheckState_Found(t *testing.T) { - t.Parallel() - - resource.Test(t, resource.TestCase{ - // Provider definition omitted. - Steps: []resource.TestStep{ - { - Config: `resource "test_resource" "one" { - string_attribute = "value1" - } - - resource "test_resource" "two" { - set_attribute = [ - test_resource.one.string_attribute, - "value2" - ] - }`, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectContains( - "test_resource.two", - tfjsonpath.New("set_attribute"), - "test_resource.one", - tfjsonpath.New("string_attribute"), - ), - }, - }, - }, - }) -} -``` - ## `ExpectKnownValue` State Check The [`statecheck.ExpectKnownValue(address, path, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue) state check provides a basis for asserting that a specific resource attribute has a known type, and value. From fca9dee6d10c4360eac082d8b7675241c79d1c48 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Fri, 26 Jan 2024 10:14:45 +0000 Subject: [PATCH 54/73] Removing ExpectMatchingValues state check --- .../unreleased/FEATURES-20240117-165925.yaml | 6 - helper/resource/testing.go | 51 +--- statecheck/expect_matching_values.go | 108 -------- .../expect_matching_values_example_test.go | 40 --- statecheck/expect_matching_values_test.go | 257 ------------------ .../state-checks/resource.mdx | 45 --- 6 files changed, 5 insertions(+), 502 deletions(-) delete mode 100644 .changes/unreleased/FEATURES-20240117-165925.yaml delete mode 100644 statecheck/expect_matching_values.go delete mode 100644 statecheck/expect_matching_values_example_test.go delete mode 100644 statecheck/expect_matching_values_test.go diff --git a/.changes/unreleased/FEATURES-20240117-165925.yaml b/.changes/unreleased/FEATURES-20240117-165925.yaml deleted file mode 100644 index 36ef5e40b..000000000 --- a/.changes/unreleased/FEATURES-20240117-165925.yaml +++ /dev/null @@ -1,6 +0,0 @@ -kind: FEATURES -body: 'statecheck: Added `ExpectMatchingValues built-in state check, which asserts - that the given attributes have matching values' -time: 2024-01-17T16:59:25.504116Z -custom: - Issue: "276" diff --git a/helper/resource/testing.go b/helper/resource/testing.go index b6e3c4bf0..4405b8d7e 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -1885,53 +1885,12 @@ func TestCheckModuleResourceAttrPtr(mp []string, name string, key string, value // - .%: Number of elements in map. // // Deprecated: State checks have been superseded by ConfigStateChecks. -// Use the built-in statecheck.ExpectMatchingValues state check instead. -// TestCheckResourceAttrPair function will be removed in the next major version. +// TestCheckResourceAttrPair has been deprecated without replacement. Please +// use the GitHub issue [Deprecation of Built-In TestCheckFunc Implementations for Checking Pairs of Values] +// to indicate if you have a use-case for a built-in ConfigStateChecks state check +// function that would replicate the behaviour of TestCheckResourceAttrPair. // -// The following is an example of using statecheck.ExpectMatchingValues -// to replicate the behaviour of TestCheckResourceAttrPair. -// -// package example_test -// -// import ( -// "testing" -// -// "github.com/hashicorp/terraform-plugin-testing/helper/resource" -// "github.com/hashicorp/terraform-plugin-testing/statecheck" -// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -// ) -// -// func TestExpectMatchingValues_CheckState_AttributeValuesEqual_Bool(t *testing.T) { -// t.Parallel() -// -// resource.Test(t, resource.TestCase{ -// // Provider definition omitted. -// -// Steps: []resource.TestStep{ -// { -// Config: `resource "test_resource" "one" { -// bool_attribute = true -// } -// -// resource "test_resource" "two" { -// bool_attribute = true -// }`, -// ConfigStateChecks: []statecheck.StateCheck{ -// statecheck.ExpectMatchingValues( -// "test_resource.one", -// tfjsonpath.New("bool_attribute"), -// "test_resource.two", -// tfjsonpath.New("bool_attribute"), -// ), -// }, -// }, -// }, -// }) -// } -// -// [ExpectMatchingValues]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectMatchingValues -// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck -// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck +// [Deprecation of Built-In TestCheckFunc Implementations for Checking Pairs of Values]: https://github.com/hashicorp/terraform-plugin-testing/issues/282 func TestCheckResourceAttrPair(nameFirst, keyFirst, nameSecond, keySecond string) TestCheckFunc { return checkIfIndexesIntoTypeSetPair(keyFirst, keySecond, func(s *terraform.State) error { isFirst, err := primaryInstanceState(s, nameFirst) diff --git a/statecheck/expect_matching_values.go b/statecheck/expect_matching_values.go deleted file mode 100644 index e7d586b66..000000000 --- a/statecheck/expect_matching_values.go +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package statecheck - -import ( - "context" - "fmt" - "reflect" - - tfjson "github.com/hashicorp/terraform-json" - - "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -) - -// Resource State Check -var _ StateCheck = expectMatchingValues{} - -type expectMatchingValues struct { - resourceAddressOne string - attributePathOne tfjsonpath.Path - resourceAddressTwo string - attributePathTwo tfjsonpath.Path -} - -// CheckState implements the state check logic. -func (e expectMatchingValues) CheckState(ctx context.Context, req CheckStateRequest, resp *CheckStateResponse) { - var resourceOne, resourceTwo *tfjson.StateResource - - if req.State == nil { - resp.Error = fmt.Errorf("state is nil") - - return - } - - if req.State.Values == nil { - resp.Error = fmt.Errorf("state does not contain any state values") - - return - } - - if req.State.Values.RootModule == nil { - resp.Error = fmt.Errorf("state does not contain a root module") - - return - } - - for _, r := range req.State.Values.RootModule.Resources { - if e.resourceAddressOne == r.Address { - resourceOne = r - - break - } - } - - if resourceOne == nil { - resp.Error = fmt.Errorf("%s - Resource not found in state", e.resourceAddressOne) - - return - } - - resultOne, err := tfjsonpath.Traverse(resourceOne.AttributeValues, e.attributePathOne) - - if err != nil { - resp.Error = err - - return - } - - for _, r := range req.State.Values.RootModule.Resources { - if e.resourceAddressTwo == r.Address { - resourceTwo = r - - break - } - } - - if resourceTwo == nil { - resp.Error = fmt.Errorf("%s - Resource not found in state", e.resourceAddressTwo) - - return - } - - resultTwo, err := tfjsonpath.Traverse(resourceTwo.AttributeValues, e.attributePathTwo) - - if err != nil { - resp.Error = err - - return - } - - if !reflect.DeepEqual(resultOne, resultTwo) { - resp.Error = fmt.Errorf("values are not equal: %v != %v", resultOne, resultTwo) - - return - } -} - -// ExpectMatchingValues returns a state check that asserts that the specified attributes at the given resources -// have a matching value. -func ExpectMatchingValues(resourceAddressOne string, attributePathOne tfjsonpath.Path, resourceAddressTwo string, attributePathTwo tfjsonpath.Path) StateCheck { - return expectMatchingValues{ - resourceAddressOne: resourceAddressOne, - attributePathOne: attributePathOne, - resourceAddressTwo: resourceAddressTwo, - attributePathTwo: attributePathTwo, - } -} diff --git a/statecheck/expect_matching_values_example_test.go b/statecheck/expect_matching_values_example_test.go deleted file mode 100644 index 484bb2af2..000000000 --- a/statecheck/expect_matching_values_example_test.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package statecheck_test - -import ( - "testing" - - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/statecheck" - "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -) - -func ExampleExpectMatchingValues() { - t := &testing.T{} - t.Parallel() - - resource.Test(t, resource.TestCase{ - // Provider definition omitted. - Steps: []resource.TestStep{ - { - Config: `resource "test_resource" "one" { - bool_attribute = true - } - - resource "test_resource" "two" { - bool_attribute = true - }`, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectMatchingValues( - "test_resource.one", - tfjsonpath.New("bool_attribute"), - "test_resource.two", - tfjsonpath.New("bool_attribute"), - ), - }, - }, - }, - }) -} diff --git a/statecheck/expect_matching_values_test.go b/statecheck/expect_matching_values_test.go deleted file mode 100644 index 35d86f363..000000000 --- a/statecheck/expect_matching_values_test.go +++ /dev/null @@ -1,257 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package statecheck_test - -import ( - "regexp" - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - - r "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/statecheck" - "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -) - -func TestExpectMatchingValues_CheckState_ResourceOneNotFound(t *testing.T) { - t.Parallel() - - r.Test(t, r.TestCase{ - ProviderFactories: map[string]func() (*schema.Provider, error){ - "test": func() (*schema.Provider, error) { //nolint:unparam // required signature - return testProvider(), nil - }, - }, - Steps: []r.TestStep{ - { - Config: `resource "test_resource" "one" {} - - resource "test_resource" "two" {}`, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectMatchingValues( - "does_not_exist_one", - tfjsonpath.New("bool_attribute"), - "test_resource.two", - tfjsonpath.New("bool_attribute"), - ), - }, - ExpectError: regexp.MustCompile("does_not_exist_one - Resource not found in state"), - }, - }, - }) -} - -func TestExpectMatchingValues_CheckState_ResourceTwoNotFound(t *testing.T) { - t.Parallel() - - r.Test(t, r.TestCase{ - ProviderFactories: map[string]func() (*schema.Provider, error){ - "test": func() (*schema.Provider, error) { //nolint:unparam // required signature - return testProvider(), nil - }, - }, - Steps: []r.TestStep{ - { - Config: `resource "test_resource" "one" {} - - resource "test_resource" "two" {}`, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectMatchingValues( - "test_resource.one", - tfjsonpath.New("bool_attribute"), - "does_not_exist_two", - tfjsonpath.New("bool_attribute"), - ), - }, - ExpectError: regexp.MustCompile("does_not_exist_two - Resource not found in state"), - }, - }, - }) -} - -func TestExpectMatchingValues_CheckState_AttributeOneNotFound(t *testing.T) { - t.Parallel() - - r.Test(t, r.TestCase{ - ProviderFactories: map[string]func() (*schema.Provider, error){ - "test": func() (*schema.Provider, error) { //nolint:unparam // required signature - return testProvider(), nil - }, - }, - Steps: []r.TestStep{ - { - Config: `resource "test_resource" "one" {} - - resource "test_resource" "two" {}`, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectMatchingValues( - "test_resource.one", - tfjsonpath.New("does_not_exist_one"), - "test_resource.two", - tfjsonpath.New("bool_attribute"), - ), - }, - ExpectError: regexp.MustCompile("path not found: specified key does_not_exist_one not found in map at does_not_exist_one"), - }, - }, - }) -} - -func TestExpectMatchingValues_CheckState_AttributeTwoNotFound(t *testing.T) { - t.Parallel() - - r.Test(t, r.TestCase{ - ProviderFactories: map[string]func() (*schema.Provider, error){ - "test": func() (*schema.Provider, error) { //nolint:unparam // required signature - return testProvider(), nil - }, - }, - Steps: []r.TestStep{ - { - Config: `resource "test_resource" "one" {} - - resource "test_resource" "two" {}`, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectMatchingValues( - "test_resource.one", - tfjsonpath.New("bool_attribute"), - "test_resource.two", - tfjsonpath.New("does_not_exist_two"), - ), - }, - ExpectError: regexp.MustCompile("path not found: specified key does_not_exist_two not found in map at does_not_exist_two"), - }, - }, - }) -} - -func TestExpectMatchingValues_CheckState_AttributeValuesNotEqualNil(t *testing.T) { - t.Parallel() - - r.Test(t, r.TestCase{ - ProviderFactories: map[string]func() (*schema.Provider, error){ - "test": func() (*schema.Provider, error) { //nolint:unparam // required signature - return testProvider(), nil - }, - }, - Steps: []r.TestStep{ - { - Config: `resource "test_resource" "one" { - bool_attribute = true - } - - resource "test_resource" "two" {}`, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectMatchingValues( - "test_resource.one", - tfjsonpath.New("bool_attribute"), - "test_resource.two", - tfjsonpath.New("bool_attribute"), - ), - }, - ExpectError: regexp.MustCompile("values are not equal: true != "), - }, - }, - }) -} - -func TestExpectMatchingValues_CheckState_AttributeValuesNotEqual(t *testing.T) { - t.Parallel() - - r.Test(t, r.TestCase{ - ProviderFactories: map[string]func() (*schema.Provider, error){ - "test": func() (*schema.Provider, error) { //nolint:unparam // required signature - return testProvider(), nil - }, - }, - Steps: []r.TestStep{ - { - Config: `resource "test_resource" "one" { - bool_attribute = true - } - - resource "test_resource" "two" { - bool_attribute = false - }`, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectMatchingValues( - "test_resource.one", - tfjsonpath.New("bool_attribute"), - "test_resource.two", - tfjsonpath.New("bool_attribute"), - ), - }, - ExpectError: regexp.MustCompile("values are not equal: true != false"), - }, - }, - }) -} - -func TestExpectMatchingValues_CheckState_AttributeValuesEqual_Bool(t *testing.T) { - t.Parallel() - - r.Test(t, r.TestCase{ - ProviderFactories: map[string]func() (*schema.Provider, error){ - "test": func() (*schema.Provider, error) { //nolint:unparam // required signature - return testProvider(), nil - }, - }, - Steps: []r.TestStep{ - { - Config: `resource "test_resource" "one" { - bool_attribute = true - } - - resource "test_resource" "two" { - bool_attribute = true - }`, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectMatchingValues( - "test_resource.one", - tfjsonpath.New("bool_attribute"), - "test_resource.two", - tfjsonpath.New("bool_attribute"), - ), - }, - }, - }, - }) -} - -func TestExpectMatchingValues_CheckState_AttributeValuesEqual_List(t *testing.T) { - t.Parallel() - - r.Test(t, r.TestCase{ - ProviderFactories: map[string]func() (*schema.Provider, error){ - "test": func() (*schema.Provider, error) { //nolint:unparam // required signature - return testProvider(), nil - }, - }, - Steps: []r.TestStep{ - { - Config: `resource "test_resource" "one" { - list_attribute = [ - "value1", - "value2" - ] - } - - resource "test_resource" "two" { - list_attribute = [ - "value1", - "value2" - ] - }`, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectMatchingValues( - "test_resource.one", - tfjsonpath.New("list_attribute"), - "test_resource.two", - tfjsonpath.New("list_attribute"), - ), - }, - }, - }, - }) -} diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx index 1bdd9213f..a0df20e3f 100644 --- a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx @@ -12,7 +12,6 @@ The `terraform-plugin-testing` module provides a package [`statecheck`](https:// | Check | Description | |-----------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | [`ExpectKnownValue`](/terraform/plugin/testing/acceptance-tests/state-checks/resource#expectknownvalue-state-check) | Asserts the specified attribute at the given managed resource, or data source, has the specified type, and value. | -| [`ExpectMatchingValues`](/terraform/plugin/testing/acceptance-tests/state-checks/resource#expectmatchingvalues-state-check) | Asserts the specified attributes at the given managed resources have matching values. | | [`ExpectNoValueExists`](/terraform/plugin/testing/acceptance-tests/state-checks/resource#expectnovalueexists-state-check) | Asserts the specified attribute at the given managed resource, or data source, does not exist. | | [`ExpectSensitiveValue`](/terraform/plugin/testing/acceptance-tests/state-checks/resource#expectsensitivevalue-state-check) | Asserts the specified attribute at the given managed resource, or data source, has a sensitive value. | @@ -58,50 +57,6 @@ func TestExpectKnownValue_CheckState_Bool(t *testing.T) { } ``` -## `ExpectMatchingValues` State Check - -The [`statecheck.ExpectMatchingValues(addressOne, pathOne, addressTwo, pathTwo)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectMatchingValues) state check provides a basis for asserting that the specified resource attributes have matching values. - -```go -package example_test - -import ( - "testing" - - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/statecheck" - "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -) - -func TestExpectMatchingValues_CheckState_AttributeValuesEqual_Bool(t *testing.T) { - t.Parallel() - - resource.Test(t, resource.TestCase{ - // Provider definition omitted. - - Steps: []resource.TestStep{ - { - Config: `resource "test_resource" "one" { - bool_attribute = true - } - - resource "test_resource" "two" { - bool_attribute = true - }`, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectMatchingValues( - "test_resource.one", - tfjsonpath.New("bool_attribute"), - "test_resource.two", - tfjsonpath.New("bool_attribute"), - ), - }, - }, - }, - }) -} -``` - ## `ExpectNoValueExists` State Check The [`statecheck.ExpectNoValueExists(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectNoValueExists) state check provides a basis for asserting that a specific resource attribute does not exist. From 5ebf12da930c6a9c219f45b49efa883258c6f072 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Fri, 26 Jan 2024 13:16:15 +0000 Subject: [PATCH 55/73] Updating docs --- helper/resource/testing.go | 266 ++++++------------ helper/resource/testing_sets.go | 96 ++----- plancheck/expect_null_output_value.go | 5 +- plancheck/expect_null_output_value_at_path.go | 5 +- ...known_output_value_at_path_example_test.go | 1 + .../expect_known_output_value_example_test.go | 1 + statecheck/expect_known_value_example_test.go | 1 + .../expect_no_value_exists_example_test.go | 1 + .../known-value-checks/bool.mdx | 7 +- .../known-value-checks/float64.mdx | 7 +- .../known-value-checks/int64.mdx | 7 +- .../known-value-checks/list.mdx | 30 +- .../known-value-checks/map.mdx | 30 +- .../known-value-checks/not-null.mdx | 7 +- .../known-value-checks/null.mdx | 3 +- .../known-value-checks/number.mdx | 7 +- .../known-value-checks/object.mdx | 20 +- .../known-value-checks/set.mdx | 30 +- .../known-value-checks/string.mdx | 7 +- .../acceptance-tests/state-checks/custom.mdx | 8 +- .../acceptance-tests/state-checks/output.mdx | 22 +- .../state-checks/resource.mdx | 14 +- 22 files changed, 196 insertions(+), 379 deletions(-) diff --git a/helper/resource/testing.go b/helper/resource/testing.go index 4405b8d7e..49765d894 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -559,11 +559,8 @@ type TestStep struct { // // If this is nil, no check is done on this step. // - // Deprecated: State checks have been superseded by ConfigStateChecks. + // Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. // This field will be removed in the next major version. - // - // [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck - // [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck Check TestCheckFunc // Destroy will create a destroy plan if set to true. @@ -598,10 +595,7 @@ type TestStep struct { RefreshPlanChecks RefreshPlanChecks // ConfigStateChecks allow assertions to be made against the state file during a Config (apply) test using a state check. - // Custom state checks can be created by implementing the [StateCheck] interface, or by using a StateCheck implementation from the provided [statecheck] package - // - // [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck - // [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck + // Custom state checks can be created by implementing the [statecheck.StateCheck] interface, or by using a StateCheck implementation from the provided [statecheck] package. ConfigStateChecks []statecheck.StateCheck // PlanOnly can be set to only run `plan` with this configuration, and not @@ -967,11 +961,8 @@ func testResource(c TestStep, state *terraform.State) (*terraform.ResourceState, // ComposeTestCheckFunc returns immediately on the first TestCheckFunc error. // To aggregrate all errors, use ComposeAggregateTestCheckFunc instead. // -// Deprecated: State checks have been superseded by ConfigStateChecks. +// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. // This function will be removed in the next major version. -// -// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck -// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck func ComposeTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc { return func(s *terraform.State) error { for i, f := range fs { @@ -993,11 +984,8 @@ func ComposeTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc { // Unlike ComposeTestCheckFunc, ComposeAggergateTestCheckFunc runs _all_ of the // TestCheckFuncs and aggregates failures. // -// Deprecated: State checks have been superseded by ConfigStateChecks. +// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. // This function will be removed in the next major version. -// -// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck -// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck func ComposeAggregateTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc { return func(s *terraform.State) error { var result []error @@ -1055,11 +1043,11 @@ func ComposeAggregateTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc { // attribute directly is not supported. Use TestCheckResourceAttr with // the special .# or .% key syntax for those situations instead. // -// Deprecated: State checks have been superseded by ConfigStateChecks. -// Use the built-in statecheck.KnownValue state check with knownvalue.NotNull instead. -// TestCheckResourceAttrSet function will be removed in the next major version. +// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. +// Use the built-in [ExpectKnownValue] state check with the [knownvalue.NotNull] known value type +// instead. TestCheckResourceAttrSet function will be removed in the next major version. // -// The following is an example of using statecheck.ExpectKnownValue with knownvalue.NotNull +// The following is an example of using [ExpectKnownValue] with [knownvalue.NotNull] // to replicate the behaviour of TestCheckResourceAttrSet. // // package example_test @@ -1068,6 +1056,7 @@ func ComposeAggregateTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc { // "testing" // // "github.com/hashicorp/terraform-plugin-testing/helper/resource" +// "github.com/hashicorp/terraform-plugin-testing/knownvalue" // "github.com/hashicorp/terraform-plugin-testing/statecheck" // "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" // ) @@ -1079,14 +1068,12 @@ func ComposeAggregateTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc { // // Provider definition omitted. // Steps: []resource.TestStep{ // { -// Config: `resource "test_resource" "one" { -// bool_attribute = true -// } -// `, +// // Example resource containing a computed attribute named "computed_attribute" +// Config: `resource "test_resource" "one" {}`, // ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectKnownValue( // "test_resource.one", -// tfjsonpath.New("bool_attribute"), +// tfjsonpath.New("computed_attribute"), // knownvalue.NotNull(), // ), // }, @@ -1094,11 +1081,6 @@ func ComposeAggregateTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc { // }, // }) // } -// -// [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue -// [NotNull]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NotNull -// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck -// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck func TestCheckResourceAttrSet(name, key string) TestCheckFunc { return checkIfIndexesIntoTypeSet(key, func(s *terraform.State) error { is, err := primaryInstanceState(s, name) @@ -1199,11 +1181,11 @@ func testCheckResourceAttrSet(is *terraform.InstanceState, name string, key stri // - Float/Integer: Stringified number, such as "1.2" or "123". // - String: No conversion necessary. // -// Deprecated: State checks have been superseded by ConfigStateChecks. -// Use the built-in statecheck.ExpectKnownValue state check instead. +// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. +// Use the built-in [statecheck.ExpectKnownValue] state check instead. // TestCheckResourceAttr function will be removed in the next major version. // -// The following is an example of using statecheck.ExpectKnownValue +// The following is an example of using [statecheck.ExpectKnownValue] // to replicate the behaviour of TestCheckResourceAttr. // // package example_test @@ -1224,14 +1206,12 @@ func testCheckResourceAttrSet(is *terraform.InstanceState, name string, key stri // // Provider definition omitted. // Steps: []resource.TestStep{ // { -// Config: `resource "test_resource" "one" { -// bool_attribute = true -// } -// `, +// // Example resource containing a computed boolean attribute named "computed_attribute" +// Config: `resource "test_resource" "one" {}`, // ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectKnownValue( // "test_resource.one", -// tfjsonpath.New("bool_attribute"), +// tfjsonpath.New("computed_attribute"), // knownvalue.Bool(true), // ), // }, @@ -1239,10 +1219,6 @@ func testCheckResourceAttrSet(is *terraform.InstanceState, name string, key stri // }, // }) // } -// -// [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue -// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck -// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck func TestCheckResourceAttr(name, key, value string) TestCheckFunc { return checkIfIndexesIntoTypeSet(key, func(s *terraform.State) error { is, err := primaryInstanceState(s, name) @@ -1327,23 +1303,20 @@ func testCheckResourceAttr(is *terraform.InstanceState, name string, key string, // // When this function returns an error, TestCheckResourceAttrWith will fail the check. // -// Deprecated: State checks have been superseded by ConfigStateChecks. -// Use the built-int statecheck.ExpectKnownValue state check in combination -// with a custom knownvalue.Check instead. +// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. +// Use the built-int [statecheck.ExpectKnownValue] state check in combination +// with a [custom] [knownvalue.Check] instead. // CheckResourceAttrWithFunc will be removed in the next major version. // -// The following is an example of using statecheck.ExpectKnownValue in combination -// with a custom knownvalue.Check to replicate the behaviour of TestCheckResourceAttrWith. +// The following is an example of using [statecheck.ExpectKnownValue] in combination +// with a [custom] [knownvalue.Check] to replicate the behaviour of TestCheckResourceAttrWith. // // package example_test // // import ( -// "fmt" -// "strings" // "testing" // // "github.com/hashicorp/terraform-plugin-testing/helper/resource" -// "github.com/hashicorp/terraform-plugin-testing/knownvalue" // "github.com/hashicorp/terraform-plugin-testing/statecheck" // "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" // ) @@ -1355,14 +1328,12 @@ func testCheckResourceAttr(is *terraform.InstanceState, name string, key string, // // Provider definition omitted. // Steps: []resource.TestStep{ // { -// Config: `resource "test_resource" "one" { -// string_attribute = "string" -// } -// `, +// // Example resource containing a computed string attribute named "computed_attribute" +// Config: `resource "test_resource" "one" {}`, // ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectKnownValue( // "test_resource.one", -// tfjsonpath.New("string_attribute"), +// tfjsonpath.New("computed_attribute"), // StringContains("tri")), // }, // }, @@ -1370,11 +1341,7 @@ func testCheckResourceAttr(is *terraform.InstanceState, name string, key string, // }) // } // -// [Check]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check -// [Custom Known Value Checks]: https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests/known-value-checks/custom -// [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue -// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck -// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck +// [custom]: https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests/known-value-checks/custom type CheckResourceAttrWithFunc func(value string) error // TestCheckResourceAttrWith ensures a value stored in state for the @@ -1413,23 +1380,20 @@ type CheckResourceAttrWithFunc func(value string) error // if it was found in the state. The function must return an error for the // check to fail, or `nil` to succeed. // -// Deprecated: State checks have been superseded by ConfigStateChecks. -// Use the built-int statecheck.ExpectKnownValue state check in combination -// with a custom knownvalue.Check instead. +// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. +// Use the built-int [statecheck.ExpectKnownValue] state check in combination +// with a [custom] [knownvalue.Check] instead. // TestCheckResourceAttrWith function will be removed in the next major version. // -// The following is an example of using statecheck.ExpectKnownValue in combination -// with a custom knownvalue.Check to replicate the behaviour of TestCheckResourceAttrWith. +// The following is an example of using [statecheck.ExpectKnownValue] in combination +// with a [custom] [knownvalue.Check] to replicate the behaviour of TestCheckResourceAttrWith. // // package example_test // // import ( -// "fmt" -// "strings" // "testing" // // "github.com/hashicorp/terraform-plugin-testing/helper/resource" -// "github.com/hashicorp/terraform-plugin-testing/knownvalue" // "github.com/hashicorp/terraform-plugin-testing/statecheck" // "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" // ) @@ -1441,14 +1405,12 @@ type CheckResourceAttrWithFunc func(value string) error // // Provider definition omitted. // Steps: []resource.TestStep{ // { -// Config: `resource "test_resource" "one" { -// string_attribute = "string" -// } -// `, +// // Example resource containing a computed string attribute named "computed_attribute" +// Config: `resource "test_resource" "one" {}`, // ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectKnownValue( // "test_resource.one", -// tfjsonpath.New("string_attribute"), +// tfjsonpath.New("computed_attribute"), // StringContains("tri")), // }, // }, @@ -1456,11 +1418,7 @@ type CheckResourceAttrWithFunc func(value string) error // }) // } // -// [Check]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check -// [Custom Known Value Checks]: https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests/known-value-checks/custom -// [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue -// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck -// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck +// [custom]: https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests/known-value-checks/custom func TestCheckResourceAttrWith(name, key string, checkValueFunc CheckResourceAttrWithFunc) TestCheckFunc { return checkIfIndexesIntoTypeSet(key, func(s *terraform.State) error { is, err := primaryInstanceState(s, name) @@ -1514,11 +1472,11 @@ func TestCheckResourceAttrWith(name, key string, checkValueFunc CheckResourceAtt // attribute directly is not supported. Use TestCheckResourceAttr with // the special .# or .% key syntax for those situations instead. // -// Deprecated: State checks have been superseded by ConfigStateChecks. -// Use the built-in statecheck.ExpectNoValueExists instead. +// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. +// Use the built-in [statecheck.ExpectNoValueExists] instead. // TestCheckNoResourceAttr function will be removed in the next major version. // -// The following is an example of using statecheck.ExpectNoValueExists to +// The following is an example of using [statecheck.ExpectNoValueExists] to // replicate the behaviour of TestCheckNoResourceAttr. // // package example_test @@ -1538,10 +1496,8 @@ func TestCheckResourceAttrWith(name, key string, checkValueFunc CheckResourceAtt // // Provider definition omitted. // Steps: []resource.TestStep{ // { -// Config: `resource "test_resource" "one" { -// bool_attribute = true -// } -// `, +// // Example resource which does not contain an attribute named "does_not_exist" +// Config: `resource "test_resource" "one" {}`, // ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectNoValueExists( // "test_resource.one", @@ -1552,10 +1508,6 @@ func TestCheckResourceAttrWith(name, key string, checkValueFunc CheckResourceAtt // }, // }) // } -// -// [ExpectNoValueExists]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectNoValueExists -// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck -// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck func TestCheckNoResourceAttr(name, key string) TestCheckFunc { return checkIfIndexesIntoTypeSet(key, func(s *terraform.State) error { is, err := primaryInstanceState(s, name) @@ -1661,24 +1613,21 @@ func testCheckNoResourceAttr(is *terraform.InstanceState, name string, key strin // regular expression is supported by the Go regular expression handlers during // compilation. // -// Deprecated: State checks have been superseded by ConfigStateChecks. -// Use the built-in statecheck.ExpectKnownValue state check in combination -// with a custom knownvalue.Check instead. +// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. +// Use the built-in [statecheck.ExpectKnownValue] state check in combination +// with a [custom] [knownvalue.Check] instead. // TestMatchResourceAttr function will be removed in the next major version. // -// The following is an example of using statecheck.ExpectKnownValue -// in combination with a custom knownvalue.Check to replicate the behaviour of +// The following is an example of using [statecheck.ExpectKnownValue] +// in combination with a [custom] [knownvalue.Check] to replicate the behaviour of // TestMatchResourceAttr. // // package example_test // // import ( -// "fmt" -// "strings" // "testing" // // "github.com/hashicorp/terraform-plugin-testing/helper/resource" -// "github.com/hashicorp/terraform-plugin-testing/knownvalue" // "github.com/hashicorp/terraform-plugin-testing/statecheck" // "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" // ) @@ -1690,14 +1639,12 @@ func testCheckNoResourceAttr(is *terraform.InstanceState, name string, key strin // // Provider definition omitted. // Steps: []resource.TestStep{ // { -// Config: `resource "test_resource" "one" { -// string_attribute = "string" -// } -// `, +// // Example resource containing a computed string attribute named "computed_attribute" +// Config: `resource "test_resource" "one" {}`, // ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectKnownValue( // "test_resource.one", -// tfjsonpath.New("string_attribute"), +// tfjsonpath.New("computed_attribute"), // StringContains("tri")), // }, // }, @@ -1705,11 +1652,7 @@ func testCheckNoResourceAttr(is *terraform.InstanceState, name string, key strin // }) // } // -// [Check]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check -// [Custom Known Value Checks]: https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests/known-value-checks/custom -// [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue -// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck -// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck +// [custom]: https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests/known-value-checks/custom func TestMatchResourceAttr(name, key string, r *regexp.Regexp) TestCheckFunc { return checkIfIndexesIntoTypeSet(key, func(s *terraform.State) error { is, err := primaryInstanceState(s, name) @@ -1763,12 +1706,12 @@ func testMatchResourceAttr(is *terraform.InstanceState, name string, key string, // Refer to the TestCheckResourceAttr documentation for more information about // setting the name, key, and value parameters. // -// Deprecated: State checks have been superseded by ConfigStateChecks. -// Use the built-in statecheck.ExpectKnownValue state check in combination -// with types implementing knownvalue.Check instead. +// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. +// Use the built-in [statecheck.ExpectKnownValue] state check in combination +// with types implementing [knownvalue.Check] instead. // TestCheckResourceAttrPtr function will be removed in the next major version. // -// The following is an example of using statecheck.ExpectKnownValue +// The following is an example of using [statecheck.ExpectKnownValue] // to replicate the behaviour of TestCheckResourceAttrPtr. // // package example_test @@ -1792,15 +1735,13 @@ func testMatchResourceAttr(is *terraform.InstanceState, name string, key string, // // Provider definition omitted. // Steps: []resource.TestStep{ // { -// Config: `resource "test_resource" "one" { -// bool_attribute = true -// } -// `, +// // Example resource containing a computed boolean attribute named "computed_attribute" +// Config: `resource "test_resource" "one" {}`, // ConfigStateChecks: []statecheck.StateCheck{ // AlterValue(testBool), // statecheck.ExpectKnownValue( // "test_resource.one", -// tfjsonpath.New("bool_attribute"), +// tfjsonpath.New("computed_attribute"), // knownvalue.Bool(*testBool), // ), // }, @@ -1823,11 +1764,6 @@ func testMatchResourceAttr(is *terraform.InstanceState, name string, key string, // // return mutate{} // } -// -// [Check]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check -// [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue -// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck -// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck func TestCheckResourceAttrPtr(name string, key string, value *string) TestCheckFunc { return func(s *terraform.State) error { return TestCheckResourceAttr(name, key, *value)(s) @@ -1884,10 +1820,10 @@ func TestCheckModuleResourceAttrPtr(mp []string, name string, key string, value // - .#: Number of elements in list or set. // - .%: Number of elements in map. // -// Deprecated: State checks have been superseded by ConfigStateChecks. +// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. // TestCheckResourceAttrPair has been deprecated without replacement. Please // use the GitHub issue [Deprecation of Built-In TestCheckFunc Implementations for Checking Pairs of Values] -// to indicate if you have a use-case for a built-in ConfigStateChecks state check +// to indicate if you have a use-case for a built-in [TestStep.ConfigStateChecks] state check // function that would replicate the behaviour of TestCheckResourceAttrPair. // // [Deprecation of Built-In TestCheckFunc Implementations for Checking Pairs of Values]: https://github.com/hashicorp/terraform-plugin-testing/issues/282 @@ -1986,12 +1922,12 @@ func testCheckResourceAttrPair(isFirst *terraform.InstanceState, nameFirst strin // TestCheckOutput checks an output in the Terraform configuration // -// Deprecated: State checks have been superseded by ConfigStateChecks. -// Use the built-in statecheck.ExpectKnownOutputValue, and -// statecheck.ExpectKnownOutputValueAtPath state checks instead. +// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. +// Use the built-in [statecheck.ExpectKnownOutputValue], and +// [statecheck.ExpectKnownOutputValueAtPath] state checks instead. // TestCheckOutput function will be removed in the next major version. // -// The following is an example of using statecheck.ExpectKnownOutputValue +// The following is an example of using [statecheck.ExpectKnownOutputValue] // to replicate the behaviour of TestCheckOutput. // // package example_test @@ -2011,17 +1947,15 @@ func testCheckResourceAttrPair(isFirst *terraform.InstanceState, nameFirst strin // // Provider definition omitted. // Steps: []resource.TestStep{ // { -// Config: `resource "test_resource" "one" { -// bool_attribute = true -// } -// -// output bool_output { -// value = test_resource.one.bool_attribute -// } -// `, +// // Example resource containing a computed boolean attribute named "computed_attribute" +// Config: `resource "test_resource" "one" {} +// +// output computed_output { +// value = test_resource.one.computed_attribute +// }`, // ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectKnownOutputValue( -// "bool_output", +// "computed_output", // knownvalue.Bool(true), // ), // }, @@ -2051,18 +1985,17 @@ func testCheckResourceAttrPair(isFirst *terraform.InstanceState, nameFirst strin // // Provider definition omitted. // Steps: []resource.TestStep{ // { -// Config: `resource "test_resource" "one" { -// bool_attribute = true -// } -// -// output test_resource_one_output { -// value = test_resource.one -// } -// `, +// // Example resource containing a computed boolean attribute named "computed_attribute" +// Config: `resource "test_resource" "one" {} +// +// output test_resource_one_output { +// value = test_resource.one +// } +// `, // ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectKnownOutputValueAtPath( // "test_resource_one_output", -// tfjsonpath.New("bool_attribute"), +// tfjsonpath.New("computed_attribute"), // knownvalue.Bool(true), // ), // }, @@ -2070,11 +2003,6 @@ func testCheckResourceAttrPair(isFirst *terraform.InstanceState, nameFirst strin // }, // }) // } -// -// [ExpectKnownOutputValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValue -// [ExpectKnownOutputValueAtPath]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValueAtPath -// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck -// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck func TestCheckOutput(name, value string) TestCheckFunc { return func(s *terraform.State) error { ms := s.RootModule() @@ -2095,25 +2023,22 @@ func TestCheckOutput(name, value string) TestCheckFunc { } } -// Deprecated: State checks have been superseded by ConfigStateChecks. -// Use the built-in statecheck.ExpectKnownOutputValue, and -// statecheck.ExpectKnownOutputValueAtPath state checks, can be used in -// combination with a custom knownvalue.Check instead. +// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. +// Use the built-in [statecheck.ExpectKnownOutputValue], and +// [statecheck.ExpectKnownOutputValueAtPath] state checks, can be used in +// combination with a [custom] [knownvalue.Check] instead. // TestMatchOutput function will be removed in the next major version. // -// The following is an example of using statecheck.ExpectKnownOutputValueAtPath -// in combination with a custom knownvalue.Check to replicate the behaviour of +// The following is an example of using [statecheck.ExpectKnownOutputValueAtPath] +// in combination with a [custom] [knownvalue.Check] to replicate the behaviour of // TestMatchOutput. // // package example_test // // import ( -// "fmt" -// "strings" // "testing" // // "github.com/hashicorp/terraform-plugin-testing/helper/resource" -// "github.com/hashicorp/terraform-plugin-testing/knownvalue" // "github.com/hashicorp/terraform-plugin-testing/statecheck" // "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" // ) @@ -2125,18 +2050,16 @@ func TestCheckOutput(name, value string) TestCheckFunc { // // Provider definition omitted. // Steps: []resource.TestStep{ // { -// Config: `resource "test_resource" "one" { -// string_attribute = "string" -// } -// -// output test_resource_one_output { -// value = test_resource.one -// } -// `, +// // Example resource containing a computed string attribute named "computed_attribute" +// Config: `resource "test_resource" "one" {} +// +// output test_resource_one_output { +// value = test_resource.one +// }`, // ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectKnownOutputValueAtPath( // "test_resource_one_output", -// tfjsonpath.New("string_attribute"), +// tfjsonpath.New("computed_attribute"), // StringContains("str")), // }, // }, @@ -2144,12 +2067,7 @@ func TestCheckOutput(name, value string) TestCheckFunc { // }) // } // -// [Check]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check -// [Custom Known Value Checks]: https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests/known-value-checks/custom -// [ExpectKnownOutputValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValue -// [ExpectKnownOutputValueAtPath]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValueAtPath -// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck -// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck +// [custom]: https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests/known-value-checks/custom func TestMatchOutput(name string, r *regexp.Regexp) TestCheckFunc { return func(s *terraform.State) error { ms := s.RootModule() diff --git a/helper/resource/testing_sets.go b/helper/resource/testing_sets.go index 835ef3741..14ae6a333 100644 --- a/helper/resource/testing_sets.go +++ b/helper/resource/testing_sets.go @@ -58,13 +58,13 @@ const ( // you were not intending to in the set. Provide the most complete mapping of // attributes possible to be sure the unique element exists. // -// Deprecated: State checks have been superseded by ConfigStateChecks. -// Use the built-in statecheck.ExpectKnownValue state check in combination -// with knownvalue.SetExact or knownvalue.SetPartial instead. +// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. +// Use the built-in [statecheck.ExpectKnownValue] state check in combination +// with [knownvalue.SetExact] or [knownvalue.SetPartial] instead. // TestCheckTypeSetElemNestedAttrs function will be removed in the next major version. // -// The following is an example of using statecheck.ExpectKnownValue in combination -// with knownvalue.SetPartial to replicate the behaviour of TestCheckTypeSetElemNestedAttrs. +// The following is an example of using [statecheck.ExpectKnownValue] in combination +// with [knownvalue.SetPartial] to replicate the behaviour of TestCheckTypeSetElemNestedAttrs. // // package example_test // @@ -84,17 +84,12 @@ const ( // // Provider definition omitted. // Steps: []resource.TestStep{ // { -// Config: `resource "test_resource" "one" { -// set_attribute = [ -// "value1", -// "value2" -// ] -// } -// `, +// // Example resource containing a computed set attribute named "computed_attribute" +// Config: `resource "test_resource" "one" {}`, // ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectKnownValue( // "test_resource.one", -// tfjsonpath.New("set_attribute"), +// tfjsonpath.New("computed_attribute"), // knownvalue.SetPartial([]knownvalue.Check{ // knownvalue.StringExact("value2"), // }), @@ -104,12 +99,6 @@ const ( // }, // }) // } -// -// [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue -// [SetExact]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetExact -// [SetPartial]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetPartial -// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck -// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck func TestCheckTypeSetElemNestedAttrs(name, attr string, values map[string]string) TestCheckFunc { return func(s *terraform.State) error { is, err := primaryInstanceState(s, name) @@ -183,21 +172,19 @@ func TestCheckTypeSetElemNestedAttrs(name, attr string, values map[string]string // you were not intending to in the set. Provide the most complete mapping of // attributes possible to be sure the unique element exists. // -// Deprecated: State checks have been superseded by ConfigStateChecks. -// Use the built-in statecheck.ExpectKnownValue state check, can be used in combination -// with knownvalue.ListExact, knownvalue.ListPartial, knownvalue.SetExact, or -// knownvalue.SetPartial, with nested custom knownvalue.Check instead. +// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. +// Use the built-in [statecheck.ExpectKnownValue] state check, can be used in combination +// with [knownvalue.ListExact], [knownvalue.ListPartial], [knownvalue.SetExact], or +// [knownvalue.SetPartial], with nested [custom] [knownvalue.Check] instead. // TestMatchTypeSetElemNestedAttrs function will be removed in the next major version. // -// The following is an example of using statecheck.ExpectKnownValue in combination -// with knownvalue.SetExact, with a nested custom knownvalue.Check to replicate +// The following is an example of using [statecheck.ExpectKnownValue] in combination +// with [knownvalue.SetExact], with a nested [custom] [knownvalue.Check] to replicate // the behaviour of TestCheckTypeSetElemAttr. // // package example_test // // import ( -// "fmt" -// "strings" // "testing" // // "github.com/hashicorp/terraform-plugin-testing/helper/resource" @@ -213,25 +200,18 @@ func TestCheckTypeSetElemNestedAttrs(name, attr string, values map[string]string // // Provider definition omitted. // Steps: []resource.TestStep{ // { -// Config: `resource "test_resource" "one" { -// set_nested_block { -// set_nested_block_attribute = "string" -// } -// set_nested_block { -// set_nested_block_attribute = "girts" -// } -// } -// `, +// // Example resource containing a set nested block name "block" which contains a computed string attribute named "computed_attribute" +// Config: `resource "test_resource" "one" {}`, // ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectKnownValue( // "test_resource.one", -// tfjsonpath.New("set_nested_block"), +// tfjsonpath.New("block"), // knownvalue.SetExact([]knownvalue.Check{ // knownvalue.MapExact(map[string]knownvalue.Check{ -// "set_nested_block_attribute": StringContains("str"), +// "computed_attribute": StringContains("str"), // }), // knownvalue.MapExact(map[string]knownvalue.Check{ -// "set_nested_block_attribute": StringContains("rts"), +// "computed_attribute": StringContains("rts"), // }), // }), // ), @@ -241,14 +221,7 @@ func TestCheckTypeSetElemNestedAttrs(name, attr string, values map[string]string // }) // } // -// [Custom Known Value Checks]: https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests/known-value-checks/custom -// [ListExact]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ListExact -// [ListPartial]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#ListPartial -// [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue -// [SetExact]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetExact -// [SetPartial]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetPartial -// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck -// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck +// [custom]: https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests/known-value-checks/custom func TestMatchTypeSetElemNestedAttrs(name, attr string, values map[string]*regexp.Regexp) TestCheckFunc { return func(s *terraform.State) error { is, err := primaryInstanceState(s, name) @@ -321,13 +294,13 @@ func TestMatchTypeSetElemNestedAttrs(name, attr string, values map[string]*regex // - Float/Integer: Stringified number, such as "1.2" or "123". // - String: No conversion necessary. // -// Deprecated: State checks have been superseded by ConfigStateChecks. -// Use the built-in statecheck.ExpectKnownValue state check in combination -// with knownvalue.SetExact or knownvalue.SetPartial instead. +// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. +// Use the built-in [statecheck.ExpectKnownValue] state check in combination +// with [knownvalue.SetExact] or [knownvalue.SetPartial] instead. // TestCheckTypeSetElemAttr function will be removed in the next major version. // -// The following is an example of using statecheck.ExpectKnownValue in combination -// with knownvalue.SetExact to replicate the behaviour of TestCheckTypeSetElemAttr. +// The following is an example of using [statecheck.ExpectKnownValue] in combination +// with [knownvalue.SetExact] to replicate the behaviour of TestCheckTypeSetElemAttr. // // package example_test // @@ -347,17 +320,12 @@ func TestMatchTypeSetElemNestedAttrs(name, attr string, values map[string]*regex // // Provider definition omitted. // Steps: []resource.TestStep{ // { -// Config: `resource "test_resource" "one" { -// set_attribute = [ -// "value1", -// "value2" -// ] -// } -// `, +// // Example resource containing a computed set attribute named "computed_attribute" +// Config: `resource "test_resource" "one" {}`, // ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectKnownValue( // "test_resource.one", -// tfjsonpath.New("set_attribute"), +// tfjsonpath.New("computed_attribute"), // knownvalue.SetExact([]knownvalue.Check{ // knownvalue.StringExact("value2"), // knownvalue.StringExact("value1"), @@ -368,12 +336,6 @@ func TestMatchTypeSetElemNestedAttrs(name, attr string, values map[string]*regex // }, // }) // } -// -// [ExpectKnownValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownValue -// [SetExact]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetExact -// [SetPartial]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#SetPartial -// [StateCheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#StateCheck -// [statecheck]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck func TestCheckTypeSetElemAttr(name, attr, value string) TestCheckFunc { return func(s *terraform.State) error { is, err := primaryInstanceState(s, name) @@ -417,7 +379,7 @@ func TestCheckTypeSetElemAttr(name, attr, value string) TestCheckFunc { // a list or set. The sentinel value can be used for each list or set index, if // there are multiple lists or sets in the attribute path. // -// Deprecated: State checks have been superseded by ConfigStateChecks. +// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. // TestCheckTypeSetElemAttrPair has been deprecated without replacement. Please // use the GitHub issue [Deprecation of Built-In TestCheckFunc Implementations for Checking Pairs of Values] // to indicate if you have a use-case for a built-in ConfigStateChecks state check diff --git a/plancheck/expect_null_output_value.go b/plancheck/expect_null_output_value.go index 64cbf8483..92fbf89dd 100644 --- a/plancheck/expect_null_output_value.go +++ b/plancheck/expect_null_output_value.go @@ -65,11 +65,8 @@ func (e expectNullOutputValue) CheckPlan(ctx context.Context, req CheckPlanReque // values may differ. For example, terraform-plugin-sdk based providers may have less precise representations of null values, such // as marking whole maps as null rather than individual element values. // -// Deprecated: Use ExpectKnownOutputValue with knownvalue.Null instead. +// Deprecated: Use [plancheck.ExpectKnownOutputValue] with [knownvalue.Null] instead. // ExpectNullOutputValue will be removed in the next major version release. -// -// [ExpectKnownOutputValue]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectKnownOutputValue -// [Null]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Null func ExpectNullOutputValue(outputAddress string) PlanCheck { return expectNullOutputValue{ outputAddress: outputAddress, diff --git a/plancheck/expect_null_output_value_at_path.go b/plancheck/expect_null_output_value_at_path.go index deeeda3fb..69f237d5f 100644 --- a/plancheck/expect_null_output_value_at_path.go +++ b/plancheck/expect_null_output_value_at_path.go @@ -66,11 +66,8 @@ func (e expectNullOutputValueAtPath) CheckPlan(ctx context.Context, req CheckPla // values may differ. For example, terraform-plugin-sdk based providers may have less precise representations of null values, such // as marking whole maps as null rather than individual element values. // -// Deprecated: Use ExpectKnownOutputValueAtPath with knownvalue.Null instead. +// Deprecated: Use [plancheck.ExpectKnownOutputValueAtPath] with [knownvalue.Null] instead. // ExpectNullOutputValueAtPath will be removed in the next major version release. -// -// [ExpectKnownOutputValueAtPath]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectKnownOutputValueAtPath -// [Null]: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Null func ExpectNullOutputValueAtPath(outputAddress string, valuePath tfjsonpath.Path) PlanCheck { return expectNullOutputValueAtPath{ outputAddress: outputAddress, diff --git a/statecheck/expect_known_output_value_at_path_example_test.go b/statecheck/expect_known_output_value_at_path_example_test.go index 692067a16..a6bb4bc12 100644 --- a/statecheck/expect_known_output_value_at_path_example_test.go +++ b/statecheck/expect_known_output_value_at_path_example_test.go @@ -13,6 +13,7 @@ import ( ) func ExampleExpectKnownOutputValueAtPath() { + // A typical test would accept *testing.T as a function parameter, for instance `func TestSomething(t *testing.T) { ... }`. t := &testing.T{} t.Parallel() diff --git a/statecheck/expect_known_output_value_example_test.go b/statecheck/expect_known_output_value_example_test.go index faeac222e..2d3e3275e 100644 --- a/statecheck/expect_known_output_value_example_test.go +++ b/statecheck/expect_known_output_value_example_test.go @@ -12,6 +12,7 @@ import ( ) func ExampleExpectKnownOutputValue() { + // A typical test would accept *testing.T as a function parameter, for instance `func TestSomething(t *testing.T) { ... }`. t := &testing.T{} t.Parallel() diff --git a/statecheck/expect_known_value_example_test.go b/statecheck/expect_known_value_example_test.go index f3792e8e3..ef26d64c3 100644 --- a/statecheck/expect_known_value_example_test.go +++ b/statecheck/expect_known_value_example_test.go @@ -13,6 +13,7 @@ import ( ) func ExampleExpectKnownValue() { + // A typical test would accept *testing.T as a function parameter, for instance `func TestSomething(t *testing.T) { ... }`. t := &testing.T{} t.Parallel() diff --git a/statecheck/expect_no_value_exists_example_test.go b/statecheck/expect_no_value_exists_example_test.go index 14f66a583..45cfe3728 100644 --- a/statecheck/expect_no_value_exists_example_test.go +++ b/statecheck/expect_no_value_exists_example_test.go @@ -12,6 +12,7 @@ import ( ) func ExampleExpectNoValueExists() { + // A typical test would accept *testing.T as a function parameter, for instance `func TestSomething(t *testing.T) { ... }`. t := &testing.T{} t.Parallel() diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/bool.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/bool.mdx index a996b569a..a3f8be559 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/bool.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/bool.mdx @@ -24,14 +24,13 @@ func TestExpectKnownValue_CheckPlan_Bool(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - Config: `resource "test_resource" "one" { - bool_attribute = true - }`, + // Example resource containing a computed boolean attribute named "computed_attribute" + Config: `resource "test_resource" "one" {}`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( "test_resource.one", - tfjsonpath.New("bool_attribute"), + tfjsonpath.New("computed_attribute"), knownvalue.Bool(true), ), }, diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/float64.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/float64.mdx index 7a22133ef..af7de4d29 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/float64.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/float64.mdx @@ -24,14 +24,13 @@ func TestExpectKnownValue_CheckPlan_Float64(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - Config: `resource "test_resource" "one" { - float_attribute = 1.23 - }`, + // Example resource containing a computed float64 attribute named "computed_attribute" + Config: `resource "test_resource" "one" {}`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( "test_resource.one", - tfjsonpath.New("float_attribute"), + tfjsonpath.New("computed_attribute"), knownvalue.Float64Exact(1.23), ), }, diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/int64.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/int64.mdx index ab3b61829..af647e701 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/int64.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/int64.mdx @@ -24,14 +24,13 @@ func TestExpectKnownValue_CheckPlan_Int64(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - Config: `resource "test_resource" "one" { - int_attribute = 123 - }`, + // Example resource containing a computed int64 attribute named "computed_attribute" + Config: `resource "test_resource" "one" {}`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( "test_resource.one", - tfjsonpath.New("int_attribute"), + tfjsonpath.New("computed_attribute"), knownvalue.Int64Exact(123), ), }, diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/list.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/list.mdx index fad959b43..92963b91e 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/list.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/list.mdx @@ -26,17 +26,13 @@ func TestExpectKnownValue_CheckPlan_List(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - Config: `resource "test_resource" "one" { - list_attribute = [ - "value1", - "value2" - ] - }`, + // Example resource containing a computed list attribute named "computed_attribute" + Config: `resource "test_resource" "one" {}`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( "test_resource.one", - tfjsonpath.New("list_attribute"), + tfjsonpath.New("computed_attribute"), knownvalue.ListExact([]knownvalue.Check{ knownvalue.StringExact("value1"), knownvalue.StringExact("value2"), @@ -64,17 +60,13 @@ func TestExpectKnownValue_CheckPlan_ListPartial(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - Config: `resource "test_resource" "one" { - list_attribute = [ - "value1", - "value2" - ] - }`, + // Example resource containing a computed list attribute named "computed_attribute" + Config: `resource "test_resource" "one" {}`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( "test_resource.one", - tfjsonpath.New("list_attribute"), + tfjsonpath.New("computed_attribute"), knownvalue.ListPartial(map[int]knownvalue.Check{ 0: knownvalue.StringExact("value1"), }), @@ -101,17 +93,13 @@ func TestExpectKnownValue_CheckPlan_ListElements(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - Config: `resource "test_resource" "one" { - list_attribute = [ - "value1", - "value2" - ] - }`, + // Example resource containing a computed list attribute named "computed_attribute" + Config: `resource "test_resource" "one" {}`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( "test_resource.one", - tfjsonpath.New("list_attribute"), + tfjsonpath.New("computed_attribute"), knownvalue.ListSizeExact(2), ), }, diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/map.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/map.mdx index 482686753..9685249c4 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/map.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/map.mdx @@ -26,17 +26,13 @@ func TestExpectKnownValue_CheckPlan_Map(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - Config: `resource "test_resource" "one" { - map_attribute = { - key1 = "value1" - key2 = "value2" - } - }`, + // Example resource containing a computed map attribute named "computed_attribute" + Config: `resource "test_resource" "one" {}`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( "test_resource.one", - tfjsonpath.New("map_attribute"), + tfjsonpath.New("computed_attribute"), knownvalue.MapExact(map[string]knownvalue.Check{ "key1": knownvalue.StringExact("value1"), "key2": knownvalue.StringExact("value2"), @@ -66,17 +62,13 @@ func TestExpectKnownValue_CheckPlan_MapPartial(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - Config: `resource "test_resource" "one" { - map_attribute = { - key1 = "value1" - key2 = "value2" - } - }`, + // Example resource containing a computed map attribute named "computed_attribute" + Config: `resource "test_resource" "one" {}`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( "test_resource.one", - tfjsonpath.New("map_attribute"), + tfjsonpath.New("computed_attribute"), knownvalue.MapPartial(map[string]knownvalue.Check{ "key1": knownvalue.StringExact("value1"), }), @@ -103,17 +95,13 @@ func TestExpectKnownValue_CheckPlan_MapElements(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - Config: `resource "test_resource" "one" { - map_attribute = { - key1 = "value1" - key2 = "value2" - } - }`, + // Example resource containing a computed map attribute named "computed_attribute" + Config: `resource "test_resource" "one" {}`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( "test_resource.one", - tfjsonpath.New("map_attribute"), + tfjsonpath.New("computed_attribute"), knownvalue.MapSizeExact(2), ), }, diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/not-null.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/not-null.mdx index edea7c2b5..7fee5b918 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/not-null.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/not-null.mdx @@ -24,13 +24,12 @@ func TestExpectKnownValue_CheckState_AttributeValueNull(t *testing.T) { // Provider definition omitted. Steps: []r.TestStep{ { - Config: `resource "test_resource" "one" { - bool_attribute = true - }`, + // Example resource containing a computed attribute named "computed_attribute" + Config: `resource "test_resource" "one" {}`, ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", - tfjsonpath.New("bool_attribute"), + tfjsonpath.New("computed_attribute"), knownvalue.NotNull(), ), }, diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/null.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/null.mdx index 0ab575e39..8cd4bee00 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/null.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/null.mdx @@ -24,11 +24,12 @@ func TestExpectKnownValue_CheckState_AttributeValueNull(t *testing.T) { // Provider definition omitted. Steps: []r.TestStep{ { + // Example resource containing a computed attribute named "computed_attribute" Config: `resource "test_resource" "one" {}`, ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", - tfjsonpath.New("bool_attribute"), + tfjsonpath.New("computed_attribute"), knownvalue.Null(), ), }, diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/number.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/number.mdx index 6aee9e7cc..fa4b6dcbb 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/number.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/number.mdx @@ -30,14 +30,13 @@ func TestExpectKnownValue_CheckPlan_Number(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - Config: `resource "test_resource" "one" { - number_attribute = 123 - }`, + // Example resource containing a computed number attribute named "computed_attribute" + Config: `resource "test_resource" "one" {}`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( "test_resource.one", - tfjsonpath.New("number_attribute"), + tfjsonpath.New("computed_attribute"), knownvalue.NumberExact(num), ), }, diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/object.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/object.mdx index 0d7229aed..68569dcde 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/object.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/object.mdx @@ -25,17 +25,13 @@ func TestExpectKnownValue_CheckPlan_Object(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - Config: `resource "test_resource" "one" { - object_attribute = { - attr1 = "value1" - attr2 = "value2" - } - }`, + // Example resource containing a computed object attribute named "computed_attribute" + Config: `resource "test_resource" "one" {}`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( "test_resource.one", - tfjsonpath.New("object_attribute"), + tfjsonpath.New("computed_attribute"), knownvalue.ObjectExact(map[string]knownvalue.Check{ "attr1": knownvalue.StringExact("value1"), "attr2": knownvalue.StringExact("value2"), @@ -65,17 +61,13 @@ func TestExpectKnownValue_CheckPlan_ObjectPartial(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - Config: `resource "test_resource" "one" { - object_attribute = { - attr1 = "value1" - attr2 = "value2" - } - }`, + // Example resource containing a computed object attribute named "computed_attribute" + Config: `resource "test_resource" "one" {}`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( "test_resource.one", - tfjsonpath.New("object_attribute"), + tfjsonpath.New("computed_attribute"), knownvalue.ObjectPartial(map[string]knownvalue.Check{ "attr1": knownvalue.StringExact("value1"), }), diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/set.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/set.mdx index 23acb33a6..48d906926 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/set.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/set.mdx @@ -26,17 +26,13 @@ func TestExpectKnownValue_CheckPlan_Set(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - Config: `resource "test_resource" "one" { - set_attribute = [ - "value1", - "value2" - ] - }`, + // Example resource containing a computed set attribute named "computed_attribute" + Config: `resource "test_resource" "one" {}`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( "test_resource.one", - tfjsonpath.New("set_attribute"), + tfjsonpath.New("computed_attribute"), knownvalue.SetExact([]knownvalue.Check{ knownvalue.StringExact("value2"), knownvalue.StringExact("value1"), @@ -64,17 +60,13 @@ func TestExpectKnownValue_CheckPlan_SetPartial(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - Config: `resource "test_resource" "one" { - set_attribute = [ - "value1", - "value2" - ] - }`, + // Example resource containing a computed set attribute named "computed_attribute" + Config: `resource "test_resource" "one" {}`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( "test_resource.one", - tfjsonpath.New("set_attribute"), + tfjsonpath.New("computed_attribute"), knownvalue.SetPartial([]knownvalue.Check{ knownvalue.StringExact("value2"), }), @@ -101,17 +93,13 @@ func TestExpectKnownValue_CheckPlan_SetElements(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - Config: `resource "test_resource" "one" { - set_attribute = [ - "value1", - "value2" - ] - }`, + // Example resource containing a computed set attribute named "computed_attribute" + Config: `resource "test_resource" "one" {}`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( "test_resource.one", - tfjsonpath.New("set_attribute"), + tfjsonpath.New("computed_attribute"), knownvalue.SetSizeExact(2), ), }, diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/string.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/string.mdx index bbe2fd80c..dfb460543 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/string.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/string.mdx @@ -24,14 +24,13 @@ func TestExpectKnownValue_CheckPlan_String(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - Config: `resource "test_resource" "one" { - string_attribute = "str" - }`, + // Example resource containing a computed string attribute named "computed_attribute" + Config: `resource "test_resource" "one" {}`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( "test_resource.one", - tfjsonpath.New("string_attribute"), + tfjsonpath.New("computed_attribute"), knownvalue.StringExact("str")), }, }, diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx index 230923cd2..54da165d3 100644 --- a/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx @@ -106,14 +106,12 @@ func TestExpectKnownValue_CheckState_Bool(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - Config: `resource "test_resource" "one" { - bool_attribute = true - } - `, + // Example resource containing a computed boolean attribute named "computed_attribute" + Config: `resource "test_resource" "one" {}`, ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", - tfjsonpath.New("bool_attribute"), + tfjsonpath.New("computed_attribute"), knownvalue.Bool(true), ), }, diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx index 746b14bbf..54385f457 100644 --- a/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx @@ -38,17 +38,16 @@ func TestExpectKnownOutputValue_CheckState_Bool(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - Config: `resource "test_resource" "one" { - bool_attribute = true - } + // Example resource containing a computed boolean attribute named "computed_attribute" + Config: `resource "test_resource" "one" {} - output bool_output { - value = test_resource.one.bool_attribute + output computed_output { + value = test_resource.one.computed_attribute } `, ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( - "bool_output", + "computed_output", knownvalue.Bool(true), ), }, @@ -58,11 +57,7 @@ func TestExpectKnownOutputValue_CheckState_Bool(t *testing.T) { } ``` -<<<<<<< HEAD ## `ExpectKnownOutputValueAtPath` State Check -======= -## Example using `statecheck.ExpectKnownOutputValueAtPath` ->>>>>>> origin/main The [`statecheck.ExpectKnownOutputValueAtPath(address, path, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectKnownOutputValueAtPath) state check verifies that a specific output value at a defined path has a known type, and value. @@ -87,9 +82,8 @@ func TestExpectKnownOutputValueAtPath_CheckState_Bool(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - Config: `resource "test_resource" "one" { - bool_attribute = true - } + // Example resource containing a computed boolean attribute named "computed_attribute" + Config: `resource "test_resource" "one" {} output test_resource_one_output { value = test_resource.one @@ -98,7 +92,7 @@ func TestExpectKnownOutputValueAtPath_CheckState_Bool(t *testing.T) { ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", - tfjsonpath.New("bool_attribute"), + tfjsonpath.New("computed_attribute"), knownvalue.Bool(true), ), }, diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx index a0df20e3f..b62ddc1c2 100644 --- a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx @@ -40,14 +40,12 @@ func TestExpectKnownValue_CheckState_Bool(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - Config: `resource "test_resource" "one" { - bool_attribute = true - } - `, + // Example resource containing a computed boolean attribute named "computed_attribute" + Config: `resource "test_resource" "one" {}`, ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( "test_resource.one", - tfjsonpath.New("bool_attribute"), + tfjsonpath.New("computed_attribute"), knownvalue.Bool(true), ), }, @@ -79,10 +77,8 @@ func TestExpectNoValueExists_CheckState_AttributeNotFound(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - Config: `resource "test_resource" "one" { - bool_attribute = true - } - `, + // Example resource that does not contain an attribute named "does_not_exist" + Config: `resource "test_resource" "one" {}`, ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectNoValueExists( "test_resource.one", From b9ef8f7500b3d273cf32ed16fddbebff9e93bc8d Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Tue, 30 Jan 2024 11:47:04 +0000 Subject: [PATCH 56/73] Apply suggestions from code review Co-authored-by: Brian Flad --- helper/resource/testing.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/helper/resource/testing.go b/helper/resource/testing.go index 49765d894..0ca34cd0c 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -962,7 +962,8 @@ func testResource(c TestStep, state *terraform.State) (*terraform.ResourceState, // To aggregrate all errors, use ComposeAggregateTestCheckFunc instead. // // Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. -// This function will be removed in the next major version. +// This function is unnecessary with ConfigStateChecks as all checks will be ran and therefore +// this function will be removed in the next major version. func ComposeTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc { return func(s *terraform.State) error { for i, f := range fs { @@ -985,7 +986,8 @@ func ComposeTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc { // TestCheckFuncs and aggregates failures. // // Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. -// This function will be removed in the next major version. +// This function is unnecessary with ConfigStateChecks as all checks will be ran and therefore +// this function will be removed in the next major version. func ComposeAggregateTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc { return func(s *terraform.State) error { var result []error From a6230d2da6765524a1add3682e3b1115d6dc789e Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Tue, 30 Jan 2024 12:04:27 +0000 Subject: [PATCH 57/73] Removing ExpectNoValueExists --- .../unreleased/FEATURES-20240117-165715.yaml | 6 -- helper/resource/testing.go | 13 +-- statecheck/expect_no_value_exists.go | 74 --------------- .../expect_no_value_exists_example_test.go | 36 ------- statecheck/expect_no_value_exists_test.go | 94 ------------------- .../state-checks/resource.mdx | 37 -------- 6 files changed, 7 insertions(+), 253 deletions(-) delete mode 100644 .changes/unreleased/FEATURES-20240117-165715.yaml delete mode 100644 statecheck/expect_no_value_exists.go delete mode 100644 statecheck/expect_no_value_exists_example_test.go delete mode 100644 statecheck/expect_no_value_exists_test.go diff --git a/.changes/unreleased/FEATURES-20240117-165715.yaml b/.changes/unreleased/FEATURES-20240117-165715.yaml deleted file mode 100644 index 3cf34c017..000000000 --- a/.changes/unreleased/FEATURES-20240117-165715.yaml +++ /dev/null @@ -1,6 +0,0 @@ -kind: FEATURES -body: 'statecheck: Added `ExpectNoValueExists` built-in state check, which asserts - that a given attribute does not exist' -time: 2024-01-17T16:57:15.53079Z -custom: - Issue: "276" diff --git a/helper/resource/testing.go b/helper/resource/testing.go index 0ca34cd0c..0907ecf44 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -1475,10 +1475,10 @@ func TestCheckResourceAttrWith(name, key string, checkValueFunc CheckResourceAtt // the special .# or .% key syntax for those situations instead. // // Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. -// Use the built-in [statecheck.ExpectNoValueExists] instead. +// Use the built-in [statecheck.ExpectKnownValue] with [knownvalue.Null] instead. // TestCheckNoResourceAttr function will be removed in the next major version. // -// The following is an example of using [statecheck.ExpectNoValueExists] to +// The following is an example of using [statecheck.ExpectKnownValue] with [knownvalue.Null] to // replicate the behaviour of TestCheckNoResourceAttr. // // package example_test @@ -1491,19 +1491,20 @@ func TestCheckResourceAttrWith(name, key string, checkValueFunc CheckResourceAtt // "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" // ) // -// func TestExpectNoValueExists_CheckState_AttributeNotFound(t *testing.T) { +// func TestExpectKnownValue_CheckState_AttributeNull(t *testing.T) { // t.Parallel() // // resource.Test(t, resource.TestCase{ // // Provider definition omitted. // Steps: []resource.TestStep{ // { -// // Example resource which does not contain an attribute named "does_not_exist" +// // Example resource containing a computed attribute named "computed_attribute" that has a null value // Config: `resource "test_resource" "one" {}`, // ConfigStateChecks: []statecheck.StateCheck{ -// statecheck.ExpectNoValueExists( +// statecheck.ExpectKnownValue( // "test_resource.one", -// tfjsonpath.New("does_not_exist"), +// tfjsonpath.New("computed_attribute"), +// knownvalue.Null(), // ), // }, // }, diff --git a/statecheck/expect_no_value_exists.go b/statecheck/expect_no_value_exists.go deleted file mode 100644 index 45bb736f0..000000000 --- a/statecheck/expect_no_value_exists.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package statecheck - -import ( - "context" - "fmt" - - tfjson "github.com/hashicorp/terraform-json" - - "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -) - -// Resource State Check -var _ StateCheck = expectNoValueExists{} - -type expectNoValueExists struct { - resourceAddress string - attributePath tfjsonpath.Path -} - -// CheckState implements the state check logic. -func (e expectNoValueExists) CheckState(ctx context.Context, req CheckStateRequest, resp *CheckStateResponse) { - var resource *tfjson.StateResource - - if req.State == nil { - resp.Error = fmt.Errorf("state is nil") - - return - } - - if req.State.Values == nil { - resp.Error = fmt.Errorf("state does not contain any state values") - - return - } - - if req.State.Values.RootModule == nil { - resp.Error = fmt.Errorf("state does not contain a root module") - - return - } - - for _, r := range req.State.Values.RootModule.Resources { - if e.resourceAddress == r.Address { - resource = r - - break - } - } - - // Resource doesn't exist - if resource == nil { - return - } - - _, err := tfjsonpath.Traverse(resource.AttributeValues, e.attributePath) - - if err == nil { - resp.Error = fmt.Errorf("attribute found at path: %s.%s", e.resourceAddress, e.attributePath.String()) - - return - } -} - -// ExpectNoValueExists returns a state check that asserts that the specified attribute at the given resource -// does not exist. -func ExpectNoValueExists(resourceAddress string, attributePath tfjsonpath.Path) StateCheck { - return expectNoValueExists{ - resourceAddress: resourceAddress, - attributePath: attributePath, - } -} diff --git a/statecheck/expect_no_value_exists_example_test.go b/statecheck/expect_no_value_exists_example_test.go deleted file mode 100644 index 45cfe3728..000000000 --- a/statecheck/expect_no_value_exists_example_test.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package statecheck_test - -import ( - "testing" - - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/statecheck" - "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -) - -func ExampleExpectNoValueExists() { - // A typical test would accept *testing.T as a function parameter, for instance `func TestSomething(t *testing.T) { ... }`. - t := &testing.T{} - t.Parallel() - - resource.Test(t, resource.TestCase{ - // Provider definition omitted. - Steps: []resource.TestStep{ - { - Config: `resource "test_resource" "one" { - bool_attribute = true - } - `, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectNoValueExists( - "test_resource.one", - tfjsonpath.New("does_not_exist"), - ), - }, - }, - }, - }) -} diff --git a/statecheck/expect_no_value_exists_test.go b/statecheck/expect_no_value_exists_test.go deleted file mode 100644 index d17d3cf7f..000000000 --- a/statecheck/expect_no_value_exists_test.go +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package statecheck_test - -import ( - "regexp" - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - - r "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/statecheck" - "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -) - -func TestExpectNoValueExists_CheckState_ResourceNotFound(t *testing.T) { - t.Parallel() - - r.Test(t, r.TestCase{ - ProviderFactories: map[string]func() (*schema.Provider, error){ - "test": func() (*schema.Provider, error) { //nolint:unparam // required signature - return testProvider(), nil - }, - }, - Steps: []r.TestStep{ - { - Config: `resource "test_resource" "one" { - bool_attribute = true - } - `, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectNoValueExists( - "does_not_exist", - tfjsonpath.New("bool_attribute"), - ), - }, - }, - }, - }) -} - -func TestExpectNoValueExists_CheckState_AttributeNotFound(t *testing.T) { - t.Parallel() - - r.Test(t, r.TestCase{ - ProviderFactories: map[string]func() (*schema.Provider, error){ - "test": func() (*schema.Provider, error) { //nolint:unparam // required signature - return testProvider(), nil - }, - }, - Steps: []r.TestStep{ - { - Config: `resource "test_resource" "one" { - bool_attribute = true - } - `, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectNoValueExists( - "test_resource.one", - tfjsonpath.New("does_not_exist"), - ), - }, - }, - }, - }) -} - -func TestExpectNoValueExists_CheckState_AttributeFound(t *testing.T) { - t.Parallel() - - r.Test(t, r.TestCase{ - ProviderFactories: map[string]func() (*schema.Provider, error){ - "test": func() (*schema.Provider, error) { //nolint:unparam // required signature - return testProvider(), nil - }, - }, - Steps: []r.TestStep{ - { - Config: `resource "test_resource" "one" { - bool_attribute = true - } - `, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectNoValueExists( - "test_resource.one", - tfjsonpath.New("bool_attribute"), - ), - }, - ExpectError: regexp.MustCompile(`attribute found at path: test_resource\.one\.bool_attribute`), - }, - }, - }) -} diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx index b62ddc1c2..bacc4e79f 100644 --- a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx @@ -12,7 +12,6 @@ The `terraform-plugin-testing` module provides a package [`statecheck`](https:// | Check | Description | |-----------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | [`ExpectKnownValue`](/terraform/plugin/testing/acceptance-tests/state-checks/resource#expectknownvalue-state-check) | Asserts the specified attribute at the given managed resource, or data source, has the specified type, and value. | -| [`ExpectNoValueExists`](/terraform/plugin/testing/acceptance-tests/state-checks/resource#expectnovalueexists-state-check) | Asserts the specified attribute at the given managed resource, or data source, does not exist. | | [`ExpectSensitiveValue`](/terraform/plugin/testing/acceptance-tests/state-checks/resource#expectsensitivevalue-state-check) | Asserts the specified attribute at the given managed resource, or data source, has a sensitive value. | ## `ExpectKnownValue` State Check @@ -55,42 +54,6 @@ func TestExpectKnownValue_CheckState_Bool(t *testing.T) { } ``` -## `ExpectNoValueExists` State Check - -The [`statecheck.ExpectNoValueExists(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectNoValueExists) state check provides a basis for asserting that a specific resource attribute does not exist. - -```go -package example_test - -import ( - "testing" - - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/statecheck" - "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -) - -func TestExpectNoValueExists_CheckState_AttributeNotFound(t *testing.T) { - t.Parallel() - - resource.Test(t, resource.TestCase{ - // Provider definition omitted. - Steps: []resource.TestStep{ - { - // Example resource that does not contain an attribute named "does_not_exist" - Config: `resource "test_resource" "one" {}`, - ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectNoValueExists( - "test_resource.one", - tfjsonpath.New("does_not_exist"), - ), - }, - }, - }, - }) -} -``` - ## `ExpectSensitiveValue` State Check The [`statecheck.ExpectSensitiveValue(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/statecheck#ExpectSensitiveValue) state check provides a basis for asserting that a specific resource attribute is marked as sensitive. From 4f16fc8babcaa776eb9da50336dfa7346a902f33 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Tue, 30 Jan 2024 14:02:44 +0000 Subject: [PATCH 58/73] Adding knownvalue.StringRegularExpression --- helper/resource/testing.go | 32 +++----- helper/resource/testing_sets.go | 10 +-- knownvalue/string_regexp.go | 45 +++++++++++ knownvalue/string_regexp_test.go | 75 +++++++++++++++++++ .../known-value-checks/string.mdx | 33 +++++++- 5 files changed, 168 insertions(+), 27 deletions(-) create mode 100644 knownvalue/string_regexp.go create mode 100644 knownvalue/string_regexp_test.go diff --git a/helper/resource/testing.go b/helper/resource/testing.go index 0907ecf44..cb621551c 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -1307,11 +1307,11 @@ func testCheckResourceAttr(is *terraform.InstanceState, name string, key string, // // Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. // Use the built-int [statecheck.ExpectKnownValue] state check in combination -// with a [custom] [knownvalue.Check] instead. +// with a [knownvalue.Check] instead. // CheckResourceAttrWithFunc will be removed in the next major version. // // The following is an example of using [statecheck.ExpectKnownValue] in combination -// with a [custom] [knownvalue.Check] to replicate the behaviour of TestCheckResourceAttrWith. +// with [knownvalue.StringRegularExpression] to replicate the behaviour of TestCheckResourceAttrWith. // // package example_test // @@ -1336,14 +1336,12 @@ func testCheckResourceAttr(is *terraform.InstanceState, name string, key string, // statecheck.ExpectKnownValue( // "test_resource.one", // tfjsonpath.New("computed_attribute"), -// StringContains("tri")), +// knownvalue.StringRegularExpression(regexp.MustCompile("str")), // }, // }, // }, // }) // } -// -// [custom]: https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests/known-value-checks/custom type CheckResourceAttrWithFunc func(value string) error // TestCheckResourceAttrWith ensures a value stored in state for the @@ -1384,11 +1382,11 @@ type CheckResourceAttrWithFunc func(value string) error // // Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. // Use the built-int [statecheck.ExpectKnownValue] state check in combination -// with a [custom] [knownvalue.Check] instead. +// with a [knownvalue.Check] instead. // TestCheckResourceAttrWith function will be removed in the next major version. // // The following is an example of using [statecheck.ExpectKnownValue] in combination -// with a [custom] [knownvalue.Check] to replicate the behaviour of TestCheckResourceAttrWith. +// with [knownvalue.StringRegularExpression] to replicate the behaviour of TestCheckResourceAttrWith. // // package example_test // @@ -1413,14 +1411,12 @@ type CheckResourceAttrWithFunc func(value string) error // statecheck.ExpectKnownValue( // "test_resource.one", // tfjsonpath.New("computed_attribute"), -// StringContains("tri")), +// knownvalue.StringRegularExpression(regexp.MustCompile("str")), // }, // }, // }, // }) // } -// -// [custom]: https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests/known-value-checks/custom func TestCheckResourceAttrWith(name, key string, checkValueFunc CheckResourceAttrWithFunc) TestCheckFunc { return checkIfIndexesIntoTypeSet(key, func(s *terraform.State) error { is, err := primaryInstanceState(s, name) @@ -1618,11 +1614,11 @@ func testCheckNoResourceAttr(is *terraform.InstanceState, name string, key strin // // Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. // Use the built-in [statecheck.ExpectKnownValue] state check in combination -// with a [custom] [knownvalue.Check] instead. +// with a [knownvalue.Check] instead. // TestMatchResourceAttr function will be removed in the next major version. // // The following is an example of using [statecheck.ExpectKnownValue] -// in combination with a [custom] [knownvalue.Check] to replicate the behaviour of +// in combination with [knownvalue.StringRegularExpression] to replicate the behaviour of // TestMatchResourceAttr. // // package example_test @@ -1648,14 +1644,12 @@ func testCheckNoResourceAttr(is *terraform.InstanceState, name string, key strin // statecheck.ExpectKnownValue( // "test_resource.one", // tfjsonpath.New("computed_attribute"), -// StringContains("tri")), +// knownvalue.StringRegularExpression(regexp.MustCompile("str")), // }, // }, // }, // }) // } -// -// [custom]: https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests/known-value-checks/custom func TestMatchResourceAttr(name, key string, r *regexp.Regexp) TestCheckFunc { return checkIfIndexesIntoTypeSet(key, func(s *terraform.State) error { is, err := primaryInstanceState(s, name) @@ -2029,11 +2023,11 @@ func TestCheckOutput(name, value string) TestCheckFunc { // Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. // Use the built-in [statecheck.ExpectKnownOutputValue], and // [statecheck.ExpectKnownOutputValueAtPath] state checks, can be used in -// combination with a [custom] [knownvalue.Check] instead. +// combination with a [knownvalue.Check] instead. // TestMatchOutput function will be removed in the next major version. // // The following is an example of using [statecheck.ExpectKnownOutputValueAtPath] -// in combination with a [custom] [knownvalue.Check] to replicate the behaviour of +// in combination with [knownvalue.StringRegularExpression] to replicate the behaviour of // TestMatchOutput. // // package example_test @@ -2063,14 +2057,12 @@ func TestCheckOutput(name, value string) TestCheckFunc { // statecheck.ExpectKnownOutputValueAtPath( // "test_resource_one_output", // tfjsonpath.New("computed_attribute"), -// StringContains("str")), +// knownvalue.StringRegularExpression(regexp.MustCompile("str")), // }, // }, // }, // }) // } -// -// [custom]: https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests/known-value-checks/custom func TestMatchOutput(name string, r *regexp.Regexp) TestCheckFunc { return func(s *terraform.State) error { ms := s.RootModule() diff --git a/helper/resource/testing_sets.go b/helper/resource/testing_sets.go index 14ae6a333..8c1fcbfe7 100644 --- a/helper/resource/testing_sets.go +++ b/helper/resource/testing_sets.go @@ -175,11 +175,11 @@ func TestCheckTypeSetElemNestedAttrs(name, attr string, values map[string]string // Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. // Use the built-in [statecheck.ExpectKnownValue] state check, can be used in combination // with [knownvalue.ListExact], [knownvalue.ListPartial], [knownvalue.SetExact], or -// [knownvalue.SetPartial], with nested [custom] [knownvalue.Check] instead. +// [knownvalue.SetPartial], with nested [knownvalue.Check] instead. // TestMatchTypeSetElemNestedAttrs function will be removed in the next major version. // // The following is an example of using [statecheck.ExpectKnownValue] in combination -// with [knownvalue.SetExact], with a nested [custom] [knownvalue.Check] to replicate +// with [knownvalue.SetExact], with a nested [knownvalue.StringRegularExpression] to replicate // the behaviour of TestCheckTypeSetElemAttr. // // package example_test @@ -208,10 +208,10 @@ func TestCheckTypeSetElemNestedAttrs(name, attr string, values map[string]string // tfjsonpath.New("block"), // knownvalue.SetExact([]knownvalue.Check{ // knownvalue.MapExact(map[string]knownvalue.Check{ -// "computed_attribute": StringContains("str"), +// "computed_attribute": knownvalue.StringRegularExpression(regexp.MustCompile("str")), // }), // knownvalue.MapExact(map[string]knownvalue.Check{ -// "computed_attribute": StringContains("rts"), +// "computed_attribute": knownvalue.StringRegularExpression(regexp.MustCompile("rts")), // }), // }), // ), @@ -220,8 +220,6 @@ func TestCheckTypeSetElemNestedAttrs(name, attr string, values map[string]string // }, // }) // } -// -// [custom]: https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests/known-value-checks/custom func TestMatchTypeSetElemNestedAttrs(name, attr string, values map[string]*regexp.Regexp) TestCheckFunc { return func(s *terraform.State) error { is, err := primaryInstanceState(s, name) diff --git a/knownvalue/string_regexp.go b/knownvalue/string_regexp.go new file mode 100644 index 000000000..d690d4998 --- /dev/null +++ b/knownvalue/string_regexp.go @@ -0,0 +1,45 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package knownvalue + +import ( + "fmt" + "regexp" +) + +var _ Check = stringRegularExpression{} + +type stringRegularExpression struct { + regex *regexp.Regexp +} + +// CheckValue determines whether the passed value is of type string, and +// contains a sequence of bytes that match the regular expression supplied +// to StringRegularExpression. +func (v stringRegularExpression) CheckValue(other any) error { + otherVal, ok := other.(string) + + if !ok { + return fmt.Errorf("expected string value for StringRegularExpression check, got: %T", other) + } + + if !v.regex.MatchString(otherVal) { + return fmt.Errorf("expected regex match %s for StringRegularExpression check, got: %s", v.regex.String(), otherVal) + } + + return nil +} + +// String returns the string representation of the value. +func (v stringRegularExpression) String() string { + return v.regex.String() +} + +// StringRegularExpression returns a Check for asserting equality between the +// supplied regular expression and a value passed to the CheckValue method. +func StringRegularExpression(regex *regexp.Regexp) stringRegularExpression { + return stringRegularExpression{ + regex: regex, + } +} diff --git a/knownvalue/string_regexp_test.go b/knownvalue/string_regexp_test.go new file mode 100644 index 000000000..4994408d6 --- /dev/null +++ b/knownvalue/string_regexp_test.go @@ -0,0 +1,75 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package knownvalue_test + +import ( + "fmt" + "regexp" + "testing" + + "github.com/google/go-cmp/cmp" + + "github.com/hashicorp/terraform-plugin-testing/knownvalue" +) + +func TestStringRegularExpression_CheckValue(t *testing.T) { + t.Parallel() + + testCases := map[string]struct { + self knownvalue.Check + other any + expectedError error + }{ + "zero-nil": { + self: knownvalue.StringRegularExpression(regexp.MustCompile("")), + expectedError: fmt.Errorf("expected string value for StringExact check, got: "), + }, + "zero-other": { + self: knownvalue.StringRegularExpression(regexp.MustCompile("")), + other: "", // checking against the underlying value field zero-value + }, + "nil": { + self: knownvalue.StringRegularExpression(regexp.MustCompile("str")), + expectedError: fmt.Errorf("expected string value for StringRegularExpression check, got: "), + }, + "wrong-type": { + self: knownvalue.StringRegularExpression(regexp.MustCompile("str")), + other: 1.234, + expectedError: fmt.Errorf("expected string value for StringRegularExpression check, got: float64"), + }, + "not-equal": { + self: knownvalue.StringRegularExpression(regexp.MustCompile("str")), + other: "rts", + expectedError: fmt.Errorf("expected regex match str for StringRegularExpression check, got: rts"), + }, + "equal": { + self: knownvalue.StringRegularExpression(regexp.MustCompile("str")), + other: "str", + }, + } + + 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 TestStringRegularExpression_String(t *testing.T) { + t.Parallel() + + got := knownvalue.StringRegularExpression(regexp.MustCompile("^str[0-9a-z]")).String() + + if diff := cmp.Diff(got, "^str[0-9a-z]"); diff != "" { + t.Errorf("unexpected difference: %s", diff) + } +} diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/string.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/string.mdx index dfb460543..b44e30360 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/string.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/string.mdx @@ -9,6 +9,7 @@ description: >- The known value checks that are available for string values are: * [StringExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/string#stringexact-check) +* [StringRegularExpression](/terraform/plugin/testing/acceptance-tests/known-value-checks/string#stringregularexpression-check) ## `StringExact` Check @@ -17,7 +18,7 @@ The [StringExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testi Example usage of [StringExact](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#StringExact) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. ```go -func TestExpectKnownValue_CheckPlan_String(t *testing.T) { +func TestExpectKnownValue_CheckPlan_StringExact(t *testing.T) { t.Parallel() resource.Test(t, resource.TestCase{ @@ -39,3 +40,33 @@ func TestExpectKnownValue_CheckPlan_String(t *testing.T) { }) } ``` + +## `StringRegularExpression` Check + +The [StringRegularExpression](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#StringRegularExpression) check tests that a resource attribute, or output value has a string value which matches the supplied regular expression. + +Example usage of [StringRegularExpression](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#StringRegularExpression) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. + +```go +func TestExpectKnownValue_CheckPlan_StringRegularExpression(t *testing.T) { + t.Parallel() + + resource.Test(t, resource.TestCase{ + // Provider definition omitted. + Steps: []resource.TestStep{ + { + // Example resource containing a computed string 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.StringRegularExpression(regexp.MustCompile("str"))), + }, + }, + }, + }, + }) +} +``` From 3690fb5b5b3362f4370d0a400d5e23aa88acc271 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Wed, 31 Jan 2024 09:37:24 +0000 Subject: [PATCH 59/73] Adding `CheckStateFunc` type and test for illustrating replacement of TestCheckResourceAttrPtr --- statecheck/expect_known_value_test.go | 172 +++++++++++++++++++------- statecheck/state_check.go | 6 + 2 files changed, 133 insertions(+), 45 deletions(-) diff --git a/statecheck/expect_known_value_test.go b/statecheck/expect_known_value_test.go index eb2bbbffd..74fc2f02d 100644 --- a/statecheck/expect_known_value_test.go +++ b/statecheck/expect_known_value_test.go @@ -221,51 +221,6 @@ func TestExpectKnownValue_CheckState_Bool(t *testing.T) { }) } -func TestExpectKnownValue_CheckState_BoolPointer(t *testing.T) { - t.Parallel() - - testBool := Pointer(false) - - r.Test(t, r.TestCase{ - ProviderFactories: map[string]func() (*schema.Provider, error){ - "test": func() (*schema.Provider, error) { //nolint:unparam // required signature - return testProvider(), nil - }, - }, - Steps: []r.TestStep{ - { - Config: `resource "test_resource" "one" { - bool_attribute = true - } - `, - ConfigStateChecks: []statecheck.StateCheck{ - AlterValue(testBool), - statecheck.ExpectKnownValue( - "test_resource.one", - tfjsonpath.New("bool_attribute"), - knownvalue.Bool(*testBool), - ), - }, - }, - }, - }) -} - -func Pointer[T any](in T) *T { - return &in -} - -type mutate struct{} - -func (m mutate) CheckState(context.Context, statecheck.CheckStateRequest, *statecheck.CheckStateResponse) { -} - -func AlterValue(b *bool) mutate { - *b = true - - return mutate{} -} - func TestExpectKnownValue_CheckState_Bool_KnownValueWrongType(t *testing.T) { t.Parallel() @@ -1475,6 +1430,123 @@ func StringContains(value string) stringContains { } } +func TestExpectKnownValue_CheckState_BoolPointer(t *testing.T) { + t.Parallel() + + var apiObj apiObject + + r.Test(t, r.TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": func() (*schema.Provider, error) { //nolint:unparam // required signature + return testProvider(), nil + }, + }, + Steps: []r.TestStep{ + { + Config: `resource "test_resource" "one" {}`, + ConfigStateChecks: []statecheck.StateCheck{ + makeAPICall("test_resource.one", &apiObj), + statecheck.ExpectKnownValue( + "test_resource.one", + tfjsonpath.New("string_computed_attribute"), + StringPtr(&apiObj.s), + ), + }, + }, + }, + }) +} + +var _ knownvalue.Check = stringPtr{} + +type stringPtr struct { + value *string +} + +// CheckValue determines whether the passed value is of type string, and +// contains a matching string value. +func (v stringPtr) CheckValue(other any) error { + otherVal, ok := other.(string) + + if !ok { + return fmt.Errorf("expected string value for StringPtr check, got: %T", other) + } + + if otherVal != *v.value { + return fmt.Errorf("expected value %s for StringPtr check, got: %s", *v.value, otherVal) + } + + return nil +} + +// String returns the string representation of the string value. +func (v stringPtr) String() string { + return *v.value +} + +// StringPtr returns a Check for asserting equality between the +// supplied string and the value passed to the CheckValue method. +func StringPtr(value *string) stringPtr { + return stringPtr{ + value: value, + } +} + +type apiObject struct { + s string +} + +func makeAPICall(name string, apiObj *apiObject) statecheck.CheckStateFunc { + return func(ctx context.Context, req statecheck.CheckStateRequest, resp *statecheck.CheckStateResponse) { + var resource *tfjson.StateResource + + if req.State == nil { + resp.Error = fmt.Errorf("state is nil") + + return + } + + if req.State.Values == nil { + resp.Error = fmt.Errorf("state does not contain any state values") + + return + } + + if req.State.Values.RootModule == nil { + resp.Error = fmt.Errorf("state does not contain a root module") + + return + } + + for _, res := range req.State.Values.RootModule.Resources { + if name == res.Address { + resource = res + + break + } + } + + if resource == nil { + resp.Error = fmt.Errorf("%s - Resource not found in state", name) + + return + } + + // Typically, an ID, or some other unique identifier would be extracted from the resource and + // supplied to an API client in order to make an API call to retrieve an API object. + s, err := tfjsonpath.Traverse(resource.AttributeValues, tfjsonpath.New("string_computed_attribute")) + + if err != nil { + resp.Error = err + + return + } + + //nolint:forcetypeassert // we know the type of the value + *apiObj = apiObject{s: s.(string)} + } +} + func TestExpectKnownValue_CheckState_String_KnownValueWrongType(t *testing.T) { t.Parallel() @@ -1592,6 +1664,12 @@ func testProvider() *schema.Provider { "test_resource": { CreateContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { d.SetId("test") + + err := d.Set("string_computed_attribute", "computed") + if err != nil { + return diag.Errorf("error setting string_computed_attribute: %s", err) + } + return nil }, UpdateContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { @@ -1665,6 +1743,10 @@ func testProvider() *schema.Provider { Optional: true, Type: schema.TypeString, }, + "string_computed_attribute": { + Computed: true, + Type: schema.TypeString, + }, }, }, }, diff --git a/statecheck/state_check.go b/statecheck/state_check.go index cfd2da6b1..3af9fa1ac 100644 --- a/statecheck/state_check.go +++ b/statecheck/state_check.go @@ -28,3 +28,9 @@ type CheckStateResponse struct { // to be reported as a test failure. Error error } + +type CheckStateFunc func(context.Context, CheckStateRequest, *CheckStateResponse) + +func (f CheckStateFunc) CheckState(ctx context.Context, req CheckStateRequest, resp *CheckStateResponse) { + f(ctx, req, resp) +} From 1d2753a53fe29548ff25fef145b4d99f0d455619 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Wed, 31 Jan 2024 10:00:28 +0000 Subject: [PATCH 60/73] Updating docs regarding usage of preferring direct testing of resource attributes rather than using output values --- helper/resource/testing.go | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/helper/resource/testing.go b/helper/resource/testing.go index cb621551c..1b551ff1f 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -1944,17 +1944,12 @@ func testCheckResourceAttrPair(isFirst *terraform.InstanceState, nameFirst strin // // Provider definition omitted. // Steps: []resource.TestStep{ // { -// // Example resource containing a computed boolean attribute named "computed_attribute" -// Config: `resource "test_resource" "one" {} -// -// output computed_output { -// value = test_resource.one.computed_attribute -// }`, +// // Example provider containing a provider-defined function named "bool" +// Config: `output "test" { +// value = provider::example::bool(true) +// }`, // ConfigStateChecks: []statecheck.StateCheck{ -// statecheck.ExpectKnownOutputValue( -// "computed_output", -// knownvalue.Bool(true), -// ), +// statecheck.ExpectKnownOutputValue("test", knownvalue.Bool(true)), // }, // }, // }, @@ -1985,6 +1980,9 @@ func testCheckResourceAttrPair(isFirst *terraform.InstanceState, nameFirst strin // // Example resource containing a computed boolean attribute named "computed_attribute" // Config: `resource "test_resource" "one" {} // +// // Generally, it is not necessary to use an output to test a resource attribute, +// // the resource attribute should be tested directly instead. This is only shown as +// // an example. // output test_resource_one_output { // value = test_resource.one // } @@ -2050,9 +2048,12 @@ func TestCheckOutput(name, value string) TestCheckFunc { // // Example resource containing a computed string attribute named "computed_attribute" // Config: `resource "test_resource" "one" {} // -// output test_resource_one_output { -// value = test_resource.one -// }`, +// // Generally, it is not necessary to use an output to test a resource attribute, +// // the resource attribute should be tested directly instead. This is only shown as +// // an example. +// output test_resource_one_output { +// value = test_resource.one +// }`, // ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectKnownOutputValueAtPath( // "test_resource_one_output", From 9fb18ee686446dfc455e18e72e7b2b16887f1d35 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Wed, 31 Jan 2024 10:08:12 +0000 Subject: [PATCH 61/73] Modify docs to highlight caveats of using ExpectKnownOutputValueAtPath plan check with versions of Terraform <1.3.0 --- plancheck/expect_known_output_value_at_path.go | 3 ++- .../plugin/testing/acceptance-tests/plan-checks/output.mdx | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/plancheck/expect_known_output_value_at_path.go b/plancheck/expect_known_output_value_at_path.go index ffb8ee334..42f07a151 100644 --- a/plancheck/expect_known_output_value_at_path.go +++ b/plancheck/expect_known_output_value_at_path.go @@ -60,7 +60,8 @@ func (e expectKnownOutputValueAtPath) CheckPlan(ctx context.Context, req CheckPl } // ExpectKnownOutputValueAtPath returns a plan check that asserts that the specified output at the given path -// has a known type and value. +// has a known type and value. Prior to Terraform v1.3.0 a planned output is marked as fully unknown +// if any attribute is unknown. func ExpectKnownOutputValueAtPath(outputAddress string, outputPath tfjsonpath.Path, knownValue knownvalue.Check) PlanCheck { return expectKnownOutputValueAtPath{ outputAddress: outputAddress, diff --git a/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx b/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx index c5a23435a..892ebbc89 100644 --- a/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx +++ b/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx @@ -68,6 +68,8 @@ func TestExpectKnownOutputValue_CheckPlan_Bool(t *testing.T) { The [`plancheck.ExpectKnownOutputValueAtPath(address, path, value)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectKnownOutputValueAtPath) plan check verifies that a specific output value at a defined path has a known type, and value. +~> **Note**: Prior to Terraform v1.3.0 a planned output is marked as fully unknown if any attribute is unknown. + Refer to [Known Value Checks](/terraform/plugin/testing/acceptance-tests/known-value-checks) for details, and examples of the available [knownvalue.Check](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#Check) types that can be used with the `ExpectKnownOutputValueAtPath` plan check. ```go From 1573251e762d81d6dfeaf0fa70b074056e7b0043 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Wed, 31 Jan 2024 10:13:27 +0000 Subject: [PATCH 62/73] Fixing test --- knownvalue/string_regexp_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/knownvalue/string_regexp_test.go b/knownvalue/string_regexp_test.go index 4994408d6..f4e07315a 100644 --- a/knownvalue/string_regexp_test.go +++ b/knownvalue/string_regexp_test.go @@ -23,7 +23,7 @@ func TestStringRegularExpression_CheckValue(t *testing.T) { }{ "zero-nil": { self: knownvalue.StringRegularExpression(regexp.MustCompile("")), - expectedError: fmt.Errorf("expected string value for StringExact check, got: "), + expectedError: fmt.Errorf("expected string value for StringRegularExpression check, got: "), }, "zero-other": { self: knownvalue.StringRegularExpression(regexp.MustCompile("")), From fa80c476bd6bb56ecec273ac40b0eae82ae3f72c Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Wed, 31 Jan 2024 11:23:43 +0000 Subject: [PATCH 63/73] Updating docs --- helper/resource/testing.go | 4 ++ .../acceptance-tests/plan-checks/output.mdx | 39 ++++++++++--------- .../acceptance-tests/state-checks/output.mdx | 22 ++++++----- 3 files changed, 38 insertions(+), 27 deletions(-) diff --git a/helper/resource/testing.go b/helper/resource/testing.go index 1b551ff1f..c9b928bc6 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -1935,12 +1935,16 @@ func testCheckResourceAttrPair(isFirst *terraform.InstanceState, nameFirst strin // "github.com/hashicorp/terraform-plugin-testing/helper/resource" // "github.com/hashicorp/terraform-plugin-testing/knownvalue" // "github.com/hashicorp/terraform-plugin-testing/statecheck" +// "github.com/hashicorp/terraform-plugin-testing/tfversion" // ) // // func TestExpectKnownOutputValue_CheckState_Bool(t *testing.T) { // t.Parallel() // // resource.Test(t, resource.TestCase{ +// TerraformVersionChecks: []tfversion.TerraformVersionCheck{ +// tfversion.SkipBelow(tfversion.Version1_8_0), +// }, // // Provider definition omitted. // Steps: []resource.TestStep{ // { diff --git a/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx b/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx index 892ebbc89..bb4548e70 100644 --- a/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx +++ b/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx @@ -33,27 +33,27 @@ import ( "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/tfversion" ) func TestExpectKnownOutputValue_CheckPlan_Bool(t *testing.T) { t.Parallel() - resource.Test(t, resource.TestCase{ + resource.UnitTest(t, resource.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_8_0), + }, // Provider definition omitted. Steps: []resource.TestStep{ { - Config: `resource "test_resource" "one" { - bool_attribute = true - } - - output bool_output { - value = test_resource.one.bool_attribute - } - `, + Config: ` + output "test" { + value = provider::example::bool(true) + }`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownOutputValue( - "bool_output", + "test", knownvalue.Bool(true), ), }, @@ -90,18 +90,21 @@ func TestExpectKnownOutputValue_CheckPlan_Bool(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - Config: `resource "test_resource" "one" { - bool_attribute = true - } - - output bool_output { - value = test_resource.one.bool_attribute + // Example resource containing a computed boolean attribute named "computed_attribute" + Config: `resource "test_resource" "one" {} + + // Generally, it is not necessary to use an output to test a resource attribute, + // the resource attribute should be tested directly instead. This is only shown as + // an example. + output test { + value = test_resource.one } `, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ - plancheck.ExpectKnownOutputValue( - "bool_output", + plancheck.ExpectKnownOutputValueAtPath( + "test", + tfjsonpath.New("computed_attribute"), knownvalue.Bool(true), ), }, diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx index 54385f457..d420e8a5d 100644 --- a/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx @@ -29,25 +29,26 @@ import ( "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/knownvalue" "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfversion" ) func TestExpectKnownOutputValue_CheckState_Bool(t *testing.T) { t.Parallel() - resource.Test(t, resource.TestCase{ + resource.UnitTest(t, resource.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_8_0), + }, // Provider definition omitted. Steps: []resource.TestStep{ { - // Example resource containing a computed boolean attribute named "computed_attribute" - Config: `resource "test_resource" "one" {} - - output computed_output { - value = test_resource.one.computed_attribute - } - `, + Config: ` + output "test" { + value = provider::example::bool(true) + }`, ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValue( - "computed_output", + "test", knownvalue.Bool(true), ), }, @@ -85,6 +86,9 @@ func TestExpectKnownOutputValueAtPath_CheckState_Bool(t *testing.T) { // Example resource containing a computed boolean attribute named "computed_attribute" Config: `resource "test_resource" "one" {} + // Generally, it is not necessary to use an output to test a resource attribute, + // the resource attribute should be tested directly instead. This is only shown as + // an example. output test_resource_one_output { value = test_resource.one } From 11cdf9ab995c7df01a81101893b1c7be332a726d Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Wed, 28 Feb 2024 12:01:58 +0000 Subject: [PATCH 64/73] Removing deprecation of built-in TestCheckFunc implementations --- helper/resource/testing.go | 120 ++------------------------------ helper/resource/testing_sets.go | 24 ------- 2 files changed, 4 insertions(+), 140 deletions(-) diff --git a/helper/resource/testing.go b/helper/resource/testing.go index c9b928bc6..ecceabb2a 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -558,9 +558,6 @@ type TestStep struct { // destroy plan will still be attempted. // // If this is nil, no check is done on this step. - // - // Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. - // This field will be removed in the next major version. Check TestCheckFunc // Destroy will create a destroy plan if set to true. @@ -960,10 +957,6 @@ func testResource(c TestStep, state *terraform.State) (*terraform.ResourceState, // // ComposeTestCheckFunc returns immediately on the first TestCheckFunc error. // To aggregrate all errors, use ComposeAggregateTestCheckFunc instead. -// -// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. -// This function is unnecessary with ConfigStateChecks as all checks will be ran and therefore -// this function will be removed in the next major version. func ComposeTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc { return func(s *terraform.State) error { for i, f := range fs { @@ -984,10 +977,6 @@ func ComposeTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc { // // Unlike ComposeTestCheckFunc, ComposeAggergateTestCheckFunc runs _all_ of the // TestCheckFuncs and aggregates failures. -// -// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. -// This function is unnecessary with ConfigStateChecks as all checks will be ran and therefore -// this function will be removed in the next major version. func ComposeAggregateTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc { return func(s *terraform.State) error { var result []error @@ -1045,10 +1034,6 @@ func ComposeAggregateTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc { // attribute directly is not supported. Use TestCheckResourceAttr with // the special .# or .% key syntax for those situations instead. // -// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. -// Use the built-in [ExpectKnownValue] state check with the [knownvalue.NotNull] known value type -// instead. TestCheckResourceAttrSet function will be removed in the next major version. -// // The following is an example of using [ExpectKnownValue] with [knownvalue.NotNull] // to replicate the behaviour of TestCheckResourceAttrSet. // @@ -1183,10 +1168,6 @@ func testCheckResourceAttrSet(is *terraform.InstanceState, name string, key stri // - Float/Integer: Stringified number, such as "1.2" or "123". // - String: No conversion necessary. // -// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. -// Use the built-in [statecheck.ExpectKnownValue] state check instead. -// TestCheckResourceAttr function will be removed in the next major version. -// // The following is an example of using [statecheck.ExpectKnownValue] // to replicate the behaviour of TestCheckResourceAttr. // @@ -1305,11 +1286,6 @@ func testCheckResourceAttr(is *terraform.InstanceState, name string, key string, // // When this function returns an error, TestCheckResourceAttrWith will fail the check. // -// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. -// Use the built-int [statecheck.ExpectKnownValue] state check in combination -// with a [knownvalue.Check] instead. -// CheckResourceAttrWithFunc will be removed in the next major version. -// // The following is an example of using [statecheck.ExpectKnownValue] in combination // with [knownvalue.StringRegularExpression] to replicate the behaviour of TestCheckResourceAttrWith. // @@ -1380,11 +1356,6 @@ type CheckResourceAttrWithFunc func(value string) error // if it was found in the state. The function must return an error for the // check to fail, or `nil` to succeed. // -// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. -// Use the built-int [statecheck.ExpectKnownValue] state check in combination -// with a [knownvalue.Check] instead. -// TestCheckResourceAttrWith function will be removed in the next major version. -// // The following is an example of using [statecheck.ExpectKnownValue] in combination // with [knownvalue.StringRegularExpression] to replicate the behaviour of TestCheckResourceAttrWith. // @@ -1470,10 +1441,6 @@ func TestCheckResourceAttrWith(name, key string, checkValueFunc CheckResourceAtt // attribute directly is not supported. Use TestCheckResourceAttr with // the special .# or .% key syntax for those situations instead. // -// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. -// Use the built-in [statecheck.ExpectKnownValue] with [knownvalue.Null] instead. -// TestCheckNoResourceAttr function will be removed in the next major version. -// // The following is an example of using [statecheck.ExpectKnownValue] with [knownvalue.Null] to // replicate the behaviour of TestCheckNoResourceAttr. // @@ -1612,11 +1579,6 @@ func testCheckNoResourceAttr(is *terraform.InstanceState, name string, key strin // regular expression is supported by the Go regular expression handlers during // compilation. // -// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. -// Use the built-in [statecheck.ExpectKnownValue] state check in combination -// with a [knownvalue.Check] instead. -// TestMatchResourceAttr function will be removed in the next major version. -// // The following is an example of using [statecheck.ExpectKnownValue] // in combination with [knownvalue.StringRegularExpression] to replicate the behaviour of // TestMatchResourceAttr. @@ -1702,65 +1664,6 @@ func testMatchResourceAttr(is *terraform.InstanceState, name string, key string, // // Refer to the TestCheckResourceAttr documentation for more information about // setting the name, key, and value parameters. -// -// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. -// Use the built-in [statecheck.ExpectKnownValue] state check in combination -// with types implementing [knownvalue.Check] instead. -// TestCheckResourceAttrPtr function will be removed in the next major version. -// -// The following is an example of using [statecheck.ExpectKnownValue] -// to replicate the behaviour of TestCheckResourceAttrPtr. -// -// package example_test -// -// import ( -// "context" -// "testing" -// -// "github.com/hashicorp/terraform-plugin-testing/helper/resource" -// "github.com/hashicorp/terraform-plugin-testing/knownvalue" -// "github.com/hashicorp/terraform-plugin-testing/statecheck" -// "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" -// ) -// -// func TestExpectKnownValue_CheckState_BoolPointer(t *testing.T) { -// t.Parallel() -// -// testBool := Pointer(false) -// -// resource.Test(t, resource.TestCase{ -// // Provider definition omitted. -// Steps: []resource.TestStep{ -// { -// // Example resource containing a computed boolean attribute named "computed_attribute" -// Config: `resource "test_resource" "one" {}`, -// ConfigStateChecks: []statecheck.StateCheck{ -// AlterValue(testBool), -// statecheck.ExpectKnownValue( -// "test_resource.one", -// tfjsonpath.New("computed_attribute"), -// knownvalue.Bool(*testBool), -// ), -// }, -// }, -// }, -// }) -// } -// -// func Pointer[T any](in T) *T { -// return &in -// } -// -// type mutate struct{} -// -// func (m mutate) CheckState(context.Context, statecheck.CheckStateRequest, *statecheck.CheckStateResponse) { -// } -// -// func AlterValue(b *bool) mutate { -// *b = true -// -// return mutate{} -// } func TestCheckResourceAttrPtr(name string, key string, value *string) TestCheckFunc { return func(s *terraform.State) error { return TestCheckResourceAttr(name, key, *value)(s) @@ -1816,14 +1719,6 @@ func TestCheckModuleResourceAttrPtr(mp []string, name string, key string, value // value. // - .#: Number of elements in list or set. // - .%: Number of elements in map. -// -// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. -// TestCheckResourceAttrPair has been deprecated without replacement. Please -// use the GitHub issue [Deprecation of Built-In TestCheckFunc Implementations for Checking Pairs of Values] -// to indicate if you have a use-case for a built-in [TestStep.ConfigStateChecks] state check -// function that would replicate the behaviour of TestCheckResourceAttrPair. -// -// [Deprecation of Built-In TestCheckFunc Implementations for Checking Pairs of Values]: https://github.com/hashicorp/terraform-plugin-testing/issues/282 func TestCheckResourceAttrPair(nameFirst, keyFirst, nameSecond, keySecond string) TestCheckFunc { return checkIfIndexesIntoTypeSetPair(keyFirst, keySecond, func(s *terraform.State) error { isFirst, err := primaryInstanceState(s, nameFirst) @@ -1919,11 +1814,6 @@ func testCheckResourceAttrPair(isFirst *terraform.InstanceState, nameFirst strin // TestCheckOutput checks an output in the Terraform configuration // -// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. -// Use the built-in [statecheck.ExpectKnownOutputValue], and -// [statecheck.ExpectKnownOutputValueAtPath] state checks instead. -// TestCheckOutput function will be removed in the next major version. -// // The following is an example of using [statecheck.ExpectKnownOutputValue] // to replicate the behaviour of TestCheckOutput. // @@ -1960,7 +1850,7 @@ func testCheckResourceAttrPair(isFirst *terraform.InstanceState, nameFirst strin // }) // } // -// The following is an example of using statecheck.ExpectKnownOutputValueAtPath +// The following is an example of using [statecheck.ExpectKnownOutputValueAtPath] // to replicate the behaviour of TestCheckOutput. // // package example_test @@ -2022,11 +1912,9 @@ func TestCheckOutput(name, value string) TestCheckFunc { } } -// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. -// Use the built-in [statecheck.ExpectKnownOutputValue], and -// [statecheck.ExpectKnownOutputValueAtPath] state checks, can be used in -// combination with a [knownvalue.Check] instead. -// TestMatchOutput function will be removed in the next major version. +// TestMatchOutput ensures a value matching a regular expression is +// stored in state for the given name. State value checking is only +// recommended for testing Computed attributes and attribute defaults. // // The following is an example of using [statecheck.ExpectKnownOutputValueAtPath] // in combination with [knownvalue.StringRegularExpression] to replicate the behaviour of diff --git a/helper/resource/testing_sets.go b/helper/resource/testing_sets.go index 8c1fcbfe7..82575d2a0 100644 --- a/helper/resource/testing_sets.go +++ b/helper/resource/testing_sets.go @@ -58,11 +58,6 @@ const ( // you were not intending to in the set. Provide the most complete mapping of // attributes possible to be sure the unique element exists. // -// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. -// Use the built-in [statecheck.ExpectKnownValue] state check in combination -// with [knownvalue.SetExact] or [knownvalue.SetPartial] instead. -// TestCheckTypeSetElemNestedAttrs function will be removed in the next major version. -// // The following is an example of using [statecheck.ExpectKnownValue] in combination // with [knownvalue.SetPartial] to replicate the behaviour of TestCheckTypeSetElemNestedAttrs. // @@ -172,12 +167,6 @@ func TestCheckTypeSetElemNestedAttrs(name, attr string, values map[string]string // you were not intending to in the set. Provide the most complete mapping of // attributes possible to be sure the unique element exists. // -// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. -// Use the built-in [statecheck.ExpectKnownValue] state check, can be used in combination -// with [knownvalue.ListExact], [knownvalue.ListPartial], [knownvalue.SetExact], or -// [knownvalue.SetPartial], with nested [knownvalue.Check] instead. -// TestMatchTypeSetElemNestedAttrs function will be removed in the next major version. -// // The following is an example of using [statecheck.ExpectKnownValue] in combination // with [knownvalue.SetExact], with a nested [knownvalue.StringRegularExpression] to replicate // the behaviour of TestCheckTypeSetElemAttr. @@ -292,11 +281,6 @@ func TestMatchTypeSetElemNestedAttrs(name, attr string, values map[string]*regex // - Float/Integer: Stringified number, such as "1.2" or "123". // - String: No conversion necessary. // -// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. -// Use the built-in [statecheck.ExpectKnownValue] state check in combination -// with [knownvalue.SetExact] or [knownvalue.SetPartial] instead. -// TestCheckTypeSetElemAttr function will be removed in the next major version. -// // The following is an example of using [statecheck.ExpectKnownValue] in combination // with [knownvalue.SetExact] to replicate the behaviour of TestCheckTypeSetElemAttr. // @@ -376,14 +360,6 @@ func TestCheckTypeSetElemAttr(name, attr, value string) TestCheckFunc { // attribute. Use the sentinel value '*' to replace the element indexing into // a list or set. The sentinel value can be used for each list or set index, if // there are multiple lists or sets in the attribute path. -// -// Deprecated: State checks using [TestStep.Check] have been superseded by [TestStep.ConfigStateChecks]. -// TestCheckTypeSetElemAttrPair has been deprecated without replacement. Please -// use the GitHub issue [Deprecation of Built-In TestCheckFunc Implementations for Checking Pairs of Values] -// to indicate if you have a use-case for a built-in ConfigStateChecks state check -// function that would replicate the behaviour of TestCheckTypeSetElemAttrPair. -// -// [Deprecation of Built-In TestCheckFunc Implementations for Checking Pairs of Values](https://github.com/hashicorp/terraform-plugin-testing/issues/282) func TestCheckTypeSetElemAttrPair(nameFirst, keyFirst, nameSecond, keySecond string) TestCheckFunc { return func(s *terraform.State) error { isFirst, err := primaryInstanceState(s, nameFirst) From b22c0bb2f8bea533369c73617fbdb363c468883b Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Wed, 28 Feb 2024 12:13:17 +0000 Subject: [PATCH 65/73] Updating tests --- plancheck/expect_known_output_value_test.go | 2 +- statecheck/expect_known_output_value_test.go | 2 +- statecheck/expect_known_value_test.go | 117 ------------------- 3 files changed, 2 insertions(+), 119 deletions(-) diff --git a/plancheck/expect_known_output_value_test.go b/plancheck/expect_known_output_value_test.go index 0bde45150..504c30c8f 100644 --- a/plancheck/expect_known_output_value_test.go +++ b/plancheck/expect_known_output_value_test.go @@ -225,7 +225,7 @@ func TestExpectKnownOutputValue_CheckPlan_AttributeValueNotNull(t *testing.T) { ), plancheck.ExpectKnownOutputValue( "set_nested_block_output", - knownvalue.ListSizeExact(1), + knownvalue.SetSizeExact(1), ), plancheck.ExpectKnownOutputValue( "string_output", diff --git a/statecheck/expect_known_output_value_test.go b/statecheck/expect_known_output_value_test.go index 8b4dc3293..62d9067fe 100644 --- a/statecheck/expect_known_output_value_test.go +++ b/statecheck/expect_known_output_value_test.go @@ -169,7 +169,7 @@ func TestExpectKnownOutputValue_CheckState_AttributeValueNotNull(t *testing.T) { ), statecheck.ExpectKnownOutputValue( "set_nested_block_output", - knownvalue.ListSizeExact(1), + knownvalue.SetSizeExact(1), ), statecheck.ExpectKnownOutputValue( "string_output", diff --git a/statecheck/expect_known_value_test.go b/statecheck/expect_known_value_test.go index 74fc2f02d..f02b8cd09 100644 --- a/statecheck/expect_known_value_test.go +++ b/statecheck/expect_known_value_test.go @@ -1430,123 +1430,6 @@ func StringContains(value string) stringContains { } } -func TestExpectKnownValue_CheckState_BoolPointer(t *testing.T) { - t.Parallel() - - var apiObj apiObject - - r.Test(t, r.TestCase{ - ProviderFactories: map[string]func() (*schema.Provider, error){ - "test": func() (*schema.Provider, error) { //nolint:unparam // required signature - return testProvider(), nil - }, - }, - Steps: []r.TestStep{ - { - Config: `resource "test_resource" "one" {}`, - ConfigStateChecks: []statecheck.StateCheck{ - makeAPICall("test_resource.one", &apiObj), - statecheck.ExpectKnownValue( - "test_resource.one", - tfjsonpath.New("string_computed_attribute"), - StringPtr(&apiObj.s), - ), - }, - }, - }, - }) -} - -var _ knownvalue.Check = stringPtr{} - -type stringPtr struct { - value *string -} - -// CheckValue determines whether the passed value is of type string, and -// contains a matching string value. -func (v stringPtr) CheckValue(other any) error { - otherVal, ok := other.(string) - - if !ok { - return fmt.Errorf("expected string value for StringPtr check, got: %T", other) - } - - if otherVal != *v.value { - return fmt.Errorf("expected value %s for StringPtr check, got: %s", *v.value, otherVal) - } - - return nil -} - -// String returns the string representation of the string value. -func (v stringPtr) String() string { - return *v.value -} - -// StringPtr returns a Check for asserting equality between the -// supplied string and the value passed to the CheckValue method. -func StringPtr(value *string) stringPtr { - return stringPtr{ - value: value, - } -} - -type apiObject struct { - s string -} - -func makeAPICall(name string, apiObj *apiObject) statecheck.CheckStateFunc { - return func(ctx context.Context, req statecheck.CheckStateRequest, resp *statecheck.CheckStateResponse) { - var resource *tfjson.StateResource - - if req.State == nil { - resp.Error = fmt.Errorf("state is nil") - - return - } - - if req.State.Values == nil { - resp.Error = fmt.Errorf("state does not contain any state values") - - return - } - - if req.State.Values.RootModule == nil { - resp.Error = fmt.Errorf("state does not contain a root module") - - return - } - - for _, res := range req.State.Values.RootModule.Resources { - if name == res.Address { - resource = res - - break - } - } - - if resource == nil { - resp.Error = fmt.Errorf("%s - Resource not found in state", name) - - return - } - - // Typically, an ID, or some other unique identifier would be extracted from the resource and - // supplied to an API client in order to make an API call to retrieve an API object. - s, err := tfjsonpath.Traverse(resource.AttributeValues, tfjsonpath.New("string_computed_attribute")) - - if err != nil { - resp.Error = err - - return - } - - //nolint:forcetypeassert // we know the type of the value - *apiObj = apiObject{s: s.(string)} - } -} - func TestExpectKnownValue_CheckState_String_KnownValueWrongType(t *testing.T) { t.Parallel() From 2217b9c171d2459a612b608b8754b07bda72db30 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Wed, 28 Feb 2024 16:25:22 +0000 Subject: [PATCH 66/73] Remove CheckStateFunc type --- statecheck/state_check.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/statecheck/state_check.go b/statecheck/state_check.go index 3af9fa1ac..cfd2da6b1 100644 --- a/statecheck/state_check.go +++ b/statecheck/state_check.go @@ -28,9 +28,3 @@ type CheckStateResponse struct { // to be reported as a test failure. Error error } - -type CheckStateFunc func(context.Context, CheckStateRequest, *CheckStateResponse) - -func (f CheckStateFunc) CheckState(ctx context.Context, req CheckStateRequest, resp *CheckStateResponse) { - f(ctx, req, resp) -} From 374aae62c7ac5fa3f16f154a2a8b87da36a620d6 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Thu, 29 Feb 2024 10:49:16 +0000 Subject: [PATCH 67/73] Updating docs --- .../acceptance-tests/known-value-checks/not-null.mdx | 2 +- .../acceptance-tests/known-value-checks/string.mdx | 4 ++-- .../testing/acceptance-tests/plan-checks/output.mdx | 8 ++++---- .../testing/acceptance-tests/plan-checks/resource.mdx | 8 +++----- .../testing/acceptance-tests/state-checks/custom.mdx | 2 +- .../testing/acceptance-tests/state-checks/resource.mdx | 2 +- 6 files changed, 12 insertions(+), 14 deletions(-) diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/not-null.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/not-null.mdx index 7fee5b918..68e5d8688 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/not-null.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/not-null.mdx @@ -24,7 +24,7 @@ func TestExpectKnownValue_CheckState_AttributeValueNull(t *testing.T) { // Provider definition omitted. Steps: []r.TestStep{ { - // Example resource containing a computed attribute named "computed_attribute" + // Example resource containing a computed attribute named "computed_attribute" Config: `resource "test_resource" "one" {}`, ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/string.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/string.mdx index b44e30360..756dc313d 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/string.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/string.mdx @@ -25,7 +25,7 @@ func TestExpectKnownValue_CheckPlan_StringExact(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - // Example resource containing a computed string attribute named "computed_attribute" + // Example resource containing a computed string attribute named "computed_attribute" Config: `resource "test_resource" "one" {}`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ @@ -55,7 +55,7 @@ func TestExpectKnownValue_CheckPlan_StringRegularExpression(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - // Example resource containing a computed string attribute named "computed_attribute" + // Example resource containing a computed string attribute named "computed_attribute" Config: `resource "test_resource" "one" {}`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ diff --git a/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx b/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx index bb4548e70..70981bdb9 100644 --- a/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx +++ b/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx @@ -96,10 +96,10 @@ func TestExpectKnownOutputValue_CheckPlan_Bool(t *testing.T) { // Generally, it is not necessary to use an output to test a resource attribute, // the resource attribute should be tested directly instead. This is only shown as // an example. - output test { - value = test_resource.one - } - `, + output test { + value = test_resource.one + } + `, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownOutputValueAtPath( diff --git a/website/docs/plugin/testing/acceptance-tests/plan-checks/resource.mdx b/website/docs/plugin/testing/acceptance-tests/plan-checks/resource.mdx index 1aabb1281..b96ae68bb 100644 --- a/website/docs/plugin/testing/acceptance-tests/plan-checks/resource.mdx +++ b/website/docs/plugin/testing/acceptance-tests/plan-checks/resource.mdx @@ -41,15 +41,13 @@ func TestExpectKnownValue_CheckPlan_String(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - Config: `resource "test_resource" "one" { - string_attribute = "str" - } - `, + // Example resource containing a computed string attribute named "computed_attribute" + Config: `resource "test_resource" "one" {}`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( "test_resource.one", - tfjsonpath.New("string_attribute"), + tfjsonpath.New("computed_attribute"), knownvalue.StringExact("str")), }, }, diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx index 54da165d3..46cd3877e 100644 --- a/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/custom.mdx @@ -106,7 +106,7 @@ func TestExpectKnownValue_CheckState_Bool(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - // Example resource containing a computed boolean attribute named "computed_attribute" + // Example resource containing a computed boolean attribute named "computed_attribute" Config: `resource "test_resource" "one" {}`, ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx index bacc4e79f..a3e94cbbe 100644 --- a/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/resource.mdx @@ -39,7 +39,7 @@ func TestExpectKnownValue_CheckState_Bool(t *testing.T) { // Provider definition omitted. Steps: []resource.TestStep{ { - // Example resource containing a computed boolean attribute named "computed_attribute" + // Example resource containing a computed boolean attribute named "computed_attribute" Config: `resource "test_resource" "one" {}`, ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue( From 6469dc3ec9e65c7d88636504ebbde147cc7e6e1b Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Thu, 29 Feb 2024 11:00:22 +0000 Subject: [PATCH 68/73] Adding changelog --- .changes/unreleased/NOTES-20240229-105744.yaml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changes/unreleased/NOTES-20240229-105744.yaml diff --git a/.changes/unreleased/NOTES-20240229-105744.yaml b/.changes/unreleased/NOTES-20240229-105744.yaml new file mode 100644 index 000000000..3592cf3f4 --- /dev/null +++ b/.changes/unreleased/NOTES-20240229-105744.yaml @@ -0,0 +1,7 @@ +kind: NOTES +body: 'all: `ExpectKnownValue`, `ExpectKnownOutputValue` and `ExpectKnownOutputValueAtPath` + plan and state checks, along with the `knownvalue` package are experimental and may be + altered or removed in a subsequent release' +time: 2024-02-29T10:57:44.318605Z +custom: + Issue: "276" From 2102e65a43547ea07ab5d110daa4731cbabdc16e Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Thu, 29 Feb 2024 11:06:14 +0000 Subject: [PATCH 69/73] Fixing links --- .../plugin/testing/acceptance-tests/plan-checks/output.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx b/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx index 70981bdb9..d8070cbc3 100644 --- a/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx +++ b/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx @@ -117,7 +117,7 @@ func TestExpectKnownOutputValue_CheckPlan_Bool(t *testing.T) { ## `ExpectNullOutputValue` Plan Check -~> **Note**: `ExpectNullOutputValue` is deprecated. Use [`ExpectKnownOutputValue`](/terraform/plugin/testing/acceptance-tests/plan-checks/output#expectknownoutputvalue-plan-check) with [`knownvalue.Null()`](/terraform/plugin/testing/acceptance-tests/known-value-checks#null) instead. +~> **Note**: `ExpectNullOutputValue` is deprecated. Use [`ExpectKnownOutputValue`](/terraform/plugin/testing/acceptance-tests/plan-checks/output#expectknownoutputvalue-plan-check) with [`knownvalue.Null()`](/terraform/plugin/testing/acceptance-tests/known-value-checks/null) instead. The built-in [`plancheck.ExpectNullOutputValue(address)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectNullOutputValue) plan check determines whether an output at the specified address has a null value. @@ -159,7 +159,7 @@ func Test_ExpectNullOutputValue_StringAttribute_NullConfig(t *testing.T) { ## `ExpectNullOutputValueAtPath` Plan Check -~> **Note**: `ExpectNullOutputValueAtPath` is deprecated. Use [`ExpectKnownOutputValueAtPath`](/terraform/plugin/testing/acceptance-tests/plan-checks/output#expectknownoutputvalueatpath-plan-check) with [`knownvalue.Null()`](/terraform/plugin/testing/acceptance-tests/known-value-checks#null) instead. +~> **Note**: `ExpectNullOutputValueAtPath` is deprecated. Use [`ExpectKnownOutputValueAtPath`](/terraform/plugin/testing/acceptance-tests/plan-checks/output#expectknownoutputvalueatpath-plan-check) with [`knownvalue.Null()`](/terraform/plugin/testing/acceptance-tests/known-value-checks/null) instead. The built-in [`plancheck.ExpectNullOutputValueAtPath(address, path)`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/plancheck#ExpectNullOutputValueAtPath) plan check determines whether an output at the specified address, and path has a null value. | From 57aeb6336cfed2df6fb06d710d115e43fba1340b Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Thu, 29 Feb 2024 11:25:27 +0000 Subject: [PATCH 70/73] Adding changelog entries --- .changes/unreleased/NOTES-20240229-105744.yaml | 7 ------- .changes/unreleased/NOTES-20240229-112244.yaml | 6 ++++++ .changes/unreleased/NOTES-20240229-112333.yaml | 6 ++++++ .changes/unreleased/NOTES-20240229-112401.yaml | 6 ++++++ helper/resource/testing.go | 8 ++++---- 5 files changed, 22 insertions(+), 11 deletions(-) delete mode 100644 .changes/unreleased/NOTES-20240229-105744.yaml create mode 100644 .changes/unreleased/NOTES-20240229-112244.yaml create mode 100644 .changes/unreleased/NOTES-20240229-112333.yaml create mode 100644 .changes/unreleased/NOTES-20240229-112401.yaml diff --git a/.changes/unreleased/NOTES-20240229-105744.yaml b/.changes/unreleased/NOTES-20240229-105744.yaml deleted file mode 100644 index 3592cf3f4..000000000 --- a/.changes/unreleased/NOTES-20240229-105744.yaml +++ /dev/null @@ -1,7 +0,0 @@ -kind: NOTES -body: 'all: `ExpectKnownValue`, `ExpectKnownOutputValue` and `ExpectKnownOutputValueAtPath` - plan and state checks, along with the `knownvalue` package are experimental and may be - altered or removed in a subsequent release' -time: 2024-02-29T10:57:44.318605Z -custom: - Issue: "276" diff --git a/.changes/unreleased/NOTES-20240229-112244.yaml b/.changes/unreleased/NOTES-20240229-112244.yaml new file mode 100644 index 000000000..0dbed4b45 --- /dev/null +++ b/.changes/unreleased/NOTES-20240229-112244.yaml @@ -0,0 +1,6 @@ +kind: NOTES +body: 'plancheck: `ExpectKnownValue`, `ExpectKnownOutputValue` and `ExpectKnownOutputValueAtPath` + plan checks are considered experimental and may be altered or removed in a subsequent release' +time: 2024-02-29T11:22:44.292647Z +custom: + Issue: "276" diff --git a/.changes/unreleased/NOTES-20240229-112333.yaml b/.changes/unreleased/NOTES-20240229-112333.yaml new file mode 100644 index 000000000..6076d9415 --- /dev/null +++ b/.changes/unreleased/NOTES-20240229-112333.yaml @@ -0,0 +1,6 @@ +kind: NOTES +body: 'statecheck: `ExpectKnownValue`, `ExpectKnownOutputValue` and `ExpectKnownOutputValueAtPath` + state checks are considered experimental and may be altered or removed in a subsequent release' +time: 2024-02-29T11:23:33.77075Z +custom: + Issue: "276" diff --git a/.changes/unreleased/NOTES-20240229-112401.yaml b/.changes/unreleased/NOTES-20240229-112401.yaml new file mode 100644 index 000000000..15df58a3f --- /dev/null +++ b/.changes/unreleased/NOTES-20240229-112401.yaml @@ -0,0 +1,6 @@ +kind: NOTES +body: 'knownvalue: The `knownvalue` package is considered experimental and may + be altered or removed in a subsequent release' +time: 2024-02-29T11:24:01.600093Z +custom: + Issue: "276" diff --git a/helper/resource/testing.go b/helper/resource/testing.go index ecceabb2a..1d3934be3 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -1877,10 +1877,10 @@ func testCheckResourceAttrPair(isFirst *terraform.InstanceState, nameFirst strin // // Generally, it is not necessary to use an output to test a resource attribute, // // the resource attribute should be tested directly instead. This is only shown as // // an example. -// output test_resource_one_output { -// value = test_resource.one -// } -// `, +// output test_resource_one_output { +// value = test_resource.one +// } +// `, // ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectKnownOutputValueAtPath( // "test_resource_one_output", From 2d37e789e4597cd530c7dd4015c0398b6c4d4010 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Thu, 29 Feb 2024 11:26:38 +0000 Subject: [PATCH 71/73] Removing nolint directives --- internal/plugintest/working_dir_json_test.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/internal/plugintest/working_dir_json_test.go b/internal/plugintest/working_dir_json_test.go index 05952cddc..f29c0fed0 100644 --- a/internal/plugintest/working_dir_json_test.go +++ b/internal/plugintest/working_dir_json_test.go @@ -27,16 +27,13 @@ func TestJSONConfig(t *testing.T) { ProviderFactories: providerFactories, Steps: []resource.TestStep{{ Config: `{"resource":{"tst_t":{"r1":{"s":"x1"}}}}`, - //nolint - Check: resource.TestCheckResourceAttr("tst_t.r1", "s", "x1"), + Check: resource.TestCheckResourceAttr("tst_t.r1", "s", "x1"), }, { Config: `resource "tst_t" "r1" { s = "x2" }`, - //nolint - Check: resource.TestCheckResourceAttr("tst_t.r1", "s", "x2"), + Check: resource.TestCheckResourceAttr("tst_t.r1", "s", "x2"), }, { Config: `{"resource":{"tst_t":{"r1":{"s":"x3"}}}}`, - //nolint - Check: resource.TestCheckResourceAttr("tst_t.r1", "s", "x3"), + Check: resource.TestCheckResourceAttr("tst_t.r1", "s", "x3"), }}, }) } From e80e87da34b451b73eae4bd63bf3bfb4a4e80465 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Mon, 4 Mar 2024 14:18:56 +0000 Subject: [PATCH 72/73] Updating docs and renaming following code review --- helper/resource/testing.go | 48 +++++++++++++------ helper/resource/testing_sets.go | 6 +-- knownvalue/string_regexp.go | 20 ++++---- knownvalue/string_regexp_test.go | 26 +++++----- .../known-value-checks/string.mdx | 12 ++--- .../acceptance-tests/plan-checks/output.mdx | 15 +++++- .../acceptance-tests/state-checks/output.mdx | 16 ++++++- 7 files changed, 93 insertions(+), 50 deletions(-) diff --git a/helper/resource/testing.go b/helper/resource/testing.go index 1d3934be3..ef4c83dd5 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -1287,7 +1287,7 @@ func testCheckResourceAttr(is *terraform.InstanceState, name string, key string, // When this function returns an error, TestCheckResourceAttrWith will fail the check. // // The following is an example of using [statecheck.ExpectKnownValue] in combination -// with [knownvalue.StringRegularExpression] to replicate the behaviour of TestCheckResourceAttrWith. +// with [knownvalue.StringRegexp] to replicate the behaviour of TestCheckResourceAttrWith. // // package example_test // @@ -1312,7 +1312,7 @@ func testCheckResourceAttr(is *terraform.InstanceState, name string, key string, // statecheck.ExpectKnownValue( // "test_resource.one", // tfjsonpath.New("computed_attribute"), -// knownvalue.StringRegularExpression(regexp.MustCompile("str")), +// knownvalue.StringRegexp(regexp.MustCompile("str")), // }, // }, // }, @@ -1357,7 +1357,7 @@ type CheckResourceAttrWithFunc func(value string) error // check to fail, or `nil` to succeed. // // The following is an example of using [statecheck.ExpectKnownValue] in combination -// with [knownvalue.StringRegularExpression] to replicate the behaviour of TestCheckResourceAttrWith. +// with [knownvalue.StringRegexp] to replicate the behaviour of TestCheckResourceAttrWith. // // package example_test // @@ -1382,7 +1382,7 @@ type CheckResourceAttrWithFunc func(value string) error // statecheck.ExpectKnownValue( // "test_resource.one", // tfjsonpath.New("computed_attribute"), -// knownvalue.StringRegularExpression(regexp.MustCompile("str")), +// knownvalue.StringRegexp(regexp.MustCompile("str")), // }, // }, // }, @@ -1580,7 +1580,7 @@ func testCheckNoResourceAttr(is *terraform.InstanceState, name string, key strin // compilation. // // The following is an example of using [statecheck.ExpectKnownValue] -// in combination with [knownvalue.StringRegularExpression] to replicate the behaviour of +// in combination with [knownvalue.StringRegexp] to replicate the behaviour of // TestMatchResourceAttr. // // package example_test @@ -1606,7 +1606,7 @@ func testCheckNoResourceAttr(is *terraform.InstanceState, name string, key strin // statecheck.ExpectKnownValue( // "test_resource.one", // tfjsonpath.New("computed_attribute"), -// knownvalue.StringRegularExpression(regexp.MustCompile("str")), +// knownvalue.StringRegexp(regexp.MustCompile("str")), // }, // }, // }, @@ -1875,12 +1875,21 @@ func testCheckResourceAttrPair(isFirst *terraform.InstanceState, nameFirst strin // Config: `resource "test_resource" "one" {} // // // Generally, it is not necessary to use an output to test a resource attribute, -// // the resource attribute should be tested directly instead. This is only shown as -// // an example. +// // the resource attribute should be tested directly instead, by inspecting the +// // value of the resource attribute. For instance: +// // +// // ConfigStateChecks: []statecheck.StateCheck{ +// // statecheck.ExpectKnownValue( +// // "test_resource.one", +// // tfjsonpath.New("computed_attribute"), +// // knownvalue.Bool(true), +// // ), +// // }, +// // +// // This is only shown as an example. // output test_resource_one_output { // value = test_resource.one -// } -// `, +// }`, // ConfigStateChecks: []statecheck.StateCheck{ // statecheck.ExpectKnownOutputValueAtPath( // "test_resource_one_output", @@ -1917,7 +1926,7 @@ func TestCheckOutput(name, value string) TestCheckFunc { // recommended for testing Computed attributes and attribute defaults. // // The following is an example of using [statecheck.ExpectKnownOutputValueAtPath] -// in combination with [knownvalue.StringRegularExpression] to replicate the behaviour of +// in combination with [knownvalue.StringRegexp] to replicate the behaviour of // TestMatchOutput. // // package example_test @@ -1941,8 +1950,18 @@ func TestCheckOutput(name, value string) TestCheckFunc { // Config: `resource "test_resource" "one" {} // // // Generally, it is not necessary to use an output to test a resource attribute, -// // the resource attribute should be tested directly instead. This is only shown as -// // an example. +// // the resource attribute should be tested directly instead, by inspecting the +// // value of the resource attribute. For instance: +// // +// // ConfigStateChecks: []statecheck.StateCheck{ +// // statecheck.ExpectKnownValue( +// // "test_resource.one", +// // tfjsonpath.New("computed_attribute"), +// // knownvalue.StringRegexp(regexp.MustCompile("str")), +// // ), +// // }, +// // +// // This is only shown as an example. // output test_resource_one_output { // value = test_resource.one // }`, @@ -1950,7 +1969,8 @@ func TestCheckOutput(name, value string) TestCheckFunc { // statecheck.ExpectKnownOutputValueAtPath( // "test_resource_one_output", // tfjsonpath.New("computed_attribute"), -// knownvalue.StringRegularExpression(regexp.MustCompile("str")), +// knownvalue.StringRegexp(regexp.MustCompile("str"), +// ), // }, // }, // }, diff --git a/helper/resource/testing_sets.go b/helper/resource/testing_sets.go index 82575d2a0..29aa0361f 100644 --- a/helper/resource/testing_sets.go +++ b/helper/resource/testing_sets.go @@ -168,7 +168,7 @@ func TestCheckTypeSetElemNestedAttrs(name, attr string, values map[string]string // attributes possible to be sure the unique element exists. // // The following is an example of using [statecheck.ExpectKnownValue] in combination -// with [knownvalue.SetExact], with a nested [knownvalue.StringRegularExpression] to replicate +// with [knownvalue.SetExact], with a nested [knownvalue.StringRegexp] to replicate // the behaviour of TestCheckTypeSetElemAttr. // // package example_test @@ -197,10 +197,10 @@ func TestCheckTypeSetElemNestedAttrs(name, attr string, values map[string]string // tfjsonpath.New("block"), // knownvalue.SetExact([]knownvalue.Check{ // knownvalue.MapExact(map[string]knownvalue.Check{ -// "computed_attribute": knownvalue.StringRegularExpression(regexp.MustCompile("str")), +// "computed_attribute": knownvalue.StringRegexp(regexp.MustCompile("str")), // }), // knownvalue.MapExact(map[string]knownvalue.Check{ -// "computed_attribute": knownvalue.StringRegularExpression(regexp.MustCompile("rts")), +// "computed_attribute": knownvalue.StringRegexp(regexp.MustCompile("rts")), // }), // }), // ), diff --git a/knownvalue/string_regexp.go b/knownvalue/string_regexp.go index d690d4998..782e29747 100644 --- a/knownvalue/string_regexp.go +++ b/knownvalue/string_regexp.go @@ -8,38 +8,38 @@ import ( "regexp" ) -var _ Check = stringRegularExpression{} +var _ Check = stringRegexp{} -type stringRegularExpression struct { +type stringRegexp struct { regex *regexp.Regexp } // CheckValue determines whether the passed value is of type string, and // contains a sequence of bytes that match the regular expression supplied -// to StringRegularExpression. -func (v stringRegularExpression) CheckValue(other any) error { +// to StringRegexp. +func (v stringRegexp) CheckValue(other any) error { otherVal, ok := other.(string) if !ok { - return fmt.Errorf("expected string value for StringRegularExpression check, got: %T", other) + return fmt.Errorf("expected string value for StringRegexp check, got: %T", other) } if !v.regex.MatchString(otherVal) { - return fmt.Errorf("expected regex match %s for StringRegularExpression check, got: %s", v.regex.String(), otherVal) + return fmt.Errorf("expected regex match %s for StringRegexp check, got: %s", v.regex.String(), otherVal) } return nil } // String returns the string representation of the value. -func (v stringRegularExpression) String() string { +func (v stringRegexp) String() string { return v.regex.String() } -// StringRegularExpression returns a Check for asserting equality between the +// StringRegexp returns a Check for asserting equality between the // supplied regular expression and a value passed to the CheckValue method. -func StringRegularExpression(regex *regexp.Regexp) stringRegularExpression { - return stringRegularExpression{ +func StringRegexp(regex *regexp.Regexp) stringRegexp { + return stringRegexp{ regex: regex, } } diff --git a/knownvalue/string_regexp_test.go b/knownvalue/string_regexp_test.go index f4e07315a..172a72286 100644 --- a/knownvalue/string_regexp_test.go +++ b/knownvalue/string_regexp_test.go @@ -13,7 +13,7 @@ import ( "github.com/hashicorp/terraform-plugin-testing/knownvalue" ) -func TestStringRegularExpression_CheckValue(t *testing.T) { +func TestStringRegexp_CheckValue(t *testing.T) { t.Parallel() testCases := map[string]struct { @@ -22,29 +22,29 @@ func TestStringRegularExpression_CheckValue(t *testing.T) { expectedError error }{ "zero-nil": { - self: knownvalue.StringRegularExpression(regexp.MustCompile("")), - expectedError: fmt.Errorf("expected string value for StringRegularExpression check, got: "), + self: knownvalue.StringRegexp(regexp.MustCompile("")), + expectedError: fmt.Errorf("expected string value for StringRegexp check, got: "), }, "zero-other": { - self: knownvalue.StringRegularExpression(regexp.MustCompile("")), + self: knownvalue.StringRegexp(regexp.MustCompile("")), other: "", // checking against the underlying value field zero-value }, "nil": { - self: knownvalue.StringRegularExpression(regexp.MustCompile("str")), - expectedError: fmt.Errorf("expected string value for StringRegularExpression check, got: "), + self: knownvalue.StringRegexp(regexp.MustCompile("str")), + expectedError: fmt.Errorf("expected string value for StringRegexp check, got: "), }, "wrong-type": { - self: knownvalue.StringRegularExpression(regexp.MustCompile("str")), + self: knownvalue.StringRegexp(regexp.MustCompile("str")), other: 1.234, - expectedError: fmt.Errorf("expected string value for StringRegularExpression check, got: float64"), + expectedError: fmt.Errorf("expected string value for StringRegexp check, got: float64"), }, "not-equal": { - self: knownvalue.StringRegularExpression(regexp.MustCompile("str")), + self: knownvalue.StringRegexp(regexp.MustCompile("str")), other: "rts", - expectedError: fmt.Errorf("expected regex match str for StringRegularExpression check, got: rts"), + expectedError: fmt.Errorf("expected regex match str for StringRegexp check, got: rts"), }, "equal": { - self: knownvalue.StringRegularExpression(regexp.MustCompile("str")), + self: knownvalue.StringRegexp(regexp.MustCompile("str")), other: "str", }, } @@ -64,10 +64,10 @@ func TestStringRegularExpression_CheckValue(t *testing.T) { } } -func TestStringRegularExpression_String(t *testing.T) { +func TestStringRegexp_String(t *testing.T) { t.Parallel() - got := knownvalue.StringRegularExpression(regexp.MustCompile("^str[0-9a-z]")).String() + got := knownvalue.StringRegexp(regexp.MustCompile("^str[0-9a-z]")).String() if diff := cmp.Diff(got, "^str[0-9a-z]"); diff != "" { t.Errorf("unexpected difference: %s", diff) diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/string.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/string.mdx index 756dc313d..ce92df3cd 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/string.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/string.mdx @@ -9,7 +9,7 @@ description: >- The known value checks that are available for string values are: * [StringExact](/terraform/plugin/testing/acceptance-tests/known-value-checks/string#stringexact-check) -* [StringRegularExpression](/terraform/plugin/testing/acceptance-tests/known-value-checks/string#stringregularexpression-check) +* [StringRegexp](/terraform/plugin/testing/acceptance-tests/known-value-checks/string#stringregexp-check) ## `StringExact` Check @@ -41,14 +41,14 @@ func TestExpectKnownValue_CheckPlan_StringExact(t *testing.T) { } ``` -## `StringRegularExpression` Check +## `StringRegexp` Check -The [StringRegularExpression](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#StringRegularExpression) check tests that a resource attribute, or output value has a string value which matches the supplied regular expression. +The [StringRegexp](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#StringRegexp) check tests that a resource attribute, or output value has a string value which matches the supplied regular expression. -Example usage of [StringRegularExpression](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#StringRegularExpression) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. +Example usage of [StringRegexp](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#StringRegexp) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/plan-checks/resource) plan check. ```go -func TestExpectKnownValue_CheckPlan_StringRegularExpression(t *testing.T) { +func TestExpectKnownValue_CheckPlan_StringRegexp(t *testing.T) { t.Parallel() resource.Test(t, resource.TestCase{ @@ -62,7 +62,7 @@ func TestExpectKnownValue_CheckPlan_StringRegularExpression(t *testing.T) { plancheck.ExpectKnownValue( "test_resource.one", tfjsonpath.New("computed_attribute"), - knownvalue.StringRegularExpression(regexp.MustCompile("str"))), + knownvalue.StringRegexp(regexp.MustCompile("str"))), }, }, }, diff --git a/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx b/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx index d8070cbc3..3f0b97bf7 100644 --- a/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx +++ b/website/docs/plugin/testing/acceptance-tests/plan-checks/output.mdx @@ -96,10 +96,21 @@ func TestExpectKnownOutputValue_CheckPlan_Bool(t *testing.T) { // Generally, it is not necessary to use an output to test a resource attribute, // the resource attribute should be tested directly instead. This is only shown as // an example. + // + // ConfigPlanChecks: resource.ConfigPlanChecks{ + // PreApply: []plancheck.PlanCheck{ + // plancheck.ExpectKnownValue( + // "test_resource.one", + // tfjsonpath.New("computed_attribute"), + // knownvalue.Bool(true), + // ), + // }, + // }, + // + // This is only shown as an example. output test { value = test_resource.one - } - `, + }`, ConfigPlanChecks: resource.ConfigPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownOutputValueAtPath( diff --git a/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx b/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx index d420e8a5d..434e7486b 100644 --- a/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx +++ b/website/docs/plugin/testing/acceptance-tests/state-checks/output.mdx @@ -89,10 +89,22 @@ func TestExpectKnownOutputValueAtPath_CheckState_Bool(t *testing.T) { // Generally, it is not necessary to use an output to test a resource attribute, // the resource attribute should be tested directly instead. This is only shown as // an example. + // Generally, it is not necessary to use an output to test a resource attribute, + // the resource attribute should be tested directly instead, by inspecting the + // value of the resource attribute. For instance: + // + // ConfigStateChecks: []statecheck.StateCheck{ + // statecheck.ExpectKnownValue( + // "test_resource.one", + // tfjsonpath.New("computed_attribute"), + // knownvalue.Bool(true), + // ), + // }, + // + // This is only shown as an example. output test_resource_one_output { value = test_resource.one - } - `, + }`, ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownOutputValueAtPath( "test_resource_one_output", From 22e35c2397c5e96b51dfeb69844828dc66674552 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Tue, 5 Mar 2024 10:11:55 +0000 Subject: [PATCH 73/73] Updating docs following code review --- helper/resource/testing.go | 69 +++++++++++++------ helper/resource/testing_sets.go | 27 ++++++-- .../known-value-checks/not-null.mdx | 2 +- 3 files changed, 70 insertions(+), 28 deletions(-) diff --git a/helper/resource/testing.go b/helper/resource/testing.go index ef4c83dd5..f98abda39 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -1034,8 +1034,11 @@ func ComposeAggregateTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc { // attribute directly is not supported. Use TestCheckResourceAttr with // the special .# or .% key syntax for those situations instead. // -// The following is an example of using [ExpectKnownValue] with [knownvalue.NotNull] -// to replicate the behaviour of TestCheckResourceAttrSet. +// An experimental interface exists to potentially replace the +// TestCheckResourceAttrSet functionality in the future and feedback +// would be appreciated. This example performs the same check as +// TestCheckResourceAttrSet with that experimental interface, by +// using [ExpectKnownValue] with [knownvalue.NotNull]: // // package example_test // @@ -1168,8 +1171,11 @@ func testCheckResourceAttrSet(is *terraform.InstanceState, name string, key stri // - Float/Integer: Stringified number, such as "1.2" or "123". // - String: No conversion necessary. // -// The following is an example of using [statecheck.ExpectKnownValue] -// to replicate the behaviour of TestCheckResourceAttr. +// An experimental interface exists to potentially replace the +// TestCheckResourceAttr functionality in the future and feedback +// would be appreciated. This example performs the same check as +// TestCheckResourceAttr with that experimental interface, by +// using [statecheck.ExpectKnownValue]: // // package example_test // @@ -1286,8 +1292,12 @@ func testCheckResourceAttr(is *terraform.InstanceState, name string, key string, // // When this function returns an error, TestCheckResourceAttrWith will fail the check. // -// The following is an example of using [statecheck.ExpectKnownValue] in combination -// with [knownvalue.StringRegexp] to replicate the behaviour of TestCheckResourceAttrWith. +// An experimental interface exists to potentially replace the +// CheckResourceAttrWithFunc functionality in the future and feedback +// would be appreciated. This example performs the same check as +// TestCheckResourceAttrWith with that experimental interface, by +// using [statecheck.ExpectKnownValue] in combination with +// [knownvalue.StringRegexp]: // // package example_test // @@ -1356,8 +1366,12 @@ type CheckResourceAttrWithFunc func(value string) error // if it was found in the state. The function must return an error for the // check to fail, or `nil` to succeed. // -// The following is an example of using [statecheck.ExpectKnownValue] in combination -// with [knownvalue.StringRegexp] to replicate the behaviour of TestCheckResourceAttrWith. +// An experimental interface exists to potentially replace the +// TestCheckResourceAttrWith functionality in the future and feedback +// would be appreciated. This example performs the same check as +// TestCheckResourceAttrWith with that experimental interface, by +// using [statecheck.ExpectKnownValue] in combination with +// [knownvalue.StringRegexp]: // // package example_test // @@ -1441,8 +1455,11 @@ func TestCheckResourceAttrWith(name, key string, checkValueFunc CheckResourceAtt // attribute directly is not supported. Use TestCheckResourceAttr with // the special .# or .% key syntax for those situations instead. // -// The following is an example of using [statecheck.ExpectKnownValue] with [knownvalue.Null] to -// replicate the behaviour of TestCheckNoResourceAttr. +// An experimental interface exists to potentially replace the +// TestCheckNoResourceAttr functionality in the future and feedback +// would be appreciated. This example performs the same check as +// TestCheckNoResourceAttr with that experimental interface, by +// using [statecheck.ExpectKnownValue] with [knownvalue.Null]: // // package example_test // @@ -1579,9 +1596,12 @@ func testCheckNoResourceAttr(is *terraform.InstanceState, name string, key strin // regular expression is supported by the Go regular expression handlers during // compilation. // -// The following is an example of using [statecheck.ExpectKnownValue] -// in combination with [knownvalue.StringRegexp] to replicate the behaviour of -// TestMatchResourceAttr. +// An experimental interface exists to potentially replace the +// TestMatchResourceAttr functionality in the future and feedback +// would be appreciated. This example performs the same check as +// TestMatchResourceAttr with that experimental interface, by +// using [statecheck.ExpectKnownValue] in combination with +// [knownvalue.StringRegexp]: // // package example_test // @@ -1814,8 +1834,11 @@ func testCheckResourceAttrPair(isFirst *terraform.InstanceState, nameFirst strin // TestCheckOutput checks an output in the Terraform configuration // -// The following is an example of using [statecheck.ExpectKnownOutputValue] -// to replicate the behaviour of TestCheckOutput. +// An experimental interface exists to potentially replace the +// TestCheckOutput functionality in the future and feedback +// would be appreciated. This example performs the same check as +// TestCheckOutput with that experimental interface, by +// using [statecheck.ExpectKnownOutputValue]: // // package example_test // @@ -1850,8 +1873,11 @@ func testCheckResourceAttrPair(isFirst *terraform.InstanceState, nameFirst strin // }) // } // -// The following is an example of using [statecheck.ExpectKnownOutputValueAtPath] -// to replicate the behaviour of TestCheckOutput. +// An experimental interface exists to potentially replace the +// TestCheckOutput functionality in the future and feedback +// would be appreciated. This example performs the same check as +// TestCheckOutput with that experimental interface, by using +// [statecheck.ExpectKnownOutputValueAtPath]: // // package example_test // @@ -1925,9 +1951,12 @@ func TestCheckOutput(name, value string) TestCheckFunc { // stored in state for the given name. State value checking is only // recommended for testing Computed attributes and attribute defaults. // -// The following is an example of using [statecheck.ExpectKnownOutputValueAtPath] -// in combination with [knownvalue.StringRegexp] to replicate the behaviour of -// TestMatchOutput. +// An experimental interface exists to potentially replace the +// TestMatchOutput functionality in the future and feedback +// would be appreciated. This example performs the same check as +// TestMatchOutput with that experimental interface, by using +// [statecheck.ExpectKnownOutputValueAtPath] in combination with +// [knownvalue.StringRegexp]: // // package example_test // diff --git a/helper/resource/testing_sets.go b/helper/resource/testing_sets.go index 29aa0361f..851122204 100644 --- a/helper/resource/testing_sets.go +++ b/helper/resource/testing_sets.go @@ -58,8 +58,11 @@ const ( // you were not intending to in the set. Provide the most complete mapping of // attributes possible to be sure the unique element exists. // -// The following is an example of using [statecheck.ExpectKnownValue] in combination -// with [knownvalue.SetPartial] to replicate the behaviour of TestCheckTypeSetElemNestedAttrs. +// An experimental interface exists to potentially replace the +// TestCheckTypeSetElemNestedAttrs functionality in the future and feedback +// would be appreciated. This example performs the same check as +// TestCheckTypeSetElemNestedAttrs with that experimental interface, by using +// [statecheck.ExpectKnownValue] in combination with [knownvalue.SetPartial]: // // package example_test // @@ -167,9 +170,16 @@ func TestCheckTypeSetElemNestedAttrs(name, attr string, values map[string]string // you were not intending to in the set. Provide the most complete mapping of // attributes possible to be sure the unique element exists. // -// The following is an example of using [statecheck.ExpectKnownValue] in combination -// with [knownvalue.SetExact], with a nested [knownvalue.StringRegexp] to replicate -// the behaviour of TestCheckTypeSetElemAttr. +// If the values map is not granular enough, it is possible to match an element +// you were not intending to in the set. Provide the most complete mapping of +// attributes possible to be sure the unique element exists. +// +// An experimental interface exists to potentially replace the +// TestMatchTypeSetElemNestedAttrs functionality in the future and feedback +// would be appreciated. This example performs the same check as +// TestMatchTypeSetElemNestedAttrs with that experimental interface, by using +// [statecheck.ExpectKnownValue] in combination with [knownvalue.SetExact], +// with a nested [knownvalue.StringRegexp]: // // package example_test // @@ -281,8 +291,11 @@ func TestMatchTypeSetElemNestedAttrs(name, attr string, values map[string]*regex // - Float/Integer: Stringified number, such as "1.2" or "123". // - String: No conversion necessary. // -// The following is an example of using [statecheck.ExpectKnownValue] in combination -// with [knownvalue.SetExact] to replicate the behaviour of TestCheckTypeSetElemAttr. +// An experimental interface exists to potentially replace the +// TestCheckTypeSetElemAttr functionality in the future and feedback +// would be appreciated. This example performs the same check as +// TestCheckTypeSetElemAttr with that experimental interface, by using +// [statecheck.ExpectKnownValue] in combination with [knownvalue.SetExact]: // // package example_test // diff --git a/website/docs/plugin/testing/acceptance-tests/known-value-checks/not-null.mdx b/website/docs/plugin/testing/acceptance-tests/known-value-checks/not-null.mdx index 68e5d8688..b6e39030f 100644 --- a/website/docs/plugin/testing/acceptance-tests/known-value-checks/not-null.mdx +++ b/website/docs/plugin/testing/acceptance-tests/known-value-checks/not-null.mdx @@ -12,7 +12,7 @@ The known value checks that are available for values that are not null are: ## `NotNull` Check -The [NotNull](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NotNull) check tests that a resource attribute, or output value is not null. +The [NotNull](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NotNull) check tests that a resource attribute, or output value is not null (i.e., any known value). Example usage of [NotNull](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-testing/knownvalue#NotNull) in an [ExpectKnownValue](/terraform/plugin/testing/acceptance-tests/state-checks/resource) state check.