Does Branch coverage implies Condition Coverage?
If you're talking specifically about the gcov tools, the branch coverage is really counting the points at which the end of each basic block is reached. See Understanding branches in gcov files.
Condition coverage is something different. See Is it possible to check condition coverage with gcov? (The answer is no, it's not, at least not with just gcov.) As Marc Gilsse's comment notes, you can use gcov -a
to count executions through each basic block, and use that as a reasonable approximation—but it's not the same thing.
C++'s exceptions make dealing with branch coverage messy; see LCOV/GCOV branch coverage with C++ producing branches all over the place. This means you won't necessarily be able to cover all branches in the first place.
See also, e.g., Understanding blocks in gcov files.
Understand control flow graph in lcov branch coverage output
Please refer the answer [here] as below[1]:
The short form, is that lcov's interaction with branching, especially with inline calls, can find some of the hidden branches in the code, that are beyond your control.
For example, templated functions (of which std::cout << "foo" is one)
can be inlined efficiently by the compiler. Which means that any
branches present in that code can also be seen by the compiler. This
of course lets the compiler do a more thorough optimization. This is
the branch you are seeing here. It's not in code you wrote, but in
code the template instantiated for you.In particular, most formatted output functions on basic_ostream are
going to ensure that the stream is in a good state prior to doing the
formatting or inserting work.When I'm doing branch analysis, I tend to disregard branch misses on
functions like this. There are several similar places in C++ which
branches are detected by gcov/lcov, but are only implementation
details. I try to focus on the branches under my control.
the reason here is the same, QString::number() is a static function and it calls a inline function [QString::setNum][2] which had many branch inside.
Can check below as an example to illustrate this:
foo.h
extern void foo(int);
class Bar {
public:
inline bool doCheckInt(int a) { return a > 0 && a < 2; }
static bool checkParam(int a) {
Bar bar;
return bar.doCheckInt(a);
}
};
foo.cpp
#include "foo.h"
#include <iostream>
void foo(int num)
{
if (Bar::checkParam(num)) {
std::cout << "when num is equal to 1..." << std::endl;
} else if (num == 2){
std::cout << "when num is equal to 2..." << std::endl;
} else {
std::cout << "when num is equal to "<< num << std::endl;
}
}
main.c
#include <stdio.h>
#include "foo.h"
int main(void)
{
printf("Start calling foo() ...\n");
foo(1);
foo(2);
return 0;
}
after compile and generate code coverage report(relate method refered [here][3]), can get below coverage report for function foo():
[![foo_coverage][4]][4]
we can find that foo have total 8 branchs(2 X 2 X 2), and the two foo(1), foo(2) hit 5 of the branchs.
[1]: https://stackoverflow.com/a/69164983/4277805
[2]: https://github.com/radekp/qt/blob/master/src/corelib/tools/qstring.h
[3]: https://shenxianpeng.github.io/2021/07/gcov-example/
[4]: https://i.stack.imgur.com/n6huJ.png
Related Topics
Order of Constructor Call in Virtual Inheritance
Unresolved Externals in C++ When Using Vectors and Find
Is Circumventing a Class' Constructor Legal or Does It Result in Undefined Behaviour
How to Check Whether Multiple Variables Are Equal to the Same Value
Why Is F(I = -1, I = -1) Undefined Behavior
When to Make a Type Non-Movable in C++11
When to Use Shared_Ptr and When to Use Raw Pointers
Std::Thread Is Not a Member of Namespace Std Using Eclipse Kepler Mingw
C++ N Nested Vectors at Runtime
How to Use Nested Loops with Vectors in Cpp
C++: How to Implement Polymorphic Object Creator to Populate a Table
Double Delete in Initializer_List VS 2013
Why Is a Constexpr Function on a Reference Not Constexpr
Using the Less Than Comparison Operator for Strings
How to Copy/Paste from the Clipboard in C++
How to Open a Gstreamer Pipeline from Opencv with Videowriter