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

Run Miri on CI #578

Merged
merged 2 commits into from
Jan 7, 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
10 changes: 10 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,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 @@ -174,6 +183,7 @@ jobs:
- codegen
- rustfmt
- clippy
- miri
- san
- loom
- docs
Expand Down
36 changes: 36 additions & 0 deletions ci/miri.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/bin/bash

cd "$(dirname "$0")"/..
set -ex

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

MIRIFLAGS="-Zmiri-tag-raw-pointers" \
cargo miri test \
-p crossbeam-queue

# -Zmiri-tag-raw-pointers doesn't work with std::thread::Builder::name on Linux: https://github.com/rust-lang/miri/issues/1717
MIRIFLAGS="-Zmiri-disable-isolation" \
cargo miri test \
-p crossbeam-utils

# -Zmiri-ignore-leaks is needed because we use detached threads in tests/docs: https://github.com/rust-lang/miri/issues/1371
# When enable -Zmiri-tag-raw-pointers, miri reports stacked borrows violation: https://github.com/crossbeam-rs/crossbeam/issues/762
MIRIFLAGS="-Zmiri-disable-isolation -Zmiri-ignore-leaks" \
cargo miri test \
-p crossbeam-channel

# -Zmiri-ignore-leaks is needed for https://github.com/crossbeam-rs/crossbeam/issues/579
# -Zmiri-disable-stacked-borrows is needed for https://github.com/crossbeam-rs/crossbeam/issues/545
MIRIFLAGS="-Zmiri-disable-isolation -Zmiri-ignore-leaks -Zmiri-disable-stacked-borrows" \
cargo miri test \
-p crossbeam-epoch \
-p crossbeam-skiplist \
-p crossbeam

MIRIFLAGS="-Zmiri-disable-isolation -Zmiri-ignore-leaks -Zmiri-disable-stacked-borrows -Zmiri-compare-exchange-weak-failure-rate=1.0" \
cargo miri test \
-p crossbeam-deque
8 changes: 3 additions & 5 deletions crossbeam-channel/src/flavors/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

