mte/unikernel/duniverse/dune_/test/blackbox-tests/test-cases/watching/fs-memo.t
2025-11-11 02:07:51 +01:00

467 lines
19 KiB
Perl

Tests for [Fs_memo] module.
$ . ./helpers.sh
$ test () {
> echo "------------------------------------------"
> before=$(cat _build/default/result 2>/dev/null)
> start_dune --debug-cache=fs
> build . | grep -v Success
> between=$(cat _build/default/result)
> eval "$@"
> build . | grep -v Success
> stop_dune | grep -v dune-workspace >> .#tmp
> after=$(cat _build/default/result)
> cat .#tmp | grep -v Updating
> echo "------------------------------------------"
> echo "result = '$before' -> '$between' -> '$after'"
> echo "------------------------------------------"
> cat .#tmp | grep Updating | sort
> rm .#tmp
> }
The action ignores the dependency [dep]. We use it to force rerunning the action
when necessary.
$ echo "(lang dune 2.0)" > dune-project
$ cat >dune <<EOF
> (rule
> (alias default)
> (deps dep
> (glob_files file-?)
> (glob_files dir/file-?)
> (glob_files dir/subdir/file-?))
> (target result)
> (action (system "\| echo Executing rule...
> "\| echo %{deps} |
> "\| tr ' ' '\n' |
> "\| xargs -n 1 |
> "\| grep -v dep |
> "\| xargs cat > result
> )))
> EOF
$ echo -n 1 > file-1
$ touch dep
Note that we receive two events for [file-2] because it's first created empty
and then the contents is written to it.
$ test "echo -n 2 > file-2"
------------------------------------------
Executing rule...
Success, waiting for filesystem changes...
Executing rule...
Success, waiting for filesystem changes...
------------------------------------------
result = '' -> '1' -> '12'
------------------------------------------
Updating dir_contents cache for ".": Updated { changed = true }
Updating dir_contents cache for "file-2": Skipped
Updating dir_contents cache for "file-2": Skipped
Updating file_digest cache for ".": Skipped
Updating file_digest cache for "file-2": Skipped
Updating file_digest cache for "file-2": Skipped
Updating path_stat cache for ".": Updated { changed = false }
Updating path_stat cache for "file-2": Skipped
Updating path_stat cache for "file-2": Skipped
Note that Dune did not re-execute the rule because the set of files matching
the glob remains unchanged.
$ test "mkdir dir"
------------------------------------------
Success, waiting for filesystem changes...
Success, waiting for filesystem changes...
------------------------------------------
result = '12' -> '12' -> '12'
------------------------------------------
Updating dir_contents cache for ".": Updated { changed = true }
Updating dir_contents cache for "dir": Skipped
Updating file_digest cache for ".": Skipped
Updating file_digest cache for "dir": Skipped
Updating path_stat cache for ".": Updated { changed = false }
Updating path_stat cache for "dir": Skipped
We create [dir/file-3] before running Dune, so we only observe a single
[file_digest] change event with the file watcher.
$ echo -n '?' > dir/file-3
$ test "echo -n 3 > dir/file-3"
------------------------------------------
Executing rule...
Success, waiting for filesystem changes...
Executing rule...
Success, waiting for filesystem changes...
------------------------------------------
result = '12' -> '12?' -> '123'
------------------------------------------
Updating dir_contents cache for "dir/file-3": Skipped
Updating file_digest cache for "dir/file-3": Updated { changed = true }
Updating path_stat cache for "dir/file-3": Skipped
Now, Dune similarly updates [file_digest] for [file-2].
$ test "echo -n '*' > file-2"
------------------------------------------
Success, waiting for filesystem changes...
Executing rule...
Success, waiting for filesystem changes...
------------------------------------------
result = '123' -> '123' -> '1*3'
------------------------------------------
Updating dir_contents cache for "file-2": Skipped
Updating file_digest cache for "file-2": Updated { changed = true }
Updating path_stat cache for "file-2": Skipped
On deletion of a file, we receive events for the file and the parent directory.
$ test "rm file-2"
------------------------------------------
Success, waiting for filesystem changes...
Executing rule...
Success, waiting for filesystem changes...
------------------------------------------
result = '1*3' -> '1*3' -> '13'
------------------------------------------
Updating dir_contents cache for ".": Updated { changed = true }
Updating dir_contents cache for "file-2": Skipped
Updating file_digest cache for ".": Skipped
Updating file_digest cache for "file-2": Updated { changed = true }
Updating path_stat cache for ".": Updated { changed = false }
Updating path_stat cache for "file-2": Skipped
Dune notices that [dir_contents] of both [dir] and [.] changed, and also that
[dir/file-3]'s digest changed (from a digest to the error about missing file).
$ test "mv dir/file-3 ."
------------------------------------------
Success, waiting for filesystem changes...
Executing rule...
Success, waiting for filesystem changes...
------------------------------------------
result = '13' -> '13' -> '13'
------------------------------------------
Updating dir_contents cache for ".": Updated { changed = true }
Updating dir_contents cache for "dir": Updated { changed = true }
Updating dir_contents cache for "dir/file-3": Skipped
Updating dir_contents cache for "file-3": Skipped
Updating file_digest cache for ".": Skipped
Updating file_digest cache for "dir": Skipped
Updating file_digest cache for "dir/file-3": Updated { changed = true }
Updating file_digest cache for "file-3": Skipped
Updating path_stat cache for ".": Updated { changed = false }
Updating path_stat cache for "dir": Updated { changed = false }
Updating path_stat cache for "dir/file-3": Skipped
Updating path_stat cache for "file-3": Skipped
$ test "mkdir dir/subdir"
------------------------------------------
Success, waiting for filesystem changes...
Success, waiting for filesystem changes...
------------------------------------------
result = '13' -> '13' -> '13'
------------------------------------------
Updating dir_contents cache for "dir": Updated { changed = true }
Updating dir_contents cache for "dir/subdir": Skipped
Updating file_digest cache for "dir": Skipped
Updating file_digest cache for "dir/subdir": Skipped
Updating path_stat cache for "dir": Updated { changed = false }
Updating path_stat cache for "dir/subdir": Skipped
Again, there are two events for [file-4]: for creation and modification.
$ test "echo -n 4 > dir/subdir/file-4"
------------------------------------------
Success, waiting for filesystem changes...
Executing rule...
Success, waiting for filesystem changes...
------------------------------------------
result = '13' -> '13' -> '134'
------------------------------------------
Updating dir_contents cache for "dir/subdir": Updated { changed = true }
Updating dir_contents cache for "dir/subdir/file-4": Skipped
Updating dir_contents cache for "dir/subdir/file-4": Skipped
Updating file_digest cache for "dir/subdir": Skipped
Updating file_digest cache for "dir/subdir/file-4": Skipped
Updating file_digest cache for "dir/subdir/file-4": Skipped
Updating path_stat cache for "dir/subdir": Updated { changed = false }
Updating path_stat cache for "dir/subdir/file-4": Skipped
Updating path_stat cache for "dir/subdir/file-4": Skipped
Here we are getting duplicate events for directories [dir] and [dir/subdir]
because we watch each of them both directly and via their parents.
$ test "mv dir/subdir ."
------------------------------------------
Success, waiting for filesystem changes...
Executing rule...
Success, waiting for filesystem changes...
------------------------------------------
result = '134' -> '134' -> '13'
------------------------------------------
Updating dir_contents cache for ".": Updated { changed = true }
Updating dir_contents cache for "dir": Updated { changed = false }
Updating dir_contents cache for "dir": Updated { changed = true }
Updating dir_contents cache for "dir/subdir": Updated { changed = false }
Updating dir_contents cache for "dir/subdir": Updated { changed = true }
Updating dir_contents cache for "subdir": Skipped
Updating file_digest cache for ".": Skipped
Updating file_digest cache for "dir": Skipped
Updating file_digest cache for "dir": Skipped
Updating file_digest cache for "dir/subdir": Skipped
Updating file_digest cache for "dir/subdir": Skipped
Updating file_digest cache for "subdir": Skipped
Updating path_stat cache for ".": Updated { changed = false }
Updating path_stat cache for "dir": Updated { changed = false }
Updating path_stat cache for "dir": Updated { changed = false }
Updating path_stat cache for "dir/subdir": Updated { changed = false }
Updating path_stat cache for "dir/subdir": Updated { changed = true }
Updating path_stat cache for "subdir": Skipped
This seems to be a bug: Dune doesn't notice that a directory's permission
changed and succeeds instead of failing.
$ test "chmod -r subdir"
------------------------------------------
Success, waiting for filesystem changes...
Success, waiting for filesystem changes...
------------------------------------------
result = '13' -> '13' -> '13'
------------------------------------------
If we repeat the test, we finally see the failure.
# CR-someday amokhov: Fix this.
$ test "echo How about now?"
------------------------------------------
Failure
How about now?
Failure
Error: inotify_add_watch(subdir): Permission denied
Had 1 error, waiting for filesystem changes...
Error: inotify_add_watch(subdir): Permission denied
Had 1 error, waiting for filesystem changes...
------------------------------------------
result = '13' -> '13' -> '13'
------------------------------------------
Same problem in the other direction.
$ test "chmod +r subdir"
------------------------------------------
Failure
Failure
Error: inotify_add_watch(subdir): Permission denied
Had 1 error, waiting for filesystem changes...
Error: inotify_add_watch(subdir): Permission denied
Had 1 error, waiting for filesystem changes...
------------------------------------------
result = '13' -> '13' -> '13'
------------------------------------------
$ test "echo How about now?"
------------------------------------------
How about now?
Success, waiting for filesystem changes...
Success, waiting for filesystem changes...
------------------------------------------
result = '13' -> '13' -> '13'
------------------------------------------
Same problem for files.
$ test "chmod -r file-1"
------------------------------------------
Success, waiting for filesystem changes...
Success, waiting for filesystem changes...
------------------------------------------
result = '13' -> '13' -> '13'
------------------------------------------
$ test "chmod +r file-1"
------------------------------------------
Failure
Failure
Error: file-1: Permission denied
-> required by _build/default/file-1
-> required by _build/default/result
-> required by alias default
Had 1 error, waiting for filesystem changes...
Error: file-1: Permission denied
-> required by _build/default/file-1
-> required by _build/default/result
-> required by alias default
Had 1 error, waiting for filesystem changes...
------------------------------------------
result = '13' -> '13' -> '13'
------------------------------------------
Dune receives one event for [file-1] when moving it within the same directory,
and two events for [file-5]: for moving and for changing. There are two events
for [dir_contents] of [.] because moving a file is interpreted as deleting and
then creating a file.
$ test "mv file-1 file-5; echo -n 5 > file-5"
------------------------------------------
Success, waiting for filesystem changes...
Executing rule...
Success, waiting for filesystem changes...
------------------------------------------
result = '13' -> '13' -> '35'
------------------------------------------
Updating dir_contents cache for ".": Updated { changed = false }
Updating dir_contents cache for ".": Updated { changed = true }
Updating dir_contents cache for "file-1": Skipped
Updating dir_contents cache for "file-5": Skipped
Updating dir_contents cache for "file-5": Skipped
Updating file_digest cache for ".": Skipped
Updating file_digest cache for ".": Skipped
Updating file_digest cache for "file-1": Updated { changed = true }
Updating file_digest cache for "file-5": Skipped
Updating file_digest cache for "file-5": Skipped
Updating path_stat cache for ".": Updated { changed = false }
Updating path_stat cache for ".": Updated { changed = false }
Updating path_stat cache for "file-1": Skipped
Updating path_stat cache for "file-5": Skipped
Updating path_stat cache for "file-5": Skipped
Tests for watching symbolic links.
First, create a symbolic link. Dune correctly updates the [result].
$ test "ln -s ../file-3 dir/file-6"
------------------------------------------
Success, waiting for filesystem changes...
Executing rule...
Success, waiting for filesystem changes...
------------------------------------------
result = '35' -> '35' -> '353'
------------------------------------------
Updating dir_contents cache for "dir": Updated { changed = true }
Updating dir_contents cache for "dir/file-6": Skipped
Updating file_digest cache for "dir": Skipped
Updating file_digest cache for "dir/file-6": Skipped
Updating path_stat cache for "dir": Updated { changed = false }
Updating path_stat cache for "dir/file-6": Skipped
Now, delete the symbolic link. Dune receives the corresponding events and
reruns the affected action.
$ test "rm dir/file-6"
------------------------------------------
Success, waiting for filesystem changes...
Executing rule...
Success, waiting for filesystem changes...
------------------------------------------
result = '353' -> '353' -> '35'
------------------------------------------
Updating dir_contents cache for "dir": Updated { changed = true }
Updating dir_contents cache for "dir/file-6": Skipped
Updating file_digest cache for "dir": Skipped
Updating file_digest cache for "dir/file-6": Updated { changed = true }
Updating path_stat cache for "dir": Updated { changed = false }
Updating path_stat cache for "dir/file-6": Updated { changed = true }
Now test symbolic links to directories.
$ mkdir another-dir
$ rmdir dir
$ ln -s another-dir dir
At first, things appear to be working well: we correctly discover [dir/file-7]
and re-execute the rule.
$ test "echo -n 7 > another-dir/file-7"
------------------------------------------
Success, waiting for filesystem changes...
Executing rule...
Success, waiting for filesystem changes...
------------------------------------------
result = '35' -> '35' -> '357'
------------------------------------------
Updating dir_contents cache for "dir": Updated { changed = true }
Updating dir_contents cache for "dir/file-7": Skipped
Updating dir_contents cache for "dir/file-7": Skipped
Updating file_digest cache for "dir": Skipped
Updating file_digest cache for "dir/file-7": Skipped
Updating file_digest cache for "dir/file-7": Skipped
Updating path_stat cache for "dir": Updated { changed = false }
Updating path_stat cache for "dir/file-7": Skipped
Updating path_stat cache for "dir/file-7": Skipped
Deleting [dir] triggers a rebuild.
$ test "rm dir"
------------------------------------------
Success, waiting for filesystem changes...
Executing rule...
Success, waiting for filesystem changes...
------------------------------------------
result = '357' -> '357' -> '35'
------------------------------------------
Updating dir_contents cache for ".": Updated { changed = true }
Updating dir_contents cache for "dir": Updated { changed = true }
Updating file_digest cache for ".": Skipped
Updating file_digest cache for "dir": Skipped
Updating path_stat cache for ".": Updated { changed = false }
Updating path_stat cache for "dir": Updated { changed = true }
Restoring the symlink is correctly noticed.
$ test "ln -s another-dir dir"
------------------------------------------
Success, waiting for filesystem changes...
Executing rule...
Success, waiting for filesystem changes...
------------------------------------------
result = '35' -> '35' -> '357'
------------------------------------------
Updating dir_contents cache for ".": Updated { changed = true }
Updating dir_contents cache for "dir": Skipped
Updating file_digest cache for ".": Skipped
Updating file_digest cache for "dir": Skipped
Updating path_stat cache for ".": Updated { changed = false }
Updating path_stat cache for "dir": Skipped
However, deleting [another-dir] isn't handled correctly.
# CR-someday amokhov: Fix this.
$ test "rm another-dir/file-7; sleep 0.001; rmdir another-dir"
------------------------------------------
Success, waiting for filesystem changes...
Executing rule...
Success, waiting for filesystem changes...
------------------------------------------
result = '357' -> '357' -> '35'
------------------------------------------
Updating dir_contents cache for ".": Updated { changed = true }
Updating dir_contents cache for "another-dir": Updated { changed = true }
Updating dir_contents cache for "dir": Updated { changed = true }
Updating dir_contents cache for "dir/file-7": Skipped
Updating file_digest cache for ".": Skipped
Updating file_digest cache for "another-dir": Skipped
Updating file_digest cache for "dir": Skipped
Updating file_digest cache for "dir/file-7": Updated { changed = true }
Updating path_stat cache for ".": Updated { changed = false }
Updating path_stat cache for "another-dir": Updated { changed = true }
Updating path_stat cache for "dir": Updated { changed = false }
Updating path_stat cache for "dir/file-7": Skipped
If we force a rebuild, Dune belatedly notices that [another-dir/file-7] is now
unreachable but doesn't complain about the symlink [dir] now being broken. We
should fix this too.
$ test "echo force > dep"
------------------------------------------
Success, waiting for filesystem changes...
Executing rule...
Success, waiting for filesystem changes...
------------------------------------------
result = '35' -> '35' -> '35'
------------------------------------------
Updating dir_contents cache for "dep": Skipped
Updating file_digest cache for "dep": Updated { changed = true }
Updating path_stat cache for "dep": Skipped