use chaincraft::examples::chatroom::{helpers, ChatroomObject};
use chaincraft::{
clear_local_registry,
crypto::ecdsa::{ECDSASigner, ECDSAVerifier},
network::PeerId,
shared_object::ApplicationObject,
storage::MemoryStorage,
ChaincraftNode,
};
use serde_json::json;
use std::sync::Arc;
use tokio::time::{sleep, Duration};
async fn create_node_with_chatroom() -> ChaincraftNode {
clear_local_registry();
let id = PeerId::new();
let storage = Arc::new(MemoryStorage::new());
let mut node = ChaincraftNode::new(id, storage);
node.set_port(0);
node.disable_local_discovery();
let chatroom_obj: Box<dyn ApplicationObject> = Box::new(ChatroomObject::new());
node.add_shared_object(chatroom_obj).await.unwrap();
node.start().await.unwrap();
node
}
#[tokio::test]
async fn test_chatroom_creation() {
let mut node = create_node_with_chatroom().await;
let admin_signer = ECDSASigner::new().unwrap();
let create_msg =
helpers::create_chatroom_message("test_room".to_string(), &admin_signer).unwrap();
node.create_shared_message_with_data(create_msg)
.await
.unwrap();
sleep(Duration::from_millis(100)).await;
let shared_objects = node.shared_objects().await;
if let Some(obj) = shared_objects.first() {
if let Some(chatroom_obj) = obj.as_any().downcast_ref::<ChatroomObject>() {
let chatrooms = chatroom_obj.get_chatrooms();
assert!(chatrooms.contains_key("test_room"));
let room = &chatrooms["test_room"];
assert_eq!(room.name, "test_room");
assert_eq!(room.admin, admin_signer.get_public_key_pem().unwrap());
assert!(room
.members
.contains(&admin_signer.get_public_key_pem().unwrap()));
} else {
panic!("Expected ChatroomObject");
}
} else {
panic!("No shared objects found");
}
node.close().await.unwrap();
}
#[tokio::test]
async fn test_chatroom_posting() {
let mut node = create_node_with_chatroom().await;
let admin_signer = ECDSASigner::new().unwrap();
let create_msg =
helpers::create_chatroom_message("chat_room".to_string(), &admin_signer).unwrap();
node.create_shared_message_with_data(create_msg)
.await
.unwrap();
sleep(Duration::from_millis(100)).await;
let post_msg = helpers::create_post_message(
"chat_room".to_string(),
"Hello, world!".to_string(),
&admin_signer,
)
.unwrap();
node.create_shared_message_with_data(post_msg)
.await
.unwrap();
sleep(Duration::from_millis(100)).await;
let shared_objects = node.shared_objects().await;
if let Some(obj) = shared_objects.first() {
if let Some(chatroom_obj) = obj.as_any().downcast_ref::<ChatroomObject>() {
let chatrooms = chatroom_obj.get_chatrooms();
let room = &chatrooms["chat_room"];
let post_messages: Vec<_> = room
.messages
.iter()
.filter(|m| m.message_type == "POST_MESSAGE")
.collect();
assert_eq!(post_messages.len(), 1);
assert_eq!(post_messages[0].text.as_ref().unwrap(), "Hello, world!");
assert_eq!(post_messages[0].public_key_pem, admin_signer.get_public_key_pem().unwrap());
}
}
node.close().await.unwrap();
}
#[tokio::test]
async fn test_signature_verification() {
let signer = ECDSASigner::new().unwrap();
let verifier = ECDSAVerifier::new();
let message = b"test message";
let signature = signer.sign(message).unwrap();
let public_key_pem = signer.get_public_key_pem().unwrap();
let is_valid = verifier
.verify(message, &signature, &public_key_pem)
.unwrap();
assert!(is_valid);
let wrong_message = b"wrong message";
let is_invalid = verifier
.verify(wrong_message, &signature, &public_key_pem)
.unwrap();
assert!(!is_invalid);
}
#[tokio::test]
async fn test_invalid_chatroom_message() {
let mut node = create_node_with_chatroom().await;
let invalid_msg = json!({
"message_type": "CREATE_CHATROOM",
"chatroom_name": "test_room"
});
let _result = node.create_shared_message_with_data(invalid_msg).await;
sleep(Duration::from_millis(100)).await;
let shared_objects = node.shared_objects().await;
if let Some(obj) = shared_objects.first() {
if let Some(chatroom_obj) = obj.as_any().downcast_ref::<ChatroomObject>() {
let chatrooms = chatroom_obj.get_chatrooms();
assert!(chatrooms.is_empty());
}
}
node.close().await.unwrap();
}
#[tokio::test]
async fn test_chatroom_state() {
let mut node = create_node_with_chatroom().await;
let signer = ECDSASigner::new().unwrap();
let create_msg = helpers::create_chatroom_message("state_room".to_string(), &signer).unwrap();
node.create_shared_message_with_data(create_msg)
.await
.unwrap();
sleep(Duration::from_millis(100)).await;
let shared_objects = node.shared_objects().await;
if let Some(obj) = shared_objects.first() {
let state = obj.get_state().await.unwrap();
assert_eq!(state["chatroom_count"], 1);
assert_eq!(state["total_messages"], 0);
let chatrooms = state["chatrooms"].as_array().unwrap();
assert_eq!(chatrooms.len(), 1);
assert_eq!(chatrooms[0], "state_room");
}
node.close().await.unwrap();
}