1use crate::SequentialSpec;
2
3#[derive(Clone, Debug, Hash, PartialEq)]
6#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
7pub enum VecOp<T> {
8 Push(T),
9 Pop,
10 Len,
11}
12
13#[derive(Clone, Debug, Hash, PartialEq)]
15#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
16pub enum VecRet<T> {
17 PushOk,
18 PopOk(Option<T>),
19 LenOk(usize),
20}
21
22impl<T> SequentialSpec for Vec<T>
23where
24 T: Clone + PartialEq,
25{
26 type Op = VecOp<T>;
27 type Ret = VecRet<T>;
28 fn invoke(&mut self, op: &Self::Op) -> Self::Ret {
29 match op {
30 VecOp::Push(v) => {
31 self.push(v.clone());
32 VecRet::PushOk
33 }
34 VecOp::Pop => VecRet::PopOk(self.pop()),
35 VecOp::Len => VecRet::LenOk(self.len()),
36 }
37 }
38 fn is_valid_step(&mut self, op: &Self::Op, ret: &Self::Ret) -> bool {
39 match (op, ret) {
41 (VecOp::Push(v), VecRet::PushOk) => {
42 self.push(v.clone());
43 true
44 }
45 (VecOp::Pop, VecRet::PopOk(v)) => &self.pop() == v,
46 (VecOp::Len, VecRet::LenOk(l)) => &self.len() == l,
47 _ => false,
48 }
49 }
50}
51
52#[cfg(test)]
53mod test {
54 use super::*;
55
56 #[test]
57 fn models_expected_semantics() {
58 let mut v = vec!['A'];
59 assert_eq!(v.invoke(&VecOp::Len), VecRet::LenOk(1));
60 assert_eq!(v.invoke(&VecOp::Push('B')), VecRet::PushOk);
61 assert_eq!(v.invoke(&VecOp::Len), VecRet::LenOk(2));
62 assert_eq!(v.invoke(&VecOp::Pop), VecRet::PopOk(Some('B')));
63 assert_eq!(v.invoke(&VecOp::Len), VecRet::LenOk(1));
64 assert_eq!(v.invoke(&VecOp::Pop), VecRet::PopOk(Some('A')));
65 assert_eq!(v.invoke(&VecOp::Len), VecRet::LenOk(0));
66 assert_eq!(v.invoke(&VecOp::Pop), VecRet::PopOk(None));
67 assert_eq!(v.invoke(&VecOp::Len), VecRet::LenOk(0));
68 }
69
70 #[test]
71 fn accepts_valid_histories() {
72 assert!(Vec::<isize>::new().is_valid_history(vec![]));
73 assert!(Vec::new().is_valid_history(vec![
74 (VecOp::Push(10), VecRet::PushOk),
75 (VecOp::Push(20), VecRet::PushOk),
76 (VecOp::Len, VecRet::LenOk(2)),
77 (VecOp::Pop, VecRet::PopOk(Some(20))),
78 (VecOp::Len, VecRet::LenOk(1)),
79 (VecOp::Pop, VecRet::PopOk(Some(10))),
80 (VecOp::Len, VecRet::LenOk(0)),
81 (VecOp::Pop, VecRet::PopOk(None)),
82 ]));
83 }
84
85 #[test]
86 fn rejects_invalid_histories() {
87 assert!(!Vec::new().is_valid_history(vec![
88 (VecOp::Push(10), VecRet::PushOk),
89 (VecOp::Push(20), VecRet::PushOk),
90 (VecOp::Len, VecRet::LenOk(1)),
91 (VecOp::Push(30), VecRet::PushOk),
92 ]));
93 assert!(!Vec::new().is_valid_history(vec![
94 (VecOp::Push(10), VecRet::PushOk),
95 (VecOp::Push(20), VecRet::PushOk),
96 (VecOp::Pop, VecRet::PopOk(Some(10))),
97 ]));
98 }
99}