Subject: tests: begin migrating from test-lib.sh to init.sh

From: Jim Meyering <[email-masked]>
Date: Wed, 30 Jun 2010 19:50:35 +0200

The first patch here is just an update from gnulib.

Patches 2/3 and 3/3 are more interesting.
Rather, their motivation is more interesting.

This started with an infloop in the tail-2/inotify-rotate test.
A mystery in itself.  If anyone can suggest how that happened,
please let us know:

   [quick summary, on the 27th iteration of this loop, the file "out"
    was empty, even though file "k" had a line "b".  That led to the
    while-loop never terminating.  By the time I noticed, the 10-second
    timeout had long since killed the tail process, so I couldn't debug
    that.  Nothing suspicious in the .log file.  I could not reproduce
    it after hundreds of attempts.

    for i in $(seq 50); do
        echo $i
        rm -rf k x out
        :>k && :>x && timeout 10 tail -F k > out 2>&1 &
        pid=$!
        sleep .1
        echo b > k;
        # wait for b to appear in out
>>>     while :; do grep b out > /dev/null && break; done
        mv x k
        ...

    As I write this, I think I've realized the only possible
    explanation: the 10-second timeout was too short.
    In other words, the tail process took longer than 10s
    between when it was forked/exec'd and when it would have
    performed its first write of that single line.
    Since I run the tests with -j9, and with RUN_EXPENSIVE_TESTS=yes,
    lots of system-hammering tests can end up running concurrently,
    and there may have been some heavy swapping (unrelated) around
    then, too.

    Unfortunately, there's no way to know from the log output if timeout
    killed that tail -F process.  To remedy that, I may replace the line
    above with something that reports the problem:

        :>k && :>x && \
          { timeout 10 tail -F k; test -s out \
              || warn_ tail produced no output in 10s; } > out 2>&1 &
    ]

While making that test fail rather than infloop, my reflex was to use
the new fail_ function, but that is provided by the newer init.sh,
not test-lib.sh.
Also, this test script uses test-lib.sh's expensive_ test.
Factoring the many helper functions into init.cfg makes it so both
frameworks use the same functions, and I can now use fail_ there.

>From cfee734a41111c975c708744c6aab1f99aa0262b Mon Sep 17 00:00:00 2001
From: Jim Meyering <[email-masked]>
Date: Wed, 30 Jun 2010 14:34:23 +0200
Subject: [PATCH 1/3] tests: sync tests/init.sh from gnulib

* tests/init.sh: Update from gnulib.
---
 tests/init.sh |   47 ++++++++++++++++++++++++-----------------------
 1 files changed, 24 insertions(+), 23 deletions(-)

diff --git a/tests/init.sh b/tests/init.sh
index e23aa54..7943526 100644
--- a/tests/init.sh
+++ b/tests/init.sh
@@ -57,6 +57,28 @@
 #   4. Finally
 #   $ exit

+ME_=`expr "./$0" : '.*/\(.*\)$'`
+
+# 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...; exec 9>&2; $(SHELL)" 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}
+
+warn_() { echo "$@" 1>&$stderr_fileno_; }
+fail_() { warn_ "$ME_: failed test: $@"; Exit 1; }
+skip_() { warn_ "$ME_: skipped test: $@"; Exit 77; }
+framework_failure_() { warn_ "$ME_: set-up failure: $@"; Exit 99; }
+
 # We require $(...) support unconditionally.
 # We require a few additional shell features only when $EXEEXT is nonempty,
 # in order to support automatic $EXEEXT emulation:
@@ -118,34 +140,14 @@ test -n "$EXEEXT" && shopt -s expand_aliases
 : ${MALLOC_PERTURB_=87}
 export MALLOC_PERTURB_

-# 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...; exec 9>&2; $(SHELL)" 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}
-
-warn_() { echo "$@" 1>&$stderr_fileno_; }
-fail_() { warn_ "$ME_: failed test: $@"; Exit 1; }
-skip_() { warn_ "$ME_: skipped test: $@"; Exit 77; }
-framework_failure_() { warn_ "$ME_: set-up failure: $@"; Exit 1; }
-
 # 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_() { :; }

