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