Skip to content

Commit ec75e73

Browse files
committed
test: add tests for file selection funcs and DioptraFile validation
1 parent dd41625 commit ec75e73

File tree

1 file changed

+185
-0
lines changed

1 file changed

+185
-0
lines changed

tests/unit/client/test_utils.py

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
# This Software (Dioptra) is being made available as a public service by the
2+
# National Institute of Standards and Technology (NIST), an Agency of the United
3+
# States Department of Commerce. This software was developed in part by employees of
4+
# NIST and in part by NIST contractors. Copyright in portions of this software that
5+
# were developed by NIST contractors has been licensed or assigned to NIST. Pursuant
6+
# to Title 17 United States Code Section 105, works of NIST employees are not
7+
# subject to copyright protection in the United States. However, NIST may hold
8+
# international copyright in software created by its employees and domestic
9+
# copyright (or licensing rights) in portions of software that were assigned or
10+
# licensed to NIST. To the extent that NIST holds copyright in this software, it is
11+
# being made available under the Creative Commons Attribution 4.0 International
12+
# license (CC BY 4.0). The disclaimers of the CC BY 4.0 license apply to all parts
13+
# of the software developed or licensed by NIST.
14+
#
15+
# ACCESS THE FULL CC BY 4.0 LICENSE HERE:
16+
# https://creativecommons.org/licenses/by/4.0/legalcode
17+
import io
18+
import re
19+
from pathlib import Path
20+
21+
import pytest
22+
23+
from dioptra.client import (
24+
DioptraFile,
25+
select_files_in_directory,
26+
select_one_or_more_files,
27+
)
28+
29+
30+
@pytest.fixture
31+
def fake_directory(tmp_path: Path) -> Path:
32+
(tmp_path / "subdir").mkdir()
33+
(tmp_path / "subdir" / "subdir2").mkdir()
34+
(tmp_path / "subdir" / "file1.txt").write_text("Content of file1")
35+
(tmp_path / "subdir" / "file2.txt").write_text("Content of file2")
36+
(tmp_path / "subdir" / "subdir2" / "file1.txt").write_text("Content of file1")
37+
(tmp_path / "subdir" / "subdir2" / "file3.md").write_text("# Content of file3")
38+
(tmp_path / "file4.txt").write_text("Content of file4")
39+
return tmp_path
40+
41+
42+
@pytest.mark.parametrize(
43+
"recursive, include_pattern, expected_filenames",
44+
[
45+
(False, None, {"file4.txt"}),
46+
(
47+
True,
48+
None,
49+
{
50+
"file4.txt",
51+
"subdir/file1.txt",
52+
"subdir/file2.txt",
53+
"subdir/subdir2/file1.txt",
54+
"subdir/subdir2/file3.md",
55+
},
56+
),
57+
(True, r".*\.md", {"subdir/subdir2/file3.md"}),
58+
(True, re.compile(r".*\.md"), {"subdir/subdir2/file3.md"}),
59+
(
60+
True,
61+
r".*\.txt",
62+
{
63+
"file4.txt",
64+
"subdir/file1.txt",
65+
"subdir/file2.txt",
66+
"subdir/subdir2/file1.txt",
67+
},
68+
),
69+
],
70+
)
71+
def test_select_files_in_directory(
72+
fake_directory: Path,
73+
recursive: bool,
74+
include_pattern: str | re.Pattern | None,
75+
expected_filenames: set[str],
76+
) -> None:
77+
# Select the files from the temporary directory
78+
selected_files = select_files_in_directory(
79+
fake_directory, recursive=recursive, include_pattern=include_pattern
80+
)
81+
82+
# Extract filenames to validate their paths
83+
filenames = [dioptra_file.filename for dioptra_file in selected_files]
84+
85+
# Validate that all filenames match the expected relative POSIX paths
86+
assert set(filenames) == expected_filenames
87+
88+
# Verify DioptraFile structure
89+
for dioptra_file in selected_files:
90+
assert isinstance(dioptra_file, DioptraFile)
91+
assert dioptra_file.stream.readable()
92+
93+
94+
@pytest.mark.parametrize(
95+
"relative_file_paths, renames, expected_filenames",
96+
[
97+
(["file4.txt"], None, {"file4.txt"}),
98+
(
99+
[
100+
"file4.txt",
101+
"subdir/file1.txt",
102+
"subdir/file2.txt",
103+
"subdir/subdir2/file3.md",
104+
],
105+
None,
106+
{"file4.txt", "file1.txt", "file2.txt", "file3.md"},
107+
),
108+
(["subdir/subdir2/file3.md"], None, {"file3.md"}),
109+
(["subdir/subdir2/file3.md", "file4.txt"], None, {"file3.md", "file4.txt"}),
110+
(
111+
["file4.txt", "subdir/file1.txt", "subdir/subdir2/file1.txt"],
112+
{"subdir/subdir2/file1.txt": "file1_copy.txt"},
113+
{"file1.txt", "file4.txt", "file1_copy.txt"},
114+
),
115+
],
116+
)
117+
def test_select_one_or_more_files(
118+
fake_directory: Path,
119+
relative_file_paths: list[str],
120+
renames: dict[str | Path, str] | None,
121+
expected_filenames: set[str],
122+
) -> None:
123+
file_paths: list[str | Path] = [
124+
fake_directory / file_path for file_path in relative_file_paths
125+
]
126+
if renames is not None:
127+
renames = {
128+
str(fake_directory / relative_path): new_filename
129+
for relative_path, new_filename in renames.items()
130+
}
131+
132+
# Select the files from the temporary directory
133+
selected_files = select_one_or_more_files(file_paths, renames=renames)
134+
135+
# Extract filenames for validation
136+
filenames = [dioptra_file.filename for dioptra_file in selected_files]
137+
138+
# Validate that list of selected filenames match the expected ones after renaming
139+
assert set(filenames) == set(expected_filenames)
140+
141+
# Verify DioptraFile structure
142+
for dioptra_file in selected_files:
143+
assert isinstance(dioptra_file, DioptraFile)
144+
assert dioptra_file.stream.readable()
145+
146+
147+
def test_select_one_or_more_with_duplicate_filename_fails(
148+
fake_directory: Path,
149+
) -> None:
150+
relative_file_paths = ["file4.txt", "subdir/file1.txt", "subdir/subdir2/file1.txt"]
151+
file_paths: list[str | Path] = [
152+
fake_directory / file_path for file_path in relative_file_paths
153+
]
154+
155+
with pytest.raises(ValueError):
156+
select_one_or_more_files(file_paths)
157+
158+
159+
@pytest.mark.parametrize(
160+
"filename",
161+
[
162+
"/home/username/script.py",
163+
"../script.py",
164+
".../script.py",
165+
"..../script.py",
166+
"../a/./script.py",
167+
"../a/.../script.py",
168+
"./a/script.py",
169+
"a//script.py",
170+
"a/.../script.py",
171+
"a/b/",
172+
"a/b/../script.py",
173+
"a\\script.py",
174+
"a\\..\\script.py",
175+
"a\\b/script.py",
176+
"C:\\Users\\username\\script.py",
177+
],
178+
)
179+
def test_invalid_dioptra_filenames_fail(filename: str) -> None:
180+
with pytest.raises(ValueError):
181+
DioptraFile(
182+
filename=filename,
183+
stream=None, # type: ignore[arg-type]
184+
content_type=None,
185+
)

0 commit comments

Comments
 (0)