Skip to content

Commit 5b17c36

Browse files
committed
fix: exhaustive nanoflow denylist test, error handling coverage comment, and trailing-dot numeric literal
1 parent 55643a9 commit 5b17c36

4 files changed

Lines changed: 31 additions & 1 deletion

File tree

mdl/executor/cmd_microflows_format_action.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1159,7 +1159,7 @@ func isNumericLiteral(s string) bool {
11591159
return false
11601160
}
11611161
}
1162-
return hasDigit
1162+
return hasDigit && s[len(s)-1] != '.'
11631163
}
11641164

11651165
// formatImportXmlAction formats an import mapping action as MDL.

mdl/executor/cmd_microflows_format_action_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,11 @@ func TestIsNumericLiteral(t *testing.T) {
742742
{"$42", false},
743743
{"1.2.3", false},
744744
{"42abc", false},
745+
{".", false},
746+
{"-.", false},
747+
{"5.", false},
748+
{".5", true},
749+
{"-.5", true},
745750
}
746751
for _, tt := range tests {
747752
got := isNumericLiteral(tt.input)

mdl/executor/cmd_nanoflows_mock_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,9 @@ func TestShowAccessOnNanoflow_Mock_NotFound(t *testing.T) {
303303
// --- NANOFLOW VALIDATION ---
304304

305305
func TestValidateNanoflowBody_DisallowedActions(t *testing.T) {
306+
// EXHAUSTIVE: every type in checkDisallowedNanoflowAction must appear here.
307+
// If a new server-side action is added to the AST but not to the denylist,
308+
// add it here so the test fails visibly.
306309
tests := []struct {
307310
name string
308311
stmt ast.MicroflowStatement
@@ -311,9 +314,24 @@ func TestValidateNanoflowBody_DisallowedActions(t *testing.T) {
311314
{"RaiseError", &ast.RaiseErrorStmt{}, "ErrorEvent"},
312315
{"JavaAction", &ast.CallJavaActionStmt{}, "Java"},
313316
{"DatabaseQuery", &ast.ExecuteDatabaseQueryStmt{}, "database"},
317+
{"CallExternalAction", &ast.CallExternalActionStmt{}, "external action"},
314318
{"ShowHomePage", &ast.ShowHomePageStmt{}, "SHOW HOME PAGE"},
315319
{"RestCall", &ast.RestCallStmt{}, "REST"},
320+
{"SendRestRequest", &ast.SendRestRequestStmt{}, "REST"},
321+
{"ImportFromMapping", &ast.ImportFromMappingStmt{}, "import mapping"},
322+
{"ExportToMapping", &ast.ExportToMappingStmt{}, "export mapping"},
323+
{"TransformJson", &ast.TransformJsonStmt{}, "JSON transformation"},
316324
{"CallWorkflow", &ast.CallWorkflowStmt{}, "workflow"},
325+
{"GetWorkflowData", &ast.GetWorkflowDataStmt{}, "workflow"},
326+
{"GetWorkflows", &ast.GetWorkflowsStmt{}, "workflow"},
327+
{"GetWorkflowActivityRecords", &ast.GetWorkflowActivityRecordsStmt{}, "workflow"},
328+
{"WorkflowOperation", &ast.WorkflowOperationStmt{}, "workflow"},
329+
{"SetTaskOutcome", &ast.SetTaskOutcomeStmt{}, "workflow"},
330+
{"OpenUserTask", &ast.OpenUserTaskStmt{}, "workflow"},
331+
{"NotifyWorkflow", &ast.NotifyWorkflowStmt{}, "workflow"},
332+
{"OpenWorkflow", &ast.OpenWorkflowStmt{}, "workflow"},
333+
{"LockWorkflow", &ast.LockWorkflowStmt{}, "workflow"},
334+
{"UnlockWorkflow", &ast.UnlockWorkflowStmt{}, "workflow"},
317335
}
318336

319337
for _, tt := range tests {
@@ -338,6 +356,7 @@ func TestValidateNanoflowBody_AllowedActions(t *testing.T) {
338356
{"ShowPage", &ast.ShowPageStmt{}},
339357
{"CallMicroflow", &ast.CallMicroflowStmt{}},
340358
{"CallNanoflow", &ast.CallNanoflowStmt{}},
359+
{"CallJavaScriptAction", &ast.CallJavaScriptActionStmt{}},
341360
{"CreateVariable", &ast.DeclareStmt{}},
342361
{"ChangeVariable", &ast.MfSetStmt{}},
343362
}

mdl/executor/nanoflow_validation.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,12 @@ func checkDisallowedNanoflowAction(stmt ast.MicroflowStatement) string {
9797
}
9898

9999
// getErrorHandling extracts the ErrorHandlingClause from statements that have one.
100+
//
101+
// NOTE: This function does not cover all statement types that carry an ErrorHandling
102+
// field (e.g., CallWorkflowStmt, ShowHomePageStmt, workflow action stmts). That is
103+
// safe because validateNanoflowStatements checks the denylist FIRST and skips
104+
// recursion (via continue) for disallowed actions. If the denylist ordering changes,
105+
// add error handling extraction for those types here.
100106
func getErrorHandling(stmt ast.MicroflowStatement) *ast.ErrorHandlingClause {
101107
switch s := stmt.(type) {
102108
case *ast.CreateObjectStmt:

0 commit comments

Comments
 (0)