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
@@ -20,6 +20,7 @@ $: << File.join(here, '../../../lib')
20
20
  # real bin/ceedling bootstrap always loads ceedling/constants first, so this load
21
21
  # order only ever bites a spec harness requiring cli_handler.rb directly.
22
22
  require 'ceedling/constants'
23
+ require 'version' # The launcher's own version, which #version reports for this repository
23
24
  require 'cli_handler'
24
25
  require 'app_cfg'
25
26
  require 'path_validator'
@@ -40,16 +41,22 @@ require 'ceedling/rake_app/rake_task_registry'
40
41
  # exercising the real filtering/standardizing behavior it coordinates).
41
42
  describe CliHandler do
42
43
  before(:each) do
43
- @loginator = double('loginator').as_null_object
44
- @helper = double('cli_helper').as_null_object
44
+ @loginator = double('loginator').as_null_object
45
+ @helper = double('cli_helper').as_null_object
46
+ @composinator = double('composinator').as_null_object
47
+ @projectinator = double('projectinator').as_null_object
48
+ @path_validator = double('path_validator').as_null_object
49
+ @actionator = double('actionator').as_null_object
50
+ @launchinator = double('launchinator').as_null_object
45
51
 
46
52
  @cli_handler = described_class.new({
47
- :composinator => double('composinator').as_null_object,
48
- :projectinator => double('projectinator').as_null_object,
53
+ :composinator => @composinator,
54
+ :projectinator => @projectinator,
49
55
  :cli_helper => @helper,
50
- :path_validator => double('path_validator').as_null_object,
56
+ :path_validator => @path_validator,
51
57
  :rake_task_registry => double('rake_task_registry').as_null_object,
52
- :actionator => double('actionator').as_null_object,
58
+ :actionator => @actionator,
59
+ :launchinator => @launchinator,
53
60
  :loginator => @loginator,
54
61
  })
55
62
  end
@@ -77,6 +84,9 @@ describe CliHandler do
77
84
  describe '#version' do
78
85
  before(:each) do
79
86
  @app_cfg = CeedlingAppConfig.new
87
+ # No project file unless an example says otherwise
88
+ allow(@projectinator).to receive(:config_available?).and_return( false )
89
+ allow(@path_validator).to receive(:standardize_paths) { |*paths| paths }
80
90
  end
81
91
 
82
92
  def fake_application_version(install_path)
@@ -109,12 +119,278 @@ describe CliHandler do
109
119
  )
110
120
 
111
121
  expect(@loginator).to receive(:console) do |message, _label|
112
- expect(message).to include( 'Ceedling Launcher => 1.2.0' )
122
+ # The launcher reports the version of the Ceedling running this spec
123
+ expect(message).to include( "Ceedling Launcher => #{Ceedling::Version::GEM}" )
113
124
  expect(message).to include( 'Ceedling App => 1.2.0' )
114
125
  end
115
126
 
116
127
  @cli_handler.version( {}, @app_cfg )
117
128
  end
129
+
130
+ # GH #1365: `version` reported the launcher for a project selecting another installation
131
+ context 'with a project' do
132
+ before(:each) do
133
+ allow(@helper).to receive(:manufacture_app_version).and_return( fake_application_version( '/elsewhere' ) )
134
+ allow(@helper).to receive(:process_mixin_filepaths) { |mixins| mixins }
135
+ end
136
+
137
+ it 'resolves which Ceedling from an explicit --project and its mixins, loading silently' do
138
+ config = {:project => {:which_ceedling => '/elsewhere'}}
139
+ expect(@composinator).to receive(:loadinate).with(
140
+ hash_including( filepath: 'other/project.yml', mixins: ['ci.yml'], silent: true )
141
+ ).and_return( ['other/project.yml', config] )
142
+ expect(@launchinator).to receive(:resolve).with( env: {}, app_cfg: @app_cfg, config: config )
143
+
144
+ @cli_handler.version( {}, @app_cfg, {:project => 'other/project.yml', :mixin => ['ci.yml']} )
145
+ end
146
+
147
+ it 'raises when an explicit --project cannot be loaded' do
148
+ allow(@composinator).to receive(:loadinate).and_raise( 'Could not find project filepath' )
149
+
150
+ expect {
151
+ @cli_handler.version( {}, @app_cfg, {:project => 'missing.yml', :mixin => []} )
152
+ }.to raise_error( /Could not find project filepath/ )
153
+ end
154
+
155
+ it 'raises when an explicit --mixin cannot be loaded with the default project file' do
156
+ allow(@composinator).to receive(:loadinate).and_raise( 'Command line failed validation' )
157
+
158
+ expect {
159
+ @cli_handler.version( {}, @app_cfg, {:project => nil, :mixin => ['missing.yml']} )
160
+ }.to raise_error( /Command line failed validation/ )
161
+ end
162
+
163
+ it 'reads the default project file when one is available' do
164
+ config = {:project => {:which_ceedling => 'vendor/ceedling'}}
165
+ allow(@projectinator).to receive(:config_available?).and_return( true )
166
+ allow(@composinator).to receive(:loadinate).and_return( ['project.yml', config] )
167
+ expect(@launchinator).to receive(:resolve).with( env: {}, app_cfg: @app_cfg, config: config )
168
+
169
+ @cli_handler.version( {}, @app_cfg )
170
+ end
171
+
172
+ it 'falls back to resolving without a project when the default project file cannot be loaded' do
173
+ allow(@projectinator).to receive(:config_available?).and_return( true )
174
+ allow(@composinator).to receive(:loadinate).and_raise( 'Project configuration file section :mixins failed validation' )
175
+ expect(@launchinator).to receive(:resolve).with( env: {}, app_cfg: @app_cfg, config: {} )
176
+
177
+ expect { @cli_handler.version( {}, @app_cfg ) }.to_not raise_error
178
+ end
179
+
180
+ it 'resolves without a project when no project file is available' do
181
+ expect(@composinator).to_not receive(:loadinate)
182
+ expect(@launchinator).to receive(:resolve).with( env: {}, app_cfg: @app_cfg, config: {} )
183
+
184
+ @cli_handler.version( {}, @app_cfg )
185
+ end
186
+
187
+ it 'never hands off, since it reports on both installations' do
188
+ @cli_handler.version( {}, @app_cfg )
189
+
190
+ expect(@launchinator).to_not have_received(:launch)
191
+ end
192
+
193
+ it 'reports the launcher from where it runs, even after resolution moves the application paths' do
194
+ allow(@launchinator).to receive(:resolve) { |app_cfg:, **| app_cfg.set_paths( '/elsewhere' ) }
195
+
196
+ expect(@loginator).to receive(:console) do |message, _label|
197
+ expect(message).to include( "Ceedling Launcher => #{Ceedling::Version::GEM}" )
198
+ expect(message).to include( "#{@app_cfg[:launcher_root_path]}/" )
199
+ end
200
+
201
+ @cli_handler.version( {}, @app_cfg )
202
+ end
203
+ end
204
+ end
205
+
206
+ # GH #1365: every command but `version` runs in the installation it selects. An exec
207
+ # never returns, so a raise stands in for it: nothing after the hand-off may run.
208
+ describe 'hand-off' do
209
+ HandedOff = Class.new( StandardError )
210
+
211
+ before(:each) do
212
+ @app_cfg = CeedlingAppConfig.new
213
+ @config = {:project => {:which_ceedling => 'vendor/ceedling'}}
214
+ allow(@path_validator).to receive(:standardize_paths) { |*paths| paths }
215
+ allow(@helper).to receive(:process_mixin_filepaths) { |mixins| mixins }
216
+ allow(@composinator).to receive(:loadinate).and_return( ['project.yml', @config] )
217
+ end
218
+
219
+ def expect_no_work_done
220
+ [:log_project_name, :console_project_name, :load_ceedling, :run_rake_tasks, :dump_yaml,
221
+ :project_exists?, :vendor_tools, :copy_docs, :lookup_example_projects, :help_footer].each do |work|
222
+ expect(@helper).to_not have_received( work )
223
+ end
224
+ expect(@actionator).to_not have_received(:make_directory)
225
+ expect(@actionator).to_not have_received(:remove_directory)
226
+ expect(@loginator).to_not have_received(:console)
227
+ end
228
+
229
+ {
230
+ 'build' => ->(h, cfg) { h.build( env: {}, app_cfg: cfg, options: {:project => nil, :mixin => []}, tasks: ['test:all'] ) },
231
+ 'check' => ->(h, cfg) { h.check( {}, cfg, {:project => nil, :mixin => []} ) },
232
+ 'environment' => ->(h, cfg) { h.environment( {}, cfg, {:project => nil, :mixin => []} ) },
233
+ 'dumpconfig' => ->(h, cfg) { h.dumpconfig( {}, cfg, {:project => nil, :mixin => [], :app => true}, 'out.yml', [] ) },
234
+ 'dumpconfig --no-app' => ->(h, cfg) { h.dumpconfig( {}, cfg, {:project => nil, :mixin => [], :app => false}, 'out.yml', [] ) },
235
+ '-T' => ->(h, cfg) { h.rake_help( env: {}, app_cfg: cfg ) },
236
+ }.each do |name, command|
237
+ it "#{name} hands off with the project's configuration before doing anything else" do
238
+ expect(@launchinator).to receive(:launch).with( env: {}, app_cfg: @app_cfg, config: @config ).and_raise( HandedOff )
239
+
240
+ expect { command.call( @cli_handler, @app_cfg ) }.to raise_error( HandedOff )
241
+ expect_no_work_done()
242
+ end
243
+ end
244
+
245
+ it 'help hands off with the project\'s configuration before printing any help' do
246
+ allow(@projectinator).to receive(:config_available?).and_return( true )
247
+ expect(@launchinator).to receive(:launch).with( env: {}, app_cfg: @app_cfg, config: @config ).and_raise( HandedOff )
248
+ printed = false
249
+
250
+ expect { @cli_handler.app_help( {}, @app_cfg, {:project => nil, :mixin => []}, nil ) { printed = true } }.to raise_error( HandedOff )
251
+ expect(printed).to be( false )
252
+ expect_no_work_done()
253
+ end
254
+
255
+ it 'help for one command hands off without the project when the project fails to load' do
256
+ allow(@projectinator).to receive(:config_available?).and_return( true )
257
+ allow(@composinator).to receive(:loadinate).and_raise( 'Project configuration file section :mixins failed validation' )
258
+ expect(@launchinator).to receive(:launch).with( env: {}, app_cfg: @app_cfg, config: {} ).and_raise( HandedOff )
259
+
260
+ expect { @cli_handler.app_help( {}, @app_cfg, {:project => nil, :mixin => []}, 'build' ) { } }.to raise_error( HandedOff )
261
+ end
262
+
263
+ it 'help for every command still fails when the project fails to load' do
264
+ allow(@projectinator).to receive(:config_available?).and_return( true )
265
+ allow(@composinator).to receive(:loadinate).and_raise( 'Project configuration file section :mixins failed validation' )
266
+
267
+ expect {
268
+ @cli_handler.app_help( {}, @app_cfg, {:project => nil, :mixin => []}, nil ) { }
269
+ }.to raise_error( /failed validation/ )
270
+ expect(@launchinator).to_not have_received(:launch)
271
+ end
272
+
273
+ it 'help without a project hands off by environment and vendor detection alone' do
274
+ allow(@projectinator).to receive(:config_available?).and_return( false )
275
+ expect(@launchinator).to receive(:launch).with( env: {}, app_cfg: @app_cfg, config: {} ).and_raise( HandedOff )
276
+
277
+ expect { @cli_handler.app_help( {}, @app_cfg, {:project => nil, :mixin => []}, 'build' ) { } }.to raise_error( HandedOff )
278
+ expect(@composinator).to_not have_received(:loadinate)
279
+ end
280
+
281
+ {
282
+ 'new' => ->(h, cfg) { h.new_project( {}, cfg, '1.2.2', {:local => true, :configs => true}, 'proj' ) },
283
+ 'examples' => ->(h, cfg) { h.list_examples( {}, cfg, {} ) },
284
+ 'example' => ->(h, cfg) { h.create_example( {}, cfg, {:local => true}, 'temp_sensor', nil ) },
285
+ }.each do |name, command|
286
+ it "#{name} hands off by environment and vendor detection before doing anything else" do
287
+ expect(@launchinator).to receive(:launch).with( env: {}, app_cfg: @app_cfg ).and_raise( HandedOff )
288
+
289
+ expect { command.call( @cli_handler, @app_cfg ) }.to raise_error( HandedOff )
290
+ expect_no_work_done()
291
+ end
292
+ end
293
+
294
+ # GH #1365: a `--local` copy carries no documentation bundle, so it would export only licenses
295
+ describe 'docs' do
296
+ before(:each) do
297
+ @launcher = Installation.new( @app_cfg[:launcher_root_path] )
298
+ @copy = Installation.new( 'vendor/ceedling' )
299
+ allow(@launchinator).to receive(:resolve) { |app_cfg:, **| app_cfg.set_paths( @copy.root ); @copy }
300
+ end
301
+
302
+ it 'hands off to the selected installation when it holds a documentation bundle' do
303
+ allow(@helper).to receive(:docs_bundle?).with( @copy.root ).and_return( true )
304
+ expect(@launchinator).to receive(:proceed).with( target: @copy, app_cfg: @app_cfg ).and_raise( HandedOff )
305
+
306
+ expect { @cli_handler.docs( {}, @app_cfg, 'out' ) }.to raise_error( HandedOff )
307
+ expect_no_work_done()
308
+ end
309
+
310
+ it 'exports the launcher\'s documentation, saying so, when the selected installation has none' do
311
+ allow(@helper).to receive(:docs_bundle?).with( @copy.root ).and_return( false )
312
+
313
+ expect(@loginator).to receive(:console).with(
314
+ "#{@copy.describe} holds no documentation bundle to export. " +
315
+ "Exporting the documentation of #{@launcher.describe( 'Ceedling launcher' )} instead.",
316
+ LogLabels::NOTICE
317
+ ).ordered
318
+ expect(@helper).to receive(:copy_docs).with( @launcher.root, 'out' ).ordered
319
+
320
+ @cli_handler.docs( {}, @app_cfg, 'out' )
321
+
322
+ expect(@launchinator).to_not have_received(:proceed)
323
+ expect(@app_cfg[:ceedling_root_path]).to eq( @launcher.root )
324
+ end
325
+
326
+ it 'exports the launcher\'s own documentation with no notice when it is selected' do
327
+ allow(@launchinator).to receive(:resolve).and_return( @launcher )
328
+
329
+ expect(@helper).to receive(:copy_docs).with( @launcher.root, 'out' )
330
+
331
+ @cli_handler.docs( {}, @app_cfg, 'out' )
332
+
333
+ expect(@loginator).to_not have_received(:console)
334
+ end
335
+ end
336
+
337
+ it 'upgrade hands off by environment alone, never to a vendor/ceedling it detects' do
338
+ source = Installation.new( 'elsewhere/ceedling' )
339
+ expect(@launchinator).to receive(:resolve).with( env: {}, app_cfg: @app_cfg, detect_vendor: false ).and_return( source )
340
+ expect(@launchinator).to receive(:proceed).with( target: source, app_cfg: @app_cfg ).and_raise( HandedOff )
341
+
342
+ expect { @cli_handler.upgrade_project( {}, @app_cfg, {:project => 'project.yml'}, 'proj' ) }.to raise_error( HandedOff )
343
+ expect_no_work_done()
344
+ end
345
+
346
+ # GH #1365: WHICH_CEEDLING naming the project's own copy would hand off to it, and a copy
347
+ # before 1.2.2 deletes itself as its own source
348
+ it 'upgrade refuses to re-vendor a project from its own vendored copy, before handing off to it' do
349
+ allow(@launchinator).to receive(:resolve) { |app_cfg:, **| app_cfg.set_paths( 'proj/vendor/ceedling' ); Installation.new( 'proj/vendor/ceedling' ) }
350
+
351
+ expect {
352
+ @cli_handler.upgrade_project( {'WHICH_CEEDLING' => 'proj/vendor/ceedling'}, @app_cfg, {:project => 'project.yml'}, 'proj' )
353
+ }.to raise_error( CeedlingException, /Cannot upgrade #{Regexp.escape( File.expand_path( 'proj/vendor/ceedling' ) )}\/ from itself/ )
354
+ expect(@launchinator).to_not have_received(:proceed)
355
+ expect_no_work_done()
356
+ end
357
+ end
358
+
359
+ # GH #1371: exported documentation was never refreshed, and refreshing it removed all of docs/
360
+ describe '#upgrade_project documentation' do
361
+ before(:each) do
362
+ @app_cfg = CeedlingAppConfig.new
363
+ @source = Installation.new( 'elsewhere/ceedling' )
364
+ @docs = File.join( 'proj', 'docs' )
365
+ allow(@path_validator).to receive(:standardize_paths) { |*paths| paths }
366
+ allow(@launchinator).to receive(:resolve) { |app_cfg:, **| app_cfg.set_paths( @source.root ); @source }
367
+ allow(@helper).to receive(:project_exists?).and_return( true )
368
+ end
369
+
370
+ def upgrade
371
+ @cli_handler.upgrade_project( {}, @app_cfg, {:project => 'project.yml'}, 'proj' )
372
+ end
373
+
374
+ it 'replaces what an export wrote, keeping the bundle when the source has none, then exports again' do
375
+ allow(@helper).to receive(:exported_docs?).with( @docs ).and_return( true )
376
+ allow(@helper).to receive(:docs_bundle?).with( @source.root ).and_return( false )
377
+
378
+ expect(@helper).to receive(:remove_exported_docs).with( @docs, keep_bundle: true ).ordered
379
+ expect(@helper).to receive(:copy_docs).with( @source.root, @docs ).ordered
380
+
381
+ upgrade()
382
+
383
+ expect(@actionator).to_not have_received(:remove_directory).with( @docs )
384
+ end
385
+
386
+ it 'leaves docs/ alone when it holds no export' do
387
+ allow(@helper).to receive(:exported_docs?).with( @docs ).and_return( false )
388
+
389
+ upgrade()
390
+
391
+ expect(@helper).to_not have_received(:remove_exported_docs)
392
+ expect(@helper).to_not have_received(:copy_docs)
393
+ end
118
394
  end
119
395
 
120
396
  describe '#list_examples' do
@@ -167,6 +443,7 @@ describe CliHandler do
167
443
  :path_validator => real_path_validator,
168
444
  :rake_task_registry => double('rake_task_registry').as_null_object,
169
445
  :actionator => double('actionator').as_null_object,
446
+ :launchinator => double('launchinator').as_null_object,
170
447
  :loginator => double('loginator').as_null_object,
171
448
  })
172
449
  end
@@ -7,6 +7,7 @@
7
7
 
8
8
  require 'spec_helper'
9
9
  require 'tmpdir'
10
+ require 'fileutils'
10
11
  require 'rake'
11
12
 
12
13
  # bin/versionator.rb (pulled in transitively by cli_helper.rb) uses bare `require`
@@ -22,6 +23,8 @@ $: << File.join(here, '../../../lib')
22
23
  require 'cli_helper'
23
24
  require 'app_cfg'
24
25
  require 'ceedling/ruby_expandinator'
26
+ require 'ceedling/config/config_walkinator'
27
+ require 'ceedling/filesystem/file_wrapper'
25
28
  # CliHelper#test_task? references RakeTaskRegistry::TAG_TEST, but only
26
29
  # bin/cli_handler.rb requires this file in the real bootstrap (loaded before
27
30
  # cli_helper.rb's methods are ever called) -- required directly here since this
@@ -111,70 +114,117 @@ describe CliHelper do
111
114
  end
112
115
  end
113
116
 
114
- describe '#which_ceedling?' do
115
- before(:each) do
116
- @app_cfg = CeedlingAppConfig.new
117
- # Baseline: no :project ↳ :which_ceedling entry found. Tests exercising that
118
- # config path override this with a more specific `.with(...)` stub below.
119
- allow(@config_walkinator).to receive(:fetch_value).and_return( [nil, nil] )
117
+ # Whether a command's tasks build a release decides what build/vendor needs (GH #1361)
118
+ describe '#release_task?' do
119
+ it 'is true when any task belongs to a release-building namespace' do
120
+ allow(@rake_task_registry).to receive(:task_is?) { |task, tag| task == 'release' && tag == RakeTaskRegistry::TAG_RELEASE }
121
+
122
+ expect( @cli_helper.release_task?( tasks: ['test:all', 'release'] ) ).to be(true)
123
+ expect( @cli_helper.release_task?( tasks: ['test:all', 'files:test'] ) ).to be(false)
120
124
  end
125
+ end
121
126
 
122
- it 'uses the WHICH_CEEDLING environment variable at highest priority' do
123
- which, path = @cli_helper.which_ceedling?( env: {'WHICH_CEEDLING' => 'gem'}, app_cfg: @app_cfg )
127
+ describe '#docs_bundle?' do
128
+ it 'is true when the installation holds an HTML documentation bundle' do
129
+ allow(@file_wrapper).to receive(:directory?).with( File.join( '/ceedling', DOCS_SITE_LOCAL_PATH ) ).and_return( true )
124
130
 
125
- expect(which).to eq( :gem )
126
- expect(path).to eq( @app_cfg[:ceedling_rakefile_filepath] )
131
+ expect(@cli_helper.docs_bundle?( '/ceedling' )).to be( true )
127
132
  end
128
133
 
129
- it 'falls back to config :project ↳ :which_ceedling when no environment variable is set' do
130
- config = {:project => {:which_ceedling => 'gem'}}
131
- allow(@config_walkinator).to receive(:fetch_value).with( :project, :which_ceedling, hash: config ).and_return( ['gem', nil] )
132
-
133
- which, path = @cli_helper.which_ceedling?( env: {}, config: config, app_cfg: @app_cfg )
134
+ it 'is false when it does not, as for any --local copy' do
135
+ allow(@file_wrapper).to receive(:directory?).with( File.join( '/ceedling', DOCS_SITE_LOCAL_PATH ) ).and_return( false )
134
136
 