-if ( diff --version < /dev/null 2>&1 | grep GNU ) 2>&1 > /dev/null; then
+if ( diff --version < /dev/null 2>&1 | grep GNU ) > /dev/null 2>&1; then
   compare() { diff -u "$@"; }
-elif ( cmp --version < /dev/null 2>&1 | grep GNU ) 2>&1 > /dev/null; then
+elif ( cmp --version < /dev/null 2>&1 | grep GNU ) > /dev/null 2>&1; then
   compare() { cmp -s "$@"; }
 else
   compare() { cmp "$@"; }
@@ -247,7 +249,6 @@ setup_()
   test "$VERBOSE" = yes && set -x

   initial_cwd_=$PWD
-  ME_=`expr "./$0" : '.*/\(.*\)$'`

   pfx_=`testdir_prefix_`
   test_dir_=`mktempd_ "$initial_cwd_" "$pfx_-$ME_.XXXX"` \
--
1.7.2.rc0.206.g3336

>From b062bbd94712c9a761ee42b9ac267651b334f836 Mon Sep 17 00:00:00 2001
From: Jim Meyering <[email-masked]>
Date: Wed, 30 Jun 2010 17:06:53 +0200
Subject: [PATCH 2/3] tests: move most helper functions from test-lib.sh to new init.cfg

>From there, they will be used by both test-lib.sh (as we phase it out)
and the newer init.sh, to which all tests will migrate.
* tests/test-lib.sh: Move most functions from here, ...
* tests/init.cfg: ...to here.  New file.
* tests/Makefile.am (EXTRA_DIST): Add init.cfg.
---
 tests/Makefile.am |    1 +
 tests/init.cfg    |  360 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/test-lib.sh |  355 +---------------------------------------------------
 3 files changed, 364 insertions(+), 352 deletions(-)
 create mode 100644 tests/init.cfg

diff --git a/tests/Makefile.am b/tests/Makefile.am
index c458574..a993e82 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -10,6 +10,7 @@ EXTRA_DIST =		\
   CuTmpdir.pm		\
   check.mk		\
   envvar-check		\
+  init.cfg		\
   init.sh		\
   lang-default		\
   other-fs-tmpdir	\
