use lincheck::{ConcurrentSpec, Lincheck, SequentialSpec}; use loom::sync::Mutex; use proptest::prelude::*; #[derive(Debug, Clone, Copy, PartialEq, Eq)] enum Op { Push(T), Pop, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] enum Ret { Push, Pop(Option), } impl Arbitrary for Op { type Parameters = (); type Strategy = BoxedStrategy; fn arbitrary_with(_: Self::Parameters) -> Self::Strategy { prop_oneof![any::().prop_map(Op::Push), Just(Op::Pop),].boxed() } } struct SequentialStack { stack: Vec, } impl Default for SequentialStack { fn default() -> Self { Self { stack: Vec::new() } } } impl SequentialSpec for SequentialStack { type Op = Op; type Ret = Ret; fn exec(&mut self, op: Self::Op) -> Self::Ret { match op { Op::Push(value) => { self.stack.push(value); Ret::Push } Op::Pop => Ret::Pop(self.stack.pop()), } } } struct ConcurrentStack { stack: Mutex>, } impl Default for ConcurrentStack { fn default() -> Self { Self { stack: Mutex::new(Vec::new()), } } } impl ConcurrentSpec for ConcurrentStack { type Seq = SequentialStack; fn exec(&self, op: Op) -> Ret { let mut stack = self.stack.lock().unwrap(); match op { Op::Push(value) => { stack.push(value); Ret::Push } Op::Pop => Ret::Pop(stack.pop()), } } } #[test] fn models_stack() { Lincheck::default().verify_or_panic::>(); }