use std::cell::UnsafeCell;
use std::marker::PhantomData;
use std::mem::{self, MaybeUninit};
use std::mem::MaybeUninit;
use std::ptr;
use std::sync::atomic::{self, AtomicUsize, Ordering};
use std::time::Instant;
Expand Down Expand Up @@ -110,7 +110,7 @@ impl<T> Channel<T> {
// Allocate a buffer of `cap` slots initialized
// with stamps.
let buffer = {
let mut boxed: Box<[Slot<T>]> = (0..cap)
let boxed: Box<[Slot<T>]> = (0..cap)
.map(|i| {
// Set the stamp to `{ lap: 0, mark: 0, index: i }`.
Slot {
Expand All @@ -119,9 +119,7 @@ impl<T> Channel<T> {
}
})
.collect();
let ptr = boxed.as_mut_ptr();
mem::forget(boxed);
ptr
Box::into_raw(boxed) as *mut Slot<T>
};

Channel {
Expand Down
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
59 changes: 51 additions & 8 deletions crossbeam-channel/tests/golang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,9 @@ macro_rules! go {
mod doubleselect {
use super::*;

#[cfg(miri)]
const ITERATIONS: i32 = 100;
#[cfg(not(miri))]
const ITERATIONS: i32 = 10_000;

fn sender(n: i32, c1: Chan<i32>, c2: Chan<i32>, c3: Chan<i32>, c4: Chan<i32>) {
Expand Down Expand Up @@ -691,6 +694,11 @@ mod select {
mod select2 {
use super::*;

#[cfg(miri)]
const N: i32 = 1000;
#[cfg(not(miri))]
const N: i32 = 100000;

#[test]
fn main() {
fn sender(c: &Chan<i32>, n: i32) {
Expand All @@ -717,15 +725,18 @@ mod select2 {

ALLOCATED.store(0, SeqCst);

go!(c, sender(&c, 100000));
receiver(&c, &dummy, 100000);
go!(c, sender(&c, N));
receiver(&c, &dummy, N);

let alloc = ALLOCATED.load(SeqCst);

go!(c, sender(&c, 100000));
receiver(&c, &dummy, 100000);
go!(c, sender(&c, N));
receiver(&c, &dummy, N);

assert!(!(ALLOCATED.load(SeqCst) > alloc && (ALLOCATED.load(SeqCst) - alloc) > 110000))
assert!(
!(ALLOCATED.load(SeqCst) > alloc
&& (ALLOCATED.load(SeqCst) - alloc) > (N as usize + 10000))
)
}
}

Expand Down Expand Up @@ -913,6 +924,9 @@ mod chan_test {

#[test]
fn test_chan() {
#[cfg(miri)]
const N: i32 = 20;
#[cfg(not(miri))]
const N: i32 = 200;

for cap in 0..N {
Expand Down Expand Up @@ -1052,6 +1066,9 @@ mod chan_test {

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

for _ in 0..N {
Expand All @@ -1073,6 +1090,9 @@ mod chan_test {

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

let done = make::<bool>(1);
Expand Down Expand Up @@ -1106,6 +1126,9 @@ mod chan_test {

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

let done = make::<bool>(1);
Expand Down Expand Up @@ -1142,6 +1165,11 @@ mod chan_test {
// Ensure that send/recv on the same chan in select
// does not crash nor deadlock.

#[cfg(miri)]
const N: usize = 100;
#[cfg(not(miri))]
const N: usize = 1000;

for &cap in &[0, 10] {
let wg = WaitGroup::new();
wg.add(2);
Expand All @@ -1151,7 +1179,7 @@ mod chan_test {
let p = p;
go!(wg, p, c, {
defer! { wg.done() }
for i in 0..1000 {
for i in 0..N {
if p == 0 || i % 2 == 0 {
select! {
send(c.tx(), p) -> _ => {}
Expand Down Expand Up @@ -1180,15 +1208,18 @@ mod chan_test {

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

let c = vec![
make::<i32>(0),
make::<i32>(0),
make::<i32>(2),
make::<i32>(3),
];

const N: usize = 10000;

// There are 4 goroutines that send N values on each of the chans,
// + 4 goroutines that receive N values on each of the chans,
// + 1 goroutine that sends N values on each of the chans in a single select,
Expand Down Expand Up @@ -1286,6 +1317,9 @@ mod chan_test {

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

let c1 = make::<u8>(TRIALS + 1);
Expand Down Expand Up @@ -1369,6 +1403,9 @@ mod chan_test {

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

for cap in 0..N {
Expand Down Expand Up @@ -1412,6 +1449,9 @@ mod chan_test {
#[test]
fn test_multi_consumer() {
const NWORK: usize = 23;
#[cfg(miri)]
const NITER: usize = 100;
#[cfg(not(miri))]
const NITER: usize = 271828;

let pn = [2, 3, 7, 11, 13, 17, 19, 23, 27, 31];
Expand Down Expand Up @@ -1510,6 +1550,9 @@ mod chan1 {
use super::*;

// sent messages
#[cfg(miri)]
const N: usize = 100;
#[cfg(not(miri))]
const N: usize = 1000;
// receiving "goroutines"
const M: usize = 10;
Expand Down
29 changes: 28 additions & 1 deletion 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 @@ -310,6 +319,9 @@ fn stress_oneshot() {

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

let (request_s, request_r) = unbounded();
Expand Down Expand Up @@ -371,8 +383,11 @@ fn stress_timeout_two_threads() {
.unwrap();
}

#[cfg_attr(miri, ignore)] // Miri is too slow
#[test]
fn drops() {
const RUNS: usize = 100;

static DROPS: AtomicUsize = AtomicUsize::new(0);

#[derive(Debug, PartialEq)]
Expand All @@ -386,7 +401,7 @@ fn drops() {

let mut rng = thread_rng();

for _ in 0..100 {
for _ in 0..RUNS {
let steps = rng.gen_range(0..10_000);
let additional = rng.gen_range(0..1000);

Expand Down Expand Up @@ -421,6 +436,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 +459,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 +484,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 +520,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
Loading