ceedling 1.1.9 → 1.2.0

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 (1130) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +3 -0
  3. data/.simplecov +73 -0
  4. data/GIT_COMMIT_SHA +1 -1
  5. data/Gemfile +84 -8
  6. data/Gemfile.lock +38 -8
  7. data/README.md +53 -30
  8. data/Rakefile +768 -16
  9. data/assets/{project.yml → features/project.yml} +4 -1
  10. data/assets/fixtures/bullseye_branch_coverage/src/branchy.c +24 -0
  11. data/assets/fixtures/bullseye_branch_coverage/src/branchy.h +14 -0
  12. data/assets/fixtures/bullseye_branch_coverage/test/test_branchy.c +18 -0
  13. data/assets/fixtures/cppcheck_findings/findings.c +23 -0
  14. data/assets/fixtures/cppcheck_findings/findings.h +13 -0
  15. data/assets/fixtures/header_include_path_validation/alt_drivers/foo.h +6 -0
  16. data/assets/fixtures/header_include_path_validation/bar.h +6 -0
  17. data/assets/fixtures/header_include_path_validation/drivers/foo.h +6 -0
  18. data/assets/fixtures/header_include_path_validation/dup.h +6 -0
  19. data/assets/fixtures/header_include_path_validation/other_inc/dup.h +6 -0
  20. data/assets/fixtures/header_include_path_validation/test_ambiguous_mock.c +15 -0
  21. data/assets/fixtures/header_include_path_validation/test_bare_mock.c +11 -0
  22. data/assets/fixtures/header_include_path_validation/test_bogus_mock_path.c +11 -0
  23. data/assets/fixtures/header_include_path_validation/test_bogus_vanilla_path.c +10 -0
  24. data/assets/fixtures/header_include_path_validation/test_include_outranks_test_include_path.c +16 -0
  25. data/assets/fixtures/header_include_path_validation/test_pathed_mock.c +11 -0
  26. data/assets/fixtures/header_include_path_validation/test_pathed_mock_ambiguous.c +14 -0
  27. data/assets/fixtures/header_include_path_validation/test_test_include_path_outranks_include.c +17 -0
  28. data/assets/fixtures/implicit_source_header_correspondence/alpha/dup.c +6 -0
  29. data/assets/fixtures/implicit_source_header_correspondence/alpha/dup.h +6 -0
  30. data/assets/fixtures/implicit_source_header_correspondence/beta/dup.c +6 -0
  31. data/assets/fixtures/implicit_source_header_correspondence/beta/dup.h +6 -0
  32. data/assets/fixtures/implicit_source_header_correspondence/gamma/dup_gamma.c +6 -0
  33. data/assets/fixtures/implicit_source_header_correspondence/test_dup_alpha.c +10 -0
  34. data/assets/fixtures/implicit_source_header_correspondence/test_dup_bare.c +10 -0
  35. data/assets/fixtures/implicit_source_header_correspondence/test_dup_beta.c +10 -0
  36. data/assets/fixtures/implicit_source_header_correspondence/test_dup_override.c +19 -0
  37. data/assets/fixtures/implicit_source_header_correspondence/test_dup_subtractive.c +19 -0
  38. data/assets/fixtures/implicit_source_header_correspondence/test_dup_subtractive_noop.c +16 -0
  39. data/assets/fixtures/parent_directory_references/alpha/extra.c +4 -0
  40. data/assets/fixtures/parent_directory_references/common/helper.c +6 -0
  41. data/assets/fixtures/parent_directory_references/common/helper.h +6 -0
  42. data/assets/fixtures/parent_directory_references/unit/test_dotdot_include.c +10 -0
  43. data/assets/fixtures/parent_directory_references/unit/test_dotdot_source.c +16 -0
  44. data/assets/fixtures/plain_inline_module.h +9 -0
  45. data/assets/fixtures/same_named_modules/include/drivers/spi/config.h +6 -0
  46. data/assets/fixtures/same_named_modules/include/drivers/uart/config.h +6 -0
  47. data/assets/fixtures/same_named_modules/src/drivers/spi/config.c +8 -0
  48. data/assets/fixtures/same_named_modules/src/drivers/uart/config.c +10 -0
  49. data/assets/fixtures/same_named_modules/test/test_both_configs.c +26 -0
  50. data/assets/fixtures/same_named_modules/test/test_both_configs_mocked.c +20 -0
  51. data/assets/fixtures/same_named_modules/test/test_both_configs_mocked_traditional.c +19 -0
  52. data/assets/fixtures/same_named_modules/test/test_both_modules.c +19 -0
  53. data/assets/fixtures/same_named_modules/test/test_uart_config_bare.c +19 -0
  54. data/assets/fixtures/same_named_modules/test/test_uart_config_partial_only.c +20 -0
  55. data/assets/fixtures/sources_with_duplicate_basenames/baz/bar.c +6 -0
  56. data/assets/fixtures/sources_with_duplicate_basenames/baz/bar.h +6 -0
  57. data/assets/fixtures/sources_with_duplicate_basenames/foo/bar.c +6 -0
  58. data/assets/fixtures/sources_with_duplicate_basenames/foo/bar.h +6 -0
  59. data/assets/fixtures/sources_with_duplicate_basenames/main.c +11 -0
  60. data/assets/fixtures/sources_with_duplicate_basenames/test_baz_bar.c +10 -0
  61. data/assets/fixtures/sources_with_duplicate_basenames/test_both_bars.c +12 -0
  62. data/assets/fixtures/sources_with_duplicate_basenames/test_foo_bar.c +10 -0
  63. data/assets/{test_example_file_boom.c → fixtures/test_nosanitize_boom.c} +9 -0
  64. data/assets/{test_example_file_crash_assert.c → fixtures/test_nosanitize_crash_assert.c} +8 -0
  65. data/assets/{test_example_file_crash_sigsegv.c → fixtures/test_nosanitize_crash_sigsegv.c} +8 -0
  66. data/assets/{test_example_file_crash_sigsegv_with_param.c → fixtures/test_nosanitize_crash_sigsegv_with_param.c} +8 -0
  67. data/assets/fixtures/test_nosanitize_heap_buffer_overflow.c +31 -0
  68. data/assets/fixtures/test_nosanitize_leak.c +34 -0
  69. data/assets/fixtures/test_nosanitize_two_findings.c +36 -0
  70. data/assets/{test_example_file_ub_shift_overflow.c → fixtures/test_nosanitize_ub_shift_overflow.c} +9 -0
  71. data/assets/fixtures/test_plain_inline_module.c +15 -0
  72. data/assets/fixtures/test_source_file_duplicate_basenames/alpha/calc.c +4 -0
  73. data/assets/fixtures/test_source_file_duplicate_basenames/beta/calc.c +4 -0
  74. data/assets/fixtures/test_source_file_duplicate_basenames/test_calc_alpha.c +15 -0
  75. data/assets/fixtures/test_source_file_duplicate_basenames/test_calc_ambiguous.c +15 -0
  76. data/assets/fixtures/test_source_file_duplicate_basenames/test_calc_beta.c +15 -0
  77. data/assets/fixtures/tests_with_conditional_includes/src/feature_extra2.h +13 -0
  78. data/assets/fixtures/tests_with_conditional_includes/src/macro_target_extra.h +13 -0
  79. data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/widget.c +19 -3
  80. data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/widget.h +1 -0
  81. data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/widget_feature.c +17 -1
  82. data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/test/test_widget.c +12 -4
  83. data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/test/test_widget_feature.c +8 -5
  84. data/assets/fixtures/tests_with_conditional_mocks/src/Case_01.c +7 -0
  85. data/assets/fixtures/tests_with_conditional_mocks/src/Case_01.h +6 -0
  86. data/assets/fixtures/tests_with_conditional_mocks/src/Case_02.c +16 -0
  87. data/assets/fixtures/tests_with_conditional_mocks/src/Case_02.h +6 -0
  88. data/assets/fixtures/tests_with_conditional_mocks/src/FeatureConfig.h +6 -0
  89. data/assets/fixtures/tests_with_conditional_mocks/src/Gpt.h +6 -0
  90. data/assets/fixtures/tests_with_conditional_mocks/src/MyModuleConfig.h +17 -0
  91. data/assets/fixtures/tests_with_conditional_mocks/src/MyModulePart1.h +6 -0
  92. data/assets/fixtures/tests_with_conditional_mocks/src/MyModulePart2.h +6 -0
  93. data/assets/fixtures/tests_with_conditional_mocks/src/drivers/widget.h +6 -0
  94. data/assets/fixtures/tests_with_conditional_mocks/src/reader.c +7 -0
  95. data/assets/fixtures/tests_with_conditional_mocks/src/reader.h +6 -0
  96. data/assets/fixtures/tests_with_conditional_mocks/test/test_Case_01.c +21 -0
  97. data/assets/fixtures/tests_with_conditional_mocks/test/test_Case_01_legacy.c +16 -0
  98. data/assets/fixtures/tests_with_conditional_mocks/test/test_Case_02.c +31 -0
  99. data/assets/fixtures/tests_with_conditional_mocks/test/test_FeatureConfig.c +15 -0
  100. data/assets/fixtures/tests_with_conditional_mocks/test/test_reader.c +13 -0
  101. data/assets/fixtures/tests_with_duplicate_test_names/integration/test_foo.c +21 -0
  102. data/assets/fixtures/tests_with_duplicate_test_names/unit/test_foo.c +21 -0
  103. data/assets/fixtures/tests_with_fallback_conditionals/src/conditional_module.c +28 -0
  104. data/assets/{tests_with_fallback_conditionals → fixtures/tests_with_fallback_conditionals}/test/test_conditionals.c +8 -1
  105. data/assets/fixtures/tests_with_multiple_assembly_extensions/src/asm_helper_lower.s +2 -0
  106. data/assets/fixtures/tests_with_multiple_assembly_extensions/src/asm_helper_upper.S +13 -0
  107. data/assets/fixtures/tests_with_multiple_assembly_extensions/src/counter_module.c +13 -0
  108. data/assets/fixtures/tests_with_multiple_assembly_extensions/src/counter_module.h +13 -0
  109. data/assets/fixtures/tests_with_multiple_assembly_extensions/test/test_counter_module.c +27 -0
  110. data/assets/fixtures/tests_with_subdir_includes/src/module/app/config.h +13 -0
  111. data/assets/fixtures/tests_with_subdir_includes/src/module/drivers/config.h +13 -0
  112. data/assets/fixtures/tests_with_subdir_includes/src/module/sensor.c +30 -0
  113. data/assets/fixtures/tests_with_subdir_includes/src/module/sensor.h +13 -0
  114. data/assets/fixtures/tests_with_subdir_includes/src/shared/config.h +13 -0
  115. data/assets/fixtures/tests_with_subdir_includes/test/test_sensor.c +32 -0
  116. data/bin/actionator.rb +234 -0
  117. data/bin/app_cfg.rb +7 -0
  118. data/bin/cli.rb +78 -47
  119. data/bin/cli_handler.rb +89 -57
  120. data/bin/cli_helper.rb +90 -49
  121. data/bin/cli_options_transform.rb +22 -0
  122. data/bin/{configinator.rb → composinator.rb} +39 -32
  123. data/bin/mixin_resolvinator.rb +124 -0
  124. data/bin/mixin_standardizer.rb +31 -61
  125. data/bin/mixinator.rb +27 -29
  126. data/bin/mixins.rb +0 -5
  127. data/bin/objects.yml +20 -7
  128. data/bin/path_validator.rb +6 -5
  129. data/bin/projectinator.rb +51 -142
  130. data/bin/rake_patches.rb +36 -2
  131. data/bin/recursive_merger.rb +7 -1
  132. data/bin/versionator.rb +2 -3
  133. data/ceedling.gemspec +83 -12
  134. data/docs/BreakingChanges.md +46 -2
  135. data/docs/CONTRIBUTING.md +45 -29
  136. data/docs/CeedlingPullRequestChecklist.md +10 -9
  137. data/docs/Changelog.md +337 -37
  138. data/docs/KnownIssues.md +39 -4
  139. data/docs/ReleaseNotes.md +288 -12
  140. data/docs/SECURITY.md +86 -4
  141. data/docs/ThrowTheSwitchCodingStandard.md +21 -3
  142. data/docs/overrides/main.html +32 -0
  143. data/examples/temp_sensor/mixin/add_bullseye.yml +19 -0
  144. data/examples/wondrous_forest/README.md +3 -0
  145. data/examples/wondrous_forest/src/sensors/light/Calibration.c +21 -0
  146. data/examples/wondrous_forest/src/sensors/light/Calibration.h +14 -0
  147. data/examples/wondrous_forest/src/sensors/soil/Calibration.c +23 -0
  148. data/examples/wondrous_forest/src/sensors/soil/Calibration.h +14 -0
  149. data/examples/wondrous_forest/test/TestCalibration.c +39 -0
  150. data/lib/ceedling/batchinator.rb +81 -22
  151. data/lib/ceedling/c_extractor/README.md +61 -0
  152. data/lib/ceedling/c_extractor/c_extractor.rb +33 -2
  153. data/lib/ceedling/c_extractor/c_extractor_code_text.rb +18 -10
  154. data/lib/ceedling/c_extractor/c_extractor_constants.rb +10 -10
  155. data/lib/ceedling/c_extractor/c_extractor_declarations.rb +14 -14
  156. data/lib/ceedling/c_extractor/c_extractor_functions.rb +10 -13
  157. data/lib/ceedling/c_extractor/c_extractor_preprocessing.rb +77 -0
  158. data/lib/ceedling/c_extractor/c_extractor_types.rb +8 -5
  159. data/lib/ceedling/ceedling.h +33 -0
  160. data/lib/ceedling/config/config_matchinator.rb +36 -13
  161. data/lib/ceedling/config/configurator.rb +366 -530
  162. data/lib/ceedling/config/configurator_builder.rb +253 -365
  163. data/lib/ceedling/config/configurator_plugins.rb +68 -102
  164. data/lib/ceedling/config/configurator_setup.rb +343 -610
  165. data/lib/ceedling/config/configurator_validator.rb +114 -142
  166. data/lib/ceedling/config/line_marker_suppressors.rb +67 -0
  167. data/lib/ceedling/constants.rb +60 -6
  168. data/lib/ceedling/defaults.rb +28 -14
  169. data/lib/ceedling/defineinator.rb +9 -4
  170. data/lib/ceedling/dependencies/README.md +69 -0
  171. data/lib/ceedling/dependencies/dependency_cache_store.rb +160 -0
  172. data/lib/ceedling/dependencies/dependency_debug_tree.rb +129 -0
  173. data/lib/ceedling/dependencies/dependency_differ.rb +127 -0
  174. data/lib/ceedling/dependencies/dependency_hasher.rb +94 -0
  175. data/lib/ceedling/dependencies/dependency_path_normalizer.rb +80 -0
  176. data/lib/ceedling/dependencies/dependency_tracker.rb +405 -0
  177. data/lib/ceedling/dependencies/dependinator.rb +65 -0
  178. data/lib/ceedling/dependencies/gcc_dependency_parser.rb +86 -0
  179. data/lib/ceedling/encodinator.rb +23 -11
  180. data/lib/ceedling/file_finder.rb +373 -89
  181. data/lib/ceedling/file_finder_helper.rb +44 -33
  182. data/lib/ceedling/file_path_collection_utils.rb +17 -4
  183. data/lib/ceedling/file_path_utils.rb +310 -52
  184. data/lib/ceedling/file_wrapper.rb +245 -8
  185. data/lib/ceedling/filename_extension.rb +91 -0
  186. data/lib/ceedling/flaginator.rb +6 -2
  187. data/lib/ceedling/generators/generator.rb +202 -75
  188. data/lib/ceedling/generators/generator_helper.rb +116 -69
  189. data/lib/ceedling/generators/generator_mocks.rb +13 -8
  190. data/lib/ceedling/generators/generator_partials.rb +93 -25
  191. data/lib/ceedling/generators/generator_test_results.rb +29 -17
  192. data/lib/ceedling/generators/generator_test_results_backtrace.rb +199 -107
  193. data/lib/ceedling/generators/generator_test_results_sanity_checker.rb +1 -1
  194. data/lib/ceedling/includes/include_factory.rb +21 -6
  195. data/lib/ceedling/includes/include_pathinator.rb +40 -4
  196. data/lib/ceedling/includes/includes.rb +215 -61
  197. data/lib/ceedling/loginator.rb +13 -4
  198. data/lib/ceedling/objects.yml +218 -33
  199. data/lib/ceedling/parsing_parcels.rb +39 -13
  200. data/lib/ceedling/partials/README.md +53 -0
  201. data/lib/ceedling/partials/partializer.rb +272 -117
  202. data/lib/ceedling/partials/partializer_config.rb +141 -8
  203. data/lib/ceedling/partials/partializer_helper.rb +88 -2
  204. data/lib/ceedling/partials/partializer_utils.rb +1 -1
  205. data/lib/ceedling/partials/partials.rb +4 -4
  206. data/lib/ceedling/path_matcher.rb +163 -0
  207. data/lib/ceedling/path_mirror.rb +73 -0
  208. data/lib/ceedling/plugins/plugin.rb +1 -1
  209. data/lib/ceedling/plugins/plugin_manager.rb +31 -15
  210. data/lib/ceedling/plugins/plugin_manager_helper.rb +5 -1
  211. data/lib/ceedling/plugins/plugin_reportinator.rb +36 -7
  212. data/lib/ceedling/plugins/plugin_reportinator_helper.rb +3 -3
  213. data/lib/ceedling/plugins/report_log_writer_plugin.rb +66 -0
  214. data/lib/ceedling/plugins/report_tests_stdout_plugin.rb +18 -5
  215. data/lib/ceedling/preprocess/README.md +135 -120
  216. data/lib/ceedling/preprocess/c_comment_scanner.rb +9 -7
  217. data/lib/ceedling/preprocess/c_preprocessor_conditionals.rb +27 -10
  218. data/lib/ceedling/preprocess/preprocessinator.rb +253 -217
  219. data/lib/ceedling/preprocess/preprocessinator_bare_includes_extractor.rb +7 -10
  220. data/lib/ceedling/preprocess/preprocessinator_code_finder.rb +8 -6
  221. data/lib/ceedling/preprocess/preprocessinator_comment_stripper.rb +5 -3
  222. data/lib/ceedling/preprocess/preprocessinator_file_assembler.rb +86 -82
  223. data/lib/ceedling/preprocess/preprocessinator_includes_handler.rb +182 -163
  224. data/lib/ceedling/preprocess/preprocessinator_line_marker_includes_extractor.rb +174 -8
  225. data/lib/ceedling/preprocess/preprocessinator_reconstructor.rb +41 -20
  226. data/lib/ceedling/quote_include_isolator.rb +129 -0
  227. data/lib/ceedling/rake_app/rake_task_registry.rb +9 -9
  228. data/lib/ceedling/rake_app/rake_wrapper.rb +0 -13
  229. data/lib/ceedling/rake_app/rakefile_component_resolver.rb +24 -12
  230. data/lib/ceedling/rakefile.rb +2 -1
  231. data/lib/ceedling/{tasks_base.rake → rakefiles/base/tasks_base.rake} +1 -1
  232. data/lib/ceedling/{tasks_filesystem.rake → rakefiles/base/tasks_filesystem.rake} +3 -0
  233. data/lib/ceedling/rakefiles/release/rules_release.rake +52 -0
  234. data/lib/ceedling/{erb_wrapper.rb → rakefiles/release/tasks_release.rake} +5 -8
  235. data/lib/ceedling/rakefiles/tests/rules_tests.rake +43 -0
  236. data/lib/ceedling/rakefiles/tests/rules_tests_generate.rake +80 -0
  237. data/lib/ceedling/{tasks_tests.rake → rakefiles/tests/tasks_tests.rake} +11 -20
  238. data/lib/ceedling/rakefiles/tests/tasks_tests_generate.rake +55 -0
  239. data/lib/ceedling/release_invoker/README.md +35 -0
  240. data/lib/ceedling/release_invoker/release_build_executor.rb +263 -0
  241. data/lib/ceedling/release_invoker/release_build_planner.rb +80 -0
  242. data/lib/ceedling/release_invoker/release_invoker.rb +78 -0
  243. data/lib/ceedling/release_invoker/release_invoker_types.rb +40 -0
  244. data/lib/ceedling/reportinator.rb +18 -2
  245. data/lib/ceedling/ruby_expandinator.rb +40 -1
  246. data/lib/ceedling/setupinator.rb +9 -3
  247. data/lib/ceedling/system_wrapper.rb +17 -0
  248. data/lib/ceedling/templateinator.rb +146 -0
  249. data/lib/ceedling/test_context_extractor.rb +59 -28
  250. data/lib/ceedling/test_invoker/HEADER_COLLISIONS.md +41 -0
  251. data/lib/ceedling/test_invoker/PIPELINE.md +142 -0
  252. data/lib/ceedling/test_invoker/README.md +6 -0
  253. data/lib/ceedling/test_invoker/mock_locator.rb +49 -0
  254. data/lib/ceedling/test_invoker/partials_manager.rb +426 -0
  255. data/lib/ceedling/test_invoker/standin_headerinator.rb +136 -0
  256. data/lib/ceedling/test_invoker/test_bare_includes_extractinator.rb +117 -0
  257. data/lib/ceedling/test_invoker/test_build_executor.rb +783 -415
  258. data/lib/ceedling/test_invoker/test_build_planner.rb +175 -70
  259. data/lib/ceedling/test_invoker/test_build_setup.rb +132 -241
  260. data/lib/ceedling/test_invoker/test_build_validations.rb +102 -0
  261. data/lib/ceedling/test_invoker/test_file_preprocessinator.rb +148 -0
  262. data/lib/ceedling/test_invoker/test_includes_extractinator.rb +34 -0
  263. data/lib/ceedling/test_invoker/test_includes_preprocessinator.rb +118 -0
  264. data/lib/ceedling/test_invoker/test_includes_reconcilinator.rb +149 -0
  265. data/lib/ceedling/test_invoker/test_invoker.rb +16 -183
  266. data/lib/ceedling/test_invoker/test_invoker_types.rb +85 -16
  267. data/lib/ceedling/test_invoker/test_pipeline_helpers.rb +121 -0
  268. data/lib/ceedling/test_invoker/test_pipeline_manager.rb +303 -0
  269. data/lib/ceedling/test_invoker/test_runner_generatinator.rb +105 -0
  270. data/lib/ceedling/test_invoker/test_search_paths.rb +73 -0
  271. data/lib/ceedling/test_invoker/test_source_file_directive_resolver.rb +78 -0
  272. data/lib/ceedling/tool_executor.rb +42 -13
  273. data/lib/ceedling/tool_executor_helper.rb +1 -1
  274. data/lib/ceedling/tool_validator.rb +124 -123
  275. data/lib/ceedling/yaml_wrapper.rb +5 -3
  276. data/lib/version.rb +19 -2
  277. data/mkdocs.prerelease.yml +42 -0
  278. data/mkdocs.yml +10 -2
  279. data/plugins/bullseye/bullseye.rake +70 -107
  280. data/plugins/bullseye/config/defaults.yml +12 -54
  281. data/plugins/bullseye/config/defaults_bullseye.rb +182 -0
  282. data/plugins/bullseye/lib/bullseye.rb +511 -120
  283. data/plugins/bullseye/lib/bullseye_constants.rb +100 -0
  284. data/plugins/command_hooks/lib/command_hooks.rb +117 -199
  285. data/plugins/compile_commands_json_db/lib/compile_commands_json_db.rb +72 -27
  286. data/plugins/cppcheck/config/defaults.yml +6 -1
  287. data/plugins/cppcheck/config/defaults_cppcheck.rb +5 -1
  288. data/plugins/cppcheck/cppcheck.rake +7 -1
  289. data/plugins/cppcheck/lib/cppcheck.rb +175 -26
  290. data/plugins/cppcheck/lib/cppcheck_constants.rb +12 -0
  291. data/plugins/cppcheck/lib/cppcheck_reports.rb +5 -1
  292. data/plugins/dependencies/Rakefile +14 -2
  293. data/plugins/dependencies/config/defaults.yml +9 -6
  294. data/plugins/dependencies/dependencies.rake +46 -76
  295. data/plugins/dependencies/example/boss/project.yml +1 -1
  296. data/plugins/dependencies/example/supervisor/project.yml +1 -1
  297. data/plugins/dependencies/example/version.tar.gzip +0 -0
  298. data/plugins/dependencies/lib/dependencies.rb +232 -427
  299. data/plugins/dependencies/lib/dependency_commands.rb +72 -0
  300. data/plugins/dependencies/lib/dependency_environment.rb +57 -0
  301. data/plugins/dependencies/lib/dependency_spec.rb +145 -0
  302. data/plugins/fff/.rspec +1 -0
  303. data/plugins/fff/Rakefile +14 -2
  304. data/plugins/fff/examples/fff_example/project.yml +1 -1
  305. data/plugins/fff/lib/fff.rb +30 -9
  306. data/plugins/fff/lib/fff_mock_generator.rb +142 -128
  307. data/plugins/fff/spec/fff_mock_header_generator_spec.rb +15 -0
  308. data/plugins/fff/spec/fff_mock_source_generator_spec.rb +14 -0
  309. data/plugins/fff/spec/spec_helper.rb +45 -0
  310. data/plugins/fff/src/fff_unity_helper.h +5 -0
  311. data/plugins/fff/vendor/fff/fakegen.rb +5 -4
  312. data/plugins/fff/vendor/fff/fff.h +4 -4
  313. data/plugins/gcov/config/defaults.yml +5 -0
  314. data/plugins/gcov/gcov.rake +12 -8
  315. data/plugins/gcov/lib/console_reportinator.rb +140 -20
  316. data/plugins/gcov/lib/gcov.rb +155 -60
  317. data/plugins/gcov/lib/gcov_constants.rb +4 -7
  318. data/plugins/gcov/lib/gcov_reportinator.rb +90 -0
  319. data/plugins/gcov/lib/gcov_types.rb +62 -1
  320. data/plugins/gcov/lib/gcovr_reportinator.rb +255 -213
  321. data/plugins/gcov/lib/reportgenerator_reportinator.rb +122 -44
  322. data/plugins/module_generator/Rakefile +4 -4
  323. data/plugins/module_generator/config/module_generator.yml +0 -1
  324. data/plugins/module_generator/example/project.yml +1 -1
  325. data/plugins/module_generator/lib/module_generator.rb +117 -87
  326. data/plugins/module_generator/lib/module_generator_options.rb +150 -0
  327. data/plugins/module_generator/lib/module_generator_project.rb +45 -0
  328. data/plugins/module_generator/lib/module_generator_request.rb +83 -0
  329. data/plugins/module_generator/lib/module_generator_test_file.rb +68 -0
  330. data/plugins/module_generator/lib/module_generator_unity.rb +24 -0
  331. data/plugins/module_generator/module_generator.rake +24 -46
  332. data/plugins/report_build_warnings_log/config/defaults.yml +4 -1
  333. data/plugins/report_build_warnings_log/lib/report_build_warnings_log.rb +47 -55
  334. data/plugins/report_build_warnings_log/lib/warning_collector.rb +140 -0
  335. data/plugins/report_build_warnings_log/lib/warning_reports.rb +135 -0
  336. data/plugins/report_tests_gtestlike_stdout/assets/test_results.template +3 -0
  337. data/{spec/units/configurator_builder_spec.rb → plugins/report_tests_gtestlike_stdout/config/defaults.yml} +6 -10
  338. data/plugins/report_tests_gtestlike_stdout/lib/gtestlike_report.rb +168 -0
  339. data/plugins/report_tests_gtestlike_stdout/lib/report_tests_gtestlike_stdout.rb +25 -1
  340. data/plugins/report_tests_ide_stdout/assets/test_results.template +50 -0
  341. data/plugins/report_tests_ide_stdout/config/defaults.yml +13 -0
  342. data/plugins/report_tests_ide_stdout/lib/ide_report_lines.rb +103 -0
  343. data/plugins/report_tests_ide_stdout/lib/report_tests_ide_stdout.rb +12 -4
  344. data/plugins/report_tests_log_factory/lib/cppunit_tests_reporter.rb +33 -51
  345. data/plugins/report_tests_log_factory/lib/html_tests_reporter.rb +286 -295
  346. data/plugins/report_tests_log_factory/lib/json_tests_reporter.rb +22 -35
  347. data/plugins/report_tests_log_factory/lib/junit_tests_reporter.rb +91 -133
  348. data/plugins/report_tests_log_factory/lib/report_tests_log_factory.rb +72 -86
  349. data/plugins/report_tests_log_factory/lib/tests_reporter.rb +31 -12
  350. data/plugins/report_tests_pretty_stdout/assets/{template.erb → test_results.template} +8 -8
  351. data/plugins/report_tests_raw_output_log/lib/report_tests_raw_output_log.rb +18 -48
  352. data/plugins/report_tests_teamcity_stdout/lib/report_tests_teamcity_stdout.rb +13 -2
  353. data/plugins/sanitize/config/defaults.yml +44 -0
  354. data/plugins/sanitize/config/defaults_sanitize.rb +20 -0
  355. data/plugins/sanitize/lib/sanitize.rb +174 -0
  356. data/plugins/sanitize/lib/sanitize_config.rb +110 -0
  357. data/plugins/sanitize/lib/sanitize_constants.rb +13 -0
  358. data/plugins/sanitize/lib/sanitize_findings.rb +85 -0
  359. data/plugins/sanitize/lib/sanitize_records.rb +115 -0
  360. data/plugins/sanitize/lib/sanitize_reports.rb +135 -0
  361. data/plugins/sanitize/sanitize.rake +108 -0
  362. data/plugins/valgrind/config/defaults.yml +7 -1
  363. data/plugins/valgrind/config/defaults_valgrind.rb +6 -1
  364. data/plugins/valgrind/lib/valgrind.rb +202 -39
  365. data/plugins/valgrind/lib/valgrind_constants.rb +4 -0
  366. data/plugins/valgrind/lib/valgrind_report.rb +52 -0
  367. data/plugins/valgrind/valgrind.rake +33 -11
  368. data/site-local/404.html +248 -14
  369. data/site-local/configuration/environment-vars.html +248 -14
  370. data/site-local/configuration/global-collections.html +248 -19
  371. data/site-local/configuration/index.html +249 -15
  372. data/site-local/configuration/loading.html +260 -22
  373. data/site-local/configuration/mixins.html +252 -17
  374. data/site-local/configuration/parallel-builds.html +248 -14
  375. data/site-local/configuration/project-file.html +275 -30
  376. data/site-local/configuration/reference/cexception.html +255 -20
  377. data/site-local/configuration/reference/cmock.html +281 -14
  378. data/site-local/configuration/reference/defines.html +262 -19
  379. data/site-local/configuration/reference/environment.html +251 -17
  380. data/site-local/configuration/reference/extension.html +361 -16
  381. data/site-local/configuration/reference/files.html +262 -14
  382. data/site-local/configuration/reference/flags.html +270 -19
  383. data/site-local/configuration/reference/index.html +248 -14
  384. data/site-local/configuration/reference/libraries.html +248 -14
  385. data/site-local/configuration/reference/mixins.html +248 -14
  386. data/site-local/configuration/reference/partials.html +249 -19
  387. data/site-local/configuration/reference/paths.html +275 -15
  388. data/site-local/configuration/reference/plugins.html +248 -14
  389. data/site-local/configuration/reference/project.html +291 -14
  390. data/site-local/configuration/reference/release-build.html +256 -14
  391. data/site-local/configuration/reference/test-build.html +290 -24
  392. data/site-local/configuration/reference/test-runner.html +288 -17
  393. data/site-local/configuration/reference/tools.html +254 -14
  394. data/site-local/configuration/reference/unity.html +280 -15
  395. data/site-local/configuration/which-ceedling.html +248 -14
  396. data/site-local/development/index.html +261 -14
  397. data/site-local/development/plugins/configuration.html +269 -17
  398. data/site-local/development/plugins/index.html +267 -15
  399. data/site-local/development/plugins/plugin-subclass.html +906 -154
  400. data/site-local/development/plugins/rake-tasks.html +276 -14
  401. data/site-local/development/releases.html +4708 -0
  402. data/site-local/development/workflow.html +1030 -51
  403. data/site-local/getting-started/builds.html +4607 -0
  404. data/site-local/getting-started/command-line.html +418 -34
  405. data/site-local/getting-started/example-projects/cipher-quest.html +248 -14
  406. data/site-local/getting-started/example-projects/index.html +249 -15
  407. data/site-local/getting-started/example-projects/temp-sensor.html +248 -14
  408. data/site-local/getting-started/example-projects/wondrous-forest.html +248 -14
  409. data/site-local/getting-started/index.html +255 -14
  410. data/site-local/getting-started/installation.html +258 -22
  411. data/site-local/getting-started/quick-start.html +251 -15
  412. data/site-local/help.html +255 -14
  413. data/site-local/index.html +292 -22
  414. data/site-local/overview/build-system.html +249 -15
  415. data/site-local/overview/index.html +248 -14
  416. data/site-local/overview/test-environments.html +257 -14
  417. data/site-local/overview/tools-and-frameworks.html +248 -14
  418. data/site-local/plugins/beep.html +251 -14
  419. data/site-local/plugins/bullseye/index.html +5079 -0
  420. data/site-local/plugins/bullseye/licensing.html +4840 -0
  421. data/site-local/plugins/command-hooks.html +265 -27
  422. data/site-local/plugins/compile-commands-json-db.html +256 -17
  423. data/site-local/plugins/cppcheck.html +1081 -262
  424. data/site-local/plugins/dependencies.html +934 -242
  425. data/site-local/plugins/fff.html +297 -16
  426. data/site-local/plugins/gcov/examples.html +251 -14
  427. data/site-local/plugins/gcov/gcovr.html +686 -31
  428. data/site-local/plugins/gcov/index.html +251 -14
  429. data/site-local/plugins/gcov/overview.html +259 -18
  430. data/site-local/plugins/gcov/reportgenerator.html +563 -28
  431. data/site-local/plugins/gcov/reporting.html +348 -100
  432. data/site-local/plugins/gcov/setup.html +253 -15
  433. data/site-local/plugins/gcov/tool-versions.html +301 -19
  434. data/site-local/plugins/gcov/troubleshooting.html +273 -36
  435. data/site-local/plugins/index.html +294 -36
  436. data/site-local/plugins/module-generator.html +779 -195
  437. data/site-local/plugins/report-build-warnings-log.html +578 -33
  438. data/site-local/plugins/report-tests-gtestlike-stdout.html +467 -84
  439. data/site-local/plugins/report-tests-ide-stdout.html +654 -51
  440. data/site-local/plugins/report-tests-log-factory.html +337 -70
  441. data/site-local/plugins/report-tests-pretty-stdout.html +251 -14
  442. data/site-local/plugins/report-tests-raw-output-log.html +251 -14
  443. data/site-local/plugins/report-tests-teamcity-stdout.html +251 -14
  444. data/site-local/plugins/sanitize.html +5332 -0
  445. data/site-local/plugins/valgrind.html +416 -26
  446. data/site-local/{plugins/bullseye.html → project/index.html} +297 -217
  447. data/site-local/project/release-history.html +251 -17
  448. data/site-local/project/sbom.html +4726 -0
  449. data/site-local/project/upgrade.html +250 -16
  450. data/site-local/reference/build-directives.html +257 -14
  451. data/site-local/reference/command-line.html +373 -16
  452. data/site-local/reference/environment-vars.html +248 -14
  453. data/site-local/reference/gcov-plugin.html +492 -18
  454. data/site-local/reference/global-collections.html +249 -15
  455. data/site-local/reference/index.html +248 -14
  456. data/site-local/reference/partials-macros.html +258 -14
  457. data/site-local/reference/project-configuration.html +248 -14
  458. data/site-local/sitemap.xml.gz +0 -0
  459. data/site-local/snapshot/assets/{project.yml → features/project.yml} +4 -1
  460. data/site-local/snapshot/examples/cipher_quest/index.html +248 -14
  461. data/site-local/snapshot/examples/temp_sensor/index.html +248 -14
  462. data/site-local/snapshot/examples/wondrous_forest/index.html +265 -25
  463. data/site-local/snapshot/plugins/bullseye/config/defaults.yml +24 -0
  464. data/site-local/snapshot/plugins/bullseye/config/defaults_bullseye.rb +182 -0
  465. data/site-local/snapshot/plugins/gcov/config/defaults.yml +5 -0
  466. data/site-local/testing-guide/build-directives.html +332 -22
  467. data/site-local/testing-guide/conventions.html +678 -153
  468. data/site-local/testing-guide/frameworks.html +248 -14
  469. data/site-local/testing-guide/index.html +248 -21
  470. data/site-local/testing-guide/partials/configuration.html +248 -14
  471. data/site-local/testing-guide/partials/conventions.html +316 -17
  472. data/site-local/testing-guide/partials/directives.html +456 -48
  473. data/site-local/testing-guide/partials/example.html +248 -14
  474. data/site-local/testing-guide/partials/index.html +255 -14
  475. data/site-local/testing-guide/partials/overview.html +248 -14
  476. data/site-local/testing-guide/partials/variables.html +248 -14
  477. data/site-local/testing-guide/test-cases.html +248 -14
  478. data/site-local/testing-guide/test-sample.html +248 -14
  479. data/site-local/testing-guide/test-suite-anatomy.html +248 -14
  480. data/spec/integration/actionator_file_operations_spec.rb +287 -0
  481. data/spec/integration/analysis_tool_output_spec.rb +204 -0
  482. data/spec/{units/c_extractor/c_extractor_integration_spec.rb → integration/c_extractor_composition_spec.rb} +196 -17
  483. data/spec/integration/command_hooks_plugin_spec.rb +152 -0
  484. data/spec/integration/compile_commands_json_db_spec.rb +76 -0
  485. data/spec/integration/configurator_pipeline_spec.rb +180 -0
  486. data/spec/integration/configurator_plugins_spec.rb +122 -0
  487. data/spec/integration/configurator_validation_spec.rb +98 -0
  488. data/spec/integration/dependencies/dependency_tracker_cache_hardening_spec.rb +396 -0
  489. data/spec/integration/dependencies/dependency_tracker_core_spec.rb +244 -0
  490. data/spec/integration/dependencies/dependency_tracker_diagnose_spec.rb +224 -0
  491. data/spec/integration/dependencies/dependency_tracker_filename_handling_spec.rb +118 -0
  492. data/spec/integration/dependencies/dependency_tracker_gcc_deps_spec.rb +199 -0
  493. data/spec/integration/dependencies/dependency_tracker_pruning_spec.rb +167 -0
  494. data/spec/integration/dependencies_plugin_spec.rb +473 -0
  495. data/spec/integration/erb_dependency_removed_spec.rb +167 -0
  496. data/spec/integration/includes_extraction_spec.rb +612 -0
  497. data/spec/integration/mixin_loading_spec.rb +414 -0
  498. data/spec/integration/module_generator_spec.rb +436 -0
  499. data/spec/integration/partials_fallback_preprocessing_spec.rb +316 -0
  500. data/spec/integration/partials_header_composition_spec.rb +889 -0
  501. data/spec/integration/partials_module_resolution_spec.rb +372 -0
  502. data/spec/integration/partials_symbol_linkage_spec.rb +371 -0
  503. data/spec/integration/preprocessing_transient_io_retry_spec.rb +135 -0
  504. data/spec/integration/quote_include_isolator_spec.rb +167 -0
  505. data/spec/integration/report_build_warnings_log_spec.rb +170 -0
  506. data/spec/integration/report_tests_log_factory_spec.rb +100 -0
  507. data/spec/integration/sanitizer_exclusions_spec.rb +126 -0
  508. data/spec/integration/system_harness_sanitizers_spec.rb +104 -0
  509. data/spec/integration/test_build_parallel_barrier_spec.rb +89 -0
  510. data/spec/integration/test_executable_manifest_spec.rb +118 -0
  511. data/spec/integration/test_includes_extractinator_spec.rb +293 -0
  512. data/spec/integration/tool_executor_spec.rb +224 -0
  513. data/spec/integration/tool_validator_spec.rb +133 -0
  514. data/spec/integration/vendor_copy_transient_io_retry_spec.rb +130 -0
  515. data/spec/manual/stress_test.rb +1 -1
  516. data/spec/support/config_yaml_helper.rb +17 -0
  517. data/spec/support/fixtures/sanitizer_reports/clang_asan_heap.txt +45 -0
  518. data/spec/support/fixtures/sanitizer_reports/clang_ubsan_shift.txt +5 -0
  519. data/spec/support/fixtures/sanitizer_reports/gcc_heap.txt +47 -0
  520. data/spec/support/fixtures/sanitizer_reports/gcc_leak.txt +10 -0
  521. data/spec/support/fixtures/sanitizer_reports/gcc_segv.txt +6 -0
  522. data/spec/support/fixtures/sanitizer_reports/gcc_ubsan_shift.txt +6 -0
  523. data/spec/support/fixtures/templates/bullseye__all_pass.txt +6 -0
  524. data/spec/support/fixtures/templates/bullseye__coverage_branches_only.txt +6 -0
  525. data/spec/support/fixtures/templates/bullseye__coverage_functions_only.txt +6 -0
  526. data/spec/support/fixtures/templates/bullseye__coverage_none.txt +6 -0
  527. data/spec/support/fixtures/templates/bullseye__empty.txt +6 -0
  528. data/spec/support/fixtures/templates/bullseye__gcov_context.txt +6 -0
  529. data/spec/support/fixtures/templates/bullseye__mixed_all.txt +6 -0
  530. data/spec/support/fixtures/templates/bullseye__one_failure_matching.txt +6 -0
  531. data/spec/support/fixtures/templates/bullseye__one_failure_multiline.txt +6 -0
  532. data/spec/support/fixtures/templates/bullseye__one_failure_no_message.txt +6 -0
  533. data/spec/support/fixtures/templates/bullseye__one_failure_nonmatching.txt +6 -0
  534. data/spec/support/fixtures/templates/bullseye__one_ignore_no_message.txt +6 -0
  535. data/spec/support/fixtures/templates/bullseye__one_ignore_with_message.txt +6 -0
  536. data/spec/support/fixtures/templates/bullseye__stdout_only.txt +6 -0
  537. data/spec/support/fixtures/templates/ide__all_pass.txt +10 -0
  538. data/spec/support/fixtures/templates/ide__coverage_branches_only.txt +10 -0
  539. data/spec/support/fixtures/templates/ide__coverage_functions_only.txt +10 -0
  540. data/spec/support/fixtures/templates/ide__coverage_none.txt +10 -0
  541. data/spec/support/fixtures/templates/ide__empty.txt +8 -0
  542. data/spec/support/fixtures/templates/ide__gcov_context.txt +28 -0
  543. data/spec/support/fixtures/templates/ide__mixed_all.txt +29 -0
  544. data/spec/support/fixtures/templates/ide__one_failure_matching.txt +15 -0
  545. data/spec/support/fixtures/templates/ide__one_failure_multiline.txt +17 -0
  546. data/spec/support/fixtures/templates/ide__one_failure_no_message.txt +15 -0
  547. data/spec/support/fixtures/templates/ide__one_failure_nonmatching.txt +15 -0
  548. data/spec/support/fixtures/templates/ide__one_ignore_no_message.txt +15 -0
  549. data/spec/support/fixtures/templates/ide__one_ignore_with_message.txt +15 -0
  550. data/spec/support/fixtures/templates/ide__stdout_only.txt +16 -0
  551. data/spec/support/fixtures/templates/pretty__all_pass.txt +8 -0
  552. data/spec/support/fixtures/templates/pretty__coverage_branches_only.txt +8 -0
  553. data/spec/support/fixtures/templates/pretty__coverage_functions_only.txt +8 -0
  554. data/spec/support/fixtures/templates/pretty__coverage_none.txt +8 -0
  555. data/spec/support/fixtures/templates/pretty__empty.txt +6 -0
  556. data/spec/support/fixtures/templates/pretty__gcov_context.txt +31 -0
  557. data/spec/support/fixtures/templates/pretty__mixed_all.txt +35 -0
  558. data/spec/support/fixtures/templates/pretty__one_failure_matching.txt +15 -0
  559. data/spec/support/fixtures/templates/pretty__one_failure_multiline.txt +17 -0
  560. data/spec/support/fixtures/templates/pretty__one_failure_no_message.txt +15 -0
  561. data/spec/support/fixtures/templates/pretty__one_failure_nonmatching.txt +15 -0
  562. data/spec/support/fixtures/templates/pretty__one_ignore_no_message.txt +15 -0
  563. data/spec/support/fixtures/templates/pretty__one_ignore_with_message.txt +15 -0
  564. data/spec/support/fixtures/templates/pretty__stdout_only.txt +15 -0
  565. data/spec/support/fixtures/valgrind_reports/sigsegv.log +51 -0
  566. data/spec/support/fixtures/valgrind_reports/sigsegv.xml +182 -0
  567. data/spec/support/include_guard_helper.rb +20 -0
  568. data/spec/support/integration/configurator_integration_helper.rb +159 -0
  569. data/spec/support/integration/dependency_tracker_integration_helper.rb +136 -0
  570. data/spec/support/integration/partials_generation_integration_helper.rb +726 -0
  571. data/spec/support/integration/spec_integration_helper.rb +285 -0
  572. data/spec/support/integration/test_includes_harness.rb +259 -0
  573. data/spec/support/integration/tool_executor_integration_helper.rb +55 -0
  574. data/spec/support/spec_helper.rb +41 -0
  575. data/spec/support/system/sanitizers/asan_ubsan.yml +82 -0
  576. data/spec/support/system/sanitizers/asan_ubsan_leaks.yml +57 -0
  577. data/spec/support/system/simplecov_boot.rb +66 -0
  578. data/spec/support/system/spec_system_helper.rb +376 -16
  579. data/spec/support/system/system_context.rb +181 -59
  580. data/spec/support/template_render_cases.rb +166 -0
  581. data/spec/system/bracket_path_handling_spec.rb +175 -0
  582. data/spec/system/build_output_mirroring_spec.rb +89 -0
  583. data/spec/system/build_recovery_spec.rb +382 -0
  584. data/spec/system/bullseye_deployment_spec.rb +102 -0
  585. data/spec/system/cli_surface_spec.rb +245 -0
  586. data/spec/system/command_hooks_spec.rb +117 -0
  587. data/spec/system/conditional_include_macro_visibility_spec.rb +32 -124
  588. data/spec/system/conditional_mock_includes_spec.rb +181 -0
  589. data/spec/system/cppcheck_deployment_spec.rb +26 -8
  590. data/spec/system/delta_builds_spec.rb +751 -0
  591. data/spec/system/deployment_as_gem_spec.rb +7 -0
  592. data/spec/system/deployment_as_vendor_spec.rb +29 -145
  593. data/spec/system/dumpconfig_spec.rb +137 -0
  594. data/spec/system/encoding_stress_spec.rb +7 -4
  595. data/spec/system/example_cipher_quest_spec.rb +25 -100
  596. data/spec/system/example_temp_sensor_spec.rb +30 -172
  597. data/spec/system/example_wondrous_forest_spec.rb +25 -62
  598. data/spec/system/extension_multiple_values_spec.rb +75 -0
  599. data/spec/system/files_paths_reporting_spec.rb +154 -0
  600. data/spec/system/gcov_deployment_spec.rb +72 -3
  601. data/spec/system/header_include_path_validation_spec.rb +222 -0
  602. data/spec/system/implicit_source_header_correspondence_disambiguation_spec.rb +100 -0
  603. data/spec/system/include_path_reconciliation_spec.rb +64 -0
  604. data/spec/system/mixin_ordering_spec.rb +30 -415
  605. data/spec/system/mocks_partials_configuration_validation_spec.rb +126 -0
  606. data/spec/system/parent_directory_reference_spec.rb +114 -0
  607. data/spec/system/partials_module_disambiguation_spec.rb +143 -0
  608. data/spec/system/pinned_thread_count_spec.rb +102 -0
  609. data/spec/system/plugin_delta_builds_spec.rb +179 -0
  610. data/spec/system/preprocessing_encoding_spec.rb +87 -4
  611. data/spec/system/preprocessing_fallback_conditionals_spec.rb +19 -25
  612. data/spec/system/preprocessing_parameterized_tests_spec.rb +2 -2
  613. data/spec/system/rake_release_task_path_disambiguation_spec.rb +97 -0
  614. data/spec/system/rake_test_task_path_disambiguation_spec.rb +118 -0
  615. data/spec/system/report_and_tooling_plugins_spec.rb +327 -0
  616. data/spec/system/ruby_replacement_spec.rb +1 -1
  617. data/spec/system/same_named_modules_spec.rb +115 -0
  618. data/spec/system/sanitize_deployment_spec.rb +64 -0
  619. data/spec/system/shuffle_tests_spec.rb +139 -0
  620. data/spec/system/sibling_header_collision_spec.rb +620 -0
  621. data/spec/system/subdir_include_preservation_spec.rb +63 -0
  622. data/spec/system/support/bullseye_common_test_cases.rb +369 -0
  623. data/spec/system/support/bullseye_helpers.rb +70 -0
  624. data/spec/system/support/common_test_cases.rb +167 -43
  625. data/spec/system/support/cppcheck_common_test_cases.rb +80 -0
  626. data/spec/system/support/cppcheck_helpers.rb +10 -8
  627. data/spec/system/support/gcov_common_test_cases.rb +173 -37
  628. data/spec/system/support/gcov_helpers.rb +3 -3
  629. data/spec/system/support/gcov_partials_test_cases.rb +48 -2
  630. data/spec/system/support/sanitize_common_test_cases.rb +222 -0
  631. data/spec/system/support/sanitize_helpers.rb +27 -0
  632. data/spec/system/support/valgrind_common_test_cases.rb +116 -16
  633. data/spec/system/support/valgrind_helpers.rb +3 -4
  634. data/spec/system/test_pipeline_stop_points_spec.rb +160 -0
  635. data/spec/system/test_runner_system_include_spec.rb +19 -41
  636. data/spec/system/test_source_file_directive_spec.rb +235 -0
  637. data/spec/system/upgrade_as_vendor_spec.rb +25 -46
  638. data/spec/system/valgrind_deployment_spec.rb +41 -0
  639. data/spec/units/batchinator_spec.rb +314 -0
  640. data/spec/units/bin/actionator_spec.rb +412 -0
  641. data/spec/units/bin/app_cfg_spec.rb +90 -0
  642. data/spec/units/bin/cli_handler_spec.rb +204 -0
  643. data/spec/units/bin/cli_helper_spec.rb +238 -10
  644. data/spec/units/bin/cli_options_transform_spec.rb +49 -0
  645. data/spec/units/bin/composinator_spec.rb +236 -0
  646. data/spec/units/bin/{projectinator_mixin_spec.rb → mixin_resolvinator_spec.rb} +122 -83
  647. data/spec/units/bin/mixin_standardizer_spec.rb +4 -3
  648. data/spec/units/bin/mixinator_spec.rb +58 -22
  649. data/spec/units/bin/path_validator_spec.rb +112 -0
  650. data/spec/units/bin/projectinator_spec.rb +223 -0
  651. data/spec/units/bin/rake_patches_spec.rb +52 -0
  652. data/spec/units/bin/recursive_merger_spec.rb +22 -0
  653. data/spec/units/bin/versionator_spec.rb +104 -0
  654. data/spec/units/c_extractor/c_extractor_code_text_spec.rb +4 -4
  655. data/spec/units/c_extractor/c_extractor_declarations_spec.rb +70 -0
  656. data/spec/units/c_extractor/c_extractor_functions_spec.rb +75 -1
  657. data/spec/units/c_extractor/c_extractor_preprocessing_spec.rb +158 -0
  658. data/spec/units/c_extractor/c_extractor_spec.rb +236 -6
  659. data/spec/units/ceedling/templateinator_golden_spec.rb +84 -0
  660. data/spec/units/ceedling/templateinator_spec.rb +188 -0
  661. data/spec/units/config/configurator_builder_spec.rb +444 -0
  662. data/spec/units/config/configurator_plugins_spec.rb +160 -0
  663. data/spec/units/config/configurator_setup_spec.rb +706 -6
  664. data/spec/units/config/configurator_spec.rb +952 -0
  665. data/spec/units/config/configurator_validator_spec.rb +259 -0
  666. data/spec/units/config/line_marker_suppressors_spec.rb +89 -0
  667. data/spec/units/config_matchinator_spec.rb +103 -0
  668. data/spec/units/defineinator_spec.rb +158 -0
  669. data/spec/units/dependencies/dependency_cache_store_spec.rb +364 -0
  670. data/spec/units/dependencies/dependency_debug_tree_spec.rb +189 -0
  671. data/spec/units/dependencies/dependency_differ_spec.rb +139 -0
  672. data/spec/units/dependencies/dependency_hasher_spec.rb +141 -0
  673. data/spec/units/dependencies/dependency_path_normalizer_spec.rb +111 -0
  674. data/spec/units/dependencies/dependency_tracker_spec.rb +905 -0
  675. data/spec/units/dependencies/dependinator_spec.rb +99 -0
  676. data/spec/units/dependencies/gcc_dependency_parser_spec.rb +152 -0
  677. data/spec/units/encodinator_spec.rb +92 -0
  678. data/spec/units/file_finder_helper_spec.rb +99 -15
  679. data/spec/units/file_finder_spec.rb +495 -0
  680. data/spec/units/file_path_collection_utils_spec.rb +9 -0
  681. data/spec/units/file_path_utils_spec.rb +736 -0
  682. data/spec/units/file_wrapper_spec.rb +447 -0
  683. data/spec/units/filename_extension_spec.rb +120 -0
  684. data/spec/units/flaginator_spec.rb +114 -0
  685. data/spec/units/generators/generator_helper_spec.rb +113 -0
  686. data/spec/units/generators/generator_mocks_spec.rb +131 -0
  687. data/spec/units/generators/generator_partials_spec.rb +366 -77
  688. data/spec/units/generators/generator_spec.rb +317 -0
  689. data/spec/units/generators/generator_test_results_backtrace_spec.rb +169 -9
  690. data/spec/units/generators/generator_test_results_sanity_checker_spec.rb +14 -6
  691. data/spec/units/generators/generator_test_results_spec.rb +65 -8
  692. data/spec/units/generators/generator_test_runner_spec.rb +1 -1
  693. data/spec/units/includes/include_factory_spec.rb +53 -0
  694. data/spec/units/includes/include_pathinator_spec.rb +269 -0
  695. data/spec/units/includes/include_spec.rb +8 -4
  696. data/spec/units/includes/includes_spec.rb +326 -18
  697. data/spec/units/mock_locator_spec.rb +74 -0
  698. data/spec/units/parsing_parcels_spec.rb +65 -0
  699. data/spec/units/partials/partializer_config_spec.rb +284 -18
  700. data/spec/units/partials/partializer_helper_spec.rb +122 -0
  701. data/spec/units/partials/partializer_spec.rb +474 -36
  702. data/spec/units/partials/partializer_utils_spec.rb +4 -4
  703. data/spec/units/partials_manager_spec.rb +539 -0
  704. data/spec/units/path_matcher_spec.rb +193 -0
  705. data/spec/units/path_mirror_spec.rb +103 -0
  706. data/spec/units/plugin_manager_spec.rb +77 -0
  707. data/spec/units/plugin_reportinator_spec.rb +78 -3
  708. data/spec/units/plugins/bullseye_spec.rb +1068 -0
  709. data/spec/units/plugins/command_hooks_spec.rb +157 -0
  710. data/spec/units/plugins/compile_commands_json_db_spec.rb +145 -0
  711. data/spec/units/plugins/console_reportinator_spec.rb +370 -0
  712. data/spec/units/plugins/cppcheck_spec.rb +330 -4
  713. data/spec/units/plugins/cppunit_tests_reporter_spec.rb +118 -0
  714. data/spec/units/plugins/dependencies_spec.rb +295 -0
  715. data/spec/units/plugins/dependency_commands_spec.rb +83 -0
  716. data/spec/units/plugins/dependency_environment_spec.rb +64 -0
  717. data/spec/units/plugins/dependency_spec_spec.rb +170 -0
  718. data/spec/units/plugins/gcov_reportinator_spec.rb +272 -0
  719. data/spec/units/plugins/gcov_spec.rb +521 -0
  720. data/spec/units/plugins/gcovr_reportinator_spec.rb +795 -0
  721. data/spec/units/plugins/gtestlike_report_spec.rb +363 -0
  722. data/spec/units/plugins/html_tests_reporter_spec.rb +158 -0
  723. data/spec/units/plugins/ide_report_lines_spec.rb +229 -0
  724. data/spec/units/plugins/json_tests_reporter_spec.rb +87 -0
  725. data/spec/units/plugins/junit_tests_reporter_spec.rb +237 -0
  726. data/spec/units/plugins/module_generator_options_spec.rb +185 -0
  727. data/spec/units/plugins/module_generator_project_spec.rb +55 -0
  728. data/spec/units/plugins/module_generator_request_spec.rb +107 -0
  729. data/spec/units/plugins/module_generator_spec.rb +214 -0
  730. data/spec/units/plugins/module_generator_test_file_spec.rb +102 -0
  731. data/spec/units/plugins/module_generator_unity_spec.rb +37 -0
  732. data/spec/units/plugins/report_build_warnings_log_spec.rb +199 -0
  733. data/spec/units/plugins/report_log_writer_plugin_spec.rb +94 -0
  734. data/spec/units/plugins/report_tests_gtestlike_stdout_spec.rb +274 -0
  735. data/spec/units/plugins/report_tests_ide_stdout_spec.rb +140 -0
  736. data/spec/units/plugins/report_tests_log_factory_spec.rb +210 -0
  737. data/spec/units/plugins/report_tests_pretty_stdout_spec.rb +83 -0
  738. data/spec/units/plugins/report_tests_raw_output_log_spec.rb +98 -0
  739. data/spec/units/plugins/report_tests_stdout_plugin_spec.rb +145 -0
  740. data/spec/units/plugins/report_tests_teamcity_stdout_spec.rb +121 -0
  741. data/spec/units/plugins/reportgenerator_reportinator_spec.rb +410 -0
  742. data/spec/units/plugins/sanitize_config_spec.rb +119 -0
  743. data/spec/units/plugins/sanitize_findings_spec.rb +69 -0
  744. data/spec/units/plugins/sanitize_records_spec.rb +114 -0
  745. data/spec/units/plugins/sanitize_reports_spec.rb +84 -0
  746. data/spec/units/plugins/sanitize_spec.rb +300 -0
  747. data/spec/units/plugins/tests_reporter_spec.rb +89 -0
  748. data/spec/units/plugins/valgrind_spec.rb +560 -0
  749. data/spec/units/plugins/warning_collector_spec.rb +185 -0
  750. data/spec/units/plugins/warning_reports_spec.rb +150 -0
  751. data/spec/units/preprocess/c_comment_scanner_spec.rb +17 -17
  752. data/spec/units/preprocess/c_preprocessor_conditionals_spec.rb +94 -0
  753. data/spec/units/preprocess/preprocessinator_bare_includes_extractor_spec.rb +73 -0
  754. data/spec/units/preprocess/preprocessinator_code_finder_spec.rb +35 -16
  755. data/spec/units/preprocess/preprocessinator_comment_stripper_spec.rb +129 -48
  756. data/spec/units/preprocess/preprocessinator_file_assembler_spec.rb +292 -9
  757. data/spec/units/preprocess/preprocessinator_includes_handler_spec.rb +294 -16
  758. data/spec/units/preprocess/preprocessinator_line_marker_includes_extractor_spec.rb +356 -6
  759. data/spec/units/preprocess/preprocessinator_reconstructor_spec.rb +58 -4
  760. data/spec/units/preprocess/preprocessinator_spec.rb +693 -5
  761. data/spec/units/quote_include_isolator_spec.rb +176 -0
  762. data/spec/units/rake_app/rake_invocation_tracker_spec.rb +94 -0
  763. data/spec/units/rake_app/rake_task_registry_spec.rb +263 -0
  764. data/spec/units/rake_app/rake_utils_spec.rb +54 -0
  765. data/spec/units/rake_app/rake_wrapper_spec.rb +64 -0
  766. data/spec/units/rake_app/rakefile_component_resolver_spec.rb +182 -0
  767. data/spec/units/release_build_executor_spec.rb +404 -0
  768. data/spec/units/release_build_planner_spec.rb +144 -0
  769. data/spec/units/release_invoker_spec.rb +127 -0
  770. data/spec/units/reportinator_spec.rb +35 -0
  771. data/spec/units/ruby_expandinator_spec.rb +36 -0
  772. data/spec/units/standin_headerinator_spec.rb +168 -0
  773. data/spec/units/system_wrapper_spec.rb +16 -0
  774. data/spec/units/test_build_executor_spec.rb +1653 -8
  775. data/spec/units/test_build_planner_spec.rb +878 -0
  776. data/spec/units/test_build_setup_spec.rb +583 -0
  777. data/spec/units/test_context_extractor_spec.rb +51 -3
  778. data/spec/units/test_file_preprocessinator_spec.rb +206 -0
  779. data/spec/units/test_includes_extractinator_spec.rb +764 -0
  780. data/spec/units/test_invoker/objects_wiring_spec.rb +31 -0
  781. data/spec/units/test_invoker_spec.rb +147 -0
  782. data/spec/units/test_invoker_types_spec.rb +182 -0
  783. data/spec/units/test_pipeline_helpers_spec.rb +100 -0
  784. data/spec/units/test_pipeline_manager_spec.rb +415 -0
  785. data/spec/units/test_runner_generatinator_spec.rb +215 -0
  786. data/spec/units/test_runner_manager_spec.rb +70 -0
  787. data/spec/units/test_search_paths_spec.rb +84 -0
  788. data/spec/units/test_source_file_directive_resolver_spec.rb +239 -0
  789. data/spec/units/tool_executor_helper_spec.rb +1 -1
  790. data/spec/units/tool_executor_spec.rb +571 -2
  791. data/spec/units/tool_validator_spec.rb +303 -24
  792. data/spec/units/version_spec.rb +74 -0
  793. data/spec/units/yaml_wrapper_spec.rb +4 -1
  794. data/vendor/cmock/docs/CMock_Summary.md +11 -0
  795. data/vendor/cmock/lib/cmock_config.rb +1 -0
  796. data/vendor/cmock/lib/cmock_generator.rb +5 -1
  797. data/vendor/cmock/test/unit/cmock_generator_main_test.rb +31 -0
  798. data/vendor/cmock/vendor/unity/auto/generate_module.rb +4 -4
  799. data/vendor/cmock/vendor/unity/auto/generate_test_runner.rb +8 -2
  800. data/vendor/cmock/vendor/unity/auto/unity_test_summary.rb +2 -2
  801. data/vendor/cmock/vendor/unity/docs/UnityChangeLog.md +7 -0
  802. data/vendor/cmock/vendor/unity/docs/UnityConfigurationGuide.md +4 -0
  803. data/vendor/cmock/vendor/unity/docs/UnityHelperScriptsGuide.md +9 -0
  804. data/vendor/cmock/vendor/unity/src/unity_internals.h +21 -7
  805. data/vendor/cmock/vendor/unity/test/Makefile +9 -2
  806. data/vendor/cmock/vendor/unity/test/rakefile_helper.rb +1 -0
  807. data/vendor/cmock/vendor/unity/test/spec/generate_module_naming_spec.rb +38 -0
  808. data/vendor/cmock/vendor/unity/test/testdata/spi/MockConfig.h +19 -0
  809. data/vendor/cmock/vendor/unity/test/testdata/testRunnerGeneratorWithSameNamedMocks.c +42 -0
  810. data/vendor/cmock/vendor/unity/test/testdata/uart/MockConfig.h +19 -0
  811. data/vendor/cmock/vendor/unity/test/tests/test_generate_test_runner.rb +78 -0
  812. data/vendor/cmock/vendor/unity/test/tests/test_unity_test_summary.rb +58 -0
  813. data/vendor/diy/lib/diy/factory.rb +5 -4
  814. data/vendor/diy/lib/diy.rb +5 -4
  815. data/vendor/diy/sample_code/car.rb +5 -4
  816. data/vendor/diy/sample_code/chassis.rb +5 -4
  817. data/vendor/diy/sample_code/diy_example.rb +5 -4
  818. data/vendor/diy/sample_code/engine.rb +5 -4
  819. data/vendor/diy/sample_code/objects.yml +5 -4
  820. data/vendor/diy/test/constructor.rb +5 -4
  821. data/vendor/diy/test/diy_test.rb +5 -4
  822. data/vendor/diy/test/factory_test.rb +5 -4
  823. data/vendor/diy/test/files/broken_construction.yml +5 -4
  824. data/vendor/diy/test/files/cat/cat.rb +5 -4
  825. data/vendor/diy/test/files/cat/extra_conflict.yml +5 -4
  826. data/vendor/diy/test/files/cat/heritage.rb +5 -4
  827. data/vendor/diy/test/files/cat/needs_input.yml +5 -4
  828. data/vendor/diy/test/files/cat/the_cat_lineage.rb +5 -4
  829. data/vendor/diy/test/files/dog/dog_model.rb +5 -4
  830. data/vendor/diy/test/files/dog/dog_presenter.rb +5 -4
  831. data/vendor/diy/test/files/dog/dog_view.rb +5 -4
  832. data/vendor/diy/test/files/dog/file_resolver.rb +5 -4
  833. data/vendor/diy/test/files/dog/other_thing.rb +5 -4
  834. data/vendor/diy/test/files/dog/simple.yml +5 -4
  835. data/vendor/diy/test/files/donkey/foo/bar/qux.rb +5 -4
  836. data/vendor/diy/test/files/donkey/foo.rb +5 -4
  837. data/vendor/diy/test/files/factory/beef.rb +5 -4
  838. data/vendor/diy/test/files/factory/dog.rb +5 -4
  839. data/vendor/diy/test/files/factory/factory.yml +5 -4
  840. data/vendor/diy/test/files/factory/farm/llama.rb +5 -4
  841. data/vendor/diy/test/files/factory/farm/pork.rb +5 -4
  842. data/vendor/diy/test/files/factory/kitten.rb +5 -4
  843. data/vendor/diy/test/files/fud/objects.yml +5 -4
  844. data/vendor/diy/test/files/fud/toy.rb +5 -4
  845. data/vendor/diy/test/files/functions/attached_things_builder.rb +5 -4
  846. data/vendor/diy/test/files/functions/invalid_method.yml +5 -4
  847. data/vendor/diy/test/files/functions/method_extractor.rb +5 -4
  848. data/vendor/diy/test/files/functions/nonsingleton_objects.yml +5 -4
  849. data/vendor/diy/test/files/functions/objects.yml +5 -4
  850. data/vendor/diy/test/files/functions/thing.rb +5 -4
  851. data/vendor/diy/test/files/functions/thing_builder.rb +5 -4
  852. data/vendor/diy/test/files/functions/things_builder.rb +5 -4
  853. data/vendor/diy/test/files/gnu/objects.yml +5 -4
  854. data/vendor/diy/test/files/gnu/thinger.rb +5 -4
  855. data/vendor/diy/test/files/goat/base.rb +5 -4
  856. data/vendor/diy/test/files/goat/can.rb +5 -4
  857. data/vendor/diy/test/files/goat/goat.rb +5 -4
  858. data/vendor/diy/test/files/goat/objects.yml +5 -4
  859. data/vendor/diy/test/files/goat/paper.rb +5 -4
  860. data/vendor/diy/test/files/goat/plane.rb +5 -4
  861. data/vendor/diy/test/files/goat/shirt.rb +5 -4
  862. data/vendor/diy/test/files/goat/wings.rb +5 -4
  863. data/vendor/diy/test/files/horse/holder_thing.rb +5 -4
  864. data/vendor/diy/test/files/horse/objects.yml +5 -4
  865. data/vendor/diy/test/files/namespace/animal/bird.rb +5 -4
  866. data/vendor/diy/test/files/namespace/animal/cat.rb +5 -4
  867. data/vendor/diy/test/files/namespace/animal/reptile/hardshell/turtle.rb +5 -4
  868. data/vendor/diy/test/files/namespace/animal/reptile/lizard.rb +5 -4
  869. data/vendor/diy/test/files/namespace/bad_module_specified.yml +5 -4
  870. data/vendor/diy/test/files/namespace/class_name_combine.yml +5 -4
  871. data/vendor/diy/test/files/namespace/no_module_specified.yml +5 -4
  872. data/vendor/diy/test/files/namespace/objects.yml +5 -4
  873. data/vendor/diy/test/files/namespace/road.rb +5 -4
  874. data/vendor/diy/test/files/namespace/sky.rb +5 -4
  875. data/vendor/diy/test/files/namespace/subcontext.yml +5 -4
  876. data/vendor/diy/test/files/non_singleton/air.rb +5 -4
  877. data/vendor/diy/test/files/non_singleton/fat_cat.rb +5 -4
  878. data/vendor/diy/test/files/non_singleton/objects.yml +5 -4
  879. data/vendor/diy/test/files/non_singleton/pig.rb +5 -4
  880. data/vendor/diy/test/files/non_singleton/thread_spinner.rb +5 -4
  881. data/vendor/diy/test/files/non_singleton/tick.rb +5 -4
  882. data/vendor/diy/test/files/non_singleton/yard.rb +5 -4
  883. data/vendor/diy/test/files/yak/core_model.rb +5 -4
  884. data/vendor/diy/test/files/yak/core_presenter.rb +5 -4
  885. data/vendor/diy/test/files/yak/core_view.rb +5 -4
  886. data/vendor/diy/test/files/yak/data_source.rb +5 -4
  887. data/vendor/diy/test/files/yak/fringe_model.rb +5 -4
  888. data/vendor/diy/test/files/yak/fringe_presenter.rb +5 -4
  889. data/vendor/diy/test/files/yak/fringe_view.rb +5 -4
  890. data/vendor/diy/test/files/yak/giant_squid.rb +5 -4
  891. data/vendor/diy/test/files/yak/krill.rb +5 -4
  892. data/vendor/diy/test/files/yak/my_objects.yml +5 -4
  893. data/vendor/diy/test/files/yak/sub_sub_context_test.yml +5 -4
  894. data/vendor/diy/test/test_helper.rb +5 -4
  895. data/vendor/unity/auto/generate_module.rb +4 -4
  896. data/vendor/unity/auto/generate_test_runner.rb +5 -1
  897. data/vendor/unity/docs/UnityHelperScriptsGuide.md +9 -0
  898. data/vendor/unity/test/spec/generate_module_naming_spec.rb +38 -0
  899. data/vendor/unity/test/testdata/spi/MockConfig.h +19 -0
  900. data/vendor/unity/test/testdata/testRunnerGeneratorWithSameNamedMocks.c +42 -0
  901. data/vendor/unity/test/testdata/uart/MockConfig.h +19 -0
  902. data/vendor/unity/test/tests/test_generate_test_runner.rb +29 -0
  903. metadata +770 -285
  904. data/assets/tests_with_fallback_conditionals/src/conditional_module.c +0 -18
  905. data/bin/actions_wrapper.rb +0 -51
  906. data/docs/mkdocs/assets/images/ceedling-logo-circle.png +0 -0
  907. data/docs/mkdocs/assets/images/ceedling.svg +0 -90
  908. data/docs/mkdocs/assets/images/favicon.png +0 -0
  909. data/docs/mkdocs/assets/stylesheets/admonitions.css +0 -152
  910. data/docs/mkdocs/assets/stylesheets/fixes-local.css +0 -15
  911. data/docs/mkdocs/assets/stylesheets/styling.css +0 -102
  912. data/docs/mkdocs/configuration/environment-vars.md +0 -14
  913. data/docs/mkdocs/configuration/global-collections.md +0 -156
  914. data/docs/mkdocs/configuration/index.md +0 -75
  915. data/docs/mkdocs/configuration/loading.md +0 -89
  916. data/docs/mkdocs/configuration/mixins.md +0 -607
  917. data/docs/mkdocs/configuration/parallel-builds.md +0 -97
  918. data/docs/mkdocs/configuration/project-file.md +0 -216
  919. data/docs/mkdocs/configuration/reference/cexception.md +0 -35
  920. data/docs/mkdocs/configuration/reference/cmock.md +0 -106
  921. data/docs/mkdocs/configuration/reference/defines.md +0 -352
  922. data/docs/mkdocs/configuration/reference/environment.md +0 -55
  923. data/docs/mkdocs/configuration/reference/extension.md +0 -63
  924. data/docs/mkdocs/configuration/reference/files.md +0 -154
  925. data/docs/mkdocs/configuration/reference/flags.md +0 -296
  926. data/docs/mkdocs/configuration/reference/index.md +0 -176
  927. data/docs/mkdocs/configuration/reference/libraries.md +0 -82
  928. data/docs/mkdocs/configuration/reference/mixins.md +0 -24
  929. data/docs/mkdocs/configuration/reference/partials.md +0 -38
  930. data/docs/mkdocs/configuration/reference/paths.md +0 -276
  931. data/docs/mkdocs/configuration/reference/plugins.md +0 -60
  932. data/docs/mkdocs/configuration/reference/project.md +0 -333
  933. data/docs/mkdocs/configuration/reference/release-build.md +0 -62
  934. data/docs/mkdocs/configuration/reference/test-build.md +0 -55
  935. data/docs/mkdocs/configuration/reference/test-runner.md +0 -61
  936. data/docs/mkdocs/configuration/reference/tools.md +0 -457
  937. data/docs/mkdocs/configuration/reference/unity.md +0 -49
  938. data/docs/mkdocs/configuration/which-ceedling.md +0 -77
  939. data/docs/mkdocs/development/index.md +0 -50
  940. data/docs/mkdocs/development/plugins/configuration.md +0 -164
  941. data/docs/mkdocs/development/plugins/index.md +0 -84
  942. data/docs/mkdocs/development/plugins/plugin-subclass.md +0 -513
  943. data/docs/mkdocs/development/plugins/rake-tasks.md +0 -54
  944. data/docs/mkdocs/development/workflow.md +0 -284
  945. data/docs/mkdocs/getting-started/command-line.md +0 -477
  946. data/docs/mkdocs/getting-started/example-projects/cipher-quest.md +0 -65
  947. data/docs/mkdocs/getting-started/example-projects/index.md +0 -49
  948. data/docs/mkdocs/getting-started/example-projects/temp-sensor.md +0 -60
  949. data/docs/mkdocs/getting-started/example-projects/wondrous-forest.md +0 -45
  950. data/docs/mkdocs/getting-started/index.md +0 -41
  951. data/docs/mkdocs/getting-started/installation.md +0 -179
  952. data/docs/mkdocs/getting-started/quick-start.md +0 -86
  953. data/docs/mkdocs/help.md +0 -49
  954. data/docs/mkdocs/index.md +0 -222
  955. data/docs/mkdocs/overview/build-system.md +0 -115
  956. data/docs/mkdocs/overview/index.md +0 -29
  957. data/docs/mkdocs/overview/test-environments.md +0 -33
  958. data/docs/mkdocs/overview/tools-and-frameworks.md +0 -115
  959. data/docs/mkdocs/plugins/beep.md +0 -134
  960. data/docs/mkdocs/plugins/bullseye.md +0 -83
  961. data/docs/mkdocs/plugins/command-hooks.md +0 -268
  962. data/docs/mkdocs/plugins/compile-commands-json-db.md +0 -42
  963. data/docs/mkdocs/plugins/cppcheck.md +0 -377
  964. data/docs/mkdocs/plugins/dependencies.md +0 -310
  965. data/docs/mkdocs/plugins/fff.md +0 -247
  966. data/docs/mkdocs/plugins/gcov/examples.md +0 -92
  967. data/docs/mkdocs/plugins/gcov/gcovr.md +0 -412
  968. data/docs/mkdocs/plugins/gcov/index.md +0 -74
  969. data/docs/mkdocs/plugins/gcov/overview.md +0 -145
  970. data/docs/mkdocs/plugins/gcov/reportgenerator.md +0 -140
  971. data/docs/mkdocs/plugins/gcov/reporting.md +0 -147
  972. data/docs/mkdocs/plugins/gcov/setup.md +0 -232
  973. data/docs/mkdocs/plugins/gcov/tool-versions.md +0 -60
  974. data/docs/mkdocs/plugins/gcov/troubleshooting.md +0 -78
  975. data/docs/mkdocs/plugins/index.md +0 -261
  976. data/docs/mkdocs/plugins/module-generator.md +0 -267
  977. data/docs/mkdocs/plugins/report-build-warnings-log.md +0 -42
  978. data/docs/mkdocs/plugins/report-tests-gtestlike-stdout.md +0 -98
  979. data/docs/mkdocs/plugins/report-tests-ide-stdout.md +0 -63
  980. data/docs/mkdocs/plugins/report-tests-log-factory.md +0 -454
  981. data/docs/mkdocs/plugins/report-tests-pretty-stdout.md +0 -56
  982. data/docs/mkdocs/plugins/report-tests-raw-output-log.md +0 -52
  983. data/docs/mkdocs/plugins/report-tests-teamcity-stdout.md +0 -96
  984. data/docs/mkdocs/plugins/sample_html_report.png +0 -0
  985. data/docs/mkdocs/plugins/valgrind.md +0 -198
  986. data/docs/mkdocs/project/release-history.md +0 -61
  987. data/docs/mkdocs/project/upgrade.md +0 -85
  988. data/docs/mkdocs/reference/build-directives.md +0 -37
  989. data/docs/mkdocs/reference/command-line.md +0 -323
  990. data/docs/mkdocs/reference/environment-vars.md +0 -60
  991. data/docs/mkdocs/reference/gcov-plugin.md +0 -600
  992. data/docs/mkdocs/reference/global-collections.md +0 -160
  993. data/docs/mkdocs/reference/index.md +0 -65
  994. data/docs/mkdocs/reference/partials-macros.md +0 -79
  995. data/docs/mkdocs/reference/project-configuration.md +0 -46
  996. data/docs/mkdocs/snapshot/assets/project.yml +0 -404
  997. data/docs/mkdocs/snapshot/examples/cipher_quest/README.md +0 -210
  998. data/docs/mkdocs/snapshot/examples/temp_sensor/README.md +0 -283
  999. data/docs/mkdocs/snapshot/examples/wondrous_forest/README.md +0 -92
  1000. data/docs/mkdocs/snapshot/plugins/gcov/config/defaults.yml +0 -32
  1001. data/docs/mkdocs/snapshot/plugins/gcov/config/defaults_gcov.rb +0 -136
  1002. data/docs/mkdocs/snapshot.yml +0 -20
  1003. data/docs/mkdocs/testing-guide/build-directives.md +0 -153
  1004. data/docs/mkdocs/testing-guide/conventions.md +0 -616
  1005. data/docs/mkdocs/testing-guide/frameworks.md +0 -192
  1006. data/docs/mkdocs/testing-guide/index.md +0 -80
  1007. data/docs/mkdocs/testing-guide/partials/configuration.md +0 -67
  1008. data/docs/mkdocs/testing-guide/partials/conventions.md +0 -68
  1009. data/docs/mkdocs/testing-guide/partials/directives.md +0 -212
  1010. data/docs/mkdocs/testing-guide/partials/example.md +0 -149
  1011. data/docs/mkdocs/testing-guide/partials/index.md +0 -88
  1012. data/docs/mkdocs/testing-guide/partials/overview.md +0 -81
  1013. data/docs/mkdocs/testing-guide/partials/variables.md +0 -244
  1014. data/docs/mkdocs/testing-guide/test-cases.md +0 -194
  1015. data/docs/mkdocs/testing-guide/test-sample.md +0 -94
  1016. data/docs/mkdocs/testing-guide/test-suite-anatomy.md +0 -58
  1017. data/lib/ceedling/cacheinator.rb +0 -53
  1018. data/lib/ceedling/cacheinator_helper.rb +0 -60
  1019. data/lib/ceedling/dependinator.rb +0 -31
  1020. data/lib/ceedling/makefile.rb +0 -52
  1021. data/lib/ceedling/release_invoker.rb +0 -112
  1022. data/lib/ceedling/rules_release.rake +0 -109
  1023. data/lib/ceedling/rules_tests.rake +0 -40
  1024. data/lib/ceedling/tasks_release.rake +0 -36
  1025. data/plugins/fff/vendor/fff/Makefile +0 -10
  1026. data/plugins/fff/vendor/fff/buildandtest +0 -15
  1027. data/plugins/fff/vendor/fff/examples/Makefile +0 -7
  1028. data/plugins/fff/vendor/fff/examples/driver_testing/Makefile +0 -64
  1029. data/plugins/fff/vendor/fff/examples/driver_testing/driver.c +0 -32
  1030. data/plugins/fff/vendor/fff/examples/driver_testing/driver.h +0 -21
  1031. data/plugins/fff/vendor/fff/examples/driver_testing/driver.test.cpp +0 -58
  1032. data/plugins/fff/vendor/fff/examples/driver_testing/driver.test.fff.cpp +0 -70
  1033. data/plugins/fff/vendor/fff/examples/driver_testing/hardware_abstraction.h +0 -25
  1034. data/plugins/fff/vendor/fff/examples/driver_testing/registers.h +0 -23
  1035. data/plugins/fff/vendor/fff/examples/embedded_ui/DISPLAY.h +0 -27
  1036. data/plugins/fff/vendor/fff/examples/embedded_ui/Kata.txt +0 -25
  1037. data/plugins/fff/vendor/fff/examples/embedded_ui/Makefile +0 -67
  1038. data/plugins/fff/vendor/fff/examples/embedded_ui/SYSTEM.h +0 -31
  1039. data/plugins/fff/vendor/fff/examples/embedded_ui/UI.c +0 -56
  1040. data/plugins/fff/vendor/fff/examples/embedded_ui/UI.h +0 -22
  1041. data/plugins/fff/vendor/fff/examples/embedded_ui/UI_test_ansic.c +0 -191
  1042. data/plugins/fff/vendor/fff/examples/embedded_ui/UI_test_cpp.cpp +0 -144
  1043. data/plugins/fff/vendor/fff/examples/embedded_ui/test_suite_template.c +0 -42
  1044. data/plugins/fff/vendor/fff/gtest/Makefile +0 -22
  1045. data/plugins/fff/vendor/fff/gtest/gtest-all.cc +0 -9118
  1046. data/plugins/fff/vendor/fff/gtest/gtest-main.cc +0 -6
  1047. data/plugins/fff/vendor/fff/gtest/gtest.h +0 -19547
  1048. data/plugins/fff/vendor/fff/test/Makefile +0 -81
  1049. data/plugins/fff/vendor/fff/test/c_test_framework.h +0 -25
  1050. data/plugins/fff/vendor/fff/test/fff_test_c.c +0 -116
  1051. data/plugins/fff/vendor/fff/test/fff_test_cpp.cpp +0 -53
  1052. data/plugins/fff/vendor/fff/test/fff_test_global_c.c +0 -84
  1053. data/plugins/fff/vendor/fff/test/fff_test_global_cpp.cpp +0 -31
  1054. data/plugins/fff/vendor/fff/test/global_fakes.c +0 -21
  1055. data/plugins/fff/vendor/fff/test/global_fakes.h +0 -47
  1056. data/plugins/fff/vendor/fff/test/test_cases.include +0 -276
  1057. data/plugins/report_tests_gtestlike_stdout/assets/template.erb +0 -83
  1058. data/spec/units/configurator_spec.rb +0 -232
  1059. /data/assets/{ceedling → features/ceedling} +0 -0
  1060. /data/assets/{ceedling.cmd → features/ceedling.cmd} +0 -0
  1061. /data/assets/{default_gitignore → features/default_gitignore} +0 -0
  1062. /data/assets/{broken_uncovered_file.c → fixtures/broken_uncovered_file.c} +0 -0
  1063. /data/assets/{example_file.c → fixtures/example_file.c} +0 -0
  1064. /data/assets/{example_file.h → fixtures/example_file.h} +0 -0
  1065. /data/assets/{example_file_call.c → fixtures/example_file_call.c} +0 -0
  1066. /data/assets/{example_file_call.h → fixtures/example_file_call.h} +0 -0
  1067. /data/assets/{example_file_with_statics.c → fixtures/example_file_with_statics.c} +0 -0
  1068. /data/assets/{example_file_with_stdio.c → fixtures/example_file_with_stdio.c} +0 -0
  1069. /data/assets/{example_file_with_stdio.h → fixtures/example_file_with_stdio.h} +0 -0
  1070. /data/assets/{fake_crash_test_fixture.rb → fixtures/fake_crash_test_fixture.rb} +0 -0
  1071. /data/assets/{partial_all_module.h → fixtures/partial_all_module.h} +0 -0
  1072. /data/assets/{run_with_ubsan.rb → fixtures/run_with_ubsan.rb} +0 -0
  1073. /data/assets/{same_dir_pairing_module.c → fixtures/same_dir_pairing_module.c} +0 -0
  1074. /data/assets/{same_dir_pairing_module.h → fixtures/same_dir_pairing_module.h} +0 -0
  1075. /data/assets/{same_dir_pairing_module_func.h → fixtures/same_dir_pairing_module_func.h} +0 -0
  1076. /data/assets/{same_dir_pairing_other.c → fixtures/same_dir_pairing_other.c} +0 -0
  1077. /data/assets/{same_dir_pairing_other.h → fixtures/same_dir_pairing_other.h} +0 -0
  1078. /data/assets/{test_example_file.c → fixtures/test_example_file.c} +0 -0
  1079. /data/assets/{test_example_file_2.c → fixtures/test_example_file_2.c} +0 -0
  1080. /data/assets/{test_example_file_source_include.c → fixtures/test_example_file_source_include.c} +0 -0
  1081. /data/assets/{test_example_file_success.c → fixtures/test_example_file_success.c} +0 -0
  1082. /data/assets/{test_example_file_unity_printf.c → fixtures/test_example_file_unity_printf.c} +0 -0
  1083. /data/assets/{test_example_file_verbose.c → fixtures/test_example_file_verbose.c} +0 -0
  1084. /data/assets/{test_example_file_with_mock.c → fixtures/test_example_file_with_mock.c} +0 -0
  1085. /data/assets/{test_example_file_with_stdio.c → fixtures/test_example_file_with_stdio.c} +0 -0
  1086. /data/assets/{test_example_with_parameterized_tests.c → fixtures/test_example_with_parameterized_tests.c} +0 -0
  1087. /data/assets/{test_partial_all_module.c → fixtures/test_partial_all_module.c} +0 -0
  1088. /data/assets/{test_same_dir_pairing.c → fixtures/test_same_dir_pairing.c} +0 -0
  1089. /data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/feature_config.h +0 -0
  1090. /data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/feature_extra.h +0 -0
  1091. /data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/local_flag_extra.h +0 -0
  1092. /data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/nested_extra.h +0 -0
  1093. /data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/nested_wrapper.h +0 -0
  1094. /data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/project_flag_extra.h +0 -0
  1095. /data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/widget_feature.h +0 -0
  1096. /data/assets/{tests_with_defines → fixtures/tests_with_defines}/src/adc_hardware.c +0 -0
  1097. /data/assets/{tests_with_defines → fixtures/tests_with_defines}/src/adc_hardware.h +0 -0
  1098. /data/assets/{tests_with_defines → fixtures/tests_with_defines}/src/adc_hardware_configurator.c +0 -0
  1099. /data/assets/{tests_with_defines → fixtures/tests_with_defines}/src/adc_hardware_configurator.h +0 -0
  1100. /data/assets/{tests_with_defines → fixtures/tests_with_defines}/test/test_adc_hardware.c +0 -0
  1101. /data/assets/{tests_with_defines → fixtures/tests_with_defines}/test/test_adc_hardware_special.c +0 -0
  1102. /data/assets/{tests_with_encoding → fixtures/tests_with_encoding}/src/unicoder.c +0 -0
  1103. /data/assets/{tests_with_encoding → fixtures/tests_with_encoding}/src/unicoder.h +0 -0
  1104. /data/assets/{tests_with_encoding → fixtures/tests_with_encoding}/test/test_unicoder.c +0 -0
  1105. /data/assets/{tests_with_encoding → fixtures/tests_with_encoding}/test/test_unicoder_partial.c +0 -0
  1106. /data/assets/{tests_with_fallback_conditionals → fixtures/tests_with_fallback_conditionals}/src/conditional_module.h +0 -0
  1107. /data/assets/{tests_with_fallback_conditionals → fixtures/tests_with_fallback_conditionals}/src/optional_dep.h +0 -0
  1108. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/src/blanks.c +0 -0
  1109. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/src/blanks.h +0 -0
  1110. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/src/counter.c +0 -0
  1111. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/src/counter.h +0 -0
  1112. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/src/decorators.c +0 -0
  1113. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/src/decorators.h +0 -0
  1114. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/test/test_blanks.c +0 -0
  1115. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/test/test_counter.c +0 -0
  1116. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/test/test_decorators.c +0 -0
  1117. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardwareA.c +0 -0
  1118. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardwareA.h +0 -0
  1119. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardwareB.c +0 -0
  1120. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardwareB.h +0 -0
  1121. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardwareC.c +0 -0
  1122. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardwareC.h +0 -0
  1123. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardware_configuratorA.h +0 -0
  1124. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardware_configuratorB.h +0 -0
  1125. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardware_configuratorC.h +0 -0
  1126. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/test/test_adc_hardwareA.c +0 -0
  1127. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/test/test_adc_hardwareB.c +0 -0
  1128. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/test/test_adc_hardwareC.c +0 -0
  1129. /data/assets/{uncovered_example_file.c → fixtures/uncovered_example_file.c} +0 -0
  1130. /data/plugins/bullseye/assets/{template.erb → coverage.template} +0 -0
