ceedling 1.1.10 → 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 (1131) 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 +51 -29
  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 +327 -37
  138. data/docs/KnownIssues.md +30 -4
  139. data/docs/ReleaseNotes.md +288 -12
  140. data/docs/SECURITY.md +46 -2
  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 +192 -70
  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 +47 -15
  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 +216 -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 +118 -26
  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 -429
  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 +254 -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 +296 -15
  426. data/site-local/plugins/gcov/examples.html +251 -14
  427. data/site-local/plugins/gcov/gcovr.html +567 -65
  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 +386 -38
  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/{docs/mkdocs/snapshot/assets → site-local/snapshot/assets/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 +336 -160
  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 +346 -71
  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 -287
  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 -61
  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 -526
  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 -246
  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/examples/cipher_quest/README.md +0 -210
  997. data/docs/mkdocs/snapshot/examples/temp_sensor/README.md +0 -283
  998. data/docs/mkdocs/snapshot/examples/wondrous_forest/README.md +0 -92
  999. data/docs/mkdocs/snapshot/plugins/gcov/config/defaults.yml +0 -32
  1000. data/docs/mkdocs/snapshot/plugins/gcov/config/defaults_gcov.rb +0 -136
  1001. data/docs/mkdocs/snapshot.yml +0 -20
  1002. data/docs/mkdocs/testing-guide/build-directives.md +0 -153
  1003. data/docs/mkdocs/testing-guide/conventions.md +0 -616
  1004. data/docs/mkdocs/testing-guide/frameworks.md +0 -192
  1005. data/docs/mkdocs/testing-guide/index.md +0 -80
  1006. data/docs/mkdocs/testing-guide/partials/configuration.md +0 -67
  1007. data/docs/mkdocs/testing-guide/partials/conventions.md +0 -68
  1008. data/docs/mkdocs/testing-guide/partials/directives.md +0 -212
  1009. data/docs/mkdocs/testing-guide/partials/example.md +0 -149
  1010. data/docs/mkdocs/testing-guide/partials/index.md +0 -88
  1011. data/docs/mkdocs/testing-guide/partials/overview.md +0 -81
  1012. data/docs/mkdocs/testing-guide/partials/variables.md +0 -244
  1013. data/docs/mkdocs/testing-guide/test-cases.md +0 -194
  1014. data/docs/mkdocs/testing-guide/test-sample.md +0 -94
  1015. data/docs/mkdocs/testing-guide/test-suite-anatomy.md +0 -58
  1016. data/lib/ceedling/cacheinator.rb +0 -53
  1017. data/lib/ceedling/cacheinator_helper.rb +0 -60
  1018. data/lib/ceedling/dependinator.rb +0 -31
  1019. data/lib/ceedling/makefile.rb +0 -52
  1020. data/lib/ceedling/release_invoker.rb +0 -112
  1021. data/lib/ceedling/rules_release.rake +0 -109
  1022. data/lib/ceedling/rules_tests.rake +0 -40
  1023. data/lib/ceedling/tasks_release.rake +0 -36
  1024. data/plugins/fff/vendor/fff/Makefile +0 -10
  1025. data/plugins/fff/vendor/fff/buildandtest +0 -15
  1026. data/plugins/fff/vendor/fff/examples/Makefile +0 -7
  1027. data/plugins/fff/vendor/fff/examples/driver_testing/Makefile +0 -64
  1028. data/plugins/fff/vendor/fff/examples/driver_testing/driver.c +0 -32
  1029. data/plugins/fff/vendor/fff/examples/driver_testing/driver.h +0 -21
  1030. data/plugins/fff/vendor/fff/examples/driver_testing/driver.test.cpp +0 -58
  1031. data/plugins/fff/vendor/fff/examples/driver_testing/driver.test.fff.cpp +0 -70
  1032. data/plugins/fff/vendor/fff/examples/driver_testing/hardware_abstraction.h +0 -25
  1033. data/plugins/fff/vendor/fff/examples/driver_testing/registers.h +0 -23
  1034. data/plugins/fff/vendor/fff/examples/embedded_ui/DISPLAY.h +0 -27
  1035. data/plugins/fff/vendor/fff/examples/embedded_ui/Kata.txt +0 -25
  1036. data/plugins/fff/vendor/fff/examples/embedded_ui/Makefile +0 -67
  1037. data/plugins/fff/vendor/fff/examples/embedded_ui/SYSTEM.h +0 -31
  1038. data/plugins/fff/vendor/fff/examples/embedded_ui/UI.c +0 -56
  1039. data/plugins/fff/vendor/fff/examples/embedded_ui/UI.h +0 -22
  1040. data/plugins/fff/vendor/fff/examples/embedded_ui/UI_test_ansic.c +0 -191
  1041. data/plugins/fff/vendor/fff/examples/embedded_ui/UI_test_cpp.cpp +0 -144
  1042. data/plugins/fff/vendor/fff/examples/embedded_ui/test_suite_template.c +0 -42
  1043. data/plugins/fff/vendor/fff/gtest/Makefile +0 -22
  1044. data/plugins/fff/vendor/fff/gtest/gtest-all.cc +0 -9118
  1045. data/plugins/fff/vendor/fff/gtest/gtest-main.cc +0 -6
  1046. data/plugins/fff/vendor/fff/gtest/gtest.h +0 -19547
  1047. data/plugins/fff/vendor/fff/test/Makefile +0 -81
  1048. data/plugins/fff/vendor/fff/test/c_test_framework.h +0 -25
  1049. data/plugins/fff/vendor/fff/test/fff_test_c.c +0 -116
  1050. data/plugins/fff/vendor/fff/test/fff_test_cpp.cpp +0 -53
  1051. data/plugins/fff/vendor/fff/test/fff_test_global_c.c +0 -84
  1052. data/plugins/fff/vendor/fff/test/fff_test_global_cpp.cpp +0 -31
  1053. data/plugins/fff/vendor/fff/test/global_fakes.c +0 -21
  1054. data/plugins/fff/vendor/fff/test/global_fakes.h +0 -47
  1055. data/plugins/fff/vendor/fff/test/test_cases.include +0 -276
  1056. data/plugins/report_tests_gtestlike_stdout/assets/template.erb +0 -83
  1057. data/site-local/snapshot/assets/project.yml +0 -404
  1058. data/spec/system/partials_types_header_spec.rb +0 -166
  1059. data/spec/units/configurator_spec.rb +0 -232
  1060. /data/assets/{ceedling → features/ceedling} +0 -0
  1061. /data/assets/{ceedling.cmd → features/ceedling.cmd} +0 -0
  1062. /data/assets/{default_gitignore → features/default_gitignore} +0 -0
  1063. /data/assets/{broken_uncovered_file.c → fixtures/broken_uncovered_file.c} +0 -0
  1064. /data/assets/{example_file.c → fixtures/example_file.c} +0 -0
  1065. /data/assets/{example_file.h → fixtures/example_file.h} +0 -0
  1066. /data/assets/{example_file_call.c → fixtures/example_file_call.c} +0 -0
  1067. /data/assets/{example_file_call.h → fixtures/example_file_call.h} +0 -0
  1068. /data/assets/{example_file_with_statics.c → fixtures/example_file_with_statics.c} +0 -0
  1069. /data/assets/{example_file_with_stdio.c → fixtures/example_file_with_stdio.c} +0 -0
  1070. /data/assets/{example_file_with_stdio.h → fixtures/example_file_with_stdio.h} +0 -0
  1071. /data/assets/{fake_crash_test_fixture.rb → fixtures/fake_crash_test_fixture.rb} +0 -0
  1072. /data/assets/{partial_all_module.h → fixtures/partial_all_module.h} +0 -0
  1073. /data/assets/{run_with_ubsan.rb → fixtures/run_with_ubsan.rb} +0 -0
  1074. /data/assets/{same_dir_pairing_module.c → fixtures/same_dir_pairing_module.c} +0 -0
  1075. /data/assets/{same_dir_pairing_module.h → fixtures/same_dir_pairing_module.h} +0 -0
  1076. /data/assets/{same_dir_pairing_module_func.h → fixtures/same_dir_pairing_module_func.h} +0 -0
  1077. /data/assets/{same_dir_pairing_other.c → fixtures/same_dir_pairing_other.c} +0 -0
  1078. /data/assets/{same_dir_pairing_other.h → fixtures/same_dir_pairing_other.h} +0 -0
  1079. /data/assets/{test_example_file.c → fixtures/test_example_file.c} +0 -0
  1080. /data/assets/{test_example_file_2.c → fixtures/test_example_file_2.c} +0 -0
  1081. /data/assets/{test_example_file_source_include.c → fixtures/test_example_file_source_include.c} +0 -0
  1082. /data/assets/{test_example_file_success.c → fixtures/test_example_file_success.c} +0 -0
  1083. /data/assets/{test_example_file_unity_printf.c → fixtures/test_example_file_unity_printf.c} +0 -0
  1084. /data/assets/{test_example_file_verbose.c → fixtures/test_example_file_verbose.c} +0 -0
  1085. /data/assets/{test_example_file_with_mock.c → fixtures/test_example_file_with_mock.c} +0 -0
  1086. /data/assets/{test_example_file_with_stdio.c → fixtures/test_example_file_with_stdio.c} +0 -0
  1087. /data/assets/{test_example_with_parameterized_tests.c → fixtures/test_example_with_parameterized_tests.c} +0 -0
  1088. /data/assets/{test_partial_all_module.c → fixtures/test_partial_all_module.c} +0 -0
  1089. /data/assets/{test_same_dir_pairing.c → fixtures/test_same_dir_pairing.c} +0 -0
  1090. /data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/feature_config.h +0 -0
  1091. /data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/feature_extra.h +0 -0
  1092. /data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/local_flag_extra.h +0 -0
  1093. /data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/nested_extra.h +0 -0
  1094. /data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/nested_wrapper.h +0 -0
  1095. /data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/project_flag_extra.h +0 -0
  1096. /data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/widget_feature.h +0 -0
  1097. /data/assets/{tests_with_defines → fixtures/tests_with_defines}/src/adc_hardware.c +0 -0
  1098. /data/assets/{tests_with_defines → fixtures/tests_with_defines}/src/adc_hardware.h +0 -0
  1099. /data/assets/{tests_with_defines → fixtures/tests_with_defines}/src/adc_hardware_configurator.c +0 -0
  1100. /data/assets/{tests_with_defines → fixtures/tests_with_defines}/src/adc_hardware_configurator.h +0 -0
  1101. /data/assets/{tests_with_defines → fixtures/tests_with_defines}/test/test_adc_hardware.c +0 -0
  1102. /data/assets/{tests_with_defines → fixtures/tests_with_defines}/test/test_adc_hardware_special.c +0 -0
  1103. /data/assets/{tests_with_encoding → fixtures/tests_with_encoding}/src/unicoder.c +0 -0
  1104. /data/assets/{tests_with_encoding → fixtures/tests_with_encoding}/src/unicoder.h +0 -0
  1105. /data/assets/{tests_with_encoding → fixtures/tests_with_encoding}/test/test_unicoder.c +0 -0
  1106. /data/assets/{tests_with_encoding → fixtures/tests_with_encoding}/test/test_unicoder_partial.c +0 -0
  1107. /data/assets/{tests_with_fallback_conditionals → fixtures/tests_with_fallback_conditionals}/src/conditional_module.h +0 -0
  1108. /data/assets/{tests_with_fallback_conditionals → fixtures/tests_with_fallback_conditionals}/src/optional_dep.h +0 -0
  1109. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/src/blanks.c +0 -0
  1110. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/src/blanks.h +0 -0
  1111. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/src/counter.c +0 -0
  1112. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/src/counter.h +0 -0
  1113. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/src/decorators.c +0 -0
  1114. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/src/decorators.h +0 -0
  1115. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/test/test_blanks.c +0 -0
  1116. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/test/test_counter.c +0 -0
  1117. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/test/test_decorators.c +0 -0
  1118. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardwareA.c +0 -0
  1119. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardwareA.h +0 -0
  1120. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardwareB.c +0 -0
  1121. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardwareB.h +0 -0
  1122. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardwareC.c +0 -0
  1123. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardwareC.h +0 -0
  1124. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardware_configuratorA.h +0 -0
  1125. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardware_configuratorB.h +0 -0
  1126. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardware_configuratorC.h +0 -0
  1127. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/test/test_adc_hardwareA.c +0 -0
  1128. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/test/test_adc_hardwareB.c +0 -0
  1129. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/test/test_adc_hardwareC.c +0 -0
  1130. /data/assets/{uncovered_example_file.c → fixtures/uncovered_example_file.c} +0 -0
  1131. /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,284 +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
180
- )
181
-
182
- @partializer.validate_config( c_module: module_contents, config: config, name: name )
183
-
184
- @partializer.sanitize( module_contents )
185
-
186
- # The real header's guard is spoofed deliberately in every generated file, and the types
187
- # header carries the dependencies its extracted types name.
188
- module_include_guard = @partializer.extract_module_include_guard( config.header.filepath )
189
- types_header_includes = @partializer.remap_types_header_includes(
190
- name: config.module,
191
- includes: (config.source.includes + config.header.includes),
192
- partials: testable.partials.configs,
193
- test: name
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
+ }
194
65
  )
