150 lines
5.0 KiB
Rust
150 lines
5.0 KiB
Rust
//! 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<Mutex<TurnSync>>,
|
|
/// What `brokerd` answers.
|
|
pub answer: Arc<Mutex<Result<SessionStateReply, String>>>,
|
|
pub lines: Arc<Mutex<Vec<String>>>,
|
|
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<LogRecord>]) {
|
|
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<OsString> { 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<Record> {
|
|
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<String> {
|
|
self.lines.lock().unwrap().clone()
|
|
}
|
|
}
|