memscope_rs/cli/commands/
test.rs

1//! Test command implementation
2//!
3//! This module provides the test subcommand functionality.
4
5use crate::core::tracker::get_global_tracker;
6use crate::track_var;
7use clap::ArgMatches;
8use std::error::Error;
9
10/// Run the test command
11pub fn run_test(matches: &ArgMatches) -> Result<(), Box<dyn Error>> {
12    let output_path = matches
13        .get_one::<String>("output")
14        .map(|s| s.as_str())
15        .unwrap_or("enhanced_memory_test");
16
17    tracing::info!("🧪 Running enhanced memory tests...");
18    tracing::info!("Output path: {}", output_path);
19
20    // Initialize memory tracking
21    crate::init();
22
23    // Run the test
24    run_enhanced_memory_test()?;
25
26    Ok(())
27}
28
29fn run_enhanced_memory_test() -> Result<(), Box<dyn Error>> {
30    use crate::core::tracker::get_global_tracker;
31
32    tracing::info!("Creating test allocations...");
33
34    // Create some test allocations
35    let vec1 = vec![1, 2, 3, 4, 5];
36    let vec2 = vec![6, 7, 8, 9, 10];
37    let string1 = String::from("Hello, World!");
38    let boxed1 = Box::new(42);
39
40    track_var!(vec1);
41    track_var!(vec2);
42    track_var!(string1);
43    track_var!(boxed1);
44
45    // Create some temporary objects
46    for i in 0..10 {
47        let temp = vec![i; i];
48        track_var!(temp);
49    }
50
51    // Get all allocations
52    let tracker = get_global_tracker();
53    let _allocations = match tracker.get_active_allocations() {
54        Ok(allocs) => allocs,
55        Err(e) => {
56            tracing::info!("Error getting allocations: {}", e);
57            Vec::new()
58        }
59    };
60
61    tracing::info!("Enhanced Memory Analysis Summary:");
62    tracing::info!("--------------------------------");
63    tracing::info!("Total active allocations: {}", _allocations.len());
64
65    // Keep variables alive until the end
66    tracing::info!("Vec1 length: {}", vec1.len());
67    tracing::info!("Vec2 length: {}", vec2.len());
68    tracing::info!("String1 length: {}", string1.len());
69    tracing::info!("Boxed1 value: {}", *boxed1);
70
71    Ok(())
72}
73
74fn _test_enhanced_memory_analysis() {
75    // Create some test allocations
76    let vec1 = vec![1, 2, 3, 4, 5];
77    let vec2 = vec![6, 7, 8, 9, 10];
78    let string1 = String::from("Hello, World!");
79    let boxed1 = Box::new(42);
80
81    track_var!(vec1);
82    track_var!(vec2);
83    track_var!(string1);
84    track_var!(boxed1);
85
86    // Create some temporary objects
87    for i in 0..10 {
88        let temp = vec![i; i];
89        track_var!(temp);
90    }
91
92    // Get all allocations
93    let tracker = get_global_tracker();
94    let _allocations = match tracker.get_active_allocations() {
95        Ok(allocs) => allocs,
96        Err(e) => {
97            tracing::info!("Error getting allocations: {}", e);
98            Vec::new()
99        }
100    };
101
102    // Run enhanced analysis
103    let report = crate::analysis::analyze_memory_with_enhanced_features()
104        .unwrap_or_else(|e| format!("Error: {e}"));
105
106    // Print summary
107    tracing::info!("Enhanced Memory Analysis Summary:");
108    tracing::info!("--------------------------------");
109    tracing::info!("Report: {}", report);
110
111    // Keep variables alive until the end
112    tracing::info!("Vec1 length: {}", vec1.len());
113    tracing::info!("Vec2 length: {}", vec2.len());
114    tracing::info!("String1 length: {}", string1.len());
115    tracing::info!("Boxed1 value: {}", *boxed1);
116}
117
118#[cfg(test)]
119mod tests {
120    use super::*;
121    use clap::{Arg, Command};
122
123    fn create_test_matches(output: Option<&str>) -> ArgMatches {
124        let cmd = Command::new("test").arg(
125            Arg::new("output")
126                .short('o')
127                .long("output")
128                .value_name("FILE")
129                .help("Output file path")
130                .default_value("enhanced_memory_test"),
131        );
132
133        if let Some(output_val) = output {
134            cmd.try_get_matches_from(vec!["test", "--output", output_val])
135                .unwrap()
136        } else {
137            cmd.try_get_matches_from(vec!["test"]).unwrap()
138        }
139    }
140
141    #[test]
142    fn test_run_test_with_default_output() {
143        let matches = create_test_matches(None);
144
145        // Test that we can extract the output path correctly
146        let output_path = matches
147            .get_one::<String>("output")
148            .map(|s| s.as_str())
149            .unwrap_or("enhanced_memory_test");
150
151        assert_eq!(output_path, "enhanced_memory_test");
152    }
153
154    #[test]
155    fn test_run_test_with_custom_output() {
156        let matches = create_test_matches(Some("custom_test_output"));
157
158        let output_path = matches
159            .get_one::<String>("output")
160            .map(|s| s.as_str())
161            .unwrap_or("enhanced_memory_test");
162
163        assert_eq!(output_path, "custom_test_output");
164    }
165
166    #[test]
167    fn test_run_enhanced_memory_test_function_exists() {
168        // Test that the function exists and has the correct signature
169        let _f: fn() -> Result<(), Box<dyn std::error::Error>> = run_enhanced_memory_test;
170
171        // Just verify the function signature is correct
172        // assert!(true); // Removed redundant assertion
173    }
174
175    #[test]
176    fn test_run_test_function_signature() {
177        // Test that run_test has the correct signature
178        let _f: fn(&ArgMatches) -> Result<(), Box<dyn std::error::Error>> = run_test;
179        // assert!(true); // Removed redundant assertion
180    }
181
182    #[test]
183    fn test_private_test_function_exists() {
184        // Test that the private test function exists
185        let _f: fn() = _test_enhanced_memory_analysis;
186
187        // assert!(true); // Removed redundant assertion
188    }
189
190    #[test]
191    fn test_argument_parsing() {
192        // Test various argument combinations
193        let test_cases = vec![
194            ("default", None, "enhanced_memory_test"),
195            ("custom", Some("my_output"), "my_output"),
196            ("path", Some("/tmp/test_output"), "/tmp/test_output"),
197        ];
198
199        for (name, input, expected) in test_cases {
200            let matches = create_test_matches(input);
201            let output_path = matches
202                .get_one::<String>("output")
203                .map(|s| s.as_str())
204                .unwrap_or("enhanced_memory_test");
205
206            assert_eq!(output_path, expected, "Test case '{name}' failed");
207        }
208    }
209
210    // Test help generation doesn't panic
211
212    // assert!(true); // Removed redundant assertion
213
214    #[test]
215    fn test_output_path_extraction_logic() {
216        // Test the core logic used in run_test
217        let test_cases = vec![
218            (Some("test_output"), "test_output"),
219            (None, "enhanced_memory_test"),
220        ];
221
222        for (input, expected) in test_cases {
223            let result = input.unwrap_or("enhanced_memory_test");
224
225            assert_eq!(result, expected);
226        }
227    }
228}