diff --git a/tests/init.cfg b/tests/init.cfg
new file mode 100644
index 0000000..aecdd5a
--- /dev/null
+++ b/tests/init.cfg
@@ -0,0 +1,360 @@
+# This file is sourced by init.sh, *before* its initialization.
+
+# This goes hand in hand with the "exec 9>&2;" in tests/Makefile.am's
+# TESTS_ENVIRONMENT definition.
+stderr_fileno_=9
+
+# FIXME: eventually s/error_/fail_/ and remove the definition of error_ below.
+# FIXME: s/(framework_failure)\>/${1}_/ and remove def. of framework_failure
+
+# 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.
+sanitize_path_()
+{
+  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
+
+  PATH=$new_path
+  export PATH
+}
+
+skip_test_()
+{
+  echo "$0: skipping test: $@" | head -1 1>&9
+  echo "$0: skipping test: $@" 1>&2
+  Exit 77
+}
+
+getlimits_()
+{
+  eval $(getlimits)
+  test "$INT_MAX" ||
+    error_ "Error running getlimits"
+}
+
+require_acl_()
+{
+  getfacl --version < /dev/null > /dev/null 2>&1 \
+    && setfacl --version < /dev/null > /dev/null 2>&1 \
+      || skip_test_ "This test requires getfacl and setfacl."
+
+  id -u bin > /dev/null 2>&1 \
+    || skip_test_ "This test requires a local user named bin."
+}
+
+# Skip this test if we're not in SELinux "enforcing" mode.
+require_selinux_enforcing_()
+{
+  test "$(getenforce)" = Enforcing \
+    || skip_test_ "This test is useful only with SELinux in Enforcing mode."
+}
+
+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" \
+    && skip_test_ 'internal error: 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_test_ 'this system lacks openat support'
+  fi
+}
+
+require_ulimit_()
+{
+  ulimit_works=yes
+  # Expect to be able to exec a program in 10MB of virtual memory,
+  # but not in 20KB.  I chose "date".  It must not be a shell built-in
+  # function, so you can't use echo, printf, true, etc.
+  # Of course, in coreutils, I could use $top_builddir/src/true,
+  # but this should be able to work for other projects, too.
+  ( ulimit -v 10000; date ) > /dev/null 2>&1 || ulimit_works=no
+  ( ulimit -v 20;    date ) > /dev/null 2>&1 && ulimit_works=no
+
+  test $ulimit_works = no \
+    && skip_test_ "this shell lacks ulimit support"
+}
+
+require_readable_root_()
+{
+  test -r / || skip_test_ "/ 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_test_ 'no strace program'
+
+  strace -qe "$1" echo > /dev/null 2>&1 ||
+    skip_test_ 'strace -qe "'"$1"'" does not work'
+}
+
+# Require a controlling input `terminal'.
+require_controlling_input_terminal_()
+{
+  tty -s || have_input_tty=no
+  test -t 0 || have_input_tty=no
+  if test "$have_input_tty" = no; then
+    skip_test_ '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_test_ "required program(s) not built"
+}
+
+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_test_ must be run as root ;;
+    non-root) skip_test_ must be run as non-root ;;
+    *) ;;  # FIXME?
+  esac
+}
+
+require_selinux_()
+{
+  case `ls -Zd .` in
+    '? .'|'unlabeled .')
+      skip_test_ "this system (or maybe just" \
+        "the current file system) lacks SELinux support"
+    ;;
+  esac
+}
+
+very_expensive_()
+{
+  if test "$RUN_VERY_EXPENSIVE_TESTS" != yes; then
+    skip_test_ '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
+'
+  fi
+}
+
+expensive_()
+{
+  if test "$RUN_EXPENSIVE_TESTS" != yes; then
+    skip_test_ '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
+'
+  fi
+}
+
+require_root_()
+{
+  uid_is_privileged_ || skip_test_ "must be run as root"
+  NON_ROOT_USERNAME=${NON_ROOT_USERNAME=nobody}
+  NON_ROOT_GROUP=${NON_ROOT_GROUP=$(id -g $NON_ROOT_USERNAME)}
+}
+
+skip_if_root_() { uid_is_privileged_ && skip_test_ "must be run as non-root"; }
+error_() { echo "$0: $@" 1>&2; Exit 1; }
+framework_failure() { error_ 'failure in testing framework'; }
+
+# 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=${COREUTILS_GROUPS-`(id -G || /usr/xpg4/bin/id -G) 2>/dev/null`}
+  case "$groups" in
+    *' '*) ;;
+    *) skip_test_ '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
+COREUTILS_GROUPS set in your environment to the space-separated list
+of group names or numbers.  E.g.,
+
+  env COREUTILS_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_test_ "/proc/$pid/status: missing or 'different'"
+    kill $pid
+}
+
+# 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_test_ 'this file system does not support sparse files'
+  fi
+}
+
+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_test_ 'NOTICE: unable to create test prerequisites'
+  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_test_ 'this directory has the setgid bit set';;
+  esac
+}
+
+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
+    *:*:*:*) ;; # four components is ok
+    *) # anything else probably means mcstransd is running
+        skip_test_ "unexpected context '$__ctx'; turn off mcstransd" ;;
+  esac
+}
+
+# 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_test_ 'your build directory has unusual umask semantics'
+  esac
+}
+
+sanitize_path_
diff --git a/tests/test-lib.sh b/tests/test-lib.sh
index ac2f8bf..82d6535 100644
--- a/tests/test-lib.sh
+++ b/tests/test-lib.sh
@@ -23,356 +23,6 @@ if test $? != 11; then
   Exit 77
 fi

