canic-host 0.109.21

Host-side App build and desired-state Fleet reconciliation library for Canic workspaces
Documentation
use super::*;

use std::{fs, path::PathBuf, time::SystemTime};

#[test]
fn repository_binaryen_authority_matches_every_supported_projection() {
    let pins = include_str!(concat!(
        env!("CARGO_MANIFEST_DIR"),
        "/../../tool-versions.env"
    ));
    for expected in [
        format!("export CANIC_BINARYEN_VERSION={BINARYEN_VERSION}"),
        "export CANIC_BINARYEN_SHA256_DARWIN_ARM64=98aad827847af7ef990ed7098d885725c8e5b5aae75073403635617ae4e259aa".to_string(),
        "export CANIC_BINARYEN_SHA256_DARWIN_X64=40c3de90bb3766bd0282a895e139a6f50253dba49b4f5bb89e66faca162d832e".to_string(),
        "export CANIC_BINARYEN_SHA256_LINUX_X64=195ddc94f9bc89f45abdabb0b9eea86023d727ba90eac8b35b80f2544fc30572".to_string(),
        "export CANIC_BINARYEN_WASM_OPT_SHA256_DARWIN_ARM64=a9c8d09d84186e4c8efe937f3de19b887404d24a96e2638f3bd3b476e17b7218".to_string(),
        "export CANIC_BINARYEN_WASM_OPT_SHA256_DARWIN_X64=c3cbd288eef3402119d8183df1739887ff0e6430caba2e1c801406df725a2bd3".to_string(),
        "export CANIC_BINARYEN_WASM_OPT_SHA256_LINUX_X64=1014958e6f20d412f1542320b43970214b0fb1ed780595e8f7c0d8761ed53725".to_string(),
    ] {
        assert!(pins.lines().any(|line| line == expected));
    }
}

#[cfg(unix)]
#[test]
fn same_version_executable_with_wrong_digest_is_rejected_before_execution() {
    let root = temp_root("wrong-digest");
    fs::create_dir_all(&root).expect("create test root");
    let executable = root.join("wasm-opt");
    fs::write(
        &executable,
        "#!/bin/sh\nprintf 'this must not execute' > execution-marker\nprintf 'wasm-opt version 132 (version_132)\\n'\n",
    )
    .expect("write fake executable");
    fs::set_permissions(&executable, fs::Permissions::from_mode(0o755))
        .expect("make fake executable runnable");

    let error = admit_binaryen_executable(&executable, &"0".repeat(64))
        .expect_err("wrong executable digest must reject");
    let message = error.to_string();

    assert!(matches!(
        error,
        BinaryenToolError::ExecutableHashMismatch { path, .. } if path == executable
    ));
    assert!(message.contains(executable.to_string_lossy().as_ref()));
    assert!(message.contains(BINARYEN_REPAIR_COMMAND));
    assert!(!root.join("execution-marker").exists());
    fs::remove_dir_all(root).expect("remove test root");
}

#[cfg(unix)]
#[test]
fn admitted_executable_records_exact_path_version_and_digest() {
    let root = temp_root("admitted");
    fs::create_dir_all(&root).expect("create test root");
    let executable = root.join("wasm-opt");
    fs::write(
        &executable,
        "#!/bin/sh\nprintf 'wasm-opt version 132 (version_132)\\n'\n",
    )
    .expect("write fake executable");
    fs::set_permissions(&executable, fs::Permissions::from_mode(0o755))
        .expect("make fake executable runnable");
    let digest = sha256_file(&executable).expect("hash fake executable");

    let admitted = admit_binaryen_executable(&executable, &digest).expect("admit exact executable");

    assert_eq!(admitted.path(), executable);
    assert_eq!(admitted.version_identity(), BINARYEN_VERSION_IDENTITY);
    assert_eq!(admitted.sha256(), digest);
    fs::remove_dir_all(root).expect("remove test root");
}

#[cfg(target_os = "linux")]
#[test]
fn staged_installer_closes_its_writer_before_executable_admission() {
    let root = temp_root("staged-admission");
    fs::create_dir_all(&root).expect("create test root");
    let candidate = root.join("candidate-wasm-opt");
    fs::write(
        &candidate,
        "#!/bin/sh\nprintf 'wasm-opt version 132 (version_132)\\n'\n",
    )
    .expect("write fake optimizer candidate");
    fs::set_permissions(&candidate, fs::Permissions::from_mode(0o755))
        .expect("make fake optimizer candidate runnable");
    let digest = sha256_file(&candidate).expect("hash fake optimizer candidate");
    let destination = root.join("bin/wasm-opt");

    publish_executable(&candidate, &destination, &digest)
        .expect("publish and admit closed staged executable");
    let admitted =
        admit_binaryen_executable(&destination, &digest).expect("admit published executable");

    assert_eq!(admitted.path(), destination);
    assert_eq!(admitted.version_identity(), BINARYEN_VERSION_IDENTITY);
    assert_eq!(admitted.sha256(), digest);
    fs::remove_dir_all(root).expect("remove test root");
}

fn temp_root(label: &str) -> PathBuf {
    let nanos = SystemTime::now()
        .duration_since(SystemTime::UNIX_EPOCH)
        .expect("system time after epoch")
        .as_nanos();
    std::env::temp_dir().join(format!(
        "canic-binaryen-{label}-{}-{nanos}",
        std::process::id()
    ))
}