ceedling 1.1.0 → 1.1.2

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 (172) hide show
  1. checksums.yaml +4 -4
  2. data/GIT_COMMIT_SHA +1 -1
  3. data/README.md +10 -7
  4. data/assets/broken_uncovered_file.c +13 -0
  5. data/assets/test_example_file_2.c +22 -0
  6. data/assets/tests_with_partials_coverage/src/blanks.c +10 -0
  7. data/assets/tests_with_partials_coverage/src/blanks.h +1 -0
  8. data/assets/tests_with_partials_coverage/src/counter.c +12 -0
  9. data/assets/tests_with_partials_coverage/src/counter.h +1 -0
  10. data/assets/tests_with_partials_coverage/src/decorators.c +11 -0
  11. data/assets/tests_with_partials_coverage/src/decorators.h +4 -0
  12. data/assets/tests_with_partials_coverage/test/test_blanks.c +8 -0
  13. data/assets/tests_with_partials_coverage/test/test_counter.c +9 -0
  14. data/assets/tests_with_partials_coverage/test/test_decorators.c +8 -0
  15. data/docs/Changelog.md +80 -38
  16. data/docs/KnownIssues.md +9 -0
  17. data/docs/ReleaseNotes.md +5 -1
  18. data/docs/mkdocs/getting-started/installation.md +8 -1
  19. data/docs/mkdocs/getting-started/quick-start.md +20 -2
  20. data/docs/mkdocs/help.md +2 -2
  21. data/docs/mkdocs/index.md +13 -6
  22. data/docs/mkdocs/overview/build-system.md +4 -4
  23. data/docs/mkdocs/plugins/bullseye.md +6 -0
  24. data/docs/mkdocs/plugins/command-hooks.md +20 -15
  25. data/docs/mkdocs/plugins/gcov/gcovr.md +130 -109
  26. data/docs/mkdocs/plugins/gcov/index.md +6 -0
  27. data/docs/mkdocs/plugins/index.md +40 -0
  28. data/docs/mkdocs/plugins/valgrind.md +6 -0
  29. data/docs/mkdocs/testing-guide/partials/index.md +22 -13
  30. data/lib/ceedling/c_extractor/c_extractor_declarations.rb +3 -1
  31. data/lib/ceedling/c_extractor/c_extractor_preprocessing.rb +20 -7
  32. data/lib/ceedling/config/configurator.rb +2 -1
  33. data/lib/ceedling/generators/generator_partials.rb +13 -3
  34. data/lib/ceedling/objects.yml +1 -0
  35. data/lib/ceedling/preprocess/preprocessinator.rb +3 -2
  36. data/lib/ceedling/preprocess/preprocessinator_file_assembler.rb +37 -15
  37. data/lib/ceedling/preprocess/preprocessinator_reconstructor.rb +23 -15
  38. data/lib/ceedling/test_invoker/test_build_executor.rb +3 -4
  39. data/lib/ceedling/test_invoker/test_build_planner.rb +0 -2
  40. data/lib/ceedling/test_invoker/test_invoker_types.rb +1 -1
  41. data/lib/ceedling/tool_executor.rb +5 -0
  42. data/lib/version.rb +1 -1
  43. data/plugins/command_hooks/lib/command_hooks.rb +4 -0
  44. data/plugins/gcov/lib/console_reportinator.rb +3 -1
  45. data/plugins/gcov/lib/gcov.rb +3 -3
  46. data/plugins/gcov/lib/gcov_reportinator.rb +4 -0
  47. data/plugins/gcov/lib/gcovr_reportinator.rb +61 -14
  48. data/plugins/gcov/lib/reportgenerator_reportinator.rb +3 -1
  49. data/site-local/404.html +3 -3
  50. data/site-local/assets/javascripts/{bundle.79ae519e.min.js → bundle.d7400e89.min.js} +2 -2
  51. data/site-local/assets/javascripts/{bundle.79ae519e.min.js.map → bundle.d7400e89.min.js.map} +2 -2
  52. data/site-local/assets/stylesheets/main.ec1eaa64.min.css +1 -0
  53. data/site-local/assets/stylesheets/{main.484c7ddc.min.css.map → main.ec1eaa64.min.css.map} +1 -1
  54. data/site-local/configuration/environment-vars.html +3 -3
  55. data/site-local/configuration/global-collections.html +3 -3
  56. data/site-local/configuration/index.html +3 -3
  57. data/site-local/configuration/loading.html +3 -3
  58. data/site-local/configuration/mixins.html +3 -3
  59. data/site-local/configuration/parallel-builds.html +3 -3
  60. data/site-local/configuration/project-file.html +3 -3
  61. data/site-local/configuration/reference/cexception.html +3 -3
  62. data/site-local/configuration/reference/cmock.html +3 -3
  63. data/site-local/configuration/reference/defines.html +3 -3
  64. data/site-local/configuration/reference/environment.html +3 -3
  65. data/site-local/configuration/reference/extension.html +3 -3
  66. data/site-local/configuration/reference/files.html +3 -3
  67. data/site-local/configuration/reference/flags.html +3 -3
  68. data/site-local/configuration/reference/index.html +3 -3
  69. data/site-local/configuration/reference/libraries.html +3 -3
  70. data/site-local/configuration/reference/mixins.html +3 -3
  71. data/site-local/configuration/reference/paths.html +3 -3
  72. data/site-local/configuration/reference/plugins.html +3 -3
  73. data/site-local/configuration/reference/project.html +3 -3
  74. data/site-local/configuration/reference/release-build.html +3 -3
  75. data/site-local/configuration/reference/test-build.html +3 -3
  76. data/site-local/configuration/reference/test-runner.html +3 -3
  77. data/site-local/configuration/reference/tools.html +3 -3
  78. data/site-local/configuration/reference/unity.html +3 -3
  79. data/site-local/configuration/which-ceedling.html +3 -3
  80. data/site-local/development/index.html +3 -3
  81. data/site-local/development/plugins/configuration.html +3 -3
  82. data/site-local/development/plugins/index.html +3 -3
  83. data/site-local/development/plugins/plugin-subclass.html +3 -3
  84. data/site-local/development/plugins/rake-tasks.html +3 -3
  85. data/site-local/development/workflow.html +3 -3
  86. data/site-local/getting-started/command-line.html +3 -3
  87. data/site-local/getting-started/example-projects/cipher-quest.html +3 -3
  88. data/site-local/getting-started/example-projects/index.html +3 -3
  89. data/site-local/getting-started/example-projects/temp-sensor.html +3 -3
  90. data/site-local/getting-started/example-projects/wondrous-forest.html +3 -3
  91. data/site-local/getting-started/index.html +3 -3
  92. data/site-local/getting-started/installation.html +12 -4
  93. data/site-local/getting-started/quick-start.html +18 -4
  94. data/site-local/help.html +4 -4
  95. data/site-local/index.html +13 -8
  96. data/site-local/overview/build-system.html +6 -6
  97. data/site-local/overview/index.html +3 -3
  98. data/site-local/overview/test-environments.html +3 -3
  99. data/site-local/overview/tools-and-frameworks.html +3 -3
  100. data/site-local/plugins/beep.html +3 -3
  101. data/site-local/plugins/bullseye.html +9 -3
  102. data/site-local/plugins/command-hooks.html +42 -38
  103. data/site-local/plugins/compile-commands-json-db.html +3 -3
  104. data/site-local/plugins/cppcheck.html +3 -3
  105. data/site-local/plugins/dependencies.html +3 -3
  106. data/site-local/plugins/fff.html +3 -3
  107. data/site-local/plugins/gcov/examples.html +3 -3
  108. data/site-local/plugins/gcov/gcovr.html +325 -227
  109. data/site-local/plugins/gcov/index.html +9 -3
  110. data/site-local/plugins/gcov/overview.html +3 -3
  111. data/site-local/plugins/gcov/reportgenerator.html +3 -3
  112. data/site-local/plugins/gcov/reporting.html +3 -3
  113. data/site-local/plugins/gcov/setup.html +3 -3
  114. data/site-local/plugins/gcov/tool-versions.html +3 -3
  115. data/site-local/plugins/gcov/troubleshooting.html +3 -3
  116. data/site-local/plugins/index.html +79 -15
  117. data/site-local/plugins/module-generator.html +3 -3
  118. data/site-local/plugins/report-build-warnings-log.html +3 -3
  119. data/site-local/plugins/report-tests-gtestlike-stdout.html +3 -3
  120. data/site-local/plugins/report-tests-ide-stdout.html +3 -3
  121. data/site-local/plugins/report-tests-log-factory.html +3 -3
  122. data/site-local/plugins/report-tests-pretty-stdout.html +3 -3
  123. data/site-local/plugins/report-tests-raw-output-log.html +3 -3
  124. data/site-local/plugins/report-tests-teamcity-stdout.html +3 -3
  125. data/site-local/plugins/valgrind.html +9 -3
  126. data/site-local/project/release-history.html +3 -3
  127. data/site-local/project/upgrade.html +3 -3
  128. data/site-local/reference/build-directives.html +3 -3
  129. data/site-local/reference/command-line.html +3 -3
  130. data/site-local/reference/environment-vars.html +3 -3
  131. data/site-local/reference/gcov-plugin.html +3 -3
  132. data/site-local/reference/global-collections.html +3 -3
  133. data/site-local/reference/index.html +3 -3
  134. data/site-local/reference/partials-macros.html +3 -3
  135. data/site-local/reference/project-configuration.html +3 -3
  136. data/site-local/sitemap.xml.gz +0 -0
  137. data/site-local/snapshot/examples/cipher_quest/index.html +3 -3
  138. data/site-local/snapshot/examples/temp_sensor/index.html +3 -3
  139. data/site-local/snapshot/examples/wondrous_forest/index.html +3 -3
  140. data/site-local/testing-guide/build-directives.html +3 -3
  141. data/site-local/testing-guide/conventions.html +3 -3
  142. data/site-local/testing-guide/frameworks.html +3 -3
  143. data/site-local/testing-guide/index.html +3 -3
  144. data/site-local/testing-guide/partials/configuration.html +3 -3
  145. data/site-local/testing-guide/partials/conventions.html +3 -3
  146. data/site-local/testing-guide/partials/directives.html +3 -3
  147. data/site-local/testing-guide/partials/example.html +3 -3
  148. data/site-local/testing-guide/partials/index.html +25 -16
  149. data/site-local/testing-guide/partials/overview.html +3 -3
  150. data/site-local/testing-guide/partials/variables.html +3 -3
  151. data/site-local/testing-guide/test-cases.html +3 -3
  152. data/site-local/testing-guide/test-sample.html +3 -3
  153. data/site-local/testing-guide/test-suite-anatomy.html +3 -3
  154. data/spec/support/system/system_context.rb +3 -1
  155. data/spec/system/gcov_deployment_spec.rb +20 -6
  156. data/spec/system/support/gcov_common_test_cases.rb +34 -45
  157. data/spec/system/support/gcov_partials_test_cases.rb +116 -0
  158. data/spec/units/c_extractor/c_extractor_declarations_spec.rb +128 -0
  159. data/spec/units/c_extractor/c_extractor_definitions_spec.rb +7 -0
  160. data/spec/units/c_extractor/c_extractor_integration_spec.rb +17 -0
  161. data/spec/units/c_extractor/c_extractor_preprocessing_spec.rb +46 -0
  162. data/spec/units/generators/generator_partials_spec.rb +32 -6
  163. data/spec/units/preprocess/preprocessinator_file_assembler_spec.rb +250 -1
  164. data/spec/units/preprocess/preprocessinator_reconstructor_spec.rb +151 -1
  165. data/spec/units/test_build_executor_spec.rb +114 -0
  166. data/vendor/unity/auto/generate_test_runner.rb +55 -5
  167. data/vendor/unity/src/unity.h +1 -1
  168. data/vendor/unity/test/testdata/testRunnerGeneratorEmpty.c +13 -0
  169. data/vendor/unity/test/tests/test_generate_test_runner.rb +11 -0
  170. metadata +22 -7
  171. data/site-local/assets/stylesheets/main.484c7ddc.min.css +0 -1
  172. data/vendor/unity/auto/run_test.erb +0 -37
