@@ -376,7 +376,10 @@ def test_main_loads_ignore_from_script_dir(mock_scan, mock_load_ignore):
376376
377377 with mock .patch ('sys.argv' , test_args ):
378378 from version_scanner import main
379- main ()
379+ try :
380+ main ()
381+ except SystemExit :
382+ pass
380383
381384 mock_load_ignore .assert_called_once ()
382385 args , kwargs = mock_load_ignore .call_args
@@ -385,6 +388,13 @@ def test_main_loads_ignore_from_script_dir(mock_scan, mock_load_ignore):
385388 assert "scripts/version_scanner" in path
386389
387390
391+ try :
392+ import googleapiclient
393+ HAS_GOOGLE_API = True
394+ except ImportError :
395+ HAS_GOOGLE_API = False
396+
397+ @pytest .mark .skipif (not HAS_GOOGLE_API , reason = "Requires googleapiclient" )
388398@mock .patch ('googleapiclient.discovery.build' )
389399@mock .patch ('google.auth.default' )
390400def test_upload_to_drive (mock_auth , mock_build ):
@@ -479,6 +489,48 @@ def test_regex_examples_from_config():
479489 break
480490 assert matched , f"Example '{ example } ' in group '{ name } ' did not match any pattern."
481491
492+ def test_main_exit_code_1 ():
493+ """Test that main() calls sys.exit(1) when matches are found."""
494+ # We can mock scan_repository to return a dummy match
495+ test_args = ['version_scanner.py' , '-d' , 'python' , '-v' , '3.7' ]
496+ with mock .patch ('sys.argv' , test_args ):
497+ from version_scanner import main
498+ with mock .patch ('version_scanner.scan_repository' , return_value = [{'file_path' : 'test' , 'line_number' : 1 , 'matched_string' : '3.7' , 'rule_name' : 'test' }]):
499+ with pytest .raises (SystemExit ) as excinfo :
500+ main ()
501+ assert excinfo .value .code == 1
502+
503+ def test_main_stdout (capsys ):
504+ """Test that --stdout prints the CSV output to stdout."""
505+ test_args = ['version_scanner.py' , '-d' , 'python' , '-v' , '3.7' , '--stdout' ]
506+ with mock .patch ('sys.argv' , test_args ):
507+ from version_scanner import main
508+ with mock .patch ('version_scanner.scan_repository' , return_value = [{'file_path' : 'test.py' , 'line_number' : 1 , 'matched_string' : '3.7' , 'rule_name' : 'test' }]):
509+ with pytest .raises (SystemExit ):
510+ main ()
511+
512+ captured = capsys .readouterr ()
513+ assert "=== CSV Output ===" in captured .out
514+ assert "test.py," in captured .out
515+ assert "test," in captured .out
516+ assert "3.7" in captured .out
517+
518+ def test_scan_file_truncation_bug (tmp_path ):
519+ """Test that searching for 3.1 does NOT match 3.10 (truncation bug)."""
520+ # Create a file with 3.10
521+ test_file = tmp_path / "test_file.py"
522+ test_file .write_text ("python_requires = '>=3.10'\n python3.10\n Python310\n " )
523+
524+ from version_scanner import ConfigManager , scan_file
525+
526+ # Init config for 3.1
527+ config_manager = ConfigManager ("python" , "3.1" )
528+ config_manager .load_config ("regex_config.yaml" )
529+
530+ # It should not match anything because all strings are 3.10, not 3.1
531+ matches = scan_file (str (test_file ), config_manager .rules )
532+ assert len (matches ) == 0 , f"Expected 0 matches for 3.1 in 3.10 content, but got { len (matches )} : { matches } "
533+
482534
483535def test_scan_repository_layout_agnostic (tmp_path ):
484536 # Create directories under different roots
0 commit comments