Skip to content

Commit f50e215

Browse files
mkarleskyclaude
andcommitted
Gcov plugin: port confirmed bug fixes from the next_version review pass
Simple, targeted patches -- master's own (older, pre-delta-builds) code shape, no refactor or new unit-test infrastructure -- porting the bug fixes confirmed during the recent next_version Gcov plugin review (gcov-plugin-review branch). Manually validated via throwtheswitch/madsciencelab-plugins Docker plus one light new system-test case. - :gcov ↳ :gcovr ↳ :decisions version floor corrected 6.0 -> 5.1 -- gcovr's own changelog and a real gcovr 5.1/5.0 pip install confirm --decisions was introduced in 5.1, not 6.0. - :fail_under_* now rejects 0 (documented range is 1-100; 0 was silently accepted as a threshold that could never actually fail). - :object_directory/:source_encoding values are now quoted -- an unquoted value containing a space previously broke the constructed gcovr command line. - Regex-metacharacter-injection risk fixed in both :gcovr's and :report_generator's auto-generated exclusion patterns -- :test_file_prefix, :mock_prefix, and build-root path values are now Regexp.escape'd before being spliced into exclusion regexes. - :mcdc's GCC-version check moved out of Gcov#setup(), which runs for every build the plugin is merely enabled for, into a lazily-invoked, memoized check that fires only on a real gcov-context compile/link. - gcovr_exec_exception? now reports every simultaneously violated :fail_under_* threshold instead of only the first. - Added the missing .dup guard in ReportGeneratorReportinator#collect_reportgenerator_opts, mirroring the existing guard on the gcovr side. - gcovr 7.0+ deprecated flag migration: :branches/:sort_uncovered/ :sort_percentage now use --txt-metric branch/--sort uncovered-number/ --sort uncovered-percent at gcovr 7.0+, silencing gcovr's own deprecation warnings; the pre-7.0 names are still used automatically below that. - Removed dead code: gcovr_reportinator.rb set an internal :mcdc flag no code path ever read. Confirmed via Docker (gcovr 8.6) that --decisions has no effect on GCC's own condition/MC-DC data in either JSON or HTML -- gcovr's Condition-labeled content is byte-identical with and without it; only a separate, additive Decision column depends on the flag. - ConsoleReportinator#log_coverage_report: a Partial-implementation source whose gcov output can't be matched at all now logs the same "Found no coverage results" COMPLAIN the equivalent non-Partial case already did, instead of silently producing no report and no log. Explicitly not ported: the broader DRY refactor (ToolVersionGating, build_args_from_table, etc.) and the new unit-test suite from the next_version pass -- out of scope per plan (simple patches only); the ReportGenerator coverage-threshold feature -- a new feature, not a bug fix. New system-test case: project_with_gcov_fail_under_line_rejects_zero (spec/system/support/gcov_common_test_cases.rb), regression-locking the `0` rejection specifically, matching the existing project_with_gcov_fail_under_decision pattern from the #1080 fix. Small doc corrections alongside the code they describe: :decisions' "Requires" floor in gcovr.md/reference/gcov-plugin.md, and the :branches/:sort_uncovered/:sort_percentage deprecated-flag notes. Verified: full unit suite (1978 examples, 0 failures), mkdocs build --strict, and the full Gcov system-test suite (26 examples, 0 failures) via throwtheswitch/madsciencelab-plugins:1.1.6 Docker. No Changelog entry in this commit -- the 1.1.8 section (both branches) is a separate, later step. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent b1534f9 commit f50e215

8 files changed

Lines changed: 145 additions & 72 deletions

File tree

docs/mkdocs/plugins/gcov/gcovr.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ Report the decision coverage. For HTML, JSON, and the summary report.
128128

129129
Implied automatically whenever `:fail_under_decision` is set.
130130

131-
**Requires:** `gcovr` 6.0 or higher
131+
**Requires:** `gcovr` 5.1 or higher
132132

133133
---
134134

@@ -163,21 +163,26 @@ Select the source file character encoding. (`gcovr --source-encoding`)
163163
### `:branches`
164164

