From c67f012138179afd8a127bd54fa94c07662aa133 Mon Sep 17 00:00:00 2001
From: Nicolas Dandrimont <nicolas@dandrimont.eu>
Date: Wed, 4 Oct 2017 22:33:45 +0200
Subject: [PATCH] from_disk: full test coverage

---
 swh/model/from_disk.py            |   8 +--
 swh/model/tests/test_from_disk.py | 116 +++++++++++++++++++++++++++++-
 2 files changed, 119 insertions(+), 5 deletions(-)

diff --git a/swh/model/from_disk.py b/swh/model/from_disk.py
index bb108a54..f9f37290 100644
--- a/swh/model/from_disk.py
+++ b/swh/model/from_disk.py
@@ -299,7 +299,7 @@ class Directory(MerkleNode):
 
     def __getitem__(self, key):
         if not isinstance(key, bytes):
-            raise ValueError('Can only get a bytes from directory')
+            raise ValueError('Can only get a bytes from Directory')
 
         # Convenience shortcut
         if key == b'':
@@ -313,9 +313,9 @@ class Directory(MerkleNode):
 
     def __setitem__(self, key, value):
         if not isinstance(key, bytes):
-            raise ValueError('Can only set a bytes directory entry')
+            raise ValueError('Can only set a bytes Directory entry')
         if not isinstance(value, (Content, Directory)):
-            raise ValueError('Can only set a directory entry to a Content or '
+            raise ValueError('Can only set a Directory entry to a Content or '
                              'Directory')
 
         if key == b'':
@@ -331,7 +331,7 @@ class Directory(MerkleNode):
 
     def __delitem__(self, key):
         if not isinstance(key, bytes):
-            raise ValueError('Can only delete a bytes directory entry')
+            raise ValueError('Can only delete a bytes Directory entry')
 
         if b'/' not in key:
             super().__delitem__(key)
diff --git a/swh/model/tests/test_from_disk.py b/swh/model/tests/test_from_disk.py
index 3a0a104c..25df48b9 100644
--- a/swh/model/tests/test_from_disk.py
+++ b/swh/model/tests/test_from_disk.py
@@ -10,7 +10,7 @@ import unittest
 
 from swh.model import from_disk
 from swh.model.from_disk import Content, Directory, DentryPerms
-from swh.model.hashutil import DEFAULT_ALGORITHMS, hash_to_bytes
+from swh.model.hashutil import DEFAULT_ALGORITHMS, hash_to_bytes, hash_to_hex
 
 
 class ModeToPerms(unittest.TestCase):
@@ -481,6 +481,7 @@ class TestContent(DataMixin, unittest.TestCase):
             conv_content = Content.from_bytes(mode=content['mode'],
                                               data=content['data'])
             self.assertContentEqual(conv_content, content)
+            self.assertIn(hash_to_hex(conv_content.hash), repr(conv_content))
 
 
 class SymlinkToContent(DataMixin, unittest.TestCase):
@@ -649,6 +650,38 @@ class DirectoryToObjects(DataMixin, unittest.TestCase):
                          len(self.contents)
                          + 1)
 
+    def test_directory_to_objects_ignore_name_case(self):
+        directory = Directory.from_disk(
+            path=self.tmpdir.name,
+            dir_filter=from_disk.ignore_named_directories([b'symLiNks'],
+                                                          case_sensitive=False)
+        )
+        for name, value in self.contents.items():
+            self.assertContentEqual(directory[b'contents/' + name], value)
+
+        for name in self.specials:
+            self.assertContentEqual(
+                directory[b'specials/' + name],
+                self.empty_content,
+            )
+
+        self.assertEqual(
+            directory[b'empty1/empty2'].get_data(),
+            self.empty_directory,
+        )
+
+        with self.assertRaisesRegex(KeyError, "b'symlinks'"):
+            directory[b'symlinks']
+
+        objs = directory.collect()
+
+        self.assertCountEqual(['content', 'directory'], objs)
+
+        self.assertEqual(len(objs['directory']), 5)
+        self.assertEqual(len(objs['content']),
+                         len(self.contents)
+                         + 1)
+
 
 class TarballTest(DataMixin, unittest.TestCase):
     def setUp(self):
@@ -668,3 +701,84 @@ class TarballTest(DataMixin, unittest.TestCase):
                 self.assertDirectoryEqual(obj, data)
             else:
                 raise self.failureException('Unknown type for %s' % obj)
+
+
+class DirectoryManipulation(DataMixin, unittest.TestCase):
+    def test_directory_access_nested(self):
+        d = Directory()
+        d[b'a'] = Directory()
+        d[b'a/b'] = Directory()
+
+        self.assertEqual(d[b'a/b'].get_data(), self.empty_directory)
+
+    def test_directory_del_nested(self):
+        d = Directory()
+        d[b'a'] = Directory()
+        d[b'a/b'] = Directory()
+
+        with self.assertRaisesRegex(KeyError, "b'c'"):
+            del d[b'a/b/c']
+
+        with self.assertRaisesRegex(KeyError, "b'level2'"):
+            del d[b'a/level2/c']
+
+        del d[b'a/b']
+
+        self.assertEqual(d[b'a'].get_data(), self.empty_directory)
+
+    def test_directory_access_self(self):
+        d = Directory()
+        self.assertIs(d, d[b''])
+        self.assertIs(d, d[b'/'])
+        self.assertIs(d, d[b'//'])
+
+    def test_directory_access_wrong_type(self):
+        d = Directory()
+        with self.assertRaisesRegex(ValueError, 'bytes from Directory'):
+            d['foo']
+        with self.assertRaisesRegex(ValueError, 'bytes from Directory'):
+            d[42]
+
+    def test_directory_repr(self):
+        entries = [b'a', b'b', b'c']
+        d = Directory()
+        for entry in entries:
+            d[entry] = Directory()
+
+        r = repr(d)
+        self.assertIn(hash_to_hex(d.hash), r)
+
+        for entry in entries:
+            self.assertIn(str(entry), r)
+
+    def test_directory_set_wrong_type_name(self):
+        d = Directory()
+        with self.assertRaisesRegex(ValueError, 'bytes Directory entry'):
+            d['foo'] = Directory()
+        with self.assertRaisesRegex(ValueError, 'bytes Directory entry'):
+            d[42] = Directory()
+
+    def test_directory_set_nul_in_name(self):
+        d = Directory()
+
+        with self.assertRaisesRegex(ValueError, 'nul bytes'):
+            d[b'\x00\x01'] = Directory()
+
+    def test_directory_set_empty_name(self):
+        d = Directory()
+        with self.assertRaisesRegex(ValueError, 'must have a name'):
+            d[b''] = Directory()
+        with self.assertRaisesRegex(ValueError, 'must have a name'):
+            d[b'/'] = Directory()
+
+    def test_directory_set_wrong_type(self):
+        d = Directory()
+        with self.assertRaisesRegex(ValueError, 'Content or Directory'):
+            d[b'entry'] = object()
+
+    def test_directory_del_wrong_type(self):
+        d = Directory()
+        with self.assertRaisesRegex(ValueError, 'bytes Directory entry'):
+            del d['foo']
+        with self.assertRaisesRegex(ValueError, 'bytes Directory entry'):
+            del d[42]
-- 
GitLab