eddyxu / cpp-coveralls

Upload gcov results to coveralls.io
Apache License 2.0
282 stars 74 forks source link

Runtime error in `parse_gcov_file`: `27-block 0` is in the gcov file, but appears to be unexpected by the parser #116

Open fedorov opened 7 years ago

fedorov commented 7 years ago

gcov version:

$ gcov --version
gcov (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609

Error:

Traceback (most recent call last):
  File "/home/fedorov/.pyenv/versions/2.7.8/bin/coveralls", line 11, in <module>
    sys.exit(run())
  File "/home/fedorov/.pyenv/versions/2.7.8/lib/python2.7/site-packages/cpp_coveralls/__init__.py", line 96, in run
    cov_report = coverage.collect(args)
  File "/home/fedorov/.pyenv/versions/2.7.8/lib/python2.7/site-packages/cpp_coveralls/coverage.py", line 457, in collect
    src_report['coverage'] = parse_gcov_file(fobj, gcov_path)
  File "/home/fedorov/.pyenv/versions/2.7.8/lib/python2.7/site-packages/cpp_coveralls/coverage.py", line 256, in parse_gcov_file
    line_num = int(report_fields[1].strip())
ValueError: invalid literal for int() with base 10: '27-block  0'

Relevant part of the coverage file:

        -:   26:  public:
function _ZN3itk29ImageIOFactoryRegisterManagerC2EPPFvvE called 0 returned 0% blocks executed 0%
    #####:   27:  ImageIOFactoryRegisterManager(void (*list[])(void))
    $$$$$:   27-block  0
        -:   28:    {
    #####:   29:    for(;*list; ++list)
    $$$$$:   29-block  0
branch  0 never executed
branch  1 never executed
unconditional  2 never executed
        -:   30:      {
    #####:   31:      (*list)();
    $$$$$:   31-block  0
call    0 never executed
        -:   32:      }
    #####:   33:    }
        -:   34:};
chrisosaurus commented 6 years ago

The above gcov file contains lots of information that our tooling doesn't understand.

I am now coming across this same error on my machine as well, only happened so far for C++ projects which seem to insert extra artifacts into the gcov file.

When working on https://github.com/eddyxu/cpp-coveralls/issues/111#issuecomment-403261317

I was seeing gcov files like

[...]

    #####:   39:  if (config.isProfilerEnabled()) {
    #####:   40:    profiler::stopListen();
    #####:   41:    PROFILER_PROFILER_DISABLE;
        -:   42:  }
    #####:   43:  screenshotCallbackHolder.removeThis();
    #####:   44:}
------------------
radix::BaseGame::~BaseGame():
    #####:   38:BaseGame::~BaseGame() {
        -:   39:  if (config.isProfilerEnabled()) {
        -:   40:    profiler::stopListen();
        -:   41:    PROFILER_PROFILER_DISABLE;
        -:   42:  }
        -:   43:  screenshotCallbackHolder.removeThis();
    #####:   44:}
------------------
radix::BaseGame::~BaseGame():
    #####:   38:BaseGame::~BaseGame() {
    #####:   39:  if (config.isProfilerEnabled()) {
    #####:   40:    profiler::stopListen();
    #####:   41:    PROFILER_PROFILER_DISABLE;
        -:   42:  }
    #####:   43:  screenshotCallbackHolder.removeThis();
    #####:   44:}
------------------
        -:   45:
    #####:   46:void BaseGame::setup() {
    #####:   47:  radix::Util::Log(radix::Info, "GameController") << "BaseGame::setup() start;";

[...]

which would then cause our parser to complain about the lines of the form

Traceback (most recent call last):
  File "/usr/bin/coveralls", line 11, in <module>
    sys.exit(run())
  File "/usr/lib/python3.6/site-packages/cpp_coveralls/__init__.py", line 97, in run
    cov_report = coverage.collect(args)
  File "/usr/lib/python3.6/site-packages/cpp_coveralls/coverage.py", line 450, in collect
    src_report['coverage'] = parse_gcov_file(args, fobj, gcov_path)
  File "/usr/lib/python3.6/site-packages/cpp_coveralls/coverage.py", line 254, in parse_gcov_file
    line_num = int(report_fields[1].strip())
ValueError: invalid literal for int() with base 10: ''
radix::BaseGame::~BaseGame():
radix::BaseGame::~BaseGame():

these appear to be function names, I think gcov is including information on a per-function level that our parser does not understand.

I can see these style of names in the manpage for gcov.

samiBendou commented 5 years ago

I had the same problem using gtest, the gcov files contained odd lines :

    2:   32:TEST_F(NPMatrixTest, Dim) {
   2*:   33:    ASSERT_EQ(_a.n(), 3);
   2*:   34:    ASSERT_EQ(_a.p(), 3);
   2*:   35:    ASSERT_TRUE(_a.isSquare());
    -:   36:}

_ZN21NPMatrixTest_Dim_Test8TestBodyEv:

The method report_fields = line.decode('utf-8', 'replace').split(':', 2) splits lines of gcov files by finding occurrences of :. It seems that sometimes when a line contains more than two : symbols this method fails to parse the line into report_fields.

On my case, I fixed this issue by verifying if the size of report_fields is equal to 3 after decode call and skipping line if not. It allows to protect next instructions from casting to int or access to array when parse failed because of :.

You can at check my fork updated with the fix : https://github.com/samiBendou/cpp-coveralls

blueyed commented 5 years ago

See https://github.com/eddyxu/cpp-coveralls/pull/140.