summaryrefslogtreecommitdiffstats
path: root/tests/posix
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2022-10-19 10:29:05 -0400
committerTavian Barnes <tavianator@tavianator.com>2022-10-19 11:50:03 -0400
commit3b387d81e63893ed3fe3b45e3721fbcfb1c5dde0 (patch)
tree513c32eda43d92a8ed977f394492ba198bba1f3b /tests/posix
parente5972621ffa8864b18d3e303ac714fdbe231be74 (diff)
downloadbfs-3b387d81e63893ed3fe3b45e3721fbcfb1c5dde0.tar.xz
tests: Split test cases into separate files
Diffstat (limited to 'tests/posix')
-rw-r--r--tests/posix/H.out1
-rw-r--r--tests/posix/H.sh1
-rw-r--r--tests/posix/H_broken.out1
-rw-r--r--tests/posix/H_broken.sh1
-rw-r--r--tests/posix/H_loops.out4
-rw-r--r--tests/posix/H_loops.sh1
-rw-r--r--tests/posix/H_notdir.out1
-rw-r--r--tests/posix/H_notdir.sh1
-rw-r--r--tests/posix/H_slash.out1
-rw-r--r--tests/posix/H_slash.sh1
-rw-r--r--tests/posix/H_type_l.out2
-rw-r--r--tests/posix/H_type_l.sh1
-rw-r--r--tests/posix/L.out17
-rw-r--r--tests/posix/L.sh1
-rw-r--r--tests/posix/L_broken.out1
-rw-r--r--tests/posix/L_broken.sh1
-rw-r--r--tests/posix/L_depth.out17
-rw-r--r--tests/posix/L_depth.sh1
-rw-r--r--tests/posix/L_loops.sh4
-rw-r--r--tests/posix/L_notdir.out1
-rw-r--r--tests/posix/L_notdir.sh1
-rw-r--r--tests/posix/L_type_l.out1
-rw-r--r--tests/posix/L_type_l.sh1
-rw-r--r--tests/posix/L_xdev.out5
-rw-r--r--tests/posix/L_xdev.sh15
-rw-r--r--tests/posix/a.out2
-rw-r--r--tests/posix/a.sh1
-rw-r--r--tests/posix/bang.out16
-rw-r--r--tests/posix/bang.sh1
-rw-r--r--tests/posix/basic.out19
-rw-r--r--tests/posix/basic.sh1
-rw-r--r--tests/posix/closed_stderr.sh1
-rw-r--r--tests/posix/closed_stdin.out19
-rw-r--r--tests/posix/closed_stdin.sh1
-rw-r--r--tests/posix/closed_stdout.sh1
-rw-r--r--tests/posix/data_flow_and_swap.out12
-rw-r--r--tests/posix/data_flow_and_swap.sh1
-rw-r--r--tests/posix/data_flow_group.out19
-rw-r--r--tests/posix/data_flow_group.sh1
-rw-r--r--tests/posix/data_flow_or_swap.out12
-rw-r--r--tests/posix/data_flow_or_swap.sh1
-rw-r--r--tests/posix/data_flow_type.out0
-rw-r--r--tests/posix/data_flow_type.sh1
-rw-r--r--tests/posix/data_flow_user.out19
-rw-r--r--tests/posix/data_flow_user.sh1
-rw-r--r--tests/posix/de_morgan_and.out10
-rw-r--r--tests/posix/de_morgan_and.sh1
-rw-r--r--tests/posix/de_morgan_not.out6
-rw-r--r--tests/posix/de_morgan_not.sh1
-rw-r--r--tests/posix/de_morgan_or.out18
-rw-r--r--tests/posix/de_morgan_or.sh1
-rw-r--r--tests/posix/deep.out16
-rw-r--r--tests/posix/deep.sh4
-rw-r--r--tests/posix/depth.out19
-rw-r--r--tests/posix/depth.sh1
-rw-r--r--tests/posix/depth_error.out2
-rw-r--r--tests/posix/depth_error.sh11
-rw-r--r--tests/posix/depth_slash.out19
-rw-r--r--tests/posix/depth_slash.sh1
-rw-r--r--tests/posix/double_negation.out3
-rw-r--r--tests/posix/double_negation.sh1
-rw-r--r--tests/posix/exec.out19
-rw-r--r--tests/posix/exec.sh1
-rw-r--r--tests/posix/exec_nonexistent.out19
-rw-r--r--tests/posix/exec_nonexistent.sh8
-rw-r--r--tests/posix/exec_nopath.out19
-rw-r--r--tests/posix/exec_nopath.sh7
-rw-r--r--tests/posix/exec_plus.out1
-rw-r--r--tests/posix/exec_plus.sh1
-rw-r--r--tests/posix/exec_plus_nonexistent.out19
-rw-r--r--tests/posix/exec_plus_nonexistent.sh5
-rw-r--r--tests/posix/exec_plus_semicolon.out19
-rw-r--r--tests/posix/exec_plus_semicolon.sh5
-rw-r--r--tests/posix/exec_plus_status.out19
-rw-r--r--tests/posix/exec_plus_status.sh4
-rw-r--r--tests/posix/extra_paren.sh1
-rw-r--r--tests/posix/flag_comma.out2
-rw-r--r--tests/posix/flag_comma.sh3
-rw-r--r--tests/posix/flag_weird_names.out28
-rw-r--r--tests/posix/flag_weird_names.sh2
-rw-r--r--tests/posix/group_id.out19
-rw-r--r--tests/posix/group_id.sh1
-rw-r--r--tests/posix/group_name.out19
-rw-r--r--tests/posix/group_name.sh1
-rw-r--r--tests/posix/group_nogroup.out19
-rw-r--r--tests/posix/group_nogroup.sh2
-rw-r--r--tests/posix/implicit_and.out2
-rw-r--r--tests/posix/implicit_and.sh1
-rw-r--r--tests/posix/incomplete.sh1
-rw-r--r--tests/posix/links.out2
-rw-r--r--tests/posix/links.sh1
-rw-r--r--tests/posix/links_minus.out1
-rw-r--r--tests/posix/links_minus.sh1
-rw-r--r--tests/posix/links_plus.out2
-rw-r--r--tests/posix/links_plus.sh1
-rw-r--r--tests/posix/missing_paren.sh1
-rw-r--r--tests/posix/name.out4
-rw-r--r--tests/posix/name.sh1
-rw-r--r--tests/posix/name_backslash.out0
-rw-r--r--tests/posix/name_backslash.sh2
-rw-r--r--tests/posix/name_bracket.out1
-rw-r--r--tests/posix/name_bracket.sh5
-rw-r--r--tests/posix/name_character_class.out3
-rw-r--r--tests/posix/name_character_class.sh1
-rw-r--r--tests/posix/name_double_backslash.out1
-rw-r--r--tests/posix/name_double_backslash.sh2
-rw-r--r--tests/posix/name_root.out1
-rw-r--r--tests/posix/name_root.sh1
-rw-r--r--tests/posix/name_root_depth.out1
-rw-r--r--tests/posix/name_root_depth.sh1
-rw-r--r--tests/posix/name_star_star.out4
-rw-r--r--tests/posix/name_star_star.sh1
-rw-r--r--tests/posix/name_trailing_slash.out1
-rw-r--r--tests/posix/name_trailing_slash.sh1
-rw-r--r--tests/posix/newer.out4
-rw-r--r--tests/posix/newer.sh1
-rw-r--r--tests/posix/newer_link.out1
-rw-r--r--tests/posix/newer_link.sh1
-rw-r--r--tests/posix/nogroup.out0
-rw-r--r--tests/posix/nogroup.sh1
-rw-r--r--tests/posix/nogroup_ulimit.out0
-rw-r--r--tests/posix/nogroup_ulimit.sh3
-rw-r--r--tests/posix/not_prune.out13
-rw-r--r--tests/posix/not_prune.sh1
-rw-r--r--tests/posix/nouser.out0
-rw-r--r--tests/posix/nouser.sh1
-rw-r--r--tests/posix/nouser_ulimit.out0
-rw-r--r--tests/posix/nouser_ulimit.sh3
-rw-r--r--tests/posix/o.out13
-rw-r--r--tests/posix/o.sh1
-rw-r--r--tests/posix/ok_stdin.out19
-rw-r--r--tests/posix/ok_stdin.sh3
-rw-r--r--tests/posix/or_purity.out0
-rw-r--r--tests/posix/or_purity.sh2
-rw-r--r--tests/posix/parens.out4
-rw-r--r--tests/posix/parens.sh1
-rw-r--r--tests/posix/path.out7
-rw-r--r--tests/posix/path.sh1
-rw-r--r--tests/posix/perm_000.out1
-rw-r--r--tests/posix/perm_000.sh1
-rw-r--r--tests/posix/perm_000_minus.out8
-rw-r--r--tests/posix/perm_000_minus.sh1
-rw-r--r--tests/posix/perm_222.out1
-rw-r--r--tests/posix/perm_222.sh1
-rw-r--r--tests/posix/perm_222_minus.out1
-rw-r--r--tests/posix/perm_222_minus.sh1
-rw-r--r--tests/posix/perm_644.out1
-rw-r--r--tests/posix/perm_644.sh1
-rw-r--r--tests/posix/perm_644_minus.out3
-rw-r--r--tests/posix/perm_644_minus.sh1
-rw-r--r--tests/posix/perm_leading_plus_symbolic_minus.out0
-rw-r--r--tests/posix/perm_leading_plus_symbolic_minus.sh1
-rw-r--r--tests/posix/perm_setid.out3
-rw-r--r--tests/posix/perm_setid.sh1
-rw-r--r--tests/posix/perm_sticky.out2
-rw-r--r--tests/posix/perm_sticky.sh1
-rw-r--r--tests/posix/perm_symbolic.out0
-rw-r--r--tests/posix/perm_symbolic.sh1
-rw-r--r--tests/posix/perm_symbolic_minus.out3
-rw-r--r--tests/posix/perm_symbolic_minus.sh1
-rw-r--r--tests/posix/permcopy.out1
-rw-r--r--tests/posix/permcopy.sh1
-rw-r--r--tests/posix/prune.out3
-rw-r--r--tests/posix/prune.sh1
-rw-r--r--tests/posix/prune_file.out10
-rw-r--r--tests/posix/prune_file.sh1
-rw-r--r--tests/posix/prune_or_print.out13
-rw-r--r--tests/posix/prune_or_print.sh1
-rw-r--r--tests/posix/size.out6
-rw-r--r--tests/posix/size.sh1
-rw-r--r--tests/posix/size_bytes.out1
-rw-r--r--tests/posix/size_bytes.sh1
-rw-r--r--tests/posix/size_plus.out1
-rw-r--r--tests/posix/size_plus.sh1
-rw-r--r--tests/posix/type_bind_mount.out1
-rw-r--r--tests/posix/type_bind_mount.sh12
-rw-r--r--tests/posix/type_d.out12
-rw-r--r--tests/posix/type_d.sh1
-rw-r--r--tests/posix/type_f.out7
-rw-r--r--tests/posix/type_f.sh1
-rw-r--r--tests/posix/type_l.out1
-rw-r--r--tests/posix/type_l.sh1
-rw-r--r--tests/posix/user_id.out19
-rw-r--r--tests/posix/user_id.sh1
-rw-r--r--tests/posix/user_name.out19
-rw-r--r--tests/posix/user_name.sh1
-rw-r--r--tests/posix/user_nouser.out19
-rw-r--r--tests/posix/user_nouser.sh2
-rw-r--r--tests/posix/weird_names.out28
-rw-r--r--tests/posix/weird_names.sh2
-rw-r--r--tests/posix/xdev.out4
-rw-r--r--tests/posix/xdev.sh13
192 files changed, 912 insertions, 0 deletions
diff --git a/tests/posix/H.out b/tests/posix/H.out
new file mode 100644
index 0000000..ff635ff
--- /dev/null
+++ b/tests/posix/H.out
@@ -0,0 +1 @@
+links/deeply/nested/dir
diff --git a/tests/posix/H.sh b/tests/posix/H.sh
new file mode 100644
index 0000000..5bae1be
--- /dev/null
+++ b/tests/posix/H.sh
@@ -0,0 +1 @@
+bfs_diff -H links/deeply/nested/dir
diff --git a/tests/posix/H_broken.out b/tests/posix/H_broken.out
new file mode 100644
index 0000000..21d6316
--- /dev/null
+++ b/tests/posix/H_broken.out
@@ -0,0 +1 @@
+links/broken
diff --git a/tests/posix/H_broken.sh b/tests/posix/H_broken.sh
new file mode 100644
index 0000000..9ff761c
--- /dev/null
+++ b/tests/posix/H_broken.sh
@@ -0,0 +1 @@
+bfs_diff -H links/broken
diff --git a/tests/posix/H_loops.out b/tests/posix/H_loops.out
new file mode 100644
index 0000000..1fc8f8f
--- /dev/null
+++ b/tests/posix/H_loops.out
@@ -0,0 +1,4 @@
+loops/deeply/nested/loop
+loops/deeply/nested/loop/nested
+loops/deeply/nested/loop/nested/dir
+loops/deeply/nested/loop/nested/loop
diff --git a/tests/posix/H_loops.sh b/tests/posix/H_loops.sh
new file mode 100644
index 0000000..90383b8
--- /dev/null
+++ b/tests/posix/H_loops.sh
@@ -0,0 +1 @@
+bfs_diff -H loops/deeply/nested/loop
diff --git a/tests/posix/H_notdir.out b/tests/posix/H_notdir.out
new file mode 100644
index 0000000..6e6658d
--- /dev/null
+++ b/tests/posix/H_notdir.out
@@ -0,0 +1 @@
+links/notdir
diff --git a/tests/posix/H_notdir.sh b/tests/posix/H_notdir.sh
new file mode 100644
index 0000000..68d7be7
--- /dev/null
+++ b/tests/posix/H_notdir.sh
@@ -0,0 +1 @@
+bfs_diff -H links/notdir
diff --git a/tests/posix/H_slash.out b/tests/posix/H_slash.out
new file mode 100644
index 0000000..df7701b
--- /dev/null
+++ b/tests/posix/H_slash.out
@@ -0,0 +1 @@
+links/deeply/nested/dir/
diff --git a/tests/posix/H_slash.sh b/tests/posix/H_slash.sh
new file mode 100644
index 0000000..b44d756
--- /dev/null
+++ b/tests/posix/H_slash.sh
@@ -0,0 +1 @@
+bfs_diff -H links/deeply/nested/dir/
diff --git a/tests/posix/H_type_l.out b/tests/posix/H_type_l.out
new file mode 100644
index 0000000..e67f10b
--- /dev/null
+++ b/tests/posix/H_type_l.out
@@ -0,0 +1,2 @@
+links/skip/broken
+links/skip/link
diff --git a/tests/posix/H_type_l.sh b/tests/posix/H_type_l.sh
new file mode 100644
index 0000000..416a53e
--- /dev/null
+++ b/tests/posix/H_type_l.sh
@@ -0,0 +1 @@
+bfs_diff -H links/skip -type l
diff --git a/tests/posix/L.out b/tests/posix/L.out
new file mode 100644
index 0000000..ec9e861
--- /dev/null
+++ b/tests/posix/L.out
@@ -0,0 +1,17 @@
+links
+links/broken
+links/deeply
+links/deeply/nested
+links/deeply/nested/broken
+links/deeply/nested/dir
+links/deeply/nested/file
+links/deeply/nested/link
+links/file
+links/hardlink
+links/notdir
+links/skip
+links/skip/broken
+links/skip/dir
+links/skip/file
+links/skip/link
+links/symlink
diff --git a/tests/posix/L.sh b/tests/posix/L.sh
new file mode 100644
index 0000000..d8aebe6
--- /dev/null
+++ b/tests/posix/L.sh
@@ -0,0 +1 @@
+bfs_diff -L links
diff --git a/tests/posix/L_broken.out b/tests/posix/L_broken.out
new file mode 100644
index 0000000..21d6316
--- /dev/null
+++ b/tests/posix/L_broken.out
@@ -0,0 +1 @@
+links/broken
diff --git a/tests/posix/L_broken.sh b/tests/posix/L_broken.sh
new file mode 100644
index 0000000..9ff761c
--- /dev/null
+++ b/tests/posix/L_broken.sh
@@ -0,0 +1 @@
+bfs_diff -H links/broken
diff --git a/tests/posix/L_depth.out b/tests/posix/L_depth.out
new file mode 100644
index 0000000..ec9e861
--- /dev/null
+++ b/tests/posix/L_depth.out
@@ -0,0 +1,17 @@
+links
+links/broken
+links/deeply
+links/deeply/nested
+links/deeply/nested/broken
+links/deeply/nested/dir
+links/deeply/nested/file
+links/deeply/nested/link
+links/file
+links/hardlink
+links/notdir
+links/skip
+links/skip/broken
+links/skip/dir
+links/skip/file
+links/skip/link
+links/symlink
diff --git a/tests/posix/L_depth.sh b/tests/posix/L_depth.sh
new file mode 100644
index 0000000..59d7ee9
--- /dev/null
+++ b/tests/posix/L_depth.sh
@@ -0,0 +1 @@
+bfs_diff -L links -depth
diff --git a/tests/posix/L_loops.sh b/tests/posix/L_loops.sh
new file mode 100644
index 0000000..f737cea
--- /dev/null
+++ b/tests/posix/L_loops.sh
@@ -0,0 +1,4 @@
+# POSIX says it's okay to either stop or keep going on seeing a filesystem
+# loop, as long as a diagnostic is printed
+errors=$(invoke_bfs -L loops 2>&1 >/dev/null)
+[ -n "$errors" ]
diff --git a/tests/posix/L_notdir.out b/tests/posix/L_notdir.out
new file mode 100644
index 0000000..6e6658d
--- /dev/null
+++ b/tests/posix/L_notdir.out
@@ -0,0 +1 @@
+links/notdir
diff --git a/tests/posix/L_notdir.sh b/tests/posix/L_notdir.sh
new file mode 100644
index 0000000..68d7be7
--- /dev/null
+++ b/tests/posix/L_notdir.sh
@@ -0,0 +1 @@
+bfs_diff -H links/notdir
diff --git a/tests/posix/L_type_l.out b/tests/posix/L_type_l.out
new file mode 100644
index 0000000..725d398
--- /dev/null
+++ b/tests/posix/L_type_l.out
@@ -0,0 +1 @@
+links/skip/broken
diff --git a/tests/posix/L_type_l.sh b/tests/posix/L_type_l.sh
new file mode 100644
index 0000000..ee9e563
--- /dev/null
+++ b/tests/posix/L_type_l.sh
@@ -0,0 +1 @@
+bfs_diff -L links/skip -type l
diff --git a/tests/posix/L_xdev.out b/tests/posix/L_xdev.out
new file mode 100644
index 0000000..2e80082
--- /dev/null
+++ b/tests/posix/L_xdev.out
@@ -0,0 +1,5 @@
+scratch
+scratch/foo
+scratch/foo/bar
+scratch/foo/qux
+scratch/mnt
diff --git a/tests/posix/L_xdev.sh b/tests/posix/L_xdev.sh
new file mode 100644
index 0000000..f0ba120
--- /dev/null
+++ b/tests/posix/L_xdev.sh
@@ -0,0 +1,15 @@
+skip_unless test "$SUDO"
+skip_if test "$UNAME" = "Darwin"
+
+rm -rf scratch/*
+mkdir scratch/{foo,mnt}
+sudo mount -t tmpfs tmpfs scratch/mnt
+ln -s ../mnt scratch/foo/bar
+$TOUCH scratch/mnt/baz
+ln -s ../mnt/baz scratch/foo/qux
+
+bfs_diff -L scratch -xdev
+ret=$?
+
+sudo umount scratch/mnt
+return $ret
diff --git a/tests/posix/a.out b/tests/posix/a.out
new file mode 100644
index 0000000..722962c
--- /dev/null
+++ b/tests/posix/a.out
@@ -0,0 +1,2 @@
+basic/k/foo
+basic/l/foo
diff --git a/tests/posix/a.sh b/tests/posix/a.sh
new file mode 100644
index 0000000..7d82d88
--- /dev/null
+++ b/tests/posix/a.sh
@@ -0,0 +1 @@
+bfs_diff basic -name foo -a -type d
diff --git a/tests/posix/bang.out b/tests/posix/bang.out
new file mode 100644
index 0000000..b286454
--- /dev/null
+++ b/tests/posix/bang.out
@@ -0,0 +1,16 @@
+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/k
+basic/k/foo/bar
+basic/l
+basic/l/foo/bar
+basic/l/foo/bar/baz
diff --git a/tests/posix/bang.sh b/tests/posix/bang.sh
new file mode 100644
index 0000000..27840cd
--- /dev/null
+++ b/tests/posix/bang.sh
@@ -0,0 +1 @@
+bfs_diff basic \! -name foo
diff --git a/tests/posix/basic.out b/tests/posix/basic.out
new file mode 100644
index 0000000..a7ccfe4
--- /dev/null
+++ b/tests/posix/basic.out
@@ -0,0 +1,19 @@
+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/posix/basic.sh b/tests/posix/basic.sh
new file mode 100644
index 0000000..3d43529
--- /dev/null
+++ b/tests/posix/basic.sh
@@ -0,0 +1 @@
+bfs_diff basic
diff --git a/tests/posix/closed_stderr.sh b/tests/posix/closed_stderr.sh
new file mode 100644
index 0000000..cc746ef
--- /dev/null
+++ b/tests/posix/closed_stderr.sh
@@ -0,0 +1 @@
+fail invoke_bfs basic >&- 2>&-
diff --git a/tests/posix/closed_stdin.out b/tests/posix/closed_stdin.out
new file mode 100644
index 0000000..a7ccfe4
--- /dev/null
+++ b/tests/posix/closed_stdin.out
@@ -0,0 +1,19 @@
+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/posix/closed_stdin.sh b/tests/posix/closed_stdin.sh
new file mode 100644
index 0000000..6932be8
--- /dev/null
+++ b/tests/posix/closed_stdin.sh
@@ -0,0 +1 @@
+bfs_diff basic <&-
diff --git a/tests/posix/closed_stdout.sh b/tests/posix/closed_stdout.sh
new file mode 100644
index 0000000..446bf56
--- /dev/null
+++ b/tests/posix/closed_stdout.sh
@@ -0,0 +1 @@
+fail invoke_bfs basic >&-
diff --git a/tests/posix/data_flow_and_swap.out b/tests/posix/data_flow_and_swap.out
new file mode 100644
index 0000000..e604709
--- /dev/null
+++ b/tests/posix/data_flow_and_swap.out
@@ -0,0 +1,12 @@
+basic
+basic/c
+basic/e
+basic/g
+basic/g/h
+basic/i
+basic/j
+basic/k
+basic/k/foo
+basic/l
+basic/l/foo
+basic/l/foo/bar
diff --git a/tests/posix/data_flow_and_swap.sh b/tests/posix/data_flow_and_swap.sh
new file mode 100644
index 0000000..9a141af
--- /dev/null
+++ b/tests/posix/data_flow_and_swap.sh
@@ -0,0 +1 @@
+bfs_diff basic \! -type f -a -type d
diff --git a/tests/posix/data_flow_group.out b/tests/posix/data_flow_group.out
new file mode 100644
index 0000000..a7ccfe4
--- /dev/null
+++ b/tests/posix/data_flow_group.out
@@ -0,0 +1,19 @@
+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/posix/data_flow_group.sh b/tests/posix/data_flow_group.sh
new file mode 100644
index 0000000..453dc3e
--- /dev/null
+++ b/tests/posix/data_flow_group.sh
@@ -0,0 +1 @@
+bfs_diff basic \( -group "$(id -g)" -nogroup \) -o \( -group "$(id -g)" -o -nogroup \)
diff --git a/tests/posix/data_flow_or_swap.out b/tests/posix/data_flow_or_swap.out
new file mode 100644
index 0000000..e604709
--- /dev/null
+++ b/tests/posix/data_flow_or_swap.out
@@ -0,0 +1,12 @@
+basic
+basic/c
+basic/e
+basic/g
+basic/g/h
+basic/i
+basic/j
+basic/k
+basic/k/foo
+basic/l
+basic/l/foo
+basic/l/foo/bar
diff --git a/tests/posix/data_flow_or_swap.sh b/tests/posix/data_flow_or_swap.sh
new file mode 100644
index 0000000..e8f504b
--- /dev/null
+++ b/tests/posix/data_flow_or_swap.sh
@@ -0,0 +1 @@
+bfs_diff basic \! \( -type f -o \! -type d \)
diff --git a/tests/posix/data_flow_type.out b/tests/posix/data_flow_type.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/posix/data_flow_type.out
diff --git a/tests/posix/data_flow_type.sh b/tests/posix/data_flow_type.sh
new file mode 100644
index 0000000..33339df
--- /dev/null
+++ b/tests/posix/data_flow_type.sh
@@ -0,0 +1 @@
+bfs_diff basic \! \( -type f -o \! -type f \)
diff --git a/tests/posix/data_flow_user.out b/tests/posix/data_flow_user.out
new file mode 100644
index 0000000..a7ccfe4
--- /dev/null
+++ b/tests/posix/data_flow_user.out
@@ -0,0 +1,19 @@
+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/posix/data_flow_user.sh b/tests/posix/data_flow_user.sh
new file mode 100644
index 0000000..44b6e1f
--- /dev/null
+++ b/tests/posix/data_flow_user.sh
@@ -0,0 +1 @@
+bfs_diff basic \( -user "$(id -u)" -nouser \) -o \( -user "$(id -u)" -o -nouser \)
diff --git a/tests/posix/de_morgan_and.out b/tests/posix/de_morgan_and.out
new file mode 100644
index 0000000..7b7afd2
--- /dev/null
+++ b/tests/posix/de_morgan_and.out
@@ -0,0 +1,10 @@
+basic
+basic/c
+basic/e
+basic/g
+basic/g/h
+basic/i
+basic/j
+basic/k
+basic/l
+basic/l/foo/bar
diff --git a/tests/posix/de_morgan_and.sh b/tests/posix/de_morgan_and.sh
new file mode 100644
index 0000000..d52975e
--- /dev/null
+++ b/tests/posix/de_morgan_and.sh
@@ -0,0 +1 @@
+bfs_diff basic \( \! -name 'foo' -a \! -type f \)
diff --git a/tests/posix/de_morgan_not.out b/tests/posix/de_morgan_not.out
new file mode 100644
index 0000000..5916da3
--- /dev/null
+++ b/tests/posix/de_morgan_not.out
@@ -0,0 +1,6 @@
+basic/a
+basic/b
+basic/c/d
+basic/e/f
+basic/k/foo/bar
+basic/l/foo/bar/baz
diff --git a/tests/posix/de_morgan_not.sh b/tests/posix/de_morgan_not.sh
new file mode 100644
index 0000000..7393ce0
--- /dev/null
+++ b/tests/posix/de_morgan_not.sh
@@ -0,0 +1 @@
+bfs_diff basic \! \( -name 'foo' -o \! -type f \)
diff --git a/tests/posix/de_morgan_or.out b/tests/posix/de_morgan_or.out
new file mode 100644
index 0000000..2a57066
--- /dev/null
+++ b/tests/posix/de_morgan_or.out
@@ -0,0 +1,18 @@
+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/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/posix/de_morgan_or.sh b/tests/posix/de_morgan_or.sh
new file mode 100644
index 0000000..378aab2
--- /dev/null
+++ b/tests/posix/de_morgan_or.sh
@@ -0,0 +1 @@
+bfs_diff basic \( \! -name 'foo' -o \! -type f \)
diff --git a/tests/posix/deep.out b/tests/posix/deep.out
new file mode 100644
index 0000000..c385fce
--- /dev/null
+++ b/tests/posix/deep.out
@@ -0,0 +1,16 @@
+deep/0/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358)
+deep/1/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358)
+deep/2/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358)
+deep/3/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358)
+deep/4/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358)
+deep/5/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358)
+deep/6/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358)
+deep/7/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358)
+deep/8/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358)
+deep/9/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358)
+deep/A/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358)
+deep/B/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358)
+deep/C/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358)
+deep/D/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358)
+deep/E/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358)
+deep/F/.../0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE (4358)
diff --git a/tests/posix/deep.sh b/tests/posix/deep.sh
new file mode 100644
index 0000000..3d1cd60
--- /dev/null
+++ b/tests/posix/deep.sh
@@ -0,0 +1,4 @@
+closefrom 4
+
+ulimit -n 16
+bfs_diff deep -type f -exec bash -c 'echo "${1:0:6}/.../${1##*/} (${#1})"' bash {} \;
diff --git a/tests/posix/depth.out b/tests/posix/depth.out
new file mode 100644
index 0000000..a7ccfe4
--- /dev/null
+++ b/tests/posix/depth.out
@@ -0,0 +1,19 @@
+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/posix/depth.sh b/tests/posix/depth.sh
new file mode 100644
index 0000000..444eba5
--- /dev/null
+++ b/tests/posix/depth.sh
@@ -0,0 +1 @@
+bfs_diff basic -depth
diff --git a/tests/posix/depth_error.out b/tests/posix/depth_error.out
new file mode 100644
index 0000000..ed0e9a1
--- /dev/null
+++ b/tests/posix/depth_error.out
@@ -0,0 +1,2 @@
+scratch
+scratch/foo
diff --git a/tests/posix/depth_error.sh b/tests/posix/depth_error.sh
new file mode 100644
index 0000000..9acf976
--- /dev/null
+++ b/tests/posix/depth_error.sh
@@ -0,0 +1,11 @@
+rm -rf scratch/*
+touchp scratch/foo/bar
+chmod a-r scratch/foo
+
+bfs_diff scratch -depth
+ret=$?
+
+chmod +r scratch/foo
+rm -rf scratch/*
+
+[ $ret -eq $EX_BFS ]
diff --git a/tests/posix/depth_slash.out b/tests/posix/depth_slash.out
new file mode 100644
index 0000000..77526d5
--- /dev/null
+++ b/tests/posix/depth_slash.out
@@ -0,0 +1,19 @@
+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/posix/depth_slash.sh b/tests/posix/depth_slash.sh
new file mode 100644
index 0000000..f73e9f1
--- /dev/null
+++ b/tests/posix/depth_slash.sh
@@ -0,0 +1 @@
+bfs_diff basic/ -depth
diff --git a/tests/posix/double_negation.out b/tests/posix/double_negation.out
new file mode 100644
index 0000000..e9d47b1
--- /dev/null
+++ b/tests/posix/double_negation.out
@@ -0,0 +1,3 @@
+basic/j/foo
+basic/k/foo
+basic/l/foo
diff --git a/tests/posix/double_negation.sh b/tests/posix/double_negation.sh
new file mode 100644
index 0000000..eefe464
--- /dev/null
+++ b/tests/posix/double_negation.sh
@@ -0,0 +1 @@
+bfs_diff basic \! \! -name 'foo'
diff --git a/tests/posix/exec.out b/tests/posix/exec.out
new file mode 100644
index 0000000..a7ccfe4
--- /dev/null
+++ b/tests/posix/exec.out
@@ -0,0 +1,19 @@
+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/posix/exec.sh b/tests/posix/exec.sh
new file mode 100644
index 0000000..96c897b
--- /dev/null
+++ b/tests/posix/exec.sh
@@ -0,0 +1 @@
+bfs_diff basic -exec echo {} \;
diff --git a/tests/posix/exec_nonexistent.out b/tests/posix/exec_nonexistent.out
new file mode 100644
index 0000000..a7ccfe4
--- /dev/null
+++ b/tests/posix/exec_nonexistent.out
@@ -0,0 +1,19 @@
+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/posix/exec_nonexistent.sh b/tests/posix/exec_nonexistent.sh
new file mode 100644
index 0000000..b4e08e0
--- /dev/null
+++ b/tests/posix/exec_nonexistent.sh
@@ -0,0 +1,8 @@
+# Failure to execute the command should lead to an error message and
+# non-zero exit status. See https://unix.stackexchange.com/q/704522/56202
+
+stderr=$(invoke_bfs basic -exec "$TESTS/nonexistent" {} \; 2>&1 >/dev/null)
+[ -n "$stderr" ] || return 1
+
+bfs_diff basic -print -exec "$TESTS/nonexistent" {} \; -print
+(($? == EX_BFS))
diff --git a/tests/posix/exec_nopath.out b/tests/posix/exec_nopath.out
new file mode 100644
index 0000000..a7ccfe4
--- /dev/null
+++ b/tests/posix/exec_nopath.out
@@ -0,0 +1,19 @@
+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/posix/exec_nopath.sh b/tests/posix/exec_nopath.sh
new file mode 100644
index 0000000..6e05d2e
--- /dev/null
+++ b/tests/posix/exec_nopath.sh
@@ -0,0 +1,7 @@
+(
+ unset PATH
+ invoke_bfs basic -exec echo {} \; >"$OUT"
+)
+
+sort_output
+diff_output
diff --git a/tests/posix/exec_plus.out b/tests/posix/exec_plus.out
new file mode 100644
index 0000000..f6b423b
--- /dev/null
+++ b/tests/posix/exec_plus.out
@@ -0,0 +1 @@
+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/posix/exec_plus.sh b/tests/posix/exec_plus.sh
new file mode 100644
index 0000000..56a93f1
--- /dev/null
+++ b/tests/posix/exec_plus.sh
@@ -0,0 +1 @@
+bfs_diff basic -exec "$TESTS/sort-args.sh" {} +
diff --git a/tests/posix/exec_plus_nonexistent.out b/tests/posix/exec_plus_nonexistent.out
new file mode 100644
index 0000000..a7ccfe4
--- /dev/null
+++ b/tests/posix/exec_plus_nonexistent.out
@@ -0,0 +1,19 @@
+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/posix/exec_plus_nonexistent.sh b/tests/posix/exec_plus_nonexistent.sh
new file mode 100644
index 0000000..f96099e
--- /dev/null
+++ b/tests/posix/exec_plus_nonexistent.sh
@@ -0,0 +1,5 @@
+stderr=$(invoke_bfs basic -exec "$TESTS/nonexistent" {} + 2>&1 >/dev/null)
+[ -n "$stderr" ] || return 1
+
+bfs_diff basic -exec "$TESTS/nonexistent" {} + -print
+(($? == EX_BFS))
diff --git a/tests/posix/exec_plus_semicolon.out b/tests/posix/exec_plus_semicolon.out
new file mode 100644
index 0000000..f33c48f
--- /dev/null
+++ b/tests/posix/exec_plus_semicolon.out
@@ -0,0 +1,19 @@
+foo basic bar + baz
+foo basic/a bar + baz
+foo basic/b bar + baz
+foo basic/c bar + baz
+foo basic/c/d bar + baz
+foo basic/e bar + baz
+foo basic/e/f bar + baz
+foo basic/g bar + baz
+foo basic/g/h bar + baz
+foo basic/i bar + baz
+foo basic/j bar + baz
+foo basic/j/foo bar + baz
+foo basic/k bar + baz
+foo basic/k/foo bar + baz
+foo basic/k/foo/bar bar + baz
+foo basic/l bar + baz
+foo basic/l/foo bar + baz
+foo basic/l/foo/bar bar + baz
+foo basic/l/foo/bar/baz bar + baz
diff --git a/tests/posix/exec_plus_semicolon.sh b/tests/posix/exec_plus_semicolon.sh
new file mode 100644
index 0000000..449a3f9
--- /dev/null
+++ b/tests/posix/exec_plus_semicolon.sh
@@ -0,0 +1,5 @@
+# POSIX says:
+# Only a <plus-sign> that immediately follows an argument containing only the two characters "{}"
+# shall punctuate the end of the primary expression. Other uses of the <plus-sign> shall not be
+# treated as special.
+bfs_diff basic -exec echo foo {} bar + baz \;
diff --git a/tests/posix/exec_plus_status.out b/tests/posix/exec_plus_status.out
new file mode 100644
index 0000000..a7ccfe4
--- /dev/null
+++ b/tests/posix/exec_plus_status.out
@@ -0,0 +1,19 @@
+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/posix/exec_plus_status.sh b/tests/posix/exec_plus_status.sh
new file mode 100644
index 0000000..ea9e5ef
--- /dev/null
+++ b/tests/posix/exec_plus_status.sh
@@ -0,0 +1,4 @@
+# -exec ... {} + should always return true, but if the command fails, bfs
+# should exit with a non-zero status
+bfs_diff basic -exec false {} + -print
+(($? == EX_BFS))
diff --git a/tests/posix/extra_paren.sh b/tests/posix/extra_paren.sh
new file mode 100644
index 0000000..cd8e8f8
--- /dev/null
+++ b/tests/posix/extra_paren.sh
@@ -0,0 +1 @@
+fail invoke_bfs basic -print \)
diff --git a/tests/posix/flag_comma.out b/tests/posix/flag_comma.out
new file mode 100644
index 0000000..3574388
--- /dev/null
+++ b/tests/posix/flag_comma.out
@@ -0,0 +1,2 @@
+,
+,/f
diff --git a/tests/posix/flag_comma.sh b/tests/posix/flag_comma.sh
new file mode 100644
index 0000000..cec87e7
--- /dev/null
+++ b/tests/posix/flag_comma.sh
@@ -0,0 +1,3 @@
+# , is a filename until a non-flag is seen
+cd weirdnames
+bfs_diff -L ',' -print
diff --git a/tests/posix/flag_weird_names.out b/tests/posix/flag_weird_names.out
new file mode 100644
index 0000000..c395659
--- /dev/null
+++ b/tests/posix/flag_weird_names.out
@@ -0,0 +1,28 @@
+!-
+!-
+!-/e
+!-/e
+(-
+(-
+(-/c
+(-/c
+)
+)
+)/g
+)/g
+,
+,
+,/f
+,/f
+-
+-
+-/a
+-/a
+./!
+./!
+./!/d
+./!/d
+./(
+./(
+./(/b
+./(/b
diff --git a/tests/posix/flag_weird_names.sh b/tests/posix/flag_weird_names.sh
new file mode 100644
index 0000000..f6596e9
--- /dev/null
+++ b/tests/posix/flag_weird_names.sh
@@ -0,0 +1,2 @@
+cd weirdnames
+bfs_diff -L '-' '(-' '!-' ',' ')' './(' './!' \( \! -print -o -print \)
diff --git a/tests/posix/group_id.out b/tests/posix/group_id.out
new file mode 100644
index 0000000..a7ccfe4
--- /dev/null
+++ b/tests/posix/group_id.out
@@ -0,0 +1,19 @@
+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/posix/group_id.sh b/tests/posix/group_id.sh
new file mode 100644
index 0000000..2ff7bb3
--- /dev/null
+++ b/tests/posix/group_id.sh
@@ -0,0 +1 @@
+bfs_diff basic -group "$(id -g)"
diff --git a/tests/posix/group_name.out b/tests/posix/group_name.out
new file mode 100644
index 0000000..a7ccfe4
--- /dev/null
+++ b/tests/posix/group_name.out
@@ -0,0 +1,19 @@
+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/posix/group_name.sh b/tests/posix/group_name.sh
new file mode 100644
index 0000000..36799d9
--- /dev/null
+++ b/tests/posix/group_name.sh
@@ -0,0 +1 @@
+bfs_diff basic -group "$(id -gn)"
diff --git a/tests/posix/group_nogroup.out b/tests/posix/group_nogroup.out
new file mode 100644
index 0000000..a7ccfe4
--- /dev/null
+++ b/tests/posix/group_nogroup.out
@@ -0,0 +1,19 @@
+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/posix/group_nogroup.sh b/tests/posix/group_nogroup.sh
new file mode 100644
index 0000000..cbd1ffc
--- /dev/null
+++ b/tests/posix/group_nogroup.sh
@@ -0,0 +1,2 @@
+# Regression test: this was wrongly optimized to -false
+bfs_diff basic -group "$(id -g)" \! -nogroup
diff --git a/tests/posix/implicit_and.out b/tests/posix/implicit_and.out
new file mode 100644
index 0000000..722962c
--- /dev/null
+++ b/tests/posix/implicit_and.out
@@ -0,0 +1,2 @@
+basic/k/foo
+basic/l/foo
diff --git a/tests/posix/implicit_and.sh b/tests/posix/implicit_and.sh
new file mode 100644
index 0000000..161ab0b
--- /dev/null
+++ b/tests/posix/implicit_and.sh
@@ -0,0 +1 @@
+bfs_diff basic -name foo -type d
diff --git a/tests/posix/incomplete.sh b/tests/posix/incomplete.sh
new file mode 100644
index 0000000..07b1b61
--- /dev/null
+++ b/tests/posix/incomplete.sh
@@ -0,0 +1 @@
+fail invoke_bfs basic \(
diff --git a/tests/posix/links.out b/tests/posix/links.out
new file mode 100644
index 0000000..996ffc8
--- /dev/null
+++ b/tests/posix/links.out
@@ -0,0 +1,2 @@
+links/file
+links/hardlink
diff --git a/tests/posix/links.sh b/tests/posix/links.sh
new file mode 100644
index 0000000..3d8ad80
--- /dev/null
+++ b/tests/posix/links.sh
@@ -0,0 +1 @@
+bfs_diff links -type f -links 2
diff --git a/tests/posix/links_minus.out b/tests/posix/links_minus.out
new file mode 100644
index 0000000..eda26f1
--- /dev/null
+++ b/tests/posix/links_minus.out
@@ -0,0 +1 @@
+links/deeply/nested/file
diff --git a/tests/posix/links_minus.sh b/tests/posix/links_minus.sh
new file mode 100644
index 0000000..3ee0803
--- /dev/null
+++ b/tests/posix/links_minus.sh
@@ -0,0 +1 @@
+bfs_diff links -type f -links -2
diff --git a/tests/posix/links_plus.out b/tests/posix/links_plus.out
new file mode 100644
index 0000000..996ffc8
--- /dev/null
+++ b/tests/posix/links_plus.out
@@ -0,0 +1,2 @@
+links/file
+links/hardlink
diff --git a/tests/posix/links_plus.sh b/tests/posix/links_plus.sh
new file mode 100644
index 0000000..375834b
--- /dev/null
+++ b/tests/posix/links_plus.sh
@@ -0,0 +1 @@
+bfs_diff links -type f -links +1
diff --git a/tests/posix/missing_paren.sh b/tests/posix/missing_paren.sh
new file mode 100644
index 0000000..ac8dd60
--- /dev/null
+++ b/tests/posix/missing_paren.sh
@@ -0,0 +1 @@
+fail invoke_bfs basic \( -print
diff --git a/tests/posix/name.out b/tests/posix/name.out
new file mode 100644
index 0000000..a9e5d42
--- /dev/null
+++ b/tests/posix/name.out
@@ -0,0 +1,4 @@
+basic/e/f
+basic/j/foo
+basic/k/foo
+basic/l/foo
diff --git a/tests/posix/name.sh b/tests/posix/name.sh
new file mode 100644
index 0000000..a673ad0
--- /dev/null
+++ b/tests/posix/name.sh
@@ -0,0 +1 @@
+bfs_diff basic -name '*f*'
diff --git a/tests/posix/name_backslash.out b/tests/posix/name_backslash.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/posix/name_backslash.out
diff --git a/tests/posix/name_backslash.sh b/tests/posix/name_backslash.sh
new file mode 100644
index 0000000..ff9b539
--- /dev/null
+++ b/tests/posix/name_backslash.sh
@@ -0,0 +1,2 @@
+# An unescaped \ doesn't match
+bfs_diff weirdnames -name '\'
diff --git a/tests/posix/name_bracket.out b/tests/posix/name_bracket.out
new file mode 100644
index 0000000..5ff3c0c
--- /dev/null
+++ b/tests/posix/name_bracket.out
@@ -0,0 +1 @@
+weirdnames/[
diff --git a/tests/posix/name_bracket.sh b/tests/posix/name_bracket.sh
new file mode 100644
index 0000000..84a417f
--- /dev/null
+++ b/tests/posix/name_bracket.sh
@@ -0,0 +1,5 @@
+# fnmatch() is broken on macOS
+skip_if test "$UNAME" = "Darwin"
+
+# An unclosed [ should be matched literally
+bfs_diff weirdnames -name '['
diff --git a/tests/posix/name_character_class.out b/tests/posix/name_character_class.out
new file mode 100644
index 0000000..e9d47b1
--- /dev/null
+++ b/tests/posix/name_character_class.out
@@ -0,0 +1,3 @@
+basic/j/foo
+basic/k/foo
+basic/l/foo
diff --git a/tests/posix/name_character_class.sh b/tests/posix/name_character_class.sh
new file mode 100644
index 0000000..ecda190
--- /dev/null
+++ b/tests/posix/name_character_class.sh
@@ -0,0 +1 @@
+bfs_diff basic -name '[e-g][!a-n][!p-z]'
diff --git a/tests/posix/name_double_backslash.out b/tests/posix/name_double_backslash.out
new file mode 100644
index 0000000..45ceda0
--- /dev/null
+++ b/tests/posix/name_double_backslash.out
@@ -0,0 +1 @@
+weirdnames/\
diff --git a/tests/posix/name_double_backslash.sh b/tests/posix/name_double_backslash.sh
new file mode 100644
index 0000000..009553a
--- /dev/null
+++ b/tests/posix/name_double_backslash.sh
@@ -0,0 +1,2 @@
+# An escaped \\ matches
+bfs_diff weirdnames -name '\\'
diff --git a/tests/posix/name_root.out b/tests/posix/name_root.out
new file mode 100644
index 0000000..511198f
--- /dev/null
+++ b/tests/posix/name_root.out
@@ -0,0 +1 @@
+basic/a
diff --git a/tests/posix/name_root.sh b/tests/posix/name_root.sh
new file mode 100644
index 0000000..785861e
--- /dev/null
+++ b/tests/posix/name_root.sh
@@ -0,0 +1 @@
+bfs_diff basic/a -name a
diff --git a/tests/posix/name_root_depth.out b/tests/posix/name_root_depth.out
new file mode 100644
index 0000000..cf4d5a9
--- /dev/null
+++ b/tests/posix/name_root_depth.out
@@ -0,0 +1 @@
+basic/g
diff --git a/tests/posix/name_root_depth.sh b/tests/posix/name_root_depth.sh
new file mode 100644
index 0000000..dc3b8bb
--- /dev/null
+++ b/tests/posix/name_root_depth.sh
@@ -0,0 +1 @@
+bfs_diff basic/g -depth -name g
diff --git a/tests/posix/name_star_star.out b/tests/posix/name_star_star.out
new file mode 100644
index 0000000..a9e5d42
--- /dev/null
+++ b/tests/posix/name_star_star.out
@@ -0,0 +1,4 @@
+basic/e/f
+basic/j/foo
+basic/k/foo
+basic/l/foo
diff --git a/tests/posix/name_star_star.sh b/tests/posix/name_star_star.sh
new file mode 100644
index 0000000..035f635
--- /dev/null
+++ b/tests/posix/name_star_star.sh
@@ -0,0 +1 @@
+bfs_diff basic -name '**f**'
diff --git a/tests/posix/name_trailing_slash.out b/tests/posix/name_trailing_slash.out
new file mode 100644
index 0000000..daff2f5
--- /dev/null
+++ b/tests/posix/name_trailing_slash.out
@@ -0,0 +1 @@
+basic/g/
diff --git a/tests/posix/name_trailing_slash.sh b/tests/posix/name_trailing_slash.sh
new file mode 100644
index 0000000..ab058d1
--- /dev/null
+++ b/tests/posix/name_trailing_slash.sh
@@ -0,0 +1 @@
+bfs_diff basic/g/ -name g
diff --git a/tests/posix/newer.out b/tests/posix/newer.out
new file mode 100644
index 0000000..7f6c0dd
--- /dev/null
+++ b/tests/posix/newer.out
@@ -0,0 +1,4 @@
+times
+times/b
+times/c
+times/l
diff --git a/tests/posix/newer.sh b/tests/posix/newer.sh
new file mode 100644
index 0000000..860623a
--- /dev/null
+++ b/tests/posix/newer.sh
@@ -0,0 +1 @@
+bfs_diff times -newer times/a
diff --git a/tests/posix/newer_link.out b/tests/posix/newer_link.out
new file mode 100644
index 0000000..d2dcdd1
--- /dev/null
+++ b/tests/posix/newer_link.out
@@ -0,0 +1 @@
+times
diff --git a/tests/posix/newer_link.sh b/tests/posix/newer_link.sh
new file mode 100644
index 0000000..685ac78
--- /dev/null
+++ b/tests/posix/newer_link.sh
@@ -0,0 +1 @@
+bfs_diff times -newer times/l
diff --git a/tests/posix/nogroup.out b/tests/posix/nogroup.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/posix/nogroup.out
diff --git a/tests/posix/nogroup.sh b/tests/posix/nogroup.sh
new file mode 100644
index 0000000..60ffd68
--- /dev/null
+++ b/tests/posix/nogroup.sh
@@ -0,0 +1 @@
+bfs_diff basic -nogroup
diff --git a/tests/posix/nogroup_ulimit.out b/tests/posix/nogroup_ulimit.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/posix/nogroup_ulimit.out
diff --git a/tests/posix/nogroup_ulimit.sh b/tests/posix/nogroup_ulimit.sh
new file mode 100644
index 0000000..e7231d9
--- /dev/null
+++ b/tests/posix/nogroup_ulimit.sh
@@ -0,0 +1,3 @@
+closefrom 4
+ulimit -n 16
+bfs_diff deep -nogroup
diff --git a/tests/posix/not_prune.out b/tests/posix/not_prune.out
new file mode 100644
index 0000000..59e3c42
--- /dev/null
+++ b/tests/posix/not_prune.out
@@ -0,0 +1,13 @@
+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/k
+basic/l
diff --git a/tests/posix/not_prune.sh b/tests/posix/not_prune.sh
new file mode 100644
index 0000000..6d7b092
--- /dev/null
+++ b/tests/posix/not_prune.sh
@@ -0,0 +1 @@
+bfs_diff basic \! \( -name foo -prune \)
diff --git a/tests/posix/nouser.out b/tests/posix/nouser.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/posix/nouser.out
diff --git a/tests/posix/nouser.sh b/tests/posix/nouser.sh
new file mode 100644
index 0000000..e7c48c0
--- /dev/null
+++ b/tests/posix/nouser.sh
@@ -0,0 +1 @@
+bfs_diff basic -nouser
diff --git a/tests/posix/nouser_ulimit.out b/tests/posix/nouser_ulimit.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/posix/nouser_ulimit.out
diff --git a/tests/posix/nouser_ulimit.sh b/tests/posix/nouser_ulimit.sh
new file mode 100644
index 0000000..1d0dd65
--- /dev/null
+++ b/tests/posix/nouser_ulimit.sh
@@ -0,0 +1,3 @@
+closefrom 4
+ulimit -n 16
+bfs_diff deep -nouser
diff --git a/tests/posix/o.out b/tests/posix/o.out
new file mode 100644
index 0000000..1650c4d
--- /dev/null
+++ b/tests/posix/o.out
@@ -0,0 +1,13 @@
+basic
+basic/c
+basic/e
+basic/g
+basic/g/h
+basic/i
+basic/j
+basic/j/foo
+basic/k
+basic/k/foo
+basic/l
+basic/l/foo
+basic/l/foo/bar
diff --git a/tests/posix/o.sh b/tests/posix/o.sh
new file mode 100644
index 0000000..6dcd442
--- /dev/null
+++ b/tests/posix/o.sh
@@ -0,0 +1 @@
+bfs_diff basic -name foo -o -type d
diff --git a/tests/posix/ok_stdin.out b/tests/posix/ok_stdin.out
new file mode 100644
index 0000000..7acf711
--- /dev/null
+++ b/tests/posix/ok_stdin.out
@@ -0,0 +1,19 @@
+basic/a? y
+basic/b? y
+basic/c/d? y
+basic/c? y
+basic/e/f? y
+basic/e? y
+basic/g/h? y
+basic/g? y
+basic/i? y
+basic/j/foo? y
+basic/j? y
+basic/k/foo/bar? y
+basic/k/foo? y
+basic/k? y
+basic/l/foo/bar/baz? y
+basic/l/foo/bar? y
+basic/l/foo? y
+basic/l? y
+basic? y
diff --git a/tests/posix/ok_stdin.sh b/tests/posix/ok_stdin.sh
new file mode 100644
index 0000000..a190d81
--- /dev/null
+++ b/tests/posix/ok_stdin.sh
@@ -0,0 +1,3 @@
+# -ok should *not* close stdin
+# See https://savannah.gnu.org/bugs/?24561
+yes | bfs_diff basic -ok bash -c 'printf "%s? " "$1" && head -n1' bash {} \;
diff --git a/tests/posix/or_purity.out b/tests/posix/or_purity.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/posix/or_purity.out
diff --git a/tests/posix/or_purity.sh b/tests/posix/or_purity.sh
new file mode 100644
index 0000000..277b18b
--- /dev/null
+++ b/tests/posix/or_purity.sh
@@ -0,0 +1,2 @@
+# Regression test: (-o lhs(pure) rhs(always_true)) <==> rhs is only valid if rhs is pure
+bfs_diff basic -name '*' -o -print
diff --git a/tests/posix/parens.out b/tests/posix/parens.out
new file mode 100644
index 0000000..a9e5d42
--- /dev/null
+++ b/tests/posix/parens.out
@@ -0,0 +1,4 @@
+basic/e/f
+basic/j/foo
+basic/k/foo
+basic/l/foo
diff --git a/tests/posix/parens.sh b/tests/posix/parens.sh
new file mode 100644
index 0000000..abbb20f
--- /dev/null
+++ b/tests/posix/parens.sh
@@ -0,0 +1 @@
+bfs_diff basic \( -name '*f*' \)
diff --git a/tests/posix/path.out b/tests/posix/path.out
new file mode 100644
index 0000000..ae1ae21
--- /dev/null
+++ b/tests/posix/path.out
@@ -0,0 +1,7 @@
+basic/e/f
+basic/j/foo
+basic/k/foo
+basic/k/foo/bar
+basic/l/foo
+basic/l/foo/bar
+basic/l/foo/bar/baz
diff --git a/tests/posix/path.sh b/tests/posix/path.sh
new file mode 100644
index 0000000..04606eb
--- /dev/null
+++ b/tests/posix/path.sh
@@ -0,0 +1 @@
+bfs_diff basic -path 'basic/*f*'
diff --git a/tests/posix/perm_000.out b/tests/posix/perm_000.out
new file mode 100644
index 0000000..5fd30bc
--- /dev/null
+++ b/tests/posix/perm_000.out
@@ -0,0 +1 @@
+perms/0
diff --git a/tests/posix/perm_000.sh b/tests/posix/perm_000.sh
new file mode 100644
index 0000000..ee25f23
--- /dev/null
+++ b/tests/posix/perm_000.sh
@@ -0,0 +1 @@
+bfs_diff perms -perm 000
diff --git a/tests/posix/perm_000_minus.out b/tests/posix/perm_000_minus.out
new file mode 100644
index 0000000..d7494b8
--- /dev/null
+++ b/tests/posix/perm_000_minus.out
@@ -0,0 +1,8 @@
+perms
+perms/0
+perms/r
+perms/rw
+perms/rwx
+perms/rx
+perms/w
+perms/wx
diff --git a/tests/posix/perm_000_minus.sh b/tests/posix/perm_000_minus.sh
new file mode 100644
index 0000000..5027b91
--- /dev/null
+++ b/tests/posix/perm_000_minus.sh
@@ -0,0 +1 @@
+bfs_diff perms -perm -000
diff --git a/tests/posix/perm_222.out b/tests/posix/perm_222.out
new file mode 100644
index 0000000..1690e43
--- /dev/null
+++ b/tests/posix/perm_222.out
@@ -0,0 +1 @@
+perms/w
diff --git a/tests/posix/perm_222.sh b/tests/posix/perm_222.sh
new file mode 100644
index 0000000..40f5804
--- /dev/null
+++ b/tests/posix/perm_222.sh
@@ -0,0 +1 @@
+bfs_diff perms -perm 222
diff --git a/tests/posix/perm_222_minus.out b/tests/posix/perm_222_minus.out
new file mode 100644
index 0000000..1690e43
--- /dev/null
+++ b/tests/posix/perm_222_minus.out
@@ -0,0 +1 @@
+perms/w
diff --git a/tests/posix/perm_222_minus.sh b/tests/posix/perm_222_minus.sh
new file mode 100644
index 0000000..4e7ad5a
--- /dev/null
+++ b/tests/posix/perm_222_minus.sh
@@ -0,0 +1 @@
+bfs_diff perms -perm -222
diff --git a/tests/posix/perm_644.out b/tests/posix/perm_644.out
new file mode 100644
index 0000000..4e64e49
--- /dev/null
+++ b/tests/posix/perm_644.out
@@ -0,0 +1 @@
+perms/rw
diff --git a/tests/posix/perm_644.sh b/tests/posix/perm_644.sh
new file mode 100644
index 0000000..9a4f41d
--- /dev/null
+++ b/tests/posix/perm_644.sh
@@ -0,0 +1 @@
+bfs_diff perms -perm 644
diff --git a/tests/posix/perm_644_minus.out b/tests/posix/perm_644_minus.out
new file mode 100644
index 0000000..2e2576b
--- /dev/null
+++ b/tests/posix/perm_644_minus.out
@@ -0,0 +1,3 @@
+perms
+perms/rw
+perms/rwx
diff --git a/tests/posix/perm_644_minus.sh b/tests/posix/perm_644_minus.sh
new file mode 100644
index 0000000..6464f84
--- /dev/null
+++ b/tests/posix/perm_644_minus.sh
@@ -0,0 +1 @@
+bfs_diff perms -perm -644
diff --git a/tests/posix/perm_leading_plus_symbolic_minus.out b/tests/posix/perm_leading_plus_symbolic_minus.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/posix/perm_leading_plus_symbolic_minus.out
diff --git a/tests/posix/perm_leading_plus_symbolic_minus.sh b/tests/posix/perm_leading_plus_symbolic_minus.sh
new file mode 100644
index 0000000..60389c0
--- /dev/null
+++ b/tests/posix/perm_leading_plus_symbolic_minus.sh
@@ -0,0 +1 @@
+bfs_diff perms -perm -+rwx
diff --git a/tests/posix/perm_setid.out b/tests/posix/perm_setid.out
new file mode 100644
index 0000000..865a74e
--- /dev/null
+++ b/tests/posix/perm_setid.out
@@ -0,0 +1,3 @@
+rainbow/sgid
+rainbow/sugid
+rainbow/suid
diff --git a/tests/posix/perm_setid.sh b/tests/posix/perm_setid.sh
new file mode 100644
index 0000000..3b98647
--- /dev/null
+++ b/tests/posix/perm_setid.sh
@@ -0,0 +1 @@
+bfs_diff rainbow -perm -u+s -o -perm -g+s
diff --git a/tests/posix/perm_sticky.out b/tests/posix/perm_sticky.out
new file mode 100644
index 0000000..c07eb61
--- /dev/null
+++ b/tests/posix/perm_sticky.out
@@ -0,0 +1,2 @@
+rainbow/sticky
+rainbow/sticky_ow
diff --git a/tests/posix/perm_sticky.sh b/tests/posix/perm_sticky.sh
new file mode 100644
index 0000000..6bdf8e9
--- /dev/null
+++ b/tests/posix/perm_sticky.sh
@@ -0,0 +1 @@
+bfs_diff rainbow -perm -a+t
diff --git a/tests/posix/perm_symbolic.out b/tests/posix/perm_symbolic.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/posix/perm_symbolic.out
diff --git a/tests/posix/perm_symbolic.sh b/tests/posix/perm_symbolic.sh
new file mode 100644
index 0000000..5cfddb6
--- /dev/null
+++ b/tests/posix/perm_symbolic.sh
@@ -0,0 +1 @@
+bfs_diff perms -perm a+r,u=wX,g+wX-w
diff --git a/tests/posix/perm_symbolic_minus.out b/tests/posix/perm_symbolic_minus.out
new file mode 100644
index 0000000..2e2576b
--- /dev/null
+++ b/tests/posix/perm_symbolic_minus.out
@@ -0,0 +1,3 @@
+perms
+perms/rw
+perms/rwx
diff --git a/tests/posix/perm_symbolic_minus.sh b/tests/posix/perm_symbolic_minus.sh
new file mode 100644
index 0000000..b6ba3a5
--- /dev/null
+++ b/tests/posix/perm_symbolic_minus.sh
@@ -0,0 +1 @@
+bfs_diff perms -perm -a+r,u=wX,g+wX-w
diff --git a/tests/posix/permcopy.out b/tests/posix/permcopy.out
new file mode 100644
index 0000000..4e64e49
--- /dev/null
+++ b/tests/posix/permcopy.out
@@ -0,0 +1 @@
+perms/rw
diff --git a/tests/posix/permcopy.sh b/tests/posix/permcopy.sh
new file mode 100644
index 0000000..3c85cce
--- /dev/null
+++ b/tests/posix/permcopy.sh
@@ -0,0 +1 @@
+bfs_diff perms -perm u+rw,g+u-w,o=g
diff --git a/tests/posix/prune.out b/tests/posix/prune.out
new file mode 100644
index 0000000..e9d47b1
--- /dev/null
+++ b/tests/posix/prune.out
@@ -0,0 +1,3 @@
+basic/j/foo
+basic/k/foo
+basic/l/foo
diff --git a/tests/posix/prune.sh b/tests/posix/prune.sh
new file mode 100644
index 0000000..b48ab48
--- /dev/null
+++ b/tests/posix/prune.sh
@@ -0,0 +1 @@
+bfs_diff basic -name foo -prune
diff --git a/tests/posix/prune_file.out b/tests/posix/prune_file.out
new file mode 100644
index 0000000..7575ae4
--- /dev/null
+++ b/tests/posix/prune_file.out
@@ -0,0 +1,10 @@
+basic
+basic/a
+basic/b
+basic/c
+basic/e
+basic/g
+basic/i
+basic/j
+basic/k
+basic/l
diff --git a/tests/posix/prune_file.sh b/tests/posix/prune_file.sh
new file mode 100644
index 0000000..29a3a33
--- /dev/null
+++ b/tests/posix/prune_file.sh
@@ -0,0 +1 @@
+bfs_diff basic -print -name '?' -prune
diff --git a/tests/posix/prune_or_print.out b/tests/posix/prune_or_print.out
new file mode 100644
index 0000000..59e3c42
--- /dev/null
+++ b/tests/posix/prune_or_print.out
@@ -0,0 +1,13 @@
+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/k
+basic/l
diff --git a/tests/posix/prune_or_print.sh b/tests/posix/prune_or_print.sh
new file mode 100644
index 0000000..85b97fd
--- /dev/null
+++ b/tests/posix/prune_or_print.sh
@@ -0,0 +1 @@
+bfs_diff basic -name foo -prune -o -print
diff --git a/tests/posix/size.out b/tests/posix/size.out
new file mode 100644
index 0000000..eeabbd7
--- /dev/null
+++ b/tests/posix/size.out
@@ -0,0 +1,6 @@
+basic/a
+basic/b
+basic/c/d
+basic/e/f
+basic/j/foo
+basic/k/foo/bar
diff --git a/tests/posix/size.sh b/tests/posix/size.sh
new file mode 100644
index 0000000..1e7528a
--- /dev/null
+++ b/tests/posix/size.sh
@@ -0,0 +1 @@
+bfs_diff basic -type f -size 0
diff --git a/tests/posix/size_bytes.out b/tests/posix/size_bytes.out
new file mode 100644
index 0000000..279f3f1
--- /dev/null
+++ b/tests/posix/size_bytes.out
@@ -0,0 +1 @@
+basic/l/foo/bar/baz
diff --git a/tests/posix/size_bytes.sh b/tests/posix/size_bytes.sh
new file mode 100644
index 0000000..6a68321
--- /dev/null
+++ b/tests/posix/size_bytes.sh
@@ -0,0 +1 @@
+bfs_diff basic -type f -size +0c
diff --git a/tests/posix/size_plus.out b/tests/posix/size_plus.out
new file mode 100644
index 0000000..279f3f1
--- /dev/null
+++ b/tests/posix/size_plus.out
@@ -0,0 +1 @@
+basic/l/foo/bar/baz
diff --git a/tests/posix/size_plus.sh b/tests/posix/size_plus.sh
new file mode 100644
index 0000000..01853d5
--- /dev/null
+++ b/tests/posix/size_plus.sh
@@ -0,0 +1 @@
+bfs_diff basic -type f -size +0
diff --git a/tests/posix/type_bind_mount.out b/tests/posix/type_bind_mount.out
new file mode 100644
index 0000000..6435159
--- /dev/null
+++ b/tests/posix/type_bind_mount.out
@@ -0,0 +1 @@
+scratch/null
diff --git a/tests/posix/type_bind_mount.sh b/tests/posix/type_bind_mount.sh
new file mode 100644
index 0000000..87b1549
--- /dev/null
+++ b/tests/posix/type_bind_mount.sh
@@ -0,0 +1,12 @@
+skip_unless test "$SUDO"
+skip_unless test "$UNAME" = "Linux"
+
+rm -rf scratch/*
+$TOUCH scratch/{file,null}
+sudo mount --bind /dev/null scratch/null
+
+bfs_diff scratch -type c
+ret=$?
+
+sudo umount scratch/null
+return $ret
diff --git a/tests/posix/type_d.out b/tests/posix/type_d.out
new file mode 100644
index 0000000..e604709
--- /dev/null
+++ b/tests/posix/type_d.out
@@ -0,0 +1,12 @@
+basic
+basic/c
+basic/e
+basic/g
+basic/g/h
+basic/i
+basic/j
+basic/k
+basic/k/foo
+basic/l
+basic/l/foo
+basic/l/foo/bar
diff --git a/tests/posix/type_d.sh b/tests/posix/type_d.sh
new file mode 100644
index 0000000..8d06b73
--- /dev/null
+++ b/tests/posix/type_d.sh
@@ -0,0 +1 @@
+bfs_diff basic -type d
diff --git a/tests/posix/type_f.out b/tests/posix/type_f.out
new file mode 100644
index 0000000..6218a0c
--- /dev/null
+++ b/tests/posix/type_f.out
@@ -0,0 +1,7 @@
+basic/a
+basic/b
+basic/c/d
+basic/e/f
+basic/j/foo
+basic/k/foo/bar
+basic/l/foo/bar/baz
diff --git a/tests/posix/type_f.sh b/tests/posix/type_f.sh
new file mode 100644
index 0000000..1fd0c8c
--- /dev/null
+++ b/tests/posix/type_f.sh
@@ -0,0 +1 @@
+bfs_diff basic -type f
diff --git a/tests/posix/type_l.out b/tests/posix/type_l.out
new file mode 100644
index 0000000..f2c8b19
--- /dev/null
+++ b/tests/posix/type_l.out
@@ -0,0 +1 @@
+links/skip
diff --git a/tests/posix/type_l.sh b/tests/posix/type_l.sh
new file mode 100644
index 0000000..457f74d
--- /dev/null
+++ b/tests/posix/type_l.sh
@@ -0,0 +1 @@
+bfs_diff links/skip -type l
diff --git a/tests/posix/user_id.out b/tests/posix/user_id.out
new file mode 100644
index 0000000..a7ccfe4
--- /dev/null
+++ b/tests/posix/user_id.out
@@ -0,0 +1,19 @@
+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/posix/user_id.sh b/tests/posix/user_id.sh
new file mode 100644
index 0000000..c3e4b31
--- /dev/null
+++ b/tests/posix/user_id.sh
@@ -0,0 +1 @@
+bfs_diff basic -user "$(id -u)"
diff --git a/tests/posix/user_name.out b/tests/posix/user_name.out
new file mode 100644
index 0000000..a7ccfe4
--- /dev/null
+++ b/tests/posix/user_name.out
@@ -0,0 +1,19 @@
+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/posix/user_name.sh b/tests/posix/user_name.sh
new file mode 100644
index 0000000..8599249
--- /dev/null
+++ b/tests/posix/user_name.sh
@@ -0,0 +1 @@
+bfs_diff basic -user "$(id -un)"
diff --git a/tests/posix/user_nouser.out b/tests/posix/user_nouser.out
new file mode 100644
index 0000000..a7ccfe4
--- /dev/null
+++ b/tests/posix/user_nouser.out
@@ -0,0 +1,19 @@
+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/posix/user_nouser.sh b/tests/posix/user_nouser.sh
new file mode 100644
index 0000000..e72bd45
--- /dev/null
+++ b/tests/posix/user_nouser.sh
@@ -0,0 +1,2 @@
+# Regression test: this was wrongly optimized to -false
+bfs_diff basic -user "$(id -u)" \! -nouser
diff --git a/tests/posix/weird_names.out b/tests/posix/weird_names.out
new file mode 100644
index 0000000..c395659
--- /dev/null
+++ b/tests/posix/weird_names.out
@@ -0,0 +1,28 @@
+!-
+!-
+!-/e
+!-/e
+(-
+(-
+(-/c
+(-/c
+)
+)
+)/g
+)/g
+,
+,
+,/f
+,/f
+-
+-
+-/a
+-/a
+./!
+./!
+./!/d
+./!/d
+./(
+./(
+./(/b
+./(/b
diff --git a/tests/posix/weird_names.sh b/tests/posix/weird_names.sh
new file mode 100644
index 0000000..8a9a8cd
--- /dev/null
+++ b/tests/posix/weird_names.sh
@@ -0,0 +1,2 @@
+cd weirdnames
+bfs_diff '-' '(-' '!-' ',' ')' './(' './!' \( \! -print -o -print \)
diff --git a/tests/posix/xdev.out b/tests/posix/xdev.out
new file mode 100644
index 0000000..f7839fb
--- /dev/null
+++ b/tests/posix/xdev.out
@@ -0,0 +1,4 @@
+scratch
+scratch/foo
+scratch/foo/bar
+scratch/mnt
diff --git a/tests/posix/xdev.sh b/tests/posix/xdev.sh
new file mode 100644
index 0000000..cbb3347
--- /dev/null
+++ b/tests/posix/xdev.sh
@@ -0,0 +1,13 @@
+skip_unless test "$SUDO"
+skip_if test "$UNAME" = "Darwin"
+
+rm -rf scratch/*
+mkdir scratch/{foo,mnt}
+sudo mount -t tmpfs tmpfs scratch/mnt
+$TOUCH scratch/foo/bar scratch/mnt/baz
+
+bfs_diff scratch -xdev
+ret=$?
+
+sudo umount scratch/mnt
+return $ret