ceedling 1.1.9 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1130) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +3 -0
  3. data/.simplecov +73 -0
  4. data/GIT_COMMIT_SHA +1 -1
  5. data/Gemfile +84 -8
  6. data/Gemfile.lock +38 -8
  7. data/README.md +53 -30
  8. data/Rakefile +768 -16
  9. data/assets/{project.yml → features/project.yml} +4 -1
  10. data/assets/fixtures/bullseye_branch_coverage/src/branchy.c +24 -0
  11. data/assets/fixtures/bullseye_branch_coverage/src/branchy.h +14 -0
  12. data/assets/fixtures/bullseye_branch_coverage/test/test_branchy.c +18 -0
  13. data/assets/fixtures/cppcheck_findings/findings.c +23 -0
  14. data/assets/fixtures/cppcheck_findings/findings.h +13 -0
  15. data/assets/fixtures/header_include_path_validation/alt_drivers/foo.h +6 -0
  16. data/assets/fixtures/header_include_path_validation/bar.h +6 -0
  17. data/assets/fixtures/header_include_path_validation/drivers/foo.h +6 -0
  18. data/assets/fixtures/header_include_path_validation/dup.h +6 -0
  19. data/assets/fixtures/header_include_path_validation/other_inc/dup.h +6 -0
  20. data/assets/fixtures/header_include_path_validation/test_ambiguous_mock.c +15 -0
  21. data/assets/fixtures/header_include_path_validation/test_bare_mock.c +11 -0
  22. data/assets/fixtures/header_include_path_validation/test_bogus_mock_path.c +11 -0
  23. data/assets/fixtures/header_include_path_validation/test_bogus_vanilla_path.c +10 -0
  24. data/assets/fixtures/header_include_path_validation/test_include_outranks_test_include_path.c +16 -0
  25. data/assets/fixtures/header_include_path_validation/test_pathed_mock.c +11 -0
  26. data/assets/fixtures/header_include_path_validation/test_pathed_mock_ambiguous.c +14 -0
  27. data/assets/fixtures/header_include_path_validation/test_test_include_path_outranks_include.c +17 -0
  28. data/assets/fixtures/implicit_source_header_correspondence/alpha/dup.c +6 -0
  29. data/assets/fixtures/implicit_source_header_correspondence/alpha/dup.h +6 -0
  30. data/assets/fixtures/implicit_source_header_correspondence/beta/dup.c +6 -0
  31. data/assets/fixtures/implicit_source_header_correspondence/beta/dup.h +6 -0
  32. data/assets/fixtures/implicit_source_header_correspondence/gamma/dup_gamma.c +6 -0
  33. data/assets/fixtures/implicit_source_header_correspondence/test_dup_alpha.c +10 -0
  34. data/assets/fixtures/implicit_source_header_correspondence/test_dup_bare.c +10 -0
  35. data/assets/fixtures/implicit_source_header_correspondence/test_dup_beta.c +10 -0
  36. data/assets/fixtures/implicit_source_header_correspondence/test_dup_override.c +19 -0
  37. data/assets/fixtures/implicit_source_header_correspondence/test_dup_subtractive.c +19 -0
  38. data/assets/fixtures/implicit_source_header_correspondence/test_dup_subtractive_noop.c +16 -0
  39. data/assets/fixtures/parent_directory_references/alpha/extra.c +4 -0
  40. data/assets/fixtures/parent_directory_references/common/helper.c +6 -0
  41. data/assets/fixtures/parent_directory_references/common/helper.h +6 -0
  42. data/assets/fixtures/parent_directory_references/unit/test_dotdot_include.c +10 -0
  43. data/assets/fixtures/parent_directory_references/unit/test_dotdot_source.c +16 -0
  44. data/assets/fixtures/plain_inline_module.h +9 -0
  45. data/assets/fixtures/same_named_modules/include/drivers/spi/config.h +6 -0
  46. data/assets/fixtures/same_named_modules/include/drivers/uart/config.h +6 -0
  47. data/assets/fixtures/same_named_modules/src/drivers/spi/config.c +8 -0
  48. data/assets/fixtures/same_named_modules/src/drivers/uart/config.c +10 -0
  49. data/assets/fixtures/same_named_modules/test/test_both_configs.c +26 -0
  50. data/assets/fixtures/same_named_modules/test/test_both_configs_mocked.c +20 -0
  51. data/assets/fixtures/same_named_modules/test/test_both_configs_mocked_traditional.c +19 -0
  52. data/assets/fixtures/same_named_modules/test/test_both_modules.c +19 -0
  53. data/assets/fixtures/same_named_modules/test/test_uart_config_bare.c +19 -0
  54. data/assets/fixtures/same_named_modules/test/test_uart_config_partial_only.c +20 -0
  55. data/assets/fixtures/sources_with_duplicate_basenames/baz/bar.c +6 -0
  56. data/assets/fixtures/sources_with_duplicate_basenames/baz/bar.h +6 -0
  57. data/assets/fixtures/sources_with_duplicate_basenames/foo/bar.c +6 -0
  58. data/assets/fixtures/sources_with_duplicate_basenames/foo/bar.h +6 -0
  59. data/assets/fixtures/sources_with_duplicate_basenames/main.c +11 -0
  60. data/assets/fixtures/sources_with_duplicate_basenames/test_baz_bar.c +10 -0
  61. data/assets/fixtures/sources_with_duplicate_basenames/test_both_bars.c +12 -0
  62. data/assets/fixtures/sources_with_duplicate_basenames/test_foo_bar.c +10 -0
  63. data/assets/{test_example_file_boom.c → fixtures/test_nosanitize_boom.c} +9 -0
  64. data/assets/{test_example_file_crash_assert.c → fixtures/test_nosanitize_crash_assert.c} +8 -0
  65. data/assets/{test_example_file_crash_sigsegv.c → fixtures/test_nosanitize_crash_sigsegv.c} +8 -0
  66. data/assets/{test_example_file_crash_sigsegv_with_param.c → fixtures/test_nosanitize_crash_sigsegv_with_param.c} +8 -0
  67. data/assets/fixtures/test_nosanitize_heap_buffer_overflow.c +31 -0
  68. data/assets/fixtures/test_nosanitize_leak.c +34 -0
  69. data/assets/fixtures/test_nosanitize_two_findings.c +36 -0
  70. data/assets/{test_example_file_ub_shift_overflow.c → fixtures/test_nosanitize_ub_shift_overflow.c} +9 -0
  71. data/assets/fixtures/test_plain_inline_module.c +15 -0
  72. data/assets/fixtures/test_source_file_duplicate_basenames/alpha/calc.c +4 -0
  73. data/assets/fixtures/test_source_file_duplicate_basenames/beta/calc.c +4 -0
  74. data/assets/fixtures/test_source_file_duplicate_basenames/test_calc_alpha.c +15 -0
  75. data/assets/fixtures/test_source_file_duplicate_basenames/test_calc_ambiguous.c +15 -0
  76. data/assets/fixtures/test_source_file_duplicate_basenames/test_calc_beta.c +15 -0
  77. data/assets/fixtures/tests_with_conditional_includes/src/feature_extra2.h +13 -0
  78. data/assets/fixtures/tests_with_conditional_includes/src/macro_target_extra.h +13 -0
  79. data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/widget.c +19 -3
  80. data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/widget.h +1 -0
  81. data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/widget_feature.c +17 -1
  82. data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/test/test_widget.c +12 -4
  83. data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/test/test_widget_feature.c +8 -5
  84. data/assets/fixtures/tests_with_conditional_mocks/src/Case_01.c +7 -0
  85. data/assets/fixtures/tests_with_conditional_mocks/src/Case_01.h +6 -0
  86. data/assets/fixtures/tests_with_conditional_mocks/src/Case_02.c +16 -0
  87. data/assets/fixtures/tests_with_conditional_mocks/src/Case_02.h +6 -0
  88. data/assets/fixtures/tests_with_conditional_mocks/src/FeatureConfig.h +6 -0
  89. data/assets/fixtures/tests_with_conditional_mocks/src/Gpt.h +6 -0
  90. data/assets/fixtures/tests_with_conditional_mocks/src/MyModuleConfig.h +17 -0
  91. data/assets/fixtures/tests_with_conditional_mocks/src/MyModulePart1.h +6 -0
  92. data/assets/fixtures/tests_with_conditional_mocks/src/MyModulePart2.h +6 -0
  93. data/assets/fixtures/tests_with_conditional_mocks/src/drivers/widget.h +6 -0
  94. data/assets/fixtures/tests_with_conditional_mocks/src/reader.c +7 -0
  95. data/assets/fixtures/tests_with_conditional_mocks/src/reader.h +6 -0
  96. data/assets/fixtures/tests_with_conditional_mocks/test/test_Case_01.c +21 -0
  97. data/assets/fixtures/tests_with_conditional_mocks/test/test_Case_01_legacy.c +16 -0
  98. data/assets/fixtures/tests_with_conditional_mocks/test/test_Case_02.c +31 -0
  99. data/assets/fixtures/tests_with_conditional_mocks/test/test_FeatureConfig.c +15 -0
  100. data/assets/fixtures/tests_with_conditional_mocks/test/test_reader.c +13 -0
  101. data/assets/fixtures/tests_with_duplicate_test_names/integration/test_foo.c +21 -0
  102. data/assets/fixtures/tests_with_duplicate_test_names/unit/test_foo.c +21 -0
  103. data/assets/fixtures/tests_with_fallback_conditionals/src/conditional_module.c +28 -0
  104. data/assets/{tests_with_fallback_conditionals → fixtures/tests_with_fallback_conditionals}/test/test_conditionals.c +8 -1
  105. data/assets/fixtures/tests_with_multiple_assembly_extensions/src/asm_helper_lower.s +2 -0
  106. data/assets/fixtures/tests_with_multiple_assembly_extensions/src/asm_helper_upper.S +13 -0
  107. data/assets/fixtures/tests_with_multiple_assembly_extensions/src/counter_module.c +13 -0
  108. data/assets/fixtures/tests_with_multiple_assembly_extensions/src/counter_module.h +13 -0
  109. data/assets/fixtures/tests_with_multiple_assembly_extensions/test/test_counter_module.c +27 -0
  110. data/assets/fixtures/tests_with_subdir_includes/src/module/app/config.h +13 -0
  111. data/assets/fixtures/tests_with_subdir_includes/src/module/drivers/config.h +13 -0
  112. data/assets/fixtures/tests_with_subdir_includes/src/module/sensor.c +30 -0
  113. data/assets/fixtures/tests_with_subdir_includes/src/module/sensor.h +13 -0
  114. data/assets/fixtures/tests_with_subdir_includes/src/shared/config.h +13 -0
  115. data/assets/fixtures/tests_with_subdir_includes/test/test_sensor.c +32 -0
  116. data/bin/actionator.rb +234 -0
  117. data/bin/app_cfg.rb +7 -0
  118. data/bin/cli.rb +78 -47
  119. data/bin/cli_handler.rb +89 -57
  120. data/bin/cli_helper.rb +90 -49
  121. data/bin/cli_options_transform.rb +22 -0
  122. data/bin/{configinator.rb → composinator.rb} +39 -32
  123. data/bin/mixin_resolvinator.rb +124 -0
  124. data/bin/mixin_standardizer.rb +31 -61
  125. data/bin/mixinator.rb +27 -29
  126. data/bin/mixins.rb +0 -5
  127. data/bin/objects.yml +20 -7
  128. data/bin/path_validator.rb +6 -5
  129. data/bin/projectinator.rb +51 -142
  130. data/bin/rake_patches.rb +36 -2
  131. data/bin/recursive_merger.rb +7 -1
  132. data/bin/versionator.rb +2 -3
  133. data/ceedling.gemspec +83 -12
  134. data/docs/BreakingChanges.md +46 -2
  135. data/docs/CONTRIBUTING.md +45 -29
  136. data/docs/CeedlingPullRequestChecklist.md +10 -9
  137. data/docs/Changelog.md +337 -37
  138. data/docs/KnownIssues.md +39 -4
  139. data/docs/ReleaseNotes.md +288 -12
  140. data/docs/SECURITY.md +86 -4
  141. data/docs/ThrowTheSwitchCodingStandard.md +21 -3
  142. data/docs/overrides/main.html +32 -0
  143. data/examples/temp_sensor/mixin/add_bullseye.yml +19 -0
  144. data/examples/wondrous_forest/README.md +3 -0
  145. data/examples/wondrous_forest/src/sensors/light/Calibration.c +21 -0
  146. data/examples/wondrous_forest/src/sensors/light/Calibration.h +14 -0
  147. data/examples/wondrous_forest/src/sensors/soil/Calibration.c +23 -0
  148. data/examples/wondrous_forest/src/sensors/soil/Calibration.h +14 -0
  149. data/examples/wondrous_forest/test/TestCalibration.c +39 -0
  150. data/lib/ceedling/batchinator.rb +81 -22
  151. data/lib/ceedling/c_extractor/README.md +61 -0
  152. data/lib/ceedling/c_extractor/c_extractor.rb +33 -2
  153. data/lib/ceedling/c_extractor/c_extractor_code_text.rb +18 -10
  154. data/lib/ceedling/c_extractor/c_extractor_constants.rb +10 -10
  155. data/lib/ceedling/c_extractor/c_extractor_declarations.rb +14 -14
  156. data/lib/ceedling/c_extractor/c_extractor_functions.rb +10 -13
  157. data/lib/ceedling/c_extractor/c_extractor_preprocessing.rb +77 -0
  158. data/lib/ceedling/c_extractor/c_extractor_types.rb +8 -5
  159. data/lib/ceedling/ceedling.h +33 -0
  160. data/lib/ceedling/config/config_matchinator.rb +36 -13
  161. data/lib/ceedling/config/configurator.rb +366 -530
  162. data/lib/ceedling/config/configurator_builder.rb +253 -365
  163. data/lib/ceedling/config/configurator_plugins.rb +68 -102
  164. data/lib/ceedling/config/configurator_setup.rb +343 -610
  165. data/lib/ceedling/config/configurator_validator.rb +114 -142
  166. data/lib/ceedling/config/line_marker_suppressors.rb +67 -0
  167. data/lib/ceedling/constants.rb +60 -6
  168. data/lib/ceedling/defaults.rb +28 -14
  169. data/lib/ceedling/defineinator.rb +9 -4
  170. data/lib/ceedling/dependencies/README.md +69 -0
  171. data/lib/ceedling/dependencies/dependency_cache_store.rb +160 -0
  172. data/lib/ceedling/dependencies/dependency_debug_tree.rb +129 -0
  173. data/lib/ceedling/dependencies/dependency_differ.rb +127 -0
  174. data/lib/ceedling/dependencies/dependency_hasher.rb +94 -0
  175. data/lib/ceedling/dependencies/dependency_path_normalizer.rb +80 -0
  176. data/lib/ceedling/dependencies/dependency_tracker.rb +405 -0
  177. data/lib/ceedling/dependencies/dependinator.rb +65 -0
  178. data/lib/ceedling/dependencies/gcc_dependency_parser.rb +86 -0
  179. data/lib/ceedling/encodinator.rb +23 -11
  180. data/lib/ceedling/file_finder.rb +373 -89
  181. data/lib/ceedling/file_finder_helper.rb +44 -33
  182. data/lib/ceedling/file_path_collection_utils.rb +17 -4
  183. data/lib/ceedling/file_path_utils.rb +310 -52
  184. data/lib/ceedling/file_wrapper.rb +245 -8
  185. data/lib/ceedling/filename_extension.rb +91 -0
  186. data/lib/ceedling/flaginator.rb +6 -2
  187. data/lib/ceedling/generators/generator.rb +202 -75
  188. data/lib/ceedling/generators/generator_helper.rb +116 -69
  189. data/lib/ceedling/generators/generator_mocks.rb +13 -8
  190. data/lib/ceedling/generators/generator_partials.rb +93 -25
  191. data/lib/ceedling/generators/generator_test_results.rb +29 -17
  192. data/lib/ceedling/generators/generator_test_results_backtrace.rb +199 -107
  193. data/lib/ceedling/generators/generator_test_results_sanity_checker.rb +1 -1
  194. data/lib/ceedling/includes/include_factory.rb +21 -6
  195. data/lib/ceedling/includes/include_pathinator.rb +40 -4
  196. data/lib/ceedling/includes/includes.rb +215 -61
  197. data/lib/ceedling/loginator.rb +13 -4
  198. data/lib/ceedling/objects.yml +218 -33
  199. data/lib/ceedling/parsing_parcels.rb +39 -13
  200. data/lib/ceedling/partials/README.md +53 -0
  201. data/lib/ceedling/partials/partializer.rb +272 -117
  202. data/lib/ceedling/partials/partializer_config.rb +141 -8
  203. data/lib/ceedling/partials/partializer_helper.rb +88 -2
  204. data/lib/ceedling/partials/partializer_utils.rb +1 -1
  205. data/lib/ceedling/partials/partials.rb +4 -4
  206. data/lib/ceedling/path_matcher.rb +163 -0
  207. data/lib/ceedling/path_mirror.rb +73 -0
  208. data/lib/ceedling/plugins/plugin.rb +1 -1
  209. data/lib/ceedling/plugins/plugin_manager.rb +31 -15
  210. data/lib/ceedling/plugins/plugin_manager_helper.rb +5 -1
  211. data/lib/ceedling/plugins/plugin_reportinator.rb +36 -7
  212. data/lib/ceedling/plugins/plugin_reportinator_helper.rb +3 -3
  213. data/lib/ceedling/plugins/report_log_writer_plugin.rb +66 -0
  214. data/lib/ceedling/plugins/report_tests_stdout_plugin.rb +18 -5
  215. data/lib/ceedling/preprocess/README.md +135 -120
  216. data/lib/ceedling/preprocess/c_comment_scanner.rb +9 -7
  217. data/lib/ceedling/preprocess/c_preprocessor_conditionals.rb +27 -10
  218. data/lib/ceedling/preprocess/preprocessinator.rb +253 -217
  219. data/lib/ceedling/preprocess/preprocessinator_bare_includes_extractor.rb +7 -10
  220. data/lib/ceedling/preprocess/preprocessinator_code_finder.rb +8 -6
  221. data/lib/ceedling/preprocess/preprocessinator_comment_stripper.rb +5 -3
  222. data/lib/ceedling/preprocess/preprocessinator_file_assembler.rb +86 -82
  223. data/lib/ceedling/preprocess/preprocessinator_includes_handler.rb +182 -163
  224. data/lib/ceedling/preprocess/preprocessinator_line_marker_includes_extractor.rb +174 -8
  225. data/lib/ceedling/preprocess/preprocessinator_reconstructor.rb +41 -20
  226. data/lib/ceedling/quote_include_isolator.rb +129 -0
  227. data/lib/ceedling/rake_app/rake_task_registry.rb +9 -9
  228. data/lib/ceedling/rake_app/rake_wrapper.rb +0 -13
  229. data/lib/ceedling/rake_app/rakefile_component_resolver.rb +24 -12
  230. data/lib/ceedling/rakefile.rb +2 -1
  231. data/lib/ceedling/{tasks_base.rake → rakefiles/base/tasks_base.rake} +1 -1
  232. data/lib/ceedling/{tasks_filesystem.rake → rakefiles/base/tasks_filesystem.rake} +3 -0
  233. data/lib/ceedling/rakefiles/release/rules_release.rake +52 -0
  234. data/lib/ceedling/{erb_wrapper.rb → rakefiles/release/tasks_release.rake} +5 -8
  235. data/lib/ceedling/rakefiles/tests/rules_tests.rake +43 -0
  236. data/lib/ceedling/rakefiles/tests/rules_tests_generate.rake +80 -0
  237. data/lib/ceedling/{tasks_tests.rake → rakefiles/tests/tasks_tests.rake} +11 -20
  238. data/lib/ceedling/rakefiles/tests/tasks_tests_generate.rake +55 -0
  239. data/lib/ceedling/release_invoker/README.md +35 -0
  240. data/lib/ceedling/release_invoker/release_build_executor.rb +263 -0
  241. data/lib/ceedling/release_invoker/release_build_planner.rb +80 -0
  242. data/lib/ceedling/release_invoker/release_invoker.rb +78 -0
  243. data/lib/ceedling/release_invoker/release_invoker_types.rb +40 -0
  244. data/lib/ceedling/reportinator.rb +18 -2
  245. data/lib/ceedling/ruby_expandinator.rb +40 -1
  246. data/lib/ceedling/setupinator.rb +9 -3
  247. data/lib/ceedling/system_wrapper.rb +17 -0
  248. data/lib/ceedling/templateinator.rb +146 -0
  249. data/lib/ceedling/test_context_extractor.rb +59 -28
  250. data/lib/ceedling/test_invoker/HEADER_COLLISIONS.md +41 -0
  251. data/lib/ceedling/test_invoker/PIPELINE.md +142 -0
  252. data/lib/ceedling/test_invoker/README.md +6 -0
  253. data/lib/ceedling/test_invoker/mock_locator.rb +49 -0
  254. data/lib/ceedling/test_invoker/partials_manager.rb +426 -0
  255. data/lib/ceedling/test_invoker/standin_headerinator.rb +136 -0
  256. data/lib/ceedling/test_invoker/test_bare_includes_extractinator.rb +117 -0
  257. data/lib/ceedling/test_invoker/test_build_executor.rb +783 -415
  258. data/lib/ceedling/test_invoker/test_build_planner.rb +175 -70
  259. data/lib/ceedling/test_invoker/test_build_setup.rb +132 -241
  260. data/lib/ceedling/test_invoker/test_build_validations.rb +102 -0
  261. data/lib/ceedling/test_invoker/test_file_preprocessinator.rb +148 -0
  262. data/lib/ceedling/test_invoker/test_includes_extractinator.rb +34 -0
  263. data/lib/ceedling/test_invoker/test_includes_preprocessinator.rb +118 -0
  264. data/lib/ceedling/test_invoker/test_includes_reconcilinator.rb +149 -0
  265. data/lib/ceedling/test_invoker/test_invoker.rb +16 -183
  266. data/lib/ceedling/test_invoker/test_invoker_types.rb +85 -16
  267. data/lib/ceedling/test_invoker/test_pipeline_helpers.rb +121 -0
  268. data/lib/ceedling/test_invoker/test_pipeline_manager.rb +303 -0
  269. data/lib/ceedling/test_invoker/test_runner_generatinator.rb +105 -0
  270. data/lib/ceedling/test_invoker/test_search_paths.rb +73 -0
  271. data/lib/ceedling/test_invoker/test_source_file_directive_resolver.rb +78 -0
  272. data/lib/ceedling/tool_executor.rb +42 -13
  273. data/lib/ceedling/tool_executor_helper.rb +1 -1
  274. data/lib/ceedling/tool_validator.rb +124 -123
  275. data/lib/ceedling/yaml_wrapper.rb +5 -3
  276. data/lib/version.rb +19 -2
  277. data/mkdocs.prerelease.yml +42 -0
  278. data/mkdocs.yml +10 -2
  279. data/plugins/bullseye/bullseye.rake +70 -107
  280. data/plugins/bullseye/config/defaults.yml +12 -54
  281. data/plugins/bullseye/config/defaults_bullseye.rb +182 -0
  282. data/plugins/bullseye/lib/bullseye.rb +511 -120
  283. data/plugins/bullseye/lib/bullseye_constants.rb +100 -0
  284. data/plugins/command_hooks/lib/command_hooks.rb +117 -199
  285. data/plugins/compile_commands_json_db/lib/compile_commands_json_db.rb +72 -27
  286. data/plugins/cppcheck/config/defaults.yml +6 -1
  287. data/plugins/cppcheck/config/defaults_cppcheck.rb +5 -1
  288. data/plugins/cppcheck/cppcheck.rake +7 -1
  289. data/plugins/cppcheck/lib/cppcheck.rb +175 -26
  290. data/plugins/cppcheck/lib/cppcheck_constants.rb +12 -0
  291. data/plugins/cppcheck/lib/cppcheck_reports.rb +5 -1
  292. data/plugins/dependencies/Rakefile +14 -2
  293. data/plugins/dependencies/config/defaults.yml +9 -6
  294. data/plugins/dependencies/dependencies.rake +46 -76
  295. data/plugins/dependencies/example/boss/project.yml +1 -1
  296. data/plugins/dependencies/example/supervisor/project.yml +1 -1
  297. data/plugins/dependencies/example/version.tar.gzip +0 -0
  298. data/plugins/dependencies/lib/dependencies.rb +232 -427
  299. data/plugins/dependencies/lib/dependency_commands.rb +72 -0
  300. data/plugins/dependencies/lib/dependency_environment.rb +57 -0
  301. data/plugins/dependencies/lib/dependency_spec.rb +145 -0
  302. data/plugins/fff/.rspec +1 -0
  303. data/plugins/fff/Rakefile +14 -2
  304. data/plugins/fff/examples/fff_example/project.yml +1 -1
  305. data/plugins/fff/lib/fff.rb +30 -9
  306. data/plugins/fff/lib/fff_mock_generator.rb +142 -128
  307. data/plugins/fff/spec/fff_mock_header_generator_spec.rb +15 -0
  308. data/plugins/fff/spec/fff_mock_source_generator_spec.rb +14 -0
  309. data/plugins/fff/spec/spec_helper.rb +45 -0
  310. data/plugins/fff/src/fff_unity_helper.h +5 -0
  311. data/plugins/fff/vendor/fff/fakegen.rb +5 -4
  312. data/plugins/fff/vendor/fff/fff.h +4 -4
  313. data/plugins/gcov/config/defaults.yml +5 -0
  314. data/plugins/gcov/gcov.rake +12 -8
  315. data/plugins/gcov/lib/console_reportinator.rb +140 -20
  316. data/plugins/gcov/lib/gcov.rb +155 -60
  317. data/plugins/gcov/lib/gcov_constants.rb +4 -7
  318. data/plugins/gcov/lib/gcov_reportinator.rb +90 -0
  319. data/plugins/gcov/lib/gcov_types.rb +62 -1
  320. data/plugins/gcov/lib/gcovr_reportinator.rb +255 -213
  321. data/plugins/gcov/lib/reportgenerator_reportinator.rb +122 -44
  322. data/plugins/module_generator/Rakefile +4 -4
  323. data/plugins/module_generator/config/module_generator.yml +0 -1
  324. data/plugins/module_generator/example/project.yml +1 -1
  325. data/plugins/module_generator/lib/module_generator.rb +117 -87
  326. data/plugins/module_generator/lib/module_generator_options.rb +150 -0
  327. data/plugins/module_generator/lib/module_generator_project.rb +45 -0
  328. data/plugins/module_generator/lib/module_generator_request.rb +83 -0
  329. data/plugins/module_generator/lib/module_generator_test_file.rb +68 -0
  330. data/plugins/module_generator/lib/module_generator_unity.rb +24 -0
  331. data/plugins/module_generator/module_generator.rake +24 -46
  332. data/plugins/report_build_warnings_log/config/defaults.yml +4 -1
  333. data/plugins/report_build_warnings_log/lib/report_build_warnings_log.rb +47 -55
  334. data/plugins/report_build_warnings_log/lib/warning_collector.rb +140 -0
  335. data/plugins/report_build_warnings_log/lib/warning_reports.rb +135 -0
  336. data/plugins/report_tests_gtestlike_stdout/assets/test_results.template +3 -0
  337. data/{spec/units/configurator_builder_spec.rb → plugins/report_tests_gtestlike_stdout/config/defaults.yml} +6 -10
  338. data/plugins/report_tests_gtestlike_stdout/lib/gtestlike_report.rb +168 -0
  339. data/plugins/report_tests_gtestlike_stdout/lib/report_tests_gtestlike_stdout.rb +25 -1
  340. data/plugins/report_tests_ide_stdout/assets/test_results.template +50 -0
  341. data/plugins/report_tests_ide_stdout/config/defaults.yml +13 -0
  342. data/plugins/report_tests_ide_stdout/lib/ide_report_lines.rb +103 -0
  343. data/plugins/report_tests_ide_stdout/lib/report_tests_ide_stdout.rb +12 -4
  344. data/plugins/report_tests_log_factory/lib/cppunit_tests_reporter.rb +33 -51
  345. data/plugins/report_tests_log_factory/lib/html_tests_reporter.rb +286 -295
  346. data/plugins/report_tests_log_factory/lib/json_tests_reporter.rb +22 -35
  347. data/plugins/report_tests_log_factory/lib/junit_tests_reporter.rb +91 -133
  348. data/plugins/report_tests_log_factory/lib/report_tests_log_factory.rb +72 -86
  349. data/plugins/report_tests_log_factory/lib/tests_reporter.rb +31 -12
  350. data/plugins/report_tests_pretty_stdout/assets/{template.erb → test_results.template} +8 -8
  351. data/plugins/report_tests_raw_output_log/lib/report_tests_raw_output_log.rb +18 -48
  352. data/plugins/report_tests_teamcity_stdout/lib/report_tests_teamcity_stdout.rb +13 -2
  353. data/plugins/sanitize/config/defaults.yml +44 -0
  354. data/plugins/sanitize/config/defaults_sanitize.rb +20 -0
  355. data/plugins/sanitize/lib/sanitize.rb +174 -0
  356. data/plugins/sanitize/lib/sanitize_config.rb +110 -0
  357. data/plugins/sanitize/lib/sanitize_constants.rb +13 -0
  358. data/plugins/sanitize/lib/sanitize_findings.rb +85 -0
  359. data/plugins/sanitize/lib/sanitize_records.rb +115 -0
  360. data/plugins/sanitize/lib/sanitize_reports.rb +135 -0
  361. data/plugins/sanitize/sanitize.rake +108 -0
  362. data/plugins/valgrind/config/defaults.yml +7 -1
  363. data/plugins/valgrind/config/defaults_valgrind.rb +6 -1
  364. data/plugins/valgrind/lib/valgrind.rb +202 -39
  365. data/plugins/valgrind/lib/valgrind_constants.rb +4 -0
  366. data/plugins/valgrind/lib/valgrind_report.rb +52 -0
  367. data/plugins/valgrind/valgrind.rake +33 -11
  368. data/site-local/404.html +248 -14
  369. data/site-local/configuration/environment-vars.html +248 -14
  370. data/site-local/configuration/global-collections.html +248 -19
  371. data/site-local/configuration/index.html +249 -15
  372. data/site-local/configuration/loading.html +260 -22
  373. data/site-local/configuration/mixins.html +252 -17
  374. data/site-local/configuration/parallel-builds.html +248 -14
  375. data/site-local/configuration/project-file.html +275 -30
  376. data/site-local/configuration/reference/cexception.html +255 -20
  377. data/site-local/configuration/reference/cmock.html +281 -14
  378. data/site-local/configuration/reference/defines.html +262 -19
  379. data/site-local/configuration/reference/environment.html +251 -17
  380. data/site-local/configuration/reference/extension.html +361 -16
  381. data/site-local/configuration/reference/files.html +262 -14
  382. data/site-local/configuration/reference/flags.html +270 -19
  383. data/site-local/configuration/reference/index.html +248 -14
  384. data/site-local/configuration/reference/libraries.html +248 -14
  385. data/site-local/configuration/reference/mixins.html +248 -14
  386. data/site-local/configuration/reference/partials.html +249 -19
  387. data/site-local/configuration/reference/paths.html +275 -15
  388. data/site-local/configuration/reference/plugins.html +248 -14
  389. data/site-local/configuration/reference/project.html +291 -14
  390. data/site-local/configuration/reference/release-build.html +256 -14
  391. data/site-local/configuration/reference/test-build.html +290 -24
  392. data/site-local/configuration/reference/test-runner.html +288 -17
  393. data/site-local/configuration/reference/tools.html +254 -14
  394. data/site-local/configuration/reference/unity.html +280 -15
  395. data/site-local/configuration/which-ceedling.html +248 -14
  396. data/site-local/development/index.html +261 -14
  397. data/site-local/development/plugins/configuration.html +269 -17
  398. data/site-local/development/plugins/index.html +267 -15
  399. data/site-local/development/plugins/plugin-subclass.html +906 -154
  400. data/site-local/development/plugins/rake-tasks.html +276 -14
  401. data/site-local/development/releases.html +4708 -0
  402. data/site-local/development/workflow.html +1030 -51
  403. data/site-local/getting-started/builds.html +4607 -0
  404. data/site-local/getting-started/command-line.html +418 -34
  405. data/site-local/getting-started/example-projects/cipher-quest.html +248 -14
  406. data/site-local/getting-started/example-projects/index.html +249 -15
  407. data/site-local/getting-started/example-projects/temp-sensor.html +248 -14
  408. data/site-local/getting-started/example-projects/wondrous-forest.html +248 -14
  409. data/site-local/getting-started/index.html +255 -14
  410. data/site-local/getting-started/installation.html +258 -22
  411. data/site-local/getting-started/quick-start.html +251 -15
  412. data/site-local/help.html +255 -14
  413. data/site-local/index.html +292 -22
  414. data/site-local/overview/build-system.html +249 -15
  415. data/site-local/overview/index.html +248 -14
  416. data/site-local/overview/test-environments.html +257 -14
  417. data/site-local/overview/tools-and-frameworks.html +248 -14
  418. data/site-local/plugins/beep.html +251 -14
  419. data/site-local/plugins/bullseye/index.html +5079 -0
  420. data/site-local/plugins/bullseye/licensing.html +4840 -0
  421. data/site-local/plugins/command-hooks.html +265 -27
  422. data/site-local/plugins/compile-commands-json-db.html +256 -17
  423. data/site-local/plugins/cppcheck.html +1081 -262
  424. data/site-local/plugins/dependencies.html +934 -242
  425. data/site-local/plugins/fff.html +297 -16
  426. data/site-local/plugins/gcov/examples.html +251 -14
  427. data/site-local/plugins/gcov/gcovr.html +686 -31
  428. data/site-local/plugins/gcov/index.html +251 -14
  429. data/site-local/plugins/gcov/overview.html +259 -18
  430. data/site-local/plugins/gcov/reportgenerator.html +563 -28
  431. data/site-local/plugins/gcov/reporting.html +348 -100
  432. data/site-local/plugins/gcov/setup.html +253 -15
  433. data/site-local/plugins/gcov/tool-versions.html +301 -19
  434. data/site-local/plugins/gcov/troubleshooting.html +273 -36
  435. data/site-local/plugins/index.html +294 -36
  436. data/site-local/plugins/module-generator.html +779 -195
  437. data/site-local/plugins/report-build-warnings-log.html +578 -33
  438. data/site-local/plugins/report-tests-gtestlike-stdout.html +467 -84
  439. data/site-local/plugins/report-tests-ide-stdout.html +654 -51
  440. data/site-local/plugins/report-tests-log-factory.html +337 -70
  441. data/site-local/plugins/report-tests-pretty-stdout.html +251 -14
  442. data/site-local/plugins/report-tests-raw-output-log.html +251 -14
  443. data/site-local/plugins/report-tests-teamcity-stdout.html +251 -14
  444. data/site-local/plugins/sanitize.html +5332 -0
  445. data/site-local/plugins/valgrind.html +416 -26
  446. data/site-local/{plugins/bullseye.html → project/index.html} +297 -217
  447. data/site-local/project/release-history.html +251 -17
  448. data/site-local/project/sbom.html +4726 -0
  449. data/site-local/project/upgrade.html +250 -16
  450. data/site-local/reference/build-directives.html +257 -14
  451. data/site-local/reference/command-line.html +373 -16
  452. data/site-local/reference/environment-vars.html +248 -14
  453. data/site-local/reference/gcov-plugin.html +492 -18
  454. data/site-local/reference/global-collections.html +249 -15
  455. data/site-local/reference/index.html +248 -14
  456. data/site-local/reference/partials-macros.html +258 -14
  457. data/site-local/reference/project-configuration.html +248 -14
  458. data/site-local/sitemap.xml.gz +0 -0
  459. data/site-local/snapshot/assets/{project.yml → features/project.yml} +4 -1
  460. data/site-local/snapshot/examples/cipher_quest/index.html +248 -14
  461. data/site-local/snapshot/examples/temp_sensor/index.html +248 -14
  462. data/site-local/snapshot/examples/wondrous_forest/index.html +265 -25
  463. data/site-local/snapshot/plugins/bullseye/config/defaults.yml +24 -0
  464. data/site-local/snapshot/plugins/bullseye/config/defaults_bullseye.rb +182 -0
  465. data/site-local/snapshot/plugins/gcov/config/defaults.yml +5 -0
  466. data/site-local/testing-guide/build-directives.html +332 -22
  467. data/site-local/testing-guide/conventions.html +678 -153
  468. data/site-local/testing-guide/frameworks.html +248 -14
  469. data/site-local/testing-guide/index.html +248 -21
  470. data/site-local/testing-guide/partials/configuration.html +248 -14
  471. data/site-local/testing-guide/partials/conventions.html +316 -17
  472. data/site-local/testing-guide/partials/directives.html +456 -48
  473. data/site-local/testing-guide/partials/example.html +248 -14
  474. data/site-local/testing-guide/partials/index.html +255 -14
  475. data/site-local/testing-guide/partials/overview.html +248 -14
  476. data/site-local/testing-guide/partials/variables.html +248 -14
  477. data/site-local/testing-guide/test-cases.html +248 -14
  478. data/site-local/testing-guide/test-sample.html +248 -14
  479. data/site-local/testing-guide/test-suite-anatomy.html +248 -14
  480. data/spec/integration/actionator_file_operations_spec.rb +287 -0
  481. data/spec/integration/analysis_tool_output_spec.rb +204 -0
  482. data/spec/{units/c_extractor/c_extractor_integration_spec.rb → integration/c_extractor_composition_spec.rb} +196 -17
  483. data/spec/integration/command_hooks_plugin_spec.rb +152 -0
  484. data/spec/integration/compile_commands_json_db_spec.rb +76 -0
  485. data/spec/integration/configurator_pipeline_spec.rb +180 -0
  486. data/spec/integration/configurator_plugins_spec.rb +122 -0
  487. data/spec/integration/configurator_validation_spec.rb +98 -0
  488. data/spec/integration/dependencies/dependency_tracker_cache_hardening_spec.rb +396 -0
  489. data/spec/integration/dependencies/dependency_tracker_core_spec.rb +244 -0
  490. data/spec/integration/dependencies/dependency_tracker_diagnose_spec.rb +224 -0
  491. data/spec/integration/dependencies/dependency_tracker_filename_handling_spec.rb +118 -0
  492. data/spec/integration/dependencies/dependency_tracker_gcc_deps_spec.rb +199 -0
  493. data/spec/integration/dependencies/dependency_tracker_pruning_spec.rb +167 -0
  494. data/spec/integration/dependencies_plugin_spec.rb +473 -0
  495. data/spec/integration/erb_dependency_removed_spec.rb +167 -0
  496. data/spec/integration/includes_extraction_spec.rb +612 -0
  497. data/spec/integration/mixin_loading_spec.rb +414 -0
  498. data/spec/integration/module_generator_spec.rb +436 -0
  499. data/spec/integration/partials_fallback_preprocessing_spec.rb +316 -0
  500. data/spec/integration/partials_header_composition_spec.rb +889 -0
  501. data/spec/integration/partials_module_resolution_spec.rb +372 -0
  502. data/spec/integration/partials_symbol_linkage_spec.rb +371 -0
  503. data/spec/integration/preprocessing_transient_io_retry_spec.rb +135 -0
  504. data/spec/integration/quote_include_isolator_spec.rb +167 -0
  505. data/spec/integration/report_build_warnings_log_spec.rb +170 -0
  506. data/spec/integration/report_tests_log_factory_spec.rb +100 -0
  507. data/spec/integration/sanitizer_exclusions_spec.rb +126 -0
  508. data/spec/integration/system_harness_sanitizers_spec.rb +104 -0
  509. data/spec/integration/test_build_parallel_barrier_spec.rb +89 -0
  510. data/spec/integration/test_executable_manifest_spec.rb +118 -0
  511. data/spec/integration/test_includes_extractinator_spec.rb +293 -0
  512. data/spec/integration/tool_executor_spec.rb +224 -0
  513. data/spec/integration/tool_validator_spec.rb +133 -0
  514. data/spec/integration/vendor_copy_transient_io_retry_spec.rb +130 -0
  515. data/spec/manual/stress_test.rb +1 -1
  516. data/spec/support/config_yaml_helper.rb +17 -0
  517. data/spec/support/fixtures/sanitizer_reports/clang_asan_heap.txt +45 -0
  518. data/spec/support/fixtures/sanitizer_reports/clang_ubsan_shift.txt +5 -0
  519. data/spec/support/fixtures/sanitizer_reports/gcc_heap.txt +47 -0
  520. data/spec/support/fixtures/sanitizer_reports/gcc_leak.txt +10 -0
  521. data/spec/support/fixtures/sanitizer_reports/gcc_segv.txt +6 -0
  522. data/spec/support/fixtures/sanitizer_reports/gcc_ubsan_shift.txt +6 -0
  523. data/spec/support/fixtures/templates/bullseye__all_pass.txt +6 -0
  524. data/spec/support/fixtures/templates/bullseye__coverage_branches_only.txt +6 -0
  525. data/spec/support/fixtures/templates/bullseye__coverage_functions_only.txt +6 -0
  526. data/spec/support/fixtures/templates/bullseye__coverage_none.txt +6 -0
  527. data/spec/support/fixtures/templates/bullseye__empty.txt +6 -0
  528. data/spec/support/fixtures/templates/bullseye__gcov_context.txt +6 -0
  529. data/spec/support/fixtures/templates/bullseye__mixed_all.txt +6 -0
  530. data/spec/support/fixtures/templates/bullseye__one_failure_matching.txt +6 -0
  531. data/spec/support/fixtures/templates/bullseye__one_failure_multiline.txt +6 -0
  532. data/spec/support/fixtures/templates/bullseye__one_failure_no_message.txt +6 -0
  533. data/spec/support/fixtures/templates/bullseye__one_failure_nonmatching.txt +6 -0
  534. data/spec/support/fixtures/templates/bullseye__one_ignore_no_message.txt +6 -0
  535. data/spec/support/fixtures/templates/bullseye__one_ignore_with_message.txt +6 -0
  536. data/spec/support/fixtures/templates/bullseye__stdout_only.txt +6 -0
  537. data/spec/support/fixtures/templates/ide__all_pass.txt +10 -0
  538. data/spec/support/fixtures/templates/ide__coverage_branches_only.txt +10 -0
  539. data/spec/support/fixtures/templates/ide__coverage_functions_only.txt +10 -0
  540. data/spec/support/fixtures/templates/ide__coverage_none.txt +10 -0
  541. data/spec/support/fixtures/templates/ide__empty.txt +8 -0
  542. data/spec/support/fixtures/templates/ide__gcov_context.txt +28 -0
  543. data/spec/support/fixtures/templates/ide__mixed_all.txt +29 -0
  544. data/spec/support/fixtures/templates/ide__one_failure_matching.txt +15 -0
  545. data/spec/support/fixtures/templates/ide__one_failure_multiline.txt +17 -0
  546. data/spec/support/fixtures/templates/ide__one_failure_no_message.txt +15 -0
  547. data/spec/support/fixtures/templates/ide__one_failure_nonmatching.txt +15 -0
  548. data/spec/support/fixtures/templates/ide__one_ignore_no_message.txt +15 -0
  549. data/spec/support/fixtures/templates/ide__one_ignore_with_message.txt +15 -0
  550. data/spec/support/fixtures/templates/ide__stdout_only.txt +16 -0
  551. data/spec/support/fixtures/templates/pretty__all_pass.txt +8 -0
  552. data/spec/support/fixtures/templates/pretty__coverage_branches_only.txt +8 -0
  553. data/spec/support/fixtures/templates/pretty__coverage_functions_only.txt +8 -0
  554. data/spec/support/fixtures/templates/pretty__coverage_none.txt +8 -0
  555. data/spec/support/fixtures/templates/pretty__empty.txt +6 -0
  556. data/spec/support/fixtures/templates/pretty__gcov_context.txt +31 -0
  557. data/spec/support/fixtures/templates/pretty__mixed_all.txt +35 -0
  558. data/spec/support/fixtures/templates/pretty__one_failure_matching.txt +15 -0
  559. data/spec/support/fixtures/templates/pretty__one_failure_multiline.txt +17 -0
  560. data/spec/support/fixtures/templates/pretty__one_failure_no_message.txt +15 -0
  561. data/spec/support/fixtures/templates/pretty__one_failure_nonmatching.txt +15 -0
  562. data/spec/support/fixtures/templates/pretty__one_ignore_no_message.txt +15 -0
  563. data/spec/support/fixtures/templates/pretty__one_ignore_with_message.txt +15 -0
  564. data/spec/support/fixtures/templates/pretty__stdout_only.txt +15 -0
  565. data/spec/support/fixtures/valgrind_reports/sigsegv.log +51 -0
  566. data/spec/support/fixtures/valgrind_reports/sigsegv.xml +182 -0
  567. data/spec/support/include_guard_helper.rb +20 -0
  568. data/spec/support/integration/configurator_integration_helper.rb +159 -0
  569. data/spec/support/integration/dependency_tracker_integration_helper.rb +136 -0
  570. data/spec/support/integration/partials_generation_integration_helper.rb +726 -0
  571. data/spec/support/integration/spec_integration_helper.rb +285 -0
  572. data/spec/support/integration/test_includes_harness.rb +259 -0
  573. data/spec/support/integration/tool_executor_integration_helper.rb +55 -0
  574. data/spec/support/spec_helper.rb +41 -0
  575. data/spec/support/system/sanitizers/asan_ubsan.yml +82 -0
  576. data/spec/support/system/sanitizers/asan_ubsan_leaks.yml +57 -0
  577. data/spec/support/system/simplecov_boot.rb +66 -0
  578. data/spec/support/system/spec_system_helper.rb +376 -16
  579. data/spec/support/system/system_context.rb +181 -59
  580. data/spec/support/template_render_cases.rb +166 -0
  581. data/spec/system/bracket_path_handling_spec.rb +175 -0
  582. data/spec/system/build_output_mirroring_spec.rb +89 -0
  583. data/spec/system/build_recovery_spec.rb +382 -0
  584. data/spec/system/bullseye_deployment_spec.rb +102 -0
  585. data/spec/system/cli_surface_spec.rb +245 -0
  586. data/spec/system/command_hooks_spec.rb +117 -0
  587. data/spec/system/conditional_include_macro_visibility_spec.rb +32 -124
  588. data/spec/system/conditional_mock_includes_spec.rb +181 -0
  589. data/spec/system/cppcheck_deployment_spec.rb +26 -8
  590. data/spec/system/delta_builds_spec.rb +751 -0
  591. data/spec/system/deployment_as_gem_spec.rb +7 -0
  592. data/spec/system/deployment_as_vendor_spec.rb +29 -145
  593. data/spec/system/dumpconfig_spec.rb +137 -0
  594. data/spec/system/encoding_stress_spec.rb +7 -4
  595. data/spec/system/example_cipher_quest_spec.rb +25 -100
  596. data/spec/system/example_temp_sensor_spec.rb +30 -172
  597. data/spec/system/example_wondrous_forest_spec.rb +25 -62
  598. data/spec/system/extension_multiple_values_spec.rb +75 -0
  599. data/spec/system/files_paths_reporting_spec.rb +154 -0
  600. data/spec/system/gcov_deployment_spec.rb +72 -3
  601. data/spec/system/header_include_path_validation_spec.rb +222 -0
  602. data/spec/system/implicit_source_header_correspondence_disambiguation_spec.rb +100 -0
  603. data/spec/system/include_path_reconciliation_spec.rb +64 -0
  604. data/spec/system/mixin_ordering_spec.rb +30 -415
  605. data/spec/system/mocks_partials_configuration_validation_spec.rb +126 -0
  606. data/spec/system/parent_directory_reference_spec.rb +114 -0
  607. data/spec/system/partials_module_disambiguation_spec.rb +143 -0
  608. data/spec/system/pinned_thread_count_spec.rb +102 -0
  609. data/spec/system/plugin_delta_builds_spec.rb +179 -0
  610. data/spec/system/preprocessing_encoding_spec.rb +87 -4
  611. data/spec/system/preprocessing_fallback_conditionals_spec.rb +19 -25
  612. data/spec/system/preprocessing_parameterized_tests_spec.rb +2 -2
  613. data/spec/system/rake_release_task_path_disambiguation_spec.rb +97 -0
  614. data/spec/system/rake_test_task_path_disambiguation_spec.rb +118 -0
  615. data/spec/system/report_and_tooling_plugins_spec.rb +327 -0
  616. data/spec/system/ruby_replacement_spec.rb +1 -1
  617. data/spec/system/same_named_modules_spec.rb +115 -0
  618. data/spec/system/sanitize_deployment_spec.rb +64 -0
  619. data/spec/system/shuffle_tests_spec.rb +139 -0
  620. data/spec/system/sibling_header_collision_spec.rb +620 -0
  621. data/spec/system/subdir_include_preservation_spec.rb +63 -0
  622. data/spec/system/support/bullseye_common_test_cases.rb +369 -0
  623. data/spec/system/support/bullseye_helpers.rb +70 -0
  624. data/spec/system/support/common_test_cases.rb +167 -43
  625. data/spec/system/support/cppcheck_common_test_cases.rb +80 -0
  626. data/spec/system/support/cppcheck_helpers.rb +10 -8
  627. data/spec/system/support/gcov_common_test_cases.rb +173 -37
  628. data/spec/system/support/gcov_helpers.rb +3 -3
  629. data/spec/system/support/gcov_partials_test_cases.rb +48 -2
  630. data/spec/system/support/sanitize_common_test_cases.rb +222 -0
  631. data/spec/system/support/sanitize_helpers.rb +27 -0
  632. data/spec/system/support/valgrind_common_test_cases.rb +116 -16
  633. data/spec/system/support/valgrind_helpers.rb +3 -4
  634. data/spec/system/test_pipeline_stop_points_spec.rb +160 -0
  635. data/spec/system/test_runner_system_include_spec.rb +19 -41
  636. data/spec/system/test_source_file_directive_spec.rb +235 -0
  637. data/spec/system/upgrade_as_vendor_spec.rb +25 -46
  638. data/spec/system/valgrind_deployment_spec.rb +41 -0
  639. data/spec/units/batchinator_spec.rb +314 -0
  640. data/spec/units/bin/actionator_spec.rb +412 -0
  641. data/spec/units/bin/app_cfg_spec.rb +90 -0
  642. data/spec/units/bin/cli_handler_spec.rb +204 -0
  643. data/spec/units/bin/cli_helper_spec.rb +238 -10
  644. data/spec/units/bin/cli_options_transform_spec.rb +49 -0
  645. data/spec/units/bin/composinator_spec.rb +236 -0
  646. data/spec/units/bin/{projectinator_mixin_spec.rb → mixin_resolvinator_spec.rb} +122 -83
  647. data/spec/units/bin/mixin_standardizer_spec.rb +4 -3
  648. data/spec/units/bin/mixinator_spec.rb +58 -22
  649. data/spec/units/bin/path_validator_spec.rb +112 -0
  650. data/spec/units/bin/projectinator_spec.rb +223 -0
  651. data/spec/units/bin/rake_patches_spec.rb +52 -0
  652. data/spec/units/bin/recursive_merger_spec.rb +22 -0
  653. data/spec/units/bin/versionator_spec.rb +104 -0
  654. data/spec/units/c_extractor/c_extractor_code_text_spec.rb +4 -4
  655. data/spec/units/c_extractor/c_extractor_declarations_spec.rb +70 -0
  656. data/spec/units/c_extractor/c_extractor_functions_spec.rb +75 -1
  657. data/spec/units/c_extractor/c_extractor_preprocessing_spec.rb +158 -0
  658. data/spec/units/c_extractor/c_extractor_spec.rb +236 -6
  659. data/spec/units/ceedling/templateinator_golden_spec.rb +84 -0
  660. data/spec/units/ceedling/templateinator_spec.rb +188 -0
  661. data/spec/units/config/configurator_builder_spec.rb +444 -0
  662. data/spec/units/config/configurator_plugins_spec.rb +160 -0
  663. data/spec/units/config/configurator_setup_spec.rb +706 -6
  664. data/spec/units/config/configurator_spec.rb +952 -0
  665. data/spec/units/config/configurator_validator_spec.rb +259 -0
  666. data/spec/units/config/line_marker_suppressors_spec.rb +89 -0
  667. data/spec/units/config_matchinator_spec.rb +103 -0
  668. data/spec/units/defineinator_spec.rb +158 -0
  669. data/spec/units/dependencies/dependency_cache_store_spec.rb +364 -0
  670. data/spec/units/dependencies/dependency_debug_tree_spec.rb +189 -0
  671. data/spec/units/dependencies/dependency_differ_spec.rb +139 -0
  672. data/spec/units/dependencies/dependency_hasher_spec.rb +141 -0
  673. data/spec/units/dependencies/dependency_path_normalizer_spec.rb +111 -0
  674. data/spec/units/dependencies/dependency_tracker_spec.rb +905 -0
  675. data/spec/units/dependencies/dependinator_spec.rb +99 -0
  676. data/spec/units/dependencies/gcc_dependency_parser_spec.rb +152 -0
  677. data/spec/units/encodinator_spec.rb +92 -0
  678. data/spec/units/file_finder_helper_spec.rb +99 -15
  679. data/spec/units/file_finder_spec.rb +495 -0
  680. data/spec/units/file_path_collection_utils_spec.rb +9 -0
  681. data/spec/units/file_path_utils_spec.rb +736 -0
  682. data/spec/units/file_wrapper_spec.rb +447 -0
  683. data/spec/units/filename_extension_spec.rb +120 -0
  684. data/spec/units/flaginator_spec.rb +114 -0
  685. data/spec/units/generators/generator_helper_spec.rb +113 -0
  686. data/spec/units/generators/generator_mocks_spec.rb +131 -0
  687. data/spec/units/generators/generator_partials_spec.rb +366 -77
  688. data/spec/units/generators/generator_spec.rb +317 -0
  689. data/spec/units/generators/generator_test_results_backtrace_spec.rb +169 -9
  690. data/spec/units/generators/generator_test_results_sanity_checker_spec.rb +14 -6
  691. data/spec/units/generators/generator_test_results_spec.rb +65 -8
  692. data/spec/units/generators/generator_test_runner_spec.rb +1 -1
  693. data/spec/units/includes/include_factory_spec.rb +53 -0
  694. data/spec/units/includes/include_pathinator_spec.rb +269 -0
  695. data/spec/units/includes/include_spec.rb +8 -4
  696. data/spec/units/includes/includes_spec.rb +326 -18
  697. data/spec/units/mock_locator_spec.rb +74 -0
  698. data/spec/units/parsing_parcels_spec.rb +65 -0
  699. data/spec/units/partials/partializer_config_spec.rb +284 -18
  700. data/spec/units/partials/partializer_helper_spec.rb +122 -0
  701. data/spec/units/partials/partializer_spec.rb +474 -36
  702. data/spec/units/partials/partializer_utils_spec.rb +4 -4
  703. data/spec/units/partials_manager_spec.rb +539 -0
  704. data/spec/units/path_matcher_spec.rb +193 -0
  705. data/spec/units/path_mirror_spec.rb +103 -0
  706. data/spec/units/plugin_manager_spec.rb +77 -0
  707. data/spec/units/plugin_reportinator_spec.rb +78 -3
  708. data/spec/units/plugins/bullseye_spec.rb +1068 -0
  709. data/spec/units/plugins/command_hooks_spec.rb +157 -0
  710. data/spec/units/plugins/compile_commands_json_db_spec.rb +145 -0
  711. data/spec/units/plugins/console_reportinator_spec.rb +370 -0
  712. data/spec/units/plugins/cppcheck_spec.rb +330 -4
  713. data/spec/units/plugins/cppunit_tests_reporter_spec.rb +118 -0
  714. data/spec/units/plugins/dependencies_spec.rb +295 -0
  715. data/spec/units/plugins/dependency_commands_spec.rb +83 -0
  716. data/spec/units/plugins/dependency_environment_spec.rb +64 -0
  717. data/spec/units/plugins/dependency_spec_spec.rb +170 -0
  718. data/spec/units/plugins/gcov_reportinator_spec.rb +272 -0
  719. data/spec/units/plugins/gcov_spec.rb +521 -0
  720. data/spec/units/plugins/gcovr_reportinator_spec.rb +795 -0
  721. data/spec/units/plugins/gtestlike_report_spec.rb +363 -0
  722. data/spec/units/plugins/html_tests_reporter_spec.rb +158 -0
  723. data/spec/units/plugins/ide_report_lines_spec.rb +229 -0
  724. data/spec/units/plugins/json_tests_reporter_spec.rb +87 -0
  725. data/spec/units/plugins/junit_tests_reporter_spec.rb +237 -0
  726. data/spec/units/plugins/module_generator_options_spec.rb +185 -0
  727. data/spec/units/plugins/module_generator_project_spec.rb +55 -0
  728. data/spec/units/plugins/module_generator_request_spec.rb +107 -0
  729. data/spec/units/plugins/module_generator_spec.rb +214 -0
  730. data/spec/units/plugins/module_generator_test_file_spec.rb +102 -0
  731. data/spec/units/plugins/module_generator_unity_spec.rb +37 -0
  732. data/spec/units/plugins/report_build_warnings_log_spec.rb +199 -0
  733. data/spec/units/plugins/report_log_writer_plugin_spec.rb +94 -0
  734. data/spec/units/plugins/report_tests_gtestlike_stdout_spec.rb +274 -0
  735. data/spec/units/plugins/report_tests_ide_stdout_spec.rb +140 -0
  736. data/spec/units/plugins/report_tests_log_factory_spec.rb +210 -0
  737. data/spec/units/plugins/report_tests_pretty_stdout_spec.rb +83 -0
  738. data/spec/units/plugins/report_tests_raw_output_log_spec.rb +98 -0
  739. data/spec/units/plugins/report_tests_stdout_plugin_spec.rb +145 -0
  740. data/spec/units/plugins/report_tests_teamcity_stdout_spec.rb +121 -0
  741. data/spec/units/plugins/reportgenerator_reportinator_spec.rb +410 -0
  742. data/spec/units/plugins/sanitize_config_spec.rb +119 -0
  743. data/spec/units/plugins/sanitize_findings_spec.rb +69 -0
  744. data/spec/units/plugins/sanitize_records_spec.rb +114 -0
  745. data/spec/units/plugins/sanitize_reports_spec.rb +84 -0
  746. data/spec/units/plugins/sanitize_spec.rb +300 -0
  747. data/spec/units/plugins/tests_reporter_spec.rb +89 -0
  748. data/spec/units/plugins/valgrind_spec.rb +560 -0
  749. data/spec/units/plugins/warning_collector_spec.rb +185 -0
  750. data/spec/units/plugins/warning_reports_spec.rb +150 -0
  751. data/spec/units/preprocess/c_comment_scanner_spec.rb +17 -17
  752. data/spec/units/preprocess/c_preprocessor_conditionals_spec.rb +94 -0
  753. data/spec/units/preprocess/preprocessinator_bare_includes_extractor_spec.rb +73 -0
  754. data/spec/units/preprocess/preprocessinator_code_finder_spec.rb +35 -16
  755. data/spec/units/preprocess/preprocessinator_comment_stripper_spec.rb +129 -48
  756. data/spec/units/preprocess/preprocessinator_file_assembler_spec.rb +292 -9
  757. data/spec/units/preprocess/preprocessinator_includes_handler_spec.rb +294 -16
  758. data/spec/units/preprocess/preprocessinator_line_marker_includes_extractor_spec.rb +356 -6
  759. data/spec/units/preprocess/preprocessinator_reconstructor_spec.rb +58 -4
  760. data/spec/units/preprocess/preprocessinator_spec.rb +693 -5
  761. data/spec/units/quote_include_isolator_spec.rb +176 -0
  762. data/spec/units/rake_app/rake_invocation_tracker_spec.rb +94 -0
  763. data/spec/units/rake_app/rake_task_registry_spec.rb +263 -0
  764. data/spec/units/rake_app/rake_utils_spec.rb +54 -0
  765. data/spec/units/rake_app/rake_wrapper_spec.rb +64 -0
  766. data/spec/units/rake_app/rakefile_component_resolver_spec.rb +182 -0
  767. data/spec/units/release_build_executor_spec.rb +404 -0
  768. data/spec/units/release_build_planner_spec.rb +144 -0
  769. data/spec/units/release_invoker_spec.rb +127 -0
  770. data/spec/units/reportinator_spec.rb +35 -0
  771. data/spec/units/ruby_expandinator_spec.rb +36 -0
  772. data/spec/units/standin_headerinator_spec.rb +168 -0
  773. data/spec/units/system_wrapper_spec.rb +16 -0
  774. data/spec/units/test_build_executor_spec.rb +1653 -8
  775. data/spec/units/test_build_planner_spec.rb +878 -0
  776. data/spec/units/test_build_setup_spec.rb +583 -0
  777. data/spec/units/test_context_extractor_spec.rb +51 -3
  778. data/spec/units/test_file_preprocessinator_spec.rb +206 -0
  779. data/spec/units/test_includes_extractinator_spec.rb +764 -0
  780. data/spec/units/test_invoker/objects_wiring_spec.rb +31 -0
  781. data/spec/units/test_invoker_spec.rb +147 -0
  782. data/spec/units/test_invoker_types_spec.rb +182 -0
  783. data/spec/units/test_pipeline_helpers_spec.rb +100 -0
  784. data/spec/units/test_pipeline_manager_spec.rb +415 -0
  785. data/spec/units/test_runner_generatinator_spec.rb +215 -0
  786. data/spec/units/test_runner_manager_spec.rb +70 -0
  787. data/spec/units/test_search_paths_spec.rb +84 -0
  788. data/spec/units/test_source_file_directive_resolver_spec.rb +239 -0
  789. data/spec/units/tool_executor_helper_spec.rb +1 -1
  790. data/spec/units/tool_executor_spec.rb +571 -2
  791. data/spec/units/tool_validator_spec.rb +303 -24
  792. data/spec/units/version_spec.rb +74 -0
  793. data/spec/units/yaml_wrapper_spec.rb +4 -1
  794. data/vendor/cmock/docs/CMock_Summary.md +11 -0
  795. data/vendor/cmock/lib/cmock_config.rb +1 -0
  796. data/vendor/cmock/lib/cmock_generator.rb +5 -1
  797. data/vendor/cmock/test/unit/cmock_generator_main_test.rb +31 -0
  798. data/vendor/cmock/vendor/unity/auto/generate_module.rb +4 -4
  799. data/vendor/cmock/vendor/unity/auto/generate_test_runner.rb +8 -2
  800. data/vendor/cmock/vendor/unity/auto/unity_test_summary.rb +2 -2
  801. data/vendor/cmock/vendor/unity/docs/UnityChangeLog.md +7 -0
  802. data/vendor/cmock/vendor/unity/docs/UnityConfigurationGuide.md +4 -0
  803. data/vendor/cmock/vendor/unity/docs/UnityHelperScriptsGuide.md +9 -0
  804. data/vendor/cmock/vendor/unity/src/unity_internals.h +21 -7
  805. data/vendor/cmock/vendor/unity/test/Makefile +9 -2
  806. data/vendor/cmock/vendor/unity/test/rakefile_helper.rb +1 -0
  807. data/vendor/cmock/vendor/unity/test/spec/generate_module_naming_spec.rb +38 -0
  808. data/vendor/cmock/vendor/unity/test/testdata/spi/MockConfig.h +19 -0
  809. data/vendor/cmock/vendor/unity/test/testdata/testRunnerGeneratorWithSameNamedMocks.c +42 -0
  810. data/vendor/cmock/vendor/unity/test/testdata/uart/MockConfig.h +19 -0
  811. data/vendor/cmock/vendor/unity/test/tests/test_generate_test_runner.rb +78 -0
  812. data/vendor/cmock/vendor/unity/test/tests/test_unity_test_summary.rb +58 -0
  813. data/vendor/diy/lib/diy/factory.rb +5 -4
  814. data/vendor/diy/lib/diy.rb +5 -4
  815. data/vendor/diy/sample_code/car.rb +5 -4
  816. data/vendor/diy/sample_code/chassis.rb +5 -4
  817. data/vendor/diy/sample_code/diy_example.rb +5 -4
  818. data/vendor/diy/sample_code/engine.rb +5 -4
  819. data/vendor/diy/sample_code/objects.yml +5 -4
  820. data/vendor/diy/test/constructor.rb +5 -4
  821. data/vendor/diy/test/diy_test.rb +5 -4
  822. data/vendor/diy/test/factory_test.rb +5 -4
  823. data/vendor/diy/test/files/broken_construction.yml +5 -4
  824. data/vendor/diy/test/files/cat/cat.rb +5 -4
  825. data/vendor/diy/test/files/cat/extra_conflict.yml +5 -4
  826. data/vendor/diy/test/files/cat/heritage.rb +5 -4
  827. data/vendor/diy/test/files/cat/needs_input.yml +5 -4
  828. data/vendor/diy/test/files/cat/the_cat_lineage.rb +5 -4
  829. data/vendor/diy/test/files/dog/dog_model.rb +5 -4
  830. data/vendor/diy/test/files/dog/dog_presenter.rb +5 -4
  831. data/vendor/diy/test/files/dog/dog_view.rb +5 -4
  832. data/vendor/diy/test/files/dog/file_resolver.rb +5 -4
  833. data/vendor/diy/test/files/dog/other_thing.rb +5 -4
  834. data/vendor/diy/test/files/dog/simple.yml +5 -4
  835. data/vendor/diy/test/files/donkey/foo/bar/qux.rb +5 -4
  836. data/vendor/diy/test/files/donkey/foo.rb +5 -4
  837. data/vendor/diy/test/files/factory/beef.rb +5 -4
  838. data/vendor/diy/test/files/factory/dog.rb +5 -4
  839. data/vendor/diy/test/files/factory/factory.yml +5 -4
  840. data/vendor/diy/test/files/factory/farm/llama.rb +5 -4
  841. data/vendor/diy/test/files/factory/farm/pork.rb +5 -4
  842. data/vendor/diy/test/files/factory/kitten.rb +5 -4
  843. data/vendor/diy/test/files/fud/objects.yml +5 -4
  844. data/vendor/diy/test/files/fud/toy.rb +5 -4
  845. data/vendor/diy/test/files/functions/attached_things_builder.rb +5 -4
  846. data/vendor/diy/test/files/functions/invalid_method.yml +5 -4
  847. data/vendor/diy/test/files/functions/method_extractor.rb +5 -4
  848. data/vendor/diy/test/files/functions/nonsingleton_objects.yml +5 -4
  849. data/vendor/diy/test/files/functions/objects.yml +5 -4
  850. data/vendor/diy/test/files/functions/thing.rb +5 -4
  851. data/vendor/diy/test/files/functions/thing_builder.rb +5 -4
  852. data/vendor/diy/test/files/functions/things_builder.rb +5 -4
  853. data/vendor/diy/test/files/gnu/objects.yml +5 -4
  854. data/vendor/diy/test/files/gnu/thinger.rb +5 -4
  855. data/vendor/diy/test/files/goat/base.rb +5 -4
  856. data/vendor/diy/test/files/goat/can.rb +5 -4
  857. data/vendor/diy/test/files/goat/goat.rb +5 -4
  858. data/vendor/diy/test/files/goat/objects.yml +5 -4
  859. data/vendor/diy/test/files/goat/paper.rb +5 -4
  860. data/vendor/diy/test/files/goat/plane.rb +5 -4
  861. data/vendor/diy/test/files/goat/shirt.rb +5 -4
  862. data/vendor/diy/test/files/goat/wings.rb +5 -4
  863. data/vendor/diy/test/files/horse/holder_thing.rb +5 -4
  864. data/vendor/diy/test/files/horse/objects.yml +5 -4
  865. data/vendor/diy/test/files/namespace/animal/bird.rb +5 -4
  866. data/vendor/diy/test/files/namespace/animal/cat.rb +5 -4
  867. data/vendor/diy/test/files/namespace/animal/reptile/hardshell/turtle.rb +5 -4
  868. data/vendor/diy/test/files/namespace/animal/reptile/lizard.rb +5 -4
  869. data/vendor/diy/test/files/namespace/bad_module_specified.yml +5 -4
  870. data/vendor/diy/test/files/namespace/class_name_combine.yml +5 -4
  871. data/vendor/diy/test/files/namespace/no_module_specified.yml +5 -4
  872. data/vendor/diy/test/files/namespace/objects.yml +5 -4
  873. data/vendor/diy/test/files/namespace/road.rb +5 -4
  874. data/vendor/diy/test/files/namespace/sky.rb +5 -4
  875. data/vendor/diy/test/files/namespace/subcontext.yml +5 -4
  876. data/vendor/diy/test/files/non_singleton/air.rb +5 -4
  877. data/vendor/diy/test/files/non_singleton/fat_cat.rb +5 -4
  878. data/vendor/diy/test/files/non_singleton/objects.yml +5 -4
  879. data/vendor/diy/test/files/non_singleton/pig.rb +5 -4
  880. data/vendor/diy/test/files/non_singleton/thread_spinner.rb +5 -4
  881. data/vendor/diy/test/files/non_singleton/tick.rb +5 -4
  882. data/vendor/diy/test/files/non_singleton/yard.rb +5 -4
  883. data/vendor/diy/test/files/yak/core_model.rb +5 -4
  884. data/vendor/diy/test/files/yak/core_presenter.rb +5 -4
  885. data/vendor/diy/test/files/yak/core_view.rb +5 -4
  886. data/vendor/diy/test/files/yak/data_source.rb +5 -4
  887. data/vendor/diy/test/files/yak/fringe_model.rb +5 -4
  888. data/vendor/diy/test/files/yak/fringe_presenter.rb +5 -4
  889. data/vendor/diy/test/files/yak/fringe_view.rb +5 -4
  890. data/vendor/diy/test/files/yak/giant_squid.rb +5 -4
  891. data/vendor/diy/test/files/yak/krill.rb +5 -4
  892. data/vendor/diy/test/files/yak/my_objects.yml +5 -4
  893. data/vendor/diy/test/files/yak/sub_sub_context_test.yml +5 -4
  894. data/vendor/diy/test/test_helper.rb +5 -4
  895. data/vendor/unity/auto/generate_module.rb +4 -4
  896. data/vendor/unity/auto/generate_test_runner.rb +5 -1
  897. data/vendor/unity/docs/UnityHelperScriptsGuide.md +9 -0
  898. data/vendor/unity/test/spec/generate_module_naming_spec.rb +38 -0
  899. data/vendor/unity/test/testdata/spi/MockConfig.h +19 -0
  900. data/vendor/unity/test/testdata/testRunnerGeneratorWithSameNamedMocks.c +42 -0
  901. data/vendor/unity/test/testdata/uart/MockConfig.h +19 -0
  902. data/vendor/unity/test/tests/test_generate_test_runner.rb +29 -0
  903. metadata +770 -285
  904. data/assets/tests_with_fallback_conditionals/src/conditional_module.c +0 -18
  905. data/bin/actions_wrapper.rb +0 -51
  906. data/docs/mkdocs/assets/images/ceedling-logo-circle.png +0 -0
  907. data/docs/mkdocs/assets/images/ceedling.svg +0 -90
  908. data/docs/mkdocs/assets/images/favicon.png +0 -0
  909. data/docs/mkdocs/assets/stylesheets/admonitions.css +0 -152
  910. data/docs/mkdocs/assets/stylesheets/fixes-local.css +0 -15
  911. data/docs/mkdocs/assets/stylesheets/styling.css +0 -102
  912. data/docs/mkdocs/configuration/environment-vars.md +0 -14
  913. data/docs/mkdocs/configuration/global-collections.md +0 -156
  914. data/docs/mkdocs/configuration/index.md +0 -75
  915. data/docs/mkdocs/configuration/loading.md +0 -89
  916. data/docs/mkdocs/configuration/mixins.md +0 -607
  917. data/docs/mkdocs/configuration/parallel-builds.md +0 -97
  918. data/docs/mkdocs/configuration/project-file.md +0 -216
  919. data/docs/mkdocs/configuration/reference/cexception.md +0 -35
  920. data/docs/mkdocs/configuration/reference/cmock.md +0 -106
  921. data/docs/mkdocs/configuration/reference/defines.md +0 -352
  922. data/docs/mkdocs/configuration/reference/environment.md +0 -55
  923. data/docs/mkdocs/configuration/reference/extension.md +0 -63
  924. data/docs/mkdocs/configuration/reference/files.md +0 -154
  925. data/docs/mkdocs/configuration/reference/flags.md +0 -296
  926. data/docs/mkdocs/configuration/reference/index.md +0 -176
  927. data/docs/mkdocs/configuration/reference/libraries.md +0 -82
  928. data/docs/mkdocs/configuration/reference/mixins.md +0 -24
  929. data/docs/mkdocs/configuration/reference/partials.md +0 -38
  930. data/docs/mkdocs/configuration/reference/paths.md +0 -276
  931. data/docs/mkdocs/configuration/reference/plugins.md +0 -60
  932. data/docs/mkdocs/configuration/reference/project.md +0 -333
  933. data/docs/mkdocs/configuration/reference/release-build.md +0 -62
  934. data/docs/mkdocs/configuration/reference/test-build.md +0 -55
  935. data/docs/mkdocs/configuration/reference/test-runner.md +0 -61
  936. data/docs/mkdocs/configuration/reference/tools.md +0 -457
  937. data/docs/mkdocs/configuration/reference/unity.md +0 -49
  938. data/docs/mkdocs/configuration/which-ceedling.md +0 -77
  939. data/docs/mkdocs/development/index.md +0 -50
  940. data/docs/mkdocs/development/plugins/configuration.md +0 -164
  941. data/docs/mkdocs/development/plugins/index.md +0 -84
  942. data/docs/mkdocs/development/plugins/plugin-subclass.md +0 -513
  943. data/docs/mkdocs/development/plugins/rake-tasks.md +0 -54
  944. data/docs/mkdocs/development/workflow.md +0 -284
  945. data/docs/mkdocs/getting-started/command-line.md +0 -477
  946. data/docs/mkdocs/getting-started/example-projects/cipher-quest.md +0 -65
  947. data/docs/mkdocs/getting-started/example-projects/index.md +0 -49
  948. data/docs/mkdocs/getting-started/example-projects/temp-sensor.md +0 -60
  949. data/docs/mkdocs/getting-started/example-projects/wondrous-forest.md +0 -45
  950. data/docs/mkdocs/getting-started/index.md +0 -41
  951. data/docs/mkdocs/getting-started/installation.md +0 -179
  952. data/docs/mkdocs/getting-started/quick-start.md +0 -86
  953. data/docs/mkdocs/help.md +0 -49
  954. data/docs/mkdocs/index.md +0 -222
  955. data/docs/mkdocs/overview/build-system.md +0 -115
  956. data/docs/mkdocs/overview/index.md +0 -29
  957. data/docs/mkdocs/overview/test-environments.md +0 -33
  958. data/docs/mkdocs/overview/tools-and-frameworks.md +0 -115
  959. data/docs/mkdocs/plugins/beep.md +0 -134
  960. data/docs/mkdocs/plugins/bullseye.md +0 -83
  961. data/docs/mkdocs/plugins/command-hooks.md +0 -268
  962. data/docs/mkdocs/plugins/compile-commands-json-db.md +0 -42
  963. data/docs/mkdocs/plugins/cppcheck.md +0 -377
  964. data/docs/mkdocs/plugins/dependencies.md +0 -310
  965. data/docs/mkdocs/plugins/fff.md +0 -247
  966. data/docs/mkdocs/plugins/gcov/examples.md +0 -92
  967. data/docs/mkdocs/plugins/gcov/gcovr.md +0 -412
  968. data/docs/mkdocs/plugins/gcov/index.md +0 -74
  969. data/docs/mkdocs/plugins/gcov/overview.md +0 -145
  970. data/docs/mkdocs/plugins/gcov/reportgenerator.md +0 -140
  971. data/docs/mkdocs/plugins/gcov/reporting.md +0 -147
  972. data/docs/mkdocs/plugins/gcov/setup.md +0 -232
  973. data/docs/mkdocs/plugins/gcov/tool-versions.md +0 -60
  974. data/docs/mkdocs/plugins/gcov/troubleshooting.md +0 -78
  975. data/docs/mkdocs/plugins/index.md +0 -261
  976. data/docs/mkdocs/plugins/module-generator.md +0 -267
  977. data/docs/mkdocs/plugins/report-build-warnings-log.md +0 -42
  978. data/docs/mkdocs/plugins/report-tests-gtestlike-stdout.md +0 -98
  979. data/docs/mkdocs/plugins/report-tests-ide-stdout.md +0 -63
  980. data/docs/mkdocs/plugins/report-tests-log-factory.md +0 -454
  981. data/docs/mkdocs/plugins/report-tests-pretty-stdout.md +0 -56
  982. data/docs/mkdocs/plugins/report-tests-raw-output-log.md +0 -52
  983. data/docs/mkdocs/plugins/report-tests-teamcity-stdout.md +0 -96
  984. data/docs/mkdocs/plugins/sample_html_report.png +0 -0
  985. data/docs/mkdocs/plugins/valgrind.md +0 -198
  986. data/docs/mkdocs/project/release-history.md +0 -61
  987. data/docs/mkdocs/project/upgrade.md +0 -85
  988. data/docs/mkdocs/reference/build-directives.md +0 -37
  989. data/docs/mkdocs/reference/command-line.md +0 -323
  990. data/docs/mkdocs/reference/environment-vars.md +0 -60
  991. data/docs/mkdocs/reference/gcov-plugin.md +0 -600
  992. data/docs/mkdocs/reference/global-collections.md +0 -160
  993. data/docs/mkdocs/reference/index.md +0 -65
  994. data/docs/mkdocs/reference/partials-macros.md +0 -79
  995. data/docs/mkdocs/reference/project-configuration.md +0 -46
  996. data/docs/mkdocs/snapshot/assets/project.yml +0 -404
  997. data/docs/mkdocs/snapshot/examples/cipher_quest/README.md +0 -210
  998. data/docs/mkdocs/snapshot/examples/temp_sensor/README.md +0 -283
  999. data/docs/mkdocs/snapshot/examples/wondrous_forest/README.md +0 -92
  1000. data/docs/mkdocs/snapshot/plugins/gcov/config/defaults.yml +0 -32
  1001. data/docs/mkdocs/snapshot/plugins/gcov/config/defaults_gcov.rb +0 -136
  1002. data/docs/mkdocs/snapshot.yml +0 -20
  1003. data/docs/mkdocs/testing-guide/build-directives.md +0 -153
  1004. data/docs/mkdocs/testing-guide/conventions.md +0 -616
  1005. data/docs/mkdocs/testing-guide/frameworks.md +0 -192
  1006. data/docs/mkdocs/testing-guide/index.md +0 -80
  1007. data/docs/mkdocs/testing-guide/partials/configuration.md +0 -67
  1008. data/docs/mkdocs/testing-guide/partials/conventions.md +0 -68
  1009. data/docs/mkdocs/testing-guide/partials/directives.md +0 -212
  1010. data/docs/mkdocs/testing-guide/partials/example.md +0 -149
  1011. data/docs/mkdocs/testing-guide/partials/index.md +0 -88
  1012. data/docs/mkdocs/testing-guide/partials/overview.md +0 -81
  1013. data/docs/mkdocs/testing-guide/partials/variables.md +0 -244
  1014. data/docs/mkdocs/testing-guide/test-cases.md +0 -194
  1015. data/docs/mkdocs/testing-guide/test-sample.md +0 -94
  1016. data/docs/mkdocs/testing-guide/test-suite-anatomy.md +0 -58
  1017. data/lib/ceedling/cacheinator.rb +0 -53
  1018. data/lib/ceedling/cacheinator_helper.rb +0 -60
  1019. data/lib/ceedling/dependinator.rb +0 -31
  1020. data/lib/ceedling/makefile.rb +0 -52
  1021. data/lib/ceedling/release_invoker.rb +0 -112
  1022. data/lib/ceedling/rules_release.rake +0 -109
  1023. data/lib/ceedling/rules_tests.rake +0 -40
  1024. data/lib/ceedling/tasks_release.rake +0 -36
  1025. data/plugins/fff/vendor/fff/Makefile +0 -10
  1026. data/plugins/fff/vendor/fff/buildandtest +0 -15
  1027. data/plugins/fff/vendor/fff/examples/Makefile +0 -7
  1028. data/plugins/fff/vendor/fff/examples/driver_testing/Makefile +0 -64
  1029. data/plugins/fff/vendor/fff/examples/driver_testing/driver.c +0 -32
  1030. data/plugins/fff/vendor/fff/examples/driver_testing/driver.h +0 -21
  1031. data/plugins/fff/vendor/fff/examples/driver_testing/driver.test.cpp +0 -58
  1032. data/plugins/fff/vendor/fff/examples/driver_testing/driver.test.fff.cpp +0 -70
  1033. data/plugins/fff/vendor/fff/examples/driver_testing/hardware_abstraction.h +0 -25
  1034. data/plugins/fff/vendor/fff/examples/driver_testing/registers.h +0 -23
  1035. data/plugins/fff/vendor/fff/examples/embedded_ui/DISPLAY.h +0 -27
  1036. data/plugins/fff/vendor/fff/examples/embedded_ui/Kata.txt +0 -25
  1037. data/plugins/fff/vendor/fff/examples/embedded_ui/Makefile +0 -67
  1038. data/plugins/fff/vendor/fff/examples/embedded_ui/SYSTEM.h +0 -31
  1039. data/plugins/fff/vendor/fff/examples/embedded_ui/UI.c +0 -56
  1040. data/plugins/fff/vendor/fff/examples/embedded_ui/UI.h +0 -22
  1041. data/plugins/fff/vendor/fff/examples/embedded_ui/UI_test_ansic.c +0 -191
  1042. data/plugins/fff/vendor/fff/examples/embedded_ui/UI_test_cpp.cpp +0 -144
  1043. data/plugins/fff/vendor/fff/examples/embedded_ui/test_suite_template.c +0 -42
  1044. data/plugins/fff/vendor/fff/gtest/Makefile +0 -22
  1045. data/plugins/fff/vendor/fff/gtest/gtest-all.cc +0 -9118
  1046. data/plugins/fff/vendor/fff/gtest/gtest-main.cc +0 -6
  1047. data/plugins/fff/vendor/fff/gtest/gtest.h +0 -19547
  1048. data/plugins/fff/vendor/fff/test/Makefile +0 -81
  1049. data/plugins/fff/vendor/fff/test/c_test_framework.h +0 -25
  1050. data/plugins/fff/vendor/fff/test/fff_test_c.c +0 -116
  1051. data/plugins/fff/vendor/fff/test/fff_test_cpp.cpp +0 -53
  1052. data/plugins/fff/vendor/fff/test/fff_test_global_c.c +0 -84
  1053. data/plugins/fff/vendor/fff/test/fff_test_global_cpp.cpp +0 -31
  1054. data/plugins/fff/vendor/fff/test/global_fakes.c +0 -21
  1055. data/plugins/fff/vendor/fff/test/global_fakes.h +0 -47
  1056. data/plugins/fff/vendor/fff/test/test_cases.include +0 -276
  1057. data/plugins/report_tests_gtestlike_stdout/assets/template.erb +0 -83
  1058. data/spec/units/configurator_spec.rb +0 -232
  1059. /data/assets/{ceedling → features/ceedling} +0 -0
  1060. /data/assets/{ceedling.cmd → features/ceedling.cmd} +0 -0
  1061. /data/assets/{default_gitignore → features/default_gitignore} +0 -0
  1062. /data/assets/{broken_uncovered_file.c → fixtures/broken_uncovered_file.c} +0 -0
  1063. /data/assets/{example_file.c → fixtures/example_file.c} +0 -0
  1064. /data/assets/{example_file.h → fixtures/example_file.h} +0 -0
  1065. /data/assets/{example_file_call.c → fixtures/example_file_call.c} +0 -0
  1066. /data/assets/{example_file_call.h → fixtures/example_file_call.h} +0 -0
  1067. /data/assets/{example_file_with_statics.c → fixtures/example_file_with_statics.c} +0 -0
  1068. /data/assets/{example_file_with_stdio.c → fixtures/example_file_with_stdio.c} +0 -0
  1069. /data/assets/{example_file_with_stdio.h → fixtures/example_file_with_stdio.h} +0 -0
  1070. /data/assets/{fake_crash_test_fixture.rb → fixtures/fake_crash_test_fixture.rb} +0 -0
  1071. /data/assets/{partial_all_module.h → fixtures/partial_all_module.h} +0 -0
  1072. /data/assets/{run_with_ubsan.rb → fixtures/run_with_ubsan.rb} +0 -0
  1073. /data/assets/{same_dir_pairing_module.c → fixtures/same_dir_pairing_module.c} +0 -0
  1074. /data/assets/{same_dir_pairing_module.h → fixtures/same_dir_pairing_module.h} +0 -0
  1075. /data/assets/{same_dir_pairing_module_func.h → fixtures/same_dir_pairing_module_func.h} +0 -0
  1076. /data/assets/{same_dir_pairing_other.c → fixtures/same_dir_pairing_other.c} +0 -0
  1077. /data/assets/{same_dir_pairing_other.h → fixtures/same_dir_pairing_other.h} +0 -0
  1078. /data/assets/{test_example_file.c → fixtures/test_example_file.c} +0 -0
  1079. /data/assets/{test_example_file_2.c → fixtures/test_example_file_2.c} +0 -0
  1080. /data/assets/{test_example_file_source_include.c → fixtures/test_example_file_source_include.c} +0 -0
  1081. /data/assets/{test_example_file_success.c → fixtures/test_example_file_success.c} +0 -0
  1082. /data/assets/{test_example_file_unity_printf.c → fixtures/test_example_file_unity_printf.c} +0 -0
  1083. /data/assets/{test_example_file_verbose.c → fixtures/test_example_file_verbose.c} +0 -0
  1084. /data/assets/{test_example_file_with_mock.c → fixtures/test_example_file_with_mock.c} +0 -0
  1085. /data/assets/{test_example_file_with_stdio.c → fixtures/test_example_file_with_stdio.c} +0 -0
  1086. /data/assets/{test_example_with_parameterized_tests.c → fixtures/test_example_with_parameterized_tests.c} +0 -0
  1087. /data/assets/{test_partial_all_module.c → fixtures/test_partial_all_module.c} +0 -0
  1088. /data/assets/{test_same_dir_pairing.c → fixtures/test_same_dir_pairing.c} +0 -0
  1089. /data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/feature_config.h +0 -0
  1090. /data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/feature_extra.h +0 -0
  1091. /data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/local_flag_extra.h +0 -0
  1092. /data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/nested_extra.h +0 -0
  1093. /data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/nested_wrapper.h +0 -0
  1094. /data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/project_flag_extra.h +0 -0
  1095. /data/assets/{tests_with_conditional_includes → fixtures/tests_with_conditional_includes}/src/widget_feature.h +0 -0
  1096. /data/assets/{tests_with_defines → fixtures/tests_with_defines}/src/adc_hardware.c +0 -0
  1097. /data/assets/{tests_with_defines → fixtures/tests_with_defines}/src/adc_hardware.h +0 -0
  1098. /data/assets/{tests_with_defines → fixtures/tests_with_defines}/src/adc_hardware_configurator.c +0 -0
  1099. /data/assets/{tests_with_defines → fixtures/tests_with_defines}/src/adc_hardware_configurator.h +0 -0
  1100. /data/assets/{tests_with_defines → fixtures/tests_with_defines}/test/test_adc_hardware.c +0 -0
  1101. /data/assets/{tests_with_defines → fixtures/tests_with_defines}/test/test_adc_hardware_special.c +0 -0
  1102. /data/assets/{tests_with_encoding → fixtures/tests_with_encoding}/src/unicoder.c +0 -0
  1103. /data/assets/{tests_with_encoding → fixtures/tests_with_encoding}/src/unicoder.h +0 -0
  1104. /data/assets/{tests_with_encoding → fixtures/tests_with_encoding}/test/test_unicoder.c +0 -0
  1105. /data/assets/{tests_with_encoding → fixtures/tests_with_encoding}/test/test_unicoder_partial.c +0 -0
  1106. /data/assets/{tests_with_fallback_conditionals → fixtures/tests_with_fallback_conditionals}/src/conditional_module.h +0 -0
  1107. /data/assets/{tests_with_fallback_conditionals → fixtures/tests_with_fallback_conditionals}/src/optional_dep.h +0 -0
  1108. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/src/blanks.c +0 -0
  1109. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/src/blanks.h +0 -0
  1110. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/src/counter.c +0 -0
  1111. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/src/counter.h +0 -0
  1112. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/src/decorators.c +0 -0
  1113. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/src/decorators.h +0 -0
  1114. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/test/test_blanks.c +0 -0
  1115. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/test/test_counter.c +0 -0
  1116. /data/assets/{tests_with_partials_coverage → fixtures/tests_with_partials_coverage}/test/test_decorators.c +0 -0
  1117. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardwareA.c +0 -0
  1118. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardwareA.h +0 -0
  1119. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardwareB.c +0 -0
  1120. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardwareB.h +0 -0
  1121. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardwareC.c +0 -0
  1122. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardwareC.h +0 -0
  1123. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardware_configuratorA.h +0 -0
  1124. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardware_configuratorB.h +0 -0
  1125. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/src/adc_hardware_configuratorC.h +0 -0
  1126. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/test/test_adc_hardwareA.c +0 -0
  1127. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/test/test_adc_hardwareB.c +0 -0
  1128. /data/assets/{tests_with_preprocessing → fixtures/tests_with_preprocessing}/test/test_adc_hardwareC.c +0 -0
  1129. /data/assets/{uncovered_example_file.c → fixtures/uncovered_example_file.c} +0 -0
  1130. /data/plugins/bullseye/assets/{template.erb → coverage.template} +0 -0
