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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 828ad43a2f6d106ff54bb18fcb6bab61f3c9164f1ae7f2c2923d8739f0351696
|
|
4
|
+
data.tar.gz: d0f1bd257e32aa6c45cb1166904a124ea4f2f5bb17c6e3504a5c8b3e7b7bce28
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 40b9742b2c4bc7deb08a52e2281cf81b4684bbcdb08ac5b3dcffd6d0ee2af087c7cda184764938bb54bbb5b1c5e9d6fd17d822468cbc8b579667a21228917ca7
|
|
7
|
+
data.tar.gz: 67be8904bf70f79f954b13a4fcfd8b47805fc82e5a2ea3e1af7b82463759dcf08846c75638b280f19f38538a212cc91d958dcde785729377f654411c3de69ef3
|
data/GIT_COMMIT_SHA
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
85ec551
|
data/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Ceedling 
|
|
2
2
|
========
|
|
3
3
|
|
|
4
|
-
**Ceedling 1.1.
|
|
4
|
+
**Ceedling 1.1.10** is the latest and greatest.
|
|
5
5
|
|
|
6
6
|
See [_Release Notes_][release-notes], [_Changelog_](docs/Changelog.md),
|
|
7
7
|
[_Breaking Changes_][breaking-changes], and [_Known Issues_][known-issues].
|
|
@@ -472,10 +472,10 @@ Matt Chernosky’s **[detailed tutorial][tutorial]** demonstrates using Ceedling
|
|
|
472
472
|
|
|
473
473
|
### Local installation from the RubyGems repository
|
|
474
474
|
|
|
475
|
-
1. Install [Ruby]. (
|
|
475
|
+
1. Install [Ruby]. (Ceedling requires Ruby 3+ but only unoficially supports Ruby 4.)
|
|
476
476
|
1. Install the Ceedling gem from the RubyGems repository. All supporting frameworks are included and this style of installation installs dependencies as well.
|
|
477
477
|
```shell
|
|
478
|
-
> gem install ceedling
|
|
478
|
+
> gem install ceedling --no-document
|
|
479
479
|
```
|
|
480
480
|
1. Begin crafting your project:
|
|
481
481
|
1. Create an empty Ceedling project.
|
|
@@ -487,6 +487,7 @@ Matt Chernosky’s **[detailed tutorial][tutorial]** demonstrates using Ceedling
|
|
|
487
487
|
```shell
|
|
488
488
|
> ceedling test:all release
|
|
489
489
|
```
|
|
490
|
+
|
|
490
491
|
### Local installation of the .gem file downloaded from this repo
|
|
491
492
|
|
|
492
493
|
If you are working with prerelease versions of Ceedling or some other off-the-beaten-path installation scenario, you may want to directly install the Ceedling .gem file attached to any of the Github releases. No problem.
|
data/docs/Changelog.md
CHANGED
|
@@ -10,6 +10,16 @@ This changelog is complemented by three other documents:
|
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
+
# [1.1.10] — 2026-10-07
|
|
14
|
+
|
|
15
|
+
## 💪 Fixed
|
|
16
|
+
|
|
17
|
+
### Partials
|
|
18
|
+
|
|
19
|
+
- [#1319](https://github.com/ThrowTheSwitch/Ceedling/issues/1319) Fixed a Partials-generated types header leaving out the `#include` directives its extracted types need, causing an `unknown type name` or `undeclared here` compilation error. The generated header now carries its needed headers itself and no longer depends on the incidental order of includes before it.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
13
23
|
# [1.1.9] — 2026-09-20
|
|
14
24
|
|
|
15
25
|
## 💪 Fixed
|
data/docs/KnownIssues.md
CHANGED
|
@@ -17,14 +17,23 @@ Known issues are complemented by three other documents:
|
|
|
17
17
|
## 1.1.0 — 2026-07-16
|
|
18
18
|
|
|
19
19
|
1. The new internal pipeline as of 1.0.0 that allows builds to be parallelized and configured per-test-executable can mean a fair amount of duplication of steps. A header file may be mocked identically multiple times. The same source file may be compiled identically multiple times. The speed gains due to parallelization help make up for this. Future releases will concentrate on optimizing away duplication of build steps.
|
|
20
|
-
1. While header file search paths are now customizable per executable, this currently only applies to the search paths the compiler uses. Distinguishing test files or header files of the same name in different directories for test runner and mock generation respectively continues to rely on educated guesses in Ceedling code.
|
|
20
|
+
1. While header file search paths are now customizable per executable, this currently only applies to the search paths the compiler uses. Distinguishing test files or header files of the same name in different directories for test runner and mock generation respectively continues to rely on educated guesses in Ceedling code. Support for full path-qualified disambiguation will arrive in 1.2.0.
|
|
21
21
|
1. All header files needed for test compilation must be within the `:includes` path collection. Relative paths in include directives that extend outside the path collection will cause build problems.
|
|
22
22
|
1. Any path for a C file specified with `TEST_SOURCE_FILE(...)` is in relation to **_project root_** — that is, from where you execute `ceedling` at the command line. If you move source files or change your directory structure, many of your `TEST_SOURCE_FILE(...)` calls may need to be updated. A more flexible and dynamic approach to path handling will come in a future update.
|
|
23
23
|
1. In certain combinations of conditional preprocessing blocks with dependent symbols defined in another file, Ceedling can silently fail to extract computed includes (e.g. `#include SOME_MACRO()`).
|
|
24
|
-
1. User includes (`#include "path/user.h"`) from source C files lose their relative path when Partial and mock header files are generated from source. Compilation failures can result from certain uncommon cases involving headers of the same names in different directories and a source file including both such headers.
|
|
25
24
|
1. The automatic vendor copying of Unity, CMock, and CException into a project's build directory can intermittently fail with a file/directory type error, most often under antivirus/EDR file locking, cloud-sync filter drivers, or two concurrent Ceedling invocations racing the same destination. Deleting `build/` (or reinstalling the gem) and rebuilding works around it.
|
|
26
25
|
1. The Bullseye code coverage plugin has been temporarily disabled as of 1.0.0. The makers of Bullseye have generously provided a license for development, and the plugin will be available in the next minor release.
|
|
27
26
|
|
|
27
|
+
### Partials
|
|
28
|
+
|
|
29
|
+
1. User includes (`#include "path/user.h"`) from source C files lose their relative path when Partial and mock header files are generated from source. Compilation failures can result from certain uncommon cases involving headers of the same names in different directories and a source file including both such headers.
|
|
30
|
+
1. Partial directive macros accept only a bare module name — a filename stem with no path. A project holding two modules of the same name in different directories cannot say which of them a Partial is for, and Ceedling resolves the name the way a compiler resolves a header, selecting the first match among the ordered search paths. Path-qualified Partial macros will arrive in 1.2.0.
|
|
31
|
+
1. A module whose header protects itself with `#pragma once` instead of a traditional `#ifndef` include guard can still hit a `redefinition` or `conflicting types` error, if any other header your module uses reaches that header in turn. Ceedling suppresses the real header by defining its include guard, and `#pragma once` provides no guard to define. Converting the module’s header to a traditional include guard works around it.
|
|
32
|
+
1. A `struct`, `union`, or `enum` written directly on a variable, as in `static struct { int depth; } slot;`, is treated as a variable alone. The generated Partial states the type twice and fails to compile.
|
|
33
|
+
1. A `struct`, `union`, or `enum` named but not defined, as in `struct node;`, is reproduced in the generated Partial as an invalid declaration. Builds treating warnings as errors fail on it.
|
|
34
|
+
1. A macro the module retires with `#undef` is carried into the generated Partial anyway, so the name stays visible to your test file and can collide with another macro of the same name.
|
|
35
|
+
1. Exposing a module’s file-scope variables and functions removes what kept their names private to that module. Two Partialized modules in one test file that each use the same name for a file-scope variable collide at link time.
|
|
36
|
+
|
|
28
37
|
---
|
|
29
38
|
|
|
30
39
|
## 1.0.0 — 2025-01-01
|
data/docs/SECURITY.md
CHANGED
|
@@ -7,6 +7,34 @@ projects, including `Unity`, `CMock`, and `Ceedling`.
|
|
|
7
7
|
* [Disclosure Policy](#disclosure-policy)
|
|
8
8
|
* [Comments on this Policy](#comments-on-this-policy)
|
|
9
9
|
|
|
10
|
+
## Automated Security Scanner False Positives
|
|
11
|
+
|
|
12
|
+
Ceedling is built with Ruby, and Ruby’s package manager (RubyGems/Bundler)
|
|
13
|
+
caches a local index of the *entire* public RubyGems.org registry in order
|
|
14
|
+
to resolve dependencies (e.g. `~/.gem/specs/rubygems.org%443/specs.4.8`).
|
|
15
|
+
That cache lists every gem ever published to RubyGems.org — including many
|
|
16
|
+
completely unrelated to Ceedling whose names happen to reference
|
|
17
|
+
cryptocurrency, wallets, or mining. An automated scanner that searches this
|
|
18
|
+
cache file for such keywords will find matches purely because of what
|
|
19
|
+
RubyGems.org hosts, not because of anything in Ceedling’s own code or its
|
|
20
|
+
declared dependencies.
|
|
21
|
+
|
|
22
|
+
If your organization’s security tooling flags a Ceedling installation for
|
|
23
|
+
cryptocurrency-related content, check first whether the flagged file
|
|
24
|
+
originates from a Ruby/RubyGems package cache rather than from Ceedling’s
|
|
25
|
+
own source tree. Ceedling’s actual dependencies are declared in `Gemfile`
|
|
26
|
+
and `ceedling.gemspec`, neither of which includes any cryptocurrency,
|
|
27
|
+
wallet, or mining related package.
|
|
28
|
+
|
|
29
|
+
Separately, Ceedling’s core function is compiling and running C test
|
|
30
|
+
executables. A scanner that flags a compiled test binary (e.g. a `.out` or
|
|
31
|
+
`.exe` file) as a suspicious executable is correctly observing Ceedling
|
|
32
|
+
doing its job, not a symptom of a security issue.
|
|
33
|
+
|
|
34
|
+
See [issue #940](https://github.com/ThrowTheSwitch/Ceedling/issues/940) for
|
|
35
|
+
an example of this exact false positive, including the specific package-cache
|
|
36
|
+
evidence.
|
|
37
|
+
|
|
10
38
|
## Reporting a Bug
|
|
11
39
|
|
|
12
40
|
The tools from `ThrowTheSwitch.org` are made to collaborate with other tools like compilers,
|
|
@@ -19,8 +47,18 @@ make every effort to improve our tools safe use. Thank you for improving the sec
|
|
|
19
47
|
our tools. We appreciate your efforts and responsible disclosure and will make every effort
|
|
20
48
|
to acknowledge your contributions.
|
|
21
49
|
|
|
22
|
-
Report security bugs
|
|
23
|
-
|
|
50
|
+
Report security bugs using the corresponding
|
|
51
|
+
[ThrowTheSwitch project’s](https://github.com/ThrowTheSwitch/) private vulnerability
|
|
52
|
+
reporting feature on GitHub
|
|
53
|
+
[[jump to Ceedling’s private vulnerability reporting](https://github.com/ThrowTheSwitch/Ceedling/security/advisories/new)]:
|
|
54
|
+
|
|
55
|
+
1. From the project’s repository page, select the **_Security_** tab
|
|
56
|
+
2. Then **_Report a vulnerability_**.
|
|
57
|
+
|
|
58
|
+
This opens a private advisory visible only to maintainers, rather than a public GitHub Issue
|
|
59
|
+
that would expose the vulnerability before a fix is available. If a ThrowTheSwitch project
|
|
60
|
+
has not yet enabled this feature, or you would rather not use GitHub, email
|
|
61
|
+
[security@thingamabyte.com](mailto:security@thingamabyte.com) instead.
|
|
24
62
|
|
|
25
63
|
Report security bugs in third-party modules to the person or team maintaining
|
|
26
64
|
the module.
|
|
@@ -18,6 +18,14 @@
|
|
|
18
18
|
Guidelines for contributing to this project — be it code, reviews,
|
|
19
19
|
documentation, or issue reports.
|
|
20
20
|
|
|
21
|
+
- :material-shield-lock: **[Security][security]**
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
See the [policy][security-policy] for disclosure details and
|
|
26
|
+
guidance on issues that vulnerability inspection tools may surface.
|
|
27
|
+
Report a vulnerability through a [private advisory][security-report].
|
|
28
|
+
|
|
21
29
|
</div>
|
|
22
30
|
|
|
23
31
|
## Projects
|
|
@@ -46,5 +54,8 @@
|
|
|
46
54
|
[code-of-conduct]: https://github.com/ThrowTheSwitch/Ceedling/blob/master/docs/CODE_OF_CONDUCT.md
|
|
47
55
|
[contributing]: https://github.com/ThrowTheSwitch/Ceedling/blob/master/docs/CONTRIBUTING.md
|
|
48
56
|
[dev-workflow]: workflow.md
|
|
57
|
+
[security]: https://github.com/ThrowTheSwitch/Ceedling?tab=security-ov-file
|
|
58
|
+
[security-policy]: https://github.com/ThrowTheSwitch/Ceedling/blob/master/docs/SECURITY.md
|
|
59
|
+
[security-report]: https://github.com/ThrowTheSwitch/Ceedling/security/advisories/new
|
|
49
60
|
|
|
50
61
|
<br/><br/>
|
data/docs/mkdocs/plugins/fff.md
CHANGED
|
@@ -4,7 +4,7 @@ This plugin causes Ceedling to use the [Fake Function Framework](https://github.
|
|
|
4
4
|
|
|
5
5
|
Using _FFF_ provides less strict mocking than CMock and affords more loosely-coupled tests.
|
|
6
6
|
|
|
7
|
-
This Ceedling 1.x plugin incorporates a snapshot of _FFF_ version
|
|
7
|
+
This Ceedling 1.x plugin incorporates a snapshot of _FFF_ version 1.1 and supersedes a separately available [FFF Ceedling plugin project](https://github.com/ElectronVector/fake_function_framework). The built-in _FFF_ plugin that now comes with Ceedling was derived from the ElectronVector project and is now maintained along with Ceedling and tracks its updates.
|
|
8
8
|
|
|
9
9
|
!!! note "Special thanks to Matt Chernosky"
|
|
10
10
|
[Matt Chernosky](http://www.electronvector.com) originally developed this plugin
|
|
@@ -27,9 +27,14 @@ GCovr can be configured in two ways:
|
|
|
27
27
|
CLI arguments. You must provide any settings that would have been provided
|
|
28
28
|
by the Gcov plugin.
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
A Gcovr config file replaces Ceedling's own automatically generated exclusion
|
|
31
|
+
patterns (see [Results filtering](#results-filtering) below) entirely — it is
|
|
32
|
+
the only way to override or remove one of those defaults, since the
|
|
33
|
+
project-configuration `:report_exclude` option can only add further
|
|
34
|
+
exclusions on top of them, never take one away. To preserve the same
|
|
35
|
+
filtering of test and build files when switching to a Gcovr config file, you
|
|
36
|
+
must provide equivalent explicit exclusion patterns matching your project
|
|
37
|
+
layout yourself (example below).
|
|
33
38
|
|
|
34
39
|
```ini
|
|
35
40
|
; You will need to revise these example exclude patterns to match your
|
|
@@ -45,6 +50,99 @@ exclude = .*test.*/test_.+\.c$
|
|
|
45
50
|
exclude = .*build/.+\.c$
|
|
46
51
|
```
|
|
47
52
|
|
|
53
|
+
## Results filtering
|
|
54
|
+
|
|
55
|
+
By default, this plugin configures `gcovr` to excludes three categories of
|
|
56
|
+
`.c` files from coverage results. These defaults exist because a
|
|
57
|
+
coverage percentage is typically only meaningful over the production code
|
|
58
|
+
you're actually trying to exercise with test coverage. Test code, test
|
|
59
|
+
support code, and every file Ceedling itself generates as part of a build
|
|
60
|
+
will skew that number if left in coverage reporting.
|
|
61
|
+
|
|
62
|
+
The list that follows details the filtering this plugin injects into
|
|
63
|
+
Gcovr coverage report generation. The examples are usable regular
|
|
64
|
+
expressions that mirror the defaults in use. The plugin dynamically
|
|
65
|
+
generates these regular expressions from your project configuration.
|
|
66
|
+
When creating them youself, you will need to match your project
|
|
67
|
+
configuration settings with static strings.
|
|
68
|
+
|
|
69
|
+
1. **Test files** — matched by `:test_file_prefix` within your configured
|
|
70
|
+
`:paths` ↳ `:test` directories.
|
|
71
|
+
|
|
72
|
+
Given `:test_file_prefix` ⇒ `test_` and a `:paths` ↳ `:test` entry of
|
|
73
|
+
`test/`:
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
.*test/.*/test_.+\.c$
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
2. **Test support files** — any `.c` file within your configured `:paths` ↳
|
|
80
|
+
`:support` directories, regardless of name. Helpers, stubs, and fixtures
|
|
81
|
+
living there are no more production code than the test files themselves.
|
|
82
|
+
|
|
83
|
+
Given a `:paths` ↳ `:support` entry of `test/support/`:
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
.*test/support/.+\.c$
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
3. **Generated and vendored files** — any `.c` file anywhere below your
|
|
90
|
+
`:build_root`: generated mocks, test runners, Partials output, and the
|
|
91
|
+
vendored Unity/CMock/CException framework sources Ceedling copies in to
|
|
92
|
+
build against. This pattern always matches a literal `.c` extension
|
|
93
|
+
regardless of your project's own `:extension` ↳ `:source` setting, since
|
|
94
|
+
every file it catches is one Ceedling itself writes in plain C.
|
|
95
|
+
|
|
96
|
+
Given `:build_root` ⇒ `build/`:
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
.*build/.+\.c$
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
These patterns are generated automatically and combined with whatever you
|
|
103
|
+
provide via [`:report_exclude`](#report_exclude) below.
|
|
104
|
+
|
|
105
|
+
!!! warning "Not applied when using a Gcovr configuration file"
|
|
106
|
+
These defaults are only generated when Ceedling builds `gcovr`'s command
|
|
107
|
+
line directly. As covered in
|
|
108
|
+
[Gcovr configuration file](#gcovr-configuration-file) above, setting
|
|
109
|
+
`:config_file` bypasses this entirely — none of the three patterns above
|
|
110
|
+
are applied, and you must supply equivalent exclusions in the config file
|
|
111
|
+
yourself.
|
|
112
|
+
|
|
113
|
+
### Overriding the defaults
|
|
114
|
+
|
|
115
|
+
[`:report_exclude`](#report_exclude) can only add exclusions on top of the
|
|
116
|
+
three defaults above — `gcovr --exclude` is a deny-list with no way to
|
|
117
|
+
"un-exclude" a pattern already passed to it, and this plugin always passes its
|
|
118
|
+
own three patterns ahead of anything you configure there. Setting
|
|
119
|
+
[`:report_include`](#report_include) doesn't help either; it narrows which
|
|
120
|
+
files are considered at all, but an exclude pattern still wins over it for
|
|
121
|
+
any file matching both.
|
|
122
|
+
|
|
123
|
+
The only way to actually remove or replace one of these defaults — for
|
|
124
|
+
example, to include test files in coverage results so you can confirm a
|
|
125
|
+
conditional test build compiled the branches you expect — is a
|
|
126
|
+
[Gcovr configuration file](#gcovr-configuration-file). Setting `:config_file`
|
|
127
|
+
stops Ceedling from generating any of the three patterns at all, handing you
|
|
128
|
+
full control:
|
|
129
|
+
|
|
130
|
+
```ini
|
|
131
|
+
; gcovr.cfg — omits the test-file exclude pattern so test files remain in
|
|
132
|
+
; coverage results, while still keeping generated/vendored build output out.
|
|
133
|
+
exclude = .*build/.+\.c$
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
```yaml
|
|
137
|
+
:gcov:
|
|
138
|
+
:gcovr:
|
|
139
|
+
:config_file: gcovr.cfg
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Note that this isn't scoped per category. Once a default is dropped, any
|
|
143
|
+
file it would have excluded is folded into the same combined report as your
|
|
144
|
+
production code, not broken out separately.
|
|
145
|
+
|
|
48
146
|
## Plugin configuration
|
|
49
147
|
|
|
50
148
|
The following options are exposed through your project configuration file, all
|
|
@@ -198,6 +296,13 @@ is in addition to any other configured reports. (`gcovr --print-summary`)
|
|
|
198
296
|
Keep only source files that match this filter. Filters are regular
|
|
199
297
|
expressions. (`gcovr --filter`)
|
|
200
298
|
|
|
299
|
+
This narrows which files are considered at all, but does not override
|
|
300
|
+
[Results filtering](#results-filtering)'s automatic exclusion defaults — a
|
|
301
|
+
file excluded by one of those three default patterns stays excluded even if
|
|
302
|
+
it also matches `:report_include`. See
|
|
303
|
+
[Overriding the defaults](#overriding-the-defaults) if you need to remove one
|
|
304
|
+
of them.
|
|
305
|
+
|
|
201
306
|
**Example:** `"^src"`
|
|
202
307
|
|
|
203
308
|
---
|
|
@@ -207,6 +312,15 @@ expressions. (`gcovr --filter`)
|
|
|
207
312
|
Exclude source files that match this filter. Filters are regular expressions.
|
|
208
313
|
(`gcovr --exclude`)
|
|
209
314
|
|
|
315
|
+
Ceedling automatically generates and prepends its own exclusion patterns for
|
|
316
|
+
test files, test support files, and generated/vendored build files — see
|
|
317
|
+
[Results filtering](#results-filtering) above for exactly what these cover
|
|
318
|
+
and why. Anything you provide here is combined with those defaults, not a
|
|
319
|
+
replacement for them. This option can only add further exclusions, never
|
|
320
|
+
remove or override one of the three defaults.
|
|
321
|
+
See [Overriding the defaults](#overriding-the-defaults) for how to do
|
|
322
|
+
that instead.
|
|
323
|
+
|
|
210
324
|
**Example:** `"^vendor.*|^build.*|^test.*|^lib.*"`
|
|
211
325
|
|
|
212
326
|
---
|
|
@@ -20,6 +20,99 @@ All generated reports are found in `<build root>/artifacts/gcov/ReportGenerator/
|
|
|
20
20
|
- "-title:MyProject"
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
+
## Results filtering
|
|
24
|
+
|
|
25
|
+
This plugin filters coverage results for `reportgenerator` coverage reporting
|
|
26
|
+
in two separate stages, each with its own defaults.
|
|
27
|
+
|
|
28
|
+
### Coverage generation filtering
|
|
29
|
+
|
|
30
|
+
Before `reportgenerator` ever runs, this plugin runs `gcov` itself against each
|
|
31
|
+
`.gcno` file produced by the coverage test build, skipping any that match an
|
|
32
|
+
exclusion pattern — no `.gcov` data is ever produced for a skipped file, so
|
|
33
|
+
nothing downstream can put it back into a report.
|
|
34
|
+
|
|
35
|
+
By default this skips:
|
|
36
|
+
|
|
37
|
+
- **Test files** — matched by `:test_file_prefix`.
|
|
38
|
+
- **Mocks** — matched by `:mock_prefix`.
|
|
39
|
+
- **Test runners** — any filename containing `_runner`.
|
|
40
|
+
- **Vendored Unity and CMock sources** — `unity.gcno` and `cmock.gcno` by
|
|
41
|
+
name.
|
|
42
|
+
|
|
43
|
+
Given `:test_file_prefix` ⇒ `test_` and CMock's default `:mock_prefix` ⇒
|
|
44
|
+
`Mock`, the equivalent filename-fragment patterns are:
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
test_[^\/\\]*
|
|
48
|
+
Mock[^\/\\]*
|
|
49
|
+
[^\/\\]*_runner[^\/\\]*
|
|
50
|
+
unity
|
|
51
|
+
cmock
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
These combine with whatever you add via [`:gcov_exclude`](#gcov_exclude)
|
|
55
|
+
below. Your patterns extend this list, they don't replace it.
|
|
56
|
+
|
|
57
|
+
### Report filtering
|
|
58
|
+
|
|
59
|
+
Separately, once `.gcov` files exist, ReportGenerator's own `-filefilters:`
|
|
60
|
+
argument controls which of them actually appear in the generated report(s).
|
|
61
|
+
By default this excludes:
|
|
62
|
+
|
|
63
|
+
1. **Test paths** — every file anywhere under each of your configured
|
|
64
|
+
`:paths` ↳ `:test` directories, not only files matching
|
|
65
|
+
`:test_file_prefix`. A support subdirectory nested under a test path
|
|
66
|
+
(e.g. `test/support/`) is excluded as a side effect of this — the whole
|
|
67
|
+
tree goes, not just prefixed test files.
|
|
68
|
+
|
|
69
|
+
Given a `:paths` ↳ `:test` entry of `test/`:
|
|
70
|
+
```
|
|
71
|
+
-./test/**/*
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
1. **The build root** — every generated and vendored file: mocks, test
|
|
75
|
+
runners, Partials output, Unity, CMock, CException.
|
|
76
|
+
|
|
77
|
+
Given `:build_root` ⇒ `build/`:
|
|
78
|
+
```
|
|
79
|
+
-./build/**/*
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
1. **Partial-generated files** — only when `:use_partials` is enabled, any
|
|
83
|
+
file whose name starts with Ceedling's Partial filename prefix, wherever
|
|
84
|
+
it's found (not only under the build root).
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
-ceedling_partial_*
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
These patterns are generated automatically and placed ahead of whatever you
|
|
91
|
+
provide via [`:file_filters`](#file_filters) below.
|
|
92
|
+
|
|
93
|
+
### Overriding the defaults
|
|
94
|
+
|
|
95
|
+
Neither filtering stage above can be overridden or narrowed by plugin
|
|
96
|
+
configuration — only added to.
|
|
97
|
+
|
|
98
|
+
For [coverage generation filtering](#coverage-generation-filtering),
|
|
99
|
+
[`:gcov_exclude`](#gcov_exclude) only ever adds more exclusion patterns; there
|
|
100
|
+
is no plugin option to disable one of the built-in exclusions, and no way to
|
|
101
|
+
resurrect `.gcov` data for a file `gcov` was never run against in the first
|
|
102
|
+
place.
|
|
103
|
+
|
|
104
|
+
For [report filtering](#report-filtering), the natural instinct is to reach
|
|
105
|
+
for [`:custom_args`](#custom_args) to pass a second, conflicting
|
|
106
|
+
`-filefilters:` argument, but this is not an option because of ReportGenerator's
|
|
107
|
+
rules and the order in which the filters are provided by the plugin.
|
|
108
|
+
|
|
109
|
+
In short, there's no supported way to broaden what this plugin reports
|
|
110
|
+
beyond its defaults. If you need to override coverage reporting filtering,
|
|
111
|
+
use the [Gcovr option for this pluing](gcovr.md) instead. Its
|
|
112
|
+
`:config_file` option hands full control to a `gcovr` configuration file,
|
|
113
|
+
bypassing Ceedling's generated exclusions entirely (see
|
|
114
|
+
[Gcovr's Results filtering](gcovr.md#results-filtering)).
|
|
115
|
+
|
|
23
116
|
## Plugin configuration
|
|
24
117
|
|
|
25
118
|
### `:history_directory`
|
|
@@ -62,10 +155,16 @@ filters. Wildcards are allowed, but not regular expressions.
|
|
|
62
155
|
|
|
63
156
|
Optional list of files that should be included or excluded in the report
|
|
64
157
|
(separated by semicolon). Exclusion filters take precedence over inclusion
|
|
65
|
-
filters. Wildcards are allowed, but not regular
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
158
|
+
filters regardless of order. Wildcards are allowed, but not regular
|
|
159
|
+
expressions.
|
|
160
|
+
|
|
161
|
+
This plugin places your own patterns first, ahead of the exclusions it
|
|
162
|
+
generates automatically for test paths, the build root, and (when Partials
|
|
163
|
+
are in use) Partial-generated files (see
|
|
164
|
+
[Report filtering](#report-filtering) above for exactly what those defaults
|
|
165
|
+
cover). Because exclusions always win, your patterns can add further
|
|
166
|
+
exclusions or includes but cannot override or remove one of those defaults;
|
|
167
|
+
see [Overriding the defaults](#overriding-the-defaults) above.
|
|
69
168
|
|
|
70
169
|
**Example:** `"-./vendor/*;-./build/*;-./test/*;-./lib/*;+./src/*"`
|
|
71
170
|
|
|
@@ -94,6 +193,13 @@ Optional list of one or more regular expressions to exclude gcov notes
|
|
|
94
193
|
files are never run through `gcov` at all. A trailing `.gcov` or `.gcno`
|
|
95
194
|
suffix on a pattern is stripped automatically, so either form works.
|
|
96
195
|
|
|
196
|
+
Ceedling combines your patterns with exclusions it generates automatically
|
|
197
|
+
for test files, mocks, test runners, and vendored Unity/CMock sources (see
|
|
198
|
+
[Coverage generation filtering](#coverage-generation-filtering) above for
|
|
199
|
+
exactly what these cover). Your patterns can only add further exclusions;
|
|
200
|
+
there's no way to override or remove one of the defaults — see
|
|
201
|
+
[Overriding the defaults](#overriding-the-defaults) above.
|
|
202
|
+
|
|
97
203
|
```yaml
|
|
98
204
|
:gcov:
|
|
99
205
|
:report_generator:
|
|
@@ -40,17 +40,19 @@ class Generator
|
|
|
40
40
|
# rather than duplicated by generate_partial_implementation and generate_partial_interface.
|
|
41
41
|
# Returns the bare generated filename (for the caller to add to each header's own includes
|
|
42
42
|
# list) or nil when the module has no typedefs or aggregate definitions to share.
|
|
43
|
-
def generate_partial_types(name:, c_module:, output_path:)
|
|
43
|
+
def generate_partial_types(name:, c_module:, output_path:, includes: [], include_guard: nil)
|
|
44
44
|
arg_hash = {
|
|
45
45
|
:name => name,
|
|
46
46
|
:c_module => c_module,
|
|
47
|
-
:output_path => output_path
|
|
47
|
+
:output_path => output_path,
|
|
48
|
+
:includes => includes,
|
|
49
|
+
:include_guard => include_guard
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
return @generator_partials.generate_types( **arg_hash )
|
|
51
53
|
end
|
|
52
54
|
|
|
53
|
-
def generate_partial_interface(test:, partial:, function_declarations:, includes:, c_module:, input_filepath:, output_path:)
|
|
55
|
+
def generate_partial_interface(test:, partial:, function_declarations:, includes:, c_module:, input_filepath:, output_path:, include_guard: nil)
|
|
54
56
|
msg = @reportinator.generate_module_progress(
|
|
55
57
|
operation: "Generating Partial mockable interface for",
|
|
56
58
|
module_name: test,
|
|
@@ -64,7 +66,8 @@ class Generator
|
|
|
64
66
|
:function_declarations => function_declarations,
|
|
65
67
|
:includes => includes,
|
|
66
68
|
:c_module => c_module,
|
|
67
|
-
:output_path => output_path
|
|
69
|
+
:output_path => output_path,
|
|
70
|
+
:include_guard => include_guard
|
|
68
71
|
}
|
|
69
72
|
|
|
70
73
|
return @generator_partials.generate_interface( **arg_hash )
|
|
@@ -78,7 +81,8 @@ class Generator
|
|
|
78
81
|
header_includes:,
|
|
79
82
|
c_module:,
|
|
80
83
|
input_filepath:,
|
|
81
|
-
output_path
|
|
84
|
+
output_path:,
|
|
85
|
+
include_guard: nil
|
|
82
86
|
)
|
|
83
87
|
|
|
84
88
|
msg = @reportinator.generate_module_progress(
|
|
@@ -95,7 +99,8 @@ class Generator
|
|
|
95
99
|
:source_includes => source_includes,
|
|
96
100
|
:header_includes => header_includes,
|
|
97
101
|
:c_module => c_module,
|
|
98
|
-
:output_path => output_path
|
|
102
|
+
:output_path => output_path,
|
|
103
|
+
:include_guard => include_guard
|
|
99
104
|
}
|
|
100
105
|
|
|
101
106
|
return @generator_partials.generate_implementation( **arg_hash )
|
|
@@ -21,7 +21,8 @@ class GeneratorPartials
|
|
|
21
21
|
source_includes:,
|
|
22
22
|
header_includes:,
|
|
23
23
|
c_module:,
|
|
24
|
-
output_path
|
|
24
|
+
output_path:,
|
|
25
|
+
include_guard: nil
|
|
25
26
|
)
|
|
26
27
|
source = @file_path_utils.form_partial_implementation_source_filename(name)
|
|
27
28
|
header = @file_path_utils.form_partial_implementation_header_filename(name)
|
|
@@ -34,7 +35,10 @@ class GeneratorPartials
|
|
|
34
35
|
# write, which would alter any line ending already present in that
|
|
35
36
|
# content instead of passing it through unchanged.
|
|
36
37
|
@file_wrapper.open(header_filepath, 'wb') do |file|
|
|
37
|
-
generate_header(
|
|
38
|
+
generate_header(
|
|
39
|
+
file, header, header_includes, function_definitions, c_module,
|
|
40
|
+
include_variables: true, include_guard: include_guard
|
|
41
|
+
)
|
|
38
42
|
end
|
|
39
43
|
|
|
40
44
|
@file_wrapper.open(source_filepath, 'wb') do |file|
|
|
@@ -44,13 +48,16 @@ class GeneratorPartials
|
|
|
44
48
|
return source_filepath
|
|
45
49
|
end
|
|
46
50
|
|
|
47
|
-
def generate_interface(test:, name:, function_declarations:, includes:, c_module:, output_path:)
|
|
51
|
+
def generate_interface(test:, name:, function_declarations:, includes:, c_module:, output_path:, include_guard: nil)
|
|
48
52
|
header = @file_path_utils.form_partial_interface_header_filename(name)
|
|
49
53
|
filepath = File.join(output_path, header)
|
|
50
54
|
|
|
51
55
|
# Binary mode: see generate_implementation above.
|
|
52
56
|
@file_wrapper.open(filepath, 'wb') do |file|
|
|
53
|
-
generate_header(
|
|
57
|
+
generate_header(
|
|
58
|
+
file, header, includes, function_declarations, c_module,
|
|
59
|
+
include_variables: false, include_guard: include_guard
|
|
60
|
+
)
|
|
54
61
|
end
|
|
55
62
|
|
|
56
63
|
return filepath
|
|
@@ -69,7 +76,7 @@ class GeneratorPartials
|
|
|
69
76
|
# @param c_module [CExtractorTypes::CModule] Merged module with type_definitions/aggregate_definitions
|
|
70
77
|
# @param output_path [String] Directory shared with the implementation and interface headers
|
|
71
78
|
# @return [String, nil] The bare filename (for use as a sibling #include), or nil if nothing was generated
|
|
72
|
-
def generate_types(name:, c_module:, output_path:)
|
|
79
|
+
def generate_types(name:, c_module:, output_path:, includes: [], include_guard: nil)
|
|
73
80
|
return nil if c_module.type_definitions.empty? && c_module.aggregate_definitions.empty?
|
|
74
81
|
|
|
75
82
|
header = @file_path_utils.form_partial_types_header_filename(name)
|
|
@@ -78,8 +85,7 @@ class GeneratorPartials
|
|
|
78
85
|
# Binary mode: see generate_implementation above.
|
|
79
86
|
@file_wrapper.open(filepath, 'wb') do |file|
|
|
80
87
|
guard = FileWrapper.generate_include_guard(header)
|
|
81
|
-
file
|
|
82
|
-
file << "#define #{guard}\n\n"
|
|
88
|
+
emit_preamble( file, guard, include_guard, includes )
|
|
83
89
|
|
|
84
90
|
anything_emitted = false
|
|
85
91
|
pending_macros = []
|
|
@@ -88,7 +94,10 @@ class GeneratorPartials
|
|
|
88
94
|
next unless item.is_a?(CExtractorTypes::CStatement)
|
|
89
95
|
|
|
90
96
|
if c_module.macro_definitions.include?(item)
|
|
91
|
-
|
|
97
|
+
# The guard emitted above also arrives among the extracted macros, since the real
|
|
98
|
+
# header's own `#define` survives preprocessing. Carrying it a second time is legal
|
|
99
|
+
# but puts a pointless duplicate in every generated types header.
|
|
100
|
+
pending_macros << item unless guard_macro?(item, include_guard)
|
|
92
101
|
next
|
|
93
102
|
end
|
|
94
103
|
|
|
@@ -116,6 +125,38 @@ class GeneratorPartials
|
|
|
116
125
|
|
|
117
126
|
private
|
|
118
127
|
|
|
128
|
+
# Everything above a generated header's own content: the file's include guard, the spoof of the
|
|
129
|
+
# real module header's guard, and the includes that header carries. Shared by all three
|
|
130
|
+
# generated headers, which open identically.
|
|
131
|
+
#
|
|
132
|
+
# The order of the last two is the whole point. A carried header can transitively reach the
|
|
133
|
+
# real module header, so the spoof has to be satisfied before any include is processed rather
|
|
134
|
+
# than after. And relocated content names things a generated file does not define, so without
|
|
135
|
+
# the includes it compiles only where something earlier in the translation unit happened to
|
|
136
|
+
# supply those names -- which is what made the types header's placement a conflict between two
|
|
137
|
+
# correct requirements rather than a choice.
|
|
138
|
+
def emit_preamble(io, guard, include_guard, includes)
|
|
139
|
+
io << "#ifndef #{guard}\n"
|
|
140
|
+
io << "#define #{guard}\n\n"
|
|
141
|
+
|
|
142
|
+
# A module header with no guard of its own supplies nothing to spoof.
|
|
143
|
+
io << "#define #{include_guard}\n\n" if include_guard
|
|
144
|
+
|
|
145
|
+
return if includes.empty?
|
|
146
|
+
|
|
147
|
+
includes.each { |include| io << "#{include}\n" }
|
|
148
|
+
io << "\n"
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Whether a macro statement is nothing but the definition of `include_guard`. Anchored so a
|
|
152
|
+
# macro whose name merely begins with the guard's name is never mistaken for it, and so a
|
|
153
|
+
# guard-named macro carrying an actual value is left alone.
|
|
154
|
+
def guard_macro?(item, include_guard)
|
|
155
|
+
return false if include_guard.nil?
|
|
156
|
+
|
|
157
|
+
item.text.match?(/\A\s*#\s*define\s+#{Regexp.escape( include_guard )}\s*\z/)
|
|
158
|
+
end
|
|
159
|
+
|
|
119
160
|
# A typedef or a non-typedef struct/enum/union tag definition establishes a type; C treats
|
|
120
161
|
# a second definition of the same type in one translation unit as a redefinition error even
|
|
121
162
|
# when the two definitions are textually identical. A macro statement carries no such
|
|
@@ -159,17 +200,9 @@ class GeneratorPartials
|
|
|
159
200
|
# @param function_list [Array] Pre-filtered Partials function objects (respond to :name and :signature)
|
|
160
201
|
# @param c_module [CExtractorTypes::CModule] Merged module with element_sequence
|
|
161
202
|
# @param include_variables [Boolean] True for implementation header (emits extern vars); false for interface
|
|
162
|
-
def generate_header(io, name, includes, function_list, c_module, include_variables)
|
|
203
|
+
def generate_header(io, name, includes, function_list, c_module, include_variables:, include_guard: nil)
|
|
163
204
|
guard = FileWrapper.generate_include_guard( name )
|
|
164
|
-
|
|
165
|
-
io << "#ifndef #{guard}\n"
|
|
166
|
-
io << "#define #{guard}\n\n"
|
|
167
|
-
|
|
168
|
-
includes.each do |include|
|
|
169
|
-
io << "#{include}\n"
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
io << "\n" if !includes.empty?
|
|
205
|
+
emit_preamble( io, guard, include_guard, includes )
|
|
173
206
|
|
|
174
207
|
func_by_name = function_list.to_h { |f| [f.name, f] }
|
|
175
208
|
emitted_funcs = {}
|
|
@@ -192,6 +225,9 @@ class GeneratorPartials
|
|
|
192
225
|
# generate_types instead of here, so that content defines a type exactly once no
|
|
193
226
|
# matter how many of a module's generated headers end up in the same test file.
|
|
194
227
|
next if type_defining?(item, c_module)
|
|
228
|
+
# The spoof above already states this one deliberately; carrying it again would put a
|
|
229
|
+
# pointless duplicate in the file.
|
|
230
|
+
next if guard_macro?(item, include_guard)
|
|
195
231
|
io << item.text << "\n"
|
|
196
232
|
last_was_func = false
|
|
197
233
|
anything_emitted = true
|