195
66
 
196
- # Generated once and shared by the implementation and interface headers below (via
197
- # their own includes lists), so a module tested and mocked in the same test file gets
198
- # exactly one C definition of each of its typedefs and aggregate types.
199
- types_header = @generator.generate_partial_types(
200
- name: config.module, # Module name, not test name -- two modules Partialed
201
- # in the same test file must not collide on one
202
- # shared types header filename
203
- c_module: module_contents,
204
- output_path: testable.paths[:partials],
205
- includes: types_header_includes,
206
- include_guard: module_include_guard
207
- )
67
+ mock.preprocessed_target = target
68
+ mock.stale = @dependinator.stale?( target )
208
69
 
209
- implementation = @partializer.extract_implementation_functions(
210
- test: name,
211
- partial: config.module,
212
- definitions: module_contents.function_definitions,
213
- config: config
214
- )
70
+ next if mock.stale
215
71
 
216
- interface = @partializer.extract_interface_functions(
217
- test: name,
218
- partial: config.module,
219
- definitions: module_contents.function_definitions,
220
- declarations: module_contents.function_declarations,
221
- config: config
222
- )
223
-
224
- @partializer.validate_extracted_functions(
225
- name: name,
226
- partial: config.module,
227
- impl: implementation,
228
- 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 )
229
76
  )
