Skip to content

Commit d2fdce8

Browse files
committed
test: add comprehensive tests for path validation and backup folder creation
1 parent c5b5f50 commit d2fdce8

1 file changed

Lines changed: 100 additions & 6 deletions

File tree

tests/test_utils.py

Lines changed: 100 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,15 @@
88
from unittest.mock import patch
99

1010
# Add the parent directory to sys.path so Python can find src
11-
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
11+
sys.path.insert(
12+
0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
13+
)
1214

13-
from autotarcompress.utils import SizeCalculator
15+
from autotarcompress.utils import (
16+
SizeCalculator,
17+
ensure_backup_folder,
18+
validate_and_expand_paths,
19+
)
1420

1521

1622
class TestSizeCalculator:
@@ -30,7 +36,9 @@ def test_size_calculator_initialization(self) -> None:
3036
assert str(calculator.directories[1]) == "/test/dir2"
3137
assert len(calculator.ignore_list) == EXPECTED_IGNORE_COUNT
3238

33-
def test_calculate_total_size_with_test_data(self, test_data_dir: str) -> None:
39+
def test_calculate_total_size_with_test_data(
40+
self, test_data_dir: str
41+
) -> None:
3442
"""Test size calculation with actual test data."""
3543
dirs = [test_data_dir]
3644
ignore_list: list[str] = []
@@ -41,10 +49,14 @@ def test_calculate_total_size_with_test_data(self, test_data_dir: str) -> None:
4149
# Should have some size from test files
4250
assert total_size > 0
4351

44-
def test_calculate_total_size_with_ignore_list(self, test_data_dir: str) -> None:
52+
def test_calculate_total_size_with_ignore_list(
53+
self, test_data_dir: str
54+
) -> None:
4555
"""Test size calculation respects ignore list."""
4656
dirs = [test_data_dir]
47-
ignore_list: list[str] = ["ignored"] # Should ignore the "ignored" directory
57+
ignore_list: list[str] = [
58+
"ignored"
59+
] # Should ignore the "ignored" directory
4860

4961
calculator = SizeCalculator(dirs, ignore_list)
5062
size_with_ignore = calculator.calculate_total_size()
@@ -58,7 +70,9 @@ def test_calculate_total_size_with_ignore_list(self, test_data_dir: str) -> None
5870
assert size_with_ignore <= size_without_ignore
5971

6072
@patch("autotarcompress.utils.os.walk")
61-
def test_calculate_total_size_handles_permission_errors(self, mock_walk) -> None:
73+
def test_calculate_total_size_handles_permission_errors(
74+
self, mock_walk
75+
) -> None:
6276
"""Test that size calculator handles permission errors gracefully."""
6377
# Mock os.walk to raise PermissionError
6478
mock_walk.side_effect = PermissionError("Permission denied")
@@ -135,3 +149,83 @@ def test_symlink_handling(self, tmp_path) -> None:
135149
# (from regular file and valid symlink)
136150
total_size = calculator.calculate_total_size()
137151
assert total_size > 0
152+
153+
154+
def test_validate_and_expand_paths(tmp_path) -> None:
155+
"""Test validate_and_expand_paths returns existing and missing lists."""
156+
existing_dir = tmp_path / "exists"
157+
existing_dir.mkdir()
158+
159+
missing_dir = tmp_path / "does_not_exist"
160+
161+
# include an empty string which should be skipped
162+
inputs = [str(existing_dir), str(missing_dir), ""]
163+
164+
existing, missing = validate_and_expand_paths(inputs)
165+
166+
# Ensure the existing directory is returned and the missing one is reported
167+
assert str(existing_dir) in existing
168+
assert str(missing_dir) in missing
169+
170+
171+
def test_ensure_backup_folder_creates_and_returns_path(tmp_path) -> None:
172+
"""Test ensure_backup_folder creates nested folders and returns a Path."""
173+
nested = tmp_path / "a" / "b" / "c"
174+
# Pass as a string (function will expanduser internally)
175+
result = ensure_backup_folder(str(nested))
176+
177+
assert result.exists()
178+
assert result.is_dir()
179+
# The returned path should match the expanded input path
180+
from pathlib import Path
181+
182+
assert result == Path(str(nested)).expanduser()
183+
184+
185+
def test_validate_and_expand_paths_handles_none() -> None:
186+
"""validate_and_expand_paths should handle a None input gracefully."""
187+
existing, missing = validate_and_expand_paths(None)
188+
assert existing == []
189+
assert missing == []
190+
191+
192+
def test_validate_and_expand_paths_with_file_and_trailing_slash(
193+
tmp_path,
194+
) -> None:
195+
"""A trailing slash on an existing file should still be reported as existing."""
196+
file = tmp_path / "afile.txt"
197+
file.write_text("content")
198+
199+
inputs = [str(file) + "/"]
200+
existing, missing = validate_and_expand_paths(inputs)
201+
202+
assert str(file) in existing
203+
assert missing == []
204+
205+
206+
def test_ensure_backup_folder_idempotent(tmp_path) -> None:
207+
"""ensure_backup_folder should be safe to call multiple times."""
208+
nested = tmp_path / "already" / "exists"
209+
nested.mkdir(parents=True)
210+
211+
first = ensure_backup_folder(str(nested))
212+
second = ensure_backup_folder(str(nested))
213+
214+
assert first == second
215+
216+
217+
def test_ensure_backup_folder_permission_error(monkeypatch, tmp_path) -> None:
218+
"""If the folder cannot be created due to permissions, an OSError is raised."""
219+
from pathlib import Path
220+
221+
import pytest
222+
223+
nested = tmp_path / "no_perms"
224+
225+
def fake_mkdir(self, parents=True, exist_ok=True):
226+
raise PermissionError("Permission denied")
227+
228+
monkeypatch.setattr(Path, "mkdir", fake_mkdir)
229+
230+
with pytest.raises(OSError):
231+
ensure_backup_folder(str(nested))

0 commit comments

Comments
 (0)