135
- expect(which).to eq( :gem )
136
- expect(path).to eq( @app_cfg[:ceedling_rakefile_filepath] )
137
+ expect(@cli_helper.docs_bundle?( '/ceedling' )).to be( false )
137
138
  end
139
+ end
138
140
 
139
- it 'falls back to a vendor/ceedling directory when neither environment nor config specify anything' do
140
- allow(@file_wrapper).to receive(:directory?).with( 'vendor/ceedling' ).and_return( true )
141
- allow(@file_wrapper).to receive(:exist?).and_return( true )
141
+ # GH #1371: `upgrade` detected exported documentation by a file exports stopped writing in
142
+ # 1.1.0, and refreshed it by deleting all of docs/, the project's own files included
143
+ describe 'exported documentation' do
144
+ LEGACY_PAGES = %w[BreakingChanges.md CODE_OF_CONDUCT.md CONTRIBUTING.md CeedlingPacket.md CeedlingUpgrade.md
145
+ Changelog.md PluginDevelopmentGuide.md ReleaseNotes.md ThrowTheSwitchCodingStandard.md]
142
146
 
143
- which, path = @cli_helper.which_ceedling?( env: {}, app_cfg: @app_cfg )
147
+ around(:each) do |example|
148
+ Dir.mktmpdir { |dir| @docs = dir; example.run }
149
+ end
144
150
 
