use crate::compiler::Compiler;
use crate::stdlib::register_vm_stdlib;
use crate::NativeVmExt;
use crate::VmValue;
use harn_lexer::Lexer;
use harn_parser::Parser;
use std::sync::Arc;
use super::harness::*;
#[test]
fn test_direct_builtin_call_uses_registered_sync_id() {
let (out, _) = run_harn_with_setup(
r#"pipeline t(harness: Harness, task: unknown) { test_sync("ok") }"#,
|vm| {
vm.register_builtin("test_sync", |args, out| {
out.push_str("sync:");
out.push_str(&args[0].display());
Ok(VmValue::Nil)
});
},
)
.unwrap();
assert_eq!(out, "sync:ok");
}
#[test]
fn test_direct_builtin_call_uses_registered_async_id() {
let (out, _) = run_harn_with_setup(
r#"pipeline t(harness: Harness, task: unknown) {
const value = test_async("ok")
harness.stdio.log(value)
}"#,
|vm| {
vm.register_async_builtin("test_async", |_ctx, args| async move {
Ok(VmValue::string(format!("async:{}", args[0].display())))
});
},
)
.unwrap();
assert_eq!(out.trim(), "[harn] async:ok");
}
#[rstest::rstest]
#[case::test_direct_builtin_callback_uses_builtin_ref_id(
r#"pipeline t(harness: Harness, task: unknown) {
const converted = ["first_name"].map(snake_to_camel)
harness.stdio.log(converted[0])
}"#,
"[harn] firstName"
)]
#[case::test_direct_builtin_call_preserves_function_shadowing(
r#"pipeline t(harness: Harness, task: unknown) {
fn push(xs, x) {
harness.stdio.log("shadow")
}
push([1], 2)
}"#,
"[harn] shadow"
)]
#[case::test_direct_builtin_call_preserves_local_closure_shadowing(
r#"pipeline t(harness: Harness, task: unknown) {
const push = { xs, x -> harness.stdio.log("local") }
push([1], 2)
}"#,
"[harn] local"
)]
fn output_run_output(#[case] source: &str, #[case] expected: &str) {
assert_eq!(run_output(source), expected);
}
#[test]
fn test_direct_builtin_call_falls_back_to_bridge() {
let rt = crate::test_support::current_thread_runtime();
let out = rt.block_on(harn_clock::test_support::with_local_tasks(async {
let tmp = tempfile::tempdir().unwrap();
let host_path = tmp.path().join("host.harn");
std::fs::write(
&host_path,
r#"pub fn bridge_echo(value) { return "bridge:" + value }"#,
)
.unwrap();
let mut host_vm = crate::new_vm();
register_vm_stdlib(&mut host_vm);
let bridge = crate::bridge::HostBridge::from_harn_module(host_vm, &host_path)
.await
.unwrap();
let source = r#"pipeline t(harness: Harness, task: unknown) { harness.stdio.log(bridge_echo("ok")) }"#;
let mut lexer = Lexer::new(source);
let tokens = lexer.tokenize().unwrap();
let mut parser = Parser::new(tokens);
let program = parser.parse().unwrap();
let chunk = Compiler::new().compile(&program).unwrap();
let mut vm = crate::new_vm();
register_vm_stdlib(&mut vm);
vm.set_bridge(Arc::new(bridge));
vm.execute(&chunk).await.unwrap();
vm.output().trim().to_string()
}));
assert_eq!(out, "[harn] bridge:ok");
}