Luigit
repositories / smith

smith

There are many coding harnesses - but this one is fast

owned by admin

smith-harness/tests/wasm_host.rs

Raw
//! Wasm host lifecycle: validate, instantiate, declare, invoke, fuel
//! (`SMH-SPEC-WASM0001`).

use smith_harness::wasm::{PluginEngine, PluginInstance};

/// Build the echo artifact, returning its path.
fn echo_artifact() -> std::path::PathBuf {
    let status = std::process::Command::new("cargo")
        .args([
            "build",
            "-p",
            "smith-plugin-echo",
            "--target",
            "wasm32-wasip2",
        ])
        .status()
        .unwrap();
    assert!(status.success(), "echo plugin build failed");
    let manifest = std::env::var("CARGO_MANIFEST_DIR").unwrap();
    std::path::Path::new(&manifest).join("../target/wasm32-wasip2/debug/smith_plugin_echo.wasm")
}

#[test]
fn echo_plugin_loads_declares_and_invokes() {
    let artifact = echo_artifact();
    let engine = PluginEngine::new().unwrap();
    let mut instance = PluginInstance::load(&engine, &artifact).unwrap();

    let tools = instance.declare_tools().unwrap();
    assert_eq!(tools.len(), 1);
    assert_eq!(tools[0].name, "echo");

    let echoed = instance.invoke("echo", "{\"text\":\"hi\"}").unwrap();
    assert_eq!(echoed, "{\"text\":\"hi\"}");

    let rejected = match instance.invoke("nope", "{}") {
        Err(error) => error,
        Ok(value) => panic!("expected plugin error, got {value}"),
    };
    assert!(rejected.to_string().contains("unknown tool: nope"));
}

#[test]
fn invalid_artifact_fails_validation() {
    let junk = std::env::temp_dir().join(format!("smith_junk_{}.wasm", std::process::id()));
    std::fs::write(&junk, b"not a component").unwrap();
    let engine = PluginEngine::new().unwrap();
    let Err(error) = PluginInstance::load(&engine, &junk) else {
        panic!("expected validation failure")
    };
    assert!(error.to_string().contains("validation failed"));
    let _ = std::fs::remove_file(&junk);
}