[farsight2/master] Add lcov stuff from core gstreamer

Olivier Crête olivier.crete at collabora.co.uk
Tue Dec 23 15:25:59 PST 2008


---
 .gitignore                               |    2 +
 Makefile.am                              |    2 +
 common/coverage/coverage-report-entry.pl |   70 +++++++++
 common/coverage/coverage-report.pl       |  125 ++++++++++++++++
 common/coverage/coverage-report.xsl      |  235 ++++++++++++++++++++++++++++++
 common/coverage/lcov.mak                 |   42 ++++++
 6 files changed, 476 insertions(+), 0 deletions(-)
 create mode 100644 common/coverage/coverage-report-entry.pl
 create mode 100644 common/coverage/coverage-report.pl
 create mode 100644 common/coverage/coverage-report.xsl
 create mode 100644 common/coverage/lcov.mak

diff --git a/.gitignore b/.gitignore
index e7be526..66af1a3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,8 @@ Makefile.in
 *#
 .#*
 *.stamp
+*.gcno
+*.gcda
 
 gst/fsrtpconference/fs-rtp-marshal.[ch]
 gst/fsrtpconference/fs-rtp-marshal.list
diff --git a/Makefile.am b/Makefile.am
index 7c734ee..3000385 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -59,3 +59,5 @@ DISTCLEANFILES = $(pcinfiles:.in=)
 dist-hook:
 	chmod u+w ${distdir}/ChangeLog
 	if test -d .git; then git log >${distdir}/ChangeLog; fi
