harn-vm 0.10.17

Async bytecode virtual machine for the Harn programming language
Documentation
use crate::orchestration::{
    clear_runtime_hooks, register_vm_hook_lazy, run_lifecycle_hooks_with_ctx, HookEvent,
};
use crate::{register_vm_stdlib, AsyncBuiltinCtx, LazyVmCallable, Vm};

#[tokio::test(flavor = "current_thread")]
async fn lazy_hook_module_state_survives_repeated_child_invocations() {
    crate::reset_thread_local_state();
    clear_runtime_hooks();
    let dir = tempfile::tempdir().expect("tempdir");
    let module_path = dir.path().join("lazy_hook.harn");
    let marker = dir.path().join("hook-count.txt");
    let marker_literal = serde_json::to_string(&marker.to_string_lossy()).expect("marker literal");
    std::fs::write(
        &module_path,
        format!(
            r"
let counter = 0

pub fn handle(_payload: dict) -> nil {{
  counter = counter + 1
  write_file({marker_literal}, to_string(counter))
  return nil
}}
"
        ),
    )
    .expect("write lazy hook module");
    register_vm_hook_lazy(
        HookEvent::SessionStart,
        "*",
        "handle",
        LazyVmCallable::new(module_path, "handle"),
    );

    let mut vm = Vm::new();
    register_vm_stdlib(&mut vm);
    vm.set_source_dir(dir.path());
    let ctx = AsyncBuiltinCtx::for_test(vm);
    let payload = serde_json::json!({"session": {"id": "lazy-hook-test"}});
    run_lifecycle_hooks_with_ctx(Some(&ctx), HookEvent::SessionStart, &payload)
        .await
        .expect("first hook invocation");
    run_lifecycle_hooks_with_ctx(Some(&ctx), HookEvent::SessionStart, &payload)
        .await
        .expect("second hook invocation");

    assert_eq!(std::fs::read_to_string(marker).expect("marker"), "2");
    clear_runtime_hooks();
}