@@ -313,6 +313,36 @@ def test_print_deleted_and_created_messages(self, temp_dirs, current_user, caplo
313313 assert "Created symbolic link:" in caplog .text
314314 assert f"{ source_file } -> { target_file } " in caplog .text
315315
316+ def test_handles_file_deleted_during_traversal (
317+ self , temp_dirs , current_user , caplog
318+ ):
319+ """Test that FileNotFoundError during stat is handled gracefully."""
320+ source_dir , target_dir = temp_dirs
321+ username = current_user
322+
323+ # Create files
324+ source_file = os .path .join (source_dir , "disappearing.txt" )
325+ with open (source_file , "w" , encoding = "utf-8" ) as f :
326+ f .write ("content" )
327+
328+ # Mock os.stat to raise FileNotFoundError for this specific file
329+ original_stat = os .stat
330+
331+ def mock_stat (path , * args , ** kwargs ):
332+ if path == source_file :
333+ raise FileNotFoundError (f"Simulated: { path } deleted during traversal" )
334+ return original_stat (path , * args , ** kwargs )
335+
336+ with patch ("os.stat" , side_effect = mock_stat ):
337+ with caplog .at_level (logging .INFO ):
338+ # Should not crash, should continue processing
339+ relink .find_and_replace_owned_files (source_dir , target_dir , username )
340+
341+ # Should complete without errors (file was skipped)
342+ # No error message should be logged (it's silently skipped via continue)
343+ assert "Error" not in caplog .text
344+ assert "disappearing.txt" not in caplog .text
345+
316346
317347class TestParseArguments :
318348 """Test suite for parse_arguments function."""
0 commit comments