agreement_tests.rs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. extern crate labrpc;
  2. extern crate ruaft;
  3. #[macro_use]
  4. extern crate anyhow;
  5. mod config;
  6. #[test]
  7. fn basic_agreement() -> config::Result<()> {
  8. const SERVERS: usize = 5;
  9. let cfg = config::make_config(SERVERS, false);
  10. let _guard = cfg.deferred_cleanup();
  11. cfg.begin("Test (2B): basic agreement");
  12. for index in 1..4 {
  13. let committed = cfg.committed_count(index)?;
  14. assert_eq!(0, committed.0, "some have committed before start()");
  15. let commit_index = cfg.one(index as i32 * 100, SERVERS, false)?;
  16. assert_eq!(
  17. index, commit_index,
  18. "got index {} but expected {}",
  19. commit_index, index
  20. );
  21. }
  22. Ok(())
  23. }
  24. #[test]
  25. fn fail_agree() -> config::Result<()> {
  26. const SERVERS: usize = 3;
  27. let cfg = config::make_config(SERVERS, false);
  28. let _guard = cfg.deferred_cleanup();
  29. cfg.begin("Test (2B): agreement despite follower disconnection");
  30. cfg.one(101, SERVERS, false)?;
  31. // follower network disconnection
  32. let leader = cfg.check_one_leader()?;
  33. cfg.disconnect((leader + 1) % SERVERS);
  34. // agree despite one disconnected server?
  35. cfg.one(102, SERVERS - 1, false)?;
  36. cfg.one(103, SERVERS - 1, false)?;
  37. config::sleep_election_timeouts(1);
  38. cfg.one(104, SERVERS - 1, false)?;
  39. cfg.one(105, SERVERS - 1, false)?;
  40. // re-connect
  41. cfg.connect((leader + 1) % SERVERS);
  42. // agree with full set of servers?
  43. cfg.one(106, SERVERS, true)?;
  44. config::sleep_election_timeouts(1);
  45. cfg.one(107, SERVERS, true)?;
  46. cfg.end();
  47. Ok(())
  48. }
  49. #[test]
  50. fn fail_no_agree() -> config::Result<()> {
  51. const SERVERS: usize = 5;
  52. let cfg = config::make_config(SERVERS, false);
  53. let _guard = cfg.deferred_cleanup();
  54. cfg.begin("Test (2B): no agreement if too many followers disconnect");
  55. cfg.one(10, SERVERS, false)?;
  56. // 3 of 5 followers disconnect
  57. let leader = cfg.check_one_leader()?;
  58. cfg.disconnect((leader + 1) % SERVERS);
  59. cfg.disconnect((leader + 2) % SERVERS);
  60. cfg.disconnect((leader + 3) % SERVERS);
  61. let result = cfg.leader_start(leader, 20);
  62. assert!(result.is_some(), "leader rejected start()");
  63. let index = result.unwrap().1;
  64. assert_eq!(2, index, "expected index 2, got {}", index);
  65. config::sleep_election_timeouts(2);
  66. let (commit_count, _) = cfg.committed_count(index)?;
  67. assert_eq!(
  68. 0, commit_count,
  69. "{} committed but no majority",
  70. commit_count
  71. );
  72. // repair
  73. cfg.connect((leader + 1) % SERVERS);
  74. cfg.connect((leader + 2) % SERVERS);
  75. cfg.connect((leader + 3) % SERVERS);
  76. // the disconnected majority may have chosen a leader from
  77. // among their own ranks, forgetting index 2.
  78. let leader2 = cfg.check_one_leader()?;
  79. let result = cfg.leader_start(leader2, 30);
  80. assert!(result.is_some(), "leader2 rejected start()");
  81. let index = result.unwrap().1;
  82. assert!(index == 2 || index == 3, "unexpected index {}", index);
  83. cfg.one(1000, SERVERS, true)?;
  84. cfg.end();
  85. Ok(())
  86. }