Browse the docs

silk.testing.exchange.

The binary plan and receipt formats that let silk test control the test runner.

When to use#

silk.testing.runner uses this module. The host (the silk test driver) writes a plan file, and the runner writes a receipt file. You do not call it from normal code.

Details#

A plan starts with the magic SLKTPLN1, a version (1), a mode, and a 32-byte nonce. All integers are little-endian. There are two modes:

  • Per-test mode (1). The plan has the count of discovered tests, then one catalog entry per test: ordinal, declaration name, execution identity, and action (0 run, 1 cached). The receipt has one result per selected test. Its disposition is 0 cached, 1 passed, or 2 failed.

  • Uncached mode (2). The plan is exactly 256 bytes. It holds a SHA-256 digest of the catalog (see updateCatalogDigest) and the test count, then zero padding. The receipt is also padded to 256 bytes.

A receipt starts with the magic SLKTRCP1, the version, the mode, the nonce of the plan, and the SHA-256 of the complete plan. It ends with the counts and the status.

A progress record lets the host continue a run after a test traps. It is exactly 48 bytes: the magic SLKTPRG1, the ordinal of the test that is starting, then the cached, executed, passed and failed counts before that test. The runner writes one before each test body runs, so after an abnormal exit the record names the test that stopped the process.

Gotchas#

  • A Plan does not stop at the first error. After a failure it reads as empty, and failed stays true. Check failed or the bool results before a test body runs.

  • Test output goes to the inherited stdout and stderr. Only the receipt decides the result.

Import as TestExchange with import silk.testing.exchange as TestExchange.

Public declarations: 21.

Plan#

silk
pub struct Plan<'a>

A cursor over one borrowed plan file that the silk test driver wrote.

Gotchas#

It does not stop at the first error. After a failure it reads as empty, and failed stays true. Check failed or the bool results before a test body runs.

Entry#

silk
pub struct Entry<'a>

One borrowed per-test catalog entry.

Progress#

silk
pub struct Progress

A run's position when a test started: the catalog ordinal of that test and the counts before it.

Details#

The runner writes it with progressRecord before each test body runs. After the process stops abnormally, readProgress reads it back, and a new runner continues after that test.

Field ordinal#

silk
pub ordinal: u64

The catalog ordinal of the test that was starting.

Field cachedCount#

silk
pub cachedCount: u64

The cached passes before that test.

Field executed#

silk
pub executed: u64

The tests executed before that test.

Field passed#

silk
pub passed: u64

The tests that passed before that test, cached passes included.

Field failedCount#

silk
pub failedCount: u64

The tests that failed before that test.

Receipt#

silk
pub struct Receipt

An owned receipt under construction. Start it with beginReceipt.

openPlan#

silk
pub fn openPlan<'a>(bytes: &'a [u8]) -> Plan<'a>

Opens a plan and checks its magic, version, mode and nonce framing.

If a check fails, the returned plan is already rejected: it reads as empty, and failed returns true.

isPerTest#

silk
pub fn isPerTest(plan: &Plan) -> bool

Returns true for a per-test plan (mode 1).

isUncached#

silk
pub fn isUncached(plan: &Plan) -> bool

Returns true for an uncached plan of 256 bytes (mode 2).

failed#

silk
pub fn failed(plan: &Plan) -> bool

Returns true after a check on the plan fails. It does not become false again.

beginPerTest#

silk
pub fn beginPerTest(plan: &mut Plan, expectedDiscovered: u64) -> bool

Reads the test count of a per-test plan, and checks it and the size bound of the file.

The count must equal expectedDiscovered. Call it before any test body runs.

readEntry#

silk
pub fn readEntry<'a>(
  plan: &mut Plan<'a>,
  expectedOrdinal: u64,
  expectedDeclaration: &[u8],
) -> Entry<'a>

Reads and checks the next catalog entry.

The ordinal and declaration name must match the expected values, and a cached entry must have an execution identity. For an uncached plan, it returns uncachedEntry and reads nothing.

cached#

silk
pub fn cached(entry: &Entry) -> bool

Returns true for a valid entry that the host marked as a cache hit.

executionIdentity#

silk
pub fn executionIdentity<'a>(entry: &Entry<'a>) -> &'a [u8]

Borrows the opaque execution identity of an entry.

uncachedEntry#

silk
pub fn uncachedEntry<'a>(bytes: &'a [u8]) -> Entry<'a>

Returns the empty entry that is not cached, for uncached mode.

finishPerTest#

silk
pub fn finishPerTest(plan: &mut Plan) -> bool

Checks that a per-test plan ends exactly after the catalog.

validateUncached#

silk
pub fn validateUncached(
  plan: &mut Plan,
  expectedCatalogDigest: &[u8],
  expectedDiscovered: u64,
) -> bool

Checks an uncached plan: exactly 256 bytes, the catalog digest, the test count, and zero padding.

updateCatalogDigest#

silk
pub fn updateCatalogDigest(state: &mut Sha256, ordinal: u64, identity: &[u8]) -> ()

Adds one catalog identity to the digest of an uncached plan.

It hashes the ordinal and the identity length as 8-byte little-endian values, then the identity.

beginReceipt#

silk
pub effect fn beginReceipt(
  plan: &[u8],
  perTest: bool,
  selected: u64,
) -> Receipt ! OutOfMemoryError ? &mut Allocator

Starts a receipt for plan. It copies the nonce and hashes the complete plan.

selected is the number of results that follow in per-test mode.

appendResult#

silk
pub effect fn appendResult(
  receipt: &mut Receipt,
  ordinal: u64,
  declaration: &[u8],
  execution: &[u8],
  disposition: u8,
) -> () ! OutOfMemoryError ? &mut Allocator

Appends one per-test result. Append results in ordinal order.

Gotchas#

It traps if the receipt is not per-test, or if disposition is more than 2.

finishReceipt#

silk
pub effect fn finishReceipt(
  receipt: Receipt,
  discovered: u64,
  selected: u64,
  cachedCount: u64,
  executed: u64,
  passed: u64,
  failedCount: u64,
  status: u32,
) -> Bytes ! OutOfMemoryError ? &mut Allocator

Appends the counts and the status, and returns the receipt bytes.

In uncached mode the receipt is padded to exactly 256 bytes.

progressRecord#

silk
pub effect fn progressRecord(progress: &Progress) -> Bytes ! OutOfMemoryError ? &mut Allocator

Returns the 48-byte progress record of progress.

Details#

The record is the magic SLKTPRG1, then the ordinal and the four counts as 8-byte little-endian integers.

readProgress#

silk
pub fn readProgress(bytes: &[u8]) -> Option<Progress>

Reads a progress record that progressRecord wrote.

Details#

It returns None unless bytes is exactly one record with the SLKTPRG1 magic.

Category: Testing.

Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2.

View the source of this page