diff --git a/src/issue.rs b/src/issue.rs new file mode 100644 index 0000000..7ad4c6c --- /dev/null +++ b/src/issue.rs @@ -0,0 +1,69 @@ +#[cfg(test)] +mod test { + use crate::test_dsl::*; + use crate::test_dsl::dsl::*; + + #[test] + #[rustfmt::skip] + fn issue_append_cancel() { + use Command::*; + use LogEntry::*; + + let a = NodeName(0); + let b = NodeName(1); + let c = NodeName(2); + let (mut service, _cluster) = build_complete_graph(&[a, b, c]); + + interpret( + &vec![ + RunAllUntilStabilize, + Timeout(a), + RunAllUntilStabilize, + + // aがリーダーになっていることを確認する + Check(a, Pred::IsLeader), + Check(b, Pred::IsFollower), + Check(c, Pred::IsFollower), + + // a-x->c + RecvBan(c, a), + + Propose(a), Propose(a), Propose(a), + Heartbeat(a), + + Step(a), Step(a), Step(a), Step(b), + Step(a), Step(a), Step(a), Step(b), + + // bで + // history: 22 + // log : 2222 + // の形にする。 + Dump(b), + + // aを孤立させて + RecvBan(b, a), + + // bとcをタイムアウトさせ + Timeout(b), Timeout(c), + RunAllUntilStabilize, + Timeout(b), + RunAllUntilStabilize, + + // bをリーダーにする + Check(b, Pred::IsLeader), + Check(c, Pred::IsFollower), + + // bは以下のようになっている + // history: 224 + // log : 2242 + Dump(b), + + // すなわち、bはInconsistentである。 + // この状態で再起動するとクラッシュする。 + Check(b, Pred::RawLogIs(0, 0, vec![Noop(2), Com(2), Noop(4), Com(2)])), + Check(b, Pred::Not(Box::new(Pred::LogTermConsistency))), + ], + &mut service, + ); + } +} diff --git a/src/lib.rs b/src/lib.rs index 05ce6ff..9b60e3b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,6 +22,7 @@ pub mod message; pub mod metrics; pub mod node; pub mod test_dsl; +pub mod issue; mod error; mod io; diff --git a/src/test_dsl/dsl.rs b/src/test_dsl/dsl.rs index 58ad649..5a0e1f9 100644 --- a/src/test_dsl/dsl.rs +++ b/src/test_dsl/dsl.rs @@ -16,7 +16,7 @@ use std::fmt; /// DSL中でノード名を表すために用いる構造体 /// 現時点ではu8のnewtypeに過ぎない #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] -pub struct NodeName(u8); +pub struct NodeName(pub u8); impl fmt::Display for NodeName { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/src/test_dsl/impl_io.rs b/src/test_dsl/impl_io.rs index cdefc93..ed56d79 100644 --- a/src/test_dsl/impl_io.rs +++ b/src/test_dsl/impl_io.rs @@ -342,7 +342,7 @@ impl Io for TestIo { } self.snapshot = Some(prefix); - LogSaver(SaveMode::SnapshotSave, self.node_id.clone()) + LogSaver(SaveMode::SnapshotSave, self.node_id.clone(), 2) } fn save_log_suffix(&mut self, suffix: &LogSuffix) -> Self::SaveLog { self.io_events.push(IOEvent::SaveSuffix); @@ -359,7 +359,7 @@ impl Io for TestIo { self.rawlog = Some(suffix.clone()); } - LogSaver(SaveMode::RawLogSave, self.node_id.clone()) + LogSaver(SaveMode::RawLogSave, self.node_id.clone(), 2) } type LoadLog = LogLoader; @@ -518,12 +518,17 @@ enum SaveMode { } /// ログ保存を表現するためのfuture(の実体) -pub struct LogSaver(SaveMode, pub NodeId); +pub struct LogSaver(SaveMode, pub NodeId, u8); impl Future for LogSaver { type Item = (); type Error = Error; fn poll(&mut self) -> Poll { - Ok(Async::Ready(())) + if self.2 == 0 { + Ok(Async::Ready(())) + } else { + self.2 -= 1; + Ok(Async::NotReady) + } } }