@@ -28,11 +28,15 @@ class GeneratorPartials
28
28
  header_filepath = File.join(output_path, header)
29
29
  source_filepath = File.join(output_path, source)
30
30
 
31
- @file_wrapper.open(header_filepath, 'w') do |file|
31
+ # Binary mode: the function bodies written below may already contain their
32
+ # own line endings verbatim. Windows text mode rewrites every "\n" on
33
+ # write, which would alter any line ending already present in that
34
+ # content instead of passing it through unchanged.
35
+ @file_wrapper.open(header_filepath, 'wb') do |file|
32
36
  generate_header(file, header, header_includes, function_definitions, c_module, true)
33
37
  end
34
38
 
35
- @file_wrapper.open(source_filepath, 'w') do |file|
39
+ @file_wrapper.open(source_filepath, 'wb') do |file|
36
40
  generate_source(file, source_includes, function_definitions, c_module)
37
41
  end
38
42
 
@@ -43,7 +47,8 @@ class GeneratorPartials
43
47
  header = @file_path_utils.form_partial_interface_header_filename(name)
44
48
  filepath = File.join(output_path, header)
45
49
 
46
- @file_wrapper.open(filepath, 'w') do |file|
50
+ # Binary mode: see generate_implementation above.
51
+ @file_wrapper.open(filepath, 'wb') do |file|
47
52
  generate_header(file, header, includes, function_declarations, c_module, false)