@@ -6,8 +6,13 @@
6
6
  # =========================================================================
7
7
 
8
8
  require 'spec_helper'
9
+ require 'ceedling/filename_extension'
10
+ require 'rake'
9
11
  require 'ceedling/test_invoker/test_build_executor'
10
12
  require 'ceedling/test_invoker/test_invoker_types'
13
+ require 'ceedling/partials/partials'
14
+ require 'ceedling/test_context_extractor'
15
+ require 'ceedling/quote_include_isolator'
11
16
 
12
17
  PROJECT_BUILD_VENDOR_UNITY_PATH = 'build/vendor/unity' unless defined?(PROJECT_BUILD_VENDOR_UNITY_PATH)
13
18
  UNITY_C_FILE = 'unity.c' unless defined?(UNITY_C_FILE)
@@ -19,26 +24,87 @@ describe TestBuildExecutor do
19
24
  @reportinator = double( "Reportinator" )
20
25
  @batchinator = double( "Batchinator" )
21
26
  @preprocessinator = double( "Preprocessinator" )
22
- @partializer = double( "Partializer" )
23
27
  @generator = double( "Generator" )
24
28
  @test_context_extractor = double( "TestContextExtractor" )
25
29
  @plugin_manager = double( "PluginManager" )
26
30
  @file_path_utils = double( "FilePathUtils" )
