1 from contextlib
import contextmanager
3 from budget_sync
.test
.mock_path
import MockPath
, MockFilesystem
, DIR
4 from pathlib
import PurePosixPath
8 def make_filesystem_and_report_if_error(test_case
: unittest
.TestCase
):
9 filesystem
= MockFilesystem()
12 except Exception as e
:
13 if isinstance(e
, AssertionError):
15 with test_case
.subTest(filesystem
=filesystem
):
19 class TestMockFilesystem(unittest
.TestCase
):
20 def test_constructor(self
):
21 filesystem
= MockFilesystem()
22 self
.assertEqual(str(filesystem
),
23 "MockFilesystem(files={'/': DIR}, "
24 "current_dir=PurePosixPath('/'))")
25 filesystem
= MockFilesystem(files
={"/": DIR
, "/tmp": DIR
})
26 self
.assertEqual(str(filesystem
),
27 "MockFilesystem(files={'/': DIR, '/tmp': DIR}, "
28 "current_dir=PurePosixPath('/'))")
29 filesystem
= MockFilesystem(files
={"/": DIR
, "/tmp": DIR
},
30 current_dir
=PurePosixPath("/tmp"))
31 self
.assertEqual(str(filesystem
),
32 "MockFilesystem(files={'/': DIR, '/tmp': DIR}, "
33 "current_dir=PurePosixPath('/tmp'))")
35 def test_normalize_path(self
):
36 filesystem
= MockFilesystem(files
={"/": DIR
, "/tmp": DIR
},
37 current_dir
=PurePosixPath("/tmp"))
38 self
.assertEqual(str(filesystem
.normalize_path("..")), "/")
39 self
.assertEqual(str(filesystem
.normalize_path(".")), "/tmp")
40 self
.assertEqual(str(filesystem
.normalize_path("./")), "/tmp")
41 self
.assertEqual(str(filesystem
.normalize_path("/")), "/")
42 self
.assertEqual(str(filesystem
.normalize_path("//")), "//")
43 self
.assertEqual(str(filesystem
.normalize_path("///")), "/")
44 self
.assertEqual(str(filesystem
.normalize_path("/a/b/../c/../../foo")),
46 filesystem
= MockFilesystem(files
={"/": DIR
, "/tmp": DIR
})
47 self
.assertEqual(str(filesystem
.normalize_path("..")), "/")
48 self
.assertEqual(str(filesystem
.normalize_path(".")), "/")
49 self
.assertEqual(str(filesystem
.normalize_path("./")), "/")
50 self
.assertEqual(str(filesystem
.normalize_path("/")), "/")
51 self
.assertEqual(str(filesystem
.normalize_path("//")), "//")
52 self
.assertEqual(str(filesystem
.normalize_path("///")), "/")
53 self
.assertEqual(str(filesystem
.normalize_path("/a/b/../c/../../foo")),
56 def test_check_parent(self
):
57 filesystem
= MockFilesystem(
58 files
={"/": DIR
, "/tmp": DIR
, "/tmp/file": b
""})
59 with self
.assertRaises(FileNotFoundError
) as cm
:
60 filesystem
.check_parent(PurePosixPath("/tmp/a/b"))
61 self
.assertEqual(str(cm
.exception
), "/tmp/a/b")
62 with self
.assertRaises(NotADirectoryError
) as cm
:
63 filesystem
.check_parent(PurePosixPath("/tmp/file/b"))
64 self
.assertEqual(str(cm
.exception
), "/tmp/file/b")
65 filesystem
.check_parent(PurePosixPath("/tmp/file"))
66 filesystem
.check_parent(PurePosixPath("/tmp/a"))
68 def test_create(self
):
69 filesystem
= MockFilesystem(
70 files
={"/": DIR
, "/tmp": DIR
, "/tmp/file": b
""})
71 with self
.assertRaises(FileNotFoundError
) as cm
:
72 filesystem
.create("/tmp/a/b", DIR
)
73 self
.assertEqual(str(cm
.exception
), "/tmp/a/b")
74 with self
.assertRaises(NotADirectoryError
) as cm
:
75 filesystem
.create("/tmp/file/b", DIR
)
76 self
.assertEqual(str(cm
.exception
), "/tmp/file/b")
77 with self
.assertRaises(FileExistsError
) as cm
:
78 filesystem
.create("/tmp/file", DIR
)
79 self
.assertEqual(str(cm
.exception
), "/tmp/file")
80 self
.assertEqual(filesystem
.files
, {
81 "/": DIR
, "/tmp": DIR
, "/tmp/file": b
"",
83 filesystem
.create("/tmp/dir", DIR
)
84 self
.assertEqual(filesystem
.files
, {
85 "/": DIR
, "/tmp": DIR
, "/tmp/file": b
"", "/tmp/dir": DIR
,
87 filesystem
.create("/tmp/file2", b
"abc")
88 self
.assertEqual(filesystem
.files
, {
89 "/": DIR
, "/tmp": DIR
, "/tmp/file": b
"", "/tmp/dir": DIR
,
93 def test_create_or_write_file(self
):
94 filesystem
= MockFilesystem(
95 files
={"/": DIR
, "/tmp": DIR
, "/tmp/file": b
""})
96 with self
.assertRaises(FileNotFoundError
) as cm
:
97 filesystem
.create_or_write_file("/tmp/a/b", b
"")
98 self
.assertEqual(str(cm
.exception
), "/tmp/a/b")
99 with self
.assertRaises(NotADirectoryError
) as cm
:
100 filesystem
.create_or_write_file("/tmp/file/b", b
"")
101 self
.assertEqual(str(cm
.exception
), "/tmp/file/b")
102 with self
.assertRaises(IsADirectoryError
) as cm
:
103 filesystem
.create_or_write_file("/tmp", b
"")
104 self
.assertEqual(str(cm
.exception
), "/tmp")
105 self
.assertEqual(filesystem
.files
, {
106 "/": DIR
, "/tmp": DIR
, "/tmp/file": b
"",
108 filesystem
.create_or_write_file("/tmp/file", b
"def")
109 self
.assertEqual(filesystem
.files
, {
110 "/": DIR
, "/tmp": DIR
, "/tmp/file": b
"def",
112 filesystem
.create_or_write_file("/tmp/file2", b
"abc")
113 self
.assertEqual(filesystem
.files
, {
114 "/": DIR
, "/tmp": DIR
, "/tmp/file": b
"def",
115 "/tmp/file2": b
"abc",
118 def test_write_existing_file(self
):
119 filesystem
= MockFilesystem(
120 files
={"/": DIR
, "/tmp": DIR
, "/tmp/file": b
""})
121 with self
.assertRaises(FileNotFoundError
) as cm
:
122 filesystem
.write_existing_file("/tmp/a/b", b
"")
123 self
.assertEqual(str(cm
.exception
), "/tmp/a/b")
124 with self
.assertRaises(NotADirectoryError
) as cm
:
125 filesystem
.write_existing_file("/tmp/file/b", b
"")
126 self
.assertEqual(str(cm
.exception
), "/tmp/file/b")
127 with self
.assertRaises(IsADirectoryError
) as cm
:
128 filesystem
.write_existing_file("/tmp", b
"")
129 self
.assertEqual(str(cm
.exception
), "/tmp")
130 with self
.assertRaises(FileNotFoundError
) as cm
:
131 filesystem
.write_existing_file("/tmp/file2", b
"")
132 self
.assertEqual(str(cm
.exception
), "/tmp/file2")
133 self
.assertEqual(filesystem
.files
, {
134 "/": DIR
, "/tmp": DIR
, "/tmp/file": b
"",
136 filesystem
.write_existing_file("/tmp/file", b
"def")
137 self
.assertEqual(filesystem
.files
, {
138 "/": DIR
, "/tmp": DIR
, "/tmp/file": b
"def",
141 def test_is_dir(self
):
142 filesystem
= MockFilesystem(
143 files
={"/": DIR
, "/tmp": DIR
, "/tmp/file": b
""})
144 self
.assertTrue(filesystem
.is_dir("/"))
145 self
.assertTrue(filesystem
.is_dir("/tmp"))
146 self
.assertFalse(filesystem
.is_dir("/tmp/file"))
147 self
.assertFalse(filesystem
.is_dir("/nonexistant"))
149 def test_change_dir(self
):
150 filesystem
= MockFilesystem(
151 files
={"/": DIR
, "/tmp": DIR
, "/tmp/file": b
"", "/tmp/dir": DIR
})
152 with self
.assertRaises(FileNotFoundError
) as cm
:
153 filesystem
.change_dir("/tmp/a/b")
154 self
.assertEqual(str(cm
.exception
), "/tmp/a/b")
155 with self
.assertRaises(FileNotFoundError
) as cm
:
156 filesystem
.change_dir("/tmp/a")
157 self
.assertEqual(str(cm
.exception
), "/tmp/a")
158 with self
.assertRaises(NotADirectoryError
) as cm
:
159 filesystem
.change_dir("/tmp/file")
160 self
.assertEqual(str(cm
.exception
), "/tmp/file")
161 self
.assertEqual(filesystem
.current_dir
, PurePosixPath("/"))
162 filesystem
.change_dir("/tmp/dir")
163 self
.assertEqual(filesystem
.current_dir
, PurePosixPath("/tmp/dir"))
164 filesystem
.change_dir("/tmp/")
165 self
.assertEqual(filesystem
.current_dir
, PurePosixPath("/tmp"))
166 filesystem
.change_dir("dir")
167 self
.assertEqual(filesystem
.current_dir
, PurePosixPath("/tmp/dir"))
168 filesystem
.change_dir(".")
169 self
.assertEqual(filesystem
.current_dir
, PurePosixPath("/tmp/dir"))
170 filesystem
.change_dir("..")
171 self
.assertEqual(filesystem
.current_dir
, PurePosixPath("/tmp"))
172 filesystem
.change_dir("dir/..")
173 self
.assertEqual(filesystem
.current_dir
, PurePosixPath("/tmp"))
174 filesystem
.change_dir("dir")
175 self
.assertEqual(filesystem
.current_dir
, PurePosixPath("/tmp/dir"))
176 filesystem
.change_dir("../..")
177 self
.assertEqual(filesystem
.current_dir
, PurePosixPath("/"))
178 filesystem
.change_dir("..")
179 self
.assertEqual(filesystem
.current_dir
, PurePosixPath("/"))
182 class TestMockPath(unittest
.TestCase
):
183 def test_constructor(self
):
184 with
make_filesystem_and_report_if_error(self
) as filesystem
:
185 path
= MockPath("/abc/", filesystem
)
186 self
.assertEqual(path
.path
, PurePosixPath("/abc/"))
187 self
.assertIs(path
.filesystem
, filesystem
)
189 def test_parent(self
):
190 with
make_filesystem_and_report_if_error(self
) as filesystem
:
191 path
= MockPath("/abc/def/", filesystem
).parent
192 self
.assertEqual(path
.path
, PurePosixPath("/abc"))
193 self
.assertIs(path
.filesystem
, filesystem
)
196 with
make_filesystem_and_report_if_error(self
) as filesystem
:
197 path
= MockPath("/abc/def/", filesystem
)
198 path2
= MockPath("/abc/def/xyz/", filesystem
)
199 path3
= MockPath("xyz/", filesystem
)
200 for lhs
in path
, path2
, path3
:
201 for rhs
in path
, path2
, path3
:
202 with self
.subTest(lhs
=repr(lhs
), rhs
=repr(rhs
)):
203 self
.assertEqual(lhs
== rhs
, lhs
.path
== rhs
.path
)
204 self
.assertEqual(lhs
!= rhs
, lhs
.path
!= rhs
.path
)
206 def test_str_repr(self
):
207 with
make_filesystem_and_report_if_error(self
) as filesystem
:
208 path
= MockPath("/abc/def/", filesystem
)
209 path2
= MockPath("/abc/def/xyz/", filesystem
)
210 path3
= MockPath("xyz/", filesystem
)
211 for i
in path
, path2
, path3
:
212 self
.assertEqual(str(i
.path
), str(i
))
213 self
.assertEqual(repr(i
.path
), repr(i
))
215 def test_is_dir(self
):
216 with
make_filesystem_and_report_if_error(self
) as filesystem
:
217 def check(path
, expected_is_dir
):
218 self
.assertEqual(MockPath(path
, filesystem
).is_dir(),
221 filesystem
.create("/tmp", DIR
)
222 filesystem
.create("/tmp/file", b
"")
225 check("/tmp/file", False)
226 check("/nonexistant", False)
228 def test_mkdir(self
):
229 with
make_filesystem_and_report_if_error(self
) as filesystem
:
230 MockPath("/dir/", filesystem
).mkdir()
231 self
.assertEqual(filesystem
.files
,
236 with self
.assertRaises(FileExistsError
) as cm
:
237 MockPath("/dir", filesystem
).mkdir()
238 self
.assertEqual(str(cm
.exception
), "/dir")
239 self
.assertEqual(filesystem
.files
,
244 MockPath("/dir", filesystem
).mkdir(exist_ok
=True)
245 self
.assertEqual(filesystem
.files
,
250 with self
.assertRaises(FileNotFoundError
) as cm
:
251 MockPath("/dir2/dir", filesystem
).mkdir()
252 self
.assertEqual(str(cm
.exception
), "/dir2/dir")
253 self
.assertEqual(filesystem
.files
,
258 filesystem
.create("/tmp", DIR
)
259 filesystem
.create("/tmp/file", b
"")
260 self
.assertEqual(filesystem
.files
,
267 with self
.assertRaises(FileNotFoundError
) as cm
:
268 MockPath("/tmp/file/a/b", filesystem
).mkdir()
269 self
.assertEqual(str(cm
.exception
), "/tmp/file/a/b")
270 self
.assertEqual(filesystem
.files
,
277 with self
.assertRaises(NotADirectoryError
) as cm
:
278 MockPath("/tmp/file/a/b", filesystem
).mkdir(parents
=True)
279 self
.assertEqual(str(cm
.exception
), "/tmp/file/a")
280 self
.assertEqual(filesystem
.files
,
287 MockPath("/tmp/dir/a/b", filesystem
).mkdir(parents
=True)
288 self
.assertEqual(filesystem
.files
,
298 with self
.assertRaises(NotADirectoryError
) as cm
:
299 MockPath("/tmp/file/a/b", filesystem
).mkdir(parents
=True)
300 self
.assertEqual(str(cm
.exception
), "/tmp/file/a")
301 self
.assertEqual(filesystem
.files
,
311 MockPath("/tmp/dir/c/d", filesystem
) \
312 .mkdir(parents
=True, exist_ok
=True)
313 self
.assertEqual(filesystem
.files
,
325 MockPath("/tmp/dir/c/d", filesystem
) \
326 .mkdir(parents
=True, exist_ok
=True)
327 self
.assertEqual(filesystem
.files
,
340 def test_joinpath(self
):
341 with
make_filesystem_and_report_if_error(self
) as filesystem
:
342 path1
= MockPath("/abc/", filesystem
)
343 path2
= MockPath("def", filesystem
)
344 path3
= MockPath("/abc/def", filesystem
)
345 path4
= MockPath("/abc/def/..", filesystem
)
346 self
.assertEqual(path1
.joinpath(path2
), path3
)
347 self
.assertEqual(path1
.joinpath(path2
, ".."), path4
)
349 def test_write_bytes(self
):
350 with
make_filesystem_and_report_if_error(self
) as filesystem
:
351 MockPath("/file", filesystem
).write_bytes(b
"abc")
352 self
.assertEqual(filesystem
.files
, {"/": DIR
, "/file": b
"abc"})
353 MockPath("/file", filesystem
).write_bytes(b
"defg")
354 self
.assertEqual(filesystem
.files
, {"/": DIR
, "/file": b
"defg"})
356 def test_write_text(self
):
357 with
make_filesystem_and_report_if_error(self
) as filesystem
:
358 MockPath("/file", filesystem
).write_text("abc")
359 self
.assertEqual(filesystem
.files
, {"/": DIR
, "/file": b
"abc"})
360 MockPath("/file", filesystem
).write_text("defg")
361 self
.assertEqual(filesystem
.files
, {"/": DIR
, "/file": b
"defg"})
362 with self
.assertRaises(TypeError):
363 MockPath("/file", filesystem
).write_text(1)
366 if __name__
== "__main__":