From 14cc98d8db90b9ecb1666fe61356d2d911636af6 Mon Sep 17 00:00:00 2001 From: Suzanne Soy Date: Tue, 12 Sep 2023 01:31:01 +0100 Subject: [PATCH] Fixed some mtime errors, more tests --- expected_test_result/{touched => create} | 0 .../{written => create_write} | 0 expected_test_result/exists | 0 expected_test_result/touch | 0 expected_test_result/truncate | 1 + fs.py | 27 ++++++---- source/exists | 0 source/truncate | 1 + test.sh | 49 +++++++++++++++---- 9 files changed, 60 insertions(+), 18 deletions(-) rename expected_test_result/{touched => create} (100%) rename expected_test_result/{written => create_write} (100%) create mode 100644 expected_test_result/exists create mode 100644 expected_test_result/touch create mode 100644 expected_test_result/truncate create mode 100644 source/exists create mode 100644 source/truncate diff --git a/expected_test_result/touched b/expected_test_result/create similarity index 100% rename from expected_test_result/touched rename to expected_test_result/create diff --git a/expected_test_result/written b/expected_test_result/create_write similarity index 100% rename from expected_test_result/written rename to expected_test_result/create_write diff --git a/expected_test_result/exists b/expected_test_result/exists new file mode 100644 index 0000000..e69de29 diff --git a/expected_test_result/touch b/expected_test_result/touch new file mode 100644 index 0000000..e69de29 diff --git a/expected_test_result/truncate b/expected_test_result/truncate new file mode 100644 index 0000000..4632e06 --- /dev/null +++ b/expected_test_result/truncate @@ -0,0 +1 @@ +123456 \ No newline at end of file diff --git a/fs.py b/fs.py index d6fa8f6..f4a8eaf 100755 --- a/fs.py +++ b/fs.py @@ -33,6 +33,7 @@ class FilterFS(Operations): rl = os.readlink(p) if rl.startswith('/!/'): cached_output = os.path.join(self.cache, 'get', path.lstrip('/')) + peek = os.path.join(self.cache, 'peek', path.lstrip('/')) if not os.path.exists(cached_output): translator = self._parse(rl) d = os.path.dirname(p) @@ -44,6 +45,9 @@ class FilterFS(Operations): self._mkparents(cached_output) shutil.move(os.path.join(d, translator.output_filename), cached_output) # end hack + attr = os.lstat(p) + os.utime(cached_output, (attr.st_ctime, attr.st_mtime)) + os.utime(peek, (attr.st_ctime, attr.st_mtime)) p = cached_output return p @@ -65,8 +69,10 @@ class FilterFS(Operations): translator = self._parse(rl) self._mkparents(peek) pathlib.Path(peek).touch() + attr = os.lstat(p) + os.utime(peek, (attr.st_ctime, attr.st_mtime)) os.chmod(peek, translator.mode) - return Entity(path = peek, is_translator = True, peek = peek, source = p, size = 9999999999999999) + return Entity(path = peek, is_translator = True, peek = peek, source = p, size = 0) return Entity(path = p, is_translator = False, peek = p, source = p, size = None) # directory @@ -139,26 +145,28 @@ class FilterFS(Operations): # other: def mknod(self, path, mode, dev): - return os.mknod(self._get_entity(path).source, mode, dev) + return os.mknod(self._get_entity('mknod', path).source, mode, dev) # filesystem def statfs(self, path): pass # symlinks - #def readlink(self, path): - # pass + def readlink(self, path): + pass def symlink(self, destination, symlink_path): pass # file def open(self, path, flags): - g = self._get("open", path) - print('open:', g) - return os.open(g, flags) + print('open', path, flags) + return os.open(self._get("open", path), flags) def read(self, path, length, offset, file_handle): + print('read', path, length, offset, file_handle) + self._get("read", path) os.lseek(file_handle, offset, os.SEEK_SET) - return os.read(file_handle, length) + r = os.read(file_handle, length) + return r def _assert_is_writable(self, why, path): # TODO: might be a bit slow for many repeated writes, but guarantees that # if a translator is created in src and a file handle was already obtained @@ -191,7 +199,8 @@ class FilterFS(Operations): return self.flush(path, file_handle) def main(source, cache, mountpoint): - FUSE(FilterFS(source, cache), mountpoint, nothreads=True, foreground=True) + # direct_io allows us to return size 0 for non-empty files + FUSE(FilterFS(source, cache), mountpoint, nothreads=True, foreground=True, direct_io = True) if __name__ == '__main__': main(sys.argv[1], sys.argv[2], sys.argv[3]) \ No newline at end of file diff --git a/source/exists b/source/exists new file mode 100644 index 0000000..e69de29 diff --git a/source/truncate b/source/truncate new file mode 100644 index 0000000..a32a434 --- /dev/null +++ b/source/truncate @@ -0,0 +1 @@ +1234567890 diff --git a/test.sh b/test.sh index 2a81436..8d23447 100755 --- a/test.sh +++ b/test.sh @@ -6,17 +6,48 @@ fusermount -u test/mnt || true rm test -fr mkdir test test/cache test/mnt cp -ai source test/source -./fs.py test/source test/cache test/mnt & pid=$! + +find test/source -print0 | xargs -0r touch --no-dereference --date="2023-01-01 00:00Z" +find expected_test_result -print0 | xargs -0r touch --no-dereference --date="2023-01-01 00:00Z" + +# TODO: are the chmod preserved by git commit + git checkout ? + +./fs.py test/source test/cache test/mnt > test/fs.log & pid=$! run_tests() { - sleep 2 # TODO: use foreground=False instead of & pid=$! - touch test/mnt/touched - echo 42 > test/mnt/written - echo 'Append' >> test/mnt/append - echo 'This is an overwrite' > test/mnt/overwrite - cp -ai test/mnt test/actual_result - fusermount -u test/mnt - diff -r test/actual_result expected_test_result + # make sure any mtime errors will show up + sleep 1.1 + + # TODO: use foreground=False instead of & pid=$! + for i in `seq 20`; do + if test -e test/mnt/exists; then + break + else + printf '.' + sleep 0.1 + fi + done + printf '\n' + + echo 01; test -e test/mnt/exists + echo 02; touch --date='2023-02-02 00:00Z' test/mnt/touch && touch --date='2023-02-02 00:00Z' expected_test_result/touch + echo 03; touch --date='2023-02-02 00:00Z' test/mnt/create && touch --date='2023-02-02 00:00Z' expected_test_result/create + echo 04; echo 42 > test/mnt/create_write && touch --reference=test/mnt/create_write expected_test_result/create_write + echo 05; echo 'Append' >> test/mnt/append && touch --reference=test/mnt/append expected_test_result/append + echo 06; echo 'This is an overwrite' > test/mnt/overwrite && touch --reference=test/mnt/overwrite expected_test_result/overwrite + echo 07; truncate --size=6 test/mnt/truncate && touch --reference=test/mnt/truncate expected_test_result/truncate + echo 08; mknod -m 644 test/mnt/mknod644p p && touch --reference=test/mnt/truncate expected_test_result/mknod644p + # TODO: test that a _peek cached but not _get cached file has the correct mtime? + + # reset the mtime of the modified directories + #touch --date='2023-01-01 00:00Z' test/mnt/some_dir # unmodified + touch --date='2023-01-01 00:00Z' test/mnt + + echo 99; cp -ai test/mnt test/actual_result + echo uu; fusermount -u test/mnt + echo ta; tar -cf test/actual.tar -C test/actual_result/ . + echo te; tar -cf test/expected.tar -C expected_test_result/ . + echo dd; diffoscope test/actual.tar test/expected.tar } if run_tests; then