Lines
92.86 %
Functions
100 %
Branches
//! End-to-end Tier 3.2 boundary-shim verification on the **script-mode**
//! linker world (`ScriptExecutor` / `Linker<ExecutionState>`).
//!
//! A top-level `(error 'code "msg")` lowers to `throw $nomi_error`; the
//! compiler-emitted boundary `try_table` around `process` catches the
//! uncaught throw, reads the condition's code+message in wasm, and calls
//! the `__nomi_raise` host fn (registered in `define_host_functions`).
//! That host fn returns `Err` carrying the `__nomi_raise:CODE:MSG`
//! marker. The wasmtime error chain is preserved through
//! `HookError::WASM`, so `classify_runtime_error` recovers the structured
//! `EngineError::ScriptRaised { code, message }` — the script's own
//! symbol on the wire, byte-identical to the rpc-eval path.
//! Before 3.2 `(error)` had no working path on this linker world at all.
use scripting::HookError;
use scripting::executor::ScriptExecutor;
use scripting::format::{ContextType, EntityType};
use scripting::runtime::{EngineError, classify_runtime_error};
use scripting::serializer::MemorySerializer;
use nomiscript::{Compiler, Program, Reader, SymbolTable};
fn compile_script_mode(src: &str) -> Vec<u8> {
let program: Program = Reader::parse(src).expect("parse script source");
let mut compiler = Compiler::with_host_fns(Vec::new());
let mut symbols = SymbolTable::with_builtins_for_wasm();
compiler
.compile(&program, &mut symbols)
.expect("(error) must compile + link in script mode post-3.2")
}
fn minimal_batch_input(output_size: u32) -> Vec<u8> {
let mut ser = MemorySerializer::new();
ser.set_context(ContextType::BatchProcess, EntityType::Transaction);
ser.finalize(output_size)
#[test]
fn top_level_error_classifies_as_script_raised_with_code_and_message() {
let wasm = compile_script_mode(r#"(error 'no-such-account "id=42")"#);
let executor = ScriptExecutor::new();
let input = minimal_batch_input(4096);
let err = executor
.execute(&wasm, &input, Some(4096))
.expect_err("uncaught (error) must surface as an Err, not Ok");
let HookError::WASM(wasm_err) = err else {
panic!("expected HookError::WASM preserving the wasmtime chain, got {err:?}");
};
match classify_runtime_error(&wasm_err) {
EngineError::ScriptRaised { code, message } => {
// Symbols upcase through the reader (Lisp convention), so the
// wire :code is the upper-cased form — byte-identical to the
// rpc-eval path (`rpc/tests/parity.rs` asserts the same).
assert_eq!(
code, "NO-SUCH-ACCOUNT",
"wire :code is the script's own (upcased) symbol"
);
assert_eq!(message, "id=42", "wire :message is the script's literal");
other => panic!("boundary bridge must classify as ScriptRaised, got {other:?}"),