blob: 1e996385dc432cfdfcc8057784a67d23830b0af6 [file] [log] [blame]
#!/bin/sh
# $Id$
#
##############################################################################
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed
# with this work for additional information regarding copyright
# ownership. The ASF licenses this file to you under the Apache
# License, Version 2.0 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied. See the License for the specific language governing
# permissions and limitations under the License.
#
# Copyright 1999-2007 Rogue Wave Software, Inc.
#
##############################################################################
#
# NAME
# runall.sh, run - run programs and analyze output
#
# SYNOPSIS
# runall.sh [option(s)...] [file(s)...]
#
# DESCRIPTION
# Takes a list of files as arguments. The files are assumed to be
# executable; if a file isn't executable, it is assumed to have a
# .o suffix, in which case it is considered as an object file and
# its existence is taken as success. If the file isn't executable
# and doesn't have a .o suffix, it is considered a failure.
#
# Runs all executables named on the command line giving each a
# fixed amount of time to complete. If the program fails to exit
# within the alotted amount of time, it is killed via a
# signal. Collects and reports statistics on each executable with
# the -p option tries to post a result file into a revison control
# system (Perforce).
#
# OPTIONS
# -a <age>
# Do not run programs, just collect output unless output
# file is older than `age' minutes.
#
# -c or --color
# Produce colorized output (default). Requires xterm.
#
# -d <text>
# Use `text' as a description when submitting a
# report. If `text' is an existing file, use the contents
# of the file as the description. Meaningful only with -p.
#
# -l <fname> or --log <fname>
# Append the file named `fname' to the end of the result
# file before posting. Meaningful only with -p.
#
# --label <name>
# Label files with the label `name', or generate own label
# name if "--label -". The generated label will have the
# following format: stdlib-<compiler>-<os>-<timestamp>.
# Meaningful only with -p.
#
# -m or --mono or --nocolor
# Produce monochrome output (no escape sequences). Default
# for all terminals other than xterm.
#
# -o <fname>
# Redirect process output to the named file. The option
# affects only the next executable to be run, it is reset
# for all others.
#
# -p <postdir>
# Run tests and examples and post results in a revision
# control system (Perforce by default).
#
# --ph Run plumhall LVS tests
#
# --rate <percent>
# Minimum pass rate (in percent) to post. If the pass rate
# is lower, send email to $P4USER notifying that post
# failed. Meaningful only with -p.
#
# -r <fname>
# Compare results against `fname' and report differences as
# regressions.
#
# -s <signo>
# Set the signal to be sent to the hung process. SIGKILL
# (signo 9) is default.
#
# -t <sec>
# Set process timeout to `sec' seconds. Negative value of
# `sec' allows an infinite timeout.
#
# -T <ts0,ts1,ts2>
# Specifies the timestamps corresponding to the local times
# at which the following events started: configuration, lib
# build, and tests (and examples) build, in that order.
# Meaningful only with -p.
#
# -X <text>
# Specifies additional command line options to be passed to
# the executable being run.
#
# -x <dir>
# Run subsequent filenames as examples and diff output
# against files in the respective subdirectories of `dir'
# (manual/ or tutorial/), if they exist.
#
##############################################################################
##############################################################################
# GLOBAL VARIABLES
##############################################################################
TIMEOUT=10 # seconds by default
SIGNO=9 # signal to be sent by default (SIGKILL by default)
REGRESS="." # regression file (cwd by default, ignored)
LINES=24 # default number of continuous lines
MANDIR="-" # directory containing manual (none by default)
MIN_PASS_RATE=70 # minimum acceptable pass rate
POSTFILE="." # posted results file name
POSTDESC="test results" # description used when posting
LABEL="-" # generate a label when posting
OUTFILE="." # default output file name
AGEMAX=0 # if non-zero will not run tests, just looks at
# test results not older than AGEMAX minutes
XOPTS="-D ." # additional options to be passed to executable
BUILDLOG=/dev/null # log to append to results when posting
TIMESTAMPS="-" # times when lib and tests builds started
case "`uname`" in
CYGWIN*)
DIFF_STRIP_CR="--strip-trailing-cr";; # strip trailing CR on CygWin
esac
##############################################################################
# FUNCTION DEFINITIONS
##############################################################################
setcolors ()
{
COLORS=$1
if [ $COLORS -ne 0 ] ; then
ESC0="" # escape sequence turning off any formatting
CLR_BLACK=""
CLR_RED=""
CLR_GREEN=""
CLR_BLUE=""
CLR_YELLOW=""
CLR_MAGENTA=""
CLR_CYAN=""
CLR_GRAY=""
CLR_ERROR="" # serious error (core dump, etc)
CLR_SUCCESS="" # important improvement (e.g., regress < 0)
CLR_WARN="" # potential problem (decrease in assertins)
else
unset ESC0
unset CLR_BLACK
unset CLR_RED
unset CLR_GREEN
unset CLR_BLUE
unset CLR_YELLOW
unset CLR_CYAN
unset CLR_GRAY
unset CLR_ERROR
unset CLR_SUCCESS
unset CLR_WARN
fi
}
# post results in Perforce
post_results ()
{
p4 opened 2>&1 | grep "File(s) not opened on this client."
if [ $? -ne 0 ] ; then
echo "Warning: files opened on $P4CLIENT."
# exit 1
fi
# create a label containing all files in our client view
if [ "$LABEL" ] ; then
[ "$LABEL" = "-" ] && LABEL="stdlib-$POSTFILE-`date +%m.%d.%y-%H:%M`"
( echo Label: $LABEL ;
echo View: ;
p4 client -o | sed -n "s:\(//.*\) //.*:\1:p" ) | p4 label -i
fi
# see if we can check the file out
P4PATH=`p4 edit $POSTDIR/$POSTFILE 2>&1`
echo $P4PATH | grep " - file(s) not on client." > /dev/null 2>&1
# add the file if it is not in p4
[ $? -eq 0 ] && P4PATH=`p4 add $POSTDIR/$POSTFILE`
[ ! -x "$POSTDIR" ] && echo "$POSTDIR doesn't exist, can't post"
# copy postfile (and a log, if any) where it can be checked in from
cat $POSTFILE $BUILDLOG > $POSTDIR/$POSTFILE
# remove junk p4 appends to the end of file names
P4PATH=`echo $P4PATH | sed "s/#[1-9][0-9]* - .*$//"`
echo "executing: p4 submit -i $P4PATH"
# submit into Perforce
cat << EOF | p4 submit -i $P4PATH
Change: new
Description:
`cat /tmp/summary-$$`
Files: $P4PATH
EOF
# clean up
rm /tmp/summary-$$
}
# send mail with postfile (containing summary info) to p4 user
send_mail ()
{
# check for mailx to use -s subject
if type mailx > /dev/null 2>&1 ; then
mailcmd=mailx -s "could not post $POSTFILE"
elif [ `uname` = Linux ] ; then
# mail on Linux understands -s
mailcmd=mail -s "could not post $POSTFILE"
else
mailcmd=mail
fi
email=`p4 user -o | sed -n "s/^Email:.\(.*\)/\1/p"`
cat $POSTFILE | $mailcmd $email
}
# format a line on output
# $1: STATUS, $2: ASSRTS, $3 HIGH, $4 DELTA, $5 FAILED, $6 LOW,
# $7: REGRESS, $8: PERCNT
format ()
{
if [ $4 -ne 0 ] ; then
ESC2="$CLR_BLACK"
ESC4="$ESC2"
fi
# colorize regression field (numeric $1 okay, non-numeric considered error)
if [ $7 -gt 0 ] || [ `expr $1 + 0 >/dev/null 2>&1; echo $?` -eq 2 ] ; then
ESC7="$CLR_ERROR"
elif [ $7 -lt 0 ] ; then
ESC7="$CLR_SUCCESS"
fi
printf "$ESC1" >&2 ; printf " %6.6s" $1 ; printf "$ESC0" >&2
# skip negative value (indicates that values don't make sense)
if [ $2 -ge 0 ] ; then
printf "$ESC2" >&2 ; printf " %6d" $2 ; printf "$ESC0" >&2
printf "$ESC3" >&2 ; printf " %6d" $3 ; printf "$ESC0" >&2
printf "$ESC4" >&2 ; printf " %6d" $4 ; printf "$ESC0" >&2
printf "$ESC5" >&2 ; printf " %6d" $5 ; printf "$ESC0" >&2
printf "$ESC6" >&2 ; printf " %6d" $6 ; printf "$ESC0" >&2
printf "$ESC7" >&2 ; printf " %6d" $7 ; printf "$ESC0" >&2
printf "$ESC8" >&2 ; printf " %5d%%" $8 ; printf "$ESC0" >&2
printf "$ESC0" >&2
fi
echo
}
# get signal name from signal number (first argument)
signame ()
{
n=`expr \( \( $1 - 1 \) % 4 + 1 \) \* 2`
n=`kill -l | grep ".$1)" | head -1 | awk "{ print $"$n" }" | sed "s/SIG//"`
[ "$n" = "" ] && n="SIG$1"
echo $n
}
# compmute the elapsed time between adjacent arguments, each of which is
# expected to be in date +%T format, result is sent to stdout in +%T format
elapsed_time ()
{
first=$1
t0=`echo $1 | awk 'BEGIN { FS=":" } { print $1 * 3600 + $2 * 60 + $3 }'`
shift
for t in $* ; do
t1=`echo $t | awk 'BEGIN { FS=":" } { print $1 * 3600 + $2 * 60 + $3 }'`
[ $t1 -lt $t0 ] && t1=`expr $t1 + 24 \* 60 \* 60`
hrs=`expr \( $t1 - $t0 \) / 3600`
if [ $hrs -gt 0 ] ; then
printf "%d:%02d:%02d " $hrs \
`expr \( \( $t1 - $t0 \) % 3600 \) / 60` \
`expr \( $t1 - $t0 \) % 60`
else
printf "%d:%02d " `expr \( \( $t1 - $t0 \) % 3600 \) / 60` \
`expr \( $t1 - $t0 \) % 60`
fi
t0=$t1
done
# compute the difference between the first and the last args
[ $# -gt 2 ] && elapsed_time $first $t
}
fmat_diff ()
{
# search file for the first occurrence of a number followed by
# the string in $2; keep number and exit immediately to save time
d=`sed -n "/$2/{s/[^0-9]*\([1-9][0-9]*\).*$2.*/\1/p;q
}" $REGRESS`
if [ "$d" != "" ] ; then
d=`expr $1 - $d`
# output only if difference is non-zero
[ $d -ne 0 ] && printf "(%+d) " $d
fi
unset d
}
##############################################################################
# MAIN LOOP
##############################################################################
# ensure consistent behavior of POSIX utilities such as grep and sed
LANG=POSIX
# show help and exit when invoked with no arguments
if [ $# -eq 0 ] ; then
# print out top of this file (between the ###-lines)
# sed expression split up to satisfy non-GNU sed
sed -n "/^###/!D; {: print
n; /^###/q; s/^#//p; t print
}" $0
exit 0
fi
# reset the terminal settings on exit
trap 'printf "$ESC0" >&2 && exit' 0 2 3 15
SIGNAME=`signame $SIGNO`
HEADER="NAME STATUS ASSRTS HIGH DELTA FAILED LOW RGRESS PERCNT"
# write out our command line - uncomment for debugging
# echo $0 $*
tst_count=0 # number of tests tried
tst_pass=0 # number of successfully run tests (perhaps with assertions)
tst_ncomp=0 # number of tests that failed to compile
tst_nlink=0 # number of tests that failed to link
tst_fail=0 # number of tests run to completion but with failures
tst_core=0 # number of tests that dumped core
tst_kill=0 # number of tests that were forcefully killed
tst_rgrs=0 # number of tests with regressions
asrt_count=0 # total number of assertions
asrt_dlta=0 # increase in assertions from last run
asrt_pass=0 # total number of passed assertions
asrt_fail=0 # total number of failed assertions
asrt_rgrs=0 # increase in failed assertions from last run
asrt_hi=0 # the total highest number of failed assertions ever
asrt_lo=0 # the total lowest number of failed assertions ever
t0=`date +%T` # timestamp
# get $LINES and $COLUMNS set if possible
type resize > /dev/null 2>&1 && eval `resize` 2>&1 > /dev/null
[ -z "$LINES" ] && LINES=40
[ -z "$COLUMNS" ] && COLUMNS=80
if [ "$TERM" = "xterm" ] ;then
setcolors 1 # turn on colorized output
else
setcolors 0 # disable colorization
fi
for i do
# process command line options
# avoid the unportable [ ! "$foo" ]
if [ "" = "$AGEMAX" ] ; then
AGEMAX=$i
continue
elif [ "$i" = "-a" ] ; then
unset AGEMAX
continue
elif [ "" = "$POSTDESC" ] ; then
POSTDESC="$i"
continue
elif [ "$i" = "-d" ] ; then
unset POSTDESC
continue
elif [ "$i" = "-m" ] || [ "$i" = "--mono" ] || [ "$i" = "--nocolor" ]; then
setcolors 0
continue
elif [ "$i" = "-c" ] || [ "$i" = "--color" ] ; then
setcolors 1
continue
elif [ "" = "$BUILDLOG" ] ; then
BUILDLOG=$i
continue
elif [ "$i" = "-l" ] || [ "$i" = "--log" ]; then
unset BUILDLOG
continue
elif [ "" = "$LABEL" ] ; then
LABEL=$i
continue
elif [ "$i" = "--label" ] ; then
unset LABEL
continue
elif [ "" = "$REGRESS" ] ; then
REGRESS=$i
continue
elif [ "$i" = "-r" ] ; then
unset REGRESS
continue
elif [ "" = "$MIN_PASS_RATE" ] ; then
MIN_PASS_RATE=$i
continue
elif [ "$i" = "--rate" ] ; then
unset MIN_PASS_RATE
continue
elif [ "" = "$TIMEOUT" ] ; then
TIMEOUT=$i
continue
elif [ "$i" = "-t" ] ; then
unset TIMEOUT
continue;
elif [ "" = "$TIMESTAMPS" ] ; then
TIMESTAMPS=$i
continue
elif [ "$i" = "-T" ] ; then
unset TIMESTAMPS
continue;
elif [ "" = "$SIGNO" ] ; then
SIGNO=$i
SIGNAME=`signame $SIGNO`
continue
elif [ "$i" = "-s" ] ; then
unset SIGNO
continue
elif [ "" = "$MANDIR" ] ; then
MANDIR=$i/manual
TUTDIR=$i/tutorial
continue
elif [ "" = "$XOPTS" ] ; then
XOPTS="$i"
continue
elif [ "$i" = "-X" ] ; then
unset XOPTS
continue
elif [ "$i" = "-x" ] ; then
unset MANDIR
continue
elif [ "$i" = "--ph" ] ; then
PLUMHALL=1
MANDIR='-' # indicates we're running tests
continue
elif [ "" = "$POSTFILE" ] ; then
POSTDIR=`dirname $i`
POSTFILE=`basename $i`
continue
elif [ "$i" = "-p" ] ; then
unset POSTFILE
continue
elif [ "" = "$OUTFILE" ] ; then
OUTFILE=$i
continue
elif [ "$i" = "-o" ] ; then
unset OUTFILE
continue
fi;
n_asrt=0 # number of assertions in this test
d_asrt=0 # increase in assertions from last run
p_asrt=0 # passed assertions in this test
f_asrt=0 # failed assertions in this test
r_asrt=0 # number of regressions
h_asrt=0 # the highest number of assertions ever tested
l_asrt=0 # the least number of assertions ever tested
pcnt_asrt=0 # percentage of passed assertions in this test
no_asserts=0 # non-zero if output doesn't contain assertion tags
exit_status=0 # successful exit status by default (will be overridden)
ESC1="$ESC0" ; ESC2="$ESC0" ; ESC3="$ESC0" ; ESC4="$ESC0"
ESC5="$ESC0" ; ESC6="$ESC0" ; ESC7="$ESC0" ; ESC8="$ESC0"
if [ `expr $tst_count % $LINES` -eq 0 ] ; then
# redirect test number to stderr in order not to mess up diff
echo ; printf "$CLR_BLACK" >&2 ; printf "%s" "--- " >&2
echo "$HEADER" ; printf "$ESC0" >&2
fi
tst_count=`expr $tst_count + 1`
printf "%3d " $tst_count 1>&2
# strip trailing `.sh' from filename if present
file=`basename $i | sed "s/\.sh//"`
printf "%-18.18s" $file
# if an executable file exists _or_ if AGEMAX is not 0
if [ -x "$i" ] || [ $AGEMAX -ne 0 ] ; then
# get the name of input file if any (/dev/null by default)
if [ -f $MANDIR/in/$file.in ] ; then
input=$MANDIR/in/$file.in
elif [ -f $TUTDIR/in/$file.in ] ; then
input=$TUTDIR/in/$file.in
else
input=/dev/null
fi
if [ "$OUTFILE" = "." ] ; then
output="$i.out"
else
output=$OUTFILE
fi
if [ $AGEMAX -eq 0 ] ; then
# save cursor position in case the shell (bash 2 on SunOS)
# reports when a process gets a signal despite redirection
[ "$COLORS" != "0" ] && printf "7" >&2
# set alarm in process (in case we can't kill it if it hangs)
alrm=`expr $TIMEOUT + 3`
# run test in the background, redirect I/O to a file
# stderr redirected to /dev/null to prevent compilation
# warnings in "script" mode from causing false errors
$i $XOPTS -O $output -L $alrm -M "`uname -a`" \
> $output < $input 2>/dev/null &
# get the background process' pid
testpid=$!
# start a subshell to kill hung process
if [ $TIMEOUT -ge 0 ] ; then
(t=$TIMEOUT
while [ $t -ne 0 ]; do
# exit right away if process doesn't exist
ps -p $testpid > /dev/null 2>&1 || exit 0
# show countdown if colorized
[ "$COLORS" != "0" ] \
&& printf "$CLR_WARN %6d$ESC0" $t >&2
t=`expr $t - 1`
sleep 1
done
kill -s $SIGNO $testpid > /dev/null 2>&1
)&
fi
# we'll test for this later
kill_status=`expr 128 + $SIGNO`
# wait for test to exit (on its own or forcefully)
wait $testpid
exit_status=$?
# restore cursor position
[ "$COLORS" != "0" ] && printf "8" >&2
else
# set kill status to be different than exit_status
kill_status=1
found=`find ./$output -mmin -$AGEMAX`
if [ "" = "$found" ] ; then
exit_status=-1
else
# indicate that output file was stale (older than AGEMAX)
exit_status=0
fi
fi
if [ $exit_status -lt 126 ] && [ "$PLUMHALL" ]; then
exit_status=0 #plum hall exit status is number of failed tests
fi
if [ $exit_status -eq 0 ]; then
if [ "$MANDIR" = "-" ] ; then # running tests
# make sure output file exists
if [ -f "$output" ] ; then
tst_pass=`expr $tst_pass + 1`
# grep for the number of total and failed assertions
if [ "$PLUMHALL" ]; then
f_asrt=`grep "errors detected" $output \
| sed "s/\*\*\*\*\* \([0-9]*\) .*/\1/"`
n_success=`grep "successful test case" $output \
| sed "s/\*\*\*\*\* \([0-9]*\) .*/\1/"`
if [ "$f_asrt" ] && [ "$n_success" ]; then
n_asrt=`expr $n_success + $f_asrt`
fi
else
n_asrt=`sed "s/[^ -~]/ /g" $output \
| grep "## Assertions" \
| tail -1 | sed "s/[^0-9]//g"`
f_asrt=`sed "s/[^ -~]/ /g" $output \
| grep "## FailedAssertions" \
| tail -1 | sed "s/[^0-9]//g"`
fi
if [ "" = "$n_asrt" ] ; then
n_asrt=0
no_assert=1
# no regression line found, something's fishy
exit_status="FORMAT" ; ESC1="$CLR_WARN"
fi
[ "" = "$f_asrt" ] && f_asrt=0
# increment the number of tests not passing at 100%
[ $f_asrt -gt 0 ] && tst_fail=`expr $tst_fail + 1`
# compute percentage of passed assertions
p_asrt=`expr $n_asrt - $f_asrt`
asrt_count=`expr $asrt_count + $n_asrt`
asrt_pass=`expr $asrt_pass + $p_asrt`
asrt_fail=`expr $asrt_fail + $f_asrt`
[ $f_asrt -gt 0 ] && ESC5="$CLR_RED"
# prevent division by zero
[ $n_asrt -ne 0 ] \
&& pcnt_asrt=`expr 100 \* $p_asrt / $n_asrt`
else # output file not found
exit_status="OUTPUT" ; ESC1="$CLR_ERROR"
fi
else # running examples (expect output)
no_asserts=1
# get the name of file against which to diff the output
if [ -f $MANDIR/out/$file.out ] ; then
diff_file=$MANDIR/out/$file.out
elif [ -f $TUTDIR/out/$file.out ] ; then
diff_file=$TUTDIR/out/$file.out
else
unset diff_file
fi
if [ "$diff_file" != "" ] ; then
diff $DIFF_STRIP_CR $diff_file $output >/dev/null 2>&1
if [ $? -eq 0 ] ; then
tst_pass=`expr $tst_pass + 1`
else
exit_status="DIFF" ; ESC1="$CLR_ERROR"
fi
else
exit_status="OUTPUT" ; ESC1="$CLR_WARN"
tst_pass=`expr $tst_pass + 1`
fi
ESC2="$ESC0" ; ESC3="$ESC2" ; ESC4="$ESC2" ; ESC5="$ESC2"
ESC6="$ESC2" ; ESC7="$ESC2" ; ESC8="$ESC2"
fi
elif [ $exit_status -eq 126 ] ; then
exit_status="EXIST" # can't find executable
ESC1="$CLR_WARN"
elif [ $exit_status -eq 127 ] ; then
exit_status="EXEC" # can't execute (check LD_LIBRARY_PATH)
ESC1="$CLR_WARN"
elif [ $exit_status -eq $kill_status ] ; then
exit_status=`signame $SIGNO` # forcefully killed
ESC1="$CLR_ERROR"
tst_kill=`expr $tst_kill + 1`
elif [ $exit_status -ge 128 ] ; then
n=`expr $exit_status - 128`
exit_status=`signame $n`
ESC1="$CLR_ERROR"
tst_core=`expr $tst_core + 1`
elif [ $exit_status -eq -1 ] ; then
exit_status="STALE"
ESC1="$CLR_WARN"
else
ESC1="$CLR_WARN"
fi
elif [ -f $i.o ] ; then
exit_status="LINK" # .o exists but no executable, failed to link
ESC1="$CLR_ERROR"
tst_nlink=`expr $tst_nlink + 1`
else
# file isn't executable, see if it's an object file...
suffix=`echo $i | sed "s/.*\(\..*\)/\1/"`
if [ "$suffix" = ".o" ] && [ -f "$i" ] ; then
no_asserts=1
tst_pass=`expr $tst_pass + 1`
else
exit_status="COMP" # no .o, failed to compile
ESC1="$CLR_ERROR"
tst_ncomp=`expr $tst_ncomp + 1`
fi
fi
if [ -f "$REGRESS" ] ; then
# find line for same executable in a previous report file
line=`grep "^$file[ .] " $REGRESS | head -n 1`
# compute difference in tried assertions
d_asrt=`echo $line | awk '{ print $3 }'`
d_asrt=`expr $n_asrt - 0$d_asrt`
# only consider if current exit status is 0 (success)
if [ "$exit_status" = "0" ] ; then
# regressions make sense only if previous exit status was 0
if [ "`echo $line | awk '{ print $2 }'`" = "0" ] ; then
r_asrt=`echo $line | awk '{ print $6 }'`
r_asrt=`expr $f_asrt - 0$r_asrt`
fi
# see if the lowest number of failed assertions improved
l_asrt=`echo $line | awk '{ print $7 }'`
[ "" = "$l_asrt" ] && l_asrt=0
[ $l_asrt -gt $f_asrt ] && l_asrt=$f_asrt && ESC6="$CLR_SUCCESS"
else
# carry over previous low assertions on failure
l_asrt=`echo $line | awk '{ print $7 }'`
[ "" = "$l_asrt" ] && l_asrt=0
# count the test as regressing if the last exit status was 0
old_status=`echo $line | awk '{ print $2 }'`
[ "$old_status" = "0" ] && tst_rgrs=`expr $tst_rgrs + 1`
fi
# adjust highest number of assertions achieved
h_asrt=`echo $line | awk '{ print $4 }'`
[ "" = "$h_asrt" ] && h_asrt=0
[ $h_asrt -lt $n_asrt ] && h_asrt=$n_asrt && ESC3="$CLR_BLACK"
# increment cumulative totals
asrt_dlta=`expr $asrt_dlta + $d_asrt`
asrt_rgrs=`expr $asrt_rgrs + $r_asrt`
[ $r_asrt -gt 0 ] && tst_rgrs=`expr $tst_rgrs + 1`
else
l_asrt=$f_asrt
h_asrt=$n_asrt
fi
# get rid of leading zeros (to prevent octal conversion by printf)
l_asrt=`expr $l_asrt + 0`
asrt_hi=`expr $h_asrt + $asrt_hi`
asrt_lo=`expr $l_asrt + $asrt_lo`
# set number of assertions negative if assertion tags not found
[ $no_asserts -ne 0 ] && n_asrt=-1
# careful with leading zeros (interpreted as octal with %d)
format $exit_status $n_asrt $h_asrt $d_asrt \
$f_asrt $l_asrt $r_asrt $pcnt_asrt
# reset name of output file
OUTFILE="."
done
# compute pass rate as percentage of tests with perfect score
# out of the total number of tests tried
pass_rate=0
[ $tst_count -gt 0 ] && pass_rate=`expr \( 100 \* \( $tst_pass - $tst_fail \) \) / $tst_count`
if [ $tst_count -gt 1 ] ; then
[ $asrt_count -ne 0 ] && pcnt_asrt=`expr 100 \* $asrt_pass / $asrt_count`
# show cumulative results
printf "\n--- " 1>&2
printf "%-18.18s" ""
ESC1="" ; ESC2="" ; ESC3="" ; ESC4=""
ESC5="" ; ESC6="" ; ESC7="" ; ESC8=""
# careful with leading zeros (interpreted as octal with %d)
format $tst_pass $asrt_count $asrt_hi $asrt_dlta \
$asrt_fail $asrt_lo $asrt_rgrs $pcnt_asrt
echo ; printf "${CLR_BLACK} " >&2
echo " FAIL COMP LINK ASSERT CORE KILL RGRESS";
printf "$ESC0 " >&2
printf " %6d %6d %6d %6d %6d %6d %6d\n" \
`expr $tst_count - $tst_pass` \
$tst_ncomp $tst_nlink $tst_fail $tst_core $tst_kill $tst_rgrs
echo
if [ -f "$REGRESS" ] ; then
# compute and format summary regressions wrt the previous report
# each var will be empty when there's no change, else "(+/-N) "
d_count=`fmat_diff $tst_count "programs"`
d_ncomp=`fmat_diff $tst_ncomp "failed to compile"`
d_nlink=`fmat_diff $tst_nlink "failed to link"`
d_fail=`fmat_diff $tst_fail "failed at least one assertion"`
d_core=`fmat_diff $tst_core "exited with a signal"`
d_kill=`fmat_diff $tst_kill "killed with signal"`
d_rate=`fmat_diff $pass_rate "pass rate"`
# special treatment (no variable $tst_nzero exists)
d_nzero=`expr $tst_count - $tst_pass`
d_nzero=`fmat_diff $d_nzero "exited with non-zero status"`
if [ -f "$POSTFILE" ] ; then
# modify REGRESS to be the p4 path name and rev # of what
# regressions are being reported against (used in description)
tmp=`p4 have $REGRESS | sed "s/ - .*//" 2>/dev/null`
[ $? -eq 0 ] && REGRESS="$tmp"
fi
regress_line="$asrt_rgrs regressions (baseline was $REGRESS)"
else
regress_line="no regressions (this is baseline)"
fi
# present summary only for more files than fits on screen or when posting
if [ $tst_count -ge $LINES -o -f "$POSTFILE" ] ; then
# compute and format timestamps
if [ "$TIMESTAMPS" != "-" ] ; then
# expect: "h0:m0:s0,h1:m1:s1,h2:m2:s2"
TIMESTAMPS="$TIMESTAMPS $t0 `date +%T`"
# replace commas with spaces
TIMESTAMPS=`echo $TIMESTAMPS | sed "s/,/ /g"`
TIMESTAMPS=`elapsed_time $TIMESTAMPS | awk '{ print \
"cfg: " $1 " lib: " $2 " tst: " $3 " run: " $4 " all: " $5 }'`
fi
# create a file containing summary info about this run
cat << EOF | tee /tmp/summary-$$
Generated by $LOGNAME@`uname -n` running `uname -sr`
`if [ -f "$POSTDESC" ]; then cat "$POSTDESC" ; else echo $POSTDESC; fi`
`[ "$TIMESTAMPS" != "-" ] && echo "Times: $TIMESTAMPS"`
Summary: out of $tst_count ${d_count}programs
`expr $tst_count - $tst_pass` ${d_nzero}exited with non-zero status
$tst_ncomp ${d_ncomp}failed to compile
$tst_nlink ${d_nlink}failed to link
$tst_fail ${d_fail}failed at least one assertion
$tst_core ${d_core}exited with a signal
$tst_kill ${d_kill}killed with signal $SIGNO
$regress_line
$pass_rate% ${d_rate}pass rate
EOF
fi
else
echo
fi
# post results in revision control system
if [ -f "$POSTFILE" ] ; then
# make sure minimum pass rate is achieved
if [ $pass_rate -lt $MIN_PASS_RATE ] ; then
# send email to p4 user if not passing at a desired rate
send_mail
echo "pass rate < $MIN_PASS_RATE%, can't post"
elif [ "$P4CLIENT" != "" ] ; then
# post results in Perforce
post_results
else
send_mail
echo "P4CLIENT not defined, can't post"
fi
elif [ "$POSTFILE" != "." ] ; then
echo "$POSTFILE not found, can't post"
exit 1
fi