diff --git a/tests/pass-dep/libc/libc-mem.rs b/tests/pass-dep/libc/libc-mem.rs index 531d637d1f..7105b076d6 100644 --- a/tests/pass-dep/libc/libc-mem.rs +++ b/tests/pass-dep/libc/libc-mem.rs @@ -1,6 +1,10 @@ #![feature(pointer_is_aligned_to)] use std::{mem, ptr, slice}; +#[path = "../../utils/mod.rs"] +mod utils; +use utils::check_nondet; + fn test_memcpy() { unsafe { let src = [1i8, 2, 3]; @@ -120,13 +124,12 @@ fn test_memset() { } fn test_malloc() { - // Test that small allocations sometimes *are* not very aligned. - let saw_unaligned = (0..64).any(|_| unsafe { + // Test that small allocations sometimes are *not* very aligned (and sometimes they are). + check_nondet(|| unsafe { let p = libc::malloc(3); libc::free(p); - (p as usize) % 4 != 0 // find any that this is *not* 4-aligned + (p as usize) % 4 == 0 }); - assert!(saw_unaligned); unsafe { let p1 = libc::malloc(20); diff --git a/tests/pass/dyn-traits.rs b/tests/pass/dyn-traits.rs index f622012096..47f913adae 100644 --- a/tests/pass/dyn-traits.rs +++ b/tests/pass/dyn-traits.rs @@ -1,3 +1,7 @@ +#[path = "../utils/mod.rs"] +mod utils; +use utils::check_nondet; + fn ref_box_dyn() { struct Struct(i32); @@ -147,7 +151,7 @@ fn vtable_ptr_eq() { // We don't always get the same vtable when casting this to a wide pointer. let x = &2; let x_wide = x as &dyn fmt::Display; - assert!((0..256).any(|_| !ptr::eq(x as &dyn fmt::Display, x_wide))); + check_nondet(|| ptr::eq(x as &dyn fmt::Display, x_wide)); } fn main() { diff --git a/tests/pass/function_pointers.rs b/tests/pass/function_pointers.rs index 7145be334a..96f6f2568e 100644 --- a/tests/pass/function_pointers.rs +++ b/tests/pass/function_pointers.rs @@ -2,6 +2,10 @@ use std::mem; +#[path = "../utils/mod.rs"] +mod utils; +use utils::check_nondet; + trait Answer { fn answer() -> Self; } @@ -30,6 +34,7 @@ fn i() -> i32 { 73 } +#[inline(never)] // optimizations mask the non-determinism we test for below fn return_fn_ptr(f: fn() -> i32) -> fn() -> i32 { f } @@ -85,7 +90,7 @@ fn main() { assert!(return_fn_ptr(i) as unsafe fn() -> i32 == i as fn() -> i32 as unsafe fn() -> i32); // Miri gives different addresses to different reifications of a generic function. // at least if we try often enough. - assert!((0..256).any(|_| return_fn_ptr(f) != f)); + check_nondet(|| return_fn_ptr(f) == f); // However, if we only turn `f` into a function pointer and use that pointer, // it is equal to itself. let f2 = f as fn() -> i32; diff --git a/tests/pass/shims/fs.rs b/tests/pass/shims/fs.rs index 022dcc5dcb..43fbf6b085 100644 --- a/tests/pass/shims/fs.rs +++ b/tests/pass/shims/fs.rs @@ -13,6 +13,7 @@ use std::path::Path; #[path = "../../utils/mod.rs"] mod utils; +use utils::check_nondet; fn main() { test_path_conversion(); @@ -81,25 +82,25 @@ fn test_file() { } fn test_file_partial_reads_writes() { - let path = utils::prepare_with_content("miri_test_fs_file.txt", b"abcdefg"); + let path1 = utils::prepare_with_content("miri_test_fs_file1.txt", b"abcdefg"); + let path2 = utils::prepare_with_content("miri_test_fs_file2.txt", b"abcdefg"); // Ensure we sometimes do incomplete writes. - let got_short_write = (0..16).any(|_| { - let _ = remove_file(&path); // FIXME(win, issue #4483): errors if the file already exists - let mut file = File::create(&path).unwrap(); - file.write(&[0; 4]).unwrap() != 4 + check_nondet(|| { + let _ = remove_file(&path1); // FIXME(win, issue #4483): errors if the file already exists + let mut file = File::create(&path1).unwrap(); + file.write(&[0; 4]).unwrap() == 4 }); - assert!(got_short_write); // Ensure we sometimes do incomplete reads. - let got_short_read = (0..16).any(|_| { - let mut file = File::open(&path).unwrap(); + check_nondet(|| { + let mut file = File::open(&path2).unwrap(); let mut buf = [0; 4]; - file.read(&mut buf).unwrap() != 4 + file.read(&mut buf).unwrap() == 4 }); - assert!(got_short_read); // Clean up - remove_file(&path).unwrap(); + remove_file(&path1).unwrap(); + remove_file(&path2).unwrap(); } fn test_file_clone() { diff --git a/tests/utils/mod.rs b/tests/utils/mod.rs index 37f9996216..f855f115e4 100644 --- a/tests/utils/mod.rs +++ b/tests/utils/mod.rs @@ -55,7 +55,10 @@ pub fn check_all_outcomes( /// Check that the operation is non-deterministic #[track_caller] pub fn check_nondet(f: impl Fn() -> T) { - let rounds = 50; + // We test some rather unlikely events with this, such as two global allocations getting the + // same "salt" (1/32 chance). So give this *many* shots before we consider the test to have + // failed. + let rounds = 500; let first = f(); for _ in 1..rounds { if f() != first {