Merge pull request #4629 from RalfJung/check-nondet

use check_nondet helper in a few more places
This commit is contained in:
Ralf Jung 2025-10-13 16:10:32 +00:00 committed by GitHub
commit 42eb21ce76
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 34 additions and 18 deletions

View file

@ -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);

View file

@ -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() {

View file

@ -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;

View file

@ -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() {

View file

@ -55,7 +55,10 @@ pub fn check_all_outcomes<T: Eq + std::hash::Hash + std::fmt::Debug>(
/// Check that the operation is non-deterministic
#[track_caller]
pub fn check_nondet<T: PartialEq + std::fmt::Debug>(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 {