230
-
231
- arg_hash = {
232
- test: name,
233
- partial: config.module,
234
- function_definitions: implementation,
235
- c_module: module_contents,
236
- header_includes: @partializer.remap_implementation_header_includes(
237
- name: config.module,
238
- includes: (config.source.includes + config.header.includes),
239
- partials: testable.partials.configs,
240
- types_header: types_header,
241
- test: name
242
- ),
243
- source_includes: @partializer.remap_implementation_source_includes(
244
- name: config.module,
245
- includes: (config.source.includes + config.header.includes),
246
- partials: testable.partials.configs,
247
- test: name
248
- ),
249
- input_filepath: config.source.filepath,
250
- output_path: testable.paths[:partials],
251
- include_guard: module_include_guard
252
- }
253
-
254
- unless implementation.nil?
255
- @generator.generate_partial_implementation( **arg_hash )
256
- state.lock.synchronize { testable.partials.tests << config.module }
257
- end
258
-
259
- arg_hash = {
260
- test: name,
261
- partial: config.module,
262
- function_declarations: interface,
263
- includes: @partializer.remap_interface_header_includes(
264
- name: config.module,
265
- includes: (config.source.includes + config.header.includes),
266
- partials: testable.partials.configs,
267
- types_header: types_header,
268
- test: name
269
- ),
270
- c_module: module_contents,
271
- input_filepath: config.header.filepath,
272
- output_path: testable.paths[:partials],
273
- include_guard: module_include_guard
274
- }
275
-
276
- unless interface.nil?
277
- @generator.generate_partial_interface( **arg_hash )
278
- state.lock.synchronize { testable.partials.mocks << config.module }
279
- end
77
+ @loginator.log( msg, Verbosity::OBNOXIOUS )
78
+ skipped += 1
280
79
  end
