use agent_frame::{Op, RootEvent, RootKind, Span, Unit, UnitId};
use content_addressable::ContentId;
const SRC_A: &[u8] = b"the quick brown fox jumps over the lazy dog";
const SRC_B: &[u8] = b"a completely different source with other bytes!!";
fn root(seq: u64) -> ContentId {
RootEvent::new(RootKind::OperatorPrompt, b"run the tests", seq)
.id()
.expect("a root event addresses")
}
fn seal(source: &[u8], span: Span, root: ContentId) -> Unit {
Unit::seal(Op::Elide, source, span, root).expect("elide over a real span is mintable")
}
#[test]
fn different_sources_mint_different_addresses() {
let r = root(0);
let a = seal(SRC_A, Span::new(4, 9), r);
let b = seal(SRC_B, Span::new(4, 9), r);
assert_ne!(
a.id().unwrap(),
b.id().unwrap(),
"same op, same span, same root, DIFFERENT source — the ids must differ, \
or the address does not name the material"
);
}
#[test]
fn different_spans_of_one_source_mint_different_addresses() {
let r = root(0);
let ids: Vec<UnitId> = [
Span::new(0, 3),
Span::new(4, 9),
Span::new(4, 10),
Span::new(5, 10),
Span::new(0, SRC_A.len() as u64),
]
.into_iter()
.map(|s| seal(SRC_A, s, r).id().unwrap())
.collect();
let mut unique = ids.clone();
unique.sort_unstable();
unique.dedup();
assert_eq!(
unique.len(),
ids.len(),
"five distinct spans of one source must mint five distinct ids, got {ids:?}"
);
}
#[test]
fn the_root_identifies_which_turn_not_merely_which_kind() {
let first = root(0);
let second = root(1);
assert_ne!(
first, second,
"the same words typed twice are two turns — a root event must distinguish them"
);
assert_ne!(
seal(SRC_A, Span::new(4, 9), first).id().unwrap(),
seal(SRC_A, Span::new(4, 9), second).id().unwrap(),
"same elision, different operator turn — the unit ids must differ"
);
let action = RootEvent::new(RootKind::UserAction, b"run the tests", 0)
.id()
.unwrap();
assert_ne!(
first, action,
"same material, same seq, different kind — still different events"
);
}
#[test]
fn lifecycle_does_not_change_the_address() {
let u = seal(SRC_A, Span::new(4, 9), root(0));
let before = u.id().unwrap();
for life in [
agent_frame::Life::Superseded,
agent_frame::Life::Withdrawn,
agent_frame::Life::Live,
] {
assert_eq!(
u.with_life(life).id().unwrap(),
before,
"{life:?} is a fact ABOUT this derivation, not a different derivation"
);
}
assert!(!u.evictable());
assert!(u.with_life(agent_frame::Life::Superseded).evictable());
}
#[test]
fn unit_ids_and_packet_ids_are_not_interchangeable() {
use agent_frame::{Packet, PacketId};
let u = seal(SRC_A, Span::new(4, 9), root(0)).id().unwrap();
let p: PacketId = Packet::genesis(vec![u]).id().unwrap();
let round: UnitId = UnitId::from(*p.as_content_id());
assert_eq!(round.as_content_id(), p.as_content_id());
assert_ne!(
std::any::TypeId::of::<UnitId>(),
std::any::TypeId::of::<PacketId>(),
"aliases would make these one type, and a packet id would fit a unit slot"
);
}