From fa636cc1f0d3d8330971183715003f6aafd7141a Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Thu, 17 Sep 2020 17:11:01 -0700 Subject: [PATCH] write rest of MockPath tests --- src/budget_sync/test/mock_path.py | 17 +- src/budget_sync/test/test_mock_path.py | 338 ++++++++++++++++++++++++- 2 files changed, 349 insertions(+), 6 deletions(-) diff --git a/src/budget_sync/test/mock_path.py b/src/budget_sync/test/mock_path.py index 5e72e38..33a7131 100644 --- a/src/budget_sync/test/mock_path.py +++ b/src/budget_sync/test/mock_path.py @@ -10,6 +10,12 @@ from functools import cached_property class MockDir(Enum): DIR = "" + def __repr__(self): + return "DIR" + + def __str__(self): + return "DIR" + DIR = MockDir.DIR @@ -20,7 +26,7 @@ class MockFilesystem: def __init__(self, files: Optional[Dict[str, Union[bytes, MockDir]]] = None, - current_dir: Optional[PathLike] = None): + current_dir: Optional[PurePosixPath] = None): if files is None: files = {"/": DIR} self.files = files @@ -81,7 +87,7 @@ class MockFilesystem: f"current_dir={self.current_dir!r})" -class MockPath: +class MockPath(PathLike): filesystem: MockFilesystem path: PurePosixPath @@ -97,7 +103,7 @@ class MockPath: return self.path == other.path def is_dir(self) -> bool: - self.filesystem.is_dir(self.path) + return self.filesystem.is_dir(self.path) def mkdir(self, parents: bool = False, exist_ok: bool = False): # derived from Python's Path.mkdir @@ -121,7 +127,7 @@ class MockPath: def write_text(self, data, encoding=None, errors=None): if not isinstance(data, str): - raise TypeError() + raise TypeError("data to write must be a str") if encoding is None: encoding = "utf-8" if errors is None: @@ -133,3 +139,6 @@ class MockPath: def __repr__(self) -> str: return repr(self.path) + + def __fspath__(self) -> Union[str, bytes]: + return str(self.path) diff --git a/src/budget_sync/test/test_mock_path.py b/src/budget_sync/test/test_mock_path.py index 6ddcd4c..cc8420e 100644 --- a/src/budget_sync/test/test_mock_path.py +++ b/src/budget_sync/test/test_mock_path.py @@ -1,6 +1,7 @@ from contextlib import contextmanager import unittest from budget_sync.test.mock_path import MockPath, MockFilesystem, DIR +from pathlib import PurePosixPath @contextmanager @@ -15,8 +16,214 @@ def make_filesystem_and_report_if_error(test_case: unittest.TestCase): raise +class TestMockFilesystem(unittest.TestCase): + def test_constructor(self): + filesystem = MockFilesystem() + self.assertEqual(str(filesystem), + "MockFilesystem(files={'/': DIR}, " + "current_dir=PurePosixPath('/'))") + filesystem = MockFilesystem(files={"/": DIR, "/tmp": DIR}) + self.assertEqual(str(filesystem), + "MockFilesystem(files={'/': DIR, '/tmp': DIR}, " + "current_dir=PurePosixPath('/'))") + filesystem = MockFilesystem(files={"/": DIR, "/tmp": DIR}, + current_dir=PurePosixPath("/tmp")) + self.assertEqual(str(filesystem), + "MockFilesystem(files={'/': DIR, '/tmp': DIR}, " + "current_dir=PurePosixPath('/tmp'))") + + def test_normalize_path(self): + filesystem = MockFilesystem(files={"/": DIR, "/tmp": DIR}, + current_dir=PurePosixPath("/tmp")) + self.assertEqual(str(filesystem.normalize_path("..")), "/") + self.assertEqual(str(filesystem.normalize_path(".")), "/tmp") + self.assertEqual(str(filesystem.normalize_path("./")), "/tmp") + self.assertEqual(str(filesystem.normalize_path("/")), "/") + self.assertEqual(str(filesystem.normalize_path("//")), "//") + self.assertEqual(str(filesystem.normalize_path("///")), "/") + self.assertEqual(str(filesystem.normalize_path("/a/b/../c/../../foo")), + "/foo") + filesystem = MockFilesystem(files={"/": DIR, "/tmp": DIR}) + self.assertEqual(str(filesystem.normalize_path("..")), "/") + self.assertEqual(str(filesystem.normalize_path(".")), "/") + self.assertEqual(str(filesystem.normalize_path("./")), "/") + self.assertEqual(str(filesystem.normalize_path("/")), "/") + self.assertEqual(str(filesystem.normalize_path("//")), "//") + self.assertEqual(str(filesystem.normalize_path("///")), "/") + self.assertEqual(str(filesystem.normalize_path("/a/b/../c/../../foo")), + "/foo") + + def test_check_parent(self): + filesystem = MockFilesystem( + files={"/": DIR, "/tmp": DIR, "/tmp/file": b""}) + with self.assertRaises(FileNotFoundError) as cm: + filesystem.check_parent(PurePosixPath("/tmp/a/b")) + self.assertEqual(str(cm.exception), "/tmp/a/b") + with self.assertRaises(NotADirectoryError) as cm: + filesystem.check_parent(PurePosixPath("/tmp/file/b")) + self.assertEqual(str(cm.exception), "/tmp/file/b") + filesystem.check_parent(PurePosixPath("/tmp/file")) + filesystem.check_parent(PurePosixPath("/tmp/a")) + + def test_create(self): + filesystem = MockFilesystem( + files={"/": DIR, "/tmp": DIR, "/tmp/file": b""}) + with self.assertRaises(FileNotFoundError) as cm: + filesystem.create("/tmp/a/b", DIR) + self.assertEqual(str(cm.exception), "/tmp/a/b") + with self.assertRaises(NotADirectoryError) as cm: + filesystem.create("/tmp/file/b", DIR) + self.assertEqual(str(cm.exception), "/tmp/file/b") + with self.assertRaises(FileExistsError) as cm: + filesystem.create("/tmp/file", DIR) + self.assertEqual(str(cm.exception), "/tmp/file") + self.assertEqual(filesystem.files, { + "/": DIR, "/tmp": DIR, "/tmp/file": b"", + }) + filesystem.create("/tmp/dir", DIR) + self.assertEqual(filesystem.files, { + "/": DIR, "/tmp": DIR, "/tmp/file": b"", "/tmp/dir": DIR, + }) + filesystem.create("/tmp/file2", b"abc") + self.assertEqual(filesystem.files, { + "/": DIR, "/tmp": DIR, "/tmp/file": b"", "/tmp/dir": DIR, + "/tmp/file2": b"abc", + }) + + def test_create_or_write_file(self): + filesystem = MockFilesystem( + files={"/": DIR, "/tmp": DIR, "/tmp/file": b""}) + with self.assertRaises(FileNotFoundError) as cm: + filesystem.create_or_write_file("/tmp/a/b", b"") + self.assertEqual(str(cm.exception), "/tmp/a/b") + with self.assertRaises(NotADirectoryError) as cm: + filesystem.create_or_write_file("/tmp/file/b", b"") + self.assertEqual(str(cm.exception), "/tmp/file/b") + with self.assertRaises(IsADirectoryError) as cm: + filesystem.create_or_write_file("/tmp", b"") + self.assertEqual(str(cm.exception), "/tmp") + self.assertEqual(filesystem.files, { + "/": DIR, "/tmp": DIR, "/tmp/file": b"", + }) + filesystem.create_or_write_file("/tmp/file", b"def") + self.assertEqual(filesystem.files, { + "/": DIR, "/tmp": DIR, "/tmp/file": b"def", + }) + filesystem.create_or_write_file("/tmp/file2", b"abc") + self.assertEqual(filesystem.files, { + "/": DIR, "/tmp": DIR, "/tmp/file": b"def", + "/tmp/file2": b"abc", + }) + + def test_write_existing_file(self): + filesystem = MockFilesystem( + files={"/": DIR, "/tmp": DIR, "/tmp/file": b""}) + with self.assertRaises(FileNotFoundError) as cm: + filesystem.write_existing_file("/tmp/a/b", b"") + self.assertEqual(str(cm.exception), "/tmp/a/b") + with self.assertRaises(NotADirectoryError) as cm: + filesystem.write_existing_file("/tmp/file/b", b"") + self.assertEqual(str(cm.exception), "/tmp/file/b") + with self.assertRaises(IsADirectoryError) as cm: + filesystem.write_existing_file("/tmp", b"") + self.assertEqual(str(cm.exception), "/tmp") + with self.assertRaises(FileNotFoundError) as cm: + filesystem.write_existing_file("/tmp/file2", b"") + self.assertEqual(str(cm.exception), "/tmp/file2") + self.assertEqual(filesystem.files, { + "/": DIR, "/tmp": DIR, "/tmp/file": b"", + }) + filesystem.write_existing_file("/tmp/file", b"def") + self.assertEqual(filesystem.files, { + "/": DIR, "/tmp": DIR, "/tmp/file": b"def", + }) + + def test_is_dir(self): + filesystem = MockFilesystem( + files={"/": DIR, "/tmp": DIR, "/tmp/file": b""}) + self.assertTrue(filesystem.is_dir("/")) + self.assertTrue(filesystem.is_dir("/tmp")) + self.assertFalse(filesystem.is_dir("/tmp/file")) + self.assertFalse(filesystem.is_dir("/nonexistant")) + + def test_change_dir(self): + filesystem = MockFilesystem( + files={"/": DIR, "/tmp": DIR, "/tmp/file": b"", "/tmp/dir": DIR}) + with self.assertRaises(FileNotFoundError) as cm: + filesystem.change_dir("/tmp/a/b") + self.assertEqual(str(cm.exception), "/tmp/a/b") + with self.assertRaises(FileNotFoundError) as cm: + filesystem.change_dir("/tmp/a") + self.assertEqual(str(cm.exception), "/tmp/a") + with self.assertRaises(NotADirectoryError) as cm: + filesystem.change_dir("/tmp/file") + self.assertEqual(str(cm.exception), "/tmp/file") + self.assertEqual(filesystem.current_dir, PurePosixPath("/")) + filesystem.change_dir("/tmp/dir") + self.assertEqual(filesystem.current_dir, PurePosixPath("/tmp/dir")) + filesystem.change_dir("/tmp/") + self.assertEqual(filesystem.current_dir, PurePosixPath("/tmp")) + filesystem.change_dir("dir") + self.assertEqual(filesystem.current_dir, PurePosixPath("/tmp/dir")) + filesystem.change_dir(".") + self.assertEqual(filesystem.current_dir, PurePosixPath("/tmp/dir")) + filesystem.change_dir("..") + self.assertEqual(filesystem.current_dir, PurePosixPath("/tmp")) + filesystem.change_dir("dir/..") + self.assertEqual(filesystem.current_dir, PurePosixPath("/tmp")) + filesystem.change_dir("dir") + self.assertEqual(filesystem.current_dir, PurePosixPath("/tmp/dir")) + filesystem.change_dir("../..") + self.assertEqual(filesystem.current_dir, PurePosixPath("/")) + filesystem.change_dir("..") + self.assertEqual(filesystem.current_dir, PurePosixPath("/")) + + class TestMockPath(unittest.TestCase): - # TODO: add more test cases + def test_constructor(self): + with make_filesystem_and_report_if_error(self) as filesystem: + path = MockPath("/abc/", filesystem) + self.assertEqual(path.path, PurePosixPath("/abc/")) + self.assertIs(path.filesystem, filesystem) + + def test_parent(self): + with make_filesystem_and_report_if_error(self) as filesystem: + path = MockPath("/abc/def/", filesystem).parent + self.assertEqual(path.path, PurePosixPath("/abc")) + self.assertIs(path.filesystem, filesystem) + + def test_eq(self): + with make_filesystem_and_report_if_error(self) as filesystem: + path = MockPath("/abc/def/", filesystem) + path2 = MockPath("/abc/def/xyz/", filesystem) + path3 = MockPath("xyz/", filesystem) + for lhs in path, path2, path3: + for rhs in path, path2, path3: + with self.subTest(lhs=repr(lhs), rhs=repr(rhs)): + self.assertEqual(lhs == rhs, lhs.path == rhs.path) + self.assertEqual(lhs != rhs, lhs.path != rhs.path) + + def test_str_repr(self): + with make_filesystem_and_report_if_error(self) as filesystem: + path = MockPath("/abc/def/", filesystem) + path2 = MockPath("/abc/def/xyz/", filesystem) + path3 = MockPath("xyz/", filesystem) + for i in path, path2, path3: + self.assertEqual(str(i.path), str(i)) + self.assertEqual(repr(i.path), repr(i)) + + def test_is_dir(self): + with make_filesystem_and_report_if_error(self) as filesystem: + def check(path, expected_is_dir): + self.assertEqual(MockPath(path, filesystem).is_dir(), + expected_is_dir) + + filesystem.create("/tmp", DIR) + filesystem.create("/tmp/file", b"") + check("/", True) + check("/tmp", True) + check("/tmp/file", False) + check("/nonexistant", False) def test_mkdir(self): with make_filesystem_and_report_if_error(self) as filesystem: @@ -26,7 +233,134 @@ class TestMockPath(unittest.TestCase): "/": DIR, "/dir": DIR, }) - # TODO: add more test cases + with self.assertRaises(FileExistsError) as cm: + MockPath("/dir", filesystem).mkdir() + self.assertEqual(str(cm.exception), "/dir") + self.assertEqual(filesystem.files, + { + "/": DIR, + "/dir": DIR, + }) + MockPath("/dir", filesystem).mkdir(exist_ok=True) + self.assertEqual(filesystem.files, + { + "/": DIR, + "/dir": DIR, + }) + with self.assertRaises(FileNotFoundError) as cm: + MockPath("/dir2/dir", filesystem).mkdir() + self.assertEqual(str(cm.exception), "/dir2/dir") + self.assertEqual(filesystem.files, + { + "/": DIR, + "/dir": DIR, + }) + filesystem.create("/tmp", DIR) + filesystem.create("/tmp/file", b"") + self.assertEqual(filesystem.files, + { + "/": DIR, + "/dir": DIR, + "/tmp": DIR, + "/tmp/file": b"", + }) + with self.assertRaises(FileNotFoundError) as cm: + MockPath("/tmp/file/a/b", filesystem).mkdir() + self.assertEqual(str(cm.exception), "/tmp/file/a/b") + self.assertEqual(filesystem.files, + { + "/": DIR, + "/dir": DIR, + "/tmp": DIR, + "/tmp/file": b"", + }) + with self.assertRaises(NotADirectoryError) as cm: + MockPath("/tmp/file/a/b", filesystem).mkdir(parents=True) + self.assertEqual(str(cm.exception), "/tmp/file/a") + self.assertEqual(filesystem.files, + { + "/": DIR, + "/dir": DIR, + "/tmp": DIR, + "/tmp/file": b"", + }) + MockPath("/tmp/dir/a/b", filesystem).mkdir(parents=True) + self.assertEqual(filesystem.files, + { + "/": DIR, + "/dir": DIR, + "/tmp": DIR, + "/tmp/file": b"", + "/tmp/dir": DIR, + "/tmp/dir/a": DIR, + "/tmp/dir/a/b": DIR, + }) + with self.assertRaises(NotADirectoryError) as cm: + MockPath("/tmp/file/a/b", filesystem).mkdir(parents=True) + self.assertEqual(str(cm.exception), "/tmp/file/a") + self.assertEqual(filesystem.files, + { + "/": DIR, + "/dir": DIR, + "/tmp": DIR, + "/tmp/file": b"", + "/tmp/dir": DIR, + "/tmp/dir/a": DIR, + "/tmp/dir/a/b": DIR, + }) + MockPath("/tmp/dir/c/d", filesystem) \ + .mkdir(parents=True, exist_ok=True) + self.assertEqual(filesystem.files, + { + "/": DIR, + "/dir": DIR, + "/tmp": DIR, + "/tmp/file": b"", + "/tmp/dir": DIR, + "/tmp/dir/a": DIR, + "/tmp/dir/a/b": DIR, + "/tmp/dir/c": DIR, + "/tmp/dir/c/d": DIR, + }) + MockPath("/tmp/dir/c/d", filesystem) \ + .mkdir(parents=True, exist_ok=True) + self.assertEqual(filesystem.files, + { + "/": DIR, + "/dir": DIR, + "/tmp": DIR, + "/tmp/file": b"", + "/tmp/dir": DIR, + "/tmp/dir/a": DIR, + "/tmp/dir/a/b": DIR, + "/tmp/dir/c": DIR, + "/tmp/dir/c/d": DIR, + }) + + def test_joinpath(self): + with make_filesystem_and_report_if_error(self) as filesystem: + path1 = MockPath("/abc/", filesystem) + path2 = MockPath("def", filesystem) + path3 = MockPath("/abc/def", filesystem) + path4 = MockPath("/abc/def/..", filesystem) + self.assertEqual(path1.joinpath(path2), path3) + self.assertEqual(path1.joinpath(path2, ".."), path4) + + def test_write_bytes(self): + with make_filesystem_and_report_if_error(self) as filesystem: + MockPath("/file", filesystem).write_bytes(b"abc") + self.assertEqual(filesystem.files, {"/": DIR, "/file": b"abc"}) + MockPath("/file", filesystem).write_bytes(b"defg") + self.assertEqual(filesystem.files, {"/": DIR, "/file": b"defg"}) + + def test_write_text(self): + with make_filesystem_and_report_if_error(self) as filesystem: + MockPath("/file", filesystem).write_text("abc") + self.assertEqual(filesystem.files, {"/": DIR, "/file": b"abc"}) + MockPath("/file", filesystem).write_text("defg") + self.assertEqual(filesystem.files, {"/": DIR, "/file": b"defg"}) + with self.assertRaises(TypeError): + MockPath("/file", filesystem).write_text(1) if __name__ == "__main__": -- 2.30.2