48
53
  end
49
54
 
@@ -149,6 +154,11 @@ class GeneratorPartials
149
154
  # Blank line before a function when preceded by a non-function item
150
155
  io << "\n" if anything_emitted && !last_was_func
151
156
  if func.line_num and func.source_filepath
157
+ # #line ties this generated file's code back to its original source
158
+ # location -- debuggers, error messages, and gcov coverage attribution
159
+ # all point at the real file/line instead of this generated stand-in.
160
+ # That mapping only holds if this file's line count matches what
161
+ # #line promises, which is why it's opened in binary mode above.
152
162
  io << "#line #{func.line_num} \"#{func.source_filepath}\"\n"
153
163
  end
154
164
  io << func.code_block << "\n\n"
@@ -288,6 +288,7 @@ preprocessinator_comment_stripper:
288
288
  preprocessinator_reconstructor:
289
289
  compose:
290
290
  - parsing_parcels
291
+ - file_wrapper
291
292
 
292
293
  preprocessinator:
293
294
  compose:
@@ -264,14 +264,15 @@ class Preprocessinator
264
264
  # `extras` are macro definitions, pragmas, etc. needed for the special case of mocking `inline` function declarations.
265
265
  # `extras` are empty for any cases other than mocking `inline` function declarations
266
266
  # (We don't want to increase our chances of a badly generated file--extracting extras could fail in complex files.)
267
- contents, extras = @file_assembler.collect_mockable_header_file_contents( **arg_hash )
267
+ contents, extras, include_guard = @file_assembler.collect_mockable_header_file_contents( **arg_hash )
268
268
 
269
269
  arg_hash = {
270
270
  filename: File.basename( filepath ),
271
271
  preprocessed_filepath: preprocessed_filepath,
272
272
  contents: contents,
273
273
  extras: extras,
274
- includes: includes
274
+ includes: includes,
275
+ include_guard: include_guard
275
276
  }
276
277
 
