#![allow(clippy::uninlined_format_args)]
pub mod common;
pub mod test_utils {
use std::sync::Once;
static INIT: Once = Once::new();
pub fn init_test_env() {
INIT.call_once(|| {
let _ = env_logger::builder()
.filter_level(log::LevelFilter::Debug)
.is_test(true)
.try_init();
});
}
pub fn create_test_binary(
format: threatflux_binary_analysis::types::BinaryFormat,
size: usize,
) -> Vec<u8> {
let mut data = match format {
threatflux_binary_analysis::types::BinaryFormat::Elf => {
vec![0x7f, 0x45, 0x4c, 0x46] }
threatflux_binary_analysis::types::BinaryFormat::Pe => {
vec![0x4d, 0x5a] }
threatflux_binary_analysis::types::BinaryFormat::MachO => {
vec![0xfe, 0xed, 0xfa, 0xce] }
threatflux_binary_analysis::types::BinaryFormat::Java => {
vec![0xca, 0xfe, 0xba, 0xbe] }
threatflux_binary_analysis::types::BinaryFormat::Wasm => {
vec![0x00, 0x61, 0x73, 0x6d] }
_ => vec![0x00, 0x01, 0x02, 0x03], };
data.resize(size, 0);
data
}
pub fn measure_performance<F, R>(name: &str, f: F) -> R
where
F: FnOnce() -> R,
{
let start = std::time::Instant::now();
let result = f();
let duration = start.elapsed();
println!("Performance test '{}': {:?}", name, duration);
match name {
"format_detection" => assert!(duration.as_millis() < 10),
"basic_analysis" => assert!(duration.as_millis() < 100),
"full_analysis" => assert!(duration.as_millis() < 1000),
_ => {} }
result
}
pub fn check_memory_usage<F>(f: F)
where
F: Fn(),
{
for _ in 0..1000 {
f();
}
}
pub fn create_temp_binary(data: &[u8]) -> tempfile::NamedTempFile {
use std::io::Write;
let mut file = tempfile::NamedTempFile::new().unwrap();
file.write_all(data).unwrap();
file.flush().unwrap();
file
}
pub fn verify_analysis_completeness(
result: &threatflux_binary_analysis::types::AnalysisResult,
expected_format: threatflux_binary_analysis::types::BinaryFormat,
) {
assert_eq!(result.format, expected_format);
assert_ne!(
result.architecture,
threatflux_binary_analysis::types::Architecture::Unknown
);
assert_eq!(result.metadata.format, result.format);
assert_eq!(result.metadata.architecture, result.architecture);
assert!(result.metadata.size > 0);
if !matches!(
expected_format,
threatflux_binary_analysis::types::BinaryFormat::Raw
| threatflux_binary_analysis::types::BinaryFormat::Unknown
) {
let _sections = &result.sections;
}
let _symbols = &result.symbols;
let _imports = &result.imports;
let _exports = &result.exports;
}
}
pub mod assertions {
use threatflux_binary_analysis::types::*;
pub fn assert_format_detected(data: &[u8], expected: BinaryFormat) {
let format = threatflux_binary_analysis::formats::detect_format(data).unwrap();
assert_eq!(
format, expected,
"Format detection failed for {:?}",
expected
);
}
pub fn assert_analysis_succeeds(data: &[u8]) {
let analyzer = threatflux_binary_analysis::BinaryAnalyzer::new();
let result = analyzer.analyze(data);
assert!(result.is_ok(), "Analysis failed: {:?}", result.err());
}
pub fn assert_analysis_result(
data: &[u8],
expected_format: BinaryFormat,
expected_arch: Architecture,
) {
let analyzer = threatflux_binary_analysis::BinaryAnalyzer::new();
let result = analyzer.analyze(data).unwrap();
assert_eq!(result.format, expected_format);
assert_eq!(result.architecture, expected_arch);
assert_eq!(result.metadata.format, expected_format);
assert_eq!(result.metadata.architecture, expected_arch);
}
pub fn assert_security_features_initialized(features: &SecurityFeatures) {
let _nx = features.nx_bit;
let _aslr = features.aslr;
let _canary = features.stack_canary;
let _cfi = features.cfi;
let _fortify = features.fortify;
let _pie = features.pie;
let _relro = features.relro;
let _signed = features.signed;
}
}
pub mod generators {
use threatflux_binary_analysis::types::*;
pub type TestBinaryTuple = (Vec<u8>, BinaryFormat, Architecture);
pub type StressTestData = Vec<(Vec<u8>, usize)>;
pub fn generate_test_binaries() -> Vec<TestBinaryTuple> {
vec![
(
super::test_utils::create_test_binary(BinaryFormat::Elf, 1024),
BinaryFormat::Elf,
Architecture::X86_64,
),
(
super::test_utils::create_test_binary(BinaryFormat::Pe, 1024),
BinaryFormat::Pe,
Architecture::X86_64,
),
(
super::test_utils::create_test_binary(BinaryFormat::MachO, 1024),
BinaryFormat::MachO,
Architecture::X86_64,
),
(
super::test_utils::create_test_binary(BinaryFormat::Java, 1024),
BinaryFormat::Java,
Architecture::Jvm,
),
(
super::test_utils::create_test_binary(BinaryFormat::Wasm, 1024),
BinaryFormat::Wasm,
Architecture::Wasm,
),
]
}
pub fn generate_malformed_binaries() -> Vec<Vec<u8>> {
vec![
vec![], vec![0xff], vec![0x00; 1024], vec![0xff; 1024], b"This is not a binary file".to_vec(), vec![0x7f, 0x45, 0x4c], vec![0x4d, 0x5a, 0x90], ]
}
pub fn generate_stress_test_data() -> StressTestData {
let sizes = vec![
1024, 64 * 1024, 1024 * 1024, 10 * 1024 * 1024, ];
sizes
.into_iter()
.map(|size| {
(
super::test_utils::create_test_binary(BinaryFormat::Elf, size),
size,
)
})
.collect()
}
}
#[cfg(test)]
mod module_tests {
use super::*;
#[test]
fn test_module_utilities() {
test_utils::init_test_env();
let data = test_utils::create_test_binary(
threatflux_binary_analysis::types::BinaryFormat::Elf,
1024,
);
assert!(data.len() == 1024);
assert!(data.starts_with(&[0x7f, 0x45, 0x4c, 0x46]));
}
#[test]
fn test_performance_measurement() {
let result = test_utils::measure_performance("test_operation", || {
std::thread::sleep(std::time::Duration::from_millis(1));
42
});
assert_eq!(result, 42);
}
#[test]
fn test_generators() {
let binaries = generators::generate_test_binaries();
assert!(!binaries.is_empty());
let malformed = generators::generate_malformed_binaries();
assert!(!malformed.is_empty());
let stress_data = generators::generate_stress_test_data();
assert!(!stress_data.is_empty());
}
}