tests: factor fiemap-related predicate into init.cfg
[platform/upstream/coreutils.git] / tests / init.cfg
1 # This file is sourced by init.sh, *before* its initialization.
2
3 # This goes hand in hand with the "exec 9>&2;" in tests/Makefile.am's
4 # TESTS_ENVIRONMENT definition.
5 stderr_fileno_=9
6
7 # FIXME: eventually s/error_/fail_/ and remove the definition of error_ below.
8 # FIXME: s/(framework_failure)\>/${1}_/ and remove def. of framework_failure
9
10 # Having an unsearchable directory in PATH causes execve to fail with EACCES
11 # when applied to an unresolvable program name, contrary to the desired ENOENT.
12 # Avoid the problem by rewriting PATH to exclude unsearchable directories.
13 sanitize_path_()
14 {
15   # FIXME: remove double quotes around $IFS when all tests use init.sh.
16   # They constitute a work-around for a bug in FreeBSD 8.1's /bin/sh.
17   local saved_IFS="$IFS"
18     IFS=:
19     set -- $PATH
20   IFS=$saved_IFS
21
22   local d d1
23   local colon=
24   local new_path=
25   for d in "$@"; do
26     test -z "$d" && d1=. || d1=$d
27     if ls -d "$d1/." > /dev/null 2>&1; then
28       new_path="$new_path$colon$d"
29       colon=':'
30     fi
31   done
32
33   PATH=$new_path
34   export PATH
35 }
36
37 skip_test_()
38 {
39   echo "$0: skipping test: $@" | head -1 1>&9
40   echo "$0: skipping test: $@" 1>&2
41   Exit 77
42 }
43
44 getlimits_()
45 {
46   eval $(getlimits)
47   test "$INT_MAX" ||
48     error_ "Error running getlimits"
49 }
50
51 require_acl_()
52 {
53   getfacl --version < /dev/null > /dev/null 2>&1 \
54     && setfacl --version < /dev/null > /dev/null 2>&1 \
55       || skip_test_ "This test requires getfacl and setfacl."
56
57   id -u bin > /dev/null 2>&1 \
58     || skip_test_ "This test requires a local user named bin."
59 }
60
61 is_local_dir_()
62 {
63   test $# = 1 || framework_failure
64   df --local "$1" >/dev/null 2>&1
65 }
66
67 require_local_dir_()
68 {
69   is_local_dir_ . ||
70     skip_test_ "This test must be run on a local file system."
71 }
72
73 # Skip this test if we're not in SELinux "enforcing" mode.
74 require_selinux_enforcing_()
75 {
76   test "$(getenforce)" = Enforcing \
77     || skip_test_ "This test is useful only with SELinux in Enforcing mode."
78 }
79
80 require_openat_support_()
81 {
82   # Skip this test if your system has neither the openat-style functions
83   # nor /proc/self/fd support with which to emulate them.
84   test -z "$CONFIG_HEADER" \
85     && skip_test_ 'internal error: CONFIG_HEADER not defined'
86
87   _skip=yes
88   grep '^#define HAVE_OPENAT' "$CONFIG_HEADER" > /dev/null && _skip=no
89   test -d /proc/self/fd && _skip=no
90   if test $_skip = yes; then
91     skip_test_ 'this system lacks openat support'
92   fi
93 }
94
95 require_ulimit_()
96 {
97   ulimit_works=yes
98   # Expect to be able to exec a program in 10MB of virtual memory,
99   # but not in 20KB.  I chose "date".  It must not be a shell built-in
100   # function, so you can't use echo, printf, true, etc.
101   # Of course, in coreutils, I could use $top_builddir/src/true,
102   # but this should be able to work for other projects, too.
103   ( ulimit -v 10000; date ) > /dev/null 2>&1 || ulimit_works=no
104   ( ulimit -v 20;    date ) > /dev/null 2>&1 && ulimit_works=no
105
106   test $ulimit_works = no \
107     && skip_test_ "this shell lacks ulimit support"
108 }
109
110 require_readable_root_()
111 {
112   test -r / || skip_test_ "/ is not readable"
113 }
114
115 # Skip the current test if strace is not available or doesn't work
116 # with the named syscall.  Usage: require_strace_ unlink
117 require_strace_()
118 {
119   test $# = 1 || framework_failure
120
121   strace -V < /dev/null > /dev/null 2>&1 ||
122     skip_test_ 'no strace program'
123
124   strace -qe "$1" echo > /dev/null 2>&1 ||
125     skip_test_ 'strace -qe "'"$1"'" does not work'
126 }
127
128 # Require a controlling input `terminal'.
129 require_controlling_input_terminal_()
130 {
131   tty -s || have_input_tty=no
132   test -t 0 || have_input_tty=no
133   if test "$have_input_tty" = no; then
134     skip_test_ 'requires controlling input terminal
135 This test must have a controlling input "terminal", so it may not be
136 run via "batch", "at", or "ssh".  On some systems, it may not even be
137 run in the background.'
138   fi
139 }
140
141 require_built_()
142 {
143   skip_=no
144   for i in "$@"; do
145     case " $built_programs " in
146       *" $i "*) ;;
147       *) echo "$i: not built" 1>&2; skip_=yes ;;
148     esac
149   done
150
151   test $skip_ = yes && skip_test_ "required program(s) not built"
152 }
153
154 uid_is_privileged_()
155 {
156   # Make sure id -u succeeds.
157   my_uid=$(id -u) \
158     || { echo "$0: cannot run \`id -u'" 1>&2; return 1; }
159
160   # Make sure it gives valid output.
161   case $my_uid in
162     0) ;;
163     *[!0-9]*)
164       echo "$0: invalid output (\`$my_uid') from \`id -u'" 1>&2
165       return 1 ;;
166     *) return 1 ;;
167   esac
168 }
169
170 get_process_status_()
171 {
172   sed -n '/^State:[      ]*\([[:alpha:]]\).*/s//\1/p' /proc/$1/status
173 }
174
175 # Convert an ls-style permission string, like drwxr----x and -rw-r-x-wx
176 # to the equivalent chmod --mode (-m) argument, (=,u=rwx,g=r,o=x and
177 # =,u=rw,g=rx,o=wx).  Ignore ACLs.
178 rwx_to_mode_()
179 {
180   case $# in
181     1) rwx=$1;;
182     *) echo "$0: wrong number of arguments" 1>&2
183       echo "Usage: $0 ls-style-mode-string" 1>&2
184       return;;
185   esac
186
187   case $rwx in
188     [ld-][rwx-][rwx-][rwxsS-][rwx-][rwx-][rwxsS-][rwx-][rwx-][rwxtT-]) ;;
189     [ld-][rwx-][rwx-][rwxsS-][rwx-][rwx-][rwxsS-][rwx-][rwx-][rwxtT-][+.]) ;;
190     *) echo "$0: invalid mode string: $rwx" 1>&2; return;;
191   esac
192
193   # Perform these conversions:
194   # S  s
195   # s  xs
196   # T  t
197   # t  xt
198   # The `T' and `t' ones are only valid for `other'.
199   s='s/S/@/;s/s/x@/;s/@/s/'
200   t='s/T/@/;s/t/x@/;s/@/t/'
201
202   u=`echo $rwx|sed 's/^.\(...\).*/,u=\1/;s/-//g;s/^,u=$//;'$s`
203   g=`echo $rwx|sed 's/^....\(...\).*/,g=\1/;s/-//g;s/^,g=$//;'$s`
204   o=`echo $rwx|sed 's/^.......\(...\).*/,o=\1/;s/-//g;s/^,o=$//;'$s';'$t`
205   echo "=$u$g$o"
206 }
207
208 skip_if_()
209 {
210   case $1 in
211     root) skip_test_ must be run as root ;;
212     non-root) skip_test_ must be run as non-root ;;
213     *) ;;  # FIXME?
214   esac
215 }
216
217 require_selinux_()
218 {
219   case `ls -Zd .` in
220     '? .'|'unlabeled .')
221       skip_test_ "this system (or maybe just" \
222         "the current file system) lacks SELinux support"
223     ;;
224   esac
225 }
226
227 very_expensive_()
228 {
229   if test "$RUN_VERY_EXPENSIVE_TESTS" != yes; then
230     skip_test_ 'very expensive: disabled by default
231 This test is very expensive, so it is disabled by default.
232 To run it anyway, rerun make check with the RUN_VERY_EXPENSIVE_TESTS
233 environment variable set to yes.  E.g.,
234
235   env RUN_VERY_EXPENSIVE_TESTS=yes make check
236 '
237   fi
238 }
239
240 expensive_()
241 {
242   if test "$RUN_EXPENSIVE_TESTS" != yes; then
243     skip_test_ 'expensive: disabled by default
244 This test is relatively expensive, so it is disabled by default.
245 To run it anyway, rerun make check with the RUN_EXPENSIVE_TESTS
246 environment variable set to yes.  E.g.,
247
248   env RUN_EXPENSIVE_TESTS=yes make check
249 '
250   fi
251 }
252
253 require_root_()
254 {
255   uid_is_privileged_ || skip_test_ "must be run as root"
256   NON_ROOT_USERNAME=${NON_ROOT_USERNAME=nobody}
257   NON_ROOT_GROUP=${NON_ROOT_GROUP=$(id -g $NON_ROOT_USERNAME)}
258 }
259
260 skip_if_root_() { uid_is_privileged_ && skip_test_ "must be run as non-root"; }
261 error_() { echo "$0: $@" 1>&2; Exit 1; }
262 framework_failure() { error_ 'failure in testing framework'; }
263
264 # Set `groups' to a space-separated list of at least two groups
265 # of which the user is a member.
266 require_membership_in_two_groups_()
267 {
268   test $# = 0 || framework_failure
269
270   groups=${COREUTILS_GROUPS-`(id -G || /usr/xpg4/bin/id -G) 2>/dev/null`}
271   case "$groups" in
272     *' '*) ;;
273     *) skip_test_ 'requires membership in two groups
274 this test requires that you be a member of more than one group,
275 but running `id -G'\'' either failed or found just one.  If you really
276 are a member of at least two groups, then rerun this test with
277 COREUTILS_GROUPS set in your environment to the space-separated list
278 of group names or numbers.  E.g.,
279
280   env COREUTILS_GROUPS='users cdrom' make check
281
282 '
283      ;;
284   esac
285 }
286
287 # Is /proc/$PID/status supported?
288 require_proc_pid_status_()
289 {
290     sleep 2 &
291     local pid=$!
292     sleep .5
293     grep '^State:[       ]*[S]' /proc/$pid/status > /dev/null 2>&1 ||
294     skip_test_ "/proc/$pid/status: missing or 'different'"
295     kill $pid
296 }
297
298 # Return nonzero if the specified directory is on a file system
299 # for which FIEMAP support exists.
300 fiemap_capable_()
301 {
302   df -T -t btrfs -t xfs -t ext4 -t ocfs2 "$@"
303 }
304
305 # Does the current (working-dir) file system support sparse files?
306 require_sparse_support_()
307 {
308   test $# = 0 || framework_failure
309   # Test whether we can create a sparse file.
310   # For example, on Darwin6.5 with a file system of type hfs, it's not possible.
311   # NTFS requires 128K before a hole appears in a sparse file.
312   t=sparse.$$
313   dd bs=1 seek=128K of=$t < /dev/null 2> /dev/null
314   set x `du -sk $t`
315   kb_size=$2
316   rm -f $t
317   if test $kb_size -ge 128; then
318     skip_test_ 'this file system does not support sparse files'
319   fi
320 }
321
322 mkfifo_or_skip_()
323 {
324   test $# = 1 || framework_failure
325   if ! mkfifo "$1"; then
326     # Make an exception of this case -- usually we interpret framework-creation
327     # failure as a test failure.  However, in this case, when running on a SunOS
328     # system using a disk NFS mounted from OpenBSD, the above fails like this:
329     # mkfifo: cannot make fifo `fifo-10558': Not owner
330     skip_test_ 'NOTICE: unable to create test prerequisites'
331   fi
332 }
333
334 # Disable the current test if the working directory seems to have
335 # the setgid bit set.
336 skip_if_setgid_()
337 {
338   setgid_tmpdir=setgid-$$
339   (umask 77; mkdir $setgid_tmpdir)
340   perms=$(stat --printf %A $setgid_tmpdir)
341   rmdir $setgid_tmpdir
342   case $perms in
343     drwx------);;
344     drwxr-xr-x);;  # Windows98 + DJGPP 2.03
345     *) skip_test_ 'this directory has the setgid bit set';;
346   esac
347 }
348
349 skip_if_mcstransd_is_running_()
350 {
351   test $# = 0 || framework_failure
352
353   # When mcstransd is running, you'll see only the 3-component
354   # version of file-system context strings.  Detect that,
355   # and if it's running, skip this test.
356   __ctx=$(stat --printf='%C\n' .) || framework_failure
357   case $__ctx in
358     *:*:*:*) ;; # four components is ok
359     *) # anything else probably means mcstransd is running
360         skip_test_ "unexpected context '$__ctx'; turn off mcstransd" ;;
361   esac
362 }
363
364 # Skip the current test if umask doesn't work as usual.
365 # This test should be run in the temporary directory that ends
366 # up being removed via the trap commands.
367 working_umask_or_skip_()
368 {
369   umask 022
370   touch file1 file2
371   chmod 644 file2
372   perms=`ls -l file1 file2 | sed 's/ .*//' | uniq`
373   rm -f file1 file2
374
375   case $perms in
376   *'
377   '*) skip_test_ 'your build directory has unusual umask semantics'
378   esac
379 }
380
381 # Retry a function requiring a sufficient delay to _pass_
382 # using a truncated exponential backoff method.
383 #     Example: retry_delay_ dd_reblock_1 .1 6
384 # This example will call the dd_reblock_1 function with
385 # an initial delay of .1 second and call it at most 6 times
386 # with a max delay of 3.2s (doubled each time), or a total of 6.3s
387 # Note ensure you do _not_ quote the parameter to GNU sleep in
388 # your function, as it may contain separate values that `sleep`
389 # needs to accumulate.
390 retry_delay_()
391 {
392   local test_func=$1
393   local init_delay=$2
394   local max_n_tries=$3
395
396   local attempt=1
397   local num_sleeps=$attempt
398   local time_fail
399   while test $attempt -le $max_n_tries; do
400     local delay=$($AWK -v n=$num_sleeps -v s="$init_delay" \
401                   'BEGIN { print s * n }')
402     "$test_func" "$delay" && { time_fail=0; break; } || time_fail=1
403     attempt=$(expr $attempt + 1)
404     num_sleeps=$(expr $num_sleeps '*' 2)
405   done
406   test "$time_fail" = 0
407 }
408
409 # Call this with a list of programs under test immediately after
410 # sourcing init.sh.
411 print_ver_()
412 {
413   if test "$VERBOSE" = yes; then
414     local i
415     for i in $*; do
416       env $i --version
417     done
418   fi
419 }
420
421 sanitize_path_