145
- expect(which).to eq( :path )
146
- expect(path).to eq( @app_cfg[:ceedling_rakefile_filepath] )
147
- expect(@app_cfg[:ceedling_root_path]).to eq( File.expand_path('vendor/ceedling') )
151
+ before(:each) do
152
+ @actions = double('actionator')
153
+ @removed = []
154
+ allow(@actions).to receive(:remove_directory) { |path| @removed << path }
155
+ @helper = described_class.new({
156
+ :file_wrapper => FileWrapper.new( {:loginator => @loginator, :verbosinator => double('verbosinator').as_null_object} ),
157
+ :actionator => @actions,
158
+ :config_walkinator => @config_walkinator,
159
+ :path_validator => @path_validator,
160
+ :rake_task_registry => @rake_task_registry,
161
+ :loginator => @loginator,
162
+ :reportinator => double('reportinator').as_null_object,
163
+ :system_wrapper => double('system_wrapper').as_null_object,
164
+ :ruby_expandinator => @ruby_expandinator,
165
+ })
166
+ end
167
+
168
+ def make(*entries)
169
+ entries.each do |entry|
170
+ path = File.join( @docs, entry )
171
+ entry.end_with?( '/' ) ? FileUtils.mkdir_p( path ) : (FileUtils.mkdir_p( File.dirname( path ) ); File.write( path, '' ))
172
+ end
148
173
  end
