Can't get coverage from multiple test folders for C++

Must-share information (formatted with Markdown):

  • which versions are you using: SonarScanner 4.3.0.2102 | SonarQube server 7.9.4 | gcov (GCC) 4.8.5 20150623 | gcc version 4.8.5 20150623
  • what are you trying to achieve | I want to have coverage report from my project
  • what have you tried so far to achieve this: I used build-wrapper for my project, then I build and executed google tests, I also created *.gcov files (used gcov) out of these tests needed for coverity and put them in a common directory({WORKSPACE}/gcov_common). Then I set `sonar.cfamily.gcov.reportsPath` to point to that directory, lets say -Dsonar.cfamily.gcov.reportsPath={WORKSPACE}/gcov_common, then Sensor gcov [cpp] says INFO: Parsing /home/user/dir/gcov_common/example.gcov
    File not analysed by Sonar, so ignoring coverage: /home/user/dir/gw/example_test.cpp (test is in different directory eg. /home/user/dir/xx/xx/xx/xx/tests) .

I can force sonnarQube to get coverity by setting sonar.cfamily.gcov.reportsPath to the directory where test really is (and also gcov files) eg. /home/user/dir/xx/xx/xx/xx/tests, but then I’ll get coverity only for that folder, but I have tests in many other directories eg. /home/user/dir/yy/yy/yy/tests.

I tried to put all test-file.cpp and .gcov files in common directory but this didn’t help,

I can’t pass multiple paths to sonar.cfamily.gcov.reportsPath. For now this seems to me to be impossible to get this coverage report works for whole project, or I must miss something.

{WORKSPACE} is /home/user/dir/ sonar.projectBaseDir={WORKSPACE}/xx

Regards,
Fabian

Hi @Fabian,

it seems like that you are fighting with relative paths.

this sounds good with one exception. You should generate *.gcov files by calling gcov from {WORKSPACE}/gcov_common folder. Could you give it a try?

Hi @mpaladin,
Thank You for the response.
Unfortunately gcov must be run inside each source folder.
I helped myself with Using Relative Paths With GCOV Sensor
and I got to the point where *.gcov are stored with test .cpp files and .gcno and .gcda files(last two are actually not important), and I set sonar.cfamily.gcov.reportsPath=. and sonar.projectBaseDir=${WORKSPACE}/gw
With this some coverage shows up, but seems like not all files are being scanned with proper coverage, one example:
gw/src/res/v/v/xxx.cc (Coverage 0%) - actually real coverage for this file is 85%
gw/src/res/v/v/tests/test-xxx.cpp (Coverage 77.5%) - test code for xxx.c

gw/src/i/n/v.cc (Coverage 43.9%) - actually real coverage for this file is 85%
gw/src/i/n/tests/test-v.cpp (Coverage 83.3%) test code for v.cc

Why there is a difference between xxx and v, while in reality they both have +85% coverage

gw/src/a/c/v/mapp.c (Coverage 13.6%) - tested file
gw/src/a/v/tests/mapp_test.cpp (Coverage 32.8%) test code for mapp.c

xxx.cc and v.cc (and dozen of others files) are relatively new files with more than 85% coverage with their tests being test-xxx.cpp and test-v.cpp, I don’t know why some files gets no coverage at all like xxx.cc while they have the same directory recess, like v.cc which gets coverage. Most coverage I have is from test files itself, not the tested files. I’d like to have it like in “v” files.

Hi @Fabian,

I am not sure if we are talking about the same thing but we are using gcov for our source code, and we are running gcov from the reports folder, not from the source folder, gcov doesn’t have the requirement to be run from the source folder.

By " each source folder" I meant calling "gcov ./.cpp" in each folder containg tests, right after their execution eg.
cd gw/src/res/v/v/tests/
make clean, make run, gcov ./
.cpp
cd gw/src/i/n/tests/
make clean, make run, gcov ./*.cpp
etc.
now leaving *.gcov where they are gw/src/res/v/v/tests/, gw/src/i/n/tests/ etc.
and setting sonar.cfamily.gcov.reportsPath=. gives the output I described above, moving all *.gcov to {WORKSPACE}/gw/gcov_common and setting sonar.cfamily.gcov.reportsPath={WORKSPACE}/gw/gcov_common gives even lower coverage.
The other way I tried recently is to execute tests, and move: .gcno, .gcda .cpp from each /tests/ directory to ${WORKSPACE}/gw/gcov_common and then executing gcov in this directory doesn’t works as real files still doesn’t have coverage while those which were moved are duplicated(but at least have coverage).

So maybe I’ll describe how do I build to have more wide view on the topic.

  1. I call build wrapper on my building script
  2. I run script that executes tests the way described above(getting inside directory with tests, make clean, make run, go to another directory with tests [generating gcov is new here I can either leave *.gcov in this particular test directory or move them to /gcov_common/,])
  3. calling sonar-scanner with some flags and sonar.cfamily.gcov.reportsPath set to either .(dot) or to point to this gcov_common.

What do I need to fix in these steps to get correct coverage?

Hi @Fabian,

FYI this is what we do on our side if it can help:

mkdir ${BWRAPPER_GCOV_DIR}
pushd ${BWRAPPER_GCOV_DIR}
for f in `find our/build/folder -name '*.o'`
do
  echo "Processing $f file..."
  gcov -o ${f} x
done
popd

and then we set -Dsonar.cfamily.gcov.reportsPath=${BWRAPPER_GCOV_DIR} property during analysis.

1 Like

Hi @mpaladin

I found a solution. Maybe this will help to somebody else.

In /…/…/XX/tests after test execution I have *.gcno, *.gcda and *.o then I call gcov on *.o files,
but there is a difference between tests, some of them include
header files and links to builded library, and the others includes source files.

Tests that have included source files produces *.gcov for source files properly, and store them in /…/…/XX/tests (what I wanted)
Tests that didn’t include source files uses -l flag in Makefiles to include library, this produced *.gcno, .gcda (.gcda are made after test execution) and .o in totally different directory lets say /objects/x86/ and puts them all together.

To get this to work I had to move particular files from /objects/x86/ to /…/…/XX and then call gcov ./*.o, doing those steps allowed me to produce necessary *.gcov files in /…/…/XX and in /…/…/XX/tests. This way I have a coverage for whole project. Also path to gcov is set to -Dsonar.cfamily.gcov.reportsPath=.

Regards,
Fabian

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.