Skip to content

Commit

Permalink
Add acceptance tests
Browse files Browse the repository at this point in the history
Terraform has a standard acceptance testing framework [0] that allows
for testing the complete lifecyle of provider resources: apply, plan,
refresh, destroy, etc. In particular, this makes it possible to test
things like a resource going missing due to a manual drop (#157).

This commit wires up the acceptance test framework, and then adds some
basic acceptance tests for creating secrets, creating cluster replicas,
and refreshing state for disappearing secrets.

Ultimately I think we should move all of today's integration tests to
this acceptance test framework.

Work towards #165.

[0]: https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests
  • Loading branch information
benesch committed Jun 5, 2023
1 parent 9f314b1 commit 85a4955
Show file tree
Hide file tree
Showing 7 changed files with 571 additions and 7 deletions.
26 changes: 26 additions & 0 deletions .github/workflows/acceptance.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: acceptance
on:
pull_request:
paths:
- pkg/**
schedule:
- cron: 0 11 * * 0

jobs:
integration:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Docker Compose Up
run: docker compose up --build -d

- name: make testacc
run: make testacc
env:
MZ_HOST: localhost
MZ_USER: materialize
MZ_TESTING: "true"

- name: Docker Compose Down
run: docker compose down
7 changes: 5 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ go 1.18
require (
github.com/DATA-DOG/go-sqlmock v1.5.0
github.com/hashicorp/terraform-plugin-docs v0.14.1
github.com/hashicorp/terraform-plugin-sdk v1.17.2
github.com/hashicorp/terraform-plugin-sdk/v2 v2.26.1
github.com/hashicorp/terraform-plugin-testing v1.2.0
github.com/jackc/pgx v3.6.2+incompatible
github.com/jmoiron/sqlx v1.3.5
github.com/stretchr/testify v1.8.4
Expand All @@ -16,6 +18,7 @@ require (
github.com/Masterminds/semver/v3 v3.1.1 // indirect
github.com/Masterminds/sprig/v3 v3.2.2 // indirect
github.com/agext/levenshtein v1.2.2 // indirect
github.com/apparentlymart/go-cidr v1.1.0 // indirect
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/armon/go-radix v1.0.0 // indirect
github.com/bgentry/speakeasy v0.1.0 // indirect
Expand All @@ -30,7 +33,7 @@ require (
github.com/hashicorp/go-checkpoint v0.5.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect
github.com/hashicorp/go-hclog v1.4.0 // indirect
github.com/hashicorp/go-hclog v1.5.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-plugin v1.4.8 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
Expand Down Expand Up @@ -73,7 +76,7 @@ require (
golang.org/x/sys v0.6.0 // indirect
golang.org/x/text v0.8.0 // indirect
google.golang.org/appengine v1.6.6 // indirect
google.golang.org/genproto v0.0.0-20200711021454-869866162049 // indirect
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d // indirect
google.golang.org/grpc v1.51.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
Expand Down
370 changes: 366 additions & 4 deletions go.sum

Large diffs are not rendered by default.

62 changes: 62 additions & 0 deletions pkg/provider/acceptance_cluster_replica_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package provider

import (
"fmt"
"testing"

"github.com/MaterializeInc/terraform-provider-materialize/pkg/materialize"
"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/jmoiron/sqlx"
)

func TestAccClusterReplica_basic(t *testing.T) {
clusterName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
replicaName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: testAccProviderFactories,
CheckDestroy: testAccCheckAllSecretsDestroyed,
Steps: []resource.TestStep{
{
Config: testAccClusterReplicaResource(clusterName, replicaName),
Check: resource.ComposeTestCheckFunc(
testAccCheckClusterReplicaExists("materialize_cluster_replica.test"),
resource.TestCheckResourceAttr("materialize_cluster_replica.test", "cluster_name", clusterName),
resource.TestCheckResourceAttr("materialize_cluster_replica.test", "name", replicaName),
resource.TestCheckResourceAttr("materialize_cluster_replica.test", "size", "1"),
resource.TestCheckResourceAttr("materialize_cluster_replica.test", "introspection_interval", "1s"),
resource.TestCheckResourceAttr("materialize_cluster_replica.test", "introspection_debugging", "false"),
resource.TestCheckNoResourceAttr("materialize_cluster_replica.test", "idle_arrangement_merge_effort"),
),
},
},
})
}

func testAccClusterReplicaResource(clusterName, replicaName string) string {
return fmt.Sprintf(`
resource "materialize_cluster" "test" {
name = "%[1]s"
}
resource "materialize_cluster_replica" "test" {
cluster_name = "%[1]s"
name = "%[2]s"
size = "1"
}
`, clusterName, replicaName)
}

func testAccCheckClusterReplicaExists(name string) resource.TestCheckFunc {
return func(s *terraform.State) error {
db := testAccProvider.Meta().(*sqlx.DB)
r, ok := s.RootModule().Resources[name]
if !ok {
return fmt.Errorf("cluster replica not found: %s", name)
}
_, err := materialize.ScanClusterReplica(db, r.Primary.ID)
return err
}
}
102 changes: 102 additions & 0 deletions pkg/provider/acceptance_secret_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package provider

import (
"database/sql"
"fmt"
"testing"

"github.com/MaterializeInc/terraform-provider-materialize/pkg/materialize"
"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/jmoiron/sqlx"
)

func TestAccSecret_basic(t *testing.T) {
secretName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: testAccProviderFactories,
CheckDestroy: testAccCheckAllSecretsDestroyed,
Steps: []resource.TestStep{
{
Config: testAccSecretResource(secretName),
Check: resource.ComposeTestCheckFunc(
testAccCheckSecretExists("materialize_secret.test"),
resource.TestCheckResourceAttr("materialize_secret.test", "name", secretName),
resource.TestCheckResourceAttr("materialize_secret.test", "value", "sekret"),
resource.TestCheckResourceAttr("materialize_secret.test", "database_name", "materialize"),
resource.TestCheckResourceAttr("materialize_secret.test", "schema_name", "public"),
resource.TestCheckResourceAttr("materialize_secret.test", "qualified_sql_name", fmt.Sprintf(`"materialize"."public"."%s"`, secretName)),
),
},
},
})
}

func TestAccSecret_disappears(t *testing.T) {
secretName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: testAccProviderFactories,
CheckDestroy: testAccCheckAllSecretsDestroyed,
Steps: []resource.TestStep{
{
Config: testAccSecretResource(secretName),
Check: resource.ComposeTestCheckFunc(
testAccCheckSecretExists("materialize_secret.test"),
testAccCheckSecretDisappears(secretName),
),
ExpectNonEmptyPlan: true,
},
},
})
}

func testAccSecretResource(name string) string {
return fmt.Sprintf(`
resource "materialize_secret" "test" {
name = "%s"
value = "sekret"
}
`, name)
}

func testAccCheckSecretExists(name string) resource.TestCheckFunc {
return func(s *terraform.State) error {
db := testAccProvider.Meta().(*sqlx.DB)
r, ok := s.RootModule().Resources[name]
if !ok {
return fmt.Errorf("secret not found: %s", name)
}
_, err := materialize.ScanSecret(db, r.Primary.ID)
return err
}
}

func testAccCheckSecretDisappears(name string) resource.TestCheckFunc {
return func(s *terraform.State) error {
db := testAccProvider.Meta().(*sqlx.DB)
_, err := db.Exec(fmt.Sprintf("DROP SECRET %s", name))
return err
}
}

func testAccCheckAllSecretsDestroyed(s *terraform.State) error {
db := testAccProvider.Meta().(*sqlx.DB)

for _, r := range s.RootModule().Resources {
if r.Type != "materialize_secret" {
continue
}

_, err := materialize.ScanSecret(db, r.Primary.ID)
if err == nil {
return fmt.Errorf("secret %v still exists", r.Primary.ID)
} else if err != sql.ErrNoRows {
return err
}
}

return nil
}
2 changes: 1 addition & 1 deletion pkg/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func Provider() *schema.Provider {
"testing": {
Type: schema.TypeBool,
Optional: true,
Default: false,
DefaultFunc: schema.EnvDefaultFunc("MZ_TESTING", false),
Description: "Enable to test the provider locally",
},
},
Expand Down
9 changes: 9 additions & 0 deletions pkg/provider/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,12 @@ func TestProvider(t *testing.T) {
func TestProvider_impl(t *testing.T) {
var _ *schema.Provider = Provider()
}

var testAccProvider = Provider()
var testAccProviderFactories = map[string]func() (*schema.Provider, error){
"materialize": func() (*schema.Provider, error) { return testAccProvider, nil },
}

func testAccPreCheck(t *testing.T) {

}

0 comments on commit 85a4955

Please sign in to comment.