ceedling 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (383) hide show
  1. checksums.yaml +4 -4
  2. data/GIT_COMMIT_SHA +1 -1
  3. data/README.md +57 -58
  4. data/Rakefile +5 -3
  5. data/assets/features/ceedling +1 -1
  6. data/assets/fixtures/test_source_file_duplicate_basenames/test_calc_typo.c +14 -0
  7. data/assets/fixtures/tests_with_duplicate_test_names/test_foo.c +21 -0
  8. data/bin/actionator.rb +6 -12
  9. data/bin/app_cfg.rb +35 -1
  10. data/bin/ceedling +13 -3
  11. data/bin/cli.rb +25 -6
  12. data/bin/cli_handler.rb +119 -73
  13. data/bin/cli_helper.rb +56 -78
  14. data/bin/installation_selector.rb +81 -0
  15. data/bin/launchinator.rb +69 -0
  16. data/bin/mixin_resolvinator.rb +26 -36
  17. data/bin/objects.yml +13 -0
  18. data/bin/path_validator.rb +25 -29
  19. data/bin/versionator.rb +47 -48
  20. data/ceedling.gemspec +19 -15
  21. data/docs/BreakingChanges.md +70 -1
  22. data/docs/Changelog.md +84 -3
  23. data/docs/KnownIssues.md +90 -4
  24. data/docs/ReleaseNotes.md +13 -0
  25. data/docs/overrides/main.html +11 -8
  26. data/lib/ceedling/build_log_writer.rb +33 -0
  27. data/lib/ceedling/config/build_root_policy.rb +70 -0
  28. data/lib/ceedling/config/configurator.rb +19 -18
  29. data/lib/ceedling/config/configurator_builder.rb +58 -28
  30. data/lib/ceedling/config/configurator_paths_validator.rb +179 -0
  31. data/lib/ceedling/config/configurator_plugins.rb +1 -1
  32. data/lib/ceedling/config/configurator_setup.rb +39 -41
  33. data/lib/ceedling/config/configurator_validator.rb +1 -110
  34. data/lib/ceedling/defaults.rb +4 -4
  35. data/lib/ceedling/dependencies/README.md +18 -16
  36. data/lib/ceedling/dependencies/dependency_cache_store.rb +20 -3
  37. data/lib/ceedling/dependencies/dependency_hasher.rb +35 -1
  38. data/lib/ceedling/filename_extension.rb +7 -1
  39. data/lib/ceedling/filesystem/FILE_TREE.md +253 -0
  40. data/lib/ceedling/filesystem/PATH_HANDLING.md +304 -0
  41. data/lib/ceedling/filesystem/README.md +41 -0
  42. data/lib/ceedling/filesystem/build_subpath.rb +102 -0
  43. data/lib/ceedling/filesystem/destination_collision.rb +25 -0
  44. data/lib/ceedling/{file_finder.rb → filesystem/file_finder.rb} +159 -104
  45. data/lib/ceedling/{file_finder_helper.rb → filesystem/file_finder_helper.rb} +36 -31
  46. data/lib/ceedling/filesystem/file_path_collection_utils.rb +183 -0
  47. data/lib/ceedling/{file_path_utils.rb → filesystem/file_path_utils.rb} +108 -97
  48. data/lib/ceedling/{file_system_wrapper.rb → filesystem/file_system_wrapper.rb} +6 -5
  49. data/lib/ceedling/filesystem/file_tree.rb +241 -0
  50. data/lib/ceedling/{file_wrapper.rb → filesystem/file_wrapper.rb} +65 -28
  51. data/lib/ceedling/filesystem/path_exclusions.rb +30 -0
  52. data/lib/ceedling/{path_matcher.rb → filesystem/path_matcher.rb} +27 -23
  53. data/lib/ceedling/{path_mirror.rb → filesystem/path_mirror.rb} +19 -18
  54. data/lib/ceedling/filesystem/path_spellings.rb +55 -0
  55. data/lib/ceedling/filesystem/project_paths.rb +184 -0
  56. data/lib/ceedling/filesystem/working_dir.rb +40 -0
  57. data/lib/ceedling/generators/generator.rb +5 -6
  58. data/lib/ceedling/generators/generator_partials.rb +1 -1
  59. data/lib/ceedling/generators/generator_test_results_backtrace.rb +7 -7
  60. data/lib/ceedling/handoff.rb +121 -0
  61. data/lib/ceedling/includes/include_factory.rb +3 -3
  62. data/lib/ceedling/includes/include_pathinator.rb +67 -10
  63. data/lib/ceedling/includes/includes.rb +1 -1
  64. data/lib/ceedling/installation.rb +92 -0
  65. data/lib/ceedling/library_resolver.rb +99 -0
  66. data/lib/ceedling/objects.yml +23 -2
  67. data/lib/ceedling/partials/partializer.rb +4 -4
  68. data/lib/ceedling/partials/partializer_config.rb +3 -1
  69. data/lib/ceedling/plugins/report_log_writer_plugin.rb +3 -5
  70. data/lib/ceedling/preprocess/preprocessinator_file_assembler.rb +1 -1
  71. data/lib/ceedling/preprocess/preprocessinator_includes_handler.rb +1 -1
  72. data/lib/ceedling/preprocess/preprocessinator_line_marker_includes_extractor.rb +1 -1
  73. data/lib/ceedling/rake_app/rakefile_component_resolver.rb +10 -17
  74. data/lib/ceedling/rake_app/test_task_name.rb +29 -0
  75. data/lib/ceedling/rakefile.rb +16 -1
  76. data/lib/ceedling/rakefiles/base/tasks_base.rake +1 -1
  77. data/lib/ceedling/rakefiles/release/rules_release.rake +4 -7
  78. data/lib/ceedling/rakefiles/tests/rules_tests.rake +3 -20
  79. data/lib/ceedling/rakefiles/tests/rules_tests_generate.rake +4 -30
  80. data/lib/ceedling/release_invoker/release_build_executor.rb +33 -44
  81. data/lib/ceedling/release_invoker/release_build_planner.rb +14 -6
  82. data/lib/ceedling/reportinator.rb +3 -4
  83. data/lib/ceedling/setupinator.rb +95 -87
  84. data/lib/ceedling/test_context_extractor.rb +5 -1
  85. data/lib/ceedling/test_invoker/PIPELINE.md +9 -7
  86. data/lib/ceedling/test_invoker/mock_locator.rb +60 -2
  87. data/lib/ceedling/test_invoker/partials_manager.rb +12 -0
  88. data/lib/ceedling/test_invoker/standin_headerinator.rb +22 -13
  89. data/lib/ceedling/test_invoker/test_build_executor.rb +42 -41
  90. data/lib/ceedling/test_invoker/test_build_planner.rb +37 -18
  91. data/lib/ceedling/test_invoker/test_build_setup.rb +17 -12
  92. data/lib/ceedling/test_invoker/test_build_validations.rb +16 -31
  93. data/lib/ceedling/test_invoker/test_file_preprocessinator.rb +1 -1
  94. data/lib/ceedling/test_invoker/test_invoker.rb +6 -1
  95. data/lib/ceedling/test_invoker/test_pipeline_helpers.rb +1 -1
  96. data/lib/ceedling/test_invoker/test_source_file_directive_resolver.rb +40 -20
  97. data/lib/ceedling/tool_executor.rb +9 -3
  98. data/lib/ceedling/yaml_wrapper.rb +3 -2
  99. data/lib/version.rb +1 -1
  100. data/plugins/bullseye/bullseye.rake +6 -9
  101. data/plugins/bullseye/config/defaults_bullseye.rb +1 -1
  102. data/plugins/bullseye/lib/bullseye.rb +9 -7
  103. data/plugins/cppcheck/config/defaults_cppcheck.rb +1 -1
  104. data/plugins/dependencies/config/defaults.yml +6 -6
  105. data/plugins/dependencies/dependencies.rake +4 -1
  106. data/plugins/dependencies/lib/dependencies.rb +18 -8
  107. data/plugins/dependencies/lib/dependency_spec.rb +17 -5
  108. data/plugins/fff/lib/fff.rb +45 -39
  109. data/plugins/fff/spec/fff_cmock_wrapper_spec.rb +128 -0
  110. data/plugins/gcov/config/defaults_gcov.rb +1 -1
  111. data/plugins/gcov/gcov.rake +6 -9
  112. data/plugins/gcov/lib/console_reportinator.rb +4 -18
  113. data/plugins/gcov/lib/gcov.rb +9 -2
  114. data/plugins/gcov/lib/gcovr_reportinator.rb +8 -40
  115. data/plugins/gcov/lib/gcovr_thresholds.rb +74 -0
  116. data/plugins/gcov/lib/reportgenerator_reportinator.rb +1 -1
  117. data/plugins/module_generator/lib/module_generator.rb +3 -3
  118. data/plugins/report_tests_teamcity_stdout/lib/report_tests_teamcity_stdout.rb +53 -80
  119. data/plugins/sanitize/lib/sanitize_records.rb +3 -6
  120. data/plugins/sanitize/sanitize.rake +6 -6
  121. data/plugins/valgrind/lib/valgrind.rb +14 -7
  122. data/plugins/valgrind/valgrind.rake +6 -6
  123. data/site-local/404.html +6 -20
  124. data/site-local/assets/javascripts/{bundle.d7400e89.min.js → bundle.c21346df.min.js} +3 -3
  125. data/site-local/assets/javascripts/{bundle.d7400e89.min.js.map → bundle.c21346df.min.js.map} +2 -2
  126. data/site-local/assets/javascripts/workers/{search.2c215733.min.js → search.a7633da7.min.js} +2 -2
  127. data/site-local/assets/javascripts/workers/{search.2c215733.min.js.map → search.a7633da7.min.js.map} +1 -1
  128. data/site-local/assets/stylesheets/main.57a0d79d.min.css +6 -0
  129. data/site-local/assets/stylesheets/main.57a0d79d.min.css.map +1 -0
  130. data/site-local/assets/stylesheets/palette.fb2fffe2.min.css +4 -0
  131. data/site-local/assets/stylesheets/palette.fb2fffe2.min.css.map +1 -0
  132. data/site-local/configuration/environment-vars.html +6 -20
  133. data/site-local/configuration/global-collections.html +6 -20
  134. data/site-local/configuration/index.html +6 -20
  135. data/site-local/configuration/loading.html +6 -20
  136. data/site-local/configuration/mixins.html +10 -24
  137. data/site-local/configuration/parallel-builds.html +6 -20
  138. data/site-local/configuration/project-file.html +8 -22
  139. data/site-local/configuration/reference/cexception.html +6 -20
  140. data/site-local/configuration/reference/cmock.html +8 -21
  141. data/site-local/configuration/reference/defines.html +16 -30
  142. data/site-local/configuration/reference/environment.html +10 -24
  143. data/site-local/configuration/reference/extension.html +6 -20
  144. data/site-local/configuration/reference/files.html +22 -30
  145. data/site-local/configuration/reference/flags.html +13 -27
  146. data/site-local/configuration/reference/index.html +6 -20
  147. data/site-local/configuration/reference/libraries.html +27 -23
  148. data/site-local/configuration/reference/mixins.html +6 -20
  149. data/site-local/configuration/reference/partials.html +6 -20
  150. data/site-local/configuration/reference/paths.html +38 -29
  151. data/site-local/configuration/reference/plugins.html +6 -20
  152. data/site-local/configuration/reference/project.html +32 -36
  153. data/site-local/configuration/reference/release-build.html +8 -20
  154. data/site-local/configuration/reference/test-build.html +6 -20
  155. data/site-local/configuration/reference/test-runner.html +6 -20
  156. data/site-local/configuration/reference/tools.html +27 -32
  157. data/site-local/configuration/reference/unity.html +6 -20
  158. data/site-local/configuration/which-ceedling.html +383 -37
  159. data/site-local/development/index.html +6 -20
  160. data/site-local/development/plugins/configuration.html +6 -20
  161. data/site-local/development/plugins/index.html +6 -20
  162. data/site-local/development/plugins/plugin-subclass.html +54 -68
  163. data/site-local/development/plugins/rake-tasks.html +8 -22
  164. data/site-local/development/releases.html +84 -29
  165. data/site-local/development/workflow.html +62 -71
  166. data/site-local/getting-started/builds.html +8 -20
  167. data/site-local/getting-started/command-line.html +62 -24
  168. data/site-local/getting-started/example-projects/cipher-quest.html +6 -20
  169. data/site-local/getting-started/example-projects/index.html +6 -20
  170. data/site-local/getting-started/example-projects/temp-sensor.html +6 -20
  171. data/site-local/getting-started/example-projects/wondrous-forest.html +6 -20
  172. data/site-local/getting-started/index.html +6 -20
  173. data/site-local/getting-started/installation.html +6 -20
  174. data/site-local/getting-started/quick-start.html +6 -20
  175. data/site-local/help.html +6 -20
  176. data/site-local/index.html +11 -24
  177. data/site-local/overview/build-system.html +6 -20
  178. data/site-local/overview/index.html +6 -20
  179. data/site-local/overview/test-environments.html +6 -20
  180. data/site-local/overview/tools-and-frameworks.html +6 -20
  181. data/site-local/plugins/beep.html +6 -20
  182. data/site-local/plugins/bullseye/index.html +13 -24
  183. data/site-local/plugins/bullseye/licensing.html +14 -28
  184. data/site-local/plugins/command-hooks.html +8 -22
  185. data/site-local/plugins/compile-commands-json-db.html +6 -20
  186. data/site-local/plugins/cppcheck.html +8 -22
  187. data/site-local/plugins/dependencies.html +16 -27
  188. data/site-local/plugins/fff.html +49 -32
  189. data/site-local/plugins/gcov/examples.html +7 -21
  190. data/site-local/plugins/gcov/gcovr.html +22 -33
  191. data/site-local/plugins/gcov/index.html +6 -20
  192. data/site-local/plugins/gcov/overview.html +9 -20
  193. data/site-local/plugins/gcov/reportgenerator.html +9 -23
  194. data/site-local/plugins/gcov/reporting.html +6 -20
  195. data/site-local/plugins/gcov/setup.html +8 -21
  196. data/site-local/plugins/gcov/tool-versions.html +6 -20
  197. data/site-local/plugins/gcov/troubleshooting.html +10 -24
  198. data/site-local/plugins/index.html +6 -20
  199. data/site-local/plugins/module-generator.html +21 -35
  200. data/site-local/plugins/report-build-warnings-log.html +53 -67
  201. data/site-local/plugins/report-tests-gtestlike-stdout.html +6 -20
  202. data/site-local/plugins/report-tests-ide-stdout.html +43 -57
  203. data/site-local/plugins/report-tests-log-factory.html +50 -64
  204. data/site-local/plugins/report-tests-pretty-stdout.html +7 -21
  205. data/site-local/plugins/report-tests-raw-output-log.html +9 -21
  206. data/site-local/plugins/report-tests-teamcity-stdout.html +20 -31
  207. data/site-local/plugins/sanitize.html +56 -65
  208. data/site-local/plugins/valgrind.html +49 -58
  209. data/site-local/project/index.html +6 -20
  210. data/site-local/project/release-history.html +6 -20
  211. data/site-local/project/sbom.html +6 -20
  212. data/site-local/project/upgrade.html +9 -20
  213. data/site-local/reference/build-directives.html +6 -20
  214. data/site-local/reference/command-line.html +15 -22
  215. data/site-local/reference/environment-vars.html +6 -20
  216. data/site-local/reference/gcov-plugin.html +6 -20
  217. data/site-local/reference/global-collections.html +6 -20
  218. data/site-local/reference/index.html +6 -20
  219. data/site-local/reference/partials-macros.html +6 -20
  220. data/site-local/reference/project-configuration.html +6 -20
  221. data/site-local/sitemap.xml.gz +0 -0
  222. data/site-local/snapshot/examples/cipher_quest/index.html +16 -30
  223. data/site-local/snapshot/examples/temp_sensor/index.html +8 -22
  224. data/site-local/snapshot/examples/wondrous_forest/index.html +6 -20
  225. data/site-local/snapshot/plugins/bullseye/config/defaults_bullseye.rb +1 -1
  226. data/site-local/snapshot/plugins/gcov/config/defaults_gcov.rb +1 -1
  227. data/site-local/testing-guide/build-directives.html +14 -28
  228. data/site-local/testing-guide/conventions.html +66 -27
  229. data/site-local/testing-guide/frameworks.html +11 -25
  230. data/site-local/testing-guide/index.html +6 -20
  231. data/site-local/testing-guide/partials/configuration.html +8 -22
  232. data/site-local/testing-guide/partials/conventions.html +8 -22
  233. data/site-local/testing-guide/partials/directives.html +16 -30
  234. data/site-local/testing-guide/partials/example.html +14 -28
  235. data/site-local/testing-guide/partials/index.html +6 -20
  236. data/site-local/testing-guide/partials/overview.html +6 -20
  237. data/site-local/testing-guide/partials/variables.html +11 -25
  238. data/site-local/testing-guide/test-cases.html +13 -27
  239. data/site-local/testing-guide/test-sample.html +12 -26
  240. data/site-local/testing-guide/test-suite-anatomy.html +6 -20
  241. data/spec/integration/actionator_file_operations_spec.rb +91 -1
  242. data/spec/integration/compile_commands_json_db_spec.rb +1 -1
  243. data/spec/integration/configurator_pipeline_spec.rb +10 -0
  244. data/spec/integration/configurator_validation_spec.rb +1 -1
  245. data/spec/integration/dependencies/dependency_tracker_cache_hardening_spec.rb +26 -0
  246. data/spec/integration/dependencies/dependency_tracker_core_spec.rb +62 -0
  247. data/spec/integration/launcher_handoff_spec.rb +297 -0
  248. data/spec/integration/mixin_loading_spec.rb +1 -1
  249. data/spec/integration/module_generator_spec.rb +3 -3
  250. data/spec/integration/nested_test_artifacts_spec.rb +99 -0
  251. data/spec/integration/partials_module_resolution_spec.rb +7 -4
  252. data/spec/integration/path_intake_scenarios_spec.rb +101 -0
  253. data/spec/integration/path_scenarios_spec.rb +322 -0
  254. data/spec/integration/quote_include_isolator_spec.rb +1 -1
  255. data/spec/integration/rake_task_registry_plugins_spec.rb +95 -0
  256. data/spec/integration/report_build_warnings_log_spec.rb +1 -1
  257. data/spec/integration/report_tests_log_factory_spec.rb +1 -1
  258. data/spec/integration/test_executable_manifest_spec.rb +1 -1
  259. data/spec/integration/test_includes_extractinator_spec.rb +2 -1
  260. data/spec/integration/test_naming_spec.rb +198 -0
  261. data/spec/integration/test_source_file_checks_spec.rb +166 -0
  262. data/spec/integration/tool_validator_spec.rb +1 -1
  263. data/spec/integration/upgrade_docs_spec.rb +84 -0
  264. data/spec/integration/vendor_copy_transient_io_retry_spec.rb +192 -75
  265. data/spec/support/file_tree_helper.rb +88 -0
  266. data/spec/support/integration/configurator_integration_helper.rb +10 -7
  267. data/spec/support/integration/dependency_tracker_integration_helper.rb +1 -1
  268. data/spec/support/integration/partials_generation_integration_helper.rb +2 -2
  269. data/spec/support/integration/path_scenario_harness.rb +173 -0
  270. data/spec/support/integration/spec_integration_helper.rb +1 -1
  271. data/spec/support/integration/test_includes_harness.rb +13 -2
  272. data/spec/support/spec_helper.rb +2 -0
  273. data/spec/support/system/spec_system_helper.rb +7 -6
  274. data/spec/support/system/system_context.rb +21 -3
  275. data/spec/support/working_dir_tracking.rb +49 -0
  276. data/spec/system/build_output_mirroring_spec.rb +2 -2
  277. data/spec/system/conditional_mock_includes_spec.rb +1 -1
  278. data/spec/system/delta_builds_spec.rb +137 -11
  279. data/spec/system/gcov_deployment_spec.rb +1 -0
  280. data/spec/system/header_include_path_validation_spec.rb +4 -4
  281. data/spec/system/launcher_handoff_spec.rb +82 -0
  282. data/spec/system/mock_include_folders_spec.rb +91 -0
  283. data/spec/system/parent_directory_reference_spec.rb +5 -3
  284. data/spec/system/path_handling_probes_spec.rb +192 -0
  285. data/spec/system/preprocessing_parameterized_tests_spec.rb +1 -1
  286. data/spec/system/rake_release_task_path_disambiguation_spec.rb +6 -6
  287. data/spec/system/rake_test_task_path_disambiguation_spec.rb +85 -0
  288. data/spec/system/special_path_characters_spec.rb +86 -0
  289. data/spec/system/support/common_test_cases.rb +23 -21
  290. data/spec/system/support/gcov_common_test_cases.rb +37 -9
  291. data/spec/system/support/sanitize_common_test_cases.rb +2 -2
  292. data/spec/system/support/valgrind_common_test_cases.rb +12 -12
  293. data/spec/system/test_pipeline_stop_points_spec.rb +4 -4
  294. data/spec/system/test_runner_system_include_spec.rb +1 -1
  295. data/spec/system/test_source_file_directive_spec.rb +34 -5
  296. data/spec/units/bin/actionator_spec.rb +14 -17
  297. data/spec/units/bin/app_cfg_spec.rb +47 -0
  298. data/spec/units/bin/cli_handler_spec.rb +284 -7
  299. data/spec/units/bin/cli_helper_spec.rb +126 -45
  300. data/spec/units/bin/installation_selector_spec.rb +114 -0
  301. data/spec/units/bin/launchinator_spec.rb +171 -0
  302. data/spec/units/bin/path_validator_spec.rb +10 -0
  303. data/spec/units/bin/versionator_spec.rb +38 -6
  304. data/spec/units/build_log_writer_spec.rb +57 -0
  305. data/spec/units/config/build_root_policy_spec.rb +61 -0
  306. data/spec/units/config/configurator_builder_spec.rb +37 -6
  307. data/spec/units/config/configurator_paths_validator_spec.rb +292 -0
  308. data/spec/units/config/configurator_setup_spec.rb +65 -103
  309. data/spec/units/config/configurator_spec.rb +37 -6
  310. data/spec/units/config/configurator_validator_spec.rb +1 -172
  311. data/spec/units/default_tools_quoting_spec.rb +83 -0
  312. data/spec/units/dependencies/dependency_cache_store_spec.rb +33 -2
  313. data/spec/units/dependencies/dependency_debug_tree_spec.rb +1 -1
  314. data/spec/units/dependencies/dependency_hasher_spec.rb +42 -1
  315. data/spec/units/dependencies/dependency_path_normalizer_spec.rb +1 -1
  316. data/spec/units/dependencies/dependency_tracker_spec.rb +3 -1
  317. data/spec/units/filename_extension_spec.rb +11 -0
  318. data/spec/units/filesystem/build_subpath_spec.rb +122 -0
  319. data/spec/units/filesystem/destination_collision_spec.rb +30 -0
  320. data/spec/units/{file_finder_helper_spec.rb → filesystem/file_finder_helper_spec.rb} +46 -1
  321. data/spec/units/{file_finder_spec.rb → filesystem/file_finder_spec.rb} +188 -22
  322. data/spec/units/{file_path_collection_utils_spec.rb → filesystem/file_path_collection_utils_spec.rb} +181 -1
  323. data/spec/units/{file_path_utils_spec.rb → filesystem/file_path_utils_spec.rb} +204 -87
  324. data/spec/units/filesystem/file_system_wrapper_spec.rb +33 -0
  325. data/spec/units/filesystem/file_tree_spec.rb +511 -0
  326. data/spec/units/filesystem/file_tree_windows_spec.rb +78 -0
  327. data/spec/units/{file_wrapper_spec.rb → filesystem/file_wrapper_spec.rb} +154 -32
  328. data/spec/units/{path_matcher_spec.rb → filesystem/path_matcher_spec.rb} +12 -1
  329. data/spec/units/{path_mirror_spec.rb → filesystem/path_mirror_spec.rb} +32 -4
  330. data/spec/units/filesystem/project_paths_spec.rb +147 -0
  331. data/spec/units/filesystem/working_dir_spec.rb +71 -0
  332. data/spec/units/generators/generator_spec.rb +12 -6
  333. data/spec/units/generators/generator_test_results_backtrace_spec.rb +50 -46
  334. data/spec/units/generators/generator_test_results_spec.rb +1 -1
  335. data/spec/units/handoff_spec.rb +205 -0
  336. data/spec/units/includes/include_factory_spec.rb +3 -3
  337. data/spec/units/includes/include_pathinator_spec.rb +46 -0
  338. data/spec/units/installation_spec.rb +228 -0
  339. data/spec/units/library_resolver_spec.rb +157 -0
  340. data/spec/units/mock_locator_spec.rb +76 -1
  341. data/spec/units/partials/partializer_config_spec.rb +7 -0
  342. data/spec/units/partials/partializer_spec.rb +1 -0
  343. data/spec/units/partials_manager_spec.rb +17 -0
  344. data/spec/units/plugins/bullseye_spec.rb +15 -2
  345. data/spec/units/plugins/console_reportinator_spec.rb +18 -20
  346. data/spec/units/plugins/dependencies_spec.rb +33 -7
  347. data/spec/units/plugins/dependency_spec_spec.rb +17 -0
  348. data/spec/units/plugins/gcov_spec.rb +28 -3
  349. data/spec/units/plugins/gcovr_reportinator_spec.rb +19 -47
  350. data/spec/units/plugins/gcovr_thresholds_spec.rb +95 -0
  351. data/spec/units/plugins/module_generator_spec.rb +5 -5
  352. data/spec/units/plugins/report_build_warnings_log_spec.rb +3 -3
  353. data/spec/units/plugins/report_log_writer_plugin_spec.rb +10 -1
  354. data/spec/units/plugins/report_tests_raw_output_log_spec.rb +13 -2
  355. data/spec/units/plugins/report_tests_teamcity_stdout_spec.rb +77 -3
  356. data/spec/units/plugins/reportgenerator_reportinator_spec.rb +1 -1
  357. data/spec/units/plugins/sanitize_records_spec.rb +3 -1
  358. data/spec/units/plugins/sanitize_spec.rb +1 -1
  359. data/spec/units/plugins/valgrind_spec.rb +23 -8
  360. data/spec/units/preprocess/preprocessinator_comment_stripper_spec.rb +1 -1
  361. data/spec/units/rake_app/rakefile_component_resolver_spec.rb +21 -0
  362. data/spec/units/rake_app/test_task_name_spec.rb +47 -0
  363. data/spec/units/release_build_executor_spec.rb +53 -14
  364. data/spec/units/release_build_planner_spec.rb +15 -3
  365. data/spec/units/reportinator_spec.rb +5 -5
  366. data/spec/units/standin_headerinator_spec.rb +31 -1
  367. data/spec/units/test_build_executor_spec.rb +107 -5
  368. data/spec/units/test_build_planner_spec.rb +104 -2
  369. data/spec/units/test_build_setup_spec.rb +96 -12
  370. data/spec/units/test_context_extractor_spec.rb +25 -0
  371. data/spec/units/test_file_preprocessinator_spec.rb +17 -1
  372. data/spec/units/test_includes_extractinator_spec.rb +5 -1
  373. data/spec/units/test_invoker/objects_wiring_spec.rb +6 -3
  374. data/spec/units/test_invoker_spec.rb +14 -1
  375. data/spec/units/test_source_file_directive_resolver_spec.rb +38 -7
  376. data/spec/units/tool_executor_spec.rb +26 -0
  377. data/spec/units/yaml_wrapper_spec.rb +11 -0
  378. metadata +122 -33
  379. data/lib/ceedling/file_path_collection_utils.rb +0 -164
  380. data/site-local/assets/stylesheets/main.ec1eaa64.min.css +0 -1
  381. data/site-local/assets/stylesheets/main.ec1eaa64.min.css.map +0 -1
  382. data/site-local/assets/stylesheets/palette.ab4e12ef.min.css +0 -1
  383. data/site-local/assets/stylesheets/palette.ab4e12ef.min.css.map +0 -1
