ceedling 1.1.6 → 1.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/GIT_COMMIT_SHA +1 -1
- data/Gemfile +4 -0
- data/Gemfile.lock +2 -0
- data/README.md +4 -1
- data/docs/Changelog.md +41 -0
- data/docs/KnownIssues.md +3 -0
- data/docs/mkdocs/configuration/project-file.md +25 -7
- data/docs/mkdocs/configuration/reference/cexception.md +1 -1
- data/docs/mkdocs/configuration/reference/cmock.md +1 -1
- data/docs/mkdocs/configuration/reference/unity.md +1 -1
- data/docs/mkdocs/getting-started/quick-start.md +11 -8
- data/docs/mkdocs/plugins/gcov/gcovr.md +329 -189
- data/docs/mkdocs/plugins/gcov/reportgenerator.md +113 -31
- data/docs/mkdocs/reference/gcov-plugin.md +29 -6
- data/docs/mkdocs/snapshot/plugins/gcov/config/defaults.yml +0 -1
- data/lib/ceedling/c_extractor/c_extractor_declarations.rb +11 -10
- data/lib/ceedling/c_extractor/c_extractor_preprocessing.rb +39 -2
- data/lib/ceedling/generators/generator_test_results_backtrace.rb +21 -11
- data/lib/ceedling/generators/generator_test_runner.rb +5 -1
- data/lib/ceedling/plugins/plugin_reportinator.rb +9 -0
- data/lib/ceedling/plugins/report_tests_stdout_plugin.rb +1 -1
- data/lib/ceedling/preprocess/preprocessinator_line_marker_includes_extractor.rb +6 -1
- data/lib/ceedling/preprocess/preprocessinator_reconstructor.rb +18 -5
- data/lib/version.rb +1 -1
- data/plugins/gcov/config/defaults.yml +0 -1
- data/plugins/gcov/lib/console_reportinator.rb +7 -0
- data/plugins/gcov/lib/gcov.rb +64 -26
- data/plugins/gcov/lib/gcovr_reportinator.rb +91 -47
- data/plugins/gcov/lib/reportgenerator_reportinator.rb +10 -6
- data/plugins/valgrind/lib/valgrind.rb +1 -1
- data/site-local/configuration/project-file.html +78 -8
- data/site-local/configuration/reference/cexception.html +5 -5
- data/site-local/configuration/reference/cmock.html +5 -5
- data/site-local/configuration/reference/unity.html +5 -5
- data/site-local/getting-started/quick-start.html +13 -9
- data/site-local/plugins/gcov/gcovr.html +1220 -255
- data/site-local/plugins/gcov/reportgenerator.html +404 -46
- data/site-local/reference/gcov-plugin.html +48 -10
- data/site-local/sitemap.xml.gz +0 -0
- data/site-local/snapshot/plugins/gcov/config/defaults.yml +0 -1
- data/spec/support/system/system_context.rb +7 -3
- data/spec/system/deployment_as_gem_spec.rb +2 -0
- data/spec/system/deployment_as_vendor_spec.rb +2 -0
- data/spec/system/gcov_deployment_spec.rb +3 -0
- data/spec/system/support/common_test_cases.rb +42 -0
- data/spec/system/support/gcov_common_test_cases.rb +70 -0
- data/spec/units/c_extractor/c_extractor_declarations_spec.rb +16 -0
- data/spec/units/c_extractor/c_extractor_integration_spec.rb +53 -0
- data/spec/units/c_extractor/c_extractor_preprocessing_spec.rb +45 -0
- data/spec/units/generators/generator_partials_spec.rb +98 -0
- data/spec/units/generators/generator_test_results_backtrace_spec.rb +77 -0
- data/spec/units/generators/generator_test_runner_spec.rb +23 -0
- data/spec/units/plugin_reportinator_spec.rb +38 -0
- data/spec/units/preprocess/preprocessinator_line_marker_includes_extractor_spec.rb +64 -0
- data/spec/units/preprocess/preprocessinator_reconstructor_spec.rb +74 -0
- metadata +6 -2
data/plugins/gcov/lib/gcov.rb
CHANGED
|
@@ -40,11 +40,19 @@ class Gcov < Plugin
|
|
|
40
40
|
)
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
# Validate
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
# #1252 -- Validate `:gcov ↳ :utilities` config (cheap, no external tool needed) and
|
|
44
|
+
# build the console summary Reportinator (needs no external tool of its own) here,
|
|
45
|
+
# eagerly, since `setup()` runs for every build this plugin is merely *enabled* for,
|
|
46
|
+
# not only real `gcov:` builds. Deliberately NOT building the gcovr/ReportGenerator
|
|
47
|
+
# Reportinators here -- doing so validates gcovr/ReportGenerator are installed
|
|
48
|
+
# (see their own constructors), which would make either a hard dependency of any
|
|
49
|
+
# build at all (e.g. plain `test:all`) rather than only a real `gcov:` build. See
|
|
50
|
+
# generate_coverage_reports, which builds (and so validates) them lazily, only once
|
|
51
|
+
# post_build already knows a gcov: task actually ran.
|
|
52
|
+
validate_utilities_config( @project_config[:gcov_utilities] )
|
|
53
|
+
@console_reportinator = summaries_enabled?( @project_config ) ?
|
|
54
|
+
ConsoleReportinator.new( @ceedling, @project_config ) : nil
|
|
55
|
+
@reportinators = nil
|
|
48
56
|
|
|
49
57
|
# Convenient instance variable references
|
|
50
58
|
@configurator = @ceedling[:configurator]
|
|
@@ -62,16 +70,12 @@ class Gcov < Plugin
|
|
|
62
70
|
|
|
63
71
|
@mutex = Mutex.new()
|
|
64
72
|
|
|
65
|
-
#
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
"(found #{gcc_version.major}.#{gcc_version.minor})"
|
|
72
|
-
)
|
|
73
|
-
end
|
|
74
|
-
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
|
|
75
79
|
end
|
|
76
80
|
|
|
77
81
|
# Called within class and also externally by plugin Rakefile
|
|
@@ -171,6 +175,8 @@ class Gcov < Plugin
|
|
|
171
175
|
|
|
172
176
|
# Compile all non-assembly files with coverage; gcovr --exclude filters non-production files from reports
|
|
173
177
|
if File.extname(source) != EXTENSION_ASSEMBLY
|
|
178
|
+
validate_mcdc_gcc_version!
|
|
179
|
+
|
|
174
180
|
arg_hash[:tool] = TOOLS_GCOV_COMPILER
|
|
175
181
|
arg_hash[:msg] = @reportinator.generate_module_progress(
|
|
176
182
|
operation: "Compiling with coverage",
|
|
@@ -184,6 +190,8 @@ class Gcov < Plugin
|
|
|
184
190
|
|
|
185
191
|
def pre_link_execute(arg_hash)
|
|
186
192
|
if arg_hash[:context] == GCOV_SYM
|
|
193
|
+
validate_mcdc_gcc_version!
|
|
194
|
+
|
|
187
195
|
@cli_gcov_task = true
|
|
188
196
|
arg_hash[:tool] = TOOLS_GCOV_LINKER
|
|
189
197
|
arg_hash[:flags] += ['-fcondition-coverage'] if @project_config[:gcov_mcdc]
|
|
@@ -214,7 +222,7 @@ class Gcov < Plugin
|
|
|
214
222
|
results: results
|
|
215
223
|
}
|
|
216
224
|
|
|
217
|
-
verbosity =
|
|
225
|
+
verbosity = @plugin_reportinator.test_results_floor_verbosity
|
|
218
226
|
|
|
219
227
|
# Print unit test suite results
|
|
220
228
|
@plugin_reportinator.run_test_results_report( hash, verbosity )
|
|
@@ -257,6 +265,15 @@ class Gcov < Plugin
|
|
|
257
265
|
def generate_coverage_reports()
|
|
258
266
|
return if not @reports_enabled
|
|
259
267
|
|
|
268
|
+
# #1252 -- Lazily build (and so validate the external tools of) the gcovr/
|
|
269
|
+
# ReportGenerator Reportinators only now: this method only runs from post_build
|
|
270
|
+
# (automatic reporting) or the standalone `gcov:report` task (manual reporting,
|
|
271
|
+
# mutually exclusive with automatic per :gcov_report_task) -- either way, only
|
|
272
|
+
# once a real gcov: task is confirmed to have already run. See setup()'s own
|
|
273
|
+
# comment for why this can't happen any earlier. `||=` just guards against ever
|
|
274
|
+
# rebuilding (and so re-validating) on a hypothetical repeat call.
|
|
275
|
+
@reportinators ||= build_reportinators( @project_config[:gcov_utilities] )
|
|
276
|
+
|
|
260
277
|
@reportinators.each do |reportinator|
|
|
261
278
|
# Create the artifacts output directory.
|
|
262
279
|
@file_wrapper.mkdir( reportinator.artifacts_path ) if reportinator.artifacts_path
|
|
@@ -312,16 +329,10 @@ class Gcov < Plugin
|
|
|
312
329
|
return sources - tested_sources
|
|
313
330
|
end
|
|
314
331
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
@console_reportinator = summaries_enabled?(@project_config) ?
|
|
320
|
-
ConsoleReportinator.new(@ceedling, @project_config) : nil
|
|
321
|
-
|
|
322
|
-
# Do not instantiate file reportinators (and tool validation) unless reports enabled
|
|
323
|
-
return reportinators if (!enabled)
|
|
324
|
-
|
|
332
|
+
# Fail fast at plugin setup if :utilities holds an unrecognized name (e.g. a typo) --
|
|
333
|
+
# cheap, config-shape-only validation, so this stays eager even though the actual
|
|
334
|
+
# Reportinators it names are built lazily (see build_reportinators, generate_coverage_reports).
|
|
335
|
+
def validate_utilities_config(config)
|
|
325
336
|
config.each do |reportinator|
|
|
326
337
|
if not GCOV_UTILITY_NAMES.map(&:upcase).include?( reportinator.upcase )
|
|
327
338
|
options = GCOV_UTILITY_NAMES.map{ |utility| "'#{utility}'" }.join(', ')
|
|
@@ -329,6 +340,14 @@ class Gcov < Plugin
|
|
|
329
340
|
raise CeedlingException.new(msg)
|
|
330
341
|
end
|
|
331
342
|
end
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
# #1252 -- Deliberately not called from setup(); see its own comment and
|
|
346
|
+
# generate_coverage_reports, the only caller. Constructing GcovrReportinator/
|
|
347
|
+
# ReportGeneratorReportinator validates gcovr/ReportGenerator are installed, so this
|
|
348
|
+
# can only run once a real gcov: task is confirmed to have run.
|
|
349
|
+
def build_reportinators(config)
|
|
350
|
+
reportinators = []
|
|
332
351
|
|
|
333
352
|
# Run reports using gcovr
|
|
334
353
|
if utility_enabled?( config, GCOV_UTILITY_NAME_GCOVR )
|
|
@@ -345,6 +364,25 @@ class Gcov < Plugin
|
|
|
345
364
|
return reportinators
|
|
346
365
|
end
|
|
347
366
|
|
|
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
|
+
|
|
348
386
|
def get_gcc_version()
|
|
349
387
|
command = @tool_executor.build_command_line( TOOLS_GCOV_GCC_VERSION, [])
|
|
350
388
|
|
|
@@ -50,6 +50,31 @@ class GcovrReportinator < GcovReportinator
|
|
|
50
50
|
"(found #{@gcovr_version.major}.#{@gcovr_version.minor})"
|
|
51
51
|
)
|
|
52
52
|
end
|
|
53
|
+
|
|
54
|
+
# --decisions requires gcovr 6+; --fail-under-decision (which depends on --decisions)
|
|
55
|
+
# is a distinct, later addition requiring gcovr 7+ -- confirmed directly against real
|
|
56
|
+
# gcovr 6.0, which rejects --fail-under-decision outright as an unrecognized argument.
|
|
57
|
+
# Raised here, upfront, rather than left to surface as gcovr's own opaque CLI error or
|
|
58
|
+
# silently dropped -- either of which would leave a configured coverage threshold
|
|
59
|
+
# quietly never actually checked.
|
|
60
|
+
gcovr_opts = @config[GCOVR_SETTING_PREFIX.to_sym] || {}
|
|
61
|
+
|
|
62
|
+
if !gcovr_opts[:fail_under_decision].nil? && !min_version?( @gcovr_version, 7, 0 )
|
|
63
|
+
raise CeedlingException.new(
|
|
64
|
+
":gcov ↳ :gcovr ↳ :fail_under_decision ➡️ requires gcovr 7 or higher " \
|
|
65
|
+
"(found #{@gcovr_version.major}.#{@gcovr_version.minor})"
|
|
66
|
+
)
|
|
67
|
+
end
|
|
68
|
+
|
|
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 )
|
|
73
|
+
raise CeedlingException.new(
|
|
74
|
+
":gcov ↳ :gcovr ↳ :decisions ➡️ requires gcovr 5.1 or higher " \
|
|
75
|
+
"(found #{@gcovr_version.major}.#{@gcovr_version.minor})"
|
|
76
|
+
)
|
|
77
|
+
end
|
|
53
78
|
end
|
|
54
79
|
|
|
55
80
|
# Generate the gcovr report(s) specified in the options.
|
|
@@ -94,9 +119,18 @@ class GcovrReportinator < GcovReportinator
|
|
|
94
119
|
args += "--gcov-filter \"#{gcovr_opts[:gcov_filter]}\" " unless gcovr_opts[:gcov_filter].nil?
|
|
95
120
|
args += "--gcov-exclude \"#{gcovr_opts[:gcov_exclude]}\" " unless gcovr_opts[:gcov_exclude].nil?
|
|
96
121
|
args += "--exclude-directories \"#{gcovr_opts[:exclude_directories]}\" " unless gcovr_opts[:exclude_directories].nil?
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
|
100
134
|
args += "--print-summary " if gcovr_opts[:print_summary]
|
|
101
135
|
args += "--gcov-executable \"#{gcovr_opts[:gcov_executable]}\" " unless gcovr_opts[:gcov_executable].nil?
|
|
102
136
|
args += "--exclude-unreachable-branches " if gcovr_opts[:exclude_unreachable_branches]
|
|
@@ -112,6 +146,14 @@ class GcovrReportinator < GcovReportinator
|
|
|
112
146
|
args += "--merge-mode-functions \"#{gcovr_opts[:merge_mode_function]}\" " unless gcovr_opts[:merge_mode_function].nil?
|
|
113
147
|
end
|
|
114
148
|
|
|
149
|
+
# --fail-under-decision is a no-op to gcovr without --decisions also present (that's
|
|
150
|
+
# what actually turns decision-coverage analysis on) -- :fail_under_decision implies
|
|
151
|
+
# it automatically so the threshold option can never be configured into silently
|
|
152
|
+
# failing outright. initialize already guarantees gcovr 6+ whenever either is set
|
|
153
|
+
# (7+ specifically whenever :fail_under_decision is set), matching this method's own
|
|
154
|
+
# 6+ gate above.
|
|
155
|
+
args += "--decisions " if gcovr_opts[:decisions] || !gcovr_opts[:fail_under_decision].nil?
|
|
156
|
+
|
|
115
157
|
[:fail_under_line,
|
|
116
158
|
:fail_under_branch,
|
|
117
159
|
:fail_under_decision,
|
|
@@ -122,18 +164,24 @@ class GcovrReportinator < GcovReportinator
|
|
|
122
164
|
next if gcovr_opts[opt].nil?
|
|
123
165
|
|
|
124
166
|
value = gcovr_opts[opt]
|
|
125
|
-
|
|
167
|
+
|
|
126
168
|
# Value sanity checks for :fail_under_* settings
|
|
127
169
|
if opt.to_s =~ /fail_/
|
|
128
170
|
if not value.is_a? Integer
|
|
129
171
|
raise CeedlingException.new(":gcov ↳ :gcovr ↳ :#{opt} ➡️ '#{value}' must be an integer")
|
|
130
|
-
elsif (value <
|
|
131
|
-
raise CeedlingException.new(":gcov ↳ :gcovr ↳ :#{opt} ➡️ '#{value}' must be an integer percentage
|
|
172
|
+
elsif (value < 1) || (value > 100)
|
|
173
|
+
raise CeedlingException.new(":gcov ↳ :gcovr ↳ :#{opt} ➡️ '#{value}' must be an integer percentage 1 – 100")
|
|
132
174
|
end
|
|
133
175
|
end
|
|
134
|
-
|
|
135
|
-
#
|
|
136
|
-
|
|
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
|
|
137
185
|
end
|
|
138
186
|
|
|
139
187
|
return args
|
|
@@ -327,7 +375,7 @@ class GcovrReportinator < GcovReportinator
|
|
|
327
375
|
# configuration must come from the gcovr configuration file itself.
|
|
328
376
|
IGNORED_WHEN_CONFIG_FILE_SET = [
|
|
329
377
|
:report_include, :report_exclude, :gcov_filter, :gcov_exclude, :exclude_directories,
|
|
330
|
-
:branches, :sort_uncovered, :sort_percentage, :print_summary, :gcov_executable,
|
|
378
|
+
:branches, :decisions, :sort_uncovered, :sort_percentage, :print_summary, :gcov_executable,
|
|
331
379
|
:exclude_unreachable_branches, :exclude_throw_branches, :use_gcov_files, :gcov_ignore_parse_errors,
|
|
332
380
|
:keep, :delete, :threads, :merge_mode_function,
|
|
333
381
|
:fail_under_line, :fail_under_branch, :fail_under_decision, :fail_under_function,
|
|
@@ -379,7 +427,12 @@ class GcovrReportinator < GcovReportinator
|
|
|
379
427
|
_opts[:report_exclude] = excludes unless excludes.empty?
|
|
380
428
|
end
|
|
381
429
|
|
|
382
|
-
|
|
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.
|
|
383
436
|
|
|
384
437
|
return _opts
|
|
385
438
|
end
|
|
@@ -387,22 +440,29 @@ class GcovrReportinator < GcovReportinator
|
|
|
387
440
|
|
|
388
441
|
# Build a combined Python regex for gcovr's `--exclude` flag covering all
|
|
389
442
|
# 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.
|
|
390
446
|
def build_report_exclusions
|
|
391
447
|
data = build_exclusion_data
|
|
392
448
|
patterns = []
|
|
393
449
|
|
|
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
|
+
|
|
394
454
|
data[:test_paths].each do |path|
|
|
395
455
|
# Test files (e.g. test_foo.c)
|
|
396
|
-
patterns << ".*#{path}.*/#{
|
|
456
|
+
patterns << ".*#{Regexp.escape(path)}.*/#{test_prefix}.+\\#{src_extension}$"
|
|
397
457
|
end
|
|
398
458
|
|
|
399
459
|
# Support files (e.g. helpers, stubs, fixtures) — never production source
|
|
400
460
|
data[:support_paths].each do |path|
|
|
401
|
-
patterns << ".*#{path}/.+\\#{
|
|
461
|
+
patterns << ".*#{Regexp.escape(path)}/.+\\#{src_extension}$"
|
|
402
462
|
end
|
|
403
463
|
|
|
404
464
|
# Any generated files for tests or vendored framework C source files below the root of the build directory
|
|
405
|
-
patterns << ".*#{
|
|
465
|
+
patterns << ".*#{build_root}/.+\\#{EXTENSION_CORE_SOURCE}$"
|
|
406
466
|
|
|
407
467
|
return patterns
|
|
408
468
|
end
|
|
@@ -505,59 +565,43 @@ class GcovrReportinator < GcovReportinator
|
|
|
505
565
|
|
|
506
566
|
# Output to console a human-friendly message on certain coverage failure exit codes.
|
|
507
567
|
# Prefers the actual gcovr error text from stderr; falls back to descriptive strings.
|
|
508
|
-
#
|
|
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.
|
|
509
570
|
def gcovr_exec_exception?(opts, exitcode, boom, shell_result=nil)
|
|
571
|
+
violations = []
|
|
510
572
|
|
|
511
573
|
# Special handling of exit code 2 with --fail-under-line
|
|
512
574
|
if ((exitcode & 2) == 2) and !opts[:fail_under_line].nil?
|
|
513
575
|
fallback = "Line coverage is less than the configured minimum of #{opts[:fail_under_line]}%"
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
raise CeedlingException.new(msg)
|
|
517
|
-
else
|
|
518
|
-
@loginator.log( msg, Verbosity::COMPLAIN )
|
|
519
|
-
# Clear bit in exit code
|
|
520
|
-
exitcode &= ~2
|
|
521
|
-
end
|
|
576
|
+
violations << "Gcovr ⏩️ #{extract_gcovr_error_message( shell_result ) || fallback}"
|
|
577
|
+
exitcode &= ~2
|
|
522
578
|
end
|
|
523
579
|
|
|
524
580
|
# Special handling of exit code 4 with --fail-under-branch
|
|
525
581
|
if ((exitcode & 4) == 4) and !opts[:fail_under_branch].nil?
|
|
526
582
|
fallback = "Branch coverage is less than the configured minimum of #{opts[:fail_under_branch]}%"
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
raise CeedlingException.new(msg)
|
|
530
|
-
else
|
|
531
|
-
@loginator.log( msg, Verbosity::COMPLAIN )
|
|
532
|
-
# Clear bit in exit code
|
|
533
|
-
exitcode &= ~4
|
|
534
|
-
end
|
|
583
|
+
violations << "Gcovr ⏩️ #{extract_gcovr_error_message( shell_result ) || fallback}"
|
|
584
|
+
exitcode &= ~4
|
|
535
585
|
end
|
|
536
586
|
|
|
537
587
|
# Special handling of exit code 8 with --fail-under-decision
|
|
538
588
|
if ((exitcode & 8) == 8) and !opts[:fail_under_decision].nil?
|
|
539
589
|
fallback = "Decision coverage is less than the configured minimum of #{opts[:fail_under_decision]}%"
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
raise CeedlingException.new(msg)
|
|
543
|
-
else
|
|
544
|
-
@loginator.log( msg, Verbosity::COMPLAIN )
|
|
545
|
-
# Clear bit in exit code
|
|
546
|
-
exitcode &= ~8
|
|
547
|
-
end
|
|
590
|
+
violations << "Gcovr ⏩️ #{extract_gcovr_error_message( shell_result ) || fallback}"
|
|
591
|
+
exitcode &= ~8
|
|
548
592
|
end
|
|
549
593
|
|
|
550
594
|
# Special handling of exit code 16 with --fail-under-function
|
|
551
595
|
if ((exitcode & 16) == 16) and !opts[:fail_under_function].nil?
|
|
552
596
|
fallback = "Function coverage is less than the configured minimum of #{opts[:fail_under_function]}%"
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
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 ) }
|
|
561
605
|
end
|
|
562
606
|
|
|
563
607
|
# A non-zero exit code is a problem
|
|
@@ -128,7 +128,9 @@ class ReportGeneratorReportinator < GcovReportinator
|
|
|
128
128
|
|
|
129
129
|
# Get the ReportGenerator options from the project options.
|
|
130
130
|
def collect_reportgenerator_opts(opts)
|
|
131
|
-
|
|
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
|
|
132
134
|
|
|
133
135
|
# Auto-generate -filefilters: exclusion patterns for test paths and the build root.
|
|
134
136
|
# These exclude test files and all generated/framework files from coverage reports.
|
|
@@ -275,17 +277,19 @@ class ReportGeneratorReportinator < GcovReportinator
|
|
|
275
277
|
# Build filename-fragment patterns for the .gcno scan exclusion regex.
|
|
276
278
|
# Excludes test files, generated mocks, and test runners from gcov processing.
|
|
277
279
|
# 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.
|
|
278
282
|
def build_gcno_exclusions
|
|
279
283
|
data = build_exclusion_data
|
|
280
284
|
# Use [^\/\\]* (no path separators) rather than .* to match filenames only.
|
|
281
285
|
# Ceedling names build output dirs after test files (e.g. build/gcov/out/test_foo/),
|
|
282
286
|
# so .* would greedily match test_foo/bar.c and exclude ALL production sources.
|
|
283
287
|
[
|
|
284
|
-
"#{data[:test_prefix]}[^\\/\\\\]*", # test_foo.gcno
|
|
285
|
-
"#{data[:mock_prefix]}[^\\/\\\\]*", # MockBar.gcno
|
|
286
|
-
"[^\\/\\\\]*_runner[^\\/\\\\]*",
|
|
287
|
-
File.basename(UNITY_C_FILE, '.*'),
|
|
288
|
-
File.basename(CMOCK_C_FILE, '.*')
|
|
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
|
|
289
293
|
]
|
|
290
294
|
end
|
|
291
295
|
|
|
@@ -101,7 +101,7 @@ class Valgrind < Plugin
|
|
|
101
101
|
results: results
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
verbosity =
|
|
104
|
+
verbosity = @plugin_reportinator.test_results_floor_verbosity
|
|
105
105
|
|
|
106
106
|
# Print unit test suite results
|
|
107
107
|
@plugin_reportinator.run_test_results_report( hash, verbosity )
|
|
@@ -1684,6 +1684,34 @@
|
|
|
1684
1684
|
</span>
|
|
1685
1685
|
</a>
|
|
1686
1686
|
|
|
1687
|
+
<nav class="md-nav" aria-label="Some YAML Learnin’">
|
|
1688
|
+
<ul class="md-nav__list">
|
|
1689
|
+
|
|
1690
|
+
<li class="md-nav__item">
|
|
1691
|
+
<a href="#yaml-highlights-overview" class="md-nav__link">
|
|
1692
|
+
<span class="md-ellipsis">
|
|
1693
|
+
|
|
1694
|
+
YAML highlights & overview
|
|
1695
|
+
|
|
1696
|
+
</span>
|
|
1697
|
+
</a>
|
|
1698
|
+
|
|
1699
|
+
</li>
|
|
1700
|
+
|
|
1701
|
+
<li class="md-nav__item">
|
|
1702
|
+
<a href="#yaml-anchors-aliases-and-extensions" class="md-nav__link">
|
|
1703
|
+
<span class="md-ellipsis">
|
|
1704
|
+
|
|
1705
|
+
YAML anchors, aliases, and extensions
|
|
1706
|
+
|
|
1707
|
+
</span>
|
|
1708
|
+
</a>
|
|
1709
|
+
|
|
1710
|
+
</li>
|
|
1711
|
+
|
|
1712
|
+
</ul>
|
|
1713
|
+
</nav>
|
|
1714
|
+
|
|
1687
1715
|
</li>
|
|
1688
1716
|
|
|
1689
1717
|
<li class="md-nav__item">
|
|
@@ -4102,6 +4130,34 @@
|
|
|
4102
4130
|
</span>
|
|
4103
4131
|
</a>
|
|
4104
4132
|
|
|
4133
|
+
<nav class="md-nav" aria-label="Some YAML Learnin’">
|
|
4134
|
+
<ul class="md-nav__list">
|
|
4135
|
+
|
|
4136
|
+
<li class="md-nav__item">
|
|
4137
|
+
<a href="#yaml-highlights-overview" class="md-nav__link">
|
|
4138
|
+
<span class="md-ellipsis">
|
|
4139
|
+
|
|
4140
|
+
YAML highlights & overview
|
|
4141
|
+
|
|
4142
|
+
</span>
|
|
4143
|
+
</a>
|
|
4144
|
+
|
|
4145
|
+
</li>
|
|
4146
|
+
|
|
4147
|
+
<li class="md-nav__item">
|
|
4148
|
+
<a href="#yaml-anchors-aliases-and-extensions" class="md-nav__link">
|
|
4149
|
+
<span class="md-ellipsis">
|
|
4150
|
+
|
|
4151
|
+
YAML anchors, aliases, and extensions
|
|
4152
|
+
|
|
4153
|
+
</span>
|
|
4154
|
+
</a>
|
|
4155
|
+
|
|
4156
|
+
</li>
|
|
4157
|
+
|
|
4158
|
+
</ul>
|
|
4159
|
+
</nav>
|
|
4160
|
+
|
|
4105
4161
|
</li>
|
|
4106
4162
|
|
|
4107
4163
|
<li class="md-nav__item">
|
|
@@ -4241,10 +4297,20 @@
|
|
|
4241
4297
|
example of a complete project configuration.</p>
|
|
4242
4298
|
</div>
|
|
4243
4299
|
<h2 id="some-yaml-learnin">Some YAML Learnin’</h2>
|
|
4244
|
-
<p>Please consult YAML documentation for the finer points of format
|
|
4245
|
-
and to understand details of our YAML-based configuration file.</p>
|
|
4246
4300
|
<p>We recommend <a href="http://en.wikipedia.org/wiki/Yaml">Wikipedia’s entry on YAML</a>
|
|
4247
|
-
|
|
4301
|
+
and <a href="https://www.educative.io/blog/advanced-yaml-syntax-cheatsheet">educative.io’s advanced YAML cheatsheet</a>
|
|
4302
|
+
for a simple overview of YAML and its syntax sufficient for
|
|
4303
|
+
understanding your Ceedling project configuration.</p>
|
|
4304
|
+
<div class="admonition tip">
|
|
4305
|
+
<p class="admonition-title"><code>ceedling dumpconfig</code> to verify your YAML</p>
|
|
4306
|
+
<p>Ceedling provides a means to export the final result of YAML
|
|
4307
|
+
processing for your inspection via <a href="../getting-started/command-line.html#ceedling-dumpconfig-filepath-sections"><code>dumpconfig</code></a>.
|
|
4308
|
+
Dump output includes the resolution of advanced YAML features and
|
|
4309
|
+
Ceedling’s own manipulations. This is a good way to troubleshoot
|
|
4310
|
+
your project configuration.</p>
|
|
4311
|
+
</div>
|
|
4312
|
+
<h3 id="yaml-highlights-overview">YAML highlights & overview</h3>
|
|
4313
|
+
<p>A few points from the preceding references:</p>
|
|
4248
4314
|
<ul>
|
|
4249
4315
|
<li>
|
|
4250
4316
|
<p>YAML streams are encoded using the set of printable Unicode
|
|
@@ -4279,12 +4345,16 @@ for this. A few highlights from that reference page:</p>
|
|
|
4279
4345
|
punctuation can generally be represented without needing
|
|
4280
4346
|
to be enclosed in quotes.</p>
|
|
4281
4347
|
</li>
|
|
4282
|
-
<li>
|
|
4283
|
-
<p>Repeated nodes are initially denoted by an ampersand (<code>&</code>) and
|
|
4284
|
-
thereafter referenced with an asterisk (<code>*</code>). These are known as
|
|
4285
|
-
anchors and aliases in YAML speak.</p>
|
|
4286
|
-
</li>
|
|
4287
4348
|
</ul>
|
|
4349
|
+
<h3 id="yaml-anchors-aliases-and-extensions">YAML anchors, aliases, and extensions</h3>
|
|
4350
|
+
<p>YAML provides several “shortcuts” for referencing and modifying blocks
|
|
4351
|
+
of YAML so you can avoid duplication. This is advanced YAML and
|
|
4352
|
+
well beyond the scope of Ceedling documentation. However, know that
|
|
4353
|
+
Ceedling’s YAML parser is entirely capable of handling these advanced
|
|
4354
|
+
aspects of YAML.</p>
|
|
4355
|
+
<p>See this <a href="https://www.educative.io/blog/advanced-yaml-syntax-cheatsheet#anchors">cheatsheet entry</a>
|
|
4356
|
+
and <a href="https://blog.daemonl.com/2016/02/yaml.html">this guide</a>
|
|
4357
|
+
for much more on these powerful but finicky features.</p>
|
|
4288
4358
|
<h2 id="notes-on-project-file-structure">Notes on Project File Structure</h2>
|
|
4289
4359
|
<ul>
|
|
4290
4360
|
<li>
|
|
@@ -2344,10 +2344,10 @@
|
|
|
2344
2344
|
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
|
2345
2345
|
|
|
2346
2346
|
<li class="md-nav__item">
|
|
2347
|
-
<a href="#
|
|
2347
|
+
<a href="#example-cmock-yaml" class="md-nav__link">
|
|
2348
2348
|
<span class="md-ellipsis">
|
|
2349
2349
|
|
|
2350
|
-
|
|
2350
|
+
Example :cmock YAML
|
|
2351
2351
|
|
|
2352
2352
|
</span>
|
|
2353
2353
|
</a>
|
|
@@ -4046,10 +4046,10 @@
|
|
|
4046
4046
|
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
|
4047
4047
|
|
|
4048
4048
|
<li class="md-nav__item">
|
|
4049
|
-
<a href="#
|
|
4049
|
+
<a href="#example-cmock-yaml" class="md-nav__link">
|
|
4050
4050
|
<span class="md-ellipsis">
|
|
4051
4051
|
|
|
4052
|
-
|
|
4052
|
+
Example :cmock YAML
|
|
4053
4053
|
|
|
4054
4054
|
</span>
|
|
4055
4055
|
</a>
|
|
@@ -4155,7 +4155,7 @@
|
|
|
4155
4155
|
|
|
4156
4156
|
<h1 id="cexception"><code>:cexception</code></h1>
|
|
4157
4157
|
<p><strong>Configure CException’s features</strong></p>
|
|
4158
|
-
<h2 id="
|
|
4158
|
+
<h2 id="example-cmock-yaml">Example <code>:cmock</code> YAML</h2>
|
|
4159
4159
|
<div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nt">:cexception</span><span class="p">:</span>
|
|
4160
4160
|
<a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a><span class="w"> </span><span class="nt">:defines</span><span class="p">:</span>
|
|
4161
4161
|
<a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a><span class="w"> </span><span class="c1"># Enables CException `#include`ing CExceptionConfig.h</span>
|
|
@@ -2288,10 +2288,10 @@
|
|
|
2288
2288
|
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
|
2289
2289
|
|
|
2290
2290
|
<li class="md-nav__item">
|
|
2291
|
-
<a href="#
|
|
2291
|
+
<a href="#example-cmock-yaml" class="md-nav__link">
|
|
2292
2292
|
<span class="md-ellipsis">
|
|
2293
2293
|
|
|
2294
|
-
|
|
2294
|
+
Example :cmock YAML
|
|
2295
2295
|
|
|
2296
2296
|
</span>
|
|
2297
2297
|
</a>
|
|
@@ -4112,10 +4112,10 @@
|
|
|
4112
4112
|
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
|
4113
4113
|
|
|
4114
4114
|
<li class="md-nav__item">
|
|
4115
|
-
<a href="#
|
|
4115
|
+
<a href="#example-cmock-yaml" class="md-nav__link">
|
|
4116
4116
|
<span class="md-ellipsis">
|
|
4117
4117
|
|
|
4118
|
-
|
|
4118
|
+
Example :cmock YAML
|
|
4119
4119
|
|
|
4120
4120
|
</span>
|
|
4121
4121
|
</a>
|
|
@@ -4290,7 +4290,7 @@
|
|
|
4290
4290
|
<p>Ceedling sets values for a subset of CMock settings. All CMock options are
|
|
4291
4291
|
available to be set, but only those options set by Ceedling in an automated
|
|
4292
4292
|
fashion are documented below. See <a href="https://github.com/ThrowTheSwitch/CMock/blob/master/docs/CMock_Summary.md">CMock documentation</a>.</p>
|
|
4293
|
-
<h2 id="
|
|
4293
|
+
<h2 id="example-cmock-yaml">Example <code>:cmock</code> YAML</h2>
|
|
4294
4294
|
<div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nt">:cmock</span><span class="p">:</span>
|
|
4295
4295
|
<a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a><span class="w"> </span><span class="nt">:when_no_prototypes</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">:warn</span>
|
|
4296
4296
|
<a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a><span class="w"> </span><span class="nt">:enforce_strict_ordering</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TRUE</span>
|
|
@@ -2260,10 +2260,10 @@
|
|
|
2260
2260
|
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
|
2261
2261
|
|
|
2262
2262
|
<li class="md-nav__item">
|
|
2263
|
-
<a href="#
|
|
2263
|
+
<a href="#example-unity-yaml" class="md-nav__link">
|
|
2264
2264
|
<span class="md-ellipsis">
|
|
2265
2265
|
|
|
2266
|
-
|
|
2266
|
+
Example :unity YAML
|
|
2267
2267
|
|
|
2268
2268
|
</span>
|
|
2269
2269
|
</a>
|
|
@@ -4057,10 +4057,10 @@
|
|
|
4057
4057
|
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
|
4058
4058
|
|
|
4059
4059
|
<li class="md-nav__item">
|
|
4060
|
-
<a href="#
|
|
4060
|
+
<a href="#example-unity-yaml" class="md-nav__link">
|
|
4061
4061
|
<span class="md-ellipsis">
|
|
4062
4062
|
|
|
4063
|
-
|
|
4063
|
+
Example :unity YAML
|
|
4064
4064
|
|
|
4065
4065
|
</span>
|
|
4066
4066
|
</a>
|
|
@@ -4177,7 +4177,7 @@
|
|
|
4177
4177
|
|
|
4178
4178
|
<h1 id="unity"><code>:unity</code></h1>
|
|
4179
4179
|
<p><strong>Configure Unity’s features</strong></p>
|
|
4180
|
-
<h2 id="
|
|
4180
|
+
<h2 id="example-unity-yaml">Example <code>:unity</code> YAML</h2>
|
|
4181
4181
|
<div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nt">:unity</span><span class="p">:</span>
|
|
4182
4182
|
<a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a><span class="w"> </span><span class="nt">:defines</span><span class="p">:</span>
|
|
4183
4183
|
<a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">UNITY_INT_WIDTH=16</span><span class="w"> </span><span class="c1"># 16 bit processor without support for 32 bit instructions</span>
|