traceforge 0.2.1

TraceForge is a model checker for concurrent and distributed programs written in Rust
Documentation
use traceforge_macros::monitor;

use traceforge::*;

use traceforge::thread::{self, JoinHandle, ThreadId};

use traceforge::monitor_types::*;

const TEST_RUNS: u32 = 1;

#[derive(Debug, Clone, PartialEq)]
pub enum Msg {
    Start(traceforge::thread::ThreadId),
    Int(u32),
}

#[monitor(Msg)]
#[derive(Clone, Debug, Default)]
pub struct MyMonitor {
    value: u32,
}

impl MyMonitor {
    pub fn new() -> Self {
        Self { value: 0 }
    }
}

impl Monitor for MyMonitor {}

impl Observer<Msg> for MyMonitor {
    fn notify(&mut self, _who: ThreadId, _whom: ThreadId, what: &Msg) -> MonitorResult {
        let old_value = self.value;
        if let Msg::Int(x) = what {
            self.value = *x;
        }
        if old_value > self.value {
            return Err("ordering error".to_string());
        }
        Ok(())
    }
}

impl Acceptor<Msg> for MyMonitor {
    fn accept(&mut self, _who: ThreadId, _whom: ThreadId, what: &Msg) -> bool {
        matches!(what, Msg::Int(_))
    }
}

#[test]
fn advanced_monitor() {
    for _ in 0..TEST_RUNS {
        let stats = crate::verify(
            crate::Config::builder()
                .with_policy(crate::SchedulePolicy::Arbitrary)
                .with_verbose(2)
                .with_seed(15528329211881264680)
                .with_cons_type(ConsType::FIFO)
                .build(),
            || {
                let _mtid1: JoinHandle<MonitorResult> =
                    start_monitor_my_monitor(MyMonitor { value: 0 });

                let tid1 = thread::spawn(|| {
                    let mtid2: Msg = crate::recv_msg_block();
                    if let Msg::Start(tid2) = mtid2 {
                        crate::send_msg(tid2, Msg::Int(1));
                        let _: Msg = crate::recv_msg_block();
                    }
                });
                let tid2 = thread::spawn(|| {
                    let mtmain: Msg = crate::recv_msg_block();
                    let mtid1: Msg = crate::recv_msg_block();
                    if let Msg::Start(tmain) = mtmain {
                        if let Msg::Start(tid1) = mtid1 {
                            crate::send_msg(tmain, Msg::Int(0));
                            let _: Msg = crate::recv_msg_block();
                            crate::send_msg(tid1, Msg::Int(2));
                        }
                    }
                });

                let tid1 = tid1.thread().id();
                let tid2 = tid2.thread().id();

                crate::send_msg(tid2, Msg::Start(thread::current().id()));
                crate::send_msg(tid2, Msg::Start(tid1));
                let _: Msg = crate::recv_msg_block();

                crate::send_msg(tid1, Msg::Start(tid2));
            },
        );
        println!("Number of execs: {} blocks: {}", stats.execs, stats.block);
        assert_eq!(stats.execs, 1);
        assert_eq!(stats.block, 0);
    }
}