@@ -7,9 +7,8 @@
7
7
 
8
8
  require 'ceedling/constants'
9
9
  require 'ceedling/exceptions'
10
- require 'ceedling/file_path_utils'
11
- require 'ceedling/path_matcher'
12
- require 'ceedling/test_invoker/test_build_validations'
10
+ require 'ceedling/filesystem/file_path_utils'
11
+ require 'ceedling/filesystem/path_matcher'
13
12
 
14
13
  # Owns everything about the TEST_SOURCE_FILE() build directive's own path
15
14
  # content: collecting a test's raw directive strings, telling additive
@@ -20,8 +19,6 @@ require 'ceedling/test_invoker/test_build_validations'
20
19
  # becomes a real filepath.
21
20
  class TestSourceFileDirectiveResolver
22
21
 
23
- include TestBuildValidations
24
-
25
22
  constructor :test_context_extractor, :file_finder, :configurator, :loginator
26
23
 
27
24
  # Splits a test's TEST_SOURCE_FILE() entries into files to add and files to
@@ -33,31 +30,33 @@ class TestSourceFileDirectiveResolver
33
30
  def resolve(test_filepath, context)
34
31
  raw = @test_context_extractor.lookup_build_directive_sources_list( test_filepath )
35
32
  additive, subtractive = raw.partition { |source| FilePathUtils.add_path?( source ) }
