use xll_utils::pe::parse_pe_file;
use xll_utils::types::Architecture;
fn fixture_path() -> std::path::PathBuf {
std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
.join("tests")
.join("fixtures")
.join("test_xll.xll")
}
#[test]
fn parse_fixture_xll() {
let pe = parse_pe_file(fixture_path()).unwrap();
assert!(pe.is_dll());
assert_eq!(pe.architecture(), Architecture::X64);
}
#[test]
fn fixture_has_exports() {
let pe = parse_pe_file(fixture_path()).unwrap();
assert!(!pe.exports().is_empty(), "fixture should have exports");
assert!(
pe.exports().len() >= 4,
"expected at least 4 exports, got {}",
pe.exports().len()
);
}
#[test]
fn fixture_has_xl_auto_open() {
let pe = parse_pe_file(fixture_path()).unwrap();
assert!(
pe.find_export("xlAutoOpen").is_some(),
"xlAutoOpen not found in exports: {:?}",
pe.export_names()
);
}
#[test]
fn fixture_has_xl_auto_close() {
let pe = parse_pe_file(fixture_path()).unwrap();
assert!(pe.find_export("xlAutoClose").is_some());
}
#[test]
fn fixture_has_xl_auto_free12() {
let pe = parse_pe_file(fixture_path()).unwrap();
assert!(pe.find_export("xlAutoFree12").is_some());
}
#[test]
fn fixture_has_xl_addin_manager_info12() {
let pe = parse_pe_file(fixture_path()).unwrap();
assert!(pe.find_export("xlAddInManagerInfo12").is_some());
}
#[test]
fn fixture_has_user_functions() {
let pe = parse_pe_file(fixture_path()).unwrap();
for name in ["xl_add", "xl_multiply", "xl_negate", "xl_version"] {
assert!(
pe.find_export(name).is_some(),
"expected export '{name}' not found"
);
}
}
#[test]
fn fixture_export_names_sorted() {
let pe = parse_pe_file(fixture_path()).unwrap();
let names = pe.export_names();
let mut sorted = names.clone();
sorted.sort();
assert_eq!(names, sorted, "export_names() should return sorted names");
}
#[test]
fn fixture_exports_are_not_forwarded() {
let pe = parse_pe_file(fixture_path()).unwrap();
for exp in pe.exports() {
assert!(
!exp.is_forwarded,
"export {:?} should not be forwarded",
exp.name
);
assert!(exp.forward_to.is_none());
assert!(exp.relative_address.is_some());
}
}
#[test]
fn fixture_export_directory_present() {
let pe = parse_pe_file(fixture_path()).unwrap();
let dir = pe.export_directory().expect("export directory should exist");
assert!(dir.address_table_entries > 0);
assert!(dir.number_of_name_pointers > 0);
assert_eq!(dir.address_table_entries, dir.number_of_name_pointers);
}
#[test]
fn fixture_image_base_nonzero() {
let pe = parse_pe_file(fixture_path()).unwrap();
assert!(pe.image_base > 0, "image base should be nonzero");
}
#[test]
fn find_export_by_ordinal() {
let pe = parse_pe_file(fixture_path()).unwrap();
let first = &pe.exports()[0];
let found = pe.find_export_by_ordinal(first.ordinal);
assert!(found.is_some());
assert_eq!(found.unwrap().name, first.name);
}
#[test]
fn find_nonexistent_export() {
let pe = parse_pe_file(fixture_path()).unwrap();
assert!(pe.find_export("nonExistentExport").is_none());
}
#[test]
fn parse_from_bytes() {
let data = std::fs::read(fixture_path()).unwrap();
let pe = xll_utils::PeFile::from_bytes(&data).unwrap();
assert!(pe.is_dll());
assert_eq!(pe.architecture(), Architecture::X64);
assert!(pe.find_export("xlAutoOpen").is_some());
}
#[test]
fn parse_invalid_data() {
let data = b"this is not a PE file";
let err = xll_utils::PeFile::from_bytes(data).unwrap_err();
assert!(
matches!(err, xll_utils::Error::InvalidFileFormat),
"expected InvalidFileFormat, got: {err}"
);
}
#[test]
fn parse_nonexistent_file() {
let err = parse_pe_file("nonexistent_file.dll").unwrap_err();
assert!(
matches!(err, xll_utils::Error::FileOpen { .. }),
"expected FileOpen, got: {err}"
);
}