-# 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.
-sanitize_path_()
-{
-  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
-
-  PATH=$new_path
-  export PATH
-}
-
-skip_test_()
-{
-  echo "$0: skipping test: $@" | head -1 1>&9
-  echo "$0: skipping test: $@" 1>&2
-  Exit 77
-}
-
-getlimits_()
-{
-  eval $(getlimits)
-  test "$INT_MAX" ||
-    error_ "Error running getlimits"
-}
-
-require_acl_()
-{
-  getfacl --version < /dev/null > /dev/null 2>&1 \
-    && setfacl --version < /dev/null > /dev/null 2>&1 \
-      || skip_test_ "This test requires getfacl and setfacl."
-
-  id -u bin > /dev/null 2>&1 \
-    || skip_test_ "This test requires a local user named bin."
-}
-
-# Skip this test if we're not in SELinux "enforcing" mode.
-require_selinux_enforcing_()
-{
-  test "$(getenforce)" = Enforcing \
-    || skip_test_ "This test is useful only with SELinux in Enforcing mode."
-}
-
-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" \
-    && skip_test_ 'internal error: 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_test_ 'this system lacks openat support'
-  fi
-}
-
-require_ulimit_()
-{
-  ulimit_works=yes
-  # Expect to be able to exec a program in 10MB of virtual memory,
-  # but not in 20KB.  I chose "date".  It must not be a shell built-in
-  # function, so you can't use echo, printf, true, etc.
-  # Of course, in coreutils, I could use $top_builddir/src/true,
-  # but this should be able to work for other projects, too.
-  ( ulimit -v 10000; date ) > /dev/null 2>&1 || ulimit_works=no
-  ( ulimit -v 20;    date ) > /dev/null 2>&1 && ulimit_works=no
-
-  test $ulimit_works = no \
-    && skip_test_ "this shell lacks ulimit support"
-}
-
-require_readable_root_()
-{
-  test -r / || skip_test_ "/ 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_test_ 'no strace program'
-
-  strace -qe "$1" echo > /dev/null 2>&1 ||
-    skip_test_ 'strace -qe "'"$1"'" does not work'
-}
-
-# Require a controlling input `terminal'.
-require_controlling_input_terminal_()
-{
-  tty -s || have_input_tty=no
-  test -t 0 || have_input_tty=no
-  if test "$have_input_tty" = no; then
-    skip_test_ '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_test_ "required program(s) not built"
-}
-
-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_test_ must be run as root ;;
-    non-root) skip_test_ must be run as non-root ;;
-    *) ;;  # FIXME?
-  esac
-}
-
-require_selinux_()
-{
-  case `ls -Zd .` in
-    '? .'|'unlabeled .')
-      skip_test_ "this system (or maybe just" \
-        "the current file system) lacks SELinux support"
-    ;;
-  esac
-}
-
-very_expensive_()
-{
-  if test "$RUN_VERY_EXPENSIVE_TESTS" != yes; then
-    skip_test_ '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
-'
-  fi
-}
-
-expensive_()
-{
-  if test "$RUN_EXPENSIVE_TESTS" != yes; then
-    skip_test_ '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
-'
-  fi
-}
-
-require_root_()
-{
-  uid_is_privileged_ || skip_test_ "must be run as root"
-  NON_ROOT_USERNAME=${NON_ROOT_USERNAME=nobody}
-  NON_ROOT_GROUP=${NON_ROOT_GROUP=$(id -g $NON_ROOT_USERNAME)}
-}
-
-skip_if_root_() { uid_is_privileged_ && skip_test_ "must be run as non-root"; }
-error_() { echo "$0: $@" 1>&2; Exit 1; }
-framework_failure() { error_ 'failure in testing framework'; }
-
-# 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=${COREUTILS_GROUPS-`(id -G || /usr/xpg4/bin/id -G) 2>/dev/null`}
-  case "$groups" in
-    *' '*) ;;
-    *) skip_test_ '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
-COREUTILS_GROUPS set in your environment to the space-separated list
-of group names or numbers.  E.g.,
-
-  env COREUTILS_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_test_ "/proc/$pid/status: missing or 'different'"
-    kill $pid
-}
-
-# 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_test_ 'this file system does not support sparse files'
-  fi
-}
-
-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_test_ 'NOTICE: unable to create test prerequisites'
-  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_test_ 'this directory has the setgid bit set';;
-  esac
-}
-
-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
-    *:*:*:*) ;; # four components is ok
-    *) # anything else probably means mcstransd is running
-        skip_test_ "unexpected context '$__ctx'; turn off mcstransd" ;;
-  esac
-}
-
-# 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_test_ 'your build directory has unusual umask semantics'
-  esac
-}
-
 # We use a trap below for cleanup.  This requires us to go through
 # hoops to get the right exit status transported through the signal.
 # So use `Exit STATUS' instead of `exit STATUS' inside of the tests.
