diff --git a/xline-client/tests/auth.rs b/xline-client/tests/auth.rs new file mode 100644 index 000000000..a5961aa6b --- /dev/null +++ b/xline-client/tests/auth.rs @@ -0,0 +1 @@ +mod common; diff --git a/xline-client/tests/cluster.rs b/xline-client/tests/cluster.rs new file mode 100644 index 000000000..a5961aa6b --- /dev/null +++ b/xline-client/tests/cluster.rs @@ -0,0 +1 @@ +mod common; diff --git a/xline-client/tests/common/cluster.rs b/xline-client/tests/common/cluster.rs new file mode 100644 index 000000000..3966354cb --- /dev/null +++ b/xline-client/tests/common/cluster.rs @@ -0,0 +1,124 @@ +#![allow(dead_code, unused)] + +use std::{ + collections::{BTreeMap, HashMap}, + path::PathBuf, + sync::Arc, +}; + +use curp::members::ClusterMember; +use rand::{distributions::Alphanumeric, thread_rng, Rng}; +use tokio::{ + net::TcpListener, + sync::broadcast::{self, Sender}, + time::{self, Duration}, +}; +use utils::config::{ClientTimeout, CurpConfig, ServerTimeout, StorageConfig}; +use xline::{server::XlineServer, storage::db::DB}; + +/// Cluster +pub struct Cluster { + /// listeners of members + listeners: BTreeMap, + /// address of members + all_members: HashMap, + /// Stop sender + stop_tx: Option>, + /// Cluster size + size: usize, + /// storage paths + paths: Vec, +} + +impl Cluster { + /// New `Cluster` + pub(crate) async fn new(size: usize) -> Self { + let mut listeners = BTreeMap::new(); + for i in 0..size { + listeners.insert(i, TcpListener::bind("0.0.0.0:0").await.unwrap()); + } + let all_members: HashMap = listeners + .iter() + .map(|(i, l)| (format!("server{}", i), l.local_addr().unwrap().to_string())) + .collect(); + + Self { + listeners, + all_members, + stop_tx: None, + size, + paths: vec![], + } + } + + /// Start `Cluster` + pub(crate) async fn start(&mut self) { + let (stop_tx, _) = broadcast::channel(1); + + for i in 0..self.size { + let name = format!("server{}", i); + let is_leader = i == 0; + let mut rx = stop_tx.subscribe(); + let listener = self.listeners.remove(&i).unwrap(); + let path = if let Some(path) = self.paths.get(i) { + path.clone() + } else { + let path = PathBuf::from(format!("/tmp/xline-{}", random_id())); + self.paths.push(path.clone()); + path + }; + #[allow(clippy::unwrap_used)] + let db: Arc = DB::open(&StorageConfig::RocksDB(path.clone())).unwrap(); + let cluster_info = ClusterMember::new(self.all_members.clone(), name.clone()); + tokio::spawn(async move { + let server = XlineServer::new( + cluster_info.into(), + is_leader, + CurpConfig { + data_dir: path.join("curp"), + ..Default::default() + }, + ClientTimeout::default(), + ServerTimeout::default(), + StorageConfig::Memory, + ); + let signal = async { + let _ = rx.recv().await; + }; + let result = server + .start_from_listener_shutdown(listener, signal, db, None) + .await; + if let Err(e) = result { + panic!("Server start error: {e}"); + } + }); + } + self.stop_tx = Some(stop_tx); + // Sleep 30ms, wait for the server to start + time::sleep(Duration::from_millis(300)).await; + } + + #[allow(dead_code)] // used in tests but get warning + pub fn addrs(&self) -> &HashMap { + &self.all_members + } +} + +impl Drop for Cluster { + fn drop(&mut self) { + if let Some(ref stop_tx) = self.stop_tx { + let _ = stop_tx.send(()); + } + for path in &self.paths { + let _ignore = std::fs::remove_dir_all(path); + } + } +} + +fn random_id() -> String { + thread_rng() + .sample_iter(&Alphanumeric) + .take(8) + .map(char::from) + .collect() +} diff --git a/xline-client/tests/common/mod.rs b/xline-client/tests/common/mod.rs new file mode 100644 index 000000000..f7b48702a --- /dev/null +++ b/xline-client/tests/common/mod.rs @@ -0,0 +1 @@ +pub mod cluster; diff --git a/xline-client/tests/election.rs b/xline-client/tests/election.rs new file mode 100644 index 000000000..a5961aa6b --- /dev/null +++ b/xline-client/tests/election.rs @@ -0,0 +1 @@ +mod common; diff --git a/xline-client/tests/kv.rs b/xline-client/tests/kv.rs new file mode 100644 index 000000000..a5961aa6b --- /dev/null +++ b/xline-client/tests/kv.rs @@ -0,0 +1 @@ +mod common; diff --git a/xline-client/tests/lease.rs b/xline-client/tests/lease.rs new file mode 100644 index 000000000..a5961aa6b --- /dev/null +++ b/xline-client/tests/lease.rs @@ -0,0 +1 @@ +mod common; diff --git a/xline-client/tests/lock.rs b/xline-client/tests/lock.rs new file mode 100644 index 000000000..a5961aa6b --- /dev/null +++ b/xline-client/tests/lock.rs @@ -0,0 +1 @@ +mod common; diff --git a/xline-client/tests/maintenance.rs b/xline-client/tests/maintenance.rs new file mode 100644 index 000000000..a5961aa6b --- /dev/null +++ b/xline-client/tests/maintenance.rs @@ -0,0 +1 @@ +mod common; diff --git a/xline-client/tests/watch.rs b/xline-client/tests/watch.rs new file mode 100644 index 000000000..a5961aa6b --- /dev/null +++ b/xline-client/tests/watch.rs @@ -0,0 +1 @@ +mod common;