165165
Report the branch coverage instead of the line coverage. Applies to the text
166-
report only. (`gcovr --branches`)
166+
report only. Uses `gcovr --txt-metric branch` on `gcovr` 7.0+ (`--branches` is
167+
deprecated as of 7.0, though still functional); `gcovr --branches` below it.
167168

168169
---
169170

170171
### `:sort_uncovered`
171172

172173
Sort entries by increasing number of uncovered lines. Applies to text and HTML
173-
reports. (`gcovr --sort-uncovered`)
174+
reports. Uses `gcovr --sort uncovered-number` on `gcovr` 7.0+
175+
(`--sort-uncovered` is deprecated as of 7.0, though still functional);
176+
`gcovr --sort-uncovered` below it.
174177

175178
---
176179

177180
### `:sort_percentage`
178181

179182
Sort entries by increasing percentage of uncovered lines. Applies to text and
180-
HTML reports. (`gcovr --sort-percentage`)
183+
HTML reports. Uses `gcovr --sort uncovered-percent` on `gcovr` 7.0+
184+
(`--sort-percentage` is deprecated as of 7.0, though still functional);
185+
`gcovr --sort-percentage` below it.
181186

182187
---
183188

docs/mkdocs/reference/gcov-plugin.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ Report the decision coverage. For HTML, JSON, and the summary report.
229229

230230
Implied automatically whenever `:fail_under_decision` is set.
231231

232-
**Requires:** `gcovr` 6.0 or higher
232+
**Requires:** `gcovr` 5.1 or higher
233233

234234
---
235235

@@ -262,21 +262,26 @@ Source file character encoding. (`gcovr --source-encoding`)
262262
### `:branches`
263263

264264
Report branch coverage instead of line coverage. Applies to text reports only.
265-
(`gcovr --branches`)
265+
Uses `gcovr --txt-metric branch` on `gcovr` 7.0+ (`--branches` is deprecated as
266+
of 7.0, though still functional); `gcovr --branches` below it.
266267

267268
---
268269

269270
### `:sort_uncovered`
270271

271272
Sort report entries by increasing number of uncovered lines. Applies to text
272-
and HTML reports. (`gcovr --sort-uncovered`)
273+
and HTML reports. Uses `gcovr --sort uncovered-number` on `gcovr` 7.0+
274+
(`--sort-uncovered` is deprecated as of 7.0, though still functional);
275+
`gcovr --sort-uncovered` below it.
273276

274277
---
275278

276279
### `:sort_percentage`
277280

278281
Sort report entries by increasing percentage of uncovered lines. Applies to
279-
text and HTML reports. (`gcovr --sort-percentage`)
282+
text and HTML reports. Uses `gcovr --sort uncovered-percent` on `gcovr` 7.0+
283+
(`--sort-percentage` is deprecated as of 7.0, though still functional);
284+
`gcovr --sort-percentage` below it.
280285

281286
---
282287

plugins/gcov/lib/console_reportinator.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,13 @@ def log_coverage_report(test, source, results, gcov_source)
169169
section = section.reject { |line| line.include?( File.basename( source,'.*') ) }
170170
report = section.map { |line| report_name + ' | ' + line }.join('')
171171
@loginator.log( report )
172+
else
173+
# A Partial whose remapped name still doesn't match any File header in gcov's
174+
# output -- without this, a Partial's unparseable coverage silently produces no
175+
# report and no log at all, unlike the equivalent non-Partial case just below.
176+
@loginator.lazy( Verbosity::COMPLAIN ) do
177+
"Found no coverage results for #{test}::#{File.basename(source)}"
178+
end
172179
end
173180

174181
# Otherwise, found no coverage results

plugins/gcov/lib/gcov.rb

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -70,16 +70,12 @@ def setup
7070

7171
@mutex = Mutex.new()
7272

73-
# Validate MC/DC configuration against GCC version (only incurs gcc --version when :mcdc: TRUE)
74-
if @project_config[:gcov_mcdc]
75-
gcc_version = get_gcc_version()
76-
if gcc_version.major < 14
77-
raise CeedlingException.new(
78-
":gcov ↳ :mcdc ➡️ Modified condition/decision coverage requires GCC 14 or higher " \
79-
"(found #{gcc_version.major}.#{gcc_version.minor})"
80-
)
81-
end
82-
end
73+
# See validate_mcdc_gcc_version! below for why this isn't checked eagerly here --
74+
# setup() runs for every build this plugin is merely *enabled* for, not only real
75+
# gcov: builds. Shelling out to `gcc --version` here would make GCC-version
76+
# validation (and a build-breaking exception on too-old a GCC) fire even for builds
77+
# that never touch :mcdc at all, e.g. plain `test:all`.
78+
@mcdc_gcc_checked = false
8379
end
8480

