mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-02-03 13:21:32 +02:00
Automate coverage summary report generation.
This report replaces the lcov report that was generated manually for each release. The lcov report was overly verbose just to say that we have virtually 100% coverage.
This commit is contained in:
parent
5bba72b874
commit
5c1d4bcd0d
@ -1,81 +1,3 @@
|
||||
# Release Build Instructions
|
||||
|
||||
## Generate Coverage Report
|
||||
|
||||
These instructions are temporary until a fully automated report is implemented.
|
||||
|
||||
- In `test/src/lcov.conf` remove:
|
||||
```
|
||||
# Specify the regular expression of lines to exclude
|
||||
lcov_excl_line=lcov_excl_line=\{\+{0,1}uncovered[^_]|\{\+{0,1}uncoverable[^_]
|
||||
|
||||
# Coverage rate limits
|
||||
genhtml_hi_limit = 100
|
||||
genhtml_med_limit = 90
|
||||
```
|
||||
|
||||
And change `uncover(ed|able)_branch` to `uncoverable_branch`.
|
||||
|
||||
- In `test/lib/pgBackRestTest/Common/JobTest.pm` modify:
|
||||
```
|
||||
if (!$bTest || $iTotalLines != $iCoveredLines || $iTotalBranches != $iCoveredBranches)
|
||||
```
|
||||
to:
|
||||
```
|
||||
if (!$bTest)
|
||||
```
|
||||
|
||||
- Run:
|
||||
```
|
||||
/backrest/test/test.pl --dev-test --vm=u18 --c-only
|
||||
```
|
||||
|
||||
- Copy coverage report:
|
||||
```
|
||||
cd <pgbackrest-base>/doc/site
|
||||
rm -rf coverage
|
||||
cp -r ../../test/coverage/c coverage
|
||||
```
|
||||
|
||||
- In `doc/site/coverage` replace:
|
||||
```
|
||||
<title>LCOV - all.lcov</title>
|
||||
```
|
||||
with:
|
||||
```
|
||||
<title>pgBackRest vX.XX C Code Coverage</title>
|
||||
```
|
||||
|
||||
- In `doc/site/coverage` replace:
|
||||
```
|
||||
<tr><td class="title">LCOV - code coverage report</td></tr>
|
||||
```
|
||||
with:
|
||||
```
|
||||
<tr><td class="title">pgBackRest vX.XX C Code Coverage</td></tr>
|
||||
```
|
||||
|
||||
- In `doc/site/coverage` replace:
|
||||
```
|
||||
<title>LCOV - all.lcov -
|
||||
```
|
||||
with:
|
||||
```
|
||||
<title>pgBackRest vX.XX C Code Coverage -
|
||||
```
|
||||
|
||||
- In `doc/site/coverage` replace:
|
||||
```
|
||||
<td class="headerValue">all.lcov</td>
|
||||
```
|
||||
with:
|
||||
```
|
||||
<td class="headerValue">all C unit</td>
|
||||
```
|
||||
|
||||
- Switch to prior dir and copy coverage:
|
||||
```
|
||||
cd prior/X.XX
|
||||
rm -rf coverage
|
||||
cp -r ../../coverage .
|
||||
```
|
||||
## Run `doc/release.pl`
|
||||
|
@ -433,7 +433,7 @@ sub sectionProcess
|
||||
|
||||
$oHeaderRowElement->addNew(
|
||||
HTML_TH,
|
||||
"table-header-${strAlign}" . ($bFill ? ",table-header-fill" : ""),
|
||||
"table-header-${strAlign}" . ($bFill ? " table-header-fill" : ""),
|
||||
{strContent => $self->processText($oColumn->textGet())});
|
||||
}
|
||||
}
|
||||
|
@ -84,6 +84,7 @@
|
||||
<source key="user-guide"/>
|
||||
<source key="reference" type="custom"/>
|
||||
<source key="release" type="custom"/>
|
||||
<source key="metric"/>
|
||||
<source key="coding"/>
|
||||
<source key="documentation"/>
|
||||
<source key="test"/>
|
||||
@ -96,6 +97,7 @@
|
||||
<render-source key="release" menu="Releases"/>
|
||||
<render-source key="configuration" source="reference" menu="Configuration"/>
|
||||
<render-source key="command" source="reference" menu="Commands"/>
|
||||
<render-source key="metric" menu="Metrics"/>
|
||||
</render>
|
||||
|
||||
<render type="pdf" file="{[pdf-file]}">
|
||||
|
@ -62,6 +62,7 @@ release.pl [options]
|
||||
Release Options:
|
||||
--build Build the cache before release (should be included in the release commit)
|
||||
--deploy Deploy documentation to website (can be done as docs are updated)
|
||||
--no-coverage Don't generate the coverage report
|
||||
=cut
|
||||
|
||||
####################################################################################################################################
|
||||
@ -73,13 +74,15 @@ my $bQuiet = false;
|
||||
my $strLogLevel = 'info';
|
||||
my $bBuild = false;
|
||||
my $bDeploy = false;
|
||||
my $bNoCoverage = false;
|
||||
|
||||
GetOptions ('help' => \$bHelp,
|
||||
'version' => \$bVersion,
|
||||
'quiet' => \$bQuiet,
|
||||
'log-level=s' => \$strLogLevel,
|
||||
'build' => \$bBuild,
|
||||
'deploy' => \$bDeploy)
|
||||
'deploy' => \$bDeploy,
|
||||
'no-coverage' => \$bNoCoverage)
|
||||
or pod2usage(2);
|
||||
|
||||
####################################################################################################################################
|
||||
@ -119,6 +122,7 @@ eval
|
||||
my $strDocPath = dirname(abs_path($0));
|
||||
my $strDocHtml = "${strDocPath}/output/html";
|
||||
my $strDocExe = "${strDocPath}/doc.pl";
|
||||
my $strTestExe = dirname($strDocPath) . "/test/test.pl";
|
||||
|
||||
my $oStorageDoc = new pgBackRest::Storage::Local(
|
||||
$strDocPath, new pgBackRest::Storage::Posix::Driver({bFileSync => false, bPathSync => false}));
|
||||
@ -135,6 +139,15 @@ eval
|
||||
# Remove all docker containers to get consistent IP address assignments
|
||||
executeTest('docker rm -f $(docker ps -a -q)', {bSuppressError => true});
|
||||
|
||||
# Generate coverage summmary
|
||||
if (!$bNoCoverage)
|
||||
{
|
||||
&log(INFO, "Generate Coverage Summary");
|
||||
executeTest(
|
||||
"${strTestExe} --no-lint --no-package --no-valgrind --no-optimize --vm-max=3 --coverage-summary",
|
||||
{bShowOutputAsync => true});
|
||||
}
|
||||
|
||||
# Generate deployment docs for RHEL/Centos 7
|
||||
&log(INFO, "Generate RHEL/CentOS 7 documentation");
|
||||
|
||||
|
@ -304,6 +304,7 @@ Table Elements
|
||||
.table
|
||||
{
|
||||
margin-top: .5em;
|
||||
border-spacing: .5em 0;
|
||||
}
|
||||
|
||||
.table-caption
|
||||
@ -318,6 +319,14 @@ Table Elements
|
||||
{
|
||||
}
|
||||
|
||||
.table-header-left,
|
||||
.table-header-center,
|
||||
.table-header-right
|
||||
{
|
||||
white-space: nowrap;
|
||||
border-bottom: 1px black solid;
|
||||
}
|
||||
|
||||
.table-header-left
|
||||
{
|
||||
text-align: left;
|
||||
@ -342,8 +351,16 @@ Table Elements
|
||||
{
|
||||
}
|
||||
|
||||
.table-data-left,
|
||||
.table-data-center,
|
||||
.table-data-right
|
||||
{
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.table-data-left
|
||||
{
|
||||
padding-top: 0px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
|
209
doc/xml/auto/metric-coverage-report.auto.xml
Normal file
209
doc/xml/auto/metric-coverage-report.auto.xml
Normal file
@ -0,0 +1,209 @@
|
||||
<table-row>
|
||||
<table-cell>command</table-cell>
|
||||
<table-cell>3/3 (100.0%)</table-cell>
|
||||
<table-cell>46/46 (100.0%)</table-cell>
|
||||
<table-cell>82/82 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>command/archive</table-cell>
|
||||
<table-cell>10/10 (100.0%)</table-cell>
|
||||
<table-cell>56/56 (100.0%)</table-cell>
|
||||
<table-cell>176/176 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>command/archive/get</table-cell>
|
||||
<table-cell>6/6 (100.0%)</table-cell>
|
||||
<table-cell>86/86 (100.0%)</table-cell>
|
||||
<table-cell>212/212 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>command/archive/push</table-cell>
|
||||
<table-cell>9/9 (100.0%)</table-cell>
|
||||
<table-cell>86/86 (100.0%)</table-cell>
|
||||
<table-cell>263/263 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>command/backup</table-cell>
|
||||
<table-cell>1/1 (100.0%)</table-cell>
|
||||
<table-cell>14/14 (100.0%)</table-cell>
|
||||
<table-cell>23/23 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>command/control</table-cell>
|
||||
<table-cell>2/2 (100.0%)</table-cell>
|
||||
<table-cell>8/8 (100.0%)</table-cell>
|
||||
<table-cell>17/17 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>command/help</table-cell>
|
||||
<table-cell>4/4 (100.0%)</table-cell>
|
||||
<table-cell>110/110 (100.0%)</table-cell>
|
||||
<table-cell>163/163 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>command/info</table-cell>
|
||||
<table-cell>7/7 (100.0%)</table-cell>
|
||||
<table-cell>104/104 (100.0%)</table-cell>
|
||||
<table-cell>259/259 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>command/local</table-cell>
|
||||
<table-cell>1/1 (100.0%)</table-cell>
|
||||
<table-cell>---</table-cell>
|
||||
<table-cell>15/15 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>command/remote</table-cell>
|
||||
<table-cell>1/1 (100.0%)</table-cell>
|
||||
<table-cell>6/6 (100.0%)</table-cell>
|
||||
<table-cell>27/27 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>common</table-cell>
|
||||
<table-cell>129/129 (100.0%)</table-cell>
|
||||
<table-cell>444/444 (100.0%)</table-cell>
|
||||
<table-cell>1375/1375 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>common/compress/gzip</table-cell>
|
||||
<table-cell>14/14 (100.0%)</table-cell>
|
||||
<table-cell>22/22 (100.0%)</table-cell>
|
||||
<table-cell>158/158 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>common/crypto</table-cell>
|
||||
<table-cell>23/23 (100.0%)</table-cell>
|
||||
<table-cell>68/68 (100.0%)</table-cell>
|
||||
<table-cell>310/310 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>common/encode</table-cell>
|
||||
<table-cell>5/5 (100.0%)</table-cell>
|
||||
<table-cell>32/32 (100.0%)</table-cell>
|
||||
<table-cell>81/81 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>common/io</table-cell>
|
||||
<table-cell>45/45 (100.0%)</table-cell>
|
||||
<table-cell>108/108 (100.0%)</table-cell>
|
||||
<table-cell>498/498 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>common/io/filter</table-cell>
|
||||
<table-cell>32/32 (100.0%)</table-cell>
|
||||
<table-cell>80/80 (100.0%)</table-cell>
|
||||
<table-cell>329/329 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>common/io/http</table-cell>
|
||||
<table-cell>29/29 (100.0%)</table-cell>
|
||||
<table-cell>146/146 (100.0%)</table-cell>
|
||||
<table-cell>388/388 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>common/io/tls</table-cell>
|
||||
<table-cell>13/13 (100.0%)</table-cell>
|
||||
<table-cell>74/74 (100.0%)</table-cell>
|
||||
<table-cell>228/228 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>common/type</table-cell>
|
||||
<table-cell>227/227 (100.0%)</table-cell>
|
||||
<table-cell>490/490 (100.0%)</table-cell>
|
||||
<table-cell>2693/2693 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>config</table-cell>
|
||||
<table-cell>97/97 (100.0%)</table-cell>
|
||||
<table-cell>536/536 (100.0%)</table-cell>
|
||||
<table-cell>1379/1379 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>info</table-cell>
|
||||
<table-cell>33/33 (100.0%)</table-cell>
|
||||
<table-cell>94/94 (100.0%)</table-cell>
|
||||
<table-cell>484/484 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>perl</table-cell>
|
||||
<table-cell>10/10 (100.0%)</table-cell>
|
||||
<table-cell>26/26 (100.0%)</table-cell>
|
||||
<table-cell>138/138 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>postgres</table-cell>
|
||||
<table-cell>14/14 (100.0%)</table-cell>
|
||||
<table-cell>64/64 (100.0%)</table-cell>
|
||||
<table-cell>184/184 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>protocol</table-cell>
|
||||
<table-cell>59/59 (100.0%)</table-cell>
|
||||
<table-cell>136/136 (100.0%)</table-cell>
|
||||
<table-cell>712/712 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>storage</table-cell>
|
||||
<table-cell>59/59 (100.0%)</table-cell>
|
||||
<table-cell>138/138 (100.0%)</table-cell>
|
||||
<table-cell>668/668 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>storage/cifs</table-cell>
|
||||
<table-cell>1/1 (100.0%)</table-cell>
|
||||
<table-cell>---</table-cell>
|
||||
<table-cell>9/9 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>storage/posix</table-cell>
|
||||
<table-cell>31/31 (100.0%)</table-cell>
|
||||
<table-cell>181/182 (99.45%)</table-cell>
|
||||
<table-cell>536/536 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>storage/remote</table-cell>
|
||||
<table-cell>22/22 (100.0%)</table-cell>
|
||||
<table-cell>46/46 (100.0%)</table-cell>
|
||||
<table-cell>387/387 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>storage/s3</table-cell>
|
||||
<table-cell>23/23 (100.0%)</table-cell>
|
||||
<table-cell>96/96 (100.0%)</table-cell>
|
||||
<table-cell>487/487 (100.0%)</table-cell>
|
||||
</table-row>
|
||||
|
||||
<table-row>
|
||||
<table-cell>TOTAL</table-cell>
|
||||
<table-cell>910/910 (100.0%)</table-cell>
|
||||
<table-cell>3297/3298 (99.97%)</table-cell>
|
||||
<table-cell>12281/12281 (100.0%)</table-cell>
|
||||
</table-row>
|
30
doc/xml/metric.xml
Normal file
30
doc/xml/metric.xml
Normal file
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE doc SYSTEM "doc.dtd" [<!ENTITY metricCoverageReport SYSTEM "auto/metric-coverage-report.auto.xml">]>
|
||||
<doc title="{[project]}" subtitle="Metrics">
|
||||
<description>!!!</description>
|
||||
|
||||
<section id="code-coverage">
|
||||
<title>Code Coverage</title>
|
||||
|
||||
<p><backrest/> aims to have complete function/branch/line coverage for the core C code in <path>/src</path>.</p>
|
||||
|
||||
<p>Function/line coverage is complete with no exceptions.</p>
|
||||
|
||||
<p>Branch coverage excludes branches inside macros and <code>assert()</code> calls. Macros have their own unit tests so they do not need to be tested everywhere they appear. Asserts are not expected to have complete branch coverage since they test cases that should always be true.</p>
|
||||
|
||||
<table>
|
||||
<table-header>
|
||||
<table-column fill="y">Directory</table-column>
|
||||
<table-column align="right">Functions</table-column>
|
||||
<table-column align="right">Branches</table-column>
|
||||
<table-column align="right">Lines</table-column>
|
||||
</table-header>
|
||||
|
||||
<table-data>
|
||||
&metricCoverageReport;
|
||||
</table-data>
|
||||
</table>
|
||||
|
||||
<p>The C unit test modules in <path>/test/src/module</path> also have complete function/line coverage but are not included in the report.</p>
|
||||
</section>
|
||||
</doc>
|
@ -185,6 +185,14 @@
|
||||
</release-development-list>
|
||||
</release-core-list>
|
||||
|
||||
<release-doc-list>
|
||||
<release-development-list>
|
||||
<release-item>
|
||||
<p>Automate coverage summary report generation.</p>
|
||||
</release-item>
|
||||
</release-development-list>
|
||||
</release-doc-list>
|
||||
|
||||
<release-test-list>
|
||||
<release-development-list>
|
||||
<release-item>
|
||||
|
@ -13,6 +13,7 @@ use English '-no_match_vars';
|
||||
|
||||
use Exporter qw(import);
|
||||
our @EXPORT = qw();
|
||||
use File::Basename qw(dirname);
|
||||
|
||||
use pgBackRest::Common::Log;
|
||||
use pgBackRest::Common::String;
|
||||
@ -21,6 +22,50 @@ use pgBackRest::Version;
|
||||
use BackRestDoc::Html::DocHtmlBuilder;
|
||||
use BackRestDoc::Html::DocHtmlElement;
|
||||
|
||||
####################################################################################################################################
|
||||
# Generate an lcov configuration file
|
||||
####################################################################################################################################
|
||||
sub coverageLCovConfigGenerate
|
||||
{
|
||||
my $oStorage = shift;
|
||||
my $strOutFile = shift;
|
||||
my $bCoverageSummary = shift;
|
||||
|
||||
my $strBranchFilter =
|
||||
'OBJECT_DEFINE_[A-Z0-9_]+\(|\s{4}[A-Z][A-Z0-9_]+\([^\?]*\)|\s{4}(ASSERT|assert|switch\s)\(|\{\+{0,1}' .
|
||||
($bCoverageSummary ? 'uncoverable_branch' : 'uncover(ed|able)_branch');
|
||||
my $strLineFilter = '\{\+{0,1}uncover' . ($bCoverageSummary ? 'able' : '(ed|able)') . '[^_]';
|
||||
|
||||
my $strConfig =
|
||||
"# LCOV Settings\n" .
|
||||
"\n" .
|
||||
"# Specify if branch coverage data should be collected and processed\n" .
|
||||
"lcov_branch_coverage=1\n" .
|
||||
"\n" .
|
||||
"# Specify the regular expression of lines to exclude from branch coverage\n" .
|
||||
"#\n" .
|
||||
'# OBJECT_DEFINE_[A-Z0-9_]+\( - exclude object definitions' . "\n" .
|
||||
'# \s{4}[A-Z][A-Z0-9_]+\([^\?]*\) - exclude macros that do not take a conditional parameter and are not themselves a parameter' . "\n" .
|
||||
'# ASSERT/(|assert\( - exclude asserts since it usually not possible to trigger both branches' . "\n" .
|
||||
'# switch \( - lcov requires default: to show complete coverage but --Wswitch-enum enforces all enum values be present' . "\n" .
|
||||
"lcov_excl_br_line=${strBranchFilter}\n" .
|
||||
"\n" .
|
||||
"# Specify the regular expression of lines to exclude\n" .
|
||||
"lcov_excl_line=${strLineFilter}\n" .
|
||||
"\n" .
|
||||
"# Coverage rate limits\n" .
|
||||
"genhtml_hi_limit = 100\n" .
|
||||
"genhtml_med_limit = 90\n" .
|
||||
"\n" .
|
||||
"# Width of line coverage field in source code view\n" .
|
||||
"genhtml_line_field_width = 9\n";
|
||||
|
||||
# Write configuration file
|
||||
$oStorage->put($strOutFile, $strConfig);
|
||||
}
|
||||
|
||||
push @EXPORT, qw(coverageLCovConfigGenerate);
|
||||
|
||||
####################################################################################################################################
|
||||
# Generate a C coverage report
|
||||
####################################################################################################################################
|
||||
@ -480,4 +525,132 @@ sub coverageGenerate
|
||||
|
||||
push @EXPORT, qw(coverageGenerate);
|
||||
|
||||
####################################################################################################################################
|
||||
# Generate a C coverage summary for the documentation
|
||||
####################################################################################################################################
|
||||
sub coverageDocSummaryGenerateValue
|
||||
{
|
||||
my $iHit = shift;
|
||||
my $iFound = shift;
|
||||
|
||||
if (!defined($iFound) || !defined($iHit) || $iFound == 0)
|
||||
{
|
||||
return "---";
|
||||
}
|
||||
|
||||
my $fPercent = $iHit * 100 / $iFound;
|
||||
my $strPercent;
|
||||
|
||||
if ($fPercent == 100)
|
||||
{
|
||||
$strPercent = '100.0';
|
||||
}
|
||||
elsif ($fPercent > 99.99)
|
||||
{
|
||||
$strPercent = '99.99';
|
||||
}
|
||||
else
|
||||
{
|
||||
$strPercent = sprintf("%.2f", $fPercent);
|
||||
}
|
||||
|
||||
return "${iHit}/${iFound} (${strPercent}%)";
|
||||
}
|
||||
|
||||
sub coverageDocSummaryGenerate
|
||||
{
|
||||
my $oStorage = shift;
|
||||
my $strCoveragePath = shift;
|
||||
my $strOutFile = shift;
|
||||
|
||||
# Track coverage summary
|
||||
my $rhSummary;
|
||||
|
||||
# Find all lcov files in the coverage path
|
||||
my $rhManifest = $oStorage->manifest($strCoveragePath);
|
||||
|
||||
foreach my $strFileCov (sort(keys(%{$rhManifest})))
|
||||
{
|
||||
next if $strFileCov =~ /^test\//;
|
||||
|
||||
if ($strFileCov =~ /\.lcov$/)
|
||||
{
|
||||
my $strCoverage = ${$oStorage->get("${strCoveragePath}/${strFileCov}")};
|
||||
my $strModule = dirname($strFileCov);
|
||||
|
||||
foreach my $strLine (split("\n", $strCoverage))
|
||||
{
|
||||
# Get Line Coverage
|
||||
if ($strLine =~ /^LF\:/)
|
||||
{
|
||||
$rhSummary->{$strModule}{line}{found} += substr($strLine, 3) + 0;
|
||||
$rhSummary->{zzztotal}{line}{found} += substr($strLine, 3) + 0;
|
||||
}
|
||||
|
||||
if ($strLine =~ /^LH\:/)
|
||||
{
|
||||
$rhSummary->{$strModule}{line}{hit} += substr($strLine, 3) + 0;
|
||||
$rhSummary->{zzztotal}{line}{hit} += substr($strLine, 3) + 0;
|
||||
}
|
||||
|
||||
# Get Function Coverage
|
||||
if ($strLine =~ /^FNF\:/)
|
||||
{
|
||||
$rhSummary->{$strModule}{function}{found} += substr($strLine, 4) + 0;
|
||||
$rhSummary->{zzztotal}{function}{found} += substr($strLine, 4) + 0;
|
||||
}
|
||||
|
||||
if ($strLine =~ /^FNH\:/)
|
||||
{
|
||||
$rhSummary->{$strModule}{function}{hit} += substr($strLine, 4) + 0;
|
||||
$rhSummary->{zzztotal}{function}{hit} += substr($strLine, 4) + 0;
|
||||
}
|
||||
|
||||
# Get Branch Coverage
|
||||
if ($strLine =~ /^BRF\:/)
|
||||
{
|
||||
$rhSummary->{$strModule}{branch}{found} += substr($strLine, 4) + 0;
|
||||
$rhSummary->{zzztotal}{branch}{found} += substr($strLine, 4) + 0;
|
||||
}
|
||||
|
||||
if ($strLine =~ /^BRH\:/)
|
||||
{
|
||||
$rhSummary->{$strModule}{branch}{hit} += substr($strLine, 4) + 0;
|
||||
$rhSummary->{zzztotal}{branch}{hit} += substr($strLine, 4) + 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# use Data::Dumper;confess Dumper($rhSummary);
|
||||
|
||||
my $strSummary;
|
||||
|
||||
foreach my $strModule (sort(keys(%{$rhSummary})))
|
||||
{
|
||||
my $rhModuleData = $rhSummary->{$strModule};
|
||||
|
||||
$strSummary .=
|
||||
(defined($strSummary) ? "\n\n" : '') .
|
||||
"<table-row>\n" .
|
||||
" <table-cell>" . ($strModule eq 'zzztotal' ? 'TOTAL' : $strModule) . "</table-cell>\n" .
|
||||
" <table-cell>" .
|
||||
coverageDocSummaryGenerateValue($rhModuleData->{function}{hit}, $rhModuleData->{function}{found}) .
|
||||
"</table-cell>\n" .
|
||||
" <table-cell>" .
|
||||
coverageDocSummaryGenerateValue($rhModuleData->{branch}{hit}, $rhModuleData->{branch}{found}) .
|
||||
"</table-cell>\n" .
|
||||
" <table-cell>" .
|
||||
coverageDocSummaryGenerateValue($rhModuleData->{line}{hit}, $rhModuleData->{line}{found}) .
|
||||
"</table-cell>\n" .
|
||||
"</table-row>";
|
||||
}
|
||||
|
||||
|
||||
# Write coverage report
|
||||
$oStorage->put($strOutFile, $strSummary);
|
||||
}
|
||||
|
||||
push @EXPORT, qw(coverageDocSummaryGenerate);
|
||||
|
||||
1;
|
||||
|
@ -26,6 +26,7 @@ use pgBackRest::Version;
|
||||
|
||||
use pgBackRestTest::Common::BuildTest;
|
||||
use pgBackRestTest::Common::ContainerTest;
|
||||
use pgBackRestTest::Common::CoverageTest;
|
||||
use pgBackRestTest::Common::DefineTest;
|
||||
use pgBackRestTest::Common::ExecuteTest;
|
||||
use pgBackRestTest::Common::ListTest;
|
||||
@ -70,6 +71,7 @@ sub new
|
||||
$self->{iRetry},
|
||||
$self->{bValgrindUnit},
|
||||
$self->{bCoverageUnit},
|
||||
$self->{bCoverageSummary},
|
||||
$self->{bOptimize},
|
||||
$self->{bBackTrace},
|
||||
$self->{bProfile},
|
||||
@ -99,6 +101,7 @@ sub new
|
||||
{name => 'iRetry'},
|
||||
{name => 'bValgrindUnit'},
|
||||
{name => 'bCoverageUnit'},
|
||||
{name => 'bCoverageSummary'},
|
||||
{name => 'bOptimize'},
|
||||
{name => 'bBackTrace'},
|
||||
{name => 'bProfile'},
|
||||
@ -578,13 +581,16 @@ sub end
|
||||
"module/$self->{oTest}->{&TEST_MODULE}/" . testRunName($self->{oTest}->{&TEST_NAME}, false) . 'Test');
|
||||
|
||||
# Generate coverage reports for the modules
|
||||
my $strLCovExe = "lcov --config-file=$self->{strGCovPath}/test/lcov.conf";
|
||||
my $strLCovConf = $self->{strBackRestBase} . '/test/.vagrant/code/lcov.conf';
|
||||
coverageLCovConfigGenerate($self->{oStorageTest}, $strLCovConf, $self->{bCoverageSummary});
|
||||
|
||||
my $strLCovExeBase = "lcov --config-file=${strLCovConf}";
|
||||
my $strLCovOut = $self->{strGCovPath} . '/test.lcov';
|
||||
my $strLCovOutTmp = $self->{strGCovPath} . '/test.tmp.lcov';
|
||||
|
||||
executeTest(
|
||||
'docker exec -i -u ' . TEST_USER . " ${strImage} " .
|
||||
"${strLCovExe} --capture --directory=$self->{strGCovPath} --o=${strLCovOut}");
|
||||
"${strLCovExeBase} --capture --directory=$self->{strGCovPath} --o=${strLCovOut}");
|
||||
|
||||
# Generate coverage report for each module
|
||||
foreach my $strModule (@stryCoveredModule)
|
||||
@ -599,6 +605,14 @@ sub end
|
||||
$bTest = true;
|
||||
}
|
||||
|
||||
# Disable branch coverage for test files
|
||||
my $strLCovExe = $strLCovExeBase;
|
||||
|
||||
if ($bTest)
|
||||
{
|
||||
$strLCovExe .= ' --rc lcov_branch_coverage=0';
|
||||
}
|
||||
|
||||
# Generate lcov reports
|
||||
my $strModulePath = $self->{strBackRestBase} . "/test/.vagrant/code/${strModuleOutName}";
|
||||
my $strLCovFile = "${strModulePath}.lcov";
|
||||
|
@ -1,24 +0,0 @@
|
||||
# LCOV Settings
|
||||
|
||||
# Specify if branch coverage data should be collected and processed
|
||||
lcov_branch_coverage=1
|
||||
|
||||
# Specify the regular expression of lines to exclude from branch coverage
|
||||
#
|
||||
# OBJECT_DEFINE_[A-Z0-9_]+\( - exclude object definitions
|
||||
# \s{4}[A-Z][A-Z0-9_]+\([^\?]*\) - exclude macros that do not take a conditional parameter and are not themselves a parameter
|
||||
# \s{4}(TEST_|HARNESS_)[A-Z0-9_]+\( - exclude macros used in unit tests
|
||||
# ASSERT/(|assert\( - exclude asserts since it usually not possible to trigger both branches
|
||||
# (testBegin\( - exclude because it generally returns true, and is not needed for coverage
|
||||
# switch \( - lcov requires default: to show complete coverage but --Wswitch-enum enforces all enum values be present
|
||||
lcov_excl_br_line=OBJECT_DEFINE_[A-Z0-9_]+\(|\s{4}[A-Z][A-Z0-9_]+\([^\?]*\)|\s{4}(TEST_|HARNESS_)[A-Z0-9_]+\(|\s{4}(ASSERT|assert|switch\s)\(|\(testBegin\(|\{\+{0,1}uncover(ed|able)_branch
|
||||
|
||||
# Specify the regular expression of lines to exclude
|
||||
lcov_excl_line=\{\+{0,1}uncovered[^_]|\{\+{0,1}uncoverable[^_]
|
||||
|
||||
# Coverage rate limits
|
||||
genhtml_hi_limit = 100
|
||||
genhtml_med_limit = 90
|
||||
|
||||
# Width of line coverage field in source code view
|
||||
genhtml_line_field_width = 9
|
36
test/test.pl
36
test/test.pl
@ -99,6 +99,9 @@ test.pl [options]
|
||||
--no-debug don't generate a debug build
|
||||
--debug-test-trace test stack trace for low-level functions (slow, esp w/valgrind, may cause timeouts)
|
||||
|
||||
Report Options:
|
||||
--coverage-summary generate a coverage summary report for the documentation
|
||||
|
||||
Configuration Options:
|
||||
--psql-bin path to the psql executables (e.g. /usr/lib/postgresql/9.3/bin/)
|
||||
--test-path path where tests are executed (defaults to ./test)
|
||||
@ -146,6 +149,7 @@ my $bNoLint = false;
|
||||
my $bBuildOnly = false;
|
||||
my $iBuildMax = 4;
|
||||
my $bCoverageOnly = false;
|
||||
my $bCoverageSummary = false;
|
||||
my $bNoCoverage = false;
|
||||
my $bCOnly = false;
|
||||
my $bGenOnly = false;
|
||||
@ -165,6 +169,8 @@ my $bNoDebug = false;
|
||||
my $bDebugTestTrace = false;
|
||||
my $iRetry = 0;
|
||||
|
||||
my @cmdOptions = @ARGV;
|
||||
|
||||
GetOptions ('q|quiet' => \$bQuiet,
|
||||
'version' => \$bVersion,
|
||||
'help' => \$bHelp,
|
||||
@ -192,6 +198,7 @@ GetOptions ('q|quiet' => \$bQuiet,
|
||||
'no-package' => \$bNoPackage,
|
||||
'no-ci-config' => \$bNoCiConfig,
|
||||
'coverage-only' => \$bCoverageOnly,
|
||||
'coverage-summary' => \$bCoverageSummary,
|
||||
'no-coverage' => \$bNoCoverage,
|
||||
'c-only' => \$bCOnly,
|
||||
'gen-only' => \$bGenOnly,
|
||||
@ -238,6 +245,15 @@ eval
|
||||
pod2usage();
|
||||
}
|
||||
|
||||
################################################################################################################################
|
||||
# Update options for --coverage-summary
|
||||
################################################################################################################################
|
||||
if ($bCoverageSummary)
|
||||
{
|
||||
$bCoverageOnly = true;
|
||||
$bCOnly = true;
|
||||
}
|
||||
|
||||
################################################################################################################################
|
||||
# Update options for --dev and --dev-fast and --dev-test
|
||||
################################################################################################################################
|
||||
@ -1311,8 +1327,8 @@ eval
|
||||
my $oJob = new pgBackRestTest::Common::JobTest(
|
||||
$oStorageTest, $strBackRestBase, $strTestPath, $strCoveragePath, $$oyTestRun[$iTestIdx], $bDryRun, $bVmOut,
|
||||
$iVmIdx, $iVmMax, $iTestIdx, $iTestMax, $strLogLevel, $strLogLevelTest, $bLogForce, $bShowOutputAsync,
|
||||
$bNoCleanup, $iRetry, !$bNoValgrind, !$bNoCoverage, !$bNoOptimize, $bBackTrace, $bProfile, !$bNoDebug,
|
||||
$bDebugTestTrace, $iBuildMax / $iVmMax < 1 ? 1 : int($iBuildMax / $iVmMax));
|
||||
$bNoCleanup, $iRetry, !$bNoValgrind, !$bNoCoverage, $bCoverageSummary, !$bNoOptimize, $bBackTrace,
|
||||
$bProfile, !$bNoDebug, $bDebugTestTrace, $iBuildMax / $iVmMax < 1 ? 1 : int($iBuildMax / $iVmMax));
|
||||
$iTestIdx++;
|
||||
|
||||
if ($oJob->run())
|
||||
@ -1496,7 +1512,7 @@ eval
|
||||
if ($oStorageBackRest->exists($strLCovFile))
|
||||
{
|
||||
executeTest(
|
||||
"genhtml ${strLCovFile} --config-file=${strBackRestBase}/test/src/lcov.conf" .
|
||||
"genhtml ${strLCovFile} --config-file=${strBackRestBase}/test/.vagrant/code/lcov.conf" .
|
||||
" --prefix=${strBackRestBase}/test/.vagrant/code" .
|
||||
" --output-directory=${strBackRestBase}/test/coverage/c");
|
||||
|
||||
@ -1555,7 +1571,17 @@ eval
|
||||
|
||||
$oStorageBackRest->remove("${strBackRestBase}/test/.vagrant/code/all.lcov", {bIgnoreMissing => true});
|
||||
coverageGenerate(
|
||||
$oStorageBackRest, "${strBackRestBase}/test/.vagrant/code", "${strBackRestBase}/test/coverage/c-coverage.html");
|
||||
$oStorageBackRest, "${strBackRestBase}/test/.vagrant/code",
|
||||
"${strBackRestBase}/test/coverage/c-coverage.html");
|
||||
|
||||
if ($bCoverageSummary)
|
||||
{
|
||||
&log(INFO, 'writing C coverage summary report');
|
||||
|
||||
coverageDocSummaryGenerate(
|
||||
$oStorageBackRest, "${strBackRestBase}/test/.vagrant/code",
|
||||
"${strBackRestBase}/doc/xml/auto/metric-coverage-report.auto.xml");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1572,7 +1598,7 @@ eval
|
||||
" WITH ${iTestFail} FAILURE(S)") . ($iTestRetry == 0 ? '' : ", ${iTestRetry} RETRY(IES)") .
|
||||
' (' . (time() - $lStartTime) . 's)');
|
||||
|
||||
exit 1 if ($iTestFail > 0 || $iUncoveredCodeModuleTotal > 0);
|
||||
exit 1 if ($iTestFail > 0 || ($iUncoveredCodeModuleTotal > 0 && !$bCoverageSummary));
|
||||
|
||||
exit 0;
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ eval
|
||||
processEnd();
|
||||
|
||||
processBegin('release documentation doc');
|
||||
executeTest("${strReleaseExe} --build", {bShowOutputAsync => true});
|
||||
executeTest("${strReleaseExe} --build --no-coverage", {bShowOutputAsync => true});
|
||||
processEnd();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user