use super::*;
fn stmt(label: &str) -> SqlStatement {
SqlStatement {
sql: "UPDATE t SET x = ? WHERE id = ?".to_string(),
params: vec![],
label: Some(label.to_string()),
}
}
fn guarded(label: &str, guard: AffectedRowGuard) -> PlanStatement {
PlanStatement {
statement: stmt(label),
guard: Some(guard),
}
}
fn unguarded(label: &str) -> PlanStatement {
PlanStatement {
statement: stmt(label),
guard: None,
}
}
#[test]
fn affected_row_guard_exactly_holds_only_for_n() {
let g = AffectedRowGuard::exactly(1);
assert!(!g.holds_for(0));
assert!(g.holds_for(1));
assert!(!g.holds_for(2));
}
#[test]
fn affected_row_guard_at_least_one_has_no_upper_bound() {
let g = AffectedRowGuard::at_least_one();
assert!(!g.holds_for(0));
assert!(g.holds_for(1));
assert!(g.holds_for(1_000));
}
#[test]
fn update_plan_guard_is_anchored_to_the_row_statement_not_the_fts_mirror() {
let id = Uuid::new_v4();
let plan = UpdatePlan {
graph_effects: Vec::new(),
entity_guard: None,
note_guard: None,
note_vector_purge: None,
note_embedding_inheritance: None,
target_id: id,
statements: vec![
guarded("update-row", AffectedRowGuard::exactly(1)),
unguarded("update-fts-mirror"),
],
post_commit: PostCommitEffect::ReindexEntity { entity_id: id },
edge_natural_key: None,
idempotent_noop: false,
};
assert_eq!(plan.target_id, id);
assert_eq!(plan.statements[0].guard, Some(AffectedRowGuard::exactly(1)));
assert_eq!(plan.statements[1].guard, None);
assert_eq!(
plan.post_commit,
PostCommitEffect::ReindexEntity { entity_id: id }
);
}
#[test]
fn delete_plan_guard_is_anchored_to_the_target_row_not_the_cascade() {
let plan = DeletePlan {
target_id: Uuid::new_v4(),
post_commit: PostCommitEffect::None,
statements: vec![
guarded("delete-row", AffectedRowGuard::exactly(1)),
unguarded("cascade-edges"),
],
};
let row_guard = plan.statements[0].guard.expect("row delete is guarded");
assert!(row_guard.holds_for(1));
assert!(!row_guard.holds_for(0));
assert_eq!(plan.statements[1].guard, None);
}
#[test]
fn link_plan_guard_is_the_endpoint_existence_probe_itself() {
let source = Uuid::new_v4();
let target = Uuid::new_v4();
let plan = LinkPlan {
source_id: source,
target_id: target,
statements: vec![guarded(
"insert-edge-where-exists",
AffectedRowGuard::exactly(1),
)],
disposition: khive_storage::EdgeUpsertDisposition::Created,
};
assert_eq!(plan.source_id, source);
assert_eq!(plan.target_id, target);
let guard = plan.statements[0].guard.expect("link insert is guarded");
assert!(!guard.holds_for(0));
}
#[test]
fn merge_plan_rewires_are_never_guarded_lifecycle_writes_always_are() {
let into = Uuid::new_v4();
let from = Uuid::new_v4();
let rewire = PlanPredicate {
description: "source_id = :from".to_string(),
statement: SqlStatement {
sql: "UPDATE graph_edges SET source_id = ? WHERE source_id = ?".to_string(),
params: vec![],
label: Some("merge-rewire".to_string()),
},
};
let plan = MergePlan {
into_id: into,
from_id: from,
rewires: vec![rewire],
lifecycle: vec![guarded(
"tombstone-from-entity",
AffectedRowGuard::exactly(1),
)],
};
assert_eq!(plan.into_id, into);
assert_eq!(plan.from_id, from);
assert_eq!(plan.rewires[0].description, "source_id = :from");
let lifecycle_guard = plan.lifecycle[0].guard.expect("lifecycle write is guarded");
assert!(!lifecycle_guard.holds_for(0));
}
#[test]
fn gtd_transition_plan_triggers_no_reindex_by_construction() {
let plan = GtdTransitionPlan {
task_id: Uuid::new_v4(),
statements: vec![guarded("update-status", AffectedRowGuard::exactly(1))],
idempotent_noop: false,
post_commit: PostCommitEffect::None,
};
assert_eq!(plan.statements.len(), 1);
assert!(plan.statements[0].guard.is_some());
assert_eq!(plan.post_commit, PostCommitEffect::None);
}
#[test]
fn gtd_transition_plan_idempotent_noop_carries_guarded_assertion_and_no_audit() {
let plan = GtdTransitionPlan {
task_id: Uuid::new_v4(),
statements: vec![guarded(
"assert-noop-snapshot",
AffectedRowGuard::exactly(1),
)],
idempotent_noop: true,
post_commit: PostCommitEffect::None,
};
assert_eq!(plan.statements.len(), 1);
assert!(plan.statements[0].guard.is_some());
assert!(plan.is_idempotent_noop());
assert_eq!(plan.post_commit, PostCommitEffect::None);
}
#[test]
fn gtd_transition_plan_carries_gtd_audit_post_commit_effect() {
let task_id = Uuid::new_v4();
let plan = GtdTransitionPlan {
task_id,
statements: vec![guarded("update-status", AffectedRowGuard::exactly(1))],
idempotent_noop: false,
post_commit: PostCommitEffect::GtdAudit {
task_id,
from_status: "inbox".to_string(),
to_status: "next".to_string(),
note: Some("handed off".to_string()),
namespace: "local".to_string(),
},
};
assert_eq!(
plan.post_commit,
PostCommitEffect::GtdAudit {
task_id,
from_status: "inbox".to_string(),
to_status: "next".to_string(),
note: Some("handed off".to_string()),
namespace: "local".to_string(),
}
);
}
#[test]
fn gtd_complete_plan_guards_the_single_snapshot_property_write() {
let plan = GtdCompletePlan {
task_id: Uuid::new_v4(),
statements: vec![guarded(
"update-status-and-completed-at",
AffectedRowGuard::exactly(1),
)],
post_commit: PostCommitEffect::None,
};
assert_eq!(plan.statements.len(), 1);
let guard = plan.statements[0]
.guard
.expect("snapshot property write is guarded");
assert!(guard.holds_for(1));
}
#[test]
fn governance_plan_covers_all_three_lifecycle_ops() {
for op in [
GovernanceOp::Propose,
GovernanceOp::Review,
GovernanceOp::Withdraw,
] {
let plan = GovernancePlan {
op,
proposal_id: Uuid::new_v4(),
statements: vec![guarded("governance-event", AffectedRowGuard::exactly(1))],
};
assert_eq!(plan.op, op);
assert!(plan.statements[0].guard.is_some());
}
}
#[test]
fn add_entity_plan_guard_is_anchored_to_the_row_statement_not_the_fts_mirror() {
let id = Uuid::new_v4();
let plan = AddEntityPlan {
entity_id: id,
statements: vec![
guarded("entity-insert", AffectedRowGuard::exactly(1)),
unguarded("entity-fts-insert"),
],
post_commit: PostCommitEffect::ReindexEntity { entity_id: id },
};
assert_eq!(plan.entity_id, id);
assert_eq!(plan.statements[0].guard, Some(AffectedRowGuard::exactly(1)));
assert_eq!(plan.statements[1].guard, None);
assert_eq!(
plan.post_commit,
PostCommitEffect::ReindexEntity { entity_id: id }
);
}
#[test]
fn add_note_plan_guard_is_anchored_to_the_row_statement_not_the_fts_mirror() {
let id = Uuid::new_v4();
let plan = AddNotePlan {
note_guard: None,
note_id: id,
statements: vec![
guarded("note-insert", AffectedRowGuard::exactly(1)),
unguarded("note-fts-insert"),
],
post_commit: PostCommitEffect::ReindexNote {
note_id: id,
version: 1,
},
};
assert_eq!(plan.note_id, id);
assert_eq!(plan.statements[0].guard, Some(AffectedRowGuard::exactly(1)));
assert_eq!(plan.statements[1].guard, None);
assert_eq!(
plan.post_commit,
PostCommitEffect::ReindexNote {
note_id: id,
version: 1
}
);
}
#[test]
fn plans_are_plain_data_no_async_no_embedding() {
let _ = PostCommitEffect::None;
}