use super::super::*;
#[test]
fn high_level_packs_literal_arrays() {
let script = [0x11, 0x12, 0x12, 0xC0, 0x40];
let nef_bytes = build_nef(&script);
let decompilation = Decompiler::new()
.decompile_bytes(&nef_bytes)
.expect("decompile succeeds");
let high_level = decompilation
.high_level
.as_deref()
.expect("high-level output");
assert!(
high_level.contains("pack 2 element"),
"expected literal PACK to be lifted: {high_level}"
);
assert!(
!high_level.contains("pack_dynamic"),
"literal PACK should not fall back to dynamic form: {high_level}"
);
}
#[test]
fn high_level_rewrites_pickitem_as_indexing() {
let script = [0xC2, 0x10, 0xCE, 0x40];
let nef_bytes = build_nef(&script);
let decompilation = Decompiler::new()
.decompile_bytes(&nef_bytes)
.expect("decompile succeeds");
let high_level = decompilation
.high_level
.as_deref()
.expect("high-level output");
assert!(
high_level.contains("t0[t1]"),
"expected PICKITEM to be rewritten as indexing: {high_level}"
);
assert!(
!high_level.contains(" get "),
"infix get should not appear after rewrite: {high_level}"
);
}
#[test]
fn high_level_rewrites_setitem_as_index_assignment() {
let script = [0xC8, 0x10, 0x11, 0xD0, 0x40];
let nef_bytes = build_nef(&script);
let decompilation = Decompiler::new()
.decompile_bytes(&nef_bytes)
.expect("decompile succeeds");
let high_level = decompilation
.high_level
.as_deref()
.expect("high-level output");
assert!(
high_level.contains("t0[t1] = t2;"),
"expected SETITEM to be rewritten as indexing assignment: {high_level}"
);
assert!(
!high_level.contains("set_item("),
"set_item helper should not appear after rewrite: {high_level}"
);
}
#[test]
fn high_level_rewrites_haskey_as_function_call() {
let script = [0xC8, 0x10, 0xCB, 0x40];
let nef_bytes = build_nef(&script);
let decompilation = Decompiler::new()
.with_inline_single_use_temps(true)
.decompile_bytes(&nef_bytes)
.expect("decompile succeeds");
let high_level = decompilation
.high_level
.as_deref()
.expect("high-level output");
assert!(
high_level.contains("has_key("),
"expected HASKEY to be rewritten as function call: {high_level}"
);
assert!(
!high_level.contains(" has_key "),
"infix has_key should not appear after rewrite: {high_level}"
);
assert!(
!high_level.contains("has_key(return"),
"return must not be nested inside the has_key call: {high_level}"
);
assert!(
high_level.contains("return has_key("),
"HASKEY result should flow into the return: {high_level}"
);
}
#[test]
fn high_level_pickitem_inside_call_keeps_brackets_balanced() {
let script = [0x11, 0x11, 0xC0, 0x10, 0xCE, 0xCA, 0x40];
let nef_bytes = build_nef(&script);
let high_level = Decompiler::new()
.with_inline_single_use_temps(true)
.decompile_bytes(&nef_bytes)
.expect("decompile succeeds")
.high_level
.expect("high-level output");
assert!(
!high_level.contains("[0)]") && !high_level.contains(" get "),
"index access inside a call must not interleave `)` and `]`: {high_level}"
);
assert!(
high_level.contains("len(") && high_level.contains("[0])"),
"PICKITEM result inside len() should render as len(arr[0]): {high_level}"
);
}
#[test]
fn high_level_istype_respects_operand_tag() {
let script = [0x11, 0xD9, 0x40, 0x40];
let nef_bytes = build_nef(&script);
let decompilation = Decompiler::new()
.decompile_bytes(&nef_bytes)
.expect("decompile succeeds");
let high_level = decompilation
.high_level
.as_deref()
.expect("high-level output");
assert!(
high_level.contains("is_type_array("),
"ISTYPE should map to a helper named for the operand tag: {high_level}"
);
assert!(
!high_level.contains("is_type("),
"High-level output should not use the two-argument shorthand: {high_level}"
);
}
#[test]
fn pack_literal_underflow_renders_elision_marker_not_synthetic_temps() {
let script = [0x11, 0x11, 0x11, 0x15, 0xC0, 0x40];
let nef_bytes = build_nef(&script);
let decompilation = Decompiler::new()
.decompile_bytes(&nef_bytes)
.expect("decompile succeeds");
let high_level = decompilation
.high_level
.as_deref()
.expect("high-level output");
assert!(
high_level.contains("/* 2 more elements */"),
"underflowing PACK should render an elision marker: {high_level}"
);
assert!(
!high_level.contains("missing_pack_item"),
"underflowing PACK should not synthesize missing_pack_item temps: {high_level}"
);
}