8581
# Called within class and also externally by plugin Rakefile
@@ -179,6 +175,8 @@ def pre_compile_execute(arg_hash)
179175

180176
# Compile all non-assembly files with coverage; gcovr --exclude filters non-production files from reports
181177
if File.extname(source) != EXTENSION_ASSEMBLY
178+
validate_mcdc_gcc_version!
179+
182180
arg_hash[:tool] = TOOLS_GCOV_COMPILER
183181
arg_hash[:msg] = @reportinator.generate_module_progress(
184182
operation: "Compiling with coverage",
@@ -192,6 +190,8 @@ def pre_compile_execute(arg_hash)
192190

193191
def pre_link_execute(arg_hash)
194192
if arg_hash[:context] == GCOV_SYM
193+
validate_mcdc_gcc_version!
194+
195195
@cli_gcov_task = true
196196
arg_hash[:tool] = TOOLS_GCOV_LINKER
197197
arg_hash[:flags] += ['-fcondition-coverage'] if @project_config[:gcov_mcdc]
@@ -364,6 +364,25 @@ def build_reportinators(config)
364364
return reportinators
365365
end
366366

367+
# Lazily validates :mcdc against the installed GCC version -- called from every
368+
# gcov-context build hook that could otherwise emit -fcondition-coverage (compile,
369+
# link), memoized so `gcc --version` runs at most once regardless of how many source
370+
# files or hooks fire before it. See setup()'s own comment for why this isn't checked
371+
# eagerly there.
372+
def validate_mcdc_gcc_version!
373+
return if @mcdc_gcc_checked
374+
@mcdc_gcc_checked = true
375+
return unless @project_config[:gcov_mcdc]
376+
377+
gcc_version = get_gcc_version()
378+
if gcc_version.major < 14
379+
raise CeedlingException.new(
380+
":gcov ↳ :mcdc ➡️ Modified condition/decision coverage requires GCC 14 or higher " \
381+
"(found #{gcc_version.major}.#{gcc_version.minor})"
382+
)
383+
end
384+
end
385+
367386
def get_gcc_version()
368387
command = @tool_executor.build_command_line( TOOLS_GCOV_GCC_VERSION, [])
369388

plugins/gcov/lib/gcovr_reportinator.rb

Lines changed: 62 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,12 @@ def initialize(system_objects, config)
6666
)
6767
end
6868

