Skip to content

Commit 3df8598

Browse files
committed
test(linter): add tests for all 14 untested rules
SQLite-backed tests for MPR002, MPR003, SEC001. Helper function tests for CONV011-014, MPR004, MPR008. Metadata + nil-reader guard tests for SEC002, SEC003, MPR007. Total: 11 new test files covering all 14 previously untested rules.
1 parent 900796d commit 3df8598

9 files changed

Lines changed: 1044 additions & 0 deletions
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
package rules
4+
5+
import (
6+
"testing"
7+
8+
"github.com/mendixlabs/mxcli/mdl/linter"
9+
"github.com/mendixlabs/mxcli/sdk/microflows"
10+
)
11+
12+
func TestFindUnhandledCalls_RestCallNoCustom(t *testing.T) {
13+
objects := []microflows.MicroflowObject{
14+
&microflows.ActionActivity{
15+
BaseActivity: microflows.BaseActivity{
16+
ErrorHandlingType: microflows.ErrorHandlingTypeAbort,
17+
},
18+
Action: &microflows.RestCallAction{},
19+
},
20+
}
21+
22+
var violations []linter.Violation
23+
r := NewErrorHandlingOnCallsRule()
24+
findUnhandledCalls(objects, testMicroflow(), r, &violations)
25+
26+
if len(violations) != 1 {
27+
t.Fatalf("expected 1 violation, got %d", len(violations))
28+
}
29+
if violations[0].RuleID != "CONV013" {
30+
t.Errorf("expected CONV013, got %s", violations[0].RuleID)
31+
}
32+
}
33+
34+
func TestFindUnhandledCalls_RestCallCustom(t *testing.T) {
35+
objects := []microflows.MicroflowObject{
36+
&microflows.ActionActivity{
37+
BaseActivity: microflows.BaseActivity{
38+
ErrorHandlingType: microflows.ErrorHandlingTypeCustom,
39+
},
40+
Action: &microflows.RestCallAction{},
41+
},
42+
}
43+
44+
var violations []linter.Violation
45+
r := NewErrorHandlingOnCallsRule()
46+
findUnhandledCalls(objects, testMicroflow(), r, &violations)
47+
48+
if len(violations) != 0 {
49+
t.Errorf("expected 0 violations with Custom handling, got %d", len(violations))
50+
}
51+
}
52+
53+
func TestFindUnhandledCalls_CustomWithoutRollback(t *testing.T) {
54+
objects := []microflows.MicroflowObject{
55+
&microflows.ActionActivity{
56+
BaseActivity: microflows.BaseActivity{
57+
ErrorHandlingType: microflows.ErrorHandlingTypeCustomWithoutRollback,
58+
},
59+
Action: &microflows.RestCallAction{},
60+
},
61+
}
62+
63+
var violations []linter.Violation
64+
r := NewErrorHandlingOnCallsRule()
65+
findUnhandledCalls(objects, testMicroflow(), r, &violations)
66+
67+
if len(violations) != 0 {
68+
t.Errorf("expected 0 violations with CustomWithoutRollback, got %d", len(violations))
69+
}
70+
}
71+
72+
func TestFindUnhandledCalls_JavaAction(t *testing.T) {
73+
objects := []microflows.MicroflowObject{
74+
&microflows.ActionActivity{
75+
BaseActivity: microflows.BaseActivity{
76+
ErrorHandlingType: microflows.ErrorHandlingTypeAbort,
77+
},
78+
Action: &microflows.JavaActionCallAction{},
79+
},
80+
}
81+
82+
var violations []linter.Violation
83+
r := NewErrorHandlingOnCallsRule()
84+
findUnhandledCalls(objects, testMicroflow(), r, &violations)
85+
86+
if len(violations) != 1 {
87+
t.Fatalf("expected 1 violation for Java action, got %d", len(violations))
88+
}
89+
}
90+
91+
func TestFindUnhandledCalls_WebServiceCall(t *testing.T) {
92+
objects := []microflows.MicroflowObject{
93+
&microflows.ActionActivity{
94+
BaseActivity: microflows.BaseActivity{
95+
ErrorHandlingType: microflows.ErrorHandlingTypeContinue,
96+
},
97+
Action: &microflows.WebServiceCallAction{},
98+
},
99+
}
100+
101+
var violations []linter.Violation
102+
r := NewErrorHandlingOnCallsRule()
103+
findUnhandledCalls(objects, testMicroflow(), r, &violations)
104+
105+
if len(violations) != 1 {
106+
t.Fatalf("expected 1 violation for WS call, got %d", len(violations))
107+
}
108+
}
109+
110+
func TestFindUnhandledCalls_NonExternalAction(t *testing.T) {
111+
objects := []microflows.MicroflowObject{
112+
&microflows.ActionActivity{
113+
BaseActivity: microflows.BaseActivity{
114+
ErrorHandlingType: microflows.ErrorHandlingTypeAbort,
115+
},
116+
Action: &microflows.CommitObjectsAction{},
117+
},
118+
}
119+
120+
var violations []linter.Violation
121+
r := NewErrorHandlingOnCallsRule()
122+
findUnhandledCalls(objects, testMicroflow(), r, &violations)
123+
124+
if len(violations) != 0 {
125+
t.Errorf("expected 0 violations for non-external action, got %d", len(violations))
126+
}
127+
}
128+
129+
func TestFindUnhandledCalls_InsideLoop(t *testing.T) {
130+
loopBody := &microflows.MicroflowObjectCollection{
131+
Objects: []microflows.MicroflowObject{
132+
&microflows.ActionActivity{
133+
BaseActivity: microflows.BaseActivity{
134+
ErrorHandlingType: microflows.ErrorHandlingTypeAbort,
135+
},
136+
Action: &microflows.RestCallAction{},
137+
},
138+
},
139+
}
140+
objects := []microflows.MicroflowObject{
141+
&microflows.LoopedActivity{
142+
ObjectCollection: loopBody,
143+
},
144+
}
145+
146+
var violations []linter.Violation
147+
r := NewErrorHandlingOnCallsRule()
148+
findUnhandledCalls(objects, testMicroflow(), r, &violations)
149+
150+
if len(violations) != 1 {
151+
t.Errorf("expected 1 violation inside loop, got %d", len(violations))
152+
}
153+
}
154+
155+
// --- CONV014 tests ---
156+
157+
func TestFindContinueErrorHandling_Activity(t *testing.T) {
158+
objects := []microflows.MicroflowObject{
159+
&microflows.ActionActivity{
160+
BaseActivity: microflows.BaseActivity{
161+
Caption: "Do something",
162+
ErrorHandlingType: microflows.ErrorHandlingTypeContinue,
163+
},
164+
Action: &microflows.CommitObjectsAction{},
165+
},
166+
}
167+
168+
var violations []linter.Violation
169+
r := NewNoContinueErrorHandlingRule()
170+
findContinueErrorHandling(objects, testMicroflow(), r, &violations)
171+
172+
if len(violations) != 1 {
173+
t.Fatalf("expected 1 violation, got %d", len(violations))
174+
}
175+
if violations[0].RuleID != "CONV014" {
176+
t.Errorf("expected CONV014, got %s", violations[0].RuleID)
177+
}
178+
}
179+
180+
func TestFindContinueErrorHandling_Loop(t *testing.T) {
181+
objects := []microflows.MicroflowObject{
182+
&microflows.LoopedActivity{
183+
Caption: "Process items",
184+
ErrorHandlingType: microflows.ErrorHandlingTypeContinue,
185+
},
186+
}
187+
188+
var violations []linter.Violation
189+
r := NewNoContinueErrorHandlingRule()
190+
findContinueErrorHandling(objects, testMicroflow(), r, &violations)
191+
192+
if len(violations) != 1 {
193+
t.Fatalf("expected 1 violation for loop, got %d", len(violations))
194+
}
195+
}
196+
197+
func TestFindContinueErrorHandling_AbortIsOk(t *testing.T) {
198+
objects := []microflows.MicroflowObject{
199+
&microflows.ActionActivity{
200+
BaseActivity: microflows.BaseActivity{
201+
ErrorHandlingType: microflows.ErrorHandlingTypeAbort,
202+
},
203+
Action: &microflows.CommitObjectsAction{},
204+
},
205+
}
206+
207+
var violations []linter.Violation
208+
r := NewNoContinueErrorHandlingRule()
209+
findContinueErrorHandling(objects, testMicroflow(), r, &violations)
210+
211+
if len(violations) != 0 {
212+
t.Errorf("expected 0 violations for Abort, got %d", len(violations))
213+
}
214+
}
215+
216+
func TestErrorHandlingOnCallsRule_Metadata(t *testing.T) {
217+
r := NewErrorHandlingOnCallsRule()
218+
if r.ID() != "CONV013" {
219+
t.Errorf("ID = %q, want CONV013", r.ID())
220+
}
221+
}
222+
223+
func TestNoContinueErrorHandlingRule_Metadata(t *testing.T) {
224+
r := NewNoContinueErrorHandlingRule()
225+
if r.ID() != "CONV014" {
226+
t.Errorf("ID = %q, want CONV014", r.ID())
227+
}
228+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
package rules
4+
5+
import (
6+
"testing"
7+
8+
"github.com/mendixlabs/mxcli/mdl/linter"
9+
"github.com/mendixlabs/mxcli/sdk/microflows"
10+
)
11+
12+
func testMicroflow() linter.Microflow {
13+
return linter.Microflow{
14+
ID: "mf1",
15+
Name: "ACT_Process",
16+
QualifiedName: "MyModule.ACT_Process",
17+
ModuleName: "MyModule",
18+
}
19+
}
20+
21+
func TestFindCommitsInLoops_NoLoop(t *testing.T) {
22+
objects := []microflows.MicroflowObject{
23+
&microflows.ActionActivity{
24+
BaseActivity: microflows.BaseActivity{},
25+
Action: &microflows.CommitObjectsAction{},
26+
},
27+
}
28+
29+
var violations []linter.Violation
30+
r := NewNoCommitInLoopRule()
31+
findCommitsInLoops(objects, testMicroflow(), r, &violations, false)
32+
33+
if len(violations) != 0 {
34+
t.Errorf("expected 0 violations outside loop, got %d", len(violations))
35+
}
36+
}
37+
38+
func TestFindCommitsInLoops_CommitInsideLoop(t *testing.T) {
39+
loopBody := &microflows.MicroflowObjectCollection{
40+
Objects: []microflows.MicroflowObject{
41+
&microflows.ActionActivity{
42+
BaseActivity: microflows.BaseActivity{},
43+
Action: &microflows.CommitObjectsAction{},
44+
},
45+
},
46+
}
47+
objects := []microflows.MicroflowObject{
48+
&microflows.LoopedActivity{
49+
ObjectCollection: loopBody,
50+
},
51+
}
52+
53+
var violations []linter.Violation
54+
r := NewNoCommitInLoopRule()
55+
findCommitsInLoops(objects, testMicroflow(), r, &violations, false)
56+
57+
if len(violations) != 1 {
58+
t.Fatalf("expected 1 violation, got %d", len(violations))
59+
}
60+
if violations[0].RuleID != "CONV011" {
61+
t.Errorf("expected CONV011, got %s", violations[0].RuleID)
62+
}
63+
}
64+
65+
func TestFindCommitsInLoops_NilAction(t *testing.T) {
66+
objects := []microflows.MicroflowObject{
67+
&microflows.ActionActivity{
68+
BaseActivity: microflows.BaseActivity{},
69+
Action: nil,
70+
},
71+
}
72+
73+
var violations []linter.Violation
74+
r := NewNoCommitInLoopRule()
75+
findCommitsInLoops(objects, testMicroflow(), r, &violations, true)
76+
77+
if len(violations) != 0 {
78+
t.Errorf("expected 0 violations for nil action, got %d", len(violations))
79+
}
80+
}
81+
82+
func TestNoCommitInLoopRule_NilReader(t *testing.T) {
83+
r := NewNoCommitInLoopRule()
84+
ctx := linter.NewLintContextFromDB(nil)
85+
// Reader() is nil, should return nil
86+
violations := r.Check(ctx)
87+
if violations != nil {
88+
t.Errorf("expected nil with nil reader, got %v", violations)
89+
}
90+
}
91+
92+
func TestNoCommitInLoopRule_Metadata(t *testing.T) {
93+
r := NewNoCommitInLoopRule()
94+
if r.ID() != "CONV011" {
95+
t.Errorf("ID = %q, want CONV011", r.ID())
96+
}
97+
if r.Category() != "performance" {
98+
t.Errorf("Category = %q, want performance", r.Category())
99+
}
100+
}

0 commit comments

Comments
 (0)