High-performance cache policies and supporting data structures.
This document describes how fuzz testing is integrated into the CacheKit CI/CD pipeline.
CacheKit uses comprehensive fuzz testing with 27 fuzz targets covering 9 core data structures. Fuzzing runs automatically in CI/CD to catch bugs, edge cases, and security issues.
| Data Structure | Fuzz Targets | Coverage |
|---|---|---|
| ClockRing | 3 | Arbitrary ops, insert stress, eviction patterns |
| FixedHistory | 3 | Arbitrary ops, record stress, property tests |
| FrequencyBuckets | 3 | Arbitrary ops, stress, property tests |
| GhostList | 3 | Arbitrary ops, LRU stress, property tests |
| KeyInterner | 3 | Arbitrary ops, stress, property tests |
| IntrusiveList | 3 | Arbitrary ops, stress, property tests |
| LazyMinHeap | 3 | Arbitrary ops, stress, property tests |
| ShardSelector | 3 | Arbitrary ops, distribution, property tests |
| SlotArena | 3 | Arbitrary ops, stress, property tests |
| Total | 27 | All core data structures |
Zero Configuration Required! 🎉
The CI/CD pipeline automatically discovers all fuzz targets using cargo fuzz list. When you add a new fuzz target to fuzz/fuzz_targets/ and register it in fuzz/Cargo.toml, the CI/CD pipeline will automatically:
No workflow file updates needed!
For best CI integration, follow this naming convention:
<module>_arbitrary_ops.rs - Random operation sequences (used in PR smoke tests)<module>_stress.rs - Heavy load testing<module>_property_tests.rs - Specific invariant testingTargets ending in _arbitrary_ops are automatically used for PR smoke tests as they provide the best general-purpose testing.
.github/workflows/ci.yml)When: Every pull request
Duration: ~60 seconds per _arbitrary_ops target
Purpose: Catch obvious bugs early before merging
Automatically discovers and runs all _arbitrary_ops targets:
# Automatic discovery
TARGETS=$(cargo fuzz list | grep '_arbitrary_ops$')
# Run each with different seed for reproducibility
for target in $TARGETS; do
cargo fuzz run "$target" -- -max_total_time=60 -seed=$seed
done
What it catches:
.github/workflows/fuzz.yml)When:
Duration: 1 hour per target by default (configurable) Purpose: Deep fuzzing to find subtle bugs
Strategy:
cargo fuzz listfail-fast: false)How Discovery Works:
discover-targets:
steps:
- name: List fuzz targets
run: |
cd fuzz
TARGETS=$(cargo fuzz list | jq -R -s -c 'split("\n") | map(select(length > 0))')
echo "targets=$TARGETS" >> $GITHUB_OUTPUT
fuzz-continuous:
needs: discover-targets
strategy:
matrix:
target: $
Features:
Fuzzing corpora (interesting test inputs) are preserved across runs:
- name: Restore corpus
uses: actions/cache@v4
with:
path: fuzz/corpus/$
key: fuzz-corpus-$-$
restore-keys: |
fuzz-corpus-$-
This ensures:
When crashes are detected:
name: fuzz-crashes-$-$
path: fuzz/artifacts/$/
retention-days: 90
bug, fuzzing, security labelsFor nightly runs, coverage is generated for representative targets:
Run all smoke tests (60 seconds each):
cd fuzz
./run_smoke_tests.sh
Or manually:
cd fuzz
cargo fuzz run clock_ring_arbitrary_ops -- -max_total_time=60 -seed=1
cargo fuzz run fixed_history_arbitrary_ops -- -max_total_time=60 -seed=2
# ... etc
Run a single target for extended duration:
cd fuzz
cargo fuzz run clock_ring_arbitrary_ops -- -max_total_time=3600
Run all targets (from fuzz/README.md):
cd fuzz
for target in $(cargo fuzz list); do
echo "Fuzzing $target..."
cargo fuzz run $target -- -max_total_time=300 -jobs=4
done
If CI finds a crash:
cd fuzz
cargo fuzz run <target> fuzz/artifacts/<target>/<crash-file>
RUST_BACKTRACE=full cargo fuzz run <target> <crash-file>
Check the following regularly:
[FUZZ] prefix and fuzzing labelPeriodically minimize corpora to remove redundant inputs:
cd fuzz
for target in $(cargo fuzz list); do
cargo fuzz cmin $target
done
This is automatically done in CI after each run.
When adding new data structures or major features:
fuzz/fuzz_targets/:
// fuzz/fuzz_targets/my_module_arbitrary_ops.rs
#![no_main]
use libfuzzer_sys::fuzz_target;
// ... implementation
fuzz/Cargo.toml:
[[bin]]
name = "my_module_arbitrary_ops"
path = "fuzz_targets/my_module_arbitrary_ops.rs"
test = false
doc = false
fuzz/README.md (optional but recommended)That’s it! ✅ The CI/CD pipeline will automatically discover and run your new target.
Naming Tips:
_arbitrary_ops to include in PR smoke tests_stress or _property_tests for specialized testing (runs in nightly only)<module>_<test_type> for claritycd fuzz && ./run_smoke_tests.sh
Fix fuzzing failures immediately: Fuzzing bugs often indicate real issues
Edit .github/workflows/fuzz.yml to adjust:
duration: Default 3600 seconds (1 hour), configurable via manual triggertimeout-minutes: Maximum 120 minutes per targetrss_limit_mb: Memory limit 4096 MBschedule: Currently runs at 2 AM UTC dailyCurrent limits:
If targets timeout:
timeout-minutes in workflowIf corpora aren’t being restored:
If fuzz tests find “issues” that aren’t real bugs: