Merge pull request #4629 from RalfJung/check-nondet
use check_nondet helper in a few more places
This commit is contained in:
commit
42eb21ce76
5 changed files with 34 additions and 18 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue