1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//! adya: a black-box checker for transactional isolation.
//!
//! Give it a history of transactions a database executed, and it infers the
//! dependency graph between them (Adya's write-write, write-read and
//! read-write edges, plus process and real-time order), then hunts for the
//! cycles that each isolation level forbids.
//!
//! ```
//! use adya::{check, History, Opts, Valid, Workload};
//!
//! // Two transactions each read both keys as empty, then append to a
//! // different one: write skew, legal under snapshot isolation only.
//! let h = History::from_json(r#"
//! {"type":"invoke","process":0,"value":[["r","x",null],["r","y",null],["append","x",1]]}
//! {"type":"invoke","process":1,"value":[["r","x",null],["r","y",null],["append","y",1]]}
//! {"type":"ok","process":0,"value":[["r","x",[]],["r","y",[]],["append","x",1]]}
//! {"type":"ok","process":1,"value":[["r","x",[]],["r","y",[]],["append","y",1]]}
//! "#).unwrap();
//!
//! let serializable = Opts { models: vec!["serializable".into()], ..Opts::default() };
//! let r = check(&h, Workload::ListAppend, &serializable);
//! assert_eq!(r.valid, Valid::False);
//! assert_eq!(r.anomaly_types, ["G2-item"]);
//!
//! let si = Opts { models: vec!["snapshot-isolation".into()], ..Opts::default() };
//! assert_eq!(check(&h, Workload::ListAppend, &si).valid, Valid::True);
//! ```
pub use ;
pub use History;
use fmt;