doc: move @shortcontents and @contents from end to start
[platform/upstream/coreutils.git] / tests / test-lib.sh
1 # source this file; set up for tests
2
3 # Skip this test if the shell lacks support for functions.
4 unset function_test
5 eval 'function_test() { return 11; }; function_test'
6 if test $? != 11; then
7   echo "$0: /bin/sh lacks support for functions; skipping this test." 1>&2
8   Exit 77
9 fi
10
11 skip_test_()
12 {
13   echo "$0: skipping test: $@" 1>&2
14   Exit 77
15 }
16
17 require_acl_()
18 {
19   getfacl --version < /dev/null > /dev/null 2>&1 \
20     && setfacl --version < /dev/null > /dev/null 2>&1 \
21       || skip_test_ "This test requires getfacl and setfacl."
22
23   id -u bin > /dev/null 2>&1 \
24     || skip_test_ "This test requires a local user named bin."
25 }
26
27 require_ulimit_()
28 {
29   ulimit_works=yes
30   # Expect to be able to exec a program in 10MB of virtual memory,
31   # but not in 20KB.  I chose "date".  It must not be a shell built-in
32   # function, so you can't use echo, printf, true, etc.
33   # Of course, in coreutils, I could use $top_builddir/src/true,
34   # but this should be able to work for other projects, too.
35   ( ulimit -v 10000; date ) > /dev/null 2>&1 || ulimit_works=no
36   ( ulimit -v 20;    date ) > /dev/null 2>&1 && ulimit_works=no
37
38   test $ulimit_works = no \
39     && skip_test_ "this shell lacks ulimit support"
40 }
41
42 require_readable_root_()
43 {
44   test -r / || skip_test_ "/ is not readable"
45 }
46
47 # Skip the current test if strace is not available or doesn't work
48 # with the named syscall.  Usage: require_strace_ unlink
49 require_strace_()
50 {
51   test $# = 1 || framework_failure
52
53   strace -V < /dev/null > /dev/null 2>&1 ||
54     skip_test_ 'no strace program'
55
56   strace -qe "$1" echo > /dev/null 2>&1 ||
57     skip_test_ 'strace -qe "'"$1"'" does not work'
58 }
59
60 # Require a controlling input `terminal'.
61 require_controlling_input_terminal_()
62 {
63   tty -s || have_input_tty=no
64   test -t 1 || have_input_tty=no
65   if test "$have_input_tty" = no; then
66     echo "$0: This test must have a controlling input \`terminal'," 1>&2
67     echo "  so it may not be run via \`batch', \`at', or \`rsh'." 1>&2
68     echo "  On some systems, it may not even be run in the background." 1>&2
69     (exit 77); exit 77
70   fi
71 }
72
73 require_built_()
74 {
75   skip_=no
76   for i in "$@"; do
77     case " $built_programs " in
78       *" $i "*) ;;
79       *) echo "$i: not built" 1>&2; skip_=yes ;;
80     esac
81   done
82
83   test $skip_ = yes && skip_test_ "required program(s) not built"
84 }
85
86 uid_is_privileged_()
87 {
88   # Make sure id -u succeeds.
89   my_uid=$(id -u) \
90     || { echo "$0: cannot run \`id -u'" 1>&2; return 1; }
91
92   # Make sure it gives valid output.
93   case $my_uid in
94     0) ;;
95     *[!0-9]*)
96       echo "$0: invalid output (\`$my_uid') from \`id -u'" 1>&2
97       return 1 ;;
98     *) return 1 ;;
99   esac
100 }
101
102 # Convert an ls-style permission string, like drwxr----x and -rw-r-x-wx
103 # to the equivalent chmod --mode (-m) argument, (=,u=rwx,g=r,o=x and
104 # =,u=rw,g=rx,o=wx).  Ignore ACLs.
105 rwx_to_mode_()
106 {
107   case $# in
108     1) rwx=$1;;
109     *) echo "$0: wrong number of arguments" 1>&2
110       echo "Usage: $0 ls-style-mode-string" 1>&2
111       return;;
112   esac
113
114   case $rwx in
115     [ld-][rwx-][rwx-][rwxsS-][rwx-][rwx-][rwxsS-][rwx-][rwx-][rwxtT-]) ;;
116     [ld-][rwx-][rwx-][rwxsS-][rwx-][rwx-][rwxsS-][rwx-][rwx-][rwxtT-]+) ;;
117     *) echo "$0: invalid mode string: $rwx" 1>&2; return;;
118   esac
119
120   # Perform these conversions:
121   # S  s
122   # s  xs
123   # T  t
124   # t  xt
125   # The `T' and `t' ones are only valid for `other'.
126   s='s/S/@/;s/s/x@/;s/@/s/'
127   t='s/T/@/;s/t/x@/;s/@/t/'
128
129   u=`echo $rwx|sed 's/^.\(...\).*/,u=\1/;s/-//g;s/^,u=$//;'$s`
130   g=`echo $rwx|sed 's/^....\(...\).*/,g=\1/;s/-//g;s/^,g=$//;'$s`
131   o=`echo $rwx|sed 's/^.......\(...\).*/,o=\1/;s/-//g;s/^,o=$//;'$s';'$t`
132   echo "=$u$g$o"
133 }
134
135 skip_if_()
136 {
137   case $1 in
138     root) skip_test_ must be run as root ;;
139     non-root) skip_test_ must be run as non-root ;;
140     *) ;;  # FIXME?
141   esac
142 }
143
144 require_selinux_()
145 {
146   case `ls -Zd .` in
147     '? .'|'unlabeled .')
148       skip_test_ "this system (or maybe just" \
149         "the current file system) lacks SELinux support"
150     ;;
151   esac
152 }
153
154 very_expensive_()
155 {
156   if test "$RUN_VERY_EXPENSIVE_TESTS" != yes; then
157     skip_test_ '
158 This test is very expensive, so it is disabled by default.
159 To run it anyway, rerun make check with the RUN_VERY_EXPENSIVE_TESTS
160 environment variable set to yes.  E.g.,
161
162   env RUN_VERY_EXPENSIVE_TESTS=yes make check
163 '
164   fi
165 }
166
167 expensive_()
168 {
169   if test "$RUN_EXPENSIVE_TESTS" != yes; then
170     skip_test_ '
171 This test is relatively expensive, so it is disabled by default.
172 To run it anyway, rerun make check with the RUN_EXPENSIVE_TESTS
173 environment variable set to yes.  E.g.,
174
175   env RUN_EXPENSIVE_TESTS=yes make check
176 '
177   fi
178 }
179
180 require_root_()
181 {
182   uid_is_privileged_ || skip_test_ "must be run as root"
183   NON_ROOT_USERNAME=${NON_ROOT_USERNAME=nobody}
184 }
185
186 skip_if_root_() { uid_is_privileged_ && skip_test_ "must be run as non-root"; }
187 error_() { echo "$0: $@" 1>&2; Exit 1; }
188 framework_failure() { error_ 'failure in testing framework'; }
189
190 # Set `groups' to a space-separated list of at least two groups
191 # of which the user is a member.
192 require_membership_in_two_groups_()
193 {
194   test $# = 0 || framework_failure
195
196   groups=${COREUTILS_GROUPS-`(id -G || /usr/xpg4/bin/id -G) 2>/dev/null`}
197   case "$groups" in
198     *' '*) ;;
199     *) skip_test_ '
200 $0: this test requires that you be a member of more than one group,
201 but running `id -G'\'' either failed or found just one.  If you really
202 are a member of at least two groups, then rerun this test with
203 COREUTILS_GROUPS set in your environment to the space-separated list
204 of group names or numbers.  E.g.,
205
206   env COREUTILS_GROUPS='users cdrom' make check
207
208 '
209      ;;
210   esac
211 }
212
213 # Does the current (working-dir) file system support sparse files?
214 require_sparse_support_()
215 {
216   test $# = 0 || framework_failure
217   # Test whether we can create a sparse file.
218   # For example, on Darwin6.5 with a file system of type hfs, it's not possible.
219   # NTFS requires 128K before a hole appears in a sparse file.
220   t=sparse.$$
221   dd bs=1 seek=128K of=$t < /dev/null 2> /dev/null
222   set x `du -sk $t`
223   kb_size=$2
224   rm -f $t
225   if test $kb_size -ge 128; then
226     skip_test_ 'this file system does not support sparse files'
227   fi
228 }
229
230 mkfifo_or_skip_()
231 {
232   test $# = 1 || framework_failure
233   if ! mkfifo "$1"; then
234     # Make an exception of this case -- usually we interpret framework-creation
235     # failure as a test failure.  However, in this case, when running on a SunOS
236     # system using a disk NFS mounted from OpenBSD, the above fails like this:
237     # mkfifo: cannot make fifo `fifo-10558': Not owner
238     skip_test_ 'NOTICE: unable to create test prerequisites'
239   fi
240 }
241
242 skip_if_mcstransd_is_running_()
243 {
244   test $# = 0 || framework_failure
245
246   # When mcstransd is running, you'll see only the 3-component
247   # version of file-system context strings.  Detect that,
248   # and if it's running, skip this test.
249   __ctx=$(stat --printf='%C\n' .) || framework_failure
250   case $__ctx in
251     *:*:*:*) ;; # four components is ok
252     *) # anything else probably means mcstransd is running
253         skip_test_ "unexpected context '$__ctx'; turn off mcstransd" ;;
254   esac
255 }
256
257 # Skip the current test if umask doesn't work as usual.
258 # This test should be run in the temporary directory that ends
259 # up being removed via the trap commands.
260 working_umask_or_skip_()
261 {
262   umask 022
263   touch file1 file2
264   chmod 644 file2
265   perms=`ls -l file1 file2 | sed 's/ .*//' | uniq`
266   rm -f file1 file2
267
268   case $perms in
269   *'
270   '*) skip_test_ 'your build directory has unusual umask semantics'
271   esac
272 }
273
274 # We use a trap below for cleanup.  This requires us to go through
275 # hoops to get the right exit status transported through the signal.
276 # So use `Exit STATUS' instead of `exit STATUS' inside of the tests.
277 # Turn off errexit here so that we don't trip the bug with OSF1/Tru64
278 # sh inside this function.
279 Exit ()
280 {
281   set +e
282   (exit $1)
283   exit $1
284 }
285
286 test_dir_=$(pwd)
287
288 this_test_() { echo "./$0" | sed 's,.*/,,'; }
289 this_test=$(this_test_)
290
291 # This is a stub function that is run upon trap (upon regular exit and
292 # interrupt).  Override it with a per-test function, e.g., to unmount
293 # a partition, or to undo any other global state changes.
294 cleanup_() { :; }
295
296 t_=$("$abs_top_builddir/src/mktemp" -d --tmp="$test_dir_" cu-$this_test.XXXXXXXXXX)\
297     || error_ "failed to create temporary directory in $test_dir_"
298
299 remove_tmp_()
300 {
301   __st=$?
302   cleanup_
303   cd "$test_dir_" && chmod -R u+rwx "$t_" && rm -rf "$t_" && exit $__st
304 }
305
306 # Run each test from within a temporary sub-directory named after the
307 # test itself, and arrange to remove it upon exception or normal exit.
308 trap remove_tmp_ 0
309 trap 'Exit $?' 1 2 13 15
310
311 cd "$t_" || error_ "failed to cd to $t_"
312
313 if ( diff --version < /dev/null 2>&1 | grep GNU ) 2>&1 > /dev/null; then
314   compare() { diff -u "$@"; }
315 elif ( cmp --version < /dev/null 2>&1 | grep GNU ) 2>&1 > /dev/null; then
316   compare() { cmp -s "$@"; }
317 else
318   compare() { cmp "$@"; }
319 fi
320
321 # Local Variables:
322 # indent-tabs-mode: nil
323 # End: