33import sys
44import asyncio
55from io import StringIO
6+ import os
67from src .analyzeMFT .cli import main
78from src .analyzeMFT .constants import VERSION
89
@@ -21,23 +22,24 @@ def mock_stdout():
2122@pytest .mark .asyncio
2223async def test_main_with_valid_arguments (mock_analyzer , caplog ):
2324 test_args = ['analyzeMFT.py' , '-f' , 'test.mft' , '-o' , 'output.csv' ]
24- with patch .object (sys , 'argv' , test_args ):
25+ with patch .object (sys , 'argv' , test_args ), \
26+ patch ('os.path.abspath' , side_effect = lambda x : f'/abs/{ x } ' ):
2527 await main ()
2628
2729 mock_analyzer .assert_called_once_with (
28- mft_file = ' test.mft' ,
29- output_file = ' output.csv' ,
30- verbosity = 0 ,
31- debug = 0 ,
32- compute_hashes = False ,
33- export_format = 'csv' ,
34- config_file = None ,
35- chunk_size = 1000 ,
36- enable_progress = True ,
37- analysis_profile = None
30+ '/abs/ test.mft' ,
31+ '/abs/ output.csv' ,
32+ 0 ,
33+ 0 ,
34+ False ,
35+ 'csv' ,
36+ None ,
37+ 1000 ,
38+ True ,
39+ None
3840 )
3941 mock_analyzer .return_value .analyze .assert_called_once ()
40- assert "Analysis complete. Results written to output.csv" in caplog .text
42+ assert "Analysis complete. Results written to /abs/ output.csv" in caplog .text
4143
4244@pytest .mark .asyncio
4345async def test_main_with_missing_arguments (capsys ):
@@ -57,83 +59,87 @@ async def test_main_with_missing_arguments(capsys):
5759 ('--excel' , 'excel' ),
5860 ('--body' , 'body' ),
5961 ('--timeline' , 'timeline' ),
60- ('--log2timeline ' , 'l2t' )
62+ ('--l2t ' , 'l2t' )
6163])
6264async def test_main_with_different_export_formats (mock_analyzer , export_flag , format_name ):
6365 output_ext = 'l2tcsv' if format_name == 'l2t' else format_name
6466 test_args = ['analyzeMFT.py' , '-f' , 'test.mft' , '-o' , f'output.{ output_ext } ' , export_flag ]
65- with patch .object (sys , 'argv' , test_args ):
67+ with patch .object (sys , 'argv' , test_args ), \
68+ patch ('os.path.abspath' , side_effect = lambda x : f'/abs/{ x } ' ):
6669 await main ()
6770
68- expected_output = f'output.{ output_ext } '
71+ expected_output = f'/abs/ output.{ output_ext } '
6972 mock_analyzer .assert_called_once_with (
70- mft_file = ' test.mft' ,
71- output_file = expected_output ,
72- verbosity = 0 ,
73- debug = 0 ,
74- compute_hashes = False ,
75- export_format = format_name ,
76- config_file = None ,
77- chunk_size = 1000 ,
78- enable_progress = True ,
79- analysis_profile = None
73+ '/abs/ test.mft' ,
74+ expected_output ,
75+ 0 ,
76+ 0 ,
77+ False ,
78+ format_name ,
79+ None ,
80+ 1000 ,
81+ True ,
82+ None
8083 )
8184
8285@pytest .mark .asyncio
8386async def test_main_with_debug_option (mock_analyzer ):
84- test_args = ['analyzeMFT.py' , '-f' , 'test.mft' , '-o' , 'output.csv' , '-d' ]
85- with patch .object (sys , 'argv' , test_args ):
87+ test_args = ['analyzeMFT.py' , '-f' , 'test.mft' , '-o' , 'output.csv' , '--debug' ]
88+ with patch .object (sys , 'argv' , test_args ), \
89+ patch ('os.path.abspath' , side_effect = lambda x : f'/abs/{ x } ' ):
8690 await main ()
8791
8892 mock_analyzer .assert_called_once_with (
89- mft_file = ' test.mft' ,
90- output_file = ' output.csv' ,
91- verbosity = 0 ,
92- debug = 1 ,
93- compute_hashes = False ,
94- export_format = 'csv' ,
95- config_file = None ,
96- chunk_size = 1000 ,
97- enable_progress = True ,
98- analysis_profile = None
93+ '/abs/ test.mft' ,
94+ '/abs/ output.csv' ,
95+ 1 ,
96+ 0 ,
97+ False ,
98+ 'csv' ,
99+ None ,
100+ 1000 ,
101+ True ,
102+ None
99103 )
100104
101105@pytest .mark .asyncio
102106async def test_main_with_verbosity_option (mock_analyzer ):
103- test_args = ['analyzeMFT.py' , '-f' , 'test.mft' , '-o' , 'output.csv' , '-v' ]
104- with patch .object (sys , 'argv' , test_args ):
107+ test_args = ['analyzeMFT.py' , '-f' , 'test.mft' , '-o' , 'output.csv' , '--verbose' ]
108+ with patch .object (sys , 'argv' , test_args ), \
109+ patch ('os.path.abspath' , side_effect = lambda x : f'/abs/{ x } ' ):
105110 await main ()
106111
107112 mock_analyzer .assert_called_once_with (
108- mft_file = ' test.mft' ,
109- output_file = ' output.csv' ,
110- verbosity = 1 ,
111- debug = 0 ,
112- compute_hashes = False ,
113- export_format = 'csv' ,
114- config_file = None ,
115- chunk_size = 1000 ,
116- enable_progress = True ,
117- analysis_profile = None
113+ '/abs/ test.mft' ,
114+ '/abs/ output.csv' ,
115+ 1 ,
116+ 0 ,
117+ False ,
118+ 'csv' ,
119+ None ,
120+ 1000 ,
121+ True ,
122+ None
118123 )
119124
120125@pytest .mark .asyncio
121126async def test_main_with_hash_option (mock_analyzer ):
122- test_args = ['analyzeMFT.py' , '-f' , 'test.mft' , '-o' , 'output.csv' , '-H' ]
123- with patch .object (sys , 'argv' , test_args ):
127+ test_args = ['analyzeMFT.py' , '-f' , 'test.mft' , '-o' , 'output.csv' , '--hash' ]
128+ with patch .object (sys , 'argv' , test_args ), \
129+ patch ('os.path.abspath' , side_effect = lambda x : f'/abs/{ x } ' ):
124130 await main ()
125131
126132 mock_analyzer .assert_called_once_with (
127- mft_file = ' test.mft' ,
128- output_file = ' output.csv' ,
129- verbosity = 0 ,
130- debug = 0 ,
131- compute_hashes = True ,
132- export_format = 'csv' ,
133- config_file = None ,
134- chunk_size = 1000 ,
135- enable_progress = True ,
136- analysis_profile = None
133+ '/abs/ test.mft' ,
134+ '/abs/ output.csv' ,
135+ 0 ,
136+ 0 ,
137+ True ,
138+ 'csv' ,
139+ None ,
140+ 1000 ,
141+ True ,
142+ None
137143 )
138144
139145@pytest .mark .asyncio
@@ -183,7 +189,8 @@ async def test_main_with_keyboard_interrupt(mock_analyzer, caplog):
183189async def test_main_with_non_windows_platform (mock_analyzer ):
184190 with patch ('sys.platform' , 'linux' ):
185191 test_args = ['analyzeMFT.py' , '-f' , 'test.mft' , '-o' , 'output.csv' ]
186- with patch .object (sys , 'argv' , test_args ):
192+ with patch .object (sys , 'argv' , test_args ), \
193+ patch ('os.path.abspath' , side_effect = lambda x : f'/abs/{ x } ' ):
187194 await main ()
188195
189196 mock_analyzer .assert_called_once ()
@@ -194,23 +201,37 @@ def test_main_with_invalid_file_path(caplog):
194201 with pytest .raises (SystemExit ):
195202 asyncio .run (main ())
196203
197- assert "Error reading MFT file" in caplog .text
198- assert "No such file or directory" in caplog .text or "not found" in caplog .text
204+ assert ( "Error reading MFT file" in caplog .text or "Validation Error" in caplog . text )
205+ assert ( "No such file or directory" in caplog .text or "not found" in caplog .text )
199206
200207def test_main_with_config_file (mock_analyzer ):
201208 test_args = ['analyzeMFT.py' , '-f' , 'test.mft' , '-o' , 'output.csv' , '-c' , 'config.json' ]
202- with patch .object (sys , 'argv' , test_args ):
209+
210+ mock_config_data = {'profile_name' : 'default' , 'verbosity' : 1 }
211+
212+ from src .analyzeMFT .config import AnalysisProfile
213+ mock_profile = AnalysisProfile (
214+ name = "test" ,
215+ export_format = "csv" ,
216+ verbosity = 1 ,
217+ chunk_size = 1000
218+ )
219+
220+ with patch .object (sys , 'argv' , test_args ), \
221+ patch ('os.path.abspath' , side_effect = lambda x : f'/abs/{ x } ' ), \
222+ patch ('src.analyzeMFT.config.ConfigManager.load_config_file' , return_value = mock_config_data ), \
223+ patch ('src.analyzeMFT.config.ConfigManager.load_profile_from_config' , return_value = mock_profile ):
203224 asyncio .run (main ())
204225
205- mock_analyzer . assert_called_once_with (
206- mft_file = 'test.mft' ,
207- output_file = 'output.csv' ,
208- verbosity = 0 ,
209- debug = 0 ,
210- compute_hashes = False ,
211- export_format = 'csv' ,
212- config_file = 'config.json' ,
213- chunk_size = 1000 ,
214- enable_progress = True ,
215- analysis_profile = None
216- )
226+ # The actual call arguments from the CLI
227+ mock_analyzer . assert_called_once ()
228+
229+ call_args = mock_analyzer . call_args [ 0 ]
230+ assert call_args [ 0 ]. endswith ( 'test.mft' ) # filename
231+ assert call_args [ 1 ]. endswith ( 'output.csv' ) # output file
232+ assert call_args [ 2 ] == 0 # verbosity from options (not profile)
233+ assert call_args [ 3 ] == 1 # debug from profile
234+ assert call_args [ 4 ] == False # compute hashes
235+ assert call_args [ 5 ] == 'csv' # export format
236+ assert call_args [ 6 ] == mock_profile # profile object
237+ assert call_args [ 7 ] == 1000 # chunk size
0 commit comments