ftt/
lib.rs

1// Copyright 2025 Clivern. All rights reserved.
2// Use of this source code is governed by the MIT
3// license that can be found in the LICENSE file.
4
5#[macro_export]
6macro_rules! timed {
7    ($name:expr, $code:block) => {{
8        let start = std::time::Instant::now();
9        let result = $code;
10        let elapsed = start.elapsed();
11        log::info!("{} took {:?}", $name, elapsed);
12        result
13    }};
14}
15
16#[cfg(test)]
17mod tests {
18    use crate::timed;
19    use std::thread;
20    use std::time::Duration;
21
22    #[test]
23    fn test_timed_macro_returns_correct_value() {
24        let result = timed!("test addition", {
25            let x = 5 + 3;
26            x
27        });
28        assert_eq!(result, 8);
29    }
30
31    #[test]
32    fn test_timed_macro_with_complex_computation() {
33        let result = timed!("fibonacci calculation", {
34            fn fibonacci(n: u32) -> u32 {
35                match n {
36                    0 => 0,
37                    1 => 1,
38                    _ => fibonacci(n - 1) + fibonacci(n - 2),
39                }
40            }
41            fibonacci(10)
42        });
43        assert_eq!(result, 55);
44    }
45
46    #[test]
47    fn test_timed_macro_with_side_effects() {
48        let mut counter = 0;
49        let result = timed!("increment counter", {
50            counter += 1;
51            counter
52        });
53        assert_eq!(result, 1);
54        assert_eq!(counter, 1);
55    }
56
57    #[test]
58    fn test_timed_macro_with_string_operations() {
59        let result = timed!("string concatenation", {
60            let mut s = String::new();
61            for i in 0..100 {
62                s.push_str(&i.to_string());
63            }
64            s.len()
65        });
66        assert_eq!(result, 190); // Sum of digits from 0-99
67    }
68
69    #[test]
70    fn test_timed_macro_with_vector_operations() {
71        let result = timed!("vector operations", {
72            let mut vec = Vec::new();
73            for i in 0..1000 {
74                vec.push(i * i);
75            }
76            vec.iter().sum::<i32>()
77        });
78        assert_eq!(result, 332833500); // Sum of squares from 0 to 999
79    }
80
81    #[test]
82    fn test_timed_macro_measurement_accuracy() {
83        let duration = timed!("sleep test", {
84            thread::sleep(Duration::from_millis(10));
85        });
86
87        // The macro should capture the elapsed time
88        // We can't directly test the logged output, but we can verify
89        // that the macro executes without panicking and returns the expected value
90        assert!(duration == ()); // The block returns unit type
91    }
92
93    #[test]
94    fn test_timed_macro_with_error_handling() {
95        let result = timed!("error handling test", {
96            match "42".parse::<i32>() {
97                Ok(n) => n * 2,
98                Err(_) => -1,
99            }
100        });
101        assert_eq!(result, 84);
102    }
103
104    #[test]
105    fn test_timed_macro_with_nested_calls() {
106        let result = timed!("nested timing", {
107            let inner = timed!("inner operation", { 5 * 5 });
108            inner + 10
109        });
110        assert_eq!(result, 35);
111    }
112
113    #[test]
114    fn test_timed_macro_with_different_data_types() {
115        // Test with boolean
116        let bool_result = timed!("boolean operation", { true && false });
117        assert_eq!(bool_result, false);
118
119        // Test with Option
120        let option_result = timed!("option operation", { Some(42).map(|x| x * 2) });
121        assert_eq!(option_result, Some(84));
122
123        // Test with Result
124        let result_result =
125            timed!("result operation", { Ok::<i32, &str>(10).map(|x| x * 3) });
126        assert_eq!(result_result, Ok(30));
127    }
128
129    #[test]
130    fn test_timed_macro_with_closure() {
131        let result = timed!("closure test", {
132            let closure = |x| x * x;
133            (0..10).map(closure).sum::<i32>()
134        });
135        assert_eq!(result, 285); // Sum of squares from 0 to 9
136    }
137
138    #[test]
139    fn test_timed_macro_performance_characteristics() {
140        // Test that timing overhead is minimal
141        let start = std::time::Instant::now();
142        let result = timed!("minimal operation", { 1 + 1 });
143        let total_time = start.elapsed();
144
145        assert_eq!(result, 2);
146        // The total time should be reasonable (less than 1ms for simple operations)
147        assert!(total_time < Duration::from_millis(1));
148    }
149
150    #[test]
151    fn test_timed_macro_with_large_data_processing() {
152        let result = timed!("large data processing", {
153            let data: Vec<i32> = (0..10000).collect();
154            data.iter().filter(|&&x| x % 2 == 0).count()
155        });
156        assert_eq!(result, 5000);
157    }
158
159    #[test]
160    fn test_logging_levels_work_correctly() {
161        // Test that the macro works with different logging levels
162        // The actual log level filtering is handled by the logger implementation
163        let result = timed!("debug level test", {
164            log::debug!("This is a debug message");
165            log::info!("This is an info message");
166            log::warn!("This is a warning message");
167            42
168        });
169
170        assert_eq!(result, 42);
171    }
172
173    #[test]
174    fn test_multiple_timed_operations() {
175        let results = timed!("multiple operations", {
176            let op1 = timed!("operation 1", { 1 + 1 });
177            let op2 = timed!("operation 2", { 2 * 2 });
178            let op3 = timed!("operation 3", { 3 * 3 });
179            (op1, op2, op3)
180        });
181
182        assert_eq!(results, (2, 4, 9));
183    }
184
185    #[test]
186    fn test_timed_macro_with_async_simulation() {
187        let result = timed!("async simulation", {
188            // Simulate some async-like behavior with threads
189            let handle = thread::spawn(|| {
190                thread::sleep(Duration::from_millis(5));
191                42
192            });
193            handle.join().unwrap()
194        });
195
196        assert_eq!(result, 42);
197    }
198}