use crate::emu::Emu;
use crate::emu64;
use rs_header::pe::{IMAGE_FILE_MACHINE_AMD64, IMAGE_FILE_MACHINE_I386, pe_machine_type};
use std::io::Write;
fn write_temp(name: &str, bytes: &[u8]) -> String {
let path = std::env::temp_dir().join(name);
std::fs::File::create(&path)
.unwrap()
.write_all(bytes)
.unwrap();
path.to_string_lossy().into_owned()
}
fn build_minimal_pe(machine: u16) -> Vec<u8> {
let e_lfanew: u32 = 0x40;
let nt_off = e_lfanew as usize;
let mut bytes = vec![0u8; nt_off + 6];
bytes[0] = b'M';
bytes[1] = b'Z';
bytes[0x3c..0x40].copy_from_slice(&e_lfanew.to_le_bytes());
bytes[nt_off..nt_off + 4].copy_from_slice(&0x0000_4550u32.to_le_bytes());
bytes[nt_off + 4..nt_off + 6].copy_from_slice(&machine.to_le_bytes());
bytes
}
#[test]
fn load_missing_file_does_not_panic() {
let mut emu = emu64();
emu.load_code("/nonexistent/path/definitely/not/here.bin");
}
#[test]
fn classifier_detects_elf() {
let mut elf = vec![0u8; 20];
elf[0..4].copy_from_slice(&[0x7f, b'E', b'L', b'F']);
elf[4] = 2; elf[18..20].copy_from_slice(&0x003eu16.to_le_bytes()); let path = write_temp("mwemu_rob_elf.bin", &elf);
assert!(Emu::is_non_windows_file(&path, false));
assert!(!Emu::is_non_windows_file(&path, true));
}
#[test]
fn classifier_treats_garbage_as_shellcode() {
let path = write_temp("mwemu_rob_sc.bin", &[0x90, 0x90, 0xc3]);
assert!(!Emu::is_non_windows_file(&path, false));
}
#[test]
fn classifier_on_missing_file_does_not_panic() {
assert!(!Emu::is_non_windows_file("/nonexistent/xyz", false));
}
#[test]
fn detect_pe_arch_identifies_pe32_x86() {
let bytes = build_minimal_pe(IMAGE_FILE_MACHINE_I386);
assert_eq!(pe_machine_type(&bytes), Some(IMAGE_FILE_MACHINE_I386));
let path = write_temp("mwemu_rob_pe32.bin", &bytes);
assert_eq!(Emu::detect_pe_arch(&path), Some(IMAGE_FILE_MACHINE_I386));
}
#[test]
fn detect_pe_arch_identifies_pe64_x86_64() {
let bytes = build_minimal_pe(IMAGE_FILE_MACHINE_AMD64);
assert_eq!(pe_machine_type(&bytes), Some(IMAGE_FILE_MACHINE_AMD64));
let path = write_temp("mwemu_rob_pe64.bin", &bytes);
assert_eq!(Emu::detect_pe_arch(&path), Some(IMAGE_FILE_MACHINE_AMD64));
}
#[test]
fn detect_pe_arch_returns_none_for_non_pe() {
let mut elf = vec![0u8; 20];
elf[0..4].copy_from_slice(&[0x7f, b'E', b'L', b'F']);
elf[4] = 2;
let elf_path = write_temp("mwemu_rob_elf_for_pe.bin", &elf);
assert_eq!(Emu::detect_pe_arch(&elf_path), None);
let sc_path = write_temp("mwemu_rob_sc_for_pe.bin", &[0x90, 0x90, 0xc3]);
assert_eq!(Emu::detect_pe_arch(&sc_path), None);
let mut mz_only = vec![0u8; 0x40];
mz_only[0] = b'M';
mz_only[1] = b'Z';
let mz_path = write_temp("mwemu_rob_mz_only.bin", &mz_only);
assert_eq!(Emu::detect_pe_arch(&mz_path), None);
assert_eq!(Emu::detect_pe_arch("/nonexistent/xyz"), None);
}
#[test]
fn pe32_x64_mismatch_only_fires_for_pe32_plus_dash_six() {
let pe32 = write_temp(
"mwemu_rob_mismatch_pe32.bin",
&build_minimal_pe(IMAGE_FILE_MACHINE_I386),
);
let pe64 = write_temp(
"mwemu_rob_mismatch_pe64.bin",
&build_minimal_pe(IMAGE_FILE_MACHINE_AMD64),
);
let sc = write_temp("mwemu_rob_mismatch_sc.bin", &[0x90, 0x90, 0xc3]);
assert!(Emu::pe32_x64_mismatch_error(&pe32, true).is_some());
assert!(Emu::pe32_x64_mismatch_error(&pe64, true).is_none());
assert!(Emu::pe32_x64_mismatch_error(&pe32, false).is_none());
assert!(Emu::pe32_x64_mismatch_error(&sc, true).is_none());
assert!(Emu::pe32_x64_mismatch_error("/nonexistent/xyz", true).is_none());
}