use super::super::*;
use crate::instruction::OpCode;
#[test]
fn high_level_lifts_local_slots() {
let script = [
OpCode::Initslot.byte(),
0x01,
0x00,
OpCode::Push1.byte(),
OpCode::Stloc0.byte(),
OpCode::Ldloc0.byte(),
OpCode::Ret.byte(),
];
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("// declare 1 locals, 0 arguments"));
assert!(
high_level.contains("let loc0 = 1;"),
"expected collapsed store: {high_level}"
);
assert!(high_level.contains("return loc0;"));
}
#[test]
fn high_level_lifts_all_local_slot_variants() {
let script = [
OpCode::Initslot.byte(),
0x07,
0x00, OpCode::Push0.byte(),
OpCode::Stloc0.byte(), OpCode::Push1.byte(),
OpCode::Stloc1.byte(), OpCode::Push2.byte(),
OpCode::Stloc2.byte(), OpCode::Push3.byte(),
OpCode::Stloc3.byte(), OpCode::Push4.byte(),
OpCode::Stloc4.byte(), OpCode::Push5.byte(),
OpCode::Stloc5.byte(), OpCode::Push6.byte(),
OpCode::Stloc6.byte(), OpCode::Ldloc0.byte(),
OpCode::Ldloc1.byte(),
OpCode::Ldloc2.byte(),
OpCode::Ldloc3.byte(),
OpCode::Ldloc4.byte(),
OpCode::Ldloc5.byte(),
OpCode::Ldloc6.byte(), OpCode::Ret.byte(), ];
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("// declare 7 locals, 0 arguments"),
"should declare 7 locals: {high_level}"
);
for i in 0..7 {
assert!(
high_level.contains(&format!("loc{i}")),
"local slot {i} should appear in output: {high_level}"
);
}
}
#[test]
fn high_level_lifts_all_argument_slot_variants() {
let script = [
OpCode::Initslot.byte(),
0x00,
0x07, OpCode::Ldarg0.byte(),
OpCode::Starg0.byte(), OpCode::Ldarg1.byte(),
OpCode::Starg1.byte(), OpCode::Ldarg2.byte(),
OpCode::Starg2.byte(), OpCode::Ldarg3.byte(),
OpCode::Starg3.byte(), OpCode::Ldarg4.byte(),
OpCode::Starg4.byte(), OpCode::Ldarg5.byte(),
OpCode::Starg5.byte(), OpCode::Ldarg6.byte(),
OpCode::Starg6.byte(), OpCode::Ret.byte(), ];
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("// declare 0 locals, 7 arguments"),
"should declare 7 arguments: {high_level}"
);
for i in 0..7 {
assert!(
high_level.contains(&format!("arg{i}")),
"argument slot {i} should appear in output: {high_level}"
);
}
}
#[test]
fn high_level_lifts_indexed_local_slot() {
let script = [
OpCode::Initslot.byte(),
0x08,
0x00, OpCode::Push1.byte(), OpCode::Stloc.byte(),
0x07, OpCode::Ldloc.byte(),
0x07, OpCode::Ret.byte(), ];
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("loc7"),
"indexed LDLOC/STLOC should reference loc7: {high_level}"
);
}
#[test]
fn high_level_lifts_indexed_argument_slot() {
let script = [
OpCode::Initslot.byte(),
0x00,
0x08, OpCode::Ldarg.byte(),
0x07, OpCode::Push1.byte(), OpCode::Starg.byte(),
0x07, OpCode::Ret.byte(), ];
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("arg7"),
"indexed LDARG/STARG should reference arg7: {high_level}"
);
}