use chaincraft::{network::PeerId, storage::MemoryStorage};
use chaincraft::{ChaincraftNode, Result};
use serde_json::json;
use std::sync::Arc;
use tokio::time::{sleep, Duration};
#[tokio::test]
async fn test_node_initialization() -> Result<()> {
let node = ChaincraftNode::builder()
.with_persistent_storage(false)
.port(8080)
.max_peers(10)
.build()?;
assert_eq!(node.port(), 8080);
assert_eq!(node.max_peers(), 10);
assert_eq!(node.host(), "127.0.0.1");
assert!(!node.is_running_async().await);
Ok(())
}
#[tokio::test]
async fn test_node_start_stop() -> Result<()> {
let mut node = ChaincraftNode::builder()
.port(0) .with_persistent_storage(false)
.build()?;
assert!(!node.is_running_async().await);
node.start().await?;
assert!(node.is_running_async().await);
node.stop().await?;
assert!(!node.is_running_async().await);
Ok(())
}
#[tokio::test]
async fn test_multiple_nodes_different_ports() -> Result<()> {
let node1 = ChaincraftNode::builder().port(8081).build()?;
let node2 = ChaincraftNode::builder().port(8082).build()?;
assert_ne!(node1.port(), node2.port());
assert_eq!(node1.port(), 8081);
assert_eq!(node2.port(), 8082);
Ok(())
}
#[tokio::test]
async fn test_connect_to_peer() -> Result<()> {
let mut node1 = ChaincraftNode::builder().port(0).build()?;
let mut node2 = ChaincraftNode::builder().port(0).build()?;
node1.start().await?;
node2.start().await?;
let peer_addr = format!("{}:{}", node2.host(), node2.port());
node1.connect_to_peer(&peer_addr).await?;
let peers = node1.get_peers().await;
assert_eq!(peers.len(), 1);
node1.close().await?;
node2.close().await?;
Ok(())
}
#[tokio::test]
async fn test_max_peers_limit() -> Result<()> {
let mut node = ChaincraftNode::builder().max_peers(2).port(0).build()?;
node.start().await?;
for i in 0..5 {
let peer_addr = format!("127.0.0.1:{}", 9000 + i);
let _ = node.connect_to_peer(&peer_addr).await;
}
assert_eq!(node.max_peers(), 2);
node.close().await?;
Ok(())
}
#[tokio::test]
async fn test_create_shared_message() -> Result<()> {
let mut node = ChaincraftNode::builder()
.port(0) .with_persistent_storage(false)
.build()?;
node.start().await?;
let test_data = "Test data";
let message_hash = node.create_shared_message(test_data.to_string()).await?;
assert!(node.has_object(&message_hash));
assert_eq!(node.db_size(), 1);
let stored_message = node.get_object(&message_hash).await?;
let value: serde_json::Value = serde_json::from_str(&stored_message)?;
assert_eq!(value["data"], test_data);
node.close().await?;
Ok(())
}
#[tokio::test]
async fn test_persistent_vs_memory_storage() -> Result<()> {
let mut memory_node = ChaincraftNode::builder()
.port(0) .with_persistent_storage(false)
.build()?;
memory_node.start().await?;
let mut persistent_node = ChaincraftNode::builder()
.port(0) .with_persistent_storage(true)
.build()?;
persistent_node.start().await?;
assert!(memory_node.is_running_async().await);
assert!(persistent_node.is_running_async().await);
memory_node.close().await?;
persistent_node.close().await?;
Ok(())
}
#[tokio::test]
async fn test_node_lifecycle() -> Result<()> {
let mut node = ChaincraftNode::builder()
.port(0) .with_persistent_storage(false)
.build()?;
assert!(!node.is_running_async().await);
node.start().await?;
assert!(node.is_running_async().await);
let _hash = node
.create_shared_message("lifecycle test".to_string())
.await?;
assert_eq!(node.db_size(), 1);
node.close().await?;
assert!(!node.is_running_async().await);
Ok(())
}
#[tokio::test]
async fn test_node_restart_capability() {
let id = PeerId::new();
let storage = Arc::new(MemoryStorage::new());
let mut node = ChaincraftNode::new(id.clone(), storage.clone());
node.set_port(0);
node.start().await.unwrap();
assert!(node.is_running_async().await);
node.close().await.unwrap();
assert!(!node.is_running_async().await);
let mut new_node = ChaincraftNode::new(id, storage);
new_node.set_port(0); new_node.start().await.unwrap();
assert!(new_node.is_running_async().await);
new_node.close().await.unwrap();
}
#[tokio::test]
async fn test_node_configuration_persistence() {
let id = PeerId::new();
let storage = Arc::new(MemoryStorage::new());
let mut node = ChaincraftNode::new(id, storage);
node.set_port(0); node.start().await.unwrap();
let test_msg = json!({"test": "persistence_data"});
node.create_shared_message_with_data(test_msg)
.await
.unwrap();
sleep(Duration::from_millis(100)).await;
node.close().await.unwrap();
}
#[tokio::test]
async fn test_graceful_shutdown() {
let id = PeerId::new();
let storage = Arc::new(MemoryStorage::new());
let mut node = ChaincraftNode::new(id, storage);
node.set_port(0); node.start().await.unwrap();
for i in 0..5 {
let msg = json!({"shutdown_test": i});
node.create_shared_message_with_data(msg).await.unwrap();
sleep(Duration::from_millis(10)).await;
}
node.close().await.unwrap();
assert!(!node.is_running_async().await);
}
#[tokio::test]
async fn test_node_isolation() {
let mut node1 = {
let id = PeerId::new();
let storage = Arc::new(MemoryStorage::new());
let mut node = ChaincraftNode::new(id, storage);
node.set_port(0); node.start().await.unwrap();
node
};
let mut node2 = {
let id = PeerId::new();
let storage = Arc::new(MemoryStorage::new());
let mut node = ChaincraftNode::new(id, storage);
node.set_port(0); node.start().await.unwrap();
node
};
let mut node3 = {
let id = PeerId::new();
let storage = Arc::new(MemoryStorage::new());
let mut node = ChaincraftNode::new(id, storage);
node.set_port(0); node.start().await.unwrap();
node
};
assert!(node1.is_running_async().await);
assert!(node2.is_running_async().await);
assert!(node3.is_running_async().await);
assert_ne!(node1.id(), node2.id());
assert_ne!(node1.id(), node3.id());
assert_ne!(node2.id(), node3.id());
assert!(node1.port() > 0);
assert!(node2.port() > 0);
assert!(node3.port() > 0);
node1.close().await.unwrap();
node2.close().await.unwrap();
node3.close().await.unwrap();
}
#[tokio::test]
async fn test_error_recovery() {
let id = PeerId::new();
let storage = Arc::new(MemoryStorage::new());
let mut node = ChaincraftNode::new(id, storage);
node.set_port(0); node.start().await.unwrap();
let invalid_msg = json!({
"invalid_field": null,
"nested": {
"deeply": {
"nested": {
"data": "test"
}
}
}
});
let _result = node.create_shared_message_with_data(invalid_msg).await;
assert!(node.is_running_async().await);
node.close().await.unwrap();
}