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