Skip to content

Commit

Permalink
Run Miri on CI
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed May 27, 2021
1 parent 399a92f commit bdd3a3f
Show file tree
Hide file tree
Showing 21 changed files with 286 additions and 14 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,15 @@ jobs:
- name: clippy
run: ./ci/clippy.sh

# Run miri.
miri:
name: miri
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: miri
run: ./ci/miri.sh

# Run sanitizers.
san:
name: san
Expand Down Expand Up @@ -156,6 +165,7 @@ jobs:
- dependencies
- rustfmt
- clippy
- miri
- san
- loom
- docs
Expand Down
19 changes: 19 additions & 0 deletions ci/miri.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash

set -ex

export RUSTFLAGS="-D warnings"

if [[ "$OSTYPE" != "linux"* ]]; then
exit 0
fi

toolchain=nightly-$(curl -s https://rust-lang.github.io/rustup-components-history/x86_64-unknown-linux-gnu/miri)
rustup set profile minimal
rustup default "$toolchain"
rustup component add miri

# -Zmiri-disable-stacked-borrows is needed for https://github.com/crossbeam-rs/crossbeam/issues/545
# -Zmiri-ignore-leaks is needed for https://github.com/crossbeam-rs/crossbeam/issues/579
export MIRIFLAGS="-Zmiri-disable-isolation -Zmiri-disable-stacked-borrows -Zmiri-ignore-leaks"
cargo miri test --all --exclude benchmarks
2 changes: 2 additions & 0 deletions crossbeam-channel/tests/after.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Tests for the after channel flavor.
#![cfg(not(miri))] // TODO: many assertions failed due to Miri is slow

use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;
use std::thread;
Expand Down
2 changes: 2 additions & 0 deletions crossbeam-channel/tests/array.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Tests for the array channel flavor.
#![cfg(not(miri))] // TODO: many assertions failed due to Miri is slow

use std::any::Any;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;
Expand Down
2 changes: 2 additions & 0 deletions crossbeam-channel/tests/golang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
//! - https://golang.org/LICENSE
//! - https://golang.org/PATENTS
#![cfg(not(miri))] // Miri is too slow

use std::alloc::{GlobalAlloc, Layout, System};
use std::any::Any;
use std::cell::Cell;
Expand Down
1 change: 1 addition & 0 deletions crossbeam-channel/tests/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ fn recv_iter_break() {
.unwrap();
}

#[cfg_attr(miri, ignore)] // Miri is too slow
#[test]
fn recv_try_iter() {
let (request_s, request_r) = unbounded();
Expand Down
23 changes: 23 additions & 0 deletions crossbeam-channel/tests/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,9 @@ fn disconnect_wakes_receiver() {

#[test]
fn spsc() {
#[cfg(miri)]
const COUNT: usize = 100;
#[cfg(not(miri))]
const COUNT: usize = 100_000;

let (s, r) = unbounded();
Expand All @@ -261,6 +264,9 @@ fn spsc() {

#[test]
fn mpmc() {
#[cfg(miri)]
const COUNT: usize = 100;
#[cfg(not(miri))]
const COUNT: usize = 25_000;
const THREADS: usize = 4;

Expand Down Expand Up @@ -295,6 +301,9 @@ fn mpmc() {

#[test]
fn stress_oneshot() {
#[cfg(miri)]
const COUNT: usize = 100;
#[cfg(not(miri))]
const COUNT: usize = 10_000;

for _ in 0..COUNT {
Expand All @@ -308,6 +317,7 @@ fn stress_oneshot() {
}
}

#[cfg_attr(miri, ignore)] // Miri is too slow
#[test]
fn stress_iter() {
const COUNT: usize = 100_000;
Expand Down Expand Up @@ -371,6 +381,7 @@ fn stress_timeout_two_threads() {
.unwrap();
}

#[cfg_attr(miri, ignore)] // Miri is too slow
#[test]
fn drops() {
static DROPS: AtomicUsize = AtomicUsize::new(0);
Expand Down Expand Up @@ -421,6 +432,9 @@ fn drops() {

#[test]
fn linearizable() {
#[cfg(miri)]
const COUNT: usize = 100;
#[cfg(not(miri))]
const COUNT: usize = 25_000;
const THREADS: usize = 4;

Expand All @@ -441,6 +455,9 @@ fn linearizable() {

#[test]
fn fairness() {
#[cfg(miri)]
const COUNT: usize = 100;
#[cfg(not(miri))]
const COUNT: usize = 10_000;

let (s1, r1) = unbounded::<()>();
Expand All @@ -463,6 +480,9 @@ fn fairness() {

#[test]
fn fairness_duplicates() {
#[cfg(miri)]
const COUNT: usize = 100;
#[cfg(not(miri))]
const COUNT: usize = 10_000;

let (s, r) = unbounded();
Expand Down Expand Up @@ -496,6 +516,9 @@ fn recv_in_send() {

#[test]
fn channel_through_channel() {
#[cfg(miri)]
const COUNT: usize = 100;
#[cfg(not(miri))]
const COUNT: usize = 1000;

type T = Box<dyn Any + Send>;
Expand Down
58 changes: 47 additions & 11 deletions crossbeam-channel/tests/mpsc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ mod channel_tests {
assert!(tx2.send(1).is_err());
}

#[cfg_attr(miri, ignore)] // Miri is too slow
#[test]
fn port_gone_concurrent() {
let (tx, rx) = channel::<i32>();
Expand All @@ -274,6 +275,7 @@ mod channel_tests {
t.join().unwrap();
}

#[cfg_attr(miri, ignore)] // Miri is too slow
#[test]
fn port_gone_concurrent_shared() {
let (tx, rx) = channel::<i32>();
Expand Down Expand Up @@ -314,20 +316,28 @@ mod channel_tests {

#[test]
fn stress() {
#[cfg(miri)]
const COUNT: usize = 500;
#[cfg(not(miri))]
const COUNT: usize = 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().unwrap();
}

#[test]
fn stress_shared() {
#[cfg(miri)]
const AMT: u32 = 500;
#[cfg(not(miri))]
const AMT: u32 = 10000;
const NTHREADS: u32 = 8;
let (tx, rx) = channel::<i32>();
Expand Down Expand Up @@ -735,12 +745,17 @@ mod channel_tests {

#[test]
fn recv_a_lot() {
#[cfg(miri)]
const N: usize = 100;
#[cfg(not(miri))]
const N: usize = 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..N {
tx.send(()).unwrap();
}
for _ in 0..10000 {
for _ in 0..N {
rx.recv().unwrap();
}
}
Expand Down Expand Up @@ -841,6 +856,7 @@ mod channel_tests {
t.join().unwrap();
}

#[cfg_attr(miri, ignore)] // Miri is too slow
#[test]
fn test_recv_try_iter() {
let (request_tx, request_rx) = channel();
Expand Down Expand Up @@ -955,6 +971,7 @@ mod channel_tests {
}

// Source: https://github.com/rust-lang/rust/blob/master/src/libstd/sync/mpsc/mod.rs
#[cfg(not(miri))] // Miri failed due to https://github.com/rust-lang/miri/issues/1371
mod sync_channel_tests {
use super::*;

Expand Down Expand Up @@ -1079,24 +1096,34 @@ mod sync_channel_tests {

#[test]
fn stress() {
#[cfg(miri)]
const N: usize = 100;
#[cfg(not(miri))]
const N: usize = 10000;

let (tx, rx) = sync_channel::<i32>(0);
let t = thread::spawn(move || {
for _ in 0..10000 {
for _ in 0..N {
tx.send(1).unwrap();
}
});
for _ in 0..10000 {
for _ in 0..N {
assert_eq!(rx.recv().unwrap(), 1);
}
t.join().unwrap();
}

#[test]
fn stress_recv_timeout_two_threads() {
#[cfg(miri)]
const N: usize = 100;
#[cfg(not(miri))]
const N: usize = 10000;

let (tx, rx) = sync_channel::<i32>(0);

let t = thread::spawn(move || {
for _ in 0..10000 {
for _ in 0..N {
tx.send(1).unwrap();
}
});
Expand All @@ -1113,7 +1140,7 @@ mod sync_channel_tests {
}
}

assert_eq!(recv_count, 10000);
assert_eq!(recv_count, N);
t.join().unwrap();
}

Expand Down Expand Up @@ -1449,12 +1476,17 @@ mod sync_channel_tests {

#[test]
fn recv_a_lot() {
#[cfg(miri)]
const N: usize = 100;
#[cfg(not(miri))]
const N: usize = 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(N);
for _ in 0..N {
tx.send(()).unwrap();
}
for _ in 0..10000 {
for _ in 0..N {
rx.recv().unwrap();
}
}
Expand Down Expand Up @@ -1792,7 +1824,11 @@ mod select_tests {

#[test]
fn stress() {
#[cfg(miri)]
const AMT: i32 = 100;
#[cfg(not(miri))]
const AMT: i32 = 10000;

let (tx1, rx1) = channel::<i32>();
let (tx2, rx2) = channel::<i32>();
let (tx3, rx3) = channel::<()>();
Expand Down
18 changes: 18 additions & 0 deletions crossbeam-channel/tests/ready.rs
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,9 @@ fn nesting() {

#[test]
fn stress_recv() {
#[cfg(miri)]
const COUNT: usize = 100;
#[cfg(not(miri))]
const COUNT: usize = 10_000;

let (s1, r1) = unbounded();
Expand Down Expand Up @@ -527,6 +530,9 @@ fn stress_recv() {

#[test]
fn stress_send() {
#[cfg(miri)]
const COUNT: usize = 100;
#[cfg(not(miri))]
const COUNT: usize = 10_000;

let (s1, r1) = bounded(0);
Expand Down Expand Up @@ -561,6 +567,9 @@ fn stress_send() {

#[test]
fn stress_mixed() {
#[cfg(miri)]
const COUNT: usize = 100;
#[cfg(not(miri))]
const COUNT: usize = 10_000;

let (s1, r1) = bounded(0);
Expand Down Expand Up @@ -666,6 +675,9 @@ fn send_recv_same_channel() {

#[test]
fn channel_through_channel() {
#[cfg(miri)]
const COUNT: usize = 100;
#[cfg(not(miri))]
const COUNT: usize = 1000;

type T = Box<dyn Any + Send>;
Expand Down Expand Up @@ -722,6 +734,9 @@ fn channel_through_channel() {

#[test]
fn fairness1() {
#[cfg(miri)]
const COUNT: usize = 100;
#[cfg(not(miri))]
const COUNT: usize = 10_000;

let (s1, r1) = bounded::<()>(COUNT);
Expand Down Expand Up @@ -767,6 +782,9 @@ fn fairness1() {

#[test]
fn fairness2() {
#[cfg(miri)]
const COUNT: usize = 100;
#[cfg(not(miri))]
const COUNT: usize = 100_000;

let (s1, r1) = unbounded::<()>();
Expand Down
Loading

0 comments on commit bdd3a3f

Please sign in to comment.