|
8 | 8 | use std::time::Duration; |
9 | 9 |
|
10 | 10 | use asap_control_core::intent_algebra::{ |
11 | | - AggIntent, ArithOp, BinaryOpKind, QueryExpr, Source, VectorMatch, VectorMatchKind, |
| 11 | + AggIntent, ArithOp, BinaryOpKind, CompareOp, GroupSide, QueryExpr, Source, VectorGrouping, |
| 12 | + VectorMatch, VectorMatchKind, |
12 | 13 | }; |
13 | 14 | use asap_control_core::types::AccuracyTarget; |
14 | 15 | use asap_control_lower::lower_promql; |
@@ -97,6 +98,119 @@ fn q20_div_two_rates() { |
97 | 98 | ); |
98 | 99 | } |
99 | 100 |
|
| 101 | +// comparison ops — filter semantics; each op between two instant vectors |
| 102 | +#[test] |
| 103 | +fn q_gt_comparison() { |
| 104 | + assert_eq!( |
| 105 | + lower("http_requests_total > http_errors_total"), |
| 106 | + QueryExpr::BinaryOp { |
| 107 | + op: BinaryOpKind::Compare(CompareOp::Gt), |
| 108 | + lhs: Box::new(scan("http_requests_total", &[])), |
| 109 | + rhs: Box::new(scan("http_errors_total", &[])), |
| 110 | + vector_match: None, |
| 111 | + } |
| 112 | + ); |
| 113 | +} |
| 114 | + |
| 115 | +#[test] |
| 116 | +fn q_lt_comparison() { |
| 117 | + assert_eq!( |
| 118 | + lower("http_requests_total < http_errors_total"), |
| 119 | + QueryExpr::BinaryOp { |
| 120 | + op: BinaryOpKind::Compare(CompareOp::Lt), |
| 121 | + lhs: Box::new(scan("http_requests_total", &[])), |
| 122 | + rhs: Box::new(scan("http_errors_total", &[])), |
| 123 | + vector_match: None, |
| 124 | + } |
| 125 | + ); |
| 126 | +} |
| 127 | + |
| 128 | +#[test] |
| 129 | +fn q_ge_comparison() { |
| 130 | + assert_eq!( |
| 131 | + lower("http_requests_total >= http_errors_total"), |
| 132 | + QueryExpr::BinaryOp { |
| 133 | + op: BinaryOpKind::Compare(CompareOp::Ge), |
| 134 | + lhs: Box::new(scan("http_requests_total", &[])), |
| 135 | + rhs: Box::new(scan("http_errors_total", &[])), |
| 136 | + vector_match: None, |
| 137 | + } |
| 138 | + ); |
| 139 | +} |
| 140 | + |
| 141 | +#[test] |
| 142 | +fn q_le_comparison() { |
| 143 | + assert_eq!( |
| 144 | + lower("http_requests_total <= http_errors_total"), |
| 145 | + QueryExpr::BinaryOp { |
| 146 | + op: BinaryOpKind::Compare(CompareOp::Le), |
| 147 | + lhs: Box::new(scan("http_requests_total", &[])), |
| 148 | + rhs: Box::new(scan("http_errors_total", &[])), |
| 149 | + vector_match: None, |
| 150 | + } |
| 151 | + ); |
| 152 | +} |
| 153 | + |
| 154 | +// ignoring(job) — match on all labels except job; labels are strings, not column ids |
| 155 | +#[test] |
| 156 | +fn q_add_with_ignoring() { |
| 157 | + assert_eq!( |
| 158 | + lower("http_requests_total + ignoring(job) http_errors_total"), |
| 159 | + QueryExpr::BinaryOp { |
| 160 | + op: BinaryOpKind::Arith(ArithOp::Add), |
| 161 | + lhs: Box::new(scan("http_requests_total", &[])), |
| 162 | + rhs: Box::new(scan("http_errors_total", &[])), |
| 163 | + vector_match: Some(VectorMatch { |
| 164 | + kind: VectorMatchKind::Ignoring, |
| 165 | + labels: vec!["job".into()], |
| 166 | + grouping: None, |
| 167 | + }), |
| 168 | + } |
| 169 | + ); |
| 170 | +} |
| 171 | + |
| 172 | +// group_left — many-to-one: left side has higher cardinality |
| 173 | +#[test] |
| 174 | +fn q_mul_group_left() { |
| 175 | + assert_eq!( |
| 176 | + lower("http_requests_total * on(job) group_left() node_info"), |
| 177 | + QueryExpr::BinaryOp { |
| 178 | + op: BinaryOpKind::Arith(ArithOp::Mul), |
| 179 | + lhs: Box::new(scan("http_requests_total", &[])), |
| 180 | + rhs: Box::new(scan("node_info", &[])), |
| 181 | + vector_match: Some(VectorMatch { |
| 182 | + kind: VectorMatchKind::On, |
| 183 | + labels: vec!["job".into()], |
| 184 | + grouping: Some(VectorGrouping { |
| 185 | + side: GroupSide::Left, |
| 186 | + labels: vec![], |
| 187 | + }), |
| 188 | + }), |
| 189 | + } |
| 190 | + ); |
| 191 | +} |
| 192 | + |
| 193 | +// group_right — one-to-many: right side has higher cardinality |
| 194 | +#[test] |
| 195 | +fn q_mul_group_right() { |
| 196 | + assert_eq!( |
| 197 | + lower("node_info * on(job) group_right() http_requests_total"), |
| 198 | + QueryExpr::BinaryOp { |
| 199 | + op: BinaryOpKind::Arith(ArithOp::Mul), |
| 200 | + lhs: Box::new(scan("node_info", &[])), |
| 201 | + rhs: Box::new(scan("http_requests_total", &[])), |
| 202 | + vector_match: Some(VectorMatch { |
| 203 | + kind: VectorMatchKind::On, |
| 204 | + labels: vec!["job".into()], |
| 205 | + grouping: Some(VectorGrouping { |
| 206 | + side: GroupSide::Right, |
| 207 | + labels: vec![], |
| 208 | + }), |
| 209 | + }), |
| 210 | + } |
| 211 | + ); |
| 212 | +} |
| 213 | + |
100 | 214 | // #21 — divide two sum-by-job aggregates over different metrics |
101 | 215 | // each side: Aggregate{Sum, by=[2]} over Scan([ts, value, job]) |
102 | 216 | #[test] |
|
0 commit comments