1use super::{FeatureCategory, FeatureTest};
14
15pub const TESTS: &[FeatureTest] = &[
16 FeatureTest {
18 name: "window_function_row_number",
19 covers: &["window_function_call", "over_clause"],
20 code: "function test() { return row_number() OVER (ORDER BY x); }",
21 function: "test",
22 category: FeatureCategory::Domain,
23 requires_data: false,
24 },
25 FeatureTest {
26 name: "window_function_partition_by",
27 covers: &["window_function_call", "over_clause", "partition_clause"],
28 code: "function test() { return sum(value) OVER (PARTITION BY category ORDER BY date); }",
29 function: "test",
30 category: FeatureCategory::Domain,
31 requires_data: false,
32 },
33 FeatureTest {
34 name: "window_function_rank",
35 covers: &["window_function_call", "over_clause"],
36 code: "function test() { return rank() OVER (PARTITION BY group ORDER BY score DESC); }",
37 function: "test",
38 category: FeatureCategory::Domain,
39 requires_data: false,
40 },
41 FeatureTest {
43 name: "time_window_last_days",
44 covers: &["time_window", "last_window"],
45 code: r#"function test() { return last(5, "days"); }"#,
46 function: "test",
47 category: FeatureCategory::Domain,
48 requires_data: false,
49 },
50 FeatureTest {
51 name: "time_window_last_keyword",
52 covers: &["last_window", "duration"],
53 code: "function test() { return last 1 year; }",
54 function: "test",
55 category: FeatureCategory::Domain,
56 requires_data: false,
57 },
58 FeatureTest {
59 name: "time_window_last_bars",
60 covers: &["time_window", "last_window"],
61 code: r#"function test() { return last(100, "bars"); }"#,
62 function: "test",
63 category: FeatureCategory::Domain,
64 requires_data: false,
65 },
66 FeatureTest {
68 name: "between_window_dates",
69 covers: &["between_window", "datetime_literal"],
70 code: r#"function test() { return between @"2020-01-01" and @"2021-01-01"; }"#,
71 function: "test",
72 category: FeatureCategory::Domain,
73 requires_data: false,
74 },
75 FeatureTest {
76 name: "between_window_time_refs",
77 covers: &["between_window", "time_ref"],
78 code: "function test() { return between @today and @tomorrow; }",
79 function: "test",
80 category: FeatureCategory::Domain,
81 requires_data: false,
82 },
83 FeatureTest {
85 name: "timeframe_spec_5m",
86 covers: &["timeframe_spec", "timeframe", "data_ref"],
87 code: "function test() { return data(5m)[0]; }",
88 function: "test",
89 category: FeatureCategory::Domain,
90 requires_data: true,
91 },
92 FeatureTest {
93 name: "timeframe_spec_1h",
94 covers: &["timeframe_spec", "timeframe"],
95 code: "function test() { return data(1h)[0].close; }",
96 function: "test",
97 category: FeatureCategory::Domain,
98 requires_data: true,
99 },
100 FeatureTest {
101 name: "timeframe_spec_daily",
102 covers: &["timeframe_spec", "timeframe"],
103 code: "function test() { return data(1d)[-1]; }",
104 function: "test",
105 category: FeatureCategory::Domain,
106 requires_data: true,
107 },
108 FeatureTest {
110 name: "datetime_arithmetic_add_days",
111 covers: &["datetime_arithmetic", "datetime_expr", "duration"],
112 code: "function test() { return @today + 5d; }",
113 function: "test",
114 category: FeatureCategory::Domain,
115 requires_data: false,
116 },
117 FeatureTest {
118 name: "datetime_arithmetic_sub_hours",
119 covers: &["datetime_arithmetic", "datetime_expr", "duration"],
120 code: "function test() { return @now - 2h; }",
121 function: "test",
122 category: FeatureCategory::Domain,
123 requires_data: false,
124 },
125 FeatureTest {
126 name: "datetime_arithmetic_complex",
127 covers: &["datetime_arithmetic", "datetime_literal", "duration"],
128 code: r#"function test() { return @"2020-06-15" + 30d - 1w; }"#,
129 function: "test",
130 category: FeatureCategory::Domain,
131 requires_data: false,
132 },
133 FeatureTest {
135 name: "compound_duration_hm",
136 covers: &["compound_duration", "duration_unit"],
137 code: "function test() { return 5h30m; }",
138 function: "test",
139 category: FeatureCategory::Literal,
140 requires_data: false,
141 },
142 FeatureTest {
143 name: "compound_duration_dh",
144 covers: &["compound_duration", "duration_unit"],
145 code: "function test() { return 1d12h; }",
146 function: "test",
147 category: FeatureCategory::Literal,
148 requires_data: false,
149 },
150 FeatureTest {
151 name: "compound_duration_hms",
152 covers: &["compound_duration", "duration_unit"],
153 code: "function test() { return 2h30m45s; }",
154 function: "test",
155 category: FeatureCategory::Literal,
156 requires_data: false,
157 },
158 FeatureTest {
160 name: "window_frame_rows_between",
161 covers: &["window_frame_clause", "frame_bound"],
162 code: "function test() { return sum(x) OVER (ORDER BY y ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING); }",
163 function: "test",
164 category: FeatureCategory::Domain,
165 requires_data: false,
166 },
167 FeatureTest {
168 name: "window_frame_rows_unbounded",
169 covers: &["window_frame_clause", "frame_bound"],
170 code: "function test() { return sum(x) OVER (ORDER BY y ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW); }",
171 function: "test",
172 category: FeatureCategory::Domain,
173 requires_data: false,
174 },
175 FeatureTest {
176 name: "window_frame_range",
177 covers: &["window_frame_clause", "frame_bound"],
178 code: "function test() { return avg(price) OVER (ORDER BY date RANGE BETWEEN 7d PRECEDING AND CURRENT ROW); }",
179 function: "test",
180 category: FeatureCategory::Domain,
181 requires_data: false,
182 },
183 FeatureTest {
185 name: "session_window_30m",
186 covers: &["session_window", "duration"],
187 code: "function test() { return session(30m); }",
188 function: "test",
189 category: FeatureCategory::Domain,
190 requires_data: false,
191 },
192 FeatureTest {
193 name: "session_window_with_gap",
194 covers: &["session_window", "duration"],
195 code: "function test() { return session(5m, gap: 1m); }",
196 function: "test",
197 category: FeatureCategory::Domain,
198 requires_data: false,
199 },
200 FeatureTest {
201 name: "session_window_1h",
202 covers: &["session_window", "duration"],
203 code: "function test() { return session(1h); }",
204 function: "test",
205 category: FeatureCategory::Domain,
206 requires_data: false,
207 },
208];
209
210#[cfg(test)]
211mod tests {
212 use super::*;
213 use std::collections::BTreeSet;
214
215 #[test]
216 fn test_window_tests_defined() {
217 assert!(!TESTS.is_empty());
218 assert!(
220 TESTS.len() >= 10,
221 "Expected at least 10 window tests, got {}",
222 TESTS.len()
223 );
224 }
225
226 #[test]
227 fn test_window_tests_cover_main_rules() {
228 let all_rules: BTreeSet<_> = TESTS
229 .iter()
230 .flat_map(|t| t.covers.iter().copied())
231 .collect();
232
233 assert!(
235 all_rules.contains(&"window_function_call"),
236 "Missing window_function_call coverage"
237 );
238 assert!(
239 all_rules.contains(&"over_clause"),
240 "Missing over_clause coverage"
241 );
242 assert!(
243 all_rules.contains(&"time_window") || all_rules.contains(&"last_window"),
244 "Missing time window coverage"
245 );
246 assert!(
247 all_rules.contains(&"between_window"),
248 "Missing between_window coverage"
249 );
250 assert!(
251 all_rules.contains(&"datetime_arithmetic"),
252 "Missing datetime_arithmetic coverage"
253 );
254 assert!(
255 all_rules.contains(&"compound_duration"),
256 "Missing compound_duration coverage"
257 );
258 assert!(
259 all_rules.contains(&"window_frame_clause"),
260 "Missing window_frame_clause coverage"
261 );
262 assert!(
263 all_rules.contains(&"session_window"),
264 "Missing session_window coverage"
265 );
266 }
267}