Summary
The .test.mdl parser panics (slice bounds out of range [:-1]) whenever a test file has CRLF line endings. Every command that parses the file dies with a stack trace instead of a diagnostic — --list included — and because the runner scans the whole tests directory, one CRLF file poisons runs that name a different file, which makes the failure look nondeterministic.
Reproduced on v0.17.0, nightly-20260813-4b15694f, and re-confirmed on v0.18.0.
Environment
- mxcli v0.18.0, windows/amd64
- Mendix 11.12.1 project, MPR v2
Reproduction
printf '/**\r\n * @test crlf probe\r\n * @expect $x = 1\r\n */\r\n$x = 1;\r\n/\r\n' > t.test.mdl
mxcli test t.test.mdl -p app.mpr --list
panic: runtime error: slice bounds out of range [:-1]
goroutine 1 [running]:
github.com/mendixlabs/mxcli/cmd/mxcli/testrunner.extractDocAndBody(...)
github.com/mendixlabs/mxcli/cmd/mxcli/testrunner/parser.go:275 +0x1da
github.com/mendixlabs/mxcli/cmd/mxcli/testrunner.parseMDLTests(...)
github.com/mendixlabs/mxcli/cmd/mxcli/testrunner/parser.go:125 +0x10c
github.com/mendixlabs/mxcli/cmd/mxcli/testrunner.ParseTestFile(...)
github.com/mendixlabs/mxcli/cmd/mxcli/testrunner/parser.go:65 +0x29a
The identical file with LF endings lists and runs fine.
Root cause
extractDocAndBody estimates the block's line number with:
line := 1 + strings.Count(fullContent[:strings.Index(fullContent, block[:20])], "\n")
Blocks are rebuilt by joining lines with "\n", so on a CRLF file block[:20] (LF-joined) never occurs in fullContent (CRLF), strings.Index returns -1, and the slice panics. Any of: normalizing \r\n → \n before splitting, searching a normalized copy, or guarding the -1 fixes it (the first also makes block extraction consistent).
Why this bites harder than it looks
- It presents as nondeterministic. A file authored with LF works; any later edit through a tool that writes platform line endings (Python text-mode
open(...,'w') on Windows, some editors, git autocrlf) silently converts it to CRLF, and a previously green suite starts panicking with no visible change.
- One bad file kills unrelated runs.
mxcli test tests/other.test.mdl --list still parses every *.test.mdl in the directory, so the panic names a file the user did not ask about.
- Windows is presumably the most common authoring platform for Mendix developers, and CRLF is its default.
Workaround
Write .test.mdl files with LF endings only (e.g. Python open(p, "w", newline="\n"), or a .gitattributes rule *.test.mdl text eol=lf).
Summary
The
.test.mdlparser panics (slice bounds out of range [:-1]) whenever a test file has CRLF line endings. Every command that parses the file dies with a stack trace instead of a diagnostic —--listincluded — and because the runner scans the whole tests directory, one CRLF file poisons runs that name a different file, which makes the failure look nondeterministic.Reproduced on v0.17.0, nightly-20260813-4b15694f, and re-confirmed on v0.18.0.
Environment
Reproduction
The identical file with LF endings lists and runs fine.
Root cause
extractDocAndBodyestimates the block's line number with:Blocks are rebuilt by joining lines with
"\n", so on a CRLF fileblock[:20](LF-joined) never occurs infullContent(CRLF),strings.Indexreturns -1, and the slice panics. Any of: normalizing\r\n→\nbefore splitting, searching a normalized copy, or guarding the-1fixes it (the first also makes block extraction consistent).Why this bites harder than it looks
open(...,'w')on Windows, some editors, gitautocrlf) silently converts it to CRLF, and a previously green suite starts panicking with no visible change.mxcli test tests/other.test.mdl --liststill parses every*.test.mdlin the directory, so the panic names a file the user did not ask about.Workaround
Write
.test.mdlfiles with LF endings only (e.g. Pythonopen(p, "w", newline="\n"), or a.gitattributesrule*.test.mdl text eol=lf).