27
31
  @file_finder = double( "FileFinder" )
28
32
  @file_wrapper = double( "FileWrapper" )
33
+ @dependinator = double( "Dependinator" )
34
+ @test_source_file_directive_resolver = double( "TestSourceFileDirectiveResolver" )
35
+ @gcc_dependency_parser = double( "GccDependencyParser" )
36
+ @quote_include_isolator = double( "QuoteIncludeIsolator" )
37
+ @generator_helper = double( "GeneratorHelper" )
29
38
 
30
- @tools_test_compiler = { name: 'fake compiler' }
31
- @tools_test_assembler = { name: 'fake assembler' }
39
+ @tools_test_compiler = { name: 'fake compiler' }
40
+ @tools_test_assembler = { name: 'fake assembler' }
41
+ @tools_test_linker = { name: 'fake linker' }
42
+ @tools_test_fixture = { name: 'fake fixture' }
43
+ @tools_test_bare_includes_preprocessor = { name: 'fake bare includes preprocessor' }
44
+ @tools_test_file_directives_only_preprocessor = { name: 'fake directives-only preprocessor' }
45
+ @tools_test_backtrace_gdb = { name: 'fake gdb backtrace' }
46
+ @tools_test_fixture_simple_backtrace = { name: 'fake simple backtrace' }
32
47
 
