202 lines
5.4 KiB
Rust
202 lines
5.4 KiB
Rust
//! Tests for writing the next epoch. Do not edit.
|
|
|
|
mod support;
|
|
|
|
use bxcore::{Epoch, LogRecord, SessionId};
|
|
use loopd::baseline::Baseline;
|
|
use loopd::compact;
|
|
use loopd::memory::{MemorySource, NoMemory};
|
|
use loopd::session::Session;
|
|
use loopd::tools::Registry;
|
|
use support::Home;
|
|
|
|
struct Block(&'static str);
|
|
|
|
impl MemorySource for Block {
|
|
fn block(&self) -> Result<String, String> {
|
|
Ok(self.0.to_string())
|
|
}
|
|
fn updated(&self, _session: &SessionId, _turn: u64) -> Result<(), String> {
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
fn id(s: &str) -> SessionId {
|
|
SessionId::new(s).unwrap()
|
|
}
|
|
|
|
fn session(home: &Home) -> (loopd::config::Config, Session) {
|
|
let cfg = home.config(std::path::Path::new("/tmp/unused.sock"));
|
|
let baseline = Baseline::assemble(&cfg, &Registry::m2b()).unwrap();
|
|
let s = Session::create(&home.dir, id("a"), baseline, cfg.slots.main).unwrap();
|
|
(cfg, s)
|
|
}
|
|
|
|
#[test]
|
|
fn commit_writes_epoch_end_a_new_baseline_and_a_new_log() {
|
|
let home = Home::new();
|
|
let (cfg, mut s) = session(&home);
|
|
s.append(LogRecord::User {
|
|
time: bxcore::Timestamp::parse("2026-09-18T08:00:00.000Z").unwrap(),
|
|
content: "hi".to_string(),
|
|
speaker: None,
|
|
})
|
|
.unwrap();
|
|
compact::commit(
|
|
&mut s,
|
|
&cfg,
|
|
&Registry::m2b(),
|
|
&NoMemory,
|
|
"the sum".to_string(),
|
|
)
|
|
.unwrap();
|
|
|
|
assert_eq!(s.epoch(), Epoch(1));
|
|
assert_eq!(s.carry(), Some("the sum"));
|
|
assert_eq!(s.slot(), cfg.slots.main);
|
|
assert_eq!(s.turns(), 1, "the old user still counts");
|
|
assert_eq!(
|
|
s.records()
|
|
.iter()
|
|
.filter(|r| matches!(r, LogRecord::User { .. }))
|
|
.count(),
|
|
0
|
|
);
|
|
|
|
let old = home.records("a");
|
|
assert!(
|
|
matches!(old.last(), Some(LogRecord::EpochEnd { next, summary, .. }) if *next == Epoch(1) && summary == "the sum")
|
|
);
|
|
assert!(home.dir.join("sessions/a/1.baseline.json").is_file());
|
|
let new_log = home.read("sessions/a/1.jsonl");
|
|
assert!(new_log.contains("\"epoch\":1"), "{new_log}");
|
|
}
|
|
|
|
#[test]
|
|
fn the_new_baseline_takes_a_fresh_memory_block() {
|
|
let home = Home::new();
|
|
let (cfg, mut s) = session(&home);
|
|
compact::commit(
|
|
&mut s,
|
|
&cfg,
|
|
&Registry::m2b(),
|
|
&Block("I take my tea strong."),
|
|
"sum".to_string(),
|
|
)
|
|
.unwrap();
|
|
assert!(
|
|
s.baseline().system.contains("I take my tea strong."),
|
|
"{}",
|
|
s.baseline().system
|
|
);
|
|
let on_disk = home.read("sessions/a/1.baseline.json");
|
|
assert!(on_disk.contains("I take my tea strong."), "{on_disk}");
|
|
}
|
|
|
|
#[test]
|
|
fn reopen_loads_the_new_epoch() {
|
|
let home = Home::new();
|
|
let (cfg, mut s) = session(&home);
|
|
compact::commit(
|
|
&mut s,
|
|
&cfg,
|
|
&Registry::m2b(),
|
|
&NoMemory,
|
|
"carry".to_string(),
|
|
)
|
|
.unwrap();
|
|
drop(s);
|
|
let s = Session::open(&home.dir, id("a")).unwrap();
|
|
assert_eq!(s.epoch(), Epoch(1));
|
|
assert_eq!(s.carry(), Some("carry"));
|
|
}
|
|
|
|
#[test]
|
|
fn a_second_commit_does_not_write_another_epoch_end_on_the_old_log() {
|
|
let home = Home::new();
|
|
let (cfg, mut s) = session(&home);
|
|
compact::commit(
|
|
&mut s,
|
|
&cfg,
|
|
&Registry::m2b(),
|
|
&NoMemory,
|
|
"first".to_string(),
|
|
)
|
|
.unwrap();
|
|
let ends = home
|
|
.records("a")
|
|
.iter()
|
|
.filter(|r| matches!(r, LogRecord::EpochEnd { .. }))
|
|
.count();
|
|
assert_eq!(ends, 1);
|
|
compact::commit(
|
|
&mut s,
|
|
&cfg,
|
|
&Registry::m2b(),
|
|
&NoMemory,
|
|
"second".to_string(),
|
|
)
|
|
.unwrap();
|
|
assert_eq!(s.epoch(), Epoch(2));
|
|
let ends = home
|
|
.records("a")
|
|
.iter()
|
|
.filter(|r| matches!(r, LogRecord::EpochEnd { .. }))
|
|
.count();
|
|
assert_eq!(ends, 1, "epoch 0 still has one EpochEnd");
|
|
let mid = home.read("sessions/a/1.jsonl");
|
|
assert!(mid.contains("\"type\":\"epoch_end\""), "{mid}");
|
|
}
|
|
|
|
#[test]
|
|
fn resume_after_epoch_end_without_next_files_does_not_write_a_second_end() {
|
|
let home = Home::new();
|
|
let (cfg, mut s) = session(&home);
|
|
s.append(LogRecord::EpochEnd {
|
|
time: bxcore::Timestamp::now(),
|
|
next: Epoch(1),
|
|
summary: "already".to_string(),
|
|
})
|
|
.unwrap();
|
|
drop(s);
|
|
let mut s = Session::open(&home.dir, id("a")).unwrap();
|
|
assert_eq!(s.epoch(), Epoch(0));
|
|
compact::commit(
|
|
&mut s,
|
|
&cfg,
|
|
&Registry::m2b(),
|
|
&NoMemory,
|
|
"ignored".to_string(),
|
|
)
|
|
.unwrap();
|
|
let ends = home
|
|
.records("a")
|
|
.iter()
|
|
.filter(|r| matches!(r, LogRecord::EpochEnd { .. }))
|
|
.count();
|
|
assert_eq!(ends, 1);
|
|
assert_eq!(s.epoch(), Epoch(1));
|
|
assert_eq!(
|
|
s.carry(),
|
|
Some("already"),
|
|
"the summary already in EpochEnd is the carry"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn the_new_session_start_keeps_the_live_slot() {
|
|
let home = Home::new();
|
|
let cfg = home.config(std::path::Path::new("/tmp/unused.sock"));
|
|
let baseline = Baseline::assemble(&cfg, &Registry::m2b()).unwrap();
|
|
let mut s = Session::create(&home.dir, id("a"), baseline, 7).unwrap();
|
|
compact::commit(&mut s, &cfg, &Registry::m2b(), &NoMemory, "s".to_string()).unwrap();
|
|
assert_eq!(s.slot(), 7);
|
|
match &s.records()[0] {
|
|
LogRecord::SessionStart { slot, epoch, .. } => {
|
|
assert_eq!(*slot, 7);
|
|
assert_eq!(*epoch, Epoch(1));
|
|
}
|
|
other => panic!("{other:?}"),
|
|
}
|
|
}
|