use super::super::{resolve_agent, resolving};
use crate::git_tree::tests::fixture::Fixture;
use std::time::Duration;
const NO_HOLD: (u32, Duration) = (0, Duration::ZERO);
const WS: &str = "alba";
fn snap(agents: Vec<crate::git_tree::Agent>) -> (std::path::PathBuf, crate::app::Snapshot) {
let ws = std::path::PathBuf::from("/names/alba");
let snapshot = crate::boundary::tests::snapshot(&ws, WS, agents, vec![]);
(ws, snapshot)
}
fn named(id: &str, name: Option<&str>) -> crate::git_tree::Agent {
crate::git_tree::Agent {
name: name.map(str::to_owned),
..crate::boundary::tests::agent(id, crate::git_tree::AgentState::Quiescent, 1)
}
}
#[test]
fn no_needle_resolves_to_nothing() {
let (ws, snapshot) = snap(vec![]);
assert_eq!(resolve_agent(&snapshot, &ws, None), Ok(String::new()));
}
#[test]
fn an_id_shaped_needle_passes_through_unread() {
let id = "20260101T000000Z-aaaa-20260102T000000Z-bbbb";
let (_, snapshot) = snap(vec![]);
assert_eq!(
resolve_agent(
&snapshot,
std::path::Path::new("/nonexistent"),
Some(id.to_owned())
),
Ok(id.to_owned())
);
}
#[test]
fn a_foreign_id_the_derivation_holds_addresses_itself() {
let (ws, snapshot) = snap(vec![named("hand-made", None)]);
assert_eq!(
resolve_agent(&snapshot, &ws, Some("hand-made".to_owned())),
Ok("hand-made".to_owned())
);
}
#[test]
fn a_stored_name_resolves_to_the_root_it_names() {
let (ws, snapshot) = snap(vec![named("20260101T000000Z-aaaa", Some("pale-otter"))]);
assert_eq!(
resolve_agent(&snapshot, &ws, Some("pale-otter".to_owned())),
Ok("20260101T000000Z-aaaa".to_owned())
);
}
#[test]
fn a_legacy_display_only_name_refuses() {
let stamped = crate::git_tree::Agent {
goal_name: Some("pale-fox".to_owned()),
..named("20260101T000000Z-aaaa", None)
};
let (ws, snapshot) = snap(vec![stamped]);
let why = resolving(
&snapshot,
&ws,
Some("pale-fox".to_owned()),
NO_HOLD.0,
NO_HOLD.1,
)
.expect_err("refused");
assert!(why.contains("unknown conversation"), "{why}");
}
#[test]
fn an_ambiguous_name_refuses() {
let (ws, snapshot) = snap(vec![
named("20260101T000000Z-aaaa", Some("pale-otter")),
named("20260101T000000Z-bbbb", Some("pale-otter")),
]);
let why = resolve_agent(&snapshot, &ws, Some("pale-otter".to_owned())).expect_err("refused");
assert!(why.contains("ambiguous conversation"), "{why}");
assert!(why.contains("pale-otter"), "{why}");
}
#[test]
fn an_unknown_name_refuses_naming_the_token() {
let (ws, snapshot) = snap(vec![named("20260101T000000Z-aaaa", Some("pale-otter"))]);
let why = resolving(
&snapshot,
&ws,
Some("grey-heron".to_owned()),
NO_HOLD.0,
NO_HOLD.1,
)
.expect_err("refused");
assert!(why.contains("unknown conversation"), "{why}");
assert!(why.contains("grey-heron"), "{why}");
}
#[test]
fn a_conversation_the_derivation_has_not_swept_resolves_off_disk() {
let fx = Fixture::new();
fx.build_agent("20260101T000000Z-aaaa", "one");
fx.name_agent("20260101T000000Z-aaaa", "pale-otter");
let (_, snapshot) = snap(vec![]);
assert_eq!(
resolve_agent(&snapshot, &fx.path, Some("pale-otter".to_owned())),
Ok("20260101T000000Z-aaaa".to_owned())
);
}
#[test]
fn a_name_the_fire_just_minted_resolves_once_the_driver_writes_its_branch() {
let fx = Fixture::new();
let ws = fx.path.clone();
let (_, snapshot) = snap(vec![]);
std::thread::scope(|scope| {
scope.spawn(|| {
std::thread::sleep(Duration::from_millis(100));
fx.build_agent("20260101T000000Z-aaaa", "one");
fx.name_agent("20260101T000000Z-aaaa", "pale-otter");
});
assert_eq!(
resolving(
&snapshot,
&ws,
Some("pale-otter".to_owned()),
80,
Duration::from_millis(25),
),
Ok("20260101T000000Z-aaaa".to_owned()),
"the disk rung waits out the driver's launch",
);
});
}
#[test]
fn a_name_that_never_appears_still_refuses_after_the_hold() {
let fx = Fixture::new();
let (_, snapshot) = snap(vec![]);
let why = resolving(
&snapshot,
&fx.path,
Some("grey-heron".to_owned()),
2,
Duration::from_millis(1),
)
.expect_err("refused");
assert!(why.contains("unknown conversation"), "{why}");
assert!(why.contains("grey-heron"), "{why}");
}