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