281
- end
282
80
 
283
- # Stage 9: Preprocess header files to be mocked.
284
- def stage_preprocess_mocks(state)
285
- directives_only = @configurator.test_build_preprocess_directives_only_available
81
+ log_skip_summary( task: "mock preprocessing", count: skipped, noun: "mocks" )
286
82
 
287
83
  # Generate directive-only preprocessor output if available
288
84
  @batchinator.exec(workload: :compile, things: state.mocks_list) do |mock|
289
- details = mock[:details]
290
- testable = mock[:testable]
85
+ next unless mock.stale
86
+
87
+ details = mock.details
88
+ testable = mock.testable
291
89
  name = testable.name
292
- filepath = details[:source]
90
+ filepath = details.source
293
91
 
294
92
  arg_hash = {
295
93
  filepath: filepath,
296
94
  test: name,
297
95
  flags: testable.preprocess_flags,
298
96
  include_paths: testable.search_paths,
299
- vendor_paths: [@configurator.project_build_vendor_ceedling_path],
97
+ vendor_paths: vendor_search_paths(),
300
98
  defines: testable.preprocess_defines
301
99
  }
302
100
 
@@ -307,199 +105,371 @@ class TestBuildExecutor
307
105
  @loginator.log( msg, Verbosity::COMPLAIN )
