1#![feature(type_alias_impl_trait)]
25#![feature(unboxed_closures)]
26#![feature(buf_read_has_data_left)]
27#![feature(mapped_lock_guards)]
28#![feature(str_as_str)]
29
30pub mod cache;
31pub mod cli;
32pub mod core;
33pub mod dependencies;
34pub mod hash;
35pub mod id;
36pub mod json;
37pub mod log;
38pub mod maths;
39pub mod net;
40pub mod pipelines;
41pub mod scripting;
42pub mod search;
43pub mod strings;
44pub mod threading;
45pub mod types;
46
47#[cfg(test)]
48mod tests {
49 use super::*;
50 use crate::cache::RUMCache;
51 use crate::core::{clamp_index, RUMResult};
52 use crate::search::rumtk_search::*;
53 use crate::strings::{
54 rumtk_format, RUMArrayConversions, RUMString, RUMStringConversions, StringUtils,
55 };
56 use crate::types::{RUMDeserialize, RUMDeserializer, RUMSerialize, RUMSerializer};
57 use compact_str::CompactString;
58 use serde_json::to_string;
59 use std::process::Stdio;
60 use std::sync::Arc;
61 use tokio::sync::RwLock;
62
63 #[test]
64 fn test_is_escaped_str() {
65 let input = "\r\n\'\\\"";
66 let expected = false;
67 let result = strings::is_escaped_str(input);
68 println!("Input: {} Expected: {} Got: {}", input, expected, result);
69 assert_eq!(
70 expected, result,
71 "Incorrect detection of unescaped string as escaped!!"
72 );
73 println!("Passed!")
74 }
75
76 #[test]
77 fn test_escaping_control() {
78 let input = "\r\n\'\"\\";
79 let expected = "\\r\\n\\'\\\"\\\\";
80 let result = strings::escape(input);
81 println!(
82 "Input: {} Expected: {} Got: {}",
83 input,
84 expected,
85 result.as_str()
86 );
87 assert_eq!(expected, result, "Incorrect string escaping!");
88 println!("Passed!")
89 }
90
91 #[test]
92 fn test_escaping_unicode() {
93 let input = "❤";
94 let expected = "\\u2764";
95 let result = strings::escape(input);
96 println!(
97 "Input: {} Expected: {} Got: {}",
98 input,
99 expected,
100 result.as_str()
101 );
102 assert_eq!(expected, result, "Incorrect string escaping!");
103 println!("Passed!")
104 }
105
106 #[test]
107 fn test_unescaping_unicode() {
108 let input = "❤";
109 let escaped = strings::escape(input);
110 let expected = "❤";
111 let result = RUMString::from_utf8(strings::unescape(escaped.as_str()).unwrap()).unwrap();
112 println!(
113 "Input: {} Expected: {} Got: {}",
114 input,
115 expected,
116 result.as_str()
117 );
118 assert_eq!(expected, result.as_str(), "Incorrect string unescaping!");
119 println!("Passed!")
120 }
121
122 #[test]
123 fn test_unescaping_string() {
124 let input = "I \\u2764 my wife!";
125 let expected = "I ❤ my wife!";
126 let result = strings::unescape_string(input).unwrap();
127 println!(
128 "Input: {} Expected: {} Got: {}",
129 input,
130 expected,
131 result.as_str()
132 );
133 assert_eq!(expected, result.as_str(), "Incorrect string unescaping!");
134 println!("Passed!")
135 }
136
137 #[test]
138 fn test_is_escaped_string() {
139 let input = "I \\u2764 my wife!";
140 let expected = true;
141 let result = strings::is_escaped_str(input);
142 println!("Input: {} Expected: {} Got: {}", input, expected, result);
143 assert_eq!(
144 expected, result,
145 "Escaped string detected as unescaped string!"
146 );
147 println!("Passed!")
148 }
149
150 #[test]
151 fn test_is_unescaped_string() {
152 let input = "I ❤ my wife!";
153 let expected = false;
154 let result = strings::is_escaped_str(input);
155 println!("Input: {} Expected: {} Got: {}", input, expected, result);
156 assert_eq!(
157 expected, result,
158 "Unescaped string detected as escaped string!"
159 );
160 println!("Passed!")
161 }
162
163 #[test]
164 fn test_unique_string() {
165 let input = "I❤mywife!";
166 assert!(input.is_unique(), "String was not detected as unique.");
167 }
168
169 #[test]
170 fn test_non_unique_string() {
171 let input = "I❤❤mywife!";
172 assert!(!input.is_unique(), "String was detected as unique.");
173 }
174
175 #[test]
176 fn test_escaping_string() {
177 let input = "I ❤ my wife!";
178 let expected = "I \\u2764 my wife!";
179 let result = strings::escape(input);
180 println!(
181 "Input: {} Expected: {} Got: {}",
182 input,
183 expected,
184 result.as_str()
185 );
186 assert_eq!(expected, result.as_str(), "Incorrect string escaping!");
187 println!("Passed!")
188 }
189
190 #[test]
191 fn test_autodecode_utf8() {
192 let input = "I ❤ my wife!";
193 let result = strings::try_decode(input.as_bytes());
194 println!(
195 "Input: {} Expected: {} Got: {}",
196 input,
197 input,
198 result.as_str()
199 );
200 assert_eq!(input, result, "Incorrect string decoding!");
201 println!("Passed!")
202 }
203
204 #[test]
205 fn test_autodecode_other() {
206 let input = "I ❤ my wife!";
208 let result = input;
209 println!("Input: {} Expected: {} Got: {}", input, input, result);
210 assert_eq!(input, result, "Incorrect string decoding!");
211 println!("Passed!")
212 }
213
214 #[test]
215 fn test_decode() {
216 let input = "I ❤ my wife!";
217 let result = strings::try_decode_with(input.as_bytes(), "utf-8");
218 println!(
219 "Input: {} Expected: {} Got: {}",
220 input,
221 input,
222 result.as_str()
223 );
224 assert_eq!(input, result, "Incorrect string decoding!");
225 println!("Passed!")
226 }
227
228 #[test]
229 fn test_rumcache_insertion() {
230 let mut cache: RUMCache<&str, CompactString> = RUMCache::with_capacity(5);
231 cache.insert("❤", CompactString::from("I ❤ my wife!"));
232 println!("Contents: {:#?}", &cache);
233 assert_eq!(cache.len(), 1, "Incorrect number of items in cache!");
234 println!("Passed!")
235 }
236
237 #[test]
238 fn test_search_string_letters() {
239 let input = "Hello World!";
240 let expr = r"\w";
241 let result = string_search(input, expr, "");
242 let expected: RUMString = RUMString::from("HelloWorld");
243 println!(
244 "Input: {:?} Expected: {:?} Got: {:?}",
245 input, expected, result
246 );
247 assert_eq!(expected, result, "String search results mismatch");
248 println!("Passed!")
249 }
250
251 #[test]
252 fn test_search_string_words() {
253 let input = "Hello World!";
254 let expr = r"\w+";
255 let result = string_search(input, expr, " ");
256 let expected: RUMString = RUMString::from("Hello World");
257 println!(
258 "Input: {:?} Expected: {:?} Got: {:?}",
259 input, expected, result
260 );
261 assert_eq!(expected, result, "String search results mismatch");
262 println!("Passed!")
263 }
264
265 #[test]
266 fn test_search_string_named_groups() {
267 let input = "Hello World!";
268 let expr = r"(?<hello>\w{5}) (?<world>\w{5})";
269 let result = string_search_named_captures(input, expr, "");
270 let expected: RUMString = RUMString::from("World");
271 println!(
272 "Input: {:?} Expected: {:?} Got: {:?}",
273 input, expected, result
274 );
275 assert_eq!(expected, result["world"], "String search results mismatch");
276 println!("Passed!")
277 }
278
279 #[test]
280 fn test_search_string_all_groups() {
281 let input = "Hello World!";
282 let expr = r"(?<hello>\w{5}) (?<world>\w{5})";
283 let result = string_search_all_captures(input, expr, "");
284 let expected: Vec<&str> = vec!["Hello", "World"];
285 println!(
286 "Input: {:?} Expected: {:?} Got: {:?}",
287 input, expected, result
288 );
289 assert_eq!(expected, result, "String search results mismatch");
290 println!("Passed!")
291 }
292
293 #[test]
295 fn test_default_num_threads() {
296 use num_cpus;
297 let threads = threading::threading_functions::get_default_system_thread_count();
298 assert_eq!(
299 threads >= num_cpus::get(),
300 true,
301 "Default thread count is incorrect! We got {}, but expected {}!",
302 threads,
303 num_cpus::get()
304 );
305 }
306
307 #[test]
308 fn test_execute_job() {
309 let rt = rumtk_init_threads!();
310 let expected = vec![1, 2, 3];
311 let task_processor = async |args: &SafeTaskArgs<i32>| -> RUMResult<Vec<i32>> {
312 let owned_args = Arc::clone(args);
313 let lock_future = owned_args.read();
314 let locked_args = lock_future.await;
315 let mut results = TaskItems::<i32>::with_capacity(locked_args.len());
316 print!("Contents: ");
317 for arg in locked_args.iter() {
318 results.push(arg.clone());
319 println!("{} ", &arg);
320 }
321 Ok(results)
322 };
323 let locked_args = RwLock::new(expected.clone());
324 let task_args = SafeTaskArgs::<i32>::new(locked_args);
325 let task_result = rumtk_wait_on_task!(rt, task_processor, &task_args);
326 let result = task_result.unwrap();
327 assert_eq!(&result, &expected, "{}", rumtk_format!("Task processing returned a different result than expected! Expected {:?} \nResults {:?}", &expected, &result));
328 }
329
330 #[test]
331 fn test_execute_job_macros() {
332 let rt = rumtk_init_threads!();
333 let expected = vec![1, 2, 3];
334 let task_processor = async |args: &SafeTaskArgs<i32>| -> RUMResult<Vec<i32>> {
335 let owned_args = Arc::clone(args);
336 let lock_future = owned_args.read();
337 let locked_args = lock_future.await;
338 let mut results = TaskItems::<i32>::with_capacity(locked_args.len());
339 print!("Contents: ");
340 for arg in locked_args.iter() {
341 results.push(arg.clone());
342 println!("{} ", &arg);
343 }
344 Ok(results)
345 };
346 let task_args = rumtk_create_task_args!(1, 2, 3);
347 let task_result = rumtk_wait_on_task!(rt, task_processor, &task_args);
348 let result = task_result.unwrap();
349 assert_eq!(&result, &expected, "{}", rumtk_format!("Task processing returned a different result than expected! Expected {:?} \nResults {:?}", &expected, &result));
350 }
351
352 #[test]
353 fn test_execute_job_macros_one_line() {
354 let rt = rumtk_init_threads!();
355 let expected = vec![1, 2, 3];
356 let result = rumtk_exec_task!(
357 async |args: &SafeTaskArgs<i32>| -> RUMResult<Vec<i32>> {
358 let owned_args = Arc::clone(args);
359 let lock_future = owned_args.read();
360 let locked_args = lock_future.await;
361 let mut results = TaskItems::<i32>::with_capacity(locked_args.len());
362 print!("Contents: ");
363 for arg in locked_args.iter() {
364 results.push(arg.clone());
365 println!("{} ", &arg);
366 }
367 Ok(results)
368 },
369 vec![1, 2, 3]
370 )
371 .unwrap();
372 assert_eq!(&result, &expected, "{}", rumtk_format!("Task processing returned a different result than expected! Expected {:?} \nResults {:?}", &expected, &result));
373 }
374
375 #[test]
376 fn test_clamp_index_positive_index() {
377 let values = vec![1, 2, 3, 4];
378 let given_index = 3isize;
379 let max_size = values.len() as isize;
380 let index = clamp_index(&given_index, &max_size).unwrap();
381 assert_eq!(
382 index, 3,
383 "Index mismatch! Requested index {} but got {}",
384 &given_index, &index
385 );
386 assert_eq!(
387 values[index], 4,
388 "Value mismatch! Expected {} but got {}",
389 &values[3], &values[index]
390 );
391 }
392
393 #[test]
394 fn test_clamp_index_reverse_index() {
395 let values = vec![1, 2, 3, 4];
396 let given_index = -1isize;
397 let max_size = values.len() as isize;
398 let index = clamp_index(&given_index, &max_size).unwrap();
399 assert_eq!(
400 index, 4,
401 "Index mismatch! Requested index {} but got {}",
402 &given_index, &index
403 );
404 assert_eq!(
405 values[index - 1],
406 4,
407 "Value mismatch! Expected {} but got {}",
408 &values[3],
409 &values[index]
410 );
411 }
412
413 use crate::cli::cli_utils::print_license_notice;
415 use crate::net::tcp::LOCALHOST;
416 use crate::pipelines::pipeline_functions::{
417 pipeline_generate_command, pipeline_pipe_process, pipeline_spawn_process,
418 };
419 use crate::pipelines::pipeline_types::RUMCommand;
420 use crate::threading::threading_functions::sleep;
421 use crate::threading::threading_manager::*;
422
423 #[test]
424 fn test_queue_data() {
425 let expected = vec![
426 RUMString::from("Hello"),
427 RUMString::from("World!"),
428 RUMString::from("Overcast"),
429 RUMString::from("and"),
430 RUMString::from("Sad"),
431 ];
432 type TestResult = RUMResult<Vec<RUMString>>;
433 let mut queue: TaskManager<TestResult> = TaskManager::new(&5).unwrap();
434 let locked_args = RwLock::new(expected.clone());
435 let task_args = SafeTaskArgs::<RUMString>::new(locked_args);
436 let processor = rumtk_create_task!(
437 async |args: &SafeTaskArgs<RUMString>| -> TestResult {
438 let owned_args = Arc::clone(args);
439 let lock_future = owned_args.read();
440 let locked_args = lock_future.await;
441 let mut results = TaskItems::<RUMString>::with_capacity(locked_args.len());
442 print!("Contents: ");
443 for arg in locked_args.iter() {
444 print!("{} ", &arg);
445 results.push(RUMString::new(arg));
446 }
447 Ok(results)
448 },
449 task_args
450 );
451
452 queue.add_task::<_>(processor);
453 let results = queue.wait();
454
455 let mut result_data = Vec::<RUMString>::with_capacity(5);
456 for r in results {
457 for v in r.unwrap().result.clone().unwrap().iter() {
458 for value in v.iter() {
459 result_data.push(value.clone());
460 }
461 }
462 }
463 assert_eq!(result_data, expected, "Results do not match expected!");
464 }
465
466 #[test]
468 fn test_server_start() {
469 let mut server = match rumtk_create_server!("localhost", 0) {
470 Ok(server) => server,
471 Err(e) => panic!("Failed to create server because {}", e),
472 };
473 match server.start(false) {
474 Ok(_) => (),
475 Err(e) => panic!("Failed to start server because {}", e),
476 }
477 }
478
479 #[test]
480 fn test_server_send() {
481 let msg = RUMString::from("Hello World!");
482 let mut server = match rumtk_create_server!(LOCALHOST, 0, 1) {
483 Ok(server) => server,
484 Err(e) => panic!("Failed to create server because {}", e),
485 };
486 match server.start(false) {
487 Ok(_) => (),
488 Err(e) => panic!("Failed to start server because {}", e),
489 };
490 let address_info = server.get_address_info().unwrap();
491 let (ip, port) = rumtk_get_ip_port!(address_info);
492 println!("Sleeping");
493 rumtk_sleep!(1);
494 let mut client = match rumtk_connect!(port) {
495 Ok(client) => client,
496 Err(e) => panic!("Failed to create server because {}", e),
497 };
498 let client_id = client.get_address().unwrap();
499 rumtk_sleep!(1);
500 match server.send(&client_id, &msg.to_raw()) {
501 Ok(_) => (),
502 Err(e) => panic!("Server failed to send message because {}", e),
503 };
504 rumtk_sleep!(1);
505 let received_message = client.receive().unwrap();
506 assert_eq!(
507 &msg.to_raw(),
508 &received_message,
509 "{}",
510 rumtk_format!(
511 "Received message does not match sent message by server {:?}",
512 &received_message
513 )
514 );
515 }
516
517 #[test]
518 fn test_server_receive() {
519 let msg = RUMString::from("Hello World!");
520 let mut server = match rumtk_create_server!(LOCALHOST, 0) {
521 Ok(server) => server,
522 Err(e) => panic!("Failed to create server because {}", e),
523 };
524 match server.start(false) {
525 Ok(_) => (),
526 Err(e) => panic!("Failed to start server because {}", e),
527 };
528 let address_info = server.get_address_info().unwrap();
529 let (ip, port) = rumtk_get_ip_port!(address_info);
530 println!("Sleeping");
531 rumtk_sleep!(1);
532 let mut client = match rumtk_connect!(port) {
533 Ok(client) => client,
534 Err(e) => panic!("Failed to create server because {}", e),
535 };
536 match client.send(&msg.to_raw()) {
537 Ok(_) => (),
538 Err(e) => panic!("Failed to send message because {}", e),
539 };
540 rumtk_sleep!(1);
541 let client_id = client.get_address().expect("Failed to get client id");
542 let incoming_message = server.receive(&client_id).unwrap().to_rumstring();
543 println!("Received message => {:?}", &incoming_message);
544 assert_eq!(&incoming_message, msg, "Received message corruption!");
545 }
546
547 #[test]
548 fn test_server_get_clients() {
549 let mut server = match rumtk_create_server!(LOCALHOST, 0) {
550 Ok(server) => server,
551 Err(e) => panic!("Failed to create server because {}", e),
552 };
553 match server.start(false) {
554 Ok(_) => (),
555 Err(e) => panic!("Failed to start server because {}", e),
556 };
557 let address_info = server.get_address_info().unwrap();
558 let (ip, port) = rumtk_get_ip_port!(address_info);
559 println!("Sleeping");
560 rumtk_sleep!(1);
561 let mut client = match rumtk_connect!(port) {
562 Ok(client) => client,
563 Err(e) => panic!("Failed to create server because {}", e),
564 };
565 rumtk_sleep!(1);
566 let expected_client_id = client.get_address().expect("Failed to get client id");
567 let clients = server.get_client_ids();
568 let incoming_client_id = clients.get(0).expect("Expected client to have connected!");
569 println!("Connected client id => {}", &incoming_client_id);
570 assert_eq!(
571 &incoming_client_id, &expected_client_id,
572 "Connected client does not match the connecting client! Client id => {}",
573 &incoming_client_id
574 );
575 }
576
577 #[test]
578 fn test_server_stop() {
579 let msg = RUMString::from("Hello World!");
580 let mut server = match rumtk_create_server!("localhost", 0) {
581 Ok(server) => server,
582 Err(e) => panic!("Failed to create server because {}", e),
583 };
584 match server.start(false) {
585 Ok(_) => (),
586 Err(e) => panic!("Failed to start server because {}", e),
587 };
588 println!("Sleeping");
589 rumtk_sleep!(1);
590 match server.stop() {
591 Ok(_) => (),
592 Err(e) => panic!("Failed to stop server because {}", e),
593 };
594 }
595
596 #[test]
597 fn test_server_get_address_info() {
598 let msg = RUMString::from("Hello World!");
599 let mut server = match rumtk_create_server!("localhost", 0) {
600 Ok(server) => server,
601 Err(e) => panic!("Failed to create server because {}", e),
602 };
603 match server.start(false) {
604 Ok(_) => (),
605 Err(e) => panic!("Failed to start server because {}", e),
606 };
607 println!("Sleeping");
608 rumtk_sleep!(1);
609 match server.get_address_info() {
610 Some(addr) => println!("Server address info => {}", addr),
611 None => panic!("No address. Perhaps the server was never initialized?"),
612 };
613 }
614
615 #[test]
616 fn test_client_send() {
617 let msg = RUMString::from("Hello World!");
618 let mut server = match rumtk_create_server!(LOCALHOST, 0) {
619 Ok(server) => server,
620 Err(e) => panic!("Failed to create server because {}", e),
621 };
622 match server.start(false) {
623 Ok(_) => (),
624 Err(e) => panic!("Failed to start server because {}", e),
625 };
626 let address_info = server.get_address_info().unwrap();
627 let (ip, port) = rumtk_get_ip_port!(address_info);
628 println!("Sleeping");
629 rumtk_sleep!(1);
630 let mut client = match rumtk_connect!(port) {
631 Ok(client) => client,
632 Err(e) => panic!("Failed to create server because {}", e),
633 };
634 rumtk_sleep!(2);
635 match client.send(&msg.to_raw()) {
636 Ok(_) => (),
637 Err(e) => panic!("Failed to send message because {}", e),
638 };
639 rumtk_sleep!(1);
640 let clients = server.get_client_ids();
641 let incoming_client_id = clients.first().expect("Expected client to have connected!");
642 let mut received_message = server.receive(incoming_client_id).unwrap();
643 if received_message.is_empty() {
644 rumtk_sleep!(1);
645 received_message = server.receive(incoming_client_id).unwrap();
646 }
647 assert_eq!(
648 &msg.to_raw(),
649 &received_message,
650 "{}",
651 rumtk_format!(
652 "Received message does not match sent message by client {:?}",
653 &received_message
654 )
655 );
656 }
657
658 #[test]
661 fn test_serialize_json() {
662 #[derive(RUMSerialize)]
663 struct MyStruct {
664 hello: RUMString,
665 }
666
667 let hw = MyStruct {
668 hello: RUMString::from("World"),
669 };
670 let hw_str = rumtk_serialize!(&hw, true).unwrap();
671
672 assert!(
673 !hw_str.is_empty(),
674 "Empty JSON string generated from the test struct!"
675 );
676 }
677
678 #[test]
679 fn test_deserialize_serde_json() {
680 use serde_json::{from_str, to_string};
681
682 #[derive(RUMSerialize, RUMDeserialize, PartialEq, Debug, Clone)]
683 struct MyStruct {
684 hello: RUMString,
685 }
686
687 let hw = MyStruct {
688 hello: RUMString::from("World"),
689 };
690 let hw_str = to_string(&hw).unwrap();
691 let new_hw: MyStruct = from_str(&hw_str).unwrap();
692
693 assert_eq!(
694 new_hw, hw,
695 "Deserialized JSON does not match the expected value!"
696 );
697 }
698
699 #[test]
700 fn test_deserialize_json() {
701 #[derive(RUMSerialize, RUMDeserialize, PartialEq)]
702 struct MyStruct {
703 hello: RUMString,
704 }
705
706 let hw = MyStruct {
707 hello: RUMString::from("World"),
708 };
709 let hw_str = rumtk_serialize!(&hw, true).unwrap();
710 let new_hw: MyStruct = rumtk_deserialize!(&hw_str).unwrap();
711
712 assert!(
713 new_hw == hw,
714 "Deserialized JSON does not match the expected value!"
715 );
716 }
717
718 #[test]
754 fn test_print_license_notice() {
755 print_license_notice("RUMTK", "2025", &vec!["Luis M. Santos, M.D."]);
756 }
757
758 #[test]
763 fn test_pipe_processes() {
764 let ls_name = "ls";
765 let mut ls_command = RUMCommand::default();
766 ls_command.path = RUMString::from(ls_name);
767 let mut sys_ls_command = pipeline_generate_command(&ls_command);
768 sys_ls_command.stdin(Stdio::piped());
769 sys_ls_command.stdout(Stdio::piped());
770
771 let wc_name = "wc";
772 let mut wc_command = RUMCommand::default();
773 wc_command.path = RUMString::from(wc_name);
774 let mut sys_wc_command = pipeline_generate_command(&wc_command);
775
776 let mut sys_ls_process = pipeline_spawn_process(&mut sys_ls_command).unwrap();
777 pipeline_pipe_process(&mut sys_ls_process, &mut sys_wc_command).unwrap();
778 let mut sys_wc_process = pipeline_spawn_process(&mut sys_wc_command).unwrap();
779
780 sys_ls_process.wait();
781 sys_wc_process.wait();
782 }
783
784 }