1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
|
#!/usr/bin/env perl
# Copyright (C) 2017 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
use 5.010;
use strict;
use warnings;
=head1 NAME
coveragerunner_testcocoon - helper script to run coverage analysis after build (tool used is TestCocoon)
=head1 SYNOPSIS
# Run code coverage analysis
$ ./coveragerunner_testcocoon --qtmodule-dir path/to/module --qtmodule-name modulename --qtcoverage-tests_output path/to/output/folder/tests_database.csmes"
# Example launch script for a qt module (ie qtbase)
# ./coveragerunner_testcocoon --qtmodule-dir path/to/qtbase --qtmodule-name qtbase --qtcoverage-tests_output "$HOME/qtbase/alltests.csmes"
# Will generate:
#
# $HOME/qtbase/qtbase-coverage_report-<currentdatetime>.xml
# $HOME/qtbase/qtbase-coverage_global-<currentdatetime>.csmes
#
This script depends on auto tests run with testrunner script. It is designed to integrate with Qt configured
with -testcocoon option and testrunner run with the testcocoon plugin loaded.
Required qtcoverage-tests_output
generated from testrunner. This file is renamed with unique name to avoid overwriting it.
=head1 OPTIONS
=over
=item B<--help>
Print this message.
=item B<--qtmodule-dir> <directory>
Required. Path to Qt5 module to analyze.
=item B<--qtmodule-name> <value>
Required. Name of Qt5 module to analyze.
=item B<--qtcoverage-tests-output> <directory>
Required. Full path to the csmes database gathering tests results.
=back
=cut
use FindBin;
use lib "$FindBin::Bin/../lib/perl5";
package QtQA::App::CoverageRunnerTestCocoon;
use base qw(QtQA::TestScript);
use Carp;
use Getopt::Long qw(GetOptionsFromArray);
use English qw( -no_match_vars );
use File::Basename;
use File::Spec::Functions;
use Pod::Usage qw( pod2usage );
use autodie;
use POSIX qw/strftime/;
use File::Copy;
use File::Find::Rule;
sub new
{
my ($class) = @_;
my $self = $class->SUPER::new;
bless $self, $class;
return $self;
}
sub run
{
my ($self, @args) = @_;
my $qt_gitmodule_dir;
my $qt_gitmodule;
my $testcocoon_tests_output;
GetOptionsFromArray( \@args,
'help|?' => sub { pod2usage(1) },
'qt-gitmodule-dir=s' => \$qt_gitmodule_dir,
'qt-gitmodule=s' => \$qt_gitmodule,
'qtcoverage-tests-output=s' => \$testcocoon_tests_output,
) || pod2usage(2);
my $currentdatetime = strftime('%Y%m%d-%H%M', localtime);
if (! -f $testcocoon_tests_output) {
confess "$testcocoon_tests_output does not exist. Either the tests have not been run or coverage was not enabled at build time";
}
my $coverage_dir = dirname($testcocoon_tests_output);
# Named unique output files
my $xml_report = $qt_gitmodule . "_coverage_report-" . $currentdatetime . ".xml";
my $csmes_source = $qt_gitmodule . "_coverage_src-" . $currentdatetime . ".csmes";
my $csmes_tests = $qt_gitmodule . "_coverage_unittests-" . $currentdatetime . ".csmes";
my $csmes_global = $qt_gitmodule . "_coverage_global-" . $currentdatetime . ".csmes";
$xml_report = catfile( $coverage_dir, $xml_report );
$csmes_source = catfile( $coverage_dir, $csmes_source );
$csmes_tests = catfile( $coverage_dir, $csmes_tests );
$csmes_global = catfile( $coverage_dir, $csmes_global );
# Rename global tests csmes file with unique name
move($testcocoon_tests_output, $csmes_tests) or confess "move $testcocoon_tests_output: $!";
my $qt_git_qtbase_dir =
($qt_gitmodule eq 'qtbase') ? $qt_gitmodule_dir
: ($qt_gitmodule eq 'qt5') ? catfile($qt_gitmodule_dir, 'qtbase')
: catfile($qt_gitmodule_dir, '..', 'qtbase');
# Get all sources files csmes gathered in a global database (from lib and plugins folder)
my $qt_git_qtbase_libdir = catfile($qt_git_qtbase_dir, 'lib');
print "Gather all library files covered in a global database\n";
my $qt_git_qtbase_pluginsdir = catfile($qt_git_qtbase_dir, 'plugins');
my $qt_git_qtbase_importsdir = catfile($qt_git_qtbase_dir, 'imports');
my @allcsmes = File::Find::Rule->file()->name( '*.csmes' )->in($qt_git_qtbase_libdir);
push @allcsmes, File::Find::Rule->file()->name( '*.csmes' )->in($qt_git_qtbase_pluginsdir);
push @allcsmes, File::Find::Rule->file()->name( '*.csmes' )->in($qt_git_qtbase_importsdir);
@allcsmes = map { canonpath($_) } sort(@allcsmes);
print "List of all source files in coverage\n";
foreach my $csmes (@allcsmes) {
print "$csmes\n";
if (-e $csmes_source) {
$self->exe('cmmerge',
'--append',
"--output=$csmes_source",
$csmes
);
} else {
copy($csmes, $csmes_source) or confess "copy $csmes: $!";
}
}
print "End of list\n";
# Create global database
move($csmes_source, $csmes_global) or confess "move $csmes_source: $!";
# Merge tests into global
$self->exe('cmmerge',
'--append',
"--output=$csmes_global",
$csmes_tests
);
# Delete the tests csmes to save space.
unlink($csmes_tests) or confess "unlink $csmes_tests: $!";
# Generate report
$self->exe('cmreport',
"--csmes=$csmes_global",
"--xml=$xml_report",
'--select=.*',
'--source=all',
'--source-sort=name',
'--global=all'
);
# Compress global csmes to save space
$self->exe('gzip',
$csmes_global);
# Create hmtl reports
my $xml2html = catfile( $FindBin::Bin, 'xml2html_testcocoon.pl' );
$xml2html = 'xml2html_testcocoon' if (defined $ENV{ TESTING_COVERAGERUNNER });
$self->exe($xml2html,
'--xml',
$xml_report,
'--module',
$qt_gitmodule,
'--output',
$coverage_dir,
'--include',
catfile($qt_gitmodule_dir, 'src'),
'--exclude',
catfile($qt_gitmodule_dir, 'src', '3rdparty')
);
return;
}
QtQA::App::CoverageRunnerTestCocoon->new( )->run( @ARGV ) if (!caller);
1;
|