Skip to content

Commit 7867c8e

Browse files
authored
Merge pull request #4629 from RalfJung/check-nondet
use check_nondet helper in a few more places
2 parents 47d6568 + a8c2ccb commit 7867c8e

File tree

5 files changed

+34
-18
lines changed

5 files changed

+34
-18
lines changed

tests/pass-dep/libc/libc-mem.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
#![feature(pointer_is_aligned_to)]
22
use std::{mem, ptr, slice};
33

4+
#[path = "../../utils/mod.rs"]
5+
mod utils;
6+
use utils::check_nondet;
7+
48
fn test_memcpy() {
59
unsafe {
610
let src = [1i8, 2, 3];
@@ -120,13 +124,12 @@ fn test_memset() {
120124
}
121125

122126
fn test_malloc() {
123-
// Test that small allocations sometimes *are* not very aligned.
124-
let saw_unaligned = (0..64).any(|_| unsafe {
127+
// Test that small allocations sometimes are *not* very aligned (and sometimes they are).
128+
check_nondet(|| unsafe {
125129
let p = libc::malloc(3);
126130
libc::free(p);
127-
(p as usize) % 4 != 0 // find any that this is *not* 4-aligned
131+
(p as usize) % 4 == 0
128132
});
129-
assert!(saw_unaligned);
130133

131134
unsafe {
132135
let p1 = libc::malloc(20);

tests/pass/dyn-traits.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
#[path = "../utils/mod.rs"]
2+
mod utils;
3+
use utils::check_nondet;
4+
15
fn ref_box_dyn() {
26
struct Struct(i32);
37

@@ -147,7 +151,7 @@ fn vtable_ptr_eq() {
147151
// We don't always get the same vtable when casting this to a wide pointer.
148152
let x = &2;
149153
let x_wide = x as &dyn fmt::Display;
150-
assert!((0..256).any(|_| !ptr::eq(x as &dyn fmt::Display, x_wide)));
154+
check_nondet(|| ptr::eq(x as &dyn fmt::Display, x_wide));
151155
}
152156

153157
fn main() {

tests/pass/function_pointers.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
use std::mem;
44

5+
#[path = "../utils/mod.rs"]
6+
mod utils;
7+
use utils::check_nondet;
8+
59
trait Answer {
610
fn answer() -> Self;
711
}
@@ -30,6 +34,7 @@ fn i() -> i32 {
3034
73
3135
}
3236

37+
#[inline(never)] // optimizations mask the non-determinism we test for below
3338
fn return_fn_ptr(f: fn() -> i32) -> fn() -> i32 {
3439
f
3540
}
@@ -85,7 +90,7 @@ fn main() {
8590
assert!(return_fn_ptr(i) as unsafe fn() -> i32 == i as fn() -> i32 as unsafe fn() -> i32);
8691
// Miri gives different addresses to different reifications of a generic function.
8792
// at least if we try often enough.
88-
assert!((0..256).any(|_| return_fn_ptr(f) != f));
93+
check_nondet(|| return_fn_ptr(f) == f);
8994
// However, if we only turn `f` into a function pointer and use that pointer,
9095
// it is equal to itself.
9196
let f2 = f as fn() -> i32;

tests/pass/shims/fs.rs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use std::path::Path;
1313

1414
#[path = "../../utils/mod.rs"]
1515
mod utils;
16+
use utils::check_nondet;
1617

1718
fn main() {
1819
test_path_conversion();
@@ -81,25 +82,25 @@ fn test_file() {
8182
}
8283

8384
fn test_file_partial_reads_writes() {
84-
let path = utils::prepare_with_content("miri_test_fs_file.txt", b"abcdefg");
85+
let path1 = utils::prepare_with_content("miri_test_fs_file1.txt", b"abcdefg");
86+
let path2 = utils::prepare_with_content("miri_test_fs_file2.txt", b"abcdefg");
8587

8688
// Ensure we sometimes do incomplete writes.
87-
let got_short_write = (0..16).any(|_| {
88-
let _ = remove_file(&path); // FIXME(win, issue #4483): errors if the file already exists
89-
let mut file = File::create(&path).unwrap();
90-
file.write(&[0; 4]).unwrap() != 4
89+
check_nondet(|| {
90+
let _ = remove_file(&path1); // FIXME(win, issue #4483): errors if the file already exists
91+
let mut file = File::create(&path1).unwrap();
92+
file.write(&[0; 4]).unwrap() == 4
9193
});
92-
assert!(got_short_write);
9394
// Ensure we sometimes do incomplete reads.
94-
let got_short_read = (0..16).any(|_| {
95-
let mut file = File::open(&path).unwrap();
95+
check_nondet(|| {
96+
let mut file = File::open(&path2).unwrap();
9697
let mut buf = [0; 4];
97-
file.read(&mut buf).unwrap() != 4
98+
file.read(&mut buf).unwrap() == 4
9899
});
99-
assert!(got_short_read);
100100

101101
// Clean up
102-
remove_file(&path).unwrap();
102+
remove_file(&path1).unwrap();
103+
remove_file(&path2).unwrap();
103104
}
104105

105106
fn test_file_clone() {

tests/utils/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,10 @@ pub fn check_all_outcomes<T: Eq + std::hash::Hash + std::fmt::Debug>(
5555
/// Check that the operation is non-deterministic
5656
#[track_caller]
5757
pub fn check_nondet<T: PartialEq + std::fmt::Debug>(f: impl Fn() -> T) {
58-
let rounds = 50;
58+
// We test some rather unlikely events with this, such as two global allocations getting the
59+
// same "salt" (1/32 chance). So give this *many* shots before we consider the test to have
60+
// failed.
61+
let rounds = 500;
5962
let first = f();
6063
for _ in 1..rounds {
6164
if f() != first {

0 commit comments

Comments
 (0)