Skip to content

Commit

Permalink
test: ✅ new tests
Browse files Browse the repository at this point in the history
refactor: ♻️ routing_operations
  • Loading branch information
Tahinli committed May 26, 2024
1 parent fb951c4 commit 5350348
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 41 deletions.
7 changes: 2 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use tokio::sync::Mutex;

pub mod chat;
pub mod routing;
pub mod routing_operations;
pub mod test;
pub mod utils;

Expand All @@ -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 {
Expand Down Expand Up @@ -52,10 +53,6 @@ impl AppState {
}
}
}
// if chats[chat_index].last_interaction < current - chat_cleaning_timeout as u64 {
// chats.remove(chat_index);
// return;
// }
}
}
}
41 changes: 5 additions & 36 deletions src/routing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 changes: 50 additions & 0 deletions src/routing_operations.rs
Original file line number Diff line number Diff line change
@@ -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()),
}
}
95 changes: 95 additions & 0 deletions src/test.rs
Original file line number Diff line number Diff line change
@@ -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);
}

0 comments on commit 5350348

Please sign in to comment.