69-
if gcovr_opts[:decisions] && !min_version?( @gcovr_version, 6, 0 )
69+
# --decisions was introduced in gcovr 5.1, not 6.0 -- confirmed directly against
70+
# gcovr's own changelog and a real gcovr 5.1/5.0 install (5.1 accepts --decisions
71+
# and proceeds; 5.0 rejects it outright as unrecognized).
72+
if gcovr_opts[:decisions] && !min_version?( @gcovr_version, 5, 1 )
7073
raise CeedlingException.new(
71-
":gcov ↳ :gcovr ↳ :decisions ➡️ requires gcovr 6 or higher " \
74+
":gcov ↳ :gcovr ↳ :decisions ➡️ requires gcovr 5.1 or higher " \
7275
"(found #{@gcovr_version.major}.#{@gcovr_version.minor})"
7376
)
7477
end
@@ -116,9 +119,18 @@ def args_builder_common(gcovr_opts, gcovr_version)
116119
args += "--gcov-filter \"#{gcovr_opts[:gcov_filter]}\" " unless gcovr_opts[:gcov_filter].nil?
117120
args += "--gcov-exclude \"#{gcovr_opts[:gcov_exclude]}\" " unless gcovr_opts[:gcov_exclude].nil?
118121
args += "--exclude-directories \"#{gcovr_opts[:exclude_directories]}\" " unless gcovr_opts[:exclude_directories].nil?
119-
args += "--branches " if gcovr_opts[:branches]
120-
args += "--sort-uncovered " if gcovr_opts[:sort_uncovered]
121-
args += "--sort-percentage " if gcovr_opts[:sort_percentage]
122+
# gcovr 7.0 deprecated --branches/--sort-uncovered/--sort-percentage in favor of
123+
# these renamed equivalents (still functional, but warn, below 7.0); use whichever
124+
# form the detected gcovr_version actually expects.
125+
if gcovr_opts[:branches]
126+
args += (min_version?(gcovr_version, 7, 0) ? "--txt-metric branch " : "--branches ")
127+
end
128+
if gcovr_opts[:sort_uncovered]
129+
args += (min_version?(gcovr_version, 7, 0) ? "--sort uncovered-number " : "--sort-uncovered ")
130+
end
131+
if gcovr_opts[:sort_percentage]
132+
args += (min_version?(gcovr_version, 7, 0) ? "--sort uncovered-percent " : "--sort-percentage ")
133+
end
122134
args += "--print-summary " if gcovr_opts[:print_summary]
123135
args += "--gcov-executable \"#{gcovr_opts[:gcov_executable]}\" " unless gcovr_opts[:gcov_executable].nil?
124136
args += "--exclude-unreachable-branches " if gcovr_opts[:exclude_unreachable_branches]
@@ -152,18 +164,24 @@ def args_builder_common(gcovr_opts, gcovr_version)
152164
next if gcovr_opts[opt].nil?
153165

154166
value = gcovr_opts[opt]
155-
167+
156168
# Value sanity checks for :fail_under_* settings
157169
if opt.to_s =~ /fail_/
158170
if not value.is_a? Integer
159171
raise CeedlingException.new(":gcov ↳ :gcovr ↳ :#{opt} ➡️ '#{value}' must be an integer")
160-
elsif (value < 0) || (value > 100)
161-
raise CeedlingException.new(":gcov ↳ :gcovr ↳ :#{opt} ➡️ '#{value}' must be an integer percentage 0 – 100")
172+
elsif (value < 1) || (value > 100)
173+
raise CeedlingException.new(":gcov ↳ :gcovr ↳ :#{opt} ➡️ '#{value}' must be an integer percentage 1 – 100")
162174
end
163175
end
164-
165-
# If the YAML key has a value, trasnform key into command line argument with value and concatenate
166-
args += "--#{opt.to_s.gsub('_','-')} #{value} " unless value.nil?
176+
177+
# :source_encoding/:object_directory are quoted (unlike the already-validated,
178+
# always-integer :fail_under_* values) so a value containing a space doesn't
179+
# break the constructed command line.
180+
if [:source_encoding, :object_directory].include?(opt)
181+
args += "--#{opt.to_s.gsub('_','-')} \"#{value}\" " unless value.nil?
182+
else
183+
args += "--#{opt.to_s.gsub('_','-')} #{value} " unless value.nil?
184+
end
167185
end
168186

169187
return args
@@ -409,30 +427,42 @@ def collect_gcovr_opts(opts)
409427
_opts[:report_exclude] = excludes unless excludes.empty?
410428
end
411429

412-
_opts[:mcdc] = true if opts[:gcov_mcdc]
430+
# No :mcdc-specific gcovr flag to set here -- GCC's own condition/MC-DC data flows
431+
# into gcovr's reports unconditionally, in every format, regardless of --decisions
432+
# (confirmed directly: gcovr's Condition-labeled HTML/JSON content is byte-identical
433+
# with and without --decisions; that flag only adds its own separate, additive
434+
# Decision data alongside it). :mcdc's own gcovr-version floor is still enforced in
435+
# initialize -- there's just nothing more for gcovr's own CLI args to do here.
413436

414437
return _opts
415438
end
416439

417440

418441
# Build a combined Python regex for gcovr's `--exclude` flag covering all
419442
# non-production file categories: test files, support files, and generated/framework files.
443+
# Path/prefix values are config-driven, so they're Regexp-escaped -- interpolated raw, a
444+
# metacharacter (e.g. a literal '.') in a project's own path would silently over- or
445+
# under-match.
420446
def build_report_exclusions
421447
data = build_exclusion_data
422448
patterns = []
423449

