//! A Honcho worker for tests, stepped by hand: a home with session logs and a ledger, the fake //! Honcho, `brokerd` as a closure whose answer the test sets, and the log lines collected. Do not //! edit. #![allow(dead_code)] // each test file uses a different part of this module use std::collections::BTreeMap; use std::ffi::OsString; use std::path::PathBuf; use std::sync::{Arc, Mutex}; use std::time::Duration; use bxcore::{LogRecord, SessionStateReply, Timestamp}; use memoryd::honcho::client::{Clients, Timeouts}; use memoryd::honcho::config::HonchoConfig; use memoryd::honcho::ledger::{Ledger, Record}; use memoryd::honcho::turns::{LEDGER, TurnSync}; use memoryd::honcho::worker::{Tuning, Wake, Worker}; use memoryd::serve::Log; use crate::honcho::FakeHoncho; use crate::tmp::TempDir; use crate::turns::{clean, sid, write_turns}; pub const FAST: Tuning = Tuning { backoff: Duration::from_millis(1), backoff_max: Duration::from_millis(8), idle: Duration::from_millis(1), }; /// When the tests' ledgers began: before every turn they log (`spoken`). pub const BEGAN: &str = "2026-09-28T09:00:00.000Z"; pub fn began() -> Timestamp { Timestamp::parse(BEGAN).unwrap() } /// The ledger line of `BEGAN`, for a test that writes a ledger itself. pub fn began_line() -> String { format!(r#"{{"type":"began","time":"{BEGAN}"}}"#) } pub fn config(url: &str) -> HonchoConfig { HonchoConfig { url: url.to_string(), agent: "boxmaker0".to_string(), owner: "kyle".to_string(), trusted: "boxmaker0-trusted".to_string(), untrusted: "boxmaker0-untrusted".to_string(), fleet: "fleet".to_string(), read: Vec::new(), keys: BTreeMap::new(), } } pub struct Home { pub sync: Arc>, /// What `brokerd` answers. pub answer: Arc>>, pub lines: Arc>>, pub dir: TempDir, } impl Home { /// A home whose ledger has begun, at `BEGAN`, as `memoryd` makes it at its first start. pub fn new(tag: &str) -> Home { let dir = TempDir::new(tag); std::fs::create_dir_all(dir.path().join("memory")).unwrap(); let mut ledger = Ledger::open(&dir.path().join("memory").join(LEDGER)).unwrap(); ledger.append(Record::Began { time: began() }).unwrap(); Home { sync: Arc::new(Mutex::new(TurnSync::new( ledger, "boxmaker0", &dir.path().join("sessions"), ))), answer: Arc::new(Mutex::new(Ok(clean()))), lines: Arc::new(Mutex::new(Vec::new())), dir, } } pub fn ledger_path(&self) -> PathBuf { self.dir.path().join("memory").join(LEDGER) } /// A new `TurnSync` over the ledger as it is on disk, resumed: what a restart makes. pub fn restart(&mut self) { let mut sync = TurnSync::new( Ledger::open(&self.ledger_path()).unwrap(), "boxmaker0", &self.dir.path().join("sessions"), ); sync.resume(); self.sync = Arc::new(Mutex::new(sync)); } pub fn log(&self, session: &str, turns: &[Vec]) { write_turns(self.dir.path(), session, turns); } /// `loopd` reports turn `turn` of `session`: decided now, with `answer`. pub fn report(&self, session: &str, turn: u64) { let answer = Arc::clone(&self.answer); let ask = move |_: &bxcore::SessionId| answer.lock().unwrap().clone(); let lines = Arc::clone(&self.lines); let log = move |line: &str| lines.lock().unwrap().push(line.to_string()); let now = Timestamp::parse("2026-09-28T10:00:00.000Z").unwrap(); self.sync .lock() .unwrap() .updated(&sid(session), turn, &ask, now, &log); } pub fn worker(&self, fake: &FakeHoncho, tuning: Tuning) -> Worker { let no_env = |_: &str| -> Option { None }; let timeouts = Timeouts { connect: Duration::from_secs(5), read: Duration::from_millis(300), }; let (clients, _) = Clients::new(&config(&fake.url), &no_env, timeouts).unwrap(); let answer = Arc::clone(&self.answer); let lines = Arc::clone(&self.lines); let log: Log = Arc::new(move |line: &str| lines.lock().unwrap().push(line.to_string())); Worker::new( Arc::clone(&self.sync), clients, Arc::new(Wake::default()), Box::new(move |_: &bxcore::SessionId| answer.lock().unwrap().clone()), log, tuning, "boxmaker0", ) } /// Every record of the ledger on disk but its `Began`, in order. pub fn records(&self) -> Vec { std::fs::read_to_string(self.ledger_path()) .unwrap_or_default() .lines() .map(|l| serde_json::from_str(l).unwrap()) .filter(|r| !matches!(r, Record::Began { .. })) .collect() } pub fn lines(&self) -> Vec { self.lines.lock().unwrap().clone() } }