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. 15get_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 29runcmd () { 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 62valgrind_svn_repo="svn://svn.valgrind.org/valgrind/trunk" 63vex_svn_repo="svn://svn.valgrind.org/vex/trunk" 64 65# Must have exactly two arguments 66if [ $# -ne 2 ] ; then 67 echo "usage: $0 /path/to/valgrind/nightly <tag>" 68 exit 1 69fi 70 71# Get args from command line 72DIR=$1 73TAG=$2 74 75# Get times and date 76START=`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. 80svn_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. 84svn_old_date= 85if [ "z" = "z${svn_old_date}" ] ; then 86 # Linux method. 87 svn_old_date=`date --date=yesterday $svn_date_format 2> /dev/null` 88fi 89if [ "z" = "z${svn_old_date}" ] ; then 90 # Darwin method. 91 svn_old_date=`date -v-24H $svn_date_format 2> /dev/null` 92fi 93if [ "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; 96fi 97 98# The time-and-date for now is easy. 99svn_new_date=`date $svn_date_format` 100 101cd $DIR 102 103# Clean up output files produced by a previous run. 104rm -rf diffs diffs.txt diff.short final new.short new.verbose old.short old.verbose 105rm -rf sendmail.log unchanged.log valgrind-old valgrind-new 106 107# Setup any relevant environment variables from conf/<tag>.conf. 108. conf/$TAG.conf 109if [ "${ABT_JOBS}" = "" ]; then 110 ABT_JOBS=1 111fi 112if [ "${ABT_EVAL}" = "" ]; then 113 ABT_EVAL="eval" 114fi 115if [ "${ABT_RUN_REGTEST}" = "" ]; then 116 ABT_RUN_REGTEST="make regtest" 117fi 118 119if [ "${ABT_PERF_TOOLS}" = "" ]; then 120 ABT_PERF_TOOLS="--tools=none,memcheck,callgrind,helgrind,cachegrind,drd,massif" 121fi 122if [ "${ABT_PERF_REPS}" = "" ]; then 123 ABT_PERF_REPS="--reps=3" 124fi 125 126 127#---------------------------------------------------------------------------- 128# Check out, build, test 129#---------------------------------------------------------------------------- 130 131vg_old_rev="`get_svn_revision ${svn_old_date} ${valgrind_svn_repo}`" 132vg_new_rev="`get_svn_revision ${svn_new_date} ${valgrind_svn_repo}`" 133vex_old_rev="`get_svn_revision ${svn_old_date} ${vex_svn_repo}`" 134vex_new_rev="`get_svn_revision ${svn_new_date} ${vex_svn_repo}`" 135if [ "${vg_old_rev}" = "${vg_new_rev}" -a "${vex_old_rev}" = "${vex_new_rev}" ] 136then 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 140fi 141 142# Do everything twice -- once for the 24 hours old Valgrind, and once 143# for the current one. 144for 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 ) 203done 204 205# if requested, run regression tests and produce results in perflogfile.out 206if [ "${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 .. 211fi 212 213 214#---------------------------------------------------------------------------- 215# Prepare results and send 216#---------------------------------------------------------------------------- 217 218# Get times and date 219END=`date "+%F %H:%M:%S %Z"` 220 221# Gather some information about this run and its environment 222valgrind_revision="`svn info valgrind-new | grep Revision | sed 's/Revision[ ]*:[ ]*//'`" 223vex_revision="`svn info valgrind-new/VEX | grep Revision | sed 's/Revision[ ]*:[ ]*//'`" 224gcc_version="`gcc --version 2> /dev/null | head -1`" 225gdb_version="`gdb --version 2> /dev/null | head -1`" 226as_version="`as --version 2> /dev/null | head -1`" 227libc_so="`ls -1 /lib/libc.so.* /lib64/libc.so.* /lib32/libc.so.* /lib/*-linux-gnu/libc.so.* 2>/dev/null | tail -1`" 228libc="unknown" 229if [ "x$libc_so" != "x" ]; then 230 if [ -e "$libc_so" -a -r "$libc_so" ]; then 231 libc="`$libc_so | head -1`" 232 fi 233fi 234libc=`echo $libc | sed "s/, by Roland.*//"` 235uname_stuff="`uname -mrs`" 236if [ -r /etc/os-release ]; then 237 vendor_stuff="`. /etc/os-release; echo ${NAME} ${VERSION}`" 238elif which lsb_release 2>&1 > /dev/null; then 239 vendor_stuff="`lsb_release -sicr | xargs echo`" 240elif [ -e "/etc/issue.net" -a -r "/etc/issue.net" ]; then 241 vendor_stuff="`cat /etc/issue.net | head -1`" 242else 243 vendor_stuff="unknown" 244fi 245 246echo "valgrind revision: $valgrind_revision" > final 247echo "VEX revision: $vex_revision" >> final 248echo "C compiler: $gcc_version" >> final 249echo "GDB: $gdb_version" >> final 250echo "Assembler: $as_version" >> final 251echo "C library: $libc" >> final 252echo "uname -mrs: $uname_stuff" >> final 253echo "Vendor version: $vendor_stuff" >> final 254 255# 'final' shows the difference between the old and new results 256echo >> final 257echo "Nightly build on" $TAG "(" $ABT_DETAILS ")" >> final 258echo "Started at" $START >> final 259echo "Ended at" $END >> final 260 261# If the results differ from 24 hours ago, print extra stuff. 262diff -C1 old.short new.short > diff.short 263changed=$? 264 265if [ $changed != 0 ] ; then 266 echo "Results differ from 24 hours ago" >> final 267 changed_str="" 268else 269 echo "Results unchanged from 24 hours ago" >> final 270 changed_str="(unchanged) " 271fi 272 273# Always show the current results. 274cat new.short >> final 275 276if [ $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 289fi 290 291# add perf results if requested 292if [ "${ABT_PERF}" != "" ]; then 293 cat perflogfile >> final 294fi 295 296# Gather up the diffs (at most the first 100 lines for each one) into a 297# single file. 298MAX_LINES=100 299diff_files=`find . -name '*.diff*' | sort` 300if [ z"$diff_files" = z ] ; then 301 echo "Congratulations, all tests passed!" >> diffs 302else 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 314fi 315 316# Rename diffs into diffs.txt such that it can be viewed easily with an 317# e-mail client. 318mv diffs diffs.txt 319 320# Use the conf/<tag>.sendmail script to email the results. 321conf/$TAG.sendmail \ 322 "$changed_str$START nightly build ($TAG, $ABT_DETAILS)" \ 323 final \ 324 diffs.txt > sendmail.log 2>&1 325