Fuzz Testing for Announcement
This directory contains fuzz testing infrastructure using cargo-fuzz and libFuzzer.
Overview
We have 4 fuzz targets that test different aspects of the announcement library:
- fuzz_announce - Tests the announce operation with various data types and patterns
- fuzz_close - Tests close/drop scenarios and the closed detection API
- fuzz_listen - Tests listener operations (try_listen, is_announced, etc.)
- fuzz_concurrent - Tests concurrent access patterns with multiple threads
Prerequisites
Fuzzing requires nightly Rust and cargo-fuzz:
rustup install nightly
cargo install cargo-fuzz
Running Fuzz Tests
Run a single fuzz target:
cargo +nightly fuzz run fuzz_announce
Run with a time limit (recommended for CI):
cargo +nightly fuzz run fuzz_announce -- -max_total_time=60
Run with a specific number of iterations:
cargo +nightly fuzz run fuzz_announce -- -runs=10000
Run all fuzz targets sequentially:
for target in fuzz_announce fuzz_close fuzz_listen fuzz_concurrent; do
echo "Running $target..."
cargo +nightly fuzz run $target -- -runs=10000
done
Continuous Fuzzing
For deeper testing, run fuzz targets for extended periods:
# Run overnight (8 hours)
cargo +nightly fuzz run fuzz_concurrent -- -max_total_time=28800
# Run until crash (or Ctrl+C)
cargo +nightly fuzz run fuzz_announce
Understanding Output
Fuzzer output includes:
cov: X- Code coverage (number of edges covered)ft: X- Feature coverage (number of unique code paths)corp: X/Yb- Corpus size (X inputs, Y bytes total)exec/s: X- Executions per second
If a crash is found:
- Crash input is saved to
artifacts/FUZZ_TARGET/crash-* - Reproduce with:
cargo +nightly fuzz run FUZZ_TARGET artifacts/FUZZ_TARGET/crash-*
Fuzz Target Details
fuzz_announce
Tests basic announce operations:
- Various data types (Vec, String, u64, Arc)
- Multiple listeners receiving the same data
- is_announced() flag behavior
- Data integrity verification
fuzz_close
Tests closed detection API:
- Drop without announce
- Explicit close() call
- Announce then drop (should not be closed)
- Multiple listeners with close
- Listener created after close
fuzz_listen
Tests listener operations:
- try_listen() before and after announce
- Multiple try_listen() calls
- Multiple listeners
- Clone and listener creation
- is_announced() vs is_closed() states
fuzz_concurrent
Tests thread safety:
- Multiple threads with concurrent listeners
- Concurrent clone and listener creation
- Concurrent is_announced() checks
- Concurrent is_closed() checks
- Various timing patterns with barriers
Adding New Fuzz Targets
- Create a new file in
fuzz_targets/(e.g.,fuzz_new_feature.rs) - Use the template:
#![no_main]
use libfuzzer_sys::fuzz_target;
use announcement::Announcement;
fuzz_target!(|data: &[u8]| {
// Your fuzz test here
});
- Add to
fuzz/Cargo.toml:
[[bin]]
name = "fuzz_new_feature"
path = "fuzz_targets/fuzz_new_feature.rs"
test = false
doc = false
bench = false
- Build and run:
cargo +nightly fuzz build
cargo +nightly fuzz run fuzz_new_feature
CI Integration
Fuzzing runs automatically in CI on every push/PR:
- Each target runs for 60-120 seconds
- Targets run 1,000-10,000 iterations minimum
- Any crashes fail the build
See .github/workflows/ci.yml for details.
Corpus Management
The fuzzer builds a corpus of interesting inputs in corpus/FUZZ_TARGET/. These inputs:
- Are automatically discovered during fuzzing
- Can be committed to Git for regression testing
- Help future fuzzing sessions start with good coverage
To minimize the corpus:
cargo +nightly fuzz cmin fuzz_announce
Tips
- Start with short runs - Use
-max_total_time=60to catch obvious bugs quickly - Run overnight - For thorough testing, run for hours or days
- Check coverage - Monitor
cov:values to ensure good code coverage - Save crashes - Commit crash artifacts as regression tests
- Update regularly - Re-run fuzzing when adding new features