33
- allow(@configurator).to receive(:extension_assembly).and_return( '.asm' )
48
+ allow(@configurator).to receive(:extension_assembly).and_return( FilenameExtension.new('.asm') )
49
+ allow(@configurator).to receive(:extension_testfail).and_return( FilenameExtension.new('.fail') )
34
50
  allow(@configurator).to receive(:tools_test_compiler).and_return( @tools_test_compiler )
35
51
  allow(@configurator).to receive(:tools_test_assembler).and_return( @tools_test_assembler )
52
+ allow(@configurator).to receive(:tools_test_linker).and_return( @tools_test_linker )
53
+ allow(@configurator).to receive(:tools_test_fixture).and_return( @tools_test_fixture )
54
+ allow(@configurator).to receive(:tools_test_bare_includes_preprocessor).and_return( @tools_test_bare_includes_preprocessor )
55
+ allow(@configurator).to receive(:tools_test_file_directives_only_preprocessor).and_return( @tools_test_file_directives_only_preprocessor )
56
+ # tools_test_backtrace_gdb is deliberately NOT stubbed here -- the real Configurator
57
+ # only defines it at all when :use_backtrace is :gdb (see test_build_executor.rb's
58
+ # own comment at its one call site), so leaving it unstubbed here means any example
59
+ # that calls it without :gdb mode explicitly set up fails loudly, the same way the
60
+ # real Configurator would raise NoMethodError.
61
+ allow(@configurator).to receive(:tools_test_fixture_simple_backtrace).and_return( @tools_test_fixture_simple_backtrace )
62
+ allow(@configurator).to receive(:project_config_hash).and_return( { project_use_backtrace: :simple } )
63
+ allow(@configurator).to receive(:test_build_preprocess_force_fallback).and_return( false )
36
64
  allow(@configurator).to receive(:project_use_mocks).and_return( false )
