added unit tests for sender and receiver

This commit is contained in:
Patryk Hegenberg 2024-04-28 01:43:24 +02:00
parent 97d1ff9323
commit a362d8ce5c
5 changed files with 323 additions and 31 deletions

View file

@ -15,8 +15,8 @@ jobs:
include:
- name: linux
os: ubuntu-latest
artifact_name: caesar
asset_name: caesar-linux-amd64
artifact_name: target/release/caesar
asset_name: caesar-linux
steps:
- name: Checkout

View file

@ -606,3 +606,156 @@ pub async fn start(socket: Socket, fragment: &str) {
// Wait for either future to complete
future::select(incoming_handler, outgoing_handler).await;
}
#[cfg(test)]
mod tests {
use super::*;
use aes_gcm::KeyInit;
use tokio_tungstenite::tungstenite::Message as WebSocketMessage;
#[test]
fn test_on_join_room_valid_size() {
assert_eq!(on_join_room(Some(10)), Status::Continue());
}
#[test]
fn test_on_join_room_invalid_size() {
assert_eq!(
on_join_room(None),
Status::Err("Invalid join room packet.".into())
);
}
#[test]
fn test_on_error_with_message() {
assert_eq!(
on_error("Error message".to_string()),
Status::Err("Error message".to_string())
);
}
#[test]
fn test_on_leave_room() {
let (sender, _) = flume::bounded(1000);
let mut context = Context {
hmac: vec![],
sender: sender,
key: EphemeralSecret::random(&mut OsRng),
shared_key: None,
files: vec![
File {
name: "file1.txt".to_string(),
size: 100,
progress: 100,
handle: fs::File::create("file1.txt").unwrap(),
},
File {
name: "file2.txt".to_string(),
size: 100,
progress: 50,
handle: fs::File::create("file2.txt").unwrap(),
},
],
sequence: 0,
index: 0,
progress: 0,
length: 0,
};
assert_eq!(
on_leave_room(&mut context, 0),
Status::Err("Transfer was interrupted because the host left the room.".into())
);
context.files[1].progress = 100;
assert_eq!(on_leave_room(&mut context, 0), Status::Exit());
}
#[test]
fn test_on_message_text_join() {
let (sender, _) = flume::bounded(1000);
let mut context = Context {
hmac: vec![],
sender: sender,
key: EphemeralSecret::random(&mut OsRng),
shared_key: None,
files: vec![],
sequence: 0,
index: 0,
progress: 0,
length: 0,
};
let text_message = WebSocketMessage::Text(r#"{"type":"join","size":10}"#.to_string());
assert_eq!(on_message(&mut context, text_message), Status::Continue());
}
#[test]
fn test_on_chunk() {
let (sender, _) = flume::bounded(1000);
// let mut context = Context {
// hmac: vec![],
// sender: sender.clone(),
// key: EphemeralSecret::random(&mut OsRng),
// shared_key: Some(Aes128Gcm::new(Key::<Aes128Gcm>::from_slice(&[0u8; 16]))),
// files: vec![File {
// name: "file1.txt".to_string(),
// size: 100,
// progress: 0,
// handle: fs::File::create("file1.txt").unwrap(),
// }],
// sequence: 0,
// index: 0,
// progress: 0,
// length: 0,
// };
// let chunk_packet = ChunkPacket {
// sequence: 0,
// chunk: b"Hello, world!".to_vec(),
// };
// assert_eq!(on_chunk(&mut context, chunk_packet), Status::Continue());
// assert_eq!(context.sequence, 1);
// assert_eq!(context.length, 14);
// assert_eq!(context.progress, 14);
// let chunk_packet = ChunkPacket {
// sequence: 1,
// chunk: b"Hello, world!".to_vec(),
// };
// assert_eq!(
// on_chunk(&mut context, chunk_packet),
// Status::Err("Expected sequence 1, but got 1.".into())
// );
// context.files.clear();
// let chunk_packet = ChunkPacket {
// sequence: 0,
// chunk: b"Hello, world!".to_vec(),
// };
// assert_eq!(
// on_chunk(&mut context, chunk_packet),
// Status::Err("Invalid file index.".into())
// );
// Test a chunk packet with no shared key
let mut context = Context {
hmac: vec![],
sender: sender,
key: EphemeralSecret::random(&mut OsRng),
shared_key: None,
files: vec![File {
name: "file1.txt".to_string(),
size: 100,
progress: 0,
handle: fs::File::create("file1.txt").unwrap(),
}],
sequence: 0,
index: 0,
progress: 0,
length: 0,
};
let chunk_packet = ChunkPacket {
sequence: 0,
chunk: b"Hello, world!".to_vec(),
};
assert_eq!(
on_chunk(&mut context, chunk_packet),
Status::Err("Invalid chunk packet: no shared key established".into())
);
}
}

View file

@ -704,3 +704,170 @@ pub async fn start(socket: Socket, paths: Vec<String>) {
// `outgoing_handler` completes, return the result of the `outgoing_handler`.
future::select(incoming_handler, outgoing_handler).await;
}
#[cfg(test)]
mod tests {
use super::*;
use aes_gcm::KeyInit;
#[test]
fn test_on_chunk() {
let (sender, _) = flume::bounded(1000);
let mut context = Context {
hmac: vec![],
sender: sender,
key: EphemeralSecret::random(&mut OsRng),
shared_key: None,
files: vec![
File {
name: "file1.txt".to_string(),
size: 100,
path: "file1.txt".to_string(),
},
File {
name: "file2.txt".to_string(),
size: 100,
path: "file2.txt".to_string(),
},
],
task: None,
};
}
#[test]
fn test_on_progress() {
let (sender, _) = flume::bounded(1000);
let mut context = Context {
hmac: vec![],
sender: sender,
key: EphemeralSecret::random(&mut OsRng),
shared_key: Some(Aes128Gcm::new(Key::<Aes128Gcm>::from_slice(&[0u8; 16]))),
files: vec![
File {
name: "file1.txt".to_string(),
size: 100,
path: "file1.txt".to_string(),
},
File {
name: "file2.txt".to_string(),
size: 100,
path: "file2.txt".to_string(),
},
],
task: None,
};
assert_eq!(on_progress(&context, ProgressPacket { index: 0, progress: 50 }), Status::Continue());
}
#[test]
fn test_on_create_room() {
let (sender, _) = flume::bounded(1000);
let mut context = Context {
hmac: vec![],
sender: sender,
key: EphemeralSecret::random(&mut OsRng),
shared_key: None,
files: vec![
File {
name: "file1.txt".to_string(),
size: 100,
path: "file1.txt".to_string(),
},
File {
name: "file2.txt".to_string(),
size: 100,
path: "file2.txt".to_string(),
},
],
task: None,
};
assert_eq!(
on_create_room(
&context,
"b531e87d-e51a-4507-94f4-335cbe2d32f3-Nc5skZReq7qJN7INwckyAZLWEEbxsrFfH/692tUNgkM="
.to_string()
),
Status::Continue()
);
}
// #[test]
// fn test_on_join_room(){
// let (sender, _) = flume::bounded(1000);
// let mut context = Context {
// hmac: vec![],
// sender: sender,
// key: EphemeralSecret::random(&mut OsRng),
// shared_key: None,
// files: vec![
// File {
// name: "file1.txt".to_string(),
// size: 100,
// path: "file1.txt".to_string(),
// },
// File {
// name: "file2.txt".to_string(),
// size: 100,
// path: "file2.txt".to_string(),
// },
// ],
// task: None,
// };
// assert_eq!(on_join_room(&context, None), Status::Continue());
// }
#[test]
fn test_on_error() {
assert_eq!(
on_error("Error message".to_string()),
Status::Err("Error message".to_string())
);
}
#[test]
fn test_on_leave_room() {
let (sender, _) = flume::bounded(1000);
let mut context = Context {
hmac: vec![],
sender: sender,
key: EphemeralSecret::random(&mut OsRng),
shared_key: None,
files: vec![
File {
name: "file1.txt".to_string(),
size: 100,
path: "file1.txt".to_string(),
},
File {
name: "file2.txt".to_string(),
size: 100,
path: "file2.txt".to_string(),
},
],
task: None,
};
assert_eq!(on_leave_room(&mut context, 5), Status::Continue());
}
#[test]
fn test_on_message() {
let (sender, _) = flume::bounded(1000);
let mut context = Context {
hmac: vec![],
sender: sender,
key: EphemeralSecret::random(&mut OsRng),
shared_key: None,
files: vec![
File {
name: "file1.txt".to_string(),
size: 100,
path: "file1.txt".to_string(),
},
File {
name: "file2.txt".to_string(),
size: 100,
path: "file2.txt".to_string(),
},
],
task: None,
};
assert_eq!(on_message(&mut context, WebSocketMessage::Text(r#"{"type":"leave","index":5}"#.to_string())), Status::Continue());
assert_eq!(on_message(&mut context, WebSocketMessage::Text(r#"{"type":"create","id":"b531e87d-e51a-4507-94f4-335cbe2d32f3-Nc5skZReq7qJN7INwckyAZLWEEbxsrFfH/692tUNgkM="}"#.to_string())), Status::Continue());
assert_eq!(on_message(&mut context, WebSocketMessage::Text(r#"{"type":"error","message":"Error Message: Test"}"#.to_string())), Status::Err("Error Message: Test".to_string()));
}
}

View file

@ -63,40 +63,11 @@ pub async fn start_sender(relay: &str, files: &[String]) {
}
Err(e) => {
error!("Error: Failed to connect with error: {e}");
return;
}
}
}
Err(e) => {
error!("Error: failed to create request with reason: {e:?}");
return;
}
}
// let Ok(mut request) = relay.into_client_request() else {
// println!("Error: Failed to create request.");
// return;
// };
// request
// .headers_mut()
// .insert("Origin", HeaderValue::from_str(relay).unwrap());
// debug!("Attempting to connect to {relay}...");
// match connect_async(request).await {
// Ok((socket, _)) => {
// let paths = files.to_vec();
// sender::start(socket, paths).await;
// }
// Err(e) => {
// error!("Error: Failed to connect with error: {e}");
// return;
// }
// }
// let Ok((socket, _)) = connect_async(request).await else {
// error!("Error: Failed to connect.");
// return;
// };
// let paths = files.to_vec();
// sender::start(socket, paths).await
}

View file

@ -110,6 +110,7 @@ pub enum JsonPacketResponse {
/// written from the perspective of the user and should give the user enough
/// information to understand what went wrong and how they might be able to
/// fix the problem.
#[derive(Debug, PartialEq)]
pub enum Status {
/// Indicates that the event loop should continue processing events.
Continue(),