Skip to main content

memscope_rs/query/
presets.rs

1//! Query Presets - Predefined common queries
2//!
3//! This module provides preset queries for common use cases,
4//! making it easy to get standard information without writing
5//! custom queries.
6
7use super::types::Query;
8
9/// Preset query factory
10pub struct QueryPresets;
11
12impl QueryPresets {
13    /// Create a query to find top allocations by size
14    pub fn top_allocations_by_size(limit: usize) -> Query {
15        Query::TopAllocationsBySize { limit }
16    }
17
18    /// Create a query to find top allocations by count
19    pub fn top_allocations_by_count(limit: usize) -> Query {
20        Query::TopAllocationsByCount { limit }
21    }
22
23    /// Create a query to find memory leaks
24    pub fn memory_leaks(min_age_ms: u64) -> Query {
25        Query::MemoryLeaks { min_age_ms }
26    }
27
28    /// Create a query to find large allocations
29    pub fn large_allocations(min_size: usize) -> Query {
30        Query::LargeAllocations { min_size }
31    }
32
33    /// Create a query to get thread memory statistics
34    pub fn thread_memory_stats(thread_id: u64) -> Query {
35        Query::ThreadMemoryStats { thread_id }
36    }
37
38    /// Create a query to get scope memory statistics
39    pub fn scope_memory_stats(scope_name: String) -> Query {
40        Query::ScopeMemoryStats { scope_name }
41    }
42
43    /// Create a query to get type memory statistics
44    pub fn type_memory_stats(type_name: String) -> Query {
45        Query::TypeMemoryStats { type_name }
46    }
47
48    /// Create a query to get system-wide summary
49    pub fn system_summary() -> Query {
50        Query::Summary
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57
58    /// Objective: Verify that top_allocations_by_size creates correct query with limit.
59    /// Invariants: Query variant must be TopAllocationsBySize with exact limit value.
60    #[test]
61    fn test_top_allocations_by_size() {
62        let query = QueryPresets::top_allocations_by_size(10);
63        assert!(
64            matches!(query, Query::TopAllocationsBySize { limit: 10 }),
65            "Query should be TopAllocationsBySize with limit 10"
66        );
67    }
68
69    /// Objective: Verify that top_allocations_by_count creates correct query.
70    /// Invariants: Query variant must be TopAllocationsByCount with exact limit value.
71    #[test]
72    fn test_top_allocations_by_count() {
73        let query = QueryPresets::top_allocations_by_count(25);
74        assert!(
75            matches!(query, Query::TopAllocationsByCount { limit: 25 }),
76            "Query should be TopAllocationsByCount with limit 25"
77        );
78    }
79
80    /// Objective: Verify that memory_leaks creates correct query with age threshold.
81    /// Invariants: Query variant must be MemoryLeaks with exact min_age_ms value.
82    #[test]
83    fn test_memory_leaks() {
84        let query = QueryPresets::memory_leaks(1000);
85        assert!(
86            matches!(query, Query::MemoryLeaks { min_age_ms: 1000 }),
87            "Query should be MemoryLeaks with min_age_ms 1000"
88        );
89    }
90
91    /// Objective: Verify that large_allocations creates correct query with size threshold.
92    /// Invariants: Query variant must be LargeAllocations with exact min_size value.
93    #[test]
94    fn test_large_allocations() {
95        let query = QueryPresets::large_allocations(1024);
96        assert!(
97            matches!(query, Query::LargeAllocations { min_size: 1024 }),
98            "Query should be LargeAllocations with min_size 1024"
99        );
100    }
101
102    /// Objective: Verify that thread_memory_stats creates correct query with thread ID.
103    /// Invariants: Query variant must be ThreadMemoryStats with exact thread_id value.
104    #[test]
105    fn test_thread_memory_stats() {
106        let query = QueryPresets::thread_memory_stats(42);
107        assert!(
108            matches!(query, Query::ThreadMemoryStats { thread_id: 42 }),
109            "Query should be ThreadMemoryStats with thread_id 42"
110        );
111    }
112
113    /// Objective: Verify that scope_memory_stats creates correct query with scope name.
114    /// Invariants: Query variant must be ScopeMemoryStats with exact scope_name value.
115    #[test]
116    fn test_scope_memory_stats() {
117        let query = QueryPresets::scope_memory_stats("main".to_string());
118        match query {
119            Query::ScopeMemoryStats { scope_name } => {
120                assert_eq!(scope_name, "main", "Scope name should be 'main'");
121            }
122            _ => panic!("Expected ScopeMemoryStats query"),
123        }
124    }
125
126    /// Objective: Verify that type_memory_stats creates correct query with type name.
127    /// Invariants: Query variant must be TypeMemoryStats with exact type_name value.
128    #[test]
129    fn test_type_memory_stats() {
130        let query = QueryPresets::type_memory_stats("Vec<u8>".to_string());
131        match query {
132            Query::TypeMemoryStats { type_name } => {
133                assert_eq!(type_name, "Vec<u8>", "Type name should be 'Vec<u8>'");
134            }
135            _ => panic!("Expected TypeMemoryStats query"),
136        }
137    }
138
139    /// Objective: Verify that system_summary creates correct summary query.
140    /// Invariants: Query variant must be Summary.
141    #[test]
142    fn test_system_summary() {
143        let query = QueryPresets::system_summary();
144        assert!(
145            matches!(query, Query::Summary),
146            "Query should be Summary variant"
147        );
148    }
149
150    /// Objective: Verify edge case with zero limit for allocations query.
151    /// Invariants: Query should still be created with zero limit.
152    #[test]
153    fn test_top_allocations_zero_limit() {
154        let query = QueryPresets::top_allocations_by_size(0);
155        assert!(
156            matches!(query, Query::TopAllocationsBySize { limit: 0 }),
157            "Query should accept zero limit"
158        );
159    }
160
161    /// Objective: Verify edge case with large thread ID.
162    /// Invariants: Query should handle large u64 values correctly.
163    #[test]
164    fn test_thread_memory_stats_large_id() {
165        let large_id = u64::MAX;
166        let query = QueryPresets::thread_memory_stats(large_id);
167        assert!(
168            matches!(query, Query::ThreadMemoryStats { thread_id } if thread_id == large_id),
169            "Query should handle max u64 thread ID"
170        );
171    }
172}