use super::*;
#[test]
fn automatic_refresh_covers_first_use_threshold_and_small_idle_changes() {
assert!(StatisticsMaintenance::default().due(true, 0, 1));
let mut state = StatisticsMaintenance {
changes: 1,
dirty_since_ms: 100,
analyzed_rows: Some(100),
statistics_format: 1,
..StatisticsMaintenance::default()
};
assert!(!state.due(false, 101, 1));
assert!(state.due(false, 60_100, 1));
state.changes = 60;
assert!(state.due(false, 101, 1));
}
#[test]
fn a_session_keeps_only_the_changes_that_decide_nothing() {
let clean = StatisticsMaintenance {
analyzed_rows: Some(1_000),
statistics_format: 1,
..StatisticsMaintenance::default()
};
assert!(!clean.defers(1, 100));
let mut state = clean.clone();
state.record_changes([1; 16], 1, Some(1_000), 100).unwrap();
assert!(state.defers(1, 200));
assert!(state.defers(36, 200));
assert!(!state.defers(37, 200));
state.changes = 140;
assert!(state.defers(9, 200));
assert!(!state.defers(10, 200));
state.changes = 150;
assert!(state.defers(1_000_000, 200));
state.changes = 1;
assert!(state.defers(1_000_000, 60_100));
assert!(!state.defers(37, 60_099));
let mut small = StatisticsMaintenance {
changes: 1,
dirty_since_ms: 100,
analyzed_rows: Some(10),
statistics_format: 1,
..StatisticsMaintenance::default()
};
assert!(small.defers(15, 200));
assert!(!small.defers(16, 200));
small.analyzed_rows = Some(0);
assert!(small.defers(1_000, 200));
small.analyzed_rows = None;
assert!(small.defers(1_000, 200));
}
#[test]
fn an_analysis_covers_the_commits_up_to_its_sample() {
let mut state = StatisticsMaintenance::default();
assert!(!state.covers(Some(1)));
state.analyzed([1; 16], 10, 1, Some(40)).unwrap();
assert!(state.covers(Some(40)));
assert!(state.covers(Some(7)));
assert!(!state.covers(Some(41)));
assert!(!state.covers(None));
let json = serde_json::to_string(&state).unwrap();
assert!(json.contains(r#""analyzed_at":40"#));
state.record_changes([1; 16], 3, Some(10), 100).unwrap();
assert!(state.covers(Some(40)));
state.analyzed([1; 16], 13, 1, None).unwrap();
assert!(!state.covers(Some(40)));
assert!(!serde_json::to_string(&state)
.unwrap()
.contains("analyzed_at"));
let old: StatisticsMaintenance =
serde_json::from_str(r#"{"generation":4,"changes":0,"analyzed_rows":120}"#).unwrap();
assert!(!old.covers(Some(0)));
let before = StatisticsMaintenance {
object_id: Some([1; 16]),
analyzed_rows: Some(10),
statistics_format: 1,
..StatisticsMaintenance::default()
};
let mut analysis = before.clone();
analysis.analyzed([1; 16], 12, 1, Some(9)).unwrap();
let mut written = before.clone();
written.record_changes([1; 16], 2, Some(10), 100).unwrap();
let merged = StatisticsMaintenance::merge(&before, &analysis, &written)
.unwrap()
.unwrap();
assert!(merged.covers(Some(9)));
let merged = StatisticsMaintenance::merge(&before, &written, &analysis)
.unwrap()
.unwrap();
assert!(merged.covers(Some(9)));
}
#[test]
fn legacy_statistics_are_refreshed_without_waiting_for_another_write() {
let old: StatisticsMaintenance =
serde_json::from_str(r#"{"generation":4,"changes":0,"analyzed_rows":120}"#).unwrap();
assert!(old.due(false, 0, 1));
}
#[test]
fn merged_changes_reject_overflow_and_incompatible_object_replacements() {
let before = StatisticsMaintenance {
object_id: Some([1; 16]),
..StatisticsMaintenance::default()
};
let mut after = before.clone();
after.record_changes([1; 16], 1, Some(0), 100).unwrap();
for field in ["changes", "generation"] {
let mut current = before.clone();
if field == "changes" {
current.changes = u64::MAX;
} else {
current.generation = u64::MAX;
}
assert!(StatisticsMaintenance::merge(&before, &after, ¤t).is_err());
}
let mut replacement = before.clone();
replacement.object_id = Some([2; 16]);
assert!(StatisticsMaintenance::merge(&before, &after, &replacement)
.unwrap()
.is_none());
assert!(StatisticsMaintenance::merge(&before, &replacement, &before)
.unwrap()
.is_none());
}