use std::collections::HashMap;
use std::sync::Arc;
use tempfile::TempDir;
use tokio::sync::RwLock;
pub struct TestNode {
pub id: usize,
pub temp_dir: TempDir,
}
impl TestNode {
pub async fn new(id: usize) -> Result<Self, Box<dyn std::error::Error>> {
let temp_dir = TempDir::new()?;
Ok(TestNode { id, temp_dir })
}
pub async fn cleanup(self) -> Result<(), Box<dyn std::error::Error>> {
Ok(())
}
}
pub struct NetworkSimulator {
pub nodes: HashMap<usize, Arc<RwLock<TestNode>>>,
pub connections: HashMap<(usize, usize), bool>,
}
impl Default for NetworkSimulator {
fn default() -> Self {
Self::new()
}
}
impl NetworkSimulator {
pub fn new() -> Self {
NetworkSimulator {
nodes: HashMap::new(),
connections: HashMap::new(),
}
}
pub fn add_node(&mut self, node: TestNode) -> usize {
let id = node.id;
self.nodes.insert(id, Arc::new(RwLock::new(node)));
id
}
pub fn connect_nodes(&mut self, node1: usize, node2: usize) {
self.connections.insert((node1, node2), true);
self.connections.insert((node2, node1), true);
}
pub fn are_connected(&self, node1: usize, node2: usize) -> bool {
self.connections
.get(&(node1, node2))
.copied()
.unwrap_or(false)
}
pub async fn get_node(&self, id: usize) -> Option<Arc<RwLock<TestNode>>> {
self.nodes.get(&id).cloned()
}
}
pub struct TestHarness {
pub network: Arc<RwLock<NetworkSimulator>>,
pub temp_dir: TempDir,
}
impl TestHarness {
pub async fn new(node_count: usize) -> Result<Self, Box<dyn std::error::Error>> {
let temp_dir = TempDir::new()?;
let network = Arc::new(RwLock::new(NetworkSimulator::new()));
let harness = TestHarness { network, temp_dir };
for i in 0..node_count {
let node = TestNode::new(i).await?;
harness.network.write().await.add_node(node);
}
for i in 0..node_count {
for j in (i + 1)..node_count {
harness.network.write().await.connect_nodes(i, j);
}
}
Ok(harness)
}
pub async fn create_storage_engine(&self) -> Result<(), Box<dyn std::error::Error>> {
Ok(())
}
pub async fn get_storage_engine(
&self,
_node_id: usize,
) -> Result<(), Box<dyn std::error::Error>> {
Ok(())
}
pub async fn get_user_storage(
&self,
_username: &str,
) -> Result<(), Box<dyn std::error::Error>> {
Ok(())
}
pub async fn cleanup(self) -> Result<(), Box<dyn std::error::Error>> {
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_harness_creation() {
let harness = TestHarness::new(3).await.unwrap();
let network = harness.network.read().await;
assert_eq!(network.nodes.len(), 3);
drop(network); harness.cleanup().await.unwrap();
}
#[tokio::test]
async fn test_node_connections() {
let harness = TestHarness::new(3).await.unwrap();
let network = harness.network.read().await;
assert!(network.are_connected(0, 1));
assert!(network.are_connected(1, 2));
assert!(network.are_connected(0, 2));
}
#[tokio::test]
async fn test_storage_engine_placeholder() {
let harness = TestHarness::new(1).await.unwrap();
assert!(harness.create_storage_engine().await.is_ok());
assert!(harness.get_storage_engine(0).await.is_ok());
assert!(harness.get_user_storage("test").await.is_ok());
}
}