use super::*;
#[tokio::test]
async fn list_barks_reads_the_file_with_no_shepherd_anywhere_in_reach() {
let dir = tempfile::tempdir().unwrap();
let barks_path = dir.path().join("barks.jsonl");
let bark = shep_core::barks::Bark {
at_ms: 1,
rule: "restart-loop".to_string(),
subject: "web".to_string(),
message: "web restarted 5 times in 60s".to_string(),
sinks: Vec::new(),
};
std::fs::write(
&barks_path,
format!("{}\n", serde_json::to_string(&bark).unwrap()),
)
.unwrap();
let unreachable_socket = shep_client::testing::control_address(dir.path());
let whistle = whistle_at(unreachable_socket, barks_path);
let result = tokio::time::timeout(
TEST_TIMEOUT,
whistle.list_barks(Parameters(BarksParams { tail: None })),
)
.await
.expect("list_barks must return within the test timeout")
.expect("reading straight off disk must not fail");
assert_eq!(result.0.barks.len(), 1);
assert_eq!(result.0.barks[0].subject, "web");
}
fn bark_at(at_ms: u64) -> shep_core::barks::Bark {
shep_core::barks::Bark {
at_ms,
rule: "restart-loop".to_string(),
subject: "web".to_string(),
message: format!("web restarted {at_ms} times in 60s"),
sinks: Vec::new(),
}
}
fn write_barks(path: &Path, records: &[shep_core::barks::Bark]) {
let text: String = records
.iter()
.map(|bark| format!("{}\n", serde_json::to_string(bark).unwrap()))
.collect();
std::fs::write(path, text).unwrap();
}
#[tokio::test]
async fn list_barks_returns_the_newest_tail_asked_for_oldest_first() {
let dir = tempfile::tempdir().unwrap();
let barks_path = dir.path().join("barks.jsonl");
write_barks(&barks_path, &[bark_at(1), bark_at(2), bark_at(3)]);
let whistle = whistle_at(
shep_client::testing::control_address(dir.path()),
barks_path,
);
let result = tokio::time::timeout(
TEST_TIMEOUT,
whistle.list_barks(Parameters(BarksParams { tail: Some(2) })),
)
.await
.expect("list_barks must return within the test timeout")
.expect("reading the tail of the history must not fail");
let stamps: Vec<u64> = result.0.barks.iter().map(|row| row.at_ms).collect();
assert_eq!(
stamps,
vec![2, 3],
"the newest two, still in file order: {stamps:?}"
);
}
#[tokio::test]
async fn list_barks_caps_the_tail_at_the_maximum() {
let dir = tempfile::tempdir().unwrap();
let barks_path = dir.path().join("barks.jsonl");
let records: Vec<shep_core::barks::Bark> = (1..=205).map(bark_at).collect();
write_barks(&barks_path, &records);
let whistle = whistle_at(
shep_client::testing::control_address(dir.path()),
barks_path,
);
let result = tokio::time::timeout(
TEST_TIMEOUT,
whistle.list_barks(Parameters(BarksParams { tail: Some(1000) })),
)
.await
.expect("list_barks must return within the test timeout")
.expect("a request over the cap must be clamped, not refused");
assert_eq!(
result.0.barks.len(),
200,
"the 200 clamp must hold even against a request for 1000: {}",
result.0.barks.len()
);
assert_eq!(
result.0.barks.last().map(|row| row.at_ms),
Some(205),
"the clamped tail still ends on the newest alert"
);
assert_eq!(
result.0.barks.first().map(|row| row.at_ms),
Some(6),
"and drops the oldest 5, not the newest"
);
}