#[cfg(all(test, not(feature = "jit-direct-only")))]
#[allow(unused_variables)]
mod tests {
    use crate::box_trait::{IntegerBox, NyashBox, StringBox};
    use crate::boxes::array::ArrayBox;

    use crate::runtime::plugin_loader_unified::PluginHost;
    use std::env;
    use std::fs;

    // RAII: environment variable guard (restores on drop)
    struct EnvGuard {
        key: &'static str,
        prev: Option<String>,
    }

    impl EnvGuard {
        fn set(key: &'static str, val: &str) -> Self {
            let prev = env::var(key).ok();
            env::set_var(key, val);
            EnvGuard { key, prev }
        }

        fn remove(key: &'static str) -> Self {
            let prev = env::var(key).ok();
            env::remove_var(key);
            EnvGuard { key, prev }
        }
    }

    impl Drop for EnvGuard {
        fn drop(&mut self) {
            match &self.prev {
                Some(v) => env::set_var(self.key, v),
                None => env::remove_var(self.key),
            }
        }
    }

    // Helper: read-lock the global plugin host and pass immutable ref to closure
    fn with_host<R>(f: impl FnOnce(&PluginHost) -> R) -> R {
        let host = crate::runtime::get_global_plugin_host();
        let guard = host.read().expect("plugin host RwLock poisoned");
        f(&*guard)
    }

    // ---- Test helpers (invoke wrappers) ----
    fn inv_ok(
        h: &PluginHost,
        box_ty: &str,
        method: &str,
        id: u32,
        args: &[Box<dyn NyashBox>],
    ) -> Option<Box<dyn NyashBox>> {
        h.invoke_instance_method(box_ty, method, id, args)
            .expect(&format!("invoke {}::{}", box_ty, method))
    }

    fn inv_some(
        h: &PluginHost,
        box_ty: &str,
        method: &str,
        id: u32,
        args: &[Box<dyn NyashBox>],
    ) -> Box<dyn NyashBox> {
        inv_ok(h, box_ty, method, id, args)
            .unwrap_or_else(|| panic!("{}::{} returned None", box_ty, method))
    }

    fn inv_void(h: &PluginHost, box_ty: &str, method: &str, id: u32, args: &[Box<dyn NyashBox>]) {
        let _ = h
            .invoke_instance_method(box_ty, method, id, args)
            .expect(&format!("invoke {}::{}", box_ty, method));
    }

    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 bx = with_host(|h| h.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]
    #[ignore = "MIR13 parity: MapBox TLV vs TypeBox under unified BoxCall/TypeOp pending"]
    fn mapbox_get_set_size_tlv_vs_typebox() {
        ensure_host();
        // TLV path: disable typebox (restored automatically)
        let _g = EnvGuard::set("NYASH_DISABLE_TYPEBOX", "1");
        let (bt1, id1, _hold1) = create_plugin_instance("MapBox");
        let out_tlv = with_host(|h| {
            inv_void(
                h,
                &bt1,
                "set",
                id1,
                &[Box::new(StringBox::new("k")), Box::new(IntegerBox::new(42))],
            );
            let sz = inv_some(h, &bt1, "size", id1, &[]);
            let gv = inv_some(h, &bt1, "get", id1, &[Box::new(StringBox::new("k"))]);
            (sz.to_string_box().value, gv.to_string_box().value)
        });

        // TypeBox path: enable typebox
        let _g2 = EnvGuard::remove("NYASH_DISABLE_TYPEBOX");
        let (bt2, id2, _hold2) = create_plugin_instance("MapBox");
        let out_tb = with_host(|h| {
            inv_void(
                h,
                &bt2,
                "set",
                id2,
                &[Box::new(StringBox::new("k")), Box::new(IntegerBox::new(42))],
            );
            let sz = inv_some(h, &bt2, "size", id2, &[]);
            let gv = inv_some(h, &bt2, "get", id2, &[Box::new(StringBox::new("k"))]);
            (sz.to_string_box().value, gv.to_string_box().value)
        });

        assert_eq!(out_tlv, out_tb, "TLV vs TypeBox results should match");
    }

