diff --git a/cpp_coveralls/coverage.py b/cpp_coveralls/coverage.py index 4f2c6e3..905f911 100644 --- a/cpp_coveralls/coverage.py +++ b/cpp_coveralls/coverage.py @@ -260,7 +260,11 @@ def parse_gcov_file(args, fobj, filename): cov_num = report_fields[0].strip() line_num = int(line_num) text = report_fields[2] - if line_num == 0: + + # skip gcov meta data and + # repeated lines for instances(templated code), because the 1st occurence reports the total count, we can + # ignore the instance specializations + if line_num == 0 or line_num <= len(coverage): continue if re.search(r'\bLCOV_EXCL_START\b', text): if ignoring: diff --git a/cpp_coveralls/parse_gcov_test.py b/cpp_coveralls/parse_gcov_test.py new file mode 100644 index 0000000..c686181 --- /dev/null +++ b/cpp_coveralls/parse_gcov_test.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python +# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 +# + +import io +import unittest + +from . import coverage + + +class ParseGcovTest(unittest.TestCase): + # test template example from the documentation (https://gcc.gnu.org/onlinedocs/gcc/Invoking-Gcov.html#Invoking-Gcov) + def test_templated_coverage(self): + args = coverage.create_args("") + f = io.BytesIO(b""" + -: 0:Source:tmp.cpp + -: 0:Working directory:/home/gcc/testcase + -: 0:Graph:tmp.gcno + -: 0:Data:tmp.gcda + -: 0:Runs:1 + -: 0:Programs:1 + -: 1:#include + -: 2: + -: 3:template + -: 4:class Foo + -: 5:{ + -: 6: public: + 1*: 7: Foo(): b (1000) {} +------------------ +Foo::Foo(): + #####: 7: Foo(): b (1000) {} +------------------ +Foo::Foo(): + 1: 7: Foo(): b (1000) {} +------------------ + """) + parsed_lines = coverage.parse_gcov_file(args, f, "bar") + self.assertEqual(7, len(parsed_lines)) + self.assertEqual(1, parsed_lines[6])