Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add miri-test-libstd support to libstd #100129

Merged
merged 5 commits into from
Aug 20, 2022
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
8 changes: 4 additions & 4 deletions library/alloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,6 @@
//! [`Rc`]: rc
//! [`RefCell`]: core::cell

// To run liballoc tests without x.py without ending up with two copies of liballoc, Miri needs to be
// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
// rustc itself never sets the feature, so this line has no affect there.
#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
#![allow(unused_attributes)]
#![stable(feature = "alloc", since = "1.36.0")]
#![doc(
Expand All @@ -77,6 +73,10 @@
))]
#![no_std]
#![needs_allocator]
// To run liballoc tests without x.py without ending up with two copies of liballoc, Miri needs to be
// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
// rustc itself never sets the feature, so this line has no affect there.
#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
//
// Lints:
#![deny(unsafe_op_in_unsafe_fn)]
Expand Down
19 changes: 19 additions & 0 deletions library/alloc/src/sync/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -618,3 +618,22 @@ fn test_arc_cyclic_two_refs() {
assert_eq!(Arc::strong_count(&two_refs), 3);
assert_eq!(Arc::weak_count(&two_refs), 2);
}

/// Test for Arc::drop bug (https://github.com/rust-lang/rust/issues/55005)
#[test]
#[cfg(miri)] // relies on Stacked Borrows in Miri
fn arc_drop_dereferenceable_race() {
// The bug seems to take up to 700 iterations to reproduce with most seeds (tested 0-9).
for _ in 0..750 {
let arc_1 = Arc::new(());
let arc_2 = arc_1.clone();
let thread = thread::spawn(|| drop(arc_2));
// Spin a bit; makes the race more likely to appear
let mut i = 0;
while i < 256 {
i += 1;
}
drop(arc_1);
thread.join().unwrap();
}
}
24 changes: 14 additions & 10 deletions library/std/src/collections/hash/map/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,53 +268,56 @@ fn test_lots_of_insertions() {

// Try this a few times to make sure we never screw up the hashmap's
// internal state.
for _ in 0..10 {
let loops = if cfg!(miri) { 2 } else { 10 };
for _ in 0..loops {
assert!(m.is_empty());

for i in 1..1001 {
let count = if cfg!(miri) { 101 } else { 1001 };

for i in 1..count {
assert!(m.insert(i, i).is_none());

for j in 1..=i {
let r = m.get(&j);
assert_eq!(r, Some(&j));
}

for j in i + 1..1001 {
for j in i + 1..count {
let r = m.get(&j);
assert_eq!(r, None);
}
}

for i in 1001..2001 {
for i in count..(2 * count) {
assert!(!m.contains_key(&i));
}

// remove forwards
for i in 1..1001 {
for i in 1..count {
assert!(m.remove(&i).is_some());

for j in 1..=i {
assert!(!m.contains_key(&j));
}

for j in i + 1..1001 {
for j in i + 1..count {
assert!(m.contains_key(&j));
}
}

for i in 1..1001 {
for i in 1..count {
assert!(!m.contains_key(&i));
}

for i in 1..1001 {
for i in 1..count {
assert!(m.insert(i, i).is_none());
}

// remove backwards
for i in (1..1001).rev() {
for i in (1..count).rev() {
assert!(m.remove(&i).is_some());

for j in i..1001 {
for j in i..count {
assert!(!m.contains_key(&j));
}

Expand Down Expand Up @@ -817,6 +820,7 @@ fn test_retain() {
}

#[test]
#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM
#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc
fn test_try_reserve() {
let mut empty_bytes: HashMap<u8, u8> = HashMap::new();
Expand Down
3 changes: 2 additions & 1 deletion library/std/src/io/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ fn read_to_end() {
assert_eq!(c.read_to_end(&mut v).unwrap(), 1);
assert_eq!(v, b"1");

let cap = 1024 * 1024;
let cap = if cfg!(miri) { 1024 } else { 1024 * 1024 };
let data = (0..cap).map(|i| (i / 3) as u8).collect::<Vec<_>>();
let mut v = Vec::new();
let (a, b) = data.split_at(data.len() / 2);
Expand Down Expand Up @@ -309,6 +309,7 @@ fn chain_zero_length_read_is_not_eof() {

#[bench]
#[cfg_attr(target_os = "emscripten", ignore)]
#[cfg_attr(miri, ignore)] // Miri isn't fast...
fn bench_read_to_end(b: &mut test::Bencher) {
b.iter(|| {
let mut lr = repeat(1).take(10000000);
Expand Down
17 changes: 14 additions & 3 deletions library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@
//! [rust-discord]: https://discord.gg/rust-lang
//! [array]: prim@array
//! [slice]: prim@slice

#![cfg_attr(not(feature = "restricted-std"), stable(feature = "rust1", since = "1.0.0"))]
#![cfg_attr(feature = "restricted-std", unstable(feature = "restricted_std", issue = "none"))]
#![doc(
Expand All @@ -201,25 +202,35 @@
no_global_oom_handling,
not(no_global_oom_handling)
))]
// To run libstd tests without x.py without ending up with two copies of libstd, Miri needs to be
// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
// rustc itself never sets the feature, so this line has no affect there.
#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
// miri-test-libstd also prefers to make std use the sysroot versions of the dependencies.
#![cfg_attr(feature = "miri-test-libstd", feature(rustc_private))]
// Don't link to std. We are std.
#![no_std]
// Tell the compiler to link to either panic_abort or panic_unwind
#![needs_panic_runtime]
//
// Lints:
#![warn(deprecated_in_future)]
#![warn(missing_docs)]
#![warn(missing_debug_implementations)]
#![allow(explicit_outlives_requirements)]
#![allow(unused_lifetimes)]
// Tell the compiler to link to either panic_abort or panic_unwind
#![needs_panic_runtime]
#![deny(rustc::existing_doc_keyword)]
// Ensure that std can be linked against panic_abort despite compiled with `-C panic=unwind`
#![deny(ffi_unwind_calls)]
// std may use features in a platform-specific way
#![allow(unused_features)]
//
// Features:
#![cfg_attr(test, feature(internal_output_capture, print_internals, update_panic_count, rt))]
#![cfg_attr(
all(target_vendor = "fortanix", target_env = "sgx"),
feature(slice_index_methods, coerce_unsized, sgx_platform)
)]
#![deny(rustc::existing_doc_keyword)]
//
// Language features:
#![feature(alloc_error_handler)]
Expand Down
5 changes: 5 additions & 0 deletions library/std/src/path/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1768,6 +1768,7 @@ fn test_windows_absolute() {
}

#[bench]
#[cfg_attr(miri, ignore)] // Miri isn't fast...
fn bench_path_cmp_fast_path_buf_sort(b: &mut test::Bencher) {
let prefix = "my/home";
let mut paths: Vec<_> =
Expand All @@ -1781,6 +1782,7 @@ fn bench_path_cmp_fast_path_buf_sort(b: &mut test::Bencher) {
}

#[bench]
#[cfg_attr(miri, ignore)] // Miri isn't fast...
fn bench_path_cmp_fast_path_long(b: &mut test::Bencher) {
let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/";
let paths: Vec<_> =
Expand All @@ -1799,6 +1801,7 @@ fn bench_path_cmp_fast_path_long(b: &mut test::Bencher) {
}

#[bench]
#[cfg_attr(miri, ignore)] // Miri isn't fast...
fn bench_path_cmp_fast_path_short(b: &mut test::Bencher) {
let prefix = "my/home";
let paths: Vec<_> =
Expand All @@ -1817,6 +1820,7 @@ fn bench_path_cmp_fast_path_short(b: &mut test::Bencher) {
}

#[bench]
#[cfg_attr(miri, ignore)] // Miri isn't fast...
fn bench_path_hashset(b: &mut test::Bencher) {
let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/";
let paths: Vec<_> =
Expand All @@ -1835,6 +1839,7 @@ fn bench_path_hashset(b: &mut test::Bencher) {
}

#[bench]
#[cfg_attr(miri, ignore)] // Miri isn't fast...
fn bench_path_hashset_miss(b: &mut test::Bencher) {
let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/";
let paths: Vec<_> =
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sync/mpsc/mpsc_queue/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ fn test_full() {
#[test]
fn test() {
let nthreads = 8;
let nmsgs = 1000;
let nmsgs = if cfg!(miri) { 100 } else { 1000 };
let q = Queue::new();
match q.pop() {
Empty => {}
Expand Down
5 changes: 3 additions & 2 deletions library/std/src/sync/mpsc/spsc_queue/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,13 @@ fn stress() {
}

unsafe fn stress_bound(bound: usize) {
let count = if cfg!(miri) { 1000 } else { 100000 };
let q = Arc::new(Queue::with_additions(bound, (), ()));

let (tx, rx) = channel();
let q2 = q.clone();
let _t = thread::spawn(move || {
for _ in 0..100000 {
for _ in 0..count {
loop {
match q2.pop() {
Some(1) => break,
Expand All @@ -93,7 +94,7 @@ fn stress() {
}
tx.send(()).unwrap();
});
for _ in 0..100000 {
for _ in 0..count {
q.push(1);
}
rx.recv().unwrap();
Expand Down
21 changes: 12 additions & 9 deletions library/std/src/sync/mpsc/sync_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,23 +113,25 @@ fn chan_gone_concurrent() {

#[test]
fn stress() {
let count = if cfg!(miri) { 100 } else { 10000 };
let (tx, rx) = sync_channel::<i32>(0);
thread::spawn(move || {
for _ in 0..10000 {
for _ in 0..count {
tx.send(1).unwrap();
}
});
for _ in 0..10000 {
for _ in 0..count {
assert_eq!(rx.recv().unwrap(), 1);
}
}

#[test]
fn stress_recv_timeout_two_threads() {
let count = if cfg!(miri) { 100 } else { 10000 };
let (tx, rx) = sync_channel::<i32>(0);

thread::spawn(move || {
for _ in 0..10000 {
for _ in 0..count {
tx.send(1).unwrap();
}
});
Expand All @@ -146,12 +148,12 @@ fn stress_recv_timeout_two_threads() {
}
}

assert_eq!(recv_count, 10000);
assert_eq!(recv_count, count);
}

#[test]
fn stress_recv_timeout_shared() {
const AMT: u32 = 1000;
const AMT: u32 = if cfg!(miri) { 100 } else { 1000 };
const NTHREADS: u32 = 8;
let (tx, rx) = sync_channel::<i32>(0);
let (dtx, drx) = sync_channel::<()>(0);
Expand Down Expand Up @@ -191,7 +193,7 @@ fn stress_recv_timeout_shared() {

#[test]
fn stress_shared() {
const AMT: u32 = 1000;
const AMT: u32 = if cfg!(miri) { 100 } else { 1000 };
const NTHREADS: u32 = 8;
let (tx, rx) = sync_channel::<i32>(0);
let (dtx, drx) = sync_channel::<()>(0);
Expand Down Expand Up @@ -438,12 +440,13 @@ fn stream_send_recv_stress() {

#[test]
fn recv_a_lot() {
let count = if cfg!(miri) { 1000 } else { 10000 };
// Regression test that we don't run out of stack in scheduler context
let (tx, rx) = sync_channel(10000);
for _ in 0..10000 {
let (tx, rx) = sync_channel(count);
for _ in 0..count {
tx.send(()).unwrap();
}
for _ in 0..10000 {
for _ in 0..count {
rx.recv().unwrap();
}
}
Expand Down
12 changes: 7 additions & 5 deletions library/std/src/sync/mpsc/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,21 +120,22 @@ fn chan_gone_concurrent() {

#[test]
fn stress() {
let count = if cfg!(miri) { 100 } else { 10000 };
let (tx, rx) = channel::<i32>();
let t = thread::spawn(move || {
for _ in 0..10000 {
for _ in 0..count {
tx.send(1).unwrap();
}
});
for _ in 0..10000 {
for _ in 0..count {
assert_eq!(rx.recv().unwrap(), 1);
}
t.join().ok().expect("thread panicked");
}

#[test]
fn stress_shared() {
const AMT: u32 = 10000;
const AMT: u32 = if cfg!(miri) { 100 } else { 10000 };
const NTHREADS: u32 = 8;
let (tx, rx) = channel::<i32>();

Expand Down Expand Up @@ -504,12 +505,13 @@ fn very_long_recv_timeout_wont_panic() {

#[test]
fn recv_a_lot() {
let count = if cfg!(miri) { 1000 } else { 10000 };
// Regression test that we don't run out of stack in scheduler context
let (tx, rx) = channel();
for _ in 0..10000 {
for _ in 0..count {
tx.send(()).unwrap();
}
for _ in 0..10000 {
for _ in 0..count {
rx.recv().unwrap();
}
}
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sync/rwlock/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ fn smoke() {
#[test]
fn frob() {
const N: u32 = 10;
const M: usize = 1000;
const M: usize = if cfg!(miri) { 100 } else { 1000 };

let r = Arc::new(RwLock::new(()));

Expand Down
2 changes: 2 additions & 0 deletions library/std/src/sys/unix/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,7 @@ impl DirEntry {
target_os = "fuchsia",
target_os = "redox"
)))]
#[cfg_attr(miri, allow(unused))]
fn name_cstr(&self) -> &CStr {
unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()) }
}
Expand All @@ -840,6 +841,7 @@ impl DirEntry {
target_os = "fuchsia",
target_os = "redox"
))]
#[cfg_attr(miri, allow(unused))]
fn name_cstr(&self) -> &CStr {
&self.name
}
Expand Down
Loading