Home | History | Annotate | Download | only in bin
      1 #!/bin/sh
      2 
      3 #----------------------------------------------------------------------------
      4 # Automated build and test for Valgrind.  Compares Valgrind from 24 hours
      5 # ago with the current one.  See the README.txt on how to run it.
      6 #----------------------------------------------------------------------------
      7 
      8 #----------------------------------------------------------------------------
      9 # Helper functions
     10 #----------------------------------------------------------------------------
     11 
     12 # Returns the revision number for the source files at date $1 in Subversion
     13 # repo $2. Note: the "--depth" command line argument is supported from
     14 # Subversion version 1.5 on.
     15 get_svn_revision() {
     16   (
     17     cd $DIR
     18     rm -rf infodir
     19     if ! svn co -r "{$1}" --depth empty "$2" infodir > /dev/null 2>&1; then
     20       # Subversion 1.4 or before.
     21       rm -rf infodir
     22       svn co -r "{$1}" --non-recursive "$2" infodir > /dev/null
     23     fi
     24     svn info infodir | sed -n 's/^Revision: //p'
     25     rm -rf infodir
     26   )
     27 }
     28 
     29 runcmd () {
     30    logfile=$1
     31    str=$2
     32    shift 2
     33 
     34    # Header in short logfile.
     35    # We use "printf" to avoid printing a newline;  "echo -n" isn't POSIX and
     36    # so isn't supported on all systems.
     37    printf "   $str  ... " >> $logfile.short
     38 
     39    # Header and command in verbose logfile
     40    printf "   $str  ... " >> $logfile.verbose
     41    echo "$*" >> $logfile.verbose
     42 
     43    # Run the command
     44    ("${ABT_EVAL}" "$*") >> $logfile.verbose 2>&1
     45    res=$?
     46 
     47    # Write result to the short logfile
     48    if [ $res = 0 ]
     49    then
     50       echo "done"   >> $logfile.short
     51    else
     52       echo "failed" >> $logfile.short
     53    fi
     54 
     55    return $res
     56 }
     57 
     58 #----------------------------------------------------------------------------
     59 # Startup
     60 #----------------------------------------------------------------------------
     61 
     62 valgrind_svn_repo="svn://svn.valgrind.org/valgrind/trunk"
     63 vex_svn_repo="svn://svn.valgrind.org/vex/trunk"
     64 
     65 # Must have exactly two arguments
     66 if [ $# -ne 2 ] ; then
     67     echo "usage: $0 /path/to/valgrind/nightly <tag>"
     68     exit 1
     69 fi
     70 
     71 # Get args from command line
     72 DIR=$1
     73 TAG=$2
     74 
     75 # Get times and date
     76 START=`date "+%F %H:%M:%S %Z"`
     77 
     78 # This is one of the formats SVN accepts.  Yes, the 'T' appears in the final
     79 # string, it's supposed to be like that.
     80 svn_date_format="+%Y-%m-%dT%H:%M:%S"
     81 
     82 # The time-and-date from 24 hours ago is tricky;  Linux and Darwin have
     83 # different ways of getting it, so we try things until something works.
     84 svn_old_date=
     85 if [ "z" = "z${svn_old_date}" ] ; then
     86     # Linux method.
     87     svn_old_date=`date --date=yesterday $svn_date_format 2> /dev/null`
     88 fi
     89 if [ "z" = "z${svn_old_date}" ] ; then
     90     # Darwin method.
     91     svn_old_date=`date -v-24H $svn_date_format 2> /dev/null`
     92 fi
     93 if [ "z" = "z${svn_old_date}" ] ; then
     94     echo "Sorry, can't work out the time and date for 24 hours ago, aborting"
     95     exit 1;
     96 fi
     97 
     98 # The time-and-date for now is easy.
     99 svn_new_date=`date $svn_date_format`
    100 
    101 cd $DIR
    102 
    103 # Clean up output files produced by a previous run.
    104 rm -rf diffs diffs.txt diff.short final new.short new.verbose old.short old.verbose
    105 rm -rf sendmail.log unchanged.log valgrind-old valgrind-new
    106 
    107 # Setup any relevant environment variables from conf/<tag>.conf.
    108 . conf/$TAG.conf
    109 if [ "${ABT_JOBS}" = "" ]; then
    110   ABT_JOBS=1
    111 fi
    112 if [ "${ABT_EVAL}" = "" ]; then
    113   ABT_EVAL="eval"
    114 fi
    115 if [ "${ABT_RUN_REGTEST}" = "" ]; then
    116   ABT_RUN_REGTEST="make regtest"
    117 fi
    118 
    119 if [ "${ABT_PERF_TOOLS}" = "" ]; then
    120   ABT_PERF_TOOLS="--tools=none,memcheck,callgrind,helgrind,cachegrind,drd,massif"
    121 fi
    122 if [ "${ABT_PERF_REPS}" = "" ]; then
    123   ABT_PERF_REPS="--reps=3"
    124 fi
    125 
    126 
    127 #----------------------------------------------------------------------------
    128 # Check out, build, test
    129 #----------------------------------------------------------------------------
    130 
    131 vg_old_rev="`get_svn_revision ${svn_old_date} ${valgrind_svn_repo}`"
    132 vg_new_rev="`get_svn_revision ${svn_new_date} ${valgrind_svn_repo}`"
    133 vex_old_rev="`get_svn_revision ${svn_old_date} ${vex_svn_repo}`"
    134 vex_new_rev="`get_svn_revision ${svn_new_date} ${vex_svn_repo}`"
    135 if [ "${vg_old_rev}" = "${vg_new_rev}" -a "${vex_old_rev}" = "${vex_new_rev}" ]
    136 then
    137   echo "Both {$svn_old_date} and {$svn_new_date} correspond to Valgrind r${vg_new_rev} / VEX r${vex_new_rev}"\
    138        "-- skipping nightly build." >unchanged.log
    139   exit 0
    140 fi
    141 
    142 # Do everything twice -- once for the 24 hours old Valgrind, and once 
    143 # for the current one.
    144 for logfile in old new ; do
    145 
    146    # Remove old short and verbose log files, and start the new ones
    147    for ext in short verbose ; do
    148       echo > $logfile.$ext
    149    done
    150 
    151    # Choose the current Valgrind, or one from 24 hours ago
    152    if [ $logfile = "old" ] ; then
    153       svn_date=$svn_old_date
    154    else
    155       svn_date=$svn_new_date
    156    fi
    157 
    158    # Get dates for the old and new versions
    159 
    160    # Check out, build, run tests
    161    runcmd $logfile \
    162           "Checking out valgrind source tree" \
    163           "svn co ${valgrind_svn_repo} -r {$svn_date} valgrind-$logfile\
    164            && svn update -r {$svn_date} valgrind-$logfile/VEX" && \
    165    \
    166    runcmd $logfile \
    167           "Configuring valgrind             " \
    168           "cd valgrind-$logfile && ./autogen.sh  && ./configure --prefix=`pwd`/valgrind-$logfile/Inst ${ABT_CONFIGURE_OPTIONS}" && \
    169    \
    170    runcmd $logfile \
    171           "Building valgrind                " \
    172           "cd valgrind-$logfile && make -j ${ABT_JOBS} && make -j ${ABT_JOBS} check && make install" && \
    173    \
    174    runcmd $logfile \
    175           "Running regression tests         " \
    176           "cd valgrind-$logfile && ${ABT_RUN_REGTEST}"
    177 
    178    # Stash away the return code of the regression run
    179    regrun_rc=$?
    180 
    181    # Grab some indicative text for the short log file -- if the regtests
    182    # succeeded, show their results.  If we didn't make it that far, show the
    183    # last 20 lines.
    184    egrep -q '^== [0-9]+ tests' $logfile.verbose && (
    185       echo >> $logfile.short
    186       echo "Regression test results follow" >> $logfile.short
    187       echo >> $logfile.short
    188       awk '/^== [0-9]+ tests/, /^$/ { print }' $logfile.verbose >> $logfile.short
    189    # Check the return code of the regression run; we might have successfully
    190    # run all tests but still failed in the post-regtest checks.
    191       if [ $regrun_rc != "0" ]; then
    192          echo >> $logfile.short
    193          echo "Last 20 lines of verbose log follow" >> $logfile.short \
    194          echo >> $logfile.short
    195          tail -20 $logfile.verbose >> $logfile.short
    196       fi
    197    ) || (
    198       echo >> $logfile.short
    199       echo "Last 20 lines of verbose log follow" >> $logfile.short \
    200       echo >> $logfile.short
    201       tail -20 $logfile.verbose >> $logfile.short
    202    )
    203 done
    204 
    205 # if requested, run regression tests and produce results in perflogfile.out
    206 if [ "${ABT_PERF}" != "" ]; then
    207    cd valgrind-new
    208    echo ${ABT_PERF_TOOLS} ${ABT_PERF_REPS} ${ABT_PERF} > ../perflogfile
    209    (time perl perf/vg_perf ${ABT_PERF_TOOLS} ${ABT_PERF_REPS} ${ABT_PERF} perf) >> ../perflogfile 2>&1
    210    cd ..
    211 fi
    212 
    213 
    214 #----------------------------------------------------------------------------
    215 # Prepare results and send
    216 #----------------------------------------------------------------------------
    217 
    218 # Get times and date
    219 END=`date "+%F %H:%M:%S %Z"`
    220 
    221 # Gather some information about this run and its environment
    222 valgrind_revision="`svn info valgrind-new | grep Revision | sed 's/Revision[ ]*:[ ]*//'`"
    223 vex_revision="`svn info valgrind-new/VEX | grep Revision | sed 's/Revision[ ]*:[ ]*//'`"
    224 gcc_version="`gcc --version 2> /dev/null | head -1`"
    225 gdb_version="`gdb --version 2> /dev/null | head -1`"
    226 as_version="`as --version 2> /dev/null | head -1`"
    227 libc_so="`ls -1 /lib/libc.so.* /lib64/libc.so.* /lib32/libc.so.* /lib/*-linux-gnu/libc.so.* 2>/dev/null | tail -1`"
    228 libc="unknown"
    229 if [ "x$libc_so" != "x" ]; then
    230   if [ -e "$libc_so" -a -r "$libc_so" ]; then
    231     libc="`$libc_so | head -1`"
    232   fi
    233 fi
    234 libc=`echo $libc | sed "s/, by Roland.*//"`
    235 uname_stuff="`uname -mrs`"
    236 if [ -r /etc/os-release ]; then
    237   vendor_stuff="`. /etc/os-release; echo ${NAME} ${VERSION}`"
    238 elif which lsb_release 2>&1 > /dev/null; then
    239   vendor_stuff="`lsb_release -sicr | xargs echo`"
    240 elif [ -e "/etc/issue.net" -a -r "/etc/issue.net" ]; then
    241   vendor_stuff="`cat /etc/issue.net | head -1`"
    242 else
    243   vendor_stuff="unknown"
    244 fi
    245 
    246 echo "valgrind revision: $valgrind_revision" >  final
    247 echo "VEX revision:      $vex_revision"      >> final
    248 echo "C compiler:        $gcc_version"       >> final
    249 echo "GDB:               $gdb_version"       >> final
    250 echo "Assembler:         $as_version"        >> final
    251 echo "C library:         $libc"              >> final
    252 echo "uname -mrs:        $uname_stuff"       >> final
    253 echo "Vendor version:    $vendor_stuff"      >> final
    254 
    255 # 'final' shows the difference between the old and new results
    256 echo                                              >> final
    257 echo "Nightly build on" $TAG "(" $ABT_DETAILS ")" >> final
    258 echo "Started at" $START                          >> final
    259 echo "Ended   at" $END                            >> final
    260 
    261 # If the results differ from 24 hours ago, print extra stuff.
    262 diff -C1 old.short new.short > diff.short
    263 changed=$?
    264 
    265 if [ $changed != 0 ] ; then
    266    echo "Results differ from 24 hours ago"      >> final
    267    changed_str=""
    268 else
    269    echo "Results unchanged from 24 hours ago"   >> final
    270    changed_str="(unchanged) "
    271 fi
    272 
    273 # Always show the current results.
    274 cat new.short >> final
    275 
    276 if [ $changed != 0 ] ; then
    277    echo "=================================================" >> final
    278    echo "== Results from 24 hours ago                   ==" >> final
    279    echo "=================================================" >> final
    280    cat old.short                                            >> final
    281 
    282    echo                                                     >> final
    283    echo "=================================================" >> final
    284    echo "== Difference between 24 hours ago and now     ==" >> final
    285    echo "=================================================" >> final
    286    echo                                                     >> final
    287    cat diff.short                                           >> final
    288    echo                                                     >> final
    289 fi
    290 
    291 # add perf results if requested
    292 if [ "${ABT_PERF}" != "" ]; then
    293    cat perflogfile                                             >> final
    294 fi
    295 
    296 # Gather up the diffs (at most the first 100 lines for each one) into a
    297 # single file.
    298 MAX_LINES=100
    299 diff_files=`find . -name '*.diff*' | sort`
    300 if [ z"$diff_files" = z ] ; then
    301    echo "Congratulations, all tests passed!" >> diffs
    302 else
    303    for i in $diff_files ; do
    304       echo "=================================================" >> diffs
    305       echo $i                                                  >> diffs 
    306       echo "=================================================" >> diffs
    307       if [ `wc -l < $i` -le $MAX_LINES ] ; then
    308          cat $i                                                >> diffs
    309       else
    310          head -n $MAX_LINES $i                                 >> diffs
    311          echo "<truncated beyond $MAX_LINES lines>"            >> diffs
    312       fi
    313    done
    314 fi
    315 
    316 # Rename diffs into diffs.txt such that it can be viewed easily with an
    317 # e-mail client.
    318 mv diffs diffs.txt
    319 
    320 # Use the conf/<tag>.sendmail script to email the results.
    321 conf/$TAG.sendmail \
    322    "$changed_str$START nightly build ($TAG, $ABT_DETAILS)" \
    323    final \
    324    diffs.txt > sendmail.log 2>&1
    325