use logicaffeine_compile::compile::compile_to_rust;
use std::fs;
fn benchmark_programs() -> Vec<(String, String)> {
let dir = concat!(env!("CARGO_MANIFEST_DIR"), "/../../benchmarks/programs");
let mut out = Vec::new();
for entry in fs::read_dir(dir).expect("benchmarks/programs directory") {
let path = entry.unwrap().path();
let main_lg = path.join("main.lg");
if main_lg.exists() {
let name = path.file_name().unwrap().to_string_lossy().into_owned();
out.push((name, fs::read_to_string(&main_lg).unwrap()));
}
}
out.sort();
out
}
const DET_SHARDS: usize = 4;
fn det_shard(shard: usize) -> impl Iterator<Item = usize> {
(0..benchmark_programs().len()).filter(move |i| i % DET_SHARDS == shard)
}
fn run_determinism_shard(shard: usize) {
const ROUNDS: usize = 6;
let programs = benchmark_programs();
let mut owned = 0usize;
let mut nondeterministic: Vec<String> = Vec::new();
for i in det_shard(shard) {
owned += 1;
let (name, src) = &programs[i];
let first = match compile_to_rust(src) {
Ok(r) => r,
Err(_) => continue, };
let stable = (1..ROUNDS).all(|_| compile_to_rust(src).map(|r| r == *first).unwrap_or(false));
if !stable {
nondeterministic.push(name.clone());
}
}
assert!(owned > 0, "determinism shard {shard}/{DET_SHARDS} owns no programs");
assert!(
nondeterministic.is_empty(),
"codegen is non-deterministic for (shard {shard}/{DET_SHARDS}): {nondeterministic:?}"
);
}
macro_rules! determinism_shards {
($($name:ident => $idx:expr;)+) => {
$(
#[test] fn $name() { run_determinism_shard($idx); }
)+
};
}
determinism_shards! {
codegen_is_deterministic_across_compiles_s0 => 0;
codegen_is_deterministic_across_compiles_s1 => 1;
codegen_is_deterministic_across_compiles_s2 => 2;
codegen_is_deterministic_across_compiles_s3 => 3;
}
#[test]
fn det_partition_tiles_programs() {
let len = benchmark_programs().len();
let mut hits = vec![0u32; len];
for shard in 0..DET_SHARDS {
for i in det_shard(shard) {
hits[i] += 1;
}
}
assert!(
hits.iter().all(|&h| h == 1),
"programs not tiled exactly once by {DET_SHARDS} shards: {hits:?}"
);
for shard in 0..DET_SHARDS {
assert!(det_shard(shard).count() > 0, "determinism shard {shard} owns no programs");
}
}