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