#![feature(type_alias_impl_trait)]
#![feature(unboxed_closures)]
#![feature(buf_read_has_data_left)]
#![feature(mapped_lock_guards)]
#![feature(str_as_str)]
#![feature(const_trait_impl)]
#![feature(const_cmp)]
#![feature(macro_metavar_expr)]
#![feature(const_default)]
pub mod cache;
pub mod cli;
pub mod core;
pub mod dependencies;
pub mod hash;
pub mod id;
pub mod json;
pub mod log;
pub mod maths;
pub mod net;
pub mod pipelines;
pub mod scripting;
pub mod search;
pub mod strings;
pub mod threading;
pub mod types;
pub mod buffers;
#[cfg(test)]
mod tests {
use super::*;
use crate::buffers::{buffer_find, buffer_replace, buffer_replace_in_place, buffer_slice_trim, buffer_split_fast, buffer_to_string, buffer_trim};
use crate::cache::RUMCache;
use crate::core::{clamp_index, RUMResult};
use crate::search::rumtk_search::*;
use crate::strings::{rumtk_format, AsStr, RUMArrayConversions, RUMString, RUMStringConversions, StringUtils};
use crate::types::{RUMBuffer, RUMDeserialize, RUMDeserializer, RUMSerialize, RUMSerializer};
use compact_str::CompactString;
use serde_json::to_string;
use std::process::Stdio;
use std::sync::Arc;
use tokio::io::AsyncBufReadExt;
use tokio::sync::RwLock;
#[test]
fn test_is_escaped_str() {
let input = "\r\n\'\\\"";
let expected = false;
let result = strings::is_escaped_str(input);
println!("Input: {} Expected: {} Got: {}", input, expected, result);
assert_eq!(
expected, result,
"Incorrect detection of unescaped string as escaped!!"
);
println!("Passed!")
}
#[test]
fn test_escaping_control() {
let input = "\r\n\'\"\\";
let expected = "\\r\\n\\'\\\"\\\\";
let result = strings::escape(input);
println!(
"Input: {} Expected: {} Got: {}",
input,
expected,
result.as_str()
);
assert_eq!(expected, result, "Incorrect string escaping!");
println!("Passed!")
}
#[test]
fn test_escaping_unicode() {
let input = "❤";
let expected = "\\u2764";
let result = strings::escape(input);
println!(
"Input: {} Expected: {} Got: {}",
input,
expected,
result.as_str()
);
assert_eq!(expected, result, "Incorrect string escaping!");
println!("Passed!")
}
#[test]
fn test_unescaping_unicode() {
let input = "❤";
let escaped = strings::escape(input);
let expected = "❤";
let result = RUMString::from_utf8(strings::unescape(escaped.as_str()).unwrap()).unwrap();
println!(
"Input: {} Expected: {} Got: {}",
input,
expected,
result.as_str()
);
assert_eq!(expected, result.as_str(), "Incorrect string unescaping!");
println!("Passed!")
}
#[test]
fn test_unescaping_string() {
let input = "I \\u2764 my wife!";
let expected = "I ❤ my wife!";
let result = strings::unescape_string(input).unwrap();
println!(
"Input: {} Expected: {} Got: {}",
input,
expected,
result.as_str()
);
assert_eq!(expected, result.as_str(), "Incorrect string unescaping!");
println!("Passed!")
}
#[test]
fn test_is_escaped_string() {
let input = "I \\u2764 my wife!";
let expected = true;
let result = strings::is_escaped_str(input);
println!("Input: {} Expected: {} Got: {}", input, expected, result);
assert_eq!(
expected, result,
"Escaped string detected as unescaped string!"
);
println!("Passed!")
}
#[test]
fn test_is_unescaped_string() {
let input = "I ❤ my wife!";
let expected = false;
let result = strings::is_escaped_str(input);
println!("Input: {} Expected: {} Got: {}", input, expected, result);
assert_eq!(
expected, result,
"Unescaped string detected as escaped string!"
);
println!("Passed!")
}
#[test]
fn test_unique_string() {
let input = "I❤mywife!";
assert!(
input.as_grapheme_str().is_unique(),
"String was not detected as unique."
);
}
#[test]
fn test_non_unique_string() {
let input = "I❤❤mywife!";
assert!(
!input.as_grapheme_str().is_unique(),
"String was detected as unique."
);
}
#[test]
fn test_escaping_string() {
let input = "I ❤ my wife!";
let expected = "I \\u2764 my wife!";
let result = strings::escape(input);
println!(
"Input: {} Expected: {} Got: {}",
input,
expected,
result.as_str()
);
assert_eq!(expected, result.as_str(), "Incorrect string escaping!");
println!("Passed!")
}
#[test]
fn test_autodecode_utf8() {
let input = "I ❤ my wife!";
let result = strings::try_decode(input.as_bytes()).unwrap();
println!(
"Input: {} Expected: {} Got: {}",
input,
input,
result.as_str()
);
assert_eq!(input, result, "Incorrect string decoding!");
println!("Passed!")
}
#[test]
fn test_autodecode_other() {
let input = "I ❤ my wife!";
let result = input;
println!("Input: {} Expected: {} Got: {}", input, input, result);
assert_eq!(input, result, "Incorrect string decoding!");
println!("Passed!")
}
#[test]
fn test_decode() {
let input = "I ❤ my wife!";
let result = strings::try_decode_with(input.as_bytes(), "utf-8").unwrap();
println!(
"Input: {} Expected: {} Got: {}",
input,
input,
result.as_str()
);
assert_eq!(input, result, "Incorrect string decoding!");
println!("Passed!")
}
#[test]
fn test_rumcache_insertion() {
let mut cache: RUMCache<&str, CompactString> = RUMCache::with_capacity(5);
cache.insert("❤", CompactString::from("I ❤ my wife!"));
println!("Contents: {:#?}", &cache);
assert_eq!(cache.len(), 1, "Incorrect number of items in cache!");
println!("Passed!")
}
#[test]
fn test_search_string_letters() {
let input = "Hello World!";
let expr = r"\w";
let result = string_search(input, expr, "").unwrap();
let expected: RUMString = RUMString::from("HelloWorld");
println!(
"Input: {:?} Expected: {:?} Got: {:?}",
input, expected, result
);
assert_eq!(expected, result, "String search results mismatch");
println!("Passed!")
}
#[test]
fn test_search_string_words() {
let input = "Hello World!";
let expr = r"\w+";
let result = string_search(input, expr, " ").unwrap();
let expected: RUMString = RUMString::from("Hello World");
println!(
"Input: {:?} Expected: {:?} Got: {:?}",
input, expected, result
);
assert_eq!(expected, result, "String search results mismatch");
println!("Passed!")
}
#[test]
fn test_search_string_named_groups() {
let input = "Hello World!";
let expr = r"(?<hello>\w{5}) (?<world>\w{5})";
let result = string_search_named_captures(input, expr, "").unwrap();
let expected: RUMString = RUMString::from("World");
println!(
"Input: {:?} Expected: {:?} Got: {:?}",
input, expected, result
);
assert_eq!(expected, result["world"], "String search results mismatch");
println!("Passed!")
}
#[test]
fn test_search_string_all_groups() {
let input = "Hello World!";
let expr = r"(?<hello>\w{5}) (?<world>\w{5})";
let result = string_search_all_captures(input, expr, "").unwrap();
let expected: Vec<&str> = vec!["Hello", "World"];
println!(
"Input: {:?} Expected: {:?} Got: {:?}",
input, expected, result
);
assert_eq!(expected, result, "String search results mismatch");
println!("Passed!")
}
#[test]
fn test_find_value_in_string() {
let haystack = "Range (min \\xe2\\x80\\xa6 max): 0.6 ms \\xe2\\x80\\xa6 2.9 ms 1273 runs";
let patterns = ["\\d+ runs", "\\d+"];
let expected = 1273;
let result = string_find_value::<usize>(haystack, &patterns);
assert_eq!(result, Ok(expected), "Did not find the needle in the haystack or returned the wrong type!");
}
#[test]
fn test_default_num_threads() {
use num_cpus;
let threads = threading::threading_functions::get_default_system_thread_count();
assert_eq!(
threads >= num_cpus::get(),
true,
"Default thread count is incorrect! We got {}, but expected {}!",
threads,
num_cpus::get()
);
}
#[test]
fn test_execute_job() {
let expected = vec![1, 2, 3];
let task_processor = async |args: &SafeTaskArgs<i32>| -> RUMResult<Vec<i32>> {
let owned_args = Arc::clone(args);
let lock_future = owned_args.read();
let locked_args = lock_future.await;
let mut results = TaskItems::<i32>::with_capacity(locked_args.len());
print!("Contents: ");
for arg in locked_args.iter() {
results.push(arg.clone());
println!("{} ", &arg);
}
Ok(results)
};
let locked_args = RwLock::new(expected.clone());
let task_args = SafeTaskArgs::<i32>::new(locked_args);
let task_result = rumtk_wait_on_task!(task_processor, &task_args);
let result = task_result.unwrap();
assert_eq!(&result, &expected, "{}", rumtk_format!("Task processing returned a different result than expected! Expected {:?} \nResults {:?}", &expected, &result));
}
#[test]
fn test_execute_job_macros() {
let expected = vec![1, 2, 3];
let task_processor = async |args: &SafeTaskArgs<i32>| -> RUMResult<Vec<i32>> {
let owned_args = Arc::clone(args);
let lock_future = owned_args.read();
let locked_args = lock_future.await;
let mut results = TaskItems::<i32>::with_capacity(locked_args.len());
print!("Contents: ");
for arg in locked_args.iter() {
results.push(arg.clone());
println!("{} ", &arg);
}
Ok(results)
};
let task_args = rumtk_create_task_args!(1, 2, 3);
let task_result = rumtk_wait_on_task!(task_processor, &task_args);
let result = task_result.unwrap();
assert_eq!(&result, &expected, "{}", rumtk_format!("Task processing returned a different result than expected! Expected {:?} \nResults {:?}", &expected, &result));
}
#[test]
fn test_execute_job_macros_one_line() {
let expected = vec![1, 2, 3];
let result = rumtk_exec_task!(
async |args: &SafeTaskArgs<i32>| -> RUMResult<Vec<i32>> {
let owned_args = Arc::clone(args);
let lock_future = owned_args.read();
let locked_args = lock_future.await;
let mut results = TaskItems::<i32>::with_capacity(locked_args.len());
print!("Contents: ");
for arg in locked_args.iter() {
results.push(arg.clone());
println!("{} ", &arg);
}
Ok(results)
},
vec![1, 2, 3]
)
.unwrap();
assert_eq!(&result, &expected, "{}", rumtk_format!("Task processing returned a different result than expected! Expected {:?} \nResults {:?}", &expected, &result));
}
#[test]
fn test_clamp_index_positive_index() {
let values = vec![1, 2, 3, 4];
let given_index = 3isize;
let max_size = values.len() as isize;
let index = clamp_index(&given_index, &max_size).unwrap();
assert_eq!(
index, 3,
"Index mismatch! Requested index {} but got {}",
&given_index, &index
);
assert_eq!(
values[index], 4,
"Value mismatch! Expected {} but got {}",
&values[3], &values[index]
);
}
#[test]
fn test_clamp_index_reverse_index() {
let values = vec![1, 2, 3, 4];
let given_index = -1isize;
let max_size = values.len() as isize;
let index = clamp_index(&given_index, &max_size).unwrap();
assert_eq!(
index, 4,
"Index mismatch! Requested index {} but got {}",
&given_index, &index
);
assert_eq!(
values[index - 1],
4,
"Value mismatch! Expected {} but got {}",
&values[3],
&values[index]
);
}
#[test]
fn test_block_on_task() {
let expect = 5;
let value = block_on_task(async move { 5 });
assert_eq!(
value, 5,
"Value mismatch from async task! Expected {} but got {}",
&expect, &value
);
}
use crate::cli::cli_utils::print_license_notice;
use crate::net::tcp::LOCALHOST;
use crate::pipelines::pipeline_functions::{pipeline_add_stdin_data_to_pipeline, pipeline_create_command, pipeline_patch_args, pipeline_pipe_processes, pipeline_spawn_process};
use crate::pipelines::pipeline_types::RUMCommand;
use crate::threading::threading_functions::block_on_task;
use crate::threading::threading_manager::*;
#[test]
fn test_queue_data() {
let expected = vec![
RUMString::from("Hello"),
RUMString::from("World!"),
RUMString::from("Overcast"),
RUMString::from("and"),
RUMString::from("Sad"),
];
type TestResult = RUMResult<Vec<RUMString>>;
let mut queue: TaskManager<TestResult> = TaskManager::new(&5).unwrap();
let locked_args = RwLock::new(expected.clone());
let task_args = SafeTaskArgs::<RUMString>::new(locked_args);
let processor = rumtk_create_task!(
async |args: &SafeTaskArgs<RUMString>| -> TestResult {
let owned_args = Arc::clone(args);
let lock_future = owned_args.read();
let locked_args = lock_future.await;
let mut results = TaskItems::<RUMString>::with_capacity(locked_args.len());
print!("Contents: ");
for arg in locked_args.iter() {
print!("{} ", &arg);
results.push(RUMString::from(arg));
}
Ok(results)
},
task_args
);
queue.add_task::<_>(processor);
let results = queue.wait();
let mut result_data = Vec::<RUMString>::with_capacity(5);
for r in results {
for v in r.unwrap().result.clone().unwrap().iter() {
for value in v.iter() {
result_data.push(value.clone());
}
}
}
assert_eq!(result_data, expected, "Results do not match expected!");
}
#[test]
fn test_server_start() {
let server = match rumtk_create_server!("localhost", 0) {
Ok(server) => server,
Err(e) => panic!("Failed to create server because {}", e),
};
}
#[test]
fn test_server_send() {
let msg = RUMString::from("Hello World!");
let mut server = match rumtk_create_server!(LOCALHOST, 0) {
Ok(server) => server,
Err(e) => panic!("Failed to create server because {}", e),
};
let address_info = server.get_address_info().unwrap();
let (ip, port) = rumtk_get_ip_port!(address_info);
rumtk_sleep!(1);
let mut client = match rumtk_connect!(port) {
Ok(client) => client,
Err(e) => panic!("Failed to create server because {}", e),
};
let client_id = client.get_address().unwrap();
match server.send(&client_id, &msg.to_raw()) {
Ok(_) => (),
Err(e) => panic!("Server failed to send message because {}", e),
};
let received_message = client.receive().unwrap();
assert_eq!(
&msg.len(),
&received_message.len(),
"Received message does not match expected length!"
);
assert_eq!(
&msg.to_raw(),
&received_message,
"{}",
rumtk_format!(
"Received message does not match sent message by server {:?}",
&received_message
)
);
}
#[test]
fn test_server_receive() {
let msg = RUMString::from("Hello World!");
let mut server = match rumtk_create_server!(LOCALHOST, 0) {
Ok(server) => server,
Err(e) => panic!("Failed to create server because {}", e),
};
let address_info = server.get_address_info().unwrap();
let (ip, port) = rumtk_get_ip_port!(address_info);
println!("Sleeping");
rumtk_sleep!(1);
let mut client = match rumtk_connect!(port) {
Ok(client) => client,
Err(e) => panic!("Failed to create server because {}", e),
};
println!("Sleeping");
rumtk_sleep!(1);
match client.send(msg.to_raw()) {
Ok(_) => (),
Err(e) => panic!("Failed to send message because {}", e),
};
let client_id = client.get_address().expect("Failed to get client id");
let incoming_message = server.receive(&client_id, true).unwrap().to_string().unwrap();
println!("Received message => {:?}", &incoming_message);
assert_eq!(incoming_message, msg, "Received message corruption!");
}
#[test]
fn test_server_get_clients() {
let mut server = match rumtk_create_server!(LOCALHOST, 0) {
Ok(server) => server,
Err(e) => panic!("Failed to create server because {}", e),
};
let address_info = server.get_address_info().unwrap();
let (ip, port) = rumtk_get_ip_port!(address_info);
println!("Sleeping");
rumtk_sleep!(1);
let mut client = match rumtk_connect!(port) {
Ok(client) => client,
Err(e) => panic!("Failed to create client because {}", e),
};
println!("Sleeping");
rumtk_sleep!(1);
let expected_client_id = client.get_address().expect("Failed to get client id");
let clients = server.get_client_ids();
let incoming_client_id = clients.get(0).expect("Expected client to have connected!");
println!("Connected client id => {}", &incoming_client_id);
assert_eq!(
incoming_client_id, &expected_client_id,
"Connected client does not match the connecting client! Client id => {}",
&incoming_client_id
);
}
#[test]
fn test_server_stop() {
let msg = RUMString::from("Hello World!");
let server = match rumtk_create_server!("localhost", 0) {
Ok(server) => server,
Err(e) => panic!("Failed to create server because {}", e),
};
println!("Sleeping");
}
#[test]
fn test_server_get_address_info() {
let msg = RUMString::from("Hello World!");
let mut server = match rumtk_create_server!("localhost", 0) {
Ok(server) => server,
Err(e) => panic!("Failed to create server because {}", e),
};
let addr = server.get_address_info().unwrap();
assert!(!addr.is_empty(), "No address returned....Got => {}", addr)
}
#[test]
fn test_client_send() {
let msg = RUMString::from("Hello World!");
let mut server = match rumtk_create_server!(LOCALHOST, 0) {
Ok(server) => server,
Err(e) => panic!("Failed to create server because {}", e),
};
let address_info = server.get_address_info().unwrap();
let (ip, port) = rumtk_get_ip_port!(address_info);
println!("Sleeping");
rumtk_sleep!(1);
let mut client = match rumtk_connect!(port) {
Ok(client) => client,
Err(e) => panic!("Failed to create server because {}", e),
};
match client.send(msg.to_raw()) {
Ok(_) => (),
Err(e) => panic!("Failed to send message because {}", e),
};
let clients = server.get_client_ids();
let incoming_client_id = clients.first().expect("Expected client to have connected!");
let mut received_message = server.receive(incoming_client_id, true).unwrap();
if received_message.is_empty() {
received_message = server.receive(incoming_client_id, true).unwrap();
}
assert_eq!(
&msg.to_raw(),
&received_message,
"{}",
rumtk_format!(
"Received message does not match sent message by client {:?}",
&received_message
)
);
}
#[test]
fn test_serialize_json() {
#[derive(RUMSerialize)]
struct MyStruct {
hello: RUMString,
}
let hw = MyStruct {
hello: RUMString::from("World"),
};
let hw_str = rumtk_serialize!(&hw, true).unwrap();
assert!(
!hw_str.is_empty(),
"Empty JSON string generated from the test struct!"
);
}
#[test]
fn test_deserialize_serde_json() {
use serde_json::{from_str, to_string};
#[derive(RUMSerialize, RUMDeserialize, PartialEq, Debug, Clone)]
struct MyStruct {
hello: RUMString,
}
let hw = MyStruct {
hello: RUMString::from("World"),
};
let hw_str = to_string(&hw).unwrap();
let new_hw: MyStruct = from_str(&hw_str).unwrap();
assert_eq!(
new_hw, hw,
"Deserialized JSON does not match the expected value!"
);
}
#[test]
fn test_deserialize_json() {
#[derive(RUMSerialize, RUMDeserialize, PartialEq)]
struct MyStruct {
hello: RUMString,
}
let hw = MyStruct {
hello: RUMString::from("World"),
};
let hw_str = rumtk_serialize!(&hw, true).unwrap();
let new_hw: MyStruct = rumtk_deserialize!(&hw_str).unwrap();
assert!(
new_hw == hw,
"Deserialized JSON does not match the expected value!"
);
}
#[test]
fn test_print_license_notice() {
print_license_notice("RUMTK", "2025", &vec!["Luis M. Santos, M.D."]);
}
#[test]
fn test_pipe_processes() {
let ls_name = "ls";
let mut ls_command = RUMCommand::default();
ls_command.path = RUMString::from(ls_name);
let mut sys_ls_command = pipeline_create_command(&ls_command);
sys_ls_command.stdin(Stdio::piped());
sys_ls_command.stdout(Stdio::piped());
let wc_name = "wc";
let mut wc_command = RUMCommand::default();
wc_command.path = RUMString::from(wc_name);
let mut sys_wc_command = pipeline_create_command(&wc_command);
let mut sys_ls_process = pipeline_spawn_process(&mut sys_ls_command).unwrap();
pipeline_pipe_processes(&mut sys_ls_process, &mut sys_wc_command).unwrap();
let mut sys_wc_process = pipeline_spawn_process(&mut sys_wc_command).unwrap();
sys_ls_process.wait();
sys_wc_process.wait();
}
#[test]
fn test_quick_pipe() {let data = RUMBuffer::from_static(b"Hello World");
let wc_name = "wc";
let mut wc_command = RUMCommand::default();
wc_command.path = RUMString::from(wc_name);
let mut pipeline = vec![
wc_command
];
let processor = || -> RUMResult<RUMBuffer> {rumtk_pipeline_run!(&pipeline, &data)};
let result_string = buffer_to_string(&processor().unwrap()).unwrap();
let binding = result_string.as_str().replace('\n', "");
let result_items: Vec<&str> = binding.split(" ").collect();
let result = result_items.get(2).unwrap().trim().parse::<i32>().unwrap();
assert_eq!(result, 2, "Data was not piped properly!");
}
#[test]
fn test_patch_pipeline_arguments() {let data = RUMBuffer::from_static(b"Hello World");
let ls_name = "ls";
let mut ls_command = RUMCommand::default();
ls_command.path = RUMString::from(ls_name);
ls_command.args.push(RUMString::from("{options}"));
let mut pipeline = vec![
ls_command
];
pipeline_patch_args(&mut pipeline, &[("{options}", "-la")]);
let processor = || -> RUMResult<RUMBuffer> {rumtk_pipeline_run!(&pipeline)};
let result_string = buffer_to_string(&processor().unwrap()).unwrap();
let results: Vec<&str> = result_string.as_str().split("\n").collect();
let dot_dir = results.get(1).unwrap().chars().last().unwrap();
assert_eq!(dot_dir, '.', "Incorrect options passed!");
}
#[test]
fn test_buffer_split() {
let data = RUMBuffer::from_static(b"Hello|World|Test|||||||||||||||||||");
let splits = buffer_split_fast(data, '|' as u8);
assert_eq!(splits.len(), 22, "Bad buffer split! Got {:?}", splits);
}
#[test]
fn test_buffer_find() {
let data = RUMBuffer::from_static(b"Hello|World|Test|||||||||||||||||||");
let indx = buffer_find(data.as_slice(), &['|' as u8]);
assert_eq!(indx, 5, "Bad buffer find! Got {:?}", indx);
}
#[test]
fn test_buffer_find_long() {
let pattern = "|Test";
let data = RUMBuffer::from_static(b"Hello|World|Test|||||||||||||||||||");
let indx = buffer_find(data.as_slice(), pattern.as_bytes());
assert_eq!(indx, 11, "Bad buffer find! Got {:?}", indx);
}
#[test]
fn test_buffer_replace() {
let pattern = "|Test";
let replacement = "|Test123";
let data = RUMBuffer::from_static(b"Hello|World|Test|||||||||||||||||||");
let expected = RUMBuffer::from_static(b"Hello|World|Test123|||||||||||||||||||");
let new = buffer_replace(data.as_slice(), pattern.as_bytes(), replacement.as_bytes());
assert_eq!(new, expected, "Bad buffer replace! Got {:?}", new);
}
#[test]
fn test_buffer_replace_in_place() {
let pattern = "|Test";
let replacement = "|Tes1";
let mut data = RUMBuffer::copy_from_slice(b"Hello|World|Test|||||||||||||||||||");
let expected = RUMBuffer::from_static(b"Hello|World|Tes1|||||||||||||||||||");
data = match data.try_into_mut() {
Ok(mut data) => {
buffer_replace_in_place(&mut data, pattern.as_bytes(), replacement.as_bytes());
data.freeze()
},
Err(data) => data
};
assert_eq!(data, expected, "Bad buffer replace! Got {:?}", data);
}
#[test]
fn test_buffer_trim() {
let data = RUMBuffer::from_static(b"\n Hello|World \n");
let expected = RUMBuffer::from_static(b"Hello|World");
let new = buffer_trim(&data);
assert_eq!(new, expected, "Bad buffer trim! Got {:?}", new);
}
#[test]
fn test_buffer_slice_trim() {
let data = b"\n Hello|World \n";
let expected = b"Hello|World";
let new = buffer_slice_trim(data);
assert_eq!(new, expected, "Bad buffer slice trim! Got {:?}", new);
}
}