Skip to content

Commit

Permalink
WIP Provider tersts
Browse files Browse the repository at this point in the history
  • Loading branch information
iwahbe committed Oct 14, 2024
1 parent b85ceb5 commit a4ae424
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 25 deletions.
18 changes: 6 additions & 12 deletions pf/tests/internal/cross-tests/configure.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func MakeConfigure(schema schema.Schema, tfConfig map[string]cty.Value, puConfig
// +--------------------+ +---------------------+
//
// Configure should be safe to run in parallel.
func Configure(t *testing.T, schema schema.Schema, tfConfig map[string]cty.Value, puConfig resource.PropertyMap) {
func Configure(t TestingT, schema schema.Schema, tfConfig map[string]cty.Value, puConfig resource.PropertyMap) {
skipUnlessLinux(t)

// By default, logs only show when they are on a failed test. By logging to
Expand All @@ -103,8 +103,8 @@ func Configure(t *testing.T, schema schema.Schema, tfConfig map[string]cty.Value
}

var tfOutput, puOutput tfsdk.Config
t.Run("tf", func(t *testing.T) {
defer propageteSkip(topLevelT, t)

withAugment(t, func(t augmentedT) { // --- Run Terraform Provider ---
var hcl bytes.Buffer
err := crosstests.WritePF(&hcl).Provider(schema, providerName, tfConfig)
require.NoError(t, err)
Expand All @@ -125,8 +125,7 @@ resource "` + providerName + `_res" "res" {}
require.NoError(t, err)
})

t.Run("bridged", func(t *testing.T) {
defer propageteSkip(topLevelT, t)
withAugment(t, func(t augmentedT) { // --- Run Pulumi Provider ---
dir := t.TempDir()

pulumiYaml := map[string]any{
Expand Down Expand Up @@ -187,11 +186,6 @@ resource "` + providerName + `_res" "res" {}
contract.Ignore(test.Up(t)) // Assert that the update succeeded, but not the result.
})

skipCompare := t.Failed() || t.Skipped()
t.Run("compare", func(t *testing.T) {
if skipCompare {
t.Skipf("skipping since earlier steps did not complete")
}
assert.Equal(t, tfOutput, puOutput)
})
// --- Compare results -----------------------------
assert.Equal(t, tfOutput, puOutput)
}
71 changes: 63 additions & 8 deletions pf/tests/internal/cross-tests/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,26 @@ import (
"os"
"runtime"
"strings"
"testing"
"time"

"github.com/pulumi/pulumi/sdk/v3/go/common/diag"
"github.com/pulumi/pulumi/sdk/v3/go/common/resource"
"github.com/stretchr/testify/require"
)

func propageteSkip(parent, child *testing.T) {
if child.Skipped() {
parent.Skipf("skipping due to skipped child test")
}
type TestingT interface {
Skip(args ...any)
Failed() bool
Errorf(format string, args ...any)
Name() string
Log(...any)
Logf(string, ...any)
Fail()
FailNow()
Helper()
}

type testLogSink struct{ t *testing.T }
type testLogSink struct{ t TestingT }

func (s testLogSink) Log(_ context.Context, sev diag.Severity, urn resource.URN, msg string) error {
return s.log("LOG", sev, urn, msg)
Expand All @@ -50,7 +56,7 @@ func (s testLogSink) log(kind string, sev diag.Severity, urn resource.URN, msg s
return nil
}

func convertResourceValue(t *testing.T, properties resource.PropertyMap) map[string]any {
func convertResourceValue(t TestingT, properties resource.PropertyMap) map[string]any {
var convertValue func(resource.PropertyValue) (any, bool)
convertValue = func(v resource.PropertyValue) (any, bool) {
if v.IsComputed() {
Expand Down Expand Up @@ -81,8 +87,57 @@ func convertResourceValue(t *testing.T, properties resource.PropertyMap) map[str
return properties.MapRepl(nil, convertValue)
}

func skipUnlessLinux(t *testing.T) {
func skipUnlessLinux(t TestingT) {
if ci, ok := os.LookupEnv("CI"); ok && ci == "true" && !strings.Contains(strings.ToLower(runtime.GOOS), "linux") {
t.Skip("Skipping on non-Linux platforms as our CI does not yet install Terraform CLI required for these tests")
}
}

type augmentedT interface {
TestingT
Cleanup(func())
Deadline() (time.Time, bool)
TempDir() string
}

func withAugment(t TestingT, f func(t augmentedT)) {
c := withAugmentedT{TestingT: t}
defer c.all()
f(&c)
}

type withAugmentedT struct {
TestingT
tasks []func()
}

// TempDir returns a temporary directory for the test to use.
// The directory is automatically removed when the test and
// all its subtests complete.
// Each subsequent call to t.TempDir returns a unique directory;
// if the directory creation fails, TempDir terminates the test by calling Fatal.
func (t *withAugmentedT) TempDir() string {
name := t.Name()
name = strings.ReplaceAll(name, "#", "")
name = strings.ReplaceAll(name, string(os.PathSeparator), "")
dir, err := os.MkdirTemp("", name)
require.NoError(t, err)
return dir
}

func (t *withAugmentedT) Cleanup(f func()) {
t.tasks = append(t.tasks, f)
}

func (t *withAugmentedT) Deadline() (time.Time, bool) {
return time.Time{}, false
}

func (t *withAugmentedT) all() {
for i := len(t.tasks) - 1; i >= 0; i-- {
v := t.tasks[i]
if v != nil {
v()
}
}
}
6 changes: 3 additions & 3 deletions pf/tests/provider_configure_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,10 @@ func TestConfigureInvalidTypes(t *testing.T) {
func TestConfigureProperties(t *testing.T) {
t.Parallel()

rapid.Check(t, func(r *rapid.T) {
rapid.Check(t, func(t *rapid.T) {
ctx := context.Background()
schema := propProviderSchema.Schema(ctx).Draw(r, "schema")
value := propProviderValue.WithValue(schema).Draw(r, "value")
schema := propProviderSchema.Schema(ctx).Draw(t, "schema")
value := propProviderValue.WithValue(schema).Draw(t, "value")
crosstests.Configure(t, schema, value.Tf.AsValueMap(), value.Pu)
})
}
Expand Down
29 changes: 27 additions & 2 deletions pf/tests/util/property/pf/value/provider/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,16 @@ import (
"fmt"
"hash/maphash"

"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/provider/schema"
"github.com/hashicorp/terraform-plugin-go/tftypes"
"github.com/zclconf/go-cty/cty"
"pgregory.net/rapid"

"github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge"
shim "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim"
shimschema "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim/schema"

"github.com/pulumi/pulumi/sdk/v3/go/common/resource"
"github.com/pulumi/pulumi/sdk/v3/go/common/util/contract"
)
Expand Down Expand Up @@ -66,15 +71,21 @@ func WithValue(schema schema.Schema) *rapid.Generator[Value] {
v := g.withAttr(s).Draw(t, k)
ctyM[k] = v.Tf
if v.hasValue {
puM[resource.PropertyKey(k)] = v.Pu
puK := tfbridge.TerraformToPulumiNameV2(k, shimschema.SchemaMap{
k: (&shimschema.Schema{Type: shimType(s.GetType())}).Shim(),
}, nil)
puM[resource.PropertyKey(puK)] = v.Pu
}
}

for k, b := range schema.Blocks {
v := g.withBlock(b).Draw(t, k)
ctyM[k] = v.Tf
if v.hasValue {
puM[resource.PropertyKey(k)] = v.Pu
puK := tfbridge.TerraformToPulumiNameV2(k, shimschema.SchemaMap{
k: (&shimschema.Schema{Type: shimType(b.Type())}).Shim(),
}, nil)
puM[resource.PropertyKey(puK)] = v.Pu
}
}

Expand All @@ -85,6 +96,20 @@ func WithValue(schema schema.Schema) *rapid.Generator[Value] {
})
}

func shimType(a attr.Type) shim.ValueType {
t := a.TerraformType(context.Background())
switch {
case t.Is(tftypes.Set{}):
return shim.TypeSet
case t.Is(tftypes.Map{}):
return shim.TypeMap
case t.Is(tftypes.List{}):
return shim.TypeList
default:
return shim.TypeBool
}
}

func (g generator) withAttr(attr schema.Attribute) *rapid.Generator[value] {
contract.Assertf(g.isInput, "only input values are implemented")

Expand Down

0 comments on commit a4ae424

Please sign in to comment.