summaryrefslogtreecommitdiff
path: root/rust/tests/binary_view.rs
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2025-01-31 15:14:14 -0500
committerMason Reed <mason@vector35.com>2025-07-02 01:56:53 -0400
commitdb8f0a498947c6bbd93526520b4a51f758cae540 (patch)
treebd9150bf45510387e332805b931773588cd6bdae /rust/tests/binary_view.rs
parentf8aaf21991c2a5adcdca56f3638f321b2ccbe809 (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.rs60
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);
+ }
+ }
+}