36
-
37
- # A directive's own text is written directly in the test file, so its `..`, if
38
- # any, is anchored to that same test file's own directory -- exactly as a
39
- # directory-relative #include would be.
40
33
  anchor = File.dirname( test_filepath )
41
34
 
42
- find = -> (source) {
43
- stripped = FilePathUtils.no_aggregation_decorators( source )
44
- @file_finder.find_build_input_file(
45
- filepath: PathMatcher.resolve_relative( stripped, anchor: anchor ),
46
- complain: :ignore,
47
- context: context
48
- )
49
- }
50
-
51
- additive_sources = additive.map(&find).compact
35
+ additive_sources = additive.filter_map { |source| locate( source, anchor: anchor, context: context ) }
52
36
 
53
37
  subtractive_sources = subtractive.each_with_object({}) do |source, hash|
54
- resolved = find.call( source )
38
+ resolved = locate( source, anchor: anchor, context: context )
55
39
  hash[resolved] = source unless resolved.nil?
56
40
  end
57
41
 
58
42
  return [additive_sources, subtractive_sources]
59
43
  end
60
44
 
45
+ # A TEST_SOURCE_FILE() entry must name a real, recognized file whether it adds or removes.
46
+ # A typo fails loudly on either side of the +:/-: convention, naming the test that holds
47
+ # it. Entries are found exactly as `resolve` finds them, so any entry a build uses passes.
48
+ def validate!(test:, test_filepath:, context:)
49
+ anchor = File.dirname( test_filepath )
50
+
51
+ @test_context_extractor.lookup_build_directive_sources_list( test_filepath ).each do |entry|
52
+ source = FilePathUtils.no_aggregation_decorators( entry )
53
+ validate_extension!( test, source )
54
+ next unless locate( entry, anchor: anchor, context: context ).nil?
55
+
56
+ raise CeedlingException.new( "File '#{source}' specified with TEST_SOURCE_FILE() in #{test} cannot be found in the source file collection" )
57
+ end
58
+ end
59
+
61
60
  # Applies this test's TEST_SOURCE_FILE("-:...") entries against the fully
