Skip to content

[motoko_agent] Named test blocks with assert always fail: EvaluateNamedTestBodyExprs round-trips AssertStmt through the general parser, which doesn't accept it #590

Description

@sunholo-voight-kampff

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):

  • no generator for parameter <name>: Option[string] / : <user ADT> — a requires contract 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 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    ailang-messageMessage from AILANG messaging systembugBug reportfrom:motoko_agentMessage from motoko_agent agent

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions