linux-test-project / lcov

LCOV
GNU General Public License v2.0
867 stars 235 forks source link

filter branch options make no affect to .inl file #250

Closed musnows closed 7 months ago

musnows commented 7 months ago

Here is a lite demo for this error

code file

myfunc.h

#ifndef __TEST_INCLUDE__
#define __TEST_INCLUDE__

#include <string>
#include <cstring>

void test_string_plus_inl(const std::string &local, const std::string &remote);

// This is just a lcov test function, it does not have actual functionality
void test_string_plus(const std::string &local, const std::string &remote)
{
    static std::string recv_msg;
    std::string target("/");
    if (local < remote)
    {
        target += local + "_" + remote;
    } else
    {
        target += remote + "_" + local;
    }

    char sun_path[128];
    static_cast<void>(strncpy(sun_path, (recv_msg).c_str(), sizeof(sun_path) - 1));
}

#include "myfunc.inl"
#endif // __TEST_INCLUDE__

myfunc.inl

#ifndef __TEST_INL__
#define __TEST_INL__

#include "myfunc.h"

// This is just a lcov test function, it does not have actual functionality
void test_string_plus_inl(const std::string &local, const std::string &remote)
{
    static std::string recv_msg;
    std::string target("/");
    if (local < remote)
    {
        target += local + "_" + remote;
    } else
    {
        target += remote + "_" + local;
    }

    char sun_path[128];
    static_cast<void>(strncpy(sun_path, (recv_msg).c_str(), sizeof(sun_path) - 1));
}

#endif  // __TEST_INL__

test.cpp

#include "include/myfunc.h"

void test1()
{
    test_string_plus("test", "1");
    test_string_plus("2", "test");
}

void test2()
{   
    test_string_plus_inl("test", "3");
    test_string_plus_inl("4", "test");
}

int main()
{
    test1();
    test2();
    return 0;
}

complie command & tools version

g++ test.cpp -o test -fprofile-arcs -ftest-coverage -fprofile-update=atomic && ./test
lcov --capture \                                                               
                 --rc branch_coverage=1 \
                 --directory . \
                 --filter branch \
                 --output-file coverage_all.info \
                 --ignore-errors mismatch && \
genhtml coverage_all.info \
                  --rc branch_coverage=1 \
                  --filter branch \
                  --ignore-errors mismatch \
                  --output-directory coverage_report

tools version:

lcov result

In this demo, the test_string_plus and test_string_plus_inl are exactly the same, but lcov report shows like this.

image

image

gcov result

I also run gcov -b -c -o . test.cpp command to generate gcov file. The branch coverage of these two functions is the same in the gcov file, so I think the problem here is that the --filter branch option does not have an effect on the .inl file.


Excerpt from gcov file 👇

myfunc.h

function _Z16test_string_plusRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES6_ called 2 returned 100% blocks executed 61%
        2:   10:void test_string_plus(const std::string &local, const std::string &remote)
        -:   11:{
        2:   12:    static std::string recv_msg;
branch  0 taken 1 (fallthrough)
branch  1 taken 1
call    2 returned 1
branch  3 taken 1 (fallthrough)
branch  4 taken 0
call    5 returned 1
call    6 returned 1
call    7 returned 1
        2:   13:    std::string target("/");
call    0 returned 2
call    1 returned 2
branch  2 taken 2 (fallthrough)
branch  3 taken 0 (throw)

myfunc.inl

function _Z20test_string_plus_inlRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES6_ called 2 returned 100% blocks executed 61%
        2:    7:void test_string_plus_inl(const std::string &local, const std::string &remote)
        -:    8:{
        2:    9:    static std::string recv_msg;
branch  0 taken 1 (fallthrough)
branch  1 taken 1
call    2 returned 1
branch  3 taken 1 (fallthrough)
branch  4 taken 0
call    5 returned 1
call    6 returned 1
call    7 returned 1
        2:   10:    std::string target("/");
call    0 returned 2
call    1 returned 2
branch  2 taken 2 (fallthrough)
branch  3 taken 0 (throw)

The temporary solution I am currently using is to move the contents of .inl back to the .h file and change .h to .hpp, which --filter branch options could work perfectly.

henry2cox commented 7 months ago

lcov/geninfo/genhtml try to apply filtering only to languages whose syntax they think they understand - so we filter C/C++ and Verilog - but not python/java/etc.

The tool identifies the language of particular source file by looking at the filename - by default, 'c|h|i||C|H|I|icc|cpp|cc|cxx|hh|hpp|hxx'. You can change this via your lcovrc file or via the command line option --rc c_file_extension='h|inl|...' See the lcovrc man page for more details.

The man page description of the --filter option should probably be modified to clarify how the tool decides to apply filtering (or not), and perhaps the tools should notify the user when filtering is being skipped due to lack of language support. (Such notification would need to be off by default - which would kind of defeat the purpose, as you would need to know about language restrictions to know to turn on the notification...and which point, you didn't need to be notified.)

musnows commented 7 months ago

thanks for your help, I checkout the lcovrc man page, it works after add this options to lcov/genhtml command

--rc c_file_extensions=c,cpp,hpp,h,inl

image