Skip to main content

rumtk_core/
lib.rs

1/*
2 * rumtk attempts to implement HL7 and medical protocols for interoperability in medicine.
3 * This toolkit aims to be reliable, simple, performant, and standards compliant.
4 * Copyright (C) 2024  Luis M. Santos, M.D. <lsantos@medicalmasses.com>
5 * Copyright (C) 2025  MedicalMasses L.L.C. <contact@medicalmasses.com>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19 */
20
21//#![feature(unboxed_closures)]
22//#![feature(inherent_associated_types)]
23#![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#![feature(const_trait_impl)]
29#![feature(const_cmp)]
30#![feature(macro_metavar_expr)]
31
32pub mod cache;
33pub mod cli;
34pub mod core;
35pub mod dependencies;
36pub mod hash;
37pub mod id;
38pub mod json;
39pub mod log;
40pub mod maths;
41pub mod net;
42pub mod pipelines;
43pub mod scripting;
44pub mod search;
45pub mod strings;
46pub mod threading;
47pub mod types;
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52    use crate::cache::RUMCache;
53    use crate::core::{clamp_index, RUMResult};
54    use crate::search::rumtk_search::*;
55    use crate::strings::{buffer_to_string, rumtk_format, AsStr, RUMArrayConversions, RUMString, RUMStringConversions, StringUtils};
56    use crate::types::{RUMBuffer, 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::io::AsyncBufReadExt;
62    use tokio::sync::RwLock;
63
64    #[test]
65    fn test_is_escaped_str() {
66        let input = "\r\n\'\\\"";
67        let expected = false;
68        let result = strings::is_escaped_str(input);
69        println!("Input: {} Expected: {} Got: {}", input, expected, result);
70        assert_eq!(
71            expected, result,
72            "Incorrect detection of unescaped string as escaped!!"
73        );
74        println!("Passed!")
75    }
76
77    #[test]
78    fn test_escaping_control() {
79        let input = "\r\n\'\"\\";
80        let expected = "\\r\\n\\'\\\"\\\\";
81        let result = strings::escape(input);
82        println!(
83            "Input: {} Expected: {} Got: {}",
84            input,
85            expected,
86            result.as_str()
87        );
88        assert_eq!(expected, result, "Incorrect string escaping!");
89        println!("Passed!")
90    }
91
92    #[test]
93    fn test_escaping_unicode() {
94        let input = "❤";
95        let expected = "\\u2764";
96        let result = strings::escape(input);
97        println!(
98            "Input: {} Expected: {} Got: {}",
99            input,
100            expected,
101            result.as_str()
102        );
103        assert_eq!(expected, result, "Incorrect string escaping!");
104        println!("Passed!")
105    }
106
107    #[test]
108    fn test_unescaping_unicode() {
109        let input = "❤";
110        let escaped = strings::escape(input);
111        let expected = "❤";
112        let result = RUMString::from_utf8(strings::unescape(escaped.as_str()).unwrap()).unwrap();
113        println!(
114            "Input: {} Expected: {} Got: {}",
115            input,
116            expected,
117            result.as_str()
118        );
119        assert_eq!(expected, result.as_str(), "Incorrect string unescaping!");
120        println!("Passed!")
121    }
122
123    #[test]
124    fn test_unescaping_string() {
125        let input = "I \\u2764 my wife!";
126        let expected = "I ❤ my wife!";
127        let result = strings::unescape_string(input).unwrap();
128        println!(
129            "Input: {} Expected: {} Got: {}",
130            input,
131            expected,
132            result.as_str()
133        );
134        assert_eq!(expected, result.as_str(), "Incorrect string unescaping!");
135        println!("Passed!")
136    }
137
138    #[test]
139    fn test_is_escaped_string() {
140        let input = "I \\u2764 my wife!";
141        let expected = true;
142        let result = strings::is_escaped_str(input);
143        println!("Input: {} Expected: {} Got: {}", input, expected, result);
144        assert_eq!(
145            expected, result,
146            "Escaped string detected as unescaped string!"
147        );
148        println!("Passed!")
149    }
150
151    #[test]
152    fn test_is_unescaped_string() {
153        let input = "I ❤ my wife!";
154        let expected = false;
155        let result = strings::is_escaped_str(input);
156        println!("Input: {} Expected: {} Got: {}", input, expected, result);
157        assert_eq!(
158            expected, result,
159            "Unescaped string detected as escaped string!"
160        );
161        println!("Passed!")
162    }
163
164    #[test]
165    fn test_unique_string() {
166        let input = "I❤mywife!";
167        assert!(
168            input.as_grapheme_str().is_unique(),
169            "String was not detected as unique."
170        );
171    }
172
173    #[test]
174    fn test_non_unique_string() {
175        let input = "I❤❤mywife!";
176        assert!(
177            !input.as_grapheme_str().is_unique(),
178            "String was detected as unique."
179        );
180    }
181
182    #[test]
183    fn test_escaping_string() {
184        let input = "I ❤ my wife!";
185        let expected = "I \\u2764 my wife!";
186        let result = strings::escape(input);
187        println!(
188            "Input: {} Expected: {} Got: {}",
189            input,
190            expected,
191            result.as_str()
192        );
193        assert_eq!(expected, result.as_str(), "Incorrect string escaping!");
194        println!("Passed!")
195    }
196
197    #[test]
198    fn test_autodecode_utf8() {
199        let input = "I ❤ my wife!";
200        let result = strings::try_decode(input.as_bytes());
201        println!(
202            "Input: {} Expected: {} Got: {}",
203            input,
204            input,
205            result.as_str()
206        );
207        assert_eq!(input, result, "Incorrect string decoding!");
208        println!("Passed!")
209    }
210
211    #[test]
212    fn test_autodecode_other() {
213        //TODO: Need an example of other encoding texts.
214        let input = "I ❤ my wife!";
215        let result = input;
216        println!("Input: {} Expected: {} Got: {}", input, input, result);
217        assert_eq!(input, result, "Incorrect string decoding!");
218        println!("Passed!")
219    }
220
221    #[test]
222    fn test_decode() {
223        let input = "I ❤ my wife!";
224        let result = strings::try_decode_with(input.as_bytes(), "utf-8");
225        println!(
226            "Input: {} Expected: {} Got: {}",
227            input,
228            input,
229            result.as_str()
230        );
231        assert_eq!(input, result, "Incorrect string decoding!");
232        println!("Passed!")
233    }
234
235    #[test]
236    fn test_rumcache_insertion() {
237        let mut cache: RUMCache<&str, CompactString> = RUMCache::with_capacity(5);
238        cache.insert("❤", CompactString::from("I ❤ my wife!"));
239        println!("Contents: {:#?}", &cache);
240        assert_eq!(cache.len(), 1, "Incorrect number of items in cache!");
241        println!("Passed!")
242    }
243
244    #[test]
245    fn test_search_string_letters() {
246        let input = "Hello World!";
247        let expr = r"\w";
248        let result = string_search(input, expr, "").unwrap();
249        let expected: RUMString = RUMString::from("HelloWorld");
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_words() {
260        let input = "Hello World!";
261        let expr = r"\w+";
262        let result = string_search(input, expr, " ").unwrap();
263        let expected: RUMString = RUMString::from("Hello World");
264        println!(
265            "Input: {:?} Expected: {:?} Got: {:?}",
266            input, expected, result
267        );
268        assert_eq!(expected, result, "String search results mismatch");
269        println!("Passed!")
270    }
271
272    #[test]
273    fn test_search_string_named_groups() {
274        let input = "Hello World!";
275        let expr = r"(?<hello>\w{5}) (?<world>\w{5})";
276        let result = string_search_named_captures(input, expr, "").unwrap();
277        let expected: RUMString = RUMString::from("World");
278        println!(
279            "Input: {:?} Expected: {:?} Got: {:?}",
280            input, expected, result
281        );
282        assert_eq!(expected, result["world"], "String search results mismatch");
283        println!("Passed!")
284    }
285
286    #[test]
287    fn test_search_string_all_groups() {
288        let input = "Hello World!";
289        let expr = r"(?<hello>\w{5}) (?<world>\w{5})";
290        let result = string_search_all_captures(input, expr, "").unwrap();
291        let expected: Vec<&str> = vec!["Hello", "World"];
292        println!(
293            "Input: {:?} Expected: {:?} Got: {:?}",
294            input, expected, result
295        );
296        assert_eq!(expected, result, "String search results mismatch");
297        println!("Passed!")
298    }
299
300    #[test]
301    fn test_find_value_in_string() {
302        let haystack = "Range (min \\xe2\\x80\\xa6 max):     0.6 ms \\xe2\\x80\\xa6   2.9 ms    1273 runs";
303        let patterns = ["\\d+ runs", "\\d+"];
304        let expected = 1273;
305        let result = string_find_value::<usize>(haystack, &patterns);
306
307        assert_eq!(result, Ok(expected), "Did not find the needle in the haystack or returned the wrong type!");
308    }
309
310    ///////////////////////////////////Threading Tests/////////////////////////////////////////////////
311    #[test]
312    fn test_default_num_threads() {
313        use num_cpus;
314        let threads = threading::threading_functions::get_default_system_thread_count();
315        assert_eq!(
316            threads >= num_cpus::get(),
317            true,
318            "Default thread count is incorrect! We got {}, but expected {}!",
319            threads,
320            num_cpus::get()
321        );
322    }
323
324    #[test]
325    fn test_execute_job() {
326        let expected = vec![1, 2, 3];
327        let task_processor = async |args: &SafeTaskArgs<i32>| -> RUMResult<Vec<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 locked_args = RwLock::new(expected.clone());
340        let task_args = SafeTaskArgs::<i32>::new(locked_args);
341        let task_result = rumtk_wait_on_task!(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() {
348        let expected = vec![1, 2, 3];
349        let task_processor = async |args: &SafeTaskArgs<i32>| -> RUMResult<Vec<i32>> {
350            let owned_args = Arc::clone(args);
351            let lock_future = owned_args.read();
352            let locked_args = lock_future.await;
353            let mut results = TaskItems::<i32>::with_capacity(locked_args.len());
354            print!("Contents: ");
355            for arg in locked_args.iter() {
356                results.push(arg.clone());
357                println!("{} ", &arg);
358            }
359            Ok(results)
360        };
361        let task_args = rumtk_create_task_args!(1, 2, 3);
362        let task_result = rumtk_wait_on_task!(task_processor, &task_args);
363        let result = task_result.unwrap();
364        assert_eq!(&result, &expected, "{}", rumtk_format!("Task processing returned a different result than expected! Expected {:?} \nResults {:?}", &expected, &result));
365    }
366
367    #[test]
368    fn test_execute_job_macros_one_line() {
369        let expected = vec![1, 2, 3];
370        let result = rumtk_exec_task!(
371            async |args: &SafeTaskArgs<i32>| -> RUMResult<Vec<i32>> {
372                let owned_args = Arc::clone(args);
373                let lock_future = owned_args.read();
374                let locked_args = lock_future.await;
375                let mut results = TaskItems::<i32>::with_capacity(locked_args.len());
376                print!("Contents: ");
377                for arg in locked_args.iter() {
378                    results.push(arg.clone());
379                    println!("{} ", &arg);
380                }
381                Ok(results)
382            },
383            vec![1, 2, 3]
384        )
385        .unwrap();
386        assert_eq!(&result, &expected, "{}", rumtk_format!("Task processing returned a different result than expected! Expected {:?} \nResults {:?}", &expected, &result));
387    }
388
389    #[test]
390    fn test_clamp_index_positive_index() {
391        let values = vec![1, 2, 3, 4];
392        let given_index = 3isize;
393        let max_size = values.len() as isize;
394        let index = clamp_index(&given_index, &max_size).unwrap();
395        assert_eq!(
396            index, 3,
397            "Index mismatch! Requested index {} but got {}",
398            &given_index, &index
399        );
400        assert_eq!(
401            values[index], 4,
402            "Value mismatch! Expected {} but got {}",
403            &values[3], &values[index]
404        );
405    }
406
407    #[test]
408    fn test_clamp_index_reverse_index() {
409        let values = vec![1, 2, 3, 4];
410        let given_index = -1isize;
411        let max_size = values.len() as isize;
412        let index = clamp_index(&given_index, &max_size).unwrap();
413        assert_eq!(
414            index, 4,
415            "Index mismatch! Requested index {} but got {}",
416            &given_index, &index
417        );
418        assert_eq!(
419            values[index - 1],
420            4,
421            "Value mismatch! Expected {} but got {}",
422            &values[3],
423            &values[index]
424        );
425    }
426
427    #[test]
428    fn test_block_on_task() {
429        let expect = 5;
430        let value = block_on_task(async move { 5 });
431        assert_eq!(
432            value, 5,
433            "Value mismatch from async task! Expected {} but got {}",
434            &expect, &value
435        );
436    }
437
438    ///////////////////////////////////Queue Tests/////////////////////////////////////////////////
439    use crate::cli::cli_utils::print_license_notice;
440    use crate::net::tcp::LOCALHOST;
441    use crate::pipelines::pipeline_functions::{pipeline_add_stdin_data_to_pipeline, pipeline_create_command, pipeline_patch_args, pipeline_pipe_processes, pipeline_spawn_process};
442    use crate::pipelines::pipeline_types::RUMCommand;
443    use crate::threading::threading_functions::block_on_task;
444    use crate::threading::threading_manager::*;
445
446    #[test]
447    fn test_queue_data() {
448        let expected = vec![
449            RUMString::from("Hello"),
450            RUMString::from("World!"),
451            RUMString::from("Overcast"),
452            RUMString::from("and"),
453            RUMString::from("Sad"),
454        ];
455        type TestResult = RUMResult<Vec<RUMString>>;
456        let mut queue: TaskManager<TestResult> = TaskManager::new(&5).unwrap();
457        let locked_args = RwLock::new(expected.clone());
458        let task_args = SafeTaskArgs::<RUMString>::new(locked_args);
459        let processor = rumtk_create_task!(
460            async |args: &SafeTaskArgs<RUMString>| -> TestResult {
461                let owned_args = Arc::clone(args);
462                let lock_future = owned_args.read();
463                let locked_args = lock_future.await;
464                let mut results = TaskItems::<RUMString>::with_capacity(locked_args.len());
465                print!("Contents: ");
466                for arg in locked_args.iter() {
467                    print!("{} ", &arg);
468                    results.push(RUMString::new(arg));
469                }
470                Ok(results)
471            },
472            task_args
473        );
474
475        queue.add_task::<_>(processor);
476        let results = queue.wait();
477
478        let mut result_data = Vec::<RUMString>::with_capacity(5);
479        for r in results {
480            for v in r.unwrap().result.clone().unwrap().iter() {
481                for value in v.iter() {
482                    result_data.push(value.clone());
483                }
484            }
485        }
486        assert_eq!(result_data, expected, "Results do not match expected!");
487    }
488
489    ///////////////////////////////////Net Tests/////////////////////////////////////////////////
490    #[test]
491    fn test_server_start() {
492        let server = match rumtk_create_server!("localhost", 0) {
493            Ok(server) => server,
494            Err(e) => panic!("Failed to create server because {}", e),
495        };
496    }
497
498    #[test]
499    fn test_server_send() {
500        let msg = RUMString::from("Hello World!");
501        let mut server = match rumtk_create_server!(LOCALHOST, 0) {
502            Ok(server) => server,
503            Err(e) => panic!("Failed to create server because {}", e),
504        };
505        let address_info = server.get_address_info().unwrap();
506        let (ip, port) = rumtk_get_ip_port!(address_info);
507        rumtk_sleep!(1);
508        let mut client = match rumtk_connect!(port) {
509            Ok(client) => client,
510            Err(e) => panic!("Failed to create server because {}", e),
511        };
512        let client_id = client.get_address().unwrap();
513        match server.send(&client_id, &msg.to_raw()) {
514            Ok(_) => (),
515            Err(e) => panic!("Server failed to send message because {}", e),
516        };
517        let received_message = client.receive().unwrap();
518        assert_eq!(
519            &msg.len(),
520            &received_message.len(),
521            "Received message does not match expected length!"
522        );
523        assert_eq!(
524            &msg.to_raw(),
525            &received_message,
526            "{}",
527            rumtk_format!(
528                "Received message does not match sent message by server {:?}",
529                &received_message
530            )
531        );
532    }
533
534    #[test]
535    fn test_server_receive() {
536        let msg = RUMString::from("Hello World!");
537        let mut server = match rumtk_create_server!(LOCALHOST, 0) {
538            Ok(server) => server,
539            Err(e) => panic!("Failed to create server because {}", e),
540        };
541        let address_info = server.get_address_info().unwrap();
542        let (ip, port) = rumtk_get_ip_port!(address_info);
543        println!("Sleeping");
544        rumtk_sleep!(1);
545        let mut client = match rumtk_connect!(port) {
546            Ok(client) => client,
547            Err(e) => panic!("Failed to create server because {}", e),
548        };
549        println!("Sleeping");
550        rumtk_sleep!(1);
551        match client.send(msg.to_raw()) {
552            Ok(_) => (),
553            Err(e) => panic!("Failed to send message because {}", e),
554        };
555        let client_id = client.get_address().expect("Failed to get client id");
556        let incoming_message = server.receive(&client_id, true).unwrap().to_rumstring();
557        println!("Received message => {:?}", &incoming_message);
558        assert_eq!(&incoming_message, msg, "Received message corruption!");
559    }
560
561    #[test]
562    fn test_server_get_clients() {
563        let mut server = match rumtk_create_server!(LOCALHOST, 0) {
564            Ok(server) => server,
565            Err(e) => panic!("Failed to create server because {}", e),
566        };
567        let address_info = server.get_address_info().unwrap();
568        let (ip, port) = rumtk_get_ip_port!(address_info);
569        println!("Sleeping");
570        rumtk_sleep!(1);
571        let mut client = match rumtk_connect!(port) {
572            Ok(client) => client,
573            Err(e) => panic!("Failed to create client because {}", e),
574        };
575        println!("Sleeping");
576        rumtk_sleep!(1);
577        let expected_client_id = client.get_address().expect("Failed to get client id");
578        let clients = server.get_client_ids();
579        let incoming_client_id = clients.get(0).expect("Expected client to have connected!");
580        println!("Connected client id => {}", &incoming_client_id);
581        assert_eq!(
582            &incoming_client_id, &expected_client_id,
583            "Connected client does not match the connecting client! Client id => {}",
584            &incoming_client_id
585        );
586    }
587
588    #[test]
589    fn test_server_stop() {
590        let msg = RUMString::from("Hello World!");
591        let server = match rumtk_create_server!("localhost", 0) {
592            Ok(server) => server,
593            Err(e) => panic!("Failed to create server because {}", e),
594        };
595        println!("Sleeping");
596    }
597
598    #[test]
599    fn test_server_get_address_info() {
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 addr = server.get_address_info().unwrap();
606        assert!(!addr.is_empty(), "No address returned....Got => {}", addr)
607    }
608
609    #[test]
610    fn test_client_send() {
611        let msg = RUMString::from("Hello World!");
612        let mut server = match rumtk_create_server!(LOCALHOST, 0) {
613            Ok(server) => server,
614            Err(e) => panic!("Failed to create server because {}", e),
615        };
616        let address_info = server.get_address_info().unwrap();
617        let (ip, port) = rumtk_get_ip_port!(address_info);
618        println!("Sleeping");
619        rumtk_sleep!(1);
620        let mut client = match rumtk_connect!(port) {
621            Ok(client) => client,
622            Err(e) => panic!("Failed to create server because {}", e),
623        };
624        match client.send(msg.to_raw()) {
625            Ok(_) => (),
626            Err(e) => panic!("Failed to send message because {}", e),
627        };
628        let clients = server.get_client_ids();
629        let incoming_client_id = clients.first().expect("Expected client to have connected!");
630        let mut received_message = server.receive(incoming_client_id, true).unwrap();
631        if received_message.is_empty() {
632            received_message = server.receive(incoming_client_id, true).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    ////////////////////////////JSON Tests/////////////////////////////////
646
647    #[test]
648    fn test_serialize_json() {
649        #[derive(RUMSerialize)]
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_json::{from_str, to_string};
668
669        #[derive(RUMSerialize, RUMDeserialize, 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(RUMSerialize, RUMDeserialize, 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    /*
706    #[test]
707    fn test_escape_unescape_json() {
708        #[derive(Serialize, Deserialize, PartialEq)]
709        struct MyStruct {
710            hello: RUMString,
711        }
712
713        let hw = MyStruct {
714            hello: RUMString::from("World"),
715        };
716
717        let hw_str = rumtk_serialize!(&hw, true).unwrap();
718        let hw_escaped_str = strings::basic_escape(&hw_str);
719        println!("Escaped => {}", hw_escaped_str);
720
721        let hw_unescaped_str = strings::unescape_string(&hw_escaped_str).unwrap();
722        println!("Unescaped => {}", hw_unescaped_str);
723        assert_eq!(
724            hw_str.to_rumstring(),
725            hw_unescaped_str.to_rumstring(),
726            "Unescaped serialized JSON mismatch!"
727        );
728
729        let new_hw: MyStruct = rumtk_deserialize!(&hw_unescaped_str).unwrap();
730
731        assert!(
732            new_hw == hw,
733            "Deserialized JSON does not match the expected value!"
734        );
735    }
736    */
737
738    ////////////////////////////CLI Tests/////////////////////////////////
739
740    #[test]
741    fn test_print_license_notice() {
742        print_license_notice("RUMTK", "2025", &vec!["Luis M. Santos, M.D."]);
743    }
744
745    //////////////////////////////////////////////////////////////////////////////////////////////
746
747    ////////////////////////////Pipeline Tests/////////////////////////////////
748
749    #[test]
750    fn test_pipe_processes() {
751        let ls_name = "ls";
752        let mut ls_command = RUMCommand::default();
753        ls_command.path = RUMString::from(ls_name);
754        let mut sys_ls_command = pipeline_create_command(&ls_command);
755        sys_ls_command.stdin(Stdio::piped());
756        sys_ls_command.stdout(Stdio::piped());
757
758        let wc_name = "wc";
759        let mut wc_command = RUMCommand::default();
760        wc_command.path = RUMString::from(wc_name);
761        let mut sys_wc_command = pipeline_create_command(&wc_command);
762
763        let mut sys_ls_process = pipeline_spawn_process(&mut sys_ls_command).unwrap();
764        pipeline_pipe_processes(&mut sys_ls_process, &mut sys_wc_command).unwrap();
765        let mut sys_wc_process = pipeline_spawn_process(&mut sys_wc_command).unwrap();
766
767        sys_ls_process.wait();
768        sys_wc_process.wait();
769    }
770
771    #[test]
772    fn test_quick_pipe() {let data = RUMBuffer::from_static(b"Hello World");
773        let wc_name = "wc";
774        let mut wc_command = RUMCommand::default();
775        wc_command.path = RUMString::from(wc_name);
776        let mut pipeline = vec![
777            wc_command
778        ];
779
780        let processor = || -> RUMResult<RUMBuffer> {rumtk_pipeline_run!(&pipeline, &data)};
781        let result_string = buffer_to_string(&processor().unwrap()).unwrap();
782        let binding = result_string.as_str().replace('\n', "");
783        let result_items: Vec<&str> = binding.split("      ").collect();
784        let result = result_items.get(2).unwrap().trim().parse::<i32>().unwrap();
785
786        assert_eq!(result, 2, "Data was not piped properly!");
787    }
788
789    #[test]
790    fn test_patch_pipeline_arguments() {let data = RUMBuffer::from_static(b"Hello World");
791        let ls_name = "ls";
792        let mut ls_command = RUMCommand::default();
793        ls_command.path = RUMString::from(ls_name);
794        ls_command.args.push(RUMString::from("{options}"));
795        let mut pipeline = vec![
796            ls_command
797        ];
798        pipeline_patch_args(&mut pipeline, &[("{options}", "-la")]);
799
800        let processor = || -> RUMResult<RUMBuffer> {rumtk_pipeline_run!(&pipeline)};
801        let result_string = buffer_to_string(&processor().unwrap()).unwrap();
802        let results: Vec<&str> = result_string.as_str().split("\n").collect();
803        let dot_dir = results.get(1).unwrap().chars().last().unwrap();
804
805        assert_eq!(dot_dir, '.', "Incorrect options passed!");
806    }
807
808    //////////////////////////////////////////////////////////////////////////////////////////////
809}