@@ -510,6 +510,221 @@ def test_timing_default(self, mock_default_dirs):
510510 assert args .timing is False
511511
512512
513+ class TestVerbosityLevels :
514+ """Test suite for verbosity level behavior."""
515+
516+ def test_quiet_mode_suppresses_info_messages (self , temp_dirs , caplog ):
517+ """Test that quiet mode suppresses INFO level messages."""
518+ source_dir , target_dir = temp_dirs
519+ username = os .environ ["USER" ]
520+
521+ # Create files
522+ source_file = os .path .join (source_dir , "test_file.txt" )
523+ target_file = os .path .join (target_dir , "test_file.txt" )
524+
525+ with open (source_file , "w" , encoding = "utf-8" ) as f :
526+ f .write ("source" )
527+ with open (target_file , "w" , encoding = "utf-8" ) as f :
528+ f .write ("target" )
529+
530+ # Create a symlink to test "Skipping symlink" message
531+ source_link = os .path .join (source_dir , "existing_link.txt" )
532+ dummy_target = os .path .join (tempfile .gettempdir (), "somewhere" )
533+ os .symlink (dummy_target , source_link )
534+
535+ # Run the function with WARNING level (quiet mode)
536+ with caplog .at_level (logging .WARNING ):
537+ relink .find_and_replace_owned_files (source_dir , target_dir , username )
538+
539+ # Verify INFO messages are NOT in the log
540+ assert "Searching for files owned by" not in caplog .text
541+ assert "Skipping symlink:" not in caplog .text
542+ assert "Found owned file:" not in caplog .text
543+ assert "Deleted original file:" not in caplog .text
544+ assert "Created symbolic link:" not in caplog .text
545+
546+ def test_quiet_mode_shows_warnings (self , temp_dirs , caplog ):
547+ """Test that quiet mode still shows WARNING level messages."""
548+ source_dir , target_dir = temp_dirs
549+ username = os .environ ["USER" ]
550+
551+ # Create only source file (no corresponding target) to trigger warning
552+ source_file = os .path .join (source_dir , "orphan.txt" )
553+ with open (source_file , "w" , encoding = "utf-8" ) as f :
554+ f .write ("orphan content" )
555+
556+ # Run the function with WARNING level (quiet mode)
557+ with caplog .at_level (logging .WARNING ):
558+ relink .find_and_replace_owned_files (source_dir , target_dir , username )
559+
560+ # Verify WARNING message IS in the log
561+ assert "Warning: Corresponding file not found" in caplog .text
562+
563+ def test_quiet_mode_shows_errors (self , temp_dirs , caplog ):
564+ """Test that quiet mode still shows ERROR level messages."""
565+ source_dir , target_dir = temp_dirs
566+ username = os .environ ["USER" ]
567+
568+ # Test 1: Invalid username error
569+ invalid_username = "nonexistent_user_12345"
570+ with caplog .at_level (logging .WARNING ):
571+ relink .find_and_replace_owned_files (
572+ source_dir , target_dir , invalid_username
573+ )
574+ assert "Error: User" in caplog .text
575+ assert "not found" in caplog .text
576+
577+ # Clear the log for next test
578+ caplog .clear ()
579+
580+ # Test 2: Error deleting file
581+ source_file = os .path .join (source_dir , "test.txt" )
582+ target_file = os .path .join (target_dir , "test.txt" )
583+
584+ with open (source_file , "w" , encoding = "utf-8" ) as f :
585+ f .write ("source" )
586+ with open (target_file , "w" , encoding = "utf-8" ) as f :
587+ f .write ("target" )
588+
589+ def mock_rename (src , dst ):
590+ raise OSError ("Simulated rename error" )
591+
592+ with patch ("os.rename" , side_effect = mock_rename ):
593+ with caplog .at_level (logging .WARNING ):
594+ relink .find_and_replace_owned_files (source_dir , target_dir , username )
595+ assert "Error deleting file" in caplog .text
596+
597+ # Clear the log for next test
598+ caplog .clear ()
599+
600+ # Test 3: Error creating symlink
601+ source_file2 = os .path .join (source_dir , "test2.txt" )
602+ target_file2 = os .path .join (target_dir , "test2.txt" )
603+
604+ with open (source_file2 , "w" , encoding = "utf-8" ) as f :
605+ f .write ("source2" )
606+ with open (target_file2 , "w" , encoding = "utf-8" ) as f :
607+ f .write ("target2" )
608+
609+ def mock_symlink (src , dst ):
610+ raise OSError ("Simulated symlink error" )
611+
612+ with patch ("os.symlink" , side_effect = mock_symlink ):
613+ with caplog .at_level (logging .WARNING ):
614+ relink .find_and_replace_owned_files (source_dir , target_dir , username )
615+ assert "Error creating symlink" in caplog .text
616+
617+ class TestEdgeCases :
618+ """Test edge cases and error handling."""
619+
620+ def test_empty_directories (self , temp_dirs ):
621+ """Test with empty directories."""
622+ source_dir , target_dir = temp_dirs
623+ username = os .environ ["USER" ]
624+
625+ # Run with empty directories (should not crash)
626+ relink .find_and_replace_owned_files (source_dir , target_dir , username )
627+
628+ # Should complete without errors
629+ assert True
630+
631+ def test_file_with_spaces_in_name (self , temp_dirs ):
632+ """Test files with spaces in their names."""
633+ source_dir , target_dir = temp_dirs
634+ username = os .environ ["USER" ]
635+
636+ # Create files with spaces
637+ source_file = os .path .join (source_dir , "file with spaces.txt" )
638+ target_file = os .path .join (target_dir , "file with spaces.txt" )
639+
640+ with open (source_file , "w" , encoding = "utf-8" ) as f :
641+ f .write ("content" )
642+ with open (target_file , "w" , encoding = "utf-8" ) as f :
643+ f .write ("target content" )
644+
645+ # Run the function
646+ relink .find_and_replace_owned_files (source_dir , target_dir , username )
647+
648+ # Verify
649+ assert os .path .islink (source_file )
650+ assert os .readlink (source_file ) == target_file
651+
652+ def test_file_with_special_characters (self , temp_dirs ):
653+ """Test files with special characters in names."""
654+ source_dir , target_dir = temp_dirs
655+ username = os .environ ["USER" ]
656+
657+ # Create files with special chars (that are valid in filenames)
658+ filename = "file-with_special.chars@123.txt"
659+ source_file = os .path .join (source_dir , filename )
660+ target_file = os .path .join (target_dir , filename )
661+
662+ with open (source_file , "w" , encoding = "utf-8" ) as f :
663+ f .write ("content" )
664+ with open (target_file , "w" , encoding = "utf-8" ) as f :
665+ f .write ("target content" )
666+
667+ # Run the function
668+ relink .find_and_replace_owned_files (source_dir , target_dir , username )
669+
670+ # Verify
671+ assert os .path .islink (source_file )
672+ assert os .readlink (source_file ) == target_file
673+
674+ def test_error_deleting_file (self , temp_dirs , caplog ):
675+ """Test error message when file deletion fails."""
676+ source_dir , target_dir = temp_dirs
677+ username = os .environ ["USER" ]
678+
679+ # Create files
680+ source_file = os .path .join (source_dir , "test.txt" )
681+ target_file = os .path .join (target_dir , "test.txt" )
682+
683+ with open (source_file , "w" , encoding = "utf-8" ) as f :
684+ f .write ("source" )
685+ with open (target_file , "w" , encoding = "utf-8" ) as f :
686+ f .write ("target" )
687+
688+ # Mock os.rename to raise an error
689+ def mock_rename (src , dst ):
690+ raise OSError ("Simulated rename error" )
691+
692+ with patch ("os.rename" , side_effect = mock_rename ):
693+ # Run the function
694+ with caplog .at_level (logging .INFO ):
695+ relink .find_and_replace_owned_files (source_dir , target_dir , username )
696+
697+ # Check error message
698+ assert "Error deleting file" in caplog .text
699+ assert source_file in caplog .text
700+
701+ def test_error_creating_symlink (self , temp_dirs , caplog ):
702+ """Test error message when symlink creation fails."""
703+ source_dir , target_dir = temp_dirs
704+ username = os .environ ["USER" ]
705+
706+ # Create source file
707+ source_file = os .path .join (source_dir , "test.txt" )
708+ target_file = os .path .join (target_dir , "test.txt" )
709+
710+ with open (source_file , "w" , encoding = "utf-8" ) as f :
711+ f .write ("source" )
712+ with open (target_file , "w" , encoding = "utf-8" ) as f :
713+ f .write ("target" )
714+
715+ # Mock os.symlink to raise an error
716+ def mock_symlink (src , dst ):
717+ raise OSError ("Simulated symlink error" )
718+
719+ with patch ("os.symlink" , side_effect = mock_symlink ):
720+ # Run the function
721+ with caplog .at_level (logging .INFO ):
722+ relink .find_and_replace_owned_files (source_dir , target_dir , username )
723+
724+ # Check error message
725+ assert "Error creating symlink" in caplog .text
726+ assert source_file in caplog .text
727+
513728class TestTiming :
514729 """Test suite for timing functionality."""
515730
0 commit comments