149
174
 
150
- it 'defaults to :gem when nothing is set and no vendor/ceedling directory exists' do
151
- allow(@file_wrapper).to receive(:directory?).with( 'vendor/ceedling' ).and_return( false )
175
+ def removed
176
+ return @removed.map { |path| path.delete_prefix( File.join( @docs, '' ) ) }.sort
177
+ end
152
178
 
153
- which, path = @cli_helper.which_ceedling?( env: {}, app_cfg: @app_cfg )
179
+ describe '#exported_docs?' do
180
+ it 'finds an export of 1.1.0 or later by its framework or bundle directories' do
181
+ %w[ceedling/ unity/ cmock/ c_exception/].each do |entry|
182
+ Dir.mktmpdir do |dir|
183
+ FileUtils.mkdir_p( File.join( dir, entry ) )
184
+ expect(@helper.exported_docs?( dir )).to be( true ), entry
185
+ end
186
+ end
187
+ end
154
188
 
155
- expect(which).to eq( :gem )
156
- expect(path).to eq( @app_cfg[:ceedling_rakefile_filepath] )
157
- end
189
+ it 'finds a 1.0.x export by its CeedlingPacket.md' do
190
+ make( 'CeedlingPacket.md' )
158
191
 
159
- it 'raises when a configured launch path does not exist as a directory' do
160
- config = {:project => {:which_ceedling => 'nonexistent/path'}}
161
- allow(@config_walkinator).to receive(:fetch_value).with( :project, :which_ceedling, hash: config ).and_return( ['nonexistent/path', nil] )
162
- allow(@file_wrapper).to receive(:directory?).and_return( false )
192
+ expect(@helper.exported_docs?( @docs )).to be( true )
193
+ end
163
194
 
164
- expect {
165
- @cli_helper.which_ceedling?( env: {}, config: config, app_cfg: @app_cfg )
166
- }.to raise_error( /does not exist/ )
195
+ it 'finds nothing in a docs/ holding only the project\'s own files, or in no docs/ at all' do
196
+ make( 'notes.md', 'design/' )
197
+
198
+ expect(@helper.exported_docs?( @docs )).to be( false )
199
+ expect(@helper.exported_docs?( File.join( @docs, 'absent' ) )).to be( false )
200
+ end
167
201
  end
168
202
 
