xref: /netbsd-src/external/gpl3/gcc.old/dist/contrib/patch_tester.sh (revision 1debfc3d3fad8af6f31804271c18e67f77b4d718)
1*1debfc3dSmrg#!/bin/sh
2*1debfc3dSmrg
3*1debfc3dSmrg# Tests a set of patches from a directory.
4*1debfc3dSmrg# Copyright (C) 2007, 2008, 2011  Free Software Foundation, Inc.
5*1debfc3dSmrg# Contributed by Sebastian Pop <sebastian.pop@amd.com>
6*1debfc3dSmrg
7*1debfc3dSmrg# This program is free software; you can redistribute it and/or modify
8*1debfc3dSmrg# it under the terms of the GNU General Public License as published by
9*1debfc3dSmrg# the Free Software Foundation; either version 3 of the License, or
10*1debfc3dSmrg# (at your option) any later version.
11*1debfc3dSmrg
12*1debfc3dSmrg# This program is distributed in the hope that it will be useful,
13*1debfc3dSmrg# but WITHOUT ANY WARRANTY; without even the implied warranty of
14*1debfc3dSmrg# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*1debfc3dSmrg# GNU General Public License for more details.
16*1debfc3dSmrg
17*1debfc3dSmrg# You should have received a copy of the GNU General Public License
18*1debfc3dSmrg# along with this program; if not, write to the Free Software
19*1debfc3dSmrg# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20*1debfc3dSmrg
21*1debfc3dSmrgcat <<EOF
22*1debfc3dSmrg
23*1debfc3dSmrgWARNING: This script should only be fed with patches from known
24*1debfc3dSmrg         authorized and trusted sources.  Don't even think about
25*1debfc3dSmrg         hooking it up to a raw feed from the gcc-patches list or
26*1debfc3dSmrg         you'll regret it.
27*1debfc3dSmrg
28*1debfc3dSmrgEOF
29*1debfc3dSmrg
30*1debfc3dSmrgargs=$@
31*1debfc3dSmrg
32*1debfc3dSmrgsvnpath=svn://gcc.gnu.org/svn/gcc
33*1debfc3dSmrgdashj=
34*1debfc3dSmrgdefault_standby=1
35*1debfc3dSmrgstandby=$default_standby
36*1debfc3dSmrgdefault_watermark=0.60
37*1debfc3dSmrgwatermark=$default_watermark
38*1debfc3dSmrgsavecompilers=false
39*1debfc3dSmrgnopristinecache=false
40*1debfc3dSmrgnogpg=false
41*1debfc3dSmrgstop=false
42*1debfc3dSmrg
43*1debfc3dSmrgusage() {
44*1debfc3dSmrg    cat <<EOF
45*1debfc3dSmrgpatch_tester.sh [-j<N>] [-standby N] [-watermark N] [-savecompilers] [-nogpg]
46*1debfc3dSmrg                [-svnpath URL] [-stop] [-nopristinecache]
47*1debfc3dSmrg                <source_dir> [patches_dir [state_dir [build_dir]]]
48*1debfc3dSmrg
49*1debfc3dSmrg    J is the flag passed to make.  Default is empty string.
50*1debfc3dSmrg
51*1debfc3dSmrg    STANDBY is the number of minutes between checks for new patches in
52*1debfc3dSmrg    PATCHES_DIR.  Default is ${default_standby} minutes.
53*1debfc3dSmrg
54*1debfc3dSmrg    WATERMARK is the 5 minute average system charge under which a new
55*1debfc3dSmrg    compile can start.  Default is ${default_watermark}.
56*1debfc3dSmrg
57*1debfc3dSmrg    SAVECOMPILERS copies the compilers in the same directory as the
58*1debfc3dSmrg    test results for the non patched version.  Default is not copy.
59*1debfc3dSmrg
60*1debfc3dSmrg    NOPRISTINECACHE prevents use of cached test results from any earlier
61*1debfc3dSmrg    test runs on the pristine version of the branch and revision under
62*1debfc3dSmrg    test (the default behaviour).  This should be used when testing the
63*1debfc3dSmrg    same revision and patch with multiple sets of configure options, as
64*1debfc3dSmrg    these may affect the set of baseline failures.
65*1debfc3dSmrg
66*1debfc3dSmrg    NOGPG can be used to avoid checking the GPG signature of patches.
67*1debfc3dSmrg
68*1debfc3dSmrg    URL is the location of the GCC SVN repository.  The default is
69*1debfc3dSmrg    ${svnpath}.
70*1debfc3dSmrg
71*1debfc3dSmrg    STOP exits when PATCHES_DIR is empty.
72*1debfc3dSmrg
73*1debfc3dSmrg    SOURCE_DIR is the directory containing GCC's toplevel configure.
74*1debfc3dSmrg
75*1debfc3dSmrg    PATCHES_DIR is the directory containing the patches to be tested.
76*1debfc3dSmrg    Default is SOURCE_DIR/patches.
77*1debfc3dSmrg
78*1debfc3dSmrg    STATE_DIR is where the tester maintains its internal state.
79*1debfc3dSmrg    Default is SOURCE_DIR/state.
80*1debfc3dSmrg
81*1debfc3dSmrg    BUILD_DIR is the build tree, a temporary directory that this
82*1debfc3dSmrg    script will delete and recreate.  Default is SOURCE_DIR/obj.
83*1debfc3dSmrg
84*1debfc3dSmrgEOF
85*1debfc3dSmrg    exit 1
86*1debfc3dSmrg}
87*1debfc3dSmrg
88*1debfc3dSmrgmakedir () {
89*1debfc3dSmrg    DIRNAME=$1
90*1debfc3dSmrg    mkdir -p $DIRNAME
91*1debfc3dSmrg    if [ $? -ne 0 ]; then
92*1debfc3dSmrg	echo "ERROR: could not make directory $DIRNAME"
93*1debfc3dSmrg	exit 1
94*1debfc3dSmrg    fi
95*1debfc3dSmrg}
96*1debfc3dSmrg
97*1debfc3dSmrgwhile [ $# -ne 0 ]; do
98*1debfc3dSmrg    case $1 in
99*1debfc3dSmrg	-j*)
100*1debfc3dSmrg	    dashj=$1; shift
101*1debfc3dSmrg	    ;;
102*1debfc3dSmrg	-standby)
103*1debfc3dSmrg	    [[ $# > 2 ]] || usage
104*1debfc3dSmrg	    standby=$2; shift; shift
105*1debfc3dSmrg	    ;;
106*1debfc3dSmrg	-watermark)
107*1debfc3dSmrg	    [[ $# > 2 ]] || usage
108*1debfc3dSmrg	    watermark=$2; shift; shift
109*1debfc3dSmrg	    ;;
110*1debfc3dSmrg	-savecompilers)
111*1debfc3dSmrg	    savecompilers=true; shift
112*1debfc3dSmrg	    ;;
113*1debfc3dSmrg	-nopristinecache)
114*1debfc3dSmrg	    nopristinecache=true; shift
115*1debfc3dSmrg	    ;;
116*1debfc3dSmrg	-nogpg)
117*1debfc3dSmrg	    nogpg=true; shift
118*1debfc3dSmrg	    ;;
119*1debfc3dSmrg	-stop)
120*1debfc3dSmrg	    stop=true; shift
121*1debfc3dSmrg	    ;;
122*1debfc3dSmrg	-svnpath)
123*1debfc3dSmrg	    svnpath=$2; shift; shift
124*1debfc3dSmrg	    ;;
125*1debfc3dSmrg	-*)
126*1debfc3dSmrg	    echo "Invalid option: $1"
127*1debfc3dSmrg	    usage
128*1debfc3dSmrg	    ;;
129*1debfc3dSmrg	*)
130*1debfc3dSmrg	    break
131*1debfc3dSmrg	    ;;
132*1debfc3dSmrg    esac
133*1debfc3dSmrgdone
134*1debfc3dSmrg
135*1debfc3dSmrgtest $# -eq 0 && usage
136*1debfc3dSmrg
137*1debfc3dSmrgSOURCE=$1
138*1debfc3dSmrgPATCHES=
139*1debfc3dSmrgSTATE=
140*1debfc3dSmrgBUILD=
141*1debfc3dSmrg
142*1debfc3dSmrgif [[ $# < 2 ]]; then
143*1debfc3dSmrg    PATCHES=$SOURCE/patches
144*1debfc3dSmrgelse
145*1debfc3dSmrg    PATCHES=$2
146*1debfc3dSmrgfi
147*1debfc3dSmrgif [[ $# < 3 ]]; then
148*1debfc3dSmrg    STATE=$SOURCE/state
149*1debfc3dSmrgelse
150*1debfc3dSmrg    STATE=$3
151*1debfc3dSmrgfi
152*1debfc3dSmrgif [[ $# < 4 ]]; then
153*1debfc3dSmrg    BUILD=$SOURCE/obj
154*1debfc3dSmrgelse
155*1debfc3dSmrg    BUILD=$4
156*1debfc3dSmrgfi
157*1debfc3dSmrg
158*1debfc3dSmrg[ -d $PATCHES ] || makedir $PATCHES
159*1debfc3dSmrg[ -d $STATE ] || makedir $STATE
160*1debfc3dSmrg[ -d $STATE/patched ] || makedir $STATE/patched
161*1debfc3dSmrg[ -d $SOURCE ] || makedir $SOURCE
162*1debfc3dSmrg[ -f $SOURCE/config.guess ] || {
163*1debfc3dSmrg    cd $SOURCE
164*1debfc3dSmrg    svn -q co $svnpath/trunk .
165*1debfc3dSmrg    if [ $? -ne 0 ]; then
166*1debfc3dSmrg	echo "ERROR: initial svn checkout failed"
167*1debfc3dSmrg	exit 1
168*1debfc3dSmrg    fi
169*1debfc3dSmrg}
170*1debfc3dSmrg
171*1debfc3dSmrg# This can contain required local settings:
172*1debfc3dSmrg#  default_config  configure options, always passed
173*1debfc3dSmrg#  default_make    make bootstrap options, always passed
174*1debfc3dSmrg#  default_check   make check options, always passed
175*1debfc3dSmrg[ -f $STATE/defaults ] && . $STATE/defaults
176*1debfc3dSmrg
177*1debfc3dSmrgVERSION=`svn info $SOURCE | grep "^Revision:" | sed -e "s/^Revision://g" -e "s/ //g"`
178*1debfc3dSmrg
179*1debfc3dSmrgexec >> $STATE/tester.log 2>&1 || exit 1
180*1debfc3dSmrgset -x
181*1debfc3dSmrg
182*1debfc3dSmrgTESTING=$STATE/testing
183*1debfc3dSmrgREPORT=$TESTING/report
184*1debfc3dSmrgPRISTINE=$TESTING/pristine
185*1debfc3dSmrgPATCHED=$TESTING/patched
186*1debfc3dSmrgPATCH=
187*1debfc3dSmrgTARGET=`$SOURCE/config.guess || exit 1`
188*1debfc3dSmrgTESTLOGS="gcc/testsuite/gcc/gcc.sum
189*1debfc3dSmrggcc/testsuite/gfortran/gfortran.sum
190*1debfc3dSmrggcc/testsuite/g++/g++.sum
191*1debfc3dSmrggcc/testsuite/objc/objc.sum
192*1debfc3dSmrg$TARGET/libstdc++-v3/testsuite/libstdc++.sum
193*1debfc3dSmrg$TARGET/libffi/testsuite/libffi.sum
194*1debfc3dSmrg$TARGET/libgomp/testsuite/libgomp.sum
195*1debfc3dSmrg$TARGET/libmudflap/testsuite/libmudflap.sum"
196*1debfc3dSmrgCOMPILERS="gcc/cc1
197*1debfc3dSmrggcc/cc1obj
198*1debfc3dSmrggcc/cc1plus
199*1debfc3dSmrggcc/f951
200*1debfc3dSmrggcc/jc1
201*1debfc3dSmrggcc/gnat1
202*1debfc3dSmrggcc/tree1"
203*1debfc3dSmrg
204*1debfc3dSmrgnow () {
205*1debfc3dSmrg    echo `TZ=UTC date +"%Y_%m_%d_%H_%M_%S"`
206*1debfc3dSmrg}
207*1debfc3dSmrg
208*1debfc3dSmrgreport () {
209*1debfc3dSmrg    echo "$@" >> $REPORT
210*1debfc3dSmrg}
211*1debfc3dSmrg
212*1debfc3dSmrgfreport () {
213*1debfc3dSmrg    if [ -s $1 ]; then
214*1debfc3dSmrg	report "(cat $1"
215*1debfc3dSmrg	cat $1 >> $REPORT
216*1debfc3dSmrg	report "tac)"
217*1debfc3dSmrg    fi
218*1debfc3dSmrg}
219*1debfc3dSmrg
220*1debfc3dSmrgcleanup () {
221*1debfc3dSmrg    cd $SOURCE
222*1debfc3dSmrg    svn cleanup && svn revert -R . && svn st | cut -d' ' -f5- | xargs rm -v
223*1debfc3dSmrg}
224*1debfc3dSmrg
225*1debfc3dSmrgselfexec () {
226*1debfc3dSmrg    exec ${CONFIG_SHELL-/bin/sh} $0 $args
227*1debfc3dSmrg}
228*1debfc3dSmrg
229*1debfc3dSmrgupdate () {
230*1debfc3dSmrg    svn_branch=`grep "^branch:" $PATCH | sed -e "s/^branch://g" -e "s/ //g"`
231*1debfc3dSmrg    if [ x$svn_branch = x ]; then
232*1debfc3dSmrg	svn_branch=trunk
233*1debfc3dSmrg    fi
234*1debfc3dSmrg
235*1debfc3dSmrg    svn_revision=`grep "^revision:" $PATCH | sed -e "s/^revision://g" -e "s/ //g"`
236*1debfc3dSmrg    if [ x$svn_revision = x ]; then
237*1debfc3dSmrg	svn_revision=HEAD
238*1debfc3dSmrg    fi
239*1debfc3dSmrg
240*1debfc3dSmrg    cleanup
241*1debfc3dSmrg    cd $SOURCE
242*1debfc3dSmrg    case $svn_branch in
243*1debfc3dSmrg	trunk)
244*1debfc3dSmrg	    if ! svn switch -r $svn_revision $svnpath/trunk &> $TESTING/svn ; then
245*1debfc3dSmrg		report "failed to update svn sources with"
246*1debfc3dSmrg		report "svn switch -r $svn_revision $svnpath/trunk"
247*1debfc3dSmrg		freport $TESTING/svn
248*1debfc3dSmrg		return 1
249*1debfc3dSmrg	    fi
250*1debfc3dSmrg	    ;;
251*1debfc3dSmrg
252*1debfc3dSmrg	${svnpath}*)
253*1debfc3dSmrg	    if ! svn switch -r $svn_revision $svn_branch &> $TESTING/svn ; then
254*1debfc3dSmrg		report "failed to update svn sources with"
255*1debfc3dSmrg		report "svn switch -r $svn_revision $svn_branch"
256*1debfc3dSmrg		freport $TESTING/svn
257*1debfc3dSmrg		return 1
258*1debfc3dSmrg	    fi
259*1debfc3dSmrg	    ;;
260*1debfc3dSmrg
261*1debfc3dSmrg	*)
262*1debfc3dSmrg	    if ! svn switch -r $svn_revision $svnpath/branches/$svn_branch &> $TESTING/svn ; then
263*1debfc3dSmrg		report "failed to update svn sources with"
264*1debfc3dSmrg		report "svn switch -r $svn_revision $svnpath/branches/$svn_branch"
265*1debfc3dSmrg		freport $TESTING/svn
266*1debfc3dSmrg		return 1
267*1debfc3dSmrg	    fi
268*1debfc3dSmrg	    ;;
269*1debfc3dSmrg    esac
270*1debfc3dSmrg    contrib/gcc_update --touch
271*1debfc3dSmrg
272*1debfc3dSmrg    current_version=`svn info $SOURCE | grep "^Revision:" | sed -e "s/^Revision://g" -e "s/ //g"`
273*1debfc3dSmrg    if [[ $VERSION < $current_version ]]; then
274*1debfc3dSmrg	if [ -f $SOURCE/contrib/patch_tester.sh ]; then
275*1debfc3dSmrg	    selfexec
276*1debfc3dSmrg	fi
277*1debfc3dSmrg    fi
278*1debfc3dSmrg
279*1debfc3dSmrg    return 0
280*1debfc3dSmrg}
281*1debfc3dSmrg
282*1debfc3dSmrgapply_patch () {
283*1debfc3dSmrg    if [ $nogpg = false ]; then
284*1debfc3dSmrg	if ! gpg --batch --verify $PATCH &> $TESTING/gpgverify ; then
285*1debfc3dSmrg	    report "your patch failed to verify:"
286*1debfc3dSmrg	    freport $TESTING/gpgverify
287*1debfc3dSmrg	    return 1
288*1debfc3dSmrg	fi
289*1debfc3dSmrg    fi
290*1debfc3dSmrg
291*1debfc3dSmrg    cd $SOURCE
292*1debfc3dSmrg    if ! patch -p0 < $PATCH &> $TESTING/patching ; then
293*1debfc3dSmrg	report "your patch failed to apply:"
294*1debfc3dSmrg	report "(check that the patch was created at the top level)"
295*1debfc3dSmrg	freport $TESTING/patching
296*1debfc3dSmrg	return 1
297*1debfc3dSmrg    fi
298*1debfc3dSmrg
299*1debfc3dSmrg    # Just assume indexes for now -- not really great, but svn always
300*1debfc3dSmrg    # makes them.
301*1debfc3dSmrg    grep "^Index: " $PATCH | sed -e 's/Index: //' | while read file; do
302*1debfc3dSmrg	# If the patch resulted in an empty file, delete it.
303*1debfc3dSmrg	# This is how svn reports deletions.
304*1debfc3dSmrg	if [ ! -s $file ]; then
305*1debfc3dSmrg	    rm -f $file
306*1debfc3dSmrg	    report "Deleting empty file $file"
307*1debfc3dSmrg	fi
308*1debfc3dSmrg    done
309*1debfc3dSmrg}
310*1debfc3dSmrg
311*1debfc3dSmrgsave_compilers () {
312*1debfc3dSmrg    for COMPILER in $COMPILERS ; do
313*1debfc3dSmrg	if [ -f $BUILD/$COMPILER ]; then
314*1debfc3dSmrg	    cp $BUILD/$COMPILER $PRISTINE
315*1debfc3dSmrg	fi
316*1debfc3dSmrg    done
317*1debfc3dSmrg}
318*1debfc3dSmrg
319*1debfc3dSmrgbootntest () {
320*1debfc3dSmrg    rm -rf $BUILD
321*1debfc3dSmrg    mkdir $BUILD
322*1debfc3dSmrg    cd $BUILD
323*1debfc3dSmrg
324*1debfc3dSmrg    CONFIG_OPTIONS=`grep "^configure:" $PATCH | sed -e "s/^configure://g"`
325*1debfc3dSmrg    CONFIG_OPTIONS="$default_config $CONFIG_OPTIONS"
326*1debfc3dSmrg    if ! eval $SOURCE/configure $CONFIG_OPTIONS &> $1/configure ; then
327*1debfc3dSmrg	report "configure with `basename $1` version failed with:"
328*1debfc3dSmrg	freport $1/configure
329*1debfc3dSmrg	return 1
330*1debfc3dSmrg    fi
331*1debfc3dSmrg
332*1debfc3dSmrg    MAKE_ARGS=`grep "^make:" $PATCH | sed -e "s/^make://g"`
333*1debfc3dSmrg    MAKE_ARGS="$default_make $MAKE_ARGS"
334*1debfc3dSmrg    if ! eval make $dashj $MAKE_ARGS &> $1/bootstrap ; then
335*1debfc3dSmrg	report "bootstrap with `basename $1` version failed with last lines:"
336*1debfc3dSmrg	tail -30 $1/bootstrap > $1/last_bootstrap
337*1debfc3dSmrg	freport $1/last_bootstrap
338*1debfc3dSmrg	report "grep --context=20 Error bootstrap:"
339*1debfc3dSmrg	grep --context=20 Error $1/bootstrap > $1/bootstrap_error
340*1debfc3dSmrg	freport $1/bootstrap_error
341*1debfc3dSmrg	return 1
342*1debfc3dSmrg    fi
343*1debfc3dSmrg
344*1debfc3dSmrg    CHECK_OPTIONS=`grep "^check:" $PATCH | sed -e "s/^check://g"`
345*1debfc3dSmrg    CHECK_OPTIONS="$default_check $CHECK_OPTIONS"
346*1debfc3dSmrg    eval make $dashj $CHECK_OPTIONS -k check &> $1/check
347*1debfc3dSmrg
348*1debfc3dSmrg    SUITESRUN="`grep 'Summary ===' $1/check | cut -d' ' -f 2 | sort`"
349*1debfc3dSmrg    if [ x$SUITESRUN = x ]; then
350*1debfc3dSmrg	report "check with `basename $1` version failed, no testsuites were run"
351*1debfc3dSmrg	return 1
352*1debfc3dSmrg    fi
353*1debfc3dSmrg
354*1debfc3dSmrg    for LOG in $TESTLOGS ; do
355*1debfc3dSmrg	if [ -f $BUILD/$LOG ]; then
356*1debfc3dSmrg	    mv $BUILD/$LOG $1
357*1debfc3dSmrg	    mv `echo "$BUILD/$LOG" | sed -e "s/\.sum/\.log/g"` $1
358*1debfc3dSmrg	fi
359*1debfc3dSmrg    done
360*1debfc3dSmrg
361*1debfc3dSmrg    return 0
362*1debfc3dSmrg}
363*1debfc3dSmrg
364*1debfc3dSmrgbootntest_patched () {
365*1debfc3dSmrg    cleanup
366*1debfc3dSmrg    mkdir -p $PATCHED
367*1debfc3dSmrg    apply_patch && bootntest $PATCHED
368*1debfc3dSmrg    return $?
369*1debfc3dSmrg}
370*1debfc3dSmrg
371*1debfc3dSmrg# Build the pristine tree with exactly the same options as the patch under test.
372*1debfc3dSmrgbootntest_pristine () {
373*1debfc3dSmrg    cleanup
374*1debfc3dSmrg    current_branch=`svn info $SOURCE | grep "^URL:" | sed -e "s/URL: //g" -e "s,${svnpath},,g"`
375*1debfc3dSmrg    current_version=`svn info $SOURCE | grep "^Revision:" | sed -e "s/^Revision://g" -e "s/ //g"`
376*1debfc3dSmrg    PRISTINE=$STATE/$current_branch/$current_version
377*1debfc3dSmrg
378*1debfc3dSmrg    if [ $nopristinecache = true ]; then
379*1debfc3dSmrg      rm -rf $PRISTINE
380*1debfc3dSmrg    fi
381*1debfc3dSmrg    if [ -d $PRISTINE ]; then
382*1debfc3dSmrg	ln -s $PRISTINE $TESTING/pristine
383*1debfc3dSmrg	return 0
384*1debfc3dSmrg    else
385*1debfc3dSmrg	mkdir -p $PRISTINE
386*1debfc3dSmrg	ln -s $PRISTINE $TESTING/pristine
387*1debfc3dSmrg	bootntest $PRISTINE
388*1debfc3dSmrg	RETVAL=$?
389*1debfc3dSmrg	if [ $RETVAL = 0 -a $savecompilers = true ]; then
390*1debfc3dSmrg	    save_compilers
391*1debfc3dSmrg	fi
392*1debfc3dSmrg	return $RETVAL
393*1debfc3dSmrg    fi
394*1debfc3dSmrg}
395*1debfc3dSmrg
396*1debfc3dSmrgregtest () {
397*1debfc3dSmrg    touch $1/report
398*1debfc3dSmrg    touch $1/passes
399*1debfc3dSmrg    touch $1/failed
400*1debfc3dSmrg    touch $1/regress
401*1debfc3dSmrg
402*1debfc3dSmrg    for LOG in $TESTLOGS ; do
403*1debfc3dSmrg	NLOG=`basename $LOG`
404*1debfc3dSmrg	if [ -f $1/$NLOG ]; then
405*1debfc3dSmrg	    awk '/^FAIL: / { print "'$NLOG'",$2; }' $1/$NLOG
406*1debfc3dSmrg	fi
407*1debfc3dSmrg    done | sort | uniq > $1/failed
408*1debfc3dSmrg
409*1debfc3dSmrg    comm -12 $1/failed $1/passes >> $1/regress
410*1debfc3dSmrg    NUMREGRESS=`wc -l < $1/regress | tr -d ' '`
411*1debfc3dSmrg
412*1debfc3dSmrg    if [ $NUMREGRESS -eq 0 ] ; then
413*1debfc3dSmrg	for LOG in $TESTLOGS ; do
414*1debfc3dSmrg	    NLOG=`basename $LOG`
415*1debfc3dSmrg	    if [ -f $1/$NLOG ] ; then
416*1debfc3dSmrg		awk '/^PASS: / { print "'$NLOG'",$2; }' $1/$NLOG
417*1debfc3dSmrg	    fi
418*1debfc3dSmrg	done | sort | uniq | comm -23 - $1/failed > $1/passes
419*1debfc3dSmrg	echo "there are no regressions with your patch." >> $1/report
420*1debfc3dSmrg    else
421*1debfc3dSmrg	echo "with your patch there are $NUMREGRESS regressions." >> $1/report
422*1debfc3dSmrg	echo "list of regressions with your patch:" >> $1/report
423*1debfc3dSmrg	cat $1/regress >> $1/report
424*1debfc3dSmrg    fi
425*1debfc3dSmrg}
426*1debfc3dSmrg
427*1debfc3dSmrgcontrib_compare_tests () {
428*1debfc3dSmrg    report "comparing logs with contrib/compare_tests:"
429*1debfc3dSmrg    for LOG in $TESTLOGS ; do
430*1debfc3dSmrg 	NLOG=`basename $LOG`
431*1debfc3dSmrg 	if [ -f $PRISTINE/$NLOG -a -f $PATCHED/$NLOG ]; then
432*1debfc3dSmrg 	    $SOURCE/contrib/compare_tests $PRISTINE/$NLOG $PATCHED/$NLOG > $TESTING/compare_$NLOG
433*1debfc3dSmrg 	    freport $TESTING/compare_$NLOG
434*1debfc3dSmrg 	fi
435*1debfc3dSmrg    done
436*1debfc3dSmrg}
437*1debfc3dSmrg
438*1debfc3dSmrgcompare_passes () {
439*1debfc3dSmrg    regtest $PRISTINE
440*1debfc3dSmrg    cp $PRISTINE/passes $PATCHED
441*1debfc3dSmrg    regtest $PATCHED
442*1debfc3dSmrg    freport $PATCHED/report
443*1debfc3dSmrg    report "FAILs with patched version:"
444*1debfc3dSmrg    freport $PATCHED/failed
445*1debfc3dSmrg    report "FAILs with pristine version:"
446*1debfc3dSmrg    freport $PRISTINE/failed
447*1debfc3dSmrg
448*1debfc3dSmrg    # contrib_compare_tests
449*1debfc3dSmrg}
450*1debfc3dSmrg
451*1debfc3dSmrgwrite_report () {
452*1debfc3dSmrg    backup_patched=$STATE/patched/`now`
453*1debfc3dSmrg    report "The files used for the validation of your patch are stored in $backup_patched on the tester machine."
454*1debfc3dSmrg
455*1debfc3dSmrg    EMAIL=`grep "^email:" $PATCH | sed -e "s/^email://g" -e "s/ //g"`
456*1debfc3dSmrg    if [ x$EMAIL != x ]; then
457*1debfc3dSmrg	mutt -s "[regtest] Results for `basename $PATCH` on $TARGET" -i $REPORT -a $PATCH $EMAIL
458*1debfc3dSmrg    fi
459*1debfc3dSmrg
460*1debfc3dSmrg    mv $TESTING $backup_patched
461*1debfc3dSmrg}
462*1debfc3dSmrg
463*1debfc3dSmrgannounce () {
464*1debfc3dSmrg    EMAIL=`grep "^email:" $PATCH | sed -e "s/^email://g" -e "s/ //g"`
465*1debfc3dSmrg    if [ x$EMAIL != x ]; then
466*1debfc3dSmrg
467*1debfc3dSmrg	START_REPORT=$TESTING/start_report
468*1debfc3dSmrg	echo "Hi, " >> $START_REPORT
469*1debfc3dSmrg	echo "I'm the automatic tester running on $TARGET." >> $START_REPORT
470*1debfc3dSmrg	echo "I just started to look at your patch `basename $PATCH`." >> $START_REPORT
471*1debfc3dSmrg	echo "Bye, your automatic tester." >> $START_REPORT
472*1debfc3dSmrg	mutt -s "[regtest] Starting bootstrap for `basename $PATCH` on $TARGET" -i $START_REPORT $EMAIL
473*1debfc3dSmrg    fi
474*1debfc3dSmrg}
475*1debfc3dSmrg
476*1debfc3dSmrg# After selfexec, $TESTING is already set up.
477*1debfc3dSmrgif [ -d $TESTING ]; then
478*1debfc3dSmrg    # The only file in $TESTING is the patch.
479*1debfc3dSmrg    PATCH=`ls -rt -1 $TESTING | head -1`
480*1debfc3dSmrg    PATCH=$TESTING/$PATCH
481*1debfc3dSmrg    if [ -f $PATCH ]; then
482*1debfc3dSmrg	bootntest_patched && bootntest_pristine && compare_passes
483*1debfc3dSmrg	write_report
484*1debfc3dSmrg    fi
485*1debfc3dSmrgfi
486*1debfc3dSmrg
487*1debfc3dSmrgfirstpatch=true
488*1debfc3dSmrgwhile true; do
489*1debfc3dSmrg    PATCH=`ls -rt -1 $PATCHES | head -1`
490*1debfc3dSmrg    if [ x$PATCH = x ]; then
491*1debfc3dSmrg	if [ $stop = true ]; then
492*1debfc3dSmrg	    if [ $firstpatch = true ]; then
493*1debfc3dSmrg		echo "No patches ready to test, quitting."
494*1debfc3dSmrg		exit 1
495*1debfc3dSmrg	    else
496*1debfc3dSmrg		echo "No more patches to test."
497*1debfc3dSmrg		exit 0
498*1debfc3dSmrg	    fi
499*1debfc3dSmrg	fi
500*1debfc3dSmrg	sleep ${standby}m
501*1debfc3dSmrg    else
502*1debfc3dSmrg	firstpatch=false
503*1debfc3dSmrg	sysload=`uptime | cut -d, -f 5`
504*1debfc3dSmrg	if [[ $sysload > $watermark ]]; then
505*1debfc3dSmrg	    # Wait a bit when system load is too high.
506*1debfc3dSmrg	    sleep ${standby}m
507*1debfc3dSmrg	else
508*1debfc3dSmrg	    mkdir -p $TESTING
509*1debfc3dSmrg	    mv $PATCHES/$PATCH $TESTING/
510*1debfc3dSmrg	    PATCH=$TESTING/$PATCH
511*1debfc3dSmrg
512*1debfc3dSmrg	    announce
513*1debfc3dSmrg	    update && bootntest_patched && bootntest_pristine && compare_passes
514*1debfc3dSmrg	    write_report
515*1debfc3dSmrg	fi
516*1debfc3dSmrg    fi
517*1debfc3dSmrgdone
518