New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gcovr fails with GCC 8.0.1 #226

Closed
ernestask opened this Issue Feb 22, 2018 · 10 comments

Comments

Projects
None yet
2 participants
@ernestask

ernestask commented Feb 22, 2018

This is actually a different trace than I got the first time, but trying to generate a coverage report in a CI pipeline results in this:

Traceback (most recent call last):
  File "/usr/local/bin/gcovr", line 2412, in <module>
    process_datafile(file_, covdata, options)
  File "/usr/local/bin/gcovr", line 884, in process_datafile
    process_gcov_data(fname, covdata, abs_filename, options)
  File "/usr/local/bin/gcovr", line 616, in process_gcov_data
    covered[lineno] = int(segments[0].strip())
ValueError: invalid literal for int() with base 10: '1*'

The one I saw before was an IndexError at this line:

code = segments[2].strip()

The distro is current Fedora Rawhide with gcovr installed via pip, as the distro package is outdated now.

Full log: https://gitlab.gnome.org/GNOME/nautilus/-/jobs/8807/raw.

@latk

This comment has been minimized.

Member

latk commented Feb 22, 2018

Thank you for this report. Gcovr depends on GCOV to pre-process the coverage reports. We then parse the human-readable .gcov files. Our tests currently only use GCC 5, but other versions are known to work as well. Your report suggests that GCC 8 may change the GCOV report format.

In order to debug this problem, could you run gcovr in verbose mode (gcovr -v)? This will indicate the .gcov file causing these problems. It would be super helpful if you could provide a .gcov file on which gcovr chokes. I currently can't install GCC 8 to check this myself.

Until I can address the root cause, it might be possible to make gcovr more robust. If parsing one file fails, it will be excluded and gcovr continues with the next file. After generating the reports, gcovr would exit with an error. Would such a fail-later behaviour be helpful for you?

In the meanwhile, please consider only collecting coverage with an earlier compiler, e.g. GCC 7.x.

@ernestask

This comment has been minimized.

ernestask commented Feb 22, 2018

In order to debug this problem, could you run gcovr in verbose mode (gcovr -v)? This will indicate the .gcov file causing these problems. It would be super helpful if you could provide a .gcov file on which gcovr chokes. I currently can't install GCC 8 to check this myself.

I was hoping I wouldn’t have to do this, because I have 7.3.1 installed on my machine, but I’ll report back if I can reproduce the issue locally.

Until I can address the root cause, it might be possible to make gcovr more robust. If parsing one file fails, it will be excluded and gcovr continues with the next file. After generating the reports, gcovr would exit with an error. Would such a fail-later behaviour be helpful for you?

Really, I’d be happy with anything, including a NotImplementedError. Then I’d know that I should avoid doing the thing I’m doing. :)

In the meanwhile, please consider only collecting coverage with an earlier compiler, e.g. GCC 7.x.

That’s not a problem, just that I switched from F27 to Rawhide for a dependency that hasn’t hit stable yet.

@latk

This comment has been minimized.

Member

latk commented Feb 23, 2018

Ok, the development version of the GCOV documentation shows major changes to the .gcov file format. These changes are good, but break our current parser in many ways.

Here is an excerpt of such a .gcov file from their docs:

        -:    3:template<class T>
        -:    4:class Foo
        -:    5:{
        -:    6:  public:
       1*:    7:  Foo(): b (1000) {}
------------------
Foo<char>::Foo():
function Foo<char>::Foo() called 0 returned 0% blocks executed 0%
    #####:    7:  Foo(): b (1000) {}
------------------
Foo<int>::Foo():
function Foo<int>::Foo() called 1 returned 100% blocks executed 100%
        1:    7:  Foo(): b (1000) {}
------------------
       2*:    8:  void inc () { b++; }
------------------
Foo<char>::inc():
function Foo<char>::inc() called 0 returned 0% blocks executed 0%
    #####:    8:  void inc () { b++; }
------------------
Foo<int>::inc():
function Foo<int>::inc() called 2 returned 100% blocks executed 100%
        2:    8:  void inc () { b++; }
------------------
        -:    9:
        -:   10:  private:
        -:   11:  int b;
        -:   12:};

<snip>

        -:   29:
       1*:   30:  int v = total > 100 ? 1 : 2;
branch  0 taken 0% (fallthrough)
branch  1 taken 100%

They explain:

Note that line 7 is shown in the report multiple times. First occurrence presents total number of execution of the line and the next two belong to instances of class Foo constructors. As you can also see, line 30 contains some unexecuted basic blocks and thus execution count has asterisk symbol.

That is really cool, but complicates parsing. This weekend I want to clean up the gcov parsing code. As part of that, I'll try to add a few GCC 8-related improvements:

  • If the execution count column ends with an asterisk, strip it – we parse branch counts explicitly.
  • Exclude the template specialization sections. Unfortunately there's no clear start and end. Each template section seems to start with a function name in the first column, which should look sufficiently different from source lines and tags.
  • If a line fails to be parsed, warn and continue. This may throw off single lines in the report, but will generally still be correct.

However, I don't have a way to test this myself. I'll update this issue if I have something that I believe might work ;-)

@ernestask

This comment has been minimized.

ernestask commented Feb 23, 2018

That’s awesome, thank you for looking into this. I haven’t had time to set up a testing environment properly, but I’ll test whatever you throw my way.

@ernestask

This comment has been minimized.

ernestask commented Feb 24, 2018

This one causes this error:

Traceback (most recent call last):
  File "/home/ernestas/.local/bin/gcovr", line 2412, in <module>
    process_datafile(file_, covdata, options)
  File "/home/ernestas/.local/bin/gcovr", line 884, in process_datafile
    process_gcov_data(fname, covdata, abs_filename, options)
  File "/home/ernestas/.local/bin/gcovr", line 616, in process_gcov_data
    covered[lineno] = int(segments[0].strip())
ValueError: invalid literal for int() with base 10: '2*'

And this one seems to be causing this error:

Traceback (most recent call last):
  File "/home/ernestas/.local/bin/gcovr", line 2412, in <module>
    process_datafile(file_, covdata, options)
  File "/home/ernestas/.local/bin/gcovr", line 884, in process_datafile
    process_gcov_data(fname, covdata, abs_filename, options)
  File "/home/ernestas/.local/bin/gcovr", line 601, in process_gcov_data
    code = segments[2].strip()
IndexError: list index out of range

Hope these files help.

@latk

This comment has been minimized.

Member

latk commented Feb 24, 2018

latk added a commit to latk/gcovr that referenced this issue Feb 24, 2018

gcov: support GCC 8 gcov format
See gcovr#226 for background.

At this opportunity, the parsing was made a bit more robust.

  - Any exceptions during parsing are swallowed.
    Parsing will always succeed, but may be garbage.
  - After parsing, failed lines and any exceptions are summarized.
  - These errors are shown always, not just in verbose mode.
  - The error message links directly to the Github issues.
@latk

This comment has been minimized.

Member

latk commented Feb 24, 2018

I've implemented something that should mostly work. Please install from my branch to test this:

pip install git+https://github.com/latk/gcovr.git@simplify-gcov

Gcovr should now always carry on even when there are parse errors, and will report problems on STDERR. Please let me know if there are remaining issues.

@ernestask

This comment has been minimized.

ernestask commented Feb 24, 2018

I don’t see anything in stderr and the coverage is as pathetic as ever (it works!). ;)

@latk

This comment has been minimized.

Member

latk commented Mar 6, 2018

OK, the changes have now been merged into master. You can use this feature by pip-installing the development version from this repository. A PyPI release is still some time away.

Thanks again for bringing this issue to my attention!

@latk latk closed this Mar 6, 2018

@ernestask

This comment has been minimized.

ernestask commented Mar 6, 2018

Cool, thanks for you work. :)

JamesReynolds pushed a commit to JamesReynolds/gcovr that referenced this issue Mar 8, 2018

gcov: support GCC 8 gcov format
See gcovr#226 for background.

At this opportunity, the parsing was made a bit more robust.

  - Any exceptions during parsing are swallowed.
    Parsing will always succeed, but may be garbage.
  - After parsing, failed lines and any exceptions are summarized.
  - These errors are shown always, not just in verbose mode.
  - The error message links directly to the Github issues.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment