Testing
Policy: No Crate Is Ignored
Every crate must be tested when its code changes. No crate is silently skipped. Crates that can't run in the default test suite get their own dedicated CI jobs on the appropriate runner.
CI Runners (Azure Self-Hosted)
All CI runs on self-hosted Azure runners managed via Terraform (infra/terraform/github-runner/).
General pool (VMSS, auto-scaling):
Standard_D2s_v5(2 vCPU, 8 GB RAM, 30 GB disk)- Labels:
self-hosted, linux, x64, azure - Auto-scales from 1 to 4 instances based on CPU utilization
- Used by:
detect,check,docker, release Linux builds
Heavy runner (single VM):
Standard_D4s_v5(4 vCPU, 16 GB RAM, 64 GB disk)- Labels:
self-hosted, linux, x64, azure, heavy - Used by:
check(full suite),kernel-tests,filter-tests - Also accepts general CI jobs when pool instances are busy
Runner registration uses a GitHub PAT stored in Azure Key Vault. VMSS instances self-register on boot.
CI Test Suite
CI runs on every push to main/dev and on pull requests. The workflow (ci.yaml) uses affected-crate detection (scripts/affected-crates.sh) to only test crates whose source files — or whose dependencies — changed in the current diff. Workspace-wide files (Cargo.toml, Cargo.lock, patches/, ci.yaml) trigger a full workspace run.
Jobs
| Job | Runner | Runs when | What it tests |
|---|---|---|---|
check | general pool | Any crate changed | fmt, clippy, workspace tests (excluding heavy crates) |
kernel-tests | heavy | spt-kernel changed or full release | cargo test -p spt-kernel |
filter-tests | heavy | spt-filter changed or full release | cargo test -p spt-filter with 16 MB stack |
Default test commands
# Unit tests (quick — default for pushes/PRs, run on general pool)
cargo test --workspace --lib --exclude spt-filter --exclude spt-kernel -- --test-threads=2
# Full suite (releases, run on general pool)
cargo test --workspace --exclude spt-filter --exclude spt-kernel -- --test-threads=2Heavy Crates
These crates are tested in dedicated CI jobs on the heavy runner because they have special requirements.
spt-filter
Problem: rustc hits a stack overflow (SIGSEGV) during trait resolution. The crate uses deeply recursive type-level computation (recursion_limit = 4096) that exceeds rustc's default 8 MB thread stack.
CI behavior: The filter-tests job runs on the heavy runner with RUST_MIN_STACK=16777216 (16 MB) when spt-filter or its dependencies change, and always during full release suites.
# Test spt-filter locally (16 MB stack)
RUST_MIN_STACK=16777216 cargo test -p spt-filter --lib -- --test-threads=1
# Or use the helper script
bash scripts/test-heavy-crates.sh spt-filterspt-kernel
Problem: KernelBuilder::build() tries Docker first, which downloads Linux kernel source and compiles a bzImage inside a container (~20 min).
CI behavior: The kernel-tests job runs on the heavy runner (4 vCPU, 64 GB disk) when spt-kernel code changes, and always during full release suites. 40-minute timeout.
# Test spt-kernel locally
cargo test -p spt-kernel --lib -- --test-threads=1
# Skip the Docker kernel build (uses builtin minimal stub)
NO_DOCKER=1 bash scripts/test-heavy-crates.sh spt-kernelTesting All Heavy Crates Locally
# Run both spt-filter and spt-kernel tests
bash scripts/test-heavy-crates.sh
# Skip Docker for spt-kernel
NO_DOCKER=1 bash scripts/test-heavy-crates.shAdding New Heavy Crates
If a new crate needs a dedicated CI job:
- Add it to
HEAVY_CRATESinscripts/affected-crates.sh - Add a
<name>_changedoutput flag in the same script - Add
--exclude <crate>to the default test commands inci.yaml - Add a dedicated job in
ci.yamltargeting[self-hosted, linux, azure, heavy] - Add a test function to
scripts/test-heavy-crates.sh - Document the reason here