#[path = "common/harness.rs"]
mod harness;
use harness::TestHarness;
use macrame::graph::EdgeAssertion;
use macrame::{ConceptUpsert, Database, DbError};
const T0: &str = "2026-01-01T00:00:00.000000Z";
const OPEN: &str = "9999-12-31T23:59:59.999999Z";
const JAN: &str = "2026-01-01T00:00:00.000000Z";
const MAR: &str = "2026-03-01T00:00:00.000000Z";
const APR: &str = "2026-04-01T00:00:00.000000Z";
const JUN: &str = "2026-06-01T00:00:00.000000Z";
const SEP: &str = "2026-09-01T00:00:00.000000Z";
async fn two_concepts(db: &Database) {
for id in ["a", "b"] {
db.upsert_concept(ConceptUpsert::new(id, id).valid_from(T0))
.await
.unwrap();
}
}
#[tokio::test]
async fn raw_sql_writes_the_overlapping_pair_the_actor_refuses() {
let harness = TestHarness::new();
let db = Database::open(&harness.db_path).await.unwrap();
two_concepts(&db).await;
db.assert_edge(
EdgeAssertion::new("a", "b", "KNOWS")
.valid_from(JAN)
.valid_to(JUN),
)
.await
.unwrap();
let err = db
.assert_edge(
EdgeAssertion::new("a", "b", "KNOWS")
.valid_from(MAR)
.valid_to(SEP),
)
.await
.expect_err("the actor guards this");
assert!(
matches!(err, DbError::OverlappingInterval { .. }),
"got {err:?}"
);
let raw = db.raw().connect().unwrap();
raw.execute(
"INSERT INTO links \
(source_id, target_id, edge_type, valid_from, valid_to, weight, properties, recorded_at) \
VALUES ('a', 'b', 'KNOWS', ?1, ?2, 1.0, '{}', ?3)",
libsql::params![MAR, SEP, T0],
)
.await
.expect(
"§4.7: the schema does not guard closed-interval overlap. If this now \
fails, a migration has closed the gap and §4.7 and D-060 need updating.",
);
let edges = macrame::temporal::query_as_of_edges(db.read_conn(), APR)
.await
.unwrap();
assert_eq!(
edges.len(),
2,
"one relationship returned twice — the wrong answer the actor's guard \
prevents for writers who go through it"
);
db.close().await.unwrap();
}
#[tokio::test]
async fn a_negative_weight_is_refused_by_the_schema_through_every_door() {
let harness = TestHarness::new();
let db = Database::open(&harness.db_path).await.unwrap();
two_concepts(&db).await;
let via_api = db
.assert_edge(
EdgeAssertion::new("a", "b", "KNOWS")
.valid_from(T0)
.valid_to(OPEN)
.weight(-1.5),
)
.await;
assert!(
via_api.is_err(),
"§4.7/D-083: schema v7 refuses a negative weight — got {via_api:?}"
);
let raw = db.raw().connect().unwrap();
let via_raw = raw
.execute(
"INSERT INTO links (source_id, target_id, edge_type, valid_from, valid_to, \
weight, properties, recorded_at) VALUES ('a','b','CITES',?1,?2,-1.5,'{}',?1)",
libsql::params![T0, OPEN],
)
.await;
assert!(
via_raw.is_err(),
"§4.7/D-083: raw SQL must not be able to write a negative weight either \
— got {via_raw:?}"
);
let into_current = raw
.execute(
"INSERT INTO links_current (source_id, target_id, edge_type, valid_from, \
valid_to, weight, properties, recorded_at) \
VALUES ('a','b','KNOWS',?1,?2,-1.5,'{}',?1)",
libsql::params![T0, OPEN],
)
.await;
assert!(
into_current.is_ok(),
"links_current must stay unconstrained — got {into_current:?}"
);
let err = db.load_subgraph("a", 2, T0, 1 << 20).await.unwrap_err();
assert!(
matches!(err, DbError::NegativeEdgeWeight { weight, .. } if weight == -1.5),
"got {err:?}"
);
db.close().await.unwrap();
}
#[tokio::test]
async fn a_text_weight_is_refused_because_reading_one_panics() {
let harness = TestHarness::new();
let db = Database::open(&harness.db_path).await.unwrap();
two_concepts(&db).await;
let raw = db.raw().connect().unwrap();
let planted = raw
.execute(
"INSERT INTO links (source_id, target_id, edge_type, valid_from, valid_to, \
weight, properties, recorded_at) VALUES ('a','b','CITES',?1,?2,'abc','{}',?1)",
libsql::params![T0, OPEN],
)
.await;
assert!(
planted.is_err(),
"§4.7/D-083: `weight >= 0.0` alone admits text, so the constraint pins \
typeof too — got {planted:?}"
);
db.close().await.unwrap();
}
#[tokio::test]
async fn an_infinite_weight_is_refused_because_the_log_cannot_carry_it() {
let harness = TestHarness::new();
let db = Database::open(&harness.db_path).await.unwrap();
two_concepts(&db).await;
let via_api = db
.assert_edge(
EdgeAssertion::new("a", "b", "KNOWS")
.valid_from(T0)
.valid_to(OPEN)
.weight(f64::INFINITY),
)
.await;
assert!(
via_api.is_err(),
"§4.7/D-083: +inf must not reach links.weight — got {via_api:?}"
);
let raw = db.raw().connect().unwrap();
let via_raw = raw
.execute(
"INSERT INTO links (source_id, target_id, edge_type, valid_from, valid_to, \
weight, properties, recorded_at) VALUES ('a','b','CITES',?1,?2,9e999,'{}',?1)",
libsql::params![T0, OPEN],
)
.await;
assert!(
via_raw.is_err(),
"§4.7/D-083: raw SQL must not write an infinite weight either — got \
{via_raw:?}"
);
db.close()
.await
.expect("an infinite weight in the log makes reconstruct() fail");
}
#[tokio::test]
async fn read_conn_refuses_a_write_and_raw_does_not() {
let harness = TestHarness::new();
let db = Database::open(&harness.db_path).await.unwrap();
let refused = db
.read_conn()
.execute(
"INSERT INTO concepts (id, title, valid_from, recorded_at) \
VALUES ('x', 'x', ?1, ?1)",
libsql::params![T0],
)
.await;
assert!(
refused.is_err(),
"read_conn must stay query_only (D-019) — got {refused:?}"
);
let permitted = db
.raw()
.connect()
.unwrap()
.execute(
"INSERT INTO concepts (id, title, valid_from, recorded_at) \
VALUES ('x', 'x', ?1, ?1)",
libsql::params![T0],
)
.await;
assert!(
permitted.is_ok(),
"§4.7/D-068: raw() is an unprotected connection by design — got \
{permitted:?}"
);
db.close().await.unwrap();
}
#[tokio::test]
async fn a_nan_weight_is_refused_by_the_storage_layer_not_the_loader() {
let harness = TestHarness::new();
let db = Database::open(&harness.db_path).await.unwrap();
two_concepts(&db).await;
let via_api = db
.assert_edge(
EdgeAssertion::new("a", "b", "KNOWS")
.valid_from(T0)
.valid_to(OPEN)
.weight(f64::NAN),
)
.await;
assert!(
via_api.is_err(),
"§4.7/D-078: NaN must not reach links.weight — got {via_api:?}"
);
let raw = db.raw().connect().unwrap();
let bound = raw
.execute(
"INSERT INTO links (source_id, target_id, edge_type, valid_from, valid_to, \
weight, properties, recorded_at) VALUES ('a','b','CITES',?1,?2,?3,'{}',?1)",
libsql::params![T0, OPEN, f64::NAN],
)
.await;
assert!(
bound.is_err(),
"§4.7/D-078: raw SQL binding NaN must still be refused — got {bound:?}"
);
let literal = raw
.execute(
"INSERT INTO links (source_id, target_id, edge_type, valid_from, valid_to, \
weight, properties, recorded_at) \
VALUES ('a','b','CITES2',?1,?2, 0.0/0.0, '{}', ?1)",
libsql::params![T0, OPEN],
)
.await;
assert!(
literal.is_err(),
"§4.7/D-078: an engine-computed NaN must be refused too — got {literal:?}"
);
let mut rows = raw.query("SELECT COUNT(*) FROM links", ()).await.unwrap();
let n: i64 = rows.next().await.unwrap().unwrap().get(0).unwrap();
assert_eq!(n, 0, "a NaN weight reached links");
db.close().await.unwrap();
}