gui: add EguiBox TypeBox plugin (Windows egui stub)\n\n- plugins: add nyash-egui-plugin with TypeBox (resolve/invoke_id), Windows path for real window via eframe; stub on other OS\n- apps: add apps/egui-hello sample (open→uiLabel→run→close)\n- loader: improve Windows DLL resolution (target triples: x86_64/aarch64 msvc) and lib→dll mapping\n- tests: expand TypeBox vs TLV diff tests up to FileBox; all green\n- docs: update CURRENT_TASK checklist (diff tests completed)\n- config: nyash.toml add EguiBox (type_id=70), plugin registry and methods
This commit is contained in:
@ -7,3 +7,5 @@ pub mod identical_exec_instance;
|
||||
pub mod vtable_array_string;
|
||||
pub mod vtable_strict;
|
||||
pub mod host_reverse_slot;
|
||||
pub mod nyash_abi_basic;
|
||||
pub mod typebox_tlv_diff;
|
||||
|
||||
84
src/tests/nyash_abi_basic.rs
Normal file
84
src/tests/nyash_abi_basic.rs
Normal file
@ -0,0 +1,84 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::runtime::type_registry::{resolve_slot_by_name, known_methods_for};
|
||||
|
||||
#[test]
|
||||
fn type_registry_resolves_core_slots() {
|
||||
// MapBox
|
||||
assert_eq!(resolve_slot_by_name("MapBox", "size", 0), Some(200));
|
||||
assert_eq!(resolve_slot_by_name("MapBox", "len", 0), Some(201));
|
||||
assert_eq!(resolve_slot_by_name("MapBox", "has", 1), Some(202));
|
||||
assert_eq!(resolve_slot_by_name("MapBox", "get", 1), Some(203));
|
||||
assert_eq!(resolve_slot_by_name("MapBox", "set", 2), Some(204));
|
||||
// ArrayBox
|
||||
assert_eq!(resolve_slot_by_name("ArrayBox", "get", 1), Some(100));
|
||||
assert_eq!(resolve_slot_by_name("ArrayBox", "set", 2), Some(101));
|
||||
assert_eq!(resolve_slot_by_name("ArrayBox", "len", 0), Some(102));
|
||||
// StringBox
|
||||
assert_eq!(resolve_slot_by_name("StringBox", "len", 0), Some(300));
|
||||
|
||||
// Known methods listing should include representative entries
|
||||
let mm = known_methods_for("MapBox").expect("map methods");
|
||||
assert!(mm.contains(&"size"));
|
||||
assert!(mm.contains(&"get"));
|
||||
assert!(mm.contains(&"set"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn vm_vtable_map_set_get_has() {
|
||||
use crate::backend::vm::VM;
|
||||
use crate::mir::{MirModule, MirFunction, FunctionSignature, BasicBlockId, MirInstruction, EffectMask, ConstValue, MirType, ValueId};
|
||||
|
||||
// Enable vtable-preferred path
|
||||
std::env::set_var("NYASH_ABI_VTABLE", "1");
|
||||
|
||||
// Program: m = new MapBox(); m.set("k","v"); h = m.has("k"); g = m.get("k"); return g
|
||||
let mut m = MirModule::new("nyash_abi_map_get".into());
|
||||
let sig = FunctionSignature { name: "main".into(), params: vec![], return_type: MirType::String, effects: EffectMask::PURE };
|
||||
let mut f = MirFunction::new(sig, BasicBlockId::new(0));
|
||||
let bb = f.entry_block;
|
||||
|
||||
let mapv = f.next_value_id();
|
||||
f.get_block_mut(bb).unwrap().add_instruction(MirInstruction::NewBox { dst: mapv, box_type: "MapBox".into(), args: vec![] });
|
||||
|
||||
let k = f.next_value_id();
|
||||
f.get_block_mut(bb).unwrap().add_instruction(MirInstruction::Const { dst: k, value: ConstValue::String("k".into()) });
|
||||
let v = f.next_value_id();
|
||||
f.get_block_mut(bb).unwrap().add_instruction(MirInstruction::Const { dst: v, value: ConstValue::String("v".into()) });
|
||||
f.get_block_mut(bb).unwrap().add_instruction(MirInstruction::BoxCall { dst: None, box_val: mapv, method: "set".into(), args: vec![k, v], method_id: None, effects: EffectMask::PURE });
|
||||
|
||||
let k2 = f.next_value_id();
|
||||
f.get_block_mut(bb).unwrap().add_instruction(MirInstruction::Const { dst: k2, value: ConstValue::String("k".into()) });
|
||||
let hasv = f.next_value_id();
|
||||
f.get_block_mut(bb).unwrap().add_instruction(MirInstruction::BoxCall { dst: Some(hasv), box_val: mapv, method: "has".into(), args: vec![k2], method_id: None, effects: EffectMask::PURE });
|
||||
|
||||
let k3 = f.next_value_id();
|
||||
f.get_block_mut(bb).unwrap().add_instruction(MirInstruction::Const { dst: k3, value: ConstValue::String("k".into()) });
|
||||
let got = f.next_value_id();
|
||||
f.get_block_mut(bb).unwrap().add_instruction(MirInstruction::BoxCall { dst: Some(got), box_val: mapv, method: "get".into(), args: vec![k3], method_id: None, effects: EffectMask::PURE });
|
||||
f.get_block_mut(bb).unwrap().add_instruction(MirInstruction::Return { value: Some(got) });
|
||||
|
||||
m.add_function(f);
|
||||
|
||||
let mut vm = VM::new();
|
||||
let out = vm.execute_module(&m).expect("vm exec");
|
||||
assert_eq!(out.to_string_box().value, "v");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mapbox_keys_values_return_arrays() {
|
||||
// Direct Box-level test (not via VM): keys()/values() should return ArrayBox
|
||||
use crate::boxes::map_box::MapBox;
|
||||
use crate::box_trait::{NyashBox, StringBox, IntegerBox};
|
||||
|
||||
let map = MapBox::new();
|
||||
map.set(Box::new(StringBox::new("a")), Box::new(IntegerBox::new(1)));
|
||||
map.set(Box::new(StringBox::new("b")), Box::new(IntegerBox::new(2)));
|
||||
|
||||
let keys = map.keys();
|
||||
let values = map.values();
|
||||
assert_eq!(keys.type_name(), "ArrayBox");
|
||||
assert_eq!(values.type_name(), "ArrayBox");
|
||||
}
|
||||
}
|
||||
433
src/tests/typebox_tlv_diff.rs
Normal file
433
src/tests/typebox_tlv_diff.rs
Normal file
@ -0,0 +1,433 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::env;
|
||||
use crate::box_trait::{NyashBox, StringBox, IntegerBox};
|
||||
use crate::boxes::math_box::FloatBox;
|
||||
use crate::boxes::array::ArrayBox;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn ensure_host() {
|
||||
let _ = crate::runtime::init_global_plugin_host("nyash.toml");
|
||||
}
|
||||
|
||||
fn create_plugin_instance(box_type: &str) -> (String, u32, Box<dyn NyashBox>) {
|
||||
let host = crate::runtime::get_global_plugin_host();
|
||||
let host = host.read().unwrap();
|
||||
let bx = host.create_box(box_type, &[]).expect("create_box");
|
||||
// Downcast to PluginBoxV2 to get instance_id
|
||||
if let Some(p) = bx.as_any().downcast_ref::<crate::runtime::plugin_loader_v2::PluginBoxV2>() {
|
||||
(box_type.to_string(), p.instance_id(), bx)
|
||||
} else {
|
||||
panic!("not a plugin box: {}", bx.type_name());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mapbox_get_set_size_tlv_vs_typebox() {
|
||||
ensure_host();
|
||||
let host = crate::runtime::get_global_plugin_host();
|
||||
|
||||
// TLV path: disable typebox
|
||||
env::set_var("NYASH_DISABLE_TYPEBOX", "1");
|
||||
let (bt1, id1, _hold1) = create_plugin_instance("MapBox");
|
||||
let out_tlv = {
|
||||
let h = host.read().unwrap();
|
||||
// set("k", 42)
|
||||
let _ = h.invoke_instance_method(&bt1, "set", id1, &[Box::new(StringBox::new("k")), Box::new(IntegerBox::new(42))]).expect("set tlv");
|
||||
// size()
|
||||
let sz = h.invoke_instance_method(&bt1, "size", id1, &[]).expect("size tlv").unwrap();
|
||||
// get("k")
|
||||
let gv = h.invoke_instance_method(&bt1, "get", id1, &[Box::new(StringBox::new("k"))]).expect("get tlv").unwrap();
|
||||
(sz.to_string_box().value, gv.to_string_box().value)
|
||||
};
|
||||
|
||||
// TypeBox path: enable typebox
|
||||
env::remove_var("NYASH_DISABLE_TYPEBOX");
|
||||
let (bt2, id2, _hold2) = create_plugin_instance("MapBox");
|
||||
let out_tb = {
|
||||
let h = host.read().unwrap();
|
||||
let _ = h.invoke_instance_method(&bt2, "set", id2, &[Box::new(StringBox::new("k")), Box::new(IntegerBox::new(42))]).expect("set tb");
|
||||
let sz = h.invoke_instance_method(&bt2, "size", id2, &[]).expect("size tb").unwrap();
|
||||
let gv = h.invoke_instance_method(&bt2, "get", id2, &[Box::new(StringBox::new("k"))]).expect("get tb").unwrap();
|
||||
(sz.to_string_box().value, gv.to_string_box().value)
|
||||
};
|
||||
|
||||
assert_eq!(out_tlv, out_tb, "TLV vs TypeBox results should match");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arraybox_set_get_len_tlv_vs_typebox() {
|
||||
ensure_host();
|
||||
let host = crate::runtime::get_global_plugin_host();
|
||||
// TLV path
|
||||
env::set_var("NYASH_DISABLE_TYPEBOX", "1");
|
||||
let (bt1, id1, _hold1) = create_plugin_instance("ArrayBox");
|
||||
let out_tlv = {
|
||||
let h = host.read().unwrap();
|
||||
let _ = h.invoke_instance_method(&bt1, "set", id1, &[Box::new(IntegerBox::new(0)), Box::new(IntegerBox::new(7))]).expect("set tlv");
|
||||
let ln = h.invoke_instance_method(&bt1, "len", id1, &[]).expect("len tlv").unwrap();
|
||||
let gv = h.invoke_instance_method(&bt1, "get", id1, &[Box::new(IntegerBox::new(0))]).expect("get tlv").unwrap();
|
||||
(ln.to_string_box().value, gv.to_string_box().value)
|
||||
};
|
||||
// TypeBox path
|
||||
env::remove_var("NYASH_DISABLE_TYPEBOX");
|
||||
let (bt2, id2, _hold2) = create_plugin_instance("ArrayBox");
|
||||
let out_tb = {
|
||||
let h = host.read().unwrap();
|
||||
let _ = h.invoke_instance_method(&bt2, "set", id2, &[Box::new(IntegerBox::new(0)), Box::new(IntegerBox::new(7))]).expect("set tb");
|
||||
let ln = h.invoke_instance_method(&bt2, "length", id2, &[]).expect("len tb").unwrap();
|
||||
let gv = h.invoke_instance_method(&bt2, "get", id2, &[Box::new(IntegerBox::new(0))]).expect("get tb").unwrap();
|
||||
(ln.to_string_box().value, gv.to_string_box().value)
|
||||
};
|
||||
assert_eq!(out_tlv, out_tb, "TLV vs TypeBox results should match (ArrayBox)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stringbox_len_concat_tlv_vs_typebox() {
|
||||
ensure_host();
|
||||
let host = crate::runtime::get_global_plugin_host();
|
||||
// TLV path
|
||||
env::set_var("NYASH_DISABLE_TYPEBOX", "1");
|
||||
let (bt1, id1, _hold1) = create_plugin_instance("StringBox");
|
||||
let out_tlv = {
|
||||
let h = host.read().unwrap();
|
||||
// birth with init string: use fromUtf8 via set of arg in create? Current loader birth() no-arg, so concat
|
||||
let _ = h.invoke_instance_method(&bt1, "concat", id1, &[Box::new(StringBox::new("ab"))]).expect("concat tlv").unwrap();
|
||||
let ln = h.invoke_instance_method(&bt1, "length", id1, &[]).expect("len tlv").unwrap();
|
||||
(ln.to_string_box().value)
|
||||
};
|
||||
// TypeBox path
|
||||
env::remove_var("NYASH_DISABLE_TYPEBOX");
|
||||
let (bt2, id2, _hold2) = create_plugin_instance("StringBox");
|
||||
let out_tb = {
|
||||
let h = host.read().unwrap();
|
||||
let _ = h.invoke_instance_method(&bt2, "concat", id2, &[Box::new(StringBox::new("ab"))]).expect("concat tb").unwrap();
|
||||
let ln = h.invoke_instance_method(&bt2, "length", id2, &[]).expect("len tb").unwrap();
|
||||
(ln.to_string_box().value)
|
||||
};
|
||||
assert_eq!(out_tlv, out_tb, "TLV vs TypeBox results should match (StringBox)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn integerbox_get_set_tlv_vs_typebox() {
|
||||
ensure_host();
|
||||
let host = crate::runtime::get_global_plugin_host();
|
||||
// TLV path
|
||||
env::set_var("NYASH_DISABLE_TYPEBOX", "1");
|
||||
let (bt1, id1, _hold1) = create_plugin_instance("IntegerBox");
|
||||
let out_tlv = {
|
||||
let h = host.read().unwrap();
|
||||
let _ = h.invoke_instance_method(&bt1, "set", id1, &[Box::new(IntegerBox::new(123))]).expect("set tlv").unwrap();
|
||||
let gv = h.invoke_instance_method(&bt1, "get", id1, &[]).expect("get tlv").unwrap();
|
||||
gv.to_string_box().value
|
||||
};
|
||||
// TypeBox path
|
||||
env::remove_var("NYASH_DISABLE_TYPEBOX");
|
||||
let (bt2, id2, _hold2) = create_plugin_instance("IntegerBox");
|
||||
let out_tb = {
|
||||
let h = host.read().unwrap();
|
||||
let _ = h.invoke_instance_method(&bt2, "set", id2, &[Box::new(IntegerBox::new(123))]).expect("set tb").unwrap();
|
||||
let gv = h.invoke_instance_method(&bt2, "get", id2, &[]).expect("get tb").unwrap();
|
||||
gv.to_string_box().value
|
||||
};
|
||||
assert_eq!(out_tlv, out_tb, "TLV vs TypeBox results should match (IntegerBox)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn consolebox_println_tlv_vs_typebox() {
|
||||
ensure_host();
|
||||
let host = crate::runtime::get_global_plugin_host();
|
||||
// TLV path
|
||||
env::set_var("NYASH_DISABLE_TYPEBOX", "1");
|
||||
let (bt1, id1, _hold1) = create_plugin_instance("ConsoleBox");
|
||||
let out_tlv_is_none = {
|
||||
let h = host.read().unwrap();
|
||||
let rv = h.invoke_instance_method(&bt1, "println", id1, &[Box::new(StringBox::new("hello"))]).expect("println tlv");
|
||||
rv.is_none()
|
||||
};
|
||||
// TypeBox path
|
||||
env::remove_var("NYASH_DISABLE_TYPEBOX");
|
||||
let (bt2, id2, _hold2) = create_plugin_instance("ConsoleBox");
|
||||
let out_tb_is_none = {
|
||||
let h = host.read().unwrap();
|
||||
let rv = h.invoke_instance_method(&bt2, "println", id2, &[Box::new(StringBox::new("hello"))]).expect("println tb");
|
||||
rv.is_none()
|
||||
};
|
||||
assert!(out_tlv_is_none && out_tb_is_none, "println should return void/None in both modes");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mathbox_basic_ops_tlv_vs_typebox() {
|
||||
ensure_host();
|
||||
let host = crate::runtime::get_global_plugin_host();
|
||||
|
||||
// TLV path
|
||||
env::set_var("NYASH_DISABLE_TYPEBOX", "1");
|
||||
let (bt1, id1, _hold1) = create_plugin_instance("MathBox");
|
||||
let out_tlv = {
|
||||
let h = host.read().unwrap();
|
||||
let s1 = h.invoke_instance_method(&bt1, "sqrt", id1, &[Box::new(IntegerBox::new(9))]).expect("sqrt tlv").unwrap();
|
||||
let s2 = h.invoke_instance_method(&bt1, "sin", id1, &[Box::new(IntegerBox::new(0))]).expect("sin tlv").unwrap();
|
||||
let s3 = h.invoke_instance_method(&bt1, "cos", id1, &[Box::new(IntegerBox::new(0))]).expect("cos tlv").unwrap();
|
||||
let s4 = h.invoke_instance_method(&bt1, "round", id1, &[Box::new(IntegerBox::new(26))]).expect("round tlv").unwrap();
|
||||
(
|
||||
s1.to_string_box().value,
|
||||
s2.to_string_box().value,
|
||||
s3.to_string_box().value,
|
||||
s4.to_string_box().value,
|
||||
)
|
||||
};
|
||||
|
||||
// TypeBox path
|
||||
env::remove_var("NYASH_DISABLE_TYPEBOX");
|
||||
let (bt2, id2, _hold2) = create_plugin_instance("MathBox");
|
||||
let out_tb = {
|
||||
let h = host.read().unwrap();
|
||||
let s1 = h.invoke_instance_method(&bt2, "sqrt", id2, &[Box::new(IntegerBox::new(9))]).expect("sqrt tb").unwrap();
|
||||
let s2 = h.invoke_instance_method(&bt2, "sin", id2, &[Box::new(IntegerBox::new(0))]).expect("sin tb").unwrap();
|
||||
let s3 = h.invoke_instance_method(&bt2, "cos", id2, &[Box::new(IntegerBox::new(0))]).expect("cos tb").unwrap();
|
||||
let s4 = h.invoke_instance_method(&bt2, "round", id2, &[Box::new(IntegerBox::new(26))]).expect("round tb").unwrap();
|
||||
(
|
||||
s1.to_string_box().value,
|
||||
s2.to_string_box().value,
|
||||
s3.to_string_box().value,
|
||||
s4.to_string_box().value,
|
||||
)
|
||||
};
|
||||
assert_eq!(out_tlv, out_tb, "TLV vs TypeBox results should match (MathBox)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encodingbox_base64_hex_tlv_vs_typebox() {
|
||||
ensure_host();
|
||||
let host = crate::runtime::get_global_plugin_host();
|
||||
|
||||
// Prepare bytes ["hi"] as Array<uint8>
|
||||
let bytes_array = {
|
||||
let arr = ArrayBox::new();
|
||||
let _ = arr.push(Box::new(IntegerBox::new(104))); // 'h'
|
||||
let _ = arr.push(Box::new(IntegerBox::new(105))); // 'i'
|
||||
Box::new(arr) as Box<dyn NyashBox>
|
||||
};
|
||||
|
||||
// TLV path
|
||||
env::set_var("NYASH_DISABLE_TYPEBOX", "1");
|
||||
let (bt1, id1, _hold1) = create_plugin_instance("EncodingBox");
|
||||
let out_tlv = {
|
||||
let h = host.read().unwrap();
|
||||
let b64 = h.invoke_instance_method(&bt1, "base64Encode", id1, &[Box::new(StringBox::new("hi"))]).expect("b64 tlv").unwrap();
|
||||
let hex = h.invoke_instance_method(&bt1, "hexEncode", id1, &[Box::new(StringBox::new("hi"))]).expect("hex tlv").unwrap();
|
||||
(b64.to_string_box().value, hex.to_string_box().value)
|
||||
};
|
||||
|
||||
// TypeBox path
|
||||
env::remove_var("NYASH_DISABLE_TYPEBOX");
|
||||
let (bt2, id2, _hold2) = create_plugin_instance("EncodingBox");
|
||||
let out_tb = {
|
||||
let h = host.read().unwrap();
|
||||
let b64 = h.invoke_instance_method(&bt2, "base64Encode", id2, &[Box::new(StringBox::new("hi"))]).expect("b64 tb").unwrap();
|
||||
let hex = h.invoke_instance_method(&bt2, "hexEncode", id2, &[Box::new(StringBox::new("hi"))]).expect("hex tb").unwrap();
|
||||
(b64.to_string_box().value, hex.to_string_box().value)
|
||||
};
|
||||
assert_eq!(out_tlv, out_tb, "TLV vs TypeBox results should match (EncodingBox)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn regexbox_is_match_find_tlv_vs_typebox() {
|
||||
ensure_host();
|
||||
let host = crate::runtime::get_global_plugin_host();
|
||||
|
||||
// TLV path
|
||||
env::set_var("NYASH_DISABLE_TYPEBOX", "1");
|
||||
let (bt1, id1, _hold1) = create_plugin_instance("RegexBox");
|
||||
let out_tlv = {
|
||||
let h = host.read().unwrap();
|
||||
let _ = h.invoke_instance_method(&bt1, "compile", id1, &[Box::new(StringBox::new("h.+o"))]).expect("compile tlv");
|
||||
let m = h.invoke_instance_method(&bt1, "isMatch", id1, &[Box::new(StringBox::new("hello"))]).expect("isMatch tlv").unwrap();
|
||||
let f = h.invoke_instance_method(&bt1, "find", id1, &[Box::new(StringBox::new("hello"))]).expect("find tlv").unwrap();
|
||||
(m.to_string_box().value, f.to_string_box().value)
|
||||
};
|
||||
|
||||
// TypeBox path
|
||||
env::remove_var("NYASH_DISABLE_TYPEBOX");
|
||||
let (bt2, id2, _hold2) = create_plugin_instance("RegexBox");
|
||||
let out_tb = {
|
||||
let h = host.read().unwrap();
|
||||
let _ = h.invoke_instance_method(&bt2, "compile", id2, &[Box::new(StringBox::new("h.+o"))]).expect("compile tb");
|
||||
let m = h.invoke_instance_method(&bt2, "isMatch", id2, &[Box::new(StringBox::new("hello"))]).expect("isMatch tb").unwrap();
|
||||
let f = h.invoke_instance_method(&bt2, "find", id2, &[Box::new(StringBox::new("hello"))]).expect("find tb").unwrap();
|
||||
(m.to_string_box().value, f.to_string_box().value)
|
||||
};
|
||||
assert_eq!(out_tlv, out_tb, "TLV vs TypeBox results should match (RegexBox)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pathbox_ops_tlv_vs_typebox() {
|
||||
ensure_host();
|
||||
let host = crate::runtime::get_global_plugin_host();
|
||||
|
||||
// TLV path
|
||||
env::set_var("NYASH_DISABLE_TYPEBOX", "1");
|
||||
let (bt1, id1, _hold1) = create_plugin_instance("PathBox");
|
||||
let out_tlv = {
|
||||
let h = host.read().unwrap();
|
||||
let j = h.invoke_instance_method(&bt1, "join", id1, &[Box::new(StringBox::new("/a/b")), Box::new(StringBox::new("c.txt"))]).expect("join tlv").unwrap();
|
||||
let d = h.invoke_instance_method(&bt1, "dirname", id1, &[Box::new(StringBox::new("/a/b/c.txt"))]).expect("dirname tlv").unwrap();
|
||||
let b = h.invoke_instance_method(&bt1, "basename", id1, &[Box::new(StringBox::new("/a/b/c.txt"))]).expect("basename tlv").unwrap();
|
||||
let n = h.invoke_instance_method(&bt1, "normalize", id1, &[Box::new(StringBox::new("/a/./b/../b/c"))]).expect("normalize tlv").unwrap();
|
||||
(j.to_string_box().value, d.to_string_box().value, b.to_string_box().value, n.to_string_box().value)
|
||||
};
|
||||
|
||||
// TypeBox path
|
||||
env::remove_var("NYASH_DISABLE_TYPEBOX");
|
||||
let (bt2, id2, _hold2) = create_plugin_instance("PathBox");
|
||||
let out_tb = {
|
||||
let h = host.read().unwrap();
|
||||
let j = h.invoke_instance_method(&bt2, "join", id2, &[Box::new(StringBox::new("/a/b")), Box::new(StringBox::new("c.txt"))]).expect("join tb").unwrap();
|
||||
let d = h.invoke_instance_method(&bt2, "dirname", id2, &[Box::new(StringBox::new("/a/b/c.txt"))]).expect("dirname tb").unwrap();
|
||||
let b = h.invoke_instance_method(&bt2, "basename", id2, &[Box::new(StringBox::new("/a/b/c.txt"))]).expect("basename tb").unwrap();
|
||||
let n = h.invoke_instance_method(&bt2, "normalize", id2, &[Box::new(StringBox::new("/a/./b/../b/c"))]).expect("normalize tb").unwrap();
|
||||
(j.to_string_box().value, d.to_string_box().value, b.to_string_box().value, n.to_string_box().value)
|
||||
};
|
||||
assert_eq!(out_tlv, out_tb, "TLV vs TypeBox results should match (PathBox)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tomlbox_parse_get_tojson_tlv_vs_typebox() {
|
||||
ensure_host();
|
||||
let host = crate::runtime::get_global_plugin_host();
|
||||
let toml_text = "[package]\nname=\"nyash\"\n[deps]\nregex=\"1\"\n";
|
||||
|
||||
// TLV path
|
||||
env::set_var("NYASH_DISABLE_TYPEBOX", "1");
|
||||
let (bt1, id1, _hold1) = create_plugin_instance("TOMLBox");
|
||||
let out_tlv = {
|
||||
let h = host.read().unwrap();
|
||||
let _ = h.invoke_instance_method(&bt1, "parse", id1, &[Box::new(StringBox::new(toml_text))]).expect("parse tlv").unwrap();
|
||||
let name = h.invoke_instance_method(&bt1, "get", id1, &[Box::new(StringBox::new("package.name"))]).expect("get tlv").unwrap();
|
||||
let json = h.invoke_instance_method(&bt1, "toJson", id1, &[]).expect("toJson tlv").unwrap();
|
||||
(name.to_string_box().value, json.to_string_box().value)
|
||||
};
|
||||
|
||||
// TypeBox path
|
||||
env::remove_var("NYASH_DISABLE_TYPEBOX");
|
||||
let (bt2, id2, _hold2) = create_plugin_instance("TOMLBox");
|
||||
let out_tb = {
|
||||
let h = host.read().unwrap();
|
||||
let _ = h.invoke_instance_method(&bt2, "parse", id2, &[Box::new(StringBox::new(toml_text))]).expect("parse tb").unwrap();
|
||||
let name = h.invoke_instance_method(&bt2, "get", id2, &[Box::new(StringBox::new("package.name"))]).expect("get tb").unwrap();
|
||||
let json = h.invoke_instance_method(&bt2, "toJson", id2, &[]).expect("toJson tb").unwrap();
|
||||
(name.to_string_box().value, json.to_string_box().value)
|
||||
};
|
||||
assert_eq!(out_tlv, out_tb, "TLV vs TypeBox results should match (TOMLBox)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn timebox_now_tlv_vs_typebox_with_tolerance() {
|
||||
ensure_host();
|
||||
let host = crate::runtime::get_global_plugin_host();
|
||||
|
||||
// TLV path
|
||||
env::set_var("NYASH_DISABLE_TYPEBOX", "1");
|
||||
let (bt1, id1, _hold1) = create_plugin_instance("TimeBox");
|
||||
let t_tlv = {
|
||||
let h = host.read().unwrap();
|
||||
let v = h.invoke_instance_method(&bt1, "now", id1, &[]).expect("now tlv").unwrap();
|
||||
v.to_string_box().value.parse::<i64>().unwrap_or(0)
|
||||
};
|
||||
|
||||
// TypeBox path
|
||||
env::remove_var("NYASH_DISABLE_TYPEBOX");
|
||||
let (bt2, id2, _hold2) = create_plugin_instance("TimeBox");
|
||||
let t_tb = {
|
||||
let h = host.read().unwrap();
|
||||
let v = h.invoke_instance_method(&bt2, "now", id2, &[]).expect("now tb").unwrap();
|
||||
v.to_string_box().value.parse::<i64>().unwrap_or(0)
|
||||
};
|
||||
|
||||
let diff = (t_tb - t_tlv).abs();
|
||||
assert!(diff < 5_000, "TimeBox.now difference too large: {}ms", diff);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn counterbox_singleton_delta_increments() {
|
||||
ensure_host();
|
||||
let host = crate::runtime::get_global_plugin_host();
|
||||
|
||||
// TLV path: verify get->inc->get increases by 1
|
||||
env::set_var("NYASH_DISABLE_TYPEBOX", "1");
|
||||
let (bt1, id1, _hold1) = create_plugin_instance("CounterBox");
|
||||
let (a1, b1) = {
|
||||
let h = host.read().unwrap();
|
||||
let a = h.invoke_instance_method(&bt1, "get", id1, &[]).expect("get tlv").unwrap();
|
||||
let _ = h.invoke_instance_method(&bt1, "inc", id1, &[]).expect("inc tlv");
|
||||
let b = h.invoke_instance_method(&bt1, "get", id1, &[]).expect("get2 tlv").unwrap();
|
||||
(a.to_string_box().value.parse::<i64>().unwrap_or(0), b.to_string_box().value.parse::<i64>().unwrap_or(0))
|
||||
};
|
||||
assert_eq!(b1 - a1, 1, "CounterBox TLV should increment by 1");
|
||||
|
||||
// TypeBox path: verify same delta behavior (not comparing absolute values due to singleton)
|
||||
env::remove_var("NYASH_DISABLE_TYPEBOX");
|
||||
let (bt2, id2, _hold2) = create_plugin_instance("CounterBox");
|
||||
let (a2, b2) = {
|
||||
let h = host.read().unwrap();
|
||||
let a = h.invoke_instance_method(&bt2, "get", id2, &[]).expect("get tb").unwrap();
|
||||
let _ = h.invoke_instance_method(&bt2, "inc", id2, &[]).expect("inc tb");
|
||||
let b = h.invoke_instance_method(&bt2, "get", id2, &[]).expect("get2 tb").unwrap();
|
||||
(a.to_string_box().value.parse::<i64>().unwrap_or(0), b.to_string_box().value.parse::<i64>().unwrap_or(0))
|
||||
};
|
||||
assert_eq!(b2 - a2, 1, "CounterBox TypeBox should increment by 1");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn filebox_rw_close_tmpdir_tlv_vs_typebox() {
|
||||
ensure_host();
|
||||
let host = crate::runtime::get_global_plugin_host();
|
||||
|
||||
// Prepare temp file path
|
||||
let mut p = std::env::temp_dir();
|
||||
p.push(format!("nyash_test_{}_{}.txt", std::process::id(), rand_id())) ;
|
||||
let path_str = p.to_string_lossy().to_string();
|
||||
|
||||
// TLV path
|
||||
env::set_var("NYASH_DISABLE_TYPEBOX", "1");
|
||||
let (bt1, id1, _hold1) = create_plugin_instance("FileBox");
|
||||
let out_tlv = {
|
||||
let h = host.read().unwrap();
|
||||
let _ = h.invoke_instance_method(&bt1, "open", id1, &[Box::new(StringBox::new(&path_str)), Box::new(StringBox::new("w"))]).expect("open tlv");
|
||||
let _ = h.invoke_instance_method(&bt1, "write", id1, &[Box::new(StringBox::new("hello"))]).expect("write tlv");
|
||||
let _ = h.invoke_instance_method(&bt1, "close", id1, &[]).expect("close tlv");
|
||||
// reopen and read
|
||||
let _ = h.invoke_instance_method(&bt1, "open", id1, &[Box::new(StringBox::new(&path_str)), Box::new(StringBox::new("r"))]).expect("open2 tlv");
|
||||
let rd = h.invoke_instance_method(&bt1, "read", id1, &[]).expect("read tlv").unwrap();
|
||||
let _ = h.invoke_instance_method(&bt1, "close", id1, &[]).expect("close2 tlv");
|
||||
rd.to_string_box().value
|
||||
};
|
||||
|
||||
// TypeBox path
|
||||
env::remove_var("NYASH_DISABLE_TYPEBOX");
|
||||
let (bt2, id2, _hold2) = create_plugin_instance("FileBox");
|
||||
let out_tb = {
|
||||
let h = host.read().unwrap();
|
||||
let _ = h.invoke_instance_method(&bt2, "open", id2, &[Box::new(StringBox::new(&path_str)), Box::new(StringBox::new("w"))]).expect("open tb");
|
||||
let _ = h.invoke_instance_method(&bt2, "write", id2, &[Box::new(StringBox::new("hello"))]).expect("write tb");
|
||||
let _ = h.invoke_instance_method(&bt2, "close", id2, &[]).expect("close tb");
|
||||
let _ = h.invoke_instance_method(&bt2, "open", id2, &[Box::new(StringBox::new(&path_str)), Box::new(StringBox::new("r"))]).expect("open2 tb");
|
||||
let rd = h.invoke_instance_method(&bt2, "read", id2, &[]).expect("read tb").unwrap();
|
||||
let _ = h.invoke_instance_method(&bt2, "close", id2, &[]).expect("close2 tb");
|
||||
rd.to_string_box().value
|
||||
};
|
||||
|
||||
// Cleanup best-effort
|
||||
let _ = fs::remove_file(&path_str);
|
||||
|
||||
assert_eq!(out_tlv, out_tb, "TLV vs TypeBox results should match (FileBox)");
|
||||
}
|
||||
|
||||
fn rand_id() -> u64 {
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
|
||||
now.as_micros() as u64
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user