    #[test]
    #[ignore = "MIR13 parity: ArrayBox len/get under unified ops pending"]
    fn arraybox_set_get_len_tlv_vs_typebox() {
        ensure_host();
        // TLV path (guarded)
        let _g = EnvGuard::set("NYASH_DISABLE_TYPEBOX", "1");
        let (bt1, id1, _hold1) = create_plugin_instance("ArrayBox");
        let out_tlv = with_host(|h| {
            inv_void(
                h,
                &bt1,
                "set",
                id1,
                &[Box::new(IntegerBox::new(0)), Box::new(IntegerBox::new(7))],
            );
            let ln = inv_some(h, &bt1, "len", id1, &[]);
            let gv = inv_some(h, &bt1, "get", id1, &[Box::new(IntegerBox::new(0))]);
            (ln.to_string_box().value, gv.to_string_box().value)
        });
        // TypeBox path (guarded)
        let _g2 = EnvGuard::remove("NYASH_DISABLE_TYPEBOX");
        let (bt2, id2, _hold2) = create_plugin_instance("ArrayBox");
        let out_tb = with_host(|h| {
            inv_void(
                h,
                &bt2,
                "set",
                id2,
                &[Box::new(IntegerBox::new(0)), Box::new(IntegerBox::new(7))],
            );
            let ln = inv_some(h, &bt2, "length", id2, &[]);
            let gv = inv_some(h, &bt2, "get", id2, &[Box::new(IntegerBox::new(0))]);
            (ln.to_string_box().value, gv.to_string_box().value)
        });
        assert_eq!(
            out_tlv, out_tb,
            "TLV vs TypeBox results should match (ArrayBox)"
        );
    }

    #[test]
    #[ignore = "MIR13 parity: StringBox length/concat under unified ops pending"]
    fn stringbox_len_concat_tlv_vs_typebox() {
        ensure_host();
        let host = crate::runtime::get_global_plugin_host();
        // TLV path
        let _g = EnvGuard::set("NYASH_DISABLE_TYPEBOX", "1");
        let (bt1, id1, _hold1) = create_plugin_instance("StringBox");
        let out_tlv = with_host(|h| {
            // birth with init string: use fromUtf8 via set of arg in create? Current loader birth() no-arg, so concat
            inv_void(h, &bt1, "concat", id1, &[Box::new(StringBox::new("ab"))]);
            let ln = inv_some(h, &bt1, "length", id1, &[]);
            ln.to_string_box().value
        });
        // TypeBox path
        let _g2 = EnvGuard::remove("NYASH_DISABLE_TYPEBOX");
        let (bt2, id2, _hold2) = create_plugin_instance("StringBox");
        let out_tb = with_host(|h| {
            inv_void(h, &bt2, "concat", id2, &[Box::new(StringBox::new("ab"))]);
            let ln = inv_some(h, &bt2, "length", id2, &[]);
            ln.to_string_box().value
        });
        assert_eq!(
            out_tlv, out_tb,
            "TLV vs TypeBox results should match (StringBox)"
        );
    }

    #[test]
    #[ignore = "MIR13 parity: IntegerBox get/set under unified ops pending"]
    fn integerbox_get_set_tlv_vs_typebox() {
        ensure_host();
        let host = crate::runtime::get_global_plugin_host();
        // TLV path
        let _g = EnvGuard::set("NYASH_DISABLE_TYPEBOX", "1");
        let (bt1, id1, _hold1) = create_plugin_instance("IntegerBox");
        let out_tlv = with_host(|h| {
            inv_void(h, &bt1, "set", id1, &[Box::new(IntegerBox::new(123))]);
            let gv = inv_some(h, &bt1, "get", id1, &[]);
            gv.to_string_box().value
        });
        // TypeBox path
        let _g2 = EnvGuard::remove("NYASH_DISABLE_TYPEBOX");
        let (bt2, id2, _hold2) = create_plugin_instance("IntegerBox");
        let out_tb = with_host(|h| {
            inv_void(h, &bt2, "set", id2, &[Box::new(IntegerBox::new(123))]);
            let gv = inv_some(h, &bt2, "get", id2, &[]);
            gv.to_string_box().value
        });
        assert_eq!(
            out_tlv, out_tb,
            "TLV vs TypeBox results should match (IntegerBox)"
        );
    }

