ceedling 1.1.8 → 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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/GIT_COMMIT_SHA +1 -1
  3. data/README.md +4 -3
  4. data/docs/Changelog.md +28 -0
  5. data/docs/KnownIssues.md +12 -2
  6. data/docs/SECURITY.md +40 -2
  7. data/docs/mkdocs/development/index.md +11 -0
  8. data/docs/mkdocs/plugins/fff.md +1 -1
  9. data/docs/mkdocs/plugins/gcov/gcovr.md +117 -3
  10. data/docs/mkdocs/plugins/gcov/reportgenerator.md +110 -4
  11. data/lib/ceedling/c_extractor/c_extractor_preprocessing.rb +29 -1
  12. data/lib/ceedling/file_path_utils.rb +4 -0
  13. data/lib/ceedling/generators/generator.rb +11 -6
  14. data/lib/ceedling/generators/generator_partials.rb +54 -18
  15. data/lib/ceedling/includes/includes.rb +8 -1
  16. data/lib/ceedling/objects.yml +2 -0
  17. data/lib/ceedling/partials/partializer.rb +204 -96
  18. data/lib/ceedling/test_invoker/test_build_executor.rb +21 -7
  19. data/lib/version.rb +1 -1
  20. data/site-local/development/index.html +7 -0
  21. data/site-local/plugins/fff.html +1 -1
  22. data/site-local/plugins/gcov/gcovr.html +156 -3
  23. data/site-local/plugins/gcov/reportgenerator.html +201 -14
  24. data/site-local/sitemap.xml.gz +0 -0
  25. data/spec/system/partials_types_header_spec.rb +166 -0
  26. data/spec/units/c_extractor/c_extractor_integration_spec.rb +18 -0
  27. data/spec/units/c_extractor/c_extractor_preprocessing_spec.rb +77 -0
  28. data/spec/units/generators/generator_partials_spec.rb +130 -17
  29. data/spec/units/includes/includes_spec.rb +21 -3
  30. data/spec/units/partials/partializer_spec.rb +225 -0
  31. data/vendor/unity/auto/generate_test_runner.rb +3 -1
  32. data/vendor/unity/auto/unity_test_summary.rb +2 -2
  33. data/vendor/unity/docs/UnityChangeLog.md +7 -0
  34. data/vendor/unity/docs/UnityConfigurationGuide.md +4 -0
  35. data/vendor/unity/src/unity_internals.h +21 -7
  36. data/vendor/unity/test/Makefile +9 -2
  37. data/vendor/unity/test/rakefile_helper.rb +1 -0
  38. data/vendor/unity/test/tests/test_generate_test_runner.rb +49 -0
  39. data/vendor/unity/test/tests/test_unity_test_summary.rb +58 -0
  40. metadata +5 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3c1edc565bc9fcb24accc9fd0d5001076fe86564cb0acd02c7d1fc092476c2c1
4
- data.tar.gz: 0c5ec0119bc3249824177c6094afd3e3ef9ee7da698b92fed894924d45d83625
3
+ metadata.gz: 828ad43a2f6d106ff54bb18fcb6bab61f3c9164f1ae7f2c2923d8739f0351696
4
+ data.tar.gz: d0f1bd257e32aa6c45cb1166904a124ea4f2f5bb17c6e3504a5c8b3e7b7bce28
5
5
  SHA512:
6
- metadata.gz: 6efc0307567637d4019978131f45758d694b97ea93a4a7ada5ff6be8c682d70eff9d8d453de4882cc46344bb1b0aa098dbf7982582a7d7a168818caba2bd7e51
7
- data.tar.gz: 6366fddeaff5572f317efffb161ff64378cae4e6b2dea30aa11f3baf4aac1777611331483d071a080cb9a01aa1e4087409d5314559881ae0a12ce753a1f86311
6
+ metadata.gz: 40b9742b2c4bc7deb08a52e2281cf81b4684bbcdb08ac5b3dcffd6d0ee2af087c7cda184764938bb54bbb5b1c5e9d6fd17d822468cbc8b579667a21228917ca7
7
+ data.tar.gz: 67be8904bf70f79f954b13a4fcfd8b47805fc82e5a2ea3e1af7b82463759dcf08846c75638b280f19f38538a212cc91d958dcde785729377f654411c3de69ef3
data/GIT_COMMIT_SHA CHANGED
@@ -1 +1 @@
1
- 885dc91
1
+ 85ec551
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  Ceedling ![CI](https://github.com/ThrowTheSwitch/Ceedling/workflows/CI/badge.svg)
2
2
  ========
3
3
 
4
- **Ceedling 1.1.8** is the latest and greatest.
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]. (Only Ruby 3+ supported.)
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,34 @@ 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
+
23
+ # [1.1.9] — 2026-09-20
24
+
25
+ ## 💪 Fixed
26
+
27
+ ### Partials
28
+
29
+ - [#1293](https://github.com/ThrowTheSwitch/Ceedling/issues/1293) Fixed a Partials-generated header occasionally redefining a type already declared by the real header it replaces, causing a `typedef redefinition with different types` compilation error. The triggering condition involved a source file whose real header was reachable both directly and through a macro-included intermediate file allowed by incomplete Partials include directive ordering.
30
+
31
+ ### Preprocessing
32
+
33
+ - Fixed whitespace occasionally inserted by the underlying compiler's preprocessor around a `#` or `##` operator (e.g. `x ##y` becoming `x ## y`) being carried through verbatim into Partials-generated and reconstructed macro definitions. Extracted macro text is now normalized so preprocessing stringize and token-paste operators always sit directly against their operands, regardless of what a given toolchain's preprocessor happens to emit.
34
+
35
+ ## ⚠️ Changed
36
+
37
+ - Updated Unity to latest version.
38
+
39
+ ---
40
+
13
41
  # [1.1.8] — 2026-09-10
14
42
 
15
43
  ## 💪 Fixed
data/docs/KnownIssues.md CHANGED
@@ -17,13 +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.
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.
25
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.
26
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
+
27
37
  ---
28
38
 
29
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 by opening a Github Issue on the corresponding project or (when this
23
- itself would pose a risk) by emailing security@thingamabyte.com.
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/>
@@ -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 0.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.
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
- To preserve filtering of test and build files from coverage results when
31
- using a Gcovr config file, you must provide explicit exclusion patterns matching
32
- your project layout (example below).
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 expressions. Ceedling places
66
- your own patterns first, ahead of the exclusions it generates automatically
67
- for test paths, the build root, and (when Partials are in use) Partial
68
- source files, so your patterns take precedence.
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:
@@ -246,7 +246,10 @@ class CExtractorPreprocessing
246
246
  # literal run -- it has to be seen and dispatched on its own below, before
247
247
  # any '"' or "'" inside the comment's own text gets mistaken for the start
248
248
  # of a string/char literal (see the // and /* branches for why that matters).
249
- text << (scanner.scan(/[^"'\\\n\/]*/) || '')
249
+ # '#' is excluded the same way, so a #/## operator is seen and dispatched on
250
+ # its own below rather than absorbed into this run along with whatever
251
+ # whitespace happens to surround it (see the ## and # branches for why).
252
+ text << (scanner.scan(/[^"'\\\n\/#]*/) || '')
250
253
 
251
254
  if scanner.scan(%r{//})
252
255
  # A trailing line comment (e.g. "// don't change this") can contain an
@@ -280,6 +283,31 @@ class CExtractorPreprocessing
280
283
  elsif scanner.scan(%r{/})
281
284
  text << '/'
282
285
 
286
+ elsif scanner.scan(/##/)
287
+ # The C standard specifies ##'s token-paste semantics but not the exact
288
+ # whitespace a preprocessor emits when reconstructing macro text -- real
289
+ # toolchains can and do disagree here, and Ceedling regenerates this text
290
+ # into partials rather than promising byte-for-byte reproduction of that
291
+ # spacing. Discard whatever immediately follows the operator in the source,
292
+ # so its right-hand operand always glues on directly. The left side only
293
+ # trims when a word character (the operand actually being pasted) is
294
+ # immediately adjacent -- a lookbehind, not a blind rstrip -- so unrelated
295
+ # punctuation spacing that happens to precede the operator (e.g. the space
296
+ # after a macro argument's comma, or after the parameter list's closing
297
+ # paren when the replacement list itself starts with the operator) is left
298
+ # alone; that space was never the preprocessor-reconstruction artifact this
299
+ # is defending against. ## checked before bare '#' below so a real paste
300
+ # operator is never split into two stringize matches.
301
+ text.sub!(/(?<=\w)[ \t]+\z/, '')
302
+ scanner.scan(/[ \t]*/)
303
+ text << '##'
304
+
305
+ elsif scanner.scan(/#/)
306
+ # Same rationale as ## above, for the stringize operator.
307
+ text.sub!(/(?<=\w)[ \t]+\z/, '')
308
+ scanner.scan(/[ \t]*/)
309
+ text << '#'
310
+
283
311
  elsif (ch = scanner.peek(1)) == '"' || ch == "'"
284
312
  before = scanner.pos
285
313
  @c_extractor_code_text.skip_c_string(scanner, ch)
@@ -124,6 +124,10 @@ class FilePathUtils
124
124
  pairs = paths.map { |p| [p, p.gsub('\\', '/').chomp('/')] }
125
125
 
126
126
  # Sort shallowest-first so ancestors are always encountered before their descendants.
127
+ # No tiebreaker for same-depth entries needed: Ruby's sort_by doesn't guarantee a
128
+ # stable order among ties, but two same-depth paths can never be each other's
129
+ # ancestor, so the ancestor-exclusion check below is correct regardless of which
130
+ # order same-depth ties come out in.
127
131
  pairs.sort_by! { |_, normalized| normalized.count('/') }
128
132
 
129
133
  kept = []
@@ -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 )