canic-host 0.70.7

Host-side build, install, deployment, and fleet-template library for Canic workspaces
Documentation
use super::super::*;

#[test]
fn external_upgrade_completion_report_marks_verified_completion() {
    let (proposal, consent_evidence, verification_check) = sample_external_completion_sources();

    let report = external_upgrade_completion_report_from_evidence(
        "external-upgrade-completion-1",
        &proposal,
        &consent_evidence,
        &verification_check,
    )
    .expect("completion report should build");

    assert_eq!(report.report_id, "external-upgrade-completion-1");
    assert_eq!(report.proposal_id, proposal.proposal_id);
    assert_eq!(report.consent_evidence_id, consent_evidence.evidence_id);
    assert_eq!(report.verification_check_id, verification_check.check_id);
    assert_eq!(
        report.completion_status,
        ExternalUpgradeCompletionStatusV1::VerifiedComplete
    );
    assert!(report.blockers.is_empty());
    assert_eq!(report.report_digest.len(), 64);
    validate_external_upgrade_completion_report(&report).expect("report should validate");
    validate_external_upgrade_completion_report_for_evidence(
        &report,
        &proposal,
        &consent_evidence,
        &verification_check,
    )
    .expect("report should validate against evidence");
    assert_json_round_trip(&report);
}

#[test]
fn external_upgrade_completion_report_does_not_complete_from_supplied_observation() {
    let (proposal, consent_evidence, _) = sample_external_completion_sources();
    let policy = external_upgrade_verification_policy_from_proposal(
        "external-upgrade-verification-policy-1",
        &proposal,
    );
    let verification_check = external_upgrade_verification_check_from_policy(
        "external-upgrade-verification-check-1",
        &policy,
        matching_external_verification_observation(&proposal),
    );

    let report = external_upgrade_completion_report_from_evidence(
        "external-upgrade-completion-1",
        &proposal,
        &consent_evidence,
        &verification_check,
    )
    .expect("completion report should build");

    assert_eq!(
        report.verification_observation_source,
        ExternalVerificationObservationSourceV1::SuppliedObservation
    );
    assert_eq!(
        report.completion_status,
        ExternalUpgradeCompletionStatusV1::AwaitingVerification
    );
    assert_ne!(
        report.completion_status,
        ExternalUpgradeCompletionStatusV1::VerifiedComplete
    );
    assert!(!report.blockers.is_empty());
}

#[test]
fn external_upgrade_completion_report_marks_verification_failed() {
    let (proposal, consent_evidence, _) = sample_external_completion_sources();
    let policy = external_upgrade_verification_policy_from_proposal(
        "external-upgrade-verification-policy-1",
        &proposal,
    );
    let mut observation = matching_external_verification_observation(&proposal);
    observation.observed_module_hash = Some("wrong-module-hash".to_string());
    let verification_check = external_upgrade_verification_check_from_policy(
        "external-upgrade-verification-check-1",
        &policy,
        observation,
    );

    let report = external_upgrade_completion_report_from_evidence(
        "external-upgrade-completion-1",
        &proposal,
        &consent_evidence,
        &verification_check,
    )
    .expect("completion report should build");

    assert_eq!(
        report.completion_status,
        ExternalUpgradeCompletionStatusV1::VerificationFailed
    );
    assert_eq!(report.blockers.len(), 1);
}

#[test]
fn external_upgrade_completion_report_validation_rejects_stale_evidence() {
    let (proposal, mut consent_evidence, verification_check) = sample_external_completion_sources();
    let report = external_upgrade_completion_report_from_evidence(
        "external-upgrade-completion-1",
        &proposal,
        &consent_evidence,
        &verification_check,
    )
    .expect("completion report should build");
    consent_evidence.evidence_id = "other-consent-evidence".to_string();

    let err = validate_external_upgrade_completion_report_for_evidence(
        &report,
        &proposal,
        &consent_evidence,
        &verification_check,
    )
    .expect_err("stale evidence should fail");

    assert_eq!(
        err,
        ExternalUpgradeCompletionReportError::ConsentEvidence(
            ExternalUpgradeConsentEvidenceError::DigestMismatch {
                field: "evidence_digest"
            }
        )
    );
}

#[test]
fn external_upgrade_completion_report_json_shape_is_stable() {
    let (proposal, consent_evidence, verification_check) = sample_external_completion_sources();
    let report = external_upgrade_completion_report_from_evidence(
        "external-upgrade-completion-1",
        &proposal,
        &consent_evidence,
        &verification_check,
    )
    .expect("completion report should build");
    let encoded = serde_json::to_value(&report).expect("report should encode");

    assert_object_keys(
        &encoded,
        &[
            "schema_version",
            "report_id",
            "report_digest",
            "proposal_id",
            "proposal_digest",
            "consent_evidence_id",
            "consent_evidence_digest",
            "verification_check_id",
            "verification_check_digest",
            "subject",
            "canister_id",
            "role",
            "consent_state",
            "verification_result",
            "verification_observation_source",
            "completion_status",
            "blockers",
            "next_actions",
            "status_summary",
        ],
    );
}

#[test]
fn external_upgrade_completion_report_request_json_shape_is_stable() {
    let (proposal, consent_evidence, verification_check) = sample_external_completion_sources();
    let request = ExternalUpgradeCompletionReportRequest {
        report_id: "external-upgrade-completion-1".to_string(),
        proposal,
        consent_evidence,
        verification_check,
    };
    let encoded = serde_json::to_value(&request).expect("request should encode");

    assert_object_keys(
        &encoded,
        &[
            "report_id",
            "proposal",
            "consent_evidence",
            "verification_check",
        ],
    );
    assert_json_round_trip(&request);
}

#[test]
fn external_upgrade_completion_report_text_reports_passive_boundary() {
    let (proposal, consent_evidence, verification_check) = sample_external_completion_sources();
    let report = external_upgrade_completion_report_from_evidence(
        "external-upgrade-completion-1",
        &proposal,
        &consent_evidence,
        &verification_check,
    )
    .expect("completion report should build");

    let text = external_upgrade_completion_report_text(&report);

    assert!(text.contains("External upgrade completion report"));
    assert!(text.contains("mode: passive"));
    assert!(text.contains("execution: none"));
    assert!(text.contains("live_lookup: none"));
    assert!(text.contains("completion_status: verified_complete"));
}