use super::*;
use crate::instruction::OpCode;
#[test]
fn csharp_resolves_internal_calls_to_method_names() {
let script = [
OpCode::Call.byte(),
0x04,
OpCode::Ret.byte(),
OpCode::Nop.byte(),
OpCode::Ret.byte(),
];
let nef_bytes = build_nef(&script);
let decompilation = Decompiler::new()
.decompile_bytes_with_manifest(&nef_bytes, None, OutputFormat::All)
.expect("decompile succeeds");
let csharp = decompilation.csharp.as_deref().expect("csharp output");
assert!(
csharp.contains("sub_0x0004()"),
"C# output should resolve internal helper names instead of raw call placeholders: {csharp}"
);
assert!(
!csharp.contains("call_0x0004"),
"C# output should not emit raw call_0x placeholders when a helper name is known: {csharp}"
);
}
#[test]
fn csharp_emits_inferred_helper_methods() {
let script = [
OpCode::Call.byte(),
0x04,
OpCode::Ret.byte(),
OpCode::Nop.byte(),
OpCode::Ret.byte(),
];
let nef_bytes = build_nef(&script);
let decompilation = Decompiler::new()
.decompile_bytes_with_manifest(&nef_bytes, None, OutputFormat::All)
.expect("decompile succeeds");
let csharp = decompilation.csharp.as_deref().expect("csharp output");
assert!(
csharp.contains("private static dynamic sub_0x0004()")
|| csharp.contains("private static void sub_0x0004()")
|| csharp.contains("private static BigInteger sub_0x0004()")
|| csharp.contains("private static object sub_0x0004()"),
"C# output should emit inferred helper method definitions for resolved internal calls: {csharp}"
);
assert!(
!csharp.contains("sub_0x0003"),
"C# output should not emit nop-only inferred helper methods: {csharp}"
);
}
#[test]
fn csharp_inferred_nonvoid_helpers_do_not_emit_bare_return() {
let script = [
OpCode::Call.byte(),
0x04,
OpCode::Ret.byte(),
OpCode::Nop.byte(),
OpCode::Ret.byte(),
];
let nef_bytes = build_nef(&script);
let decompilation = Decompiler::new()
.decompile_bytes_with_manifest(&nef_bytes, None, OutputFormat::All)
.expect("decompile succeeds");
let csharp = decompilation.csharp.as_deref().expect("csharp output");
assert!(
!csharp.contains(
"private static dynamic sub_0x0004()
{
// 0004: RET
return;"
),
"non-void inferred helper bodies should not emit bare return statements: {csharp}"
);
}
#[test]
fn csharp_trims_initslot_boundaries() {
let Some(nef_bytes) = try_load_testing_nef("Contract_Delegate.nef") else {
eprintln!("Skipping: Contract_Delegate.nef not found in devpack artifacts");
return;
};
let Some(manifest) = try_load_testing_manifest("Contract_Delegate.manifest.json") else {
eprintln!("Skipping: Contract_Delegate.manifest.json not found");
return;
};
let decompilation = Decompiler::new()
.decompile_bytes_with_manifest(&nef_bytes, Some(manifest), OutputFormat::All)
.expect("decompile succeeds");
let csharp = decompilation.csharp.as_deref().expect("csharp output");
let sum_block = csharp
.split("public static BigInteger sumFunc")
.nth(1)
.and_then(|rest| rest.split("private static dynamic sub_0x000C").next())
.expect("sumFunc block present");
assert!(
sum_block.contains("// 0000: INITSLOT"),
"sumFunc should still show its entry INITSLOT"
);
assert!(
!sum_block.contains("// 000C: INITSLOT"),
"sumFunc body should stop before the inferred helper block"
);
assert!(
!sum_block.contains("return t23;"),
"duplicate return from appended block should not appear in sumFunc"
);
assert!(
csharp.contains("private static dynamic sub_0x000C"),
"inferred helper should now be emitted separately"
);
}