Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions mdl/executor/cmd_javaactions_mock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,11 @@ func TestDescribeJavaAction_Mock(t *testing.T) {
}

// NOTE: listJavaActions has no explicit not-connected guard. It calls
// getHierarchy (returns nil when disconnected) then proceeds to call
// ListJavaActions on the backend. The handler degrades gracefully —
// with an empty result set it succeeds with a nil hierarchy.
// getHierarchy (which returns nil when disconnected) and is intended to
// be reached through execShow, which enforces a connected backend first.
// A nil hierarchy is only harmless when the backend returns no Java
// actions; if Java actions are returned while disconnected, dereferencing
// the nil hierarchy would panic.

func TestShowJavaActions_BackendError(t *testing.T) {
mod := mkModule("MyModule")
Expand Down
231 changes: 231 additions & 0 deletions mdl/linter/rules/conv_error_handling_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
// SPDX-License-Identifier: Apache-2.0

package rules

import (
"testing"

"github.com/mendixlabs/mxcli/mdl/linter"
"github.com/mendixlabs/mxcli/sdk/microflows"
)

func TestFindUnhandledCalls_RestCallNoCustom(t *testing.T) {
objects := []microflows.MicroflowObject{
&microflows.ActionActivity{
BaseActivity: microflows.BaseActivity{
ErrorHandlingType: microflows.ErrorHandlingTypeAbort,
},
Action: &microflows.RestCallAction{},
},
}

var violations []linter.Violation
r := NewErrorHandlingOnCallsRule()
findUnhandledCalls(objects, testMicroflow(), r, &violations)

if len(violations) != 1 {
t.Fatalf("expected 1 violation, got %d", len(violations))
}
if violations[0].RuleID != "CONV013" {
t.Errorf("expected CONV013, got %s", violations[0].RuleID)
}
}

func TestFindUnhandledCalls_RestCallCustom(t *testing.T) {
objects := []microflows.MicroflowObject{
&microflows.ActionActivity{
BaseActivity: microflows.BaseActivity{
ErrorHandlingType: microflows.ErrorHandlingTypeCustom,
},
Action: &microflows.RestCallAction{},
},
}

var violations []linter.Violation
r := NewErrorHandlingOnCallsRule()
findUnhandledCalls(objects, testMicroflow(), r, &violations)

if len(violations) != 0 {
t.Errorf("expected 0 violations with Custom handling, got %d", len(violations))
}
}

func TestFindUnhandledCalls_CustomWithoutRollback(t *testing.T) {
objects := []microflows.MicroflowObject{
&microflows.ActionActivity{
BaseActivity: microflows.BaseActivity{
ErrorHandlingType: microflows.ErrorHandlingTypeCustomWithoutRollback,
},
Action: &microflows.RestCallAction{},
},
}

var violations []linter.Violation
r := NewErrorHandlingOnCallsRule()
findUnhandledCalls(objects, testMicroflow(), r, &violations)

if len(violations) != 0 {
t.Errorf("expected 0 violations with CustomWithoutRollback, got %d", len(violations))
}
}

func TestFindUnhandledCalls_JavaAction(t *testing.T) {
objects := []microflows.MicroflowObject{
&microflows.ActionActivity{
BaseActivity: microflows.BaseActivity{
ErrorHandlingType: microflows.ErrorHandlingTypeAbort,
},
Action: &microflows.JavaActionCallAction{},
},
}

var violations []linter.Violation
r := NewErrorHandlingOnCallsRule()
findUnhandledCalls(objects, testMicroflow(), r, &violations)

if len(violations) != 1 {
t.Fatalf("expected 1 violation for Java action, got %d", len(violations))
}
}

func TestFindUnhandledCalls_WebServiceCall(t *testing.T) {
objects := []microflows.MicroflowObject{
&microflows.ActionActivity{
BaseActivity: microflows.BaseActivity{
ErrorHandlingType: microflows.ErrorHandlingTypeContinue,
},
Action: &microflows.WebServiceCallAction{},
},
}

var violations []linter.Violation
r := NewErrorHandlingOnCallsRule()
findUnhandledCalls(objects, testMicroflow(), r, &violations)

if len(violations) != 1 {
t.Fatalf("expected 1 violation for WS call, got %d", len(violations))
}
if violations[0].RuleID != "CONV013" {
t.Errorf("expected CONV013, got %s", violations[0].RuleID)
}
}

func TestFindUnhandledCalls_NonExternalAction(t *testing.T) {
objects := []microflows.MicroflowObject{
&microflows.ActionActivity{
BaseActivity: microflows.BaseActivity{
ErrorHandlingType: microflows.ErrorHandlingTypeAbort,
},
Action: &microflows.CommitObjectsAction{},
},
}

var violations []linter.Violation
r := NewErrorHandlingOnCallsRule()
findUnhandledCalls(objects, testMicroflow(), r, &violations)

if len(violations) != 0 {
t.Errorf("expected 0 violations for non-external action, got %d", len(violations))
}
}

func TestFindUnhandledCalls_InsideLoop(t *testing.T) {
loopBody := &microflows.MicroflowObjectCollection{
Objects: []microflows.MicroflowObject{
&microflows.ActionActivity{
BaseActivity: microflows.BaseActivity{
ErrorHandlingType: microflows.ErrorHandlingTypeAbort,
},
Action: &microflows.RestCallAction{},
},
},
}
objects := []microflows.MicroflowObject{
&microflows.LoopedActivity{
ObjectCollection: loopBody,
},
}

var violations []linter.Violation
r := NewErrorHandlingOnCallsRule()
findUnhandledCalls(objects, testMicroflow(), r, &violations)

if len(violations) != 1 {
t.Errorf("expected 1 violation inside loop, got %d", len(violations))
}
}

// --- CONV014 tests ---

func TestFindContinueErrorHandling_Activity(t *testing.T) {
objects := []microflows.MicroflowObject{
&microflows.ActionActivity{
BaseActivity: microflows.BaseActivity{
Caption: "Do something",
ErrorHandlingType: microflows.ErrorHandlingTypeContinue,
},
Action: &microflows.CommitObjectsAction{},
},
}

var violations []linter.Violation
r := NewNoContinueErrorHandlingRule()
findContinueErrorHandling(objects, testMicroflow(), r, &violations)

if len(violations) != 1 {
t.Fatalf("expected 1 violation, got %d", len(violations))
}
if violations[0].RuleID != "CONV014" {
t.Errorf("expected CONV014, got %s", violations[0].RuleID)
}
}

func TestFindContinueErrorHandling_Loop(t *testing.T) {
objects := []microflows.MicroflowObject{
&microflows.LoopedActivity{
Caption: "Process items",
ErrorHandlingType: microflows.ErrorHandlingTypeContinue,
},
}

var violations []linter.Violation
r := NewNoContinueErrorHandlingRule()
findContinueErrorHandling(objects, testMicroflow(), r, &violations)

if len(violations) != 1 {
t.Fatalf("expected 1 violation for loop, got %d", len(violations))
}
}

func TestFindContinueErrorHandling_AbortIsOk(t *testing.T) {
objects := []microflows.MicroflowObject{
&microflows.ActionActivity{
BaseActivity: microflows.BaseActivity{
ErrorHandlingType: microflows.ErrorHandlingTypeAbort,
},
Action: &microflows.CommitObjectsAction{},
},
}

var violations []linter.Violation
r := NewNoContinueErrorHandlingRule()
findContinueErrorHandling(objects, testMicroflow(), r, &violations)

if len(violations) != 0 {
t.Errorf("expected 0 violations for Abort, got %d", len(violations))
}
}

func TestErrorHandlingOnCallsRule_Metadata(t *testing.T) {
r := NewErrorHandlingOnCallsRule()
if r.ID() != "CONV013" {
t.Errorf("ID = %q, want CONV013", r.ID())
}
}

func TestNoContinueErrorHandlingRule_Metadata(t *testing.T) {
r := NewNoContinueErrorHandlingRule()
if r.ID() != "CONV014" {
t.Errorf("ID = %q, want CONV014", r.ID())
}
}
91 changes: 91 additions & 0 deletions mdl/linter/rules/conv_loop_commit_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// SPDX-License-Identifier: Apache-2.0

package rules

import (
"testing"

"github.com/mendixlabs/mxcli/mdl/linter"
"github.com/mendixlabs/mxcli/sdk/microflows"
)

func TestFindCommitsInLoops_NoLoop(t *testing.T) {
objects := []microflows.MicroflowObject{
&microflows.ActionActivity{
BaseActivity: microflows.BaseActivity{},
Action: &microflows.CommitObjectsAction{},
},
}

var violations []linter.Violation
r := NewNoCommitInLoopRule()
findCommitsInLoops(objects, testMicroflow(), r, &violations, false)

if len(violations) != 0 {
t.Errorf("expected 0 violations outside loop, got %d", len(violations))
}
}

func TestFindCommitsInLoops_CommitInsideLoop(t *testing.T) {
loopBody := &microflows.MicroflowObjectCollection{
Objects: []microflows.MicroflowObject{
&microflows.ActionActivity{
BaseActivity: microflows.BaseActivity{},
Action: &microflows.CommitObjectsAction{},
},
},
}
objects := []microflows.MicroflowObject{
&microflows.LoopedActivity{
ObjectCollection: loopBody,
},
}

var violations []linter.Violation
r := NewNoCommitInLoopRule()
findCommitsInLoops(objects, testMicroflow(), r, &violations, false)

if len(violations) != 1 {
t.Fatalf("expected 1 violation, got %d", len(violations))
}
if violations[0].RuleID != "CONV011" {
t.Errorf("expected CONV011, got %s", violations[0].RuleID)
}
}

func TestFindCommitsInLoops_NilAction(t *testing.T) {
objects := []microflows.MicroflowObject{
&microflows.ActionActivity{
BaseActivity: microflows.BaseActivity{},
Action: nil,
},
}

var violations []linter.Violation
r := NewNoCommitInLoopRule()
findCommitsInLoops(objects, testMicroflow(), r, &violations, true)

if len(violations) != 0 {
t.Errorf("expected 0 violations for nil action, got %d", len(violations))
}
}

func TestNoCommitInLoopRule_NilReader(t *testing.T) {
r := NewNoCommitInLoopRule()
ctx := linter.NewLintContextFromDB(nil)
// Reader() is nil, should return nil
violations := r.Check(ctx)
if violations != nil {
t.Errorf("expected nil with nil reader, got %v", violations)
}
}

func TestNoCommitInLoopRule_Metadata(t *testing.T) {
r := NewNoCommitInLoopRule()
if r.ID() != "CONV011" {
t.Errorf("ID = %q, want CONV011", r.ID())
}
if r.Category() != "performance" {
t.Errorf("Category = %q, want performance", r.Category())
}
}
Loading
Loading