37
65
  allow(@configurator).to receive(:project_use_exceptions).and_return( false )
38
66
  allow(@configurator).to receive(:collection_all_support).and_return( [] )
67
+ allow(@configurator).to receive(:force_test_rerun).and_return( false )
68
+ allow(@configurator).to receive(:unity_shuffle_tests).and_return( false )
69
+ allow(@configurator).to receive(:project_build_vendor_ceedling_path).and_return( 'build/vendor/ceedling' )
39
70
 
40
71
  allow(@file_path_utils).to receive(:form_test_build_list_filepath).and_return( 'build/list' )
41
72
  allow(@file_path_utils).to receive(:form_test_dependencies_filepath).and_return( 'build/deps' )
73
+ allow(@file_path_utils).to receive(:form_preprocessed_source_files_cache_filepath).and_return( 'build/preprocess/build_directives/a_test/TestFoo.c_source_files.yml' )
74
+
75
+ allow(@file_wrapper).to receive(:mkdir)
76
+ allow(@quote_include_isolator).to receive(:release)
77
+ # The real literal scan over the doubled file layer, so each example's read stubs decide it
78
+ real_isolator = QuoteIncludeIsolator.new( { :file_wrapper => @file_wrapper, :loginator => @loginator } )
79
+ allow(@quote_include_isolator).to receive(:includes_by_name?) { |file, name| real_isolator.includes_by_name?( file, name ) }
80
+ allow(@generator_helper).to receive(:explain_possible_mock_partial_collision).and_return( nil )
81
+
82
+ allow(@reportinator).to receive(:generate_module_progress).and_return( '' )
83
+ allow(@reportinator).to receive(:generate_progress).and_return( '' )
84
+ allow(@reportinator).to receive(:generate_skip_summary).and_return( nil )
85
+ allow(@loginator).to receive(:log)
86
+ allow(@loginator).to receive(:log_list)
87
+ allow(@test_context_extractor).to receive(:store_build_directives_cache)
88
+ allow(@test_context_extractor).to receive(:load_build_directives_cache)
89
+
90
+ # Default: no prior `.d` file on disk, and the tracker reports every target
91
+ # stale -- i.e. every real build in this spec proceeds as an unconditional
92
+ # fresh compile unless a test overrides `stale?` to exercise the skip path.
93
+ # A prior run's .d file is looked for with exist? before a compile, and a freshly
94
+ # written one with exist_with_retry? after it. The sibling-header check calls exist?.
95
+ allow(@file_wrapper).to receive(:exist?).and_return( false )
96
+ allow(@file_wrapper).to receive(:exist_with_retry?).and_return( false )
97
+ # Default: no plugin implements the new pre-*-register hooks -- each is a
98
+ # no-op that leaves the arg_hash it's handed untouched.
99
+ allow(@plugin_manager).to receive(:pre_test_compile_register)
100
+ allow(@plugin_manager).to receive(:pre_test_link_register)
101
+ allow(@plugin_manager).to receive(:pre_test_fixture_register)
102
+
103
+ allow(@dependinator).to receive(:register)
104
+ allow(@dependinator).to receive(:register_gcc_deps_file)
105
+ allow(@dependinator).to receive(:stale?).and_return( true )
106
+ allow(@dependinator).to receive(:mark_fresh)
107
+ allow(@test_source_file_directive_resolver).to receive(:validate!)
42
108
 
43
109
  @executor = described_class.new(
44
110
  {
@@ -47,13 +113,15 @@ describe TestBuildExecutor do
47
113
  :reportinator => @reportinator,
48
114
  :batchinator => @batchinator,
49
115
  :preprocessinator => @preprocessinator,
50
- :partializer => @partializer,
51
116
  :generator => @generator,
52
- :test_context_extractor => @test_context_extractor,
53
117
  :plugin_manager => @plugin_manager,
54
118
  :file_path_utils => @file_path_utils,
55
119
  :file_finder => @file_finder,
56
- :file_wrapper => @file_wrapper
120
+ :file_wrapper => @file_wrapper,
121
+ :dependinator => @dependinator,
122
+ :gcc_dependency_parser => @gcc_dependency_parser,
123
+ :quote_include_isolator => @quote_include_isolator,
124
+ :generator_helper => @generator_helper
57
125
  }
58
126
  )
59
127
 
@@ -64,7 +132,21 @@ describe TestBuildExecutor do
64
132
  :assembler_flags => []
65
133
  )
66
134
 
67
- @state = TestInvokerTypes::PipelineState.new( :testables => { :a_test => testable } )
135
+ @state = TestInvokerTypes::PipelineState.new( :testables => { :a_test => testable }, :lock => Mutex.new )
136
+ end
137
+
138
+ # An isolation staged into `dir`, as QuoteIncludeIsolator#isolate returns one
139
+ def isolation_in(dir)
140
+ QuoteIncludeIsolator::Isolation.new( dir, {} )
141
+ end
142
+
143
+ # `@batchinator.exec` is a real collaborator only in production; here it's
144
+ # stubbed to synchronously yield every `things` entry to the given block,
145
+ # matching its real per-item iteration contract without pulling in Parallel.
146
+ def stub_batchinator_exec
147
+ allow(@batchinator).to receive(:exec) do |workload:, things:, &block|
148
+ things.each { |k, v| block.call(k, v) }
149
+ end
68
150
  end
69
151
 
70
152
  context "#compile_test_component" do
@@ -110,5 +192,1568 @@ describe TestBuildExecutor do
110
192
  :context => :test, :test => :a_test, :source => 'src/foo.asm', :object => 'build/foo.o', :state => @state
111
193
  )
112
194
  end
