Publish harness and TUI open-source
initial sync from the monorepo
This commit is contained in:
commit
c68e39f604
2734 changed files with 1437016 additions and 0 deletions
109
crates/common/xai-circuit-breaker/src/window_tests.rs
Normal file
109
crates/common/xai-circuit-breaker/src/window_tests.rs
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
//! Tests for [`crate::window::SlidingWindow`].
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn push_evict_and_error_rate() {
|
||||
let mut w = SlidingWindow::new();
|
||||
let base = Instant::now();
|
||||
w.push(true, base);
|
||||
w.push(false, base + Duration::from_millis(10));
|
||||
w.push(true, base + Duration::from_millis(20));
|
||||
|
||||
assert_eq!(w.sample_count(), 3);
|
||||
assert!((w.error_rate() - (2.0 / 3.0)).abs() < 1e-9);
|
||||
|
||||
// Evict everything older than 5ms relative to base + 20ms.
|
||||
w.evict(Duration::from_millis(5), base + Duration::from_millis(20));
|
||||
assert_eq!(w.sample_count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_error_rate_is_zero() {
|
||||
let w = SlidingWindow::new();
|
||||
assert_eq!(w.error_rate(), 0.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn push_respects_max_entries_cap() {
|
||||
let mut w = SlidingWindow::new();
|
||||
let base = Instant::now();
|
||||
for i in 0..(MAX_WINDOW_ENTRIES + 5) {
|
||||
w.push(true, base + Duration::from_nanos(i as u64));
|
||||
}
|
||||
assert_eq!(w.sample_count(), MAX_WINDOW_ENTRIES);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn failure_count_stays_consistent_under_cap_eviction() {
|
||||
// Push enough failures to overflow the cap and confirm
|
||||
// error_rate() (which is O(1) via the cached failures
|
||||
// counter) still reads 1.0 after entries are dropped from
|
||||
// the front.
|
||||
let mut w = SlidingWindow::new();
|
||||
let base = Instant::now();
|
||||
for i in 0..(MAX_WINDOW_ENTRIES + 100) {
|
||||
w.push(true, base + Duration::from_nanos(i as u64));
|
||||
}
|
||||
assert_eq!(w.sample_count(), MAX_WINDOW_ENTRIES);
|
||||
assert!((w.error_rate() - 1.0).abs() < f64::EPSILON);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn failure_count_decrements_on_time_eviction() {
|
||||
let mut w = SlidingWindow::new();
|
||||
let base = Instant::now();
|
||||
w.push(true, base);
|
||||
w.push(false, base + Duration::from_millis(10));
|
||||
w.push(true, base + Duration::from_millis(20));
|
||||
assert!((w.error_rate() - (2.0 / 3.0)).abs() < 1e-9);
|
||||
|
||||
// Evict the first two entries (the leading true and false).
|
||||
// Remaining is one true → error_rate = 1.0.
|
||||
w.evict(Duration::from_millis(5), base + Duration::from_millis(20));
|
||||
assert_eq!(w.sample_count(), 1);
|
||||
assert!((w.error_rate() - 1.0).abs() < f64::EPSILON);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clear_resets_failure_count() {
|
||||
let mut w = SlidingWindow::new();
|
||||
let base = Instant::now();
|
||||
w.push(true, base);
|
||||
w.push(true, base + Duration::from_millis(1));
|
||||
w.clear();
|
||||
// After clear, pushing one success must read error_rate 0.0;
|
||||
// a stale failures counter would read 2/1 instead.
|
||||
w.push(false, base + Duration::from_millis(2));
|
||||
assert!(w.error_rate().abs() < f64::EPSILON);
|
||||
}
|
||||
|
||||
/// Push past the cap, then advance time past the window duration and
|
||||
/// push more — eviction must continue to read the correct cached
|
||||
/// failures count even when the deque is at the cap.
|
||||
#[test]
|
||||
fn cap_then_time_eviction_keeps_failure_count_consistent() {
|
||||
let mut w = SlidingWindow::new();
|
||||
let base = Instant::now();
|
||||
|
||||
// Fill the deque to the cap with failures.
|
||||
for i in 0..MAX_WINDOW_ENTRIES {
|
||||
w.push(true, base + Duration::from_micros(i as u64));
|
||||
}
|
||||
assert_eq!(w.sample_count(), MAX_WINDOW_ENTRIES);
|
||||
assert!((w.error_rate() - 1.0).abs() < f64::EPSILON);
|
||||
|
||||
// Move past the window and evict — every existing sample falls
|
||||
// out, cached failures counter must reach zero.
|
||||
let way_later = base + Duration::from_secs(3600);
|
||||
w.evict(Duration::from_secs(1), way_later);
|
||||
assert_eq!(w.sample_count(), 0);
|
||||
assert!(w.error_rate().abs() < f64::EPSILON);
|
||||
|
||||
// New samples after a full eviction must continue to read
|
||||
// consistently (regression on a stale `failures` field).
|
||||
w.push(false, way_later);
|
||||
w.push(true, way_later + Duration::from_micros(1));
|
||||
assert_eq!(w.sample_count(), 2);
|
||||
assert!((w.error_rate() - 0.5).abs() < f64::EPSILON);
|
||||
}
|
||||
Loading…
Reference in a new issue