308
106
  end
309
107
 
310
- mock[:directives_only_filepath] = _filepath
108
+ mock.directives_only_filepath = _filepath
311
109
  end if directives_only
312
110
 
313
111
  # Preprocess and assemble header files to be mocked
314
112
  @batchinator.exec(workload: :compile, things: state.mocks_list) do |mock|
315
- details = mock[:details]
316
- testable = mock[:testable]
317
- directives_only_filepath = mock[:directives_only_filepath]
113
+ next unless mock.stale
318
114
 
319
- 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)
320
119
 
321
120
  arg_hash = {
322
121
  test: testable.name,
323
- filepath: details[:source],
122
+ filepath: details.source,
324
123
  directives_only_filepath: directives_only_filepath,
325
- fallback: (!directives_only or directives_only_filepath.nil?),
124
+ fallback: directives_only_fallback?( directives_only, directives_only_filepath ),
326
125
  flags: testable.preprocess_flags,
327
126
  include_paths: testable.search_paths,
328
- vendor_paths: [@configurator.project_build_vendor_ceedling_path],
127
+ vendor_paths: vendor_search_paths(),
329
128
  defines: testable.preprocess_defines,
330
129
  extras: extras
331
130
  }
332
131
 
333
132
  @preprocessinator.preprocess_mockable_header_file( **arg_hash )
133
+
134
+ @dependinator.mark_fresh( mock.preprocessed_target )
334
135
  end
335
136
  end
336
137
 
337
138
  # Stage 10: Generate mocks for all tests.
338
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
+
339
147
  @batchinator.exec(workload: :compile, things: state.mocks_list) do |mock|
340
- details = mock[:details]
341
- testable = mock[:testable]
148
+ details = mock.details
149
+ testable = mock.testable
342
150
 
343
- 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 )
344
153
  @file_wrapper.mkdir( output_path )
345
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
+
346
188
  arg_hash = {
347
189
  context: state.context,
348
- mock: mock[:name],
190
+ mock: mock.name,
349
191
  test: testable.name,
350
- input_filepath: details[:input],
351
- output_path: output_path
192
+ input_filepath: details.input,
193
+ output_path: output_path,
194
+ folder: folder,
195
+ overrides: overrides
352
196
  }
353
197
 
354
198
  @generator.generate_mock( **arg_hash )
355
- end
356
- end
357
-
358
- # Stage 11: Preprocess test files and extract source build directives.
359
- def stage_preprocess_test_files(state)
360
- directives_only = @configurator.test_build_preprocess_directives_only_available
361
-
362
- @batchinator.exec(workload: :compile, things: state.testables) do |_, testable|
363
- filepath = testable.filepath
364
- filename = File.basename( filepath )
365
- name = testable.name
366
- directives_only_filepath = testable.preprocess[:directives_only][:filepath]
367
-
368
- fallback = (!directives_only or directives_only_filepath.nil?)
369
-
370
- arg_hash = {
371
- test: name,
372
- filepath: filepath,
373
- directives_only_filepath: directives_only_filepath,
374
- fallback: fallback,
375
- includes: @context_extractor.lookup_all_header_includes_list( testable.filepath ),
376
- flags: testable.preprocess_flags,
377
- include_paths: testable.search_paths,
378
- vendor_paths: [@configurator.project_build_vendor_ceedling_path],
379
- defines: testable.preprocess_defines
380
- }
381
-
382
- _filepath = @preprocessinator.preprocess_test_file( **arg_hash )
383
199
 
