use super::*;
use crate::boundary::deposit;
use crate::test_support::world_under;
use crate::ui_state::Clock;
use crate::watch::NoRepaint;
use serde_json::json;
use std::time::{Duration, Instant};
use tempfile::tempdir;
struct AtClock(i64);
impl Clock for AtClock {
fn now(&self) -> Instant {
Instant::now()
}
fn stamp(&self) -> String {
self.0.to_string()
}
}
#[test]
fn a_windowless_engine_answers_a_deposit_and_stops_on_drop() {
let root = tempdir().unwrap();
let world = world_under(root.path());
let stale = world.yog_stage_root().join("nonce");
std::fs::create_dir_all(&stale).unwrap();
let far_future = 1_000_000_000_000;
let state_root = world.yog_state_root();
deposit::deposit(&state_root, "e-1", &json!({"op": "attention"})).unwrap();
let engine = Engine::boot(
&world,
&[],
None,
Arc::new(AtClock(far_future)),
std::sync::Arc::new(NoRepaint),
);
assert!(!stale.exists(), "the §5.2 startup sweep is the engine's");
assert_eq!(
engine.model.ui_json_path(),
state_root.join("ui.json"),
"the model is rooted in the world it was booted into"
);
let deadline = Instant::now() + Duration::from_secs(10);
let reply = loop {
if let Some(reply) = deposit::read_reply(&state_root, "e-1") {
break reply;
}
assert!(Instant::now() < deadline, "no face answered the deposit");
std::thread::sleep(Duration::from_millis(10));
};
assert_eq!(reply["ok"], true);
assert_eq!(reply["kind"], "attention", "the §6 queue, headless");
assert_eq!(
reply["rows"].as_array().map(Vec::len),
Some(0),
"an empty world asks nothing of anyone"
);
drop(engine); }
#[test]
fn a_booted_engine_hands_its_window_a_seat_on_its_own_wire() {
let root = tempdir().unwrap();
let world = world_under(root.path());
let mut engine = Engine::boot(
&world,
&[],
None,
Arc::new(AtClock(0)),
std::sync::Arc::new(NoRepaint),
);
let mut asker = engine
.asker(&world)
.expect("a seat on the engine's own wire");
assert!(
engine.asker(&world).is_none(),
"one asker per engine: the link end is taken, not shared"
);
assert!(
engine.model.wire_refusal().is_none(),
"a wired window records no refusal"
);
let question = crate::boundary::codec::encode(&crate::boundary::Gesture::Ask(
crate::boundary::Query::Workspaces,
));
engine.model.refresh();
assert!(engine.model.wire_ask(&question).is_none());
engine.model.refresh();
engine.model.wire_ask(&question);
assert_eq!(asker.pass(), 1, "one standing question, asked");
engine.model.refresh();
let Some(Ok(crate::boundary::reply::Reply::Workspaces(view))) =
engine.model.wire_ask(&question)
else {
panic!("the frame paints a decoded reply that crossed the wire");
};
assert!(view.rows.is_empty(), "an empty world enumerates nothing");
drop(engine);
}
#[test]
fn a_window_takes_both_halves_of_the_wire_once() {
let root = tempdir().unwrap();
let world = world_under(root.path());
let mut engine = Engine::boot(
&world,
&[],
None,
Arc::new(AtClock(0)),
std::sync::Arc::new(NoRepaint),
);
let wire = engine.window_wire(&world).expect("both halves");
assert!(engine.window_wire(&world).is_none(), "taken, never shared");
assert!(
engine.model.wire_refusal().is_none(),
"taken ends are a second call, not a refusal — this window IS wired"
);
drop(wire);
drop(engine);
}
#[test]
fn a_boot_whose_stated_port_is_held_refuses_where_the_frame_reads_it() {
let root = tempdir().unwrap();
let world = world_under(root.path());
let dir = crate::wire::material::dir(&world);
crate::test_support::wire::mint(&dir);
let holder = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
let held = holder.local_addr().unwrap().to_string();
std::fs::write(
dir.join(crate::wire::material::ADDRESS),
format!("{held}\n"),
)
.unwrap();
let mut engine = Engine::boot(
&world,
&[],
None,
Arc::new(AtClock(0)),
std::sync::Arc::new(NoRepaint),
);
assert!(engine.window_wire(&world).is_none(), "no wire to hand over");
let refusal = engine.model.wire_refusal().expect("the refusal is painted");
assert!(
refusal.contains(&format!("bind {held}")),
"the engine's own sentence, kept first: {refusal}"
);
drop(engine);
}
#[test]
fn a_missing_window_leaf_is_a_refusal_naming_it() {
let root = tempdir().unwrap();
let world = world_under(root.path());
let mut engine = Engine::boot(
&world,
&[],
None,
Arc::new(AtClock(0)),
std::sync::Arc::new(NoRepaint),
);
let dir = crate::wire::material::dir(&world);
for name in ["ca.pem", "window.pem", "window.key", "address"] {
std::fs::remove_file(dir.join(name)).unwrap();
}
assert!(engine.window_wire(&world).is_none(), "no wire to hand over");
let refusal = engine.model.wire_refusal().expect("the refusal is painted");
assert!(refusal.contains("no window leaf"), "{refusal}");
drop(engine);
}