169
- it 'raises when a configured launch path exists but contains no Ceedling installation' do
170
- config = {:project => {:which_ceedling => 'empty/path'}}
171
- allow(@config_walkinator).to receive(:fetch_value).with( :project, :which_ceedling, hash: config ).and_return( ['empty/path', nil] )
172
- allow(@file_wrapper).to receive(:directory?).and_return( true )
173
- allow(@file_wrapper).to receive(:exist?).and_return( false )
203
+ describe '#remove_exported_docs' do
204
+ it 'removes what an export of 1.1.0 or later wrote, and leaves the project\'s own files' do
205
+ make( 'ceedling/', 'unity/', 'cmock/', 'c_exception/', 'license.txt', 'LICENSE.md', 'notes.md', 'design/' )
174
206
 
175
- expect {
176
- @cli_helper.which_ceedling?( env: {}, config: config, app_cfg: @app_cfg )
177
- }.to raise_error( /contains no Ceedling installation/ )
207
+ @helper.remove_exported_docs( @docs, keep_bundle: false )
208
+
209
+ # The export overwrites its own license, so a license file in docs/ may be the project's
210
+ expect(removed).to eq( %w[c_exception ceedling cmock unity] )
211
+ end
212
+
213
+ it 'removes what a 1.0.x export wrote, and leaves the project\'s own files' do
214
+ make( *LEGACY_PAGES, 'plugins/', 'unity/', 'LICENSE.txt', 'notes.md' )
215
+
216
+ @helper.remove_exported_docs( @docs, keep_bundle: false )
217
+
218
+ expect(removed).to eq( (LEGACY_PAGES + %w[plugins unity]).sort )
219
+ end
220
+
221
+ it 'keeps the HTML bundle when the source has none to replace it with' do
222
+ make( 'ceedling/', 'unity/' )
223
+
224
+ @helper.remove_exported_docs( @docs, keep_bundle: true )
225
+
226
+ expect(removed).to eq( %w[unity] )
227
+ end
178
228
  end
179
229
  end
180
230
 
@@ -222,6 +272,37 @@ describe CliHelper do
222
272
  end
223
273
  end
224
274
 
275
+ # The path handling audit around GH #1370: every other build path reads the build root
276
+ # after Ruby expansion
277
+ describe 'G17: #process_logging_path' do
278
+ it 'places the log directory below the build root as expanded' do
279
+ helper = described_class.new({
280
+ :file_wrapper => @file_wrapper, :actionator => double('actionator').as_null_object, :config_walkinator => ConfigWalkinator.new,
281
+ :path_validator => @path_validator, :rake_task_registry => @rake_task_registry, :loginator => @loginator,
282
+ :reportinator => double('reportinator').as_null_object, :system_wrapper => double('system_wrapper').as_null_object,
283
+ :ruby_expandinator => @ruby_expandinator
284
+ })
285
+ helper.set_ruby_replacement( true )
286
+
287
+ expect(helper.process_logging_path( { project: { build_root: "\#{'out'}/build" } } )).to eq( 'out/build/logs' )
288
+ end
289
+
290
+ # An unset environment variable expands to nothing, which would place the logs at the
291
+ # filesystem root before configuration could refuse the build root
292
+ it 'refuses a build root that expands to nothing, as configuration does' do
293
+ helper = described_class.new({
294
+ :file_wrapper => @file_wrapper, :actionator => double('actionator').as_null_object, :config_walkinator => ConfigWalkinator.new,
295
+ :path_validator => @path_validator, :rake_task_registry => @rake_task_registry, :loginator => @loginator,
296
+ :reportinator => double('reportinator').as_null_object, :system_wrapper => double('system_wrapper').as_null_object,
297
+ :ruby_expandinator => @ruby_expandinator
298
+ })
299
+ helper.set_ruby_replacement( true )
300
+
301
+ expect { helper.process_logging_path( { project: { build_root: "\#{''}" } } ) }
302
+ .to raise_error( CeedlingException, ":project ↳ :build_root => '' names no directory. Give the build its own directory, such as 'build'." )
303
+ end
304
+ end
305
+
225
306
  describe '#process_log_filepath' do
226
307
  around(:each) do |example|
227
308
  Dir.mktmpdir do |dir|