277
278
  # Create a reconstituted header file from preprocessing expansion and preserving any extras
@@ -60,15 +60,26 @@ class PreprocessinatorFileAssembler
60
60
  end
61
61
 
62
62
  # Bail out if no extras are required
63
- return contents, [] if !extras
64
-
65
- # Try to find an #include guard in the first 2k of the file text.
66
- # An #include guard is one macro from the original file we don't want to preserve if we can help it.
67
- # We create our own #include guard in the header file we create.
68
- # It's possible preserving the macro from the original file's #include guard could trip something up.
69
- # Of course, it's also possible some header conditional compilation feature is dependent on it.
70
- # ¯\_(ツ)_/¯
71
- include_guard = @preprocessinator_reconstructor.extract_include_guard( @file_wrapper.read( filepath, 2048 ).clean_encoding )
63
+ return contents, [], nil if !extras
64
+
65
+ # Try to find an #include guard in the first 2k of the file text. This name is used two ways:
66
+ # 1. To exclude the guard's own #define from the macro definitions preserved as "extras" below
67
+ # (it would be redundant -- assemble_preprocessed_header_file writes its own guard).
68
+ # 2. Returned to the caller so the reconstructed header can reuse this exact guard name (see
69
+ # assemble_preprocessed_header_file) instead of a synthetic one. Reusing the original name keeps
70
+ # the reconstructed file recognized as "the same header" by the preprocessor wherever both the
71
+ # original and a reconstructed/mocked copy are reachable in the same translation unit's include
72
+ # graph. A mismatched synthetic guard was the root cause of enum/type redeclaration errors in
73
+ # https://github.com/ThrowTheSwitch/Ceedling/issues/1064.
74
+ # If no guard is found (e.g. the header uses `#pragma once` or has none), `nil` flows through and
75
+ # assemble_preprocessed_header_file falls back to a synthetic guard, matching prior behavior.
76
+ include_guard =
77
+ @preprocessinator_reconstructor.extract_include_guard(
78
+ @file_wrapper.read(
79
+ filepath,
80
+ 2048
81
+ ).clean_encoding
82
+ )
72
83
 
73
84
  if fallback
