1#![feature(type_alias_impl_trait)]
24#![feature(unboxed_closures)]
25#![feature(buf_read_has_data_left)]
26#![feature(mapped_lock_guards)]
27#![feature(str_as_str)]
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, AsStr, 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!(
166 input.as_grapheme_str().is_unique(),
167 "String was not detected as unique."
168 );
169 }
170
171 #[test]
172 fn test_non_unique_string() {
173 let input = "I❤❤mywife!";
174 assert!(
175 !input.as_grapheme_str().is_unique(),
176 "String was detected as unique."
177 );
178 }
179
180 #[test]
181 fn test_escaping_string() {
182 let input = "I ❤ my wife!";
183 let expected = "I \\u2764 my wife!";
184 let result = strings::escape(input);
185 println!(
186 "Input: {} Expected: {} Got: {}",
187 input,
188 expected,
189 result.as_str()
190 );
191 assert_eq!(expected, result.as_str(), "Incorrect string escaping!");
192 println!("Passed!")
193 }
194
195 #[test]
196 fn test_autodecode_utf8() {
197 let input = "I ❤ my wife!";
198 let result = strings::try_decode(input.as_bytes());
199 println!(
200 "Input: {} Expected: {} Got: {}",
201 input,
202 input,
203 result.as_str()
204 );
205 assert_eq!(input, result, "Incorrect string decoding!");
206 println!("Passed!")
207 }
208
209 #[test]
210 fn test_autodecode_other() {
211 let input = "I ❤ my wife!";
213 let result = input;
214 println!("Input: {} Expected: {} Got: {}", input, input, result);
215 assert_eq!(input, result, "Incorrect string decoding!");
216 println!("Passed!")
217 }
218
219 #[test]
220 fn test_decode() {
221 let input = "I ❤ my wife!";
222 let result = strings::try_decode_with(input.as_bytes(), "utf-8");
223 println!(
224 "Input: {} Expected: {} Got: {}",
225 input,
226 input,
227 result.as_str()
228 );
229 assert_eq!(input, result, "Incorrect string decoding!");
230 println!("Passed!")
231 }
232
233 #[test]
234 fn test_rumcache_insertion() {
235 let mut cache: RUMCache<&str, CompactString> = RUMCache::with_capacity(5);
236 cache.insert("❤", CompactString::from("I ❤ my wife!"));
237 println!("Contents: {:#?}", &cache);
238 assert_eq!(cache.len(), 1, "Incorrect number of items in cache!");
239 println!("Passed!")
240 }
241
242 #[test]
243 fn test_search_string_letters() {
244 let input = "Hello World!";
245 let expr = r"\w";
246 let result = string_search(input, expr, "").unwrap();
247 let expected: RUMString = RUMString::from("HelloWorld");
248 println!(
249 "Input: {:?} Expected: {:?} Got: {:?}",
250 input, expected, result
251 );
252 assert_eq!(expected, result, "String search results mismatch");
253 println!("Passed!")
254 }
255
256 #[test]
257 fn test_search_string_words() {
258 let input = "Hello World!";
259 let expr = r"\w+";
260 let result = string_search(input, expr, " ").unwrap();
261 let expected: RUMString = RUMString::from("Hello World");
262 println!(
263 "Input: {:?} Expected: {:?} Got: {:?}",
264 input, expected, result
265 );
266 assert_eq!(expected, result, "String search results mismatch");
267 println!("Passed!")
268 }
269
270 #[test]
271 fn test_search_string_named_groups() {
272 let input = "Hello World!";
273 let expr = r"(?<hello>\w{5}) (?<world>\w{5})";
274 let result = string_search_named_captures(input, expr, "").unwrap();
275 let expected: RUMString = RUMString::from("World");
276 println!(
277 "Input: {:?} Expected: {:?} Got: {:?}",
278 input, expected, result
279 );
280 assert_eq!(expected, result["world"], "String search results mismatch");
281 println!("Passed!")
282 }
283
284 #[test]
285 fn test_search_string_all_groups() {
286 let input = "Hello World!";
287 let expr = r"(?<hello>\w{5}) (?<world>\w{5})";
288 let result = string_search_all_captures(input, expr, "").unwrap();
289 let expected: Vec<&str> = vec!["Hello", "World"];
290 println!(
291 "Input: {:?} Expected: {:?} Got: {:?}",
292 input, expected, result
293 );
294 assert_eq!(expected, result, "String search results mismatch");
295 println!("Passed!")
296 }
297
298 #[test]
300 fn test_default_num_threads() {
301 use num_cpus;
302 let threads = threading::threading_functions::get_default_system_thread_count();
303 assert_eq!(
304 threads >= num_cpus::get(),
305 true,
306 "Default thread count is incorrect! We got {}, but expected {}!",
307 threads,
308 num_cpus::get()
309 );
310 }
311
312 #[test]
313 fn test_execute_job() {
314 let expected = vec![1, 2, 3];
315 let task_processor = async |args: &SafeTaskArgs<i32>| -> RUMResult<Vec<i32>> {
316 let owned_args = Arc::clone(args);
317 let lock_future = owned_args.read();
318 let locked_args = lock_future.await;
319 let mut results = TaskItems::<i32>::with_capacity(locked_args.len());
320 print!("Contents: ");
321 for arg in locked_args.iter() {
322 results.push(arg.clone());
323 println!("{} ", &arg);
324 }
325 Ok(results)
326 };
327 let locked_args = RwLock::new(expected.clone());
328 let task_args = SafeTaskArgs::<i32>::new(locked_args);
329 let task_result = rumtk_wait_on_task!(task_processor, &task_args);
330 let result = task_result.unwrap();
331 assert_eq!(&result, &expected, "{}", rumtk_format!("Task processing returned a different result than expected! Expected {:?} \nResults {:?}", &expected, &result));
332 }
333
334 #[test]
335 fn test_execute_job_macros() {
336 let expected = vec![1, 2, 3];
337 let task_processor = async |args: &SafeTaskArgs<i32>| -> RUMResult<Vec<i32>> {
338 let owned_args = Arc::clone(args);
339 let lock_future = owned_args.read();
340 let locked_args = lock_future.await;
341 let mut results = TaskItems::<i32>::with_capacity(locked_args.len());
342 print!("Contents: ");
343 for arg in locked_args.iter() {
344 results.push(arg.clone());
345 println!("{} ", &arg);
346 }
347 Ok(results)
348 };
349 let task_args = rumtk_create_task_args!(1, 2, 3);
350 let task_result = rumtk_wait_on_task!(task_processor, &task_args);
351 let result = task_result.unwrap();
352 assert_eq!(&result, &expected, "{}", rumtk_format!("Task processing returned a different result than expected! Expected {:?} \nResults {:?}", &expected, &result));
353 }
354
355 #[test]
356 fn test_execute_job_macros_one_line() {
357 let expected = vec![1, 2, 3];
358 let result = rumtk_exec_task!(
359 async |args: &SafeTaskArgs<i32>| -> RUMResult<Vec<i32>> {
360 let owned_args = Arc::clone(args);
361 let lock_future = owned_args.read();
362 let locked_args = lock_future.await;
363 let mut results = TaskItems::<i32>::with_capacity(locked_args.len());
364 print!("Contents: ");
365 for arg in locked_args.iter() {
366 results.push(arg.clone());
367 println!("{} ", &arg);
368 }
369 Ok(results)
370 },
371 vec![1, 2, 3]
372 )
373 .unwrap();
374 assert_eq!(&result, &expected, "{}", rumtk_format!("Task processing returned a different result than expected! Expected {:?} \nResults {:?}", &expected, &result));
375 }
376
377 #[test]
378 fn test_clamp_index_positive_index() {
379 let values = vec![1, 2, 3, 4];
380 let given_index = 3isize;
381 let max_size = values.len() as isize;
382 let index = clamp_index(&given_index, &max_size).unwrap();
383 assert_eq!(
384 index, 3,
385 "Index mismatch! Requested index {} but got {}",
386 &given_index, &index
387 );
388 assert_eq!(
389 values[index], 4,
390 "Value mismatch! Expected {} but got {}",
391 &values[3], &values[index]
392 );
393 }
394
395 #[test]
396 fn test_clamp_index_reverse_index() {
397 let values = vec![1, 2, 3, 4];
398 let given_index = -1isize;
399 let max_size = values.len() as isize;
400 let index = clamp_index(&given_index, &max_size).unwrap();
401 assert_eq!(
402 index, 4,
403 "Index mismatch! Requested index {} but got {}",
404 &given_index, &index
405 );
406 assert_eq!(
407 values[index - 1],
408 4,
409 "Value mismatch! Expected {} but got {}",
410 &values[3],
411 &values[index]
412 );
413 }
414
415 #[test]
416 fn test_block_on_task() {
417 let expect = 5;
418 let value = block_on_task(async move { 5 });
419 assert_eq!(
420 value, 5,
421 "Value mismatch from async task! Expected {} but got {}",
422 &expect, &value
423 );
424 }
425
426 use crate::cli::cli_utils::print_license_notice;
428 use crate::net::tcp::LOCALHOST;
429 use crate::pipelines::pipeline_functions::{
430 pipeline_generate_command, pipeline_pipe_processes, pipeline_spawn_process,
431 };
432 use crate::pipelines::pipeline_types::RUMCommand;
433 use crate::threading::threading_functions::block_on_task;
434 use crate::threading::threading_manager::*;
435
436 #[test]
437 fn test_queue_data() {
438 let expected = vec![
439 RUMString::from("Hello"),
440 RUMString::from("World!"),
441 RUMString::from("Overcast"),
442 RUMString::from("and"),
443 RUMString::from("Sad"),
444 ];
445 type TestResult = RUMResult<Vec<RUMString>>;
446 let mut queue: TaskManager<TestResult> = TaskManager::new(&5).unwrap();
447 let locked_args = RwLock::new(expected.clone());
448 let task_args = SafeTaskArgs::<RUMString>::new(locked_args);
449 let processor = rumtk_create_task!(
450 async |args: &SafeTaskArgs<RUMString>| -> TestResult {
451 let owned_args = Arc::clone(args);
452 let lock_future = owned_args.read();
453 let locked_args = lock_future.await;
454 let mut results = TaskItems::<RUMString>::with_capacity(locked_args.len());
455 print!("Contents: ");
456 for arg in locked_args.iter() {
457 print!("{} ", &arg);
458 results.push(RUMString::new(arg));
459 }
460 Ok(results)
461 },
462 task_args
463 );
464
465 queue.add_task::<_>(processor);
466 let results = queue.wait();
467
468 let mut result_data = Vec::<RUMString>::with_capacity(5);
469 for r in results {
470 for v in r.unwrap().result.clone().unwrap().iter() {
471 for value in v.iter() {
472 result_data.push(value.clone());
473 }
474 }
475 }
476 assert_eq!(result_data, expected, "Results do not match expected!");
477 }
478
479 #[test]
481 fn test_server_start() {
482 let server = match rumtk_create_server!("localhost", 0) {
483 Ok(server) => server,
484 Err(e) => panic!("Failed to create server because {}", e),
485 };
486 }
487
488 #[test]
489 fn test_server_send() {
490 let msg = RUMString::from("Hello World!");
491 let mut server = match rumtk_create_server!(LOCALHOST, 0) {
492 Ok(server) => server,
493 Err(e) => panic!("Failed to create server because {}", e),
494 };
495 let address_info = server.get_address_info().unwrap();
496 let (ip, port) = rumtk_get_ip_port!(address_info);
497 let mut client = match rumtk_connect!(port) {
498 Ok(client) => client,
499 Err(e) => panic!("Failed to create server because {}", e),
500 };
501 let client_id = client.get_address().unwrap();
502 match server.send(&client_id, &msg.to_raw()) {
503 Ok(_) => (),
504 Err(e) => panic!("Server failed to send message because {}", e),
505 };
506 let received_message = client.receive().unwrap();
507 assert_eq!(
508 &msg.len(),
509 &received_message.len(),
510 "Received message does not match expected length!"
511 );
512 assert_eq!(
513 &msg.to_raw(),
514 &received_message,
515 "{}",
516 rumtk_format!(
517 "Received message does not match sent message by server {:?}",
518 &received_message
519 )
520 );
521 }
522
523 #[test]
524 fn test_server_receive() {
525 let msg = RUMString::from("Hello World!");
526 let mut server = match rumtk_create_server!(LOCALHOST, 0) {
527 Ok(server) => server,
528 Err(e) => panic!("Failed to create server because {}", e),
529 };
530 let address_info = server.get_address_info().unwrap();
531 let (ip, port) = rumtk_get_ip_port!(address_info);
532 println!("Sleeping");
533 rumtk_sleep!(1);
534 let mut client = match rumtk_connect!(port) {
535 Ok(client) => client,
536 Err(e) => panic!("Failed to create server because {}", e),
537 };
538 println!("Sleeping");
539 rumtk_sleep!(1);
540 match client.send(msg.to_raw()) {
541 Ok(_) => (),
542 Err(e) => panic!("Failed to send message because {}", e),
543 };
544 let client_id = client.get_address().expect("Failed to get client id");
545 let incoming_message = server.receive(&client_id, true).unwrap().to_rumstring();
546 println!("Received message => {:?}", &incoming_message);
547 assert_eq!(&incoming_message, msg, "Received message corruption!");
548 }
549
550 #[test]
551 fn test_server_get_clients() {
552 let mut server = match rumtk_create_server!(LOCALHOST, 0) {
553 Ok(server) => server,
554 Err(e) => panic!("Failed to create 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 client because {}", e),
563 };
564 println!("Sleeping");
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 server = match rumtk_create_server!("localhost", 0) {
581 Ok(server) => server,
582 Err(e) => panic!("Failed to create server because {}", e),
583 };
584 println!("Sleeping");
585 }
586
587 #[test]
588 fn test_server_get_address_info() {
589 let msg = RUMString::from("Hello World!");
590 let mut server = match rumtk_create_server!("localhost", 0) {
591 Ok(server) => server,
592 Err(e) => panic!("Failed to create server because {}", e),
593 };
594 let addr = server.get_address_info().unwrap();
595 assert!(!addr.is_empty(), "No address returned....Got => {}", addr)
596 }
597
598 #[test]
599 fn test_client_send() {
600 let msg = RUMString::from("Hello World!");
601 let mut server = match rumtk_create_server!(LOCALHOST, 0) {
602 Ok(server) => server,
603 Err(e) => panic!("Failed to create server because {}", e),
604 };
605 let address_info = server.get_address_info().unwrap();
606 let (ip, port) = rumtk_get_ip_port!(address_info);
607 println!("Sleeping");
608 let mut client = match rumtk_connect!(port) {
609 Ok(client) => client,
610 Err(e) => panic!("Failed to create server because {}", e),
611 };
612 match client.send(msg.to_raw()) {
613 Ok(_) => (),
614 Err(e) => panic!("Failed to send message because {}", e),
615 };
616 let clients = server.get_client_ids();
617 let incoming_client_id = clients.first().expect("Expected client to have connected!");
618 let mut received_message = server.receive(incoming_client_id, true).unwrap();
619 if received_message.is_empty() {
620 received_message = server.receive(incoming_client_id, true).unwrap();
621 }
622 assert_eq!(
623 &msg.to_raw(),
624 &received_message,
625 "{}",
626 rumtk_format!(
627 "Received message does not match sent message by client {:?}",
628 &received_message
629 )
630 );
631 }
632
633 #[test]
636 fn test_serialize_json() {
637 #[derive(RUMSerialize)]
638 struct MyStruct {
639 hello: RUMString,
640 }
641
642 let hw = MyStruct {
643 hello: RUMString::from("World"),
644 };
645 let hw_str = rumtk_serialize!(&hw, true).unwrap();
646
647 assert!(
648 !hw_str.is_empty(),
649 "Empty JSON string generated from the test struct!"
650 );
651 }
652
653 #[test]
654 fn test_deserialize_serde_json() {
655 use serde_json::{from_str, to_string};
656
657 #[derive(RUMSerialize, RUMDeserialize, PartialEq, Debug, Clone)]
658 struct MyStruct {
659 hello: RUMString,
660 }
661
662 let hw = MyStruct {
663 hello: RUMString::from("World"),
664 };
665 let hw_str = to_string(&hw).unwrap();
666 let new_hw: MyStruct = from_str(&hw_str).unwrap();
667
668 assert_eq!(
669 new_hw, hw,
670 "Deserialized JSON does not match the expected value!"
671 );
672 }
673
674 #[test]
675 fn test_deserialize_json() {
676 #[derive(RUMSerialize, RUMDeserialize, PartialEq)]
677 struct MyStruct {
678 hello: RUMString,
679 }
680
681 let hw = MyStruct {
682 hello: RUMString::from("World"),
683 };
684 let hw_str = rumtk_serialize!(&hw, true).unwrap();
685 let new_hw: MyStruct = rumtk_deserialize!(&hw_str).unwrap();
686
687 assert!(
688 new_hw == hw,
689 "Deserialized JSON does not match the expected value!"
690 );
691 }
692
693 #[test]
729 fn test_print_license_notice() {
730 print_license_notice("RUMTK", "2025", &vec!["Luis M. Santos, M.D."]);
731 }
732
733 #[test]
738 fn test_pipe_processes() {
739 let ls_name = "ls";
740 let mut ls_command = RUMCommand::default();
741 ls_command.path = RUMString::from(ls_name);
742 let mut sys_ls_command = pipeline_generate_command(&ls_command);
743 sys_ls_command.stdin(Stdio::piped());
744 sys_ls_command.stdout(Stdio::piped());
745
746 let wc_name = "wc";
747 let mut wc_command = RUMCommand::default();
748 wc_command.path = RUMString::from(wc_name);
749 let mut sys_wc_command = pipeline_generate_command(&wc_command);
750
751 let mut sys_ls_process = pipeline_spawn_process(&mut sys_ls_command).unwrap();
752 pipeline_pipe_processes(&mut sys_ls_process, &mut sys_wc_command).unwrap();
753 let mut sys_wc_process = pipeline_spawn_process(&mut sys_wc_command).unwrap();
754
755 sys_ls_process.wait();
756 sys_wc_process.wait();
757 }
758
759 }