Skip to content

Commit a77c9b8

Browse files
committed
[PF] Property based Configure tests
1 parent 678d0fd commit a77c9b8

File tree

12 files changed

+1550
-25
lines changed

12 files changed

+1550
-25
lines changed

pf/tests/go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ require (
1818
github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tests v0.0.0-00010101000000-000000000000
1919
github.com/stretchr/testify v1.9.0
2020
github.com/terraform-providers/terraform-provider-random/randomshim v0.0.0
21+
pgregory.net/rapid v1.1.0
2122
)
2223

2324
require (
@@ -85,7 +86,6 @@ require (
8586
gotest.tools v2.2.0+incompatible // indirect
8687
gotest.tools/v3 v3.0.3 // indirect
8788
mvdan.cc/gofumpt v0.5.0 // indirect
88-
pgregory.net/rapid v0.6.1 // indirect
8989
)
9090

9191
replace (

pf/tests/go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -3173,8 +3173,8 @@ modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8=
31733173
mvdan.cc/gofumpt v0.4.0/go.mod h1:PljLOHDeZqgS8opHRKLzp2It2VBuSdteAgqUfzMTxlQ=
31743174
mvdan.cc/gofumpt v0.5.0 h1:0EQ+Z56k8tXjj/6TQD25BFNKQXpCvT0rnansIc7Ug5E=
31753175
mvdan.cc/gofumpt v0.5.0/go.mod h1:HBeVDtMKRZpXyxFciAirzdKklDlGu8aAy1wEbH5Y9js=
3176-
pgregory.net/rapid v0.6.1 h1:4eyrDxyht86tT4Ztm+kvlyNBLIk071gR+ZQdhphc9dQ=
3177-
pgregory.net/rapid v0.6.1/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
3176+
pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw=
3177+
pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
31783178
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
31793179
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
31803180
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=

pf/tests/internal/cross-tests/configure.go

+33-14
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,13 @@ import (
5050
// }
5151
//
5252
// For details on the test itself, see [Configure].
53-
func MakeConfigure(schema schema.Schema, tfConfig map[string]cty.Value, puConfig resource.PropertyMap) func(t *testing.T) {
53+
func MakeConfigure(
54+
schema schema.Schema, tfConfig map[string]cty.Value, puConfig resource.PropertyMap,
55+
options ...ConfigureOption,
56+
) func(t *testing.T) {
5457
return func(t *testing.T) {
5558
t.Parallel()
56-
Configure(t, schema, tfConfig, puConfig)
59+
Configure(t, schema, tfConfig, puConfig, options...)
5760
}
5861
}
5962

@@ -81,9 +84,17 @@ func MakeConfigure(schema schema.Schema, tfConfig map[string]cty.Value, puConfig
8184
// +--------------------+ +---------------------+
8285
//
8386
// Configure should be safe to run in parallel.
84-
func Configure(t *testing.T, schema schema.Schema, tfConfig map[string]cty.Value, puConfig resource.PropertyMap) {
87+
func Configure(
88+
t TestingT, schema schema.Schema, tfConfig map[string]cty.Value, puConfig resource.PropertyMap,
89+
options ...ConfigureOption,
90+
) {
8591
skipUnlessLinux(t)
8692

93+
var opts configureOptions
94+
for _, o := range options {
95+
o(&opts)
96+
}
97+
8798
// By default, logs only show when they are on a failed test. By logging to
8899
// topLevelT, we can log items to be shown if downstream tests fail.
89100
topLevelT := t
@@ -103,8 +114,8 @@ func Configure(t *testing.T, schema schema.Schema, tfConfig map[string]cty.Value
103114
}
104115

105116
var tfOutput, puOutput tfsdk.Config
106-
t.Run("tf", func(t *testing.T) {
107-
defer propageteSkip(topLevelT, t)
117+
118+
withAugment(t, func(t augmentedT) { // --- Run Terraform Provider ---
108119
var hcl bytes.Buffer
109120
err := crosstests.WritePF(&hcl).Provider(schema, providerName, tfConfig)
110121
require.NoError(t, err)
@@ -120,13 +131,12 @@ resource "` + providerName + `_res" "res" {}
120131

121132
driver.Write(t, hcl.String())
122133
plan, err := driver.Plan(t)
123-
require.NoError(t, err)
134+
require.NoError(t, err, "failed to generate TF plan")
124135
err = driver.Apply(t, plan)
125136
require.NoError(t, err)
126137
})
127138

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

132142
pulumiYaml := map[string]any{
@@ -187,11 +197,20 @@ resource "` + providerName + `_res" "res" {}
187197
contract.Ignore(test.Up(t)) // Assert that the update succeeded, but not the result.
188198
})
189199

190-
skipCompare := t.Failed() || t.Skipped()
191-
t.Run("compare", func(t *testing.T) {
192-
if skipCompare {
193-
t.Skipf("skipping since earlier steps did not complete")
194-
}
200+
// --- Compare results -----------------------------
201+
if opts.testEqual != nil {
202+
opts.testEqual(t, tfOutput, puOutput)
203+
} else {
195204
assert.Equal(t, tfOutput, puOutput)
196-
})
205+
}
206+
}
207+
208+
type ConfigureOption func(*configureOptions)
209+
210+
type configureOptions struct {
211+
testEqual func(t TestingT, tfOutput, puOutput tfsdk.Config)
212+
}
213+
214+
func WithConfigureEqual(equal func(t TestingT, tfOutput, puOutput tfsdk.Config)) ConfigureOption {
215+
return func(opts *configureOptions) { opts.testEqual = equal }
197216
}

pf/tests/internal/cross-tests/util.go

+63-8
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,26 @@ import (
1919
"os"
2020
"runtime"
2121
"strings"
22-
"testing"
22+
"time"
2323

2424
"github.com/pulumi/pulumi/sdk/v3/go/common/diag"
2525
"github.com/pulumi/pulumi/sdk/v3/go/common/resource"
2626
"github.com/stretchr/testify/require"
2727
)
2828

29-
func propageteSkip(parent, child *testing.T) {
30-
if child.Skipped() {
31-
parent.Skipf("skipping due to skipped child test")
32-
}
29+
type TestingT interface {
30+
Skip(args ...any)
31+
Failed() bool
32+
Errorf(format string, args ...any)
33+
Name() string
34+
Log(...any)
35+
Logf(string, ...any)
36+
Fail()
37+
FailNow()
38+
Helper()
3339
}
3440

35-
type testLogSink struct{ t *testing.T }
41+
type testLogSink struct{ t TestingT }
3642

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

53-
func convertResourceValue(t *testing.T, properties resource.PropertyMap) map[string]any {
59+
func convertResourceValue(t TestingT, properties resource.PropertyMap) map[string]any {
5460
var convertValue func(resource.PropertyValue) (any, bool)
5561
convertValue = func(v resource.PropertyValue) (any, bool) {
5662
if v.IsComputed() {
@@ -81,8 +87,57 @@ func convertResourceValue(t *testing.T, properties resource.PropertyMap) map[str
8187
return properties.MapRepl(nil, convertValue)
8288
}
8389

84-
func skipUnlessLinux(t *testing.T) {
90+
func skipUnlessLinux(t TestingT) {
8591
if ci, ok := os.LookupEnv("CI"); ok && ci == "true" && !strings.Contains(strings.ToLower(runtime.GOOS), "linux") {
8692
t.Skip("Skipping on non-Linux platforms as our CI does not yet install Terraform CLI required for these tests")
8793
}
8894
}
95+
96+
type augmentedT interface {
97+
TestingT
98+
Cleanup(func())
99+
Deadline() (time.Time, bool)
100+
TempDir() string
101+
}
102+
103+
func withAugment(t TestingT, f func(t augmentedT)) {
104+
c := withAugmentedT{TestingT: t}
105+
defer c.all()
106+
f(&c)
107+
}
108+
109+
type withAugmentedT struct {
110+
TestingT
111+
tasks []func()
112+
}
113+
114+
// TempDir returns a temporary directory for the test to use.
115+
// The directory is automatically removed when the test and
116+
// all its subtests complete.
117+
// Each subsequent call to t.TempDir returns a unique directory;
118+
// if the directory creation fails, TempDir terminates the test by calling Fatal.
119+
func (t *withAugmentedT) TempDir() string {
120+
name := t.Name()
121+
name = strings.ReplaceAll(name, "#", "")
122+
name = strings.ReplaceAll(name, string(os.PathSeparator), "")
123+
dir, err := os.MkdirTemp("", name)
124+
require.NoError(t, err)
125+
return dir
126+
}
127+
128+
func (t *withAugmentedT) Cleanup(f func()) {
129+
t.tasks = append(t.tasks, f)
130+
}
131+
132+
func (t *withAugmentedT) Deadline() (time.Time, bool) {
133+
return time.Time{}, false
134+
}
135+
136+
func (t *withAugmentedT) all() {
137+
for i := len(t.tasks) - 1; i >= 0; i-- {
138+
v := t.tasks[i]
139+
if v != nil {
140+
v()
141+
}
142+
}
143+
}
+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 2016-2024, Pulumi Corporation.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package crosstests
16+
17+
import (
18+
"testing"
19+
20+
"github.com/pulumi/pulumi/sdk/v3/go/common/resource"
21+
"github.com/stretchr/testify/assert"
22+
)
23+
24+
func TestConvertResourceValue(t *testing.T) {
25+
t.Parallel()
26+
tests := []struct {
27+
input resource.PropertyMap
28+
expected map[string]any
29+
}{
30+
{
31+
input: resource.PropertyMap{
32+
"a": resource.NewProperty(resource.PropertyMap{}),
33+
},
34+
expected: map[string]any{
35+
"a": map[string]any{},
36+
},
37+
},
38+
}
39+
40+
for _, tt := range tests {
41+
t.Run("", func(t *testing.T) {
42+
actual := convertResourceValue(t, tt.input)
43+
assert.Equal(t, tt.expected, actual)
44+
})
45+
}
46+
}

0 commit comments

Comments
 (0)