浏览代码

Add a minimal test that uses kvraft and some refactor.

The partition() method of config is refactored.
Jing Yang 4 年之前
父节点
当前提交
8905dfb7c1
共有 4 个文件被更改,包括 52 次插入9 次删除
  1. 1 0
      Cargo.toml
  2. 17 4
      kvraft/src/testing_utils/config.rs
  3. 2 5
      kvraft/tests/service_test.rs
  4. 32 0
      tests/snapshot_tests.rs

+ 1 - 0
Cargo.toml

@@ -26,6 +26,7 @@ tokio = { version = "1.0", features = ["rt-multi-thread", "time", "parking_lot"]
 anyhow = "1.0"
 futures = { version = "0.3.8", features = ["thread-pool"] }
 scopeguard = "1.1.0"
+kvraft = { path = "kvraft" }
 
 [workspace]
 members = [

+ 17 - 4
kvraft/src/testing_utils/config.rs

@@ -77,13 +77,13 @@ impl Config {
         eprintln!("{}", msg);
     }
 
-    pub fn shuffled_indexes(&self) -> Vec<usize> {
+    fn shuffled_indexes(&self) -> Vec<usize> {
         let mut indexes: Vec<usize> = (0..self.server_count).collect();
         indexes.shuffle(&mut thread_rng());
         indexes
     }
 
-    pub fn make_partition(&self) -> (Vec<usize>, Vec<usize>) {
+    pub fn partition(&self) -> (Vec<usize>, Vec<usize>) {
         let state = self.state.lock();
         let mut indexes = self.shuffled_indexes();
 
@@ -98,7 +98,20 @@ impl Config {
             .unwrap_or(0);
         indexes.swap(0, leader_position);
 
-        (indexes.split_off(state.kv_servers.len() / 2), indexes)
+        let part_one = indexes.split_off(indexes.len() / 2);
+        let part_two = indexes;
+        self.network_partition(&part_one, &part_two);
+
+        (part_one, part_two)
+    }
+
+    pub fn random_partition(&self) -> (Vec<usize>, Vec<usize>) {
+        let mut indexes = self.shuffled_indexes();
+        let part_one = indexes.split_off(indexes.len() / 2);
+        let part_two = indexes;
+        self.network_partition(&part_one, &part_two);
+
+        (part_one, part_two)
     }
 
     fn set_connect(
@@ -114,7 +127,7 @@ impl Config {
         }
     }
 
-    pub fn partition(&self, part_one: &[usize], part_two: &[usize]) {
+    fn network_partition(&self, part_one: &[usize], part_two: &[usize]) {
         let mut network = self.network.lock();
         Self::set_connect(&mut network, part_one, part_two, false);
         Self::set_connect(&mut network, part_two, part_one, false);

+ 2 - 5
kvraft/tests/service_test.rs

@@ -75,9 +75,7 @@ fn appending_client(
 const PARTITION_MAX_DELAY_MILLIS: u64 = 200;
 fn run_partition(cfg: Arc<Config>, stop: Arc<AtomicBool>) {
     while !stop.load(Ordering::Acquire) {
-        let mut indexes = cfg.shuffled_indexes();
-        let len = indexes.len();
-        cfg.partition(&(indexes.split_off(len / 2)), &indexes);
+        cfg.random_partition();
         let delay = thread_rng().gen_range(
             LONG_ELECTION_TIMEOUT_MILLIS
                 ..LONG_ELECTION_TIMEOUT_MILLIS + PARTITION_MAX_DELAY_MILLIS,
@@ -287,11 +285,10 @@ fn one_partition() -> anyhow::Result<()> {
     let mut clerk = cfg.make_clerk();
     clerk.put(KEY, "13");
 
-    let (majority, minority) = cfg.make_partition();
+    let (majority, minority) = cfg.partition();
 
     assert!(minority.len() < majority.len());
     assert_eq!(minority.len() + majority.len(), SERVERS);
-    cfg.partition(&majority, &minority);
 
     let mut clerk_majority = cfg.make_limited_clerk(&majority);
     let mut clerk_minority1 = cfg.make_limited_clerk(&minority);

+ 32 - 0
tests/snapshot_tests.rs

@@ -0,0 +1,32 @@
+extern crate kvraft;
+#[macro_use]
+extern crate scopeguard;
+
+use kvraft::testing_utils::config::{make_config, sleep_election_timeouts};
+use std::sync::Arc;
+
+#[test]
+fn install_snapshot_rpc() {
+    const SERVERS: usize = 3;
+    const MAX_RAFT_STATE: usize = 1000;
+    const KEY: &str = "a";
+    let cfg = Arc::new(make_config(SERVERS, true, 0));
+    defer!(cfg.clean_up());
+
+    let mut clerk = cfg.make_clerk();
+
+    cfg.begin("Test: InstallSnapshot RPC (3B)");
+
+    clerk.put("a", "A");
+    assert_eq!(clerk.get(KEY), Some("A".to_owned()));
+    let (majority, minority) = cfg.partition();
+    {
+        let mut clerk = cfg.make_limited_clerk(&majority);
+        for i in 0..50 {
+            let i_str = i.to_string();
+            clerk.put(&i_str, &i_str);
+        }
+        sleep_election_timeouts(1);
+        clerk.put("b", "B");
+    }
+}