450+
test_prefix = Regexp.escape(data[:test_prefix].to_s)
451+
build_root = Regexp.escape(data[:build_root].to_s)
452+
src_extension = Regexp.escape(data[:src_extension].to_s)
453+
424454
data[:test_paths].each do |path|
425455
# Test files (e.g. test_foo.c)
426-
patterns << ".*#{path}.*/#{data[:test_prefix]}.+\\#{data[:src_extension]}$"
456+
patterns << ".*#{Regexp.escape(path)}.*/#{test_prefix}.+\\#{src_extension}$"
427457
end
428458

429459
# Support files (e.g. helpers, stubs, fixtures) — never production source
430460
data[:support_paths].each do |path|
431-
patterns << ".*#{path}/.+\\#{data[:src_extension]}$"
461+
patterns << ".*#{Regexp.escape(path)}/.+\\#{src_extension}$"
432462
end
433463

434464
# Any generated files for tests or vendored framework C source files below the root of the build directory
435-
patterns << ".*#{data[:build_root]}/.+\\#{EXTENSION_CORE_SOURCE}$"
465+
patterns << ".*#{build_root}/.+\\#{EXTENSION_CORE_SOURCE}$"
436466

437467
return patterns
438468
end
@@ -535,59 +565,43 @@ def min_version?(version, major, minor)
535565

536566
# Output to console a human-friendly message on certain coverage failure exit codes.
537567
# Prefers the actual gcovr error text from stderr; falls back to descriptive strings.
538-
# Perform the logic on whether to raise an exception
568+
# gcovr's composite exit code bit-ORs every violated :fail_under_* threshold together --
569+
# every violated bit is collected and reported, not just whichever is checked first.
539570
def gcovr_exec_exception?(opts, exitcode, boom, shell_result=nil)
571+
violations = []
540572

541573
# Special handling of exit code 2 with --fail-under-line
542574
if ((exitcode & 2) == 2) and !opts[:fail_under_line].nil?
543575
fallback = "Line coverage is less than the configured minimum of #{opts[:fail_under_line]}%"
544-
msg = "Gcovr ⏩️ #{extract_gcovr_error_message( shell_result ) || fallback}"
545-
if boom
546-
raise CeedlingException.new(msg)
547-
else
548-
@loginator.log( msg, Verbosity::COMPLAIN )
549-
# Clear bit in exit code
550-
exitcode &= ~2
551-
end
576+
violations << "Gcovr ⏩️ #{extract_gcovr_error_message( shell_result ) || fallback}"
577+
exitcode &= ~2
552578
end
553579

554580
# Special handling of exit code 4 with --fail-under-branch
555581
if ((exitcode & 4) == 4) and !opts[:fail_under_branch].nil?
556582
fallback = "Branch coverage is less than the configured minimum of #{opts[:fail_under_branch]}%"
557-
msg = "Gcovr ⏩️ #{extract_gcovr_error_message( shell_result ) || fallback}"
558-
if boom
559-
raise CeedlingException.new(msg)
560-
else
561-
@loginator.log( msg, Verbosity::COMPLAIN )
562-
# Clear bit in exit code
563-
exitcode &= ~4
564-
end
583+
violations << "Gcovr ⏩️ #{extract_gcovr_error_message( shell_result ) || fallback}"
584+
exitcode &= ~4
565585
end
566586

567587
# Special handling of exit code 8 with --fail-under-decision
568588
if ((exitcode & 8) == 8) and !opts[:fail_under_decision].nil?
569589
fallback = "Decision coverage is less than the configured minimum of #{opts[:fail_under_decision]}%"
570-
msg = "Gcovr ⏩️ #{extract_gcovr_error_message( shell_result ) || fallback}"
571-
if boom
572-
raise CeedlingException.new(msg)
573-
else
574-
@loginator.log( msg, Verbosity::COMPLAIN )
575-
# Clear bit in exit code
576-
exitcode &= ~8
577-
end
590+
violations << "Gcovr ⏩️ #{extract_gcovr_error_message( shell_result ) || fallback}"
591+
exitcode &= ~8
578592
end
579593

