diff options
| author | Mason Reed <mason@vector35.com> | 2025-01-31 15:14:14 -0500 |
|---|---|---|
| committer | Mason Reed <mason@vector35.com> | 2025-07-02 01:56:53 -0400 |
| commit | db8f0a498947c6bbd93526520b4a51f758cae540 (patch) | |
| tree | bd9150bf45510387e332805b931773588cd6bdae /rust/tests/binary_view.rs | |
| parent | f8aaf21991c2a5adcdca56f3638f321b2ccbe809 (diff) | |
Add test_deterministic_functions to Rust API unit tests
This test makes sure that initial analysis is not tainting functions
Diffstat (limited to 'rust/tests/binary_view.rs')
| -rw-r--r-- | rust/tests/binary_view.rs | 60 |
1 files changed, 50 insertions, 10 deletions
diff --git a/rust/tests/binary_view.rs b/rust/tests/binary_view.rs index dbe47941..a0475cd3 100644 --- a/rust/tests/binary_view.rs +++ b/rust/tests/binary_view.rs @@ -1,4 +1,5 @@ use binaryninja::binary_view::{AnalysisState, BinaryViewBase, BinaryViewExt}; +use binaryninja::function::Function; use binaryninja::headless::Session; use binaryninja::main_thread::execute_on_main_thread_and_wait; use binaryninja::symbol::{SymbolBuilder, SymbolType}; @@ -32,15 +33,13 @@ fn test_binary_saving() { // HACK: To prevent us from deadlocking in save_to_path, we wait for all main thread actions to finish. execute_on_main_thread_and_wait(|| {}); + let temp_dir = tempfile::tempdir().expect("Failed to create temporary directory"); + let temp_path = temp_dir.path().join("atox.obj.new"); // Save the modified file - assert!(view.save_to_path(out_dir.join("atox.obj.new"))); + assert!(view.save_to_path(&temp_path)); // Verify that the file exists and is modified. - let new_view = - binaryninja::load(out_dir.join("atox.obj.new")).expect("Failed to load new view"); - assert_eq!( - new_view.read_vec(contents_addr, 4), - [0xff, 0xff, 0xff, 0xff] - ); + let new_view = binaryninja::load(temp_path).expect("Failed to load new view"); + assert_eq!(new_view.read_vec(contents_addr, 4), [0xff, 0xff, 0xff, 0xff]); } #[test] @@ -58,10 +57,11 @@ fn test_binary_saving_database() { // Verify that we modified the binary assert_eq!(entry_function.symbol().raw_name().to_string_lossy(), "test"); // Save the modified database. - assert!(view.file().create_database(out_dir.join("atox.obj.bndb"))); + let temp_dir = tempfile::tempdir().expect("Failed to create temporary directory"); + let temp_path = temp_dir.path().join("atox.obj.bndb"); + assert!(view.file().create_database(&temp_path)); // Verify that the file exists and is modified. - let new_view = - binaryninja::load(out_dir.join("atox.obj.bndb")).expect("Failed to load new view"); + let new_view = binaryninja::load(temp_path).expect("Failed to load new view"); let new_entry_function = new_view .entry_point_function() .expect("Failed to get entry point function"); @@ -92,3 +92,43 @@ fn test_binary_view_strings() { assert_eq!(str_15dc.start, image_base + 0x15dc); assert_eq!(str_15dc.length, 33); } + +// This is what we store to check if a function matches the expected function. +// See `test_deterministic_functions` for details. +#[derive(Debug, PartialEq)] +pub struct FunctionSnapshot { + name: String, + platform: Ref<Platform>, + symbol: Ref<Symbol>, +} + +impl From<&Function> for FunctionSnapshot { + fn from(func: &Function) -> Self { + Self { + name: func.symbol().raw_name().to_string(), + platform: func.platform().to_owned(), + symbol: func.symbol().to_owned(), + } + } +} + +#[rstest] +fn test_deterministic_functions(session: &Session) { + // Test to make sure that analysis always collects the same information on functions. + let out_dir = env!("OUT_DIR").parse::<PathBuf>().unwrap(); + for entry in std::fs::read_dir(out_dir).expect("Failed to read OUT_DIR") { + let entry = entry.expect("Failed to read directory entry"); + let path = entry.path(); + if path.is_file() { + let view = session.load(&path).expect("Failed to load view"); + assert_eq!(view.analysis_progress().state, AnalysisState::IdleState); + let functions: BTreeMap<u64, FunctionSnapshot> = view + .functions() + .iter() + .map(|f| (f.start(), FunctionSnapshot::from(f.as_ref()))) + .collect(); + let snapshot_name = path.file_stem().unwrap().to_str().unwrap(); + insta::assert_debug_snapshot!(snapshot_name, functions); + } + } +} |
