Skip to content

Commit 5c11790

Browse files
unit tests (#848)
1 parent c6d7c20 commit 5c11790

File tree

8 files changed

+238
-31
lines changed

8 files changed

+238
-31
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@ engine_test:
2929

3030
.PHONY: regen_tests
3131
regen_tests:
32-
find pkg/engine2/testdata -type f -name '*.input.yaml' -exec ./create_test.sh {} \;
32+
find pkg/engine2/testdata -type f -name '*.input.yaml' -exec ./create_test.sh {} \;

go.mod

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ require (
3131
github.com/stretchr/testify v1.8.2
3232
github.com/vmware-labs/yaml-jsonpath v0.3.2
3333
go.uber.org/atomic v1.9.0
34+
go.uber.org/mock v0.4.0
3435
go.uber.org/zap v1.19.1
3536
golang.org/x/tools v0.7.0
3637
gopkg.in/yaml.v2 v2.4.0
@@ -49,7 +50,7 @@ require (
4950
github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
5051
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
5152
github.com/rivo/uniseg v0.4.4 // indirect
52-
golang.org/x/mod v0.9.0 // indirect
53+
golang.org/x/mod v0.11.0 // indirect
5354
golang.org/x/oauth2 v0.4.0 // indirect
5455
k8s.io/client-go v0.26.0 // indirect
5556
)

go.sum

+4-2
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,8 @@ go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
655655
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
656656
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
657657
go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
658+
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
659+
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
658660
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
659661
go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec=
660662
go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
@@ -712,8 +714,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
712714
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
713715
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
714716
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
715-
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
716-
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
717+
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
718+
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
717719
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
718720
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
719721
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=

pkg/engine2/operational_eval/operational_rule_mock_test.go

+80
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/engine2/operational_eval/vertex_property.go

+22-24
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"strings"
77

8+
"github.com/dominikbraun/graph"
89
construct "github.com/klothoplatform/klotho/pkg/construct2"
910
"github.com/klothoplatform/klotho/pkg/engine2/constraints"
1011
"github.com/klothoplatform/klotho/pkg/engine2/operational_rule"
@@ -119,21 +120,24 @@ func (v *propertyVertex) Evaluate(eval *Evaluator) error {
119120
if err := v.evaluateConstraints(sol, res); err != nil {
120121
return err
121122
}
123+
opCtx := operational_rule.OperationalRuleContext{
124+
Solution: sol,
125+
Property: v.Template,
126+
Data: knowledgebase.DynamicValueData{Resource: res.ID},
127+
}
122128

123129
// we know we cannot change properties of imported resources only users through constraints
124130
// we still want to be able to update ids in case they are setting the property of a namespaced resource
125131
// so we just conditionally run the edge operational rules
126132
//
127133
// we still need to run the resource operational rules though,
128134
// to make sure dependencies exist where properties have operational rules set
129-
if err := v.evaluateResourceOperational(sol, res); err != nil {
135+
if err := v.evaluateResourceOperational(res, &opCtx); err != nil {
130136
return err
131137
}
132138

133-
if !res.Imported {
134-
if err := v.evaluateEdgeOperational(sol, res); err != nil {
135-
return err
136-
}
139+
if err := v.evaluateEdgeOperational(res, &opCtx); err != nil {
140+
return err
137141
}
138142

139143
if err := eval.UpdateId(v.Ref.Resource, res.ID); err != nil {
@@ -271,17 +275,14 @@ func (v *propertyVertex) evaluateConstraints(sol solution_context.SolutionContex
271275
return nil
272276
}
273277

274-
func (v *propertyVertex) evaluateResourceOperational(sol solution_context.SolutionContext, res *construct.Resource) error {
278+
func (v *propertyVertex) evaluateResourceOperational(
279+
res *construct.Resource,
280+
opCtx operational_rule.OpRuleHandler,
281+
) error {
275282
if v.Template == nil || v.Template.Details().OperationalRule == nil {
276283
return nil
277284
}
278285

279-
opCtx := operational_rule.OperationalRuleContext{
280-
Solution: sol,
281-
Property: v.Template,
282-
Data: knowledgebase.DynamicValueData{Resource: res.ID},
283-
}
284-
285286
err := opCtx.HandlePropertyRule(*v.Template.Details().OperationalRule)
286287
if err != nil {
287288
return fmt.Errorf("could not apply operational rule for %s: %w", v.Ref, err)
@@ -290,25 +291,22 @@ func (v *propertyVertex) evaluateResourceOperational(sol solution_context.Soluti
290291
return nil
291292
}
292293

293-
func (v *propertyVertex) evaluateEdgeOperational(sol solution_context.SolutionContext, res *construct.Resource) error {
294+
func (v *propertyVertex) evaluateEdgeOperational(
295+
res *construct.Resource,
296+
opCtx operational_rule.OpRuleHandler,
297+
) error {
294298
oldId := v.Ref.Resource
295-
296-
opCtx := operational_rule.OperationalRuleContext{
297-
Solution: sol,
298-
Property: v.Template,
299-
Data: knowledgebase.DynamicValueData{Resource: res.ID},
300-
}
301-
302299
var errs error
303300
for edge, rules := range v.EdgeRules {
304301
for _, rule := range rules {
305302
// In case one of the previous rules changed the ID, update it
306303
edge = UpdateEdgeId(edge, oldId, res.ID)
307304

308-
opCtx.Data.Edge = &construct.Edge{
309-
Source: edge.Source,
310-
Target: edge.Target,
311-
}
305+
opCtx.SetData(knowledgebase.DynamicValueData{
306+
Resource: res.ID,
307+
Edge: &graph.Edge[construct.ResourceId]{Source: edge.Source, Target: edge.Target},
308+
})
309+
312310
err := opCtx.HandleOperationalRule(rule)
313311
if err != nil {
314312
errs = errors.Join(errs, fmt.Errorf(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package operational_eval
2+
3+
import (
4+
"testing"
5+
6+
"github.com/dominikbraun/graph"
7+
construct "github.com/klothoplatform/klotho/pkg/construct2"
8+
knowledgebase "github.com/klothoplatform/klotho/pkg/knowledge_base2"
9+
"github.com/klothoplatform/klotho/pkg/knowledge_base2/properties"
10+
"github.com/stretchr/testify/assert"
11+
gomock "go.uber.org/mock/gomock"
12+
)
13+
14+
func Test_propertyVertex_evaluateResourceOperational(t *testing.T) {
15+
rule := &knowledgebase.PropertyRule{
16+
Value: "test",
17+
}
18+
type args struct {
19+
v *propertyVertex
20+
res *construct.Resource
21+
}
22+
tests := []struct {
23+
name string
24+
args args
25+
wantErr bool
26+
}{
27+
{
28+
name: "property rule",
29+
args: args{
30+
v: &propertyVertex{
31+
Ref: construct.PropertyRef{
32+
Property: "test",
33+
Resource: construct.ResourceId{Name: "test"},
34+
},
35+
Template: &properties.StringProperty{
36+
PropertyDetails: knowledgebase.PropertyDetails{
37+
OperationalRule: rule,
38+
},
39+
},
40+
},
41+
res: &construct.Resource{ID: construct.ResourceId{Name: "test"}},
42+
},
43+
},
44+
}
45+
for _, tt := range tests {
46+
t.Run(tt.name, func(t *testing.T) {
47+
assert := assert.New(t)
48+
ctrl := gomock.NewController(t)
49+
opctx := NewMockOpRuleHandler(ctrl)
50+
opctx.EXPECT().HandlePropertyRule(*rule).Return(nil).Times(1)
51+
err := tt.args.v.evaluateResourceOperational(tt.args.res, opctx)
52+
if tt.wantErr {
53+
assert.Error(err)
54+
return
55+
}
56+
assert.NoError(err)
57+
ctrl.Finish()
58+
})
59+
}
60+
}
61+
62+
func Test_propertyVertex_evaluateEdgeOperational(t *testing.T) {
63+
rule := knowledgebase.OperationalRule{
64+
If: "test",
65+
}
66+
type args struct {
67+
v *propertyVertex
68+
res *construct.Resource
69+
}
70+
tests := []struct {
71+
name string
72+
args args
73+
wantErr bool
74+
}{
75+
{
76+
name: "property rule",
77+
args: args{
78+
v: &propertyVertex{
79+
Ref: construct.PropertyRef{
80+
Property: "test",
81+
Resource: construct.ResourceId{Name: "test"},
82+
},
83+
EdgeRules: map[construct.SimpleEdge][]knowledgebase.OperationalRule{
84+
{
85+
Source: construct.ResourceId{Name: "test"},
86+
Target: construct.ResourceId{Name: "test2"},
87+
}: {
88+
rule,
89+
},
90+
},
91+
},
92+
res: &construct.Resource{ID: construct.ResourceId{Name: "test"}},
93+
},
94+
},
95+
}
96+
for _, tt := range tests {
97+
t.Run(tt.name, func(t *testing.T) {
98+
assert := assert.New(t)
99+
ctrl := gomock.NewController(t)
100+
opctx := NewMockOpRuleHandler(ctrl)
101+
opctx.EXPECT().SetData(knowledgebase.DynamicValueData{
102+
Resource: tt.args.v.Ref.Resource,
103+
Edge: &graph.Edge[construct.ResourceId]{Source: construct.ResourceId{Name: "test"}, Target: construct.ResourceId{Name: "test2"}},
104+
}).Times(1)
105+
opctx.EXPECT().HandleOperationalRule(rule).Return(nil).Times(1)
106+
err := tt.args.v.evaluateEdgeOperational(tt.args.res, opctx)
107+
if tt.wantErr {
108+
assert.Error(err)
109+
return
110+
}
111+
assert.NoError(err)
112+
ctrl.Finish()
113+
})
114+
}
115+
}

pkg/engine2/operational_rule/operational_rule.go

+14-2
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,23 @@ import (
1313
"go.uber.org/zap"
1414
)
1515

16+
//go:generate mockgen -source=./operational_rule.go --destination=../operational_eval/operational_rule_mock_test.go --package=operational_eval
17+
1618
type (
1719
OperationalRuleContext struct {
1820
Solution solution_context.SolutionContext
1921
Property knowledgebase.Property
2022
Data knowledgebase.DynamicValueData
2123
}
24+
25+
OpRuleHandler interface {
26+
HandleOperationalRule(rule knowledgebase.OperationalRule) error
27+
HandlePropertyRule(rule knowledgebase.PropertyRule) error
28+
SetData(data knowledgebase.DynamicValueData)
29+
}
2230
)
2331

24-
func (ctx OperationalRuleContext) HandleOperationalRule(rule knowledgebase.OperationalRule) error {
32+
func (ctx *OperationalRuleContext) HandleOperationalRule(rule knowledgebase.OperationalRule) error {
2533
shouldRun, err := EvaluateIfCondition(rule.If, ctx.Solution, ctx.Data)
2634
if err != nil {
2735
return err
@@ -49,7 +57,7 @@ func (ctx OperationalRuleContext) HandleOperationalRule(rule knowledgebase.Opera
4957
return errs
5058
}
5159

52-
func (ctx OperationalRuleContext) HandlePropertyRule(rule knowledgebase.PropertyRule) error {
60+
func (ctx *OperationalRuleContext) HandlePropertyRule(rule knowledgebase.PropertyRule) error {
5361
if ctx.Property == nil {
5462
return fmt.Errorf("property rule has no property")
5563
}
@@ -99,6 +107,10 @@ func (ctx OperationalRuleContext) HandlePropertyRule(rule knowledgebase.Property
99107
return errs
100108
}
101109

110+
func (ctx *OperationalRuleContext) SetData(data knowledgebase.DynamicValueData) {
111+
ctx.Data = data
112+
}
113+
102114
// CleanProperty clears the property associated with the rule if it no longer matches the rule.
103115
// For array properties, each element must match at least one step selector and non-matching
104116
// elements will be removed.

pkg/engine2/operational_rule/resource_placer.go

-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ type (
2323

2424
SetCtx(ctx OperationalRuleContext)
2525
}
26-
2726
SpreadPlacer struct {
2827
ctx OperationalRuleContext
2928
}

0 commit comments

Comments
 (0)