Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions tests/pass-dep/libc/libc-mem.rs
Original file line number Diff line number Diff line change
@@ -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];
Expand Down Expand Up @@ -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);
Expand Down
6 changes: 5 additions & 1 deletion tests/pass/dyn-traits.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#[path = "../utils/mod.rs"]
mod utils;
use utils::check_nondet;

fn ref_box_dyn() {
struct Struct(i32);

Expand Down Expand Up @@ -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() {
Expand Down
7 changes: 6 additions & 1 deletion tests/pass/function_pointers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

use std::mem;

#[path = "../utils/mod.rs"]
mod utils;
use utils::check_nondet;

trait Answer {
fn answer() -> Self;
}
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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;
Expand Down
23 changes: 12 additions & 11 deletions tests/pass/shims/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use std::path::Path;

#[path = "../../utils/mod.rs"]
mod utils;
use utils::check_nondet;

fn main() {
test_path_conversion();
Expand Down Expand Up @@ -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() {
Expand Down
5 changes: 4 additions & 1 deletion tests/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down