diff --git a/Cargo.lock b/Cargo.lock index eca327a..131b306 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -181,7 +181,6 @@ dependencies = [ "env_logger", "log", "rayon", - "serde", "tempfile", ] diff --git a/config.toml.example b/config.toml.example index 116af10..a0fe949 100644 --- a/config.toml.example +++ b/config.toml.example @@ -1,3 +1,4 @@ +parallel_difftest = true bb_max_len = 32 max_switch_targets = 8 max_bb_count = 50 diff --git a/config/src/lib.rs b/config/src/lib.rs index 030ef3c..9db0a07 100644 --- a/config/src/lib.rs +++ b/config/src/lib.rs @@ -9,6 +9,7 @@ pub fn load(path: impl AsRef) -> Config { #[derive(Deserialize, Clone)] pub struct Config { + pub parallel_difftest: bool, #[serde(flatten)] pub generation: GenerationConfig, #[serde(flatten)] diff --git a/difftest/Cargo.toml b/difftest/Cargo.toml index 216c276..383578a 100644 --- a/difftest/Cargo.toml +++ b/difftest/Cargo.toml @@ -12,5 +12,4 @@ colored = "2.0.0" env_logger = "0.11.3" log = "0.4.17" rayon = "1.7.0" -serde = { version = "1", features = ["derive"] } tempfile = "3.3.0" diff --git a/difftest/src/backends.rs b/difftest/src/backends.rs index 7cc0aee..0870f0a 100644 --- a/difftest/src/backends.rs +++ b/difftest/src/backends.rs @@ -174,9 +174,14 @@ impl LLVM { impl Backend for LLVM { fn compile(&self, source: &Source, target: &Path) -> ProcessOutput { - let mut command = Command::new("rustc"); - - command.arg(format!("+{}", self.toolchain)); + let mut command = if let Ok(path) = std::env::var("RUSTLANTIS_RUSTC_PATH") { + debug!("Compiling with rustc from RUSTLANTIS_RUSTC_PATH"); + Command::new(path) + } else { + let mut command = Command::new("rustc"); + command.arg(format!("+{}", self.toolchain)); + command + }; command .args(["-o", target.to_str().unwrap()]) @@ -307,13 +312,18 @@ impl Miri { impl Backend for Miri { fn execute(&self, source: &Source, _: &Path) -> ExecResult { - debug!("Executing with Miri {source}"); - let mut command = match &self.miri { - BackendSource::Path(binary) => Command::new(binary), - BackendSource::Rustup(toolchain) => { - let mut cmd = Command::new("rustup"); - cmd.args(["run", &toolchain, "miri"]); - cmd + let mut command = if let Ok(path) = std::env::var("RUSTLANTIS_MIRI_PATH") { + debug!("Executing with Miri from RUSTLANTIS_MIRI_PATH"); + Command::new(path) + } else { + debug!("Executing with Miri {source}"); + match &self.miri { + BackendSource::Path(binary) => Command::new(binary), + BackendSource::Rustup(toolchain) => { + let mut cmd = Command::new("rustup"); + cmd.args(["run", &toolchain, "miri"]); + cmd + } } }; command.args(self.flags.clone()); diff --git a/difftest/src/lib.rs b/difftest/src/lib.rs index 9fa95d4..841c99e 100644 --- a/difftest/src/lib.rs +++ b/difftest/src/lib.rs @@ -155,24 +155,28 @@ impl fmt::Display for ExecResults { pub fn run_diff_test<'a>( source: &Source, backends: HashMap>, + parallel: bool, ) -> ExecResults { let target_dir = tempfile::tempdir().unwrap(); - let exec_results: HashMap = backends - .into_par_iter() - .map(|(name, b)| { - let target_path = target_dir.path().join(&name); - let result = if log_enabled!(log::Level::Debug) { - let time = Instant::now(); - let result = b.execute(source, &target_path); - let dur = time.elapsed(); - debug!("{name} took {}s", dur.as_secs_f32()); - result - } else { - b.execute(source, &target_path) - }; - (name.clone(), result) - }) - .collect(); - ExecResults::from_exec_results(exec_results.into_iter()) + let run_test = |(name, backend): (String, Box)| -> (String, ExecResult) { + let target_path = target_dir.path().join(&name); + let result = if log_enabled!(log::Level::Debug) { + let time = Instant::now(); + let result = backend.execute(source, &target_path); + let dur = time.elapsed(); + debug!("{name} took {}s", dur.as_secs_f32()); + result + } else { + backend.execute(source, &target_path) + }; + (name, result) + }; + + let results: HashMap = if parallel { + backends.into_par_iter().map(run_test).collect() + } else { + backends.into_iter().map(run_test).collect() + }; + ExecResults::from_exec_results(results.into_iter()) } diff --git a/difftest/src/main.rs b/difftest/src/main.rs index cb4b47d..7d65992 100644 --- a/difftest/src/main.rs +++ b/difftest/src/main.rs @@ -22,6 +22,7 @@ fn main() -> ExitCode { let config_path = std::env::var("RUSTLANTIS_CONFIG").unwrap_or("config.toml".to_string()); let config = config::load(config_path); + let parallel = config.parallel_difftest; let backends = backends::from_config(config); let source = if source == "-" { @@ -44,7 +45,7 @@ fn main() -> ExitCode { .collect::() ); - let results = run_diff_test(&source, backends); + let results = run_diff_test(&source, backends, parallel); if results.all_same() && results.all_success() { info!("{} is all the same", source); debug!("{}", results); diff --git a/difftest/tests/config.toml b/difftest/tests/config.toml index ace277a..a35f45d 100644 --- a/difftest/tests/config.toml +++ b/difftest/tests/config.toml @@ -1,3 +1,4 @@ +parallel_difftest = true max_fn_count = 100 max_args_count = 0 diff --git a/difftest/tests/test.rs b/difftest/tests/test.rs index 41b8807..6ee1e26 100644 --- a/difftest/tests/test.rs +++ b/difftest/tests/test.rs @@ -6,7 +6,7 @@ fn correct_mir() { let config = config::load("tests/config.toml"); let backends = backends::from_config(config); - let results = run_diff_test(&Source::File("tests/inputs/simple.rs".into()), backends); + let results = run_diff_test(&Source::File("tests/inputs/simple.rs".into()), backends, true); println!("{}", results); assert!(results.all_same()); assert!( @@ -24,6 +24,7 @@ fn invalid_mir() { let results = run_diff_test( &Source::File("tests/inputs/invalid_mir.rs".into()), backends, + false, ); println!("{}", results); assert!(results.all_same()); @@ -36,7 +37,7 @@ fn ub() { let config = config::load("tests/config.toml"); let backends = backends::from_config(config); - let results = run_diff_test(&Source::File("tests/inputs/ub.rs".into()), backends); + let results = run_diff_test(&Source::File("tests/inputs/ub.rs".into()), backends, false); println!("{}", results); assert_eq!(results.has_ub(), Some(true)); } diff --git a/fuzz-one.sh b/fuzz-one.sh deleted file mode 100755 index 9e99f79..0000000 --- a/fuzz-one.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -echo "$1" - -TMPDIR="${TMPDIR:-/tmp}" - -target/release/generate $1 | target/release/difftest - -if [ $? -ne 0 ]; then - SOURCE_DEBUG="$TMPDIR/$1-debug.rs" - target/release/generate --debug $1 > $SOURCE_DEBUG - - REPRO_DIR="${REPRO_DIR:-repros/}" - mkdir -p $REPRO_DIR - - if target/release/difftest $SOURCE_DEBUG 2> /dev/null; then - target/release/generate $1 > "$REPRO_DIR/$1.rs" - else - mv $SOURCE_DEBUG $REPRO_DIR - fi - exit 1 -fi diff --git a/fuzz.sh b/fuzz.sh new file mode 100755 index 0000000..6f440d7 --- /dev/null +++ b/fuzz.sh @@ -0,0 +1,19 @@ +#!/bin/bash +set -eu + +cargo build --release +export MIRI_SYSROOT=$(cargo +nightly miri setup --print-sysroot) +export RUSTLANTIS_MIRI_PATH="$(rustup run nightly miri --print sysroot)/bin/miri" +export RUSTLANTIS_RUSTC_PATH="$(rustup run nightly rustc --print sysroot)/bin/rustc" + +function cleanup { + kill $(jobs -p) +} +trap cleanup EXIT + +proc=$(nproc) +for job in $(seq 0 $((proc-1))); do + nice -n 19 ./job.sh &> $job.out & +done + +wait diff --git a/fuzz10.sh b/fuzz10.sh deleted file mode 100755 index d329421..0000000 --- a/fuzz10.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -cargo build --release - -export RUST_LOG=info - -mkdir -p out -for seed in {0..10}; do - target/release/generate $seed > out/$seed.rs - target/release/difftest out/$seed.rs -done \ No newline at end of file diff --git a/job.sh b/job.sh new file mode 100755 index 0000000..9b7c39f --- /dev/null +++ b/job.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +set -eu + +while true +do + seed=$(python3 -c "print(int.from_bytes(open('/dev/urandom', 'rb').read(8), 'little'))") + code=$(target/release/generate $seed) + if ! target/release/difftest - <<< $code + then + mkdir -p out + printf "%s" "$code" > out/$seed.rs + fi +done