# Tests
tracexec currently contains two kinds of tests:
- the normal tests that are executed when running `cargo test --workspace`,
- tests requiring root that are excluded by default.
## Running the Tests
To run the normal tests, use
```bash
cargo test --workspace
```
`sudo` is needed to run the tests that requires root:
```bash
CARGO_TARGET_<TARGET_TRIPLE>_RUNNER='sudo -E' cargo test --workspace -- --ignored
```
For example, if you are testing on a x86_64 linux machine, use
```bash
CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER='sudo -E' cargo test --workspace -- --ignored
```
## eBPF Verifier Complexity
Verifier complexity collection is available as an optional UKCI-style Nix runner.
It boots the same UKCI kernels in QEMU, loads tracexec's eBPF programs with
verifier stats enabled, and writes one JSON file per kernel/LLVM combination:
```bash
nix run .#ukci-complexity
```
By default, results are written to `verifier-complexity/`.
Set `UKCI_COMPLEXITY_OUT_DIR` to use a different output directory.
This runner is intentionally separate from `ukci` and is not part of the
required UKCI test pass.
For pull requests, a dedicated Nix workflow runs this collector on x86_64 when
the compiled kernel-space eBPF sources or x86 BTF headers change. It uploads the
raw JSON and rendered plots as Actions artifacts and updates a folded summary
comment as soon as the complexity run finishes. The reporter also stores the
PNG plots on ImgBB without an expiration and embeds them in the comment so they
remain available after the artifacts expire. Configure the reporter with an
`IMGBB_API_KEY` repository secret.
To plot the collected results from the repository root:
```bash
nix run .#plot-verifier-complexity -- verifier-complexity
```
The plotting script writes charts and a summary under
`verifier-complexity-plots/` by default. Use `-o` to choose another output
directory, and `--log-scale` when comparing runs with large differences between
the smallest and largest verifier counts.
## Test Coverage
Most of the time you do not need to calculate the test coverage by yourself because we are tracking
the test coverage continuously with [CodeCov](https://about.codecov.io/).
You will see the patch coverage and code coverage diff in a comment by CodeCov once
you opened a pull request and all the tests pass.
Continue to read this section if you want to calculate the test coverage by yourself.
First, [install `cargo-llvm-cov`](https://github.com/taiki-e/cargo-llvm-cov?tab=readme-ov-file#installation)
if you haven't already installed.
Then run the normal tests with coverage instrumentation to generate a coverage report named `lcov.info`:
```bash
cargo llvm-cov --all-features --workspace --lcov --output-path lcov.info
```
After that, run the root-only tests with coverage instrumentation.
We use [`bpfcov-rs`](https://github.com/kxxt/bpfcov-rs) to collect coverage of eBPF code that executes in kernel-space.
```bash
export CARGO_TARGET_<TARGET_TRIPLE>_RUNNER='sudo -E env TRACEXEC_BPFCOV_OUTDIR=/tmp/bpfcov'
# Replace <TARGET_TRIPLE> with your rust target triple in uppercase and replace dash with underscore.
# For example: export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER='sudo -E env TRACEXEC_BPFCOV_OUTDIR=/tmp/bpfcov'
cargo llvm-cov --all-features --workspace --lcov \
--output-path root-lcov.info -- --ignored
```
After the tests finish,
- a user-space coverage report named `root-lcov.info` is produced,
- and kernel-space test coverage reports for each eBPF test is located
in `/tmp/bpfcov`.
Then, combine all the kernel-space test coverage reports:
```bash
find /tmp/bpfcov -name '*.lcov' -print0 \
| xargs -0 -I{} echo -a {} \
| xargs lcov -o ebpf.lcov
```
And finally combine all three coverage reports into one:
```bash
lcov -a ebpf.lcov -a lcov.info -a root-lcov.info -o tracexec.info
```
Optionally you can generate an HTML report with:
```bash
genhtml tracexec.info --output-directory cov-out
```
## Add a Test
Feel free to add new tests to cover new/modified code.
When adding a test that requires root, please mark it with
```rust
#[ignore = "root"]
```
When the test loads eBPF program, please make sure that it runs sequentially
with respect to other eBPF tests by marking it with:
```rust
#[rstest]
#[file_serial(bpf)]
```
The outer `rstest` attribute is a workaround for getting the real test name.