diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2022-10-19 10:29:05 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2022-10-19 11:50:03 -0400 |
commit | 3b387d81e63893ed3fe3b45e3721fbcfb1c5dde0 (patch) | |
tree | 513c32eda43d92a8ed977f394492ba198bba1f3b /tests/tests.sh | |
parent | e5972621ffa8864b18d3e303ac714fdbe231be74 (diff) | |
download | bfs-3b387d81e63893ed3fe3b45e3721fbcfb1c5dde0.tar.xz |
tests: Split test cases into separate files
Diffstat (limited to 'tests/tests.sh')
-rwxr-xr-x | tests/tests.sh | 2847 |
1 files changed, 28 insertions, 2819 deletions
diff --git a/tests/tests.sh b/tests/tests.sh index 64bd04d..d957cf1 100755 --- a/tests/tests.sh +++ b/tests/tests.sh @@ -16,6 +16,8 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # ############################################################################ +shopt -s extdebug + set -euP umask 022 @@ -92,7 +94,7 @@ function usage() { cat <<EOF Usage: ${GRN}$0${RST} [${BLU}--bfs${RST}=${MAG}path/to/bfs${RST}] [${BLU}--posix${RST}] [${BLU}--bsd${RST}] [${BLU}--gnu${RST}] [${BLU}--all${RST}] [${BLU}--sudo${RST}] $pad [${BLU}--stop${RST}] [${BLU}--noclean${RST}] [${BLU}--update${RST}] [${BLU}--verbose${RST}[=${BLD}LEVEL${RST}]] [${BLU}--help${RST}] - $pad [${BLD}test_*${RST} [${BLD}test_*${RST} ...]] + $pad [${BLD}TEST${RST} [${BLD}TEST${RST} ...]] ${BLU}--bfs${RST}=${MAG}path/to/bfs${RST} Set the path to the bfs executable to test (default: ${MAG}./bin/bfs${RST}) @@ -126,13 +128,14 @@ Usage: ${GRN}$0${RST} [${BLU}--bfs${RST}=${MAG}path/to/bfs${RST}] [${BLU}--posix ${BLU}--help${RST} This message - ${BLD}test_*${RST} - Select individual test cases to run + ${BLD}TEST${RST} + Select individual test cases to run (e.g. ${BLD}posix/basic${RST}) EOF } DEFAULT=yes POSIX= +COMMON= BSD= GNU= ALL= @@ -160,16 +163,19 @@ for arg; do --bsd) DEFAULT= POSIX=yes + COMMON=yes BSD=yes ;; --gnu) DEFAULT= POSIX=yes + COMMON=yes GNU=yes ;; --all) DEFAULT= POSIX=yes + COMMON=yes BSD=yes GNU=yes ALL=yes @@ -209,7 +215,7 @@ for arg; do usage exit 0 ;; - test_*) + */*) EXPLICIT=yes SUDO=yes enabled_tests+=("$arg") @@ -222,697 +228,14 @@ for arg; do esac done -posix_tests=( - # General parsing - test_basic - - test_parens - test_bang - test_implicit_and - test_a - test_o - - test_weird_names - - test_incomplete - test_missing_paren - test_extra_paren - - # Flags - - test_H - test_H_slash - test_H_broken - test_H_notdir - test_H_loops - - test_L - test_L_broken - test_L_notdir - test_L_loops - - test_flag_weird_names - test_flag_comma - - # Primaries - - test_depth - test_depth_slash - test_depth_error - test_L_depth - - test_exec - test_exec_nonexistent - test_exec_nopath - test_exec_plus - test_exec_plus_nonexistent - test_exec_plus_status - test_exec_plus_semicolon - - test_group_name - test_group_id - test_group_nogroup - - test_links - test_links_plus - test_links_minus - - test_name - test_name_root - test_name_root_depth - test_name_trailing_slash - test_name_star_star - test_name_character_class - test_name_bracket - test_name_backslash - test_name_double_backslash - - test_newer - test_newer_link - - test_nogroup - test_nogroup_ulimit - - test_nouser - test_nouser_ulimit - - test_ok_stdin - - test_path - - test_perm_000 - test_perm_000_minus - test_perm_222 - test_perm_222_minus - test_perm_644 - test_perm_644_minus - test_perm_symbolic - test_perm_symbolic_minus - test_perm_leading_plus_symbolic_minus - test_permcopy - test_perm_setid - test_perm_sticky - - test_prune - test_prune_file - test_prune_or_print - test_not_prune - - test_size - test_size_plus - test_size_bytes - - test_type_d - test_type_f - test_type_l - test_H_type_l - test_L_type_l - test_type_bind_mount - - test_user_name - test_user_id - test_user_nouser - - test_xdev - test_L_xdev - - # Closed file descriptors - test_closed_stdin - test_closed_stdout - test_closed_stderr - - # PATH_MAX handling - test_deep - - # Optimizer tests - test_or_purity - test_double_negation - test_de_morgan_not - test_de_morgan_and - test_de_morgan_or - test_data_flow_group - test_data_flow_user - test_data_flow_type - test_data_flow_and_swap - test_data_flow_or_swap -) - -bsd_tests=( - # Flags - - test_E - - test_P - test_P_slash - - test_X - - test_d_path - - test_f - - test_s - - test_double_dash - test_flag_double_dash - - # Primaries - - test_acl - test_L_acl - - test_anewer - test_asince - - test_delete - test_delete_many - - test_depth_maxdepth_1 - test_depth_maxdepth_2 - test_depth_mindepth_1 - test_depth_mindepth_2 - - test_depth_n - test_depth_n_plus - test_depth_n_minus - test_depth_depth_n - test_depth_depth_n_plus - test_depth_depth_n_minus - test_depth_overflow - test_data_flow_depth - - test_exec_substring - - test_execdir_nonexistent - test_execdir_pwd - test_execdir_slash - test_execdir_slash_pwd - test_execdir_slashes - test_execdir_ulimit - - test_exit - test_exit_no_implicit_print - - test_flags - - test_follow - - test_gid_name - - test_ilname - test_L_ilname - - test_iname - - test_inum - test_inum_mount - test_inum_bind_mount - - test_ipath - - test_iregex - - test_lname - test_L_lname - - test_ls - test_L_ls - - test_maxdepth - - test_mindepth - - test_mnewer - test_H_mnewer - - test_mount - test_L_mount - - test_msince - - test_mtime_units - - test_name_slash - test_name_slashes - - test_H_newer - - test_newerma - test_newermt - test_newermt_epoch_minus_one - - test_ok_stdin - test_ok_closed_stdin - - test_okdir_stdin - test_okdir_closed_stdin - - test_perm_000_plus - test_perm_222_plus - test_perm_644_plus - - test_printx - - test_quit - test_quit_child - test_quit_depth - test_quit_depth_child - test_quit_after_print - test_quit_before_print - test_quit_implicit_print - - test_rm - - test_regex - test_regex_parens - - test_samefile - test_samefile_symlink - test_H_samefile_symlink - test_L_samefile_symlink - test_samefile_broken - test_H_samefile_broken - test_L_samefile_broken - test_samefile_notdir - test_H_samefile_notdir - test_L_samefile_notdir - - test_size_T - test_size_big - - test_uid_name - - test_xattr - test_L_xattr - - test_xattrname - test_L_xattrname - - # Optimizer tests - test_data_flow_sparse -) - -gnu_tests=( - # General parsing - - test_not - test_and - test_or - test_comma - test_precedence - - test_follow_comma - - # Flags - - test_P - test_P_slash - - test_L_loops_continue - - test_double_dash - test_flag_double_dash - - # Primaries - - test_anewer - - test_path_d - - test_daystart - test_daystart_twice - - test_delete - test_delete_many - test_L_delete - - test_depth_mindepth_1 - test_depth_mindepth_2 - test_depth_maxdepth_1 - test_depth_maxdepth_2 - - test_empty - test_empty_special - - test_exec_nothing - test_exec_substring - test_exec_flush - test_exec_flush_fail - test_exec_plus_flush - test_exec_plus_flush_fail - - test_execdir - test_execdir_nonexistent - test_execdir_substring - test_execdir_plus_semicolon - test_execdir_pwd - test_execdir_slash - test_execdir_slash_pwd - test_execdir_slashes - test_execdir_ulimit - - test_executable - - test_false - - test_files0_from_file - test_files0_from_stdin - test_files0_from_none - test_files0_from_empty - test_files0_from_nowhere - test_files0_from_nothing - test_files0_from_ok - - test_fls - - test_follow - - test_fprint - test_fprint_duplicate - test_fprint_error - test_fprint_noerror - test_fprint_noarg - test_fprint_nonexistent - test_fprint_truncate - - test_fprint0 - - test_fprintf - test_fprintf_nofile - test_fprintf_noformat - - test_fstype - - test_gid - test_gid_plus - test_gid_plus_plus - test_gid_minus - test_gid_minus_plus - - test_ignore_readdir_race - test_ignore_readdir_race_root - test_ignore_readdir_race_notdir - - test_ilname - test_L_ilname - - test_iname - - test_inum - test_inum_mount - test_inum_bind_mount - test_inum_automount - - test_ipath - - test_iregex - - test_iwholename - - test_lname - test_L_lname - - test_ls - test_L_ls - - test_maxdepth - - test_mindepth - - test_mount - test_L_mount - - test_name_slash - test_name_slashes - - test_H_newer - - test_newerma - test_newermt - test_newermt_epoch_minus_one - - test_ok_closed_stdin - test_ok_nothing - - test_okdir_closed_stdin - - test_perm_000_slash - test_perm_222_slash - test_perm_644_slash - test_perm_symbolic_slash - test_perm_leading_plus_symbolic_slash - - test_print_error - - test_print0 - - test_printf - test_printf_empty - test_printf_slash - test_printf_slashes - test_printf_trailing_slash - test_printf_trailing_slashes - test_printf_flags - test_printf_types - test_printf_escapes - test_printf_times - test_printf_leak - test_printf_nul - test_printf_Y_error - test_printf_H - test_printf_u_g_ulimit - test_printf_l_nonlink - - test_quit - test_quit_child - test_quit_depth - test_quit_depth_child - test_quit_after_print - test_quit_before_print - - test_readable - - test_regex - test_regex_parens - test_regex_error - test_regex_invalid_utf8 - - test_regextype_posix_basic - test_regextype_posix_extended - test_regextype_ed - test_regextype_emacs - test_regextype_grep - test_regextype_sed - - test_samefile - test_samefile_symlink - test_H_samefile_symlink - test_L_samefile_symlink - test_samefile_broken - test_H_samefile_broken - test_L_samefile_broken - test_samefile_notdir - test_H_samefile_notdir - test_L_samefile_notdir - - test_size_big - - test_true - - test_uid - test_uid_plus - test_uid_plus_plus - test_uid_minus - test_uid_minus_plus - - test_wholename - - test_writable - - test_xtype_l - test_xtype_f - test_L_xtype_l - test_L_xtype_f - test_xtype_bind_mount - - # Optimizer tests - test_and_purity - test_not_reachability - test_comma_reachability - test_and_false_or_true - test_comma_redundant_true - test_comma_redundant_false -) - -bfs_tests=( - # General parsing - test_path_flag_expr - test_path_expr_flag - test_flag_expr_path - test_expr_flag_path - test_expr_path_flag - - test_unexpected_operator - test_and_incomplete - test_or_incomplete - test_comma_incomplete - - test_typo - - # Flags - - test_D_multi - test_D_all - - test_O0 - test_O1 - test_O2 - test_O3 - test_Ofast - - test_S_bfs - test_S_dfs - test_S_ids - - # Special forms - - test_exclude_name - test_exclude_depth - test_exclude_mindepth - test_exclude_print - test_exclude_exclude - - # Primaries - - test_capable - test_L_capable - - test_color - test_color_L - test_color_rs_lc_rc_ec - test_color_escapes - test_color_nul - test_color_ln_target - test_color_L_ln_target - test_color_mh - test_color_mh0 - test_color_or - test_color_mi - test_color_or_mi - test_color_or_mi0 - test_color_or0_mi - test_color_or0_mi0 - test_color_su_sg0 - test_color_su0_sg - test_color_su0_sg0 - test_color_st_tw_ow0 - test_color_st_tw0_ow - test_color_st_tw0_ow0 - test_color_st0_tw_ow - test_color_st0_tw_ow0 - test_color_st0_tw0_ow - test_color_st0_tw0_ow0 - test_color_ext - test_color_ext0 - test_color_ext_override - test_color_ext_underride - test_color_missing_colon - test_color_no_stat - test_color_L_no_stat - test_color_star - test_color_ls - - test_exec_flush_fprint - test_exec_flush_fprint_fail - - test_execdir_plus - test_execdir_plus_nonexistent - - test_fprint_duplicate_stdout - test_fprint_error_stdout - test_fprint_error_stderr - - test_help - - test_hidden - test_hidden_root - - test_links_noarg - test_links_empty - test_links_negative - test_links_invalid - - test_newerma_nonexistent - test_newermt_invalid - test_newermq - test_newerqm - - test_nohidden - test_nohidden_depth - - test_ok_plus_semicolon - - test_okdir_plus_semicolon - - test_perm_symbolic_trailing_comma - test_perm_symbolic_double_comma - test_perm_symbolic_missing_action - test_perm_leading_plus_symbolic - - test_printf_w - test_printf_incomplete_escape - test_printf_invalid_escape - test_printf_incomplete_format - test_printf_invalid_format - test_printf_duplicate_flag - test_printf_must_be_numeric - test_printf_color - test_printf_everything - - test_type_multi - - test_unique - test_unique_depth - test_L_unique - test_L_unique_loops - test_L_unique_depth - - test_version - - test_warn - test_nowarn - - test_xtype_multi - - # Optimizer tests - test_data_flow_hidden - test_xtype_reorder - test_xtype_depth - - # PATH_MAX handling - test_deep_strict - - # Error handling - test_stderr_fails_silently - test_stderr_fails_loudly -) - if [ "$DEFAULT" ]; then POSIX=yes + COMMON=yes BSD=yes GNU=yes ALL=yes fi -if [ ! "$EXPLICIT" ]; then - [ "$POSIX" ] && enabled_tests+=("${posix_tests[@]}") - [ "$BSD" ] && enabled_tests+=("${bsd_tests[@]}") - [ "$GNU" ] && enabled_tests+=("${gnu_tests[@]}") - [ "$ALL" ] && enabled_tests+=("${bfs_tests[@]}") -fi - -eval "enabled_tests=($(printf '%q\n' "${enabled_tests[@]}" | sort -u))" - function _realpath() { ( cd "$(dirname -- "$1")" @@ -937,6 +260,18 @@ BFS[0]=$(_realpath "$(command -v "${BFS[0]}")") TMP=$(mktemp -d "${TMPDIR:-/tmp}"/bfs.XXXXXXXXXX) chown "$(id -u):$(id -g)" "$TMP" +cd "$TESTS" + +if [ ! "$EXPLICIT" ]; then + [ "$POSIX" ] && enabled_tests+=(posix/*.sh) + [ "$COMMON" ] && enabled_tests+=(common/*.sh) + [ "$BSD" ] && enabled_tests+=(bsd/*.sh) + [ "$GNU" ] && enabled_tests+=(gnu/*.sh) + [ "$ALL" ] && enabled_tests+=(bfs/*.sh) + + enabled_tests=("${enabled_tests[@]%.sh}") +fi + # Clean up temporary directories on exit function cleanup() { # Don't force rm to deal with long paths @@ -1265,1881 +600,6 @@ function inum() { ls -id "$@" | awk '{ print $1 }' } - -cd "$TMP" -set +e - -# Test cases - -function test_basic() { - bfs_diff basic -} - -function test_type_d() { - bfs_diff basic -type d -} - -function test_type_f() { - bfs_diff basic -type f -} - -function test_type_l() { - bfs_diff links/skip -type l -} - -function test_H_type_l() { - bfs_diff -H links/skip -type l -} - -function test_L_type_l() { - bfs_diff -L links/skip -type l -} - -function test_type_multi() { - bfs_diff links -type f,d,c -} - -function test_mindepth() { - bfs_diff basic -mindepth 1 -} - -function test_maxdepth() { - bfs_diff basic -maxdepth 1 -} - -function test_depth() { - bfs_diff basic -depth -} - -function test_depth_slash() { - bfs_diff basic/ -depth -} - -function test_depth_mindepth_1() { - bfs_diff basic -mindepth 1 -depth -} - -function test_depth_mindepth_2() { - bfs_diff basic -mindepth 2 -depth -} - -function test_depth_maxdepth_1() { - bfs_diff basic -maxdepth 1 -depth -} - -function test_depth_maxdepth_2() { - bfs_diff basic -maxdepth 2 -depth -} - -function test_depth_error() { - rm -rf scratch/* - touchp scratch/foo/bar - chmod a-r scratch/foo - - bfs_diff scratch -depth - local ret=$? - - chmod +r scratch/foo - rm -rf scratch/* - - [ $ret -eq $EX_BFS ] -} - -function test_name() { - bfs_diff basic -name '*f*' -} - -function test_name_root() { - bfs_diff basic/a -name a -} - -function test_name_root_depth() { - bfs_diff basic/g -depth -name g -} - -function test_name_trailing_slash() { - bfs_diff basic/g/ -name g -} - -function test_name_slash() { - bfs_diff / -maxdepth 0 -name / -} - -function test_name_slashes() { - bfs_diff /// -maxdepth 0 -name / -} - -function test_name_star_star() { - bfs_diff basic -name '**f**' -} - -function test_name_character_class() { - bfs_diff basic -name '[e-g][!a-n][!p-z]' -} - -function test_name_bracket() { - # fnmatch() is broken on macOS - skip_if test "$UNAME" = "Darwin" - - # An unclosed [ should be matched literally - bfs_diff weirdnames -name '[' -} - -function test_name_backslash() { - # An unescaped \ doesn't match - bfs_diff weirdnames -name '\' -} - -function test_name_double_backslash() { - # An escaped \\ matches - bfs_diff weirdnames -name '\\' -} - -function test_path() { - bfs_diff basic -path 'basic/*f*' -} - -function test_wholename() { - bfs_diff basic -wholename 'basic/*f*' -} - -function test_true() { - bfs_diff basic -true -} - -function test_false() { - bfs_diff basic -false -} - -function test_executable() { - bfs_diff perms -executable -} - -function test_readable() { - bfs_diff perms -readable -} - -function test_writable() { - bfs_diff perms -writable -} - -function test_empty() { - bfs_diff basic -empty -} - -function test_empty_special() { - bfs_diff rainbow -empty -} - -function test_gid() { - bfs_diff basic -gid "$(id -g)" -} - -function test_gid_plus() { - skip_if test "$(id -g)" -eq 0 - bfs_diff basic -gid +0 -} - -function test_gid_plus_plus() { - skip_if test "$(id -g)" -eq 0 - bfs_diff basic -gid ++0 -} - -function test_gid_minus() { - bfs_diff basic -gid "-$(($(id -g) + 1))" -} - -function test_gid_minus_plus() { - bfs_diff basic -gid "-+$(($(id -g) + 1))" -} - -function test_uid() { - bfs_diff basic -uid "$(id -u)" -} - -function test_uid_plus() { - skip_if test "$(id -u)" -eq 0 - bfs_diff basic -uid +0 -} - -function test_uid_plus_plus() { - skip_if test "$(id -u)" -eq 0 - bfs_diff basic -uid ++0 -} - -function test_uid_minus() { - bfs_diff basic -uid "-$(($(id -u) + 1))" -} - -function test_uid_minus_plus() { - bfs_diff basic -uid "-+$(($(id -u) + 1))" -} - -function test_newer() { - bfs_diff times -newer times/a -} - -function test_newer_link() { - bfs_diff times -newer times/l -} - -function test_anewer() { - bfs_diff times -anewer times/a -} - -function test_asince() { - bfs_diff times -asince 1991-12-14T00:01 -} - -function test_links() { - bfs_diff links -type f -links 2 -} - -function test_links_plus() { - bfs_diff links -type f -links +1 -} - -function test_links_minus() { - bfs_diff links -type f -links -2 -} - -function test_links_noarg() { - fail invoke_bfs links -links -} - -function test_links_empty() { - fail invoke_bfs links -links '' -} - -function test_links_negative() { - fail invoke_bfs links -links +-1 -} - -function test_links_invalid() { - fail invoke_bfs links -links ASDF -} - -function test_P() { - bfs_diff -P links/deeply/nested/dir -} - -function test_P_slash() { - bfs_diff -P links/deeply/nested/dir/ -} - -function test_H() { - bfs_diff -H links/deeply/nested/dir -} - -function test_H_slash() { - bfs_diff -H links/deeply/nested/dir/ -} - -function test_H_broken() { - bfs_diff -H links/broken -} - -function test_H_notdir() { - bfs_diff -H links/notdir -} - -function test_H_newer() { - bfs_diff -H times -newer times/l -} - -function test_H_loops() { - bfs_diff -H loops/deeply/nested/loop -} - -function test_L() { - bfs_diff -L links -} - -function test_L_broken() { - bfs_diff -H links/broken -} - -function test_L_notdir() { - bfs_diff -H links/notdir -} - -function test_L_loops() { - # POSIX says it's okay to either stop or keep going on seeing a filesystem - # loop, as long as a diagnostic is printed - local errors=$(invoke_bfs -L loops 2>&1 >/dev/null) - [ -n "$errors" ] -} - -function test_L_loops_continue() { - bfs_diff -L loops - [ $? -eq $EX_BFS ] -} - -function test_X() { - bfs_diff -X weirdnames - [ $? -eq $EX_BFS ] -} - -function test_follow() { - bfs_diff links -follow -} - -function test_L_depth() { - bfs_diff -L links -depth -} - -function test_samefile() { - bfs_diff links -samefile links/file -} - -function test_samefile_symlink() { - bfs_diff links -samefile links/symlink -} - -function test_H_samefile_symlink() { - bfs_diff -H links -samefile links/symlink -} - -function test_L_samefile_symlink() { - bfs_diff -L links -samefile links/symlink -} - -function test_samefile_broken() { - bfs_diff links -samefile links/broken -} - -function test_H_samefile_broken() { - bfs_diff -H links -samefile links/broken -} - -function test_L_samefile_broken() { - bfs_diff -L links -samefile links/broken -} - -function test_samefile_notdir() { - bfs_diff links -samefile links/notdir -} - -function test_H_samefile_notdir() { - bfs_diff -H links -samefile links/notdir -} - -function test_L_samefile_notdir() { - bfs_diff -L links -samefile links/notdir -} - -function test_xtype_l() { - bfs_diff links -xtype l -} - -function test_xtype_f() { - bfs_diff links -xtype f -} - -function test_L_xtype_l() { - bfs_diff -L links -xtype l -} - -function test_L_xtype_f() { - bfs_diff -L links -xtype f -} - -function test_xtype_multi() { - bfs_diff links -xtype f,d,c -} - -function test_xtype_reorder() { - # Make sure -xtype is not reordered in front of anything -- if -xtype runs - # before -links 100, it will report an ELOOP error - bfs_diff loops -links 100 -xtype l - invoke_bfs loops -links 100 -xtype l -} - -function test_xtype_depth() { - # Make sure -xtype is considered side-effecting for facts_when_impure - fail invoke_bfs loops -xtype l -depth 100 -} - -function test_iname() { - skip_unless invoke_bfs -quit -iname PATTERN - bfs_diff basic -iname '*F*' -} - -function test_ipath() { - skip_unless invoke_bfs -quit -ipath PATTERN - bfs_diff basic -ipath 'basic/*F*' -} - -function test_iwholename() { - skip_unless invoke_bfs -quit -iwholename PATTERN - bfs_diff basic -iwholename 'basic/*F*' -} - -function test_lname() { - bfs_diff links -lname '[aq]' -} - -function test_ilname() { - skip_unless invoke_bfs -quit -ilname PATTERN - bfs_diff links -ilname '[AQ]' -} - -function test_L_lname() { - bfs_diff -L links -lname '[aq]' -} - -function test_L_ilname() { - skip_unless invoke_bfs -quit -ilname PATTERN - bfs_diff -L links -ilname '[AQ]' -} - -function test_user_name() { - bfs_diff basic -user "$(id -un)" -} - -function test_user_id() { - bfs_diff basic -user "$(id -u)" -} - -function test_user_nouser() { - # Regression test: this was wrongly optimized to -false - bfs_diff basic -user "$(id -u)" \! -nouser -} - -function test_group_name() { - bfs_diff basic -group "$(id -gn)" -} - -function test_group_id() { - bfs_diff basic -group "$(id -g)" -} - -function test_group_nogroup() { - # Regression test: this was wrongly optimized to -false - bfs_diff basic -group "$(id -g)" \! -nogroup -} - -function test_daystart() { - bfs_diff basic -daystart -mtime 0 -} - -function test_daystart_twice() { - bfs_diff basic -daystart -daystart -mtime 0 -} - -function test_newerma() { - bfs_diff times -newerma times/a -} - -function test_newermt() { - bfs_diff times -newermt 1991-12-14T00:01 -} - -function test_newermt_epoch_minus_one() { - bfs_diff times -newermt 1969-12-31T23:59:59Z -} - -function test_newermt_invalid() { - fail invoke_bfs times -newermt not_a_date_time -} - -function test_newerma_nonexistent() { - fail invoke_bfs times -newerma basic/nonexistent -} - -function test_newermq() { - fail invoke_bfs times -newermq times/a -} - -function test_newerqm() { - fail invoke_bfs times -newerqm times/a -} - -function test_size() { - bfs_diff basic -type f -size 0 -} - -function test_size_plus() { - bfs_diff basic -type f -size +0 -} - -function test_size_bytes() { - bfs_diff basic -type f -size +0c -} - -function test_size_big() { - bfs_diff basic -size 9223372036854775807 -} - -function test_exec() { - bfs_diff basic -exec echo {} \; -} - -function test_exec_nonexistent() { - # Failure to execute the command should lead to an error message and - # non-zero exit status. See https://unix.stackexchange.com/q/704522/56202 - - local 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)) -} - -function test_exec_nopath() { - ( - unset PATH - invoke_bfs basic -exec echo {} \; >"$OUT" - ) - - sort_output - diff_output -} - -function test_exec_nothing() { - # Regression test: don't segfault on missing command - fail invoke_bfs basic -exec \; -} - -function test_exec_plus() { - bfs_diff basic -exec "$TESTS/sort-args.sh" {} + -} - -function test_exec_plus_nonexistent() { - local stderr=$(invoke_bfs basic -exec "$TESTS/nonexistent" {} + 2>&1 >/dev/null) - [ -n "$stderr" ] || return 1 - - bfs_diff basic -exec "$TESTS/nonexistent" {} + -print - (($? == EX_BFS)) -} - -function test_exec_plus_status() { - # -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)) -} - -function test_exec_plus_semicolon() { - # 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 \; -} - -function test_exec_substring() { - bfs_diff basic -exec echo '-{}-' \; -} - -function test_exec_flush() { - # IO streams should be flushed before executing programs - invoke_bfs basic -print0 -exec echo found \; | tr '\0' ' ' >"$OUT" - sort_output - diff_output -} - -function test_exec_flush_fail() { - # Failure to flush streams before exec should be caught - skip_unless test -e /dev/full - fail invoke_bfs basic -print0 -exec true \; >/dev/full -} - -function test_exec_flush_fprint() { - # Even non-stdstreams should be flushed - bfs_diff basic/a -fprint scratch/foo -exec cat scratch/foo \; -} - -function test_exec_flush_fprint_fail() { - skip_unless test -e /dev/full - fail invoke_bfs basic/a -fprint /dev/full -exec true \; -} - -function test_exec_plus_flush() { - invoke_bfs basic/a -print0 -exec echo found {} + >"$OUT" - diff_output -} - -function test_exec_plus_flush_fail() { - skip_unless test -e /dev/full - fail invoke_bfs basic/a -print0 -exec echo found {} + >/dev/full -} - -function test_execdir() { - bfs_diff basic -execdir echo {} \; -} - -function test_execdir_nonexistent() { - local stderr=$(invoke_bfs basic -execdir "$TESTS/nonexistent" {} \; 2>&1 >/dev/null) - [ -n "$stderr" ] || return 1 - - bfs_diff basic -print -execdir "$TESTS/nonexistent" {} \; -print - (($? == EX_BFS)) -} - -function test_execdir_plus() { - local tree=$(invoke_bfs -D tree 2>&1 -quit) - - if [[ "$tree" == *"-S dfs"* ]]; then - skip - fi - - bfs_diff basic -execdir "$TESTS/sort-args.sh" {} + -} - -function test_execdir_plus_nonexistent() { - local stderr=$(invoke_bfs basic -execdir "$TESTS/nonexistent" {} + 2>&1 >/dev/null) - [ -n "$stderr" ] || return 1 - - bfs_diff basic -execdir "$TESTS/nonexistent" {} + -print - (($? == EX_BFS)) -} - -function test_execdir_substring() { - bfs_diff basic -execdir echo '-{}-' \; -} - -function test_execdir_plus_semicolon() { - bfs_diff basic -execdir echo foo {} bar + baz \; -} - -function test_execdir_pwd() { - local TMP_REAL=$(cd "$TMP" && pwd) - local OFFSET=$((${#TMP_REAL} + 2)) - bfs_diff basic -execdir bash -c "pwd | cut -b$OFFSET-" \; -} - -function test_execdir_slash() { - # Don't prepend ./ for absolute paths in -execdir - bfs_diff / -maxdepth 0 -execdir echo {} \; -} - -function test_execdir_slash_pwd() { - bfs_diff / -maxdepth 0 -execdir pwd \; -} - -function test_execdir_slashes() { - bfs_diff /// -maxdepth 0 -execdir echo {} \; -} - -function test_execdir_ulimit() { - rm -rf scratch/* - mkdir -p scratch/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z - mkdir -p scratch/a/b/c/d/e/f/g/h/i/j/k/l/m/0/1/2/3/4/5/6/7/8/9/A/B/C - - closefrom 4 - ulimit -n 13 - bfs_diff scratch -execdir echo {} \; -} - -function test_weird_names() { - cd weirdnames - bfs_diff '-' '(-' '!-' ',' ')' './(' './!' \( \! -print -o -print \) -} - -function test_flag_weird_names() { - cd weirdnames - bfs_diff -L '-' '(-' '!-' ',' ')' './(' './!' \( \! -print -o -print \) -} - -function test_flag_comma() { - # , is a filename until a non-flag is seen - cd weirdnames - bfs_diff -L ',' -print -} - -function test_follow_comma() { - # , is an operator after a non-flag is seen - cd weirdnames - bfs_diff -follow ',' -print -} - -function test_fprint() { - invoke_bfs basic -fprint "$OUT" - sort_output - diff_output -} - -function test_fprint_duplicate() { - touchp scratch/$TEST.out - ln scratch/$TEST.out scratch/$TEST.hard - ln -s $TEST.out scratch/$TEST.soft - - invoke_bfs basic -fprint scratch/$TEST.out -fprint scratch/$TEST.hard -fprint scratch/$TEST.soft - sort scratch/$TEST.out >"$OUT" - diff_output -} - -function test_fprint_duplicate_stdout() { - invoke_bfs basic -fprint "$OUT" -print >"$OUT" - sort_output - diff_output -} - -function test_fprint_noarg() { - fail invoke_bfs basic -fprint -} - -function test_fprint_nonexistent() { - fail invoke_bfs basic -fprint scratch/nonexistent/path -} - -function test_fprint_truncate() { - printf "basic\nbasic\n" >"$OUT" - - invoke_bfs basic -maxdepth 0 -fprint "$OUT" - sort_output - diff_output -} - -function test_double_dash() { - cd basic - bfs_diff -- . -type f -} - -function test_flag_double_dash() { - cd basic - bfs_diff -L -- . -type f -} - -function test_ignore_readdir_race() { - rm -rf scratch/* - $TOUCH scratch/{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" {} \; -} - -function test_ignore_readdir_race_root() { - # Make sure -ignore_readdir_race doesn't suppress ENOENT at the root - fail invoke_bfs basic/nonexistent -ignore_readdir_race -} - -function test_ignore_readdir_race_notdir() { - # Check -ignore_readdir_race handling when a directory is replaced with a file - rm -rf scratch/* - touchp scratch/foo/bar - - invoke_bfs scratch -mindepth 1 -ignore_readdir_race -execdir rm -r {} \; -execdir $TOUCH {} \; -} - -function test_perm_000() { - bfs_diff perms -perm 000 -} - -function test_perm_000_minus() { - bfs_diff perms -perm -000 -} - -function test_perm_000_slash() { - bfs_diff perms -perm /000 -} - -function test_perm_000_plus() { - bfs_diff perms -perm +000 -} - -function test_perm_222() { - bfs_diff perms -perm 222 -} - -function test_perm_222_minus() { - bfs_diff perms -perm -222 -} - -function test_perm_222_slash() { - bfs_diff perms -perm /222 -} - -function test_perm_222_plus() { - bfs_diff perms -perm +222 -} - -function test_perm_644() { - bfs_diff perms -perm 644 -} - -function test_perm_644_minus() { - bfs_diff perms -perm -644 -} - -function test_perm_644_slash() { - bfs_diff perms -perm /644 -} - -function test_perm_644_plus() { - bfs_diff perms -perm +644 -} - -function test_perm_symbolic() { - bfs_diff perms -perm a+r,u=wX,g+wX-w -} - -function test_perm_symbolic_minus() { - bfs_diff perms -perm -a+r,u=wX,g+wX-w -} - -function test_perm_symbolic_slash() { - bfs_diff perms -perm /a+r,u=wX,g+wX-w -} - -function test_perm_symbolic_trailing_comma() { - fail invoke_bfs perms -perm a+r, -} - -function test_perm_symbolic_double_comma() { - fail invoke_bfs perms -perm a+r,,u+w -} - -function test_perm_symbolic_missing_action() { - fail invoke_bfs perms -perm a -} - -function test_perm_leading_plus_symbolic() { - bfs_diff perms -perm +rwx -} - -function test_perm_leading_plus_symbolic_minus() { - bfs_diff perms -perm -+rwx -} - -function test_perm_leading_plus_symbolic_slash() { - bfs_diff perms -perm /+rwx -} - -function test_permcopy() { - bfs_diff perms -perm u+rw,g+u-w,o=g -} - -function test_perm_setid() { - bfs_diff rainbow -perm -u+s -o -perm -g+s -} - -function test_perm_sticky() { - bfs_diff rainbow -perm -a+t -} - -function test_prune() { - bfs_diff basic -name foo -prune -} - -function test_prune_file() { - bfs_diff basic -print -name '?' -prune -} - -function test_prune_or_print() { - bfs_diff basic -name foo -prune -o -print -} - -function test_not_prune() { - bfs_diff basic \! \( -name foo -prune \) -} - -function test_ok_nothing() { - # Regression test: don't segfault on missing command - fail invoke_bfs basic -ok \; -} - -function test_ok_stdin() { - # -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 {} \; -} - -function test_okdir_stdin() { - # -okdir should *not* close stdin - yes | bfs_diff basic -okdir bash -c 'printf "%s? " "$1" && head -n1' bash {} \; -} - -function test_ok_plus_semicolon() { - # The -ok primary shall be equivalent to -exec, except that the use of a - # <plus-sign> to punctuate the end of the primary expression need not be - # supported, ... - # - # bfs chooses not to support it, for compatibility with most other find - # implementations. - - yes | bfs_diff basic -ok echo {} + \; -} - -function test_okdir_plus_semicolon() { - yes | bfs_diff basic -okdir echo {} + \; -} - -function test_delete() { - rm -rf scratch/* - touchp scratch/foo/bar/baz - - # Don't try to delete '.' - (cd scratch && invoke_bfs . -delete) - - bfs_diff scratch -} - -function test_delete_many() { - # Test for https://github.com/tavianator/bfs/issues/67 - - rm -rf scratch/* - mkdir scratch/foo - $TOUCH scratch/foo/{1..256} - - invoke_bfs scratch/foo -delete - bfs_diff scratch -} - -function test_L_delete() { - rm -rf scratch/* - mkdir scratch/foo - mkdir scratch/bar - ln -s ../foo scratch/bar/baz - - # Don't try to rmdir() a symlink - invoke_bfs -L scratch/bar -delete || return 1 - - bfs_diff scratch -} - -function test_rm() { - rm -rf scratch/* - touchp scratch/foo/bar/baz - - (cd scratch && invoke_bfs . -rm) - - bfs_diff scratch -} - -function test_regex() { - bfs_diff basic -regex 'basic/./.' -} - -function test_iregex() { - bfs_diff basic -iregex 'basic/[A-Z]/[a-z]' -} - -function test_regex_parens() { - cd weirdnames - bfs_diff . -regex '\./\((\)' -} - -function test_regex_error() { - fail invoke_bfs basic -regex '[' -} - -function test_regex_invalid_utf8() { - rm -rf scratch/* - - # Incomplete UTF-8 sequences - skip_unless touch scratch/$'\xC3' - skip_unless touch scratch/$'\xE2\x84' - skip_unless touch scratch/$'\xF0\x9F\x92' - - bfs_diff scratch -regex 'scratch/..' -} - -function test_E() { - cd weirdnames - bfs_diff -E . -regex '\./(\()' -} - -function test_regextype_posix_basic() { - cd weirdnames - bfs_diff -regextype posix-basic -regex '\./\((\)' -} - -function test_regextype_posix_extended() { - cd weirdnames - bfs_diff -regextype posix-extended -regex '\./(\()' -} - -function test_regextype_ed() { - cd weirdnames - bfs_diff -regextype ed -regex '\./\((\)' -} - -function test_regextype_emacs() { - skip_unless invoke_bfs -regextype emacs -quit - - bfs_diff basic -regextype emacs -regex '.*/\(f+o?o?\|bar\)' -} - -function test_regextype_grep() { - skip_unless invoke_bfs -regextype grep -quit - - bfs_diff basic -regextype grep -regex '.*/f\+o\?o\?' -} - -function test_regextype_sed() { - cd weirdnames - bfs_diff -regextype sed -regex '\./\((\)' -} - -function test_d_path() { - bfs_diff -d basic -} - -function test_path_d() { - bfs_diff basic -d -} - -function test_f() { - cd weirdnames - bfs_diff -f '-' -f '(' -} - -function test_s() { - invoke_bfs -s weirdnames -maxdepth 1 >"$OUT" - diff_output -} - -function test_hidden() { - bfs_diff weirdnames -hidden -} - -function test_hidden_root() { - cd weirdnames - bfs_diff . ./. ... ./... .../.. -hidden -} - -function test_nohidden() { - bfs_diff weirdnames -nohidden -} - -function test_nohidden_depth() { - bfs_diff weirdnames -depth -nohidden -} - -function test_depth_n() { - bfs_diff basic -depth 2 -} - -function test_depth_n_plus() { - bfs_diff basic -depth +2 -} - -function test_depth_n_minus() { - bfs_diff basic -depth -2 -} - -function test_depth_depth_n() { - bfs_diff basic -depth -depth 2 -} - -function test_depth_depth_n_plus() { - bfs_diff basic -depth -depth +2 -} - -function test_depth_depth_n_minus() { - bfs_diff basic -depth -depth -2 -} - -function test_depth_overflow() { - bfs_diff basic -depth -4294967296 -} - -function test_gid_name() { - bfs_diff basic -gid "$(id -gn)" -} - -function test_uid_name() { - bfs_diff basic -uid "$(id -un)" -} - -function test_mnewer() { - bfs_diff times -mnewer times/a -} - -function test_H_mnewer() { - bfs_diff -H times -mnewer times/l -} - -function test_msince() { - bfs_diff times -msince 1991-12-14T00:01 -} - -function test_mtime_units() { - bfs_diff times -mtime +500w400d300h200m100s -} - -function test_size_T() { - bfs_diff basic -type f -size 1T -} - -function test_quit() { - bfs_diff basic/g -print -name g -quit -} - -function test_quit_child() { - bfs_diff basic/g -print -name h -quit -} - -function test_quit_depth() { - bfs_diff basic/g -depth -print -name g -quit -} - -function test_quit_depth_child() { - bfs_diff basic/g -depth -print -name h -quit -} - -function test_quit_after_print() { - bfs_diff basic basic -print -quit -} - -function test_quit_before_print() { - bfs_diff basic basic -quit -print -} - -function test_quit_implicit_print() { - bfs_diff basic -name basic -o -quit -} - -function test_inum() { - bfs_diff basic -inum "$(inum basic/k/foo/bar)" -} - -function test_nogroup() { - bfs_diff basic -nogroup -} - -function test_nogroup_ulimit() { - closefrom 4 - ulimit -n 16 - bfs_diff deep -nogroup -} - -function test_nouser() { - bfs_diff basic -nouser -} - -function test_nouser_ulimit() { - closefrom 4 - ulimit -n 16 - bfs_diff deep -nouser -} - -function test_ls() { - invoke_bfs rainbow -ls >scratch/test_ls.out -} - -function test_L_ls() { - invoke_bfs -L rainbow -ls >scratch/test_L_ls.out -} - -function test_fls() { - invoke_bfs rainbow -fls scratch/test_fls.out -} - -function test_printf() { - bfs_diff basic -printf '%%p(%p) %%d(%d) %%f(%f) %%h(%h) %%H(%H) %%P(%P) %%m(%m) %%M(%M) %%y(%y)\n' -} - -function test_printf_empty() { - bfs_diff basic -printf '' -} - -function test_printf_slash() { - bfs_diff / -maxdepth 0 -printf '(%h)/(%f)\n' -} - -function test_printf_slashes() { - bfs_diff /// -maxdepth 0 -printf '(%h)/(%f)\n' -} - -function test_printf_trailing_slash() { - bfs_diff basic/ -printf '(%h)/(%f)\n' -} - -function test_printf_trailing_slashes() { - bfs_diff basic/// -printf '(%h)/(%f)\n' -} - -function test_printf_flags() { - bfs_diff basic -printf '|%- 10.10p| %+03d %#4m\n' -} - -function test_printf_types() { - bfs_diff loops -printf '(%p) (%l) %y %Y\n' -} - -function test_printf_escapes() { - bfs_diff basic -maxdepth 0 -printf '\18\118\1118\11118\n\cfoo' -} - -function test_printf_times() { - bfs_diff times -type f -printf '%p | %a %AY-%Am-%Ad %AH:%AI:%AS %T@ | %t %TY-%Tm-%Td %TH:%TI:%TS %T@\n' -} - -function test_printf_leak() { - # Memory leak regression test - bfs_diff basic -maxdepth 0 -printf '%p' -} - -function test_printf_nul() { - # NUL byte regression test - invoke_bfs basic/a basic/b -maxdepth 0 -printf '%h\0%f\n' >"$OUT" - diff_output -} - -function test_printf_w() { - # Birth times may not be supported, so just check that %w/%W/%B can be parsed - bfs_diff times -false -printf '%w %WY %BY\n' -} - -function test_printf_Y_error() { - rm -rf scratch/* - mkdir scratch/foo - chmod -x scratch/foo - ln -s foo/bar scratch/bar - - bfs_diff scratch -printf '(%p) (%l) %y %Y\n' - local ret=$? - - chmod +x scratch/foo - rm -rf scratch/* - - [ $ret -eq $EX_BFS ] -} - -function test_printf_H() { - bfs_diff basic links -printf '%%p(%p) %%d(%d) %%f(%f) %%h(%h) %%H(%H) %%P(%P) %%y(%y)\n' -} - -function test_printf_u_g_ulimit() { - closefrom 4 - ulimit -n 16 - [ "$(invoke_bfs deep -printf '%u %g\n' | uniq)" = "$(id -un) $(id -gn)" ] -} - -function test_printf_l_nonlink() { - bfs_diff links -printf '| %26p -> %-26l |\n' -} - -function test_printf_incomplete_escape() { - fail invoke_bfs basic -printf '\' -} - -function test_printf_invalid_escape() { - fail invoke_bfs basic -printf '\!' -} - -function test_printf_incomplete_format() { - fail invoke_bfs basic -printf '%' -} - -function test_printf_invalid_format() { - fail invoke_bfs basic -printf '%!' -} - -function test_printf_duplicate_flag() { - fail invoke_bfs basic -printf '%--p' -} - -function test_printf_must_be_numeric() { - fail invoke_bfs basic -printf '%+p' -} - -function test_printf_color() { - bfs_diff -color -path './rainbow*' -printf '%H %h %f %p %P %l\n' -} - -function test_printf_everything() { - local everything=(%{a,b,c,d,D,f,F,g,G,h,H,i,k,l,m,M,n,p,P,s,S,t,u,U,y,Y}) - everything+=(%{A,C,T}{%,+,@,a,A,b,B,c,C,d,D,e,F,g,G,h,H,I,j,k,l,m,M,n,p,r,R,s,S,t,T,u,U,V,w,W,x,X,y,Y,z,Z}) - - # Check if we have birth times - if ! fail invoke_bfs basic -printf '%w' -quit >/dev/null; then - everything+=(%w %{B,W}{%,+,@,a,A,b,B,c,C,d,D,e,F,g,G,h,H,I,j,k,l,m,M,n,p,r,R,s,S,t,T,u,U,V,w,W,x,X,y,Y,z,Z}) - fi - - invoke_bfs rainbow -printf "${everything[*]}\n" >/dev/null -} - -function test_fprintf() { - invoke_bfs basic -fprintf "$OUT" '%%p(%p) %%d(%d) %%f(%f) %%h(%h) %%H(%H) %%P(%P) %%m(%m) %%M(%M) %%y(%y)\n' - sort_output - diff_output -} - -function test_fprintf_nofile() { - fail invoke_bfs basic -fprintf -} - -function test_fprintf_noformat() { - fail invoke_bfs basic -fprintf /dev/null -} - -function test_fstype() { - fstype=$(invoke_bfs basic -maxdepth 0 -printf '%F\n') - bfs_diff basic -fstype "$fstype" -} - -function test_path_flag_expr() { - bfs_diff links/skip -H -type l -} - -function test_path_expr_flag() { - bfs_diff links/skip -type l -H -} - -function test_flag_expr_path() { - bfs_diff -H -type l links/skip -} - -function test_expr_flag_path() { - bfs_diff -type l -H links/skip -} - -function test_expr_path_flag() { - bfs_diff -type l links/skip -H -} - -function test_parens() { - bfs_diff basic \( -name '*f*' \) -} - -function test_bang() { - bfs_diff basic \! -name foo -} - -function test_not() { - bfs_diff basic -not -name foo -} - -function test_implicit_and() { - bfs_diff basic -name foo -type d -} - -function test_a() { - bfs_diff basic -name foo -a -type d -} - -function test_and() { - bfs_diff basic -name foo -and -type d -} - -function test_o() { - bfs_diff basic -name foo -o -type d -} - -function test_or() { - bfs_diff basic -name foo -or -type d -} - -function test_comma() { - bfs_diff basic -name '*f*' -print , -print -} - -function test_precedence() { - bfs_diff basic \( -name foo -type d -o -name bar -a -type f \) -print , \! -empty -type f -print -} - -function test_incomplete() { - fail invoke_bfs basic \( -} - -function test_missing_paren() { - fail invoke_bfs basic \( -print -} - -function test_extra_paren() { - fail invoke_bfs basic -print \) -} - -function test_color() { - bfs_diff rainbow -color -} - -function test_color_L() { - bfs_diff -L rainbow -color -} - -function test_color_rs_lc_rc_ec() { - LS_COLORS="rs=RS:lc=LC:rc=RC:ec=EC:" bfs_diff rainbow -color -} - -function test_color_escapes() { - LS_COLORS="lc=\e[:rc=\155\::ec=^[\x5B\x6d:" bfs_diff rainbow -color -} - -function test_color_nul() { - LS_COLORS="ec=\33[m\0:" invoke_bfs rainbow -color -maxdepth 0 >"$OUT" - diff_output -} - -function test_color_ln_target() { - LS_COLORS="ln=target:or=01;31:mi=01;33:" bfs_diff rainbow -color -} - -function test_color_L_ln_target() { - LS_COLORS="ln=target:or=01;31:mi=01;33:" bfs_diff -L rainbow -color -} - -function test_color_mh() { - LS_COLORS="mh=01:" bfs_diff rainbow -color -} - -function test_color_mh0() { - LS_COLORS="mh=00:" bfs_diff rainbow -color -} - -function test_color_or() { - LS_COLORS="or=01:" bfs_diff rainbow -color -} - -function test_color_mi() { - LS_COLORS="mi=01:" bfs_diff rainbow -color -} - -function test_color_or_mi() { - LS_COLORS="or=01;31:mi=01;33:" bfs_diff rainbow -color -} - -function test_color_or_mi0() { - LS_COLORS="or=01;31:mi=00:" bfs_diff rainbow -color -} - -function test_color_or0_mi() { - LS_COLORS="or=00:mi=01;33:" bfs_diff rainbow -color -} - -function test_color_or0_mi0() { - LS_COLORS="or=00:mi=00:" bfs_diff rainbow -color -} - -function test_color_su_sg0() { - LS_COLORS="su=37;41:sg=00:" bfs_diff rainbow -color -} - -function test_color_su0_sg() { - LS_COLORS="su=00:sg=30;43:" bfs_diff rainbow -color -} - -function test_color_su0_sg0() { - LS_COLORS="su=00:sg=00:" bfs_diff rainbow -color -} - -function test_color_st_tw_ow0() { - LS_COLORS="st=37;44:tw=40;32:ow=00:" bfs_diff rainbow -color -} - -function test_color_st_tw0_ow() { - LS_COLORS="st=37;44:tw=00:ow=34;42:" bfs_diff rainbow -color -} - -function test_color_st_tw0_ow0() { - LS_COLORS="st=37;44:tw=00:ow=00:" bfs_diff rainbow -color -} - -function test_color_st0_tw_ow() { - LS_COLORS="st=00:tw=40;32:ow=34;42:" bfs_diff rainbow -color -} - -function test_color_st0_tw_ow0() { - LS_COLORS="st=00:tw=40;32:ow=00:" bfs_diff rainbow -color -} - -function test_color_st0_tw0_ow() { - LS_COLORS="st=00:tw=00:ow=34;42:" bfs_diff rainbow -color -} - -function test_color_st0_tw0_ow0() { - LS_COLORS="st=00:tw=00:ow=00:" bfs_diff rainbow -color -} - -function test_color_ext() { - LS_COLORS="*.txt=01:" bfs_diff rainbow -color -} - -function test_color_ext0() { - LS_COLORS="*.txt=00:" bfs_diff rainbow -color -} - -function test_color_ext_override() { - LS_COLORS="*.tar.gz=01;31:*.TAR=01;32:*.gz=01;33:" bfs_diff rainbow -color -} - -function test_color_ext_underride() { - LS_COLORS="*.gz=01;33:*.TAR=01;32:*.tar.gz=01;31:" bfs_diff rainbow -color -} - -function test_color_missing_colon() { - LS_COLORS="*.txt=01" bfs_diff rainbow -color -} - -function test_color_no_stat() { - LS_COLORS="mh=0:ex=0:sg=0:su=0:st=0:ow=0:tw=0:*.txt=01:" bfs_diff rainbow -color -} - -function test_color_L_no_stat() { - LS_COLORS="mh=0:ex=0:sg=0:su=0:st=0:ow=0:tw=0:*.txt=01:" bfs_diff -L rainbow -color -} - -function test_color_star() { - # Regression test: don't segfault on LS_COLORS="*" - LS_COLORS="*" bfs_diff rainbow -color -} - -function test_color_ls() { - rm -rf scratch/* - touchp scratch/foo/bar/baz - ln -s foo/bar/baz scratch/link - ln -s foo/bar/nowhere scratch/broken - ln -s foo/bar/nowhere/nothing scratch/nested - ln -s foo/bar/baz/qux scratch/notdir - ln -s scratch/foo/bar scratch/relative - mkdir scratch/__bfs__ - ln -s /__bfs__/nowhere scratch/absolute - - LS_COLORS="or=01;31:" invoke_bfs scratch/{,link,broken,nested,notdir,relative,absolute} -color -type l -ls \ - | sed 's/.* -> //' \ - | sort >"$OUT" - - diff_output -} - -function test_deep() { - closefrom 4 - - ulimit -n 16 - bfs_diff deep -type f -exec bash -c 'echo "${1:0:6}/.../${1##*/} (${#1})"' bash {} \; -} - -function test_deep_strict() { - closefrom 4 - - # Not even enough fds to keep the root open - ulimit -n 7 - bfs_diff deep -type f -exec bash -c 'echo "${1:0:6}/.../${1##*/} (${#1})"' bash {} \; -} - -function test_exit() { - invoke_bfs basic -name foo -exit 42 - if [ $? -ne 42 ]; then - return 1 - fi - - invoke_bfs basic -name qux -exit 42 - if [ $? -ne 0 ]; then - return 1 - fi - - bfs_diff basic/g -print -name g -exit -} - -function test_exit_no_implicit_print() { - bfs_diff basic -not -name foo -o -exit -} - -function test_printx() { - bfs_diff weirdnames -printx -} - -function test_and_purity() { - # Regression test: (-a lhs(pure) rhs(always_false)) <==> rhs is only valid if rhs is pure - bfs_diff basic -name nonexistent \( -print , -false \) -} - -function test_or_purity() { - # Regression test: (-o lhs(pure) rhs(always_true)) <==> rhs is only valid if rhs is pure - bfs_diff basic -name '*' -o -print -} - -function test_double_negation() { - bfs_diff basic \! \! -name 'foo' -} - -function test_not_reachability() { - bfs_diff basic -print \! -quit -print -} - -function test_comma_reachability() { - bfs_diff basic -print -quit , -print -} - -function test_de_morgan_not() { - bfs_diff basic \! \( -name 'foo' -o \! -type f \) -} - -function test_de_morgan_and() { - bfs_diff basic \( \! -name 'foo' -a \! -type f \) -} - -function test_de_morgan_or() { - bfs_diff basic \( \! -name 'foo' -o \! -type f \) -} - -function test_and_false_or_true() { - # Test (-a lhs(always_true) -false) <==> (! lhs), - # (-o lhs(always_false) -true) <==> (! lhs) - bfs_diff basic -prune -false -o -true -} - -function test_comma_redundant_true() { - # Test (, lhs(always_true) -true) <==> lhs - bfs_diff basic -prune , -true -} - -function test_comma_redundant_false() { - # Test (, lhs(always_false) -false) <==> lhs - bfs_diff basic -print -not -prune , -false -} - -function test_data_flow_depth() { - bfs_diff basic -depth +1 -depth -4 -} - -function test_data_flow_group() { - bfs_diff basic \( -group "$(id -g)" -nogroup \) -o \( -group "$(id -g)" -o -nogroup \) -} - -function test_data_flow_user() { - bfs_diff basic \( -user "$(id -u)" -nouser \) -o \( -user "$(id -u)" -o -nouser \) -} - -function test_data_flow_hidden() { - bfs_diff basic \( -hidden -not -hidden \) -o \( -hidden -o -not -hidden \) -} - -function test_data_flow_sparse() { - bfs_diff basic \( -sparse -not -sparse \) -o \( -sparse -o -not -sparse \) -} - -function test_data_flow_type() { - bfs_diff basic \! \( -type f -o \! -type f \) -} - -function test_data_flow_and_swap() { - bfs_diff basic \! -type f -a -type d -} - -function test_data_flow_or_swap() { - bfs_diff basic \! \( -type f -o \! -type d \) -} - -function test_print_error() { - skip_unless test -e /dev/full - fail invoke_bfs basic -maxdepth 0 >/dev/full -} - -function test_fprint_error() { - skip_unless test -e /dev/full - fail invoke_bfs basic -maxdepth 0 -fprint /dev/full -} - -function test_fprint_noerror() { - # Regression test: /dev/full should not fail until actually written to - skip_unless test -e /dev/full - invoke_bfs basic -false -fprint /dev/full -} - -function test_fprint_error_stdout() { - skip_unless test -e /dev/full - fail invoke_bfs basic -maxdepth 0 -fprint /dev/full >/dev/full -} - -function test_fprint_error_stderr() { - skip_unless test -e /dev/full - fail invoke_bfs basic -maxdepth 0 -fprint /dev/full 2>/dev/full -} - -function test_print0() { - invoke_bfs basic/a basic/b -print0 >"$OUT" - diff_output -} - -function test_fprint0() { - invoke_bfs basic/a basic/b -fprint0 "$OUT" - diff_output -} - -function test_closed_stdin() { - bfs_diff basic <&- -} - -function test_ok_closed_stdin() { - bfs_diff basic -ok echo \; <&- -} - -function test_okdir_closed_stdin() { - bfs_diff basic -okdir echo {} \; <&- -} - -function test_closed_stdout() { - fail invoke_bfs basic >&- -} - -function test_closed_stderr() { - fail invoke_bfs basic >&- 2>&- -} - -function test_unique() { - bfs_diff links/{file,symlink,hardlink} -unique -} - -function test_unique_depth() { - bfs_diff basic -unique -depth -} - -function test_L_unique() { - bfs_diff -L links/{file,symlink,hardlink} -unique -} - -function test_L_unique_loops() { - bfs_diff -L loops/deeply/nested -unique -} - -function test_L_unique_depth() { - bfs_diff -L loops/deeply/nested -unique -depth -} - -function test_mount() { - 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 -mount - local ret=$? - - sudo umount scratch/mnt - return $ret -} - -function test_L_mount() { - 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 -mount - local ret=$? - - sudo umount scratch/mnt - return $ret -} - -function test_xdev() { - 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 - local ret=$? - - sudo umount scratch/mnt - return $ret -} - -function test_L_xdev() { - 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 - local ret=$? - - sudo umount scratch/mnt - return $ret -} - -function test_inum_mount() { - skip_unless test "$SUDO" - skip_if test "$UNAME" = "Darwin" - - rm -rf scratch/* - mkdir scratch/{foo,mnt} - sudo mount -t tmpfs tmpfs scratch/mnt - - bfs_diff scratch -inum "$(inum scratch/mnt)" - local ret=$? - - sudo umount scratch/mnt - return $ret -} - -function test_inum_bind_mount() { - skip_unless test "$SUDO" - skip_unless test "$UNAME" = "Linux" - - rm -rf scratch/* - $TOUCH scratch/{foo,bar} - sudo mount --bind scratch/{foo,bar} - - bfs_diff scratch -inum "$(inum scratch/bar)" - local ret=$? - - sudo umount scratch/bar - return $ret -} - -function test_type_bind_mount() { - 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 - local ret=$? - - sudo umount scratch/null - return $ret -} - -function test_xtype_bind_mount() { - skip_unless test "$SUDO" - skip_unless test "$UNAME" = "Linux" - - rm -rf scratch/* - $TOUCH scratch/{file,null} - sudo mount --bind /dev/null scratch/null - ln -s /dev/null scratch/link - - bfs_diff -L scratch -type c - local ret=$? - - sudo umount scratch/null - return $ret -} - -function test_inum_automount() { - # bfs shouldn't trigger automounts unless it descends into them - - skip_unless test "$SUDO" - skip_unless command -v systemd-mount &>/dev/null - - rm -rf scratch/* - mkdir scratch/{foo,mnt} - skip_unless sudo systemd-mount -A -o bind basic scratch/mnt - - local before=$(inum scratch/mnt) - bfs_diff scratch -inum "$before" -prune - local ret=$? - local after=$(inum scratch/mnt) - - sudo systemd-umount scratch/mnt - - ((ret == 0 && before == after)) -} - function set_acl() { case "$UNAME" in Darwin) @@ -3158,60 +618,6 @@ function set_acl() { esac } -function test_acl() { - rm -rf scratch/* - - skip_unless invoke_bfs scratch -quit -acl - - $TOUCH scratch/{normal,acl} - skip_unless set_acl scratch/acl - ln -s acl scratch/link - - bfs_diff scratch -acl -} - -function test_L_acl() { - rm -rf scratch/* - - skip_unless invoke_bfs scratch -quit -acl - - $TOUCH scratch/{normal,acl} - skip_unless set_acl scratch/acl - ln -s acl scratch/link - - bfs_diff -L scratch -acl -} - -function test_capable() { - skip_unless test "$SUDO" - skip_unless test "$UNAME" = "Linux" - - rm -rf scratch/* - - skip_unless invoke_bfs scratch -quit -capable - - $TOUCH scratch/{normal,capable} - sudo setcap all+ep scratch/capable - ln -s capable scratch/link - - bfs_diff scratch -capable -} - -function test_L_capable() { - skip_unless test "$SUDO" - skip_unless test "$UNAME" = "Linux" - - rm -rf scratch/* - - skip_unless invoke_bfs scratch -quit -capable - - $TOUCH scratch/{normal,capable} - sudo setcap all+ep scratch/capable - ln -s capable scratch/link - - bfs_diff -L scratch -capable -} - function make_xattrs() { rm -rf scratch/* @@ -3241,205 +647,8 @@ function make_xattrs() { esac } -function test_xattr() { - skip_unless invoke_bfs scratch -quit -xattr - skip_unless make_xattrs - bfs_diff scratch -xattr -} - -function test_L_xattr() { - skip_unless invoke_bfs scratch -quit -xattr - skip_unless make_xattrs - bfs_diff -L scratch -xattr -} - -function test_xattrname() { - skip_unless invoke_bfs scratch -quit -xattr - skip_unless make_xattrs - - case "$UNAME" in - Darwin|FreeBSD) - bfs_diff scratch -xattrname bfs_test - ;; - *) - bfs_diff scratch -xattrname security.bfs_test - ;; - esac -} - -function test_L_xattrname() { - skip_unless invoke_bfs scratch -quit -xattr - skip_unless make_xattrs - - case "$UNAME" in - Darwin|FreeBSD) - bfs_diff -L scratch -xattrname bfs_test - ;; - *) - bfs_diff -L scratch -xattrname security.bfs_test - ;; - esac -} - -function test_help() { - invoke_bfs -help | grep -E '\{...?\}' && return 1 - invoke_bfs -D help | grep -E '\{...?\}' && return 1 - invoke_bfs -S help | grep -E '\{...?\}' && return 1 - invoke_bfs -regextype help | grep -E '\{...?\}' && return 1 - - return 0 -} - -function test_version() { - invoke_bfs -version >/dev/null -} - -function test_warn() { - local stderr=$(invoke_bfs basic -warn -depth -prune 2>&1 >/dev/null) - [ -n "$stderr" ] -} - -function test_nowarn() { - local stderr=$(invoke_bfs basic -nowarn -depth -prune 2>&1 >/dev/null) - [ -z "$stderr" ] -} - -function test_typo() { - invoke_bfs -dikkiq 2>&1 | grep follow >/dev/null -} - -function test_D_multi() { - bfs_diff -D opt,tree,unknown basic -} - -function test_D_all() { - bfs_diff -D all basic -} - -function test_O0() { - bfs_diff -O0 basic -not \( -type f -not -type f \) -} - -function test_O1() { - bfs_diff -O1 basic -not \( -type f -not -type f \) -} - -function test_O2() { - bfs_diff -O2 basic -not \( -type f -not -type f \) -} - -function test_O3() { - bfs_diff -O3 basic -not \( -type f -not -type f \) -} - -function test_Ofast() { - bfs_diff -Ofast basic -not \( -xtype f -not -xtype f \) -} - -function test_S() { - invoke_bfs -S "$1" -s basic >"$OUT" - diff_output -} - -function test_S_bfs() { - test_S bfs -} - -function test_S_dfs() { - test_S dfs -} - -function test_S_ids() { - test_S ids -} - -function test_exclude_name() { - bfs_diff basic -exclude -name foo -} - -function test_exclude_depth() { - bfs_diff basic -depth -exclude -name foo -} - -function test_exclude_mindepth() { - bfs_diff basic -mindepth 3 -exclude -name foo -} - -function test_exclude_print() { - fail invoke_bfs basic -exclude -print -} - -function test_exclude_exclude() { - fail invoke_bfs basic -exclude -exclude -name foo -} - -function test_flags() { - skip_unless invoke_bfs scratch -quit -flags offline - - rm -rf scratch/* - - $TOUCH scratch/{foo,bar} - skip_unless chflags offline scratch/bar - - bfs_diff scratch -flags -offline,nohidden -} - -function test_files0_from_file() { - cd weirdnames - invoke_bfs -mindepth 1 -fprintf ../scratch/files0.in "%P\0" - bfs_diff -files0-from ../scratch/files0.in -} - -function test_files0_from_stdin() { - cd weirdnames - invoke_bfs -mindepth 1 -printf "%P\0" | bfs_diff -files0-from - -} - -function test_files0_from_none() { - printf "" | fail invoke_bfs -files0-from - -} - -function test_files0_from_empty() { - printf "\0" | fail invoke_bfs -files0-from - -} - -function test_files0_from_nowhere() { - fail invoke_bfs -files0-from -} - -function test_files0_from_nothing() { - fail invoke_bfs -files0-from basic/nonexistent -} - -function test_files0_from_ok() { - printf "basic\0" | fail invoke_bfs -files0-from - -ok echo {} \; -} - -function test_stderr_fails_silently() { - skip_unless test -e /dev/full - bfs_diff -D all basic 2>/dev/full -} - -function test_stderr_fails_loudly() { - skip_unless test -e /dev/full - fail invoke_bfs -D all basic -false -fprint /dev/full 2>/dev/full -} - -function test_unexpected_operator() { - fail invoke_bfs \! -o -print -} - -function test_and_incomplete() { - fail invoke_bfs -print -a -} - -function test_or_incomplete() { - fail invoke_bfs -print -o -} - -function test_comma_incomplete() { - fail invoke_bfs -print , -} +cd "$TMP" +set +e BOL='\n' EOL='\n' @@ -3450,7 +659,6 @@ function update_eol() { EOL="\\033[${COLUMNS}G " } - if [ "$VERBOSE_TESTS" ]; then BOL='' elif [ -t 1 ]; then @@ -3478,11 +686,12 @@ for TEST in "${enabled_tests[@]}"; do fi OUT="$TMP/$TEST.out" + mkdir -p "${OUT%/*}" if [ "$VERBOSE_ERRORS" ]; then - ("$TEST") + (. "$TESTS/$TEST.sh") else - ("$TEST") 2>"$TMP/stderr" + (. "$TESTS/$TEST.sh") 2>"$TMP/stderr" fi status=$? |