Add comprehensive documentation and unit tests
Documentation: - Add detailed README files for all services (auth, character, database, launcher, packet, utils, world) - Create API documentation for the database service with detailed endpoint specifications - Document database schema and relationships - Add service architecture overviews and configuration instructions Unit Tests: - Implement comprehensive test suite for database repositories (user, character, session) - Add gRPC service tests for database interactions - Create tests for packet service components (bufferpool, connection, packets) - Add utility service tests (health check, logging, load balancer, redis cache, service discovery) - Implement auth service user tests - Add character service tests Code Structure: - Reorganize test files into a more consistent structure - Create a dedicated tests crate for integration testing - Add test helpers and mock implementations for easier testing
This commit is contained in:
96
tests/packet-service/bufferpool_tests.rs
Normal file
96
tests/packet-service/bufferpool_tests.rs
Normal file
@@ -0,0 +1,96 @@
|
||||
use packet_service::bufferpool::BufferPool;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_buffer_pool_creation() {
|
||||
let pool_size = 5;
|
||||
let pool = BufferPool::new(pool_size);
|
||||
|
||||
// Verify we can acquire the expected number of buffers
|
||||
for _ in 0..pool_size {
|
||||
let buffer = pool.acquire().await;
|
||||
assert!(buffer.is_some());
|
||||
}
|
||||
|
||||
// The next acquire should return None since all buffers are in use
|
||||
let buffer = pool.acquire().await;
|
||||
assert!(buffer.is_none());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_buffer_pool_release() {
|
||||
let pool_size = 3;
|
||||
let pool = BufferPool::new(pool_size);
|
||||
|
||||
// Acquire all buffers
|
||||
let mut buffers = Vec::new();
|
||||
for _ in 0..pool_size {
|
||||
let buffer = pool.acquire().await.unwrap();
|
||||
buffers.push(buffer);
|
||||
}
|
||||
|
||||
// Release one buffer
|
||||
let buffer = buffers.pop().unwrap();
|
||||
pool.release(buffer).await;
|
||||
|
||||
// We should be able to acquire one buffer now
|
||||
let buffer = pool.acquire().await;
|
||||
assert!(buffer.is_some());
|
||||
|
||||
// But not two
|
||||
let buffer = pool.acquire().await;
|
||||
assert!(buffer.is_none());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_buffer_pool_concurrent_access() {
|
||||
let pool_size = 10;
|
||||
let pool = Arc::new(BufferPool::new(pool_size));
|
||||
|
||||
// Spawn multiple tasks to acquire and release buffers
|
||||
let mut handles = Vec::new();
|
||||
|
||||
for i in 0..pool_size {
|
||||
let pool_clone = pool.clone();
|
||||
let handle = tokio::spawn(async move {
|
||||
// Acquire a buffer
|
||||
let mut buffer = pool_clone.acquire().await.unwrap();
|
||||
|
||||
// Write some data to the buffer
|
||||
buffer[0] = i as u8;
|
||||
|
||||
// Simulate some work
|
||||
tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
|
||||
|
||||
// Release the buffer
|
||||
pool_clone.release(buffer).await;
|
||||
});
|
||||
|
||||
handles.push(handle);
|
||||
}
|
||||
|
||||
// Wait for all tasks to complete
|
||||
for handle in handles {
|
||||
handle.await.unwrap();
|
||||
}
|
||||
|
||||
// All buffers should be available again
|
||||
for _ in 0..pool_size {
|
||||
let buffer = pool.acquire().await;
|
||||
assert!(buffer.is_some());
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_buffer_pool_buffer_size() {
|
||||
let pool = BufferPool::new(1);
|
||||
|
||||
// Acquire a buffer
|
||||
let buffer = pool.acquire().await.unwrap();
|
||||
|
||||
// Buffer should be large enough for maximum packet size
|
||||
assert!(buffer.len() >= 0xFFF);
|
||||
|
||||
// Release the buffer
|
||||
pool.release(buffer).await;
|
||||
}
|
||||
108
tests/packet-service/connection_service_tests.rs
Normal file
108
tests/packet-service/connection_service_tests.rs
Normal file
@@ -0,0 +1,108 @@
|
||||
use packet_service::connection_service::ConnectionService;
|
||||
use packet_service::connection_state::ConnectionState;
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[test]
|
||||
fn test_connection_service_add_connection() {
|
||||
let service = ConnectionService::new();
|
||||
|
||||
// Add a connection
|
||||
let connection_id = service.add_connection();
|
||||
|
||||
// Verify the connection exists
|
||||
let connection = service.get_connection(&connection_id);
|
||||
assert!(connection.is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_connection_service_remove_connection() {
|
||||
let service = ConnectionService::new();
|
||||
|
||||
// Add a connection
|
||||
let connection_id = service.add_connection();
|
||||
|
||||
// Verify the connection exists
|
||||
let connection = service.get_connection(&connection_id);
|
||||
assert!(connection.is_some());
|
||||
|
||||
// Remove the connection
|
||||
service.remove_connection(&connection_id);
|
||||
|
||||
// Verify the connection no longer exists
|
||||
let connection = service.get_connection(&connection_id);
|
||||
assert!(connection.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_connection_service_get_connection_mut() {
|
||||
let service = ConnectionService::new();
|
||||
|
||||
// Add a connection
|
||||
let connection_id = service.add_connection();
|
||||
|
||||
// Get a mutable reference to the connection
|
||||
let mut connection = service.get_connection_mut(&connection_id).unwrap();
|
||||
|
||||
// Modify the connection
|
||||
connection.user_id = Some("test_user".to_string());
|
||||
connection.session_id = Some("test_session".to_string());
|
||||
connection.character_id = Some(123);
|
||||
|
||||
// Drop the mutable reference
|
||||
drop(connection);
|
||||
|
||||
// Verify the changes were saved
|
||||
let connection = service.get_connection(&connection_id).unwrap();
|
||||
assert_eq!(connection.user_id, Some("test_user".to_string()));
|
||||
assert_eq!(connection.session_id, Some("test_session".to_string()));
|
||||
assert_eq!(connection.character_id, Some(123));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_connection_service_multiple_connections() {
|
||||
let service = ConnectionService::new();
|
||||
|
||||
// Add multiple connections
|
||||
let connection_ids: Vec<String> = (0..10).map(|_| service.add_connection()).collect();
|
||||
|
||||
// Verify all connections exist
|
||||
for connection_id in &connection_ids {
|
||||
let connection = service.get_connection(connection_id);
|
||||
assert!(connection.is_some());
|
||||
}
|
||||
|
||||
// Verify all connection IDs are unique
|
||||
let unique_ids: HashSet<String> = connection_ids.iter().cloned().collect();
|
||||
assert_eq!(unique_ids.len(), connection_ids.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_connection_state_new() {
|
||||
let state = ConnectionState::new();
|
||||
|
||||
// Verify initial state
|
||||
assert_eq!(state.user_id, None);
|
||||
assert_eq!(state.session_id, None);
|
||||
assert_eq!(state.character_id, None);
|
||||
assert_eq!(state.character_list, None);
|
||||
assert!(state.additional_data.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_connection_state_additional_data() {
|
||||
let mut state = ConnectionState::new();
|
||||
|
||||
// Add some additional data
|
||||
state.additional_data.insert("key1".to_string(), "value1".to_string());
|
||||
state.additional_data.insert("key2".to_string(), "value2".to_string());
|
||||
|
||||
// Verify the data was added
|
||||
assert_eq!(state.additional_data.get("key1"), Some(&"value1".to_string()));
|
||||
assert_eq!(state.additional_data.get("key2"), Some(&"value2".to_string()));
|
||||
|
||||
// Update a value
|
||||
state.additional_data.insert("key1".to_string(), "updated".to_string());
|
||||
|
||||
// Verify the value was updated
|
||||
assert_eq!(state.additional_data.get("key1"), Some(&"updated".to_string()));
|
||||
}
|
||||
98
tests/packet-service/packet_tests.rs
Normal file
98
tests/packet-service/packet_tests.rs
Normal file
@@ -0,0 +1,98 @@
|
||||
use bincode::{Decode, Encode};
|
||||
use packet_service::packet::{Packet, PacketPayload};
|
||||
use packet_service::packet_type::PacketType;
|
||||
|
||||
// Define a test payload struct
|
||||
#[derive(Debug, Encode, Decode, PartialEq)]
|
||||
struct TestPayload {
|
||||
id: u32,
|
||||
name: String,
|
||||
value: f32,
|
||||
}
|
||||
|
||||
impl PacketPayload for TestPayload {}
|
||||
|
||||
#[test]
|
||||
fn test_packet_creation() {
|
||||
let payload = TestPayload {
|
||||
id: 123,
|
||||
name: "test".to_string(),
|
||||
value: 3.14,
|
||||
};
|
||||
|
||||
let packet = Packet::new(PacketType::PakcsAlive, &payload).unwrap();
|
||||
|
||||
// Check packet fields
|
||||
assert_eq!(packet.packet_type, PacketType::PakcsAlive);
|
||||
assert_eq!(packet.packet_crc, 0); // CRC is currently not implemented
|
||||
assert!(!packet.payload.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_packet_serialization_deserialization() {
|
||||
let original_payload = TestPayload {
|
||||
id: 456,
|
||||
name: "serialization_test".to_string(),
|
||||
value: 2.71,
|
||||
};
|
||||
|
||||
// Create a packet
|
||||
let packet = Packet::new(PacketType::PakcsAlive, &original_payload).unwrap();
|
||||
|
||||
// Serialize to raw bytes
|
||||
let raw_data = packet.to_raw();
|
||||
|
||||
// Deserialize from raw bytes
|
||||
let deserialized_packet = Packet::from_raw(&raw_data).unwrap();
|
||||
|
||||
// Check packet fields match
|
||||
assert_eq!(deserialized_packet.packet_type, packet.packet_type);
|
||||
assert_eq!(deserialized_packet.packet_size, packet.packet_size);
|
||||
assert_eq!(deserialized_packet.packet_crc, packet.packet_crc);
|
||||
|
||||
// Parse the payload
|
||||
let deserialized_payload: TestPayload = deserialized_packet.parse().unwrap();
|
||||
|
||||
// Check payload fields match
|
||||
assert_eq!(deserialized_payload, original_payload);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_packet_from_raw_invalid_size() {
|
||||
// Create a packet with invalid size (too small)
|
||||
let raw_data = vec![0, 0, 0, 0]; // Only 4 bytes, less than minimum 6 bytes
|
||||
|
||||
let result = Packet::from_raw(&raw_data);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_packet_from_raw_size_mismatch() {
|
||||
// Create a packet with size mismatch
|
||||
let mut raw_data = vec![0; 10]; // 10 bytes
|
||||
|
||||
// Set packet size to 20 (more than actual data)
|
||||
raw_data[0] = 20;
|
||||
raw_data[1] = 0;
|
||||
|
||||
let result = Packet::from_raw(&raw_data);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_packet_payload_encoding_decoding() {
|
||||
let original_payload = TestPayload {
|
||||
id: 789,
|
||||
name: "encoding_test".to_string(),
|
||||
value: 1.618,
|
||||
};
|
||||
|
||||
// Encode payload
|
||||
let encoded = bincode::encode_to_vec(&original_payload, bincode::config::standard()).unwrap();
|
||||
|
||||
// Decode payload
|
||||
let decoded: TestPayload = bincode::decode_from_slice(&encoded, bincode::config::standard()).unwrap().0;
|
||||
|
||||
// Check payload fields match
|
||||
assert_eq!(decoded, original_payload);
|
||||
}
|
||||
Reference in New Issue
Block a user