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 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!(task_processor, &task_args);
325 let result = task_result.unwrap().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 expected = vec![1, 2, 3];
332 let task_processor = async |args: &SafeTaskArgs<i32>| -> RUMResult<Vec<i32>> {
333 let owned_args = Arc::clone(args);
334 let lock_future = owned_args.read();
335 let locked_args = lock_future.await;
336 let mut results = TaskItems::<i32>::with_capacity(locked_args.len());
337 print!("Contents: ");
338 for arg in locked_args.iter() {
339 results.push(arg.clone());
340 println!("{} ", &arg);
341 }
342 Ok(results)
343 };
344 let task_args = rumtk_create_task_args!(1, 2, 3);
345 let task_result = rumtk_wait_on_task!(task_processor, &task_args);
346 let result = task_result.unwrap().unwrap();
347 assert_eq!(&result, &expected, "{}", rumtk_format!("Task processing returned a different result than expected! Expected {:?} \nResults {:?}", &expected, &result));
348 }
349
350 #[test]
351 fn test_execute_job_macros_one_line() {
352 let expected = vec![1, 2, 3];
353 let result = rumtk_exec_task!(
354 async |args: &SafeTaskArgs<i32>| -> RUMResult<Vec<i32>> {
355 let owned_args = Arc::clone(args);
356 let lock_future = owned_args.read();
357 let locked_args = lock_future.await;
358 let mut results = TaskItems::<i32>::with_capacity(locked_args.len());
359 print!("Contents: ");
360 for arg in locked_args.iter() {
361 results.push(arg.clone());
362 println!("{} ", &arg);
363 }
364 Ok(results)
365 },
366 vec![1, 2, 3]
367 )
368 .unwrap()
369 .unwrap();
370 assert_eq!(&result, &expected, "{}", rumtk_format!("Task processing returned a different result than expected! Expected {:?} \nResults {:?}", &expected, &result));
371 }
372
373 #[test]
374 fn test_clamp_index_positive_index() {
375 let values = vec![1, 2, 3, 4];
376 let given_index = 3isize;
377 let max_size = values.len() as isize;
378 let index = clamp_index(&given_index, &max_size).unwrap();
379 assert_eq!(
380 index, 3,
381 "Index mismatch! Requested index {} but got {}",
382 &given_index, &index
383 );
384 assert_eq!(
385 values[index], 4,
386 "Value mismatch! Expected {} but got {}",
387 &values[3], &values[index]
388 );
389 }
390
391 #[test]
392 fn test_clamp_index_reverse_index() {
393 let values = vec![1, 2, 3, 4];
394 let given_index = -1isize;
395 let max_size = values.len() as isize;
396 let index = clamp_index(&given_index, &max_size).unwrap();
397 assert_eq!(
398 index, 4,
399 "Index mismatch! Requested index {} but got {}",
400 &given_index, &index
401 );
402 assert_eq!(
403 values[index - 1],
404 4,
405 "Value mismatch! Expected {} but got {}",
406 &values[3],
407 &values[index]
408 );
409 }
410
411 use crate::cli::cli_utils::print_license_notice;
413 use crate::net::tcp::LOCALHOST;
414 use crate::pipelines::pipeline_functions::{
415 pipeline_generate_command, pipeline_pipe_process, pipeline_spawn_process,
416 };
417 use crate::pipelines::pipeline_types::RUMCommand;
418 use crate::threading::threading_functions::sleep;
419 use crate::threading::threading_manager::*;
420
421 #[test]
422 fn test_queue_data() {
423 let expected = vec![
424 RUMString::from("Hello"),
425 RUMString::from("World!"),
426 RUMString::from("Overcast"),
427 RUMString::from("and"),
428 RUMString::from("Sad"),
429 ];
430 type TestResult = RUMResult<Vec<RUMString>>;
431 let mut queue: TaskManager<TestResult> = TaskManager::new(&5).unwrap();
432 let locked_args = RwLock::new(expected.clone());
433 let task_args = SafeTaskArgs::<RUMString>::new(locked_args);
434 let processor = rumtk_create_task!(
435 async |args: &SafeTaskArgs<RUMString>| -> TestResult {
436 let owned_args = Arc::clone(args);
437 let lock_future = owned_args.read();
438 let locked_args = lock_future.await;
439 let mut results = TaskItems::<RUMString>::with_capacity(locked_args.len());
440 print!("Contents: ");
441 for arg in locked_args.iter() {
442 print!("{} ", &arg);
443 results.push(RUMString::new(arg));
444 }
445 Ok(results)
446 },
447 task_args
448 );
449
450 queue.add_task::<_>(processor);
451 let results = queue.wait();
452
453 let mut result_data = Vec::<RUMString>::with_capacity(5);
454 for r in results {
455 for v in r.unwrap().result.clone().unwrap().iter() {
456 for value in v.iter() {
457 result_data.push(value.clone());
458 }
459 }
460 }
461 assert_eq!(result_data, expected, "Results do not match expected!");
462 }
463
464 #[test]
466 fn test_server_start() {
467 let mut server = match rumtk_create_server!("localhost", 0) {
468 Ok(server) => server,
469 Err(e) => panic!("Failed to create server because {}", e),
470 };
471 match server.start(false) {
472 Ok(_) => (),
473 Err(e) => panic!("Failed to start server because {}", e),
474 }
475 }
476
477 #[test]
478 fn test_server_send() {
479 let msg = RUMString::from("Hello World!");
480 let mut server = match rumtk_create_server!(LOCALHOST, 0) {
481 Ok(server) => server,
482 Err(e) => panic!("Failed to create server because {}", e),
483 };
484 match server.start(false) {
485 Ok(_) => (),
486 Err(e) => panic!("Failed to start server because {}", e),
487 };
488 let address_info = server.get_address_info().unwrap();
489 let (ip, port) = rumtk_get_ip_port!(address_info);
490 println!("Sleeping");
491 rumtk_sleep!(1);
492 let mut client = match rumtk_connect!(port) {
493 Ok(client) => client,
494 Err(e) => panic!("Failed to create server because {}", e),
495 };
496 let client_id = client.get_address().unwrap();
497 rumtk_sleep!(1);
498 match server.send(&client_id, &msg.to_raw()) {
499 Ok(_) => (),
500 Err(e) => panic!("Server failed to send message because {}", e),
501 };
502 rumtk_sleep!(1);
503 let received_message = client.receive().unwrap();
504 assert_eq!(
505 &msg.to_raw(),
506 &received_message,
507 "{}",
508 rumtk_format!(
509 "Received message does not match sent message by server {:?}",
510 &received_message
511 )
512 );
513 }
514
515 #[test]
516 fn test_server_receive() {
517 let msg = RUMString::from("Hello World!");
518 let mut server = match rumtk_create_server!(LOCALHOST, 0) {
519 Ok(server) => server,
520 Err(e) => panic!("Failed to create server because {}", e),
521 };
522 match server.start(false) {
523 Ok(_) => (),
524 Err(e) => panic!("Failed to start server because {}", e),
525 };
526 let address_info = server.get_address_info().unwrap();
527 let (ip, port) = rumtk_get_ip_port!(address_info);
528 println!("Sleeping");
529 rumtk_sleep!(1);
530 let mut client = match rumtk_connect!(port) {
531 Ok(client) => client,
532 Err(e) => panic!("Failed to create server because {}", e),
533 };
534 match client.send(msg.to_raw()) {
535 Ok(_) => (),
536 Err(e) => panic!("Failed to send message because {}", e),
537 };
538 rumtk_sleep!(1);
539 let client_id = client.get_address().expect("Failed to get client id");
540 let incoming_message = server.receive(&client_id).unwrap().to_rumstring();
541 println!("Received message => {:?}", &incoming_message);
542 assert_eq!(&incoming_message, msg, "Received message corruption!");
543 }
544
545 #[test]
546 fn test_server_get_clients() {
547 let mut server = match rumtk_create_server!(LOCALHOST, 0) {
548 Ok(server) => server,
549 Err(e) => panic!("Failed to create server because {}", e),
550 };
551 match server.start(false) {
552 Ok(_) => (),
553 Err(e) => panic!("Failed to start server because {}", e),
554 };
555 let address_info = server.get_address_info().unwrap();
556 let (ip, port) = rumtk_get_ip_port!(address_info);
557 println!("Sleeping");
558 rumtk_sleep!(1);
559 let mut client = match rumtk_connect!(port) {
560 Ok(client) => client,
561 Err(e) => panic!("Failed to create server because {}", e),
562 };
563 rumtk_sleep!(1);
564 let expected_client_id = client.get_address().expect("Failed to get client id");
565 let clients = server.get_client_ids();
566 let incoming_client_id = clients.get(0).expect("Expected client to have connected!");
567 println!("Connected client id => {}", &incoming_client_id);
568 assert_eq!(
569 &incoming_client_id, &expected_client_id,
570 "Connected client does not match the connecting client! Client id => {}",
571 &incoming_client_id
572 );
573 }
574
575 #[test]
576 fn test_server_stop() {
577 let msg = RUMString::from("Hello World!");
578 let mut server = match rumtk_create_server!("localhost", 0) {
579 Ok(server) => server,
580 Err(e) => panic!("Failed to create server because {}", e),
581 };
582 match server.start(false) {
583 Ok(_) => (),
584 Err(e) => panic!("Failed to start server because {}", e),
585 };
586 println!("Sleeping");
587 rumtk_sleep!(1);
588 match server.stop() {
589 Ok(_) => (),
590 Err(e) => panic!("Failed to stop server because {}", e),
591 };
592 }
593
594 #[test]
595 fn test_server_get_address_info() {
596 let msg = RUMString::from("Hello World!");
597 let mut server = match rumtk_create_server!("localhost", 0) {
598 Ok(server) => server,
599 Err(e) => panic!("Failed to create server because {}", e),
600 };
601 match server.start(false) {
602 Ok(_) => (),
603 Err(e) => panic!("Failed to start server because {}", e),
604 };
605 println!("Sleeping");
606 rumtk_sleep!(1);
607 match server.get_address_info() {
608 Some(addr) => println!("Server address info => {}", addr),
609 None => panic!("No address. Perhaps the server was never initialized?"),
610 };
611 }
612
613 #[test]
614 fn test_client_send() {
615 let msg = RUMString::from("Hello World!");
616 let mut server = match rumtk_create_server!(LOCALHOST, 0) {
617 Ok(server) => server,
618 Err(e) => panic!("Failed to create server because {}", e),
619 };
620 match server.start(false) {
621 Ok(_) => (),
622 Err(e) => panic!("Failed to start server because {}", e),
623 };
624 let address_info = server.get_address_info().unwrap();
625 let (ip, port) = rumtk_get_ip_port!(address_info);
626 println!("Sleeping");
627 rumtk_sleep!(1);
628 let mut client = match rumtk_connect!(port) {
629 Ok(client) => client,
630 Err(e) => panic!("Failed to create server because {}", e),
631 };
632 rumtk_sleep!(2);
633 match client.send(msg.to_raw()) {
634 Ok(_) => (),
635 Err(e) => panic!("Failed to send message because {}", e),
636 };
637 rumtk_sleep!(1);
638 let clients = server.get_client_ids();
639 let incoming_client_id = clients.first().expect("Expected client to have connected!");
640 let mut received_message = server.receive(incoming_client_id).unwrap();
641 if received_message.is_empty() {
642 rumtk_sleep!(1);
643 received_message = server.receive(incoming_client_id).unwrap();
644 }
645 assert_eq!(
646 &msg.to_raw(),
647 &received_message,
648 "{}",
649 rumtk_format!(
650 "Received message does not match sent message by client {:?}",
651 &received_message
652 )
653 );
654 }
655
656 #[test]
659 fn test_serialize_json() {
660 #[derive(RUMSerialize)]
661 struct MyStruct {
662 hello: RUMString,
663 }
664
665 let hw = MyStruct {
666 hello: RUMString::from("World"),
667 };
668 let hw_str = rumtk_serialize!(&hw, true).unwrap();
669
670 assert!(
671 !hw_str.is_empty(),
672 "Empty JSON string generated from the test struct!"
673 );
674 }
675
676 #[test]
677 fn test_deserialize_serde_json() {
678 use serde_json::{from_str, to_string};
679
680 #[derive(RUMSerialize, RUMDeserialize, PartialEq, Debug, Clone)]
681 struct MyStruct {
682 hello: RUMString,
683 }
684
685 let hw = MyStruct {
686 hello: RUMString::from("World"),
687 };
688 let hw_str = to_string(&hw).unwrap();
689 let new_hw: MyStruct = from_str(&hw_str).unwrap();
690
691 assert_eq!(
692 new_hw, hw,
693 "Deserialized JSON does not match the expected value!"
694 );
695 }
696
697 #[test]
698 fn test_deserialize_json() {
699 #[derive(RUMSerialize, RUMDeserialize, PartialEq)]
700 struct MyStruct {
701 hello: RUMString,
702 }
703
704 let hw = MyStruct {
705 hello: RUMString::from("World"),
706 };
707 let hw_str = rumtk_serialize!(&hw, true).unwrap();
708 let new_hw: MyStruct = rumtk_deserialize!(&hw_str).unwrap();
709
710 assert!(
711 new_hw == hw,
712 "Deserialized JSON does not match the expected value!"
713 );
714 }
715
716 #[test]
752 fn test_print_license_notice() {
753 print_license_notice("RUMTK", "2025", &vec!["Luis M. Santos, M.D."]);
754 }
755
756 #[test]
761 fn test_pipe_processes() {
762 let ls_name = "ls";
763 let mut ls_command = RUMCommand::default();
764 ls_command.path = RUMString::from(ls_name);
765 let mut sys_ls_command = pipeline_generate_command(&ls_command);
766 sys_ls_command.stdin(Stdio::piped());
767 sys_ls_command.stdout(Stdio::piped());
768
769 let wc_name = "wc";
770 let mut wc_command = RUMCommand::default();
771 wc_command.path = RUMString::from(wc_name);
772 let mut sys_wc_command = pipeline_generate_command(&wc_command);
773
774 let mut sys_ls_process = pipeline_spawn_process(&mut sys_ls_command).unwrap();
775 pipeline_pipe_process(&mut sys_ls_process, &mut sys_wc_command).unwrap();
776 let mut sys_wc_process = pipeline_spawn_process(&mut sys_wc_command).unwrap();
777
778 sys_ls_process.wait();
779 sys_wc_process.wait();
780 }
781
782 }