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:
@@ -246,21 +246,16 @@ mod tests {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let mut psar = Psar::classic();
|
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)
|
.batch(&candles)
|
||||||
.into_iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter_map(|(i, sar)| {
|
.all(|(i, sar)| sar.is_none_or(|s| s <= candles[i].low + 1e-9));
|
||||||
sar.and_then(|s| {
|
assert!(ok, "SAR sat above a candle's low on a pure uptrend");
|
||||||
if s > candles[i].low + 1e-9 {
|
|
||||||
Some((i, s, candles[i].low))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
assert!(violations.is_empty(), "SAR above low: {violations:?}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -274,22 +269,15 @@ mod tests {
|
|||||||
.collect();
|
.collect();
|
||||||
let mut psar = Psar::classic();
|
let mut psar = Psar::classic();
|
||||||
// After the trend establishes downward, SAR should sit above highs.
|
// 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)
|
.batch(&candles)
|
||||||
.into_iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.skip(5)
|
.skip(5)
|
||||||
.filter_map(|(i, sar)| {
|
.all(|(i, sar)| sar.is_none_or(|s| s >= candles[i].high - 1e-9));
|
||||||
sar.and_then(|s| {
|
assert!(ok, "SAR sat below a candle's high on a pure downtrend");
|
||||||
if s < candles[i].high - 1e-9 {
|
|
||||||
Some((i, s, candles[i].high))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
assert!(violations.is_empty(), "SAR below high: {violations:?}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user