//! Replay every committed fuzz input through the oracle, on stable. //! //! The soak tier runs on astra, on nightly, when the box is idle. That is the //! wrong place for the only copy of a property to live: a crash found there is //! fixed here, and nothing on a developer's machine would notice it coming back. //! //! So both corpora replay as an ordinary `cargo test`: //! //! - `fuzz/seeds/command/` is human intent, the shapes worth reaching first. //! - `fuzz/regressions/` is inputs that once found a bug. Anything landing there //! is a permanent test by virtue of the directory, with no test function to //! write and no chance of forgetting one. //! //! The assertion is `git_command::oracle::check_line`, the same function the //! libFuzzer target calls, so the two cannot check different things. use std::path::Path; /// Replay one directory, returning how many inputs it held. /// /// A missing directory is fine and returns zero: `fuzz/regressions/` does not /// exist until the first crash does. fn replay(dir: &Path) -> usize { let Ok(entries) = std::fs::read_dir(dir) else { return 0; }; let mut count = 0; for entry in entries { let path = entry.expect("readable dir entry").path(); if !path.is_file() { continue; } // README and friends are documentation, not inputs. if path.extension().is_some_and(|e| e == "md") { continue; } let bytes = std::fs::read(&path).expect("readable input"); // The target takes `&str`, so a non-UTF-8 artifact is not one of ours. let Ok(line) = std::str::from_utf8(&bytes) else { continue; }; // Panics here name the file, because a bare oracle panic in a loop over // 20 inputs says nothing about which one broke. let outcome = std::panic::catch_unwind(|| git_command::oracle::check_line(line)); assert!( outcome.is_ok(), "oracle failed on {}: {line:?}", path.display() ); count += 1; } count } #[test] fn every_seed_holds_the_oracle() { let dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("fuzz/seeds/command"); let n = replay(&dir); // A seed directory that silently emptied would make this test pass while // checking nothing, which is the failure mode a corpus-replay test has. assert!( n >= 20, "expected the committed seed corpus, found {n} inputs" ); } #[test] fn every_regression_holds_the_oracle() { let dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("fuzz/regressions"); // No lower bound. This is empty until the first crash, and that is the // good state. replay(&dir); }