From caae7c98e80ab41f8b9fba8fd0d346623eeb0fd2 Mon Sep 17 00:00:00 2001 From: Chanhee Lee Date: Wed, 14 Feb 2024 16:00:20 -0700 Subject: [PATCH] Add unit test cases for net_util.rs --- rust/rti/Cargo.toml | 2 + rust/rti/src/net_util.rs | 292 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 279 insertions(+), 15 deletions(-) diff --git a/rust/rti/Cargo.toml b/rust/rti/Cargo.toml index 720c8a4..caecf93 100644 --- a/rust/rti/Cargo.toml +++ b/rust/rti/Cargo.toml @@ -8,3 +8,5 @@ edition = "2021" [dependencies] byteorder = "1" priority-queue = "1.3.2" +socket-server-mocker = "0.0.4" +rand = "0.8" diff --git a/rust/rti/src/net_util.rs b/rust/rti/src/net_util.rs index b0ea568..4ac2e4b 100644 --- a/rust/rti/src/net_util.rs +++ b/rust/rti/src/net_util.rs @@ -10,6 +10,14 @@ use std::io::{Read, Write}; use std::mem; use std::net::TcpStream; +use socket_server_mocker::server_mocker::ServerMocker; +use socket_server_mocker::server_mocker_instruction::{ + ServerMockerInstruction, ServerMockerInstructionsList, +}; +use socket_server_mocker::tcp_server_mocker::TcpServerMocker; + +use rand::{rngs::StdRng, Rng, RngCore, SeedableRng}; + use crate::tag::Tag; pub struct NetUtil {} @@ -29,11 +37,6 @@ impl NetUtil { std::process::exit(1); } } {} - // print!(" [[[ PACKET from {} ]]] = ", fed_id); - // for x in buffer { - // print!("{:02X?} ", x); - // } - // println!("\n"); } pub fn read_from_stream(stream: &mut TcpStream, buffer: &mut Vec, fed_id: u16) -> usize { @@ -49,11 +52,6 @@ impl NetUtil { false } } {} - // print!(" [[[ BUFFER from {} ]]] = ", fed_id); - // for x in buffer { - // print!("{:02X?} ", x); - // } - // println!("\n"); bytes_read } @@ -160,11 +158,6 @@ impl NetUtil { } pub fn extract_tag(buffer: &[u8]) -> Tag { - // for x in buffer { - // print!("{:02X?} ", x); - // } - // print!("\n"); - // TODO: Exception handling of unwrap() let time = i64::from_le_bytes(buffer[0..mem::size_of::()].try_into().unwrap()); let microstep = u32::from_le_bytes( buffer[mem::size_of::()..(mem::size_of::() + mem::size_of::())] @@ -175,3 +168,272 @@ impl NetUtil { Tag::new(time, microstep) } } + +#[cfg(test)] +mod tests { + use super::*; + + const MAX_BUFFER_SIZE: usize = 30000; + const ERR_MESSAGE: &str = "test message"; + const I64_SIZE: usize = mem::size_of::(); + const I32_SIZE: usize = mem::size_of::(); + const LOCAL_HOST: &str = "127.0.0.1"; + + #[test] + fn test_read_from_stream_errexit_positive() { + let port_num = 35640; + let tcp_server_mocker = TcpServerMocker::new(port_num).unwrap(); + let mut ip_address = LOCAL_HOST.to_owned(); + ip_address.push_str(":"); + ip_address.push_str(&port_num.to_string()); + let mut stream = TcpStream::connect(ip_address).unwrap(); + let mut rng = rand::thread_rng(); + let buffer_size: usize = rng.gen_range(0..MAX_BUFFER_SIZE); + let msg = generate_random_bytes(buffer_size); + let _ = tcp_server_mocker.add_mock_instructions_list( + ServerMockerInstructionsList::new_with_instructions( + [ServerMockerInstruction::SendMessage(msg.clone())].as_slice(), + ), + ); + let mut buffer = vec![0 as u8; buffer_size]; + NetUtil::read_from_stream_errexit(&mut stream, &mut buffer, 0, ERR_MESSAGE); + assert!(buffer == msg); + } + + fn generate_random_bytes(buffer_size: usize) -> Vec { + let seed = [0u8; 32]; + let mut rng: StdRng = SeedableRng::from_seed(seed); + let mut bytes = vec![0 as u8; buffer_size]; + rng.fill_bytes(&mut bytes); + bytes.to_vec() + } + + #[test] + fn test_read_from_stream_positive() { + let port_num = 35642; + let tcp_server_mocker = TcpServerMocker::new(port_num).unwrap(); + let mut ip_address = LOCAL_HOST.to_owned(); + ip_address.push_str(":"); + ip_address.push_str(&port_num.to_string()); + let mut stream = TcpStream::connect(ip_address).unwrap(); + let mut rng = rand::thread_rng(); + let buffer_size: usize = rng.gen_range(0..MAX_BUFFER_SIZE); + let msg = generate_random_bytes(buffer_size); + let _ = tcp_server_mocker.add_mock_instructions_list( + ServerMockerInstructionsList::new_with_instructions( + [ServerMockerInstruction::SendMessage(msg.clone())].as_slice(), + ), + ); + let mut buffer = vec![0 as u8; buffer_size]; + let read_size = NetUtil::read_from_stream(&mut stream, &mut buffer, 0); + assert!(buffer == msg); + assert!(buffer_size == read_size); + } + + #[test] + fn test_write_to_stream_errexit_positive() { + let port_num = 35644; + let tcp_server_mocker = TcpServerMocker::new(port_num).unwrap(); + let mut ip_address = LOCAL_HOST.to_owned(); + ip_address.push_str(":"); + ip_address.push_str(&port_num.to_string()); + let mut stream = TcpStream::connect(ip_address).unwrap(); + let mut rng = rand::thread_rng(); + let buffer_size: usize = rng.gen_range(0..MAX_BUFFER_SIZE); + let buffer = generate_random_bytes(buffer_size); + let _ = NetUtil::write_to_stream_errexit(&mut stream, &buffer, 0, ERR_MESSAGE); + let _ = tcp_server_mocker.add_mock_instructions_list( + ServerMockerInstructionsList::new_with_instructions( + [ServerMockerInstruction::ReceiveMessage].as_slice(), + ), + ); + assert!(buffer == *tcp_server_mocker.pop_received_message().unwrap()); + } + + #[test] + fn test_write_to_stream_positive() { + let port_num = 35646; + let tcp_server_mocker = TcpServerMocker::new(port_num).unwrap(); + let mut ip_address = LOCAL_HOST.to_owned(); + ip_address.push_str(":"); + ip_address.push_str(&port_num.to_string()); + let mut stream = TcpStream::connect(ip_address).unwrap(); + let mut rng = rand::thread_rng(); + let buffer_size: usize = rng.gen_range(0..MAX_BUFFER_SIZE); + let buffer = generate_random_bytes(buffer_size); + let written_size = NetUtil::write_to_stream(&mut stream, &buffer, 0); + let _ = tcp_server_mocker.add_mock_instructions_list( + ServerMockerInstructionsList::new_with_instructions( + [ServerMockerInstruction::ReceiveMessage].as_slice(), + ), + ); + assert!(buffer == *tcp_server_mocker.pop_received_message().unwrap()); + assert!(buffer_size == written_size); + } + + #[test] + fn test_encode_int64_zero_index_positive() { + let mut rng = rand::thread_rng(); + let value: i64 = rng.gen_range(0..i64::MAX); + let mut buffer = vec![0 as u8; I64_SIZE]; + let _ = NetUtil::encode_int64(value, &mut buffer, 0); + let i64_value = i64::from_le_bytes(buffer[0..I64_SIZE].try_into().unwrap()); + assert!(value == i64_value); + } + + #[test] + fn test_encode_int64_non_zero_index_positive() { + let mut rng = rand::thread_rng(); + let value: i64 = rng.gen_range(0..i64::MAX); + let idx: usize = rng.gen_range(0..I64_SIZE); + let mut buffer = vec![0 as u8; idx + I64_SIZE]; + let _ = NetUtil::encode_int64(value, &mut buffer, idx); + let i64_value = i64::from_le_bytes(buffer[idx..idx + I64_SIZE].try_into().unwrap()); + assert!(value == i64_value); + } + + #[test] + fn test_encode_int64_invalid_index_negative() { + let mut rng = rand::thread_rng(); + let value: i64 = rng.gen_range(0..i64::MAX); + let idx: usize = rng.gen_range(1..I64_SIZE); + let mut buffer = vec![0 as u8; idx + I64_SIZE]; + let _ = NetUtil::encode_int64(value, &mut buffer, idx); + let i64_value = i64::from_le_bytes(buffer[0..I64_SIZE].try_into().unwrap()); + assert!(value != i64_value); + } + + #[test] + fn test_encode_int32_zero_index_positive() { + let mut rng = rand::thread_rng(); + let value: i32 = rng.gen_range(0..i32::MAX); + let mut buffer = vec![0 as u8; I32_SIZE]; + let _ = NetUtil::encode_int32(value, &mut buffer, 0); + let i32_value = i32::from_le_bytes(buffer[0..I32_SIZE].try_into().unwrap()); + assert!(value == i32_value); + } + + #[test] + fn test_encode_int32_non_zero_index_positive() { + let mut rng = rand::thread_rng(); + let value: i32 = rng.gen_range(0..i32::MAX); + let idx: usize = rng.gen_range(0..I64_SIZE); + let mut buffer = vec![0 as u8; idx + I32_SIZE]; + let _ = NetUtil::encode_int32(value, &mut buffer, idx); + let i32_value = i32::from_le_bytes(buffer[idx..idx + I32_SIZE].try_into().unwrap()); + assert!(value == i32_value); + } + + #[test] + fn test_encode_int32_invalid_index_negative() { + let mut rng = rand::thread_rng(); + let value: i32 = rng.gen_range(0..i32::MAX); + let idx: usize = rng.gen_range(1..I32_SIZE); + let mut buffer = vec![0 as u8; idx + I32_SIZE]; + let _ = NetUtil::encode_int32(value, &mut buffer, idx); + let i32_value = i32::from_le_bytes(buffer[0..I32_SIZE].try_into().unwrap()); + assert!(value != i32_value); + } + + #[test] + pub fn test_extract_timed_header_positive() { + let buffer_size = mem::size_of::() * 2 + + mem::size_of::() + + mem::size_of::() + + mem::size_of::(); + let mut buffer = vec![0 as u8; buffer_size]; + let mut rng = rand::thread_rng(); + let port_value: u16 = rng.gen_range(1..u16::MAX); + let federate_id_value: u16 = rng.gen_range(1..u16::MAX); + let local_lenth_signed_value: i32 = rng.gen_range(1..i32::MAX); + let time_value: i64 = rng.gen_range(1..i64::MAX); + let microstep_value: u32 = rng.gen_range(1..u32::MAX); + let mut idx = 0; + for val in port_value.to_le_bytes() { + buffer[idx] = val; + idx += 1; + } + for val in federate_id_value.to_le_bytes() { + buffer[idx] = val; + idx += 1; + } + for val in local_lenth_signed_value.to_le_bytes() { + buffer[idx] = val; + idx += 1; + } + for val in time_value.to_le_bytes() { + buffer[idx] = val; + idx += 1; + } + for val in microstep_value.to_le_bytes() { + buffer[idx] = val; + idx += 1; + } + let mut port = 0; + let mut federate_id = 0; + let mut local_length_signed = 0; + let mut tag = Tag::new(0, 0); + NetUtil::extract_timed_header( + &buffer, + &mut port, + &mut federate_id, + &mut local_length_signed, + &mut tag, + ); + assert!(port == port_value); + assert!(federate_id == federate_id_value); + assert!(local_length_signed == local_lenth_signed_value); + assert!(tag.time() == time_value); + assert!(tag.microstep() == microstep_value); + } + + #[test] + pub fn test_extract_timed_header_negative_local_length_negative() { + let buffer_size = mem::size_of::() * 2 + + mem::size_of::() + + mem::size_of::() + + mem::size_of::(); + let mut buffer = vec![0 as u8; buffer_size]; + let mut rng = rand::thread_rng(); + let port_value: u16 = rng.gen_range(1..u16::MAX); + let federate_id_value: u16 = rng.gen_range(1..u16::MAX); + let local_lenth_signed_value: i32 = rng.gen_range(1..i32::MAX - 1) * (-1); + let time_value: i64 = rng.gen_range(1..i64::MAX); + let microstep_value: u32 = rng.gen_range(1..u32::MAX); + let mut idx = 0; + for val in port_value.to_le_bytes() { + buffer[idx] = val; + idx += 1; + } + for val in federate_id_value.to_le_bytes() { + buffer[idx] = val; + idx += 1; + } + for val in local_lenth_signed_value.to_le_bytes() { + buffer[idx] = val; + idx += 1; + } + for val in time_value.to_le_bytes() { + buffer[idx] = val; + idx += 1; + } + for val in microstep_value.to_le_bytes() { + buffer[idx] = val; + idx += 1; + } + let mut port = 0; + let mut federate_id = 0; + let mut local_length_signed = 0; + let mut tag = Tag::new(0, 0); + NetUtil::extract_timed_header( + &buffer, + &mut port, + &mut federate_id, + &mut local_length_signed, + &mut tag, + ); + assert!(port == port_value); + assert!(federate_id == federate_id_value); + assert!(local_length_signed == 0); + } +}