#[path = "common/harness.rs"]
mod harness;
use harness::TestHarness;
use macrame::graph::TraversalBuilder;
use macrame::{Database, DbError};
const TS: &str = "2026-01-01T00:00:00.000000Z";
const TS2: &str = "2026-02-01T00:00:00.000000Z";
const TS3: &str = "2026-03-01T00:00:00.000000Z";
const TS4: &str = "2026-04-01T00:00:00.000000Z";
const NOW: &str = "2026-06-01T00:00:00.000000Z";
const SENTINEL: &str = "9999-12-31T23:59:59.999999Z";
async fn connect(harness: &TestHarness) -> libsql::Connection {
libsql::Builder::new_local(&harness.db_path)
.build()
.await
.unwrap()
.connect()
.unwrap()
}
async fn seed(conn: &libsql::Connection) {
macrame::schema::run_migrations(conn).await.unwrap();
for id in ["a", "b", "c", "d"] {
conn.execute(
"INSERT INTO concepts (id, title, valid_from, recorded_at) VALUES (?1, 'N', ?2, ?2)",
libsql::params![id, TS],
)
.await
.unwrap();
}
for (parent, child) in [("main", "b1"), ("b1", "b2")] {
conn.execute(
"INSERT INTO branches (branch_id, parent_id, forked_at, created_at) \
VALUES (?1, ?2, ?3, ?3)",
libsql::params![child, parent, TS2],
)
.await
.unwrap();
}
for (source, target) in [("a", "b"), ("b", "c"), ("c", "d")] {
edge(conn, source, target, "main", SENTINEL, 1.0, TS).await;
}
}
async fn edge(
conn: &libsql::Connection,
source: &str,
target: &str,
branch: &str,
valid_to: &str,
weight: f64,
recorded_at: &str,
) {
conn.execute(
"INSERT INTO links (source_id, target_id, edge_type, valid_from, valid_to, \
weight, properties, recorded_at, branch_id) \
VALUES (?1, ?2, 'LINKS', ?3, ?4, ?5, '{}', ?6, ?7)",
libsql::params![source, target, TS, valid_to, weight, recorded_at, branch],
)
.await
.unwrap();
}
async fn reached(conn: &libsql::Connection, branch: Option<&str>) -> Vec<String> {
let mut walk = TraversalBuilder::new("a").max_depth(5);
if let Some(b) = branch {
walk = walk.on_branch(b);
}
walk.execute_ids(conn, NOW).await.unwrap()
}
async fn reached_above(conn: &libsql::Connection, branch: &str, floor: f64) -> Vec<String> {
TraversalBuilder::new("a")
.max_depth(5)
.min_weight(floor)
.on_branch(branch)
.execute_ids(conn, NOW)
.await
.unwrap()
}
async fn reached_at_tx(conn: &libsql::Connection, branch: &str) -> Vec<String> {
TraversalBuilder::new("a")
.max_depth(5)
.as_of_recorded(NOW)
.attribute_mode(macrame::graph::AttributeMode::Omit)
.on_branch(branch)
.execute_ids(conn, NOW)
.await
.unwrap()
}
async fn as_of_arrows(conn: &libsql::Connection, branch: Option<&str>) -> Vec<String> {
let mut arrows: Vec<String> = macrame::temporal::query_as_of_edges_on(conn, NOW, branch)
.await
.unwrap()
.iter()
.map(|e| format!("{}→{}", e.0, e.1))
.collect();
arrows.sort_unstable();
arrows
}
async fn reached_via_as_of(conn: &libsql::Connection, branch: Option<&str>) -> Vec<String> {
let edges = macrame::temporal::query_as_of_edges_on(conn, NOW, branch)
.await
.unwrap();
let mut seen = std::collections::BTreeSet::from(["a".to_string()]);
for _ in 0..5 {
let grew: Vec<String> = edges
.iter()
.filter(|e| seen.contains(&e.0) && !seen.contains(&e.1))
.map(|e| e.1.clone())
.collect();
if grew.is_empty() {
break;
}
seen.extend(grew);
}
seen.into_iter().collect()
}
#[tokio::test]
async fn a_branch_reads_the_edges_its_ancestors_asserted() {
let harness = TestHarness::new();
let conn = connect(&harness).await;
seed(&conn).await;
for branch in ["main", "b1", "b2"] {
assert_eq!(
reached(&conn, Some(branch)).await,
["a", "b", "c", "d"],
"{branch} did not inherit the trunk's chain"
);
}
}
#[tokio::test]
async fn a_branch_that_retires_an_inherited_edge_loses_what_it_reached() {
let harness = TestHarness::new();
let conn = connect(&harness).await;
seed(&conn).await;
edge(&conn, "b", "c", "b1", TS2, 1.0, TS2).await;
assert_eq!(
reached(&conn, Some("b1")).await,
["a", "b"],
"the shadow row did not close the inherited edge for its own lineage"
);
assert_eq!(
reached(&conn, Some("b2")).await,
["a", "b"],
"a descendant must inherit the retirement, not the row it shadowed"
);
assert_eq!(
reached(&conn, Some("main")).await,
["a", "b", "c", "d"],
"a branch retiring an edge changed what the trunk believes"
);
let stored: i64 = conn
.query(
"SELECT COUNT(*) FROM links_current \
WHERE source_id = 'b' AND target_id = 'c'",
(),
)
.await
.unwrap()
.next()
.await
.unwrap()
.unwrap()
.get(0)
.unwrap();
assert_eq!(stored, 2, "shadowing must add a row, never overwrite one");
}
#[tokio::test]
async fn the_nearest_lineage_holding_an_edge_is_the_one_that_is_read() {
let harness = TestHarness::new();
let conn = connect(&harness).await;
seed(&conn).await;
edge(&conn, "a", "b", "b1", SENTINEL, 0.5, TS2).await;
edge(&conn, "a", "b", "b2", SENTINEL, 0.1, TS3).await;
assert_eq!(
reached_above(&conn, "main", 0.3).await,
["a", "b", "c", "d"]
);
assert_eq!(reached_above(&conn, "b1", 0.3).await, ["a", "b", "c", "d"]);
assert_eq!(
reached_above(&conn, "b2", 0.3).await,
["a"],
"b2's own correction must win over both of its ancestors' rows"
);
}
#[tokio::test]
async fn an_unbranched_read_on_a_forked_ledger_stays_on_the_trunk() {
let harness = TestHarness::new();
let conn = connect(&harness).await;
seed(&conn).await;
conn.execute(
"INSERT INTO concepts (id, title, valid_from, recorded_at, branch_id) \
VALUES ('e', 'minted on b1', ?1, ?1, 'b1')",
libsql::params![TS2],
)
.await
.unwrap();
edge(&conn, "a", "e", "b1", SENTINEL, 1.0, TS2).await;
assert_eq!(
reached(&conn, None).await,
["a", "b", "c", "d"],
"an unbranched traversal read another lineage's edge"
);
assert_eq!(
reached(&conn, Some("main")).await,
["a", "b", "c", "d"],
"naming the trunk explicitly must mean the same thing as not naming it"
);
assert!(reached(&conn, Some("b1")).await.contains(&"e".to_string()));
}
#[tokio::test]
async fn a_traversal_naming_an_unregistered_lineage_is_refused() {
let harness = TestHarness::new();
let conn = connect(&harness).await;
seed(&conn).await;
let err = TraversalBuilder::new("a")
.on_branch("ghost")
.execute_ids(&conn, NOW)
.await
.expect_err("a traversal named a lineage that does not exist");
match err {
DbError::UnknownBranch(what) => {
assert_eq!(what, "ghost", "the refusal must name it")
}
other => panic!("wrong error for an unregistered lineage: {other:?}"),
}
let harness = TestHarness::new();
let conn = connect(&harness).await;
macrame::schema::run_migrations(&conn).await.unwrap();
let err = TraversalBuilder::new("a")
.on_branch("ghost")
.execute_ids(&conn, NOW)
.await
.expect_err("the fast shape skipped the check as well as the resolution");
assert!(
matches!(err, DbError::UnknownBranch(ref w) if w == "ghost"),
"{err:?}"
);
}
#[tokio::test]
async fn a_transaction_time_traversal_resolves_lineage_in_the_fold() {
let harness = TestHarness::new();
let conn = connect(&harness).await;
seed(&conn).await;
edge(&conn, "b", "c", "b1", TS2, 1.0, TS2).await;
assert_eq!(
reached_at_tx(&conn, "b1").await,
["a", "b"],
"the retirement is in the log and the fold must carry it to b1"
);
assert_eq!(
reached_at_tx(&conn, "main").await,
["a", "b", "c", "d"],
"the fold handed the trunk a branch's belief: the partition lost a row"
);
}
#[tokio::test]
async fn the_fold_keeps_the_older_lineages_row_as_well() {
let harness = TestHarness::new();
let conn = connect(&harness).await;
macrame::schema::run_migrations(&conn).await.unwrap();
for id in ["a", "b"] {
conn.execute(
"INSERT INTO concepts (id, title, valid_from, recorded_at) VALUES (?1, 'N', ?2, ?2)",
libsql::params![id, TS],
)
.await
.unwrap();
}
conn.execute(
"INSERT INTO branches (branch_id, parent_id, forked_at, created_at) \
VALUES ('b1', 'main', ?1, ?1)",
libsql::params![TS],
)
.await
.unwrap();
edge(&conn, "a", "b", "b1", SENTINEL, 1.0, TS).await;
edge(&conn, "a", "b", "main", TS2, 1.0, TS2).await;
assert_eq!(
reached_at_tx(&conn, "b1").await,
["a", "b"],
"the later trunk row displaced the branch's own belief in the fold"
);
assert_eq!(
reached_at_tx(&conn, "main").await,
["a"],
"the trunk closed its own edge"
);
}
#[tokio::test]
async fn the_subgraph_loader_reads_the_same_lineage() {
let harness = TestHarness::new();
{
let conn = connect(&harness).await;
seed(&conn).await;
edge(&conn, "b", "c", "b1", TS2, 1.0, TS2).await;
}
let db = Database::open(&harness.db_path).await.unwrap();
let trunk = db
.load_subgraph_with(&TraversalBuilder::new("a").max_depth(5), NOW, 1 << 20)
.await
.unwrap();
assert_eq!(trunk.node_count(), 4);
assert_eq!(trunk.edge_count(), 3);
let branched = db
.load_subgraph_with(
&TraversalBuilder::new("a").max_depth(5).on_branch("b1"),
NOW,
1 << 20,
)
.await
.unwrap();
assert_eq!(
branched.node_count(),
2,
"the walk did not resolve: {:?}",
branched.node_ids().collect::<Vec<_>>()
);
assert_eq!(
branched.edge_count(),
1,
"the projection returned an edge the walk had already excluded"
);
let err = db
.load_subgraph_with(&TraversalBuilder::new("a").on_branch("ghost"), NOW, 1 << 20)
.await
.expect_err("the loader answered for a lineage that does not exist");
assert!(
matches!(err, DbError::UnknownBranch(ref w) if w == "ghost"),
"{err:?}"
);
db.close().await.unwrap();
}
#[tokio::test]
async fn the_forked_trunks_loader_projects_only_the_trunks_rows() {
let harness = TestHarness::new();
{
let conn = connect(&harness).await;
seed(&conn).await;
edge(&conn, "a", "d", "b1", SENTINEL, 2.0, TS2).await;
edge(&conn, "b", "c", "b1", SENTINEL, 5.0, TS2).await;
}
let db = Database::open(&harness.db_path).await.unwrap();
let trunk = db
.load_subgraph_with(&TraversalBuilder::new("a").max_depth(5), NOW, 1 << 20)
.await
.unwrap();
assert_eq!(trunk.node_count(), 4);
assert_eq!(
trunk.edge_count(),
3,
"the trunk's projection returned a lineage's row the trunk cannot see"
);
assert_eq!(
trunk.total_weight(),
3.0,
"the trunk's projection took the branch's reweight"
);
let branched = db
.load_subgraph_with(
&TraversalBuilder::new("a").max_depth(5).on_branch("b1"),
NOW,
1 << 20,
)
.await
.unwrap();
assert_eq!(branched.node_count(), 4);
assert_eq!(branched.edge_count(), 4, "the branch's own edge is missing");
assert_eq!(
branched.total_weight(),
9.0,
"the branch's reweight did not shadow the inherited row"
);
db.close().await.unwrap();
}
#[tokio::test]
async fn the_append_only_table_is_keyed_by_lineage() {
let harness = TestHarness::new();
let conn = connect(&harness).await;
seed(&conn).await;
conn.execute(
"INSERT INTO links (source_id, target_id, edge_type, valid_from, valid_to, \
weight, properties, recorded_at, branch_id) \
VALUES ('a', 'b', 'LINKS', ?1, ?2, 1.0, '{}', ?1, 'b1')",
libsql::params![TS, SENTINEL],
)
.await
.expect("two lineages asserting one edge at one instant were refused");
let ledger: i64 = scalar(
&conn,
"SELECT COUNT(*) FROM links WHERE source_id = 'a' AND target_id = 'b' \
AND edge_type = 'LINKS' AND valid_from = ?1",
)
.await;
assert_eq!(
ledger, 2,
"the second lineage's row did not land beside the first"
);
edge(&conn, "a", "b", "b1", SENTINEL, 0.5, TS2).await;
}
async fn scalar(conn: &libsql::Connection, sql: &str) -> i64 {
conn.query(sql, libsql::params![TS])
.await
.unwrap()
.next()
.await
.unwrap()
.unwrap()
.get(0)
.unwrap()
}
#[tokio::test]
async fn the_edge_query_reads_one_lineage_at_a_time() {
let harness = TestHarness::new();
let conn = connect(&harness).await;
seed(&conn).await;
edge(&conn, "b", "c", "b1", TS2, 1.0, TS2).await;
edge(&conn, "a", "c", "b1", SENTINEL, 1.0, TS3).await;
let trunk = macrame::temporal::query_as_of_edges(&conn, NOW)
.await
.unwrap();
let mut trunk: Vec<_> = trunk.iter().map(|e| (e.0.as_str(), e.1.as_str())).collect();
trunk.sort_unstable();
assert_eq!(
trunk,
[("a", "b"), ("b", "c"), ("c", "d")],
"the unbranched reader returned another lineage's rows"
);
let branched = macrame::temporal::query_as_of_edges_on(&conn, NOW, Some("b1"))
.await
.unwrap();
let mut branched: Vec<_> = branched
.iter()
.map(|e| (e.0.as_str(), e.1.as_str()))
.collect();
branched.sort_unstable();
assert_eq!(
branched,
[("a", "b"), ("a", "c"), ("c", "d")],
"b1 keeps its own assertion and loses the edge it shadowed"
);
assert_eq!(
macrame::temporal::query_as_of_edges_on(&conn, NOW, Some("main"))
.await
.unwrap(),
macrame::temporal::query_as_of_edges(&conn, NOW)
.await
.unwrap()
);
let err = macrame::temporal::query_as_of_edges_on(&conn, NOW, Some("ghost"))
.await
.expect_err("the reader answered for a lineage that does not exist");
assert!(
matches!(err, DbError::UnknownBranch(ref w) if w == "ghost"),
"{err:?}"
);
}
const DEPTHS: [usize; 3] = [1, 10, 100];
fn fork_instant(hop: usize) -> String {
format!("2026-02-01T00:00:00.{hop:06}Z")
}
async fn chain(conn: &libsql::Connection, depth: usize) -> String {
macrame::schema::run_migrations(conn).await.unwrap();
for id in ["a", "b", "c", "d"] {
conn.execute(
"INSERT INTO concepts (id, title, valid_from, recorded_at) VALUES (?1, 'N', ?2, ?2)",
libsql::params![id, TS],
)
.await
.unwrap();
}
let mut parent = "main".to_string();
for hop in 1..=depth {
let child = format!("L{hop}");
conn.execute(
"INSERT INTO branches (branch_id, parent_id, forked_at, created_at) \
VALUES (?1, ?2, ?3, ?3)",
libsql::params![child.as_str(), parent.as_str(), fork_instant(hop)],
)
.await
.unwrap();
parent = child;
}
for (source, target) in [("a", "b"), ("b", "c"), ("c", "d")] {
edge(conn, source, target, "main", SENTINEL, 1.0, TS).await;
}
parent
}
async fn late_concept(conn: &libsql::Connection, id: &str) {
conn.execute(
"INSERT INTO concepts (id, title, valid_from, recorded_at) VALUES (?1, 'N', ?2, ?2)",
libsql::params![id, TS3],
)
.await
.unwrap();
}
#[tokio::test]
async fn a_branch_does_not_inherit_what_its_parent_recorded_after_the_fork() {
for depth in DEPTHS {
let harness = TestHarness::new();
let conn = connect(&harness).await;
let reader = chain(&conn, depth).await;
late_concept(&conn, "e").await;
edge(&conn, "d", "e", "main", SENTINEL, 1.0, TS3).await;
assert_eq!(
reached(&conn, None).await,
["a", "b", "c", "d", "e"],
"depth {depth}: the trunk lost its own write"
);
assert_eq!(
reached(&conn, Some(&reader)).await,
["a", "b", "c", "d"],
"depth {depth}: {reader} absorbed a trunk write made after it forked"
);
}
}
#[tokio::test]
async fn a_branch_keeps_the_weight_its_parent_had_at_the_fork() {
for depth in DEPTHS {
let harness = TestHarness::new();
let conn = connect(&harness).await;
let reader = chain(&conn, depth).await;
edge(&conn, "b", "c", "main", SENTINEL, 0.1, TS3).await;
assert_eq!(
reached_above(&conn, "main", 0.5).await,
["a", "b"],
"depth {depth}: the trunk's own correction did not take"
);
assert_eq!(
reached_above(&conn, &reader, 0.5).await,
["a", "b", "c", "d"],
"depth {depth}: {reader} was handed a weight recorded after it forked"
);
}
}
#[tokio::test]
async fn a_branch_still_reaches_what_its_parent_retired_after_the_fork() {
for depth in DEPTHS {
let harness = TestHarness::new();
let conn = connect(&harness).await;
let reader = chain(&conn, depth).await;
edge(&conn, "b", "c", "main", TS3, 1.0, TS3).await;
assert_eq!(
reached(&conn, None).await,
["a", "b"],
"depth {depth}: the trunk's own retirement did not take"
);
assert_eq!(
reached(&conn, Some(&reader)).await,
["a", "b", "c", "d"],
"depth {depth}: {reader} lost a subtree to a retirement asserted \
after it forked — the projection row was filtered and the log \
entry that should have replaced it did not arrive"
);
}
}
#[tokio::test]
async fn an_ancestor_that_first_asserted_after_the_fork_contributes_nothing() {
for depth in DEPTHS {
let harness = TestHarness::new();
let conn = connect(&harness).await;
let reader = chain(&conn, depth).await;
late_concept(&conn, "e").await;
edge(&conn, "a", "e", "main", SENTINEL, 1.0, TS3).await;
edge(&conn, "a", "e", "main", SENTINEL, 0.2, TS4).await;
assert_eq!(
reached(&conn, None).await,
["a", "b", "c", "d", "e"],
"depth {depth}: the trunk lost the key it asserted twice"
);
assert_eq!(
reached(&conn, Some(&reader)).await,
["a", "b", "c", "d"],
"depth {depth}: the fold resurrected a belief with no pre-fork \
version — {reader} was handed the earlier of two post-cutoff rows"
);
}
}
#[tokio::test]
async fn a_transaction_time_read_honours_the_fork_point_too() {
for depth in DEPTHS {
let harness = TestHarness::new();
let conn = connect(&harness).await;
let reader = chain(&conn, depth).await;
edge(&conn, "b", "c", "main", TS3, 1.0, TS3).await;
assert_eq!(
reached_at_tx(&conn, "main").await,
["a", "b"],
"depth {depth}: the trunk's fold lost its own retirement"
);
assert_eq!(
reached_at_tx(&conn, &reader).await,
["a", "b", "c", "d"],
"depth {depth}: the fold applied the trunk's post-fork retirement \
to {reader}"
);
}
}
#[tokio::test]
async fn a_grandchild_reads_its_parent_as_of_its_own_fork() {
const T5: &str = "2026-05-01T00:00:00.000000Z";
let harness = TestHarness::new();
let conn = connect(&harness).await;
macrame::schema::run_migrations(&conn).await.unwrap();
for id in ["a", "b", "c", "d"] {
conn.execute(
"INSERT INTO concepts (id, title, valid_from, recorded_at) VALUES (?1, 'N', ?2, ?2)",
libsql::params![id, TS],
)
.await
.unwrap();
}
for (child, parent, forked) in [("L1", "main", TS2), ("L2", "L1", TS4)] {
conn.execute(
"INSERT INTO branches (branch_id, parent_id, forked_at, created_at) VALUES (?1, ?2, ?3, ?3)",
libsql::params![child, parent, forked],
)
.await
.unwrap();
}
for (source, target) in [("a", "b"), ("b", "c"), ("c", "d")] {
edge(&conn, source, target, "main", SENTINEL, 1.0, TS).await;
}
for (id, at) in [("e", TS3), ("f", T5)] {
conn.execute(
"INSERT INTO concepts (id, title, valid_from, recorded_at, branch_id) VALUES (?1, 'N', ?2, ?2, 'L1')",
libsql::params![id, at],
)
.await
.unwrap();
}
edge(&conn, "b", "e", "L1", SENTINEL, 1.0, TS3).await;
edge(&conn, "b", "f", "L1", SENTINEL, 1.0, T5).await;
edge(&conn, "b", "c", "L1", T5, 1.0, T5).await;
assert_eq!(
reached(&conn, Some("L1")).await,
["a", "b", "e", "f"],
"L1 must see all of its own writes, its retirement of b → c included"
);
assert_eq!(
reached(&conn, Some("L2")).await,
["a", "b", "c", "d", "e"],
"L2 must read L1 as of its own fork: the edge L1 asserted before it, neither the one after nor the retirement after — and `c` is reached through main because L1's fold came back empty rather than negative"
);
}
#[tokio::test]
async fn the_trunk_of_a_forked_ledger_has_no_cutoff() {
let harness = TestHarness::new();
let conn = connect(&harness).await;
chain(&conn, 3).await;
late_concept(&conn, "e").await;
edge(&conn, "d", "e", "main", SENTINEL, 1.0, TS3).await;
edge(&conn, "b", "c", "main", SENTINEL, 0.1, TS4).await;
assert_eq!(
reached(&conn, None).await,
["a", "b", "c", "d", "e"],
"the trunk stopped seeing writes it made itself"
);
assert_eq!(
reached(&conn, Some("main")).await,
["a", "b", "c", "d", "e"],
"naming the trunk must mean what not naming it means"
);
assert_eq!(
reached_above(&conn, "main", 0.5).await,
["a", "b"],
"the trunk's own correction stopped taking"
);
}
#[tokio::test]
async fn the_as_of_reader_does_not_hand_a_branch_a_post_fork_edge() {
for depth in DEPTHS {
let harness = TestHarness::new();
let conn = connect(&harness).await;
let reader = chain(&conn, depth).await;
late_concept(&conn, "e").await;
edge(&conn, "d", "e", "main", SENTINEL, 1.0, TS3).await;
assert_eq!(
as_of_arrows(&conn, None).await,
["a→b", "b→c", "c→d", "d→e"],
"depth {depth}: the trunk lost its own write"
);
assert_eq!(
as_of_arrows(&conn, Some(&reader)).await,
["a→b", "b→c", "c→d"],
"depth {depth}: {reader} was handed a trunk edge recorded after it \
forked — the reader resolved lineage and never looked at the cutoff"
);
}
}
#[tokio::test]
async fn the_as_of_reader_keeps_what_its_parent_retired_after_the_fork() {
for depth in DEPTHS {
let harness = TestHarness::new();
let conn = connect(&harness).await;
let reader = chain(&conn, depth).await;
edge(&conn, "b", "c", "main", TS3, 1.0, TS3).await;
assert_eq!(
as_of_arrows(&conn, None).await,
["a→b", "c→d"],
"depth {depth}: the trunk's own retirement did not take"
);
assert_eq!(
as_of_arrows(&conn, Some(&reader)).await,
["a→b", "b→c", "c→d"],
"depth {depth}: {reader} lost an inherited edge to a retirement \
recorded after it forked — the projection row was the trunk's \
closed one, and nothing went to the log for the entry behind it"
);
}
}
#[tokio::test]
async fn the_two_public_readers_agree_about_what_a_lineage_sees() {
for kind in ["new-edge", "reweight", "retirement", "post-fork-only"] {
for depth in DEPTHS {
let harness = TestHarness::new();
let conn = connect(&harness).await;
let reader = chain(&conn, depth).await;
match kind {
"new-edge" => {
late_concept(&conn, "e").await;
edge(&conn, "d", "e", "main", SENTINEL, 1.0, TS3).await;
}
"reweight" => edge(&conn, "b", "c", "main", SENTINEL, 0.1, TS3).await,
"retirement" => edge(&conn, "b", "c", "main", TS3, 1.0, TS3).await,
_ => {
late_concept(&conn, "e").await;
edge(&conn, "a", "e", "main", SENTINEL, 1.0, TS3).await;
edge(&conn, "a", "e", "main", SENTINEL, 0.2, TS4).await;
}
}
for branch in [None, Some(reader.as_str())] {
assert_eq!(
reached_via_as_of(&conn, branch).await,
reached(&conn, branch).await,
"{kind} at depth {depth}: the two public readers disagree \
about what {} sees",
branch.unwrap_or("main")
);
}
}
}
}
#[tokio::test]
async fn the_as_of_reader_leaves_the_trunk_of_a_forked_ledger_alone() {
let harness = TestHarness::new();
let conn = connect(&harness).await;
chain(&conn, 3).await;
late_concept(&conn, "e").await;
edge(&conn, "d", "e", "main", SENTINEL, 1.0, TS3).await;
edge(&conn, "b", "c", "main", SENTINEL, 0.1, TS4).await;
assert_eq!(
as_of_arrows(&conn, None).await,
["a→b", "b→c", "c→d", "d→e"],
"the trunk stopped seeing writes it made itself"
);
assert_eq!(
macrame::temporal::query_as_of_edges_on(&conn, NOW, Some("main"))
.await
.unwrap(),
macrame::temporal::query_as_of_edges(&conn, NOW)
.await
.unwrap()
);
}