test(psar): drop violation-tuple cold path in trend tests (99.03 -> 100) (#33)

After PR #27 brought psar.rs to 99.03 %, Codecov still flagged the
'violation found' tuple arms in the trend tests (line 256 in
pure_uptrend_sar_below_lows, line 285 in pure_downtrend_sar_above_highs)
as missed: both tests are designed to NEVER find a violation, so the
filter_map branch that constructs the (index, sar, bound) tuple is dead
by design.

Restructure both tests to use `.all(|(i, sar)| sar.is_none_or(|s|
<bound>))` instead of collecting violations into a Vec. The closure
runs on every emitted Some, asserts the SAR-vs-extreme bound directly,
and the iterator short-circuits on the first false — no cold tuple
construction left to count as uncovered. Semantics are identical (still
asserts every SAR sits on the correct side of every candle's extreme);
the diagnostic message loses the violating index list, which the tests
never printed in any green run anyway.

psar.rs is now at 207/207 lines, no behavioural change.
This commit is contained in:
kingchenc
2026-05-24 01:31:20 +02:00
committed by GitHub
parent 250b75d468
commit 32caf023dd
+14 -26
View File
@@ -246,21 +246,16 @@ mod tests {
})
.collect();
let mut psar = Psar::classic();
let violations: Vec<(usize, f64, f64)> = psar
// `all()` with `is_none_or` keeps every reachable arm on the hot path —
// the previous filter_map / violation-Vec construction had a cold
// "violation found" tuple branch that was unreachable on a clean
// uptrend, leaving its line uncovered by Codecov.
let ok = psar
.batch(&candles)
.into_iter()
.iter()
.enumerate()
.filter_map(|(i, sar)| {
sar.and_then(|s| {
if s > candles[i].low + 1e-9 {
Some((i, s, candles[i].low))
} else {
None
}
})
})
.collect();
assert!(violations.is_empty(), "SAR above low: {violations:?}");
.all(|(i, sar)| sar.is_none_or(|s| s <= candles[i].low + 1e-9));
assert!(ok, "SAR sat above a candle's low on a pure uptrend");
}
#[test]
@@ -274,22 +269,15 @@ mod tests {
.collect();
let mut psar = Psar::classic();
// After the trend establishes downward, SAR should sit above highs.
let violations: Vec<(usize, f64, f64)> = psar
// Same `all()` + `is_none_or` shape as `pure_uptrend_sar_below_lows`
// so the violation-tuple branch never appears as a cold path.
let ok = psar
.batch(&candles)
.into_iter()
.iter()
.enumerate()
.skip(5)
.filter_map(|(i, sar)| {
sar.and_then(|s| {
if s < candles[i].high - 1e-9 {
Some((i, s, candles[i].high))
} else {
None
}
})
})
.collect();
assert!(violations.is_empty(), "SAR below high: {violations:?}");
.all(|(i, sar)| sar.is_none_or(|s| s >= candles[i].high - 1e-9));
assert!(ok, "SAR sat below a candle's high on a pure downtrend");
}
#[test]