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