@@ -385,6 +35,9 @@ Exit ()
   exit $1
 }

+test -f "$srcdir/init.cfg" \
+  && . "$srcdir/init.cfg"
+
 test_dir_=$(pwd)

 this_test_() { echo "./$0" | sed 's,.*/,,'; }
@@ -424,7 +77,5 @@ else
   compare() { cmp "$@"; }
 fi

-sanitize_path_
-
 # Initialize; all bourne shell scripts end with "Exit $fail".
 fail=0
--
1.7.2.rc0.206.g3336

>From 7336920dd07478b7bdae05ec599da4e2e66a94ff Mon Sep 17 00:00:00 2001
From: Jim Meyering <[email-masked]>
Date: Wed, 30 Jun 2010 17:10:07 +0200
Subject: [PATCH 3/3] tests: fail rather than infloop in tail's inotify-rotate test

* tests/tail-2/inotify-rotate: Switch to new init.sh-based framework.
(grep_timeout): New function.
Use it in place of open-coded loops that might infloop.
This was prompted by my encountering an inexplicable, and so far
unreproducible, infloop in the code that was waiting for "b" to
appear in "out".
---
 tests/tail-2/inotify-rotate |   22 ++++++++++++++++------
 1 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/tests/tail-2/inotify-rotate b/tests/tail-2/inotify-rotate
index 51cd81b..9a3933e 100755
--- a/tests/tail-2/inotify-rotate
+++ b/tests/tail-2/inotify-rotate
@@ -21,9 +21,21 @@ if test "$VERBOSE" = yes; then
   tail --version
 fi

-. $srcdir/test-lib.sh
+. "${srcdir=.}/init.sh"; path_prepend_ ../src
 expensive_

+# Wait up to 10 seconds for grep REGEXP FILE to succeed.
+# Usage: grep_timeout REGEXP FILE
+grep_timeout()
+{
+    local j
+    for j in $(seq 100); do
+        grep $1 $2 > /dev/null && return 0
+        sleep 0.1
+    done
+    return 1
+}
+
 # For details, see
 # http://lists.gnu.org/archive/html/bug-coreutils/2009-11/msg00213.html

@@ -37,17 +49,15 @@ for i in $(seq 50); do
     sleep .1
     echo b > k;
     # wait for b to appear in out
+    grep_timeout b out || fail_ failed to find b in out
     while :; do grep b out > /dev/null && break; done
     mv x k
     # wait for tail to detect the rename
-    while :; do grep tail: out > /dev/null && break; done
+    grep_timeout tail: out || fail_ failed to detect rename
     echo ok >> k
     found=0
     # wait up to 10 seconds for "ok" to appear in out
-    for j in $(seq 100); do
-        grep ok out > /dev/null && { found=1; break; }
-        sleep 0.1
-    done
+    grep_timeout ok out && found=1
     kill $pid
     test $found = 0 && { fail=1; cat out; break; }
 done
--
1.7.2.rc0.206.g3336