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