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