Skip to content

fix(test): generated test callers apply entity access - #2148

Merged
ako merged 4 commits into
mainfrom
fix/2100-test-callers-entity-access
Nov 11, 2026
Merged

ako merged 4 commits into
mainfrom
fix/2100-test-callers-entity-access

Conversation

@ako

@ako ako commented Nov 11, 2026

Copy link
Copy Markdown
Owner

Closes #2100 (upstream mendixlabs#1805).

Problem

A .test.mdl test that calls a microflow with Apply entity access = Yes failed at build with CE0114, and at check with MDL-SEC22. The same happened for an applying @setup microflow. Three generators wrote their callers without the setting:

  • the endpoint test microflows (writeTestFlow);
  • the --legacy-runner's MxTest.TestRunner;
  • the MxTest.Check_* wrappers that mxcli check and the editor use.

The issue names two of them; the legacy runner is the third. The only workaround was to weaken the production microflow.

Setting it on the callers alone exposes the second error the issue reports, CE0150. An applying flow may not read $latestError/Message, and the runner's verdict and @throws handlers read it.

Measured (mx check, 11.12.1, security Off and Production)

Case Result
Non-applying caller calls an applying microflow CE0114
Applying caller reads $latestError/Message CE0150, whose text says: "Pass the object to a microflow that does not apply entity access"
Applying caller passes $latestError to a non-applying helper 0 errors
Applying caller reads an attribute of an entity with no access rules (control) 0 errors, so CE0150 is the only cost

Tests run under Core.createSystemContext, which entity access does not restrict, so nothing changes at run time.

Change

  • All three callers apply entity access, as MxTest.RegisterEndpoint already did for [up#1645] mxcli test --local: the generated MxTest.RegisterEndpoint does not apply entity access, so a project whose after-startup microflow does cannot be tested (CE0114) #1654. The check wrapper keeps the annotation on its existing line, so no body line moves.
  • The handlers read the message through a helper. Each one calls MxTest.Test_ErrorMessage(RaisedError = $latestError), a generated helper that does not apply entity access, into its own $MxTestErrorMessage[_suite]_n. attachOnError now numbers the handlers. The handlers are built in a structured way, not by rewriting text.
  • Helper ownership:
    • it is written with the test microflows, so an endpoint installed by an older mxcli still finds it;
    • its Test_ prefix means every existing discovery and cleanup path removes it, while no test ID (test_N) can produce its name;
    • the legacy cleanup and the fallback drop list name it explicitly;
    • a build error in it is reported as mxcli's.
  • Opt-out: a test whose own error handler reads $latestError/… (outside strings and comments) keeps a non-applying caller, so it builds as it does today. Under the legacy runner this applies per suite, since all tests share one microflow. The docs give the fix for a test that needs both.

Verification

  • New unit tests in caller_entity_access_test.go. Generated MDL is parsed to the AST and checked for:
    • the setting on each caller kind;
    • a non-applying helper, defined once;
    • no direct error-attribute read outside the helper;
    • one message variable per handler;
    • the opt-out, with a string-literal control;
    • cleanup and attribution.
  • Shown to catch the bug: with the setting stubbed off, the tests fail on CE0114. With the handlers stubbed to read $latestError/Message directly, they fail on CE0150.
  • End to end on an 11.12.1 app (--local --db-type hsqldb):
    • Control (main): every test calling an applying microflow, @setup included, was an ERROR with CE0114, and check reported MDL-SEC22.
    • After the fix: an applying call, a non-applying call, @throws with a matching message, bare @throws and an applying @setup all PASS. An unexpected error FAILs with exception during execution: Amount must be positive. A wrong @throws FAILs with expected an error containing 'something else', actual: Amount must be positive. A test whose own handler reads $latestError/Message PASSes. Check passes.
    • Pre-existing MxTest module: only the user's own microflow remains after cleanup.
    • --legacy-runner: builds and runs. As before this change, an unexpected error ends that runner.
  • mdl-examples/bug-tests/test-runner-2100-* was run exactly as its header documents.
  • make ci-local passes.

Docs: running-tests.md and the test-microflows skill. Also a CHANGELOG entry and a finding record.


Generated by Claude Code

claude and others added 4 commits November 11, 2026 19:30
A test calling a microflow with Apply entity access = Yes failed CE0114
at build and MDL-SEC22 at check: the endpoint test microflows, the
legacy MxTest.TestRunner and the MxTest.Check_* wrappers were written
without the setting. They now apply it, as RegisterEndpoint already did
(#1654); CE0114 has one direction, so an applying caller may call both.

An applying flow may not read $latestError/Message (CE0150), so the
runner's verdict and @throws handlers pass $latestError to a generated
non-applying helper, MxTest.Test_ErrorMessage, each into its own
variable. It carries the generated prefix, so every discovery and
cleanup path removes it; the legacy cleanup drops it explicitly, and a
build error in it is attributed to mxcli.

A test whose own handler reads $latestError/... keeps a non-applying
caller, so it builds as before. Tests run in a system context, so
nothing changes at run time.

Measured on 11.12.1 at security Off and Production; end to end with
--local, --legacy-runner and a pre-existing MxTest module.

Closes #2100. Refs mendixlabs#1805.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiMsnXa9crge2qnSk9S7Zn
@ako
ako merged commit 9c0bcdd into main Nov 11, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants