prikk-store 0.24.0

Prikk storage crate scaffold.
Documentation
use super::*;

#[test]
fn independent_pair_commutes_only_with_replay_oracle_success() {
    let mut baseline = NodeLifecycleState::new();
    seed_binary(&mut baseline, node(1), "left.bin", blob(1), MODE_REGULAR);
    seed_binary(&mut baseline, node(2), "right.bin", blob(2), MODE_REGULAR);
    let left = replace_binary(11, node(1), blob(1), blob(3));
    let right = change_perm(17, node(2), MODE_REGULAR, MODE_EXECUTABLE);
    let evidence = TestTextResolver::empty().with_blob(blob(3), BlobKind::Binary, b"new".to_vec());

    match commute_pair_result(
        &baseline,
        &evidence,
        EvidenceScope::SealedCandidateRequired,
        &left,
        &right,
    )
    .expect("commutation evidence")
    {
        CommutationResult::Commutes { proof } => {
            assert_eq!(proof.left_op_seq, 11);
            assert_eq!(proof.right_op_seq, 17);
        }
        other => panic!("expected commutes, got {other:?}"),
    }
}

#[test]
fn concrete_ordered_dependency_does_not_commute() {
    let baseline = NodeLifecycleState::new();
    let left = create_file(1, "fresh.bin", node(1), blob(1), MODE_REGULAR);
    let right = change_perm(2, node(1), MODE_REGULAR, MODE_EXECUTABLE);
    let evidence =
        TestTextResolver::empty().with_blob(blob(1), BlobKind::Binary, b"fresh".to_vec());

    match commute_pair_result(
        &baseline,
        &evidence,
        EvidenceScope::UnsealedCandidateOptional,
        &left,
        &right,
    )
    .expect("commutation evidence")
    {
        CommutationResult::DoesNotCommute {
            pair_class: PairClass::OrderedDependency { required_order, .. },
        } => assert_eq!(required_order, RequiredOrder::LeftBeforeRight),
        other => panic!("expected ordered does-not-commute, got {other:?}"),
    }
}

#[test]
fn same_node_text_pair_never_commutes() {
    let mut baseline = NodeLifecycleState::new();
    let old = b"alpha beta gamma";
    seed_text(&mut baseline, node(1), "doc.txt", old, MODE_REGULAR);
    let evidence = TestTextResolver::new([(node(1), old.to_vec())]);
    let left = edit_text(1, node(1), old, b"alpha BETA gamma");
    let right = edit_text(2, node(1), old, b"alpha beta GAMMA");

    match commute_pair_result(
        &baseline,
        &evidence,
        EvidenceScope::SealedCandidateRequired,
        &left,
        &right,
    )
    .expect("commutation evidence")
    {
        CommutationResult::Unknown { reason } => {
            assert_eq!(reason, UnknownReason::SameNodeTextCommutationDeferred);
        }
        other => panic!("expected text deferral, got {other:?}"),
    }
}

#[test]
fn malformed_sealed_candidate_operation_is_evidence_error() {
    let baseline = NodeLifecycleState::new();
    let left = create_file(1, "../escape", node(1), blob(1), MODE_REGULAR);
    let right = create_file(2, "ok.bin", node(2), blob(2), MODE_REGULAR);

    match commute_pair_result(
        &baseline,
        &TestTextResolver::empty(),
        EvidenceScope::SealedCandidateRequired,
        &left,
        &right,
    ) {
        Err(EvidenceError::Malformed {
            scope,
            fact: EvidenceFact::Operation,
            ..
        }) => assert_eq!(scope, EvidenceScope::SealedCandidateRequired),
        other => panic!("expected sealed malformed evidence error, got {other:?}"),
    }
}

#[test]
fn malformed_unsealed_candidate_is_unknown_not_commutes() {
    let baseline = NodeLifecycleState::new();
    let left = create_file(1, "../escape", node(1), blob(1), MODE_REGULAR);
    let right = create_file(2, "ok.bin", node(2), blob(2), MODE_REGULAR);

    match commute_pair_result(
        &baseline,
        &TestTextResolver::empty(),
        EvidenceScope::UnsealedCandidateOptional,
        &left,
        &right,
    )
    .expect("unsealed malformed stays algebraic")
    {
        CommutationResult::Unknown { reason } => {
            assert_eq!(reason, UnknownReason::MalformedOperation);
        }
        other => panic!("expected unsealed malformed unknown, got {other:?}"),
    }
}

#[test]
fn missing_unsealed_create_evidence_is_unknown_not_commutes() {
    let mut baseline = NodeLifecycleState::new();
    seed_binary(&mut baseline, node(9), "other.bin", blob(9), MODE_REGULAR);
    let left = create_file(1, "fresh.bin", node(1), blob(1), MODE_REGULAR);
    let right = replace_binary(2, node(9), blob(9), blob(10));

    match commute_pair_result(
        &baseline,
        &TestTextResolver::empty(),
        EvidenceScope::UnsealedCandidateOptional,
        &left,
        &right,
    )
    .expect("missing unsealed candidate evidence remains algebraic")
    {
        CommutationResult::Unknown { reason } => {
            assert_eq!(reason, UnknownReason::MissingCandidateEvidence);
        }
        other => panic!("expected missing candidate unknown, got {other:?}"),
    }
}

#[test]
fn missing_sealed_create_evidence_is_evidence_error() {
    let mut baseline = NodeLifecycleState::new();
    seed_binary(&mut baseline, node(9), "other.bin", blob(9), MODE_REGULAR);
    let left = create_file(1, "fresh.bin", node(1), blob(1), MODE_REGULAR);
    let right = replace_binary(2, node(9), blob(9), blob(10));

    assert_evidence_error(
        commute_pair_result(
            &baseline,
            &TestTextResolver::empty(),
            EvidenceScope::SealedCandidateRequired,
            &left,
            &right,
        )
        .map(|result| match result {
            CommutationResult::DoesNotCommute { pair_class } => pair_class,
            CommutationResult::Commutes { .. } | CommutationResult::Unknown { .. } => {
                PairClass::Independent
            }
        }),
        EvidenceScope::SealedCandidateRequired,
        EvidenceFact::BlobKind,
    );
}