210 lines
7.1 KiB
Python
210 lines
7.1 KiB
Python
"""
|
|
Test suite for file utility functions.
|
|
"""
|
|
|
|
import os
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
from markitect_utils.file_utils import (
|
|
safe_filename,
|
|
ensure_extension,
|
|
get_file_size,
|
|
is_text_file,
|
|
normalize_path,
|
|
)
|
|
|
|
|
|
class TestSafeFilename:
|
|
"""Test cases for the safe_filename function."""
|
|
|
|
def test_basic_sanitization(self):
|
|
"""Test basic filename sanitization."""
|
|
assert safe_filename("normal_file.txt") == "normal_file.txt"
|
|
assert safe_filename("file with spaces.txt") == "file with spaces.txt"
|
|
|
|
def test_unsafe_characters(self):
|
|
"""Test removal of unsafe characters."""
|
|
assert safe_filename("file<>name.txt") == "file__name.txt"
|
|
assert safe_filename('file"name.txt') == "file_name.txt"
|
|
assert safe_filename("file/path\\name.txt") == "file_path_name.txt"
|
|
assert safe_filename("file|name.txt") == "file_name.txt"
|
|
|
|
def test_custom_replacement(self):
|
|
"""Test custom replacement character."""
|
|
assert safe_filename("file<>name.txt", "-") == "file--name.txt"
|
|
assert safe_filename("file/path\\name.txt", "") == "filepathname.txt"
|
|
|
|
def test_reserved_names(self):
|
|
"""Test handling of Windows reserved names."""
|
|
assert safe_filename("CON") == "file_CON"
|
|
assert safe_filename("PRN.txt") == "file_PRN.txt"
|
|
assert safe_filename("COM1") == "file_COM1"
|
|
assert safe_filename("con") == "file_con" # case insensitive
|
|
|
|
def test_edge_cases(self):
|
|
"""Test edge cases."""
|
|
assert safe_filename("") == "" # Empty input returns empty
|
|
assert safe_filename(" ") == "file_" # Whitespace only gets prefix
|
|
assert safe_filename("...") == "file_" # Dots only gets prefix
|
|
assert safe_filename(".hidden") == "hidden" # Leading dot gets stripped
|
|
|
|
|
|
class TestEnsureExtension:
|
|
"""Test cases for the ensure_extension function."""
|
|
|
|
def test_add_extension(self):
|
|
"""Test adding extension to filename."""
|
|
assert ensure_extension("document", ".md") == "document.md"
|
|
assert ensure_extension("file", "txt") == "file.txt"
|
|
|
|
def test_existing_extension(self):
|
|
"""Test when extension already exists."""
|
|
assert ensure_extension("document.md", ".md") == "document.md"
|
|
assert ensure_extension("file.txt", "txt") == "file.txt"
|
|
|
|
def test_different_extension(self):
|
|
"""Test adding extension when different one exists."""
|
|
assert ensure_extension("document.txt", ".md") == "document.txt.md"
|
|
assert ensure_extension("file.doc", "pdf") == "file.doc.pdf"
|
|
|
|
def test_edge_cases(self):
|
|
"""Test edge cases."""
|
|
assert ensure_extension("", ".md") == ""
|
|
assert ensure_extension("file", "") == "file"
|
|
assert ensure_extension("file.md", "") == "file.md"
|
|
|
|
|
|
class TestGetFileSize:
|
|
"""Test cases for the get_file_size function."""
|
|
|
|
def test_existing_file(self):
|
|
"""Test getting size of existing file."""
|
|
with tempfile.NamedTemporaryFile(mode='w', delete=False) as f:
|
|
f.write("Hello, World!")
|
|
temp_path = f.name
|
|
|
|
try:
|
|
size = get_file_size(temp_path)
|
|
assert size is not None
|
|
assert size > 0
|
|
finally:
|
|
os.unlink(temp_path)
|
|
|
|
def test_nonexistent_file(self):
|
|
"""Test getting size of non-existent file."""
|
|
assert get_file_size("/path/that/does/not/exist") is None
|
|
|
|
def test_empty_file(self):
|
|
"""Test getting size of empty file."""
|
|
with tempfile.NamedTemporaryFile(delete=False) as f:
|
|
temp_path = f.name
|
|
|
|
try:
|
|
size = get_file_size(temp_path)
|
|
assert size == 0
|
|
finally:
|
|
os.unlink(temp_path)
|
|
|
|
def test_path_object(self):
|
|
"""Test with Path object."""
|
|
with tempfile.NamedTemporaryFile(mode='w', delete=False) as f:
|
|
f.write("test content")
|
|
temp_path = Path(f.name)
|
|
|
|
try:
|
|
size = get_file_size(temp_path)
|
|
assert size is not None
|
|
assert size > 0
|
|
finally:
|
|
os.unlink(temp_path)
|
|
|
|
|
|
class TestIsTextFile:
|
|
"""Test cases for the is_text_file function."""
|
|
|
|
def test_text_file(self):
|
|
"""Test with actual text file."""
|
|
with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.txt') as f:
|
|
f.write("This is a text file with some content.")
|
|
temp_path = f.name
|
|
|
|
try:
|
|
assert is_text_file(temp_path) is True
|
|
finally:
|
|
os.unlink(temp_path)
|
|
|
|
def test_binary_file(self):
|
|
"""Test with binary file."""
|
|
with tempfile.NamedTemporaryFile(mode='wb', delete=False, suffix='.bin') as f:
|
|
f.write(b'\x00\x01\x02\x03\x04\x05')
|
|
temp_path = f.name
|
|
|
|
try:
|
|
assert is_text_file(temp_path) is False
|
|
finally:
|
|
os.unlink(temp_path)
|
|
|
|
def test_empty_file(self):
|
|
"""Test with empty file."""
|
|
with tempfile.NamedTemporaryFile(delete=False) as f:
|
|
temp_path = f.name
|
|
|
|
try:
|
|
assert is_text_file(temp_path) is True # Empty files are considered text
|
|
finally:
|
|
os.unlink(temp_path)
|
|
|
|
def test_unicode_file(self):
|
|
"""Test with Unicode text file."""
|
|
with tempfile.NamedTemporaryFile(mode='w', delete=False, encoding='utf-8') as f:
|
|
f.write("Hello 世界! This is UTF-8 text.")
|
|
temp_path = f.name
|
|
|
|
try:
|
|
assert is_text_file(temp_path) is True
|
|
finally:
|
|
os.unlink(temp_path)
|
|
|
|
def test_nonexistent_file(self):
|
|
"""Test with non-existent file."""
|
|
assert is_text_file("/path/that/does/not/exist") is False
|
|
|
|
|
|
class TestNormalizePath:
|
|
"""Test cases for the normalize_path function."""
|
|
|
|
def test_relative_path(self):
|
|
"""Test normalizing relative paths."""
|
|
# Note: These tests are environment-dependent
|
|
result = normalize_path("./test")
|
|
assert os.path.isabs(result)
|
|
assert result.endswith("test")
|
|
|
|
def test_path_with_dots(self):
|
|
"""Test path with dot components."""
|
|
result = normalize_path("./dir/../file.txt")
|
|
assert os.path.isabs(result)
|
|
assert result.endswith("file.txt")
|
|
|
|
def test_already_absolute(self):
|
|
"""Test already absolute path."""
|
|
abs_path = "/tmp/test/file.txt"
|
|
result = normalize_path(abs_path)
|
|
assert result == abs_path
|
|
|
|
def test_path_object(self):
|
|
"""Test with Path object."""
|
|
path_obj = Path("./test/file.txt")
|
|
result = normalize_path(path_obj)
|
|
assert os.path.isabs(result)
|
|
assert isinstance(result, str)
|
|
|
|
def test_edge_cases(self):
|
|
"""Test edge cases."""
|
|
assert normalize_path("") == ""
|
|
|
|
# Current directory should normalize to absolute path
|
|
result = normalize_path(".")
|
|
assert os.path.isabs(result) |