@@ -8,10 +8,12 @@
8
8
  require 'ceedling/constants'
9
9
  require 'ceedling/exceptions'
10
10
  require 'ceedling/test_invoker/test_invoker_types'
11
+ require 'ceedling/test_invoker/test_pipeline_helpers'
11
12
 
12
13
  class TestBuildExecutor
13
14
 
14
15
  include TestInvokerTypes
16
+ include TestPipelineHelpers
15
17
 
16
18
  constructor(
17
19
  :configurator,
@@ -19,270 +21,80 @@ class TestBuildExecutor
19
21
  :reportinator,
20
22
  :batchinator,
21
23
  :preprocessinator,
22
- :partializer,
23
24
  :generator,
24
- :test_context_extractor,
25
25
  :plugin_manager,
26
26
  :file_path_utils,
27
27
  :file_finder,
28
- :file_wrapper
28
+ :file_wrapper,
29
+ :dependinator,
30
+ :gcc_dependency_parser,
31
+ :quote_include_isolator,
32
+ :generator_helper
29
33
  )
30
34
 
31
- def setup()
32
- @context_extractor = @test_context_extractor
33
- end
34
-
35
- # Stage 6: Preprocess partial header files for extract-and-generate pass.
36
- def stage_preprocess_partial_headers(state)
37
- directives_only = @configurator.test_build_preprocess_directives_only_available
38
-
39
- # Generate directive-only preprocessor output if available
40
- @batchinator.exec(workload: :compile, things: state.partials_headers) do |details|
41
- config = details[:config]
42
- testable = details[:testable]
43
- name = testable.name
44
-
45
- arg_hash = {
46
- filepath: config.filepath,
47
- test: name,
48
- flags: testable.preprocess_flags,
49
- include_paths: testable.search_paths,
50
- vendor_paths: [@configurator.project_build_vendor_ceedling_path],
51
- defines: testable.preprocess_defines
52
- }
53
-
54
- details[:directives_only_filepath] = @preprocessinator.generate_directives_only_output( **arg_hash )
55
- end if directives_only
56
-
57
- # Preprocess and assemble header files
58
- @batchinator.exec(workload: :compile, things: state.partials_headers) do |details|
59
- config = details[:config]
60
- testable = details[:testable]
61
- name = testable.name
62
- directives_only_filepath = details[:directives_only_filepath]
63
-
64
- arg_hash = {
65
- test: name,
66
- filepath: config.filepath,
67
- directives_only_filepath: directives_only_filepath,
68
- fallback: (!directives_only or directives_only_filepath.nil?),
69
- flags: testable.preprocess_flags,
70
- include_paths: testable.search_paths,
71
- vendor_paths: [@configurator.project_build_vendor_ceedling_path],
72
- defines: testable.preprocess_defines
73
- }
74
-
75
- config.directives_only_filepath, config.includes = @preprocessinator.preprocess_partial_header_file_preserve_macros( **arg_hash )
76
- end
77
-
78
- # Full-preprocess partial header files for expanded signature extraction.
79
- @batchinator.exec(workload: :compile, things: state.partials_headers) do |details|
80
- config = details[:config]
81
- testable = details[:testable]
82
- name = testable.name
83
-
84
- arg_hash = {
85
- filepath: config.filepath,
86
- test: name,
87
- flags: testable.preprocess_flags,
88
- include_paths: testable.search_paths,
89
- vendor_paths: [@configurator.project_build_vendor_ceedling_path],
90
- defines: testable.preprocess_defines
91
- }
92
-
93
- config.full_expansion_filepath = @preprocessinator.preprocess_partial_header_expand_macros( **arg_hash )
94
- end
95
- end
96
-
97
- # Stage 7: Preprocess partial source files for extract-and-generate pass.
98
- def stage_preprocess_partial_sources(state)
99
- directives_only = @configurator.test_build_preprocess_directives_only_available
100
-
101
- # Generate directive-only preprocessor output if available
102
- @batchinator.exec(workload: :compile, things: state.partials_sources) do |details|
103
- config = details[:config]
104
- testable = details[:testable]
105
- name = testable.name
106
-
107
- arg_hash = {
108
- filepath: config.filepath,
109
- test: name,
110
- flags: testable.preprocess_flags,
111
- include_paths: testable.search_paths,
112
- vendor_paths: [@configurator.project_build_vendor_ceedling_path],
113
- defines: testable.preprocess_defines
114
- }
115
-
116
- details[:directives_only_filepath] = @preprocessinator.generate_directives_only_output( **arg_hash )
117
- end if directives_only
118
-
119
- # Preprocess and assemble source files
120
- @batchinator.exec(workload: :compile, things: state.partials_sources) do |details|
121
- config = details[:config]
122
- testable = details[:testable]
123
- name = testable.name
124
- directives_only_filepath = details[:directives_only_filepath]
125
-
126
- arg_hash = {
127
- test: name,
128
- filepath: config.filepath,
129
- directives_only_filepath: directives_only_filepath,
130
- fallback: (!directives_only or directives_only_filepath.nil?),
131
- flags: testable.preprocess_flags,
132
- include_paths: testable.search_paths,
133
- vendor_paths: [@configurator.project_build_vendor_ceedling_path],
134
- defines: testable.preprocess_defines
135
- }
136
-
137
- config.directives_only_filepath, config.includes = @preprocessinator.preprocess_partial_source_file_preserve_macros( **arg_hash )
138
- end
139
-
140
- # Full-preprocess partial source files for expanded signature extraction.
141
- @batchinator.exec(workload: :compile, things: state.partials_sources) do |details|
142
- config = details[:config]
143
- testable = details[:testable]
144
- name = testable.name
145
-
146
- arg_hash = {
147
- filepath: config.filepath,
148
- test: name,
149
- flags: testable.preprocess_flags,
150
- include_paths: testable.search_paths,
151
- vendor_paths: [@configurator.project_build_vendor_ceedling_path],
152
- defines: testable.preprocess_defines
153
- }
154
-
155
- config.full_expansion_filepath = @preprocessinator.preprocess_partial_source_expand_macros( **arg_hash )
156
- end
157
- end
158
-
159
- # Stage 8: Extract and generate partial implementation and interface files.
160
- def stage_generate_partials(state)
35
+ # Stage 9: Preprocess header files to be mocked.
36
+ def stage_preprocess_mocks(state)
161
37
  directives_only = @configurator.test_build_preprocess_directives_only_available
