The default test runner works fine, but it is notably slower and less featureful than nextest.
Fortunately, nextest ships with the nix-shell, so assuming you have already followed the instructions in the README.md, you should be able to run
cargo nextest runeven if you have not installed nextest on your system.
[!WARNING] nextest profiles are not the same thing as cargo profiles. If you want to select a cargo profile when running nextest, use, for example
cargo nextest run --cargo-profile=releaseThe nix-shell also ships with cargo llvm-cov for collecting code coverage information. Assuming you have followed the README.md, you should be able to run
just coverageto get code coverage information.
Code coverage reports from CI are uploaded to our codecov page.
If you wish to study coverage data locally, you can run
just coverage
cd ./target/nextest/coverage/html
python3 -m http.serverAnd then open a web-browser to http://localhost:8000 to view coverage data.
The dataplane project makes fairly extensive use of fuzz testing. We use the bolero crate for our fuzz tests.
Running the test suite via cargo test or cargo nextest run will run the fuzz tests.
- The tests (even the fuzz tests) are only run briefly.
- Coverage information and sanitizers are not enabled.
- A full fuzzing engine is not set up, so evolutionary feedback is not provided when the tests are run this way.
Note
A just fuzz recipe for running full fuzz tests with libfuzzer or afl is planned for a future PR.
miri is an interpreter for Rust's MIR that catches undefined behavior, data races, alignment errors,
provenance violations, and other memory-model issues that ordinary tests can't see. The repo ships a
just miri::test recipe that runs the workspace under miri with a curated set of MIRIFLAGS.
# the whole workspace (skips packages flagged `miri = false`; see below)
just miri::test
# a specific test
just miri::test --package=dataplane-flow-entry flow_table::table::tests::test_flow_table_timeout
# fan out across more seeds for a deeper search
just miri::seeds=64 miri::testjust miri on its own runs just miri::test (the recipe is marked [default]).
The recipe drops into a nightly toolchain with the miri component, sets up MIRIFLAGS (many-seeds
sweep, preemption, weak compare-exchange failures, alignment checks, provenance), and runs
cargo miri nextest run for the configured CPU target. The default target is
powerpc64-unknown-linux-gnu -- weak memory model and big-endian, so the same run surfaces both
concurrency and endianness bugs.
Override defaults with just miri::<name>=<value> before the recipe name:
cpu(defaultpowerpc64) -- target architecture; the recipe builds for<cpu>-unknown-linux-gnu.seeds(default1) -- number of seeds to fan out via-Zmiri-many-seeds.schedule_seed(default a random digit) -- starting seed for that fan-out.provenance(defaultpermissive) --permissiveorstrictprovenance model.stacked_borrow_check(defaultdisabled) -- set to anything else to enable stacked borrows.preemption_rate(default0.10) -- probability the scheduler preempts a thread.weak_failure_rate(default0.15) -- probabilitycompare_exchange_weakspuriously fails.randomize_struct_layout(defaultenabled) -- set todisabledto keep Rust's default layout.layout_seed(default derived fromgit rev-parse HEAD) -- set torandomfor a fresh seed each run.
Some crates can't run under miri at all -- typically because they call into FFI, hardware, or DPDK
that the interpreter does not model. They're listed under [workspace.metadata.package] in the root
Cargo.toml with miri = false. The runner expands those entries into --exclude= flags
automatically when invoked without an explicit package selector.