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
@@ -11,21 +11,17 @@ require 'ceedling/config/configurator_validator'
11
11
  require 'ceedling/config/config_walkinator'
12
12
  require 'ceedling/reportinator'
13
13
 
14
- # Unit coverage for ConfiguratorValidator through a doubled file layer. What these
15
- # validations make of a real project tree is proven in
16
- # spec/integration/configurator_validation_spec.rb.
14
+ # Unit coverage for ConfiguratorValidator's checks of required entries, tools, and matchers
17
15
  describe ConfiguratorValidator do
18
16
  include ConfigYamlHelper
19
17
 
20
18
  before(:each) do
21
- @file_wrapper = double('file_wrapper')
22
19
  @loginator = double('loginator', log: nil)
23
20
  @tool_validator = double('tool_validator')
24
21
 
25
22
  @validator = described_class.new(
26
23
  {
27
24
  config_walkinator: ConfigWalkinator.new,
28
- file_wrapper: @file_wrapper,
29
25
  loginator: @loginator,
30
26
  reportinator: Reportinator.new,
31
27
  tool_validator: @tool_validator
@@ -33,14 +29,6 @@ describe ConfiguratorValidator do
33
29
  )
34
30
  end
35
31
 
36
- def existing(*paths)
37
- allow(@file_wrapper).to receive(:exist?) { |path| paths.include?( path ) }
38
- end
39
-
40
- def directories(*paths)
41
- allow(@file_wrapper).to receive(:directory?) { |path| paths.include?( path ) }
42
- end
43
-
44
32
  describe '#exists?' do
45
33
  let(:config) { config_from_yaml( ":project:\n :build_root: build\n :use_mocks: false\n" ) }
46
34
 
@@ -58,165 +46,6 @@ describe ConfiguratorValidator do
58
46
  end
59
47
  end
60
48
 
61
- describe '#validate_path_list' do
62
- let(:config) { config_from_yaml( ":paths:\n :test:\n - +:test/**\n - -:test/ignore\n - '**/generated'\n" ) }
63
-
64
- it 'checks each path stripped of its aggregation decorator and glob' do
65
- existing('test', 'test/ignore')
66
- expect(@validator.validate_path_list( config, :paths, :test )).to be true
67
- end
68
-
69
- it 'skips a path that begins with a glob' do
70
- existing('test', 'test/ignore')
71
- @validator.validate_path_list( config, :paths, :test )
72
- expect(@file_wrapper).to_not have_received(:exist?).with('')
73
- end
74
-
75
- it 'logs each path that does not exist' do
76
- existing('test')
77
- expect(@validator.validate_path_list( config, :paths, :test )).to be false
78
- expect(@loginator).to have_received(:log).with("Config path :paths ↳ :test => 'test/ignore' does not exist in the filesystem.", Verbosity::ERRORS)
79
- end
80
-
81
- it 'fails a missing entry' do
82
- expect(@validator.validate_path_list( config, :paths, :source )).to be false
83
- end
84
- end
85
-
86
- # An entry naming no path, or wrapping its path in quotes, is rejected before any
87
- # filesystem check. Both usually come from quoting only the path after a +: or -:
88
- # decoration, so each rejection carries a hint about quoting.
89
- shared_examples 'an entry that names no usable path' do |walk|
90
- {
91
- 'a bare subtractive decoration' => " - '-:'\n",
92
- 'a bare additive decoration' => " - '+:'\n",
93
- 'an empty string' => " - ''\n",
94
- 'whitespace alone' => " - ' '\n",
95
- 'a YAML null' => " -\n",
96
- }.each_pair do |label, yaml|
97
- it "rejects #{label} as naming no path, with a quoting hint" do
98
- expect(validate( yaml )).to be false
99
- expect(@loginator).to have_received(:log).with(/#{Regexp.escape(walk)} => '.*' names no path/, Verbosity::ERRORS)
100
- expect(@loginator).to have_received(:log).with(/Quote the whole entry/, Verbosity::ERRORS)
101
- end
102
- end
103
-
104
- # YAML reads an unquoted decoration with nothing after it as a one-key mapping
105
- it 'rejects an entry YAML read as something other than a path, with a quoting hint' do
106
- expect(validate( " - -:\n" )).to be false
107
- expect(@loginator).to have_received(:log).with(/#{Regexp.escape(walk)} => '.*' is not a path \(YAML read it as a Hash\)/, Verbosity::ERRORS)
108
- expect(@loginator).to have_received(:log).with(/Quote the whole entry/, Verbosity::ERRORS)
109
- end
110
-
111
- it 'rejects a path wrapped in quotes after its decoration, with a quoting hint' do
112
- expect(validate( " - '-:\"src/a.c\"'\n" )).to be false
113
- expect(@loginator).to have_received(:log).with(/#{Regexp.escape(walk)} => '-:"src\/a.c"' wraps its path in quotes/, Verbosity::ERRORS)
114
- expect(@loginator).to have_received(:log).with(/Quote the whole entry/, Verbosity::ERRORS)
115
- end
116
- end
117
-
118
- describe '#validate_paths_entries' do
119
- def validate(yaml_list)
120
- @validator.validate_paths_entries( config_from_yaml( ":paths:\n :source:\n#{yaml_list}" ), :source )
121
- end
122
-
123
- it 'accepts a glob that yields directories' do
124
- existing; directories('src', 'src/a')
125
- allow(@file_wrapper).to receive(:directory_listing).with('src/**/**').and_return(['src', 'src/a', 'src/a/x.c'])
126
-
127
- expect(validate( " - src/**\n" )).to be true
128
- end
129
-
130
- it 'warns about and skips a path naming a file' do
131
- existing('src/main.c'); directories
132
-
133
- expect(validate( " - src/main.c\n" )).to be true
134
- expect(@loginator).to have_received(:log).with(/'src\/main.c' is a filepath and will be ignored/, Verbosity::COMPLAIN)
135
- end
136
-
137
- it 'accepts a subdirectory glob of a directory that has no subdirectories' do
138
- existing; directories
139
- allow(@file_wrapper).to receive(:directory_listing).and_return([])
140
-
141
- expect(validate( " - src/*\n" )).to be true
142
- end
143
-
144
- it 'logs a path that yields no directories' do
145
- existing; directories
146
- allow(@file_wrapper).to receive(:directory_listing).and_return([])
147
-
148
- expect(validate( " - -:src/missing\n" )).to be false
149
- expect(@loginator).to have_received(:log).with(/'src\/missing' yielded no directories/, Verbosity::ERRORS)
150
- end
151
-
152
- it 'escapes literal brackets before globbing' do
153
- existing; directories('src/[legacy]')
154
- allow(@file_wrapper).to receive(:directory_listing).with('src/\[legacy\]').and_return(['src/[legacy]'])
155
-
156
- expect(validate( " - 'src/[legacy]'\n" )).to be true
157
- end
158
-
159
- it 'fails a missing entry' do
160
- expect(@validator.validate_paths_entries( { paths: {} }, :source )).to be false
161
- end
162
-
163
- it_behaves_like 'an entry that names no usable path', ':paths ↳ :source'
164
- end
165
-
166
- describe '#validate_files_entries' do
167
- def validate(yaml_list)
168
- @validator.validate_files_entries( config_from_yaml( ":files:\n :source:\n#{yaml_list}" ), :source )
169
- end
170
-
171
- it 'accepts a glob that yields files' do
172
- existing; directories
173
- allow(@file_wrapper).to receive(:instantiate_file_list).with('src/*.c').and_return(['src/a.c'])
174
-
175
- expect(validate( " - +:src/*.c\n" )).to be true
176
- end
177
-
178
- it 'warns about and skips a path naming a directory' do
179
- existing('src'); directories('src')
180
-
181
- expect(validate( " - src\n" )).to be true
182
- expect(@loginator).to have_received(:log).with(/'src' is a directory path and will be ignored/, Verbosity::COMPLAIN)
183
- end
184
-
185
- it 'logs a glob that yields no files' do
186
- existing; directories
187
- allow(@file_wrapper).to receive(:instantiate_file_list).and_return([])
188
-
189
- expect(validate( " - src/*.x\n" )).to be false
190
- expect(@loginator).to have_received(:log).with(/'src\/\*.x' yielded no files/, Verbosity::ERRORS)
191
- end
192
-
193
- it 'escapes literal brackets before globbing' do
194
- existing; directories
195
- allow(@file_wrapper).to receive(:instantiate_file_list).with('src/\[legacy\]/*.c').and_return(['src/[legacy]/a.c'])
196
-
197
- expect(validate( " - 'src/[legacy]/*.c'\n" )).to be true
198
- end
199
-
200
- it 'fails a missing entry' do
201
- expect(@validator.validate_files_entries( { files: {} }, :source )).to be false
202
- end
203
-
204
- it_behaves_like 'an entry that names no usable path', ':files ↳ :source'
205
- end
206
-
207
- describe '#validate_filepath_simple' do
208
- it 'accepts an existing path' do
209
- existing('helper.h')
210
- expect(@validator.validate_filepath_simple( 'helper.h', :cmock, :unity_helper_path )).to be true
211
- end
212
-
213
- it 'logs a missing path with the configuration walk it came from' do
214
- existing
215
- expect(@validator.validate_filepath_simple( 'helper.h', :cmock, :unity_helper_path )).to be false
216
- expect(@loginator).to have_received(:log).with("Config path 'helper.h' associated with :cmock ↳ :unity_helper_path does not exist in the filesystem.", Verbosity::ERRORS)
217
- end
218
- end
219
-
220
49
  describe '#validate_tool' do
221
50
  let(:config) { { tools: { test_compiler: { executable: 'gcc' } }, extension: { executable: '.out' } } }
222
51
 
@@ -0,0 +1,83 @@
1
+ # =========================================================================
2
+ # Ceedling - Test-Centered Build System for C
3
+ # ThrowTheSwitch.org
4
+ # Copyright (c) 2010-26 Mike Karlesky, Mark VanderVoord, & Greg Williams
5
+ # SPDX-License-Identifier: MIT
6
+ # =========================================================================
7
+
8
+ require 'spec_helper'
9
+ require 'shellwords'
10
+ require 'yaml'
11
+ require 'ceedling/defaults'
12
+ require 'ceedling/tool_executor'
13
+ require 'ceedling/ruby_expandinator'
14
+
15
+ load File.expand_path( '../../plugins/gcov/config/defaults_gcov.rb', __dir__ )
16
+ load File.expand_path( '../../plugins/bullseye/config/defaults_bullseye.rb', __dir__ )
17
+ load File.expand_path( '../../plugins/cppcheck/config/defaults_cppcheck.rb', __dir__ )
18
+
19
+ # GH #1373: the default tools that run a test executable named it unquoted, so a path holding
20
+ # an apostrophe or a space broke the shell command. Each command here is split as a POSIX
21
+ # shell splits it, and every path must come back as one word, exactly as given.
22
+ describe 'Default tools' do
23
+ SPECIAL_PATH = "build/test/out/test/o'neil dir/test_q/test_q.out"
24
+ OTHER_PATH = "src/my dir/o'neil.c"
25
+
26
+ DEPENDENCIES_TOOLS = YAML.load_file(
27
+ File.expand_path( '../../plugins/dependencies/config/defaults.yml', __dir__ ), symbolize_names: true
28
+ )[:tools]
29
+
30
+ before(:each) do
31
+ helper = double('tool_executor_helper').as_null_object
32
+ allow(helper).to receive(:osify_path_separators) { |path| path }
33
+ system_wrapper = double('system_wrapper').as_null_object
34
+ allow(system_wrapper).to receive(:constants_include?).and_return( false )
35
+
36
+ @tool_executor = ToolExecutor.new(
37
+ {
38
+ :tool_executor_helper => helper,
39
+ :loginator => double('loginator').as_null_object,
40
+ :verbosinator => double('verbosinator').as_null_object,
41
+ :system_wrapper => system_wrapper,
42
+ :ruby_expandinator => RubyExpandinator.new
43
+ }
44
+ )
45
+ end
46
+
47
+ # Configuration hands Ceedling an unfrozen copy of each default tool
48
+ def words(tool, *args)
49
+ Shellwords.split( @tool_executor.build_command_line( Marshal.load( Marshal.dump( tool ) ), [], *args )[:line] )
50
+ end
51
+
52
+ {
53
+ 'test fixture' => DEFAULT_TEST_FIXTURE_TOOL,
54
+ 'gcov fixture' => DEFAULT_GCOV_FIXTURE_TOOL,
55
+ 'Bullseye fixture' => DEFAULT_BULLSEYE_FIXTURE_TOOL,
56
+ }.each do |name, tool|
57
+ it "names the test executable as one word in the #{name}" do
58
+ expect( words( tool, SPECIAL_PATH ) ).to eq( [SPECIAL_PATH] )
59
+ end
60
+ end
61
+
62
+ it 'names the test executable as one word in a simple backtrace rerun' do
63
+ expect( words( DEFAULT_TEST_FIXTURE_SIMPLE_BACKTRACE_TOOL, SPECIAL_PATH, '-n "test_a"' ) ).to eq( [SPECIAL_PATH, '-n', 'test_a'] )
64
+ end
65
+
66
+ it 'names the test executable as one word in a gdb backtrace' do
67
+ expect( words( DEFAULT_TEST_BACKTRACE_GDB_TOOL, 'build/gdb.txt', SPECIAL_PATH, '-n "test_a"' ).last( 3 ) ).to eq( [SPECIAL_PATH, '-n', 'test_a'] )
68
+ end
69
+
70
+ it 'names each source file as one word for cppcheck' do
71
+ expect( words( DEFAULT_CPPCHECK_TOOL, ['src'], [OTHER_PATH, 'src/b.c'] ).last( 2 ) ).to eq( [OTHER_PATH, 'src/b.c'] )
72
+ end
73
+
74
+ it 'names the library and each object as one word for the Dependencies archiver' do
75
+ expect( words( DEPENDENCIES_TOOLS[:deps_linker], [OTHER_PATH, 'b.o'], 'build/my dir/libx.a' ) ).to eq(
76
+ ['ar', 'rcs', 'build/my dir/libx.a', OTHER_PATH, 'b.o']
77
+ )
78
+ end
79
+
80
+ it 'names the archive as one word for the Dependencies zip unarchiver' do
81
+ expect( words( DEPENDENCIES_TOOLS[:deps_zip], 'vendor/my dir/x.zip' ) ).to eq( ['unzip', '-o', 'vendor/my dir/x.zip'] )
82
+ end
83
+ end
@@ -7,7 +7,7 @@
7
7
 
8
8
  require 'spec_helper'
9
9
  require 'json'
10
- require 'ceedling/file_wrapper'
10
+ require 'ceedling/filesystem/file_wrapper'
11
11
  require 'ceedling/loginator'
12
12
  require 'ceedling/dependencies/dependency_cache_store'
13
13
 
@@ -124,6 +124,37 @@ describe DependencyCacheStore do
124
124
  expect( @store.load('cache.json')['entries'] ).to eq( {} )
125
125
  end
126
126
 
127
+ # GH #1364: version 2 places per-test build output by the test's path from the project root
128
+ it 'marks the 1.2.2 build layout as schema version 2' do
129
+ expect( DependencyCacheStore::CACHE_SCHEMA_VERSION ).to eq( 2 )
130
+ end
131
+
132
+ it 'rebuilds once from an older build layout, advising clobber for what that layout left' do
133
+ payload = JSON.generate(
134
+ 'schema_version' => 1, 'hash_algorithm' => DependencyHasher::HASH_ALGORITHM, 'entries' => { 'foo.o' => valid_entry }
135
+ )
136
+ stub_file( 'build/cache/.test.dep_cache.json', payload )
137
+
138
+ expect(@loginator).to receive(:log).with(
139
+ 'Dependency cache build/cache/.test.dep_cache.json comes from an earlier Ceedling build layout -- rebuilding ' \
140
+ 'everything once. Run `ceedling clobber` to remove any orphaned build output left in the old layout.',
141
+ Verbosity::COMPLAIN
142
+ )
143
+
144
+ expect( @store.load('build/cache/.test.dep_cache.json')['entries'] ).to eq( {} )
145
+ end
146
+
147
+ it 'keeps its usual warning for a schema_version it never wrote' do
148
+ payload = JSON.generate(
149
+ 'schema_version' => DependencyCacheStore::CACHE_SCHEMA_VERSION + 1, 'hash_algorithm' => DependencyHasher::HASH_ALGORITHM, 'entries' => {}
150
+ )
151
+ stub_file( 'cache.json', payload )
152
+
153
+ expect(@loginator).to receive(:log).with( /cache\.json has an incompatible or missing schema_version/, Verbosity::COMPLAIN )
154
+
155
+ @store.load('cache.json')
156
+ end
157
+
127
158
  it 'treats a mismatched hash_algorithm as an absent cache' do
128
159
  payload = JSON.generate(
129
160
  'schema_version' => DependencyCacheStore::CACHE_SCHEMA_VERSION,
@@ -153,7 +184,7 @@ describe DependencyCacheStore do
153
184
  result = @store.load('cache.json')
154
185
 
155
186
  expect( result['entries'].keys ).to eq( ['good.o'] )
156
- expect( @loginator ).to have_received(:log)
187
+ expect( @loginator ).to have_received(:log).with( /'bad\.o' in cache\.json is malformed/, Verbosity::COMPLAIN )
157
188
  end
158
189
 
159
190
  it 'drops an entry with a self_hash of the wrong length' do
@@ -7,7 +7,7 @@
7
7
 
8
8
  require 'spec_helper'
9
9
  require 'yaml'
10
- require 'ceedling/file_wrapper'
10
+ require 'ceedling/filesystem/file_wrapper'
11
11
  require 'ceedling/yaml_wrapper'
12
12
  require 'ceedling/dependencies/dependency_debug_tree'
13
13
 
@@ -7,16 +7,57 @@
7
7
 
8
8
  require 'spec_helper'
9
9
  require 'digest'
10
- require 'ceedling/file_wrapper'
10
+ require 'ceedling/filesystem/file_wrapper'
11
11
  require 'ceedling/dependencies/dependency_hasher'
12
12
 
13
13
  describe DependencyHasher do
14
14
 
15
15
  before(:each) do
16
16
  @file_wrapper = instance_double('FileWrapper')
17
+ # No file status by default, so every read below hashes afresh
18
+ allow( @file_wrapper ).to receive(:stat).and_return( nil )
17
19
  @hasher = described_class.new( { :file_wrapper => @file_wrapper } )
18
20
  end
19
21
 
22
+ # GH #1368: every test link hashes the libraries it links, so a large library was read
23
+ # once per test executable on every build
24
+ describe '#hash_of_file memo' do
25
+ def status(size, mtime)
26
+ return double( %q(File::Stat), size: size, mtime: mtime )
27
+ end
28
+
29
+ before(:each) do
30
+ allow( @file_wrapper ).to receive(:read_binary).with('libx.a').and_return('library')
31
+ end
32
+
33
+ it 'hashes a file left unchanged since before the build began only once' do
34
+ allow( @file_wrapper ).to receive(:stat).with('libx.a').and_return( status( 7, Time.now - 60 ) )
35
+
36
+ 2.times { expect( @hasher.hash_of_file('libx.a') ).to eq( Digest::SHA256.hexdigest('library') ) }
37
+
38
+ expect( @file_wrapper ).to have_received(:read_binary).once
39
+ end
40
+
41
+ it 'hashes again a file whose size or modification time changed' do
42
+ allow( @file_wrapper ).to receive(:stat).with('libx.a').and_return(
43
+ status( 7, Time.now - 60 ), status( 8, Time.now - 60 ), status( 8, Time.now - 50 )
44
+ )
45
+
46
+ 3.times { @hasher.hash_of_file('libx.a') }
47
+
48
+ expect( @file_wrapper ).to have_received(:read_binary).exactly(3).times
49
+ end
50
+
51
+ # A file the build writes can change within one timestamp tick, unseen by its status
52
+ it 'hashes afresh, every time, a file modified as the build began or since' do
53
+ allow( @file_wrapper ).to receive(:stat).with('libx.a').and_return( status( 7, Time.now ) )
54
+
55
+ 2.times { @hasher.hash_of_file('libx.a') }
56
+
57
+ expect( @file_wrapper ).to have_received(:read_binary).twice
58
+ end
59
+ end
60
+
20
61
  describe '#hash_of_file' do
21
62
  it 'returns the SHA-256 hex digest of the file content read via FileWrapper' do
22
63
  allow( @file_wrapper ).to receive(:read_binary).with('foo.c').and_return('int main(void) {}')
@@ -6,7 +6,7 @@
6
6
  # =========================================================================
7
7
 
8
8
  require 'spec_helper'
9
- require 'ceedling/file_wrapper'
9
+ require 'ceedling/filesystem/file_wrapper'
10
10
  require 'ceedling/dependencies/dependency_path_normalizer'
11
11
 
12
12
  describe DependencyPathNormalizer do
@@ -7,7 +7,7 @@
7
7
 
8
8
  require 'spec_helper'
9
9
  require 'ceedling/exceptions'
10
- require 'ceedling/file_wrapper'
10
+ require 'ceedling/filesystem/file_wrapper'
11
11
  require 'ceedling/system_wrapper'
12
12
  require 'ceedling/loginator'
13
13
  require 'ceedling/yaml_wrapper'
@@ -52,6 +52,8 @@ describe DependencyTracker do
52
52
  allow( @file_wrapper ).to receive(:mkdir)
53
53
  allow( @file_wrapper ).to receive(:write)
54
54
  allow( @file_wrapper ).to receive(:mv)
55
+ # No file status, so every hash reads its file afresh
56
+ allow( @file_wrapper ).to receive(:stat).and_return(nil)
55
57
  allow( @system_wrapper ).to receive(:env_get).with('CEEDLING_DEP_DEBUG').and_return(nil)
56
58
 
57
59
  hasher = DependencyHasher.new( { :file_wrapper => @file_wrapper } )
@@ -51,6 +51,17 @@ describe FilenameExtension do
51
51
  end
52
52
  end
53
53
 
54
+ describe '#pattern' do
55
+ it 'matches any one of its extensions, escaped, as a group' do
56
+ pattern = FilenameExtension.new( ['.c', '.c++'] ).pattern
57
+
58
+ expect('a.c++').to match( /#{pattern}\z/ )
59
+ expect('a.c').to match( /#{pattern}\z/ )
60
+ expect('a.cxx').to_not match( /#{pattern}\z/ )
61
+ expect('a_c').to_not match( /#{pattern}\z/ )
62
+ end
63
+ end
64
+
54
65
  describe '#candidates' do
55
66
  it 'produces one candidate filename per configured extension' do
56
67
  extension = FilenameExtension.new(['.s', '.S'])
@@ -0,0 +1,122 @@
1
+ # =========================================================================
2
+ # Ceedling - Test-Centered Build System for C
3
+ # ThrowTheSwitch.org
4
+ # Copyright (c) 2010-26 Mike Karlesky, Mark VanderVoord, & Greg Williams
5
+ # SPDX-License-Identifier: MIT
6
+ # =========================================================================
7
+
8
+ require 'spec_helper'
9
+ require 'tmpdir'
10
+ require 'fileutils'
11
+ require 'ceedling/filesystem/build_subpath'
12
+
13
+ # GH #1370 and the path handling audit around it: a build file placed by text could land
14
+ # outside the build directory
15
+ describe BuildSubpath do
16
+ WINDOWS_ONLY_BUILD = { if: Gem.win_platform? }.freeze
17
+
18
+ around(:each) do |example|
19
+ Dir.mktmpdir do |dir|
20
+ @ws = File.realpath( dir )
21
+ FileUtils.mkdir_p( File.join( @ws, 'app' ) )
22
+ Dir.chdir( File.join( @ws, 'app' ) ) { example.run }
23
+ end
24
+ end
25
+
26
+ # Every other example reads INSTALLATION_ROOT itself, so only this one shows it names the
27
+ # running installation
28
+ it 'names the running installation, which holds what Ceedling ships' do
29
+ expect(File.file?( File.join( BuildSubpath::INSTALLATION_ROOT, 'lib', 'ceedling', 'filesystem', 'build_subpath.rb' ) )).to be( true )
30
+ BuildSubpath::INSTALLED_DIRS.each { |dir| expect(File.directory?( dir )).to be( true ), dir }
31
+ end
32
+
33
+ describe '.encode and .decode' do
34
+ {
35
+ 'a file in the project' => ['src/drv/uart', 'src/drv/uart'],
36
+ 'a sibling of the project' => ['../shared/src', '_up_/shared/src'],
37
+ 'the working directory' => ['.', '']
38
+ }.each do |label, (path, encoded)|
39
+ it "places #{label} by its path from the project root, and reads it back" do
40
+ expect(BuildSubpath.encode( path )).to eq( encoded )
41
+ expect(BuildSubpath.decode( encoded )).to eq( path == '.' ? '' : path )
42
+ end
43
+ end
44
+
45
+ # A project's own directory may carry a marker's name, which must read back as itself
46
+ it 'places a directory named like a marker apart from the marker, and reads it back' do
47
+ ['_up_/x', 'src/a/_up_', '_ceedling_/src', '_abs_/C/x', '_unc_/srv', 'src/__up_/x'].each do |path|
48
+ encoded = BuildSubpath.encode( path )
49
+
50
+ expect(BuildSubpath.decode( encoded )).to eq( path ), "#{path} => #{encoded}"
51
+ end
52
+ expect(BuildSubpath.encode( '_up_/x' )).to_not eq( BuildSubpath.encode( '../x' ) )
53
+ # macOS and Windows file systems fold case
54
+ expect(BuildSubpath.encode( '_UP_/x' ).downcase).to_not eq( BuildSubpath.encode( '../x' ).downcase )
55
+ expect(BuildSubpath.decode( BuildSubpath.encode( '_UP_/x' ) )).to eq( '_UP_/x' )
56
+ end
57
+
58
+ # Windows has no relative path from one drive to another
59
+ it 'places a file of the running Ceedling on another drive below `_ceedling_` too' do
60
+ file = File.join( BuildSubpath::INSTALLATION_ROOT, 'plugins/fff/src' )
61
+ allow(ProjectPaths).to receive(:relative).and_call_original
62
+ allow(ProjectPaths).to receive(:relative).with( file ).and_return( file )
63
+
64
+ expect(BuildSubpath.encode( file )).to eq( '_ceedling_/plugins/fff/src' )
65
+ end
66
+
67
+ it 'places an absolute path below the project as a relative one' do
68
+ expect(BuildSubpath.encode( File.join( @ws, 'app/src/x' ) )).to eq( 'src/x' )
69
+ end
70
+
71
+ it 'places a file of the running Ceedling outside the project below `_ceedling_`, and reads it back' do
72
+ file = File.join( BuildSubpath::INSTALLATION_ROOT, 'plugins/fff/src' )
73
+
74
+ expect(BuildSubpath.encode( file )).to eq( '_ceedling_/plugins/fff/src' )
75
+ expect(File.expand_path( BuildSubpath.decode( '_ceedling_/plugins/fff/src' ) )).to eq( file )
76
+ end
77
+
78
+ # A project may itself sit inside a Ceedling checkout, as the system specs' projects do.
79
+ # Only what Ceedling ships places below `_ceedling_`.
80
+ it 'places a directory beside a project inside the installation by its path from the project root' do
81
+ root = BuildSubpath::INSTALLATION_ROOT
82
+ allow(ProjectPaths).to receive(:working_dir).and_return( File.join( root, 'specout/proj/app' ) )
83
+
84
+ expect(BuildSubpath.encode( File.join( root, 'specout/proj/shared/src' ) )).to eq( '_up_/shared/src' )
85
+ expect(BuildSubpath.encode( File.join( root, 'plugins/fff/src' ) )).to eq( '_ceedling_/plugins/fff/src' )
86
+ end
87
+
88
+ it 'places a file of the running Ceedling inside the project by its path from the project root' do
89
+ Dir.chdir( BuildSubpath::INSTALLATION_ROOT ) do
90
+ expect(BuildSubpath.encode( 'plugins/fff/src' )).to eq( 'plugins/fff/src' )
91
+ end
92
+ end
93
+
94
+ it 'places a path on another drive below `_abs_`, and reads it back', **WINDOWS_ONLY_BUILD do
95
+ other = Dir.pwd.start_with?( 'C' ) ? 'D' : 'C'
96
+
97
+ expect(BuildSubpath.encode( "#{other}:/x/inc" )).to eq( "_abs_/#{other}/x/inc" )
98
+ expect(BuildSubpath.decode( "_abs_/#{other}/x/inc" )).to eq( "#{other}:/x/inc" )
99
+ end
100
+
101
+ it 'places a UNC path below `_unc_`, and reads it back', **WINDOWS_ONLY_BUILD do
102
+ expect(BuildSubpath.encode( '//server/share/inc' )).to eq( '_unc_/server/share/inc' )
103
+ expect(BuildSubpath.decode( '_unc_/server/share/inc' )).to eq( '//server/share/inc' )
104
+ end
105
+
106
+ it 'never places a file outside the build subpath it names' do
107
+ ['../../far/x', '/opt/x', '../shared', File.join( @ws, 'app/../../x' )].each do |path|
108
+ encoded = BuildSubpath.encode( path )
109
+
110
+ expect(encoded.split( '/' )).to_not include( '..' ), "#{path}: #{encoded}"
111
+ expect(encoded).to_not start_with( '/' ), "#{path}: #{encoded}"
112
+ end
113
+ end
114
+ end
115
+
116
+ describe '.of_directory' do
117
+ it 'is the encoding of a directory, with the working directory as empty' do
118
+ expect(BuildSubpath.of_directory( 'src/drv' )).to eq( 'src/drv' )
119
+ expect(BuildSubpath.of_directory( '.' )).to eq( '' )
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,30 @@
1
+ # =========================================================================
2
+ # Ceedling - Test-Centered Build System for C
3
+ # ThrowTheSwitch.org
4
+ # Copyright (c) 2010-26 Mike Karlesky, Mark VanderVoord, & Greg Williams
5
+ # SPDX-License-Identifier: MIT
6
+ # =========================================================================
7
+
8
+ require 'spec_helper'
9
+ require 'ceedling/filesystem/destination_collision'
10
+
11
+ describe DestinationCollision do
12
+ describe '.find' do
13
+ it 'gives each output more than one input maps to, with those inputs' do
14
+ shared = DestinationCollision.find( ['a/x.c', 'b/x.c', 'c/y.c', 'a/x.c'] ) { |input| File.basename( input ) }
15
+
16
+ expect(shared).to eq( 'x.c' => ['a/x.c', 'b/x.c'] )
17
+ end
18
+
19
+ it 'gives nothing when every input has an output of its own' do
20
+ expect(DestinationCollision.find( ['a.c', 'b.c'] ) { |input| input }).to be_empty
21
+ end
22
+ end
23
+
24
+ describe '.raise_for' do
25
+ it 'names every input and the output they share, with a fix' do
26
+ expect { DestinationCollision.raise_for( 'out/x.o', ['a/x.c', 'b/x.c'], 'would build to the same file' ) }
27
+ .to raise_error( CeedlingException, '`a/x.c` and `b/x.c` would build to the same file `out/x.o`. Rename one, or move it to its own directory.' )
28
+ end
29
+ end
30
+ end