580594
# Special handling of exit code 16 with --fail-under-function
581595
if ((exitcode & 16) == 16) and !opts[:fail_under_function].nil?
582596
fallback = "Function coverage is less than the configured minimum of #{opts[:fail_under_function]}%"
583-
msg = "Gcovr ⏩️ #{extract_gcovr_error_message( shell_result ) || fallback}"
584-
if boom
585-
raise CeedlingException.new(msg)
586-
else
587-
@loginator.log( msg, Verbosity::COMPLAIN )
588-
# Clear bit in exit code
589-
exitcode &= ~16
590-
end
597+
violations << "Gcovr ⏩️ #{extract_gcovr_error_message( shell_result ) || fallback}"
598+
exitcode &= ~16
599+
end
600+
601+
if boom
602+
raise CeedlingException.new( violations.join("\n") ) unless violations.empty?
603+
else
604+
violations.each { |msg| @loginator.log( msg, Verbosity::COMPLAIN ) }
591605
end
592606

593607
# A non-zero exit code is a problem

plugins/gcov/lib/reportgenerator_reportinator.rb

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,9 @@ def build_optional_args(rg_opts, report_type_count)
128128

129129
# Get the ReportGenerator options from the project options.
130130
def collect_reportgenerator_opts(opts)
131-
_opts = opts[REPORT_GENERATOR_SETTING_PREFIX.to_sym]
131+
# dup prevents repeated calls from accumulating mutations on the shared opts hash --
132+
# mirrors GcovrReportinator#collect_gcovr_opts' identical guard and rationale.
133+
_opts = opts[REPORT_GENERATOR_SETTING_PREFIX.to_sym].dup
132134

133135
# Auto-generate -filefilters: exclusion patterns for test paths and the build root.
134136
# These exclude test files and all generated/framework files from coverage reports.
@@ -275,17 +277,19 @@ def build_filefilter_exclusions
275277
# Build filename-fragment patterns for the .gcno scan exclusion regex.
276278
# Excludes test files, generated mocks, and test runners from gcov processing.
277279
# The '.*' suffix handles source extensions embedded in .gcno filenames (e.g. test_foo.c.gcno).
280+
# test_prefix/mock_prefix are config-driven, so they're Regexp-escaped -- unescaped, a
281+
# metacharacter in either (e.g. a literal '.') would silently over- or under-match.
278282
def build_gcno_exclusions
279283
data = build_exclusion_data
280284
# Use [^\/\\]* (no path separators) rather than .* to match filenames only.
281285
# Ceedling names build output dirs after test files (e.g. build/gcov/out/test_foo/),
282286
# so .* would greedily match test_foo/bar.c and exclude ALL production sources.
283287
[
284-
"#{data[:test_prefix]}[^\\/\\\\]*", # test_foo.gcno
285-
"#{data[:mock_prefix]}[^\\/\\\\]*", # MockBar.gcno
286-
"[^\\/\\\\]*_runner[^\\/\\\\]*", # test_foo_runner.gcno
287-
File.basename(UNITY_C_FILE, '.*'), # unity.gcno
288-
File.basename(CMOCK_C_FILE, '.*') # cmock.gcno
288+
"#{Regexp.escape(data[:test_prefix].to_s)}[^\\/\\\\]*", # test_foo.gcno
289+
"#{Regexp.escape(data[:mock_prefix].to_s)}[^\\/\\\\]*", # MockBar.gcno
290+
"[^\\/\\\\]*_runner[^\\/\\\\]*", # test_foo_runner.gcno
291+
Regexp.escape(File.basename(UNITY_C_FILE, '.*')), # unity.gcno
292+
Regexp.escape(File.basename(CMOCK_C_FILE, '.*')) # cmock.gcno
289293
]
290294
end
291295

spec/system/gcov_deployment_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
test_case :project_with_gcov_success
3838
test_case :project_with_gcov_fail
3939
test_case :project_with_gcov_fail_under_decision
40+
test_case :project_with_gcov_fail_under_line_rejects_zero
4041
test_case :gcov_console_report_with_system_header
4142
test_case :gcov_console_report_with_partial
4243
# TODO: Restore these tests when the :abort_on_uncovered option is restored in the Gcov plugin

0 commit comments

Comments
 (0)