384
- state.lock.synchronize { testable.runner[:input_filepath] = _filepath }
385
-
386
- msg = @reportinator.generate_progress( "Parsing #{filename} for test source directive macros" )
387
- @loginator.log( msg )
200
+ @dependinator.mark_fresh( target )
201
+ end
388
202
 
389
- if fallback
390
- _filepath = filepath
391
- else
392
- _filepath = @file_path_utils.form_preprocessed_file_compacted_directives_only_filepath( filepath, name )
393
- end
203
+ log_skip_summary( task: "mock generation", count: skipped, noun: "mocks" )
204
+ end
394
205
 
395
- @context_extractor.collect_simple_context_from_file(
396
- _filepath,
397
- filepath,
398
- TestContextExtractor::Context::BUILD_DIRECTIVE_SOURCE_FILES
399
- )
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
400
239
 
401
- state.testables.each do |_, t|
402
- validate_build_directive_source_files( test: name, filepath: t.filepath )
403
- 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]
404
243
  end
405
- end
406
244
 
407
- # Stage 12: Collect test runner details (test case names) from preprocessed test files.
408
- def stage_collect_runner_details(state)
409
- @batchinator.exec(workload: :compile, things: state.testables) do |_, testable|
410
- msg = @reportinator.generate_module_progress(
411
- operation: 'Parsing test case names',
412
- module_name: testable.name,
413
- filename: File.basename( testable.filepath )
414
- )
415
- @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
416
249
 
417
- @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
418
261
  end
419
- end
420
262
 
421
- # Stage 13: Generate test runner files.
422
- def stage_generate_runners(state)
423
- @batchinator.exec(workload: :compile, things: state.testables) do |_, testable|
424
- arg_hash = {
425
- context: state.context,
426
- mocks: @context_extractor.lookup_mock_header_includes_list( testable.filepath ),
427
- includes: @context_extractor.lookup_nonmock_header_includes_list( testable.filepath ),
428
- test_filepath: testable.filepath,
429
- input_filepath: testable.runner[:input_filepath],
430
- runner_filepath: testable.runner[:output_filepath]
431
- }
263
+ compile_pass.call( test_file_pairs )
264
+ compile_pass.call( other_pairs )
432
265
 
433
- @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 )
434
273
  end
435
- end
436
274
 
437
- # Stage 15: Compile all test build objects in parallel.
438
- def stage_build_objects(state)
439
- @batchinator.exec(workload: :compile, things: state.objects_list) do |obj|
440
- src = @file_finder.find_build_input_file( filepath: obj[:obj], context: state.context )
441
- compile_test_component(
442
- context: state.context,
443
- test: obj[:test],
444
- source: src,
445
- object: obj[:obj],
446
- state: state
447
- )
448
- end
275
+ log_skip_summary( task: "compilation", count: skipped, noun: "objects" )
449
276
  end
450
277
 
451
278
  # Stage 16: Link test executables.
452
279
  def stage_build_executables(state)
453
280
  lib_args = convert_libraries_to_arguments()
454
281
  lib_paths = get_library_paths_to_arguments()
282
+ skipped = 0
455
283
 
456
284
  @batchinator.exec(workload: :compile, things: state.testables) do |_, testable|
457
285
  remove_partials_source_objects( testable.objects, testable.partials.configs )
458
286
 
459
- arg_hash = {
460
- context: state.context,
461
- build_path: testable.paths[:build],
462
- executable: testable.executable,
463
- objects: testable.objects,
464
- flags: testable.link_flags,
465
- lib_args: lib_args,
466
- lib_paths: lib_paths,
467
- options: state.options
468
- }
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
+ }
469
308
 
470
- 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 }
471
329
  end