62
61
  # assembled source list, regardless of how each removed file originally got
63
62
  # there -- the implicit header/source convention, a positive directive, or
@@ -75,4 +74,25 @@ class TestSourceFileDirectiveResolver
75
74
  return sources - subtractive.keys
76
75
  end
77
76
 
77
+ private
78
+
79
+ # An entry's text is written in its test file, so its `..`, if any, is anchored to that
80
+ # test file's directory, as a directory-relative #include is
81
+ def locate(entry, anchor:, context:)
82
+ stripped = FilePathUtils.no_aggregation_decorators( entry )
83
+ return @file_finder.find_build_input_file(
84
+ filepath: PathMatcher.resolve_relative( stripped, anchor: anchor ), complain: :ignore, context: context
85
+ )
86
+ end
87
+
88
+ def validate_extension!(test, source)
89
+ assembly = @configurator.test_build_use_assembly
90
+ return if @configurator.extension_source.match?( source )
91
+ return if assembly && @configurator.extension_assembly.match?( source )
92
+
93
+ extensions = @configurator.extension_source.to_s
94
+ extensions += " or #{@configurator.extension_assembly}" if assembly
95
+ raise CeedlingException.new( "File '#{source}' specified with TEST_SOURCE_FILE() in #{test} is not a #{extensions} source file" )
96
+ end
97
+
78
98
  end
