Skip to main content

Module part

Module part 

Source
Expand description

The parts of the tests of the Gate.

§Design

The Gate on GitHub runs its checks as jobs at the same time (01M513W2K3HNRWPQTQNBQPT8MZ). The tests take the most time, so they run in N parts, each part in a job of its own. just test-part I/N runs hygiene test-part I/N (01M513W2NSE303E6XAM18BW7T6):

  1. cargo test --workspace -- --list --format terse builds each test binary and lists the name of each test, also of each doc test.
  2. names reads the names, and Part::plan keeps each name of a test that is not a doc test whose fnv1a hash modulo N is I − 1.
  3. cargo test --workspace --tests --no-fail-fast -- --exact NAME... runs these tests.
  4. Part 1 also runs each doc test: cargo test --workspace --doc --no-fail-fast.

With --no-fail-fast, a failed test binary does not stop the others, so the log of a part shows each failed test.

A doc test has a name with spaces (is_doc), for example crates/x/src/lib.rs - ulid (line 57). rustdoc splits each filter at its spaces, so no filter names one doc test. The doc tests take seconds, so they run as one group.

A name is in one part only, so the N parts together run each test. A name that two test binaries share runs in each of them, as in a full run. The hash of a name does not change with the other names, so a new test moves no other test to another part.

flowchart LR
    L["cargo test -- --list:<br/>each name"] --> D{"a doc test?"}
    D -- yes --> P1["part 1: cargo test --doc"]
    D -- no --> H{"fnv1a(name) mod N"}
    H -- "I − 1" --> R["cargo test --tests -- --exact<br/>the names of part I"]
    H -- "another value" --> S["the job of another part"]
use hygiene::part::{names, Part};

let list = "cli::help: test\n\
            cli::version: test\n\
            src/lib.rs - ulid (line 57): test\n\
            bench::fast: benchmark\n";
let all = names(list);
assert_eq!(all, ["cli::help", "cli::version", "src/lib.rs - ulid (line 57)"]);

let plans: Vec<_> = ["1/2", "2/2"]
    .iter()
    .map(|p| p.parse::<Part>().unwrap().plan(&all))
    .collect();
let mut each: Vec<&str> = plans.iter().flat_map(|p| p.tests.clone()).collect();
each.sort();
assert_eq!(each, ["cli::help", "cli::version"]);
assert_eq!((plans[0].doc, plans[1].doc), (1, 0));
assert!("3/2".parse::<Part>().is_err());

Structs§

Part
Part index of count parts of the tests, as I/N gives it.
Plan
What one part runs.

Functions§

fnv1a
The 64-bit FNV-1a hash of text. It is the same on each machine and with each Rust, so each job of the Gate gives a name the same part.
is_doc
True when name is the name of a doc test: it has a space, as in crates/x/src/lib.rs - ulid (line 57). The name of each other test is a Rust path.
names
The test names of the output of cargo test -- --list --format terse: each line NAME: test, sorted, each name one time. A benchmark is not a test.
summary
The line that just test-part prints before it runs the tests of plan, of the tests names.