FYI, I've just checked in the following for the 108/bdbstore module:
[I plan to do the same for qpidd later this week, but with the difference
that it won't be turned on by default -- at least not in the beginning.]
Instrument all tests so that they are run via valgrind (when possible):
check for both errors and leaks.
* configure.ac: Check for valgrind.
* tests/Makefile.am (TESTS_ENVIRONMENT): Export VALGRIND.
* tests/.vg-supp: New file, exempting known leaks on rawhide and
Debian/unstable. Leaks on the latter system all seem to originate
in cppunit. Some of the rawhide ones look suspicious.
* tests/run-unit-tests: Use new "setup" file.
Invoke DllPlugInTester via $vg (aka valgrind).
Refer to the source directory using $pwd, since we're now running
from a temporary subdirectory.
* tests/system_test.sh: Remove traps. That is now done by "setup".
[VERBOSE]: Print qpidd --version.
Invoke qpidd via $vg.
Add a kludgey "sleep 3", because it can take a while for libtool
to start valgrind to start qpidd, in the background.
Ideally, the python script would simply sleep-0.3-and-retry for
a couple seconds, upon failure of the initial connection attempt.
* tests/setup: New file.
With these changes, if you introduce a leak and run "make check", any test
that triggers that leak will fail with info from valgrind giving a clue to
where the leaked memory was allocated. Of course, if the leak is in code
(e.g., a library) you have no control over, then you'll probably want to
ignore it -- but make a note to report/fix it upstream later. In that
case, add the appropriate "suppression" to the tests/.vg-supp file.
Since this is valgrind, it also detects used-uninitialized errors,
double-free, and the like. They too cause "make check" to fail.
One drawback with this sort of test is that it is very sensitive to the
environment (things like OS, libraries, C++ compiler version, etc.),
so if you run "make check" on RHEL N, or even straight FC 6, expect to
have to make some additions to the list of suppressions.
Index: configure.ac
===================================================================
--- configure.ac (revision 678)
+++ configure.ac (working copy)
@@ -124,6 +124,9 @@
USE_APR=1
fi
+# We use valgrind for the tests. See if it's available.
+AC_CHECK_PROG([VALGRIND], [valgrind], [yes])
+
AC_CONFIG_FILES([
Makefile
tests/Makefile
Index: tests/Makefile.am
===================================================================
--- tests/Makefile.am (revision 678)
+++ tests/Makefile.am (working copy)
@@ -28,6 +28,7 @@
TESTS_ENVIRONMENT = \
QPID_DIR=$(QPID_DIR) \
+ VALGRIND=$(VALGRIND) \
abs_builddir='$(abs_builddir)' \
abs_srcdir='$(abs_srcdir)'
Index: tests/.vg-supp
===================================================================
--- tests/.vg-supp (revision 0)
+++ tests/.vg-supp (revision 0)
@@ -0,0 +1,2553 @@
+{
+ x14262_1
+ Memcheck:Leak
+ fun:_vgrZU_libstdcZpZpZa__Znwm
[2500+ lines of mangled stack signatures (what valgrind calls suppressions)]
Index: tests/run-unit-tests
===================================================================
--- tests/run-unit-tests (revision 678)
+++ tests/run-unit-tests (working copy)
@@ -1,8 +1,14 @@
#!/bin/sh
-set -e
+. $srcdir/setup
+
+fail=0
+
DB_HOME=dbdata
mkdir -p $DB_HOME
export DB_HOME
-strace -o k -ff DllPlugInTester -c -b .libs/*.so
+$vg DllPlugInTester -c -b $pwd/.libs/*.so 2> out || fail=1
rm -rf $DB_HOME
+
+vg_check out || fail=1
+exit $fail
Index: tests/system_test.sh
===================================================================
--- tests/system_test.sh (revision 678)
+++ tests/system_test.sh (working copy)
@@ -17,21 +17,15 @@
# specific language governing permissions and limitations
# under the License.
+qpidd=$QPID_DIR/cpp/src/qpidd
+
if test "$VERBOSE" = yes; then
set -x
- qpidd --version
+ $qpidd --version
fi
-pid=0
-pwd=`pwd`
-t0=`echo "$0"|sed 's,.*/,,'`.tmp; tmp=$t0/$$
-trap 's=$?;test $pid = 0||kill -SIGINT $pid;cd "$pwd" && rm -rf $t0 && exit
$s' 0
-trap '(exit $?); exit $?' 1 2 13 15
+. $srcdir/setup
-framework_failure=0
-mkdir -p $tmp || framework_failure=1
-cd $tmp || framework_failure=1
-
# Make sure $QPID_DIR contains what we need.
xml_spec=$QPID_DIR/specs/amqp.0-8.xml
test -f $xml_spec \
@@ -48,14 +42,16 @@
fail=0
-qpidd=$QPID_DIR/cpp/src/qpidd
-
for p in `seq 1 4`; do
- $qpidd -s "$abs_builddir/../lib/.libs/libbdbstore.so" >> qpid.log & pid=$!
+ log=vg-log.$p
+ $vg $qpidd -s "$abs_builddir/../lib/.libs/libbdbstore.so" \
+ >> qpid.log 2> $log & pid=$!
+ sleep 3
echo phase $p...
python "$abs_srcdir/persistence.py" -s "$xml_spec" -p $p || fail=1
kill -SIGINT $pid || { echo process already died; cat qpid.log ; fail=1; }
wait $pid || fail=1
+ vg_check $log || fail=1
done
pid=0
Index: tests/setup
===================================================================
--- tests/setup (revision 0)
+++ tests/setup (revision 0)
@@ -0,0 +1,74 @@
+# -*- sh -*-
+
+test "$VERBOSE" = yes && set -x
+
+pwd=`pwd`
+t0=`echo "$0"|sed 's,.*/,,'`.tmp; tmp=$t0/$$
+pid=0
+test -z "$TEST_DEBUG" &&
+trap 's=$?;test $pid = 0||kill -SIGINT $pid;cd "$pwd" && rm -rf $t0 && exit
$s' 0
+test -z "$TEST_DEBUG" && trap '(exit $?); exit $?' 1 2 13 15
+
+framework_failure=0
+mkdir -p $tmp || framework_failure=1
+cd $tmp || framework_failure=1
+
+gen_supp=--gen-suppressions=all
+# This option makes valgrind significantly slower.
+full_leak_check=--leak-check=full
+
+vg_options="
+ --suppressions=$abs_srcdir/.vg-supp
+ --num-callers=25
+ --track-fds=yes
+ --demangle=no
+ $full_leak_check
+ $gen_supp
+ "
+# configure tests for the existence of valgrind.
+# If it's not available, then make $vg and vg_check no-ops.
+if test x$VALGRIND = x; then
+ vg=
+else
+ vg="libtool --mode=execute valgrind `echo $vg_options` --"
+fi
+
+vg_leak_check()
+{
+ local file=$1
+ local fail
+ # If we detect a leak, dump all output to stderr.
+ grep -E '^==[0-9]+== +definitely lost: [^0]' $file \
+ && { fail=1; cat $file 1>&2;
+ echo "found memory leaks (see log file, $file); see above" 1>&2; }
+ test "$fail" = ''
+}
+
+
+# Ensure 1) that there is an ERROR SUMMARY line, and
+# 2) that the number of errors is 0.
+# An offending line looks like this:
+# ==29302== ERROR SUMMARY: 4 errors from 2 contexts (suppressed: 16 from 5)
+vg_error_check()
+{
+ local file=$1
+ local fail
+ # If we detect a leak, dump all output to stderr.
+ grep -E '^==[0-9]+== ERROR SUMMARY:' $file > /dev/null \
+ || { fail=1; cat $file 1>&2;
+ echo "no valgrind ERROR SUMMARY line in $file" 1>&2; }
+ if test "$fail" = ''; then
+ grep -E '^==[0-9]+== ERROR SUMMARY: [^0] ' $file \
+ && { fail=1; cat $file 1>&2;
+ echo "valgrind reported errors in $file; see above" 1>&2; }
+ fi
+ test "$fail" = ''
+}
+
+vg_check()
+{
+ local file=$1
+ if test x$VALGRIND != x; then
+ vg_error_check $file && vg_leak_check $file
+ fi
+}