3 # Tests a set of patches from a directory.
4 # Copyright (C) 2007, 2008, 2011 Free Software Foundation, Inc.
5 # Contributed by Sebastian Pop <sebastian.pop@amd.com>
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 WARNING: This script should only be fed with patches from known
24 authorized and trusted sources. Don't even think about
25 hooking it up to a raw feed from the gcc-patches list or
32 svnpath
=svn
://gcc.gnu.org
/svn
/gcc
35 standby
=$default_standby
36 default_watermark
=0.60
37 watermark
=$default_watermark
45 patch_tester.sh [-j<N>] [-standby N] [-watermark N] [-savecompilers] [-nogpg]
46 [-svnpath URL] [-stop] [-nopristinecache]
47 <source_dir> [patches_dir [state_dir [build_dir]]]
49 J is the flag passed to make. Default is empty string.
51 STANDBY is the number of minutes between checks for new patches in
52 PATCHES_DIR. Default is ${default_standby} minutes.
54 WATERMARK is the 5 minute average system charge under which a new
55 compile can start. Default is ${default_watermark}.
57 SAVECOMPILERS copies the compilers in the same directory as the
58 test results for the non patched version. Default is not copy.
60 NOPRISTINECACHE prevents use of cached test results from any earlier
61 test runs on the pristine version of the branch and revision under
62 test (the default behaviour). This should be used when testing the
63 same revision and patch with multiple sets of configure options, as
64 these may affect the set of baseline failures.
66 NOGPG can be used to avoid checking the GPG signature of patches.
68 URL is the location of the GCC SVN repository. The default is
71 STOP exits when PATCHES_DIR is empty.
73 SOURCE_DIR is the directory containing GCC's toplevel configure.
75 PATCHES_DIR is the directory containing the patches to be tested.
76 Default is SOURCE_DIR/patches.
78 STATE_DIR is where the tester maintains its internal state.
79 Default is SOURCE_DIR/state.
81 BUILD_DIR is the build tree, a temporary directory that this
82 script will delete and recreate. Default is SOURCE_DIR/obj.
92 echo "ERROR: could not make directory $DIRNAME"
97 while [ $# -ne 0 ]; do
103 [[ $# > 2 ]] || usage
104 standby
=$2; shift; shift
107 [[ $# > 2 ]] || usage
108 watermark
=$2; shift; shift
111 savecompilers
=true
; shift
114 nopristinecache
=true
; shift
123 svnpath
=$2; shift; shift
126 echo "Invalid option: $1"
135 test $# -eq 0 && usage
142 if [[ $# < 2 ]]; then
143 PATCHES
=$SOURCE/patches
147 if [[ $# < 3 ]]; then
152 if [[ $# < 4 ]]; then
158 [ -d $PATCHES ] || makedir
$PATCHES
159 [ -d $STATE ] || makedir
$STATE
160 [ -d $STATE/patched
] || makedir
$STATE/patched
161 [ -d $SOURCE ] || makedir
$SOURCE
162 [ -f $SOURCE/config.guess
] ||
{
164 svn
-q co
$svnpath/trunk .
165 if [ $?
-ne 0 ]; then
166 echo "ERROR: initial svn checkout failed"
171 # This can contain required local settings:
172 # default_config configure options, always passed
173 # default_make make bootstrap options, always passed
174 # default_check make check options, always passed
175 [ -f $STATE/defaults
] && .
$STATE/defaults
177 VERSION
=`svn info $SOURCE | grep "^Revision:" | sed -e "s/^Revision://g" -e "s/ //g"`
179 exec >> $STATE/tester.log
2>&1 ||
exit 1
182 TESTING
=$STATE/testing
183 REPORT
=$TESTING/report
184 PRISTINE
=$TESTING/pristine
185 PATCHED
=$TESTING/patched
187 TARGET
=`$SOURCE/config.guess || exit 1`
188 TESTLOGS
="gcc/testsuite/gcc/gcc.sum
189 gcc/testsuite/gfortran/gfortran.sum
190 gcc/testsuite/g++/g++.sum
191 gcc/testsuite/objc/objc.sum
192 $TARGET/libstdc++-v3/testsuite/libstdc++.sum
193 $TARGET/libffi/testsuite/libffi.sum
194 $TARGET/libjava/testsuite/libjava.sum
195 $TARGET/libgomp/testsuite/libgomp.sum
196 $TARGET/libmudflap/testsuite/libmudflap.sum"
206 echo `TZ=UTC date +"%Y_%m_%d_%H_%M_%S"`
223 svn cleanup
&& svn revert
-R .
&& svn st | cut
-d' ' -f5- |
xargs rm -v
227 exec ${CONFIG_SHELL-/bin/sh} $0 $args
231 svn_branch
=`grep "^branch:" $PATCH | sed -e "s/^branch://g" -e "s/ //g"`
232 if [ x
$svn_branch = x
]; then
236 svn_revision
=`grep "^revision:" $PATCH | sed -e "s/^revision://g" -e "s/ //g"`
237 if [ x
$svn_revision = x
]; then
245 if ! svn switch
-r $svn_revision $svnpath/trunk
&> $TESTING/svn
; then
246 report
"failed to update svn sources with"
247 report
"svn switch -r $svn_revision $svnpath/trunk"
254 if ! svn switch
-r $svn_revision $svn_branch &> $TESTING/svn
; then
255 report
"failed to update svn sources with"
256 report
"svn switch -r $svn_revision $svn_branch"
263 if ! svn switch
-r $svn_revision $svnpath/branches
/$svn_branch &> $TESTING/svn
; then
264 report
"failed to update svn sources with"
265 report
"svn switch -r $svn_revision $svnpath/branches/$svn_branch"
271 contrib
/gcc_update
--touch
273 current_version
=`svn info $SOURCE | grep "^Revision:" | sed -e "s/^Revision://g" -e "s/ //g"`
274 if [[ $VERSION < $current_version ]]; then
275 if [ -f $SOURCE/contrib
/patch_tester.sh
]; then
284 if [ $nogpg = false
]; then
285 if ! gpg
--batch --verify $PATCH &> $TESTING/gpgverify
; then
286 report
"your patch failed to verify:"
287 freport
$TESTING/gpgverify
293 if ! patch -p0 < $PATCH &> $TESTING/patching
; then
294 report
"your patch failed to apply:"
295 report
"(check that the patch was created at the top level)"
296 freport
$TESTING/patching
300 # Just assume indexes for now -- not really great, but svn always
302 grep "^Index: " $PATCH |
sed -e 's/Index: //' |
while read file; do
303 # If the patch resulted in an empty file, delete it.
304 # This is how svn reports deletions.
305 if [ ! -s $file ]; then
307 report
"Deleting empty file $file"
313 for COMPILER
in $COMPILERS ; do
314 if [ -f $BUILD/$COMPILER ]; then
315 cp $BUILD/$COMPILER $PRISTINE
325 CONFIG_OPTIONS
=`grep "^configure:" $PATCH | sed -e "s/^configure://g"`
326 CONFIG_OPTIONS
="$default_config $CONFIG_OPTIONS"
327 if ! eval $SOURCE/configure
$CONFIG_OPTIONS &> $1/configure
; then
328 report
"configure with `basename $1` version failed with:"
333 MAKE_ARGS
=`grep "^make:" $PATCH | sed -e "s/^make://g"`
334 MAKE_ARGS
="$default_make $MAKE_ARGS"
335 if ! eval make $dashj $MAKE_ARGS &> $1/bootstrap
; then
336 report
"bootstrap with `basename $1` version failed with last lines:"
337 tail -30 $1/bootstrap
> $1/last_bootstrap
338 freport
$1/last_bootstrap
339 report
"grep --context=20 Error bootstrap:"
340 grep --context=20 Error
$1/bootstrap
> $1/bootstrap_error
341 freport
$1/bootstrap_error
345 CHECK_OPTIONS
=`grep "^check:" $PATCH | sed -e "s/^check://g"`
346 CHECK_OPTIONS
="$default_check $CHECK_OPTIONS"
347 eval make $dashj $CHECK_OPTIONS -k check
&> $1/check
349 SUITESRUN
="`grep 'Summary ===' $1/check | cut -d' ' -f 2 | sort`"
350 if [ x
$SUITESRUN = x
]; then
351 report
"check with `basename $1` version failed, no testsuites were run"
355 for LOG
in $TESTLOGS ; do
356 if [ -f $BUILD/$LOG ]; then
358 mv `echo "$BUILD/$LOG" | sed -e "s/\.sum/\.log/g"` $1
365 bootntest_patched
() {
368 apply_patch
&& bootntest
$PATCHED
372 # Build the pristine tree with exactly the same options as the patch under test.
373 bootntest_pristine
() {
375 current_branch
=`svn info $SOURCE | grep "^URL:" | sed -e "s/URL: //g" -e "s,${svnpath},,g"`
376 current_version
=`svn info $SOURCE | grep "^Revision:" | sed -e "s/^Revision://g" -e "s/ //g"`
377 PRISTINE
=$STATE/$current_branch/$current_version
379 if [ $nopristinecache = true
]; then
382 if [ -d $PRISTINE ]; then
383 ln -s $PRISTINE $TESTING/pristine
387 ln -s $PRISTINE $TESTING/pristine
390 if [ $RETVAL = 0 -a $savecompilers = true
]; then
403 for LOG
in $TESTLOGS ; do
405 if [ -f $1/$NLOG ]; then
406 awk '/^FAIL: / { print "'$NLOG'",$2; }' $1/$NLOG
408 done |
sort |
uniq > $1/failed
410 comm -12 $1/failed
$1/passes
>> $1/regress
411 NUMREGRESS
=`wc -l < $1/regress | tr -d ' '`
413 if [ $NUMREGRESS -eq 0 ] ; then
414 for LOG
in $TESTLOGS ; do
416 if [ -f $1/$NLOG ] ; then
417 awk '/^PASS: / { print "'$NLOG'",$2; }' $1/$NLOG
419 done |
sort |
uniq |
comm -23 - $1/failed
> $1/passes
420 echo "there are no regressions with your patch." >> $1/report
422 echo "with your patch there are $NUMREGRESS regressions." >> $1/report
423 echo "list of regressions with your patch:" >> $1/report
424 cat $1/regress
>> $1/report
428 contrib_compare_tests
() {
429 report
"comparing logs with contrib/compare_tests:"
430 for LOG
in $TESTLOGS ; do
432 if [ -f $PRISTINE/$NLOG -a -f $PATCHED/$NLOG ]; then
433 $SOURCE/contrib
/compare_tests
$PRISTINE/$NLOG $PATCHED/$NLOG > $TESTING/compare_
$NLOG
434 freport
$TESTING/compare_
$NLOG
441 cp $PRISTINE/passes
$PATCHED
443 freport
$PATCHED/report
444 report
"FAILs with patched version:"
445 freport
$PATCHED/failed
446 report
"FAILs with pristine version:"
447 freport
$PRISTINE/failed
449 # contrib_compare_tests
453 backup_patched
=$STATE/patched
/`now`
454 report
"The files used for the validation of your patch are stored in $backup_patched on the tester machine."
456 EMAIL
=`grep "^email:" $PATCH | sed -e "s/^email://g" -e "s/ //g"`
457 if [ x
$EMAIL != x
]; then
458 mutt
-s "[regtest] Results for `basename $PATCH` on $TARGET" -i $REPORT -a $PATCH $EMAIL
461 mv $TESTING $backup_patched
465 EMAIL
=`grep "^email:" $PATCH | sed -e "s/^email://g" -e "s/ //g"`
466 if [ x
$EMAIL != x
]; then
468 START_REPORT
=$TESTING/start_report
469 echo "Hi, " >> $START_REPORT
470 echo "I'm the automatic tester running on $TARGET." >> $START_REPORT
471 echo "I just started to look at your patch `basename $PATCH`." >> $START_REPORT
472 echo "Bye, your automatic tester." >> $START_REPORT
473 mutt
-s "[regtest] Starting bootstrap for `basename $PATCH` on $TARGET" -i $START_REPORT $EMAIL
477 # After selfexec, $TESTING is already set up.
478 if [ -d $TESTING ]; then
479 # The only file in $TESTING is the patch.
480 PATCH
=`ls -rt -1 $TESTING | head -1`
481 PATCH
=$TESTING/$PATCH
482 if [ -f $PATCH ]; then
483 bootntest_patched
&& bootntest_pristine
&& compare_passes
490 PATCH
=`ls -rt -1 $PATCHES | head -1`
491 if [ x
$PATCH = x
]; then
492 if [ $stop = true
]; then
493 if [ $firstpatch = true
]; then
494 echo "No patches ready to test, quitting."
497 echo "No more patches to test."
504 sysload
=`uptime | cut -d, -f 5`
505 if [[ $sysload > $watermark ]]; then
506 # Wait a bit when system load is too high.
510 mv $PATCHES/$PATCH $TESTING/
511 PATCH
=$TESTING/$PATCH
514 update
&& bootntest_patched
&& bootntest_pristine
&& compare_passes