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