Skip to content

Releases

mtest 0.9.0

Choose a tag to compare

@github-actions github-actions released this 14 Nov 19:30
6b05592
  • A selection excludes, and selects where declared (SPEC-017 P4.3). In MTEST_SELECT, a line
    !<id> leaves out that case and the cases it declares, and a line ?<id> selects a case where
    it is declared and is not missing where it is not; a selection of exclusions alone runs every
    case but those. The program event states "selection": ["except", "optional"], so a runner
    uses them only with a program that understands them. A runner divides a long case among
    processes by the cases it declares, which a list does not name (P3.4) and its history does: each
    process but one selects (?) the measured cases it was given, so a case since removed fails
    nothing, and the last selects the case without them (!), so a case no run measured runs once.
    Measured on mcpp's CI: two suites of 1373 s and 1375 s ran their cases one after another, and
    the longest case of either takes 564 s.
  • CI builds and tests with mcpp 2026.11.14.1. 2026.11.10.1 took an emsdk from a package store
    restored without the loader its compiler names as present (provides no std module source);
    2026.11.13.1 and later restore that loader's link.

mtest 0.8.5

Choose a tag to compare

@github-actions github-actions released this 14 Nov 06:47
f7bacc4
  • An output cut at its limit says so (#22). e2e::run keeps at most 1 MiB
    of a program's standard error (256 MiB of its standard output), and an outcome cut there looked
    complete: a case that searched it could not tell an absent line from a dropped one. The outcome
    now carries out_truncated, err_truncated and held_open as mcpplibs.os reports them; a
    command states its own limits (out_limit, err_limit, the former values by default); and a
    failed succeeded or exited names the output that was cut and its size. Nothing changes for an
    output within its limit.
  • CI caches the package store with its ABI directory. The store alone, restored, held the emsdk
    compiler without the loader its interpreter names, and the Web row of 0.8.4's release failed with
    "provides no std module source"; a store cached before this is not restored.

mtest 0.8.4

Choose a tag to compare

@github-actions github-actions released this 14 Nov 06:38
b24dec4
  • A test program links where no program can be started (the Web). A capability that asks for a
    command (probe::command) ran it through mcpplibs.os's process functions, which every test
    program could reach; a target whose system provides none of them -- wasm32-emscripten, by
    openkal's rule that an absent capability is absent at link -- then linked no test program at all
    (undefined symbol: kal_process_wait, ...), since 0.8.0. The target answers at compile time now:
    asked for a command there, the capability is absent ("this system starts no programs"), and
    nothing of starting one is in the program. Nothing changes where programs are started.

mtest 0.8.3

Choose a tag to compare

@github-actions github-actions released this 14 Nov 00:20
b540457
  • Each call measured by itself, as a loop (bench::laps). bench::each takes the call as a
    function; a body that keeps its state in the function it runs in writes the same measurement as
    a loop: bench::laps run{"draw"}; while (run.next()) { ... }. The time from one next to the
    following one is a call's, run is the call's lap (pause, resume, items, part, time,
    value, say, last), and when next returns false the metrics have been reported as each
    reports them; result() is where the calls lay. each is that loop around its function: one
    way of measuring, in two forms.
  • Run alone, a program shows what it measured. A measurement's line in the program's output --
    draw: 2.100 ms (p95 5.300 ms, p99 7.700 ms, max 8.400 ms; mean 2.900 ms; 139 calls; 0 over 8.333 ms), then a line for each part and quantity -- where no runner keeps the run's record.
    Under a runner nothing is added to the case's output: the record has the metrics.
  • What the lap keeps is not the call's. The allocations part, time and value make to keep
    what a call says are left out of the call's count: a frame that allocates nothing reports none
    while it states its parts (lib/tests/allocations.cpp, a program that replaces operator new).
  • A program run alone selects as the runner does. Its arguments name cases by identifier, by
    the name they lie under (suite/group, which was run and then reported as no case), or by a
    pattern with * (the cases it matches, as mcpp test --case takes one); a selection no
    case answers fails the run. The interface said "by prefix" and the program took whole
    identifiers: the statement and the behaviour are now one (lib/tests/alone.cpp).
  • Additive: each measures and reports as it did.

mtest 0.8.2

Choose a tag to compare

@github-actions github-actions released this 13 Nov 23:28
b7584e0
  • 0.8.1 as released: its tag was made and its release was not (a test of bench::each held that
    the call it had slowed was the slowest of all, which a loaded machine does not grant). The tests
    now hold each stated call to what that call said, whichever calls the machine slowed. The library
    is 0.8.1's.

mtest 0.8.0

Choose a tag to compare

@github-actions github-actions released this 13 Nov 19:37
999c16b
  • Where a case runs is stated by the case (only{}, except{}). A case or a suite names the
    platforms and architectures of mcpplibs.os it runs on (only{platform::windows},
    only{platform::linux, architecture::x86_64}) or not (except{platform::macos}); a suite's and
    its case's narrow together. Elsewhere it is skipped with one reason, only on windows (this host: linux x86_64). The Bash adapter (--only, --except), the Python adapter (only=,
    excepted=) and the C ABI (mtest_case_only, mtest_case_except) state the same; the engine
    skips a listed case outside its places without starting it.
  • Code for one platform is selected when it is compiled. mtest re-exports mcpplibs.os's
    platform, architecture, can_run_on, host and on<P>: on<platform::windows>([&](auto) { ... }) is a body that a build for another platform discards, and an ok image decides when it is
    loaded.
  • What a machine can do is declared in code and answered by the program (capability). The
    tests of [capabilities] -- a system, an architecture, programs on PATH, a file a glob matches, a
    command, environment values, other capabilities that must or must not hold -- and a function for
    what they cannot state, answered once per process. A capability is an attribute
    ("links"_test[gcc], with the tag requires:gcc); a case whose machine lacks it is skipped,
    missing capability: gcc (no g++ on PATH), under any runner (mtest, mcpp test, the program
    alone). The engine takes the program's answers: a word the program answers needs no
    [capabilities] entry, and the run records it.
  • The listing says why a case is skipped, and where it runs (P3.3): a case event may carry
    reason (with expect: skip), only, except and capabilities; the schema states them. The
    conformance suite checks them of every level-3 implementation (placed).
  • mtest ci coverage checks each case on its places: a case that states only must pass on
    each of its places that a collected run covered, and some run must have been on one -- what
    [ci.coverage] hosts states of a program, stated by the case.
  • Additive: a program, a listing and a configuration that state none of these mean what they did.

