ceedling 1.1.9 → 1.1.10
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/README.md +4 -3
- data/docs/Changelog.md +10 -0
- data/docs/KnownIssues.md +11 -2
- data/docs/SECURITY.md +40 -2
- data/docs/mkdocs/development/index.md +11 -0
- data/docs/mkdocs/plugins/fff.md +1 -1
- data/docs/mkdocs/plugins/gcov/gcovr.md +117 -3
- data/docs/mkdocs/plugins/gcov/reportgenerator.md +110 -4
- data/lib/ceedling/generators/generator.rb +11 -6
- data/lib/ceedling/generators/generator_partials.rb +54 -18
- data/lib/ceedling/objects.yml +2 -0
- data/lib/ceedling/partials/partializer.rb +164 -101
- data/lib/ceedling/test_invoker/test_build_executor.rb +21 -7
- data/lib/version.rb +1 -1
- data/site-local/development/index.html +7 -0
- data/site-local/plugins/fff.html +1 -1
- data/site-local/plugins/gcov/gcovr.html +156 -3
- data/site-local/plugins/gcov/reportgenerator.html +201 -14
- data/site-local/sitemap.xml.gz +0 -0
- data/spec/system/partials_types_header_spec.rb +166 -0
- data/spec/units/generators/generator_partials_spec.rb +130 -17
- data/spec/units/partials/partializer_spec.rb +163 -0
- metadata +4 -2
data/lib/ceedling/objects.yml
CHANGED
|
@@ -14,12 +14,18 @@ require 'ceedling/c_extractor/c_extractor'
|
|
|
14
14
|
require 'ceedling/c_extractor/c_extractor_constants'
|
|
15
15
|
require 'ceedling/c_extractor/c_extractor_types'
|
|
16
16
|
require 'ceedling/constants'
|
|
17
|
+
require 'ceedling/encodinator'
|
|
17
18
|
|
|
18
19
|
class Partializer
|
|
19
20
|
|
|
21
|
+
# Enough of a header to reach its include guard. The guard pair sits at the top of a header by
|
|
22
|
+
# construction, so a bounded read beats loading a large file to find it.
|
|
23
|
+
GUARD_SCAN_BYTES = 2048
|
|
24
|
+
|
|
20
25
|
include Partials
|
|
21
26
|
|
|
22
|
-
constructor :partializer_helper, :file_finder, :c_extractor, :file_path_utils,
|
|
27
|
+
constructor :partializer_helper, :file_finder, :c_extractor, :file_path_utils,
|
|
28
|
+
:preprocessinator_reconstructor, :file_wrapper, :reportinator, :loginator
|
|
23
29
|
|
|
24
30
|
def setup()
|
|
25
31
|
# Alias
|
|
@@ -82,120 +88,89 @@ class Partializer
|
|
|
82
88
|
return configs
|
|
83
89
|
end
|
|
84
90
|
|
|
91
|
+
# When `test:` is provided, logs the resulting includes at OBNOXIOUS.
|
|
92
|
+
# Includes for the generated implementation header. This module's own header is replaced by
|
|
93
|
+
# the shared types header at its original list position; every other partialized module's
|
|
94
|
+
# include is dropped.
|
|
95
|
+
#
|
|
85
96
|
# When `test:` is provided, logs the resulting includes at OBNOXIOUS.
|
|
86
97
|
def remap_implementation_header_includes(name:, includes:, partials:, types_header: nil, test: nil)
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
_includes = remove_matching_includes(
|
|
96
|
-
includes: _includes,
|
|
97
|
-
modules: (partials.keys - [name])
|
|
98
|
+
_remap_includes(
|
|
99
|
+
name: name,
|
|
100
|
+
includes: includes,
|
|
101
|
+
partials: partials,
|
|
102
|
+
replacement: types_header,
|
|
103
|
+
others: :drop,
|
|
104
|
+
noun: 'Header includes to inject for testable Partial',
|
|
105
|
+
test: test
|
|
98
106
|
)
|
|
99
|
-
|
|
100
|
-
# Remove any duplicates
|
|
101
|
-
Includes.sanitize!(_includes)
|
|
102
|
-
|
|
103
|
-
@loginator.log_list(
|
|
104
|
-
_includes,
|
|
105
|
-
"Header includes to inject for testable Partial #{test}::#{name}:",
|
|
106
|
-
Verbosity::OBNOXIOUS
|
|
107
|
-
) if test
|
|
108
|
-
|
|
109
|
-
return _includes
|
|
110
107
|
end
|
|
111
108
|
|
|
109
|
+
# Includes for the generated mockable interface header. Same treatment as the implementation
|
|
110
|
+
# header: both files carry the shared types header, which is how a module tested and mocked
|
|
111
|
+
# in one test file still gets exactly one definition of each of its types.
|
|
112
|
+
#
|
|
112
113
|
# When `test:` is provided, logs the resulting includes at OBNOXIOUS.
|
|
113
|
-
def
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
# is ever reached. Appending it at the very end (after this file's own copy of every
|
|
123
|
-
# other real include) would put it after exactly that kind of transitive
|
|
124
|
-
# re-inclusion instead of before it.
|
|
125
|
-
_includes = splice_in_replacement(
|
|
126
|
-
includes: _includes,
|
|
127
|
-
name: name,
|
|
128
|
-
replacement: @file_path_utils.form_partial_implementation_header_filename(name)
|
|
114
|
+
def remap_interface_header_includes(name:, includes:, partials:, types_header: nil, test: nil)
|
|
115
|
+
_remap_includes(
|
|
116
|
+
name: name,
|
|
117
|
+
includes: includes,
|
|
118
|
+
partials: partials,
|
|
119
|
+
replacement: types_header,
|
|
120
|
+
others: :drop,
|
|
121
|
+
noun: 'Header includes to inject for mockable Partial',
|
|
122
|
+
test: test
|
|
129
123
|
)
|
|
124
|
+
end
|
|
130
125
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
@file_path_utils.form_partial_interface_header_filename(_module)
|
|
147
|
-
)
|
|
148
|
-
# Remember the module for later removal of original header
|
|
149
|
-
mockable_modules << _module
|
|
150
|
-
end
|
|
151
|
-
end
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
# Remove the original headers of any OTHER modules now remapped to mockable
|
|
155
|
-
# interfaces above -- this module's own original header was already handled by
|
|
156
|
-
# the splice above.
|
|
157
|
-
_includes = remove_matching_includes(
|
|
158
|
-
includes: _includes,
|
|
159
|
-
modules: mockable_modules
|
|
126
|
+
# Includes for the generated implementation source. This module's own header is replaced by
|
|
127
|
+
# the generated implementation header, which carries the types header internally. Another
|
|
128
|
+
# partialized module that is mocked is redirected to its generated interface header; one that
|
|
129
|
+
# is not mocked keeps its real header, which the generated code still needs.
|
|
130
|
+
#
|
|
131
|
+
# When `test:` is provided, logs the resulting includes at OBNOXIOUS.
|
|
132
|
+
def remap_implementation_source_includes(name:, includes:, partials:, test: nil)
|
|
133
|
+
_remap_includes(
|
|
134
|
+
name: name,
|
|
135
|
+
includes: includes,
|
|
136
|
+
partials: partials,
|
|
137
|
+
replacement: @file_path_utils.form_partial_implementation_header_filename(name),
|
|
138
|
+
others: :mock_or_keep,
|
|
139
|
+
noun: 'Source includes to inject for testable Partial',
|
|
140
|
+
test: test
|
|
160
141
|
)
|
|
161
|
-
|
|
162
|
-
# Remove any duplicates
|
|
163
|
-
Includes.sanitize!(_includes)
|
|
164
|
-
|
|
165
|
-
@loginator.log_list(
|
|
166
|
-
_includes,
|
|
167
|
-
"Source includes to inject for testable Partial #{test}::#{name}:",
|
|
168
|
-
Verbosity::OBNOXIOUS
|
|
169
|
-
) if test
|
|
170
|
-
|
|
171
|
-
return _includes
|
|
172
142
|
end
|
|
173
143
|
|
|
144
|
+
# Includes the shared types header carries so the extracted types resolve wherever that file
|
|
145
|
+
# lands. Nothing replaces this module's own header here -- the types header cannot include
|
|
146
|
+
# itself -- so it is simply dropped. Another partialized module is redirected to its generated
|
|
147
|
+
# interface header when mocked and dropped otherwise: its real header would reintroduce the
|
|
148
|
+
# very content that module's own Partial replaced.
|
|
149
|
+
#
|
|
174
150
|
# When `test:` is provided, logs the resulting includes at OBNOXIOUS.
|
|
175
|
-
def
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
_includes = remove_matching_includes(
|
|
185
|
-
includes: _includes,
|
|
186
|
-
modules: (partials.keys - [name])
|
|
151
|
+
def remap_types_header_includes(name:, includes:, partials:, test: nil)
|
|
152
|
+
_remap_includes(
|
|
153
|
+
name: name,
|
|
154
|
+
includes: includes,
|
|
155
|
+
partials: partials,
|
|
156
|
+
replacement: nil,
|
|
157
|
+
others: :mock_or_drop,
|
|
158
|
+
noun: 'Dependency includes to carry into the shared types header for Partial',
|
|
159
|
+
test: test
|
|
187
160
|
)
|
|
161
|
+
end
|
|
188
162
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
163
|
+
# The include guard macro the module's real header defines, or nil when it has none.
|
|
164
|
+
#
|
|
165
|
+
# Read from the original header rather than from the reconstituted copy or from extracted
|
|
166
|
+
# macros. The reconstituted copy carries a synthetic guard that #sanitize strips, so neither is
|
|
167
|
+
# a dependable source. A nil return means the header guards itself some other way --
|
|
168
|
+
# `#pragma once` -- and offers no macro for a generated file to spoof.
|
|
169
|
+
def extract_module_include_guard(filepath)
|
|
170
|
+
return nil if filepath.nil?
|
|
171
|
+
|
|
172
|
+
text = @file_wrapper.read( filepath, GUARD_SCAN_BYTES ).clean_encoding
|
|
173
|
+
@preprocessinator_reconstructor.extract_include_guard( text )
|
|
199
174
|
end
|
|
200
175
|
|
|
201
176
|
# Extracts and combines C code contents from header and source files
|
|
@@ -457,6 +432,94 @@ class Partializer
|
|
|
457
432
|
)
|
|
458
433
|
end
|
|
459
434
|
|
|
435
|
+
# One body behind all four public remaps. Each differs only in what replaces this module's
|
|
436
|
+
# own header, what becomes of other partialized modules, and the noun it logs under -- the
|
|
437
|
+
# splice, the sanitize, and the logging are identical in every case.
|
|
438
|
+
#
|
|
439
|
+
# `others` selects the treatment of every OTHER partialized module in the same test file:
|
|
440
|
+
# :drop -- remove its include outright, with no substitute
|
|
441
|
+
# :mock_or_keep -- redirect to its interface header when mocked, else leave its real header
|
|
442
|
+
# :mock_or_drop -- redirect to its interface header when mocked, else drop it
|
|
443
|
+
def _remap_includes(name:, includes:, partials:, replacement:, others:, noun:, test: nil)
|
|
444
|
+
_includes = includes.clone()
|
|
445
|
+
|
|
446
|
+
# A nil replacement strips this module's own header and substitutes nothing.
|
|
447
|
+
_includes = splice_in_replacement( includes: _includes, name: name, replacement: replacement )
|
|
448
|
+
|
|
449
|
+
_includes =
|
|
450
|
+
case others
|
|
451
|
+
when :drop
|
|
452
|
+
remove_matching_includes( includes: _includes, modules: (partials.keys - [name]) )
|
|
453
|
+
when :mock_or_keep, :mock_or_drop
|
|
454
|
+
# The types header differs from the generated source in two ways at once, which is why
|
|
455
|
+
# both flags below read from one condition.
|
|
456
|
+
#
|
|
457
|
+
# It skips this module: the interface header includes the types header, so carrying the
|
|
458
|
+
# interface back in would fold that file's declarations into this one. The generated
|
|
459
|
+
# source needs the opposite -- a module tested and mocked in one test file keeps its
|
|
460
|
+
# public bodies in the implementation and the private declarations they call in the
|
|
461
|
+
# interface, so it needs both.
|
|
462
|
+
#
|
|
463
|
+
# And it drops an unmocked partialized dependency rather than keeping its real header,
|
|
464
|
+
# which would reintroduce content that module's own Partial replaced.
|
|
465
|
+
shared_types_header = ( others == :mock_or_drop )
|
|
466
|
+
|
|
467
|
+
_redirect_mocked_partials(
|
|
468
|
+
includes: _includes,
|
|
469
|
+
original: includes,
|
|
470
|
+
name: name,
|
|
471
|
+
partials: partials,
|
|
472
|
+
drop_unmocked: shared_types_header,
|
|
473
|
+
skip_self: shared_types_header
|
|
474
|
+
)
|
|
475
|
+
else
|
|
476
|
+
PartializerRuntime.raise_on_option( others )
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
# Remove any duplicates
|
|
480
|
+
Includes.sanitize!(_includes)
|
|
481
|
+
|
|
482
|
+
@loginator.log_list(
|
|
483
|
+
_includes,
|
|
484
|
+
"#{noun} #{test}::#{name}:",
|
|
485
|
+
Verbosity::OBNOXIOUS
|
|
486
|
+
) if test
|
|
487
|
+
|
|
488
|
+
return _includes
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
# Appends the generated interface header for each mocked partialized module the original list
|
|
492
|
+
# named, then removes the real headers those replaced. `skip_self` decides whether the module
|
|
493
|
+
# being generated counts as one of them, which it does everywhere except the types header --
|
|
494
|
+
# see the call site.
|
|
495
|
+
#
|
|
496
|
+
# Mutates `includes`, which always arrives fresh from splice_in_replacement.
|
|
497
|
+
#
|
|
498
|
+
# Any real (non-nil) mock mode counts. PUBLIC/PRIVATE alone once covered every mode that
|
|
499
|
+
# existed, but DEDUCT (MOCK_PARTIAL_ALL_MODULE) and ACCUMULATE (MOCK_PARTIAL_MODULE) were
|
|
500
|
+
# added later without updating the check, so a module mocked via either was silently never
|
|
501
|
+
# redirected: its real header, and any static inline or static function bodies in it, stayed
|
|
502
|
+
# #include'd verbatim and compiled straight past the mock.
|
|
503
|
+
def _redirect_mocked_partials(includes:, original:, name:, partials:, drop_unmocked:, skip_self:)
|
|
504
|
+
retired = []
|
|
505
|
+
|
|
506
|
+
partials.each do |_module, config|
|
|
507
|
+
next if skip_self && _module == name
|
|
508
|
+
next unless original.any? { |include| include.filename.ext().downcase() == _module.downcase() }
|
|
509
|
+
|
|
510
|
+
if config.mocks.type.nil?
|
|
511
|
+
retired << _module if drop_unmocked
|
|
512
|
+
else
|
|
513
|
+
includes << UserInclude.new(
|
|
514
|
+
@file_path_utils.form_partial_interface_header_filename(_module)
|
|
515
|
+
)
|
|
516
|
+
retired << _module
|
|
517
|
+
end
|
|
518
|
+
end
|
|
519
|
+
|
|
520
|
+
remove_matching_includes( includes: includes, modules: retired )
|
|
521
|
+
end
|
|
522
|
+
|
|
460
523
|
# Swaps `name`'s own header include for `replacement` at that same list position,
|
|
461
524
|
# instead of stripping it out and appending the replacement at the very end.
|
|
462
525
|
#
|
|
@@ -183,15 +183,27 @@ class TestBuildExecutor
|
|
|
183
183
|
|
|
184
184
|
@partializer.sanitize( module_contents )
|
|
185
185
|
|
|
186
|
+
# The real header's guard is spoofed deliberately in every generated file, and the types
|
|
187
|
+
# header carries the dependencies its extracted types name.
|
|
188
|
+
module_include_guard = @partializer.extract_module_include_guard( config.header.filepath )
|
|
189
|
+
types_header_includes = @partializer.remap_types_header_includes(
|
|
190
|
+
name: config.module,
|
|
191
|
+
includes: (config.source.includes + config.header.includes),
|
|
192
|
+
partials: testable.partials.configs,
|
|
193
|
+
test: name
|
|
194
|
+
)
|
|
195
|
+
|
|
186
196
|
# Generated once and shared by the implementation and interface headers below (via
|
|
187
197
|
# their own includes lists), so a module tested and mocked in the same test file gets
|
|
188
198
|
# exactly one C definition of each of its typedefs and aggregate types.
|
|
189
199
|
types_header = @generator.generate_partial_types(
|
|
190
|
-
name:
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
c_module:
|
|
194
|
-
output_path:
|
|
200
|
+
name: config.module, # Module name, not test name -- two modules Partialed
|
|
201
|
+
# in the same test file must not collide on one
|
|
202
|
+
# shared types header filename
|
|
203
|
+
c_module: module_contents,
|
|
204
|
+
output_path: testable.paths[:partials],
|
|
205
|
+
includes: types_header_includes,
|
|
206
|
+
include_guard: module_include_guard
|
|
195
207
|
)
|
|
196
208
|
|
|
197
209
|
implementation = @partializer.extract_implementation_functions(
|
|
@@ -235,7 +247,8 @@ class TestBuildExecutor
|
|
|
235
247
|
test: name
|
|
236
248
|
),
|
|
237
249
|
input_filepath: config.source.filepath,
|
|
238
|
-
output_path: testable.paths[:partials]
|
|
250
|
+
output_path: testable.paths[:partials],
|
|
251
|
+
include_guard: module_include_guard
|
|
239
252
|
}
|
|
240
253
|
|
|
241
254
|
unless implementation.nil?
|
|
@@ -256,7 +269,8 @@ class TestBuildExecutor
|
|
|
256
269
|
),
|
|
257
270
|
c_module: module_contents,
|
|
258
271
|
input_filepath: config.header.filepath,
|
|
259
|
-
output_path: testable.paths[:partials]
|
|
272
|
+
output_path: testable.paths[:partials],
|
|
273
|
+
include_guard: module_include_guard
|
|
260
274
|
}
|
|
261
275
|
|
|
262
276
|
unless interface.nil?
|
data/lib/version.rb
CHANGED
|
@@ -4080,6 +4080,13 @@ Please familiarize yourself with it before participating.</p>
|
|
|
4080
4080
|
<p>Guidelines for contributing to this project — be it code, reviews,
|
|
4081
4081
|
documentation, or issue reports.</p>
|
|
4082
4082
|
</li>
|
|
4083
|
+
<li>
|
|
4084
|
+
<p><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 1 3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5zm0 6c1.4 0 2.8 1.1 2.8 2.5V11c.6 0 1.2.6 1.2 1.3v3.5c0 .6-.6 1.2-1.3 1.2H9.2c-.6 0-1.2-.6-1.2-1.3v-3.5c0-.6.6-1.2 1.2-1.2V9.5C9.2 8.1 10.6 7 12 7m0 1.2c-.8 0-1.5.5-1.5 1.3V11h3V9.5c0-.8-.7-1.3-1.5-1.3"/></svg></span> <strong><a href="https://github.com/ThrowTheSwitch/Ceedling?tab=security-ov-file">Security</a></strong></p>
|
|
4085
|
+
<hr />
|
|
4086
|
+
<p>See the <a href="https://github.com/ThrowTheSwitch/Ceedling/blob/master/docs/SECURITY.md">policy</a> for disclosure details and
|
|
4087
|
+
guidance on issues that vulnerability inspection tools may surface.
|
|
4088
|
+
Report a vulnerability through a <a href="https://github.com/ThrowTheSwitch/Ceedling/security/advisories/new">private advisory</a>.</p>
|
|
4089
|
+
</li>
|
|
4083
4090
|
</ul>
|
|
4084
4091
|
</div>
|
|
4085
4092
|
<h2 id="projects">Projects</h2>
|
data/site-local/plugins/fff.html
CHANGED
|
@@ -4424,7 +4424,7 @@
|
|
|
4424
4424
|
<h1 id="fake-function-framework-for-ceedling">Fake Function Framework for Ceedling</h1>
|
|
4425
4425
|
<p>This plugin causes Ceedling to use the <a href="https://github.com/meekrosoft/fff">Fake Function Framework</a> for mocking instead of CMock, the default mocking framework packaged with Ceedling.</p>
|
|
4426
4426
|
<p>Using <em>FFF</em> provides less strict mocking than CMock and affords more loosely-coupled tests.</p>
|
|
4427
|
-
<p>This Ceedling 1.x plugin incorporates a snapshot of <em>FFF</em> version
|
|
4427
|
+
<p>This Ceedling 1.x plugin incorporates a snapshot of <em>FFF</em> version 1.1 and supersedes a separately available <a href="https://github.com/ElectronVector/fake_function_framework">FFF Ceedling plugin project</a>. The built-in <em>FFF</em> plugin that now comes with Ceedling was derived from the ElectronVector project and is now maintained along with Ceedling and tracks its updates.</p>
|
|
4428
4428
|
<div class="admonition note">
|
|
4429
4429
|
<p class="admonition-title">Special thanks to Matt Chernosky</p>
|
|
4430
4430
|
<p><a href="http://www.electronvector.com">Matt Chernosky</a> originally developed this plugin
|
|
@@ -2999,6 +2999,34 @@
|
|
|
2999
2999
|
</ul>
|
|
3000
3000
|
</nav>
|
|
3001
3001
|
|
|
3002
|
+
</li>
|
|
3003
|
+
|
|
3004
|
+
<li class="md-nav__item">
|
|
3005
|
+
<a href="#results-filtering" class="md-nav__link">
|
|
3006
|
+
<span class="md-ellipsis">
|
|
3007
|
+
|
|
3008
|
+
Results filtering
|
|
3009
|
+
|
|
3010
|
+
</span>
|
|
3011
|
+
</a>
|
|
3012
|
+
|
|
3013
|
+
<nav class="md-nav" aria-label="Results filtering">
|
|
3014
|
+
<ul class="md-nav__list">
|
|
3015
|
+
|
|
3016
|
+
<li class="md-nav__item">
|
|
3017
|
+
<a href="#overriding-the-defaults" class="md-nav__link">
|
|
3018
|
+
<span class="md-ellipsis">
|
|
3019
|
+
|
|
3020
|
+
Overriding the defaults
|
|
3021
|
+
|
|
3022
|
+
</span>
|
|
3023
|
+
</a>
|
|
3024
|
+
|
|
3025
|
+
</li>
|
|
3026
|
+
|
|
3027
|
+
</ul>
|
|
3028
|
+
</nav>
|
|
3029
|
+
|
|
3002
3030
|
</li>
|
|
3003
3031
|
|
|
3004
3032
|
<li class="md-nav__item">
|
|
@@ -4641,6 +4669,34 @@
|
|
|
4641
4669
|
</ul>
|
|
4642
4670
|
</nav>
|
|
4643
4671
|
|
|
4672
|
+
</li>
|
|
4673
|
+
|
|
4674
|
+
<li class="md-nav__item">
|
|
4675
|
+
<a href="#results-filtering" class="md-nav__link">
|
|
4676
|
+
<span class="md-ellipsis">
|
|
4677
|
+
|
|
4678
|
+
Results filtering
|
|
4679
|
+
|
|
4680
|
+
</span>
|
|
4681
|
+
</a>
|
|
4682
|
+
|
|
4683
|
+
<nav class="md-nav" aria-label="Results filtering">
|
|
4684
|
+
<ul class="md-nav__list">
|
|
4685
|
+
|
|
4686
|
+
<li class="md-nav__item">
|
|
4687
|
+
<a href="#overriding-the-defaults" class="md-nav__link">
|
|
4688
|
+
<span class="md-ellipsis">
|
|
4689
|
+
|
|
4690
|
+
Overriding the defaults
|
|
4691
|
+
|
|
4692
|
+
</span>
|
|
4693
|
+
</a>
|
|
4694
|
+
|
|
4695
|
+
</li>
|
|
4696
|
+
|
|
4697
|
+
</ul>
|
|
4698
|
+
</nav>
|
|
4699
|
+
|
|
4644
4700
|
</li>
|
|
4645
4701
|
|
|
4646
4702
|
<li class="md-nav__item">
|
|
@@ -5297,9 +5353,14 @@ plugin configuration. This prevents overriding config file settings with
|
|
|
5297
5353
|
CLI arguments. You must provide any settings that would have been provided
|
|
5298
5354
|
by the Gcov plugin.</p>
|
|
5299
5355
|
</div>
|
|
5300
|
-
<p>
|
|
5301
|
-
|
|
5302
|
-
|
|
5356
|
+
<p>A Gcovr config file replaces Ceedling's own automatically generated exclusion
|
|
5357
|
+
patterns (see <a href="#results-filtering">Results filtering</a> below) entirely — it is
|
|
5358
|
+
the only way to override or remove one of those defaults, since the
|
|
5359
|
+
project-configuration <code>:report_exclude</code> option can only add further
|
|
5360
|
+
exclusions on top of them, never take one away. To preserve the same
|
|
5361
|
+
filtering of test and build files when switching to a Gcovr config file, you
|
|
5362
|
+
must provide equivalent explicit exclusion patterns matching your project
|
|
5363
|
+
layout yourself (example below).</p>
|
|
5303
5364
|
<div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="c1">; You will need to revise these example exclude patterns to match your</span>
|
|
5304
5365
|
<a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a><span class="c1">; project directories and file naming as they cannot be automatically </span>
|
|
5305
5366
|
<a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a><span class="c1">; provided to Gcovr when a Gcovr configuration file is in use.</span>
|
|
@@ -5312,6 +5373,84 @@ your project layout (example below).</p>
|
|
|
5312
5373
|
<a id="__codelineno-0-10" name="__codelineno-0-10" href="#__codelineno-0-10"></a><span class="c1">; Build path exlcude for all generated C files (runners, mocks, partials).</span>
|
|
5313
5374
|
<a id="__codelineno-0-11" name="__codelineno-0-11" href="#__codelineno-0-11"></a><span class="na">exclude</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">.*build/.+\.c$</span>
|
|
5314
5375
|
</code></pre></div>
|
|
5376
|
+
<h2 id="results-filtering">Results filtering</h2>
|
|
5377
|
+
<p>By default, this plugin configures <code>gcovr</code> to excludes three categories of
|
|
5378
|
+
<code>.c</code> files from coverage results. These defaults exist because a
|
|
5379
|
+
coverage percentage is typically only meaningful over the production code
|
|
5380
|
+
you're actually trying to exercise with test coverage. Test code, test
|
|
5381
|
+
support code, and every file Ceedling itself generates as part of a build
|
|
5382
|
+
will skew that number if left in coverage reporting.</p>
|
|
5383
|
+
<p>The list that follows details the filtering this plugin injects into
|
|
5384
|
+
Gcovr coverage report generation. The examples are usable regular
|
|
5385
|
+
expressions that mirror the defaults in use. The plugin dynamically
|
|
5386
|
+
generates these regular expressions from your project configuration.
|
|
5387
|
+
When creating them youself, you will need to match your project
|
|
5388
|
+
configuration settings with static strings.</p>
|
|
5389
|
+
<ol>
|
|
5390
|
+
<li>
|
|
5391
|
+
<p><strong>Test files</strong> — matched by <code>:test_file_prefix</code> within your configured
|
|
5392
|
+
<code>:paths</code> ↳ <code>:test</code> directories.</p>
|
|
5393
|
+
<p>Given <code>:test_file_prefix</code> ⇒ <code>test_</code> and a <code>:paths</code> ↳ <code>:test</code> entry of
|
|
5394
|
+
<code>test/</code>:</p>
|
|
5395
|
+
<div class="highlight"><pre><span></span><code><a id="__codelineno-1-1" name="__codelineno-1-1" href="#__codelineno-1-1"></a>.*test/.*/test_.+\.c$
|
|
5396
|
+
</code></pre></div>
|
|
5397
|
+
</li>
|
|
5398
|
+
<li>
|
|
5399
|
+
<p><strong>Test support files</strong> — any <code>.c</code> file within your configured <code>:paths</code> ↳
|
|
5400
|
+
<code>:support</code> directories, regardless of name. Helpers, stubs, and fixtures
|
|
5401
|
+
living there are no more production code than the test files themselves.</p>
|
|
5402
|
+
<p>Given a <code>:paths</code> ↳ <code>:support</code> entry of <code>test/support/</code>:</p>
|
|
5403
|
+
<div class="highlight"><pre><span></span><code><a id="__codelineno-2-1" name="__codelineno-2-1" href="#__codelineno-2-1"></a>.*test/support/.+\.c$
|
|
5404
|
+
</code></pre></div>
|
|
5405
|
+
</li>
|
|
5406
|
+
<li>
|
|
5407
|
+
<p><strong>Generated and vendored files</strong> — any <code>.c</code> file anywhere below your
|
|
5408
|
+
<code>:build_root</code>: generated mocks, test runners, Partials output, and the
|
|
5409
|
+
vendored Unity/CMock/CException framework sources Ceedling copies in to
|
|
5410
|
+
build against. This pattern always matches a literal <code>.c</code> extension
|
|
5411
|
+
regardless of your project's own <code>:extension</code> ↳ <code>:source</code> setting, since
|
|
5412
|
+
every file it catches is one Ceedling itself writes in plain C.</p>
|
|
5413
|
+
<p>Given <code>:build_root</code> ⇒ <code>build/</code>:</p>
|
|
5414
|
+
<div class="highlight"><pre><span></span><code><a id="__codelineno-3-1" name="__codelineno-3-1" href="#__codelineno-3-1"></a>.*build/.+\.c$
|
|
5415
|
+
</code></pre></div>
|
|
5416
|
+
</li>
|
|
5417
|
+
</ol>
|
|
5418
|
+
<p>These patterns are generated automatically and combined with whatever you
|
|
5419
|
+
provide via <a href="#report_exclude"><code>:report_exclude</code></a> below.</p>
|
|
5420
|
+
<div class="admonition warning">
|
|
5421
|
+
<p class="admonition-title">Not applied when using a Gcovr configuration file</p>
|
|
5422
|
+
<p>These defaults are only generated when Ceedling builds <code>gcovr</code>'s command
|
|
5423
|
+
line directly. As covered in
|
|
5424
|
+
<a href="#gcovr-configuration-file">Gcovr configuration file</a> above, setting
|
|
5425
|
+
<code>:config_file</code> bypasses this entirely — none of the three patterns above
|
|
5426
|
+
are applied, and you must supply equivalent exclusions in the config file
|
|
5427
|
+
yourself.</p>
|
|
5428
|
+
</div>
|
|
5429
|
+
<h3 id="overriding-the-defaults">Overriding the defaults</h3>
|
|
5430
|
+
<p><a href="#report_exclude"><code>:report_exclude</code></a> can only add exclusions on top of the
|
|
5431
|
+
three defaults above — <code>gcovr --exclude</code> is a deny-list with no way to
|
|
5432
|
+
"un-exclude" a pattern already passed to it, and this plugin always passes its
|
|
5433
|
+
own three patterns ahead of anything you configure there. Setting
|
|
5434
|
+
<a href="#report_include"><code>:report_include</code></a> doesn't help either; it narrows which
|
|
5435
|
+
files are considered at all, but an exclude pattern still wins over it for
|
|
5436
|
+
any file matching both.</p>
|
|
5437
|
+
<p>The only way to actually remove or replace one of these defaults — for
|
|
5438
|
+
example, to include test files in coverage results so you can confirm a
|
|
5439
|
+
conditional test build compiled the branches you expect — is a
|
|
5440
|
+
<a href="#gcovr-configuration-file">Gcovr configuration file</a>. Setting <code>:config_file</code>
|
|
5441
|
+
stops Ceedling from generating any of the three patterns at all, handing you
|
|
5442
|
+
full control:</p>
|
|
5443
|
+
<div class="highlight"><pre><span></span><code><a id="__codelineno-4-1" name="__codelineno-4-1" href="#__codelineno-4-1"></a><span class="c1">; gcovr.cfg — omits the test-file exclude pattern so test files remain in</span>
|
|
5444
|
+
<a id="__codelineno-4-2" name="__codelineno-4-2" href="#__codelineno-4-2"></a><span class="c1">; coverage results, while still keeping generated/vendored build output out.</span>
|
|
5445
|
+
<a id="__codelineno-4-3" name="__codelineno-4-3" href="#__codelineno-4-3"></a><span class="na">exclude</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">.*build/.+\.c$</span>
|
|
5446
|
+
</code></pre></div>
|
|
5447
|
+
<div class="highlight"><pre><span></span><code><a id="__codelineno-5-1" name="__codelineno-5-1" href="#__codelineno-5-1"></a><span class="nt">:gcov</span><span class="p">:</span>
|
|
5448
|
+
<a id="__codelineno-5-2" name="__codelineno-5-2" href="#__codelineno-5-2"></a><span class="w"> </span><span class="nt">:gcovr</span><span class="p">:</span>
|
|
5449
|
+
<a id="__codelineno-5-3" name="__codelineno-5-3" href="#__codelineno-5-3"></a><span class="w"> </span><span class="nt">:config_file</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">gcovr.cfg</span>
|
|
5450
|
+
</code></pre></div>
|
|
5451
|
+
<p>Note that this isn't scoped per category. Once a default is dropped, any
|
|
5452
|
+
file it would have excluded is folded into the same combined report as your
|
|
5453
|
+
production code, not broken out separately.</p>
|
|
5315
5454
|
<h2 id="plugin-configuration">Plugin configuration</h2>
|
|
5316
5455
|
<p>The following options are exposed through your project configuration file, all
|
|
5317
5456
|
beneath <code>:gcov</code> ↳ <code>:gcovr</code>. Only specify those you need or those whose defaults
|
|
@@ -5409,11 +5548,25 @@ is in addition to any other configured reports. (<code>gcovr --print-summary</co
|
|
|
5409
5548
|
<h3 id="report_include"><code>:report_include</code></h3>
|
|
5410
5549
|
<p>Keep only source files that match this filter. Filters are regular
|
|
5411
5550
|
expressions. (<code>gcovr --filter</code>)</p>
|
|
5551
|
+
<p>This narrows which files are considered at all, but does not override
|
|
5552
|
+
<a href="#results-filtering">Results filtering</a>'s automatic exclusion defaults — a
|
|
5553
|
+
file excluded by one of those three default patterns stays excluded even if
|
|
5554
|
+
it also matches <code>:report_include</code>. See
|
|
5555
|
+
<a href="#overriding-the-defaults">Overriding the defaults</a> if you need to remove one
|
|
5556
|
+
of them.</p>
|
|
5412
5557
|
<p><strong>Example:</strong> <code>"^src"</code></p>
|
|
5413
5558
|
<hr />
|
|
5414
5559
|
<h3 id="report_exclude"><code>:report_exclude</code></h3>
|
|
5415
5560
|
<p>Exclude source files that match this filter. Filters are regular expressions.
|
|
5416
5561
|
(<code>gcovr --exclude</code>)</p>
|
|
5562
|
+
<p>Ceedling automatically generates and prepends its own exclusion patterns for
|
|
5563
|
+
test files, test support files, and generated/vendored build files — see
|
|
5564
|
+
<a href="#results-filtering">Results filtering</a> above for exactly what these cover
|
|
5565
|
+
and why. Anything you provide here is combined with those defaults, not a
|
|
5566
|
+
replacement for them. This option can only add further exclusions, never
|
|
5567
|
+
remove or override one of the three defaults.
|
|
5568
|
+
See <a href="#overriding-the-defaults">Overriding the defaults</a> for how to do
|
|
5569
|
+
that instead.</p>
|
|
5417
5570
|
<p><strong>Example:</strong> <code>"^vendor.*|^build.*|^test.*|^lib.*"</code></p>
|
|
5418
5571
|
<hr />
|
|
5419
5572
|
<h3 id="gcov_filter"><code>:gcov_filter</code></h3>
|