Skip to content
A program that checks itself

A program that checks itself

A test is a program whose exit status says whether your code does what you meant. It needs no framework.

fn round_score(first_die: int, second_die: int) -> int {
  let sum = first_die + second_die;
  if first_die == second_die { sum * 2 } else { sum }
}

fn failure_of(rule: bytes, holds: bool) -> int {
  if holds { 0 } else {
    print(concat3("FAIL ", rule, "\n"));
    1
  }
}

fn main() -> int {
  failure_of("a double scores twice the sum", round_score(6, 6) == 24)
    + failure_of("any other roll scores the sum", round_score(2, 5) == 7)
}
bootstrap/qdx run std/*.qdx check.qdx
echo $?
0

Each check is named after the rule it protects. A rule that does not hold is printed, and the exit status is the number of failures.

Keeping the code and its checks apart

Put round_score in its own file and give the compiler a different last file for each purpose: the one with the real main to build the program, and the one with the checking main to test it.

bootstrap/qdx run std/*.qdx dice.qdx game.qdx
bootstrap/qdx run std/*.qdx dice.qdx dice_check.qdx

Only one of the files given may declare main.

Checking that a program stops

To test that a program stops with the right message, run it as another process. run_program starts a program, sends its output and errors to files, and returns its exit status. A test can then read those files and compare. The repository’s own build program, build.qdx, tests the compiler this way.