330
+
331
+ log_skip_summary( task: "linking", count: skipped, noun: "executables" )
472
332
  end
473
333
 
474
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.
475
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
+
476
376
  @batchinator.exec(workload: :test, things: state.testables) do |_, testable|
477
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
+
478
428
  arg_hash = {
479
429
  context: state.context,
480
430
  test_name: testable.name,
481
431
  test_filepath: testable.filepath,
482
432
  executable: testable.executable,
483
433
  result: testable.results_pass,
484
- options: state.options
434
+ skipped: !run_now,
435
+ tool: fixture_tool
485
436
  }
486
437
 
487
- 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
488
451
 
489
452
  ensure
490
453
  @plugin_manager.post_test( testable.filepath )
491
454
  end
492
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" )
493
463
  end
494
464
 
495
465
  # -----------------------------------------------------------------------
496
466
  # Helper methods
497
467
  # -----------------------------------------------------------------------
498
468
 
499
- 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:)
500
470
  begin
501
471
  @generator.generate_executable_file(
502
- options[:test_linker],
472
+ tool,
503
473
  context,
504
474
  objects.map { |v| "\"#{v}\"" },
505
475
  flags,
@@ -509,7 +479,7 @@ class TestBuildExecutor
509
479
  lib_paths
510
480
  )
511
481
  rescue ShellException => ex
512
- if ex.shell_result[:output] =~ /symbol/i
482
+ if ex.shell_result[:output].match?(/symbol/i)
513
483
  notice = "If the linker reports missing symbols, the following may be to blame:\n" +
514
484
  " 1. This test lacks #include statements corresponding to needed source files (see note below).\n" +
515
485
  " 2. Project file paths omit source files corresponding to #include statements in this test.\n" +
@@ -520,7 +490,7 @@ class TestBuildExecutor
520
490
  end
521
491
 
522
492
  notice += "\n"
523
- 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" +
524
494
  " * By convention, Ceedling assumes header filenames correspond to source filenames.\n" +
525
495
  " * Which code files to compile and link are determined by #include statements.\n"
526
496
  if @configurator.project_use_mocks
@@ -532,7 +502,7 @@ class TestBuildExecutor
532
502
  " 1. Doublecheck this test's #include statements.\n" +
533
503
  " 2. Simplify complex macros or fully specify symbols for this test in :project ↳ :defines.\n" +
534
504
  " 3. If no header file corresponds to the needed source file, use the TEST_SOURCE_FILE()\n" +
535
- " 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" +
536
506
  "See the docs on conventions, paths, preprocessing, compilation symbols, and build directive macros.\n\n"
537
507
 
538
508
  @loginator.log( notice, Verbosity::COMPLAIN, LogLabels::NOTICE )
@@ -542,14 +512,19 @@ class TestBuildExecutor
542
512
  end
543
513
  end
544
514
 
545
- 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)
546
520
  @generator.generate_test_results(
547
- tool: options[:test_fixture],
521
+ tool: tool,
548
522
  context: context,
549
523
  test_name: test_name,
550
524
  test_filepath: test_filepath,
551
525
  executable: executable,
552
- result: result
526
+ result: result,
527
+ skipped: skipped
553
528
  )
554
529
  end
555
530
 
@@ -571,17 +546,78 @@ class TestBuildExecutor
571
546
 
572
547
  private
573
548
 
574
- # 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).
575
582
  def compile_test_component(context:, test:, source:, object:, state:)
576
583
  testable = state.testables[test.to_sym]
577
584
  defines = testable.compile_defines
578
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 )
579
587
 
580
- if @file_wrapper.extname( source ) != @configurator.extension_assembly
588
+ if !@configurator.extension_assembly.match?( source )
581
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 ) )
582
618
 
583
619
  arg_hash = {
584
- tool: @configurator.tools_test_compiler,
620
+ tool: tool,
585
621
  module_name: test,
586
622
  context: context,
587
623
  source: source,
@@ -590,16 +626,82 @@ class TestBuildExecutor
590
626
  flags: flags,
591
627
  defines: defines,
592
628
  list: @file_path_utils.form_test_build_list_filepath( object ),
593
- dependencies: @file_path_utils.form_test_dependencies_filepath( object, name: test, context: context )
629
+ dependencies: dependencies
594
630
  }