mtest 0.7.2

Choose a tag to compare

@github-actions github-actions released this 13 Nov 12:30
9880d99
  • Each call measured by itself (bench::each, mcpplibs.mtest.bench). bench::measure times
    batches and states what one call costs on the whole; each times every call, for work whose
    calls differ and whose slow ones are the point -- a frame, a request, a step of a simulation. It
    reports where the calls lie as metrics a bound can name: the median as name, and name.p95,
    name.p99, name.max, name.mean (at_most{"draw.p95", 0.016}). The body may take a
    bench::lap: pause() and resume() leave out what is not the call's (preparing the next
    input), items(n) states what the call worked through and adds name.per_item. The samples are
    not stated with these metrics: the verdict on samples that spread is for a measurement meant to
    be one number. bench::distribute and bench::percentile are the same arithmetic on samples a
    test has already. Additive; no event and no clause changed.

mtest 0.7.1

Choose a tag to compare

@github-actions github-actions released this 13 Nov 06:02
9ea5c07
  • mcpplibs.mtest.e2e, .bench and .cts are public modules of the library. Each re-exports
    mcpplibs.mtest, so the lib root cannot re-export them, and a program that imported one was told
    that it was not public and would fail against the packed library (mcpp SPEC-008). Each is now a
    feature, on by default (e2e, bench, cts), which is how mcpp counts a module beside the root
    as public; a program's imports and its manifest are unchanged.

mtest 0.7.0

Choose a tag to compare

@github-actions github-actions released this 13 Nov 04:54
da47f84
  • What a machine can do is declared once, and a requirement no machine answers is an error
    ([capabilities]). Each word states its tests -- a system, an architecture, a program on PATH, a
    command that succeeds, a file a glob matches, an environment value, other words that must or must
    not hold -- and a case that requires a word (requires:<word>, from # requires: lines through
    tags_from) that this machine lacks is skipped with the reason missing capability: <word> (<the test that failed>). A word no entry declares stops the run, naming the program. mtest capabilities prints the answers; each run records its host (MTEST_HOST, else the system) and
    its answers. Before, a project probed in a script of its own and kept a list of known words beside
    it.
  • Whether every program ran somewhere is a command (mtest ci coverage). Over the runs of all
    the jobs of a CI run, collected into one store, each program is ran, unaffected, excused or
    owed by the tables [ci.coverage] names, or uncovered, which fails; an entry that outlived its
    reason fails too, and a program that must pass on given hosts is checked on each. The capability
    words no job's machine provided are listed.
  • A selection is divided among CI's hosts before any builds (mtest ci plan): for each host, the
    cases its recorded capabilities admit, their measured time on that host, and the number of shards
    that fit [ci.plan] shard; --format github writes a job matrix to GITHUB_OUTPUT. A host with
    no history counts every case.
  • An interrupted run resumes (mtest run --resume RUN): the cases RUN judged are carried into
    the new run and are not run again.
  • A program under test is judged with matchers that carry the session
    (mcpplibs.mtest.e2e): succeeded, exited, contains, matches; an outcome carries the
    command as a POSIX shell line (shell_line), and a failed matcher reports it with the tails of
    both outputs.
  • An interactive program is driven by expecting and sending (e2e::session: start, expect,
    saw, send, send_line, finish, transcript). Both streams travel in one pipe; no terminal
    is involved, so the same session runs on every system. A serial console of an emulator is driven
    this way (measured: QEMU's serial console delivers the same bytes over a pipe as over a pseudo
    terminal).

mtest 0.6.3

Choose a tag to compare

@github-actions github-actions released this 12 Nov 18:04
e941ab7
  • A conformance suite is run against a subject, which may lack what a specification leaves
    optional
    (mcpplibs.mtest.cts: against, subject, needs). cts::against({.name, .has, .required}, declare) runs the cases declare declares as the parts of a case named after the
    implementation, tagged subject:<name>, so one program runs a suite against several. A case that
    states cts::needs{"capability"} and whose subject lacks it is not run: skip, with the reason
    unsupported: <capability> -- from what the subject states it can do, never a pass. A capability
    the run requires and the subject lacks fails once, as the case requires <capability>. Before, a
    suite wrote this in each body (if (!has(x)) skip(...)), where a missing capability and a
    machine's reason read alike, and a required one could only be skipped. The protocol is unchanged:
    the statuses and events are the ones it has.