+
+include $(top_srcdir)/common/coverage/lcov.mak
diff --git a/common/coverage/coverage-report-entry.pl b/common/coverage/coverage-report-entry.pl
new file mode 100644
index 0000000..8f653af
--- /dev/null
+++ b/common/coverage/coverage-report-entry.pl
@@ -0,0 +1,70 @@
+#!/usr/bin/perl
+#
+# Copyright (C) 2006 Daniel Berrange
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+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
diff --git a/common/coverage/coverage-report.pl b/common/coverage/coverage-report.pl
new file mode 100644
index 0000000..046bc37
--- /dev/null
+++ b/common/coverage/coverage-report.pl
@@ -0,0 +1,125 @@
+#!/usr/bin/perl
+#
+# Copyright (C) 2006 Daniel Berrange
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+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 "Shit [$_]\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);
+	$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";
diff --git a/common/coverage/coverage-report.xsl b/common/coverage/coverage-report.xsl
new file mode 100644
index 0000000..b19ebb6
--- /dev/null
+++ b/common/coverage/coverage-report.xsl
@@ -0,0 +1,235 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+#
+# Copyright (C) 2006 Daniel Berrange
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+-->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version="1.0">
+
+  <xsl:output method="html"/>
+
+  <xsl:template match="coverage">
+    <html>
+      <head>
+        <title>Coverage report</title>
+        <style type="text/css">
+          tbody tr.odd td.label {
+            border-top: 1px solid rgb(128,128,128);
+            border-bottom: 1px solid rgb(128,128,128);
+          }
+          tbody tr.odd td.label {
+            background: rgb(200,200,200);
+          }
+          
+          thead, tfoot {
+            background: rgb(60,60,60);
+            color: white;
+            font-weight: bold;
+          }
+
+          tr td.perfect {
+            background: rgb(0,255,0);
+            color: black;
+          }
+          tr td.excellant {
+            background: rgb(140,255,140);
+            color: black;
+          }
+          tr td.good {
+            background: rgb(160,255,0);
+            color: black;
+          }
+          tr td.poor {
+            background: rgb(255,160,0);
+            color: black;
+          }
+          tr td.bad {
+            background: rgb(255,140,140);
+            color: black;
+          }
+          tr td.terrible {
+            background: rgb(255,0,0);
+            color: black;
+          }
+        </style>
+      </head>
+      <body>
+        <h1>Coverage report</h1>
+        <xsl:apply-templates/>
+      </body>
+    </html>
+  </xsl:template>
+
+  <xsl:template match="functions">
+    <h2>Function coverage</h2>
+    <xsl:call-template name="content">
+      <xsl:with-param name="type" select="'function'"/>
+    </xsl:call-template>
+  </xsl:template>
+  
+
+  <xsl:template match="files">
+    <h2>File coverage</h2>
+    <xsl:call-template name="content">
+      <xsl:with-param name="type" select="'file'"/>
+    </xsl:call-template>
+  </xsl:template>
+
+  <xsl:template name="content">
+    <xsl:param name="type"/>
+    <table>
+      <thead>
+        <tr>
+          <th>Name</th>
+          <th>Lines</th>
+          <th>Branches</th>
+          <th>Conditions</th>
+          <th>Calls</th>
+        </tr>
+      </thead>
+      <tbody>
+        <xsl:for-each select="entry">
+          <xsl:call-template name="entry">
+            <xsl:with-param name="type" select="$type"/>
+            <xsl:with-param name="class">
+              <xsl:choose>
+                <xsl:when test="position() mod 2">
+                  <xsl:text>odd</xsl:text>
+                </xsl:when>
+                <xsl:otherwise>
+                  <xsl:text>even</xsl:text>
+                </xsl:otherwise>
+              </xsl:choose>
+            </xsl:with-param>
+          </xsl:call-template>
+        </xsl:for-each>
+      </tbody>
+      <tfoot>
+        <xsl:for-each select="summary">
+          <xsl:call-template name="entry">
+            <xsl:with-param name="type" select="'summary'"/>
+            <xsl:with-param name="class">
+              <xsl:choose>
+                <xsl:when test="position() mod 2">
+                  <xsl:text>odd</xsl:text>
+                </xsl:when>
+                <xsl:otherwise>
+                  <xsl:text>even</xsl:text>
+                </xsl:otherwise>
+              </xsl:choose>
+            </xsl:with-param>
+          </xsl:call-template>
+        </xsl:for-each>
+      </tfoot>
+    </table>
+  </xsl:template>
+  
+  <xsl:template name="entry">
+    <xsl:param name="type"/>
+    <xsl:param name="class"/>
+    <tr class="{$class}">
+      <xsl:choose>
+        <xsl:when test="$type = 'function'">
+          <td class="label"><a href="{@details}.html#{@name}"><xsl:value-of select="@name"/></a></td>
+        </xsl:when>
+        <xsl:when test="$type = 'file'">
+          <td class="label"><a href="{@details}.html"><xsl:value-of select="@name"/></a></td>
+        </xsl:when>
+        <xsl:otherwise>
+          <td class="label">Summary</td>
+        </xsl:otherwise>
+      </xsl:choose>
+
+      <xsl:if test="count(lines)">
+        <xsl:apply-templates select="lines"/>
+      </xsl:if>
+      <xsl:if test="not(count(lines))">
+        <xsl:call-template name="missing"/>
+      </xsl:if>
+
+      <xsl:if test="count(branches)">
+        <xsl:apply-templates select="branches"/>
+      </xsl:if>
+      <xsl:if test="not(count(branches))">
+        <xsl:call-template name="missing"/>
+      </xsl:if>
+
+      <xsl:if test="count(conditions)">
+        <xsl:apply-templates select="conditions"/>
+      </xsl:if>
+      <xsl:if test="not(count(conditions))">
+        <xsl:call-template name="missing"/>
+      </xsl:if>
+
+      <xsl:if test="count(calls)">
+        <xsl:apply-templates select="calls"/>
+      </xsl:if>
+      <xsl:if test="not(count(calls))">
+        <xsl:call-template name="missing"/>
+      </xsl:if>
+
+    </tr>
+  </xsl:template>
+  
+  <xsl:template match="lines">
+    <xsl:call-template name="row"/>
+  </xsl:template>
+
+  <xsl:template match="branches">
+    <xsl:call-template name="row"/>
+  </xsl:template>
+
+  <xsl:template match="conditions">
+    <xsl:call-template name="row"/>
+  </xsl:template>
+
+  <xsl:template match="calls">
+    <xsl:call-template name="row"/>
+  </xsl:template>
+
+  <xsl:template name="missing">
+    <td></td>
+  </xsl:template>
+
+  <xsl:template name="row">
+    <xsl:variable name="quality">
+      <xsl:choose>
+        <xsl:when test="@coverage = 100">
+          <xsl:text>perfect</xsl:text>
+        </xsl:when>
+        <xsl:when test="@coverage >= 80.0">
+          <xsl:text>excellant</xsl:text>
+        </xsl:when>
+        <xsl:when test="@coverage >= 60.0">
+          <xsl:text>good</xsl:text>
+        </xsl:when>
+        <xsl:when test="@coverage >= 40.0">
+          <xsl:text>poor</xsl:text>
+        </xsl:when>
+        <xsl:when test="@coverage >= 20.0">
+          <xsl:text>bad</xsl:text>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:text>terrible</xsl:text>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    
+    <td class="{$quality}"><xsl:value-of select="@coverage"/>% of <xsl:value-of select="@count"/></td>
+  </xsl:template>
+
+</xsl:stylesheet>
diff --git a/common/coverage/lcov.mak b/common/coverage/lcov.mak
new file mode 100644
index 0000000..0ca9456
--- /dev/null
+++ b/common/coverage/lcov.mak
@@ -0,0 +1,42 @@
+## .PHONY so it always rebuilds it
+.PHONY: lcov-reset lcov lcov-run lcov-report lcov-upload
+
+# run lcov from scratch, always
+lcov-reset:
+	$(MAKE) lcov-run
+	$(MAKE) lcov-report
+
+# run lcov from scratch if the dir is not there
+lcov:
+	$(MAKE) lcov-reset
+
+if GST_GCOV_ENABLED
+# reset run coverage tests
+lcov-run:
+	@-rm -rf lcov
+	lcov --directory . --zerocounters
+	-if test -d tests/check; then $(MAKE) -C tests/check inspect; fi
+	-$(MAKE) check
+
+# generate report based on current coverage data
+lcov-report:
+	mkdir lcov
+	lcov --compat-libtool --directory . --capture --output-file lcov/lcov.info
+	lcov -l lcov/lcov.info | grep -v "`cd $(top_srcdir) && pwd`" | cut -d: -f1 > lcov/remove
+	lcov -l lcov/lcov.info | grep "tests/check/" | cut -d: -f1 >> lcov/remove
+	lcov -r lcov/lcov.info `cat lcov/remove` > lcov/lcov.cleaned.info
+	rm lcov/remove
+	mv lcov/lcov.cleaned.info lcov/lcov.info
+	genhtml -t "$(PACKAGE_STRING)" -o lcov --num-spaces 2 lcov/lcov.info
+
+lcov-upload: lcov
+	rsync -rvz -e ssh --delete lcov/* gstreamer.freedesktop.org:/srv/gstreamer.freedesktop.org/www/data/coverage/lcov/$(PACKAGE)
+
+else
+lcov-run:
+	echo "Need to reconfigure with --enable-gcov"
+
+lcov-report:
+	echo "Need to reconfigure with --enable-gcov"
+endif
+
-- 
1.5.6.5




More information about the farsight-commits mailing list