Skip to content

Commit

Permalink
Added code coverage testing enabled via --enable-test-coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
berrange committed Feb 14, 2007
1 parent 23ad665 commit 26ceeb4
Show file tree
Hide file tree
Showing 13 changed files with 527 additions and 14 deletions.
13 changes: 13 additions & 0 deletions ChangeLog
@@ -1,3 +1,16 @@
Tue Feb 13 19:46:35 EST 2007 Daniel Berrange <berrange@redhat.com>

* autobuild.sh: Run coverage tests during automated build
* autogen.sh: Point aclocal at m4 directory explicitly
* configure.in: Added command line arg to enable coverage
* Makefile.am: Added scripts directory
* src/Makefile.am: Build with coverage testing if requested
and add target for extracting coverage data
* scripts/*: Helper tools for coverage testing
* tests/Makefile.am: Make tests link to object files instad
of the static library to ensure single output dest for
coverage data when running tests

Tue Feb 13 19:29:35 EST 2007 Daniel Berrange <berrange@redhat.com>

* src/qemu_internal.h, src/qemu_internal.c, src/Makefile.am,
Expand Down
23 changes: 21 additions & 2 deletions Makefile.am
@@ -1,6 +1,6 @@
## Process this file with automake to produce Makefile.in

SUBDIRS = src qemud proxy include docs @PYTHON_SUBDIR@ tests po
SUBDIRS = src qemud proxy include docs @PYTHON_SUBDIR@ tests po scripts

ACLOCAL_AMFLAGS = -I m4

Expand All @@ -21,4 +21,23 @@ check-local: all tests
tests:
@(cd docs/examples ; $(MAKE) MAKEFLAGS+=--silent tests)
@(if [ "@PYTHON_SUBDIR@" != "" ] ; then cd python ; \
$(MAKE) MAKEFLAGS+=--silent tests ; fi)
$(MAKE) MAKEFLAGS+=--silent tests ; fi)

cov: cov-recursive cov-am

clean-cov:
rm -rf $(top_builddir)/coverage
cd src && $(MAKE) $(AM_MAKEFLAGS) clean-cov

cov-recursive:
cd src && $(MAKE) $(AM_MAKEFLAGS) cov

cov-am:
rm -rf $(top_builddir)/coverage
mkdir $(top_builddir)/coverage
perl $(srcdir)/scripts/coverage-report.pl src/*.cov > $(top_builddir)/coverage/index.xml
xsltproc $(srcdir)/scripts/coverage-report.xsl \
$(top_builddir)/coverage/index.xml \
> $(top_builddir)/coverage/index.html
for i in $(top_builddir)/src/*.gcov ; do o=`echo $$i | sed -e 's,$(top_builddir)/src,coverage,'` ; \
perl $(srcdir)/scripts/coverage-report-entry.pl $$i > $$o.html ; done
9 changes: 5 additions & 4 deletions autobuild.sh
@@ -1,25 +1,26 @@
#!/bin/sh

set -e
set -v

# Make things clean.

test -n "$1" && RESULTS="$1" || RESULTS="results.log"

test -f Makefile && make -k distclean || :
rm -rf MANIFEST blib
rm -rf coverage

#rm -rf build
#mkdir build
#cd build

./autogen.sh --prefix=$AUTOBUILD_INSTALL_ROOT
./autogen.sh --prefix=$AUTOBUILD_INSTALL_ROOT --enable-test-coverage

make
make install

make check 1>$RESULTS 2>&1
#make cov
make check 2>&1 | tee $RESULTS
make cov

rm -f *.tar.gz
make dist
Expand Down
2 changes: 1 addition & 1 deletion autogen.sh
Expand Up @@ -57,7 +57,7 @@ fi
autopoint --force
#rm -rf m4
libtoolize --copy --force
aclocal $ACLOCAL_FLAGS
aclocal -I m4
automake --add-missing
autoconf

Expand Down
19 changes: 18 additions & 1 deletion configure.in
Expand Up @@ -268,6 +268,23 @@ AC_MSG_RESULT($RUNNING_XEND)

AM_CONDITIONAL(ENABLE_XEN_TESTS, [test "$RUNNING_XEN" != "no" -a "$RUNNING_XEND" != "no"])

AC_ARG_ENABLE(test-coverage,
[ --enable-test-coverage turn on code coverage instrumentation],
[case "${enableval}" in
yes|no) ;;
*) AC_MSG_ERROR([bad value ${enableval} for test-coverage option]) ;;
esac],
[enableval=no])

if test "${enableval}" = yes; then
gl_COMPILER_FLAGS(-fprofile-arcs)
gl_COMPILER_FLAGS(-ftest-coverage)
AC_SUBST([COVERAGE_CFLAGS], [$COMPILER_FLAGS])
AC_SUBST([COVERAGE_LDFLAGS], [$COMPILER_FLAGS])
COMPILER_FLAGS=
fi


AM_GNU_GETTEXT_VERSION([0.14.1])
AM_GNU_GETTEXT([external])
if test -d po
Expand All @@ -285,7 +302,7 @@ AC_OUTPUT(Makefile src/Makefile include/Makefile docs/Makefile \
docs/examples/Makefile docs/devhelp/Makefile \
docs/examples/python/Makefile \
libvirt.pc libvirt.spec \
po/Makefile.in \
po/Makefile.in scripts/Makefile \
include/libvirt/Makefile include/libvirt/libvirt.h \
python/Makefile python/tests/Makefile \
qemud/Makefile \
Expand Down
2 changes: 2 additions & 0 deletions scripts/.cvsignore
@@ -0,0 +1,2 @@
Makefile
Makefile.in
4 changes: 4 additions & 0 deletions scripts/Makefile.am
@@ -0,0 +1,4 @@

EXTRA_DIST = coverage-report.pl \
coverage-report-entry.pl \
coverage-report.xsl
3 changes: 3 additions & 0 deletions scripts/README
@@ -0,0 +1,3 @@
This directory provides a collection of tools used in the
build / test process. They are not installed / used after
deployment.
77 changes: 77 additions & 0 deletions scripts/coverage-report-entry.pl
@@ -0,0 +1,77 @@
#!/usr/bin/perl
#
# Copyright (C) 2006-2007 Daniel P. Berrange
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Author: Daniel P. Berrange <berrange@redhat.com>
#
# coverage-report-entry.pl: convert gcov annotated source into HTML
#
# This script takes a gcov annotated source code files on STDIN
# converts it to HTML, coloured according to coverage, and sends
# it to STDOUT

print <<EOF;
<html>
<head>
<title>Coverage report for $ARGV[0]</title>
<style type="text/css">
span.perfect {
background: rgb(0,255,0);
}
span.terrible {
background: rgb(255,0,0);
}
</style>
</head>
<body>
<h1>Coverage report for $ARGV[0]</h1>
<pre>
EOF


while (<>) {
s/&/&amp;/g;
s/</&lt;/g;
s/>/&gt;/g;

if (/^\s*function (\S+) called (\d+) returned \d+% blocks executed \d+%/) {
my $class = $2 > 0 ? "perfect" : "terrible";
$_ = "<span class=\"$class\" id=\"" . $1 . "\">$_</span>";
} elsif (/^\s*branch\s+\d+\s+taken\s+(\d+)%\s+.*$/) {
my $class = $1 > 0 ? "perfect" : "terrible";
$_ = "<span class=\"$class\">$_</span>";
} elsif (/^\s*branch\s+\d+\s+never executed.*$/) {
my $class = "terrible";
$_ = "<span class=\"$class\">$_</span>";
} elsif (/^\s*call\s+\d+\s+never executed.*$/) {
my $class = "terrible";
$_ = "<span class=\"$class\">$_</span>";
} elsif (/^\s*call\s+\d+\s+returned\s+(\d+)%.*$/) {
my $class = $1 > 0 ? "perfect" : "terrible";
$_ = "<span class=\"$class\">$_</span>";
}


print;
}

print <<EOF;
</pre>
</body>
</html>
EOF
137 changes: 137 additions & 0 deletions scripts/coverage-report.pl
@@ -0,0 +1,137 @@
#!/usr/bin/perl
#
# Copyright (C) 2006-2007 Daniel P. Berrange
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Author: Daniel P. Berrange <berrange@redhat.com>
#
# coverage-report.pl: generate XML coverage summary report
#
# This script takes a listof gcov .cov files as args, and generates
# an XML document summarizing the coverage per function and per
# source file.

use warnings;
use strict;

my %coverage = ( functions => {}, files => {} );

my %filemap;

my $type;
my $name;

my @functions;

while (<>) {
if (/^Function '(.*)'\s*$/) {
$type = "function";
$name = $1;
$coverage{$type}->{$name} = {};
push @functions, $name;
} elsif (/^File '(.*?)'\s*$/) {
$type = "file";
$name = $1;
$coverage{$type}->{$name} = {};

foreach my $func (@functions) {
$coverage{"function"}->{$func}->{file} = $name;
}
@functions = ();
} elsif (/^Lines executed:(.*)%\s*of\s*(\d+)\s*$/) {
$coverage{$type}->{$name}->{lines} = $2;
$coverage{$type}->{$name}->{linesCoverage} = $1;
} elsif (/^Branches executed:(.*)%\s*of\s*(\d+)\s*$/) {
$coverage{$type}->{$name}->{branches} = $2;
$coverage{$type}->{$name}->{branchesCoverage} = $1;
} elsif (/^Taken at least once:(.*)%\s*of\s*(\d+)\s*$/) {
$coverage{$type}->{$name}->{conds} = $2;
$coverage{$type}->{$name}->{condsCoverage} = $1;
} elsif (/^Calls executed:(.*)%\s*of\s*(\d+)\s*$/) {
$coverage{$type}->{$name}->{calls} = $2;
$coverage{$type}->{$name}->{callsCoverage} = $1;
} elsif (/^No branches$/) {
$coverage{$type}->{$name}->{branches} = 0;
$coverage{$type}->{$name}->{branchesCoverage} = "100.00";
$coverage{$type}->{$name}->{conds} = 0;
$coverage{$type}->{$name}->{condsCoverage} = "100.00";
} elsif (/^No calls$/) {
$coverage{$type}->{$name}->{calls} = 0;
$coverage{$type}->{$name}->{callsCoverage} = "100.00";
} elsif (/^\s*(.*):creating '(.*)'\s*$/) {
$filemap{$1} = $2;
} elsif (/^\s*$/) {
# nada
} else {
warn "unexpected input [$_]\n";
}
}

my %summary;
foreach my $type ("function", "file") {
$summary{$type} = {};
foreach my $m ("lines", "branches", "conds", "calls") {
my $totalGot = 0;
my $totalMiss = 0;
my $count = 0;
foreach my $func (keys %{$coverage{function}}) {
$count++;
my $got = $coverage{function}->{$func}->{$m};
$totalGot += $got;
my $miss = $got * $coverage{function}->{$func}->{$m ."Coverage"} / 100;
$totalMiss += $miss;
}
$summary{$type}->{$m} = sprintf("%d", $totalGot);
if ($totalGot == 0) {
$summary{$type}->{$m . "Coverage"} = "100.00";
} else {
$summary{$type}->{$m . "Coverage"} = sprintf("%.2f", $totalMiss / $totalGot * 100);
}
}
}



print "<coverage>\n";

foreach my $type ("function", "file") {
printf "<%ss>\n", $type;
foreach my $name (sort { $a cmp $b } keys %{$coverage{$type}}) {
my $rec = $coverage{$type}->{$name};
printf " <entry name=\"%s\" details=\"%s\">\n", $name, ($type eq "file" ? $filemap{$name} : $filemap{$rec->{file}});
printf " <lines count=\"%s\" coverage=\"%s\"/>\n", $rec->{lines}, $rec->{linesCoverage};
if (exists $rec->{branches}) {
printf " <branches count=\"%s\" coverage=\"%s\"/>\n", $rec->{branches}, $rec->{branchesCoverage};
}
if (exists $rec->{conds}) {
printf " <conditions count=\"%s\" coverage=\"%s\"/>\n", $rec->{conds}, $rec->{condsCoverage};
}
if (exists $rec->{calls}) {
printf " <calls count=\"%s\" coverage=\"%s\"/>\n", $rec->{calls}, $rec->{callsCoverage};
}
print " </entry>\n";
}

printf " <summary>\n";
printf " <lines count=\"%s\" coverage=\"%s\"/>\n", $summary{$type}->{lines}, $summary{$type}->{linesCoverage};
printf " <branches count=\"%s\" coverage=\"%s\"/>\n", $summary{$type}->{branches}, $summary{$type}->{branchesCoverage};
printf " <conditions count=\"%s\" coverage=\"%s\"/>\n", $summary{$type}->{conds}, $summary{$type}->{condsCoverage};
printf " <calls count=\"%s\" coverage=\"%s\"/>\n", $summary{$type}->{calls}, $summary{$type}->{callsCoverage};
printf " </summary>\n";
printf "</%ss>\n", $type;
}

print "</coverage>\n";

0 comments on commit 26ceeb4

Please sign in to comment.