use super::*;
use std::sync::Arc;
struct TrustedHostDispatchBridge;
impl crate::HostCallBridge for TrustedHostDispatchBridge {
fn dispatch<'a>(
&'a self,
capability: &'a str,
operation: &'a str,
_params: &'a crate::value::DictMap,
) -> crate::stdlib::host::HostCallDispatchFuture<'a> {
assert_eq!(capability, "cloud");
assert_eq!(operation, "echo");
crate::host_call_ready(Ok(Some(VmValue::String(arcstr::ArcStr::from("bridged")))))
}
}
#[test]
fn trusted_host_dispatch_is_explicit_transitive_and_executable() {
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.expect("runtime builds");
let temp = tempfile::tempdir().expect("tempdir");
let helper = temp.path().join("helper.harn");
let entry = temp.path().join("entry.harn");
std::fs::write(
&helper,
"pub fn dispatch(payload) { return host_call(\"cloud.echo\", payload) }\n",
)
.expect("write helper");
std::fs::write(
&entry,
"import { dispatch } from \"./helper\"\npub fn route(payload) { return dispatch(payload) }\n",
)
.expect("write entry");
runtime.block_on(async {
let mut ordinary = crate::new_vm();
crate::stdlib::register_vm_stdlib(&mut ordinary);
let error = ordinary
.load_module_exports(&entry)
.await
.expect_err("ordinary module graph must reject host_call while compiling");
assert!(error.to_string().contains("host_call"), "{error}");
let local = tokio::task::LocalSet::new();
local
.run_until(async {
crate::set_host_call_bridge(Arc::new(TrustedHostDispatchBridge));
let mut trusted = crate::new_vm();
crate::stdlib::register_vm_stdlib(&mut trusted);
trusted
.enable_trusted_host_dispatch()
.expect("fresh VM accepts explicit authority");
let exports = trusted
.load_module_exports(&entry)
.await
.expect("trusted graph loads transitively");
let route = exports.get("route").expect("route exported");
let value = trusted
.call_closure_pub(route, &[VmValue::dict(crate::value::DictMap::default())])
.await
.expect("host-selected callable executes");
crate::clear_host_call_bridge();
assert_eq!(value.display(), "bridged");
})
.await;
});
}
#[test]
fn unregistered_host_fixtures_require_explicit_test_local_authority() {
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.expect("runtime builds");
runtime.block_on(async {
let mut vm = crate::new_vm();
let VmValue::Harness(root) = crate::Harness::real().into_vm_value() else {
panic!("real harness lowers to a VM handle");
};
let testing = root.sub_handle("testing").expect("testing sub-handle");
let mut args = vec![
VmValue::String(arcstr::ArcStr::from("cloud")),
VmValue::String(arcstr::ArcStr::from("echo")),
VmValue::String(arcstr::ArcStr::from("fixture")),
VmValue::Nil,
VmValue::Bool(false),
];
let error = vm
.call_harness_method(&testing, "respond", &args)
.await
.expect_err("unknown host operation fails closed by default");
assert!(
error.to_string().contains("unregistered_ok=true"),
"{error}"
);
args.push(VmValue::Bool(true));
vm.call_harness_method(&testing, "respond", &args)
.await
.expect("explicit test-local host fixture is accepted");
let result = crate::harness::native_harness(&root)
.unwrap()
.fixtures()
.dispatch_host("cloud", "echo", &crate::value::DictMap::default())
.expect("fixture matches")
.expect("fixture succeeds");
assert_eq!(result.display(), "fixture");
});
}
#[test]
fn module_function_can_use_local_type_alias_as_schema_value() {
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.expect("runtime builds");
let result = runtime.block_on(async {
let mut vm = crate::new_vm();
crate::stdlib::register_vm_stdlib(&mut vm);
let loaded = vm
.load_module_exports_from_source(
"<test>/schema_alias_module.harn",
r#"
fn accepts_schema(schema) {
return schema_report({name: "Ada"}, schema).ok
}
type UserShape = {name: string}
pub fn works() {
return accepts_schema(UserShape)
}
"#,
)
.await
.expect("module loads");
let closure = Arc::clone(loaded.get("works").expect("works export exists"));
vm.call_closure_pub(&closure, &[])
.await
.expect("module closure executes")
});
assert!(matches!(result, VmValue::Bool(true)), "{result:?}");
}
#[test]
fn imported_public_struct_exports_its_runtime_constructor() {
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.expect("runtime builds");
let temp = tempfile::tempdir().expect("tempdir");
let types = temp.path().join("types.harn");
let consumer = temp.path().join("consumer.harn");
std::fs::write(&types, "pub struct Decision { allowed: bool }\n").expect("write type module");
std::fs::write(
&consumer,
r#"
import { Decision } from "./types"
pub fn decide() -> Decision {
return Decision({allowed: true})
}
"#,
)
.expect("write consumer module");
runtime.block_on(async {
let mut vm = crate::new_vm();
crate::register_vm_stdlib(&mut vm);
let exports = vm
.load_module_exports(&consumer)
.await
.expect("consumer module loads");
let decide = exports.get("decide").expect("decide export");
let result = vm
.call_closure_pub(decide, &[])
.await
.expect("imported constructor executes");
assert_eq!(result.struct_name(), Some("Decision"));
let fields = result.struct_fields_map().expect("struct fields");
let Some(VmValue::Bool(allowed)) = fields.get("allowed") else {
panic!(
"expected bool field `allowed`, got {:?}",
fields.get("allowed")
);
};
assert!(*allowed, "expected `allowed` to be true");
});
}
#[test]
fn wildcard_imported_source_callable_shadows_legacy_parser_builtin() {
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.expect("runtime builds");
let temp = tempfile::tempdir().expect("tempdir");
let library = temp.path().join("library.harn");
let consumer = temp.path().join("consumer.harn");
std::fs::write(
&library,
r"pub fn context(value: string) -> string { return value }",
)
.expect("write library module");
std::fs::write(
&consumer,
r#"
import "./library"
pub fn exercise() -> string {
return context("wildcard")
}
"#,
)
.expect("write consumer module");
runtime.block_on(async {
let mut vm = crate::new_vm();
crate::register_vm_stdlib(&mut vm);
let exports = vm
.load_module_exports(&consumer)
.await
.expect("wildcard source callable resolves before builtin policy");
let exercise = exports.get("exercise").expect("exercise export");
let result = vm
.call_closure_pub(exercise, &[])
.await
.expect("wildcard source callable executes");
assert!(matches!(
result,
VmValue::String(value) if value.as_str() == "wildcard"
));
});
}
#[test]
fn imported_public_enum_exports_namespace_and_preserves_source_context() {
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.expect("runtime builds");
let temp = tempfile::tempdir().expect("tempdir");
let library = temp.path().join("library.harn");
let facade = temp.path().join("facade.harn");
let consumer = temp.path().join("consumer.harn");
let wildcard_consumer = temp.path().join("wildcard_consumer.harn");
std::fs::write(
&library,
r"
pub enum Color {
Ready(message: string)
Empty
}
pub fn from_library(message: string) -> Color {
return Color.Ready(message)
}
",
)
.expect("write enum module");
std::fs::write(
&facade,
r#"
pub import { Color, from_library } from "./library"
"#,
)
.expect("write enum facade");
std::fs::write(
&consumer,
r#"
import { Color, from_library } from "./facade"
pub fn exercise() -> string {
const direct = Color.Ready("direct")
const indirect = from_library("indirect")
match direct {
Color.Ready(message) -> {
match indirect {
Color.Ready(other) -> { return message + ":" + other }
_ -> { return "indirect-mismatch" }
}
}
_ -> { return "direct-mismatch" }
}
}
"#,
)
.expect("write consumer module");
std::fs::write(
&wildcard_consumer,
r#"
import "./facade"
pub fn exercise() -> string {
const direct = Color.Ready("wildcard")
match direct {
Color.Ready(message) -> { return message }
_ -> { return "wildcard-mismatch" }
}
}
"#,
)
.expect("write wildcard consumer module");
runtime.block_on(async {
let mut vm = crate::new_vm();
crate::register_vm_stdlib(&mut vm);
let exports = vm
.load_module_exports(&consumer)
.await
.expect("consumer module loads");
let exercise = exports.get("exercise").expect("exercise export");
let result = vm
.call_closure_pub(exercise, &[])
.await
.expect("imported enum namespace and function execute");
assert!(matches!(
result,
VmValue::String(value) if value.as_str() == "direct:indirect"
));
let wildcard_exports = vm
.load_module_exports(&wildcard_consumer)
.await
.expect("wildcard consumer module loads");
let wildcard_exercise = wildcard_exports
.get("exercise")
.expect("wildcard exercise export");
let wildcard_result = vm
.call_closure_pub(wildcard_exercise, &[])
.await
.expect("wildcard imported enum namespace executes");
assert!(matches!(
wildcard_result,
VmValue::String(value) if value.as_str() == "wildcard"
));
});
}