model 0.1.2

model-based testing for data structures, with linearizability checking
Documentation
use model::{linearizable, model};

#[test]
fn test_model() {
    use std::sync::atomic::{AtomicUsize, Ordering};

    model! {
        Model => let m = AtomicUsize::new(0),
        Implementation => let mut i: usize = 0,
        Add(usize)(v in 0usize..4) => {
            let expected = m.fetch_add(v, Ordering::SeqCst) + v;
            i += v;
            assert_eq!(expected, i);
        },
        Set(usize)(v in 0usize..4) => {
            m.store(v, Ordering::SeqCst);
            i = v;
        },
        Eq(usize)(v in 0usize..4) => {
            let expected = m.load(Ordering::SeqCst) == v;
            let actual = i == v;
            assert_eq!(expected, actual);
        },
        Cas((usize, usize))((old, new) in (0usize..4, 0usize..4)) => {
            let expected =
                m.compare_and_swap(old, new, Ordering::SeqCst);
            let actual = if i == old {
                i = new;
                old
            } else {
                i
            };
            assert_eq!(expected, actual);
        }
    }
}

#[test]
#[should_panic]
fn test_linearizability_of_bad_impl() {
    use model::Shared;
    use std::sync::atomic::{AtomicUsize, Ordering};

    linearizable! {
        Implementation => let i = Shared::new(AtomicUsize::new(0)),
        BuggyAdd(usize)(v in 0usize..4) -> usize {
            let current = i.load(Ordering::SeqCst);
            std::thread::yield_now();
            i.store(current + v, Ordering::SeqCst);
            current + v
        },
        Set(usize)(v in 0usize..4) -> () {
            i.store(v, Ordering::SeqCst)
        },
        BuggyCas((usize, usize))((old, new) in (0usize..4, 0usize..4)) -> usize {
            let current = i.load(Ordering::SeqCst);
            std::thread::yield_now();
            if current == old {
                i.store(new, Ordering::SeqCst);
                new
            } else {
                current
            }
        }
    }
}

#[test]
fn test_linearizability_of_good_impl() {
    use model::Shared;
    use std::sync::atomic::{AtomicUsize, Ordering};

    linearizable! {
        Implementation => let i = Shared::new(AtomicUsize::new(0)),
        Add(usize)(v in 0usize..4) -> usize {
            i.fetch_add(v, Ordering::SeqCst)
        },
        Set(usize)(v in 0usize..4) -> () {
            i.store(v, Ordering::SeqCst)
        },
        Cas((usize, usize))((old, new) in (0usize..4, 0usize..4)) -> usize {
            i.compare_and_swap(old, new, Ordering::SeqCst)
        }
    }
}