1#! /bin/sh
2
3# Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
4# Copyright (C) 2003-2020 Wayne Davison
5
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License version
8# 2 as published by the Free Software Foundation.
9#
10# This program is distributed in the hope that it will be useful, but
11# WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13# Lesser General Public License for more details.
14#
15# You should have received a copy of the GNU Lesser General Public
16# License along with this program; if not, write to the Free Software
17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
19# -------------------------------------------------------------------------
20
21# rsync top-level test script -- this invokes all the other more
22# detailed tests in order.  This script can either be called by `make
23# check' or `make installcheck'.  `check' runs against the copies of
24# the program and other files in the build directory, and
25# `installcheck' against the installed copy of the program.
26
27# It can also be called on a single test file using a run like this:
28#
29#  preserve_scratch=yes whichtests=itemize.test ./runtests.sh
30
31# In either case we need to also be able to find the source directory,
32# since we read test scripts and possibly other information from
33# there.
34
35# Whenever possible, informational messages are written to stdout and
36# error messages to stderr.  They're separated out by the build farm
37# display scripts.
38
39# According to the GNU autoconf manual, the only valid place to set up
40# directory locations is through Make, since users are allowed to (try
41# to) change their mind on the Make command line.  So, Make has to
42# pass in all the values we need.
43
44# For other configured settings we read ./config.sh, which tells us
45# about shell commands on this machine and similar things.
46
47# rsync_bin gives the location of the rsync binary.  This is either
48# builddir/rsync if we're testing an uninstalled copy, or
49# install_prefix/bin/rsync if we're testing an installed copy.  On the
50# build farm rsync will be installed, but into a scratch /usr.
51
52# srcdir gives the location of the source tree, which lets us find the
53# build scripts.  At the moment we assume we are invoked from the
54# source directory.
55
56# This script must be invoked from the build directory.
57
58# A scratch directory, 'testtmp', is used in the build directory to
59# hold per-test subdirectories.
60
61# This script also uses the $loglevel environment variable.  1 is the
62# default value, and 10 the most verbose.  You can set this from the
63# Make command line.  It's also set by the build farm to give more
64# detail for failing builds.
65
66# -------------------------------------------------------------------------
67
68# NOTES FOR TEST CASES:
69
70# Each test case runs in its own shell.
71
72# Exit codes from tests:
73
74#    1  tests failed
75#    2  error in starting tests
76#   77  this test skipped (random value unlikely to happen by chance, same as
77#       automake)
78
79# HOWEVER, the overall exit code to the farm is different: we return
80# the *number of tests that failed*, so that it will show up nicely in
81# the overall summary.
82
83# rsync.fns contains some general setup functions and definitions.
84
85# -------------------------------------------------------------------------
86
87# NOTES ON PORTABILITY:
88
89# Both this script and the Makefile have to be pretty conservative
90# about which Unix features they use.
91
92# We cannot count on Make exporting variables to commands, unless
93# they're explicitly given on the command line.
94
95# Also, we can't count on 'cp -a' or 'mkdir -p', although they're
96# pretty handy (see function makepath for the latter).
97
98# I think some of the GNU documentation suggests that we shouldn't
99# rely on shell functions.  However, the Bash manual seems to say that
100# they're in POSIX 1003.2, and since the build farm relies on them
101# they're probably working on most machines we really care about.
102
103# You cannot use "function foo {" syntax, but must instead say "foo()
104# {", or it breaks on FreeBSD.
105
106# BSD machines tend not to have "head" or "seq".
107
108# You cannot do "export VAR=VALUE" all on one line; the export must be
109# separate from the assignment.  (SCO SysV)
110
111# Don't rely on grep -q, as that doesn't work everywhere -- just redirect
112# stdout to /dev/null to keep it quiet.
113
114# -------------------------------------------------------------------------
115
116# STILL TO DO:
117
118# We need a good protection against tests that hang indefinitely.
119# Perhaps some combination of starting them in the background, wait,
120# and kill?
121
122# Perhaps we need a common way to cleanup tests.  At the moment just
123# clobbering the directory when we're done should be enough.
124
125# If any of the targets fail, then (GNU?) Make returns 2, instead of
126# the return code from the failing command.  This is fine, but it
127# means that the build farm just shows "2" for failed tests, not the
128# number of tests that actually failed.  For more details we might
129# need to grovel through the log files to find a line saying how many
130# failed.
131
132
133set -e
134
135. "./shconfig"
136
137RUNSHFLAGS='-e'
138export RUNSHFLAGS
139
140# for Solaris
141if [ -d /usr/xpg4/bin ]; then
142    PATH="/usr/xpg4/bin/:$PATH"
143    export PATH
144fi
145
146if [ "x$loglevel" != x ] && [ "$loglevel" -gt 8 ]; then
147    if set -x; then
148	# If it doesn't work the first time, don't keep trying.
149	RUNSHFLAGS="$RUNSHFLAGS -x"
150    fi
151fi
152
153POSIXLY_CORRECT=1
154if test x"$TOOLDIR" = x; then
155    TOOLDIR=`pwd`
156fi
157srcdir=`dirname $0`
158if test x"$srcdir" = x -o x"$srcdir" = x.; then
159    srcdir="$TOOLDIR"
160fi
161if test x"$rsync_bin" = x; then
162    rsync_bin="$TOOLDIR/rsync"
163fi
164
165# This allows the user to specify extra rsync options -- use carefully!
166RSYNC="$rsync_bin $*"
167#RSYNC="valgrind $rsync_bin $*"
168
169TLS_ARGS=''
170if egrep '^#define HAVE_LUTIMES 1' config.h >/dev/null; then
171    TLS_ARGS="$TLS_ARGS -l"
172fi
173if egrep '#undef CHOWN_MODIFIES_SYMLINK' config.h >/dev/null; then
174    TLS_ARGS="$TLS_ARGS -L"
175fi
176
177export POSIXLY_CORRECT TOOLDIR srcdir RSYNC TLS_ARGS
178
179echo "============================================================"
180echo "$0 running in $TOOLDIR"
181echo "    rsync_bin=$RSYNC"
182echo "    srcdir=$srcdir"
183echo "    TLS_ARGS=$TLS_ARGS"
184
185if [ -f /usr/bin/whoami ]; then
186    testuser=`/usr/bin/whoami`
187elif [ -f /usr/ucb/whoami ]; then
188    testuser=`/usr/ucb/whoami`
189elif [ -f /bin/whoami ]; then
190    testuser=`/bin/whoami`
191else
192    testuser=`id -un 2>/dev/null || echo ${LOGNAME:-${USERNAME:-${USER:-'UNKNOWN'}}}`
193fi
194
195echo "    testuser=$testuser"
196echo "    os=`uname -a`"
197
198# It must be "yes", not just nonnull
199if [ "x$preserve_scratch" = xyes ]; then
200    echo "    preserve_scratch=yes"
201else
202    echo "    preserve_scratch=no"
203fi
204
205# Check if setacl/setfacl is around and if it supports the -k or -s option.
206if setacl -k u::7,g::5,o:5 testsuite 2>/dev/null; then
207    setfacl_nodef='setacl -k'
208elif setfacl --help 2>&1 | grep ' -k,\|\[-[a-z]*k' >/dev/null; then
209    setfacl_nodef='setfacl -k'
210elif setfacl -s u::7,g::5,o:5 testsuite 2>/dev/null; then
211    setfacl_nodef='setfacl -s u::7,g::5,o:5'
212else
213    # The "true" command runs successfully, but does nothing.
214    setfacl_nodef=true
215fi
216
217export setfacl_nodef
218
219if [ ! -f "$rsync_bin" ]; then
220    echo "rsync_bin $rsync_bin is not a file" >&2
221    exit 2
222fi
223
224if [ ! -d "$srcdir" ]; then
225    echo "srcdir $srcdir is not a directory" >&2
226    exit 2
227fi
228
229skipped=0
230missing=0
231passed=0
232failed=0
233
234# Directory that holds the other test subdirs.  We create separate dirs
235# inside for each test case, so that they can be left behind in case of
236# failure to aid investigation.  We don't remove the testtmp subdir at
237# the end so that it can be configured as a symlink to a filesystem that
238# has ACLs and xattr support enabled (if desired).
239scratchbase="$TOOLDIR"/testtmp
240echo "    scratchbase=$scratchbase"
241[ -d "$scratchbase" ] || mkdir "$scratchbase"
242
243suitedir="$srcdir/testsuite"
244TESTRUN_TIMEOUT=300
245
246export scratchdir suitedir TESTRUN_TIMEOUT
247
248prep_scratch() {
249    [ -d "$scratchdir" ] && chmod -R u+rwX "$scratchdir" && rm -rf "$scratchdir"
250    mkdir "$scratchdir"
251    # Get rid of default ACLs and dir-setgid to avoid confusing some tests.
252    $setfacl_nodef "$scratchdir" 2>/dev/null || true
253    chmod g-s "$scratchdir"
254    case "$srcdir" in
255    /*) ln -s "$srcdir" "$scratchdir/src" ;;
256    *)  ln -s "$TOOLDIR/$srcdir" "$scratchdir/src" ;;
257    esac
258    return 0
259}
260
261maybe_discard_scratch() {
262    [ x"$preserve_scratch" != xyes ] && [ -d "$scratchdir" ] && rm -rf "$scratchdir"
263    return 0
264}
265
266if [ "x$whichtests" = x ]; then
267    whichtests="*.test"
268fi
269
270for testscript in $suitedir/$whichtests
271do
272    testbase=`echo $testscript | sed -e 's!.*/!!' -e 's/.test\$//'`
273    scratchdir="$scratchbase/$testbase"
274
275    prep_scratch
276
277    case "$testscript" in
278    *hardlinks*) TESTRUN_TIMEOUT=600 ;;
279    *) TESTRUN_TIMEOUT=300 ;;
280    esac
281
282    set +e
283    "$TOOLDIR/"testrun $RUNSHFLAGS "$testscript" >"$scratchdir/test.log" 2>&1
284    result=$?
285    set -e
286
287    if [ "x$always_log" = xyes -o \( $result != 0 -a $result != 77 -a $result != 78 \) ]
288    then
289	echo "----- $testbase log follows"
290	cat "$scratchdir/test.log"
291	echo "----- $testbase log ends"
292	if [ -f "$scratchdir/rsyncd.log" ]; then
293	    echo "----- $testbase rsyncd.log follows"
294	    cat "$scratchdir/rsyncd.log"
295	    echo "----- $testbase rsyncd.log ends"
296	fi
297    fi
298
299    case $result in
300    0)
301	echo "PASS    $testbase"
302	passed=`expr $passed + 1`
303	maybe_discard_scratch
304	;;
305    77)
306	# backticks will fill the whole file onto one line, which is a feature
307	whyskipped=`cat "$scratchdir/whyskipped"`
308	echo "SKIP    $testbase ($whyskipped)"
309	skipped=`expr $skipped + 1`
310	maybe_discard_scratch
311	;;
312    78)
313        # It failed, but we expected that.  don't dump out error logs,
314	# because most users won't want to see them.  But do leave
315	# the working directory around.
316	echo "XFAIL   $testbase"
317	failed=`expr $failed + 1`
318	;;
319    *)
320	echo "FAIL    $testbase"
321	failed=`expr $failed + 1`
322	if [ "x$nopersist" = xyes ]; then
323	    exit 1
324	fi
325    esac
326done
327
328echo '------------------------------------------------------------'
329echo "----- overall results:"
330echo "      $passed passed"
331[ "$failed" -gt 0 ]  && echo "      $failed failed"
332[ "$skipped" -gt 0 ] && echo "      $skipped skipped"
333[ "$missing" -gt 0 ] && echo "      $missing missing"
334echo '------------------------------------------------------------'
335
336# OK, so expr exits with 0 if the result is neither null nor zero; and
337# 1 if the expression is null or zero.  This is the opposite of what
338# we want, and if we just call expr then this script will always fail,
339# because -e is set.
340
341result=`expr $failed + $missing || true`
342if [ "$result" = 0 -a "$skipped" -gt "${RSYNC_MAX_SKIPPED:-9999}" ]; then
343    result=1
344fi
345echo "overall result is $result"
346exit $result
347