mirror of
https://https.git.savannah.gnu.org/git/findutils.git
synced 2026-01-26 15:39:06 +00:00
tests: add shell-style test framework
Borrow the 'tests' framework from GNU coreutils. This allows better shell-style tests with more control over stdin, stdout, stderr, signals, preparatory steps, cleanup, return code verification, root-only tests, etc. * .gitignore: Add entries for per-test *.log and *.trs files, and the 'test-suite.log'. * .x-update-copyright: Exempt 'tests/init.sh' as this comes from gnulib. * Makefile.am: Include 'tests/local.mk'. (EXTRA_DIST): Add 'tests/GNUmakefile'. (SUBDIRS): Move 'gnulib-tests' to the end, i.e., run our own tests first. (ALL_RECURSIVE_TARGETS): Initialize. (update-gnulib-to-latest): Copy 'tests/init.sh' from gnulib. * cfg.mk: Add some syntax-check rules. * init.cfg: Add file. * tests/GNUmakefile: Likewise. * tests/envvar-check: Likewise. * tests/init.sh: Likewise. * tests/lang-default: Likewise. * tests/local.mk: Likewise. * tests/misc/help-version.sh: Likewise. * tests/other-fs-tmpdir: Likewise. * tests/sample-test: Likewise. * tests/.gitignore: Likewise. * NEWS (Changes to the build process): Mention the new test framework.
This commit is contained in:
parent
763c4725fc
commit
f72b299cdd
@ -1,3 +1,4 @@
|
||||
^ChangeLog-2013$
|
||||
^COPYING$
|
||||
^bootstrap$
|
||||
^tests/init\.sh$
|
||||
|
||||
@ -28,13 +28,16 @@ EXTRA_DIST = \
|
||||
build-aux/git-version-gen \
|
||||
config.h.in \
|
||||
stamp-h.in \
|
||||
tests/GNUmakefile \
|
||||
tool-versions.txt
|
||||
|
||||
DISTCLEANFILES = tool-versions.txt
|
||||
|
||||
|
||||
# "gnulib-tests" is the gnulib unit test dir.
|
||||
SUBDIRS = gl gnulib-tests build-aux lib find xargs locate doc po m4
|
||||
SUBDIRS = gl build-aux lib find xargs locate doc po m4 gnulib-tests
|
||||
|
||||
ALL_RECURSIVE_TARGETS =
|
||||
|
||||
ACLOCAL_AMFLAGS = -I gl/m4 -I m4
|
||||
|
||||
@ -107,6 +110,7 @@ gnulib-sync update-gnulib-to-latest:
|
||||
&& git submodule foreach git pull origin master \
|
||||
&& cp -v gnulib/doc/COPYINGv3 COPYING \
|
||||
&& cp -v gnulib/build-aux/bootstrap bootstrap \
|
||||
&& cp -v gnulib/tests/init.sh tests/init.sh \
|
||||
&& git status --short -- gnulib COPYING bootstrap \
|
||||
)
|
||||
|
||||
@ -123,3 +127,5 @@ coverage-clean:
|
||||
done
|
||||
|
||||
clean-local: coverage-clean
|
||||
|
||||
include $(top_srcdir)/tests/local.mk
|
||||
|
||||
6
NEWS
6
NEWS
@ -145,6 +145,12 @@ The translation files in the PO directory are no longer version controlled;
|
||||
instead bootstrap auto-updates them from "translationproject.org" during a
|
||||
maintainer build.
|
||||
|
||||
A shell-style test framework borrowed from GNU coreutils has been added.
|
||||
This allows better tests with more control over stdin, stdout, stderr,
|
||||
signals, preparatory steps, cleanup, return code verification, root-only
|
||||
tests, etc.
|
||||
|
||||
|
||||
* Major changes in release 4.6.0, 2015-12-28
|
||||
|
||||
** Stable Release
|
||||
|
||||
129
cfg.mk
129
cfg.mk
@ -92,16 +92,62 @@ exclude_file_name_regexp--sc_bindtextdomain = \
|
||||
# cases where neither argument is a string literal.
|
||||
local-checks-to-skip += sc_prohibit_strcmp
|
||||
|
||||
# Ensure that each root-requiring test is run via the "check-root" rule.
|
||||
sc_root_tests:
|
||||
@t1=sc-root.expected; t2=sc-root.actual; \
|
||||
grep -nl '^ *require_root_$$' `$(VC_LIST) tests` | \
|
||||
sed 's|.*/tests/|tests/|' | sort > $$t1; \
|
||||
for t in $(all_root_tests); do echo $$t; done | sort > $$t2; \
|
||||
st=0; diff -u $$t1 $$t2 || st=1; \
|
||||
rm -f $$t1 $$t2; \
|
||||
exit $$st
|
||||
|
||||
# Ensure that all version-controlled test cases are listed in $(all_tests).
|
||||
sc_tests_list_consistency:
|
||||
@bs="\\"; \
|
||||
test_extensions_rx=`echo $(TEST_EXTENSIONS) \
|
||||
| sed -e "s/ /|/g" -e "s/$$bs./$$bs$$bs./g"`; \
|
||||
{ \
|
||||
for t in $(all_tests); do echo $$t; done; \
|
||||
cd $(top_srcdir); \
|
||||
$(SHELL) build-aux/vc-list-files tests \
|
||||
| grep -Ev '^tests/init\.sh$$' \
|
||||
| $(EGREP) "$$test_extensions_rx\$$"; \
|
||||
} | sort | uniq -u | grep . && exit 1; :
|
||||
|
||||
# Ensure that all version-controlled test scripts are executable.
|
||||
sc_tests_executable:
|
||||
@set -o noglob 2>/dev/null || set -f; \
|
||||
find_ext="-name '' "`printf -- "-o -name *%s " $(TEST_EXTENSIONS)`;\
|
||||
find $(srcdir)/tests \( $$find_ext \) \! -perm -u+x -print \
|
||||
| { sed "s|^$(srcdir)/||"; git ls-files $(srcdir)/tests/; } \
|
||||
| sort | uniq -d \
|
||||
| sed -e "s/^/$(ME): Please make test executable: /" | grep . \
|
||||
&& exit 1; :
|
||||
|
||||
# Avoid :>file which doesn't propagate errors
|
||||
sc_prohibit_colon_redirection:
|
||||
@cd $(srcdir)/tests && GIT_PAGER= git grep -n ': *>.*||' \
|
||||
&& { echo '$(ME): '"The leading colon in :> will hide errors" 1>&2; \
|
||||
exit 1; } \
|
||||
|| :
|
||||
|
||||
# Usage of error() with an exit constant, should instead use die(),
|
||||
# as that avoids warnings and may generate better code, due to being apparent
|
||||
# to the compiler that it doesn't return.
|
||||
sc_die_EXIT_FAILURE:
|
||||
@GIT_PAGER= git grep -E 'error \(.*_(FAILURE|INVALID)' \
|
||||
-- find lib locate xargs \
|
||||
@cd $(srcdir) \
|
||||
&& GIT_PAGER= git grep -E 'error \(.*_(FAILURE|INVALID)' \
|
||||
-- find lib locate xargs \
|
||||
&& { echo '$(ME): '"Use die() instead of error" 1>&2; \
|
||||
exit 1; } \
|
||||
|| :
|
||||
|
||||
sc_prohibit-skip:
|
||||
@prohibit='\|\| skip ' \
|
||||
halt='Use skip_ not skip' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Disallow the C99 printf size specifiers %z and %j as they're not portable.
|
||||
# The gnulib printf replacement does support them, however the printf
|
||||
# replacement is not currently explicitly depended on by the gnulib error()
|
||||
@ -114,6 +160,79 @@ sc_prohibit-c99-printf-format:
|
||||
&& { echo '$(ME): Use PRI*MAX instead of %j or %z' 1>&2; exit 1; } \
|
||||
|| :
|
||||
|
||||
# Ensure that tests don't use `cmd ... && fail=1` as that hides crashes.
|
||||
# The "exclude" expression allows common idioms like `test ... && fail=1`
|
||||
# and the 2>... portion allows commands that redirect stderr and so probably
|
||||
# independently check its contents and thus detect any crash messages.
|
||||
sc_prohibit_and_fail_1:
|
||||
@prohibit='&& fail=1' \
|
||||
exclude='(returns_|stat|kill|test |EGREP|grep|compare|2> *[^/])' \
|
||||
halt='&& fail=1 detected. Please use: returns_ 1 ... || fail=1' \
|
||||
in_vc_files='^tests/' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Ensure that env vars are not passed through returns_ as
|
||||
# that was seen to fail on FreeBSD /bin/sh at least
|
||||
sc_prohibit_env_returns:
|
||||
@prohibit='=[^ ]* returns_ ' \
|
||||
exclude='_ returns_ ' \
|
||||
halt='Passing env vars to returns_ is non portable' \
|
||||
in_vc_files='^tests/' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Use framework_failure_, not the old name without the trailing underscore.
|
||||
sc_prohibit_framework_failure:
|
||||
@prohibit='\<framework_''failure\>' \
|
||||
halt='use framework_failure_ instead' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Prohibit the use of `...` in tests/. Use $(...) instead.
|
||||
sc_prohibit_test_backticks:
|
||||
@prohibit='`' in_vc_files='^tests/' \
|
||||
halt='use $$(...), not `...` in tests/' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Ensure that compare is used to check empty files
|
||||
# so that the unexpected contents are displayed
|
||||
sc_prohibit_test_empty:
|
||||
@prohibit='test -s.*&&' in_vc_files='^tests/' \
|
||||
halt='use `compare /dev/null ...`, not `test -s ...` in tests/' \
|
||||
$(_sc_search_regexp)
|
||||
|
||||
# Ensure that tests call the get_min_ulimit_v_ function if using ulimit -v
|
||||
sc_prohibit_test_ulimit_without_require_:
|
||||
@cd $(srcdir) \
|
||||
&& (GIT_PAGER= git grep -l get_min_ulimit_v_ -- tests; \
|
||||
GIT_PAGER= git grep -l 'ulimit -v' -- tests) \
|
||||
| sort | uniq -u | grep . && { echo "$(ME): the above test(s)"\
|
||||
" should match get_min_ulimit_v_ with ulimit -v" 1>&2; exit 1; } || :
|
||||
|
||||
# Ensure that tests call the cleanup_ function if using background processes
|
||||
sc_prohibit_test_background_without_cleanup_:
|
||||
@cd $(srcdir) \
|
||||
&& (GIT_PAGER= git grep -El '( &$$|&[^&]*=\$$!)' -- tests; \
|
||||
GIT_PAGER= git grep -l 'cleanup_()' -- tests | sed p) \
|
||||
| sort | uniq -u | grep . && { echo "$(ME): the above test(s)"\
|
||||
" should use cleanup_ for background processes" 1>&2; exit 1; } || :
|
||||
|
||||
# Ensure that tests call the print_ver_ function for programs which are
|
||||
# actually used in that test.
|
||||
sc_prohibit_test_calls_print_ver_with_irrelevant_argument:
|
||||
@cd $(srcdir) \
|
||||
&& GIT_PAGER= git grep -w print_ver_ -- tests \
|
||||
| sed 's#:print_ver_##' \
|
||||
| { fail=0; \
|
||||
while read file name; do \
|
||||
for i in $$name; do \
|
||||
grep -w "$$i" $$file|grep -vw print_ver_|grep -q . \
|
||||
|| { fail=1; \
|
||||
echo "*** Test: $$file, offending: $$i." 1>&2; };\
|
||||
done; \
|
||||
done; \
|
||||
test $$fail = 0 || exit 1; \
|
||||
} || { echo "$(ME): the above test(s) call print_ver_ for" \
|
||||
"program(s) they don't use" 1>&2; exit 1; }
|
||||
|
||||
# Exempt the contents of any usage function from the following.
|
||||
_continued_string_col_1 = \
|
||||
s/^usage .*?\n}//ms;/\\\n\w/ and print ("$$ARGV\n"),$$e=1;END{$$e||=0;exit $$e}
|
||||
@ -143,6 +262,12 @@ sc_preprocessor_indentation:
|
||||
echo '$(ME): skipping test $@: cppi not installed' 1>&2; \
|
||||
fi
|
||||
|
||||
exclude_file_name_regexp--sc_prohibit_test_backticks = \
|
||||
^tests/(local\.mk|init\.sh)$$
|
||||
|
||||
# Now that we have better tests, make this the default.
|
||||
export VERBOSE = yes
|
||||
|
||||
# During 'make update-copyright', convert a sequence with gaps to the minimal
|
||||
# containing range.
|
||||
update-copyright-env = \
|
||||
|
||||
702
init.cfg
Normal file
702
init.cfg
Normal file
@ -0,0 +1,702 @@
|
||||
# This file is sourced by init.sh, *before* its initialization.
|
||||
|
||||
# Copyright (C) 2010-2019 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# This goes hand in hand with the "exec 9>&2;" in tests/Makefile.am's
|
||||
# TESTS_ENVIRONMENT definition.
|
||||
stderr_fileno_=9
|
||||
|
||||
# Having an unsearchable directory in PATH causes execve to fail with EACCES
|
||||
# when applied to an unresolvable program name, contrary to the desired ENOENT.
|
||||
# Avoid the problem by rewriting PATH to exclude unsearchable directories.
|
||||
# Also, if PATH lacks /sbin and/or /usr/sbin, append it/them.
|
||||
sanitize_path_()
|
||||
{
|
||||
# FIXME: remove double quotes around $IFS when all tests use init.sh.
|
||||
# They constitute a work-around for a bug in FreeBSD 8.1's /bin/sh.
|
||||
local saved_IFS="$IFS"
|
||||
IFS=:
|
||||
set -- $PATH
|
||||
IFS=$saved_IFS
|
||||
|
||||
local d d1
|
||||
local colon=
|
||||
local new_path=
|
||||
for d in "$@"; do
|
||||
test -z "$d" && d1=. || d1=$d
|
||||
if ls -d "$d1/." > /dev/null 2>&1; then
|
||||
new_path="$new_path$colon$d"
|
||||
colon=':'
|
||||
fi
|
||||
done
|
||||
|
||||
for d in /sbin /usr/sbin ; do
|
||||
case ":$new_path:" in
|
||||
*:$d:*) ;;
|
||||
*) new_path="$new_path:$d" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
PATH=$new_path
|
||||
export PATH
|
||||
}
|
||||
|
||||
getlimits_()
|
||||
{
|
||||
eval $(getlimits)
|
||||
test "$INT_MAX" || fatal_ "running getlimits"
|
||||
}
|
||||
|
||||
require_no_default_acl_()
|
||||
{
|
||||
if getfacl --version < /dev/null > /dev/null 2>&1; then
|
||||
getfacl "$1" | grep '^default:' && skip_ 'Default ACL detected'
|
||||
else
|
||||
ls -ld "$1" | grep '.........+' && skip_ 'ACL detected'
|
||||
fi
|
||||
}
|
||||
|
||||
require_acl_()
|
||||
{
|
||||
getfacl --version < /dev/null > /dev/null 2>&1 \
|
||||
&& setfacl --version < /dev/null > /dev/null 2>&1 \
|
||||
|| skip_ "This test requires getfacl and setfacl."
|
||||
|
||||
id -u bin > /dev/null 2>&1 \
|
||||
|| skip_ "This test requires a local user named bin."
|
||||
}
|
||||
|
||||
is_local_dir_()
|
||||
{
|
||||
test $# = 1 || framework_failure_
|
||||
df --local "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
require_mount_list_()
|
||||
{
|
||||
local mount_list_fail='cannot read table of mounted file systems'
|
||||
df --local 2>&1 | grep -F "$mount_list_fail" >/dev/null &&
|
||||
skip_ "$mount_list_fail"
|
||||
}
|
||||
|
||||
dump_mount_list_()
|
||||
{
|
||||
cat /proc/self/mountinfo ||
|
||||
cat /proc/self/mounts ||
|
||||
cat /proc/mounts ||
|
||||
cat /etc/mtab
|
||||
}
|
||||
|
||||
require_local_dir_()
|
||||
{
|
||||
require_mount_list_
|
||||
is_local_dir_ . ||
|
||||
skip_ "This test must be run on a local file system."
|
||||
}
|
||||
|
||||
require_selinux_()
|
||||
{
|
||||
# When in a chroot of an SELinux-enabled system, but with a mock-simulated
|
||||
# SELinux-*disabled* system, recognize that SELinux is disabled system wide:
|
||||
grep 'selinuxfs$' /proc/filesystems > /dev/null \
|
||||
|| skip_ "this system lacks SELinux support"
|
||||
|
||||
# Independent of whether SELinux is enabled system-wide,
|
||||
# the current file system may lack SELinux support.
|
||||
# Also the current build may have SELinux support disabled.
|
||||
case $(ls -Zd .) in
|
||||
'? .'|'unlabeled .')
|
||||
test -z "$CONFIG_HEADER" \
|
||||
&& framework_failure_ 'CONFIG_HEADER not defined'
|
||||
grep '^#define HAVE_SELINUX_SELINUX_H 1' "$CONFIG_HEADER" > /dev/null \
|
||||
&& selinux_missing_="(file) system" || selinux_missing_="build"
|
||||
skip_ "this $selinux_missing_ lacks SELinux support"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Return the SELinux type component if available
|
||||
get_selinux_type() { ls -Zd "$1" | sed -n 's/.*:\(.*_t\)[: ].*/\1/p'; }
|
||||
|
||||
# Whether SELinux Multi Level Security is enabled
|
||||
mls_enabled_() {
|
||||
sestatus 2>&1 |
|
||||
grep 'Policy MLS status:.*enabled' > /dev/null
|
||||
}
|
||||
|
||||
# Skip this test if we're not in SELinux "enforcing" mode.
|
||||
require_selinux_enforcing_()
|
||||
{
|
||||
require_selinux_
|
||||
test "$(getenforce)" = Enforcing \
|
||||
|| skip_ "This test is useful only with SELinux in Enforcing mode."
|
||||
}
|
||||
|
||||
require_smack_()
|
||||
{
|
||||
grep 'smackfs$' /proc/filesystems > /dev/null \
|
||||
|| skip_ "this system lacks SMACK support"
|
||||
|
||||
test "$(ls -Zd .)" != '? .' \
|
||||
|| skip_ "this file system lacks SMACK support"
|
||||
}
|
||||
|
||||
require_openat_support_()
|
||||
{
|
||||
# Skip this test if your system has neither the openat-style functions
|
||||
# nor /proc/self/fd support with which to emulate them.
|
||||
|
||||
test -z "$CONFIG_HEADER" \
|
||||
&& framework_failure_ 'CONFIG_HEADER not defined'
|
||||
|
||||
_skip=yes
|
||||
grep '^#define HAVE_OPENAT' "$CONFIG_HEADER" > /dev/null && _skip=no
|
||||
test -d /proc/self/fd && _skip=no
|
||||
if test $_skip = yes; then
|
||||
skip_ 'this system lacks openat support'
|
||||
fi
|
||||
}
|
||||
|
||||
# Return true if command runs with the
|
||||
# ulimit specified in the first argument
|
||||
ulimit_supported_()
|
||||
{
|
||||
local v
|
||||
v="$1"
|
||||
shift
|
||||
|
||||
(
|
||||
# Try to disable core dumps which may
|
||||
# occur with memory constraints
|
||||
trap '' SEGV; ulimit -c 0;
|
||||
|
||||
ulimit -v $v && "$@"
|
||||
) >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Determine the minimum required VM limit to run the given command.
|
||||
# Output that value to stdout ... to be used by the caller.
|
||||
# Return 0 in case of success, and a non-Zero value otherwise.
|
||||
get_min_ulimit_v_()
|
||||
{
|
||||
local v
|
||||
local page_size
|
||||
|
||||
# Increase result by this amount to avoid alignment issues
|
||||
page_size=$(getconf PAGESIZE || echo 4096)
|
||||
page_size=$(($page_size / 1024))
|
||||
|
||||
for v in $( seq 5000 5000 50000 ); do
|
||||
if ulimit_supported_ $v "$@"; then
|
||||
local prev_v
|
||||
prev_v=$v
|
||||
for v in $( seq $(($prev_v-1000)) -1000 1000 ); do
|
||||
ulimit_supported_ $v "$@" ||
|
||||
{
|
||||
ret_v=$((prev_v + $page_size))
|
||||
echo $ret_v
|
||||
return 0
|
||||
}
|
||||
prev_v=$v
|
||||
done
|
||||
fi
|
||||
done
|
||||
# The above did not find a working limit. Echo a very small number - just
|
||||
# in case the caller does not handle the non-Zero return value.
|
||||
echo 1; return 1
|
||||
}
|
||||
|
||||
require_readable_root_()
|
||||
{
|
||||
test -r / || skip_ "/ is not readable"
|
||||
}
|
||||
|
||||
# Skip the current test if strace is not available or doesn't work
|
||||
# with the named syscall. Usage: require_strace_ unlink
|
||||
require_strace_()
|
||||
{
|
||||
test $# = 1 || framework_failure_
|
||||
|
||||
strace -V < /dev/null > /dev/null 2>&1 ||
|
||||
skip_ 'no strace program'
|
||||
|
||||
strace -qe "$1" echo > /dev/null 2>&1 ||
|
||||
skip_ 'strace -qe "'"$1"'" does not work'
|
||||
|
||||
# On some linux/sparc64 systems, strace works fine on 32-bit executables,
|
||||
# but prints only one line of output for every 64-bit executable.
|
||||
strace -o log-help ls --help >/dev/null || framework_failure_
|
||||
n_lines_help=$(wc -l < log-help)
|
||||
rm -f log-help
|
||||
if test $n_lines_help = 0 || test $n_lines_help = 1; then
|
||||
skip_ 'strace produces no more than one line of output'
|
||||
fi
|
||||
}
|
||||
|
||||
# Skip the current test if valgrind doesn't work,
|
||||
# which could happen if not installed,
|
||||
# or hasn't support for the built architecture,
|
||||
# or hasn't appropriate error suppressions installed etc.
|
||||
require_valgrind_()
|
||||
{
|
||||
valgrind --error-exitcode=1 true 2>/dev/null ||
|
||||
skip_ "requires a working valgrind"
|
||||
}
|
||||
|
||||
# Skip the current test if setfacl doesn't work on the current file system,
|
||||
# which could happen if not installed, or if ACLs are not supported by the
|
||||
# kernel or the file system, or are turned off via mount options.
|
||||
#
|
||||
# Work around the following two issues:
|
||||
#
|
||||
# 1) setfacl maps ACLs into file permission bits if on "noacl" file systems.
|
||||
#
|
||||
# On file systems which do not support ACLs (e.g. ext4 mounted with -o noacl),
|
||||
# setfacl operates on the regular file permission bits, and only fails if the
|
||||
# given ACL spec does not fit into there. Thus, to test if ACLs really work
|
||||
# on the current file system, pass an ACL spec which can't be mapped that way.
|
||||
# "Default" ACLs (-d) seem to fulfill this requirement.
|
||||
#
|
||||
# 2) setfacl only invokes the underlying system call if the ACL would change.
|
||||
#
|
||||
# If the given ACL spec would not change the ACLs on the file, then setfacl
|
||||
# does not invoke the underlying system call - setxattr(). Therefore, to test
|
||||
# if setting ACLs really works on the current file system, call setfacl twice
|
||||
# with conflictive ACL specs.
|
||||
require_setfacl_()
|
||||
{
|
||||
local d='acltestdir_'
|
||||
mkdir $d || framework_failure_
|
||||
local f=0
|
||||
|
||||
setfacl -d -m user::r-x $d \
|
||||
&& setfacl -d -m user::rwx $d \
|
||||
|| f=1
|
||||
rm -rf $d || framework_failure_
|
||||
test $f = 0 \
|
||||
|| skip_ "setfacl does not work on the current file system"
|
||||
}
|
||||
|
||||
# Require a controlling input 'terminal'.
|
||||
require_controlling_input_terminal_()
|
||||
{
|
||||
have_input_tty=yes
|
||||
tty -s || have_input_tty=no
|
||||
test -t 0 || have_input_tty=no
|
||||
if test "$have_input_tty" = no; then
|
||||
skip_ 'requires controlling input terminal
|
||||
This test must have a controlling input "terminal", so it may not be
|
||||
run via "batch", "at", or "ssh". On some systems, it may not even be
|
||||
run in the background.'
|
||||
fi
|
||||
}
|
||||
|
||||
require_built_()
|
||||
{
|
||||
skip_=no
|
||||
for i in "$@"; do
|
||||
case " $built_programs " in
|
||||
*" $i "*) ;;
|
||||
*) echo "$i: not built" 1>&2; skip_=yes ;;
|
||||
esac
|
||||
done
|
||||
|
||||
test $skip_ = yes && skip_ "required program(s) not built"
|
||||
}
|
||||
|
||||
require_file_system_bytes_free_()
|
||||
{
|
||||
local req=$1
|
||||
local expr=$(stat -f --printf "$req / %S <= %a" .)
|
||||
$AWK "BEGIN{ exit !($expr) }" \
|
||||
|| skip_ "this test needs at least $req bytes of free space"
|
||||
}
|
||||
|
||||
uid_is_privileged_()
|
||||
{
|
||||
# Make sure id -u succeeds.
|
||||
my_uid=$(id -u) \
|
||||
|| { echo "$0: cannot run 'id -u'" 1>&2; return 1; }
|
||||
|
||||
# Make sure it gives valid output.
|
||||
case $my_uid in
|
||||
0) ;;
|
||||
*[!0-9]*)
|
||||
echo "$0: invalid output ('$my_uid') from 'id -u'" 1>&2
|
||||
return 1 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
get_process_status_()
|
||||
{
|
||||
sed -n '/^State:[ ]*\([[:alpha:]]\).*/s//\1/p' /proc/$1/status
|
||||
}
|
||||
|
||||
# Convert an ls-style permission string, like drwxr----x and -rw-r-x-wx
|
||||
# to the equivalent chmod --mode (-m) argument, (=,u=rwx,g=r,o=x and
|
||||
# =,u=rw,g=rx,o=wx). Ignore ACLs.
|
||||
rwx_to_mode_()
|
||||
{
|
||||
case $# in
|
||||
1) rwx=$1;;
|
||||
*) echo "$0: wrong number of arguments" 1>&2
|
||||
echo "Usage: $0 ls-style-mode-string" 1>&2
|
||||
return;;
|
||||
esac
|
||||
|
||||
case $rwx in
|
||||
[ld-][rwx-][rwx-][rwxsS-][rwx-][rwx-][rwxsS-][rwx-][rwx-][rwxtT-]) ;;
|
||||
[ld-][rwx-][rwx-][rwxsS-][rwx-][rwx-][rwxsS-][rwx-][rwx-][rwxtT-][+.]) ;;
|
||||
*) echo "$0: invalid mode string: $rwx" 1>&2; return;;
|
||||
esac
|
||||
|
||||
# Perform these conversions:
|
||||
# S s
|
||||
# s xs
|
||||
# T t
|
||||
# t xt
|
||||
# The 'T' and 't' ones are only valid for 'other'.
|
||||
s='s/S/@/;s/s/x@/;s/@/s/'
|
||||
t='s/T/@/;s/t/x@/;s/@/t/'
|
||||
|
||||
u=$(echo $rwx|sed 's/^.\(...\).*/,u=\1/;s/-//g;s/^,u=$//;'$s)
|
||||
g=$(echo $rwx|sed 's/^....\(...\).*/,g=\1/;s/-//g;s/^,g=$//;'$s)
|
||||
o=$(echo $rwx|sed 's/^.......\(...\).*/,o=\1/;s/-//g;s/^,o=$//;'$s';'$t)
|
||||
echo "=$u$g$o"
|
||||
}
|
||||
|
||||
skip_if_()
|
||||
{
|
||||
case $1 in
|
||||
root) skip_ must be run as root ;;
|
||||
non-root) skip_ must be run as non-root ;;
|
||||
*) ;; # FIXME?
|
||||
esac
|
||||
}
|
||||
|
||||
very_expensive_()
|
||||
{
|
||||
if test "$RUN_VERY_EXPENSIVE_TESTS" != yes; then
|
||||
skip_ 'very expensive: disabled by default
|
||||
This test is very expensive, so it is disabled by default.
|
||||
To run it anyway, rerun make check with the RUN_VERY_EXPENSIVE_TESTS
|
||||
environment variable set to yes. E.g.,
|
||||
|
||||
env RUN_VERY_EXPENSIVE_TESTS=yes make check
|
||||
|
||||
or use the shortcut target of the toplevel Makefile,
|
||||
|
||||
make check-very-expensive
|
||||
'
|
||||
fi
|
||||
}
|
||||
|
||||
expensive_()
|
||||
{
|
||||
if test "$RUN_EXPENSIVE_TESTS" != yes; then
|
||||
skip_ 'expensive: disabled by default
|
||||
This test is relatively expensive, so it is disabled by default.
|
||||
To run it anyway, rerun make check with the RUN_EXPENSIVE_TESTS
|
||||
environment variable set to yes. E.g.,
|
||||
|
||||
env RUN_EXPENSIVE_TESTS=yes make check
|
||||
|
||||
or use the shortcut target of the toplevel Makefile,
|
||||
|
||||
make check-expensive
|
||||
'
|
||||
fi
|
||||
}
|
||||
|
||||
# Test whether we can run our just-built root owned find,
|
||||
# i.e., that $NON_ROOT_USERNAME has access to the build directory.
|
||||
nonroot_has_perm_()
|
||||
{
|
||||
require_built_ chroot
|
||||
|
||||
local find_version=$(
|
||||
chroot --skip-chdir --user=$NON_ROOT_USERNAME / env PATH="$PATH" \
|
||||
find --version |
|
||||
sed -n '1s/.* //p'
|
||||
)
|
||||
case ":$find_version:" in
|
||||
:$PACKAGE_VERSION:) ;;
|
||||
*) return 1;;
|
||||
esac
|
||||
}
|
||||
|
||||
require_root_()
|
||||
{
|
||||
uid_is_privileged_ || skip_ "must be run as root"
|
||||
NON_ROOT_USERNAME=${NON_ROOT_USERNAME=nobody}
|
||||
NON_ROOT_GID=${NON_ROOT_GID=$(id -g $NON_ROOT_USERNAME)}
|
||||
|
||||
# When the current test invokes chroot, call nonroot_has_perm_
|
||||
# to check for a common problem.
|
||||
grep '^[ ]*chroot' "../$0" \
|
||||
&& { nonroot_has_perm_ \
|
||||
|| skip_ "user $NON_ROOT_USERNAME lacks execute permissions"; }
|
||||
}
|
||||
|
||||
skip_if_root_() { uid_is_privileged_ && skip_ "must be run as non-root"; }
|
||||
|
||||
# Set 'groups' to a space-separated list of at least two groups
|
||||
# of which the user is a member.
|
||||
require_membership_in_two_groups_()
|
||||
{
|
||||
test $# = 0 || framework_failure_
|
||||
|
||||
groups=${FINDUTILS_GROUPS-$( (id -G || /usr/xpg4/bin/id -G) 2>/dev/null)}
|
||||
case "$groups" in
|
||||
*' '*) ;;
|
||||
*) skip_ 'requires membership in two groups
|
||||
this test requires that you be a member of more than one group,
|
||||
but running '\''id -G'\'' either failed or found just one. If you really
|
||||
are a member of at least two groups, then rerun this test with
|
||||
FINDUTILS_GROUPS set in your environment to the space-separated list
|
||||
of group names or numbers. E.g.,
|
||||
|
||||
env FINDUTILS_GROUPS='\''users cdrom'\'' make check
|
||||
|
||||
'
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Is /proc/$PID/status supported?
|
||||
require_proc_pid_status_()
|
||||
{
|
||||
sleep 2 &
|
||||
local pid=$!
|
||||
sleep .5
|
||||
grep '^State:[ ]*[S]' /proc/$pid/status > /dev/null 2>&1 ||
|
||||
skip_ "/proc/$pid/status: missing or 'different'"
|
||||
kill $pid
|
||||
}
|
||||
|
||||
# Does trap support signal names?
|
||||
# Old versions of ash did not.
|
||||
require_trap_signame_()
|
||||
{
|
||||
(trap '' CHLD) || skip_ 'requires trap with signal name support'
|
||||
}
|
||||
|
||||
# Does kill support sending signal to whole group?
|
||||
# dash 0.5.8 at least does not.
|
||||
require_kill_group_()
|
||||
{
|
||||
kill -0 -- -1 || skip_ 'requires kill with group signalling support'
|
||||
}
|
||||
|
||||
# Return nonzero if the specified path is on a file system for
|
||||
# which FIEMAP support exists. Note some file systems (like ext3 and btrfs)
|
||||
# only support FIEMAP for files, not directories.
|
||||
fiemap_capable_()
|
||||
{
|
||||
if ! python < /dev/null; then
|
||||
warn_ 'fiemap_capable_: python missing: assuming not fiemap capable'
|
||||
return 1
|
||||
fi
|
||||
python "$abs_srcdir"/tests/fiemap-capable "$@"
|
||||
}
|
||||
|
||||
# Skip the current test if "." lacks d_type support.
|
||||
require_dirent_d_type_()
|
||||
{
|
||||
python < /dev/null \
|
||||
|| skip_ python missing: assuming no d_type support
|
||||
|
||||
python "$abs_srcdir"/tests/d_type-check \
|
||||
|| skip_ requires d_type support
|
||||
}
|
||||
|
||||
# Skip the current test if we lack Perl.
|
||||
require_perl_()
|
||||
{
|
||||
: ${PERL=perl}
|
||||
$PERL -e 'use warnings' > /dev/null 2>&1 \
|
||||
|| skip_ 'configure did not find a usable version of Perl'
|
||||
}
|
||||
|
||||
# Does the current (working-dir) file system support sparse files?
|
||||
require_sparse_support_()
|
||||
{
|
||||
test $# = 0 || framework_failure_
|
||||
# Test whether we can create a sparse file.
|
||||
# For example, on Darwin6.5 with a file system of type hfs, it's not possible.
|
||||
# NTFS requires 128K before a hole appears in a sparse file.
|
||||
t=sparse.$$
|
||||
dd bs=1 seek=128K of=$t < /dev/null 2> /dev/null
|
||||
set x $(du -sk $t)
|
||||
kb_size=$2
|
||||
rm -f $t
|
||||
if test $kb_size -ge 128; then
|
||||
skip_ 'this file system does not support sparse files'
|
||||
fi
|
||||
}
|
||||
|
||||
# Compile a shared lib using the GCC options for doing so.
|
||||
# Pass input and output file as parameters respectively.
|
||||
# Any other optional parmeters are passed to $CC.
|
||||
gcc_shared_()
|
||||
{
|
||||
local in=$1
|
||||
local out=$2
|
||||
shift 2 || return 1
|
||||
|
||||
$CC -Wall -shared --std=gnu99 -fPIC -O2 $* "$in" -o "$out" -ldl
|
||||
}
|
||||
|
||||
# There are a myriad of ways to build shared libs,
|
||||
# so we only consider running tests requiring shared libs,
|
||||
# on platforms that support building them as follows.
|
||||
require_gcc_shared_()
|
||||
{
|
||||
gcc_shared_ '-' 'd.so' -xc < /dev/null 2>&1 \
|
||||
|| skip_ '$CC -shared ... failed to build a shared lib'
|
||||
rm -f d.so
|
||||
}
|
||||
|
||||
mkfifo_or_skip_()
|
||||
{
|
||||
test $# = 1 || framework_failure_
|
||||
if ! mkfifo "$1"; then
|
||||
# Make an exception of this case -- usually we interpret framework-creation
|
||||
# failure as a test failure. However, in this case, when running on a SunOS
|
||||
# system using a disk NFS mounted from OpenBSD, the above fails like this:
|
||||
# mkfifo: cannot make fifo 'fifo-10558': Not owner
|
||||
skip_ 'unable to create a fifo'
|
||||
fi
|
||||
}
|
||||
|
||||
# Disable the current test if the working directory seems to have
|
||||
# the setgid bit set.
|
||||
skip_if_setgid_()
|
||||
{
|
||||
setgid_tmpdir=setgid-$$
|
||||
(umask 77; mkdir $setgid_tmpdir)
|
||||
perms=$(stat --printf %A $setgid_tmpdir)
|
||||
rmdir $setgid_tmpdir
|
||||
case $perms in
|
||||
drwx------);;
|
||||
drwxr-xr-x);; # Windows98 + DJGPP 2.03
|
||||
*) skip_ 'this directory has the setgid bit set';;
|
||||
esac
|
||||
}
|
||||
|
||||
# Skip if files are created with a different group to the current user
|
||||
# This can happen due to a setgid dir, or by some other mechanism on OS X:
|
||||
# https://unix.stackexchange.com/q/63865
|
||||
# https://bugs.gnu.org/14024#41
|
||||
skip_if_nondefault_group_()
|
||||
{
|
||||
touch grp.$$
|
||||
gen_ug=$(stat -c '%u:%g' grp.$$)
|
||||
rm grp.$$
|
||||
test "$gen_ug" = "$(id -ru):$(id -rg)" ||
|
||||
skip_ 'Files are created with a different gid'
|
||||
}
|
||||
|
||||
skip_if_mcstransd_is_running_()
|
||||
{
|
||||
test $# = 0 || framework_failure_
|
||||
|
||||
# When mcstransd is running, you'll see only the 3-component
|
||||
# version of file-system context strings. Detect that,
|
||||
# and if it's running, skip this test.
|
||||
__ctx=$(stat --printf='%C\n' .) || framework_failure_
|
||||
case $__ctx in
|
||||
*:*:*:*) __ctx_ok=1 ;; # four components is ok
|
||||
*:*:*) # three components is ok too if there is no MLS
|
||||
mls_enabled_ || __ctx_ok=1 ;;
|
||||
esac
|
||||
|
||||
test "$__ctx_ok" ||
|
||||
skip_ "unexpected context '$__ctx'; turn off mcstransd"
|
||||
}
|
||||
|
||||
# Skip the current test if umask doesn't work as usual.
|
||||
# This test should be run in the temporary directory that ends
|
||||
# up being removed via the trap commands.
|
||||
working_umask_or_skip_()
|
||||
{
|
||||
umask 022
|
||||
touch file1 file2
|
||||
chmod 644 file2
|
||||
perms=$(ls -l file1 file2 | sed 's/ .*//' | uniq)
|
||||
rm -f file1 file2
|
||||
|
||||
case $perms in
|
||||
*'
|
||||
'*) skip_ 'your build directory has unusual umask semantics'
|
||||
esac
|
||||
}
|
||||
|
||||
# Retry a function requiring a sufficient delay to _pass_
|
||||
# using a truncated exponential backoff method.
|
||||
# Example: retry_delay_ dd_reblock_1 .1 6
|
||||
# This example will call the dd_reblock_1 function with
|
||||
# an initial delay of .1 second and call it at most 6 times
|
||||
# with a max delay of 3.2s (doubled each time), or a total of 6.3s
|
||||
# Note ensure you do _not_ quote the parameter to GNU sleep in
|
||||
# your function, as it may contain separate values that sleep
|
||||
# needs to accumulate.
|
||||
# Further function arguments will be forwarded to the test function.
|
||||
retry_delay_()
|
||||
{
|
||||
local test_func=$1
|
||||
local init_delay=$2
|
||||
local max_n_tries=$3
|
||||
shift 3 || return 1
|
||||
|
||||
local attempt=1
|
||||
local num_sleeps=$attempt
|
||||
local time_fail
|
||||
while test $attempt -le $max_n_tries; do
|
||||
local delay=$($AWK -v n=$num_sleeps -v s="$init_delay" \
|
||||
'BEGIN { print s * n }')
|
||||
"$test_func" "$delay" "$@" && { time_fail=0; break; } || time_fail=1
|
||||
attempt=$(expr $attempt + 1)
|
||||
num_sleeps=$(expr $num_sleeps '*' 2)
|
||||
done
|
||||
test "$time_fail" = 0
|
||||
}
|
||||
|
||||
# Call this with a list of programs under test immediately after
|
||||
# sourcing init.sh.
|
||||
print_ver_()
|
||||
{
|
||||
require_built_ "$@"
|
||||
if test "$VERBOSE" = yes; then
|
||||
local i
|
||||
for i in $*; do
|
||||
env $i --version
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
# Are we running on GNU/Hurd?
|
||||
require_gnu_()
|
||||
{
|
||||
test "$(uname)" = GNU \
|
||||
|| skip_ 'not running on GNU/Hurd'
|
||||
}
|
||||
|
||||
# Prepend all our source directories to PATH.
|
||||
path_prepend_ "${srcdir=.}/find" "${srcdir=.}/locate" "${srcdir=.}/xargs"
|
||||
|
||||
sanitize_path_
|
||||
3
tests/.gitignore
vendored
Normal file
3
tests/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
/*/*.log
|
||||
/*/*.trs
|
||||
/test-suite.log
|
||||
20
tests/GNUmakefile
Normal file
20
tests/GNUmakefile
Normal file
@ -0,0 +1,20 @@
|
||||
# Provide a compatibility layer so that the commands used before the
|
||||
# conversion of tests/ to non-recursive make still work. To do that, we
|
||||
# must rerun the "make check" from the parent, and with tests/ prefixed
|
||||
# onto any TESTS values. The SUBDIRS=. is to prevent the top-level check
|
||||
# rules from descending into e.g., gnulib-test/.
|
||||
|
||||
.PHONY: all
|
||||
all:
|
||||
@echo 'tests/GNUmakefile: did you mean to make "check"?' 1>&2
|
||||
@exit 1
|
||||
|
||||
ifeq ($(TESTS),)
|
||||
tests =
|
||||
else
|
||||
tests = TESTS=$(addprefix tests/,$(TESTS))
|
||||
endif
|
||||
|
||||
.PHONY: check
|
||||
check:
|
||||
cd .. && $(MAKE) $@ $(tests) SUBDIRS=.
|
||||
58
tests/envvar-check
Normal file
58
tests/envvar-check
Normal file
@ -0,0 +1,58 @@
|
||||
# -*- sh -*-
|
||||
# Check environment variables for sane values while testing.
|
||||
|
||||
# Copyright (C) 2000-2019 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
|
||||
as_unset=unset
|
||||
else
|
||||
as_unset=false
|
||||
fi
|
||||
|
||||
envvar_check_fail=0
|
||||
vars='
|
||||
_POSIX2_VERSION
|
||||
_STDBUF_E
|
||||
_STDBUF_I
|
||||
_STDBUF_O
|
||||
BASH_ENV
|
||||
BLOCKSIZE
|
||||
BLOCK_SIZE
|
||||
CDPATH
|
||||
COLUMNS
|
||||
ENV
|
||||
LANGUAGE
|
||||
POSIXLY_CORRECT
|
||||
QUOTING_STYLE
|
||||
SIMPLE_BACKUP_SUFFIX
|
||||
TABSIZE
|
||||
TERM
|
||||
COLORTERM
|
||||
TIME_STYLE
|
||||
TMPDIR
|
||||
VERSION_CONTROL
|
||||
'
|
||||
for var in $vars
|
||||
do
|
||||
$as_unset $var
|
||||
if eval test \"\${$var+set}\" = set; then
|
||||
echo "$0: the $var environment variable is set --" \
|
||||
' unset it and rerun this test' >&2
|
||||
envvar_check_fail=1
|
||||
fi
|
||||
done
|
||||
|
||||
test "$envvar_check_fail" = 1 && exit 1
|
||||
618
tests/init.sh
Executable file
618
tests/init.sh
Executable file
@ -0,0 +1,618 @@
|
||||
# source this file; set up for tests
|
||||
|
||||
# Copyright (C) 2009-2019 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# Using this file in a test
|
||||
# =========================
|
||||
#
|
||||
# The typical skeleton of a test looks like this:
|
||||
#
|
||||
# #!/bin/sh
|
||||
# . "${srcdir=.}/init.sh"; path_prepend_ .
|
||||
# Execute some commands.
|
||||
# Note that these commands are executed in a subdirectory, therefore you
|
||||
# need to prepend "../" to relative filenames in the build directory.
|
||||
# Note that the "path_prepend_ ." is useful only if the body of your
|
||||
# test invokes programs residing in the initial directory.
|
||||
# For example, if the programs you want to test are in src/, and this test
|
||||
# script is named tests/test-1, then you would use "path_prepend_ ../src",
|
||||
# or perhaps export PATH='$(abs_top_builddir)/src$(PATH_SEPARATOR)'"$$PATH"
|
||||
# to all tests via automake's TESTS_ENVIRONMENT.
|
||||
# Set the exit code 0 for success, 77 for skipped, or 1 or other for failure.
|
||||
# Use the skip_ and fail_ functions to print a diagnostic and then exit
|
||||
# with the corresponding exit code.
|
||||
# Exit $?
|
||||
|
||||
# Executing a test that uses this file
|
||||
# ====================================
|
||||
#
|
||||
# Running a single test:
|
||||
# $ make check TESTS=test-foo.sh
|
||||
#
|
||||
# Running a single test, with verbose output:
|
||||
# $ make check TESTS=test-foo.sh VERBOSE=yes
|
||||
#
|
||||
# Running a single test, keeping the temporary directory:
|
||||
# $ make check TESTS=test-foo.sh KEEP=yes
|
||||
#
|
||||
# Running a single test, with single-stepping:
|
||||
# 1. Go into a sub-shell:
|
||||
# $ bash
|
||||
# 2. Set relevant environment variables from TESTS_ENVIRONMENT in the
|
||||
# Makefile:
|
||||
# $ export srcdir=../../tests # this is an example
|
||||
# 3. Execute the commands from the test, copy&pasting them one by one:
|
||||
# $ . "$srcdir/init.sh"; path_prepend_ .
|
||||
# ...
|
||||
# 4. Finally
|
||||
# $ exit
|
||||
|
||||
ME_=`expr "./$0" : '.*/\(.*\)$'`
|
||||
|
||||
# Prepare PATH_SEPARATOR.
|
||||
# The user is always right.
|
||||
if test "${PATH_SEPARATOR+set}" != set; then
|
||||
# Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which
|
||||
# contains only /bin. Note that ksh looks also at the FPATH variable,
|
||||
# so we have to set that as well for the test.
|
||||
PATH_SEPARATOR=:
|
||||
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \
|
||||
&& { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \
|
||||
|| PATH_SEPARATOR=';'
|
||||
}
|
||||
fi
|
||||
|
||||
# We use a trap below for cleanup. This requires us to go through
|
||||
# hoops to get the right exit status transported through the handler.
|
||||
# So use 'Exit STATUS' instead of 'exit STATUS' inside of the tests.
|
||||
# Turn off errexit here so that we don't trip the bug with OSF1/Tru64
|
||||
# sh inside this function.
|
||||
Exit () { set +e; (exit $1); exit $1; }
|
||||
|
||||
# Print warnings (e.g., about skipped and failed tests) to this file number.
|
||||
# Override by defining to say, 9, in init.cfg, and putting say,
|
||||
# export ...ENVVAR_SETTINGS...; $(SHELL) 9>&2
|
||||
# in the definition of TESTS_ENVIRONMENT in your tests/Makefile.am file.
|
||||
# This is useful when using automake's parallel tests mode, to print
|
||||
# the reason for skip/failure to console, rather than to the .log files.
|
||||
: ${stderr_fileno_=2}
|
||||
|
||||
# Note that correct expansion of "$*" depends on IFS starting with ' '.
|
||||
# Always write the full diagnostic to stderr.
|
||||
# When stderr_fileno_ is not 2, also emit the first line of the
|
||||
# diagnostic to that file descriptor.
|
||||
warn_ ()
|
||||
{
|
||||
# If IFS does not start with ' ', set it and emit the warning in a subshell.
|
||||
case $IFS in
|
||||
' '*) printf '%s\n' "$*" >&2
|
||||
test $stderr_fileno_ = 2 \
|
||||
|| { printf '%s\n' "$*" | sed 1q >&$stderr_fileno_ ; } ;;
|
||||
*) (IFS=' '; warn_ "$@");;
|
||||
esac
|
||||
}
|
||||
fail_ () { warn_ "$ME_: failed test: $@"; Exit 1; }
|
||||
skip_ () { warn_ "$ME_: skipped test: $@"; Exit 77; }
|
||||
fatal_ () { warn_ "$ME_: hard error: $@"; Exit 99; }
|
||||
framework_failure_ () { warn_ "$ME_: set-up failure: $@"; Exit 99; }
|
||||
|
||||
# This is used to simplify checking of the return value
|
||||
# which is useful when ensuring a command fails as desired.
|
||||
# I.e., just doing `command ... &&fail=1` will not catch
|
||||
# a segfault in command for example. With this helper you
|
||||
# instead check an explicit exit code like
|
||||
# returns_ 1 command ... || fail
|
||||
returns_ () {
|
||||
# Disable tracing so it doesn't interfere with stderr of the wrapped command
|
||||
{ set +x; } 2>/dev/null
|
||||
|
||||
local exp_exit="$1"
|
||||
shift
|
||||
"$@"
|
||||
test $? -eq $exp_exit && ret_=0 || ret_=1
|
||||
|
||||
if test "$VERBOSE" = yes && test "$gl_set_x_corrupts_stderr_" = false; then
|
||||
set -x
|
||||
fi
|
||||
{ return $ret_; } 2>/dev/null
|
||||
}
|
||||
|
||||
# Sanitize this shell to POSIX mode, if possible.
|
||||
DUALCASE=1; export DUALCASE
|
||||
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
|
||||
emulate sh
|
||||
NULLCMD=:
|
||||
alias -g '${1+"$@"}'='"$@"'
|
||||
setopt NO_GLOB_SUBST
|
||||
else
|
||||
case `(set -o) 2>/dev/null` in
|
||||
*posix*) set -o posix ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# We require $(...) support unconditionally.
|
||||
# We require non-surprising "local" semantics (this eliminates dash).
|
||||
# This takes the admittedly draconian step of eliminating dash, because the
|
||||
# assignment tab=$(printf '\t') works fine, yet preceding it with "local "
|
||||
# transforms it into an assignment that sets the variable to the empty string.
|
||||
# That is too counter-intuitive, and can lead to subtle run-time malfunction.
|
||||
# The example below is less subtle in that with dash, it evokes the run-time
|
||||
# exception "dash: 1: local: 1: bad variable name".
|
||||
# We require a few additional shell features only when $EXEEXT is nonempty,
|
||||
# in order to support automatic $EXEEXT emulation:
|
||||
# - hyphen-containing alias names
|
||||
# - we prefer to use ${var#...} substitution, rather than having
|
||||
# to work around lack of support for that feature.
|
||||
# The following code attempts to find a shell with support for these features.
|
||||
# If the current shell passes the test, we're done. Otherwise, test other
|
||||
# shells until we find one that passes. If one is found, re-exec it.
|
||||
# If no acceptable shell is found, skip the current test.
|
||||
#
|
||||
# The "...set -x; P=1 true 2>err..." test is to disqualify any shell that
|
||||
# emits "P=1" into err, as /bin/sh from SunOS 5.11 and OpenBSD 4.7 do.
|
||||
#
|
||||
# Use "9" to indicate success (rather than 0), in case some shell acts
|
||||
# like Solaris 10's /bin/sh but exits successfully instead of with status 2.
|
||||
|
||||
# Eval this code in a subshell to determine a shell's suitability.
|
||||
# 10 - passes all tests; ok to use
|
||||
# 9 - ok, but enabling "set -x" corrupts app stderr; prefer higher score
|
||||
# ? - not ok
|
||||
gl_shell_test_script_='
|
||||
test $(echo y) = y || exit 1
|
||||
f_local_() { local v=1; }; f_local_ || exit 1
|
||||
f_dash_local_fail_() { local t=$(printf " 1"); }; f_dash_local_fail_
|
||||
score_=10
|
||||
if test "$VERBOSE" = yes; then
|
||||
test -n "$( (exec 3>&1; set -x; P=1 true 2>&3) 2> /dev/null)" && score_=9
|
||||
fi
|
||||
test -z "$EXEEXT" && exit $score_
|
||||
shopt -s expand_aliases
|
||||
alias a-b="echo zoo"
|
||||
v=abx
|
||||
test ${v%x} = ab \
|
||||
&& test ${v#a} = bx \
|
||||
&& test $(a-b) = zoo \
|
||||
&& exit $score_
|
||||
'
|
||||
|
||||
if test "x$1" = "x--no-reexec"; then
|
||||
shift
|
||||
else
|
||||
# Assume a working shell. Export to subshells (setup_ needs this).
|
||||
gl_set_x_corrupts_stderr_=false
|
||||
export gl_set_x_corrupts_stderr_
|
||||
|
||||
# Record the first marginally acceptable shell.
|
||||
marginal_=
|
||||
|
||||
# Search for a shell that meets our requirements.
|
||||
for re_shell_ in __current__ "${CONFIG_SHELL:-no_shell}" \
|
||||
/bin/sh bash dash zsh pdksh fail
|
||||
do
|
||||
test "$re_shell_" = no_shell && continue
|
||||
|
||||
# If we've made it all the way to the sentinel, "fail" without
|
||||
# finding even a marginal shell, skip this test.
|
||||
if test "$re_shell_" = fail; then
|
||||
test -z "$marginal_" && skip_ failed to find an adequate shell
|
||||
re_shell_=$marginal_
|
||||
break
|
||||
fi
|
||||
|
||||
# When testing the current shell, simply "eval" the test code.
|
||||
# Otherwise, run it via $re_shell_ -c ...
|
||||
if test "$re_shell_" = __current__; then
|
||||
# 'eval'ing this code makes Solaris 10's /bin/sh exit with
|
||||
# $? set to 2. It does not evaluate any of the code after the
|
||||
# "unexpected" first '('. Thus, we must run it in a subshell.
|
||||
( eval "$gl_shell_test_script_" ) > /dev/null 2>&1
|
||||
else
|
||||
"$re_shell_" -c "$gl_shell_test_script_" 2>/dev/null
|
||||
fi
|
||||
|
||||
st_=$?
|
||||
|
||||
# $re_shell_ works just fine. Use it.
|
||||
if test $st_ = 10; then
|
||||
gl_set_x_corrupts_stderr_=false
|
||||
break
|
||||
fi
|
||||
|
||||
# If this is our first marginally acceptable shell, remember it.
|
||||
if test "$st_:$marginal_" = 9: ; then
|
||||
marginal_="$re_shell_"
|
||||
gl_set_x_corrupts_stderr_=true
|
||||
fi
|
||||
done
|
||||
|
||||
if test "$re_shell_" != __current__; then
|
||||
# Found a usable shell. Preserve -v and -x.
|
||||
case $- in
|
||||
*v*x* | *x*v*) opts_=-vx ;;
|
||||
*v*) opts_=-v ;;
|
||||
*x*) opts_=-x ;;
|
||||
*) opts_= ;;
|
||||
esac
|
||||
re_shell=$re_shell_
|
||||
export re_shell
|
||||
exec "$re_shell_" $opts_ "$0" --no-reexec "$@"
|
||||
echo "$ME_: exec failed" 1>&2
|
||||
exit 127
|
||||
fi
|
||||
fi
|
||||
|
||||
# If this is bash, turn off all aliases.
|
||||
test -n "$BASH_VERSION" && unalias -a
|
||||
|
||||
# Note that when supporting $EXEEXT (transparently mapping from PROG_NAME to
|
||||
# PROG_NAME.exe), we want to support hyphen-containing names like test-acos.
|
||||
# That is part of the shell-selection test above. Why use aliases rather
|
||||
# than functions? Because support for hyphen-containing aliases is more
|
||||
# widespread than that for hyphen-containing function names.
|
||||
test -n "$EXEEXT" && test -n "$BASH_VERSION" && shopt -s expand_aliases
|
||||
|
||||
# Enable glibc's malloc-perturbing option.
|
||||
# This is useful for exposing code that depends on the fact that
|
||||
# malloc-related functions often return memory that is mostly zeroed.
|
||||
# If you have the time and cycles, use valgrind to do an even better job.
|
||||
: ${MALLOC_PERTURB_=87}
|
||||
export MALLOC_PERTURB_
|
||||
|
||||
# This is a stub function that is run upon trap (upon regular exit and
|
||||
# interrupt). Override it with a per-test function, e.g., to unmount
|
||||
# a partition, or to undo any other global state changes.
|
||||
cleanup_ () { :; }
|
||||
|
||||
# Emit a header similar to that from diff -u; Print the simulated "diff"
|
||||
# command so that the order of arguments is clear. Don't bother with @@ lines.
|
||||
emit_diff_u_header_ ()
|
||||
{
|
||||
printf '%s\n' "diff -u $*" \
|
||||
"--- $1 1970-01-01" \
|
||||
"+++ $2 1970-01-01"
|
||||
}
|
||||
|
||||
# Arrange not to let diff or cmp operate on /dev/null,
|
||||
# since on some systems (at least OSF/1 5.1), that doesn't work.
|
||||
# When there are not two arguments, or no argument is /dev/null, return 2.
|
||||
# When one argument is /dev/null and the other is not empty,
|
||||
# cat the nonempty file to stderr and return 1.
|
||||
# Otherwise, return 0.
|
||||
compare_dev_null_ ()
|
||||
{
|
||||
test $# = 2 || return 2
|
||||
|
||||
if test "x$1" = x/dev/null; then
|
||||
test -s "$2" || return 0
|
||||
emit_diff_u_header_ "$@"; sed 's/^/+/' "$2"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if test "x$2" = x/dev/null; then
|
||||
test -s "$1" || return 0
|
||||
emit_diff_u_header_ "$@"; sed 's/^/-/' "$1"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 2
|
||||
}
|
||||
|
||||
for diff_opt_ in -u -U3 -c '' no; do
|
||||
test "$diff_opt_" != no &&
|
||||
diff_out_=`exec 2>/dev/null; diff $diff_opt_ "$0" "$0" < /dev/null` &&
|
||||
break
|
||||
done
|
||||
if test "$diff_opt_" != no; then
|
||||
if test -z "$diff_out_"; then
|
||||
compare_ () { diff $diff_opt_ "$@"; }
|
||||
else
|
||||
compare_ ()
|
||||
{
|
||||
# If no differences were found, AIX and HP-UX 'diff' produce output
|
||||
# like "No differences encountered". Hide this output.
|
||||
diff $diff_opt_ "$@" > diff.out
|
||||
diff_status_=$?
|
||||
test $diff_status_ -eq 0 || cat diff.out || diff_status_=2
|
||||
rm -f diff.out || diff_status_=2
|
||||
return $diff_status_
|
||||
}
|
||||
fi
|
||||
elif cmp -s /dev/null /dev/null 2>/dev/null; then
|
||||
compare_ () { cmp -s "$@"; }
|
||||
else
|
||||
compare_ () { cmp "$@"; }
|
||||
fi
|
||||
|
||||
# Usage: compare EXPECTED ACTUAL
|
||||
#
|
||||
# Given compare_dev_null_'s preprocessing, defer to compare_ if 2 or more.
|
||||
# Otherwise, propagate $? to caller: any diffs have already been printed.
|
||||
compare ()
|
||||
{
|
||||
# This looks like it can be factored to use a simple "case $?"
|
||||
# after unchecked compare_dev_null_ invocation, but that would
|
||||
# fail in a "set -e" environment.
|
||||
if compare_dev_null_ "$@"; then
|
||||
return 0
|
||||
else
|
||||
case $? in
|
||||
1) return 1;;
|
||||
*) compare_ "$@";;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
|
||||
# An arbitrary prefix to help distinguish test directories.
|
||||
testdir_prefix_ () { printf gt; }
|
||||
|
||||
# Run the user-overridable cleanup_ function, remove the temporary
|
||||
# directory and exit with the incoming value of $?.
|
||||
remove_tmp_ ()
|
||||
{
|
||||
__st=$?
|
||||
cleanup_
|
||||
if test "$KEEP" = yes; then
|
||||
echo "Not removing temporary directory $test_dir_"
|
||||
else
|
||||
# cd out of the directory we're about to remove
|
||||
cd "$initial_cwd_" || cd / || cd /tmp
|
||||
chmod -R u+rwx "$test_dir_"
|
||||
# If removal fails and exit status was to be 0, then change it to 1.
|
||||
rm -rf "$test_dir_" || { test $__st = 0 && __st=1; }
|
||||
fi
|
||||
exit $__st
|
||||
}
|
||||
|
||||
# Given a directory name, DIR, if every entry in it that matches *.exe
|
||||
# contains only the specified bytes (see the case stmt below), then print
|
||||
# a space-separated list of those names and return 0. Otherwise, don't
|
||||
# print anything and return 1. Naming constraints apply also to DIR.
|
||||
find_exe_basenames_ ()
|
||||
{
|
||||
feb_dir_=$1
|
||||
feb_fail_=0
|
||||
feb_result_=
|
||||
feb_sp_=
|
||||
for feb_file_ in $feb_dir_/*.exe; do
|
||||
# If there was no *.exe file, or there existed a file named "*.exe" that
|
||||
# was deleted between the above glob expansion and the existence test
|
||||
# below, just skip it.
|
||||
test "x$feb_file_" = "x$feb_dir_/*.exe" && test ! -f "$feb_file_" \
|
||||
&& continue
|
||||
# Exempt [.exe, since we can't create a function by that name, yet
|
||||
# we can't invoke [ by PATH search anyways due to shell builtins.
|
||||
test "x$feb_file_" = "x$feb_dir_/[.exe" && continue
|
||||
case $feb_file_ in
|
||||
*[!-a-zA-Z/0-9_.+]*) feb_fail_=1; break;;
|
||||
*) # Remove leading file name components as well as the .exe suffix.
|
||||
feb_file_=${feb_file_##*/}
|
||||
feb_file_=${feb_file_%.exe}
|
||||
feb_result_="$feb_result_$feb_sp_$feb_file_";;
|
||||
esac
|
||||
feb_sp_=' '
|
||||
done
|
||||
test $feb_fail_ = 0 && printf %s "$feb_result_"
|
||||
return $feb_fail_
|
||||
}
|
||||
|
||||
# Consider the files in directory, $1.
|
||||
# For each file name of the form PROG.exe, create an alias named
|
||||
# PROG that simply invokes PROG.exe, then return 0. If any selected
|
||||
# file name or the directory name, $1, contains an unexpected character,
|
||||
# define no alias and return 1.
|
||||
create_exe_shims_ ()
|
||||
{
|
||||
case $EXEEXT in
|
||||
'') return 0 ;;
|
||||
.exe) ;;
|
||||
*) echo "$0: unexpected \$EXEEXT value: $EXEEXT" 1>&2; return 1 ;;
|
||||
esac
|
||||
|
||||
base_names_=`find_exe_basenames_ $1` \
|
||||
|| { echo "$0 (exe_shim): skipping directory: $1" 1>&2; return 0; }
|
||||
|
||||
if test -n "$base_names_"; then
|
||||
for base_ in $base_names_; do
|
||||
alias "$base_"="$base_$EXEEXT"
|
||||
done
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Use this function to prepend to PATH an absolute name for each
|
||||
# specified, possibly-$initial_cwd_-relative, directory.
|
||||
path_prepend_ ()
|
||||
{
|
||||
while test $# != 0; do
|
||||
path_dir_=$1
|
||||
case $path_dir_ in
|
||||
'') fail_ "invalid path dir: '$1'";;
|
||||
/* | ?:*) abs_path_dir_=$path_dir_;;
|
||||
*) abs_path_dir_=$initial_cwd_/$path_dir_;;
|
||||
esac
|
||||
case $abs_path_dir_ in
|
||||
*$PATH_SEPARATOR*) fail_ "invalid path dir: '$abs_path_dir_'";;
|
||||
esac
|
||||
PATH="$abs_path_dir_$PATH_SEPARATOR$PATH"
|
||||
|
||||
# Create an alias, FOO, for each FOO.exe in this directory.
|
||||
create_exe_shims_ "$abs_path_dir_" \
|
||||
|| fail_ "something failed (above): $abs_path_dir_"
|
||||
shift
|
||||
done
|
||||
export PATH
|
||||
}
|
||||
|
||||
setup_ ()
|
||||
{
|
||||
if test "$VERBOSE" = yes; then
|
||||
# Test whether set -x may cause the selected shell to corrupt an
|
||||
# application's stderr. Many do, including zsh-4.3.10 and the /bin/sh
|
||||
# from SunOS 5.11, OpenBSD 4.7 and Irix 5.x and 6.5.
|
||||
# If enabling verbose output this way would cause trouble, simply
|
||||
# issue a warning and refrain.
|
||||
if $gl_set_x_corrupts_stderr_; then
|
||||
warn_ "using SHELL=$SHELL with 'set -x' corrupts stderr"
|
||||
else
|
||||
set -x
|
||||
fi
|
||||
fi
|
||||
|
||||
initial_cwd_=$PWD
|
||||
|
||||
pfx_=`testdir_prefix_`
|
||||
test_dir_=`mktempd_ "$initial_cwd_" "$pfx_-$ME_.XXXX"` \
|
||||
|| fail_ "failed to create temporary directory in $initial_cwd_"
|
||||
cd "$test_dir_" || fail_ "failed to cd to temporary directory"
|
||||
|
||||
# As autoconf-generated configure scripts do, ensure that IFS
|
||||
# is defined initially, so that saving and restoring $IFS works.
|
||||
gl_init_sh_nl_='
|
||||
'
|
||||
IFS=" "" $gl_init_sh_nl_"
|
||||
|
||||
# This trap statement, along with a trap on 0 below, ensure that the
|
||||
# temporary directory, $test_dir_, is removed upon exit as well as
|
||||
# upon receipt of any of the listed signals.
|
||||
for sig_ in 1 2 3 13 15; do
|
||||
eval "trap 'Exit $(expr $sig_ + 128)' $sig_"
|
||||
done
|
||||
}
|
||||
|
||||
# Create a temporary directory, much like mktemp -d does.
|
||||
# Written by Jim Meyering.
|
||||
#
|
||||
# Usage: mktempd_ /tmp phoey.XXXXXXXXXX
|
||||
#
|
||||
# First, try to use the mktemp program.
|
||||
# Failing that, we'll roll our own mktemp-like function:
|
||||
# - try to get random bytes from /dev/urandom
|
||||
# - failing that, generate output from a combination of quickly-varying
|
||||
# sources and gzip. Ignore non-varying gzip header, and extract
|
||||
# "random" bits from there.
|
||||
# - given those bits, map to file-name bytes using tr, and try to create
|
||||
# the desired directory.
|
||||
# - make only $MAX_TRIES_ attempts
|
||||
|
||||
# Helper function. Print $N pseudo-random bytes from a-zA-Z0-9.
|
||||
rand_bytes_ ()
|
||||
{
|
||||
n_=$1
|
||||
|
||||
# Maybe try openssl rand -base64 $n_prime_|tr '+/=\012' abcd first?
|
||||
# But if they have openssl, they probably have mktemp, too.
|
||||
|
||||
chars_=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
|
||||
dev_rand_=/dev/urandom
|
||||
if test -r "$dev_rand_"; then
|
||||
# Note: 256-length($chars_) == 194; 3 copies of $chars_ is 186 + 8 = 194.
|
||||
dd ibs=$n_ count=1 if=$dev_rand_ 2>/dev/null \
|
||||
| LC_ALL=C tr -c $chars_ 01234567$chars_$chars_$chars_
|
||||
return
|
||||
fi
|
||||
|
||||
n_plus_50_=`expr $n_ + 50`
|
||||
cmds_='date; date +%N; free; who -a; w; ps auxww; ps -ef'
|
||||
data_=` (eval "$cmds_") 2>&1 | gzip `
|
||||
|
||||
# Ensure that $data_ has length at least 50+$n_
|
||||
while :; do
|
||||
len_=`echo "$data_"|wc -c`
|
||||
test $n_plus_50_ -le $len_ && break;
|
||||
data_=` (echo "$data_"; eval "$cmds_") 2>&1 | gzip `
|
||||
done
|
||||
|
||||
echo "$data_" \
|
||||
| dd bs=1 skip=50 count=$n_ 2>/dev/null \
|
||||
| LC_ALL=C tr -c $chars_ 01234567$chars_$chars_$chars_
|
||||
}
|
||||
|
||||
mktempd_ ()
|
||||
{
|
||||
case $# in
|
||||
2);;
|
||||
*) fail_ "Usage: mktempd_ DIR TEMPLATE";;
|
||||
esac
|
||||
|
||||
destdir_=$1
|
||||
template_=$2
|
||||
|
||||
MAX_TRIES_=4
|
||||
|
||||
# Disallow any trailing slash on specified destdir:
|
||||
# it would subvert the post-mktemp "case"-based destdir test.
|
||||
case $destdir_ in
|
||||
/ | //) destdir_slash_=$destdir;;
|
||||
*/) fail_ "invalid destination dir: remove trailing slash(es)";;
|
||||
*) destdir_slash_=$destdir_/;;
|
||||
esac
|
||||
|
||||
case $template_ in
|
||||
*XXXX) ;;
|
||||
*) fail_ \
|
||||
"invalid template: $template_ (must have a suffix of at least 4 X's)";;
|
||||
esac
|
||||
|
||||
# First, try to use mktemp.
|
||||
d=`unset TMPDIR; { mktemp -d -t -p "$destdir_" "$template_"; } 2>/dev/null` &&
|
||||
|
||||
# The resulting name must be in the specified directory.
|
||||
case $d in "$destdir_slash_"*) :;; *) false;; esac &&
|
||||
|
||||
# It must have created the directory.
|
||||
test -d "$d" &&
|
||||
|
||||
# It must have 0700 permissions. Handle sticky "S" bits.
|
||||
perms=`ls -dgo "$d" 2>/dev/null` &&
|
||||
case $perms in drwx--[-S]---*) :;; *) false;; esac && {
|
||||
echo "$d"
|
||||
return
|
||||
}
|
||||
|
||||
# If we reach this point, we'll have to create a directory manually.
|
||||
|
||||
# Get a copy of the template without its suffix of X's.
|
||||
base_template_=`echo "$template_"|sed 's/XX*$//'`
|
||||
|
||||
# Calculate how many X's we've just removed.
|
||||
template_length_=`echo "$template_" | wc -c`
|
||||
nx_=`echo "$base_template_" | wc -c`
|
||||
nx_=`expr $template_length_ - $nx_`
|
||||
|
||||
err_=
|
||||
i_=1
|
||||
while :; do
|
||||
X_=`rand_bytes_ $nx_`
|
||||
candidate_dir_="$destdir_slash_$base_template_$X_"
|
||||
err_=`mkdir -m 0700 "$candidate_dir_" 2>&1` \
|
||||
&& { echo "$candidate_dir_"; return; }
|
||||
test $MAX_TRIES_ -le $i_ && break;
|
||||
i_=`expr $i_ + 1`
|
||||
done
|
||||
fail_ "$err_"
|
||||
}
|
||||
|
||||
# If you want to override the testdir_prefix_ function,
|
||||
# or to add more utility functions, use this file.
|
||||
test -f "$srcdir/init.cfg" \
|
||||
&& . "$srcdir/init.cfg"
|
||||
|
||||
setup_ "$@"
|
||||
# This trap is here, rather than in the setup_ function, because some
|
||||
# shells run the exit trap at shell function exit, rather than script exit.
|
||||
trap remove_tmp_ 0
|
||||
10
tests/lang-default
Normal file
10
tests/lang-default
Normal file
@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
# Set locale-related environment variables so we get consistent
|
||||
# message translations, time formats, sort orderings, etc.
|
||||
|
||||
LC_ALL=C
|
||||
export LC_ALL
|
||||
unset LANGUAGE NLSPATH
|
||||
|
||||
# These settings shouldn't matter, but unset them anyway just in case.
|
||||
unset LANG LC_COLLATE LC_CTYPE LC_MESSAGES LC_MONETARY LC_NUMERIC LC_TIME
|
||||
109
tests/local.mk
Normal file
109
tests/local.mk
Normal file
@ -0,0 +1,109 @@
|
||||
## Process this file with automake to produce Makefile.in -*-Makefile-*-.
|
||||
|
||||
## Copyright (C) 2007-2019 Free Software Foundation, Inc.
|
||||
|
||||
## This program is free software: you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation, either version 3 of the License, or
|
||||
## (at your option) any later version.
|
||||
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
built_programs = find oldfind xargs frcode locate updatedb
|
||||
|
||||
# Indirections required so that we'll still be able to know the
|
||||
# complete list of our tests even if the user overrides TESTS
|
||||
# from the command line (as permitted by the test harness API).
|
||||
TESTS = $(all_tests)
|
||||
root_tests = $(all_root_tests)
|
||||
|
||||
EXTRA_DIST += $(all_tests)
|
||||
|
||||
TEST_EXTENSIONS = .sh
|
||||
|
||||
SH_LOG_COMPILER = $(SHELL)
|
||||
|
||||
# We don't want this to go in the top-level directory.
|
||||
TEST_SUITE_LOG = tests/test-suite.log
|
||||
|
||||
# Note that the first lines are statements. They ensure that environment
|
||||
# variables that can perturb tests are unset or set to expected values.
|
||||
# The rest are envvar settings that propagate build-related Makefile
|
||||
# variables to test scripts.
|
||||
TESTS_ENVIRONMENT = \
|
||||
. $(srcdir)/tests/lang-default; \
|
||||
tmp__=$${TMPDIR-/tmp}; \
|
||||
test -d "$$tmp__" && test -w "$$tmp__" || tmp__=.; \
|
||||
. $(srcdir)/tests/envvar-check; \
|
||||
TMPDIR=$$tmp__; export TMPDIR; \
|
||||
export \
|
||||
VERSION='$(VERSION)' \
|
||||
LOCALE_FR='$(LOCALE_FR)' \
|
||||
LOCALE_FR_UTF8='$(LOCALE_FR_UTF8)' \
|
||||
abs_top_builddir='$(abs_top_builddir)' \
|
||||
abs_top_srcdir='$(abs_top_srcdir)' \
|
||||
abs_srcdir='$(abs_srcdir)' \
|
||||
built_programs='$(built_programs) $(single_binary_progs)' \
|
||||
fail=0 \
|
||||
host_os=$(host_os) \
|
||||
host_triplet='$(host_triplet)' \
|
||||
srcdir='$(srcdir)' \
|
||||
top_srcdir='$(top_srcdir)' \
|
||||
CONFIG_HEADER='$(abs_top_builddir)/$(CONFIG_INCLUDE)' \
|
||||
CC='$(CC)' \
|
||||
AWK='$(AWK)' \
|
||||
EGREP='$(EGREP)' \
|
||||
EXEEXT='$(EXEEXT)' \
|
||||
MAKE=$(MAKE) \
|
||||
PACKAGE_VERSION=$(PACKAGE_VERSION) \
|
||||
PERL='$(PERL)' \
|
||||
SHELL='$(PREFERABLY_POSIX_SHELL)' \
|
||||
; test -d /usr/xpg4/bin && PATH='/usr/xpg4/bin$(PATH_SEPARATOR)'"$$PATH"; \
|
||||
PATH='$(abs_top_builddir)/find$(PATH_SEPARATOR)$(abs_top_builddir)/locate$(PATH_SEPARATOR)$(abs_top_builddir)/xargs$(PATH_SEPARATOR)'"$$PATH" \
|
||||
; 9>&2
|
||||
|
||||
# On failure, display the global testsuite log on stdout.
|
||||
VERBOSE = yes
|
||||
|
||||
EXTRA_DIST += \
|
||||
init.cfg \
|
||||
tests/envvar-check \
|
||||
tests/init.sh \
|
||||
tests/lang-default \
|
||||
tests/other-fs-tmpdir \
|
||||
tests/sample-test
|
||||
|
||||
all_root_tests =
|
||||
|
||||
ALL_RECURSIVE_TARGETS += check-root
|
||||
.PHONY: check-root
|
||||
check-root:
|
||||
$(MAKE) check TESTS='$(root_tests)' SUBDIRS=.
|
||||
|
||||
# Do not choose a name that is a shell keyword like 'if', or a
|
||||
# commonly-used utility like 'cat' or 'test', as the name of a test.
|
||||
# Otherwise, VPATH builds will fail on hosts like Solaris, since they
|
||||
# will expand 'if test ...' to 'if .../test ...', and the '.../test'
|
||||
# will execute the test script rather than the standard utility.
|
||||
|
||||
# Notes on the ordering of these tests:
|
||||
# Place early in the list tests of the tools that
|
||||
# are most commonly used in test scripts themselves.
|
||||
# E.g., nearly every test script uses rm and chmod.
|
||||
# help-version comes early because it's a basic sanity test.
|
||||
# Put seq early, since lots of other tests use it.
|
||||
# Put tests that sleep early, but not all together, so in parallel builds
|
||||
# they share time with tests that burn CPU, not with others that sleep.
|
||||
# Put head-elide-tail early, because it's long-running.
|
||||
|
||||
all_tests = \
|
||||
tests/misc/help-version.sh \
|
||||
$(all_root_tests)
|
||||
|
||||
$(TEST_LOGS): $(PROGRAMS)
|
||||
64
tests/misc/help-version.sh
Executable file
64
tests/misc/help-version.sh
Executable file
@ -0,0 +1,64 @@
|
||||
#!/bin/sh
|
||||
# Make sure all of these programs work properly
|
||||
# when invoked with --help or --version.
|
||||
|
||||
# Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
. "${srcdir=.}/tests/init.sh"
|
||||
|
||||
# Terminate any background processes
|
||||
cleanup_() { kill $pid 2>/dev/null && wait $pid; }
|
||||
echo PATH=$PATH
|
||||
test "$built_programs" \
|
||||
|| fail_ "built_programs not specified!?!"
|
||||
|
||||
test "$VERSION" \
|
||||
|| fail_ "set envvar VERSION; it is required for a PATH sanity-check"
|
||||
|
||||
# Extract version from --version output of the first program
|
||||
for i in $built_programs; do
|
||||
v=$(set -x; env $i --version | sed -n '1s/.* //p;q')
|
||||
break
|
||||
done
|
||||
|
||||
# Ensure that it matches $VERSION.
|
||||
test "x$v" = "x$VERSION" \
|
||||
|| fail_ "--version-\$VERSION mismatch"
|
||||
|
||||
for i in $built_programs; do
|
||||
# Make sure they exit successfully, under normal conditions.
|
||||
env $i --help >/dev/null || fail=1
|
||||
env $i --version >/dev/null || fail=1
|
||||
|
||||
# Make sure they fail upon 'disk full' error.
|
||||
if test -w /dev/full && test -c /dev/full; then
|
||||
prog=$(set -x; echo $i|sed "s/$EXEEXT$//");
|
||||
eval "expected=\$expected_failure_status_$prog"
|
||||
test x$expected = x && expected=1
|
||||
|
||||
returns_ $expected env $i --help >/dev/full 2>/dev/null &&
|
||||
returns_ $expected env $i --version >/dev/full 2>/dev/null ||
|
||||
{
|
||||
fail=1
|
||||
env $i --help >/dev/full 2>/dev/null
|
||||
status=$?
|
||||
echo "*** $i: bad exit status '$status' (expected $expected)," 1>&2
|
||||
echo " with --help or --version output redirected to /dev/full" 1>&2
|
||||
}
|
||||
fi
|
||||
done
|
||||
|
||||
Exit $fail
|
||||
55
tests/other-fs-tmpdir
Normal file
55
tests/other-fs-tmpdir
Normal file
@ -0,0 +1,55 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Use stat to find a writable directory on a file system different from that
|
||||
# of the current directory. If one is found, create a temporary directory
|
||||
# inside it.
|
||||
|
||||
# Copyright (C) 1998-2019 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
test "${CANDIDATE_TMP_DIRS+set}" = set \
|
||||
|| CANDIDATE_TMP_DIRS="$TMPDIR /tmp /dev/shm /var/tmp /usr/tmp $HOME"
|
||||
|
||||
other_partition_tmpdir=
|
||||
|
||||
dot_mount_point=$(stat -c %d .)
|
||||
for d in $CANDIDATE_TMP_DIRS; do
|
||||
|
||||
# Skip nonexistent directories.
|
||||
test -d "$d" || continue
|
||||
|
||||
d_mount_point=$(stat -L -c %d "$d")
|
||||
|
||||
# Same partition? Skip it.
|
||||
test "x$d_mount_point" = "x$dot_mount_point" && continue
|
||||
|
||||
# See if we can create a directory in it.
|
||||
if mkdir "$d/tmp$$" > /dev/null 2>&1; then
|
||||
other_partition_tmpdir="$d/tmp$$"
|
||||
break
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
if test -z "$other_partition_tmpdir"; then
|
||||
skip_ \
|
||||
"requires a writable directory on a different disk partition,
|
||||
and I couldn't find one. I tried these:
|
||||
$CANDIDATE_TMP_DIRS
|
||||
Set your environment variable CANDIDATE_TMP_DIRS to make
|
||||
this test use a different list."
|
||||
fi
|
||||
|
||||
test "$VERBOSE" = yes && set -x
|
||||
36
tests/sample-test
Normal file
36
tests/sample-test
Normal file
@ -0,0 +1,36 @@
|
||||
#!/bin/sh
|
||||
# FIXME
|
||||
|
||||
# Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
. "${srcdir=.}/tests/init.sh"
|
||||
print_ver_ FIXME
|
||||
|
||||
# FIXME: skip_if_root_
|
||||
# FIXME: require_root_
|
||||
|
||||
# If used, these must *follow* init.sh.
|
||||
# FIXME: cleanup_() { rm -rf "$other_partition_tmpdir"; }
|
||||
# FIXME: . "$abs_srcdir/tests/other-fs-tmpdir"
|
||||
|
||||
FIXME > out || fail=1
|
||||
cat <<\EOF > exp || framework_failure_
|
||||
FIXME
|
||||
EOF
|
||||
|
||||
compare exp out || fail=1
|
||||
|
||||
Exit $fail
|
||||
Loading…
x
Reference in New Issue
Block a user