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.
5 * Copyright (C) 2025  MedicalMasses L.L.C.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library 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 GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22//#![feature(unboxed_closures)]
23//#![feature(inherent_associated_types)]
24#![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        //TODO: Need an example of other encoding texts.
207        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    ///////////////////////////////////Threading Tests/////////////////////////////////////////////////
294    #[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 rt = rumtk_init_threads!();
310        let expected = vec![1, 2, 3];
311        let task_processor = async |args: &SafeTaskArgs<i32>| -> RUMResult<Vec<i32>> {
312            let owned_args = Arc::clone(args);
313            let lock_future = owned_args.read();
314            let locked_args = lock_future.await;
315            let mut results = TaskItems::<i32>::with_capacity(locked_args.len());
316            print!("Contents: ");
317            for arg in locked_args.iter() {
318                results.push(arg.clone());
319                println!("{} ", &arg);
320            }
321            Ok(results)
322        };
323        let locked_args = RwLock::new(expected.clone());
324        let task_args = SafeTaskArgs::<i32>::new(locked_args);
325        let task_result = rumtk_wait_on_task!(rt, task_processor, &task_args);
326        let result = task_result.unwrap();
327        assert_eq!(&result, &expected, "{}", rumtk_format!("Task processing returned a different result than expected! Expected {:?} \nResults {:?}", &expected, &result));
328    }
329
330    #[test]
331    fn test_execute_job_macros() {
332        let rt = rumtk_init_threads!();
333        let expected = vec![1, 2, 3];
334        let task_processor = async |args: &SafeTaskArgs<i32>| -> RUMResult<Vec<i32>> {
335            let owned_args = Arc::clone(args);
336            let lock_future = owned_args.read();
337            let locked_args = lock_future.await;
338            let mut results = TaskItems::<i32>::with_capacity(locked_args.len());
339            print!("Contents: ");
340            for arg in locked_args.iter() {
341                results.push(arg.clone());
342                println!("{} ", &arg);
343            }
344            Ok(results)
345        };
346        let task_args = rumtk_create_task_args!(1, 2, 3);
347        let task_result = rumtk_wait_on_task!(rt, task_processor, &task_args);
348        let result = task_result.unwrap();
349        assert_eq!(&result, &expected, "{}", rumtk_format!("Task processing returned a different result than expected! Expected {:?} \nResults {:?}", &expected, &result));
350    }
351
352    #[test]
353    fn test_execute_job_macros_one_line() {
354        let rt = rumtk_init_threads!();
355        let expected = vec![1, 2, 3];
356        let result = rumtk_exec_task!(
357            async |args: &SafeTaskArgs<i32>| -> RUMResult<Vec<i32>> {
358                let owned_args = Arc::clone(args);
359                let lock_future = owned_args.read();
360                let locked_args = lock_future.await;
361                let mut results = TaskItems::<i32>::with_capacity(locked_args.len());
362                print!("Contents: ");
363                for arg in locked_args.iter() {
364                    results.push(arg.clone());
365                    println!("{} ", &arg);
366                }
367                Ok(results)
368            },
369            vec![1, 2, 3]
370        )
371        .unwrap();
372        assert_eq!(&result, &expected, "{}", rumtk_format!("Task processing returned a different result than expected! Expected {:?} \nResults {:?}", &expected, &result));
373    }
374
375    #[test]
376    fn test_clamp_index_positive_index() {
377        let values = vec![1, 2, 3, 4];
378        let given_index = 3isize;
379        let max_size = values.len() as isize;
380        let index = clamp_index(&given_index, &max_size).unwrap();
381        assert_eq!(
382            index, 3,
383            "Index mismatch! Requested index {} but got {}",
384            &given_index, &index
385        );
386        assert_eq!(
387            values[index], 4,
388            "Value mismatch! Expected {} but got {}",
389            &values[3], &values[index]
390        );
391    }
392
393    #[test]
394    fn test_clamp_index_reverse_index() {
395        let values = vec![1, 2, 3, 4];
396        let given_index = -1isize;
397        let max_size = values.len() as isize;
398        let index = clamp_index(&given_index, &max_size).unwrap();
399        assert_eq!(
400            index, 4,
401            "Index mismatch! Requested index {} but got {}",
402            &given_index, &index
403        );
404        assert_eq!(
405            values[index - 1],
406            4,
407            "Value mismatch! Expected {} but got {}",
408            &values[3],
409            &values[index]
410        );
411    }
412
413    ///////////////////////////////////Queue Tests/////////////////////////////////////////////////
414    use crate::cli::cli_utils::print_license_notice;
415    use crate::net::tcp::LOCALHOST;
416    use crate::pipelines::pipeline_functions::{
417        pipeline_generate_command, pipeline_pipe_process, pipeline_spawn_process,
418    };
419    use crate::pipelines::pipeline_types::RUMCommand;
420    use crate::threading::threading_functions::sleep;
421    use crate::threading::threading_manager::*;
422
423    #[test]
424    fn test_queue_data() {
425        let expected = vec![
426            RUMString::from("Hello"),
427            RUMString::from("World!"),
428            RUMString::from("Overcast"),
429            RUMString::from("and"),
430            RUMString::from("Sad"),
431        ];
432        type TestResult = RUMResult<Vec<RUMString>>;
433        let mut queue: TaskManager<TestResult> = TaskManager::new(&5).unwrap();
434        let locked_args = RwLock::new(expected.clone());
435        let task_args = SafeTaskArgs::<RUMString>::new(locked_args);
436        let processor = rumtk_create_task!(
437            async |args: &SafeTaskArgs<RUMString>| -> TestResult {
438                let owned_args = Arc::clone(args);
439                let lock_future = owned_args.read();
440                let locked_args = lock_future.await;
441                let mut results = TaskItems::<RUMString>::with_capacity(locked_args.len());
442                print!("Contents: ");
443                for arg in locked_args.iter() {
444                    print!("{} ", &arg);
445                    results.push(RUMString::new(arg));
446                }
447                Ok(results)
448            },
449            task_args
450        );
451
452        queue.add_task::<_>(processor);
453        let results = queue.wait();
454
455        let mut result_data = Vec::<RUMString>::with_capacity(5);
456        for r in results {
457            for v in r.unwrap().result.clone().unwrap().iter() {
458                for value in v.iter() {
459                    result_data.push(value.clone());
460                }
461            }
462        }
463        assert_eq!(result_data, expected, "Results do not match expected!");
464    }
465
466    ///////////////////////////////////Net Tests/////////////////////////////////////////////////
467    #[test]
468    fn test_server_start() {
469        let mut server = match rumtk_create_server!("localhost", 0) {
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    }
478
479    #[test]
480    fn test_server_send() {
481        let msg = RUMString::from("Hello World!");
482        let mut server = match rumtk_create_server!(LOCALHOST, 0, 1) {
483            Ok(server) => server,
484            Err(e) => panic!("Failed to create server because {}", e),
485        };
486        match server.start(false) {
487            Ok(_) => (),
488            Err(e) => panic!("Failed to start server because {}", e),
489        };
490        let address_info = server.get_address_info().unwrap();
491        let (ip, port) = rumtk_get_ip_port!(address_info);
492        println!("Sleeping");
493        rumtk_sleep!(1);
494        let mut client = match rumtk_connect!(port) {
495            Ok(client) => client,
496            Err(e) => panic!("Failed to create server because {}", e),
497        };
498        let client_id = client.get_address().unwrap();
499        rumtk_sleep!(1);
500        match server.send(&client_id, &msg.to_raw()) {
501            Ok(_) => (),
502            Err(e) => panic!("Server failed to send message because {}", e),
503        };
504        rumtk_sleep!(1);
505        let received_message = client.receive().unwrap();
506        assert_eq!(
507            &msg.to_raw(),
508            &received_message,
509            "{}",
510            rumtk_format!(
511                "Received message does not match sent message by server {:?}",
512                &received_message
513            )
514        );
515    }
516
517    #[test]
518    fn test_server_receive() {
519        let msg = RUMString::from("Hello World!");
520        let mut server = match rumtk_create_server!(LOCALHOST, 0) {
521            Ok(server) => server,
522            Err(e) => panic!("Failed to create server because {}", e),
523        };
524        match server.start(false) {
525            Ok(_) => (),
526            Err(e) => panic!("Failed to start server because {}", e),
527        };
528        let address_info = server.get_address_info().unwrap();
529        let (ip, port) = rumtk_get_ip_port!(address_info);
530        println!("Sleeping");
531        rumtk_sleep!(1);
532        let mut client = match rumtk_connect!(port) {
533            Ok(client) => client,
534            Err(e) => panic!("Failed to create server because {}", e),
535        };
536        match client.send(&msg.to_raw()) {
537            Ok(_) => (),
538            Err(e) => panic!("Failed to send message because {}", e),
539        };
540        rumtk_sleep!(1);
541        let client_id = client.get_address().expect("Failed to get client id");
542        let incoming_message = server.receive(&client_id).unwrap().to_rumstring();
543        println!("Received message => {:?}", &incoming_message);
544        assert_eq!(&incoming_message, msg, "Received message corruption!");
545    }
546
547    #[test]
548    fn test_server_get_clients() {
549        let mut server = match rumtk_create_server!(LOCALHOST, 0) {
550            Ok(server) => server,
551            Err(e) => panic!("Failed to create server because {}", e),
552        };
553        match server.start(false) {
554            Ok(_) => (),
555            Err(e) => panic!("Failed to start server because {}", e),
556        };
557        let address_info = server.get_address_info().unwrap();
558        let (ip, port) = rumtk_get_ip_port!(address_info);
559        println!("Sleeping");
560        rumtk_sleep!(1);
561        let mut client = match rumtk_connect!(port) {
562            Ok(client) => client,
563            Err(e) => panic!("Failed to create server because {}", e),
564        };
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 mut server = match rumtk_create_server!("localhost", 0) {
581            Ok(server) => server,
582            Err(e) => panic!("Failed to create server because {}", e),
583        };
584        match server.start(false) {
585            Ok(_) => (),
586            Err(e) => panic!("Failed to start server because {}", e),
587        };
588        println!("Sleeping");
589        rumtk_sleep!(1);
590        match server.stop() {
591            Ok(_) => (),
592            Err(e) => panic!("Failed to stop server because {}", e),
593        };
594    }
595
596    #[test]
597    fn test_server_get_address_info() {
598        let msg = RUMString::from("Hello World!");
599        let mut server = match rumtk_create_server!("localhost", 0) {
600            Ok(server) => server,
601            Err(e) => panic!("Failed to create server because {}", e),
602        };
603        match server.start(false) {
604            Ok(_) => (),
605            Err(e) => panic!("Failed to start server because {}", e),
606        };
607        println!("Sleeping");
608        rumtk_sleep!(1);
609        match server.get_address_info() {
610            Some(addr) => println!("Server address info => {}", addr),
611            None => panic!("No address. Perhaps the server was never initialized?"),
612        };
613    }
614
615    #[test]
616    fn test_client_send() {
617        let msg = RUMString::from("Hello World!");
618        let mut server = match rumtk_create_server!(LOCALHOST, 0) {
619            Ok(server) => server,
620            Err(e) => panic!("Failed to create server because {}", e),
621        };
622        match server.start(false) {
623            Ok(_) => (),
624            Err(e) => panic!("Failed to start server because {}", e),
625        };
626        let address_info = server.get_address_info().unwrap();
627        let (ip, port) = rumtk_get_ip_port!(address_info);
628        println!("Sleeping");
629        rumtk_sleep!(1);
630        let mut client = match rumtk_connect!(port) {
631            Ok(client) => client,
632            Err(e) => panic!("Failed to create server because {}", e),
633        };
634        rumtk_sleep!(2);
635        match client.send(&msg.to_raw()) {
636            Ok(_) => (),
637            Err(e) => panic!("Failed to send message because {}", e),
638        };
639        rumtk_sleep!(1);
640        let clients = server.get_client_ids();
641        let incoming_client_id = clients.first().expect("Expected client to have connected!");
642        let mut received_message = server.receive(incoming_client_id).unwrap();
643        if received_message.is_empty() {
644            rumtk_sleep!(1);
645            received_message = server.receive(incoming_client_id).unwrap();
646        }
647        assert_eq!(
648            &msg.to_raw(),
649            &received_message,
650            "{}",
651            rumtk_format!(
652                "Received message does not match sent message by client {:?}",
653                &received_message
654            )
655        );
656    }
657
658    ////////////////////////////JSON Tests/////////////////////////////////
659
660    #[test]
661    fn test_serialize_json() {
662        #[derive(RUMSerialize)]
663        struct MyStruct {
664            hello: RUMString,
665        }
666
667        let hw = MyStruct {
668            hello: RUMString::from("World"),
669        };
670        let hw_str = rumtk_serialize!(&hw, true).unwrap();
671
672        assert!(
673            !hw_str.is_empty(),
674            "Empty JSON string generated from the test struct!"
675        );
676    }
677
678    #[test]
679    fn test_deserialize_serde_json() {
680        use serde_json::{from_str, to_string};
681
682        #[derive(RUMSerialize, RUMDeserialize, PartialEq, Debug, Clone)]
683        struct MyStruct {
684            hello: RUMString,
685        }
686
687        let hw = MyStruct {
688            hello: RUMString::from("World"),
689        };
690        let hw_str = to_string(&hw).unwrap();
691        let new_hw: MyStruct = from_str(&hw_str).unwrap();
692
693        assert_eq!(
694            new_hw, hw,
695            "Deserialized JSON does not match the expected value!"
696        );
697    }
698
699    #[test]
700    fn test_deserialize_json() {
701        #[derive(RUMSerialize, RUMDeserialize, PartialEq)]
702        struct MyStruct {
703            hello: RUMString,
704        }
705
706        let hw = MyStruct {
707            hello: RUMString::from("World"),
708        };
709        let hw_str = rumtk_serialize!(&hw, true).unwrap();
710        let new_hw: MyStruct = rumtk_deserialize!(&hw_str).unwrap();
711
712        assert!(
713            new_hw == hw,
714            "Deserialized JSON does not match the expected value!"
715        );
716    }
717
718    /*
719    #[test]
720    fn test_escape_unescape_json() {
721        #[derive(Serialize, Deserialize, PartialEq)]
722        struct MyStruct {
723            hello: RUMString,
724        }
725
726        let hw = MyStruct {
727            hello: RUMString::from("World"),
728        };
729
730        let hw_str = rumtk_serialize!(&hw, true).unwrap();
731        let hw_escaped_str = strings::basic_escape(&hw_str);
732        println!("Escaped => {}", hw_escaped_str);
733
734        let hw_unescaped_str = strings::unescape_string(&hw_escaped_str).unwrap();
735        println!("Unescaped => {}", hw_unescaped_str);
736        assert_eq!(
737            hw_str.to_rumstring(),
738            hw_unescaped_str.to_rumstring(),
739            "Unescaped serialized JSON mismatch!"
740        );
741
742        let new_hw: MyStruct = rumtk_deserialize!(&hw_unescaped_str).unwrap();
743
744        assert!(
745            new_hw == hw,
746            "Deserialized JSON does not match the expected value!"
747        );
748    }
749    */
750
751    ////////////////////////////CLI Tests/////////////////////////////////
752
753    #[test]
754    fn test_print_license_notice() {
755        print_license_notice("RUMTK", "2025", &vec!["Luis M. Santos, M.D."]);
756    }
757
758    //////////////////////////////////////////////////////////////////////////////////////////////
759
760    ////////////////////////////Pipeline Tests/////////////////////////////////
761
762    #[test]
763    fn test_pipe_processes() {
764        let ls_name = "ls";
765        let mut ls_command = RUMCommand::default();
766        ls_command.path = RUMString::from(ls_name);
767        let mut sys_ls_command = pipeline_generate_command(&ls_command);
768        sys_ls_command.stdin(Stdio::piped());
769        sys_ls_command.stdout(Stdio::piped());
770
771        let wc_name = "wc";
772        let mut wc_command = RUMCommand::default();
773        wc_command.path = RUMString::from(wc_name);
774        let mut sys_wc_command = pipeline_generate_command(&wc_command);
775
776        let mut sys_ls_process = pipeline_spawn_process(&mut sys_ls_command).unwrap();
777        pipeline_pipe_process(&mut sys_ls_process, &mut sys_wc_command).unwrap();
778        let mut sys_wc_process = pipeline_spawn_process(&mut sys_wc_command).unwrap();
779
780        sys_ls_process.wait();
781        sys_wc_process.wait();
782    }
783
784    //////////////////////////////////////////////////////////////////////////////////////////////
785}