#![allow(clippy::uninlined_format_args)]
use threatflux_binary_analysis::types::*;
#[cfg(feature = "elf")]
use threatflux_binary_analysis::BinaryFile;
use threatflux_binary_analysis::{AnalysisConfig, BinaryAnalyzer};
#[allow(dead_code)]
fn create_mock_elf_data() -> Vec<u8> {
let mut data = vec![
0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, ];
data.resize(64, 0);
data[16] = 0x02; data[17] = 0x00;
data[18] = 0x3e; data[19] = 0x00;
data[24] = 0x00; data[25] = 0x10;
data[26] = 0x00;
data[27] = 0x00;
data[28] = 0x00;
data[29] = 0x00;
data[30] = 0x00;
data[31] = 0x00;
data.resize(1024, 0);
data
}
#[cfg(feature = "pe")]
fn create_mock_pe_data() -> Vec<u8> {
let mut data = vec![
0x4d, 0x5a, ];
data.resize(0x3c + 4, 0);
data[0x3c] = 0x80; data[0x3d] = 0x00;
data.resize(0x84, 0);
data[0x80] = 0x50; data[0x81] = 0x45;
data[0x82] = 0x00;
data[0x83] = 0x00;
data.resize(0x88, 0);
data[0x84] = 0x64; data[0x85] = 0x86;
data.resize(1024, 0);
data
}
#[test]
fn test_analyzer_creation() {
let analyzer = BinaryAnalyzer::new();
assert!(analyzer.config().enable_disassembly);
assert!(analyzer.config().enable_control_flow);
assert!(analyzer.config().enable_entropy);
assert!(analyzer.config().enable_symbols);
assert_eq!(analyzer.config().max_analysis_size, 100 * 1024 * 1024);
assert!(analyzer.config().architecture_hint.is_none());
}
#[test]
fn test_analyzer_with_custom_config() {
let config = AnalysisConfig {
enable_disassembly: false,
#[cfg(any(feature = "disasm-capstone", feature = "disasm-iced"))]
disassembly_engine: threatflux_binary_analysis::DisassemblyEngine::Auto,
enable_control_flow: true,
enable_entropy: false,
enable_symbols: true,
max_analysis_size: 1024,
architecture_hint: Some(Architecture::X86_64),
..Default::default()
};
let analyzer = BinaryAnalyzer::with_config(config);
assert!(!analyzer.config().enable_disassembly);
assert!(analyzer.config().enable_control_flow);
assert!(!analyzer.config().enable_entropy);
assert!(analyzer.config().enable_symbols);
assert_eq!(analyzer.config().max_analysis_size, 1024);
assert_eq!(
analyzer.config().architecture_hint,
Some(Architecture::X86_64)
);
}
#[test]
#[cfg(feature = "elf")]
fn test_analyze_elf_binary() {
let data = create_mock_elf_data();
let analyzer = BinaryAnalyzer::new();
let result = analyzer.analyze(&data);
assert!(result.is_ok(), "Analysis should succeed for valid ELF data");
let analysis = result.unwrap();
assert_eq!(analysis.format, BinaryFormat::Elf);
assert_eq!(analysis.architecture, Architecture::X86_64);
assert!(analysis.entry_point.is_some());
}
#[test]
#[cfg(feature = "pe")]
fn test_analyze_pe_binary() {
let data = create_mock_pe_data();
let analyzer = BinaryAnalyzer::new();
let result = analyzer.analyze(&data);
assert!(result.is_ok(), "Analysis should succeed for valid PE data");
let analysis = result.unwrap();
assert_eq!(analysis.format, BinaryFormat::Pe);
assert_eq!(analysis.architecture, Architecture::X86_64);
}
#[test]
fn test_analyze_invalid_binary() {
let data = vec![0x00, 0x01, 0x02, 0x03]; let analyzer = BinaryAnalyzer::new();
let result = analyzer.analyze(&data);
if let Ok(analysis) = result {
assert!(matches!(
analysis.format,
BinaryFormat::Unknown | BinaryFormat::Raw
));
}
}
#[test]
fn test_analyze_empty_data() {
let data = vec![];
let analyzer = BinaryAnalyzer::new();
let result = analyzer.analyze(&data);
assert!(result.is_err(), "Analysis should fail for empty data");
}
#[test]
#[cfg(feature = "elf")]
fn test_binary_file_parsing() {
let data = create_mock_elf_data();
let binary_file = BinaryFile::parse(&data);
assert!(binary_file.is_ok(), "Binary file parsing should succeed");
let binary = binary_file.unwrap();
assert_eq!(binary.format(), BinaryFormat::Elf);
assert_eq!(binary.architecture(), Architecture::X86_64);
assert!(binary.entry_point().is_some());
assert!(!binary.data().is_empty());
}
#[test]
#[cfg(feature = "elf")]
fn test_binary_file_sections() {
let data = create_mock_elf_data();
let binary = BinaryFile::parse(&data).unwrap();
let _sections = binary.sections();
}
#[test]
#[cfg(feature = "elf")]
fn test_binary_file_symbols() {
let data = create_mock_elf_data();
let binary = BinaryFile::parse(&data).unwrap();
let _symbols = binary.symbols();
}
#[test]
#[cfg(feature = "elf")]
fn test_binary_file_imports() {
let data = create_mock_elf_data();
let binary = BinaryFile::parse(&data).unwrap();
let _imports = binary.imports();
}
#[test]
#[cfg(feature = "elf")]
fn test_binary_file_exports() {
let data = create_mock_elf_data();
let binary = BinaryFile::parse(&data).unwrap();
let _exports = binary.exports();
}
#[test]
#[cfg(feature = "elf")]
fn test_binary_file_metadata() {
let data = create_mock_elf_data();
let binary = BinaryFile::parse(&data).unwrap();
let metadata = binary.metadata();
assert_eq!(metadata.format, BinaryFormat::Elf);
assert_eq!(metadata.architecture, Architecture::X86_64);
assert!(metadata.size > 0);
}
#[test]
fn test_analysis_config_default() {
let config = AnalysisConfig::default();
assert!(config.enable_disassembly);
assert!(config.enable_control_flow);
assert!(config.enable_entropy);
assert!(config.enable_symbols);
assert_eq!(config.max_analysis_size, 100 * 1024 * 1024);
assert!(config.architecture_hint.is_none());
}
#[test]
fn test_analyzer_default() {
let analyzer1 = BinaryAnalyzer::default();
let analyzer2 = BinaryAnalyzer::new();
assert_eq!(
analyzer1.config().enable_disassembly,
analyzer2.config().enable_disassembly
);
assert_eq!(
analyzer1.config().enable_control_flow,
analyzer2.config().enable_control_flow
);
assert_eq!(
analyzer1.config().enable_entropy,
analyzer2.config().enable_entropy
);
assert_eq!(
analyzer1.config().enable_symbols,
analyzer2.config().enable_symbols
);
}
#[test]
#[cfg(feature = "elf")]
fn test_large_file_analysis() {
let mut data = create_mock_elf_data();
data.resize(5 * 1024 * 1024, 0);
let config = AnalysisConfig {
max_analysis_size: 1024 * 1024, ..Default::default()
};
let analyzer = BinaryAnalyzer::with_config(config);
let result = analyzer.analyze(&data);
assert!(result.is_ok());
}
#[test]
#[cfg(feature = "elf")]
fn test_architecture_hint() {
let data = create_mock_elf_data();
let config = AnalysisConfig {
architecture_hint: Some(Architecture::Arm64),
..Default::default()
};
let analyzer = BinaryAnalyzer::with_config(config);
let result = analyzer.analyze(&data);
assert!(result.is_ok());
}
#[test]
#[cfg(feature = "elf")]
fn test_disabled_analysis_features() {
let data = create_mock_elf_data();
let config = AnalysisConfig {
enable_disassembly: false,
enable_control_flow: false,
enable_entropy: false,
enable_symbols: false,
..Default::default()
};
let analyzer = BinaryAnalyzer::with_config(config);
let result = analyzer.analyze(&data);
assert!(result.is_ok());
let analysis = result.unwrap();
assert!(analysis.disassembly.is_none());
assert!(analysis.control_flow.is_none());
assert!(analysis.entropy.is_none());
}
#[test]
#[cfg(feature = "elf")]
fn test_concurrent_analysis() {
use std::sync::Arc;
use std::thread;
let data = Arc::new(create_mock_elf_data());
let mut handles = vec![];
for _ in 0..5 {
let data_clone = Arc::clone(&data);
let handle = thread::spawn(move || {
let analyzer = BinaryAnalyzer::new();
analyzer.analyze(&data_clone)
});
handles.push(handle);
}
for handle in handles {
let result = handle.join().unwrap();
assert!(result.is_ok());
let analysis = result.unwrap();
assert_eq!(analysis.format, BinaryFormat::Elf);
}
}
#[test]
#[cfg(feature = "elf")]
fn test_analysis_result_completeness() {
let data = create_mock_elf_data();
let analyzer = BinaryAnalyzer::new();
let result = analyzer.analyze(&data).unwrap();
assert_ne!(result.format, BinaryFormat::Unknown);
assert_ne!(result.architecture, Architecture::Unknown);
assert_eq!(result.metadata.format, result.format);
assert_eq!(result.metadata.architecture, result.architecture);
assert!(result.metadata.size > 0);
}
#[test]
fn test_error_handling() {
let analyzer = BinaryAnalyzer::new();
let empty_data = vec![];
assert!(analyzer.analyze(&empty_data).is_err());
let corrupt_data = vec![0xff; 10];
let result = analyzer.analyze(&corrupt_data);
if let Ok(analysis_result) = result {
let format = analysis_result.format;
assert!(matches!(format, BinaryFormat::Unknown | BinaryFormat::Raw));
}
}
#[test]
#[cfg(feature = "elf")]
fn test_analysis_performance() {
let data = create_mock_elf_data();
let analyzer = BinaryAnalyzer::new();
let start = std::time::Instant::now();
let result = analyzer.analyze(&data);
let duration = start.elapsed();
assert!(result.is_ok());
assert!(duration.as_millis() < 1000); }