162
-
163
- partials = []
164
- state.testables.each do |_, testable|
165
- next if testable.partials.configs.empty?
166
- testable.partials.configs.each do |_, config|
167
- partials << { config: config, testable: testable }
168
- end
169
- end
170
-
171
- @batchinator.exec(workload: :compile, things: partials) do |partial|
172
- config = partial[:config]
173
- testable = partial[:testable]
174
- name = testable.name
175
-
176
- module_contents = @partializer.extract_module_contents(
177
- name,
178
- config,
179
- !directives_only
38
+ skipped = 0
39
+
40
+ # Register every mock's preprocessed-header target and settle its staleness
41
+ # up front (sequentially -- cheap, no subprocess work), since it gates both
42
+ # of the parallel batches below.
43
+ state.mocks_list.each do |mock|
44
+ details = mock.details
45
+ testable = mock.testable
46
+
47
+ # A Partial mock's own generated header is already free of inline function
48
+ # bodies, so it never needs this extra pass regardless of what the project
49
+ # configures for CMock's own mocks of real headers elsewhere.
50
+ extras = !details.partial && (@configurator.cmock_treat_inlines == :include)
51
+
52
+ target = @file_path_utils.form_preprocessed_file_filepath( details.source, testable.name )
53
+
54
+ @dependinator.register(
55
+ target,
56
+ files: [details.source],
57
+ meta: {
58
+ flags: testable.preprocess_flags,
59
+ defines: testable.preprocess_defines,
60
+ search_paths: testable.search_paths,
61
+ extras: extras,
62
+ tools: [@configurator.tools_test_bare_includes_preprocessor, @configurator.tools_test_file_directives_only_preprocessor],
63
+ preprocess_force_fallback: @configurator.test_build_preprocess_force_fallback
64
+ }
180
65
  )
181
66
 
182
- @partializer.validate_config( c_module: module_contents, config: config, name: name )
183
-
184
- @partializer.sanitize( module_contents )
67
+ mock.preprocessed_target = target
68
+ mock.stale = @dependinator.stale?( target )
185
69
 
186
- # Generated once and shared by the implementation and interface headers below (via
187
- # their own includes lists), so a module tested and mocked in the same test file gets
188
- # exactly one C definition of each of its typedefs and aggregate types.
189
- types_header = @generator.generate_partial_types(
190
- name: config.module, # Module name, not test name -- two modules Partialed
191
- # in the same test file must not collide on one
192
- # shared types header filename
193
- c_module: module_contents,
194
- output_path: testable.paths[:partials]
195
- )
196
-
197
- implementation = @partializer.extract_implementation_functions(
198
- test: name,
199
- partial: config.module,
200
- definitions: module_contents.function_definitions,
201
- config: config
202
- )
70
+ next if mock.stale
203
71
 
204
- interface = @partializer.extract_interface_functions(
205
- test: name,
206
- partial: config.module,
207
- definitions: module_contents.function_definitions,
208
- declarations: module_contents.function_declarations,
209
- config: config
210
- )
211
-
212
- @partializer.validate_extracted_functions(
213
- name: name,
214
- partial: config.module,
215
- impl: implementation,
216
- interface: interface
72
+ msg = @reportinator.generate_module_progress(
73
+ operation: 'Skipping mock preprocessing for',
74
+ module_name: testable.name,
75
+ filename: File.basename( details.source )
217
76
  )
218
-
219
- arg_hash = {
220
- test: name,
221
- partial: config.module,
222
- function_definitions: implementation,
223
- c_module: module_contents,
224
- header_includes: @partializer.remap_implementation_header_includes(
225
- name: config.module,
226
- includes: (config.source.includes + config.header.includes),
227
- partials: testable.partials.configs,
228
- types_header: types_header,
229
- test: name
230
- ),
231
- source_includes: @partializer.remap_implementation_source_includes(
232
- name: config.module,
233
- includes: (config.source.includes + config.header.includes),
234
- partials: testable.partials.configs,
235
- test: name
236
- ),
237
- input_filepath: config.source.filepath,
238
- output_path: testable.paths[:partials]
239
- }
240
-
241
- unless implementation.nil?
242
- @generator.generate_partial_implementation( **arg_hash )
243
- state.lock.synchronize { testable.partials.tests << config.module }
244
- end
245
-
246
- arg_hash = {
247
- test: name,
248
- partial: config.module,
249
- function_declarations: interface,
250
- includes: @partializer.remap_interface_header_includes(
251
- name: config.module,
252
- includes: (config.source.includes + config.header.includes),
253
- partials: testable.partials.configs,
254
- types_header: types_header,
255
- test: name
256
- ),
257
- c_module: module_contents,
258
- input_filepath: config.header.filepath,
259
- output_path: testable.paths[:partials]
260
- }
261
-
262
- unless interface.nil?
263
- @generator.generate_partial_interface( **arg_hash )
264
- state.lock.synchronize { testable.partials.mocks << config.module }
265
- end
77
+ @loginator.log( msg, Verbosity::OBNOXIOUS )
78
+ skipped += 1
266
79
  end
267
- end
268
80
 
269
- # Stage 9: Preprocess header files to be mocked.
270
- def stage_preprocess_mocks(state)
271
- directives_only = @configurator.test_build_preprocess_directives_only_available
81
+ log_skip_summary( task: "mock preprocessing", count: skipped, noun: "mocks" )
272
82
 
273
83
  # Generate directive-only preprocessor output if available
274
84
  @batchinator.exec(workload: :compile, things: state.mocks_list) do |mock|
275
- details = mock[:details]
276
- testable = mock[:testable]
85
+ next unless mock.stale
86
+
87
+ details = mock.details
88
+ testable = mock.testable
277
89
  name = testable.name
278
- filepath = details[:source]
90
+ filepath = details.source
279
91
 
280
92
  arg_hash = {
281
93
  filepath: filepath,
282
94
  test: name,
283
95
  flags: testable.preprocess_flags,
284
96
  include_paths: testable.search_paths,
285
- vendor_paths: [@configurator.project_build_vendor_ceedling_path],
97
+ vendor_paths: vendor_search_paths(),
286
98
  defines: testable.preprocess_defines
287
99
  }
288
100
 
@@ -293,199 +105,371 @@ class TestBuildExecutor
293
105
  @loginator.log( msg, Verbosity::COMPLAIN )
294
106
  end
295
107
 
296
- mock[:directives_only_filepath] = _filepath
108
+ mock.directives_only_filepath = _filepath
297
109
  end if directives_only
298
110
 
299
111
  # Preprocess and assemble header files to be mocked
300
112
  @batchinator.exec(workload: :compile, things: state.mocks_list) do |mock|
301
- details = mock[:details]
302
- testable = mock[:testable]
303
- directives_only_filepath = mock[:directives_only_filepath]
113
+ next unless mock.stale
304
114
 
305
- extras = (@configurator.cmock_treat_inlines == :include)
115
+ details = mock.details
116
+ testable = mock.testable
117
+ directives_only_filepath = mock.directives_only_filepath
118
+ extras = !details.partial && (@configurator.cmock_treat_inlines == :include)
306
119
 
307
120
  arg_hash = {
308
121
  test: testable.name,
309
- filepath: details[:source],
122
+ filepath: details.source,
310
123
  directives_only_filepath: directives_only_filepath,
311
- fallback: (!directives_only or directives_only_filepath.nil?),
124
+ fallback: directives_only_fallback?( directives_only, directives_only_filepath ),
312
125
  flags: testable.preprocess_flags,
313
126
  include_paths: testable.search_paths,
314
- vendor_paths: [@configurator.project_build_vendor_ceedling_path],
127
+ vendor_paths: vendor_search_paths(),
315
128
  defines: testable.preprocess_defines,
316
129
  extras: extras
317
130
  }
318
131
 
319
132
  @preprocessinator.preprocess_mockable_header_file( **arg_hash )
133
+
134
+ @dependinator.mark_fresh( mock.preprocessed_target )
320
135
  end
321
136
  end
322
137
 
323
138
  # Stage 10: Generate mocks for all tests.
324
139
  def stage_generate_mocks(state)
140
+ # get_cmock_config, not project_config_hash[:cmock]: project_config_hash is
141
+ # flattened -- CMock's own settings live there as individual top-level keys
142
+ # like :cmock_mock_prefix, not as a :cmock section -- so this is the only
143
+ # place that still holds CMock's configuration as a single value to compare.
144
+ cmock_meta = @configurator.get_cmock_config
145
+ skipped = 0
146
+
325
147
  @batchinator.exec(workload: :compile, things: state.mocks_list) do |mock|
326
- details = mock[:details]
327
- testable = mock[:testable]
148
+ details = mock.details
149
+ testable = mock.testable
328
150
 
329
- output_path = File.join( testable.paths[:mocks], details[:path] )
151
+ output_path = @file_path_utils.form_mock_output_path( testable.paths[:mocks], details.path )
152
+ folder, output_path = mock_folder_and_path( testable.paths[:mocks], output_path, details.include_path )
330
153
  @file_wrapper.mkdir( output_path )
331
154
 
155
+ # `details.input` -- not the stage 9 preprocessed target -- is the
156
+ # correct antecedent here: it's exactly what CMock reads, whether or not
157
+ # mock preprocessing is enabled for this project (see stage_determine_files).
158
+ #
159
+ # `details.name` (a String), not `mock.name` (the Symbol key T2 carried
160
+ # the same value in for hash lookups) -- needed here as a real filename.
161
+ target = File.join( output_path, details.name + EXTENSION_CORE_SOURCE )
162
+ mock_header = File.join( output_path, details.name + EXTENSION_CORE_HEADER )
163
+
164
+ # CMock writes `mock_header` in the same call as `target`, so the mock vouches for
165
+ # it as an output. Stage 4 places a stand-in at this exact path when no file is
166
+ # there or an earlier stand-in is out of date (StandinHeaderinator), independent of
167
+ # this mock's antecedents. The recorded hash catches a stand-in in the mock's place
168
+ # and regenerates the mock.
169
+ @dependinator.register( target, files: [details.input], meta: { cmock: cmock_meta }, outputs: [mock_header] )
170
+
171
+ unless @dependinator.stale?( target )
172
+ msg = @reportinator.generate_module_progress(
173
+ operation: 'Skipping mock generation for',
174
+ module_name: testable.name,
175
+ filename: details.name
176
+ )
177
+ @loginator.log( msg, Verbosity::OBNOXIOUS )
178
+ state.lock.synchronize { skipped += 1 }
179
+ next
180
+ end
181
+
182
+ # A Partial mock's own generated header is already free of inline function
183
+ # bodies -- CMock's own inline handling has nothing to do on it and is
184
+ # skipped for this one mock, independent of whatever the project configures
185
+ # for CMock's own mocks of real headers elsewhere in the same test suite.
186
+ overrides = details.partial ? { treat_inlines: :exclude } : {}
187
+
332
188
  arg_hash = {
333
189
  context: state.context,
334
- mock: mock[:name],
190
+ mock: mock.name,
335
191
  test: testable.name,
336
- input_filepath: details[:input],
337
- output_path: output_path
192
+ input_filepath: details.input,
193
+ output_path: output_path,
194
+ folder: folder,
195
+ overrides: overrides
338
196
  }
339
197
 
340
198
  @generator.generate_mock( **arg_hash )
341
- end
342
- end
343
-
344
- # Stage 11: Preprocess test files and extract source build directives.
345
- def stage_preprocess_test_files(state)
346
- directives_only = @configurator.test_build_preprocess_directives_only_available
347
-
348
- @batchinator.exec(workload: :compile, things: state.testables) do |_, testable|
349
- filepath = testable.filepath
350
- filename = File.basename( filepath )
351
- name = testable.name
352
- directives_only_filepath = testable.preprocess[:directives_only][:filepath]
353
-
354
- fallback = (!directives_only or directives_only_filepath.nil?)
355
-
356
- arg_hash = {
357
- test: name,
358
- filepath: filepath,
359
- directives_only_filepath: directives_only_filepath,
360
- fallback: fallback,
361
- includes: @context_extractor.lookup_all_header_includes_list( testable.filepath ),
362
- flags: testable.preprocess_flags,
363
- include_paths: testable.search_paths,
364
- vendor_paths: [@configurator.project_build_vendor_ceedling_path],
365
- defines: testable.preprocess_defines
366
- }
367
-
368
- _filepath = @preprocessinator.preprocess_test_file( **arg_hash )
369
-
370
- state.lock.synchronize { testable.runner[:input_filepath] = _filepath }
371
199
 
372
- msg = @reportinator.generate_progress( "Parsing #{filename} for test source directive macros" )
373
- @loginator.log( msg )
200
+ @dependinator.mark_fresh( target )
201
+ end
374
202
 
375
- if fallback
376
- _filepath = filepath
377
- else
378
- _filepath = @file_path_utils.form_preprocessed_file_compacted_directives_only_filepath( filepath, name )
379
- end
203
+ log_skip_summary( task: "mock generation", count: skipped, noun: "mocks" )
204
+ end
380
205
 
381
- @context_extractor.collect_simple_context_from_file(
382
- _filepath,
383
- filepath,
384
- TestContextExtractor::Context::BUILD_DIRECTIVE_SOURCE_FILES
385
- )
206
+ # Stage 15: Compile all test build objects in parallel.
207
+ #
208
+ # An unchanged object skips its compile-execute plugin hooks entirely (see
209
+ # compile_test_component), so plugins that accumulate per-run state from
210
+ # pre_compile_execute/post_compile_execute -- compile_commands_json_db,
211
+ # report_build_warnings_log, bullseye, command_hooks -- only see objects
212
+ # actually recompiled this run, not the full set. Same for stage 16's link
213
+ # hooks. Contrast with stage 17, where Generator#generate_test_results
214
+ # reports a skipped executable's cached result through both fixture-execute
215
+ # hooks regardless, so consumers of *that* pair always see every test.
216
+ #
217
+ # Compiles in two sequential batches -- every test's own file first, in a batch
218
+ # fully completed before any other object starts. compile_test_component's own
219
+ # sibling-header isolation (run only against a test's own file) may correct that
220
+ # testable's search paths; every other object in the same test needs to compile
221
+ # against the corrected paths, never the original ones, and a real barrier
222
+ # between the two groups is the only way parallel compilation can guarantee that.
223
+ #
224
+ # BARRIER INVARIANT (see also apply_sibling_isolation's own note): each pair below
225
+ # runs through @batchinator.exec -- real worker threads via Parallel.map -- and
226
+ # `compile_pass.call( test_file_pairs )` fully drains (Parallel.map blocks until
227
+ # every thread in that call is done) before `compile_pass.call( other_pairs )`
228
+ # even starts. That's what makes apply_sibling_isolation's unguarded writes to
229
+ # testable.search_paths/isolated_headers_path safe: the only thread that ever
230
+ # writes them is the one compiling that test's own file, in the first batch, and
231
+ # every thread reading them afterward starts only once that write has already
232
+ # happened. Merging or reordering these two calls -- e.g. to parallelize them
233
+ # together for speed -- would reintroduce a real, unguarded data race on those
234
+ # fields, confirmed experimentally (see concurrency-file-presence-factfinding
235
+ # memory, Finding 4): a merged single-pass variant of this exact shape saw
236
+ # violations on 97%+ of reads once the barrier was removed.
237
+ def stage_build_objects(state)
238
+ skipped = 0
386
239
 
387
- state.testables.each do |_, t|
388
- validate_build_directive_source_files( test: name, filepath: t.filepath )
389
- end
240
+ resolved = state.objects_list.map do |obj|
241
+ src = @file_finder.find_build_input_file( filepath: obj.obj, context: state.context, test: obj.test )
242
+ [obj, src]
390
243
  end
391
- end
392
244
 
393
- # Stage 12: Collect test runner details (test case names) from preprocessed test files.
394
- def stage_collect_runner_details(state)
395
- @batchinator.exec(workload: :compile, things: state.testables) do |_, testable|
396
- msg = @reportinator.generate_module_progress(
397
- operation: 'Parsing test case names',
398
- module_name: testable.name,
399
- filename: File.basename( testable.filepath )
400
- )
401
- @loginator.log( msg )
245
+ test_file_pairs, other_pairs = resolved.partition do |obj, src|
246
+ testable = state.testables[obj.test.to_sym]
247
+ !testable.nil? && src == testable.filepath
248
+ end
402
249
 
403
- @context_extractor.collect_test_runner_details( testable.filepath, testable.runner[:input_filepath] )
250
+ compile_pass = lambda do |pairs|
251
+ @batchinator.exec(workload: :compile, things: pairs) do |obj, src|
252
+ compiled = compile_test_component(
253
+ context: state.context,
254
+ test: obj.test,
255
+ source: src,
256
+ object: obj.obj,
257
+ state: state
258
+ )
259
+ state.lock.synchronize { skipped += 1 } unless compiled
260
+ end
404
261
  end
405
- end
406
262
 
407
- # Stage 13: Generate test runner files.
408
- def stage_generate_runners(state)
409
- @batchinator.exec(workload: :compile, things: state.testables) do |_, testable|
410
- arg_hash = {
411
- context: state.context,
412
- mocks: @context_extractor.lookup_mock_header_includes_list( testable.filepath ),
413
- includes: @context_extractor.lookup_nonmock_header_includes_list( testable.filepath ),
414
- test_filepath: testable.filepath,
415
- input_filepath: testable.runner[:input_filepath],
416
- runner_filepath: testable.runner[:output_filepath]
417
- }
263
+ compile_pass.call( test_file_pairs )
264
+ compile_pass.call( other_pairs )
418
265
 
419
- @generator.generate_test_runner( **arg_hash )
266
+ # Any isolated sibling-header copy staged for a testable during either batch
267
+ # above was scoped to this one build and never registered as a tracked
268
+ # dependency in its own right (see isolate_sibling_headers) -- nothing past
269
+ # this point still needs it to exist.
270
+ state.testables.each_value do |testable|
271
+ next if testable.isolated_headers_path.nil?
272
+ @quote_include_isolator.release( testable.isolated_headers_path )
420
273
  end
421
- end
422
274
 
423
- # Stage 15: Compile all test build objects in parallel.
424
- def stage_build_objects(state)
425
- @batchinator.exec(workload: :compile, things: state.objects_list) do |obj|
426
- src = @file_finder.find_build_input_file( filepath: obj[:obj], context: state.context )
427
- compile_test_component(
428
- context: state.context,
429
- test: obj[:test],
430
- source: src,
431
- object: obj[:obj],
432
- state: state
433
- )
434
- end
275
+ log_skip_summary( task: "compilation", count: skipped, noun: "objects" )
435
276
  end
436
277
 
437
278
  # Stage 16: Link test executables.
438
279
  def stage_build_executables(state)
439
280
  lib_args = convert_libraries_to_arguments()
440
281
  lib_paths = get_library_paths_to_arguments()
282
+ skipped = 0
441
283
 
442
284
  @batchinator.exec(workload: :compile, things: state.testables) do |_, testable|
443
285
  remove_partials_source_objects( testable.objects, testable.partials.configs )
444
286
 
445
- arg_hash = {
446
- context: state.context,
447
- build_path: testable.paths[:build],
448
- executable: testable.executable,
449
- objects: testable.objects,
450
- flags: testable.link_flags,
451
- lib_args: lib_args,
452
- lib_paths: lib_paths,
453
- options: state.options
454
- }
287
+ link_flags = testable.link_flags
288
+ tool, link_flags = resolve_link_tool( context: state.context, tool: @configurator.tools_test_linker, flags: link_flags, executable: testable.executable )
289
+
290
+ @dependinator.register(
291
+ testable.executable,
292
+ files: testable.objects,
293
+ meta: { flags: link_flags, lib_args: lib_args, lib_paths: lib_paths, tools: [tool] }
294
+ )
295
+ stale = @dependinator.stale?( testable.executable )
296
+
297
+ if stale
298
+ arg_hash = {
299
+ context: state.context,
300
+ build_path: testable.paths[:build],
301
+ executable: testable.executable,
302
+ objects: testable.objects,
303
+ flags: link_flags,
304
+ lib_args: lib_args,
305
+ lib_paths: lib_paths,
306
+ tool: tool
307
+ }
455
308
 
456
- generate_executable_now( **arg_hash )
309
+ generate_executable( **arg_hash )
310
+
311
+ @dependinator.mark_fresh( testable.executable )
312
+ else
313
+ msg = @reportinator.generate_module_progress(
314
+ operation: 'Skipping linking for',
315
+ module_name: testable.name,
316
+ filename: File.basename( testable.executable )
317
+ )
318
+ @loginator.log( msg, Verbosity::OBNOXIOUS )
319
+ state.lock.synchronize { skipped += 1 }
320
+ end
321
+
322
+ @generator.generate_test_executable_manifest( executable: testable.executable, test_filepath: testable.filepath )
323
+
324
+ # Stage 17 relies on this rather than a second `stale?` call -- by the
325
+ # time it runs, `mark_fresh` above (when `stale` was true) has already
326
+ # updated the cache entry to match the executable's current state, so a
327
+ # fresh `stale?` query would always answer false.
328
+ state.lock.synchronize { testable.executable_rebuilt = stale }
457
329
  end
330
+
331
+ log_skip_summary( task: "linking", count: skipped, noun: "executables" )
458
332
  end
459
333
 
460
334
  # Stage 17: Execute test fixtures and collect results.
335
+ #
336
+ # An executable that didn't need relinking (see stage 16) still has valid
337
+ # cached results on disk from whenever it was last built -- Generator#generate_test_results
338
+ # reports those instead of actually (re)running it, per `skipped:` below.
339
+ #
340
+ # `:force_test_rerun` and `:unity ↳ :shuffle_tests` both override that skip:
341
+ # shuffled test-case order is decided at runtime inside the executable itself
342
+ # (Unity's generated `main()` reshuffles on every invocation), not at compile
343
+ # or link time, so an executable that's otherwise unchanged still needs to
344
+ # actually run again for shuffling to have any effect at all.
345
+ #
346
+ # The dependency tracker gives a third reason to rerun, alongside those two:
347
+ # `testable.executable` unchanged says nothing about whether the *tool* that
348
+ # actually runs it -- :tools ↳ :test_fixture -- changed since the last run.
349
+ # This target is registered separately from stage 16's own executable target
350
+ # (not reusing it) so a tool-only change reruns the fixture without also
351
+ # marking the executable itself stale and forcing an unnecessary relink.
352
+ #
353
+ # The target itself is a dedicated marker file, not either outcome-dependent
354
+ # results file (.pass/.fail) -- which of those two actually gets written
355
+ # depends on whether the test passes, so neither is guaranteed to exist after
356
+ # every run, and a target `mark_fresh` can't hash is a crash on a failing
357
+ # test, while a target `stale?` can't find is permanent, unwanted staleness
358
+ # for a test that keeps failing the same way. The marker's own content is
359
+ # irrelevant and never changes -- only its existence (written after every
360
+ # real run, pass or fail alike) and the registered files/meta drive staleness.
461
361
  def stage_execute(state)
362
+ skipped = 0
363
+ force_rerun = @configurator.force_test_rerun || @configurator.unity_shuffle_tests
364
+
365
+ overridden = state.testables.values.count { |t| !t.executable_rebuilt }
366
+
367
+ if @configurator.unity_shuffle_tests && overridden > 0
368
+ noun = overridden == 1 ? 'test executable' : 'test executables'
369
+ @loginator.log(
370
+ "Test shuffling is enabled -- rerunning #{overridden} already up-to-date #{noun} to randomize test case order.",
371
+ Verbosity::NORMAL,
372
+ LogLabels::NOTICE
373
+ )
374
+ end
375
+
462
376
  @batchinator.exec(workload: :test, things: state.testables) do |_, testable|
463
377
  begin
378
+ # `paths[:results]` is only per-test-unique for a test mirrored into its own
379
+ # subdirectory -- a test with no mirrored subdir shares that directory with
380
+ # every other such test, so the marker's own filename (not just its directory)
381
+ # must be test-specific too, matching clean_test_results' own `test + '.*'`
382
+ # naming below.
383
+ fixture_target = File.join( testable.paths[:results], "#{File.basename( testable.name )}.fixture_run" )
384
+
385
+ fixture_tool = resolve_fixture_tool( context: state.context, tool: @configurator.tools_test_fixture, test_name: testable.name, target: fixture_target )
386
+
387
+ # :use_backtrace doesn't swap the fixture tool itself (unlike Valgrind/Gcov's own
388
+ # pre_test_fixture_register hooks) -- it only selects what happens *after*
389
+ # run_fixture detects a crash (generator.rb's own case on :project_use_backtrace:
390
+ # :gdb runs tools_test_backtrace_gdb, :simple runs tools_test_fixture_simple_backtrace,
391
+ # :none does neither). Without capturing that selector (and the tool config(s) it
392
+ # actually drives) as meta here, toggling :use_backtrace -- or editing a backtrace
393
+ # tool's own executable/args -- would never invalidate this fixture_target, so a
394
+ # delta build would keep reusing a stale crash-diagnosis result on the next crash.
395
+ #
396
+ # tools_test_backtrace_gdb only exists at all when :use_backtrace is :gdb --
397
+ # Configurator only merges its defaults (DEFAULT_TOOLS_TEST_GDB_BACKTRACE) in that
398
+ # case (configurator.rb) -- so it's only read here when actually relevant.
399
+ # tools_test_fixture_simple_backtrace has no such gate (DEFAULT_TOOLS_TEST always
400
+ # includes it) and is always safe to read.
401
+ use_backtrace = @configurator.project_config_hash[:project_use_backtrace]
402
+ backtrace_tools = [@configurator.tools_test_fixture_simple_backtrace]
403
+ backtrace_tools << @configurator.tools_test_backtrace_gdb if use_backtrace == :gdb
404
+
405
+ @dependinator.register(
406
+ fixture_target, files: [testable.executable],
407
+ meta: { tools: [fixture_tool], use_backtrace: use_backtrace, backtrace_tools: backtrace_tools }
408
+ )
409
+
410
+ run_now = testable.executable_rebuilt || force_rerun || @dependinator.stale?( fixture_target )
411
+
412
+ # Clear out any stale prior result (e.g. a lingering `.fail` from a test
413
+ # that now passes) immediately before an actual (re)run -- not upfront
414
+ # for every test regardless of whether it's about to run, which would
415
+ # destroy the still-valid cached result of a test left unchanged.
416
+ clean_test_results( testable.paths[:results], File.basename( testable.name ) ) if run_now
417
+
418
+ unless run_now
419
+ msg = @reportinator.generate_module_progress(
420
+ operation: 'Skipping test execution for',
421
+ module_name: testable.name,
422
+ filename: File.basename( testable.executable )
423
+ )
424
+ @loginator.log( msg, Verbosity::OBNOXIOUS )
425
+ state.lock.synchronize { skipped += 1 }
426
+ end
427
+
464
428
  arg_hash = {
465
429
  context: state.context,
466
430
  test_name: testable.name,
467
431
  test_filepath: testable.filepath,
468
432
  executable: testable.executable,
469
433
  result: testable.results_pass,
470
- options: state.options
434
+ skipped: !run_now,
435
+ tool: fixture_tool
471
436
  }
472
437
 
473
- run_fixture_now( **arg_hash )
438
+ run_fixture( **arg_hash )
439
+
440
+ if run_now
441
+ @file_wrapper.touch( fixture_target )
442
+
443
+ # A later skipped run reuses the result this run wrote, so the fixture target
444
+ # vouches for it. Only whichever of the two exists is recorded.
445
+ @dependinator.register(
446
+ fixture_target,
447
+ outputs: [testable.results_pass, testable.results_pass.ext( @configurator.extension_testfail.primary )]
448
+ )
449
+ @dependinator.mark_fresh( fixture_target )
450
+ end
474
451
 
475
452
  ensure
476
453
  @plugin_manager.post_test( testable.filepath )
477
454
  end
478
455
  end
456
+
457
+ # `@batchinator.exec` above fully drains before returning -- every test executable
458
+ # in this run has finished executing, so this is the one correct point to flush the
459
+ # whole-suite gdb health summary, once, before final results reporting.
460
+ @generator.report_gdb_attach_health()
461
+
462
+ log_skip_summary( task: "test execution", count: skipped, noun: "tests", reason: "reusing cached results" )
479
463
  end
480
464
 
481
465
  # -----------------------------------------------------------------------
482
466
  # Helper methods
483
467
  # -----------------------------------------------------------------------
484
468
 
485
- def generate_executable_now(context:, build_path:, executable:, objects:, flags:, lib_args:, lib_paths:, options:)
469
+ def generate_executable(context:, build_path:, executable:, objects:, flags:, lib_args:, lib_paths:, tool:)
486
470
  begin
487
471
  @generator.generate_executable_file(
488
- options[:test_linker],
472
+ tool,
489
473
  context,
490
474
  objects.map { |v| "\"#{v}\"" },
491
475
  flags,
@@ -495,7 +479,7 @@ class TestBuildExecutor
495
479
  lib_paths
496
480
  )
497
481
  rescue ShellException => ex
498
- if ex.shell_result[:output] =~ /symbol/i
482
+ if ex.shell_result[:output].match?(/symbol/i)
499
483
  notice = "If the linker reports missing symbols, the following may be to blame:\n" +
500
484
  " 1. This test lacks #include statements corresponding to needed source files (see note below).\n" +
501
485
  " 2. Project file paths omit source files corresponding to #include statements in this test.\n" +
@@ -506,7 +490,7 @@ class TestBuildExecutor
506
490
  end
507
491
 
508
492
  notice += "\n"
509
- notice += "NOTE: A test file directs the build of a test executable with #include statemetns:\n" +
493
+ notice += "NOTE: A test file directs the build of a test executable with #include statements:\n" +
510
494
  " * By convention, Ceedling assumes header filenames correspond to source filenames.\n" +
511
495
  " * Which code files to compile and link are determined by #include statements.\n"
512
496
  if @configurator.project_use_mocks
@@ -518,7 +502,7 @@ class TestBuildExecutor
518
502
  " 1. Doublecheck this test's #include statements.\n" +
519
503
  " 2. Simplify complex macros or fully specify symbols for this test in :project ↳ :defines.\n" +
520
504
  " 3. If no header file corresponds to the needed source file, use the TEST_SOURCE_FILE()\n" +
521
- " build diective macro in this test to inject a source file into the build.\n\n" +
505
+ " build directive macro in this test to inject a source file into the build.\n\n" +
522
506
  "See the docs on conventions, paths, preprocessing, compilation symbols, and build directive macros.\n\n"
523
507
 
524
508
  @loginator.log( notice, Verbosity::COMPLAIN, LogLabels::NOTICE )
@@ -528,14 +512,19 @@ class TestBuildExecutor
528
512
  end
529
513
  end
530
514
 
531
- def run_fixture_now(context:, test_name:, test_filepath:, executable:, result:, options:)
515
+ def clean_test_results(path, test)
516
+ @file_wrapper.rm_f( Dir.glob( File.join( path, test + '.*' ) ) )
517
+ end
518
+
519
+ def run_fixture(context:, test_name:, test_filepath:, executable:, result:, tool:, skipped: false)
532
520
  @generator.generate_test_results(
533
- tool: options[:test_fixture],
521
+ tool: tool,
534
522
  context: context,
535
523
  test_name: test_name,
536
524
  test_filepath: test_filepath,
537
525
  executable: executable,
538
- result: result
526
+ result: result,
527
+ skipped: skipped
539
528
  )
540
529
  end
541
530
 
@@ -557,17 +546,78 @@ class TestBuildExecutor
557
546
 
558
547
  private
559
548
 
560
- # Compile a single C or assembly source file into an object file.
549
+ # Finds the folder a mock's #include names and the directory the mock is written to.
550
+ #
551
+ # CMock names a mock's guard and lifecycle functions by that folder, and the runner names
552
+ # its calls by the same #include. Two same-named mocks stay distinct only if the folder
553
+ # reaches CMock. CMock writes below its own root at that folder, so the folder must end the
554
+ # mock's directory. A folder trailing the mirrored location keeps that location. An #include
555
+ # spelling more path than the mirror holds moves its mock below the per-test root at the
556
+ # written path, which the root search path still reaches. A bare #include has no folder.
557
+ # Without :mock_name_include_folder no folder is passed, and CMock names by filename alone.
558
+ def mock_folder_and_path(mocks_root, output_path, include_path)
559
+ return [nil, output_path] unless @configurator.cmock_mock_name_include_folder
560
+
561
+ folder = File.dirname( include_path.to_s ).sub( %r{\A(?:\./)+}, '' )
562
+
563
+ return [nil, output_path] if folder.empty? || folder == '.'
564
+ return [folder, output_path] if output_path.end_with?( File.join( '', folder ) )
565
+
566
+ return [folder, File.join( mocks_root, folder )]
567
+ end
568
+
569
+ # Compile a single C or assembly source file into an object file. Returns
570
+ # whether a real compile actually happened, so the caller can report how
571
+ # many objects across the whole build needed nothing done.
572
+ #
573
+ # A test file's own C compile (only) gets one extra check: isolate_sibling_headers
574
+ # inspects its freshly-written .d file for a real header sharing a directory with
575
+ # one this test mocks or Partializes, and retries with corrected search paths if
576
+ # it finds one. A failure that's still standing afterward -- nothing to isolate,
577
+ # or an isolated retry that failed too -- gets one last look from generator_helper
578
+ # before it's raised, in case it's explainable as this same class of collision.
579
+ #
580
+ # Any other source sharing a directory with a header mocked under inline shadowing
581
+ # compiles from an isolated copy instead (compile_isolated_source).
561
582
  def compile_test_component(context:, test:, source:, object:, state:)
562
583
  testable = state.testables[test.to_sym]
563
584
  defines = testable.compile_defines
564
585
  search_paths = tailor_search_paths( search_paths: testable.search_paths, filepath: source )
586
+ dependencies = @file_path_utils.form_test_dependencies_filepath( object, name: test, context: context )
565
587
 
566
- if @file_wrapper.extname( source ) != @configurator.extension_assembly
588
+ if !@configurator.extension_assembly.match?( source )
567
589
  flags = testable.compile_flags
590
+ tool, flags, defines = resolve_compile_tool(
591
+ context: context, operation: OPERATION_COMPILE_SYM, tool: @configurator.tools_test_compiler,
592
+ flags: flags, defines: defines, module_name: test, source: source, object: object
593
+ )
594
+ stale = register_and_check_object_staleness( object: object, source: source, dependencies: dependencies, flags: flags, defines: defines, search_paths: search_paths, tool: tool )
595
+
596
+ unless stale
597
+ # A skipped compile still needs this test's search paths corrected the same
598
+ # way a real compile would have left them -- otherwise every other object in
599
+ # this test's build (compiled or skipped) would compute its own staleness
600
+ # against paths that silently drift from whatever the last real compile
601
+ # actually cached, forcing a recompile on every subsequent build regardless
602
+ # of whether anything actually changed. The existing .d file already on disk
603
+ # (from whichever run last actually compiled this file) is what a skip has
604
+ # to go on -- there's no fresh one to write this run.
605
+ if source == testable.filepath && @file_wrapper.exist_with_retry?( dependencies )
606
+ apply_sibling_isolation( testable: testable, dependencies_filepath: dependencies )
607
+ end
608
+
609
+ return log_compile_skip( test: test, source: source )
610
+ end
611
+
612
+ # A module-under-test or support source mirrored into its own subdirectory needs that
613
+ # subdirectory (and its dependencies-file counterpart) to actually exist before the
614
+ # compiler can write there -- the test's own per-test directories are pre-created
615
+ # upfront, but a mirrored subdirectory beneath one is not.
616
+ @file_wrapper.mkdir( File.dirname( object ) )
617
+ @file_wrapper.mkdir( File.dirname( dependencies ) )
568
618
 
569
619
  arg_hash = {
570
- tool: @configurator.tools_test_compiler,
620
+ tool: tool,
571
621
  module_name: test,
572
622
  context: context,
573
623
  source: source,
@@ -576,16 +626,82 @@ class TestBuildExecutor
576
626
  flags: flags,
577
627
  defines: defines,
578
628
  list: @file_path_utils.form_test_build_list_filepath( object ),
579
- dependencies: @file_path_utils.form_test_dependencies_filepath( object, name: test, context: context )
629
+ dependencies: dependencies
580
630
  }
581
631
 
582
- @generator.generate_object_file_c( **arg_hash )
632
+ compile_failure = nil
633
+ shadowed_header = inline_mocked_sibling_header( testable, source )
634
+
635
+ if shadowed_header
636
+ compile_failure = compile_isolated_source( arg_hash: arg_hash, testable: testable, header: shadowed_header )
637
+ else
638
+ begin
639
+ @generator.generate_object_file_c( **arg_hash )
640
+ rescue ShellException => ex
641
+ compile_failure = ex
642
+ end
643
+ end
644
+
645
+ # gcc's dependency output is a side effect of preprocessing -- already written to
646
+ # disk by the time a later parse/type-check phase can still fail -- so this
647
+ # attempt's own .d file is worth registering whether or not it went on to fail.
648
+ # exist_with_retry? rides out the file briefly not yet being visible right after
649
+ # the shell-out exits (a raw miss here silently drops this compile's discovered
650
+ # header dependencies -- self-correcting into one extra recompile next run, but
651
+ # worth riding out directly).
652
+ @dependinator.register_gcc_deps_file( dependencies ) if @file_wrapper.exist_with_retry?( dependencies )
653
+
654
+ # Only the test file's own compile is ever checked here directly -- every other
655
+ # object in the same test's build already sees whatever search paths that check
656
+ # settled on (see stage_build_objects's own two-pass split).
657
+ if source == testable.filepath && @file_wrapper.exist_with_retry?( dependencies )
658
+ isolation = apply_sibling_isolation( testable: testable, dependencies_filepath: dependencies )
659
+
660
+ if isolation
661
+ # A throwaway retry: its own .d file is never registered, so the attempt
662
+ # registered just above -- real headers, real paths -- remains the lasting
663
+ # record of this object's antecedents. The isolated copy is always freshly,
664
+ # fully derived from those same tracked files, so it can never itself go
665
+ # stale independently and needs no tracking of its own.
666
+ retry_arg_hash = arg_hash.merge(
667
+ search_paths: tailor_search_paths( search_paths: isolation[:search_paths], filepath: source ),
668
+ dependencies: dependencies + '.isolated_retry'
669
+ )
670
+
671
+ begin
672
+ @generator.generate_object_file_c( **retry_arg_hash )
673
+ compile_failure = nil
674
+ rescue ShellException => ex
675
+ compile_failure = ex
676
+ end
677
+ end
678
+ end
679
+
680
+ if compile_failure
681
+ notice = @generator_helper.explain_possible_mock_partial_collision(
682
+ output: compile_failure.shell_result[:output],
683
+ mocked_headers: mocked_and_partialized_headers( testable )
684
+ )
685
+ @loginator.log( notice, Verbosity::ERRORS, LogLabels::NOTICE ) if notice
686
+
687
+ raise compile_failure
688
+ end
583
689
 
584
690
  elsif @configurator.test_build_use_assembly
585
691
  flags = testable.assembler_flags
692
+ tool, flags, defines = resolve_compile_tool(
693
+ context: context, operation: OPERATION_ASSEMBLE_SYM, tool: @configurator.tools_test_assembler,
694
+ flags: flags, defines: defines, module_name: test, source: source, object: object
695
+ )
696
+ stale = register_and_check_object_staleness( object: object, source: source, dependencies: dependencies, flags: flags, defines: defines, search_paths: search_paths, tool: tool )
697
+
698
+ return log_compile_skip( test: test, source: source ) unless stale
699
+
700
+ @file_wrapper.mkdir( File.dirname( object ) )
701
+ @file_wrapper.mkdir( File.dirname( dependencies ) )
586
702
 
587
703
  arg_hash = {
588
- tool: @configurator.tools_test_assembler,
704
+ tool: tool,
589
705
  module_name: test,
590
706
  context: context,
591
707
  source: source,
@@ -594,80 +710,332 @@ class TestBuildExecutor
594
710
  flags: flags,
595
711
  defines: defines,
596
712
  list: @file_path_utils.form_test_build_list_filepath( object ),
597
- dependencies: @file_path_utils.form_test_dependencies_filepath( object, name: test, context: context )
713
+ dependencies: dependencies
598
714
  }
599
715
 
600
716
  @generator.generate_object_file_asm( **arg_hash )
717
+
718
+ # register_gcc_deps_file again to pick up the freshly-written `.d` file's current
719
+ # header set (a no-op call here regardless, since the assembler tool has no
720
+ # -MMD/-MF of its own) before recording this target's new baseline.
721
+ @dependinator.register_gcc_deps_file( dependencies ) if @file_wrapper.exist_with_retry?( dependencies )
722
+ else
723
+ return false
601
724
  end
725
+
726
+ @dependinator.mark_fresh( object )
727
+
728
+ true
602
729
  end
603
730
 
604
- def tailor_search_paths(filepath:, search_paths:)
605
- _search_paths = []
606
-
607
- if filepath == File.join( PROJECT_BUILD_VENDOR_UNITY_PATH, UNITY_C_FILE )
608
- _search_paths += @configurator.collection_paths_support
609
- _search_paths << PROJECT_BUILD_VENDOR_UNITY_PATH
610
-
611
- elsif @configurator.project_use_mocks and
612
- (filepath == File.join( PROJECT_BUILD_VENDOR_CMOCK_PATH, CMOCK_C_FILE ))
613
- _search_paths += @configurator.collection_paths_support
614
- _search_paths << PROJECT_BUILD_VENDOR_UNITY_PATH
615
- _search_paths << PROJECT_BUILD_VENDOR_CMOCK_PATH
616
- _search_paths << PROJECT_BUILD_VENDOR_CEXCEPTION_PATH if @configurator.project_use_exceptions
617
-
618
- elsif @configurator.project_use_exceptions and
619
- (filepath == File.join( PROJECT_BUILD_VENDOR_CEXCEPTION_PATH, CEXCEPTION_C_FILE ))
620
- _search_paths += @configurator.collection_paths_support
621
- _search_paths << PROJECT_BUILD_VENDOR_CEXCEPTION_PATH
622
-
623
- elsif @configurator.collection_all_support.include?( filepath )
624
- _search_paths = search_paths
625
- _search_paths += @configurator.collection_paths_support
626
- _search_paths << PROJECT_BUILD_VENDOR_UNITY_PATH
627
- _search_paths << PROJECT_BUILD_VENDOR_CMOCK_PATH if @configurator.project_use_mocks
628
- _search_paths << PROJECT_BUILD_VENDOR_CEXCEPTION_PATH if @configurator.project_use_exceptions
731
+ # The mocked header `source` would reach directly in place of its mock, or nil.
732
+ #
733
+ # With :treat_inlines set to :include, CMock writes an inline-stripped copy of a mocked
734
+ # header into the mocks directory, first on the search path. A source sharing a directory
735
+ # with the real header and quote-including it finds the real one first. Its inline bodies
736
+ # then run in place of the mock. A Partial mock writes no such copy, and a test file
737
+ # reaches its mocks by their own names.
738
+ def inline_mocked_sibling_header(testable, source)
739
+ return nil unless @configurator.project_use_mocks
740
+ return nil unless @configurator.cmock_treat_inlines == :include
741
+ return nil if source == testable.filepath
742
+
743
+ directory = File.expand_path( File.dirname( source ) )
744
+
745
+ (testable.mocks || {}).each_value do |details|
746
+ next if details.partial || details.source.nil?
747
+ next unless File.expand_path( File.dirname( details.source ) ) == directory
748
+
749
+ header = File.basename( details.source )
750
+ return details.source if @quote_include_isolator.includes_by_name?( source, header )
629
751
  end
630
752
 
631
- return search_paths if _search_paths.empty?
753
+ return nil
754
+ end
632
755
 
633
- return _search_paths.uniq
756
+ # Compiles a source from a copy staged alone, returning any compile failure.
757
+ #
758
+ # With no real header beside the copy, its quoted #include of `header` reaches CMock's
759
+ # inline-stripped copy on the search path. A #line directive keeps every report naming
760
+ # the original. The original's directory follows all other search paths so its other
761
+ # includes still resolve. The dependency file is restored before the copy is released,
762
+ # so tracking never names a file that no longer exists.
763
+ def compile_isolated_source(arg_hash:, testable:, header:)
764
+ source = arg_hash[:source]
765
+
766
+ msg = "Compiling an isolated copy of '#{source}' for this test because it shares a directory with " \
767
+ "mocked header '#{header}', whose inline functions it would otherwise call instead of the mock."
768
+ @loginator.log( msg, Verbosity::NORMAL, LogLabels::NOTICE )
769
+
770
+ @quote_include_isolator.within( parent: testable.paths[:build], files: [source], preserve_location: true ) do |isolation|
771
+ begin
772
+ @generator.generate_object_file_c(
773
+ **arg_hash.merge(
774
+ compile_source: isolation.copy_of( source ),
775
+ search_paths: arg_hash[:search_paths] + [File.dirname( source )]
776
+ )
777
+ )
778
+ nil
779
+ rescue ShellException => ex
780
+ ex
781
+ ensure
782
+ @quote_include_isolator.restore_dependencies( isolation, arg_hash[:dependencies] )
783
+ end
784
+ end
634
785
  end
635
786
 
636
- def validate_build_directive_source_files(test:, filepath:)
637
- sources = @test_context_extractor.lookup_build_directive_sources_list( filepath )
787
+ def log_compile_skip(test:, source:)
788
+ msg = @reportinator.generate_module_progress(
789
+ operation: 'Skipping compilation for',
790
+ module_name: test,
791
+ filename: File.basename( source )
792
+ )
793
+ @loginator.log( msg, Verbosity::OBNOXIOUS )
794
+ false
795
+ end
638
796
 
639
- ext_message = @configurator.extension_source
640
- if @configurator.test_build_use_assembly
641
- ext_message += " or #{@configurator.extension_assembly}"
642
- end
797
+ # Lets a plugin swap in its own compiler tool (and adjust flags/defines) for a
798
+ # particular build context -- e.g. Gcov/Bullseye's instrumented compilers -- via
799
+ # pre_test_compile_register, *before* dependency-tracker meta is computed below, so a
800
+ # plugin's own tool config is what actually drives that target's staleness rather
801
+ # than the plain test compiler it's about to be swapped out for. The resolved
802
+ # values are also what the real compile itself uses (see the two call sites
803
+ # above), so the two can never disagree about which tool actually ran.
804
+ def resolve_compile_tool(context:, operation:, tool:, flags:, defines:, module_name:, source:, object:)
805
+ arg_hash = {
806
+ context: context, operation: operation, tool: tool, flags: flags, defines: defines,
807
+ module_name: module_name, source: source, object: object
808
+ }
809
+ @plugin_manager.pre_test_compile_register( arg_hash )
810
+ return arg_hash[:tool], arg_hash[:flags], arg_hash[:defines]
811
+ end
643
812
 
644
- sources.each do |source|
645
- valid_extension = true
813
+ # As resolve_compile_tool above, for the link step's own tool swap (pre_test_link_register),
814
+ # e.g. Gcov/Bullseye's instrumented linkers.
815
+ def resolve_link_tool(context:, tool:, flags:, executable:)
816
+ arg_hash = { context: context, tool: tool, flags: flags, executable: executable }
817
+ @plugin_manager.pre_test_link_register( arg_hash )
818
+ return arg_hash[:tool], arg_hash[:flags]
819
+ end
646
820
 
647
- if not @configurator.test_build_use_assembly
648
- valid_extension = false if @file_wrapper.extname( source ) != @configurator.extension_source
649
- else
650
- ext = @file_wrapper.extname( source )
651
- valid_extension = false if (ext != @configurator.extension_assembly) and (ext != @configurator.extension_source)
652
- end
821
+ # As resolve_compile_tool/resolve_link_tool above, for the test-fixture step's own
822
+ # tool swap (pre_test_fixture_register), e.g. Valgrind wrapping the executable.
823
+ # `target` (the fixture-run marker target -- see stage_execute) is included so a
824
+ # plugin can register additional meta of its own against the same target, merging
825
+ # with what this stage registers immediately after -- Dependinator#register is
826
+ # additive across multiple calls for one target regardless of call order.
827
+ def resolve_fixture_tool(context:, tool:, test_name:, target:)
828
+ arg_hash = { context: context, tool: tool, test_name: test_name, target: target }
829
+ @plugin_manager.pre_test_fixture_register( arg_hash )
830
+ return arg_hash[:tool]
831
+ end
653
832
 
654
- if not valid_extension
655
- error = "File '#{source}' specified with TEST_SOURCE_FILE() in #{test} is not a #{ext_message} source file"
656
- raise CeedlingException.new( error )
833
+ # Checks `dependencies_filepath` (this test's own most recent `.d` file, whether
834
+ # freshly written by a real compile just now or left over from whichever run
835
+ # last actually compiled it) for a sibling-header risk, and mutates `testable`
836
+ # in place to apply whatever it finds -- the one path both a real compile and a
837
+ # skipped one share, so search_paths reads the same way regardless of which one
838
+ # happened this run. Returns whatever isolate_sibling_headers itself returned.
839
+ # BARRIER INVARIANT (see also stage_build_objects's own note): the writes below to
840
+ # testable.search_paths/isolated_headers_path are completely unguarded -- no mutex --
841
+ # which is only safe because this method is only ever called while compiling a
842
+ # test's own file, and stage_build_objects's two-pass split guarantees every other
843
+ # object belonging to that same test compiles in a later, separate batch that starts
844
+ # only after this one has fully finished. That ordering, not anything visible at
845
+ # these two lines, is the entire safety argument -- do not call this from, or read
846
+ # these fields during, a batch that could run concurrently with a test's own-file
847
+ # compile.
848
+ def apply_sibling_isolation(testable:, dependencies_filepath:)
849
+ isolation = isolate_sibling_headers( testable: testable, dependencies_filepath: dependencies_filepath )
850
+ return nil if isolation.nil?
851
+
852
+ testable.search_paths = isolation[:search_paths]
853
+ testable.isolated_headers_path = isolation[:isolation_dir]
854
+
855
+ isolation
856
+ end
857
+
858
+ # A mock or Partial substitutes a header only by way of search-path order -- a
859
+ # module reaching the same real header a second way, unmocked, can slip past the
860
+ # substitution entirely, silently, because C's own quote-include rule checks a
861
+ # file's own directory before ever consulting a search path. A test file's own
862
+ # freshly-compiled `.d` file already reveals every real header reachable from
863
+ # it, mocked/Partialized or not, which is enough to know where that risk exists
864
+ # even though it says nothing about whether any given occurrence actually won.
865
+ #
866
+ # For each header this test mocks or Partializes, any other file sharing its real
867
+ # directory in that dependency list, that itself actually #includes the real
868
+ # header by name, is staged, alone, into an isolated directory -- with nothing
869
+ # else there for its own #include of the real header to find, that #include is
870
+ # forced through the search paths that list the mock/Partial first. Actually
871
+ # #including the real header is the deciding signal, not mere co-residency: most
872
+ # real projects keep every header in one shared directory as a matter of
873
+ # ordinary convention, so "shares a directory" alone would flag nearly every
874
+ # file in the project. Only one level deep: a directory elsewhere in the same
875
+ # dependency list that shares no header with any of this test's own mocks or
876
+ # Partials, but itself holds more than one candidate, is shaped the same way
877
+ # and reported, but nothing designates which of its occupants should win, so
878
+ # nothing there is acted on.
879
+ #
880
+ # Returns nil when nothing needs isolating; otherwise a hash of the search
881
+ # paths to compile with (isolation directory listed first) and that directory's
882
+ # own path, for the caller to track and eventually clean up.
883
+ def isolate_sibling_headers(testable:, dependencies_filepath:)
884
+ mocked_headers = mocked_and_partialized_headers( testable )
885
+ return nil if mocked_headers.empty?
886
+
887
+ parsed = @gcc_dependency_parser.parse( @file_wrapper.read( dependencies_filepath ) )
888
+ dependencies = parsed.values.flatten.uniq
889
+ by_directory = dependencies.group_by { |dep| File.dirname( dep ) }
890
+
891
+ isolated = []
892
+ mocked_dirs = mocked_headers.values.map { |real_path| File.dirname( real_path ) }.uniq
893
+
894
+ mocked_headers.each_value do |real_path|
895
+ next unless dependencies.include?( real_path )
896
+
897
+ basename = File.basename( real_path )
898
+ siblings = (by_directory[File.dirname( real_path )] || []) - [real_path]
899
+ # A same-directory file is only a genuine risk if it actually #includes the
900
+ # real header by name -- most real projects keep every header in one shared
901
+ # directory, so "shares a directory" alone would flag nearly everything.
902
+ siblings = siblings.select { |sibling| @quote_include_isolator.includes_by_name?( sibling, basename ) }
903
+ next if siblings.empty?
904
+
905
+ siblings.each do |sibling|
906
+ isolated << sibling
907
+
908
+ msg = "Isolated '#{sibling}' into its own directory for this test's build because it shares a " \
909
+ "directory with '#{real_path}' and C conventions could bypass mock substitution leading to " \
910
+ "false negative test failures or even test fixture crashes."
911
+ @loginator.log( msg, Verbosity::NORMAL, LogLabels::NOTICE )
657
912
  end
913
+ end
658
914
 
659
- if @file_finder.find_build_input_file( filepath: source, complain: :ignore, context: TEST_SYM ).nil?
660
- error = "File '#{source}' specified with TEST_SOURCE_FILE() in #{test} cannot be found in the source file collection"
661
- raise CeedlingException.new( error )
915
+ # Any other directory in this same reachable set holding more than one file is
916
+ # shaped the same way a mocked header's own directory is -- but with no
917
+ # designated substitute among its occupants, there's nothing to safely isolate.
918
+ # Ceedling's own generated/vendor directories are exempt: a mocks output
919
+ # directory or a vendor framework's own source directory routinely holds
920
+ # several co-resident files as a matter of course, never a same-directory
921
+ # quote-include shortcut risk the way a real project header directory is.
922
+ generated_dirs = generated_content_dirs( testable )
923
+
924
+ by_directory.each do |dir, files|
925
+ next if mocked_dirs.include?( dir )
926
+ next if generated_dirs.any? { |gd| dir.start_with?( gd ) }
927
+
928
+ files.uniq.combination( 2 ).each do |a, b|
929
+ msg = "'#{a}' sits alongside '#{b}' at a nesting depth beyond what automated sibling-header " \
930
+ "isolation provides. If this test's build fails with a redeclaration or conflicting types " \
931
+ "error, the include ordering and path structure leading to '#{a}' or '#{b}' is worth investigating."
932
+ @loginator.log( msg, Verbosity::COMPLAIN, LogLabels::NOTICE )
662
933
  end
663
934
  end
935
+
936
+ return nil if isolated.empty?
937
+
938
+ isolation = @quote_include_isolator.isolate( parent: testable.paths[:build], files: isolated.uniq )
939
+
940
+ { search_paths: [isolation.dir] + testable.search_paths, isolation_dir: isolation.dir }
664
941
  end
665
942
 
666
- def remove_partials_source_objects(objects, configs)
667
- modules = configs.keys
668
- objects.delete_if do |filepath|
669
- modules.include?( File.basename( filepath ).ext() )
943
+ # `{ basename => real path }` for every real header this test substitutes -- CMock
944
+ # mocks of a real header, and Partials -- cross-referenced elsewhere against
945
+ # whatever a test's own compile actually reached. A mock Partial's own `source` is
946
+ # its own generated interface header, not a real project header, and is excluded.
947
+ def mocked_and_partialized_headers(testable)
948
+ headers = {}
949
+
950
+ (testable.mocks || {}).each_value do |details|
951
+ next if details.partial
952
+ headers[File.basename( details.source )] = details.source if details.source
953
+ end
954
+
955
+ testable.partials.configs.each_value do |config|
956
+ filepath = config.header.filepath
957
+ headers[File.basename( filepath )] = filepath if filepath
670
958
  end
959
+
960
+ headers
961
+ end
962
+
963
+ # Directory roots holding only Ceedling's own generated or vendored content for this
964
+ # test -- never real project headers, so co-residency there is routine, not a
965
+ # same-directory quote-include risk. A test's own Partials output directory
966
+ # routinely holds several generated headers side by side (a types header, an
967
+ # interface header, and more, one set per Partialized module), exactly the same
968
+ # shape as the mocks output directory.
969
+ def generated_content_dirs(testable)
970
+ [
971
+ testable.paths[:mocks],
972
+ testable.paths[:partials],
973
+ PROJECT_BUILD_VENDOR_UNITY_PATH,
974
+ PROJECT_BUILD_VENDOR_CMOCK_PATH,
975
+ PROJECT_BUILD_VENDOR_CEXCEPTION_PATH,
976
+ @configurator.project_build_vendor_ceedling_path
977
+ ].compact
978
+ end
979
+
980
+ # Registers `object`'s antecedents (its source file, plus whatever headers
981
+ # gcc's `-MMD -MF` discovered on the *previous* successful compile, if any)
982
+ # and reports whether it needs (re)building. The previous run's `.d` file is
983
+ # the only header list available before this run's compile has happened --
984
+ # if headers changed, that's exactly what makes this stale. Nothing has just
985
+ # written that file, so one look suffices: a clean build has none, and a missed
986
+ # one leaves the object stale, forcing a recompile.
987
+ def register_and_check_object_staleness(object:, source:, dependencies:, flags:, defines:, search_paths:, tool:)
988
+ @dependinator.register( object, files: [source], meta: dependency_meta( flags: flags, defines: defines, search_paths: search_paths, tools: [tool] ) )
989
+ @dependinator.register_gcc_deps_file( dependencies ) if @file_wrapper.exist?( dependencies )
990
+ @dependinator.stale?( object )
991
+ end
992
+
993
+ # Each framework/support source needs its own vendor path (and, for CMock and a
994
+ # support file, other frameworks' vendor paths too, when those frameworks are also in
995
+ # play) spliced in ahead of a test's ordinary search paths -- the vendor sources
996
+ # themselves live outside any configured :test/:source/:support/:include root, so
997
+ # without this they'd never resolve. An ordinary test source matches none of the
998
+ # cases below and falls through to `search_paths` unchanged.
999
+ def tailor_search_paths(filepath:, search_paths:)
1000
+ _search_paths =
1001
+ if filepath == File.join( PROJECT_BUILD_VENDOR_UNITY_PATH, UNITY_C_FILE )
1002
+ unity_search_paths()
1003
+ elsif @configurator.project_use_mocks and
1004
+ (filepath == File.join( PROJECT_BUILD_VENDOR_CMOCK_PATH, CMOCK_C_FILE ))
1005
+ cmock_search_paths()
1006
+ elsif @configurator.project_use_exceptions and
1007
+ (filepath == File.join( PROJECT_BUILD_VENDOR_CEXCEPTION_PATH, CEXCEPTION_C_FILE ))
1008
+ cexception_search_paths()
1009
+ elsif @configurator.collection_all_support.include?( filepath )
1010
+ support_file_search_paths( search_paths )
1011
+ else
1012
+ []
1013
+ end
1014
+
1015
+ return search_paths if _search_paths.empty?
1016
+
1017
+ return _search_paths.uniq
1018
+ end
1019
+
1020
+ def unity_search_paths()
1021
+ @configurator.collection_paths_support + [PROJECT_BUILD_VENDOR_UNITY_PATH]
1022
+ end
1023
+
1024
+ def cmock_search_paths()
1025
+ paths = @configurator.collection_paths_support + [PROJECT_BUILD_VENDOR_UNITY_PATH, PROJECT_BUILD_VENDOR_CMOCK_PATH]
1026
+ paths << PROJECT_BUILD_VENDOR_CEXCEPTION_PATH if @configurator.project_use_exceptions
1027
+ paths
1028
+ end
1029
+
1030
+ def cexception_search_paths()
1031
+ @configurator.collection_paths_support + [PROJECT_BUILD_VENDOR_CEXCEPTION_PATH]
1032
+ end
1033
+
1034
+ def support_file_search_paths(search_paths)
1035
+ paths = search_paths + @configurator.collection_paths_support + [PROJECT_BUILD_VENDOR_UNITY_PATH]
1036
+ paths << PROJECT_BUILD_VENDOR_CMOCK_PATH if @configurator.project_use_mocks
1037
+ paths << PROJECT_BUILD_VENDOR_CEXCEPTION_PATH if @configurator.project_use_exceptions
1038
+ paths
671
1039
  end
672
1040
 
673
1041
  end