    #[test]
    #[ignore = "Plugin host not configured in CI by default; println parity covered elsewhere"]
    fn consolebox_println_tlv_vs_typebox() {
        ensure_host();
        let host = crate::runtime::get_global_plugin_host();
        // TLV path
        let _g = EnvGuard::set("NYASH_DISABLE_TYPEBOX", "1");
        let (bt1, id1, _hold1) = create_plugin_instance("ConsoleBox");
        let out_tlv_is_none = with_host(|h| {
            let rv = h
                .invoke_instance_method(&bt1, "println", id1, &[Box::new(StringBox::new("hello"))])
                .expect("println tlv");
            rv.is_none()
        });
        // TypeBox path
        let _g2 = EnvGuard::remove("NYASH_DISABLE_TYPEBOX");
        let (bt2, id2, _hold2) = create_plugin_instance("ConsoleBox");
        let out_tb_is_none = with_host(|h| {
            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]
    #[ignore = "MIR13 parity: MathBox basic ops under unified ops pending"]
    fn mathbox_basic_ops_tlv_vs_typebox() {
        ensure_host();
        let host = crate::runtime::get_global_plugin_host();

        // TLV path
        let _g = EnvGuard::set("NYASH_DISABLE_TYPEBOX", "1");
        let (bt1, id1, _hold1) = create_plugin_instance("MathBox");
        let out_tlv = with_host(|h| {
            let s1 = inv_some(h, &bt1, "sqrt", id1, &[Box::new(IntegerBox::new(9))]);
            let s2 = inv_some(h, &bt1, "sin", id1, &[Box::new(IntegerBox::new(0))]);
            let s3 = inv_some(h, &bt1, "cos", id1, &[Box::new(IntegerBox::new(0))]);
            let s4 = inv_some(h, &bt1, "round", id1, &[Box::new(IntegerBox::new(26))]);
            (
                s1.to_string_box().value,
                s2.to_string_box().value,
                s3.to_string_box().value,
                s4.to_string_box().value,
            )
        });

        // TypeBox path
        let _g2 = EnvGuard::remove("NYASH_DISABLE_TYPEBOX");
        let (bt2, id2, _hold2) = create_plugin_instance("MathBox");
        let out_tb = with_host(|h| {
            let s1 = inv_some(h, &bt2, "sqrt", id2, &[Box::new(IntegerBox::new(9))]);
            let s2 = inv_some(h, &bt2, "sin", id2, &[Box::new(IntegerBox::new(0))]);
            let s3 = inv_some(h, &bt2, "cos", id2, &[Box::new(IntegerBox::new(0))]);
            let s4 = inv_some(h, &bt2, "round", id2, &[Box::new(IntegerBox::new(26))]);
            (
                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]
    #[ignore = "MIR13 parity: EncodingBox base64/hex under unified ops pending"]
    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
        let _g = EnvGuard::set("NYASH_DISABLE_TYPEBOX", "1");
        let (bt1, id1, _hold1) = create_plugin_instance("EncodingBox");
        let out_tlv = with_host(|h| {
            let b64 = inv_some(
                h,
                &bt1,
                "base64Encode",
                id1,
                &[Box::new(StringBox::new("hi"))],
            );
            let hex = inv_some(h, &bt1, "hexEncode", id1, &[Box::new(StringBox::new("hi"))]);
            (b64.to_string_box().value, hex.to_string_box().value)
        });

        // TypeBox path
        let _g2 = EnvGuard::remove("NYASH_DISABLE_TYPEBOX");
        let (bt2, id2, _hold2) = create_plugin_instance("EncodingBox");
        let out_tb = with_host(|h| {
            let b64 = inv_some(
                h,
                &bt2,
                "base64Encode",
                id2,
                &[Box::new(StringBox::new("hi"))],
            );
            let hex = inv_some(h, &bt2, "hexEncode", id2, &[Box::new(StringBox::new("hi"))]);
            (b64.to_string_box().value, hex.to_string_box().value)
        });
        assert_eq!(
            out_tlv, out_tb,
            "TLV vs TypeBox results should match (EncodingBox)"
        );
    }

    #[test]
    #[ignore = "MIR13 parity: RegexBox match/find under unified ops pending"]
    fn regexbox_is_match_find_tlv_vs_typebox() {
        ensure_host();
        let host = crate::runtime::get_global_plugin_host();

        // TLV path
        let _g = EnvGuard::set("NYASH_DISABLE_TYPEBOX", "1");
        let (bt1, id1, _hold1) = create_plugin_instance("RegexBox");
        let out_tlv = with_host(|h| {
            inv_void(h, &bt1, "compile", id1, &[Box::new(StringBox::new("h.+o"))]);
            let m = inv_some(
                h,
                &bt1,
                "isMatch",
                id1,
                &[Box::new(StringBox::new("hello"))],
            );
            let f = inv_some(h, &bt1, "find", id1, &[Box::new(StringBox::new("hello"))]);
            (m.to_string_box().value, f.to_string_box().value)
        });

        // TypeBox path
        let _g2 = EnvGuard::remove("NYASH_DISABLE_TYPEBOX");
        let (bt2, id2, _hold2) = create_plugin_instance("RegexBox");
        let out_tb = with_host(|h| {
            inv_void(h, &bt2, "compile", id2, &[Box::new(StringBox::new("h.+o"))]);
            let m = inv_some(
                h,
                &bt2,
                "isMatch",
                id2,
                &[Box::new(StringBox::new("hello"))],
            );
            let f = inv_some(h, &bt2, "find", id2, &[Box::new(StringBox::new("hello"))]);
            (m.to_string_box().value, f.to_string_box().value)
        });
        assert_eq!(
            out_tlv, out_tb,
            "TLV vs TypeBox results should match (RegexBox)"
        );
    }

    #[test]
    #[ignore = "MIR13 parity: PathBox ops under unified ops pending"]
    fn pathbox_ops_tlv_vs_typebox() {
        ensure_host();
        let host = crate::runtime::get_global_plugin_host();

        // TLV path
        let _g = EnvGuard::set("NYASH_DISABLE_TYPEBOX", "1");
        let (bt1, id1, _hold1) = create_plugin_instance("PathBox");
        let out_tlv = with_host(|h| {
            let j = inv_some(
                h,
                &bt1,
                "join",
                id1,
                &[
                    Box::new(StringBox::new("/a/b")),
                    Box::new(StringBox::new("c.txt")),
                ],
            );
            let d = inv_some(
                h,
                &bt1,
                "dirname",
                id1,
                &[Box::new(StringBox::new("/a/b/c.txt"))],
            );
            let b = inv_some(
                h,
                &bt1,
                "basename",
                id1,
                &[Box::new(StringBox::new("/a/b/c.txt"))],
            );
            let n = inv_some(
                h,
                &bt1,
                "normalize",
                id1,
                &[Box::new(StringBox::new("/a/./b/../b/c"))],
            );
            (
                j.to_string_box().value,
                d.to_string_box().value,
                b.to_string_box().value,
                n.to_string_box().value,
            )
        });

        // TypeBox path
        let _g2 = EnvGuard::remove("NYASH_DISABLE_TYPEBOX");
        let (bt2, id2, _hold2) = create_plugin_instance("PathBox");
        let out_tb = with_host(|h| {
            let j = inv_some(
                h,
                &bt2,
                "join",
                id2,
                &[
                    Box::new(StringBox::new("/a/b")),
                    Box::new(StringBox::new("c.txt")),
                ],
            );
            let d = inv_some(
                h,
                &bt2,
                "dirname",
                id2,
                &[Box::new(StringBox::new("/a/b/c.txt"))],
            );
            let b = inv_some(
                h,
                &bt2,
                "basename",
                id2,
                &[Box::new(StringBox::new("/a/b/c.txt"))],
            );
            let n = inv_some(
                h,
                &bt2,
                "normalize",
                id2,
                &[Box::new(StringBox::new("/a/./b/../b/c"))],
            );
            (
                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]
    #[ignore = "MIR13 parity: TOMLBox parse/get/toJson under unified ops pending"]
    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
        let _g = EnvGuard::set("NYASH_DISABLE_TYPEBOX", "1");
        let (bt1, id1, _hold1) = create_plugin_instance("TOMLBox");
        let out_tlv = with_host(|h| {
            inv_void(
                h,
                &bt1,
                "parse",
                id1,
                &[Box::new(StringBox::new(toml_text))],
            );
            let name = inv_some(
                h,
                &bt1,
                "get",
                id1,
                &[Box::new(StringBox::new("package.name"))],
            );
            let json = inv_some(h, &bt1, "toJson", id1, &[]);
            (name.to_string_box().value, json.to_string_box().value)
        });

        // TypeBox path
        let _g2 = EnvGuard::remove("NYASH_DISABLE_TYPEBOX");
        let (bt2, id2, _hold2) = create_plugin_instance("TOMLBox");
        let out_tb = with_host(|h| {
            inv_void(
                h,
                &bt2,
                "parse",
                id2,
                &[Box::new(StringBox::new(toml_text))],
            );
            let name = inv_some(
                h,
                &bt2,
                "get",
                id2,
                &[Box::new(StringBox::new("package.name"))],
            );
            let json = inv_some(h, &bt2, "toJson", id2, &[]);
            (name.to_string_box().value, json.to_string_box().value)
        });
        assert_eq!(
            out_tlv, out_tb,
            "TLV vs TypeBox results should match (TOMLBox)"
        );
    }

    #[test]
    #[ignore = "MIR13 parity: TimeBox now tolerance under unified ops pending"]
    fn timebox_now_tlv_vs_typebox_with_tolerance() {
        ensure_host();
        let host = crate::runtime::get_global_plugin_host();

        // TLV path
        let _g = EnvGuard::set("NYASH_DISABLE_TYPEBOX", "1");
        let (bt1, id1, _hold1) = create_plugin_instance("TimeBox");
        let t_tlv = with_host(|h| {
            let v = inv_some(h, &bt1, "now", id1, &[]);
            v.to_string_box().value.parse::<i64>().unwrap_or(0)
        });

        // TypeBox path
        let _g2 = EnvGuard::remove("NYASH_DISABLE_TYPEBOX");
        let (bt2, id2, _hold2) = create_plugin_instance("TimeBox");
        let t_tb = with_host(|h| {
            let v = inv_some(h, &bt2, "now", id2, &[]);
            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]
    #[ignore = "MIR13 parity: CounterBox singleton delta under unified ops pending"]
    fn counterbox_singleton_delta_increments() {
        ensure_host();
        let host = crate::runtime::get_global_plugin_host();

        // TLV path: verify get->inc->get increases by 1
        let _g = EnvGuard::set("NYASH_DISABLE_TYPEBOX", "1");
        let (bt1, id1, _hold1) = create_plugin_instance("CounterBox");
        let (a1, b1) = with_host(|h| {
            let a = inv_some(h, &bt1, "get", id1, &[]);
            inv_void(h, &bt1, "inc", id1, &[]);
            let b = inv_some(h, &bt1, "get", id1, &[]);
            (
                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)
        let _g2 = EnvGuard::remove("NYASH_DISABLE_TYPEBOX");
        let (bt2, id2, _hold2) = create_plugin_instance("CounterBox");
        let (a2, b2) = with_host(|h| {
            let a = inv_some(h, &bt2, "get", id2, &[]);
            inv_void(h, &bt2, "inc", id2, &[]);
            let b = inv_some(h, &bt2, "get", id2, &[]);
            (
                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]
    #[ignore = "MIR13 parity: FileBox RW/close under unified ops pending"]
    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 = with_host(|h| {
            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 = inv_some(h, &bt1, "read", id1, &[]);
            let _ = h
                .invoke_instance_method(&bt1, "close", id1, &[])
                .expect("close2 tlv");
            rd.to_string_box().value
        });

        // TypeBox path
        let _g2 = EnvGuard::remove("NYASH_DISABLE_TYPEBOX");
        let (bt2, id2, _hold2) = create_plugin_instance("FileBox");
        let out_tb = with_host(|h| {
            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 = inv_some(h, &bt2, "read", id2, &[]);
            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)
            .expect("SystemTime before UNIX_EPOCH");
        now.as_micros() as u64
    }
}