74
85
  msg = @reportinator.generate_module_progress(
@@ -104,7 +115,7 @@ class PreprocessinatorFileAssembler
104
115
  end
105
116
  end
106
117
 
107
- return contents, (pragmas + macro_defs)
118
+ return contents, (pragmas + macro_defs), include_guard
108
119
  end
109
120
 
110
121
 
@@ -197,13 +208,20 @@ class PreprocessinatorFileAssembler
197
208
  end
198
209
 
199
210
 
200
- def assemble_preprocessed_header_file(filename:, preprocessed_filepath:, contents:, extras:, includes:)
201
- # Generate #include guard name for header files
202
- guardname = FileWrapper.generate_include_guard( filename )
211
+ def assemble_preprocessed_header_file(filename:, preprocessed_filepath:, contents:, extras:, includes:, include_guard: nil)
212
+ # Reuse the original header's own #include guard name when we found one so that this
213
+ # reconstructed file is recognized as "the same header" by the preprocessor wherever both
214
+ # are reachable (e.g. once via a mock's shadowed copy, once via the original source path).
215
+ # Fall back to a synthetic guard derived from the filename otherwise.
216
+ guardname = include_guard || FileWrapper.generate_include_guard( filename )
203
217
 
204
218
  # Write contents of final preprocessed file a line at a time
205
219
  # ----------------------------------------------------------
206
- @file_wrapper.open( preprocessed_filepath, 'w' ) do |file|
220
+ # Binary mode: `contents` lines below come from an upstream preprocessed
221
+ # file and may already carry their own line endings. Windows text mode
222
+ # rewrites "\n" on write, which would alter a line ending already present
223
+ # in that content instead of passing it through unchanged.
224
+ @file_wrapper.open( preprocessed_filepath, 'wb' ) do |file|
207
225
  # Add include guards and extra blank lines to beginning of file contents
208
226
  file << "#ifndef #{guardname}\n"
209
227
  file << "#define #{guardname}\n\n"
@@ -347,7 +365,11 @@ class PreprocessinatorFileAssembler
347
365
  def assemble_preprocessed_code_file(filename:, preprocessed_filepath:, contents:, extras:, includes:)
348
366
  # Write contents of final preprocessed file a line at a time
349
367
  # ----------------------------------------------------------
350
- @file_wrapper.open( preprocessed_filepath, 'w' ) do |file|
368
+ # Binary mode: `contents` lines below come from an upstream preprocessed
369
+ # file and may already carry their own line endings. Windows text mode
370
+ # rewrites "\n" on write, which would alter a line ending already present
371
+ # in that content instead of passing it through unchanged.
372
+ @file_wrapper.open( preprocessed_filepath, 'wb' ) do |file|
351
373
  # Reinsert #include statements into stripped down file
352
374
  # Rely on Include object stringification for formatting of incudes
353
375
  includes.each { |include| file << "#{include}\n" }
@@ -9,9 +9,9 @@ require 'ceedling/constants'
9
9
  require 'ceedling/encodinator'
10
10
  require 'ceedling/parsing_parcels'
11
11
 
12
- class PreprocessinatorReconstructor
13
-
14
- constructor :parsing_parcels
12
+ class PreprocessinatorReconstructor
13
+
14
+ constructor :parsing_parcels, :file_wrapper
15
15
 
16
16
  ##
17
17
  ## Preprocessor Expansion Output Handling
@@ -104,10 +104,13 @@ class PreprocessinatorReconstructor
104
104
  # Opens `input_filepath` for reading and `output_filepath` for writing,
105
105
  # then delegates to `compact_from_expansion` with the resulting IO objects.
106
106
  def compact_file_from_expansion(input_filepath:, source_filepath:, output_filepath:)
107
- # Open input in binary mode: GCC output under non-C locale contains non-ASCII bytes
108
- # (localized markers). Per-line clean_encoding in _scan_expansion_for_file handles content.
109
- File.open( input_filepath, 'rb' ) do |input|
110
- File.open( output_filepath, 'w' ) do |output|
107
+ # Binary mode on both ends: GCC output under non-C locale contains non-ASCII
108
+ # bytes (localized markers; per-line clean_encoding in _scan_expansion_for_file
109
+ # handles content), and the compacted output is read again downstream by code
110
+ # that depends on its line count being exact. Windows text mode would rewrite
111
+ # "\n" to "\r\n" on write, which this content must not be subject to.
112
+ @file_wrapper.open( input_filepath, 'rb' ) do |input|
113
+ @file_wrapper.open( output_filepath, 'wb' ) do |output|
111
114
  compact_from_expansion( input: input, filepath: source_filepath, output: output )
112
115
  end
113
116
  end
@@ -280,16 +283,21 @@ class PreprocessinatorReconstructor
280
283
 
281
284
  # Buffer for the last logical line (may still receive aggregated content)
282
285
  pending_line = nil
283
- # Whether a blank line should follow pending_line when flushed
284
- pending_blank = false
285
-
286
- # Yields pending_line (and optional trailing blank) then clears the buffer
286
+ # Count of blank lines to emit after pending_line when flushed. Tracked as
287
+ # an exact count, not just "was there a blank" -- callers that depend on
288
+ # this method for line-for-line fidelity with the original source (so
289
+ # that unrelated line-number math downstream stays correct) need every
290
+ # blank line preserved, including runs that used to be a multi-line
291
+ # comment before an earlier pass turned it into equivalent blank lines.
292
+ pending_blank_count = 0
293
+
294
+ # Yields pending_line (and any pending blank lines) then clears the buffer
287
295
  flush = lambda do
288
296
  unless pending_line.nil?
289
297
  block.call( pending_line )
290
- block.call( '' ) if pending_blank
298
+ pending_blank_count.times { block.call( '' ) }
291
299
  pending_line = nil
292
- pending_blank = false
300
+ pending_blank_count = 0
293
301
  end
294
302
  end
295
303
 
@@ -308,9 +316,9 @@ class PreprocessinatorReconstructor
308
316
  # Strip a line so we can omit useless blank lines
309
317
  _line = line.strip()
310
318
 
311
- # Skip processing blank lines, but mark a pending blank unless we already have one
319
+ # Skip processing blank lines, but track an exact count of them so runs of blanks survive intact
312
320
  if _line.empty?
313
- pending_blank = true if !pending_line.nil? && !pending_line.empty?
321
+ pending_blank_count += 1 if !pending_line.nil? && !pending_line.empty?
314
322
  next
315
323
  end
316
324
 
@@ -412,7 +412,6 @@ class TestBuildExecutor
412
412
  @batchinator.exec(workload: :compile, things: state.objects_list) do |obj|
413
413
  src = @file_finder.find_build_input_file( filepath: obj[:obj], context: state.context )
414
414
  compile_test_component(
415
- tool: obj[:tool],
416
415
  context: state.context,
417
416
  test: obj[:test],
418
417
  source: src,
@@ -546,7 +545,7 @@ class TestBuildExecutor
546
545
  private
547
546
 
548
547
  # Compile a single C or assembly source file into an object file.
549
- def compile_test_component(tool:, context:, test:, source:, object:, state:)
548
+ def compile_test_component(context:, test:, source:, object:, state:)
550
549
  testable = state.testables[test.to_sym]
551
550
  defines = testable.compile_defines
552
551
  search_paths = tailor_search_paths( search_paths: testable.search_paths, filepath: source )
@@ -555,7 +554,7 @@ class TestBuildExecutor
555
554
  flags = testable.compile_flags
556
555
 
557
556
  arg_hash = {
558
- tool: tool,
557
+ tool: @configurator.tools_test_compiler,
559
558
  module_name: test,
560
559
  context: context,
561
560
  source: source,
@@ -573,7 +572,7 @@ class TestBuildExecutor
573
572
  flags = testable.assembler_flags
574
573
 
575
574
  arg_hash = {
576
- tool: tool,
575
+ tool: @configurator.tools_test_assembler,
577
576
  module_name: test,
578
577
  context: context,
579
578
  source: source,
@@ -162,7 +162,6 @@ class TestBuildPlanner
162
162
  testable.no_link_objects = test_no_link_objects
163
163
  testable.results_pass = test_pass
164
164
  testable.results_fail = test_fail
165
- testable.tool = TOOLS_TEST_COMPILER
166
165
  end
167
166
  end
168
167
  end
@@ -172,7 +171,6 @@ class TestBuildPlanner
172
171
  state.objects_list = state.testables.map do |_, testable|
173
172
  testable.objects.map do |obj|
174
173
  {
175
- tool: testable.tool,
176
174
  test: testable.name,
177
175
  obj: obj
178
176
  }
@@ -37,7 +37,7 @@ module TestInvokerTypes
37
37
  :mocks, # Hash — mock name → mock info
38
38
  :partials, # TestablePartials — configs map + tests/mocks module name lists
39
39
  :sources, :frameworks, :core, :objects, :executable,
40
- :no_link_objects, :results_pass, :results_fail, :tool,
40
+ :no_link_objects, :results_pass, :results_fail,
41
41
  keyword_init: true
42
42
  ) do
43
43
  def initialize(**kwargs)
@@ -11,6 +11,11 @@ require 'benchmark'
11
11
 
12
12
  class ToolExecutor
13
13
 
14
+ # Populate a tool config hash's :name key from `default` if the user did not set one explicitly.
15
+ def self.default_name!(tool, default)
16
+ tool[:name] = default if tool[:name].nil?
17
+ end
18
+
14
19
  constructor :configurator, :tool_executor_helper, :loginator, :verbosinator, :system_wrapper, :ruby_expandinator
15
20
 
16
21
  # build up a command line from yaml provided config
data/lib/version.rb CHANGED
@@ -15,7 +15,7 @@
15
15
  module Ceedling
16
16
  module Version
17
17
  # Convenience constants for gem building, etc.
18
- GEM = '1.1.0'
18
+ GEM = '1.1.2'
19
19
  TAG = GEM
20
20
 
21
21
  # If run as a script print Ceedling's version to $stdout
@@ -8,6 +8,7 @@
8
8
  require 'ceedling/constants'
9
9
  require 'ceedling/exceptions'
10
10
  require 'ceedling/plugins/plugin'
11
+ require 'ceedling/tool_executor'
11
12
 
12
13
  COMMAND_HOOKS_ROOT_NAME = 'command_hooks'.freeze
13
14
  COMMAND_HOOKS_SYM = COMMAND_HOOKS_ROOT_NAME.to_sym
@@ -157,6 +158,9 @@ class CommandHooks < Plugin
157
158
  raise CeedlingException.new( error )
158
159
  end
159
160
 
161
+ # Populate name if not given
162
+ ToolExecutor.default_name!( entry, keys.join('_') )
163
+
160
164
  # Validate the Ceedling tool components of the hook entry config
161
165
  @tool_validator.validate( tool: entry, name: name, boom: true )
162
166
 
@@ -16,7 +16,9 @@ class ConsoleReportinator < GcovReportinator
16
16
 
17
17
  attr_reader :artifacts_path # nil — console output only, no filesystem artifacts
18
18
 
19
- def initialize(system_objects)
19
+ def initialize(system_objects, config)
20
+ super(config)
21
+
20
22
  @loginator = system_objects[:loginator]
21
23
  @plugin_reportinator = system_objects[:plugin_reportinator]
22
24
  @test_invoker = system_objects[:test_invoker]
@@ -317,7 +317,7 @@ class Gcov < Plugin
317
317
 
318
318
  # Instantiate console summary reportinator if summaries enabled
319
319
  @console_reportinator = summaries_enabled?(@project_config) ?
320
- ConsoleReportinator.new(@ceedling) : nil
320
+ ConsoleReportinator.new(@ceedling, @project_config) : nil
321
321
 
322
322
  # Do not instantiate file reportinators (and tool validation) unless reports enabled
323
323
  return reportinators if (!enabled)
@@ -332,13 +332,13 @@ class Gcov < Plugin
332
332
 
333
333
  # Run reports using gcovr
334
334
  if utility_enabled?( config, GCOV_UTILITY_NAME_GCOVR )
335
- reportinator = GcovrReportinator.new( @ceedling )
335
+ reportinator = GcovrReportinator.new( @ceedling, @project_config )
336
336
  reportinators << reportinator
337
337
  end
338
338
 
339
339
  # Run reports using ReportGenerator
340
340
  if utility_enabled?( config, GCOV_UTILITY_NAME_REPORT_GENERATOR )
341
- reportinator = ReportGeneratorReportinator.new( @ceedling )
341
+ reportinator = ReportGeneratorReportinator.new( @ceedling, @project_config )
342
342
  reportinators << reportinator
343
343
  end
344
344
 
@@ -20,6 +20,10 @@
20
20
  #
21
21
  class GcovReportinator
22
22
 
23
+ def initialize(config)
24
+ @config = config
25
+ end
26
+
23
27
  def name
24
28
  raise NotImplementedError.new("#{self.class} must implement name()")
25
29
  end
@@ -20,7 +20,9 @@ class GcovrReportinator < GcovReportinator
20
20
 
21
21
  GCOVR_SETTING_PREFIX = "gcov_gcovr"
22
22
 
23
- def initialize(system_objects)
23
+ def initialize(system_objects, config)
24
+ super(config)
25
+
24
26
  @artifacts_path = GCOV_GCOVR_ARTIFACTS_PATH
25
27
  @summary = ''
26
28
  @ceedling = system_objects
@@ -37,6 +39,8 @@ class GcovrReportinator < GcovReportinator
37
39
  @tool_executor = @ceedling[:tool_executor]
38
40
  @configurator = @ceedling[:configurator]
39
41
 
42
+ check_config_options()
43
+
40
44
  @gcovr_version = get_gcovr_version()
41
45
 
42
46
  # MC/DC reporting requires gcovr 8+
@@ -78,13 +82,13 @@ class GcovrReportinator < GcovReportinator
78
82
  # and are not included in the string returned by this method.
79
83
  def args_builder_common(gcovr_opts, gcovr_version)
80
84
  args = ""
81
- args += "--config \"#{gcovr_opts[:config_file]}\" " unless gcovr_opts[:config_file].nil?
85
+ args += "--config \"#{gcovr_opts[:config_file]}\" " if config_file_in_use?(gcovr_opts)
82
86
 
83
87
  # When a config file is provided, defer all other options to it.
84
88
  # This prevents Ceedling from overriding config file values with its CLI arguments.
85
89
  # --root (${1}) is always passed; --exclude (${2}) is nil when a config file is present,
86
90
  # so the tool executor omits those flags and the config file governs exclusions.
87
- return args if gcovr_opts[:config_file]
91
+ return args if config_file_in_use?(gcovr_opts)
88
92
 
89
93
  args += "--filter \"#{gcovr_opts[:report_include]}\" " unless gcovr_opts[:report_include].nil?
90
94
  args += "--gcov-filter \"#{gcovr_opts[:gcov_filter]}\" " unless gcovr_opts[:gcov_filter].nil?
@@ -149,7 +153,7 @@ class GcovrReportinator < GcovReportinator
149
153
  artifacts_file_cobertura = File.join(GCOV_GCOVR_ARTIFACTS_PATH, gcovr_opts[:cobertura_artifact_filename])
150
154
  end
151
155
 
152
- args += "--xml-pretty " if gcovr_opts[:cobertura_pretty]
156
+ args += "--xml-pretty " if gcovr_opts[:cobertura_pretty] && !config_file_in_use?(gcovr_opts)
153
157
  args += "--xml #{use_output_option ? "--output " : ""} \"#{artifacts_file_cobertura}\" "
154
158
  end
155
159
 
@@ -190,7 +194,7 @@ class GcovrReportinator < GcovReportinator
190
194
  artifacts_file_json = File.join(GCOV_GCOVR_ARTIFACTS_PATH, gcovr_opts[:json_artifact_filename])
191
195
  end
192
196
 
193
- args += "--json-pretty " if gcovr_opts[:json_pretty]
197
+ args += "--json-pretty " if gcovr_opts[:json_pretty] && !config_file_in_use?(gcovr_opts)
194
198
  # Note: In gcovr 4.2, the JSON report is output only when the --output option is specified.
195
199
  # Hopefully we can remove --output after a future gcovr release.
196
200
  args += "--json #{use_output_option ? "--output " : ""} \"#{artifacts_file_json}\" "
@@ -219,12 +223,17 @@ class GcovrReportinator < GcovReportinator
219
223
  is_html_report_type_detailed = (opts[:gcov_html_report_type].is_a? String) && (opts[:gcov_html_report_type].casecmp("detailed") == 0)
220
224
 
221
225
  args += "--html-details " if is_html_report_type_detailed || report_enabled?(opts, ReportTypes::HTML_DETAILED)
222
- args += "--html-title \"#{gcovr_opts[:html_title]}\" " unless gcovr_opts[:html_title].nil?
223
- args += "--html-absolute-paths " if !(gcovr_opts[:html_absolute_paths].nil?) && gcovr_opts[:html_absolute_paths]
224
- args += "--html-encoding \"#{gcovr_opts[:html_encoding]}\" " unless gcovr_opts[:html_encoding].nil?
225
226
 
226
- [:html_medium_threshold, :html_high_threshold].each do |opt|
227
- args += "--#{opt.to_s.gsub('_','-')} #{gcovr_opts[opt]} " unless gcovr_opts[opt].nil?
227
+ # These options duplicate settings a gcovr configuration file would provide, so they're
228
+ # withheld when :config_file is set to avoid silently overriding the file's values.
229
+ if !config_file_in_use?(gcovr_opts)
230
+ args += "--html-title \"#{gcovr_opts[:html_title]}\" " unless gcovr_opts[:html_title].nil?
231
+ args += "--html-absolute-paths " if !(gcovr_opts[:html_absolute_paths].nil?) && gcovr_opts[:html_absolute_paths]
232
+ args += "--html-encoding \"#{gcovr_opts[:html_encoding]}\" " unless gcovr_opts[:html_encoding].nil?
233
+
234
+ [:html_medium_threshold, :html_high_threshold].each do |opt|
235
+ args += "--#{opt.to_s.gsub('_','-')} #{gcovr_opts[opt]} " unless gcovr_opts[opt].nil?
236
+ end
228
237
  end
229
238
 
230
239
  # The following option must be appended last for gcovr version <= 4.2 to properly work.
@@ -313,6 +322,42 @@ class GcovrReportinator < GcovReportinator
313
322
  end
314
323
 
315
324
 
325
+ # gcovr options silently ignored whenever :config_file is set (dropped by args_builder_common's
326
+ # early return, or gated in args_builder_cobertura/json/html) -- in that case all such
327
+ # configuration must come from the gcovr configuration file itself.
328
+ IGNORED_WHEN_CONFIG_FILE_SET = [
329
+ :report_include, :report_exclude, :gcov_filter, :gcov_exclude, :exclude_directories,
330
+ :branches, :sort_uncovered, :sort_percentage, :print_summary, :gcov_executable,
331
+ :exclude_unreachable_branches, :exclude_throw_branches, :use_gcov_files, :gcov_ignore_parse_errors,
332
+ :keep, :delete, :threads, :merge_mode_function,
333
+ :fail_under_line, :fail_under_branch, :fail_under_decision, :fail_under_function,
334
+ :source_encoding, :object_directory,
335
+ :cobertura_pretty, :json_pretty,
336
+ :html_title, :html_absolute_paths, :html_encoding, :html_medium_threshold, :html_high_threshold
337
+ ].freeze
338
+
339
+ # True when a gcovr configuration file is in use, meaning Ceedling must defer to it and
340
+ # withhold any option that would silently override its settings.
341
+ def config_file_in_use?(gcovr_opts)
342
+ !gcovr_opts[:config_file].nil?
343
+ end
344
+
345
+
346
+ # Validate the gcovr plugin configuration for known-bad combinations.
347
+ def check_config_options
348
+ gcovr_opts = @config[GCOVR_SETTING_PREFIX.to_sym] || {}
349
+ return unless config_file_in_use?(gcovr_opts)
350
+
351
+ ignored = IGNORED_WHEN_CONFIG_FILE_SET.select { |key| !gcovr_opts[key].nil? }
352
+ return if ignored.empty?
353
+
354
+ list = ignored.map { |key| ":#{key}" }.join(', ')
355
+ msg = ":gcov ↳ :gcovr ↳ :config_file is set, so the following options are ignored: #{list}. " \
356
+ "Provide equivalent settings directly in your gcovr configuration file instead."
357
+ @loginator.log( msg, Verbosity::COMPLAIN )
358
+ end
359
+
360
+
316
361
  # Get the gcovr options from the project options.
317
362
  def collect_gcovr_opts(opts)
318
363
  # dup prevents repeated calls from accumulating mutations on the shared opts hash.
@@ -320,10 +365,12 @@ class GcovrReportinator < GcovReportinator
320
365
  # would see the already-mutated :report_exclude from the previous call and nest it.
321
366
  _opts = opts[GCOVR_SETTING_PREFIX.to_sym].dup
322
367
 
323
- # Only auto-generate --exclude patterns when no config file is specified.
324
- # A gcovr config file is authoritative; CLI args override it, so injecting
325
- # auto-excludes would silently defeat the config file.
326
- unless _opts[:config_file]
368
+ if config_file_in_use?(_opts)
369
+ # A gcovr config file is authoritative; CLI args override it, so injecting
370
+ # auto-excludes would silently defeat the config file. Force an empty array
371
+ # (not nil) so the tool executor omits the --exclude flag entirely.
372
+ _opts[:report_exclude] = []
373
+ else
327
374
  # Build array of --exclude patterns: user-provided value (if any) + internally-generated per-file patterns.
328
375
  # Splat via *Array() handles both a user-supplied string and a user-supplied array
329
376
  # without introducing a nested element into the exclusions list.
@@ -19,7 +19,9 @@ class ReportGeneratorReportinator < GcovReportinator
19
19
 
20
20
  attr_reader :artifacts_path
21
21
 
22
- def initialize(system_objects)
22
+ def initialize(system_objects, config)
23
+ super(config)
24
+
23
25
  @artifacts_path = GCOV_REPORT_GENERATOR_ARTIFACTS_PATH
24
26
  @summary = ''
25
27
  @ceedling = system_objects
data/site-local/404.html CHANGED
@@ -17,7 +17,7 @@
17
17
 
18
18
 
19
19
  <link rel="icon" href="/assets/images/favicon.png">
20
- <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.7.6">
20
+ <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.7.7">
21
21
 
22
22
 
23
23
 
@@ -25,7 +25,7 @@
25
25
 
26
26
 
27
27
 
28
- <link rel="stylesheet" href="/assets/stylesheets/main.484c7ddc.min.css">
28
+ <link rel="stylesheet" href="/assets/stylesheets/main.ec1eaa64.min.css">
29
29
 
30
30
 
31
31
  <link rel="stylesheet" href="/assets/stylesheets/palette.ab4e12ef.min.css">
@@ -3995,7 +3995,7 @@
3995
3995
  <script id="__config" type="application/json">{"annotate": null, "base": "/", "features": ["navigation.tabs", "navigation.sections", "navigation.top", "navigation.indexes", "navigation.path", "search.suggest", "search.highlight", "content.code.copy", "content.code.annotate"], "search": "/assets/javascripts/workers/search.2c215733.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": {"default": "latest", "provider": "mike"}}</script>
3996
3996
 
3997
3997
 
3998
- <script src="/assets/javascripts/bundle.79ae519e.min.js"></script>
3998
+ <script src="/assets/javascripts/bundle.d7400e89.min.js"></script>
3999
3999
 
4000
4000
 
4001
4001
  </body>