summaryrefslogtreecommitdiffstats
path: root/tests/gnu
diff options
context:
space:
mode:
Diffstat (limited to 'tests/gnu')
-rw-r--r--tests/gnu/L_delete.out4
-rw-r--r--tests/gnu/L_delete.sh11
-rw-r--r--tests/gnu/L_printf_types.out17
-rw-r--r--tests/gnu/L_printf_types.sh1
-rw-r--r--tests/gnu/daystart.sh2
-rw-r--r--tests/gnu/daystart_twice.sh2
-rw-r--r--tests/gnu/empty.out8
-rw-r--r--tests/gnu/empty.sh1
-rw-r--r--tests/gnu/empty_special.out20
-rw-r--r--tests/gnu/empty_special.sh1
-rw-r--r--tests/gnu/execdir_path_dot.sh1
-rw-r--r--tests/gnu/execdir_path_empty.sh1
-rw-r--r--tests/gnu/execdir_path_relative.sh1
-rw-r--r--tests/gnu/execdir_ulimit.out16
-rw-r--r--tests/gnu/execdir_ulimit.sh2
-rw-r--r--tests/gnu/executable.out21
-rw-r--r--tests/gnu/files0_from_empty.sh2
-rw-r--r--tests/gnu/files0_from_file.out12
-rw-r--r--tests/gnu/files0_from_file.sh6
-rw-r--r--tests/gnu/files0_from_file_file.out2
-rw-r--r--tests/gnu/files0_from_file_file.sh3
-rw-r--r--tests/gnu/files0_from_ok.sh1
-rw-r--r--tests/gnu/files0_from_stdin.out12
-rw-r--r--tests/gnu/files0_from_stdin_ok.sh1
-rw-r--r--tests/gnu/files0_from_stdin_ok_file.out45
-rw-r--r--tests/gnu/files0_from_stdin_ok_file.sh4
-rw-r--r--tests/gnu/files0_from_stdin_stdin.out45
-rw-r--r--tests/gnu/files0_from_stdin_stdin.sh2
-rw-r--r--tests/gnu/fls.sh3
-rw-r--r--tests/gnu/fls_nonexistent.sh2
-rw-r--r--tests/gnu/fls_overflow.sh4
-rw-r--r--tests/gnu/follow_comma.out8
-rw-r--r--tests/gnu/follow_files0_from.out42
-rw-r--r--tests/gnu/follow_files0_from.sh1
-rw-r--r--tests/gnu/fprint0_nonexistent.sh2
-rw-r--r--tests/gnu/fprint_duplicate.sh10
-rw-r--r--tests/gnu/fprint_nonexistent.sh2
-rw-r--r--tests/gnu/fprint_unreached_error.sh (renamed from tests/gnu/fprint_noerror.sh)0
-rw-r--r--tests/gnu/fprintf_nonexistent.sh2
-rw-r--r--tests/gnu/fstype_btrfs_subvol.out4
-rw-r--r--tests/gnu/fstype_btrfs_subvol.sh25
-rw-r--r--tests/gnu/fstype_stacked.out2
-rw-r--r--tests/gnu/fstype_stacked.sh14
-rw-r--r--tests/gnu/fstype_umount.sh14
-rw-r--r--tests/gnu/gid.sh1
-rw-r--r--tests/gnu/gid_minus.out19
-rw-r--r--tests/gnu/gid_minus.sh1
-rw-r--r--tests/gnu/gid_minus_plus.out19
-rw-r--r--tests/gnu/gid_minus_plus.sh1
-rw-r--r--tests/gnu/gid_plus.out19
-rw-r--r--tests/gnu/gid_plus.sh2
-rw-r--r--tests/gnu/gid_plus_plus.out19
-rw-r--r--tests/gnu/gid_plus_plus.sh2
-rw-r--r--tests/gnu/ignore_readdir_race.sh6
-rw-r--r--tests/gnu/ignore_readdir_race_loop.out11
-rw-r--r--tests/gnu/ignore_readdir_race_loop.sh2
-rw-r--r--tests/gnu/ignore_readdir_race_notdir.sh8
-rw-r--r--tests/gnu/ignore_readdir_race_rmdir.out2
-rw-r--r--tests/gnu/ignore_readdir_race_rmdir.sh5
-rw-r--r--tests/gnu/inum_automount.out2
-rw-r--r--tests/gnu/inum_automount.sh14
-rw-r--r--tests/gnu/newer_link.out1
-rw-r--r--tests/gnu/newer_link.sh1
-rw-r--r--tests/gnu/not_comma.out (renamed from tests/gnu/gid.out)15
-rw-r--r--tests/gnu/not_comma.sh2
-rw-r--r--tests/gnu/ok_files0_from_stdin.sh1
-rw-r--r--tests/gnu/ok_flush.sh2
-rw-r--r--tests/gnu/okdir_path_dot.sh1
-rw-r--r--tests/gnu/okdir_path_empty.sh1
-rw-r--r--tests/gnu/okdir_path_relative.sh1
-rw-r--r--tests/gnu/perm_000_slash.out35
-rw-r--r--tests/gnu/perm_222_slash.out23
-rw-r--r--tests/gnu/perm_644_slash.out31
-rw-r--r--tests/gnu/perm_leading_plus_symbolic_slash.out33
-rw-r--r--tests/gnu/perm_symbolic_slash.out29
-rw-r--r--tests/gnu/print0.outbin16 -> 0 bytes
-rw-r--r--tests/gnu/print0.sh2
-rw-r--r--tests/gnu/printf_Y_error.out6
-rw-r--r--tests/gnu/printf_Y_error.sh12
-rw-r--r--tests/gnu/printf_flags.sh2
-rw-r--r--tests/gnu/printf_u_g_ulimit.sh3
-rw-r--r--tests/gnu/readable.out22
-rw-r--r--tests/gnu/regex_invalid_utf8.out2
-rw-r--r--tests/gnu/regex_invalid_utf8.sh10
-rw-r--r--tests/gnu/regextype_awk.out2
-rw-r--r--tests/gnu/regextype_awk.sh3
-rw-r--r--tests/gnu/regextype_egrep.out0
-rw-r--r--tests/gnu/regextype_egrep.sh3
-rw-r--r--tests/gnu/regextype_emacs.sh2
-rw-r--r--tests/gnu/regextype_findutils_default.out3
-rw-r--r--tests/gnu/regextype_findutils_default.sh3
-rw-r--r--tests/gnu/regextype_gnu_awk.out2
-rw-r--r--tests/gnu/regextype_gnu_awk.sh3
-rw-r--r--tests/gnu/regextype_posix_awk.out2
-rw-r--r--tests/gnu/regextype_posix_awk.sh3
-rw-r--r--tests/gnu/regextype_posix_minimal_basic.out1
-rw-r--r--tests/gnu/regextype_posix_minimal_basic.sh2
-rw-r--r--tests/gnu/uid.out19
-rw-r--r--tests/gnu/uid.sh1
-rw-r--r--tests/gnu/uid_minus.out19
-rw-r--r--tests/gnu/uid_minus.sh1
-rw-r--r--tests/gnu/uid_minus_plus.out19
-rw-r--r--tests/gnu/uid_minus_plus.sh1
-rw-r--r--tests/gnu/uid_plus.out19
-rw-r--r--tests/gnu/uid_plus.sh2
-rw-r--r--tests/gnu/uid_plus_plus.out19
-rw-r--r--tests/gnu/uid_plus_plus.sh2
-rw-r--r--tests/gnu/used.out4
-rw-r--r--tests/gnu/used.sh21
-rw-r--r--tests/gnu/writable.out23
-rw-r--r--tests/gnu/xtype_bind_mount.out4
-rw-r--r--tests/gnu/xtype_bind_mount.sh12
-rw-r--r--tests/gnu/xtype_l_loops.out3
-rw-r--r--tests/gnu/xtype_l_loops.sh1
114 files changed, 606 insertions, 340 deletions
diff --git a/tests/gnu/L_delete.out b/tests/gnu/L_delete.out
index ed0e9a1..7ed5f0d 100644
--- a/tests/gnu/L_delete.out
+++ b/tests/gnu/L_delete.out
@@ -1,2 +1,2 @@
-scratch
-scratch/foo
+.
+./foo
diff --git a/tests/gnu/L_delete.sh b/tests/gnu/L_delete.sh
index 8fdb12a..0559c49 100644
--- a/tests/gnu/L_delete.sh
+++ b/tests/gnu/L_delete.sh
@@ -1,9 +1,8 @@
-clean_scratch
-mkdir scratch/foo
-mkdir scratch/bar
-ln -s ../foo scratch/bar/baz
+cd "$TEST"
+mkdir foo bar
+ln -s ../foo bar/baz
# Don't try to rmdir() a symlink
-invoke_bfs -L scratch/bar -delete
+invoke_bfs -L bar -delete
-bfs_diff scratch
+bfs_diff .
diff --git a/tests/gnu/L_printf_types.out b/tests/gnu/L_printf_types.out
new file mode 100644
index 0000000..734b15f
--- /dev/null
+++ b/tests/gnu/L_printf_types.out
@@ -0,0 +1,17 @@
+(links) () d d
+(links/broken) (nowhere) l N
+(links/deeply) () d d
+(links/deeply/nested) () d d
+(links/deeply/nested/broken) (nowhere) l N
+(links/deeply/nested/dir) () d d
+(links/deeply/nested/file) () f f
+(links/deeply/nested/link) () f f
+(links/file) () f f
+(links/hardlink) () f f
+(links/notdir) (symlink/file) l N
+(links/skip) () d d
+(links/skip/broken) (nowhere) l N
+(links/skip/dir) () d d
+(links/skip/file) () f f
+(links/skip/link) () f f
+(links/symlink) () f f
diff --git a/tests/gnu/L_printf_types.sh b/tests/gnu/L_printf_types.sh
new file mode 100644
index 0000000..caa9083
--- /dev/null
+++ b/tests/gnu/L_printf_types.sh
@@ -0,0 +1 @@
+bfs_diff -L links -printf '(%p) (%l) %y %Y\n'
diff --git a/tests/gnu/daystart.sh b/tests/gnu/daystart.sh
index 9799bca..9c3be1a 100644
--- a/tests/gnu/daystart.sh
+++ b/tests/gnu/daystart.sh
@@ -1 +1 @@
-bfs_diff basic -daystart -mtime 0
+TZ=WAT-1 bfs_diff basic -daystart -mtime 0
diff --git a/tests/gnu/daystart_twice.sh b/tests/gnu/daystart_twice.sh
index 21b2c0f..edbf18d 100644
--- a/tests/gnu/daystart_twice.sh
+++ b/tests/gnu/daystart_twice.sh
@@ -1 +1 @@
-bfs_diff basic -daystart -daystart -mtime 0
+TZ=WAT-1 bfs_diff basic -daystart -daystart -mtime 0
diff --git a/tests/gnu/empty.out b/tests/gnu/empty.out
deleted file mode 100644
index a0f4b76..0000000
--- a/tests/gnu/empty.out
+++ /dev/null
@@ -1,8 +0,0 @@
-basic/a
-basic/b
-basic/c/d
-basic/e/f
-basic/g/h
-basic/i
-basic/j/foo
-basic/k/foo/bar
diff --git a/tests/gnu/empty.sh b/tests/gnu/empty.sh
deleted file mode 100644
index 95ee988..0000000
--- a/tests/gnu/empty.sh
+++ /dev/null
@@ -1 +0,0 @@
-bfs_diff basic -empty
diff --git a/tests/gnu/empty_special.out b/tests/gnu/empty_special.out
deleted file mode 100644
index fa35478..0000000
--- a/tests/gnu/empty_special.out
+++ /dev/null
@@ -1,20 +0,0 @@
-rainbow//
-rainbow/exec.sh
-rainbow/file.dat
-rainbow/file.txt
-rainbow/lower.gz
-rainbow/lower.tar
-rainbow/lower.tar.gz
-rainbow/lu.tar.GZ
-rainbow/mh1
-rainbow/mh2
-rainbow/ow
-rainbow/sgid
-rainbow/sticky
-rainbow/sticky_ow
-rainbow/sugid
-rainbow/suid
-rainbow/ul.TAR.gz
-rainbow/upper.GZ
-rainbow/upper.TAR
-rainbow/upper.TAR.GZ
diff --git a/tests/gnu/empty_special.sh b/tests/gnu/empty_special.sh
deleted file mode 100644
index 31e9d2e..0000000
--- a/tests/gnu/empty_special.sh
+++ /dev/null
@@ -1 +0,0 @@
-bfs_diff rainbow -empty
diff --git a/tests/gnu/execdir_path_dot.sh b/tests/gnu/execdir_path_dot.sh
new file mode 100644
index 0000000..632dbb4
--- /dev/null
+++ b/tests/gnu/execdir_path_dot.sh
@@ -0,0 +1 @@
+! PATH=".:$PATH" invoke_bfs basic -execdir echo {} +
diff --git a/tests/gnu/execdir_path_empty.sh b/tests/gnu/execdir_path_empty.sh
new file mode 100644
index 0000000..eda6b1c
--- /dev/null
+++ b/tests/gnu/execdir_path_empty.sh
@@ -0,0 +1 @@
+! PATH=":$PATH" invoke_bfs basic -execdir echo {} +
diff --git a/tests/gnu/execdir_path_relative.sh b/tests/gnu/execdir_path_relative.sh
new file mode 100644
index 0000000..69899ad
--- /dev/null
+++ b/tests/gnu/execdir_path_relative.sh
@@ -0,0 +1 @@
+! PATH="foo:$PATH" invoke_bfs basic -execdir echo {} +
diff --git a/tests/gnu/execdir_ulimit.out b/tests/gnu/execdir_ulimit.out
new file mode 100644
index 0000000..6749f7d
--- /dev/null
+++ b/tests/gnu/execdir_ulimit.out
@@ -0,0 +1,16 @@
+64 ./0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE
+64 ./0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE
+64 ./0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE
+64 ./0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE
+64 ./0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE
+64 ./0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE
+64 ./0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE
+64 ./0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE
+64 ./0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE
+64 ./0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE
+64 ./0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE
+64 ./0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE
+64 ./0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE
+64 ./0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE
+64 ./0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE
+64 ./0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE
diff --git a/tests/gnu/execdir_ulimit.sh b/tests/gnu/execdir_ulimit.sh
new file mode 100644
index 0000000..e14e716
--- /dev/null
+++ b/tests/gnu/execdir_ulimit.sh
@@ -0,0 +1,2 @@
+ulimit -Sn 64
+bfs_diff deep -type f -execdir bash -c 'printf "%d %s\n" $(ulimit -Sn) "$1"' bash {} \;
diff --git a/tests/gnu/executable.out b/tests/gnu/executable.out
index 49c1b21..e256554 100644
--- a/tests/gnu/executable.out
+++ b/tests/gnu/executable.out
@@ -1,4 +1,19 @@
perms
-perms/rwx
-perms/rx
-perms/wx
+perms/dr-x------
+perms/dr-xr-xr-x
+perms/drwx------
+perms/drwxr-xr-x
+perms/drwxrwxr-x
+perms/drwxrwxrwx
+perms/f--x------
+perms/f--x--x--x
+perms/f-wx------
+perms/f-wx--x--x
+perms/f-wx-wx--x
+perms/f-wx-wx-wx
+perms/fr-x------
+perms/fr-xr-xr-x
+perms/frwxr-----
+perms/frwxr-xr-x
+perms/frwxrwxr-x
+perms/frwxrwxrwx
diff --git a/tests/gnu/files0_from_empty.sh b/tests/gnu/files0_from_empty.sh
index 85eee8f..7b42772 100644
--- a/tests/gnu/files0_from_empty.sh
+++ b/tests/gnu/files0_from_empty.sh
@@ -1 +1 @@
-! printf "\0" | invoke_bfs -files0-from -
+! printf '\0' | invoke_bfs -files0-from -
diff --git a/tests/gnu/files0_from_file.out b/tests/gnu/files0_from_file.out
index 1d87e6b..0f6b00d 100644
--- a/tests/gnu/files0_from_file.out
+++ b/tests/gnu/files0_from_file.out
@@ -1,3 +1,7 @@
+
+
+
+
/j
/j
@@ -16,6 +20,9 @@
)
)/g
)/g
+*
+*/m
+*/m
,
,/f
,/f
@@ -25,9 +32,14 @@
...
.../h
.../h
+/n
+/n
[
[/k
[/k
\
\/i
\/i
+{
+{/l
+{/l
diff --git a/tests/gnu/files0_from_file.sh b/tests/gnu/files0_from_file.sh
index 089a20e..81435a0 100644
--- a/tests/gnu/files0_from_file.sh
+++ b/tests/gnu/files0_from_file.sh
@@ -1,4 +1,4 @@
-clean_scratch
+FILE="$TMP/$TEST.in"
cd weirdnames
-invoke_bfs -mindepth 1 -fprintf ../scratch/files0.in "%P\0"
-bfs_diff -files0-from ../scratch/files0.in
+invoke_bfs -mindepth 1 -fprintf "$FILE" "%P\0"
+bfs_diff -files0-from "$FILE"
diff --git a/tests/gnu/files0_from_file_file.out b/tests/gnu/files0_from_file_file.out
new file mode 100644
index 0000000..fb683c7
--- /dev/null
+++ b/tests/gnu/files0_from_file_file.out
@@ -0,0 +1,2 @@
+basic/g
+basic/g/h
diff --git a/tests/gnu/files0_from_file_file.sh b/tests/gnu/files0_from_file_file.sh
new file mode 100644
index 0000000..1119952
--- /dev/null
+++ b/tests/gnu/files0_from_file_file.sh
@@ -0,0 +1,3 @@
+printf 'basic/c\0' >"$TEST/in1"
+printf 'basic/g\0' >"$TEST/in2"
+bfs_diff -files0-from "$TEST/in1" -files0-from "$TEST/in2"
diff --git a/tests/gnu/files0_from_ok.sh b/tests/gnu/files0_from_ok.sh
deleted file mode 100644
index 8e145ce..0000000
--- a/tests/gnu/files0_from_ok.sh
+++ /dev/null
@@ -1 +0,0 @@
-! printf "basic\0" | invoke_bfs -files0-from - -ok echo {} \;
diff --git a/tests/gnu/files0_from_stdin.out b/tests/gnu/files0_from_stdin.out
index 1d87e6b..0f6b00d 100644
--- a/tests/gnu/files0_from_stdin.out
+++ b/tests/gnu/files0_from_stdin.out
@@ -1,3 +1,7 @@
+
+
+
+
/j
/j
@@ -16,6 +20,9 @@
)
)/g
)/g
+*
+*/m
+*/m
,
,/f
,/f
@@ -25,9 +32,14 @@
...
.../h
.../h
+/n
+/n
[
[/k
[/k
\
\/i
\/i
+{
+{/l
+{/l
diff --git a/tests/gnu/files0_from_stdin_ok.sh b/tests/gnu/files0_from_stdin_ok.sh
new file mode 100644
index 0000000..0283c8d
--- /dev/null
+++ b/tests/gnu/files0_from_stdin_ok.sh
@@ -0,0 +1 @@
+! printf 'basic\0' | invoke_bfs -files0-from - -ok echo {} \;
diff --git a/tests/gnu/files0_from_stdin_ok_file.out b/tests/gnu/files0_from_stdin_ok_file.out
new file mode 100644
index 0000000..0f6b00d
--- /dev/null
+++ b/tests/gnu/files0_from_stdin_ok_file.out
@@ -0,0 +1,45 @@
+
+
+
+
+
+ /j
+ /j
+!
+!-
+!-/e
+!-/e
+!/d
+!/d
+(
+(-
+(-/c
+(-/c
+(/b
+(/b
+)
+)/g
+)/g
+*
+*/m
+*/m
+,
+,/f
+,/f
+-
+-/a
+-/a
+...
+.../h
+.../h
+/n
+/n
+[
+[/k
+[/k
+\
+\/i
+\/i
+{
+{/l
+{/l
diff --git a/tests/gnu/files0_from_stdin_ok_file.sh b/tests/gnu/files0_from_stdin_ok_file.sh
new file mode 100644
index 0000000..028df0c
--- /dev/null
+++ b/tests/gnu/files0_from_stdin_ok_file.sh
@@ -0,0 +1,4 @@
+FILE="$TMP/$TEST.in"
+cd weirdnames
+invoke_bfs -mindepth 1 -fprintf "$FILE" "%P\0"
+yes | bfs_diff -files0-from - -ok printf '%s\n' {} \; -files0-from "$FILE"
diff --git a/tests/gnu/files0_from_stdin_stdin.out b/tests/gnu/files0_from_stdin_stdin.out
new file mode 100644
index 0000000..0f6b00d
--- /dev/null
+++ b/tests/gnu/files0_from_stdin_stdin.out
@@ -0,0 +1,45 @@
+
+
+
+
+
+ /j
+ /j
+!
+!-
+!-/e
+!-/e
+!/d
+!/d
+(
+(-
+(-/c
+(-/c
+(/b
+(/b
+)
+)/g
+)/g
+*
+*/m
+*/m
+,
+,/f
+,/f
+-
+-/a
+-/a
+...
+.../h
+.../h
+/n
+/n
+[
+[/k
+[/k
+\
+\/i
+\/i
+{
+{/l
+{/l
diff --git a/tests/gnu/files0_from_stdin_stdin.sh b/tests/gnu/files0_from_stdin_stdin.sh
new file mode 100644
index 0000000..8f6368f
--- /dev/null
+++ b/tests/gnu/files0_from_stdin_stdin.sh
@@ -0,0 +1,2 @@
+cd weirdnames
+invoke_bfs -mindepth 1 -printf "%P\0" | bfs_diff -files0-from - -files0-from -
diff --git a/tests/gnu/fls.sh b/tests/gnu/fls.sh
index a86fa20..d2ff794 100644
--- a/tests/gnu/fls.sh
+++ b/tests/gnu/fls.sh
@@ -1,2 +1 @@
-clean_scratch
-invoke_bfs rainbow -fls scratch/fls.out
+invoke_bfs rainbow -fls "$OUT"
diff --git a/tests/gnu/fls_nonexistent.sh b/tests/gnu/fls_nonexistent.sh
index ff86763..2854569 100644
--- a/tests/gnu/fls_nonexistent.sh
+++ b/tests/gnu/fls_nonexistent.sh
@@ -1 +1 @@
-! invoke_bfs rainbow -fls scratch/nonexistent/path
+! invoke_bfs rainbow -fls nonexistent/path
diff --git a/tests/gnu/fls_overflow.sh b/tests/gnu/fls_overflow.sh
new file mode 100644
index 0000000..067bc86
--- /dev/null
+++ b/tests/gnu/fls_overflow.sh
@@ -0,0 +1,4 @@
+# Regression test: times that overflow localtime() should still print
+cd "$TEST"
+"$XTOUCH" -t "@1111111111111111111" overflow || skip
+invoke_bfs . -fls "$OUT"
diff --git a/tests/gnu/follow_comma.out b/tests/gnu/follow_comma.out
index 920b3d3..5e4b806 100644
--- a/tests/gnu/follow_comma.out
+++ b/tests/gnu/follow_comma.out
@@ -1,4 +1,7 @@
+
.
+./
+./
./
./ /j
./!
@@ -11,6 +14,8 @@
./(/b
./)
./)/g
+./*
+./*/m
./,
./,/f
./-
@@ -21,3 +26,6 @@
./[/k
./\
./\/i
+./{
+./{/l
+/n
diff --git a/tests/gnu/follow_files0_from.out b/tests/gnu/follow_files0_from.out
new file mode 100644
index 0000000..c77d546
--- /dev/null
+++ b/tests/gnu/follow_files0_from.out
@@ -0,0 +1,42 @@
+links
+links/broken
+links/broken
+links/deeply
+links/deeply
+links/deeply/nested
+links/deeply/nested
+links/deeply/nested
+links/deeply/nested/broken
+links/deeply/nested/broken
+links/deeply/nested/broken
+links/deeply/nested/broken
+links/deeply/nested/dir
+links/deeply/nested/dir
+links/deeply/nested/dir
+links/deeply/nested/dir
+links/deeply/nested/file
+links/deeply/nested/file
+links/deeply/nested/file
+links/deeply/nested/file
+links/deeply/nested/link
+links/deeply/nested/link
+links/deeply/nested/link
+links/deeply/nested/link
+links/file
+links/file
+links/hardlink
+links/hardlink
+links/notdir
+links/notdir
+links/skip
+links/skip
+links/skip/broken
+links/skip/broken
+links/skip/dir
+links/skip/dir
+links/skip/file
+links/skip/file
+links/skip/link
+links/skip/link
+links/symlink
+links/symlink
diff --git a/tests/gnu/follow_files0_from.sh b/tests/gnu/follow_files0_from.sh
new file mode 100644
index 0000000..8c20f6d
--- /dev/null
+++ b/tests/gnu/follow_files0_from.sh
@@ -0,0 +1 @@
+invoke_bfs links -print0 | bfs_diff -follow -files0-from -
diff --git a/tests/gnu/fprint0_nonexistent.sh b/tests/gnu/fprint0_nonexistent.sh
index ec14c2d..4906081 100644
--- a/tests/gnu/fprint0_nonexistent.sh
+++ b/tests/gnu/fprint0_nonexistent.sh
@@ -1 +1 @@
-! invoke_bfs basic -fprint0 scratch/nonexistent/path
+! invoke_bfs basic -fprint0 nonexistent/path
diff --git a/tests/gnu/fprint_duplicate.sh b/tests/gnu/fprint_duplicate.sh
index 5275502..8533b05 100644
--- a/tests/gnu/fprint_duplicate.sh
+++ b/tests/gnu/fprint_duplicate.sh
@@ -1,7 +1,7 @@
-"$XTOUCH" -p scratch/foo.out
-ln scratch/foo.out scratch/foo.hard
-ln -s foo.out scratch/foo.soft
+"$XTOUCH" -p "$TEST/foo.out"
+ln "$TEST/foo.out" "$TEST/foo.hard"
+ln -s foo.out "$TEST/foo.soft"
-invoke_bfs basic -fprint scratch/foo.out -fprint scratch/foo.hard -fprint scratch/foo.soft
-sort scratch/foo.out >"$OUT"
+invoke_bfs basic -fprint "$TEST/foo.out" -fprint "$TEST/foo.hard" -fprint "$TEST/foo.soft"
+sort "$TEST/foo.out" >"$OUT"
diff_output
diff --git a/tests/gnu/fprint_nonexistent.sh b/tests/gnu/fprint_nonexistent.sh
index 4409162..2a403a2 100644
--- a/tests/gnu/fprint_nonexistent.sh
+++ b/tests/gnu/fprint_nonexistent.sh
@@ -1 +1 @@
-! invoke_bfs basic -fprint scratch/nonexistent/path
+! invoke_bfs basic -fprint nonexistent/path
diff --git a/tests/gnu/fprint_noerror.sh b/tests/gnu/fprint_unreached_error.sh
index f13a62b..f13a62b 100644
--- a/tests/gnu/fprint_noerror.sh
+++ b/tests/gnu/fprint_unreached_error.sh
diff --git a/tests/gnu/fprintf_nonexistent.sh b/tests/gnu/fprintf_nonexistent.sh
index 160e739..b1eea10 100644
--- a/tests/gnu/fprintf_nonexistent.sh
+++ b/tests/gnu/fprintf_nonexistent.sh
@@ -1 +1 @@
-! invoke_bfs basic -fprintf scratch/nonexistent/path '%p\n'
+! invoke_bfs basic -fprintf nonexistent/path '%p\n'
diff --git a/tests/gnu/fstype_btrfs_subvol.out b/tests/gnu/fstype_btrfs_subvol.out
new file mode 100644
index 0000000..8871fb9
--- /dev/null
+++ b/tests/gnu/fstype_btrfs_subvol.out
@@ -0,0 +1,4 @@
+mnt
+mnt/file
+mnt/subvol
+mnt/subvol/file
diff --git a/tests/gnu/fstype_btrfs_subvol.sh b/tests/gnu/fstype_btrfs_subvol.sh
new file mode 100644
index 0000000..71df45c
--- /dev/null
+++ b/tests/gnu/fstype_btrfs_subvol.sh
@@ -0,0 +1,25 @@
+# Test that -fstype works in btrfs subvolumes
+
+command -v btrfs &>/dev/null || skip
+
+cd "$TEST"
+
+# Make a btrfs filesystem image
+truncate -s128M img
+mkfs.btrfs img >&2
+
+# Mount it
+mkdir mnt
+bfs_sudo mount img mnt || skip
+defer bfs_sudo umount mnt
+
+# Make it owned by us
+bfs_sudo chown "$(id -u):$(id -g)" mnt
+
+# Create a subvolume inside it
+btrfs subvolume create mnt/subvol >&2
+
+# Make a file in and outside the subvolume
+"$XTOUCH" mnt/file mnt/subvol/file
+
+bfs_diff mnt -fstype btrfs -print -o -printf '%p %F\n'
diff --git a/tests/gnu/fstype_stacked.out b/tests/gnu/fstype_stacked.out
index 99c7511..c1e0e6c 100644
--- a/tests/gnu/fstype_stacked.out
+++ b/tests/gnu/fstype_stacked.out
@@ -1 +1 @@
-scratch/mnt
+mnt
diff --git a/tests/gnu/fstype_stacked.sh b/tests/gnu/fstype_stacked.sh
index 16f428f..a9739bb 100644
--- a/tests/gnu/fstype_stacked.sh
+++ b/tests/gnu/fstype_stacked.sh
@@ -1,12 +1,12 @@
test "$UNAME" = "Linux" || skip
-clean_scratch
-mkdir scratch/mnt
+cd "$TEST"
+mkdir mnt
-bfs_sudo mount -t tmpfs tmpfs scratch/mnt || skip
-trap "bfs_sudo umount scratch/mnt" EXIT
+bfs_sudo mount -t tmpfs tmpfs mnt || skip
+defer bfs_sudo umount mnt
-bfs_sudo mount -t ramfs ramfs scratch/mnt || skip
-trap "bfs_sudo umount scratch/mnt; bfs_sudo umount scratch/mnt" EXIT
+bfs_sudo mount -t ramfs ramfs mnt || skip
+defer bfs_sudo umount mnt
-bfs_diff scratch/mnt -fstype ramfs -print -o -printf '%p: %F\n'
+bfs_diff mnt -fstype ramfs -print -o -printf '%p: %F\n'
diff --git a/tests/gnu/fstype_umount.sh b/tests/gnu/fstype_umount.sh
index e817831..81c195f 100644
--- a/tests/gnu/fstype_umount.sh
+++ b/tests/gnu/fstype_umount.sh
@@ -1,12 +1,12 @@
test "$UNAME" = "Linux" || skip
-clean_scratch
+cd "$TEST"
-mkdir scratch/tmp
-bfs_sudo mount -t tmpfs tmpfs scratch/tmp || skip
-trap "bfs_sudo umount -R scratch/tmp" EXIT
+mkdir tmp
+bfs_sudo mount -t tmpfs tmpfs tmp || skip
+defer bfs_sudo umount -R tmp
-mkdir scratch/tmp/ram
-bfs_sudo mount -t ramfs ramfs scratch/tmp/ram || skip
+mkdir tmp/ram
+bfs_sudo mount -t ramfs ramfs tmp/ram || skip
-bfs_diff scratch/tmp -path scratch/tmp -exec "${SUDO[@]}" umount scratch/tmp/ram \; , -fstype ramfs -print
+bfs_diff tmp -path tmp -exec "${SUDO[@]}" umount tmp/ram \; , -fstype ramfs -print
diff --git a/tests/gnu/gid.sh b/tests/gnu/gid.sh
deleted file mode 100644
index 2707b4a..0000000
--- a/tests/gnu/gid.sh
+++ /dev/null
@@ -1 +0,0 @@
-bfs_diff basic -gid "$(id -g)"
diff --git a/tests/gnu/gid_minus.out b/tests/gnu/gid_minus.out
deleted file mode 100644
index a7ccfe4..0000000
--- a/tests/gnu/gid_minus.out
+++ /dev/null
@@ -1,19 +0,0 @@
-basic
-basic/a
-basic/b
-basic/c
-basic/c/d
-basic/e
-basic/e/f
-basic/g
-basic/g/h
-basic/i
-basic/j
-basic/j/foo
-basic/k
-basic/k/foo
-basic/k/foo/bar
-basic/l
-basic/l/foo
-basic/l/foo/bar
-basic/l/foo/bar/baz
diff --git a/tests/gnu/gid_minus.sh b/tests/gnu/gid_minus.sh
deleted file mode 100644
index e3822f0..0000000
--- a/tests/gnu/gid_minus.sh
+++ /dev/null
@@ -1 +0,0 @@
-bfs_diff basic -gid "-$(($(id -g) + 1))"
diff --git a/tests/gnu/gid_minus_plus.out b/tests/gnu/gid_minus_plus.out
deleted file mode 100644
index a7ccfe4..0000000
--- a/tests/gnu/gid_minus_plus.out
+++ /dev/null
@@ -1,19 +0,0 @@
-basic
-basic/a
-basic/b
-basic/c
-basic/c/d
-basic/e
-basic/e/f
-basic/g
-basic/g/h
-basic/i
-basic/j
-basic/j/foo
-basic/k
-basic/k/foo
-basic/k/foo/bar
-basic/l
-basic/l/foo
-basic/l/foo/bar
-basic/l/foo/bar/baz
diff --git a/tests/gnu/gid_minus_plus.sh b/tests/gnu/gid_minus_plus.sh
deleted file mode 100644
index 4ff0877..0000000
--- a/tests/gnu/gid_minus_plus.sh
+++ /dev/null
@@ -1 +0,0 @@
-bfs_diff basic -gid "-+$(($(id -g) + 1))"
diff --git a/tests/gnu/gid_plus.out b/tests/gnu/gid_plus.out
deleted file mode 100644
index a7ccfe4..0000000
--- a/tests/gnu/gid_plus.out
+++ /dev/null
@@ -1,19 +0,0 @@
-basic
-basic/a
-basic/b
-basic/c
-basic/c/d
-basic/e
-basic/e/f
-basic/g
-basic/g/h
-basic/i
-basic/j
-basic/j/foo
-basic/k
-basic/k/foo
-basic/k/foo/bar
-basic/l
-basic/l/foo
-basic/l/foo/bar
-basic/l/foo/bar/baz
diff --git a/tests/gnu/gid_plus.sh b/tests/gnu/gid_plus.sh
deleted file mode 100644
index ccba0e6..0000000
--- a/tests/gnu/gid_plus.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-test "$(id -g)" -eq 0 && skip
-bfs_diff basic -gid +0
diff --git a/tests/gnu/gid_plus_plus.out b/tests/gnu/gid_plus_plus.out
deleted file mode 100644
index a7ccfe4..0000000
--- a/tests/gnu/gid_plus_plus.out
+++ /dev/null
@@ -1,19 +0,0 @@
-basic
-basic/a
-basic/b
-basic/c
-basic/c/d
-basic/e
-basic/e/f
-basic/g
-basic/g/h
-basic/i
-basic/j
-basic/j/foo
-basic/k
-basic/k/foo
-basic/k/foo/bar
-basic/l
-basic/l/foo
-basic/l/foo/bar
-basic/l/foo/bar/baz
diff --git a/tests/gnu/gid_plus_plus.sh b/tests/gnu/gid_plus_plus.sh
deleted file mode 100644
index ec7ae86..0000000
--- a/tests/gnu/gid_plus_plus.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-test "$(id -g)" -eq 0 && skip
-bfs_diff basic -gid ++0
diff --git a/tests/gnu/ignore_readdir_race.sh b/tests/gnu/ignore_readdir_race.sh
index 6586bcc..75165f6 100644
--- a/tests/gnu/ignore_readdir_race.sh
+++ b/tests/gnu/ignore_readdir_race.sh
@@ -1,5 +1,5 @@
-clean_scratch
-"$XTOUCH" scratch/{foo,bar}
+cd "$TEST"
+"$XTOUCH" foo bar
# -links 1 forces a stat() call, which will fail for the second file
-invoke_bfs scratch -mindepth 1 -ignore_readdir_race -links 1 -exec "$TESTS/remove-sibling.sh" {} \;
+invoke_bfs . -mindepth 1 -ignore_readdir_race -links 1 -exec "$TESTS/remove-sibling.sh" {} \;
diff --git a/tests/gnu/ignore_readdir_race_loop.out b/tests/gnu/ignore_readdir_race_loop.out
new file mode 100644
index 0000000..a514555
--- /dev/null
+++ b/tests/gnu/ignore_readdir_race_loop.out
@@ -0,0 +1,11 @@
+loops
+loops/broken
+loops/deeply
+loops/deeply/nested
+loops/deeply/nested/dir
+loops/file
+loops/notdir
+loops/skip
+loops/skip/dir
+loops/skip/loop
+loops/symlink
diff --git a/tests/gnu/ignore_readdir_race_loop.sh b/tests/gnu/ignore_readdir_race_loop.sh
new file mode 100644
index 0000000..3329169
--- /dev/null
+++ b/tests/gnu/ignore_readdir_race_loop.sh
@@ -0,0 +1,2 @@
+# Make sure -ignore_readdir_race doesn't suppress ELOOP from an actual filesystem loop
+! bfs_diff -L loops -ignore_readdir_race
diff --git a/tests/gnu/ignore_readdir_race_notdir.sh b/tests/gnu/ignore_readdir_race_notdir.sh
index 5b8b56d..12e9fe6 100644
--- a/tests/gnu/ignore_readdir_race_notdir.sh
+++ b/tests/gnu/ignore_readdir_race_notdir.sh
@@ -1,5 +1,7 @@
# Check -ignore_readdir_race handling when a directory is replaced with a file
-clean_scratch
-"$XTOUCH" -p scratch/foo/bar
+cd "$TEST"
+mkdir foo
-invoke_bfs scratch -mindepth 1 -ignore_readdir_race -execdir rm -r {} \; -execdir "$XTOUCH" {} \;
+invoke_bfs . -mindepth 1 -ignore_readdir_race \
+ -type d -execdir rmdir {} \; \
+ -execdir "$XTOUCH" {} \;
diff --git a/tests/gnu/ignore_readdir_race_rmdir.out b/tests/gnu/ignore_readdir_race_rmdir.out
new file mode 100644
index 0000000..ede8749
--- /dev/null
+++ b/tests/gnu/ignore_readdir_race_rmdir.out
@@ -0,0 +1,2 @@
+./bar
+./foo
diff --git a/tests/gnu/ignore_readdir_race_rmdir.sh b/tests/gnu/ignore_readdir_race_rmdir.sh
new file mode 100644
index 0000000..87f36a9
--- /dev/null
+++ b/tests/gnu/ignore_readdir_race_rmdir.sh
@@ -0,0 +1,5 @@
+cd "$TEST"
+"$XTOUCH" -p foo/ bar/
+
+# Check that -ignore_readdir_race suppresses errors from opendir()
+bfs_diff . -ignore_readdir_race -mindepth 1 -print -name foo -exec rmdir {} \;
diff --git a/tests/gnu/inum_automount.out b/tests/gnu/inum_automount.out
index 7b53ae3..3378e2d 100644
--- a/tests/gnu/inum_automount.out
+++ b/tests/gnu/inum_automount.out
@@ -1 +1 @@
-scratch/automnt
+./automnt
diff --git a/tests/gnu/inum_automount.sh b/tests/gnu/inum_automount.sh
index c4450ef..86b23e1 100644
--- a/tests/gnu/inum_automount.sh
+++ b/tests/gnu/inum_automount.sh
@@ -2,13 +2,13 @@
command -v systemd-mount &>/dev/null || skip
-clean_scratch
-mkdir scratch/{foo,automnt}
+cd "$TEST"
+mkdir foo automnt
-bfs_sudo systemd-mount -A -o bind basic scratch/automnt || skip
-trap "bfs_sudo systemd-umount scratch/automnt" EXIT
+bfs_sudo systemd-mount -A -o bind "$TMP/basic" automnt || skip
+defer bfs_sudo systemd-umount automnt
-before=$(inum scratch/automnt)
-bfs_diff scratch -inum "$before" -prune
-after=$(inum scratch/automnt)
+before=$(inum automnt)
+bfs_diff . -inum "$before" -prune
+after=$(inum automnt)
((before == after))
diff --git a/tests/gnu/newer_link.out b/tests/gnu/newer_link.out
new file mode 100644
index 0000000..d2dcdd1
--- /dev/null
+++ b/tests/gnu/newer_link.out
@@ -0,0 +1 @@
+times
diff --git a/tests/gnu/newer_link.sh b/tests/gnu/newer_link.sh
new file mode 100644
index 0000000..685ac78
--- /dev/null
+++ b/tests/gnu/newer_link.sh
@@ -0,0 +1 @@
+bfs_diff times -newer times/l
diff --git a/tests/gnu/gid.out b/tests/gnu/not_comma.out
index a7ccfe4..b90468e 100644
--- a/tests/gnu/gid.out
+++ b/tests/gnu/not_comma.out
@@ -1,19 +1,34 @@
basic
+basic
+basic/a
basic/a
basic/b
+basic/b
+basic/c
basic/c
basic/c/d
+basic/c/d
+basic/e
basic/e
basic/e/f
basic/g
+basic/g
+basic/g/h
basic/g/h
basic/i
+basic/i
+basic/j
basic/j
basic/j/foo
basic/k
+basic/k
basic/k/foo
basic/k/foo/bar
+basic/k/foo/bar
+basic/l
basic/l
basic/l/foo
basic/l/foo/bar
+basic/l/foo/bar
+basic/l/foo/bar/baz
basic/l/foo/bar/baz
diff --git a/tests/gnu/not_comma.sh b/tests/gnu/not_comma.sh
new file mode 100644
index 0000000..04c0195
--- /dev/null
+++ b/tests/gnu/not_comma.sh
@@ -0,0 +1,2 @@
+# Regression test: assertion failure in sink_not_comma()
+bfs_diff basic -not \( -print , -name '*f*' \) -print
diff --git a/tests/gnu/ok_files0_from_stdin.sh b/tests/gnu/ok_files0_from_stdin.sh
new file mode 100644
index 0000000..2c4de7b
--- /dev/null
+++ b/tests/gnu/ok_files0_from_stdin.sh
@@ -0,0 +1 @@
+! printf 'basic\0' | invoke_bfs -ok echo {} \; -files0-from -
diff --git a/tests/gnu/ok_flush.sh b/tests/gnu/ok_flush.sh
index 87c7298..a5dc0d0 100644
--- a/tests/gnu/ok_flush.sh
+++ b/tests/gnu/ok_flush.sh
@@ -1,4 +1,4 @@
# I/O streams should be flushed before -ok prompts
-yes | invoke_bfs basic -printf '%p ? ' -ok echo found \; 2>&1 | tr '\0' ' ' | sed 's/?.*?/?/' >"$OUT"
+yes | invoke_bfs basic -printf '%p ? ' -ok echo found \; 2>&1 | sed 's/?.*?/?/' >"$OUT"
sort_output
diff_output
diff --git a/tests/gnu/okdir_path_dot.sh b/tests/gnu/okdir_path_dot.sh
new file mode 100644
index 0000000..5b40e27
--- /dev/null
+++ b/tests/gnu/okdir_path_dot.sh
@@ -0,0 +1 @@
+! PATH=".:$PATH" invoke_bfs basic -okdir echo {} \;
diff --git a/tests/gnu/okdir_path_empty.sh b/tests/gnu/okdir_path_empty.sh
new file mode 100644
index 0000000..2669ee8
--- /dev/null
+++ b/tests/gnu/okdir_path_empty.sh
@@ -0,0 +1 @@
+! PATH=":$PATH" invoke_bfs basic -okdir echo {} \;
diff --git a/tests/gnu/okdir_path_relative.sh b/tests/gnu/okdir_path_relative.sh
new file mode 100644
index 0000000..05100a1
--- /dev/null
+++ b/tests/gnu/okdir_path_relative.sh
@@ -0,0 +1 @@
+! PATH="foo:$PATH" invoke_bfs basic -okdir echo {} \;
diff --git a/tests/gnu/perm_000_slash.out b/tests/gnu/perm_000_slash.out
index d7494b8..e279684 100644
--- a/tests/gnu/perm_000_slash.out
+++ b/tests/gnu/perm_000_slash.out
@@ -1,8 +1,29 @@
perms
-perms/0
-perms/r
-perms/rw
-perms/rwx
-perms/rx
-perms/w
-perms/wx
+perms/dr-x------
+perms/dr-xr-xr-x
+perms/drwx------
+perms/drwxr-xr-x
+perms/drwxrwxr-x
+perms/drwxrwxrwx
+perms/f---------
+perms/f--x------
+perms/f--x--x--x
+perms/f-w-------
+perms/f-w--w----
+perms/f-w--w--w-
+perms/f-wx------
+perms/f-wx--x--x
+perms/f-wx-wx--x
+perms/f-wx-wx-wx
+perms/fr--------
+perms/fr--r--r--
+perms/fr-x------
+perms/fr-xr-xr-x
+perms/frw-------
+perms/frw-r--r--
+perms/frw-rw-r--
+perms/frw-rw-rw-
+perms/frwxr-----
+perms/frwxr-xr-x
+perms/frwxrwxr-x
+perms/frwxrwxrwx
diff --git a/tests/gnu/perm_222_slash.out b/tests/gnu/perm_222_slash.out
index 9a5b95a..1b6d885 100644
--- a/tests/gnu/perm_222_slash.out
+++ b/tests/gnu/perm_222_slash.out
@@ -1,5 +1,20 @@
perms
-perms/rw
-perms/rwx
-perms/w
-perms/wx
+perms/drwx------
+perms/drwxr-xr-x
+perms/drwxrwxr-x
+perms/drwxrwxrwx
+perms/f-w-------
+perms/f-w--w----
+perms/f-w--w--w-
+perms/f-wx------
+perms/f-wx--x--x
+perms/f-wx-wx--x
+perms/f-wx-wx-wx
+perms/frw-------
+perms/frw-r--r--
+perms/frw-rw-r--
+perms/frw-rw-rw-
+perms/frwxr-----
+perms/frwxr-xr-x
+perms/frwxrwxr-x
+perms/frwxrwxrwx
diff --git a/tests/gnu/perm_644_slash.out b/tests/gnu/perm_644_slash.out
index 7e5ae98..eef88ca 100644
--- a/tests/gnu/perm_644_slash.out
+++ b/tests/gnu/perm_644_slash.out
@@ -1,7 +1,26 @@
perms
-perms/r
-perms/rw
-perms/rwx
-perms/rx
-perms/w
-perms/wx
+perms/dr-x------
+perms/dr-xr-xr-x
+perms/drwx------
+perms/drwxr-xr-x
+perms/drwxrwxr-x
+perms/drwxrwxrwx
+perms/f-w-------
+perms/f-w--w----
+perms/f-w--w--w-
+perms/f-wx------
+perms/f-wx--x--x
+perms/f-wx-wx--x
+perms/f-wx-wx-wx
+perms/fr--------
+perms/fr--r--r--
+perms/fr-x------
+perms/fr-xr-xr-x
+perms/frw-------
+perms/frw-r--r--
+perms/frw-rw-r--
+perms/frw-rw-rw-
+perms/frwxr-----
+perms/frwxr-xr-x
+perms/frwxrwxr-x
+perms/frwxrwxrwx
diff --git a/tests/gnu/perm_leading_plus_symbolic_slash.out b/tests/gnu/perm_leading_plus_symbolic_slash.out
index 7e5ae98..fcbf49e 100644
--- a/tests/gnu/perm_leading_plus_symbolic_slash.out
+++ b/tests/gnu/perm_leading_plus_symbolic_slash.out
@@ -1,7 +1,28 @@
perms
-perms/r
-perms/rw
-perms/rwx
-perms/rx
-perms/w
-perms/wx
+perms/dr-x------
+perms/dr-xr-xr-x
+perms/drwx------
+perms/drwxr-xr-x
+perms/drwxrwxr-x
+perms/drwxrwxrwx
+perms/f--x------
+perms/f--x--x--x
+perms/f-w-------
+perms/f-w--w----
+perms/f-w--w--w-
+perms/f-wx------
+perms/f-wx--x--x
+perms/f-wx-wx--x
+perms/f-wx-wx-wx
+perms/fr--------
+perms/fr--r--r--
+perms/fr-x------
+perms/fr-xr-xr-x
+perms/frw-------
+perms/frw-r--r--
+perms/frw-rw-r--
+perms/frw-rw-rw-
+perms/frwxr-----
+perms/frwxr-xr-x
+perms/frwxrwxr-x
+perms/frwxrwxrwx
diff --git a/tests/gnu/perm_symbolic_slash.out b/tests/gnu/perm_symbolic_slash.out
index 7e5ae98..5a21321 100644
--- a/tests/gnu/perm_symbolic_slash.out
+++ b/tests/gnu/perm_symbolic_slash.out
@@ -1,7 +1,24 @@
perms
-perms/r
-perms/rw
-perms/rwx
-perms/rx
-perms/w
-perms/wx
+perms/dr-x------
+perms/dr-xr-xr-x
+perms/drwx------
+perms/drwxr-xr-x
+perms/drwxrwxr-x
+perms/drwxrwxrwx
+perms/f-w-------
+perms/f-w--w----
+perms/f-w--w--w-
+perms/f-wx------
+perms/f-wx--x--x
+perms/f-wx-wx--x
+perms/f-wx-wx-wx
+perms/fr--r--r--
+perms/fr-xr-xr-x
+perms/frw-------
+perms/frw-r--r--
+perms/frw-rw-r--
+perms/frw-rw-rw-
+perms/frwxr-----
+perms/frwxr-xr-x
+perms/frwxrwxr-x
+perms/frwxrwxrwx
diff --git a/tests/gnu/print0.out b/tests/gnu/print0.out
deleted file mode 100644
index 1347444..0000000
--- a/tests/gnu/print0.out
+++ /dev/null
Binary files differ
diff --git a/tests/gnu/print0.sh b/tests/gnu/print0.sh
deleted file mode 100644
index b916172..0000000
--- a/tests/gnu/print0.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-invoke_bfs basic/a basic/b -print0 >"$OUT"
-diff_output
diff --git a/tests/gnu/printf_Y_error.out b/tests/gnu/printf_Y_error.out
index 410a9b5..1dd554e 100644
--- a/tests/gnu/printf_Y_error.out
+++ b/tests/gnu/printf_Y_error.out
@@ -1,3 +1,3 @@
-(scratch) () d d
-(scratch/bar) (foo/bar) l ?
-(scratch/foo) () d d
+(.) () d d
+(./bar) (foo/bar) l ?
+(./foo) () d d
diff --git a/tests/gnu/printf_Y_error.sh b/tests/gnu/printf_Y_error.sh
index 3aa816e..d3130ce 100644
--- a/tests/gnu/printf_Y_error.sh
+++ b/tests/gnu/printf_Y_error.sh
@@ -1,8 +1,8 @@
-clean_scratch
-mkdir scratch/foo
-ln -s foo/bar scratch/bar
+cd "$TEST"
+mkdir foo
+ln -s foo/bar bar
-chmod -x scratch/foo
-trap "chmod +x scratch/foo" EXIT
+chmod -x foo
+defer chmod +x foo
-! bfs_diff scratch -printf '(%p) (%l) %y %Y\n'
+! bfs_diff . -printf '(%p) (%l) %y %Y\n'
diff --git a/tests/gnu/printf_flags.sh b/tests/gnu/printf_flags.sh
index 2ef37ad..98e8faa 100644
--- a/tests/gnu/printf_flags.sh
+++ b/tests/gnu/printf_flags.sh
@@ -1 +1 @@
-bfs_diff basic -printf '|%- 10.10p| %+03d %#4m\n'
+bfs_diff basic -printf '|%-10.10p| %+03d % #4m\n'
diff --git a/tests/gnu/printf_u_g_ulimit.sh b/tests/gnu/printf_u_g_ulimit.sh
index a84ee29..c621b9b 100644
--- a/tests/gnu/printf_u_g_ulimit.sh
+++ b/tests/gnu/printf_u_g_ulimit.sh
@@ -1,3 +1,2 @@
-closefrom 4
-ulimit -n 16
+ulimit -n $((NOPENFD + 13))
[ "$(invoke_bfs deep -printf '%u %g\n' | uniq)" = "$(id -un) $(id -gn)" ]
diff --git a/tests/gnu/readable.out b/tests/gnu/readable.out
index 386feba..56d1f52 100644
--- a/tests/gnu/readable.out
+++ b/tests/gnu/readable.out
@@ -1,5 +1,19 @@
perms
-perms/r
-perms/rw
-perms/rwx
-perms/rx
+perms/dr-x------
+perms/dr-xr-xr-x
+perms/drwx------
+perms/drwxr-xr-x
+perms/drwxrwxr-x
+perms/drwxrwxrwx
+perms/fr--------
+perms/fr--r--r--
+perms/fr-x------
+perms/fr-xr-xr-x
+perms/frw-------
+perms/frw-r--r--
+perms/frw-rw-r--
+perms/frw-rw-rw-
+perms/frwxr-----
+perms/frwxr-xr-x
+perms/frwxrwxr-x
+perms/frwxrwxrwx
diff --git a/tests/gnu/regex_invalid_utf8.out b/tests/gnu/regex_invalid_utf8.out
index 03f3f58..a133b1a 100644
--- a/tests/gnu/regex_invalid_utf8.out
+++ b/tests/gnu/regex_invalid_utf8.out
@@ -1 +1 @@
-scratch/â„
+./â„
diff --git a/tests/gnu/regex_invalid_utf8.sh b/tests/gnu/regex_invalid_utf8.sh
index 603d688..7006dcd 100644
--- a/tests/gnu/regex_invalid_utf8.sh
+++ b/tests/gnu/regex_invalid_utf8.sh
@@ -1,8 +1,8 @@
-clean_scratch
+cd "$TEST"
# Incomplete UTF-8 sequences
-touch scratch/$'\xC3' || skip
-touch scratch/$'\xE2\x84' || skip
-touch scratch/$'\xF0\x9F\x92' || skip
+touch $'\xC3' || skip
+touch $'\xE2\x84' || skip
+touch $'\xF0\x9F\x92' || skip
-bfs_diff scratch -regex 'scratch/..'
+bfs_diff . -regex '\./..'
diff --git a/tests/gnu/regextype_awk.out b/tests/gnu/regextype_awk.out
new file mode 100644
index 0000000..0f32fc4
--- /dev/null
+++ b/tests/gnu/regextype_awk.out
@@ -0,0 +1,2 @@
+weirdnames/*/m
+weirdnames/[/k
diff --git a/tests/gnu/regextype_awk.sh b/tests/gnu/regextype_awk.sh
new file mode 100644
index 0000000..3718473
--- /dev/null
+++ b/tests/gnu/regextype_awk.sh
@@ -0,0 +1,3 @@
+invoke_bfs -regextype awk -quit || skip
+
+bfs_diff weirdnames -regextype awk -regex '.*/[\[\*]/.*'
diff --git a/tests/gnu/regextype_egrep.out b/tests/gnu/regextype_egrep.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/gnu/regextype_egrep.out
diff --git a/tests/gnu/regextype_egrep.sh b/tests/gnu/regextype_egrep.sh
new file mode 100644
index 0000000..281d9c0
--- /dev/null
+++ b/tests/gnu/regextype_egrep.sh
@@ -0,0 +1,3 @@
+invoke_bfs -regextype egrep -quit || skip
+
+bfs_diff weirdnames -regextype egrep -regex '*.*/{l'
diff --git a/tests/gnu/regextype_emacs.sh b/tests/gnu/regextype_emacs.sh
index 3cc388c..164d17a 100644
--- a/tests/gnu/regextype_emacs.sh
+++ b/tests/gnu/regextype_emacs.sh
@@ -1,3 +1,3 @@
invoke_bfs -regextype emacs -quit || skip
-bfs_diff basic -regextype emacs -regex '.*/\(f+o?o?\|bar\)'
+bfs_diff basic -regextype emacs -regex '.*/\(?:f+o?o?\|bar\)'
diff --git a/tests/gnu/regextype_findutils_default.out b/tests/gnu/regextype_findutils_default.out
new file mode 100644
index 0000000..709a7ba
--- /dev/null
+++ b/tests/gnu/regextype_findutils_default.out
@@ -0,0 +1,3 @@
+/n
+weirdnames/
+weirdnames/*/m
diff --git a/tests/gnu/regextype_findutils_default.sh b/tests/gnu/regextype_findutils_default.sh
new file mode 100644
index 0000000..c870312
--- /dev/null
+++ b/tests/gnu/regextype_findutils_default.sh
@@ -0,0 +1,3 @@
+invoke_bfs -regextype findutils-default -quit || skip
+
+bfs_diff weirdnames -regextype findutils-default -regex '.*/./\(m\|n\)'
diff --git a/tests/gnu/regextype_gnu_awk.out b/tests/gnu/regextype_gnu_awk.out
new file mode 100644
index 0000000..0f32fc4
--- /dev/null
+++ b/tests/gnu/regextype_gnu_awk.out
@@ -0,0 +1,2 @@
+weirdnames/*/m
+weirdnames/[/k
diff --git a/tests/gnu/regextype_gnu_awk.sh b/tests/gnu/regextype_gnu_awk.sh
new file mode 100644
index 0000000..6b66496
--- /dev/null
+++ b/tests/gnu/regextype_gnu_awk.sh
@@ -0,0 +1,3 @@
+invoke_bfs -regextype gnu-awk -quit || skip
+
+bfs_diff weirdnames -regextype gnu-awk -regex '.*/[\[\*]/(\<.\>)'
diff --git a/tests/gnu/regextype_posix_awk.out b/tests/gnu/regextype_posix_awk.out
new file mode 100644
index 0000000..0f32fc4
--- /dev/null
+++ b/tests/gnu/regextype_posix_awk.out
@@ -0,0 +1,2 @@
+weirdnames/*/m
+weirdnames/[/k
diff --git a/tests/gnu/regextype_posix_awk.sh b/tests/gnu/regextype_posix_awk.sh
new file mode 100644
index 0000000..86377d7
--- /dev/null
+++ b/tests/gnu/regextype_posix_awk.sh
@@ -0,0 +1,3 @@
+invoke_bfs -regextype posix-awk -quit || skip
+
+bfs_diff weirdnames -regextype posix-awk -regex '.*/[\[\*]/.*'
diff --git a/tests/gnu/regextype_posix_minimal_basic.out b/tests/gnu/regextype_posix_minimal_basic.out
new file mode 100644
index 0000000..0f0971e
--- /dev/null
+++ b/tests/gnu/regextype_posix_minimal_basic.out
@@ -0,0 +1 @@
+./(
diff --git a/tests/gnu/regextype_posix_minimal_basic.sh b/tests/gnu/regextype_posix_minimal_basic.sh
new file mode 100644
index 0000000..ee324f3
--- /dev/null
+++ b/tests/gnu/regextype_posix_minimal_basic.sh
@@ -0,0 +1,2 @@
+cd weirdnames
+bfs_diff -regextype posix-minimal-basic -regex '\./\((\)'
diff --git a/tests/gnu/uid.out b/tests/gnu/uid.out
deleted file mode 100644
index a7ccfe4..0000000
--- a/tests/gnu/uid.out
+++ /dev/null
@@ -1,19 +0,0 @@
-basic
-basic/a
-basic/b
-basic/c
-basic/c/d
-basic/e
-basic/e/f
-basic/g
-basic/g/h
-basic/i
-basic/j
-basic/j/foo
-basic/k
-basic/k/foo
-basic/k/foo/bar
-basic/l
-basic/l/foo
-basic/l/foo/bar
-basic/l/foo/bar/baz
diff --git a/tests/gnu/uid.sh b/tests/gnu/uid.sh
deleted file mode 100644
index fb3cd93..0000000
--- a/tests/gnu/uid.sh
+++ /dev/null
@@ -1 +0,0 @@
-bfs_diff basic -uid "$(id -u)"
diff --git a/tests/gnu/uid_minus.out b/tests/gnu/uid_minus.out
deleted file mode 100644
index a7ccfe4..0000000
--- a/tests/gnu/uid_minus.out
+++ /dev/null
@@ -1,19 +0,0 @@
-basic
-basic/a
-basic/b
-basic/c
-basic/c/d
-basic/e
-basic/e/f
-basic/g
-basic/g/h
-basic/i
-basic/j
-basic/j/foo
-basic/k
-basic/k/foo
-basic/k/foo/bar
-basic/l
-basic/l/foo
-basic/l/foo/bar
-basic/l/foo/bar/baz
diff --git a/tests/gnu/uid_minus.sh b/tests/gnu/uid_minus.sh
deleted file mode 100644
index 6d371f2..0000000
--- a/tests/gnu/uid_minus.sh
+++ /dev/null
@@ -1 +0,0 @@
-bfs_diff basic -uid "-$(($(id -u) + 1))"
diff --git a/tests/gnu/uid_minus_plus.out b/tests/gnu/uid_minus_plus.out
deleted file mode 100644
index a7ccfe4..0000000
--- a/tests/gnu/uid_minus_plus.out
+++ /dev/null
@@ -1,19 +0,0 @@
-basic
-basic/a
-basic/b
-basic/c
-basic/c/d
-basic/e
-basic/e/f
-basic/g
-basic/g/h
-basic/i
-basic/j
-basic/j/foo
-basic/k
-basic/k/foo
-basic/k/foo/bar
-basic/l
-basic/l/foo
-basic/l/foo/bar
-basic/l/foo/bar/baz
diff --git a/tests/gnu/uid_minus_plus.sh b/tests/gnu/uid_minus_plus.sh
deleted file mode 100644
index e7a0496..0000000
--- a/tests/gnu/uid_minus_plus.sh
+++ /dev/null
@@ -1 +0,0 @@
-bfs_diff basic -uid "-+$(($(id -u) + 1))"
diff --git a/tests/gnu/uid_plus.out b/tests/gnu/uid_plus.out
deleted file mode 100644
index a7ccfe4..0000000
--- a/tests/gnu/uid_plus.out
+++ /dev/null
@@ -1,19 +0,0 @@
-basic
-basic/a
-basic/b
-basic/c
-basic/c/d
-basic/e
-basic/e/f
-basic/g
-basic/g/h
-basic/i
-basic/j
-basic/j/foo
-basic/k
-basic/k/foo
-basic/k/foo/bar
-basic/l
-basic/l/foo
-basic/l/foo/bar
-basic/l/foo/bar/baz
diff --git a/tests/gnu/uid_plus.sh b/tests/gnu/uid_plus.sh
deleted file mode 100644
index 22b2c8e..0000000
--- a/tests/gnu/uid_plus.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-test "$(id -u)" -eq 0 && skip
-bfs_diff basic -uid +0
diff --git a/tests/gnu/uid_plus_plus.out b/tests/gnu/uid_plus_plus.out
deleted file mode 100644
index a7ccfe4..0000000
--- a/tests/gnu/uid_plus_plus.out
+++ /dev/null
@@ -1,19 +0,0 @@
-basic
-basic/a
-basic/b
-basic/c
-basic/c/d
-basic/e
-basic/e/f
-basic/g
-basic/g/h
-basic/i
-basic/j
-basic/j/foo
-basic/k
-basic/k/foo
-basic/k/foo/bar
-basic/l
-basic/l/foo
-basic/l/foo/bar
-basic/l/foo/bar/baz
diff --git a/tests/gnu/uid_plus_plus.sh b/tests/gnu/uid_plus_plus.sh
deleted file mode 100644
index e021888..0000000
--- a/tests/gnu/uid_plus_plus.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-test "$(id -u)" -eq 0 && skip
-bfs_diff basic -uid ++0
diff --git a/tests/gnu/used.out b/tests/gnu/used.out
new file mode 100644
index 0000000..647621b
--- /dev/null
+++ b/tests/gnu/used.out
@@ -0,0 +1,4 @@
+-used +7: ./nextyear
+-used 1: ./tomorrow
+-used 2: ./dayafter
+-used 7: ./nextweek
diff --git a/tests/gnu/used.sh b/tests/gnu/used.sh
new file mode 100644
index 0000000..fe0a778
--- /dev/null
+++ b/tests/gnu/used.sh
@@ -0,0 +1,21 @@
+cd "$TEST"
+
+now=$(epoch_time)
+
+# -used is always false if atime < ctime
+"$XTOUCH" -at "@$((now - 60 * 60 * 24))" yesterday
+
+# -used rounds up
+"$XTOUCH" -at "@$((now + 60 * 60))" tomorrow
+
+"$XTOUCH" -at "@$((now + 60 * 60 * 25))" dayafter
+
+"$XTOUCH" -at "@$((now + 60 * 60 * (24 * 6 + 1)))" nextweek
+
+"$XTOUCH" -at "@$((now + 60 * 60 * 24 * 365))" nextyear
+
+bfs_diff -mindepth 1 \
+ -a -used 1 -printf '-used 1: %p\n' \
+ -o -used 2 -printf '-used 2: %p\n' \
+ -o -used 7 -printf '-used 7: %p\n' \
+ -o -used +7 -printf '-used +7: %p\n'
diff --git a/tests/gnu/writable.out b/tests/gnu/writable.out
index 9a5b95a..1b6d885 100644
--- a/tests/gnu/writable.out
+++ b/tests/gnu/writable.out
@@ -1,5 +1,20 @@
perms
-perms/rw
-perms/rwx
-perms/w
-perms/wx
+perms/drwx------
+perms/drwxr-xr-x
+perms/drwxrwxr-x
+perms/drwxrwxrwx
+perms/f-w-------
+perms/f-w--w----
+perms/f-w--w--w-
+perms/f-wx------
+perms/f-wx--x--x
+perms/f-wx-wx--x
+perms/f-wx-wx-wx
+perms/frw-------
+perms/frw-r--r--
+perms/frw-rw-r--
+perms/frw-rw-rw-
+perms/frwxr-----
+perms/frwxr-xr-x
+perms/frwxrwxr-x
+perms/frwxrwxrwx
diff --git a/tests/gnu/xtype_bind_mount.out b/tests/gnu/xtype_bind_mount.out
index 16804ea..d18d706 100644
--- a/tests/gnu/xtype_bind_mount.out
+++ b/tests/gnu/xtype_bind_mount.out
@@ -1,2 +1,2 @@
-scratch/link
-scratch/null
+./link
+./null
diff --git a/tests/gnu/xtype_bind_mount.sh b/tests/gnu/xtype_bind_mount.sh
index 99a11ab..35fb3f5 100644
--- a/tests/gnu/xtype_bind_mount.sh
+++ b/tests/gnu/xtype_bind_mount.sh
@@ -1,10 +1,10 @@
test "$UNAME" = "Linux" || skip
-clean_scratch
-"$XTOUCH" scratch/{file,null}
-ln -s /dev/null scratch/link
+cd "$TEST"
+"$XTOUCH" file null
+ln -s /dev/null link
-bfs_sudo mount --bind /dev/null scratch/null || skip
-trap "bfs_sudo umount scratch/null" EXIT
+bfs_sudo mount --bind /dev/null null || skip
+defer bfs_sudo umount null
-bfs_diff -L scratch -type c
+bfs_diff . -xtype c
diff --git a/tests/gnu/xtype_l_loops.out b/tests/gnu/xtype_l_loops.out
new file mode 100644
index 0000000..fdaccab
--- /dev/null
+++ b/tests/gnu/xtype_l_loops.out
@@ -0,0 +1,3 @@
+loops/broken
+loops/loop
+loops/notdir
diff --git a/tests/gnu/xtype_l_loops.sh b/tests/gnu/xtype_l_loops.sh
new file mode 100644
index 0000000..6893134
--- /dev/null
+++ b/tests/gnu/xtype_l_loops.sh
@@ -0,0 +1 @@
+bfs_diff loops -xtype l