harn-vm 0.10.121

Async bytecode virtual machine for the Harn programming language
Documentation
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::sync::Mutex;

use super::*;

struct FailingProbeRunner(String);

impl ToolchainProbeRunner for FailingProbeRunner {
    fn run(&self, _probe: &ToolchainProbeRequirement) -> Result<ToolchainProbeResult, String> {
        Err(self.0.clone())
    }
}

#[derive(Default)]
struct ToggleReceiptSink {
    fail: AtomicBool,
    receipts: Mutex<Vec<RunAuthorityReceipt>>,
}

impl AuthorityReceiptSink for ToggleReceiptSink {
    fn persist(&self, receipt: &RunAuthorityReceipt) -> Result<(), String> {
        if self.fail.load(Ordering::SeqCst) {
            return Err("fixture receipt persistence failure".to_string());
        }
        self.receipts
            .lock()
            .expect("fixture receipt sink poisoned")
            .push(receipt.clone());
        Ok(())
    }
}

#[test]
fn missing_toolchain_discovery_leaves_parent_lease_executable() {
    failed_optional_discovery_leaves_parent_lease_executable(&format!(
        "toolchain executable was not found: {SECRET_CANARY}"
    ));
}

#[test]
fn malformed_toolchain_discovery_leaves_parent_lease_executable() {
    failed_optional_discovery_leaves_parent_lease_executable(&format!(
        "toolchain probe returned malformed output: {SECRET_CANARY}"
    ));
}

fn failed_optional_discovery_leaves_parent_lease_executable(error: &str) {
    let probe = toolchain_probe("/toolchains");
    let model_calls = Arc::new(AtomicUsize::new(0));
    let run = PreparedRun::with_clock(
        FixtureExecutor {
            requirements: Vec::new(),
            model_calls: model_calls.clone(),
        },
        Arc::new(MemoryAuthorityReceiptSink::default()),
        Arc::new(|| NOW_MS),
    );
    let mut run_intent = intent();
    run_intent.toolchain_probes = vec![probe.clone()];
    let mut host = host_facts();
    host.toolchain_probes.insert(probe.clone());
    let mut lease = approved_lease(&run, &run_intent, &host);

    match run.discover_toolchain(&mut lease, &probe, &FailingProbeRunner(error.to_string())) {
        ToolchainDiscoveryOutcome::Blocked {
            diagnostics,
            receipt,
        } => {
            assert_eq!(diagnostics[0].code, "toolchain_probe_failed");
            assert!(!format!("{diagnostics:?}").contains(SECRET_CANARY));
            assert!(!serde_json::to_string(&receipt)
                .expect("serialize discovery receipt")
                .contains(SECRET_CANARY));
        }
        other => panic!("failed optional probe must be receipted, got {other:?}"),
    }
    match run.execute(lease) {
        ExecutionOutcome::Completed { .. } => {}
        ExecutionOutcome::ExecutorFailed { error, .. }
        | ExecutionOutcome::AuthorityFailed { error, .. } => {
            panic!("failed optional discovery invalidated the parent lease: {error}")
        }
    }
    assert_eq!(model_calls.load(Ordering::SeqCst), 1);
}

#[test]
fn expired_toolchain_discovery_invalidates_parent_lease() {
    let clock = Arc::new(AtomicU64::new(NOW_MS));
    let probe = toolchain_probe("/toolchains");
    let run = PreparedRun::with_clock(
        FixtureExecutor {
            requirements: Vec::new(),
            model_calls: Arc::new(AtomicUsize::new(0)),
        },
        Arc::new(MemoryAuthorityReceiptSink::default()),
        {
            let clock = clock.clone();
            Arc::new(move || clock.load(Ordering::SeqCst))
        },
    );
    let mut run_intent = intent();
    run_intent.toolchain_probes = vec![probe.clone()];
    let mut host = host_facts();
    host.toolchain_probes.insert(probe.clone());
    let mut lease = approved_lease(&run, &run_intent, &host);
    clock.store(DEADLINE_MS + 1, Ordering::SeqCst);

    match run.discover_toolchain(
        &mut lease,
        &probe,
        &FailingProbeRunner("runner must not be invoked".to_string()),
    ) {
        ToolchainDiscoveryOutcome::Blocked { diagnostics, .. } => {
            assert_eq!(diagnostics[0].code, "toolchain_discovery_lease_expired");
        }
        other => panic!("expired discovery must block, got {other:?}"),
    }
    assert!(lease.invalidated.is_some());
}

#[test]
fn probe_outside_fingerprinted_lease_invalidates_parent_lease() {
    let probe = toolchain_probe("/toolchains");
    let run = PreparedRun::with_clock(
        FixtureExecutor {
            requirements: Vec::new(),
            model_calls: Arc::new(AtomicUsize::new(0)),
        },
        Arc::new(MemoryAuthorityReceiptSink::default()),
        Arc::new(|| NOW_MS),
    );
    let mut run_intent = intent();
    run_intent.toolchain_probes = vec![probe.clone()];
    let mut host = host_facts();
    host.toolchain_probes.insert(probe.clone());
    let mut lease = approved_lease(&run, &run_intent, &host);
    let mut unreviewed_probe = probe;
    unreviewed_probe.arguments.push("--unreviewed".to_string());

    match run.discover_toolchain(
        &mut lease,
        &unreviewed_probe,
        &FailingProbeRunner("runner must not be invoked".to_string()),
    ) {
        ToolchainDiscoveryOutcome::Blocked { diagnostics, .. } => {
            assert_eq!(diagnostics[0].code, "toolchain_probe_outside_lease");
        }
        other => panic!("unreviewed probe must block, got {other:?}"),
    }
    assert!(lease.invalidated.is_some());
}

#[test]
fn discovery_receipt_persistence_failure_invalidates_parent_lease() {
    let probe = toolchain_probe("/toolchains");
    let sink = Arc::new(ToggleReceiptSink::default());
    let run = PreparedRun::with_clock(
        FixtureExecutor {
            requirements: Vec::new(),
            model_calls: Arc::new(AtomicUsize::new(0)),
        },
        sink.clone(),
        Arc::new(|| NOW_MS),
    );
    let mut run_intent = intent();
    run_intent.toolchain_probes = vec![probe.clone()];
    let mut host = host_facts();
    host.toolchain_probes.insert(probe.clone());
    let mut lease = approved_lease(&run, &run_intent, &host);
    sink.fail.store(true, Ordering::SeqCst);

    match run.discover_toolchain(
        &mut lease,
        &probe,
        &FixtureProbeRunner {
            result: ToolchainProbeResult::default(),
            calls: Arc::new(AtomicUsize::new(0)),
        },
    ) {
        ToolchainDiscoveryOutcome::Blocked { diagnostics, .. } => {
            assert_eq!(diagnostics[0].code, "discovery_receipt_persistence");
        }
        other => panic!("unreceipted discovery must block, got {other:?}"),
    }
    assert!(lease.invalidated.is_some());
}