Skip to content

Commit 765b493

Browse files
committed
Add first test and test harness.
1 parent 07c8464 commit 765b493

File tree

1 file changed

+147
-0
lines changed

1 file changed

+147
-0
lines changed

tfsdk/type_plan_modification_test.go

+147
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
package tfsdk
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"strings"
7+
"testing"
8+
9+
"github.com/google/go-cmp/cmp"
10+
"github.com/hashicorp/terraform-plugin-framework/attr"
11+
"github.com/hashicorp/terraform-plugin-framework/diag"
12+
testtypes "github.com/hashicorp/terraform-plugin-framework/internal/testing/types"
13+
"github.com/hashicorp/terraform-plugin-framework/types"
14+
"github.com/hashicorp/terraform-plugin-go/tftypes"
15+
)
16+
17+
type typeWithPlanModifier struct {
18+
modifyPlan func(ctx context.Context, state attr.Value, plan attr.Value, path *tftypes.AttributePath) (attr.Value, diag.Diagnostics)
19+
}
20+
21+
func (t typeWithPlanModifier) TerraformType(_ context.Context) tftypes.Type {
22+
return tftypes.String
23+
}
24+
25+
func (t typeWithPlanModifier) ValueFromTerraform(_ context.Context, val tftypes.Value) (attr.Value, error) {
26+
ret := testtypes.String{CreatedBy: t}
27+
if val.IsNull() {
28+
ret.String = types.String{Null: true}
29+
return ret, nil
30+
}
31+
if !val.IsKnown() {
32+
ret.String = types.String{Unknown: true}
33+
return ret, nil
34+
}
35+
var v string
36+
err := val.As(&v)
37+
if err != nil {
38+
return nil, err
39+
}
40+
ret.String = types.String{Value: v}
41+
return ret, nil
42+
}
43+
44+
func (t typeWithPlanModifier) Equal(o attr.Type) bool {
45+
_, ok := o.(typeWithPlanModifier)
46+
if !ok {
47+
return false
48+
}
49+
return true
50+
}
51+
52+
func (t typeWithPlanModifier) String() string {
53+
return "tfsdk.typeWithPlanModifier"
54+
}
55+
56+
func (t typeWithPlanModifier) ApplyTerraform5AttributePathStep(step tftypes.AttributePathStep) (interface{}, error) {
57+
return nil, fmt.Errorf("cannot apply AttributePathStep %T to %s", step, t.String())
58+
}
59+
60+
func (t typeWithPlanModifier) ModifyPlan(ctx context.Context, state attr.Value, plan attr.Value, path *tftypes.AttributePath) (attr.Value, diag.Diagnostics) {
61+
return t.modifyPlan(ctx, state, plan, path)
62+
}
63+
64+
func TestRunTypePlanModifiers(t *testing.T) {
65+
t.Parallel()
66+
67+
type testCase struct {
68+
state tftypes.Value
69+
plan tftypes.Value
70+
schema Schema
71+
resp *planResourceChangeResponse
72+
expectedPlan tftypes.Value
73+
expectedDiags diag.Diagnostics
74+
expectedRR []*tftypes.AttributePath
75+
expectedOK bool
76+
}
77+
78+
tests := map[string]testCase{
79+
"case-insensitive": {
80+
state: tftypes.NewValue(tftypes.Object{
81+
AttributeTypes: map[string]tftypes.Type{
82+
"input": tftypes.String,
83+
},
84+
}, map[string]tftypes.Value{
85+
"input": tftypes.NewValue(tftypes.String, "hello, world"),
86+
}),
87+
plan: tftypes.NewValue(tftypes.Object{
88+
AttributeTypes: map[string]tftypes.Type{
89+
"input": tftypes.String,
90+
},
91+
}, map[string]tftypes.Value{
92+
"input": tftypes.NewValue(tftypes.String, "hElLo, WoRlD"),
93+
}),
94+
schema: Schema{
95+
Attributes: map[string]Attribute{
96+
"input": {
97+
Type: typeWithPlanModifier{
98+
modifyPlan: func(ctx context.Context, state attr.Value, plan attr.Value, path *tftypes.AttributePath) (attr.Value, diag.Diagnostics) {
99+
st := state.(testtypes.String)
100+
pl := plan.(testtypes.String)
101+
if strings.ToLower(st.String.Value) == strings.ToLower(pl.String.Value) {
102+
return state, nil
103+
}
104+
return plan, nil
105+
},
106+
},
107+
Required: true,
108+
},
109+
},
110+
},
111+
resp: &planResourceChangeResponse{},
112+
expectedPlan: tftypes.NewValue(tftypes.Object{
113+
AttributeTypes: map[string]tftypes.Type{
114+
"input": tftypes.String,
115+
},
116+
}, map[string]tftypes.Value{
117+
"input": tftypes.NewValue(tftypes.String, "hello, world"),
118+
}),
119+
expectedDiags: nil,
120+
expectedRR: nil,
121+
expectedOK: true,
122+
},
123+
}
124+
125+
for name, tc := range tests {
126+
name, tc := name, tc
127+
128+
t.Run(name, func(t *testing.T) {
129+
t.Parallel()
130+
131+
plan, ok := runTypePlanModifiers(context.Background(), tc.state, tc.plan, tc.schema, tc.resp)
132+
133+
if ok != tc.expectedOK {
134+
t.Fatalf("expected ok to be %v, got %v", tc.expectedOK, ok)
135+
}
136+
if diff := cmp.Diff(tc.resp.Diagnostics, tc.expectedDiags); diff != "" {
137+
t.Fatalf("Unexpected diff in diagnostics (+wanted, -got): %s", diff)
138+
}
139+
if diff := cmp.Diff(plan, tc.expectedPlan); diff != "" {
140+
t.Fatalf("Unexpected diff in plan result (+wanted, -got): %s", diff)
141+
}
142+
if diff := cmp.Diff(tc.resp.RequiresReplace, tc.expectedRR); diff != "" {
143+
t.Fatalf("Unexpected diff in requires replace (+wanted, -got): %s", diff)
144+
}
145+
})
146+
}
147+
}

0 commit comments

Comments
 (0)