Faster tests: hostile_params_never_panic shares its commands across threads (154 s to 20 s), the design-file fuzz test tries its seeded cases on all cores (21 s to 7.5 s), the kernel's tangent-primitive boolean test runs its three seeds at once, and the headless scenario harness skips the software viewport render it threw away every frame (scenarios 63 s to 26 s). kill_mid_save waits for the saver to reach a varying round instead of sleeping a fixed time, so it holds on a busy machine
This commit is contained in:
1 parent
4a41de72ec
commit
aa268f0f0e
6 files changed
+90
-41
No files matched your search
@@ -153,7 +153,8 @@ fn try_bytes(bytes: &[u8]) {
|
||||
#[test]
|
||||
fn damaged_and_hostile_design_files_never_panic() {
|
||||
let mut rng = Rng(0x5eed_cafe_f00d_d00d);
|
||||
let mut failures = Vec::new();
|
||||
// The cases come from one seeded sequence; trying them is independent, so threads share it.
|
||||
let mut all_cases: Vec<(String, String, Vec<u8>)> = Vec::new();
|
||||
for p in corpus() {
|
||||
let name = p.file_name().unwrap_or_default().to_string_lossy().to_string();
|
||||
let bytes = std::fs::read(&p).unwrap();
|
||||
@@ -198,14 +199,28 @@ fn damaged_and_hostile_design_files_never_panic() {
|
||||
cases.push(("features repeated".into(), v.to_string().into_bytes()));
|
||||
cases.push(("deep nesting".into(), format!("{}{}", "[".repeat(100_000), "]".repeat(100_000)).into_bytes()));
|
||||
cases.push(("binary".into(), (0..4096u32).map(|i| (i.wrapping_mul(2_654_435_761) >> 24) as u8).collect()));
|
||||
for (what, b) in cases {
|
||||
if std::env::var_os("CORPUS_TRACE").is_some() {
|
||||
eprintln!("{name}: {what}");
|
||||
}
|
||||
if std::panic::catch_unwind(|| try_bytes(&b)).is_err() {
|
||||
failures.push(format!("{name}: {what}"));
|
||||
}
|
||||
}
|
||||
all_cases.extend(cases.into_iter().map(|(what, b)| (name.clone(), what, b)));
|
||||
}
|
||||
let next = std::sync::atomic::AtomicUsize::new(0);
|
||||
let threads = std::thread::available_parallelism().map_or(4, |n| n.get());
|
||||
let failures: Vec<String> = std::thread::scope(|scope| {
|
||||
let workers: Vec<_> = (0..threads)
|
||||
.map(|_| {
|
||||
scope.spawn(|| {
|
||||
let mut failures = Vec::new();
|
||||
while let Some((name, what, b)) = all_cases.get(next.fetch_add(1, std::sync::atomic::Ordering::Relaxed)) {
|
||||
if std::env::var_os("CORPUS_TRACE").is_some() {
|
||||
eprintln!("{name}: {what}");
|
||||
}
|
||||
if std::panic::catch_unwind(|| try_bytes(b)).is_err() {
|
||||
failures.push(format!("{name}: {what}"));
|
||||
}
|
||||
}
|
||||
failures
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
workers.into_iter().flat_map(|w| w.join().unwrap()).collect()
|
||||
});
|
||||
assert!(failures.is_empty(), "panics:\n{}", failures.join("\n"));
|
||||
}
|
||||
@@ -22,10 +22,20 @@ fn killed_mid_save_the_old_file_survives() {
|
||||
assert_eq!(round_of(&path).as_deref(), Some("0"));
|
||||
let mut kills = 0;
|
||||
let mut seen = std::collections::BTreeSet::new();
|
||||
let modified = || std::fs::metadata(&path).and_then(|m| m.modified()).ok();
|
||||
for i in 0..25u64 {
|
||||
let before = modified();
|
||||
let mut child = Command::new(exe).args(["save-stress", &path.to_string_lossy(), "100000"]).spawn().unwrap();
|
||||
// Let it get into its save loop (building the design takes a moment), then kill it.
|
||||
std::thread::sleep(Duration::from_millis(150 + (i * 37) % 200));
|
||||
// Wait until it is in its save loop (its first save replaced the file) and has reached a
|
||||
// round that varies from kill to kill, however busy the machine is; then kill it a
|
||||
// varying while later.
|
||||
let target = i % 10;
|
||||
let reached = || modified() != before && round_of(&path).and_then(|r| r.parse::<u64>().ok()).is_some_and(|r| r >= target);
|
||||
let t0 = std::time::Instant::now();
|
||||
while !reached() && t0.elapsed() < Duration::from_secs(20) && child.try_wait().unwrap().is_none() {
|
||||
std::thread::sleep(Duration::from_millis(2));
|
||||
}
|
||||
std::thread::sleep(Duration::from_millis((i * 7) % 30));
|
||||
if child.try_wait().unwrap().is_none() {
|
||||
child.kill().unwrap();
|
||||
kills += 1;
|
||||
|
||||
Reference in new issue
Block a user