@@ -189,8 +189,8 @@ class ToolExecutor
189
189
 
190
190
  # Handle array or anything else passed into method to be expanded in place of replacement operators
191
191
  case (to_process)
192
- when Array then to_process.each {|value| build_string.concat( "#{element.sub(match, value.to_s)} " ) } if (to_process.size > 0)
193
- else build_string.concat( element.sub(match, to_process.to_s) )
192
+ when Array then to_process.each {|value| build_string.concat( "#{substitute( element, match, value )} " ) } if (to_process.size > 0)
193
+ else build_string.concat( substitute( element, match, to_process ) )
194
194
  end
195
195
 
196
196
  # Handle inline ruby string substitution
@@ -256,7 +256,7 @@ class ToolExecutor
256
256
  # expand elements (whether string or array) into substitution string & replace escaped '\$'
257
257
  elements.flatten!
258
258
  elements.each do |element|
259
- build_string.concat( substitution.sub(/([^\\]*)\$/, "\\1#{element}") ) # don't replace escaped '\$' but allow us to replace just a lonesome '$'
259
+ build_string.concat( substitute( substitution, /(?<!\\)\$/, element ) ) # don't replace escaped '\$' but allow us to replace just a lonesome '$'
260
260
  build_string.gsub!(/\\\$/, '$')
261
261
  build_string.concat(' ')
262
262
  end
@@ -264,6 +264,12 @@ class ToolExecutor
264
264
  return build_string.strip
265
265
  end
266
266
 
267
+ # Replaces the first match of pattern in template with value, taken literally. A
268
+ # replacement string would read a path's `\0`, `\1` or `\\` as a back-reference.
269
+ def substitute(template, pattern, value)
270
+ return template.sub( pattern ) { value.to_s }
271
+ end
272
+
267
273
  def pretty_tool_name(command)
268
274
  # Titleize command's name -- each word capitalized plus underscores replaced with spaces
269
275
  name = "#{command[:name].split(/ |\_/).map(&:capitalize).join(" ")}"
@@ -82,8 +82,9 @@ class YamlWrapper
82
82
  # already picks the right calling convention for the installed Psych, so this should be
83
83
  # unreachable in practice; it exists as a last-resort safety net for an unanticipated
84
84
  # Psych version/interface mismatch, reported distinctly so it isn't mistaken for a user
