write rest of MockPath tests
authorJacob Lifshay <programmerjake@gmail.com>
Fri, 18 Sep 2020 00:11:01 +0000 (17:11 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Fri, 18 Sep 2020 00:11:01 +0000 (17:11 -0700)
src/budget_sync/test/mock_path.py
src/budget_sync/test/test_mock_path.py

index 5e72e38..33a7131 100644 (file)
@@ -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)
index 6ddcd4c..cc8420e 100644 (file)
@@ -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__":