595
631
 
596
- @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
597
689
 
598
690
  elsif @configurator.test_build_use_assembly
599
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 ) )
600
702
 
601
703
  arg_hash = {
602
- tool: @configurator.tools_test_assembler,
704
+ tool: tool,
603
705
  module_name: test,
604
706
  context: context,
605
707
  source: source,
@@ -608,80 +710,332 @@ class TestBuildExecutor
608
710
  flags: flags,
609
711
  defines: defines,
610
712
  list: @file_path_utils.form_test_build_list_filepath( object ),
611
- dependencies: @file_path_utils.form_test_dependencies_filepath( object, name: test, context: context )
713
+ dependencies: dependencies
612
714
  }
613
715
 
614
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
615
724
  end
725
+
726
+ @dependinator.mark_fresh( object )
727
+
728
+ true
616
729
  end
617
730
 
618
- def tailor_search_paths(filepath:, search_paths:)
619
- _search_paths = []
620
-
621
- if filepath == File.join( PROJECT_BUILD_VENDOR_UNITY_PATH, UNITY_C_FILE )
622
- _search_paths += @configurator.collection_paths_support
623
- _search_paths << PROJECT_BUILD_VENDOR_UNITY_PATH
624
-
625
- elsif @configurator.project_use_mocks and
626
- (filepath == File.join( PROJECT_BUILD_VENDOR_CMOCK_PATH, CMOCK_C_FILE ))
627
- _search_paths += @configurator.collection_paths_support
628
- _search_paths << PROJECT_BUILD_VENDOR_UNITY_PATH
629
- _search_paths << PROJECT_BUILD_VENDOR_CMOCK_PATH
630
- _search_paths << PROJECT_BUILD_VENDOR_CEXCEPTION_PATH if @configurator.project_use_exceptions
631
-
632
- elsif @configurator.project_use_exceptions and
633
- (filepath == File.join( PROJECT_BUILD_VENDOR_CEXCEPTION_PATH, CEXCEPTION_C_FILE ))
634
- _search_paths += @configurator.collection_paths_support
635
- _search_paths << PROJECT_BUILD_VENDOR_CEXCEPTION_PATH
636
-
637
- elsif @configurator.collection_all_support.include?( filepath )
638
- _search_paths = search_paths
639
- _search_paths += @configurator.collection_paths_support
640
- _search_paths << PROJECT_BUILD_VENDOR_UNITY_PATH
641
- _search_paths << PROJECT_BUILD_VENDOR_CMOCK_PATH if @configurator.project_use_mocks
642
- _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 )
643
751
  end
644
752
 
645
- return search_paths if _search_paths.empty?
753
+ return nil
754
+ end
646
755
 
647
- 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
648
785
  end
649
786
 
650
- def validate_build_directive_source_files(test:, filepath:)
651
- 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
652
796
 
653
- ext_message = @configurator.extension_source
654
- if @configurator.test_build_use_assembly
655
- ext_message += " or #{@configurator.extension_assembly}"
656
- 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
657
812
 
658
- sources.each do |source|
659
- 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
660
820
 
661
- if not @configurator.test_build_use_assembly
662
- valid_extension = false if @file_wrapper.extname( source ) != @configurator.extension_source
663
- else
664
- ext = @file_wrapper.extname( source )
665
- valid_extension = false if (ext != @configurator.extension_assembly) and (ext != @configurator.extension_source)
666
- 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
667
832
 
668
- if not valid_extension
669
- error = "File '#{source}' specified with TEST_SOURCE_FILE() in #{test} is not a #{ext_message} source file"
670
- 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 )
671
912
  end
913
+ end
672
914
 
673
- if @file_finder.find_build_input_file( filepath: source, complain: :ignore, context: TEST_SYM ).nil?
674
- error = "File '#{source}' specified with TEST_SOURCE_FILE() in #{test} cannot be found in the source file collection"
675
- 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 )
676
933
  end
677
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 }
678
941
  end
679
942
 
680
- def remove_partials_source_objects(objects, configs)
681
- modules = configs.keys
682
- objects.delete_if do |filepath|
683
- 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
684
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
685
1039
  end
686
1040
 
687
1041
  end