11use binaryninja:: binary_view:: { AnalysisState , BinaryViewBase , BinaryViewExt } ;
2+ use binaryninja:: function:: Function ;
23use binaryninja:: headless:: Session ;
34use binaryninja:: main_thread:: execute_on_main_thread_and_wait;
4- use binaryninja:: symbol:: { SymbolBuilder , SymbolType } ;
5+ use binaryninja:: platform:: Platform ;
6+ use binaryninja:: rc:: Ref ;
7+ use binaryninja:: symbol:: { Symbol , SymbolBuilder , SymbolType } ;
58use rstest:: * ;
9+ use std:: collections:: BTreeMap ;
610use std:: path:: PathBuf ;
711
812#[ fixture]
@@ -37,15 +41,13 @@ fn test_binary_saving(_session: &Session) {
3741 // HACK: To prevent us from deadlocking in save_to_path we wait for all main thread actions to finish.
3842 execute_on_main_thread_and_wait ( || { } ) ;
3943
44+ let temp_dir = tempfile:: tempdir ( ) . expect ( "Failed to create temporary directory" ) ;
45+ let temp_path = temp_dir. path ( ) . join ( "atox.obj.new" ) ;
4046 // Save the modified file
41- assert ! ( view. save_to_path( out_dir . join ( "atox.obj.new" ) ) ) ;
47+ assert ! ( view. save_to_path( & temp_path ) ) ;
4248 // Verify that the file exists and is modified.
43- let new_view =
44- binaryninja:: load ( out_dir. join ( "atox.obj.new" ) ) . expect ( "Failed to load new view" ) ;
45- assert_eq ! (
46- new_view. read_vec( contents_addr, 4 ) ,
47- [ 0xff , 0xff , 0xff , 0xff ]
48- ) ;
49+ let new_view = binaryninja:: load ( temp_path) . expect ( "Failed to load new view" ) ;
50+ assert_eq ! ( new_view. read_vec( contents_addr, 4 ) , [ 0xff , 0xff , 0xff , 0xff ] ) ;
4951}
5052
5153#[ rstest]
@@ -62,12 +64,53 @@ fn test_binary_saving_database(_session: &Session) {
6264 // Verify that we modified the binary
6365 assert_eq ! ( entry_function. symbol( ) . raw_name( ) . as_str( ) , "test" ) ;
6466 // Save the modified database.
65- assert ! ( view. file( ) . create_database( out_dir. join( "atox.obj.bndb" ) ) ) ;
67+ let temp_dir = tempfile:: tempdir ( ) . expect ( "Failed to create temporary directory" ) ;
68+ let temp_path = temp_dir. path ( ) . join ( "atox.obj.bndb" ) ;
69+ assert ! ( view. file( ) . create_database( & temp_path) ) ;
6670 // Verify that the file exists and is modified.
67- let new_view =
68- binaryninja:: load ( out_dir. join ( "atox.obj.bndb" ) ) . expect ( "Failed to load new view" ) ;
71+ let new_view = binaryninja:: load ( temp_path) . expect ( "Failed to load new view" ) ;
6972 let new_entry_function = new_view
7073 . entry_point_function ( )
7174 . expect ( "Failed to get entry point function" ) ;
7275 assert_eq ! ( new_entry_function. symbol( ) . raw_name( ) . as_str( ) , "test" ) ;
7376}
77+
78+ // This is what we store to check if a function matches the expected function.
79+ // See `test_deterministic_functions` for details.
80+ #[ derive( Debug , PartialEq ) ]
81+ pub struct FunctionSnapshot {
82+ name : String ,
83+ platform : Ref < Platform > ,
84+ symbol : Ref < Symbol > ,
85+ }
86+
87+ impl From < & Function > for FunctionSnapshot {
88+ fn from ( func : & Function ) -> Self {
89+ Self {
90+ name : func. symbol ( ) . raw_name ( ) . to_string ( ) ,
91+ platform : func. platform ( ) . to_owned ( ) ,
92+ symbol : func. symbol ( ) . to_owned ( ) ,
93+ }
94+ }
95+ }
96+
97+ #[ rstest]
98+ fn test_deterministic_functions ( session : & Session ) {
99+ // Test to make sure that analysis always collects the same information on functions.
100+ let out_dir = env ! ( "OUT_DIR" ) . parse :: < PathBuf > ( ) . unwrap ( ) ;
101+ for entry in std:: fs:: read_dir ( out_dir) . expect ( "Failed to read OUT_DIR" ) {
102+ let entry = entry. expect ( "Failed to read directory entry" ) ;
103+ let path = entry. path ( ) ;
104+ if path. is_file ( ) {
105+ let view = session. load ( & path) . expect ( "Failed to load view" ) ;
106+ assert_eq ! ( view. analysis_progress( ) . state, AnalysisState :: IdleState ) ;
107+ let functions: BTreeMap < u64 , FunctionSnapshot > = view
108+ . functions ( )
109+ . iter ( )
110+ . map ( |f| ( f. start ( ) , FunctionSnapshot :: from ( f. as_ref ( ) ) ) )
111+ . collect ( ) ;
112+ let snapshot_name = path. file_stem ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
113+ insta:: assert_debug_snapshot!( snapshot_name, functions) ;
114+ }
115+ }
116+ }
0 commit comments