"""Tests for filename sanitization.""" import pytest from local_deep_research.security.filename_sanitizer import ( UnsafeFilenameError, sanitize_filename, ) class TestSanitizeFilename: """Tests for sanitize_filename().""" def test_normal_filename(self): assert sanitize_filename("report.pdf") == "report.pdf" def test_path_traversal(self): result = sanitize_filename("../../etc/passwd.pdf") assert ".." not in result assert result == "etc_passwd.pdf" def test_null_bytes_stripped(self): result = sanitize_filename("file\x00name.pdf") assert "\x00" not in result assert result == "filename.pdf" def test_empty_filename_raises(self): with pytest.raises(UnsafeFilenameError, match="No filename"): sanitize_filename("") def test_none_filename_raises(self): with pytest.raises(UnsafeFilenameError, match="No filename"): sanitize_filename(None) def test_sanitizes_to_empty_raises(self): with pytest.raises(UnsafeFilenameError, match="no safe characters"): sanitize_filename("../../../") def test_allowed_extensions_pass(self): result = sanitize_filename("doc.pdf", allowed_extensions={".pdf"}) assert result == "doc.pdf" def test_disallowed_extension_raises(self): with pytest.raises(UnsafeFilenameError, match="not allowed"): sanitize_filename("script.exe", allowed_extensions={".pdf", ".txt"}) def test_extension_check_case_insensitive(self): result = sanitize_filename("doc.PDF", allowed_extensions={".pdf"}) assert result == "doc.PDF" def test_max_length_truncates(self): long_name = "a" * 300 + ".pdf" result = sanitize_filename(long_name, max_length=50) assert len(result) <= 50 assert result.endswith(".pdf") def test_max_length_no_extension(self): long_name = "a" * 300 result = sanitize_filename(long_name, max_length=50) assert len(result) <= 50 def test_spaces_in_filename(self): result = sanitize_filename("my report file.pdf") assert result == "my_report_file.pdf" def test_special_characters(self): result = sanitize_filename("file@#$%.pdf") assert result # should not be empty assert ".." not in result