195
+
196
+ it "skips compiling and does not mark the object fresh when the dependency tracker reports it unchanged" do
197
+ allow(@file_wrapper).to receive(:extname).with( 'src/foo.c' ).and_return( '.c' )
198
+ allow(@configurator).to receive(:test_build_use_assembly).and_return( false )
199
+ allow(@dependinator).to receive(:stale?).and_return( false )
200
+
201
+ expect(@generator).to_not receive(:generate_object_file_c)
202
+ expect(@dependinator).to_not receive(:mark_fresh)
203
+
204
+ @executor.send(
205
+ :compile_test_component,
206
+ :context => :test, :test => :a_test, :source => 'src/foo.c', :object => 'build/foo.o', :state => @state
207
+ )
208
+ end
209
+
210
+ it "registers the object's source before checking staleness, and its freshly-written gcc deps file after a real compile" do
211
+ allow(@file_wrapper).to receive(:extname).with( 'src/foo.c' ).and_return( '.c' )
212
+ allow(@configurator).to receive(:test_build_use_assembly).and_return( false )
213
+ allow(@file_wrapper).to receive(:exist?).with('build/deps').and_return( true )
214
+ allow(@file_wrapper).to receive(:exist_with_retry?).with('build/deps').and_return( true )
215
+
216
+ expect(@dependinator).to receive(:register).with( 'build/foo.o', files: ['src/foo.c'], meta: anything ).ordered
217
+ expect(@dependinator).to receive(:register_gcc_deps_file).with('build/deps').ordered # pre-compile: prior .d file, if any
218
+ expect(@dependinator).to receive(:stale?).with('build/foo.o').and_return(true).ordered
219
+ expect(@generator).to receive(:generate_object_file_c).ordered
220
+ expect(@dependinator).to receive(:register_gcc_deps_file).with('build/deps').ordered # post-compile: freshly-written .d file
221
+ expect(@dependinator).to receive(:mark_fresh).with('build/foo.o').ordered
222
+
223
+ @executor.send(
224
+ :compile_test_component,
225
+ :context => :test, :test => :a_test, :source => 'src/foo.c', :object => 'build/foo.o', :state => @state
226
+ )
227
+ end
228
+
229
+ # A clean build has no .d file before a compile, and nothing has just written one,
230
+ # so a single look settles it. Waiting out a transient miss there would cost every
231
+ # object in a clean build the whole retry schedule.
232
+ it "looks once for a prior .d file before compiling, without waiting for one" do
233
+ allow(@file_wrapper).to receive(:extname).with( 'src/foo.c' ).and_return( '.c' )
234
+ allow(@configurator).to receive(:test_build_use_assembly).and_return( false )
235
+ allow(@dependinator).to receive(:stale?).and_return( false )
236
+
237
+ expect(@file_wrapper).to receive(:exist?).with('build/deps').and_return( false )
238
+ expect(@file_wrapper).to_not receive(:exist_with_retry?)
239
+ expect(@dependinator).to_not receive(:register_gcc_deps_file)
240
+
241
+ @executor.send(
242
+ :compile_test_component,
243
+ :context => :test, :test => :a_test, :source => 'src/foo.c', :object => 'build/foo.o', :state => @state
244
+ )
245
+ end
246
+
247
+ # The .d file a compile just wrote can briefly read as absent once the compiler exits.
248
+ # exist_with_retry? waits that out, so its headers are registered this run rather than
249
+ # on the next. Its retry mechanism is proven in file_wrapper_spec.rb.
250
+ it "registers the .d file a compile just wrote through exist_with_retry?, though none was there before" do
251
+ allow(@file_wrapper).to receive(:extname).with( 'src/foo.c' ).and_return( '.c' )
252
+ allow(@configurator).to receive(:test_build_use_assembly).and_return( false )
253
+ allow(@file_wrapper).to receive(:exist?).with('build/deps').and_return( false )
254
+ allow(@file_wrapper).to receive(:exist_with_retry?).with('build/deps').and_return( true )
255
+
256
+ expect(@generator).to receive(:generate_object_file_c)
257
+ expect(@dependinator).to receive(:register_gcc_deps_file).with('build/deps').once
258
+
259
+ @executor.send(
260
+ :compile_test_component,
261
+ :context => :test, :test => :a_test, :source => 'src/foo.c', :object => 'build/foo.o', :state => @state
262
+ )
263
+ end
264
+
265
+ it "resolves the compile tool/flags/defines through pre_test_compile_register before registering staleness meta, and uses the resolved values for the real compile" do
266
+ allow(@file_wrapper).to receive(:extname).with( 'src/foo.c' ).and_return( '.c' )
267
+ allow(@configurator).to receive(:test_build_use_assembly).and_return( false )
268
+
269
+ swapped_tool = { name: 'fake gcov compiler' }
270
+ allow(@plugin_manager).to receive(:pre_test_compile_register) do |arg_hash|
271
+ arg_hash[:tool] = swapped_tool
272
+ arg_hash[:flags] += ['-fcondition-coverage']
273
+ arg_hash[:defines] += ['CODE_COVERAGE']
274
+ end
275
+
276
+ expect(@dependinator).to receive(:register).with(
277
+ 'build/foo.o',
278
+ files: ['src/foo.c'],
279
+ meta: hash_including(
280
+ tools: [swapped_tool],
281
+ flags: array_including('-fcondition-coverage'),
282
+ defines: array_including('CODE_COVERAGE')
283
+ )
284
+ )
285
+ expect(@generator).to receive(:generate_object_file_c) do |**args|
286
+ expect( args[:tool] ).to eq( swapped_tool )
287
+ expect( args[:flags] ).to include('-fcondition-coverage')
288
+ expect( args[:defines] ).to include('CODE_COVERAGE')
289
+ end
290
+
291
+ @executor.send(
292
+ :compile_test_component,
293
+ :context => :test, :test => :a_test, :source => 'src/foo.c', :object => 'build/foo.o', :state => @state
294
+ )
295
+ end
296
+
297
+ it "registers the configured compiler tool as meta for a C source, and the configured assembler tool for an assembly source" do
298
+ allow(@file_wrapper).to receive(:extname).with( 'src/foo.c' ).and_return( '.c' )
299
+ allow(@file_wrapper).to receive(:extname).with( 'src/foo.asm' ).and_return( '.asm' )
300
+ allow(@configurator).to receive(:test_build_use_assembly).and_return( true )
301
+ allow(@generator).to receive(:generate_object_file_c)
302
+ allow(@generator).to receive(:generate_object_file_asm)
303
+
304
+ expect(@dependinator).to receive(:register).with( 'build/foo.o', files: ['src/foo.c'], meta: hash_including( tools: [@tools_test_compiler] ) )
305
+ @executor.send(
306
+ :compile_test_component,
307
+ :context => :test, :test => :a_test, :source => 'src/foo.c', :object => 'build/foo.o', :state => @state
308
+ )
309
+
310
+ expect(@dependinator).to receive(:register).with( 'build/foo.o', files: ['src/foo.asm'], meta: hash_including( tools: [@tools_test_assembler] ) )
311
+ @executor.send(
312
+ :compile_test_component,
313
+ :context => :test, :test => :a_test, :source => 'src/foo.asm', :object => 'build/foo.o', :state => @state
314
+ )
315
+ end
316
+
317
+ # A test's own file compile is the one point where its full, transitive dependency
318
+ # closure is freshly known -- reached headers a mock or Partial never sees directly,
319
+ # since substitution only ever looks at what the test file itself #includes. When
320
+ # that closure reveals a real header sharing a directory with one this test mocks or
321
+ # Partializes, quote-include's own same-directory-first rule could let that real
322
+ # content slip past the substitution entirely; isolating the sibling and retrying
323
+ # with corrected search paths closes that gap without ever touching the original
324
+ # compile's own registered dependencies.
325
+ # A source beside a header mocked under :treat_inlines :include would find the real
326
+ # header first and run its inline bodies. It compiles from an isolated copy instead.
327
+ context "a source sharing a directory with a header mocked with inline shadowing" do
328
+ let(:isolation) do
329
+ QuoteIncludeIsolator::Isolation.new( 'build/test/out/a_test/tmp1', { 'src/gpio.c' => 'build/test/out/a_test/tmp1/gpio.c' } )
330
+ end
331
+
332
+ before(:each) do
333
+ allow(@configurator).to receive(:test_build_use_assembly).and_return( false )
334
+ allow(@configurator).to receive(:project_use_mocks).and_return( true )
335
+ allow(@configurator).to receive(:cmock_treat_inlines).and_return( :include )
336
+ allow(@file_wrapper).to receive(:exist_with_retry?).and_return( false )
337
+
338
+ @testable = @state.testables[:a_test]
339
+ @testable.filepath = 'test/test_gpio.c'
340
+ @testable.paths = { :build => 'build/test/out/a_test' }
341
+ @testable.search_paths = ['build/test/mocks/a_test', 'src']
342
+ @testable.mocks = {
343
+ :mock_board => TestInvokerTypes::MockDetails.new( name: 'mock_board', source: 'src/board.h', partial: false )
344
+ }
345
+
346
+ allow(@file_wrapper).to receive(:exist?).with( 'src/gpio.c' ).and_return( true )
347
+ allow(@file_wrapper).to receive(:read).with( 'src/gpio.c' ).and_return( %(#include "board.h"\n) )
348
+
349
+ # A real scoped isolation hands back whatever its block returns
350
+ allow(@quote_include_isolator).to receive(:within) { |**_, &block| block.call( isolation ) }
351
+ allow(@quote_include_isolator).to receive(:restore_dependencies)
352
+ allow(@generator).to receive(:generate_object_file_c)
353
+ end
354
+
355
+ def compile(source: 'src/gpio.c')
356
+ @executor.send(
357
+ :compile_test_component,
358
+ :context => :test, :test => :a_test, :source => source, :object => 'build/gpio.o', :state => @state
359
+ )
360
+ end
361
+
362
+ it "compiles a location-preserving copy, with the original's directory searched last" do
363
+ compile()
364
+
365
+ expect(@quote_include_isolator).to have_received(:within)
366
+ .with( parent: 'build/test/out/a_test', files: ['src/gpio.c'], preserve_location: true )
367
+ expect(@generator).to have_received(:generate_object_file_c).with( hash_including(
368
+ source: 'src/gpio.c',
369
+ compile_source: 'build/test/out/a_test/tmp1/gpio.c',
370
+ search_paths: ['build/test/mocks/a_test', 'src', 'src']
371
+ ) )
372
+ end
373
+
374
+ it "restores the dependency file before registering it" do
375
+ allow(@file_wrapper).to receive(:exist_with_retry?).with( 'build/deps' ).and_return( true )
376
+
377
+ expect(@quote_include_isolator).to receive(:restore_dependencies).with( isolation, 'build/deps' ).ordered
378
+ expect(@dependinator).to receive(:register_gcc_deps_file).with( 'build/deps' ).ordered
379
+
380
+ compile()
381
+ end
382
+
383
+ it "restores the dependency file and raises when the compile fails" do
384
+ ex = ShellException.new( shell_result: { output: 'error' }, name: 'compiler' )
385
+ allow(@generator).to receive(:generate_object_file_c).and_raise( ex )
386
+
387
+ expect { compile() }.to raise_error( ShellException )
388
+ expect(@quote_include_isolator).to have_received(:restore_dependencies).with( isolation, 'build/deps' )
389
+ end
390
+
391
+ it "logs the isolation at NORMAL verbosity, decorated as a notice" do
392
+ compile()
393
+
394
+ expect(@loginator).to have_received(:log).with( a_string_including( 'src/gpio.c', 'src/board.h' ), Verbosity::NORMAL, LogLabels::NOTICE )
395
+ end
396
+
397
+ # Isolation is an implementation detail of how a source compiles. Its staleness must
398
+ # read the same either way, or toggling isolation would force a rebuild.
399
+ it "registers the same staleness meta as an ordinary compile" do
400
+ metas = []
401
+ allow(@dependinator).to receive(:register) { |_, **kwargs| metas << kwargs[:meta] }
402
+
403
+ compile()
404
+ allow(@configurator).to receive(:cmock_treat_inlines).and_return( :exclude )
405
+ compile()
406
+
407
+ expect( metas.uniq.length ).to eq( 1 )
408
+ end
409
+
410
+ shared_examples "an ordinary compile" do
411
+ it "compiles the original in place" do
412
+ compile( source: source )
413
+
414
+ expect(@quote_include_isolator).to_not have_received(:within)
415
+ expect(@generator).to have_received(:generate_object_file_c).with( hash_excluding( :compile_source ) )
416
+ end
417
+ end
418
+
419
+ context "when inline functions are excluded from mocking" do
420
+ before(:each) { allow(@configurator).to receive(:cmock_treat_inlines).and_return( :exclude ) }
421
+ let(:source) { 'src/gpio.c' }
422
+ include_examples "an ordinary compile"
423
+ end
424
+
425
+ context "when mocks are disabled" do
426
+ before(:each) { allow(@configurator).to receive(:project_use_mocks).and_return( false ) }
427
+ let(:source) { 'src/gpio.c' }
428
+ include_examples "an ordinary compile"
429
+ end
430
+
431
+ context "when the mock is a Partial mock" do
432
+ before(:each) { @testable.mocks[:mock_board].partial = true }
433
+ let(:source) { 'src/gpio.c' }
434
+ include_examples "an ordinary compile"
435
+ end
436
+
437
+ context "when the mocked header lives in another directory" do
438
+ before(:each) { @testable.mocks[:mock_board].source = 'inc/board.h' }
439
+ let(:source) { 'src/gpio.c' }
440
+ include_examples "an ordinary compile"
441
+ end
442
+
443
+ context "when the source does not include the mocked header" do
444
+ before(:each) { allow(@file_wrapper).to receive(:read).with( 'src/gpio.c' ).and_return( %(#include "gpio.h"\n) ) }
445
+ let(:source) { 'src/gpio.c' }
446
+ include_examples "an ordinary compile"
447
+ end
448
+
449
+ context "when the source is the test file itself" do
450
+ before(:each) { @testable.filepath = 'src/gpio.c' }
451
+ let(:source) { 'src/gpio.c' }
452
+ include_examples "an ordinary compile"
453
+ end
454
+ end
455
+
456
+ context "sibling-header isolation retry" do
457
+ before(:each) do
458
+ allow(@file_wrapper).to receive(:extname).with( 'test/a_test.c' ).and_return( '.c' )
459
+ allow(@configurator).to receive(:test_build_use_assembly).and_return( false )
460
+ allow(@file_wrapper).to receive(:exist_with_retry?).with( 'build/deps' ).and_return( true )
461
+ allow(@file_wrapper).to receive(:read).and_return( '' )
462
+
463
+ @state.testables[:a_test].filepath = 'test/a_test.c'
464
+ @state.testables[:a_test].paths = { build: 'build/test/out/a_test' }
465
+ @state.testables[:a_test].mocks = {
466
+ gpio: TestInvokerTypes::MockDetails.new(
467
+ name: 'gpio', filepath: '/project/library/gpio.h', path: 'library',
468
+ source: '/project/library/gpio.h', input: '/project/library/gpio.h', partial: false
469
+ )
470
+ }
471
+
472
+ allow(@gcc_dependency_parser).to receive(:parse).and_return(
473
+ { 'build/foo.o' => ['test/a_test.c', '/project/library/gpio.h', '/project/library/driverlib.h'] }
474
+ )
475
+
476
+ # driverlib.h is the sibling under test throughout this context -- it
477
+ # genuinely #includes gpio.h, the signal that distinguishes a real risk
478
+ # from merely sharing a directory.
479
+ allow(@file_wrapper).to receive(:exist?).with( '/project/library/driverlib.h' ).and_return( true )
480
+ allow(@file_wrapper).to receive(:read).with( '/project/library/driverlib.h' ).and_return( "#include \"gpio.h\"\n" )
481
+ end
482
+
483
+ it "retries the compile with corrected search paths when a sibling risk is found, and clears an initial failure" do
484
+ allow(@quote_include_isolator).to receive(:isolate)
485
+ .with( parent: 'build/test/out/a_test', files: ['/project/library/driverlib.h'] )
486
+ .and_return( isolation_in( 'build/test/out/a_test/isolated_headers/xyz' ) )
487
+
488
+ ex = ShellException.new( shell_result: { output: 'redeclaration of struct gpio' }, name: 'compiler' )
489
+ call_count = 0
490
+ allow(@generator).to receive(:generate_object_file_c) do
491
+ call_count += 1
492
+ raise ex if call_count == 1
493
+ end
494
+
495
+ expect {
496
+ @executor.send(
497
+ :compile_test_component,
498
+ :context => :test, :test => :a_test, :source => 'test/a_test.c', :object => 'build/foo.o', :state => @state
499
+ )
500
+ }.to_not raise_error
501
+
502
+ expect( @generator ).to have_received( :generate_object_file_c ).twice
503
+ expect( @state.testables[:a_test].search_paths ).to include( 'build/test/out/a_test/isolated_headers/xyz' )
504
+ expect( @state.testables[:a_test].isolated_headers_path ).to eq( 'build/test/out/a_test/isolated_headers/xyz' )
505
+ end
506
+
507
+ it "retries against a separate, throwaway dependencies path, and registers only the original .d file" do
508
+ allow(@quote_include_isolator).to receive(:isolate).and_return( isolation_in( 'build/test/out/a_test/isolated_headers/xyz' ) )
509
+ allow(@generator).to receive(:generate_object_file_c)
510
+
511
+ expect(@generator).to receive(:generate_object_file_c).with( hash_including( dependencies: 'build/deps' ) ).ordered
512
+ expect(@generator).to receive(:generate_object_file_c).with( hash_including( dependencies: a_string_matching(/\Abuild\/deps\..+/) ) ).ordered
513
+
514
+ expect(@dependinator).to receive(:register_gcc_deps_file).with( 'build/deps' ).at_least(:once)
515
+ expect(@dependinator).to_not receive(:register_gcc_deps_file).with( a_string_matching(/\Abuild\/deps\..+/) )
516
+
517
+ @executor.send(
518
+ :compile_test_component,
519
+ :context => :test, :test => :a_test, :source => 'test/a_test.c', :object => 'build/foo.o', :state => @state
520
+ )
521
+ end
522
+
523
+ it "still raises when the retry itself also fails" do
524
+ allow(@quote_include_isolator).to receive(:isolate).and_return( isolation_in( 'build/test/out/a_test/isolated_headers/xyz' ) )
525
+
526
+ ex = ShellException.new( shell_result: { output: 'redeclaration of struct gpio' }, name: 'compiler' )
527
+ allow(@generator).to receive(:generate_object_file_c).and_raise( ex )
528
+
529
+ expect {
530
+ @executor.send(
531
+ :compile_test_component,
532
+ :context => :test, :test => :a_test, :source => 'test/a_test.c', :object => 'build/foo.o', :state => @state
533
+ )
534
+ }.to raise_error( ShellException )
535
+ end
536
+
537
+ it "does not retry, and still raises, when no sibling risk is found" do
538
+ allow(@gcc_dependency_parser).to receive(:parse).and_return(
539
+ { 'build/foo.o' => ['test/a_test.c', '/project/library/gpio.h'] }
540
+ )
541
+
542
+ ex = ShellException.new( shell_result: { output: 'some unrelated failure' }, name: 'compiler' )
543
+ allow(@generator).to receive(:generate_object_file_c).and_raise( ex )
544
+
545
+ expect {
546
+ @executor.send(
547
+ :compile_test_component,
548
+ :context => :test, :test => :a_test, :source => 'test/a_test.c', :object => 'build/foo.o', :state => @state
549
+ )
550
+ }.to raise_error( ShellException )
551
+
552
+ expect( @generator ).to have_received( :generate_object_file_c ).once
553
+ end
554
+
555
+ it "still registers the original compile's own .d file when the first attempt fails and nothing is isolated" do
556
+ allow(@gcc_dependency_parser).to receive(:parse).and_return(
557
+ { 'build/foo.o' => ['test/a_test.c', '/project/library/gpio.h'] }
558
+ )
559
+ allow(@generator).to receive(:generate_object_file_c).and_raise(
560
+ ShellException.new( shell_result: { output: 'some unrelated failure' }, name: 'compiler' )
561
+ )
562
+
563
+ # Once pre-compile for the previous run's .d file, and once again for the .d file the
564
+ # failed attempt wrote. A failed compile is still a real attempt whose dependency
565
+ # output is worth keeping.
566
+ allow(@file_wrapper).to receive(:exist?).with( 'build/deps' ).and_return( true )
567
+ expect(@dependinator).to receive(:register_gcc_deps_file).with( 'build/deps' ).twice
568
+
569
+ expect {
570
+ @executor.send(
571
+ :compile_test_component,
572
+ :context => :test, :test => :a_test, :source => 'test/a_test.c', :object => 'build/foo.o', :state => @state
573
+ )
574
+ }.to raise_error( ShellException )
575
+ end
576
+
577
+ it "does not attempt isolation for an object other than the test's own file" do
578
+ allow(@file_wrapper).to receive(:extname).with( 'src/other.c' ).and_return( '.c' )
579
+ allow(@generator).to receive(:generate_object_file_c)
580
+
581
+ expect(@gcc_dependency_parser).to_not receive(:parse)
582
+
583
+ @executor.send(
584
+ :compile_test_component,
585
+ :context => :test, :test => :a_test, :source => 'src/other.c', :object => 'build/other.o', :state => @state
586
+ )
587
+ end
588
+
589
+ # A delta build's own whole point is that an unchanged object never recompiles --
590
+ # but isolation's own correction to search_paths only ever happens as a side
591
+ # effect of a real compile. Without also applying it here, every other object in
592
+ # this same test's build would compute its own staleness against paths that
593
+ # silently drift from what actually got cached the last time isolation *did* run,
594
+ # forcing them to recompile on every single subsequent build, forever, even
595
+ # though nothing about the project actually changed.
596
+ it "applies whatever isolation the existing .d file already reveals even when this object is not stale" do
597
+ allow(@dependinator).to receive(:stale?).with( 'build/foo.o' ).and_return( false )
598
+ allow(@quote_include_isolator).to receive(:isolate)
599
+ .with( parent: 'build/test/out/a_test', files: ['/project/library/driverlib.h'] )
600
+ .and_return( isolation_in( 'build/test/out/a_test/isolated_headers/xyz' ) )
601
+
602
+ expect(@generator).to_not receive(:generate_object_file_c)
603
+
604
+ @executor.send(
605
+ :compile_test_component,
606
+ :context => :test, :test => :a_test, :source => 'test/a_test.c', :object => 'build/foo.o', :state => @state
607
+ )
608
+
609
+ expect( @state.testables[:a_test].search_paths ).to include( 'build/test/out/a_test/isolated_headers/xyz' )
610
+ expect( @state.testables[:a_test].isolated_headers_path ).to eq( 'build/test/out/a_test/isolated_headers/xyz' )
611
+ end
612
+
613
+ it "does not attempt isolation on a skip when there is no existing .d file yet" do
614
+ allow(@dependinator).to receive(:stale?).with( 'build/foo.o' ).and_return( false )
615
+ allow(@file_wrapper).to receive(:exist_with_retry?).with( 'build/deps' ).and_return( false )
616
+
617
+ expect(@gcc_dependency_parser).to_not receive(:parse)
618
+ expect(@generator).to_not receive(:generate_object_file_c)
619
+
620
+ @executor.send(
621
+ :compile_test_component,
622
+ :context => :test, :test => :a_test, :source => 'test/a_test.c', :object => 'build/foo.o', :state => @state
623
+ )
624
+ end
625
+
626
+ # A Partial's own generated content never gives isolation an alternative same-named
627
+ # file for a search path to fall through to, so a redeclaration/conflicting-types
628
+ # failure can survive every attempt here. Logging the likely cause alongside the raw
629
+ # compiler error, rather than raising it bare, is the deliberate fallback for exactly
630
+ # that case -- and for any other collision isolation doesn't resolve.
631
+ it "logs the guidance from generator_helper and still raises, when the compile fails with no isolation to try" do
632
+ allow(@gcc_dependency_parser).to receive(:parse).and_return(
633
+ { 'a.o' => ['test/a_test.c', '/project/library/gpio.h'] }
634
+ )
635
+
636
+ ex = ShellException.new( shell_result: { output: 'redeclaration of struct gpio' }, name: 'compiler' )
637
+ allow(@generator).to receive(:generate_object_file_c).and_raise( ex )
638
+
639
+ allow(@generator_helper).to receive(:explain_possible_mock_partial_collision)
640
+ .with( output: 'redeclaration of struct gpio', mocked_headers: { 'gpio.h' => '/project/library/gpio.h' } )
641
+ .and_return( 'explanatory notice text' )
642
+
643
+ expect(@loginator).to receive(:log).with( 'explanatory notice text', Verbosity::ERRORS, LogLabels::NOTICE )
644
+
645
+ expect {
646
+ @executor.send(
647
+ :compile_test_component,
648
+ :context => :test, :test => :a_test, :source => 'test/a_test.c', :object => 'build/foo.o', :state => @state
649
+ )
650
+ }.to raise_error( ShellException )
651
+ end
652
+
653
+ it "logs the guidance after a retry that also fails" do
654
+ allow(@quote_include_isolator).to receive(:isolate).and_return( isolation_in( 'build/test/out/a_test/isolated_headers/xyz' ) )
655
+
656
+ ex = ShellException.new( shell_result: { output: 'redeclaration of struct gpio' }, name: 'compiler' )
657
+ allow(@generator).to receive(:generate_object_file_c).and_raise( ex )
658
+ allow(@generator_helper).to receive(:explain_possible_mock_partial_collision).and_return( 'explanatory notice text' )
659
+
660
+ expect(@loginator).to receive(:log).with( 'explanatory notice text', Verbosity::ERRORS, LogLabels::NOTICE )
661
+
662
+ expect {
663
+ @executor.send(
664
+ :compile_test_component,
665
+ :context => :test, :test => :a_test, :source => 'test/a_test.c', :object => 'build/foo.o', :state => @state
666
+ )
667
+ }.to raise_error( ShellException )
668
+ end
669
+
670
+ it "logs nothing extra when generator_helper finds no explanation" do
671
+ allow(@gcc_dependency_parser).to receive(:parse).and_return(
672
+ { 'a.o' => ['test/a_test.c', '/project/library/gpio.h'] }
673
+ )
674
+ ex = ShellException.new( shell_result: { output: 'totally unrelated failure' }, name: 'compiler' )
675
+ allow(@generator).to receive(:generate_object_file_c).and_raise( ex )
676
+
677
+ expect(@loginator).to_not receive(:log).with( anything, Verbosity::ERRORS, LogLabels::NOTICE )
678
+
679
+ expect {
680
+ @executor.send(
681
+ :compile_test_component,
682
+ :context => :test, :test => :a_test, :source => 'test/a_test.c', :object => 'build/foo.o', :state => @state
683
+ )
684
+ }.to raise_error( ShellException )
685
+ end
686
+ end
687
+ end
688
+
689
+ context "#isolate_sibling_headers" do
690
+ before(:each) do
691
+ @testable = TestInvokerTypes::Testable.new(
692
+ :name => 'a_test', :filepath => 'test/a_test.c',
693
+ :search_paths => ['test/support'],
694
+ :paths => { build: 'build/test/out/a_test' }
695
+ )
696
+
697
+ allow(@file_wrapper).to receive(:read).with( 'build/deps' ).and_return( '' )
698
+ end
699
+
700
+ def call_it
701
+ @executor.send( :isolate_sibling_headers, testable: @testable, dependencies_filepath: 'build/deps' )
702
+ end
703
+
704
+ it "returns nil, and never reads the dependencies file, when the testable mocks or Partializes nothing" do
705
+ expect(@file_wrapper).to_not receive(:read)
706
+ expect( call_it() ).to be_nil
707
+ end
708
+
709
+ context "with a mocked header" do
710
+ before(:each) do
711
+ @testable.mocks = {
712
+ gpio: TestInvokerTypes::MockDetails.new(
713
+ name: 'gpio', filepath: '/project/library/gpio.h', path: 'library',
714
+ source: '/project/library/gpio.h', input: '/project/library/gpio.h', partial: false
715
+ )
716
+ }
717
+
718
+ # driverlib.h is the sibling under test throughout this context -- it
719
+ # genuinely #includes gpio.h, the signal that distinguishes a real risk
720
+ # from merely sharing a directory.
721
+ allow(@file_wrapper).to receive(:exist?).with( '/project/library/driverlib.h' ).and_return( true )
722
+ allow(@file_wrapper).to receive(:read).with( '/project/library/driverlib.h' ).and_return( "#include \"gpio.h\"\n" )
723
+ end
724
+
725
+ it "returns nil when the mocked header itself never appears in the dependency list" do
726
+ allow(@gcc_dependency_parser).to receive(:parse).and_return(
727
+ { 'a.o' => ['test/a_test.c', '/project/other/unrelated.h'] }
728
+ )
729
+ expect( call_it() ).to be_nil
730
+ end
731
+
732
+ it "returns nil when the mocked header has no directory-mates in the dependency list" do
733
+ allow(@gcc_dependency_parser).to receive(:parse).and_return(
734
+ { 'a.o' => ['test/a_test.c', '/project/library/gpio.h', '/project/other/unrelated.h'] }
735
+ )
736
+ expect( call_it() ).to be_nil
737
+ end
738
+
739
+ # A same-directory file is a real project header layout, not a special one --
740
+ # most projects keep every header in one shared directory as ordinary
741
+ # convention. A candidate that merely lives beside the mocked header, without
742
+ # itself #including it, is exactly that ordinary case, not a collision risk;
743
+ # isolating it anyway would recompile it every single build for no reason.
744
+ it "does not isolate a same-directory file that does not itself #include the mocked header" do
745
+ allow(@file_wrapper).to receive(:exist?).with( '/project/library/unrelated_neighbor.h' ).and_return( true )
746
+ allow(@file_wrapper).to receive(:read).with( '/project/library/unrelated_neighbor.h' ).and_return( "#include <stdint.h>\n" )
747
+
748
+ allow(@gcc_dependency_parser).to receive(:parse).and_return(
749
+ { 'a.o' => ['test/a_test.c', '/project/library/gpio.h', '/project/library/unrelated_neighbor.h'] }
750
+ )
751
+
752
+ expect(@quote_include_isolator).to_not receive(:isolate)
753
+ expect( call_it() ).to be_nil
754
+ end
755
+
756
+ it "isolates a real header sharing a directory with the mocked header, prepending the isolation directory to search paths" do
757
+ allow(@gcc_dependency_parser).to receive(:parse).and_return(
758
+ { 'a.o' => ['test/a_test.c', '/project/library/gpio.h', '/project/library/driverlib.h'] }
759
+ )
760
+ allow(@quote_include_isolator).to receive(:isolate)
761
+ .with( parent: 'build/test/out/a_test', files: ['/project/library/driverlib.h'] )
762
+ .and_return( isolation_in( 'build/test/out/a_test/isolated_headers/xyz' ) )
763
+
764
+ result = call_it()
765
+
766
+ expect( result ).to eq(
767
+ search_paths: ['build/test/out/a_test/isolated_headers/xyz', 'test/support'],
768
+ isolation_dir: 'build/test/out/a_test/isolated_headers/xyz'
769
+ )
770
+ end
771
+
772
+ it "logs the isolation at NORMAL verbosity, decorated as a notice" do
773
+ allow(@gcc_dependency_parser).to receive(:parse).and_return(
774
+ { 'a.o' => ['test/a_test.c', '/project/library/gpio.h', '/project/library/driverlib.h'] }
775
+ )
776
+ allow(@quote_include_isolator).to receive(:isolate).and_return( isolation_in( 'isolated/dir' ) )
777
+
778
+ expect(@loginator).to receive(:log).with(
779
+ a_string_including( '/project/library/driverlib.h' ).and( a_string_including( '/project/library/gpio.h' ) ),
780
+ Verbosity::NORMAL, LogLabels::NOTICE
781
+ )
782
+
783
+ call_it()
784
+ end
785
+
786
+ it "excludes a mock-Partial's own generated source from consideration entirely" do
787
+ @testable.mocks[:gpio].partial = true
788
+
789
+ allow(@gcc_dependency_parser).to receive(:parse).and_return(
790
+ { 'a.o' => ['test/a_test.c', '/project/library/gpio.h', '/project/library/driverlib.h'] }
791
+ )
792
+
793
+ expect(@quote_include_isolator).to_not receive(:isolate)
794
+ expect( call_it() ).to be_nil
795
+ end
796
+
797
+ it "reports, but does not isolate, another shared directory elsewhere in the dependency list" do
798
+ allow(@gcc_dependency_parser).to receive(:parse).and_return(
799
+ {
800
+ 'a.o' => [
801
+ 'test/a_test.c', '/project/library/gpio.h', '/project/library/driverlib.h',
802
+ '/project/other/x.h', '/project/other/y.h'
803
+ ]
804
+ }
805
+ )
806
+ allow(@quote_include_isolator).to receive(:isolate)
807
+ .with( parent: 'build/test/out/a_test', files: ['/project/library/driverlib.h'] )
808
+ .and_return( isolation_in( 'isolated/dir' ) )
809
+
810
+ expect(@loginator).to receive(:log).with(
811
+ a_string_including( '/project/other/x.h' ).and( a_string_including( '/project/other/y.h' ) ),
812
+ Verbosity::COMPLAIN, LogLabels::NOTICE
813
+ )
814
+
815
+ result = call_it()
816
+
817
+ expect( result[:search_paths] ).to_not include( a_string_including( '/project/other' ) )
818
+ end
819
+
820
+ it "logs nothing at all when there is no risk anywhere in the dependency list" do
821
+ allow(@gcc_dependency_parser).to receive(:parse).and_return(
822
+ { 'a.o' => ['test/a_test.c', '/project/library/gpio.h'] }
823
+ )
824
+
825
+ expect(@loginator).to_not receive(:log).with( anything, anything, LogLabels::NOTICE )
826
+
827
+ call_it()
828
+ end
829
+
830
+ # This test's own mocks output directory routinely holds several generated files
831
+ # side by side (a mock's own interface header, and -- when :treat_inlines: :include
832
+ # is configured -- a same-basename shadow of the real header too), and Unity's own
833
+ # vendor directory ships more than one header as a matter of course. Neither is a
834
+ # real project header directory a quote-include could ambiguously resolve within,
835
+ # so neither belongs in the "worth investigating" heads-up.
836
+ it "does not report co-resident files inside this test's own mocks output directory or a vendor framework directory" do
837
+ @testable.paths = { build: 'build/test/out/a_test', mocks: 'build/test/mocks/a_test' }
838
+
839
+ allow(@gcc_dependency_parser).to receive(:parse).and_return(
840
+ {
841
+ 'a.o' => [
842
+ 'test/a_test.c', '/project/library/gpio.h',
843
+ 'build/test/mocks/a_test/mock_gpio.h', 'build/test/mocks/a_test/gpio.h',
844
+ PROJECT_BUILD_VENDOR_UNITY_PATH + '/unity.h', PROJECT_BUILD_VENDOR_UNITY_PATH + '/unity_internals.h'
845
+ ]
846
+ }
847
+ )
848
+
849
+ expect(@loginator).to_not receive(:log).with( anything, Verbosity::COMPLAIN, anything )
850
+
851
+ call_it()
852
+ end
853
+
854
+ # A test's own Partials output directory is shaped exactly the same way as its
855
+ # mocks output directory -- several generated headers (a types header, an
856
+ # interface header, and more) routinely sit side by side there, one set per
857
+ # Partialized module, none of it a real project header.
858
+ it "does not report co-resident files inside this test's own Partials output directory" do
859
+ @testable.paths = { build: 'build/test/out/a_test', partials: 'build/test/partials/a_test' }
860
+
861
+ allow(@gcc_dependency_parser).to receive(:parse).and_return(
862
+ {
863
+ 'a.o' => [
864
+ 'test/a_test.c', '/project/library/gpio.h',
865
+ 'build/test/partials/a_test/ceedling_partial_moduleA_impl.h',
866
+ 'build/test/partials/a_test/ceedling_partial_gpio_interface.h',
867
+ 'build/test/partials/a_test/ceedling_partial_gpio_types.h'
868
+ ]
869
+ }
870
+ )
871
+
872
+ expect(@loginator).to_not receive(:log).with( anything, Verbosity::COMPLAIN, anything )
873
+
874
+ call_it()
875
+ end
876
+ end
877
+
878
+ context "with a Partialized header" do
879
+ it "isolates a real header sharing a directory with the Partial's own header" do
880
+ @testable.partials = TestInvokerTypes::TestablePartials.new(
881
+ configs: { moduleA: double( "PartialConfig", header: double( "HeaderFile", filepath: '/project/library/moduleA.h' ) ) },
882
+ tests: [], mocks: []
883
+ )
884
+
885
+ allow(@gcc_dependency_parser).to receive(:parse).and_return(
886
+ { 'a.o' => ['test/a_test.c', '/project/library/moduleA.h', '/project/library/driverlib.h'] }
887
+ )
888
+ allow(@file_wrapper).to receive(:exist?).with( '/project/library/driverlib.h' ).and_return( true )
889
+ allow(@file_wrapper).to receive(:read).with( '/project/library/driverlib.h' ).and_return( "#include \"moduleA.h\"\n" )
890
+ allow(@quote_include_isolator).to receive(:isolate)
891
+ .with( parent: 'build/test/out/a_test', files: ['/project/library/driverlib.h'] )
892
+ .and_return( isolation_in( 'isolated/dir' ) )
893
+
894
+ expect( call_it() ).to_not be_nil
895
+ end
896
+ end
113
897
  end
898
+
899
+ context "#stage_build_objects" do
900
+ before(:each) do
901
+ stub_batchinator_exec()
902
+
903
+ allow(@file_finder).to receive(:find_build_input_file).and_return( 'src/foo.c' )
904
+ allow(@file_wrapper).to receive(:extname).and_return( '.c' )
905
+ allow(@configurator).to receive(:test_build_use_assembly).and_return( false )
906
+
907
+ @testable = TestInvokerTypes::Testable.new(
908
+ :name => 'a_test',
909
+ :compile_defines => [], :search_paths => [], :compile_flags => []
910
+ )
911
+ @state = TestInvokerTypes::PipelineState.new(
912
+ :testables => { :a_test => @testable },
913
+ :objects_list => [ TestInvokerTypes::ObjectWork.new( test: :a_test, obj: 'build/foo.o' ) ],
914
+ :lock => Mutex.new, :context => :test, :options => []
915
+ )
916
+ end
917
+
918
+ it "logs a summary line stating how many objects were recalled from cache" do
919
+ allow(@dependinator).to receive(:stale?).and_return( false )
920
+
921
+ allow(@reportinator).to receive(:generate_skip_summary).and_return( "Skipping compilation for 1 object (nothing changed)..." )
922
+
923
+ expect(@loginator).to receive(:log).with( "Skipping compilation for 1 object (nothing changed)..." )
924
+ @executor.stage_build_objects( @state )
925
+ end
926
+
927
+ it "logs no summary line when every object needed compiling" do
928
+ allow(@dependinator).to receive(:stale?).and_return( true )
929
+ allow(@generator).to receive(:generate_object_file_c)
930
+
931
+ expect(@loginator).to_not receive(:log).with( /Skipping compilation/ )
932
+
933
+ @executor.stage_build_objects( @state )
934
+ end
935
+
936
+ # A test's own file compiles in a batch fully completed before any other object
937
+ # starts -- any search-path fix-up sibling isolation makes during that first
938
+ # compile needs to be visible to every other object in the same test's build,
939
+ # and parallel compilation gives no other guarantee that it lands before them.
940
+ it "compiles the test's own file fully before any other object in the same test begins" do
941
+ @testable.filepath = 'test/a_test.c'
942
+ @testable.paths = { build: 'build/test/out/a_test' }
943
+
944
+ @state.objects_list = [
945
+ TestInvokerTypes::ObjectWork.new( test: :a_test, obj: 'build/other.o' ),
946
+ TestInvokerTypes::ObjectWork.new( test: :a_test, obj: 'build/a_test.o' )
947
+ ]
948
+
949
+ allow(@file_finder).to receive(:find_build_input_file)
950
+ .with( filepath: 'build/other.o', context: :test, test: :a_test ).and_return( 'src/other.c' )
951
+ allow(@file_finder).to receive(:find_build_input_file)
952
+ .with( filepath: 'build/a_test.o', context: :test, test: :a_test ).and_return( 'test/a_test.c' )
953
+
954
+ order = []
955
+ allow(@generator).to receive(:generate_object_file_c) do |**args|
956
+ order << args[:source]
957
+ end
958
+
959
+ @executor.stage_build_objects( @state )
960
+
961
+ expect( order ).to eq( ['test/a_test.c', 'src/other.c'] )
962
+ end
963
+
964
+ it "removes a testable's isolated headers directory once, after both batches complete" do
965
+ @testable.isolated_headers_path = 'build/test/out/a_test/isolated_headers/xyz'
966
+ allow(@dependinator).to receive(:stale?).and_return( false )
967
+
968
+ expect(@quote_include_isolator).to receive(:release).with( 'build/test/out/a_test/isolated_headers/xyz' ).once
969
+
970
+ @executor.stage_build_objects( @state )
971
+ end
972
+
973
+ it "attempts no cleanup for a testable that never isolated anything" do
974
+ allow(@dependinator).to receive(:stale?).and_return( false )
975
+
976
+ expect(@quote_include_isolator).to_not receive(:release)
977
+
978
+ @executor.stage_build_objects( @state )
979
+ end
980
+ end
981
+
982
+ context "#stage_build_executables" do
983
+ before(:each) do
984
+ stub_batchinator_exec()
985
+
986
+ allow(@configurator).to receive(:project_config_hash).and_return( {} )
987
+ allow(@file_path_utils).to receive(:form_test_build_map_filepath).and_return( 'build/map' )
988
+
989
+ allow(@generator).to receive(:generate_test_executable_manifest)
990
+
991
+ @testable = TestInvokerTypes::Testable.new(
992
+ :name => 'a_test',
993
+ :filepath => 'test/a_test.c',
994
+ :objects => ['build/foo.o'],
995
+ :executable => 'build/a_test.out',
996
+ :link_flags => [],
997
+ :paths => { :build => 'build/test' }
998
+ )
999
+ @state = TestInvokerTypes::PipelineState.new( :testables => { :a_test => @testable }, :lock => Mutex.new, :context => :test, :options => [] )
1000
+ end
1001
+
1002
+ it "links and marks the executable fresh, and records that it was rebuilt, when the dependency tracker reports it stale" do
1003
+ allow(@dependinator).to receive(:stale?).and_return( true )
1004
+ expect(@generator).to receive(:generate_executable_file)
1005
+ expect(@dependinator).to receive(:mark_fresh).with('build/a_test.out')
1006
+
1007
+ @executor.stage_build_executables( @state )
1008
+
1009
+ expect( @testable.executable_rebuilt ).to be(true)
1010
+ end
1011
+
1012
+ it "skips linking and records that it was not rebuilt when the dependency tracker reports it unchanged" do
1013
+ allow(@dependinator).to receive(:stale?).and_return( false )
1014
+ expect(@generator).to_not receive(:generate_executable_file)
1015
+ expect(@dependinator).to_not receive(:mark_fresh)
1016
+
1017
+ @executor.stage_build_executables( @state )
1018
+
1019
+ expect( @testable.executable_rebuilt ).to be(false)
1020
+ end
1021
+
1022
+ # An executable linked by an earlier build still needs its manifest
1023
+ it "provides each executable its manifest, whether linked or skipped" do
1024
+ allow(@generator).to receive(:generate_executable_file)
1025
+
1026
+ [true, false].each do |stale|
1027
+ allow(@dependinator).to receive(:stale?).and_return( stale )
1028
+ expect(@generator).to receive(:generate_test_executable_manifest).with( executable: 'build/a_test.out', test_filepath: 'test/a_test.c' )
1029
+
1030
+ @executor.stage_build_executables( @state )
1031
+ end
1032
+ end
1033
+
1034
+ it "resolves the link tool/flags through pre_test_link_register before registering staleness meta, and uses the resolved values for the real link" do
1035
+ allow(@dependinator).to receive(:stale?).and_return( true )
1036
+
1037
+ swapped_tool = { name: 'fake bullseye linker' }
1038
+ allow(@plugin_manager).to receive(:pre_test_link_register) do |arg_hash|
1039
+ arg_hash[:tool] = swapped_tool
1040
+ end
1041
+
1042
+ expect(@dependinator).to receive(:register).with(
1043
+ 'build/a_test.out',
1044
+ files: ['build/foo.o'],
1045
+ meta: hash_including( tools: [swapped_tool] )
1046
+ )
1047
+ expect(@generator).to receive(:generate_executable_file) do |tool, *_rest|
1048
+ expect( tool ).to eq( swapped_tool )
1049
+ end
1050
+
1051
+ @executor.stage_build_executables( @state )
1052
+ end
1053
+
1054
+ it "registers the configured test linker tool as meta, alongside link flags and library arguments" do
1055
+ allow(@dependinator).to receive(:stale?).and_return( false )
1056
+
1057
+ expect(@dependinator).to receive(:register).with(
1058
+ 'build/a_test.out',
1059
+ files: ['build/foo.o'],
1060
+ meta: { flags: [], lib_args: [], lib_paths: [], tools: [@tools_test_linker] }
1061
+ )
1062
+
1063
+ @executor.stage_build_executables( @state )
1064
+ end
1065
+
1066
+ it "logs a summary line stating how many executables were recalled from cache" do
1067
+ allow(@dependinator).to receive(:stale?).and_return( false )
1068
+
1069
+ allow(@reportinator).to receive(:generate_skip_summary).and_return( "Skipping linking for 1 executable (nothing changed)..." )
1070
+
1071
+ expect(@loginator).to receive(:log).with( "Skipping linking for 1 executable (nothing changed)..." )
1072
+ @executor.stage_build_executables( @state )
1073
+ end
1074
+ end
1075
+
1076
+ context "#generate_executable" do
1077
+ before(:each) do
1078
+ allow(@file_path_utils).to receive(:form_test_build_map_filepath).and_return( 'build/map' )
1079
+ allow(@configurator).to receive(:project_use_mocks).and_return( false )
1080
+ end
1081
+
1082
+ def build_args
1083
+ {
1084
+ context: :test,
1085
+ build_path: 'build/test',
1086
+ executable: 'build/a_test.out',
1087
+ objects: ['build/foo.o'],
1088
+ flags: [],
1089
+ lib_args: [],
1090
+ lib_paths: [],
1091
+ tool: { name: 'fake linker' }
1092
+ }
1093
+ end
1094
+
1095
+ it "re-raises a ShellException from the linker" do
1096
+ ex = ShellException.new( shell_result: { output: 'some unrelated linker failure' }, name: 'linker' )
1097
+ allow(@generator).to receive(:generate_executable_file).and_raise( ex )
1098
+ allow(@loginator).to receive(:log)
1099
+
1100
+ expect {
1101
+ @executor.generate_executable( **build_args )
1102
+ }.to raise_error( ShellException )
1103
+ end
1104
+
1105
+ it "logs missing-symbols guidance when the shell output mentions a symbol, before re-raising" do
1106
+ ex = ShellException.new( shell_result: { output: 'undefined reference to symbol foo' }, name: 'linker' )
1107
+ allow(@generator).to receive(:generate_executable_file).and_raise( ex )
1108
+
1109
+ expect(@loginator).to receive(:log).with(
1110
+ a_string_matching(/missing symbols/i),
1111
+ Verbosity::COMPLAIN,
1112
+ LogLabels::NOTICE
1113
+ )
1114
+
1115
+ expect {
1116
+ @executor.generate_executable( **build_args )
1117
+ }.to raise_error( ShellException )
1118
+ end
1119
+
1120
+ it "does not log guidance when the shell output does not mention a symbol" do
1121
+ ex = ShellException.new( shell_result: { output: 'some unrelated linker failure' }, name: 'linker' )
1122
+ allow(@generator).to receive(:generate_executable_file).and_raise( ex )
1123
+
1124
+ expect(@loginator).to_not receive(:log)
1125
+
1126
+ expect {
1127
+ @executor.generate_executable( **build_args )
1128
+ }.to raise_error( ShellException )
1129
+ end
1130
+
1131
+ it "includes mock-specific guidance only when the project uses mocks" do
1132
+ ex = ShellException.new( shell_result: { output: 'missing symbol foo' }, name: 'linker' )
1133
+ allow(@generator).to receive(:generate_executable_file).and_raise( ex )
1134
+ allow(@configurator).to receive(:project_use_mocks).and_return( true )
1135
+
1136
+ expect(@loginator).to receive(:log).with(
1137
+ a_string_matching(/needed mocks/i),
1138
+ Verbosity::COMPLAIN,
1139
+ LogLabels::NOTICE
1140
+ )
1141
+
1142
+ expect {
1143
+ @executor.generate_executable( **build_args )
1144
+ }.to raise_error( ShellException )
1145
+ end
1146
+
1147
+ it "does not raise when the linker succeeds" do
1148
+ allow(@generator).to receive(:generate_executable_file)
1149
+
1150
+ expect { @executor.generate_executable( **build_args ) }.to_not raise_error
1151
+ end
1152
+ end
1153
+
1154
+ context "#stage_execute" do
1155
+ before(:each) do
1156
+ stub_batchinator_exec()
1157
+ allow(@plugin_manager).to receive(:post_test)
1158
+ # Flushed once after every testable in this stage has executed -- see
1159
+ # `report_gdb_attach_health`'s own spec for its actual behavior.
1160
+ allow(@generator).to receive(:report_gdb_attach_health)
1161
+
1162
+ # This context's own tests are about executable_rebuilt/force_rerun/shuffle
1163
+ # deciding whether a fixture reruns, so the fixture-target's own staleness
1164
+ # (the tool-config trigger) defaults to fresh here -- see the dedicated
1165
+ # "tool configuration changed" examples below for that case on its own.
1166
+ allow(@dependinator).to receive(:stale?).and_return( false )
1167
+ allow(@file_wrapper).to receive(:touch)
1168
+
1169
+ @testable = TestInvokerTypes::Testable.new(
1170
+ :name => 'a_test',
1171
+ :filepath => 'test/TestFoo.c',
1172
+ :executable => 'build/a_test.out',
1173
+ :results_pass => 'build/a_test.pass',
1174
+ :paths => { :results => 'build/test/results' }
1175
+ )
1176
+ @state = TestInvokerTypes::PipelineState.new( :testables => { :a_test => @testable }, :lock => Mutex.new, :context => :test, :options => [] )
1177
+ @fixture_target = 'build/test/results/a_test.fixture_run'
1178
+ end
1179
+
1180
+ it "runs the test fixture when stage 16 rebuilt the executable, first clearing any stale prior result" do
1181
+ @testable.executable_rebuilt = true
1182
+ allow(@file_wrapper).to receive(:rm_f)
1183
+ expect(@file_wrapper).to receive(:rm_f).with( Dir.glob( File.join( 'build/test/results', 'a_test.*' ) ) )
1184
+ expect(@generator).to receive(:generate_test_results).with( hash_including( skipped: false ) )
1185
+
1186
+ @executor.stage_execute( @state )
1187
+ end
1188
+
1189
+ # A skipped run reuses the result file, so the fixture target vouches for it. Damage
1190
+ # to that file then reads as stale and the test reruns instead of reusing it.
1191
+ it "registers the result files as outputs of the fixture target before marking it fresh after a real run" do
1192
+ @testable.executable_rebuilt = true
1193
+ allow(@file_wrapper).to receive(:rm_f)
1194
+ allow(@generator).to receive(:generate_test_results)
1195
+
1196
+ expect(@dependinator).to receive(:register).with( @fixture_target, outputs: ['build/a_test.pass', 'build/a_test.fail'] ).ordered
1197
+ expect(@dependinator).to receive(:mark_fresh).with( @fixture_target ).ordered
1198
+
1199
+ @executor.stage_execute( @state )
1200
+ end
1201
+
1202
+ it "registers no outputs on a skipped run" do
1203
+ @testable.executable_rebuilt = false
1204
+ allow(@generator).to receive(:generate_test_results)
1205
+
1206
+ expect(@dependinator).to_not receive(:register).with( @fixture_target, hash_including( :outputs ) )
1207
+
1208
+ @executor.stage_execute( @state )
1209
+ end
1210
+
1211
+ it "reports the cached result instead of running the test fixture when stage 16 found the executable unchanged, and does not touch the cached result file" do
1212
+ @testable.executable_rebuilt = false
1213
+ expect(@generator).to receive(:generate_test_results).with( hash_including( skipped: true ) )
1214
+ expect(@file_wrapper).to_not receive(:rm_f)
1215
+
1216
+ @executor.stage_execute( @state )
1217
+ end
1218
+
1219
+ it "runs the test fixture and clears any stale prior result when :force_test_rerun is enabled, even though the executable is unchanged" do
1220
+ @testable.executable_rebuilt = false
1221
+ allow(@configurator).to receive(:force_test_rerun).and_return( true )
1222
+ allow(@file_wrapper).to receive(:rm_f)
1223
+ expect(@file_wrapper).to receive(:rm_f).with( Dir.glob( File.join( 'build/test/results', 'a_test.*' ) ) )
1224
+ expect(@generator).to receive(:generate_test_results).with( hash_including( skipped: false ) )
1225
+
1226
+ @executor.stage_execute( @state )
1227
+ end
1228
+
1229
+ it "runs the test fixture and clears any stale prior result when :unity ↳ :shuffle_tests is enabled, even though the executable is unchanged" do
1230
+ @testable.executable_rebuilt = false
1231
+ allow(@configurator).to receive(:unity_shuffle_tests).and_return( true )
1232
+ allow(@file_wrapper).to receive(:rm_f)
1233
+ expect(@file_wrapper).to receive(:rm_f).with( Dir.glob( File.join( 'build/test/results', 'a_test.*' ) ) )
1234
+ expect(@generator).to receive(:generate_test_results).with( hash_including( skipped: false ) )
1235
+
1236
+ @executor.stage_execute( @state )
1237
+ end
1238
+
1239
+ it "logs a NOTICE that shuffling is overriding a delta-build skip when :unity ↳ :shuffle_tests is enabled and the executable is unchanged" do
1240
+ @testable.executable_rebuilt = false
1241
+ allow(@configurator).to receive(:unity_shuffle_tests).and_return( true )
1242
+ allow(@generator).to receive(:generate_test_results)
1243
+ allow(@file_wrapper).to receive(:rm_f)
1244
+
1245
+ expect(@loginator).to receive(:log)
1246
+ .with( /1 already up-to-date test executable/, Verbosity::NORMAL, LogLabels::NOTICE )
1247
+
1248
+ @executor.stage_execute( @state )
1249
+ end
1250
+
1251
+ it "does not log the shuffling NOTICE when :unity ↳ :shuffle_tests is enabled but the executable was already rebuilt (nothing to override)" do
1252
+ @testable.executable_rebuilt = true
1253
+ allow(@configurator).to receive(:unity_shuffle_tests).and_return( true )
1254
+ allow(@generator).to receive(:generate_test_results)
1255
+ allow(@file_wrapper).to receive(:rm_f)
1256
+
1257
+ expect(@loginator).to_not receive(:log).with( /shuffl/i, any_args )
1258
+
1259
+ @executor.stage_execute( @state )
1260
+ end
1261
+
1262
+ it "does not log the shuffling NOTICE when :force_test_rerun (not shuffling) is what forces the rerun" do
1263
+ @testable.executable_rebuilt = false
1264
+ allow(@configurator).to receive(:force_test_rerun).and_return( true )
1265
+ allow(@generator).to receive(:generate_test_results)
1266
+ allow(@file_wrapper).to receive(:rm_f)
1267
+
1268
+ expect(@loginator).to_not receive(:log).with( /shuffl/i, any_args )
1269
+
1270
+ @executor.stage_execute( @state )
1271
+ end
1272
+
1273
+ it "always fires the post_test plugin hook, rebuilt or not" do
1274
+ @testable.executable_rebuilt = false
1275
+ allow(@generator).to receive(:generate_test_results)
1276
+ expect(@plugin_manager).to receive(:post_test).with('test/TestFoo.c')
1277
+
1278
+ @executor.stage_execute( @state )
1279
+ end
1280
+
1281
+ it "logs a summary line stating how many tests reused a cached result" do
1282
+ @testable.executable_rebuilt = false
1283
+ allow(@generator).to receive(:generate_test_results)
1284
+
1285
+ allow(@reportinator).to receive(:generate_skip_summary).and_return( "Skipping test execution for 1 test (reusing cached results)..." )
1286
+
1287
+ expect(@loginator).to receive(:log).with( "Skipping test execution for 1 test (reusing cached results)..." )
1288
+ @executor.stage_execute( @state )
1289
+ end
1290
+
1291
+ it "resolves the fixture tool through pre_test_fixture_register before registering staleness meta, and uses the resolved value for the real run" do
1292
+ @testable.executable_rebuilt = false
1293
+
1294
+ swapped_tool = { name: 'fake valgrind wrapper' }
1295
+ allow(@plugin_manager).to receive(:pre_test_fixture_register) do |arg_hash|
1296
+ expect( arg_hash[:target] ).to eq( @fixture_target )
1297
+ arg_hash[:tool] = swapped_tool
1298
+ end
1299
+
1300
+ expect(@dependinator).to receive(:register).with(
1301
+ @fixture_target,
1302
+ files: ['build/a_test.out'],
1303
+ meta: hash_including( tools: [swapped_tool] )
1304
+ )
1305
+ expect(@generator).to receive(:generate_test_results) do |**args|
1306
+ expect( args[:tool] ).to eq( swapped_tool )
1307
+ end
1308
+
1309
+ @executor.stage_execute( @state )
1310
+ end
1311
+
1312
+ it "registers a dedicated marker target separate from the executable, with the executable as antecedent and the test fixture tool as meta" do
1313
+ @testable.executable_rebuilt = false
1314
+ allow(@generator).to receive(:generate_test_results)
1315
+
1316
+ expect(@dependinator).to receive(:register).with(
1317
+ @fixture_target,
1318
+ files: ['build/a_test.out'],
1319
+ meta: hash_including( tools: [@tools_test_fixture] )
1320
+ )
1321
+
1322
+ @executor.stage_execute( @state )
1323
+ end
1324
+
1325
+ # :use_backtrace doesn't swap the fixture tool itself -- it only selects what
1326
+ # generator.rb does *after* a crash is detected (see this call site's own comment
1327
+ # in test_build_executor.rb). Without capturing it (and the tool config(s) it
1328
+ # drives) as meta here, toggling it would never invalidate a cached-fresh
1329
+ # fixture_target, so a delta build would keep reusing a stale crash-diagnosis result.
1330
+ it "registers :use_backtrace and the gdb backtrace tool as meta when :use_backtrace is :gdb" do
1331
+ @testable.executable_rebuilt = false
1332
+ allow(@generator).to receive(:generate_test_results)
1333
+ allow(@configurator).to receive(:project_config_hash).and_return( { project_use_backtrace: :gdb } )
1334
+ allow(@configurator).to receive(:tools_test_backtrace_gdb).and_return( @tools_test_backtrace_gdb )
1335
+
1336
+ expect(@dependinator).to receive(:register).with(
1337
+ @fixture_target,
1338
+ files: ['build/a_test.out'],
1339
+ meta: {
1340
+ tools: [@tools_test_fixture],
1341
+ use_backtrace: :gdb,
1342
+ backtrace_tools: [@tools_test_fixture_simple_backtrace, @tools_test_backtrace_gdb]
1343
+ }
1344
+ )
1345
+
1346
+ @executor.stage_execute( @state )
1347
+ end
1348
+
1349
+ # Regression guard: tools_test_backtrace_gdb only exists on the real Configurator
1350
+ # when :use_backtrace is :gdb (Configurator only merges its defaults in that case) --
1351
+ # calling it unconditionally raised NoMethodError against a real project configured
1352
+ # for :simple or :none. @configurator here is a plain double with no stub for
1353
+ # tools_test_backtrace_gdb, so it fails the same way a real run would if this
1354
+ # regressed.
1355
+ it "registers only the simple backtrace tool as meta, and never reads the gdb tool's config, when :use_backtrace is :simple" do
1356
+ @testable.executable_rebuilt = false
1357
+ allow(@generator).to receive(:generate_test_results)
1358
+ allow(@configurator).to receive(:project_config_hash).and_return( { project_use_backtrace: :simple } )
1359
+
1360
+ expect(@dependinator).to receive(:register).with(
1361
+ @fixture_target,
1362
+ files: ['build/a_test.out'],
1363
+ meta: {
1364
+ tools: [@tools_test_fixture],
1365
+ use_backtrace: :simple,
1366
+ backtrace_tools: [@tools_test_fixture_simple_backtrace]
1367
+ }
1368
+ )
1369
+
1370
+ @executor.stage_execute( @state )
1371
+ end
1372
+
1373
+ it "reruns the test fixture when only the :tools ↳ :test_fixture configuration changed, even though the executable is unchanged" do
1374
+ @testable.executable_rebuilt = false
1375
+ allow(@dependinator).to receive(:stale?).with(@fixture_target).and_return( true )
1376
+ allow(@file_wrapper).to receive(:rm_f)
1377
+
1378
+ expect(@file_wrapper).to receive(:rm_f).with( Dir.glob( File.join( 'build/test/results', 'a_test.*' ) ) )
1379
+ expect(@generator).to receive(:generate_test_results).with( hash_including( skipped: false ) )
1380
+ expect(@dependinator).to receive(:mark_fresh).with(@fixture_target)
1381
+
1382
+ @executor.stage_execute( @state )
1383
+ end
1384
+
1385
+ # The whole reason this target is a dedicated marker file rather than the test's own
1386
+ # outcome-dependent .pass/.fail result file: a failing test never writes the .pass
1387
+ # path, and DependencyTracker#mark_fresh would otherwise crash trying to hash a target
1388
+ # that doesn't exist -- exactly the CI failure this scenario guards against regressing.
1389
+ it "marks the marker target fresh after a real run even when the test itself fails" do
1390
+ @testable.executable_rebuilt = true
1391
+ allow(@file_wrapper).to receive(:rm_f)
1392
+ allow(@generator).to receive(:generate_test_results).and_return( { results: { counts: { failed: 1 } } } )
1393
+
1394
+ expect(@file_wrapper).to receive(:touch).with(@fixture_target)
1395
+ expect(@dependinator).to receive(:mark_fresh).with(@fixture_target)
1396
+
1397
+ @executor.stage_execute( @state )
1398
+ end
1399
+
1400
+ it "does not mark the fixture target fresh when the run was skipped" do
1401
+ @testable.executable_rebuilt = false
1402
+ allow(@generator).to receive(:generate_test_results)
1403
+
1404
+ expect(@dependinator).to_not receive(:mark_fresh)
1405
+
1406
+ @executor.stage_execute( @state )
1407
+ end
1408
+ end
1409
+
1410
+ context "#stage_preprocess_mocks" do
1411
+ before(:each) do
1412
+ stub_batchinator_exec()
1413
+
1414
+ allow(@configurator).to receive(:test_build_preprocess_directives_only_available).and_return( false )
1415
+ allow(@configurator).to receive(:cmock_treat_inlines).and_return( :exclude )
1416
+ allow(@configurator).to receive(:project_build_vendor_ceedling_path).and_return( 'build/vendor/ceedling' )
1417
+ allow(@file_path_utils).to receive(:form_preprocessed_file_filepath).and_return( 'build/preprocess/MockFoo.h' )
1418
+
1419
+ @testable = TestInvokerTypes::Testable.new(
1420
+ :name => 'a_test',
1421
+ :preprocess_flags => [], :preprocess_defines => [], :search_paths => []
1422
+ )
1423
+ mock = TestInvokerTypes::MockWork.new(
1424
+ :details => TestInvokerTypes::MockDetails.new( :source => 'src/Foo.h', :path => 'sub' ),
1425
+ :testable => @testable,
1426
+ :name => :MockFoo,
1427
+ :directives_only_filepath => nil
1428
+ )
1429
+ @state = TestInvokerTypes::PipelineState.new( :testables => { :a_test => @testable }, :mocks_list => [mock], :context => :test, :options => [] )
1430
+ end
1431
+
1432
+ it "preprocesses and marks fresh the mockable header when the dependency tracker reports it stale" do
1433
+ allow(@dependinator).to receive(:stale?).and_return( true )
1434
+ expect(@preprocessinator).to receive(:preprocess_mockable_header_file)
1435
+ expect(@dependinator).to receive(:mark_fresh).with('build/preprocess/MockFoo.h')
1436
+
1437
+ @executor.stage_preprocess_mocks( @state )
1438
+ end
1439
+
1440
+ it "skips preprocessing the mockable header when the dependency tracker reports it unchanged" do
1441
+ allow(@dependinator).to receive(:stale?).and_return( false )
1442
+ expect(@preprocessinator).to_not receive(:preprocess_mockable_header_file)
1443
+ expect(@dependinator).to_not receive(:mark_fresh)
1444
+
1445
+ @executor.stage_preprocess_mocks( @state )
1446
+ end
1447
+
1448
+ it "logs a summary line stating how many mocks' preprocessing was recalled from cache" do
1449
+ allow(@dependinator).to receive(:stale?).and_return( false )
1450
+
1451
+ allow(@reportinator).to receive(:generate_skip_summary).and_return( "Skipping mock preprocessing for 1 mock (nothing changed)..." )
1452
+
1453
+ expect(@loginator).to receive(:log).with( "Skipping mock preprocessing for 1 mock (nothing changed)..." )
1454
+ @executor.stage_preprocess_mocks( @state )
1455
+ end
1456
+
1457
+ it "registers the bare-includes and directives-only preprocessor tools, and the fallback setting, as meta" do
1458
+ allow(@preprocessinator).to receive(:preprocess_mockable_header_file)
1459
+
1460
+ expect(@dependinator).to receive(:register).with(
1461
+ 'build/preprocess/MockFoo.h',
1462
+ files: ['src/Foo.h'],
1463
+ meta: {
1464
+ flags: [], defines: [], search_paths: [], extras: false,
1465
+ tools: [@tools_test_bare_includes_preprocessor, @tools_test_file_directives_only_preprocessor],
1466
+ preprocess_force_fallback: false
1467
+ }
1468
+ )
1469
+
1470
+ @executor.stage_preprocess_mocks( @state )
1471
+ end
1472
+
1473
+ it "runs the extra treat-inlines-aware pass for an ordinary mock when the project configures :treat_inlines: :include" do
1474
+ allow(@configurator).to receive(:cmock_treat_inlines).and_return( :include )
1475
+ allow(@preprocessinator).to receive(:preprocess_mockable_header_file)
1476
+
1477
+ expect(@dependinator).to receive(:register).with(
1478
+ 'build/preprocess/MockFoo.h',
1479
+ files: anything,
1480
+ meta: hash_including( extras: true )
1481
+ )
1482
+
1483
+ @executor.stage_preprocess_mocks( @state )
1484
+ end
1485
+
1486
+ it "skips the extra treat-inlines-aware pass for a Partial mock even when the project configures :treat_inlines: :include -- its own generated header is already inline-free" do
1487
+ @state.mocks_list.first.details.partial = true
1488
+ allow(@configurator).to receive(:cmock_treat_inlines).and_return( :include )
1489
+ allow(@preprocessinator).to receive(:preprocess_mockable_header_file)
1490
+
1491
+ expect(@dependinator).to receive(:register).with(
1492
+ 'build/preprocess/MockFoo.h',
1493
+ files: anything,
1494
+ meta: hash_including( extras: false )
1495
+ )
1496
+
1497
+ @executor.stage_preprocess_mocks( @state )
1498
+ end
1499
+ end
1500
+
1501
+ context "#stage_generate_mocks" do
1502
+ before(:each) do
1503
+ stub_batchinator_exec()
1504
+
1505
+ allow(@configurator).to receive(:project_config_hash).and_return( {} )
1506
+ allow(@configurator).to receive(:get_cmock_config).and_return( { mock_prefix: 'Mock' } )
1507
+ allow(@configurator).to receive(:cmock_mock_name_include_folder).and_return( true )
1508
+ allow(@file_wrapper).to receive(:mkdir)
1509
+ # Where a mock's files sit is composed in one shared place, so the stage that
1510
+ # compiles a mock and the stage that generates it cannot disagree.
1511
+ allow(@file_path_utils).to receive(:form_mock_output_path) do |root, subdir|
1512
+ subdir.nil? || subdir.empty? ? root : File.join( root, subdir )
1513
+ end
1514
+
1515
+ @testable = TestInvokerTypes::Testable.new(
1516
+ :name => 'a_test',
1517
+ :paths => { :mocks => 'build/test/mocks' }
1518
+ )
1519
+ mock = TestInvokerTypes::MockWork.new(
1520
+ :details => TestInvokerTypes::MockDetails.new(
1521
+ :source => 'src/Foo.h', :path => 'sub', :input => 'build/preprocess/MockFoo.h', :name => 'MockFoo'
1522
+ ),
1523
+ :testable => @testable,
1524
+ :name => :MockFoo
1525
+ )
1526
+ @state = TestInvokerTypes::PipelineState.new( :testables => { :a_test => @testable }, :mocks_list => [mock], :lock => Mutex.new, :context => :test, :options => [] )
1527
+ end
1528
+
1529
+ it "generates and marks fresh the mock when the dependency tracker reports it stale" do
1530
+ allow(@dependinator).to receive(:stale?).and_return( true )
1531
+ expect(@generator).to receive(:generate_mock)
1532
+ expect(@dependinator).to receive(:mark_fresh).with('build/test/mocks/sub/MockFoo.c')
1533
+
1534
+ @executor.stage_generate_mocks( @state )
1535
+ end
1536
+
1537
+ it "skips generating the mock when the dependency tracker reports it unchanged" do
1538
+ allow(@dependinator).to receive(:stale?).and_return( false )
1539
+ expect(@generator).to_not receive(:generate_mock)
1540
+ expect(@dependinator).to_not receive(:mark_fresh)
1541
+
1542
+ @executor.stage_generate_mocks( @state )
1543
+ end
1544
+
1545
+ it "logs a summary line stating how many mocks were recalled from cache" do
1546
+ allow(@dependinator).to receive(:stale?).and_return( false )
1547
+
1548
+ allow(@reportinator).to receive(:generate_skip_summary).and_return( "Skipping mock generation for 1 mock (nothing changed)..." )
1549
+
1550
+ expect(@loginator).to receive(:log).with( "Skipping mock generation for 1 mock (nothing changed)..." )
1551
+ @executor.stage_generate_mocks( @state )
1552
+ end
1553
+
1554
+ it "tracks the mock's own generated header as an output of the mock" do
1555
+ # Includes stand-in generation (test_build_setup.rb) can overwrite a mock's
1556
+ # generated header with a blank placeholder on a run where only the test file's
1557
+ # own bare-includes cache misses. The header's recorded hash is what lets that
1558
+ # overwrite be detected and the mock regenerated on the next run.
1559
+ allow(@dependinator).to receive(:stale?).and_return( true )
1560
+ allow(@generator).to receive(:generate_mock)
1561
+ allow(@dependinator).to receive(:mark_fresh)
1562
+
1563
+ expect(@dependinator).to receive(:register).with(
1564
+ 'build/test/mocks/sub/MockFoo.c',
1565
+ files: ['build/preprocess/MockFoo.h'],
1566
+ meta: anything,
1567
+ outputs: ['build/test/mocks/sub/MockFoo.h']
1568
+ )
1569
+
1570
+ @executor.stage_generate_mocks( @state )
1571
+ end
1572
+
1573
+ it "registers CMock's actual configuration as meta, not project_config_hash's flattened (and therefore always-empty) :cmock entry" do
1574
+ # project_config_hash is flattened -- CMock's settings live there as individual
1575
+ # top-level keys like :cmock_mock_prefix, never as a :cmock section -- so a
1576
+ # config change (e.g. :cmock ↳ :mock_prefix) can only be detected here via
1577
+ # get_cmock_config, the one place CMock's configuration still exists as a
1578
+ # single value.
1579
+ allow(@configurator).to receive(:get_cmock_config).and_return( { mock_prefix: 'Custom' } )
1580
+ allow(@dependinator).to receive(:stale?).and_return( true )
1581
+ allow(@generator).to receive(:generate_mock)
1582
+ allow(@dependinator).to receive(:mark_fresh)
1583
+
1584
+ expect(@dependinator).to receive(:register).with(
1585
+ 'build/test/mocks/sub/MockFoo.c',
1586
+ files: anything,
1587
+ meta: { cmock: { mock_prefix: 'Custom' } },
1588
+ outputs: anything
1589
+ )
1590
+
1591
+ @executor.stage_generate_mocks( @state )
1592
+ end
1593
+
1594
+ it "generates an ordinary mock with no configuration override" do
1595
+ allow(@dependinator).to receive(:stale?).and_return( true )
1596
+ allow(@dependinator).to receive(:mark_fresh)
1597
+
1598
+ expect(@generator).to receive(:generate_mock).with( hash_including( overrides: {} ) )
1599
+
1600
+ @executor.stage_generate_mocks( @state )
1601
+ end
1602
+
1603
+ it "generates a Partial mock with its inline handling disabled, redundant alongside Partials' own" do
1604
+ @state.mocks_list.first.details.partial = true
1605
+ allow(@dependinator).to receive(:stale?).and_return( true )
1606
+ allow(@dependinator).to receive(:mark_fresh)
1607
+
1608
+ expect(@generator).to receive(:generate_mock).with( hash_including( overrides: { treat_inlines: :exclude } ) )
1609
+
1610
+ @executor.stage_generate_mocks( @state )
1611
+ end
1612
+
1613
+ # CMock and the runner both name a mock by the folder its #include names. CMock writes
1614
+ # below its own root at that folder, so the folder must also end the mock's directory.
1615
+ context "naming a mock by its #include's folder" do
1616
+ before(:each) do
1617
+ allow(@dependinator).to receive(:stale?).and_return( true )
1618
+ allow(@dependinator).to receive(:mark_fresh)
1619
+ end
1620
+
1621
+ def include_as(path)
1622
+ @state.mocks_list.first.details.include_path = path
1623
+ end
1624
+
1625
+ it "passes no folder for a bare #include and keeps the mirrored location" do
1626
+ include_as( 'MockFoo.h' )
1627
+
1628
+ expect(@generator).to receive(:generate_mock)
1629
+ .with( hash_including( output_path: 'build/test/mocks/sub', folder: nil ) )
1630
+
1631
+ @executor.stage_generate_mocks( @state )
1632
+ end
1633
+
1634
+ it "passes the folder and keeps the mirrored location when the folder ends it" do
1635
+ include_as( 'sub/MockFoo.h' )
1636
+
1637
+ expect(@generator).to receive(:generate_mock)
1638
+ .with( hash_including( output_path: 'build/test/mocks/sub', folder: 'sub' ) )
1639
+
1640
+ @executor.stage_generate_mocks( @state )
1641
+ end
1642
+
1643
+ # The runner ignores a leading ./ too, so both name the mock alike
1644
+ it "drops a leading ./ from the folder" do
1645
+ include_as( './sub/MockFoo.h' )
1646
+
1647
+ expect(@generator).to receive(:generate_mock)
1648
+ .with( hash_including( output_path: 'build/test/mocks/sub', folder: 'sub' ) )
1649
+
1650
+ @executor.stage_generate_mocks( @state )
1651
+ end
1652
+
1653
+ # The mirror cannot hold a folder longer than itself, so the mock moves to the
1654
+ # written path below the per-test root, and its tracked target moves with it.
1655
+ it "places the mock at its written path when the #include spells more than the mirror" do
1656
+ include_as( 'more/sub/MockFoo.h' )
1657
+
1658
+ expect(@generator).to receive(:generate_mock)
1659
+ .with( hash_including( output_path: 'build/test/mocks/more/sub', folder: 'more/sub' ) )
1660
+ expect(@dependinator).to receive(:mark_fresh).with( 'build/test/mocks/more/sub/MockFoo.c' )
1661
+
1662
+ @executor.stage_generate_mocks( @state )
1663
+ end
1664
+
1665
+ it "passes no folder when :mock_name_include_folder is disabled" do
1666
+ allow(@configurator).to receive(:cmock_mock_name_include_folder).and_return( false )
1667
+ include_as( 'sub/MockFoo.h' )
1668
+
1669
+ expect(@generator).to receive(:generate_mock)
1670
+ .with( hash_including( output_path: 'build/test/mocks/sub', folder: nil ) )
1671
+
1672
+ @executor.stage_generate_mocks( @state )
1673
+ end
1674
+ end
1675
+ end
1676
+
1677
+ context "#tailor_search_paths" do
1678
+ PROJECT_BUILD_VENDOR_CMOCK_PATH = 'build/vendor/cmock' unless defined?(PROJECT_BUILD_VENDOR_CMOCK_PATH)
1679
+ PROJECT_BUILD_VENDOR_CEXCEPTION_PATH = 'build/vendor/cexception' unless defined?(PROJECT_BUILD_VENDOR_CEXCEPTION_PATH)
1680
+
1681
+ before(:each) do
1682
+ allow(@configurator).to receive(:collection_paths_support).and_return( ['support'] )
1683
+ end
1684
+
1685
+ it "returns the given search paths unchanged for an ordinary test source" do
1686
+ result = @executor.send( :tailor_search_paths, filepath: 'src/Foo.c', search_paths: ['src', 'test'] )
1687
+
1688
+ expect(result).to eq( ['src', 'test'] )
1689
+ end
1690
+
1691
+ it "swaps in the support paths plus Unity's own vendor path for Unity's own source" do
1692
+ filepath = File.join( PROJECT_BUILD_VENDOR_UNITY_PATH, UNITY_C_FILE )
1693
+
1694
+ result = @executor.send( :tailor_search_paths, filepath: filepath, search_paths: ['src', 'test'] )
1695
+
1696
+ expect(result).to eq( ['support', PROJECT_BUILD_VENDOR_UNITY_PATH] )
1697
+ end
1698
+
1699
+ it "swaps in the support, Unity, and CMock vendor paths for CMock's own source when mocks are in use" do
1700
+ allow(@configurator).to receive(:project_use_mocks).and_return( true )
1701
+ filepath = File.join( PROJECT_BUILD_VENDOR_CMOCK_PATH, CMOCK_C_FILE )
1702
+
1703
+ result = @executor.send( :tailor_search_paths, filepath: filepath, search_paths: ['src', 'test'] )
1704
+
1705
+ expect(result).to eq( ['support', PROJECT_BUILD_VENDOR_UNITY_PATH, PROJECT_BUILD_VENDOR_CMOCK_PATH] )
1706
+ end
1707
+
1708
+ it "also folds in the CException vendor path for CMock's own source when exceptions are also in use" do
1709
+ allow(@configurator).to receive(:project_use_mocks).and_return( true )
1710
+ allow(@configurator).to receive(:project_use_exceptions).and_return( true )
1711
+ filepath = File.join( PROJECT_BUILD_VENDOR_CMOCK_PATH, CMOCK_C_FILE )
1712
+
1713
+ result = @executor.send( :tailor_search_paths, filepath: filepath, search_paths: ['src', 'test'] )
1714
+
1715
+ expect(result).to eq(
1716
+ ['support', PROJECT_BUILD_VENDOR_UNITY_PATH, PROJECT_BUILD_VENDOR_CMOCK_PATH, PROJECT_BUILD_VENDOR_CEXCEPTION_PATH]
1717
+ )
1718
+ end
1719
+
1720
+ it "leaves CMock's own source untouched when mocks are not in use, falling through to the given search paths" do
1721
+ filepath = File.join( PROJECT_BUILD_VENDOR_CMOCK_PATH, CMOCK_C_FILE )
1722
+
1723
+ result = @executor.send( :tailor_search_paths, filepath: filepath, search_paths: ['src', 'test'] )
1724
+
1725
+ expect(result).to eq( ['src', 'test'] )
1726
+ end
1727
+
1728
+ it "swaps in the support and CException vendor paths for CException's own source when exceptions are in use" do
1729
+ allow(@configurator).to receive(:project_use_exceptions).and_return( true )
1730
+ filepath = File.join( PROJECT_BUILD_VENDOR_CEXCEPTION_PATH, CEXCEPTION_C_FILE )
1731
+
1732
+ result = @executor.send( :tailor_search_paths, filepath: filepath, search_paths: ['src', 'test'] )
1733
+
1734
+ expect(result).to eq( ['support', PROJECT_BUILD_VENDOR_CEXCEPTION_PATH] )
1735
+ end
1736
+
1737
+ it "adds the support and every in-use framework's own vendor path for a support file" do
1738
+ allow(@configurator).to receive(:project_use_mocks).and_return( true )
1739
+ allow(@configurator).to receive(:project_use_exceptions).and_return( true )
1740
+ allow(@configurator).to receive(:collection_all_support).and_return( ['test/support/CustomAsserts.c'] )
1741
+
1742
+ result = @executor.send( :tailor_search_paths, filepath: 'test/support/CustomAsserts.c', search_paths: ['src', 'test'] )
1743
+
1744
+ expect(result).to eq(
1745
+ ['src', 'test', 'support', PROJECT_BUILD_VENDOR_UNITY_PATH, PROJECT_BUILD_VENDOR_CMOCK_PATH, PROJECT_BUILD_VENDOR_CEXCEPTION_PATH]
1746
+ )
1747
+ end
1748
+
1749
+ it "deduplicates the tailored search paths it assembles" do
1750
+ allow(@configurator).to receive(:collection_paths_support).and_return( ['support', PROJECT_BUILD_VENDOR_UNITY_PATH] )
1751
+ filepath = File.join( PROJECT_BUILD_VENDOR_UNITY_PATH, UNITY_C_FILE )
1752
+
1753
+ result = @executor.send( :tailor_search_paths, filepath: filepath, search_paths: ['src', 'test'] )
1754
+
1755
+ expect(result).to eq( ['support', PROJECT_BUILD_VENDOR_UNITY_PATH] )
1756
+ end
1757
+ end
1758
+
114
1759
  end