85
- # YAML-authoring error.
86
- rescue ArgumentError => e
85
+ # YAML-authoring error. `::ArgumentError` names Ruby's own class, which the constructor
86
+ # gem's same-named class would otherwise shadow here.
87
+ rescue ::ArgumentError => e
87
88
  raise YamlLoadException.new(
88
89
  reason: :incompatible, source: source_label, original_error: e,
89
90
  message: "Installed Psych YAML library (#{Psych::VERSION}) does not support a safe-loading feature Ceedling requires ⏩️ #{e.message}"
data/lib/version.rb CHANGED
@@ -21,7 +21,7 @@ module Ceedling
21
21
  # Target version for the current release cycle. Maintained by hand, one edit
22
22
  # per minor or major cycle. Never edited to match a release tag. The release
23
23
  # pipeline rewrites this line from the tag that triggered it.
24
- BASE = '1.2.0'
24
+ BASE = '1.2.2'
25
25
 
26
26
  # Marker for a build the release pipeline did not produce. That pipeline
27
27
  # empties this line, so a published gem reports a bare version while a local
@@ -38,11 +38,12 @@ namespace BULLSEYE_SYM do
38
38
  @ceedling[:bullseye].process_untested_sources( sources:COLLECTION_ALL_SOURCE )
39
39
  end
40
40
 
41
- desc 'Run single test w/ coverage ([*] test or source file name, no path).'
41
+ desc 'Run single test w/ coverage ([*] test or source file name, with optional path).'
42
42
  task :* do
43
43
  message = "Oops! '#{BULLSEYE_ROOT_NAME}:*' isn't a real task. " \
44
- "Use a real test or source file name (no path) in place of the wildcard.\n" \
45
- "Example: `ceedling #{BULLSEYE_ROOT_NAME}:foo.c`"
44
+ "Use a real test or source file name in place of the wildcard, " \
45
+ "adding as much of its path as needed to identify one file among any same-named tests.\n" \
46
+ "Example: `ceedling #{BULLSEYE_ROOT_NAME}:foo.c` or `ceedling #{BULLSEYE_ROOT_NAME}:unit/foo.c`"
46
47
 
47
48
  @ceedling[:loginator].log( message, Verbosity::ERRORS )
48
49
  end
@@ -83,12 +84,8 @@ namespace BULLSEYE_SYM do
83
84
  # Use a rule to increase efficiency for large projects
84
85
  rule(/^#{BULLSEYE_TASK_ROOT}\S+$/ => [ # bullseye test tasks by regex
85
86
  proc do |task_name|
86
- # Yield clean test name => Strip the task string, remove Rake test task prefix, and remove any code file extension
87
- test = task_name.strip().sub(/^#{BULLSEYE_TASK_ROOT}/, '')
88
- EXTENSION_SOURCE.each { |ext| test = test.chomp( ext ) }
89
-
90
- # Ensure the test name begins with a test name prefix
91
- test = PROJECT_TEST_FILE_PREFIX + test if not (test.start_with?( PROJECT_TEST_FILE_PREFIX ))
87
+ # Any directory typed ahead of the name is kept. See TestTaskName.
88
+ test = TestTaskName.test_name( task_name, root: BULLSEYE_TASK_ROOT )
92
89
 
93
90
  # Provide the filepath for the target test task back to the Rake task
94
91
  @ceedling[:file_finder].find_test_file_from_name( test )
@@ -51,7 +51,7 @@ DEFAULT_BULLSEYE_LINKER_TOOL = {
51
51
  }
52
52
 
53
53
  DEFAULT_BULLSEYE_FIXTURE_TOOL = {
54
- :executable => '${1}'.freeze,
54
+ :executable => '"${1}"'.freeze, # Test executable, quoted as a path
55
55
  :name => 'default_bullseye_fixture'.freeze,
56
56
  :optional => false.freeze,
57
57
  :arguments => [].freeze
@@ -220,7 +220,7 @@ class Bullseye < Plugin
220
220
  end
221
221
 
222
222
  header = "Untested source files not in the coverage report (:untested_sources is :list):"
223
- @loginator.log_list( untested_sources.sort, header, Verbosity::COMPLAIN, LogLabels::WARNING )
223
+ @loginator.log_list( untested_sources.sort, header, Verbosity::COMPLAIN )
224
224
 
225
225
  when BULLSEYE_UNTESTED_SOURCES_COMPILE
226
226
  untested_sources = collect_untested_sources( sources )
@@ -236,7 +236,7 @@ class Bullseye < Plugin
236
236
  untested_sources.each do |filepath|
237
237
  filename = File.basename(filepath)
238
238
  object = @ceedling[:file_path_utils].form_test_object_filepath( filepath, context: BULLSEYE_SYM )
239
- dependencies = @ceedling[:file_path_utils].form_test_dependencies_filepath( filepath, context: BULLSEYE_SYM )
239
+ dependencies = @ceedling[:file_path_utils].form_test_dependencies_filepath( object, context: BULLSEYE_SYM )
240
240
  search_paths = @configurator.collection_paths_include
241
241
  # Defines and flags resolve as a tested source's do, against this source's filepath
242
242
  flags = @ceedling[:test_build_setup].flags( context: BULLSEYE_SYM, operation: OPERATION_COMPILE_SYM, filepath: filepath )
@@ -263,6 +263,9 @@ class Bullseye < Plugin
263
263
  next
264
264
  end
265
265
 
266
+ @file_wrapper.mkdir( File.dirname( object ) )
267
+ @file_wrapper.mkdir( File.dirname( dependencies ) )
268
+
266
269
  begin
267
270
  @ceedling[:generator].generate_object_file_c(
268
271
  tool: TOOLS_BULLSEYE_COMPILER,
@@ -559,11 +562,10 @@ class Bullseye < Plugin
559
562
  coverage_sources = []
560
563
  @test_invoker.each_test_with_sources { |_, srcs| coverage_sources.concat( srcs ) }
561
564
  coverage_sources.uniq!
562
- # Every configured source extension is a valid ending for a mock/ignored-source name,
563
- # so the two are joined into one regex alternation rather than matching just one.
564
- source_extensions = EXTENSION_SOURCE.to_a.map { |ext| Regexp.escape(ext) }.join('|')
565
- coverage_sources.delete_if {|item| item =~ /#{@configurator.cmock_mock_prefix}.+(?:#{source_extensions})$/}
566
- coverage_sources.delete_if {|item| item =~ /(?:#{BULLSEYE_IGNORE_SOURCES.join('|')})(?:#{source_extensions})$/}
565
+ # Every configured source extension is a valid ending for a mock/ignored-source name
566
+ source_extensions = EXTENSION_SOURCE.pattern
567
+ coverage_sources.delete_if {|item| item =~ /#{@configurator.cmock_mock_prefix}.+#{source_extensions}$/}
568
+ coverage_sources.delete_if {|item| item =~ /(?:#{BULLSEYE_IGNORE_SOURCES.join('|')})#{source_extensions}$/}
567
569
 
568
570
  coverage_sources.each do |source|
569
571
  command = @ceedling[:tool_executor].build_command_line(TOOLS_BULLSEYE_REPORT_COVFN, [], source)
@@ -16,7 +16,7 @@ DEFAULT_CPPCHECK_TOOL = {
16
16
  :optional => true.freeze,
17
17
  :arguments => [
18
18
  '-I"${1}"'.freeze,
19
- '${2}'.freeze
19
+ '"${2}"'.freeze
20
20
  ].freeze
21
21
  }
22
22
 
@@ -26,9 +26,9 @@
26
26
  :name: 'Dependencies archiver'
27
27
  :optional: true # Checked when :build_lib archives, not by every Ceedling command
28
28
  :arguments:
29
- - rcs
30
- - ${2}
31
- - ${1}
29
+ - rcs
30
+ - '"${2}"' # Library
31
+ - '"${1}"' # Objects
32
32
 
33
33
  :deps_zip:
34
34
  :executable: unzip
@@ -36,7 +36,7 @@
36
36
  :optional: true
37
37
  :arguments:
38
38
  - -o
39
- - ${1} # Filepath
39
+ - '"${1}"' # Filepath
40
40
 
41
41
  :deps_targzip:
42
42
  :executable: tar
@@ -57,7 +57,7 @@
57
57
  - clone
58
58
  - ${1} # Optional branch with `-b` flag
59
59
  - ${2} # Optional depth with `--depth` flag
60
- - ${3} # Repository source
60
+ - '"${3}"' # Repository source
61
61
  - .
62
62
 
63
63
  :deps_git_checkout:
@@ -75,7 +75,7 @@
75
75
  :arguments:
76
76
  - checkout
77
77
  - ${1} # Optional branch with `--revision` flag
78
- - ${2} # Repository source
78
+ - '"${2}"' # Repository source
79
79
  - .
80
80
 
81
81
  ...
@@ -89,12 +89,15 @@
89
89
  task :prepare => all_deps
90
90
  end
91
91
 
92
- # Dependency libraries join the library names and paths test and release builds link with
92
+ # Dependency libraries join the library names and paths test and release builds link with,
93
+ # and their files join those the links depend on
93
94
  link_libraries = @ceedling[DEPENDENCIES_SYM].link_libraries
94
95
  PATHS_LIBRARIES ||= []
95
96
  PATHS_LIBRARIES.concat( link_libraries[:paths] ).uniq!
96
97
  LIBRARIES_SYSTEM ||= []
97
98
  LIBRARIES_SYSTEM.concat( link_libraries[:names] ).uniq!
99
+ LIBRARIES_LINK_FILES ||= []
100
+ LIBRARIES_LINK_FILES.concat( link_libraries[:files] ).uniq!
98
101
 
99
102
  # Add any artifact:include or :source folders to our release & test includes paths so linking and mocking work.
100
103
  @ceedling[DEPENDENCIES_SYM].add_headers_and_sources()
@@ -8,6 +8,8 @@
8
8
  require 'ceedling/plugins/plugin'
9
9
  require 'ceedling/constants'
10
10
  require 'ceedling/exceptions'
11
+ require 'ceedling/filesystem/project_paths'
12
+ require 'ceedling/filesystem/working_dir'
11
13
  require 'dependency_spec'
12
14
  require 'dependency_commands'
13
15
  require 'dependency_environment'
@@ -121,13 +123,15 @@ class Dependencies < Plugin
121
123
  end
122
124
  end
123
125
 
124
- # Library names and their directories, for test and release linking
126
+ # Library names and their directories, for test and release linking, and the library files
127
+ # themselves, which those links depend on
125
128
  def link_libraries
126
129
  libraries = @specs.flat_map { |spec| spec.static_libraries + spec.dynamic_libraries }
127
130
 
128
131
  return {
129
132
  names: libraries.map { |library| File.basename( library, '.*' ).delete_prefix( 'lib' ) }.reject( &:empty? ).uniq,
130
- paths: libraries.map { |library| File.dirname( library ) }.reject( &:empty? ).uniq
133
+ paths: libraries.map { |library| File.dirname( library ) }.reject( &:empty? ).uniq,
134
+ files: libraries.uniq
131
135
  }
132
136
  end
133
137
 
@@ -173,7 +177,7 @@ class Dependencies < Plugin
173
177
 
174
178
  # The one place this plugin changes directory, around a dependency's own commands
175
179
  def in_directory(path, &block)
176
- Dir.chdir( path, &block )
180
+ WorkingDir.chdir( path, &block )
177
181
  end
178
182
 
179
183
  # A fetch path that already holds files is taken as fetched, so fetching again, or
@@ -273,7 +277,7 @@ class Dependencies < Plugin
273
277
  end
274
278
 
275
279
  def compile(spec, source, search_paths)
276
- object = object_for( spec, source )
280
+ object = prepared_object( spec, source )
277
281
  @ceedling[:generator].generate_object_file_c(
278
282
  tool: TOOLS_DEPS_COMPILER,
279
283
  module_name: File.basename( source ).ext,
@@ -283,13 +287,13 @@ class Dependencies < Plugin
283
287
  search_paths: search_paths,
284
288
  flags: spec.flags,
285
289
  defines: spec.defines,
286
- list: @ceedling[:file_path_utils].form_release_build_list_filepath( File.basename( source ).ext )
290
+ list: @ceedling[:file_path_utils].form_release_build_list_filepath( object )
287
291
  )
288
292
  return object
289
293
  end
290
294
 
291
295
  def assemble(spec, source)
292
- object = object_for( spec, source )
296
+ object = prepared_object( spec, source )
293
297
  @ceedling[:generator].generate_object_file_asm(
294
298
  tool: TOOLS_DEPS_ASSEMBLER, module_name: File.basename( source ).ext, context: DEPENDENCIES_SYM,
295
299
  source: source, object: object
@@ -297,8 +301,14 @@ class Dependencies < Plugin
297
301
  return object
298
302
  end
299
303
 
300
- def object_for(spec, source)
301
- return File.join( spec.build_path, File.basename( source ).ext( EXTENSION_OBJECT.primary ) )
304
+ # A source's object sits at the source's own path below the dependency's source path, so
305
+ # same-named sources in different directories keep apart. Its directory is made here.
306
+ def prepared_object(spec, source)
307
+ subdir = ProjectPaths.subdir_below( spec.source_path, File.dirname( source ) ) || ''
308
+ object = File.join( spec.build_path, subdir, File.basename( source ).ext( EXTENSION_OBJECT.primary ) )
309
+
310
+ @ceedling[:file_wrapper].mkdir( File.dirname( object ) )
311
+ return object
302
312
  end
303
313
 
304
314
  def copy_library(built, destination)
@@ -6,14 +6,15 @@
6
6
  # =========================================================================
7
7
 
8
8
  require 'ceedling/exceptions'
9
+ require 'ceedling/filesystem/project_paths'
9
10
 
10
11
  # One configured dependency, validated and normalized.
11
12
  #
12
13
  # Each dependency names its paths under :paths, and each path falls back to another when
13
14
  # left out: :source and :fetch to each other, :build to :source then :fetch, :artifact to
14
15
  # :build. With none configured, every path is `dependencies/<task name>`. Artifacts
15
- # (libraries, executables, includes, sources) live under the artifact path. An optional
16
- # :deploy path receives deployed copies.
16
+ # (libraries, executables, includes, sources) live under the artifact path, unless named by
17
+ # an absolute path. An optional :deploy path receives deployed copies.
17
18
  #
18
19
  # The task name is the configured name's word characters, which `dependencies:*` tasks
19
20
  # use, so it must be non-empty and unique among dependencies.
@@ -47,7 +48,7 @@ class DependencySpec
47
48
  @name = dep[:name] or raise CeedlingException.new( 'Each dependency must have a :name.' )
48
49
  @task_name = task_name_for( @name )
49
50
  @fetch = dep[:fetch] || {}
50
- @paths = dep[:paths] || {}
51
+ @paths = standardized( dep[:paths] || {} )
51
52
  @artifacts = dep[:artifacts] || {}
52
53
 
53
54
  problem = fetch_problem
@@ -106,7 +107,7 @@ class DependencySpec
106
107
  # glob expands through `collector` against the disk, and anything else is a directory.
107
108
  def include_directories(collector)
108
109
  return Array( @artifacts[:includes] ).flat_map do |include|
109
- path = File.join( artifact_path, include )
110
+ path = artifact_at( include )
110
111
  if include.end_with?( '.h' ) then [File.dirname( path )]
111
112
  elsif include.match?( INCLUDE_GLOB ) then collector.call( path )
112
113
  else [path]
@@ -128,7 +129,18 @@ class DependencySpec
128
129
  end
129
130
 
130
131
  def artifacts(kind)
131
- return Array( @artifacts[kind] ).map { |path| File.join( artifact_path, path ) }
132
+ return Array( @artifacts[kind] ).map { |path| artifact_at( path ) }
133
+ end
134
+
135
+ # Configured paths, read as every configured path is read
136
+ def standardized(paths)
137
+ return paths.transform_values { |path| path.is_a?( String ) ? ProjectPaths.standardize( path ) : path }
138
+ end
139
+
140
+ # An artifact below the artifact path, or one named by an absolute path as written
141
+ def artifact_at(path)
142
+ path = ProjectPaths.standardize( path )
143
+ return ProjectPaths.absolute?( path ) ? path : File.join( artifact_path, path )
132
144
  end
133
145
 
134
146
  # What is wrong with the fetch configuration, or nil
@@ -10,6 +10,7 @@
10
10
  # ⏩️ https://github.com/ElectronVector/fake_function_framework
11
11
  # =========================================================================
12
12
 
13
+ require 'fileutils'
13
14
  require 'ceedling/plugins/plugin'
14
15
  require 'fff_mock_generator'
15
16
 
@@ -36,16 +37,17 @@ end # class Fff
36
37
 
37
38
  class FffCMockWrapper
38
39
 
39
- def initialize(options=nil)
40
+ def initialize(options=nil)
40
41
  @cm_config = CMockConfig.new(options)
41
42
  @cm_parser = CMockHeaderParser.new(@cm_config)
42
- @silent = (@cm_config.verbosity < 2)
43
-
44
- # These are the additional files to include in the mock files.
45
- @includes_h_pre_orig_header = (@cm_config.includes || @cm_config.includes_h_pre_orig_header || []).map{|h| h.match?(/</) ? h : "\"#{h}\""}
46
- @includes_h_post_orig_header = (@cm_config.includes_h_post_orig_header || []).map{|h| h.match?(/</) ? h : "\"#{h}\""}
47
- @includes_c_pre_header = (@cm_config.includes_c_pre_header || []).map{|h| h.match?(/</) ? h : "\"#{h}\""}
48
- @includes_c_post_header = (@cm_config.includes_c_post_header || []).map{|h| h.match?(/</) ? h : "\"#{h}\""}
43
+ # CMock's levels: 0 errors only, 1 warnings, 2 normal, 3 verbose
44
+ @verbosity = @cm_config.verbosity
45
+
46
+ # The additional files to include in the fake files, gathered as CMock gathers them
47
+ @includes_h_pre_orig_header = quoted( @cm_config.includes, @cm_config.includes_h_pre_orig_header )
48
+ @includes_h_post_orig_header = quoted( @cm_config.includes_h_post_orig_header )
49
+ @includes_c_pre_header = quoted( @cm_config.includes_c_pre_header )
50
+ @includes_c_post_header = quoted( @cm_config.includes_c_post_header )
49
51
  end
50
52
 
51
53
  # Matches CMock's own entry point, which Ceedling calls with the folder a mock's
@@ -57,37 +59,14 @@ class FffCMockWrapper
57
59
  end
58
60
 
59
61
  def generate_mock(header_file_to_mock, folder=nil)
60
- module_name = File.basename(header_file_to_mock, '.h')
61
- puts( "Creating fake functions for #{module_name}..." ) unless @silent
62
- mock_name = @cm_config.mock_prefix + module_name + @cm_config.mock_suffix
63
- mock_path = folder.nil? ? @cm_config.mock_path : File.join(@cm_config.mock_path, folder)
64
- if @cm_config.subdir
65
- # If a subdirectory has been configured, append it to the mock path.
66
- mock_path = "#{mock_path}/#{@cm_config.subdir}"
67
- end
68
- full_path_for_mock = "#{mock_path}/#{mock_name}"
69
- c_name = c_name_for(mock_name, folder)
70
-
71
- # Parse the header file so we know what to mock.
72
- parsed_header = @cm_parser.parse(module_name, File.read(header_file_to_mock))
73
-
74
- # Create the directory if it doesn't exist.
75
- mkdir_p full_path_for_mock.pathmap("%d")
76
-
77
- # Generate the fake function header file.
78
- puts( "Creating fake functions: #{full_path_for_mock}.h" )
79
-
80
- # Create the mock header.
81
- File.open("#{full_path_for_mock}.h", 'w') do |f|
82
- f.write(FffMockGenerator.create_mock_header(module_name, mock_name, parsed_header,
83
- @includes_h_pre_orig_header, @includes_h_post_orig_header, c_name: c_name))
84
- end
85
-
86
- # Create the mock source file.
87
- File.open("#{full_path_for_mock}.c", 'w') do |f|
88
- f.write(FffMockGenerator.create_mock_source(mock_name, parsed_header,
89
- @includes_c_pre_orig_header, @includes_c_post_orig_header, c_name: c_name))
90
- end
62
+ module_name = File.basename(header_file_to_mock, '.h')
63
+ puts( "Creating fake functions for #{module_name}..." ) unless @verbosity < 2
64
+ mock_name = @cm_config.mock_prefix + module_name + @cm_config.mock_suffix
65
+
66
+ # Parse the header file so we know what to mock.
67
+ parsed_header = @cm_parser.parse(module_name, File.read(header_file_to_mock))
68
+
69
+ write_fake( "#{mock_path_for( folder )}/#{mock_name}", module_name, mock_name, parsed_header, c_name_for( mock_name, folder ) )
91
70
  end
92
71
 
93
72
  # The name for a fake's guard and control functions, as CMock forms it. With
@@ -103,6 +82,33 @@ class FffCMockWrapper
103
82
  return identity.gsub( %r{[-/\\.,\s]}, '_' )
104
83
  end
105
84
 
85
+ private
86
+
87
+ # The directory a fake is written to: the mock root, the folder its #include names,
88
+ # then any configured :subdir
89
+ def mock_path_for(folder)
90
+ mock_path = folder.nil? ? @cm_config.mock_path : File.join( @cm_config.mock_path, folder )
91
+ return @cm_config.subdir ? "#{mock_path}/#{@cm_config.subdir}" : mock_path
92
+ end
93
+
94
+ # Writes the fake's header and source at `path`, which ends in the mock's name
95
+ def write_fake(path, module_name, mock_name, parsed_header, c_name)
96
+ FileUtils.mkdir_p( File.dirname( path ) )
97
+
98
+ puts( "Creating fake functions: #{path}.h and #{path}.c" ) unless @verbosity < 3
99
+ File.write( "#{path}.h", FffMockGenerator.create_mock_header( module_name, mock_name, parsed_header,
100
+ @includes_h_pre_orig_header, @includes_h_post_orig_header, c_name: c_name ) )
101
+
102
+ File.write( "#{path}.c", FffMockGenerator.create_mock_source( mock_name, parsed_header,
103
+ @includes_c_pre_header, @includes_c_post_header, c_name: c_name ) )
104
+ end
105
+
106
+ # Joins include lists, each named once, as #include operands. A name holding `<` is
107
+ # kept as written, and any other is quoted, as CMock does.
108
+ def quoted(*lists)
109
+ return lists.compact.flatten.uniq.map { |name| name.match?( /</ ) ? name : "\"#{name}\"" }
110
+ end
111
+
106
112
  end
107
113
 
108
114
  # Switch out the CMock with FFF Mock Generator