#分布式系统 #Paxos #Raft #Actor #模拟 #模型检查

fibril_verifier

验证使用纤维库实现的分布式系统的行为

13 个版本

0.0.12 2023 年 6 月 5 日
0.0.11 2023 年 6 月 4 日
0.0.10 2023 年 2 月 12 日
0.0.8 2023 年 1 月 17 日

#1113 in 并发

MIT/Apache

170KB
3.5K SLoC

纤维验证器

纤维验证器是一个用于模型检查 Fibril 系统的库。

用法

请参阅 fibril_verifier 的文档。


lib.rs:

纤维验证器是一个用于模型检查 Fibril 系统的库。

示例

[dependencies]
fibril = { version = "0", features = ["fibers", "rt", "serde_json"] }
serde = { version = "1", features = ["derive"] }

[dev-dependencies]
fibril_verifier = "0"
use fibril::*;

#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
enum Msg { Inc, Double, Value(u64) }

fn server(sdk: Sdk<Msg>) {
    let mut val = 0;
    loop {
        let (src, msg) = sdk.recv();
        match msg {
            Msg::Inc => {
                val += 1;
                sdk.send(src, Msg::Value(val));
            }
            Msg::Double => {
                val *= 2;
                sdk.send(src, Msg::Value(val));
            }
            _ => sdk.exit(),
        }
    }
}

// In the binary, bind the server to a UDP socket.
fn run_server_over_udp() {
    use std::net::Ipv4Addr;
    let mut rt = UdpRuntime::new_with_serde_json()
        .ipv4(Ipv4Addr::LOCALHOST)
        .port_fn(|n| 3000 + n);
    rt.spawn(|| Fiber::new(server));
    rt.join().unwrap();
}

// In the tests, the model checker will attempt to find a "trace" (sequence of steps) that
// causes a panic.
#[cfg(test)]
#[test]
fn may_panic() {
    use fibril_verifier::*;
    let mut verifier = Verifier::new(|cfg| {
        let server = cfg.spawn(Fiber::new(server));
        cfg.spawn(Fiber::new(move |sdk| {
            sdk.send(server, Msg::Inc);
            let (_src, msg) = sdk.recv();
            assert_eq!(msg, Msg::Value(1)); // truth depends on race winner
        }));
        cfg.spawn(Fiber::new(move |sdk| {
            sdk.send(server, Msg::Double);
            let (_src, msg) = sdk.recv();
            assert_eq!(msg, Msg::Value(2)); // truth depends on race winner
        }));
    });
    // TIP: alternatively use verifier.assert_no_panic() to fail the test.
    let (msg, _minimal_trace) = verifier.assert_panic();
    assert!(msg.contains("left == right"));
}

以下是一个使用 netcat 与服务器交互的示例。

# send STDOUT to disk for clarity as replies are not newline delimited
$ nc -u 127.0.0.1 3000 > /tmp/replies
"Inc"
"Inc"
"Double"
^C

$ cat /tmp/replies
{"Value":1}{"Value":2}{"Value":4}

依赖项

~4–14MB
~155K SLoC