test: add tests

refactor: ♻️ routing_operations
This commit is contained in:
Ahmet Kaan GÜMÜŞ 2024-05-27 01:33:30 +03:00
parent e67aee396f
commit da2b65e7dc
4 changed files with 152 additions and 41 deletions

View file

@ -6,6 +6,7 @@ use tokio::sync::Mutex;
pub mod chat;
pub mod routing;
pub mod routing_operations;
pub mod test;
pub mod utils;
@ -24,7 +25,7 @@ pub struct AppState {
}
impl AppState {
pub async fn is_chat_exists(&mut self, room_id: &String) -> Option<usize> {
pub async fn is_chat_exists(&self, room_id: &String) -> Option<usize> {
let chats = self.chats.lock().await;
for i in 0..chats.len() {
if chats[i].room_id == *room_id {
@ -52,10 +53,6 @@ impl AppState {
}
}
}
// if chats[chat_index].last_interaction < current - chat_cleaning_timeout as u64 {
// chats.remove(chat_index);
// return;
// }
}
}
}

View file

@ -8,10 +8,7 @@ use axum::{
use serde::Deserialize;
use tower_http::cors::CorsLayer;
use crate::{
chat::{Chat, Message},
AppState,
};
use crate::{routing_operations, AppState};
#[derive(Debug, Deserialize)]
struct ReceivedMessage {
@ -37,46 +34,18 @@ async fn alive() -> impl IntoResponse {
}
async fn receive_message(
State(mut state): State<AppState>,
State(state): State<AppState>,
Json(received_message): Json<ReceivedMessage>,
) {
let sender = received_message.username;
let data = received_message.message;
let room_id = received_message.room_id;
let message = Message::new(sender, data);
match state.is_chat_exists(&room_id).await {
Some(index) => {
let mut chats = state.chats.lock().await;
chats[index].add_message(message, state.max_message_counter);
}
None => {
let mut new_chat = Chat::new(room_id);
new_chat.add_message(message, state.max_message_counter);
let mut chats = state.chats.lock().await;
let room_id = new_chat.room_id.clone();
chats.push(new_chat);
drop(chats);
tokio::spawn(AppState::chat_destroyer(
state.chats.clone(),
room_id,
state.chat_cleaning_timeout,
));
}
}
routing_operations::receive_message(sender, data, room_id, &state).await;
}
async fn send_message(
Path(room_id): Path<String>,
State(mut state): State<AppState>,
State(state): State<AppState>,
) -> impl IntoResponse {
match state.is_chat_exists(&room_id).await {
Some(index) => {
let chats = state.chats.lock().await;
(
StatusCode::OK,
serde_json::to_string(&chats[index]).unwrap(),
)
}
None => (StatusCode::BAD_REQUEST, serde_json::to_string("").unwrap()),
}
routing_operations::send_message(room_id, state).await
}

50
src/routing_operations.rs Normal file
View file

@ -0,0 +1,50 @@
use axum::http::StatusCode;
use crate::{
chat::{Chat, Message},
AppState,
};
pub async fn receive_message(
sender: impl ToString,
data: impl ToString,
room_id: impl ToString,
state: &AppState,
) {
let message = Message::new(sender.to_string(), data.to_string());
match state.is_chat_exists(&room_id.to_string()).await {
Some(index) => {
let mut chats = state.chats.lock().await;
chats[index].add_message(message, state.max_message_counter);
}
None => {
let mut new_chat = Chat::new(room_id.to_string());
new_chat.add_message(message, state.max_message_counter);
let mut chats = state.chats.lock().await;
let room_id = new_chat.room_id.clone();
chats.push(new_chat);
drop(chats);
tokio::spawn(AppState::chat_destroyer(
state.chats.clone(),
room_id,
state.chat_cleaning_timeout,
));
}
}
}
pub async fn send_message(
room_id: impl ToString,
state: AppState,
) -> (axum::http::StatusCode, std::string::String) {
match state.is_chat_exists(&room_id.to_string()).await {
Some(index) => {
let chats = state.chats.lock().await;
(
StatusCode::OK,
serde_json::to_string(&chats[index]).unwrap(),
)
}
None => (StatusCode::BAD_REQUEST, serde_json::to_string("").unwrap()),
}
}

View file

@ -1 +1,96 @@
#[cfg(test)]
use crate::{routing_operations::receive_message, AppState};
#[cfg(test)]
use std::sync::Arc;
#[cfg(test)]
use std::time::Duration;
#[cfg(test)]
use tokio::sync::Mutex;
#[tokio::test]
async fn new_message_no_chat() {
let state = AppState {
chats: Arc::new(Mutex::new(vec![])),
max_message_counter: 5,
chat_cleaning_timeout: 10,
};
receive_message("Tahinli", "Hi", "Tahinli-Chat", &state).await;
let chats = state.chats.lock().await;
assert_eq!(chats.len(), 1);
assert_eq!(chats[0].messages.len(), 1);
}
#[tokio::test]
async fn new_message_with_chat() {
let state = AppState {
chats: Arc::new(Mutex::new(vec![])),
max_message_counter: 5,
chat_cleaning_timeout: 10,
};
receive_message("Tahinli", "Hi", "Tahinli-Chat", &state).await;
let chats = state.chats.lock().await;
assert_eq!(chats.len(), 1);
assert_eq!(chats[0].messages.len(), 1);
drop(chats);
receive_message("Tahinli", "Hi Again", "Tahinli-Chat", &state).await;
let chats = state.chats.lock().await;
assert_eq!(chats.len(), 1);
assert_eq!(chats[0].messages.len(), 2);
}
#[tokio::test]
async fn chat_auto_deletion_with_timeout() {
let state = AppState {
chats: Arc::new(Mutex::new(vec![])),
max_message_counter: 5,
chat_cleaning_timeout: 1,
};
receive_message("Tahinli", "Hi", "Tahinli-Chat", &state).await;
let chats = state.chats.lock().await;
assert_eq!(chats.len(), 1);
assert_eq!(chats[0].messages.len(), 1);
drop(chats);
tokio::time::sleep(Duration::from_secs(2)).await;
let chats = state.chats.lock().await;
assert_eq!(chats.len(), 0);
}
#[tokio::test]
async fn message_auto_deletion_with_counter() {
let state = AppState {
chats: Arc::new(Mutex::new(vec![])),
max_message_counter: 1,
chat_cleaning_timeout: 10,
};
receive_message("Tahinli", "Hi", "Tahinli-Chat", &state).await;
let chats = state.chats.lock().await;
assert_eq!(chats.len(), 1);
assert_eq!(chats[0].messages.len(), 1);
drop(chats);
receive_message("Tahinli", "Hi", "Tahinli-Chat", &state).await;
let chats = state.chats.lock().await;
assert_eq!(chats.len(), 1);
assert_eq!(chats[0].messages.len(), 1);
}
#[tokio::test]
async fn create_multiple_chats() {
let state = AppState {
chats: Arc::new(Mutex::new(vec![])),
max_message_counter: 1,
chat_cleaning_timeout: 10,
};
receive_message("Tahinli", "Hi", "Tahinli-Chat-1", &state).await;
let chats = state.chats.lock().await;
assert_eq!(chats.len(), 1);
assert_eq!(chats[0].messages.len(), 1);
drop(chats);
receive_message("Tahinli", "Hi", "Tahinli-Chat-2", &state).await;
let chats = state.chats.lock().await;
assert_eq!(chats.len(), 2);
assert_eq!(chats[1].messages.len(), 1);
}