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
72
73
74
75
76
77
78
79
80
81
82
use node::NodeType;
#[derive(Debug, Clone)]
pub struct Guard {
pub path: String,
pub version: u64
}
#[derive(Debug, Clone)]
pub enum WriteOp {
CreateNode { path: String, ty: NodeType },
DeleteNode { path: String },
BlobPut { path: String, val: Vec<u8> },
QueuePush { path: String, val: Vec<u8> },
QueuePop { path: String },
SetInsert { path: String, val: Vec<u8> },
SetRemove { path: String, val: Vec<u8> },
Snapshot { directory: String }
}
#[cfg(test)]
mod tests {
use quickcheck::{Arbitrary, Gen};
use tree::{Tree, Reply};
use node::NodeType;
use super::WriteOp;
use rand::distributions::range::Range;
use rand::distributions::IndependentSample;
use arbitrary::Path;
#[cfg_attr(rustfmt, rustfmt_skip)]
impl Arbitrary for WriteOp {
fn arbitrary<G: Gen>(g: &mut G) -> WriteOp {
let range = Range::new(1u8, 8u8);
let path = Path::arbitrary(g).0;
let mut val: Vec<u8> = vec![0; 5];
g.fill_bytes(&mut val);
match range.ind_sample(g) {
1 => WriteOp::CreateNode {path: path, ty: NodeType::arbitrary(g)},
2 => WriteOp::DeleteNode {path: path},
3 => WriteOp::BlobPut {path: path, val: val},
4 => WriteOp::QueuePush {path: path, val: val},
5 => WriteOp::QueuePop {path: path},
6 => WriteOp::SetInsert {path: path, val: val},
7 => WriteOp::SetRemove {path: path, val: val},
_ => unreachable!()
}
}
}
quickcheck! {
fn prop_multi_cas_equals_individual_ops(ops: Vec<WriteOp>) -> bool {
let tree = Tree::new();
let (filtered_ops, individual_replies, individual_tree) = filter_by_valid(ops);
let (replies, new_tree) = tree.multi_cas(vec![], filtered_ops).unwrap();
new_tree.iter().zip(individual_tree.iter())
.all(|(node1, node2)| node1 == node2) && (replies == individual_replies)
}
}
fn filter_by_valid<'a>(ops: Vec<WriteOp>) -> (Vec<WriteOp>, Vec<Reply>, Tree) {
ops.into_iter()
.fold((Vec::new(), Vec::new(), Tree::new()), |(mut ops, mut replies, tree), op| {
match tree.multi_cas(vec![], vec![op.clone()]) {
Ok((new_replies, new_tree)) => {
ops.push(op);
replies.extend(new_replies);
(ops, replies, new_tree)
}
Err(_) => (ops, replies, tree),
}
})
}
}