From d03109e461a00e7505475eef7fdeb1babacb13ad Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Tue, 10 Feb 2026 16:02:09 -0500 Subject: [PATCH 01/10] add changelogs and new test --- .../unreleased/BUG FIXES-20260210-153921.yaml | 5 ++ .../unreleased/BUG FIXES-20260210-154312.yaml | 6 ++ .../unreleased/BUG FIXES-20260210-154602.yaml | 5 ++ helper/resource/testing_new_config.go | 2 +- helper/resource/testing_new_config_test.go | 56 +++++++++++++++++++ 5 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 .changes/unreleased/BUG FIXES-20260210-153921.yaml create mode 100644 .changes/unreleased/BUG FIXES-20260210-154312.yaml create mode 100644 .changes/unreleased/BUG FIXES-20260210-154602.yaml diff --git a/.changes/unreleased/BUG FIXES-20260210-153921.yaml b/.changes/unreleased/BUG FIXES-20260210-153921.yaml new file mode 100644 index 00000000..122903f6 --- /dev/null +++ b/.changes/unreleased/BUG FIXES-20260210-153921.yaml @@ -0,0 +1,5 @@ +kind: BUG FIXES +body: 'helper/resource: Test steps in `Config` mode using the `TF_ACC_REFRESH_AFTER_APPLY` compatibility flag will now force post-apply plans to refresh.' +time: 2026-02-10T15:39:21.121944-05:00 +custom: + Issue: "602" diff --git a/.changes/unreleased/BUG FIXES-20260210-154312.yaml b/.changes/unreleased/BUG FIXES-20260210-154312.yaml new file mode 100644 index 00000000..31950c87 --- /dev/null +++ b/.changes/unreleased/BUG FIXES-20260210-154312.yaml @@ -0,0 +1,6 @@ +kind: BUG FIXES +body: 'helper/resource: Test steps in `Config` mode using `Destroy: true` and `Check` functions will now create an additional destroy plan prior to + running `terraform apply` to avoid a potential "Saved Plan is Stale" error from Terraform.' +time: 2026-02-10T15:43:12.029656-05:00 +custom: + Issue: "602" diff --git a/.changes/unreleased/BUG FIXES-20260210-154602.yaml b/.changes/unreleased/BUG FIXES-20260210-154602.yaml new file mode 100644 index 00000000..8b66da13 --- /dev/null +++ b/.changes/unreleased/BUG FIXES-20260210-154602.yaml @@ -0,0 +1,5 @@ +kind: BUG FIXES +body: 'helper/resource: Test steps in `Config` mode using the `TF_ACC_REFRESH_AFTER_APPLY` compatibility flag will not refresh if `ExpectNonEmptyPlan` is true.' +time: 2026-02-10T15:46:02.221648-05:00 +custom: + Issue: "602" diff --git a/helper/resource/testing_new_config.go b/helper/resource/testing_new_config.go index fb97d4ec..f41c0fe4 100644 --- a/helper/resource/testing_new_config.go +++ b/helper/resource/testing_new_config.go @@ -191,7 +191,7 @@ func testStepNewConfig(ctx context.Context, t testing.T, c TestCase, wd *plugint return wd.CreatePlan(ctx, opts...) }) if err != nil { - return fmt.Errorf("Error running pre-apply plan: %w", err) + return fmt.Errorf("Error running destroy plan after step.Check shimmed state was retrieved: %w", err) } } diff --git a/helper/resource/testing_new_config_test.go b/helper/resource/testing_new_config_test.go index 8ce9747f..5f2a39d9 100644 --- a/helper/resource/testing_new_config_test.go +++ b/helper/resource/testing_new_config_test.go @@ -16,6 +16,7 @@ import ( "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/terraform" "github.com/hashicorp/terraform-plugin-testing/tfversion" ) @@ -906,3 +907,58 @@ func Test_PostApplyFunc_Called(t *testing.T) { t.Error("expected ConfigStateChecks spy1 to be called at least once") } } + +// This regression test ensures that the combination of Config, Destroy, and Check never result in +// a "Saved Plan is Stale" error message, which occurs when the state serial does not match the plan. +// +// This can occur when the refresh that is only done to produce the shimmed "Check" state produces a new state serial. +// Running a fresh plan after refreshing solves that issue, which was introduced in: https://github.com/hashicorp/terraform-plugin-testing/pull/602 +func Test_Destroy_Checks_Avoid_Stale_Plan(t *testing.T) { + t.Parallel() + + 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" {}`, + Destroy: true, + Check: func(s *terraform.State) error { return nil }, + }, + }, + }) +} From 9ce4d21c95a0d502679c36a1868483a1300b2672 Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Wed, 11 Feb 2026 17:16:10 -0500 Subject: [PATCH 02/10] trace logs --- .github/workflows/ci-go.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci-go.yml b/.github/workflows/ci-go.yml index 1a9b7520..4cbc9850 100644 --- a/.github/workflows/ci-go.yml +++ b/.github/workflows/ci-go.yml @@ -42,6 +42,7 @@ jobs: - run: go test -v -coverprofile=coverage.out ./... env: TF_ACC: "1" + TF_ACC_LOG: "TRACE" - name: Remove wildcard suffix from TF version id: tf_version run: | From cc4c31f9cfb3c2b8367e55723ebafdb04cf22d4a Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Wed, 11 Feb 2026 17:28:04 -0500 Subject: [PATCH 03/10] log --- .github/workflows/ci-go.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci-go.yml b/.github/workflows/ci-go.yml index 4cbc9850..2a6a5dc3 100644 --- a/.github/workflows/ci-go.yml +++ b/.github/workflows/ci-go.yml @@ -43,6 +43,7 @@ jobs: env: TF_ACC: "1" TF_ACC_LOG: "TRACE" + TF_LOG: "TRACE" - name: Remove wildcard suffix from TF version id: tf_version run: | From 226431259a237c978d5d29e9b3fe47d27c4cefe1 Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Wed, 11 Feb 2026 17:35:49 -0500 Subject: [PATCH 04/10] single test --- .github/workflows/ci-go.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-go.yml b/.github/workflows/ci-go.yml index 2a6a5dc3..c10b461b 100644 --- a/.github/workflows/ci-go.yml +++ b/.github/workflows/ci-go.yml @@ -39,7 +39,7 @@ jobs: terraform_version: ${{ matrix.terraform }} terraform_wrapper: false - run: go mod download - - run: go test -v -coverprofile=coverage.out ./... + - run: go test -v -run ^TestTest_ConfigDirectory_TestStepDirectory_Vars$ github.com/hashicorp/terraform-plugin-testing/helper/resource env: TF_ACC: "1" TF_ACC_LOG: "TRACE" From d5ba7b7290baa51e7caf249ebf4d9e87819cc8a8 Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Wed, 11 Feb 2026 17:36:54 -0500 Subject: [PATCH 05/10] cover --- .github/workflows/ci-go.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-go.yml b/.github/workflows/ci-go.yml index c10b461b..c5195ec4 100644 --- a/.github/workflows/ci-go.yml +++ b/.github/workflows/ci-go.yml @@ -39,7 +39,7 @@ jobs: terraform_version: ${{ matrix.terraform }} terraform_wrapper: false - run: go mod download - - run: go test -v -run ^TestTest_ConfigDirectory_TestStepDirectory_Vars$ github.com/hashicorp/terraform-plugin-testing/helper/resource + - run: go test -v -coverprofile=coverage.out -run ^TestTest_ConfigDirectory_TestStepDirectory_Vars$ github.com/hashicorp/terraform-plugin-testing/helper/resource env: TF_ACC: "1" TF_ACC_LOG: "TRACE" From 9c07a4c6fb1d289095cc9c1ad9b828a2f25ce15e Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Wed, 11 Feb 2026 17:38:31 -0500 Subject: [PATCH 06/10] revert --- .github/workflows/ci-go.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/ci-go.yml b/.github/workflows/ci-go.yml index c5195ec4..1a9b7520 100644 --- a/.github/workflows/ci-go.yml +++ b/.github/workflows/ci-go.yml @@ -39,11 +39,9 @@ jobs: terraform_version: ${{ matrix.terraform }} terraform_wrapper: false - run: go mod download - - run: go test -v -coverprofile=coverage.out -run ^TestTest_ConfigDirectory_TestStepDirectory_Vars$ github.com/hashicorp/terraform-plugin-testing/helper/resource + - run: go test -v -coverprofile=coverage.out ./... env: TF_ACC: "1" - TF_ACC_LOG: "TRACE" - TF_LOG: "TRACE" - name: Remove wildcard suffix from TF version id: tf_version run: | From dc91f62218ba8e05a4cdcdd6efe89b41435fc1f7 Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Thu, 12 Feb 2026 14:46:44 -0500 Subject: [PATCH 07/10] quick log attempt --- helper/resource/teststep_providers_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/helper/resource/teststep_providers_test.go b/helper/resource/teststep_providers_test.go index 86da5ff9..683b46a4 100644 --- a/helper/resource/teststep_providers_test.go +++ b/helper/resource/teststep_providers_test.go @@ -4043,7 +4043,8 @@ func TestTest_ConfigFile_TestNameFile(t *testing.T) { } func TestTest_ConfigFile_TestNameFile_Vars(t *testing.T) { - t.Parallel() + t.Setenv("TF_ACC_LOG", "TRACE") + t.Setenv("TF_ACC_LOG_PATH", "./config_test_out.log") Test(t, TestCase{ Steps: []TestStep{ From 1e4e0f33eec4e0989056e8131181d22b77cf6a01 Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Thu, 12 Feb 2026 15:01:14 -0500 Subject: [PATCH 08/10] upload some logs on failure --- .github/workflows/ci-go.yml | 8 ++++++++ helper/resource/teststep_providers_test.go | 8 +++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-go.yml b/.github/workflows/ci-go.yml index 1a9b7520..4cf44c45 100644 --- a/.github/workflows/ci-go.yml +++ b/.github/workflows/ci-go.yml @@ -26,6 +26,7 @@ jobs: name: test (Go ${{ matrix.go-version }} / TF ${{ matrix.terraform }}) runs-on: ubuntu-latest strategy: + fail-fast: false matrix: go-version: [ '1.25', '1.24' ] terraform: ${{ fromJSON(vars.TF_VERSIONS_PROTOCOL_V5) }} @@ -42,6 +43,13 @@ jobs: - run: go test -v -coverprofile=coverage.out ./... env: TF_ACC: "1" + - name: Upload test logs on failure + if: failure() + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + with: + name: go-${{ matrix.go-version }}-terraform-${{ matrix.terraform }}-test-logs + path: ./*.log + if-no-files-found: warn - name: Remove wildcard suffix from TF version id: tf_version run: | diff --git a/helper/resource/teststep_providers_test.go b/helper/resource/teststep_providers_test.go index 683b46a4..af3108ff 100644 --- a/helper/resource/teststep_providers_test.go +++ b/helper/resource/teststep_providers_test.go @@ -3483,7 +3483,8 @@ func TestTest_ConfigDirectory_TestStepDirectory(t *testing.T) { // configuration files that are copied from the test step directory in test step 1 // are removed prior to running test step 2. func TestTest_ConfigDirectory_TestStepDirectory_StepNotHardcoded(t *testing.T) { - t.Parallel() + t.Setenv("TF_ACC_LOG", "TRACE") + t.Setenv("TF_ACC_LOG_PATH", "./TestTest_ConfigDirectory_TestStepDirectory_StepNotHardcoded.log") Test(t, TestCase{ Steps: []TestStep{ @@ -3530,7 +3531,8 @@ func TestTest_ConfigDirectory_StaticDirectory_MultipleFiles(t *testing.T) { } func TestTest_ConfigDirectory_StaticDirectory_MultipleFiles_Vars(t *testing.T) { - t.Parallel() + t.Setenv("TF_ACC_LOG", "TRACE") + t.Setenv("TF_ACC_LOG_PATH", "./TestTest_ConfigDirectory_StaticDirectory_MultipleFiles_Vars.log") Test(t, TestCase{ Steps: []TestStep{ @@ -4044,7 +4046,7 @@ func TestTest_ConfigFile_TestNameFile(t *testing.T) { func TestTest_ConfigFile_TestNameFile_Vars(t *testing.T) { t.Setenv("TF_ACC_LOG", "TRACE") - t.Setenv("TF_ACC_LOG_PATH", "./config_test_out.log") + t.Setenv("TF_ACC_LOG_PATH", "./TestTest_ConfigFile_TestNameFile_Vars.log") Test(t, TestCase{ Steps: []TestStep{ From ad57f4542dea3620bbc8a918bf777bb942d5dd6c Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Thu, 12 Feb 2026 15:07:19 -0500 Subject: [PATCH 09/10] glob --- .github/workflows/ci-go.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-go.yml b/.github/workflows/ci-go.yml index 4cf44c45..3c136792 100644 --- a/.github/workflows/ci-go.yml +++ b/.github/workflows/ci-go.yml @@ -48,7 +48,7 @@ jobs: uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: go-${{ matrix.go-version }}-terraform-${{ matrix.terraform }}-test-logs - path: ./*.log + path: "**/*.log" if-no-files-found: warn - name: Remove wildcard suffix from TF version id: tf_version From e5c6d796e63aacdec76059f72579c8f46a3a699a Mon Sep 17 00:00:00 2001 From: Austin Valle Date: Thu, 12 Feb 2026 15:16:39 -0500 Subject: [PATCH 10/10] revert test changes --- .github/workflows/ci-go.yml | 7 ------- helper/resource/teststep_providers_test.go | 9 +++------ 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci-go.yml b/.github/workflows/ci-go.yml index 3c136792..9baaaf9a 100644 --- a/.github/workflows/ci-go.yml +++ b/.github/workflows/ci-go.yml @@ -43,13 +43,6 @@ jobs: - run: go test -v -coverprofile=coverage.out ./... env: TF_ACC: "1" - - name: Upload test logs on failure - if: failure() - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 - with: - name: go-${{ matrix.go-version }}-terraform-${{ matrix.terraform }}-test-logs - path: "**/*.log" - if-no-files-found: warn - name: Remove wildcard suffix from TF version id: tf_version run: | diff --git a/helper/resource/teststep_providers_test.go b/helper/resource/teststep_providers_test.go index af3108ff..86da5ff9 100644 --- a/helper/resource/teststep_providers_test.go +++ b/helper/resource/teststep_providers_test.go @@ -3483,8 +3483,7 @@ func TestTest_ConfigDirectory_TestStepDirectory(t *testing.T) { // configuration files that are copied from the test step directory in test step 1 // are removed prior to running test step 2. func TestTest_ConfigDirectory_TestStepDirectory_StepNotHardcoded(t *testing.T) { - t.Setenv("TF_ACC_LOG", "TRACE") - t.Setenv("TF_ACC_LOG_PATH", "./TestTest_ConfigDirectory_TestStepDirectory_StepNotHardcoded.log") + t.Parallel() Test(t, TestCase{ Steps: []TestStep{ @@ -3531,8 +3530,7 @@ func TestTest_ConfigDirectory_StaticDirectory_MultipleFiles(t *testing.T) { } func TestTest_ConfigDirectory_StaticDirectory_MultipleFiles_Vars(t *testing.T) { - t.Setenv("TF_ACC_LOG", "TRACE") - t.Setenv("TF_ACC_LOG_PATH", "./TestTest_ConfigDirectory_StaticDirectory_MultipleFiles_Vars.log") + t.Parallel() Test(t, TestCase{ Steps: []TestStep{ @@ -4045,8 +4043,7 @@ func TestTest_ConfigFile_TestNameFile(t *testing.T) { } func TestTest_ConfigFile_TestNameFile_Vars(t *testing.T) { - t.Setenv("TF_ACC_LOG", "TRACE") - t.Setenv("TF_ACC_LOG_PATH", "./TestTest_ConfigFile_TestNameFile_Vars.log") + t.Parallel() Test(t, TestCase{ Steps: []TestStep{