log_array.rs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  1. use serde_derive::{Deserialize, Serialize};
  2. use crate::index_term::IndexTerm;
  3. use crate::{Index, LogEntry, LogEntryEnum, Term};
  4. /// A log array that stores a tail of the whole Raft log.
  5. ///
  6. /// The Raft log represented by the log array has length `end()`. Only log
  7. /// entries after `start()` are physically stored in the log array (with some
  8. /// caveats). The index and term of log entries in range `[start(), end())` are
  9. /// accessible. A snapshot is stored at the beginning of the log array, which
  10. /// covers all commands before and **including** `start()`. The command at
  11. /// `start()` is **not** accessible, but all commands after that are.
  12. ///
  13. /// New entries can be appended to the end of the Raft log via `add_command()`
  14. /// or `push()`.
  15. ///
  16. /// The log array can be truncated to at most one entry, which is at `start()`
  17. /// and contains the snapshot. The start of the log array can be shifted towards
  18. /// `end()`, if another snapshot at that position is provided.
  19. ///
  20. /// The log array can also be reset to a single entry, contains an index, a term
  21. /// and a snapshot, via `reset()`.
  22. ///
  23. /// The log array is guaranteed to have at least one element, containing an
  24. /// index, a term and a snapshot.
  25. ///
  26. /// All APIs **will** panic if the given index(es) are out of bound.
  27. ///
  28. /// NOT THREAD SAFE.
  29. #[derive(Clone, Serialize, Deserialize)]
  30. pub(crate) struct LogArray<C> {
  31. inner: Vec<LogEntry<C>>,
  32. snapshot: Vec<u8>,
  33. }
  34. #[derive(Debug)]
  35. pub(crate) enum ValidationError {
  36. IndexMismatch(Index, Vec<IndexTerm>),
  37. TermSpike(Index, Vec<IndexTerm>),
  38. FutureTerm(Term, Index, Vec<IndexTerm>),
  39. }
  40. impl<C: Default> LogArray<C> {
  41. /// Create the initial Raft log with no user-supplied commands.
  42. pub fn create() -> LogArray<C> {
  43. let ret = LogArray {
  44. inner: vec![Self::build_first_entry(0, Term(0))],
  45. snapshot: vec![],
  46. };
  47. ret.check_one_element();
  48. ret
  49. }
  50. }
  51. // Log accessors
  52. impl<C> LogArray<C> {
  53. /// The start of the stored log entries. The command at this index is no
  54. /// longer accessible, since it is included in the snapshot.
  55. pub fn start(&self) -> Index {
  56. self.first_entry().index
  57. }
  58. /// The end index of the Raft log.
  59. pub fn end(&self) -> Index {
  60. self.start() + self.inner.len()
  61. }
  62. /// The first index and term stored in this log array.
  63. pub fn first_index_term(&self) -> IndexTerm {
  64. self.first_entry().into()
  65. }
  66. /// The last index and term of the Raft log.
  67. pub fn last_index_term(&self) -> IndexTerm {
  68. self.last_entry().into()
  69. }
  70. /// The log entry at the given index.
  71. pub fn at(&self, index: Index) -> &LogEntry<C> {
  72. let index = self.check_at_index(index);
  73. &self.inner[index]
  74. }
  75. /// The first log entry on or after the given index.
  76. pub fn first_after(&self, index: Index) -> &LogEntry<C> {
  77. if index >= self.start() {
  78. self.at(index)
  79. } else {
  80. self.first_entry()
  81. }
  82. }
  83. /// All log entries after the given index.
  84. pub fn after(&self, index: Index) -> &[LogEntry<C>] {
  85. let index = self.check_range_index(index);
  86. &self.inner[index..]
  87. }
  88. /// All log entries in range [start, end).
  89. pub fn between(&self, start: Index, end: Index) -> &[LogEntry<C>] {
  90. let start = self.check_range_index(start);
  91. let end = self.check_range_index(end);
  92. &self.inner[start..end]
  93. }
  94. /// All log entries stored in the array.
  95. #[cfg(test)]
  96. pub fn all(&self) -> &[LogEntry<C>] {
  97. &self.inner[..]
  98. }
  99. /// `IndexTerm` of all log entries, without command.
  100. pub fn all_index_term(&self) -> Vec<IndexTerm> {
  101. self.inner.iter().map(|e| e.into()).collect()
  102. }
  103. /// The snapshot before and including `start()`.
  104. pub fn snapshot(&self) -> (IndexTerm, &[u8]) {
  105. (self.first_index_term(), &self.snapshot)
  106. }
  107. pub fn validate(&self, current_term: Term) -> Result<(), ValidationError> {
  108. let all_index_term = self.all_index_term();
  109. let (mut index, mut term) = all_index_term[0].clone().into();
  110. for entry in all_index_term[1..].iter() {
  111. index += 1;
  112. if entry.index != index {
  113. return Err(ValidationError::IndexMismatch(
  114. index,
  115. all_index_term,
  116. ));
  117. }
  118. if entry.term < term {
  119. return Err(ValidationError::TermSpike(index, all_index_term));
  120. }
  121. if entry.term > current_term {
  122. return Err(ValidationError::FutureTerm(
  123. current_term,
  124. index,
  125. all_index_term,
  126. ));
  127. }
  128. term = entry.term;
  129. }
  130. Ok(())
  131. }
  132. }
  133. // Mutations
  134. impl<C> LogArray<C> {
  135. /// Add a new entry to the Raft log. The new index is returned.
  136. pub fn add_entry(&mut self, term: Term, entry: LogEntryEnum<C>) -> Index {
  137. let index = self.end();
  138. self.push(LogEntry {
  139. index,
  140. term,
  141. command: entry,
  142. });
  143. index
  144. }
  145. /// Add a new entry to the Raft log, with term and command. The new index is
  146. /// returned.
  147. pub fn add_command(&mut self, term: Term, command: C) -> Index {
  148. self.add_entry(term, LogEntryEnum::Command(command))
  149. }
  150. /// Push a LogEntry into the Raft log. The index of the log entry must match
  151. /// the next index in the log.
  152. pub fn push(&mut self, log_entry: LogEntry<C>) {
  153. let index = log_entry.index;
  154. assert_eq!(index, self.end(), "Expecting new index to be exact at len");
  155. self.inner.push(log_entry);
  156. assert_eq!(
  157. index + 1,
  158. self.end(),
  159. "Expecting len increase by one after push",
  160. );
  161. assert_eq!(
  162. self.at(index).index,
  163. index,
  164. "Expecting pushed element to have the same index",
  165. );
  166. self.check_one_element();
  167. }
  168. /// Remove all log entries on and after `index`.
  169. pub fn truncate(&mut self, index: Index) {
  170. let index = self.check_middle_index(index);
  171. self.inner.truncate(index);
  172. self.check_one_element()
  173. }
  174. }
  175. impl<C: Default> LogArray<C> {
  176. /// Shift the start of the array to `index`, and store a new snapshot that
  177. /// covers all commands before and at `index`.
  178. pub fn shift(&mut self, index: Index, snapshot: Vec<u8>) {
  179. // Discard everything before index and store the snapshot.
  180. let offset = self.check_middle_index(index);
  181. // WARNING: Potentially all entries after offset would be copied.
  182. self.inner.drain(0..offset);
  183. self.snapshot = snapshot;
  184. // Override the first entry, we know there is at least one entry. This
  185. // is not strictly needed. One benefit is that the command can be
  186. // released after this point.
  187. let first = self.first_index_term();
  188. self.inner[0] = Self::build_first_entry(first.index, first.term);
  189. assert_eq!(
  190. first.index, index,
  191. "Expecting the first entry to have the same index."
  192. );
  193. self.check_one_element()
  194. }
  195. /// Reset the array to contain only one snapshot at the given `index` with
  196. /// the given `term`.
  197. pub fn reset(
  198. &mut self,
  199. index: Index,
  200. term: Term,
  201. snapshot: Vec<u8>,
  202. ) -> Vec<LogEntry<C>> {
  203. let mut inner = vec![Self::build_first_entry(index, term)];
  204. std::mem::swap(&mut inner, &mut self.inner);
  205. self.snapshot = snapshot;
  206. self.check_one_element();
  207. inner
  208. }
  209. }
  210. impl<C> LogArray<C> {
  211. fn first_entry(&self) -> &LogEntry<C> {
  212. self.inner
  213. .first()
  214. .expect("There must be at least one element in log")
  215. }
  216. fn last_entry(&self) -> &LogEntry<C> {
  217. self.inner
  218. .last()
  219. .expect("There must be at least one entry in log")
  220. }
  221. fn offset(&self, index: Index) -> usize {
  222. index - self.start()
  223. }
  224. fn check_at_index(&self, index: Index) -> usize {
  225. assert!(
  226. index >= self.start() && index < self.end(),
  227. "Accessing start log index {} out of range [{}, {})",
  228. index,
  229. self.start(),
  230. self.end()
  231. );
  232. self.offset(index)
  233. }
  234. fn check_range_index(&self, index: Index) -> usize {
  235. assert!(
  236. index >= self.start() && index <= self.end(),
  237. "Accessing end log index {} out of range [{}, {}]",
  238. index,
  239. self.start(),
  240. self.end()
  241. );
  242. self.offset(index)
  243. }
  244. fn check_middle_index(&self, index: Index) -> usize {
  245. assert!(
  246. index > self.start() && index < self.end(),
  247. "Log index {} out of range ({}, {})",
  248. index,
  249. self.start(),
  250. self.end()
  251. );
  252. self.offset(index)
  253. }
  254. #[allow(clippy::len_zero)]
  255. fn check_one_element(&self) {
  256. assert!(
  257. self.inner.len() >= 1,
  258. "There must be at least one element in log"
  259. )
  260. }
  261. }
  262. impl<C> LogArray<C> {
  263. fn build_first_entry(index: Index, term: Term) -> LogEntry<C> {
  264. LogEntry {
  265. index,
  266. term,
  267. command: LogEntryEnum::Noop,
  268. }
  269. }
  270. }
  271. #[cfg(test)]
  272. mod tests {
  273. use std::panic::catch_unwind;
  274. use super::*;
  275. impl<C> std::ops::Index<usize> for LogArray<C> {
  276. type Output = LogEntry<C>;
  277. fn index(&self, index: usize) -> &Self::Output {
  278. self.at(index)
  279. }
  280. }
  281. fn make_log_array(len: usize) -> LogArray<i32> {
  282. make_log_array_range(0, len)
  283. }
  284. fn make_log_array_range(start: usize, end: usize) -> LogArray<i32> {
  285. let mut ret = vec![];
  286. for i in start..end {
  287. ret.push(LogEntry {
  288. term: Term(i / 3),
  289. index: i,
  290. command: LogEntryEnum::Command((end - i) as i32),
  291. })
  292. }
  293. LogArray {
  294. inner: ret,
  295. snapshot: vec![1, 2, 3],
  296. }
  297. }
  298. fn default_log_array() -> (usize, usize, LogArray<i32>) {
  299. (8, 17, make_log_array_range(8, 17))
  300. }
  301. #[test]
  302. fn test_create() {
  303. let log = LogArray::<i32>::create();
  304. log.check_one_element();
  305. assert_eq!(1, log.end());
  306. assert_eq!((0, Term(0)), log.first_index_term().into());
  307. assert_eq!(LogEntryEnum::Noop, log[0].command);
  308. }
  309. #[test]
  310. fn test_start() {
  311. let log = make_log_array_range(9, 17);
  312. assert_eq!(9, log.start());
  313. let log = make_log_array(9);
  314. assert_eq!(0, log.start());
  315. }
  316. #[test]
  317. fn test_end() {
  318. let log = make_log_array(7);
  319. assert_eq!(7, log.end());
  320. let log = make_log_array_range(8, 17);
  321. assert_eq!(17, log.end());
  322. }
  323. #[test]
  324. fn test_accessors() {
  325. let (start, end, log) = default_log_array();
  326. assert_eq!((start, Term(2)), log.first_index_term().into());
  327. assert_eq!((end - 1, Term(5)), log.last_index_term().into());
  328. assert_eq!(
  329. ((start, Term(2)).into(), [1, 2, 3].as_ref()),
  330. log.snapshot()
  331. );
  332. let all = log.all();
  333. assert_eq!(end - start, all.len());
  334. for i in start..end {
  335. assert_eq!(all[i - start].index, i);
  336. }
  337. }
  338. #[test]
  339. fn test_at() {
  340. let (start, end, log) = default_log_array();
  341. let last = log.at(end - 1);
  342. assert_eq!(end - 1, last.index);
  343. assert_eq!(5, last.term.0);
  344. assert_eq!(LogEntryEnum::Command(1), last.command);
  345. let first = log.at(start);
  346. assert_eq!(start, first.index);
  347. assert_eq!(2, first.term.0);
  348. assert_eq!(LogEntryEnum::Command(9), first.command);
  349. assert!(start < 12);
  350. assert!(end > 12);
  351. let middle = log.at(12);
  352. assert_eq!(12, middle.index);
  353. assert_eq!(4, middle.term.0);
  354. assert_eq!(LogEntryEnum::Command(5), middle.command);
  355. let at_before_start = catch_unwind(|| {
  356. log.at(start - 1);
  357. });
  358. assert!(at_before_start.is_err());
  359. let at_after_end = catch_unwind(|| {
  360. log.at(end);
  361. });
  362. assert!(at_after_end.is_err());
  363. }
  364. #[test]
  365. fn test_first_after() {
  366. let (start, _, log) = default_log_array();
  367. assert_eq!(log.first_after(0).index, log.first_entry().index);
  368. assert_eq!(log.first_after(start).index, log.at(start).index);
  369. assert_eq!(log.first_after(start + 1).index, log.at(start + 1).index);
  370. assert_ne!(log.first_after(0).index, log.first_after(start + 1).index);
  371. }
  372. #[test]
  373. fn test_index_operator() {
  374. let (start, end, log) = default_log_array();
  375. for i in start..end {
  376. assert_eq!(log[i].index, log.at(i).index);
  377. assert_eq!(log[i].term, log.at(i).term);
  378. assert_eq!(log[i].command, log.at(i).command);
  379. }
  380. assert!(catch_unwind(|| log[0].term).is_err());
  381. assert!(catch_unwind(|| log[20].term).is_err());
  382. }
  383. #[test]
  384. fn test_after() {
  385. let (start, end, log) = default_log_array();
  386. let offset = 12;
  387. assert!(offset > start);
  388. assert!(offset < end);
  389. let after = log.after(offset);
  390. assert_eq!(end - offset, after.len());
  391. for i in offset..end {
  392. assert_eq!(after[i - offset].index, i);
  393. assert_eq!(after[i - offset].term.0, i / 3);
  394. }
  395. assert!(catch_unwind(|| log.after(start - 1)).is_err());
  396. assert!(catch_unwind(|| log.after(start)).is_ok());
  397. assert!(catch_unwind(|| log.after(end)).is_ok());
  398. assert!(catch_unwind(|| log.after(end + 1)).is_err());
  399. }
  400. #[test]
  401. fn test_between() {
  402. let (start, end, log) = default_log_array();
  403. let between = log.between(start + 2, end);
  404. assert_eq!(end - start - 2, between.len());
  405. for i in start + 2..end {
  406. assert_eq!(between[i - start - 2].index, i);
  407. assert_eq!(between[i - start - 2].term.0, i / 3);
  408. }
  409. assert!(catch_unwind(|| log.between(start - 1, end)).is_err());
  410. assert!(catch_unwind(|| log.between(start + 2, end + 1)).is_err());
  411. assert!(catch_unwind(|| log.between(start, end)).is_ok());
  412. }
  413. #[test]
  414. fn test_add_command() {
  415. let (_, end, mut log) = default_log_array();
  416. let index = log.add_command(Term(8), 9);
  417. assert_eq!(8, log.at(index).term.0);
  418. assert_eq!(LogEntryEnum::Command(9), log.at(index).command);
  419. assert_eq!(index, end);
  420. assert_eq!(index + 1, log.end());
  421. }
  422. #[test]
  423. fn test_push() {
  424. let (_, end, mut log) = default_log_array();
  425. log.push(LogEntry {
  426. term: Term(8),
  427. index: end,
  428. command: LogEntryEnum::Command(1),
  429. });
  430. assert_eq!(8, log.at(end).term.0);
  431. assert_eq!(LogEntryEnum::Command(1), log.at(end).command);
  432. assert_eq!(end + 1, log.end());
  433. }
  434. #[test]
  435. #[should_panic]
  436. fn test_push_small_index() {
  437. let (_, end, mut log) = default_log_array();
  438. log.push(LogEntry {
  439. term: Term(8),
  440. index: end - 1,
  441. command: LogEntryEnum::Command(1),
  442. });
  443. }
  444. #[test]
  445. #[should_panic]
  446. fn test_push_big_index() {
  447. let (_, end, mut log) = default_log_array();
  448. log.push(LogEntry {
  449. term: Term(8),
  450. index: end + 1,
  451. command: LogEntryEnum::Command(1),
  452. });
  453. }
  454. #[test]
  455. fn test_truncate() {
  456. let (start, _, mut log) = default_log_array();
  457. log.truncate(start + 5);
  458. assert_eq!(start + 5, log.end());
  459. for i in start..start + 5 {
  460. assert_eq!(log[i].index, i);
  461. assert_eq!(log[i].term.0, i / 3);
  462. }
  463. log.truncate(start + 1);
  464. assert_eq!(1, log.all().len());
  465. }
  466. #[test]
  467. #[should_panic]
  468. fn test_truncate_at_start() {
  469. let (start, _, mut log) = default_log_array();
  470. log.truncate(start);
  471. }
  472. #[test]
  473. #[should_panic]
  474. fn test_truncate_at_end() {
  475. let (_, end, mut log) = default_log_array();
  476. log.truncate(end);
  477. }
  478. #[test]
  479. #[should_panic]
  480. fn test_truncate_before_start() {
  481. let (start, _, mut log) = default_log_array();
  482. log.truncate(start - 1);
  483. }
  484. #[test]
  485. #[should_panic]
  486. fn test_truncate_after_end() {
  487. let (_, end, mut log) = default_log_array();
  488. log.truncate(end + 1);
  489. }
  490. #[test]
  491. fn test_shift() {
  492. let (start, end, mut log) = default_log_array();
  493. let offset = 10;
  494. assert!(offset > start);
  495. assert!(offset < end);
  496. log.shift(offset, vec![]);
  497. assert_eq!((offset, Term(3)), log.first_index_term().into());
  498. assert_eq!(LogEntryEnum::Noop, log[offset].command);
  499. let all = log.all();
  500. assert_eq!(end - offset, all.len());
  501. for i in offset..end {
  502. assert_eq!(i, all[i - offset].index);
  503. assert_eq!(i / 3, all[i - offset].term.0);
  504. }
  505. assert_eq!(log.snapshot, vec![]);
  506. }
  507. #[test]
  508. #[should_panic]
  509. fn test_shift_before_start() {
  510. let (start, end, mut log) = default_log_array();
  511. assert!(start < end);
  512. log.shift(start - 1, vec![]);
  513. }
  514. #[test]
  515. #[should_panic]
  516. fn test_shift_at_start() {
  517. let (start, end, mut log) = default_log_array();
  518. assert!(start < end);
  519. log.shift(start, vec![]);
  520. }
  521. #[test]
  522. #[should_panic]
  523. fn test_shift_at_end() {
  524. let (start, end, mut log) = default_log_array();
  525. assert!(start < end);
  526. log.shift(end, vec![]);
  527. }
  528. #[test]
  529. #[should_panic]
  530. fn test_shift_after_end() {
  531. let (start, end, mut log) = default_log_array();
  532. assert!(start < end);
  533. log.shift(end + 1, vec![]);
  534. }
  535. #[test]
  536. fn test_reset() {
  537. let (start, end, mut log) = default_log_array();
  538. let dump = log.reset(88, Term(99), vec![1, 2]);
  539. assert_eq!(1, log.all().len());
  540. assert_eq!(vec![1, 2], log.snapshot);
  541. assert_eq!(88, log[88].index);
  542. assert_eq!(99, log[88].term.0);
  543. assert_eq!(LogEntryEnum::Noop, log[88].command);
  544. assert_eq!(end - start, dump.len());
  545. }
  546. #[test]
  547. fn test_private_accessors() {
  548. let (start, end, log) = default_log_array();
  549. let first = log.first_entry();
  550. assert_eq!(start, first.index);
  551. assert_eq!(start / 3, first.term.0);
  552. let last = log.last_entry();
  553. assert_eq!(end - 1, last.index);
  554. assert_eq!((end - 1) / 3, last.term.0);
  555. assert_eq!(10 - start, log.offset(10));
  556. }
  557. #[test]
  558. fn test_check_start_index() {
  559. let (start, end, log) = default_log_array();
  560. assert!(start < end);
  561. assert!(catch_unwind(|| log.check_at_index(start - 8)).is_err());
  562. assert!(catch_unwind(|| log.check_at_index(start - 1)).is_err());
  563. assert!(catch_unwind(|| log.check_at_index(start)).is_ok());
  564. assert!(catch_unwind(|| log.check_at_index(start + 1)).is_ok());
  565. assert!(catch_unwind(|| log.check_at_index(end - 1)).is_ok());
  566. assert!(catch_unwind(|| log.check_at_index(end)).is_err());
  567. assert!(catch_unwind(|| log.check_at_index(end + 1)).is_err());
  568. assert!(catch_unwind(|| log.check_at_index(end + 5)).is_err());
  569. }
  570. #[test]
  571. fn test_check_range_index() {
  572. let (start, end, log) = default_log_array();
  573. assert!(start < end);
  574. assert!(catch_unwind(|| log.check_range_index(start - 8)).is_err());
  575. assert!(catch_unwind(|| log.check_range_index(start - 1)).is_err());
  576. assert!(catch_unwind(|| log.check_range_index(start)).is_ok());
  577. assert!(catch_unwind(|| log.check_range_index(start + 1)).is_ok());
  578. assert!(catch_unwind(|| log.check_range_index(end - 1)).is_ok());
  579. assert!(catch_unwind(|| log.check_range_index(end)).is_ok());
  580. assert!(catch_unwind(|| log.check_range_index(end + 1)).is_err());
  581. assert!(catch_unwind(|| log.check_range_index(end + 5)).is_err());
  582. }
  583. #[test]
  584. fn test_check_middle_index() {
  585. let (start, end, log) = default_log_array();
  586. assert!(start < end);
  587. assert!(catch_unwind(|| log.check_middle_index(start - 8)).is_err());
  588. assert!(catch_unwind(|| log.check_middle_index(start - 1)).is_err());
  589. assert!(catch_unwind(|| log.check_middle_index(start)).is_err());
  590. assert!(catch_unwind(|| log.check_middle_index(start + 1)).is_ok());
  591. assert!(catch_unwind(|| log.check_middle_index(end - 1)).is_ok());
  592. assert!(catch_unwind(|| log.check_middle_index(end)).is_err());
  593. assert!(catch_unwind(|| log.check_middle_index(end + 1)).is_err());
  594. assert!(catch_unwind(|| log.check_middle_index(end + 5)).is_err());
  595. }
  596. #[test]
  597. fn test_check_one_element() {
  598. let log = make_log_array(0);
  599. assert!(catch_unwind(|| log.check_one_element()).is_err());
  600. }
  601. #[test]
  602. fn test_integration_test() {
  603. let mut log = make_log_array(1);
  604. log.add_command(Term(3), 19);
  605. log.push(LogEntry {
  606. term: Term(3),
  607. index: 2,
  608. command: LogEntryEnum::Command(3),
  609. });
  610. log.add_command(Term(4), 20);
  611. log.push(LogEntry {
  612. term: Term(4),
  613. index: 4,
  614. command: LogEntryEnum::Command(7),
  615. });
  616. for i in 0..100 {
  617. log.add_command(Term(5), i);
  618. }
  619. assert_eq!(0, log.start());
  620. assert_eq!(105, log.end());
  621. assert_eq!((0, Term(0)), log.first_index_term().into());
  622. assert_eq!((104, Term(5)), log.last_index_term().into());
  623. assert_eq!(8, log.at(8).index);
  624. assert_eq!(5, log[8].term.0);
  625. assert_eq!(LogEntryEnum::Command(7), log[4].command);
  626. log.truncate(50);
  627. // End changed, start does not.
  628. assert_eq!(0, log.start());
  629. assert_eq!(50, log.end());
  630. assert_eq!((49, Term(5)), log.last_index_term().into());
  631. assert_eq!(49, log.at(49).index);
  632. assert_eq!(LogEntryEnum::Command(44), log[49].command);
  633. assert_eq!(5, log.at(5).term.0);
  634. // Cannot assert 50 is out of range. log is mut and cannot be used in
  635. // catch_unwind().
  636. // Snapshot is not changed.
  637. assert_eq!(((0, Term(0)).into(), [1, 2, 3].as_ref()), log.snapshot());
  638. log.shift(5, vec![]);
  639. // Start changed, end did not;
  640. assert_eq!(5, log.start());
  641. assert_eq!((5, Term(5)), log.first_index_term().into());
  642. assert_eq!(5, log.at(5).index);
  643. assert_eq!(5, log.at(5).term.0);
  644. // Cannot assert 4 is out of range. log is mut and cannot be used in
  645. // catch_unwind().
  646. // Snapshot is changed, too.
  647. assert_eq!(((5, Term(5)).into(), [].as_ref()), log.snapshot());
  648. // Ranged accessors.
  649. assert_eq!(45, log.all().len());
  650. assert_eq!(10, log.after(40).len());
  651. assert_eq!(20, log.between(20, 40).len());
  652. // Reset!
  653. log.reset(9, Term(7), vec![7, 8, 9]);
  654. assert_eq!(10, log.end());
  655. assert_eq!(1, log.all().len());
  656. assert_eq!(log.first_index_term(), log.last_index_term());
  657. assert_eq!(((9, Term(7)).into(), [7, 8, 9].as_ref()), log.snapshot());
  658. }
  659. #[test]
  660. fn test_validate_or_panic_current_term() {
  661. let log_array = make_log_array(7);
  662. let last_term = log_array.last_index_term().term.0;
  663. log_array
  664. .validate(Term(last_term))
  665. .expect("Validation should not fail");
  666. log_array
  667. .validate(Term(last_term + 1))
  668. .expect("Validation should not fail");
  669. let err = log_array
  670. .validate(Term(last_term - 1))
  671. .expect_err("Validation should have failed");
  672. assert!(matches!(
  673. err,
  674. ValidationError::FutureTerm(Term(_last_term), _, _)
  675. ));
  676. }
  677. #[test]
  678. fn test_validate_or_panic_increasing_term() {
  679. let mut log_array = make_log_array(7);
  680. let last_term = log_array.last_index_term().term.0;
  681. log_array
  682. .validate(Term(last_term + 1))
  683. .expect("Validation should not fail");
  684. log_array.inner[1].term = Term(last_term + 1);
  685. let err = log_array
  686. .validate(Term(last_term + 1))
  687. .expect_err("Validation should have failed");
  688. assert!(matches!(err, ValidationError::TermSpike(2, _)));
  689. }
  690. #[test]
  691. fn test_validate_or_panic_increasing_index() {
  692. let mut log_array = make_log_array_range(7, 10);
  693. let last_term = log_array.last_index_term().term.0;
  694. // OK
  695. log_array.inner[1].index = 8;
  696. log_array
  697. .validate(Term(last_term + 1))
  698. .expect("Validation should not fail");
  699. // Not 8, error
  700. log_array.inner[1].index = 7;
  701. let err = log_array
  702. .validate(Term(last_term + 1))
  703. .expect_err("Validation should have failed");
  704. assert!(matches!(err, ValidationError::IndexMismatch(8, _)));
  705. // Not 8, error
  706. log_array.inner[1].index = 9;
  707. let err = log_array
  708. .validate(Term(last_term + 1))
  709. .expect_err("Validation should have failed");
  710. assert!(matches!(err, ValidationError::IndexMismatch(8, _)));
  711. }
  712. }