You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[motoko_agent] Named test blocks with assert always fail: EvaluateNamedTestBodyExprs round-trips AssertStmt through the general parser, which doesn't accept it #590
Reported (stale) behaviour vs. current (re-confirmed) behaviour: the original report (fb_ebebcacb3f29f3a5, v0.26.0) described test "name" { ... } blocks being silently skipped with Named test blocks not yet implemented, so a file where every test is skipped still prints All tests passed! and exits 0. That skip path is gone on current dev (v0.33.0-1-gdd68e0741) — named test blocks are now actually executed via internal/testing/executor.go's EvaluateNamedTestBodyExprs. But re-testing the reporter's exact repro on current HEAD surfaces a different, 100%-reproducible bug that supersedes the original report:
Repro (current HEAD, confirmed):
module skipped
export pure func add_one(n: int) -> int { n + 1 }
test "add_one increments" {
assert add_one(1) == 2
}
$ ailang test skipped.ail
✗ add_one increments
pipeline error: module loading error: failed to load ./_namedtest_body_....ail: parse errors:
PAR_NO_PREFIX_PARSE at _namedtest_body_....ail:7:3: unexpected token in expression: assert
...
1 tests: 0 passed, 1 failed, 0 skipped
exit=1
This fails regardless of whether the assertion is true or false — I confirmed both the true and the deliberately-false assertion from the original repro fail identically. Removing assert and using a plain boolean expression body works fine:
test "no assert, plain bool expr" {
add_one(1) == 2
}
passes cleanly (1 tests: 1 passed).
Root cause:assert <expr> is only a valid production inside the dedicated test-declaration parser (internal/parser/parser_test_decl.go, gated on p.curTokenIs(lexer.ASSERT) at the top of test-body parsing). It is not registered as a prefix-parselet for general expression/block parsing. EvaluateNamedTestBodyExprs (internal/testing/executor.go:184) extracts the parsed body ast.Exprs, serializes them back to source with PrintAILANGSource, wraps the result in { ... }, writes it to a temp file, and re-runs the general pipeline (pipeline.Run with pipeline.ModeEval) on it — so any body containing an AssertStmt round-trips to source that the general parser rejects outright.
Impact: every named test block (test "name" { ... }) whose body uses assert — the form shown in the language's own test examples/docs — currently cannot execute at all; it always errors out rather than passing or (previously) skipping. This is a regression relative to the skip behavior in the sense that a whole documented feature is now 100% broken, though it does fail loudly (exit 1) rather than silently reporting success, which is the correct direction for the original report's concern about CI gates.
Two further named-test skip reasons the original reporter hit, unverified on current HEAD (filing for visibility, not yet re-confirmed):
requires not satisfied by random input — a property whose precondition the generator rarely satisfies; non-deterministic and invisible in the pass count.
Suggested direction: either (a) make EvaluateNamedTestBodyExprs evaluate the parsed AST directly instead of print-and-reparse (avoids the round-trip entirely), or (b) register assert as a general-expression prefix parselet so the reprinted source is valid outside the test-decl context, or (c) have PrintAILANGSource lower AssertStmt to an equivalent general-syntax form (e.g. if not (cond) { panic(...) } else { () }) when printing outside a test-decl body.
Reported via public feedback MCP. Ticket: fb_ebebcacb3f29f3a5.
Original ailang_version: v0.26.0 (commit 3b52a24). Re-confirmed independently on v0.33.0-1-gdd68e0741 (commit dd68e07) with a fresh minimal repro — the specific failure mode differs from what was originally reported, but the underlying feature (named test blocks with assert) is currently unusable either way.
Reported (stale) behaviour vs. current (re-confirmed) behaviour: the original report (fb_ebebcacb3f29f3a5, v0.26.0) described
test "name" { ... }blocks being silently skipped withNamed test blocks not yet implemented, so a file where every test is skipped still printsAll tests passed!and exits 0. That skip path is gone on currentdev(v0.33.0-1-gdd68e0741) — named test blocks are now actually executed viainternal/testing/executor.go'sEvaluateNamedTestBodyExprs. But re-testing the reporter's exact repro on current HEAD surfaces a different, 100%-reproducible bug that supersedes the original report:Repro (current HEAD, confirmed):
This fails regardless of whether the assertion is true or false — I confirmed both the true and the deliberately-false assertion from the original repro fail identically. Removing
assertand using a plain boolean expression body works fine:passes cleanly (
1 tests: 1 passed).Root cause:
assert <expr>is only a valid production inside the dedicated test-declaration parser (internal/parser/parser_test_decl.go, gated onp.curTokenIs(lexer.ASSERT)at the top of test-body parsing). It is not registered as a prefix-parselet for general expression/block parsing.EvaluateNamedTestBodyExprs(internal/testing/executor.go:184) extracts the parsed bodyast.Exprs, serializes them back to source withPrintAILANGSource, wraps the result in{ ... }, writes it to a temp file, and re-runs the general pipeline (pipeline.Runwithpipeline.ModeEval) on it — so any body containing anAssertStmtround-trips to source that the general parser rejects outright.Impact: every named test block (
test "name" { ... }) whose body usesassert— the form shown in the language's own test examples/docs — currently cannot execute at all; it always errors out rather than passing or (previously) skipping. This is a regression relative to the skip behavior in the sense that a whole documented feature is now 100% broken, though it does fail loudly (exit 1) rather than silently reporting success, which is the correct direction for the original report's concern about CI gates.Two further named-test skip reasons the original reporter hit, unverified on current HEAD (filing for visibility, not yet re-confirmed):
no generator for parameter <name>: Option[string]/: <user ADT>— arequirescontract on a non-primitive parameter generates a property test the generator can't feed; the module still reports success with 0 tests actually run. Likely overlaps with already-open ailang test: property tests over ADT/record parameters SKIP silently with success:true — 'no generator for parameter' #517 (ailang test: property tests over ADT/record parameters SKIP silently with success:true).requires not satisfied by random input— a property whose precondition the generator rarely satisfies; non-deterministic and invisible in the pass count.Suggested direction: either (a) make
EvaluateNamedTestBodyExprsevaluate the parsed AST directly instead of print-and-reparse (avoids the round-trip entirely), or (b) registerassertas a general-expression prefix parselet so the reprinted source is valid outside the test-decl context, or (c) havePrintAILANGSourcelowerAssertStmtto an equivalent general-syntax form (e.g.if not (cond) { panic(...) } else { () }) when printing outside a test-decl body.Reported via public feedback MCP. Ticket: fb_ebebcacb3f29f3a5.
Original ailang_version: v0.26.0 (commit 3b52a24). Re-confirmed independently on v0.33.0-1-gdd68e0741 (commit dd68e07) with a fresh minimal repro — the specific failure mode differs from what was originally reported, but the underlying feature (named test blocks with
assert) is currently unusable either way.