ceedling 1.2.1 → 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 (276) hide show
  1. checksums.yaml +4 -4
  2. data/GIT_COMMIT_SHA +1 -1
  3. data/README.md +11 -9
  4. data/Rakefile +2 -1
  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 +14 -1
  10. data/bin/ceedling +13 -3
  11. data/bin/cli.rb +25 -6
  12. data/bin/cli_handler.rb +113 -73
  13. data/bin/cli_helper.rb +51 -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 +74 -3
  23. data/docs/KnownIssues.md +90 -4
  24. data/docs/ReleaseNotes.md +13 -0
  25. data/lib/ceedling/build_log_writer.rb +33 -0
  26. data/lib/ceedling/config/build_root_policy.rb +70 -0
  27. data/lib/ceedling/config/configurator.rb +14 -16
  28. data/lib/ceedling/config/configurator_builder.rb +58 -28
  29. data/lib/ceedling/config/configurator_paths_validator.rb +179 -0
  30. data/lib/ceedling/config/configurator_plugins.rb +1 -1
  31. data/lib/ceedling/config/configurator_setup.rb +15 -28
  32. data/lib/ceedling/config/configurator_validator.rb +1 -110
  33. data/lib/ceedling/defaults.rb +4 -4
  34. data/lib/ceedling/dependencies/README.md +18 -16
  35. data/lib/ceedling/dependencies/dependency_cache_store.rb +20 -3
  36. data/lib/ceedling/dependencies/dependency_hasher.rb +35 -1
  37. data/lib/ceedling/filename_extension.rb +7 -1
  38. data/lib/ceedling/filesystem/FILE_TREE.md +253 -0
  39. data/lib/ceedling/filesystem/PATH_HANDLING.md +304 -0
  40. data/lib/ceedling/filesystem/README.md +41 -0
  41. data/lib/ceedling/filesystem/build_subpath.rb +102 -0
  42. data/lib/ceedling/filesystem/destination_collision.rb +25 -0
  43. data/lib/ceedling/{file_finder.rb → filesystem/file_finder.rb} +159 -104
  44. data/lib/ceedling/{file_finder_helper.rb → filesystem/file_finder_helper.rb} +36 -31
  45. data/lib/ceedling/filesystem/file_path_collection_utils.rb +183 -0
  46. data/lib/ceedling/{file_path_utils.rb → filesystem/file_path_utils.rb} +108 -97
  47. data/lib/ceedling/{file_system_wrapper.rb → filesystem/file_system_wrapper.rb} +6 -5
  48. data/lib/ceedling/filesystem/file_tree.rb +241 -0
  49. data/lib/ceedling/{file_wrapper.rb → filesystem/file_wrapper.rb} +45 -38
  50. data/lib/ceedling/filesystem/path_exclusions.rb +30 -0
  51. data/lib/ceedling/{path_matcher.rb → filesystem/path_matcher.rb} +27 -23
  52. data/lib/ceedling/{path_mirror.rb → filesystem/path_mirror.rb} +19 -18
  53. data/lib/ceedling/filesystem/path_spellings.rb +55 -0
  54. data/lib/ceedling/filesystem/project_paths.rb +184 -0
  55. data/lib/ceedling/filesystem/working_dir.rb +40 -0
  56. data/lib/ceedling/generators/generator.rb +5 -6
  57. data/lib/ceedling/generators/generator_partials.rb +1 -1
  58. data/lib/ceedling/generators/generator_test_results_backtrace.rb +7 -7
  59. data/lib/ceedling/handoff.rb +121 -0
  60. data/lib/ceedling/includes/include_factory.rb +3 -3
  61. data/lib/ceedling/includes/include_pathinator.rb +67 -10
  62. data/lib/ceedling/includes/includes.rb +1 -1
  63. data/lib/ceedling/installation.rb +92 -0
  64. data/lib/ceedling/library_resolver.rb +99 -0
  65. data/lib/ceedling/objects.yml +23 -2
  66. data/lib/ceedling/partials/partializer.rb +4 -4
  67. data/lib/ceedling/partials/partializer_config.rb +3 -1
  68. data/lib/ceedling/plugins/report_log_writer_plugin.rb +3 -5
  69. data/lib/ceedling/preprocess/preprocessinator_file_assembler.rb +1 -1
  70. data/lib/ceedling/preprocess/preprocessinator_includes_handler.rb +1 -1
  71. data/lib/ceedling/preprocess/preprocessinator_line_marker_includes_extractor.rb +1 -1
  72. data/lib/ceedling/rake_app/rakefile_component_resolver.rb +10 -17
  73. data/lib/ceedling/rakefile.rb +15 -1
  74. data/lib/ceedling/rakefiles/base/tasks_base.rake +1 -1
  75. data/lib/ceedling/rakefiles/release/rules_release.rake +4 -7
  76. data/lib/ceedling/release_invoker/release_build_executor.rb +33 -44
  77. data/lib/ceedling/release_invoker/release_build_planner.rb +14 -6
  78. data/lib/ceedling/reportinator.rb +3 -4
  79. data/lib/ceedling/setupinator.rb +94 -90
  80. data/lib/ceedling/test_context_extractor.rb +5 -1
  81. data/lib/ceedling/test_invoker/PIPELINE.md +9 -7
  82. data/lib/ceedling/test_invoker/mock_locator.rb +60 -2
  83. data/lib/ceedling/test_invoker/partials_manager.rb +12 -0
  84. data/lib/ceedling/test_invoker/standin_headerinator.rb +22 -13
  85. data/lib/ceedling/test_invoker/test_build_executor.rb +24 -40
  86. data/lib/ceedling/test_invoker/test_build_planner.rb +37 -18
  87. data/lib/ceedling/test_invoker/test_build_setup.rb +17 -12
  88. data/lib/ceedling/test_invoker/test_build_validations.rb +16 -31
  89. data/lib/ceedling/test_invoker/test_file_preprocessinator.rb +1 -1
  90. data/lib/ceedling/test_invoker/test_invoker.rb +6 -1
  91. data/lib/ceedling/test_invoker/test_pipeline_helpers.rb +1 -1
  92. data/lib/ceedling/test_invoker/test_source_file_directive_resolver.rb +40 -20
  93. data/lib/ceedling/tool_executor.rb +9 -3
  94. data/lib/ceedling/yaml_wrapper.rb +3 -2
  95. data/lib/version.rb +1 -1
  96. data/plugins/bullseye/config/defaults_bullseye.rb +1 -1
  97. data/plugins/bullseye/lib/bullseye.rb +9 -7
  98. data/plugins/cppcheck/config/defaults_cppcheck.rb +1 -1
  99. data/plugins/dependencies/config/defaults.yml +6 -6
  100. data/plugins/dependencies/dependencies.rake +4 -1
  101. data/plugins/dependencies/lib/dependencies.rb +18 -8
  102. data/plugins/dependencies/lib/dependency_spec.rb +17 -5
  103. data/plugins/fff/lib/fff.rb +45 -39
  104. data/plugins/fff/spec/fff_cmock_wrapper_spec.rb +128 -0
  105. data/plugins/gcov/config/defaults_gcov.rb +1 -1
  106. data/plugins/gcov/lib/console_reportinator.rb +4 -18
  107. data/plugins/gcov/lib/gcov.rb +9 -2
  108. data/plugins/gcov/lib/gcovr_reportinator.rb +8 -40
  109. data/plugins/gcov/lib/gcovr_thresholds.rb +74 -0
  110. data/plugins/gcov/lib/reportgenerator_reportinator.rb +1 -1
  111. data/plugins/module_generator/lib/module_generator.rb +3 -3
  112. data/plugins/report_tests_teamcity_stdout/lib/report_tests_teamcity_stdout.rb +53 -80
  113. data/plugins/sanitize/lib/sanitize_records.rb +3 -6
  114. data/plugins/valgrind/lib/valgrind.rb +14 -7
  115. data/site-local/configuration/reference/cmock.html +2 -1
  116. data/site-local/configuration/reference/files.html +9 -3
  117. data/site-local/configuration/reference/libraries.html +21 -3
  118. data/site-local/configuration/reference/paths.html +29 -6
  119. data/site-local/configuration/reference/project.html +17 -7
  120. data/site-local/configuration/reference/release-build.html +2 -0
  121. data/site-local/configuration/reference/tools.html +9 -0
  122. data/site-local/configuration/which-ceedling.html +377 -17
  123. data/site-local/development/releases.html +5 -1
  124. data/site-local/development/workflow.html +48 -43
  125. data/site-local/getting-started/builds.html +2 -0
  126. data/site-local/getting-started/command-line.html +56 -4
  127. data/site-local/plugins/dependencies.html +6 -3
  128. data/site-local/plugins/fff.html +42 -11
  129. data/site-local/plugins/gcov/gcovr.html +15 -12
  130. data/site-local/plugins/gcov/setup.html +2 -1
  131. data/site-local/plugins/report-tests-raw-output-log.html +3 -1
  132. data/site-local/plugins/report-tests-teamcity-stdout.html +6 -3
  133. data/site-local/plugins/sanitize.html +7 -6
  134. data/site-local/plugins/valgrind.html +8 -7
  135. data/site-local/project/upgrade.html +3 -0
  136. data/site-local/reference/command-line.html +9 -2
  137. data/site-local/sitemap.xml.gz +0 -0
  138. data/site-local/snapshot/plugins/bullseye/config/defaults_bullseye.rb +1 -1
  139. data/site-local/snapshot/plugins/gcov/config/defaults_gcov.rb +1 -1
  140. data/site-local/testing-guide/conventions.html +53 -0
  141. data/spec/integration/actionator_file_operations_spec.rb +91 -1
  142. data/spec/integration/compile_commands_json_db_spec.rb +1 -1
  143. data/spec/integration/configurator_validation_spec.rb +1 -1
  144. data/spec/integration/dependencies/dependency_tracker_cache_hardening_spec.rb +26 -0
  145. data/spec/integration/dependencies/dependency_tracker_core_spec.rb +22 -0
  146. data/spec/integration/launcher_handoff_spec.rb +297 -0
  147. data/spec/integration/mixin_loading_spec.rb +1 -1
  148. data/spec/integration/module_generator_spec.rb +3 -3
  149. data/spec/integration/nested_test_artifacts_spec.rb +99 -0
  150. data/spec/integration/partials_module_resolution_spec.rb +7 -4
  151. data/spec/integration/path_intake_scenarios_spec.rb +101 -0
  152. data/spec/integration/path_scenarios_spec.rb +322 -0
  153. data/spec/integration/quote_include_isolator_spec.rb +1 -1
  154. data/spec/integration/report_build_warnings_log_spec.rb +1 -1
  155. data/spec/integration/report_tests_log_factory_spec.rb +1 -1
  156. data/spec/integration/test_executable_manifest_spec.rb +1 -1
  157. data/spec/integration/test_includes_extractinator_spec.rb +2 -1
  158. data/spec/integration/test_naming_spec.rb +198 -0
  159. data/spec/integration/test_source_file_checks_spec.rb +166 -0
  160. data/spec/integration/tool_validator_spec.rb +1 -1
  161. data/spec/integration/upgrade_docs_spec.rb +84 -0
  162. data/spec/integration/vendor_copy_transient_io_retry_spec.rb +74 -5
  163. data/spec/support/file_tree_helper.rb +88 -0
  164. data/spec/support/integration/configurator_integration_helper.rb +6 -6
  165. data/spec/support/integration/dependency_tracker_integration_helper.rb +1 -1
  166. data/spec/support/integration/partials_generation_integration_helper.rb +2 -2
  167. data/spec/support/integration/path_scenario_harness.rb +173 -0
  168. data/spec/support/integration/spec_integration_helper.rb +1 -1
  169. data/spec/support/integration/test_includes_harness.rb +13 -2
  170. data/spec/support/spec_helper.rb +2 -0
  171. data/spec/support/system/spec_system_helper.rb +7 -6
  172. data/spec/support/system/system_context.rb +21 -3
  173. data/spec/support/working_dir_tracking.rb +49 -0
  174. data/spec/system/build_output_mirroring_spec.rb +2 -2
  175. data/spec/system/conditional_mock_includes_spec.rb +1 -1
  176. data/spec/system/delta_builds_spec.rb +137 -11
  177. data/spec/system/gcov_deployment_spec.rb +1 -0
  178. data/spec/system/header_include_path_validation_spec.rb +4 -4
  179. data/spec/system/launcher_handoff_spec.rb +82 -0
  180. data/spec/system/mock_include_folders_spec.rb +91 -0
  181. data/spec/system/parent_directory_reference_spec.rb +5 -3
  182. data/spec/system/path_handling_probes_spec.rb +192 -0
  183. data/spec/system/preprocessing_parameterized_tests_spec.rb +1 -1
  184. data/spec/system/rake_release_task_path_disambiguation_spec.rb +6 -6
  185. data/spec/system/rake_test_task_path_disambiguation_spec.rb +85 -0
  186. data/spec/system/special_path_characters_spec.rb +86 -0
  187. data/spec/system/support/common_test_cases.rb +23 -21
  188. data/spec/system/support/gcov_common_test_cases.rb +37 -9
  189. data/spec/system/support/sanitize_common_test_cases.rb +2 -2
  190. data/spec/system/support/valgrind_common_test_cases.rb +12 -12
  191. data/spec/system/test_pipeline_stop_points_spec.rb +4 -4
  192. data/spec/system/test_runner_system_include_spec.rb +1 -1
  193. data/spec/system/test_source_file_directive_spec.rb +34 -5
  194. data/spec/units/bin/actionator_spec.rb +14 -17
  195. data/spec/units/bin/app_cfg_spec.rb +37 -0
  196. data/spec/units/bin/cli_handler_spec.rb +282 -6
  197. data/spec/units/bin/cli_helper_spec.rb +116 -45
  198. data/spec/units/bin/installation_selector_spec.rb +114 -0
  199. data/spec/units/bin/launchinator_spec.rb +171 -0
  200. data/spec/units/bin/path_validator_spec.rb +10 -0
  201. data/spec/units/bin/versionator_spec.rb +38 -6
  202. data/spec/units/build_log_writer_spec.rb +57 -0
  203. data/spec/units/config/build_root_policy_spec.rb +61 -0
  204. data/spec/units/config/configurator_builder_spec.rb +37 -6
  205. data/spec/units/config/configurator_paths_validator_spec.rb +292 -0
  206. data/spec/units/config/configurator_setup_spec.rb +9 -65
  207. data/spec/units/config/configurator_spec.rb +27 -5
  208. data/spec/units/config/configurator_validator_spec.rb +1 -172
  209. data/spec/units/default_tools_quoting_spec.rb +83 -0
  210. data/spec/units/dependencies/dependency_cache_store_spec.rb +33 -2
  211. data/spec/units/dependencies/dependency_debug_tree_spec.rb +1 -1
  212. data/spec/units/dependencies/dependency_hasher_spec.rb +42 -1
  213. data/spec/units/dependencies/dependency_path_normalizer_spec.rb +1 -1
  214. data/spec/units/dependencies/dependency_tracker_spec.rb +3 -1
  215. data/spec/units/filename_extension_spec.rb +11 -0
  216. data/spec/units/filesystem/build_subpath_spec.rb +122 -0
  217. data/spec/units/filesystem/destination_collision_spec.rb +30 -0
  218. data/spec/units/{file_finder_helper_spec.rb → filesystem/file_finder_helper_spec.rb} +46 -1
  219. data/spec/units/{file_finder_spec.rb → filesystem/file_finder_spec.rb} +188 -22
  220. data/spec/units/{file_path_collection_utils_spec.rb → filesystem/file_path_collection_utils_spec.rb} +181 -1
  221. data/spec/units/{file_path_utils_spec.rb → filesystem/file_path_utils_spec.rb} +204 -87
  222. data/spec/units/filesystem/file_system_wrapper_spec.rb +33 -0
  223. data/spec/units/filesystem/file_tree_spec.rb +511 -0
  224. data/spec/units/filesystem/file_tree_windows_spec.rb +78 -0
  225. data/spec/units/{file_wrapper_spec.rb → filesystem/file_wrapper_spec.rb} +95 -12
  226. data/spec/units/{path_matcher_spec.rb → filesystem/path_matcher_spec.rb} +12 -1
  227. data/spec/units/{path_mirror_spec.rb → filesystem/path_mirror_spec.rb} +32 -4
  228. data/spec/units/filesystem/project_paths_spec.rb +147 -0
  229. data/spec/units/filesystem/working_dir_spec.rb +71 -0
  230. data/spec/units/generators/generator_spec.rb +12 -6
  231. data/spec/units/generators/generator_test_results_backtrace_spec.rb +50 -46
  232. data/spec/units/generators/generator_test_results_spec.rb +1 -1
  233. data/spec/units/handoff_spec.rb +205 -0
  234. data/spec/units/includes/include_factory_spec.rb +3 -3
  235. data/spec/units/includes/include_pathinator_spec.rb +46 -0
  236. data/spec/units/installation_spec.rb +228 -0
  237. data/spec/units/library_resolver_spec.rb +157 -0
  238. data/spec/units/mock_locator_spec.rb +76 -1
  239. data/spec/units/partials/partializer_config_spec.rb +7 -0
  240. data/spec/units/partials/partializer_spec.rb +1 -0
  241. data/spec/units/partials_manager_spec.rb +17 -0
  242. data/spec/units/plugins/bullseye_spec.rb +15 -2
  243. data/spec/units/plugins/console_reportinator_spec.rb +18 -20
  244. data/spec/units/plugins/dependencies_spec.rb +33 -7
  245. data/spec/units/plugins/dependency_spec_spec.rb +17 -0
  246. data/spec/units/plugins/gcov_spec.rb +28 -3
  247. data/spec/units/plugins/gcovr_reportinator_spec.rb +19 -47
  248. data/spec/units/plugins/gcovr_thresholds_spec.rb +95 -0
  249. data/spec/units/plugins/module_generator_spec.rb +5 -5
  250. data/spec/units/plugins/report_build_warnings_log_spec.rb +3 -3
  251. data/spec/units/plugins/report_log_writer_plugin_spec.rb +10 -1
  252. data/spec/units/plugins/report_tests_raw_output_log_spec.rb +13 -2
  253. data/spec/units/plugins/report_tests_teamcity_stdout_spec.rb +77 -3
  254. data/spec/units/plugins/reportgenerator_reportinator_spec.rb +1 -1
  255. data/spec/units/plugins/sanitize_records_spec.rb +3 -1
  256. data/spec/units/plugins/sanitize_spec.rb +1 -1
  257. data/spec/units/plugins/valgrind_spec.rb +23 -8
  258. data/spec/units/preprocess/preprocessinator_comment_stripper_spec.rb +1 -1
  259. data/spec/units/rake_app/rakefile_component_resolver_spec.rb +21 -0
  260. data/spec/units/release_build_executor_spec.rb +53 -14
  261. data/spec/units/release_build_planner_spec.rb +15 -3
  262. data/spec/units/reportinator_spec.rb +5 -5
  263. data/spec/units/standin_headerinator_spec.rb +31 -1
  264. data/spec/units/test_build_executor_spec.rb +65 -3
  265. data/spec/units/test_build_planner_spec.rb +104 -2
  266. data/spec/units/test_build_setup_spec.rb +96 -12
  267. data/spec/units/test_context_extractor_spec.rb +25 -0
  268. data/spec/units/test_file_preprocessinator_spec.rb +17 -1
  269. data/spec/units/test_includes_extractinator_spec.rb +5 -1
  270. data/spec/units/test_invoker/objects_wiring_spec.rb +6 -3
  271. data/spec/units/test_invoker_spec.rb +14 -1
  272. data/spec/units/test_source_file_directive_resolver_spec.rb +38 -7
  273. data/spec/units/tool_executor_spec.rb +26 -0
  274. data/spec/units/yaml_wrapper_spec.rb +11 -0
  275. metadata +109 -25
  276. data/lib/ceedling/file_path_collection_utils.rb +0 -164
@@ -0,0 +1,171 @@
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/constants'
12
+ require 'launchinator'
13
+ require 'app_cfg'
14
+
15
+ describe Launchinator do
16
+ before(:each) do
17
+ @selector = double('installation_selector')
18
+ @loginator = double('loginator').as_null_object
19
+ @app_cfg = CeedlingAppConfig.new( argv: ['test:all', '--verbosity=obnoxious'] )
20
+ @launcher = Installation.new( @app_cfg[:launcher_root_path] )
21
+
22
+ @launchinator = described_class.new({
23
+ :installation_selector => @selector,
24
+ :loginator => @loginator,
25
+ })
26
+
27
+ allow(Handoff).to receive(:exec)
28
+ end
29
+
30
+ def select(installation)
31
+ allow(@selector).to receive(:select) do |app_cfg:, **|
32
+ app_cfg.set_paths( installation.root )
33
+ installation
34
+ end
35
+ end
36
+
37
+ describe '#resolve' do
38
+ it 'selects which Ceedling without handing off' do
39
+ Dir.mktmpdir do |other|
40
+ select( Installation.new( other ) )
41
+
42
+ expect(@launchinator.resolve( env: {}, app_cfg: @app_cfg )).to eq( Installation.new( other ) )
43
+ expect(Handoff).to_not have_received(:exec)
44
+ end
45
+ end
46
+
47
+ it 'passes the configuration and vendor detection through to selection' do
48
+ select( @launcher )
49
+ config = {:project => {}}
50
+
51
+ @launchinator.resolve( env: {'X' => '1'}, app_cfg: @app_cfg, config: config, detect_vendor: false )
52
+
53
+ expect(@selector).to have_received(:select).with( env: {'X' => '1'}, config: config, app_cfg: @app_cfg, detect_vendor: false )
54
+ end
55
+ end
56
+
57
+ describe '#proceed' do
58
+ it 'hands off to an already selected installation without selecting again' do
59
+ Dir.mktmpdir do |other|
60
+ target = Installation.new( other )
61
+ FileUtils.mkdir_p( File.dirname( target.bin_path ) )
62
+ FileUtils.touch( target.bin_path )
63
+
64
+ expect(@selector).to_not receive(:select)
65
+
66
+ @launchinator.proceed( target: target, app_cfg: @app_cfg )
67
+
68
+ expect(Handoff).to have_received(:exec).with( target: target, launcher: @launcher, argv: @app_cfg[:argv], loginator: @loginator )
69
+ end
70
+ end
71
+
72
+ it 'returns the rakefile of the launcher\'s own installation' do
73
+ expect(@launchinator.proceed( target: @launcher, app_cfg: @app_cfg )).to eq( @launcher.rakefile_path )
74
+ end
75
+ end
76
+
77
+ describe '#launch' do
78
+ it 'continues in-process and returns the rakefile when the launcher\'s own installation is selected' do
79
+ select( @launcher )
80
+
81
+ expect(@launchinator.launch( env: {}, app_cfg: @app_cfg )).to eq( @launcher.rakefile_path )
82
+ expect(Handoff).to_not have_received(:exec)
83
+ expect(@loginator).to_not have_received(:log)
84
+ end
85
+
86
+ # GH #1365: another installation once ran inside this launcher's process
87
+ it 'hands off to another installation with the original command line, after saying so' do
88
+ Dir.mktmpdir do |other|
89
+ target = Installation.new( other )
90
+ FileUtils.mkdir_p( File.dirname( target.bin_path ) )
91
+ FileUtils.touch( target.bin_path )
92
+ select( target )
93
+
94
+ expect(@loginator).to receive(:log).with(
95
+ Handoff.handing_off_message( launcher: @launcher, target: target ), Verbosity::COMPLAIN, LogLabels::NOTICE
96
+ ).ordered
97
+ expect(Handoff).to receive(:exec).with(
98
+ target: target, launcher: @launcher, argv: ['test:all', '--verbosity=obnoxious'], loginator: @loginator
99
+ ).ordered
100
+
101
+ @launchinator.launch( env: {}, app_cfg: @app_cfg )
102
+ end
103
+ end
104
+
105
+ it 'raises rather than hand off to an installation with no launcher' do
106
+ Dir.mktmpdir do |other|
107
+ select( Installation.new( other ) )
108
+
109
+ expect {
110
+ @launchinator.launch( env: {}, app_cfg: @app_cfg )
111
+ }.to raise_error( CeedlingException, /#{Regexp.escape( Installation.new( other ).bin_path )}/ )
112
+ expect(Handoff).to_not have_received(:exec)
113
+ end
114
+ end
115
+
116
+ # GH #1365: such a copy only ever ran inside another launcher's process
117
+ it 'stops with advice to upgrade rather than hand off to a copy vendored without its built-in mixins' do
118
+ Dir.mktmpdir do |other|
119
+ target = Installation.new( other )
120
+ FileUtils.mkdir_p( File.dirname( target.bin_path ) )
121
+ FileUtils.touch( target.bin_path )
122
+ File.write( File.join( other, 'bin', 'mixins.rb' ), "BUILTIN_MIXIN_LOAD_PATHS = []\n" )
123
+ select( target )
124
+
125
+ expect {
126
+ @launchinator.launch( env: {}, app_cfg: @app_cfg )
127
+ }.to raise_error( CeedlingException, /#{Regexp.escape( target.describe )} cannot run on its own.*ceedling upgrade/m )
128
+ expect(Handoff).to_not have_received(:exec)
129
+ end
130
+ end
131
+
132
+ context 'in a process another launcher handed off to' do
133
+ before(:each) do
134
+ @app_cfg.set_handoff( {launcher: '/usr/lib/gems/ceedling-1.2.3', target: @launcher.root} )
135
+ end
136
+
137
+ it 'says where it was launched from and continues in-process' do
138
+ select( @launcher )
139
+
140
+ expect(@loginator).to receive(:log).with(
141
+ Handoff.received_message( @app_cfg[:handoff], own: @launcher ), Verbosity::COMPLAIN, LogLabels::NOTICE
142
+ )
143
+
144
+ expect(@launchinator.launch( env: {}, app_cfg: @app_cfg )).to eq( @launcher.rakefile_path )
145
+ expect(Handoff).to_not have_received(:exec)
146
+ end
147
+
148
+ it 'never hands off again, even when another installation is selected' do
149
+ Dir.mktmpdir do |other|
150
+ select( Installation.new( other ) )
151
+
152
+ expect(@launchinator.launch( env: {}, app_cfg: @app_cfg )).to eq( Installation.new( other ).rakefile_path )
153
+ expect(Handoff).to_not have_received(:exec)
154
+ end
155
+ end
156
+ end
157
+
158
+ it 'ignores markers naming another installation as the target' do
159
+ Dir.mktmpdir do |other|
160
+ FileUtils.mkdir_p( File.join( other, 'bin' ) )
161
+ FileUtils.touch( File.join( other, 'bin', 'ceedling' ) )
162
+ @app_cfg.set_handoff( {launcher: '/gem', target: '/somewhere/else'} )
163
+ select( Installation.new( other ) )
164
+
165
+ @launchinator.launch( env: {}, app_cfg: @app_cfg )
166
+
167
+ expect(Handoff).to have_received(:exec)
168
+ end
169
+ end
170
+ end
171
+ end
@@ -94,6 +94,16 @@ describe PathValidator do
94
94
  it 'passes nil and empty arguments through unchanged, without raising' do
95
95
  expect(@path_validator.standardize_paths( nil, '' )).to eq( [nil, ''] )
96
96
  end
97
+
98
+ # The path handling audit around GH #1370: a path bin/ takes in reads as lib/ reads one
99
+ # A destination of only spaces stays the relative name it was, never the filesystem root
100
+ it 'passes a path of only whitespace through unchanged' do
101
+ expect(@path_validator.standardize_paths( ' ' )).to eq( [' '] )
102
+ end
103
+
104
+ it 'reads `~` as the home directory and drops a trailing separator' do
105
+ expect(@path_validator.standardize_paths( '~/mixins/clang.yml', 'mixins\\' )).to eq( [File.join( Dir.home, 'mixins/clang.yml' ), 'mixins'] )
106
+ end
97
107
  end
98
108
 
99
109
  describe '#filepath?' do
@@ -11,8 +11,7 @@ require 'fileutils'
11
11
 
12
12
  # versionator.rb's bare `require 'exceptions'`/`require 'constants'` statements only
13
13
  # resolve when lib/ceedling/ is directly on the load path -- true in the real
14
- # bin/ceedling bootstrap but not in this spec harness's load path setup. `require
15
- # 'version'` similarly needs lib/ on the load path.
14
+ # bin/ceedling bootstrap but not in this spec harness's load path setup.
16
15
  here = File.dirname(__FILE__)
17
16
  $: << File.join(here, '../../../lib/ceedling')
18
17
  $: << File.join(here, '../../../lib')
@@ -35,30 +34,60 @@ describe Versionator do
35
34
  HEADER
36
35
  end
37
36
 
37
+ # Each fixture root is its own installation with its own lib/version.rb
38
+ def write_version(root, base)
39
+ FileUtils.mkdir_p( File.join( root, 'lib' ) )
40
+ File.write( File.join( root, 'lib', 'version.rb' ), <<~RUBY )
41
+ module Ceedling
42
+ module Version
43
+ BASE = '#{base}'
44
+ DEV = ''
45
+ GEM = BASE
46
+ TAG = GEM
47
+ end
48
+ end
49
+ RUBY
50
+ end
51
+
38
52
  describe 'Ceedling tag and build string' do
39
- it 'sets the Ceedling tag from the Version module' do
53
+ # GH #1365: the tag once came from whichever installation's constant loaded first
54
+ it 'sets the Ceedling tag from the installation\'s own lib/version.rb' do
40
55
  Dir.mktmpdir do |root|
56
+ write_version( root, '1.2.0' )
57
+ stub_const( 'Ceedling::Version::TAG', '9.9.9' )
58
+
41
59
  versionator = described_class.new( root )
42
60
 
43
- expect(versionator.ceedling_tag).to eq( Ceedling::Version::TAG )
61
+ expect(versionator.ceedling_tag).to eq( '1.2.0' )
62
+ end
63
+ end
64
+
65
+ it 'raises a CeedlingException naming the file when the installation has no version' do
66
+ Dir.mktmpdir do |root|
67
+ expect {
68
+ described_class.new( root )
69
+ }.to raise_error( CeedlingException, /#{Regexp.escape( File.join( File.expand_path( root ), 'lib', 'version.rb' ) )}/ )
44
70
  end
45
71
  end
46
72
 
47
73
  it 'builds without a commit SHA suffix when no SHA file is present' do
48
74
  Dir.mktmpdir do |root|
75
+ write_version( root, '1.2.0' )
76
+
49
77
  versionator = described_class.new( root )
50
78
 
51
- expect(versionator.ceedling_build).to eq( Ceedling::Version::TAG )
79
+ expect(versionator.ceedling_build).to eq( '1.2.0' )
52
80
  end
53
81
  end
54
82
 
55
83
  it 'appends the commit SHA to the build string when the SHA file is present' do
56
84
  Dir.mktmpdir do |root|
85
+ write_version( root, '1.2.0' )
57
86
  File.write( File.join( root, GIT_COMMIT_SHA_FILENAME ), "abc1234\n" )
58
87
 
59
88
  versionator = described_class.new( root )
60
89
 
61
- expect(versionator.ceedling_build).to eq( "#{Ceedling::Version::TAG}-abc1234" )
90
+ expect(versionator.ceedling_build).to eq( '1.2.0-abc1234' )
62
91
  end
63
92
  end
64
93
  end
@@ -66,6 +95,7 @@ describe Versionator do
66
95
  describe 'framework version gathering' do
67
96
  it 'skips framework tags entirely when no vendor path is given' do
68
97
  Dir.mktmpdir do |root|
98
+ write_version( root, '1.2.0' )
69
99
  versionator = described_class.new( root )
70
100
 
71
101
  expect(versionator.unity_tag).to be_nil
@@ -76,6 +106,7 @@ describe Versionator do
76
106
 
77
107
  it 'parses version tags out of each vendored framework header' do
78
108
  Dir.mktmpdir do |root|
109
+ write_version( root, '1.2.0' )
79
110
  Dir.mktmpdir do |vendor|
80
111
  write_version_header( vendor, 'unity', File.join('src', 'unity.h'), major: 2, minor: 7, build: 1 )
81
112
  write_version_header( vendor, 'cmock', File.join('src', 'cmock.h'), major: 2, minor: 7, build: 0 )
@@ -92,6 +123,7 @@ describe Versionator do
92
123
 
93
124
  it 'raises a CeedlingException when a framework header cannot be read' do
94
125
  Dir.mktmpdir do |root|
126
+ write_version( root, '1.2.0' )
95
127
  Dir.mktmpdir do |vendor|
96
128
  # No headers written -- vendor is empty, so every read fails.
97
129
  expect {
@@ -0,0 +1,57 @@
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 'ceedling/build_log_writer'
11
+ require 'ceedling/filesystem/file_wrapper'
12
+
13
+ describe BuildLogWriter do
14
+ let(:file_wrapper) { double('file_wrapper') }
15
+ let(:writer) { described_class.new( file_wrapper: file_wrapper ) }
16
+
17
+ before(:each) do
18
+ allow(file_wrapper).to receive(:mkdir_for) { |path| path }
19
+ allow(file_wrapper).to receive(:write)
20
+ end
21
+
22
+ it "replaces an earlier build's log with this build's first entry" do
23
+ writer.write( 'logs/test/test/test_foo/test_a.gdb.log', "first\n" )
24
+
25
+ expect(file_wrapper).to have_received(:mkdir_for).with( 'logs/test/test/test_foo/test_a.gdb.log' )
26
+ expect(file_wrapper).to have_received(:write).with( 'logs/test/test/test_foo/test_a.gdb.log', "first\n", 'w' )
27
+ end
28
+
29
+ it 'appends later entries in the same build, after the separator' do
30
+ writer.write( 'a.log', 'one', separator: "\n" )
31
+ writer.write( 'a.log', 'two', separator: "\n" )
32
+
33
+ expect(file_wrapper).to have_received(:write).with( 'a.log', 'one', 'w' ).ordered
34
+ expect(file_wrapper).to have_received(:write).with( 'a.log', "\ntwo", 'a' ).ordered
35
+ end
36
+
37
+ it 'replaces each log separately' do
38
+ writer.write( 'a.log', 'one' )
39
+ writer.write( 'b.log', 'two' )
40
+
41
+ expect(file_wrapper).to have_received(:write).with( 'a.log', 'one', 'w' )
42
+ expect(file_wrapper).to have_received(:write).with( 'b.log', 'two', 'w' )
43
+ end
44
+
45
+ it 'keeps every entry when build threads write one log at once' do
46
+ Dir.mktmpdir do |dir|
47
+ loginator = double( 'loginator', log: nil )
48
+ real = described_class.new( file_wrapper: FileWrapper.new( loginator: loginator, verbosinator: double( 'verbosinator', should_output?: false ) ) )
49
+ log = File.join( dir, 'test', 'unit', 'test_foo.log' )
50
+
51
+ threads = Array.new( 8 ) { |index| Thread.new { real.write( log, "entry #{index}\n" ) } }
52
+ threads.each( &:join )
53
+
54
+ expect( File.readlines( log ).map( &:chomp ) ).to match_array( Array.new( 8 ) { |index| "entry #{index}" } )
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,61 @@
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/config/build_root_policy'
12
+
13
+ # The path handling audit around GH #1370: clobber empties the build root's test and release
14
+ # trees, so a build root holding the project's own files is refused however it is spelled
15
+ describe BuildRootPolicy do
16
+ around(:each) do |example|
17
+ Dir.mktmpdir do |dir|
18
+ @ws = File.realpath( dir )
19
+ FileUtils.mkdir_p( File.join( @ws, 'proj', 'src' ) )
20
+ Dir.chdir( File.join( @ws, 'proj' ) ) { example.run }
21
+ end
22
+ end
23
+
24
+ it 'accepts a build root of its own' do
25
+ expect(BuildRootPolicy.problem( 'build' )).to be_nil
26
+ end
27
+
28
+ # macOS spells /tmp/proj as /private/tmp/proj, and a project reached through any symlink
29
+ # has two spellings
30
+ it 'refuses the project directory or a directory above it, but no directory below it, spelled through a symlink', unless: Gem.win_platform? do
31
+ File.symlink( File.join( @ws, 'proj' ), File.join( @ws, 'link' ) )
32
+
33
+ expect(BuildRootPolicy.problem( File.join( @ws, 'link' ) )).to eq( 'is the project directory or holds it' )
34
+ expect(BuildRootPolicy.problem( File.join( @ws, 'link', 'src' ) )).to be_nil
35
+ end
36
+
37
+ it 'names each :paths and :files entry that adds to a build from within the build root' do
38
+ config = { paths: { source: ['src/**', 'build/gen/**', '-:build/old'] }, files: { include: ['+:build/gen/table.h'] } }
39
+
40
+ expect(BuildRootPolicy.entries_within( 'build', config )).to eq( [[:paths, :source, 'build/gen/**'], [:files, :include, '+:build/gen/table.h']] )
41
+ expect(BuildRootPolicy.entries_within( 'out', config )).to be_empty
42
+ end
43
+
44
+ it 'names the directories Ceedling and its enabled plugins create' do
45
+ config = {
46
+ project_build_root: 'build', project_build_artifacts_root: 'build/artifacts', project_build_tests_root: 'build/test',
47
+ project_build_release_root: 'build/release', project_build_vendor_root: 'build/vendor',
48
+ project_build_dependencies_cache_path: 'build/cache', project_log_path: 'build/logs', cmock_mock_path: 'mocks',
49
+ plugins_enabled: ['gcov', 'report_tests_pretty_stdout']
50
+ }
51
+
52
+ expect(BuildRootPolicy.reserved( config )).to contain_exactly(
53
+ 'build/artifacts', 'build/test', 'build/release', 'build/vendor', 'build/cache', 'build/logs', 'mocks', 'build/gcov', 'build/report_tests_pretty_stdout'
54
+ )
55
+ end
56
+
57
+ # An empty path would name the project directory itself
58
+ it 'names no directory for a setting with no path' do
59
+ expect(BuildRootPolicy.reserved( { project_log_path: '', plugins_enabled: ['gcov'] } )).to be_empty
60
+ end
61
+ end
@@ -80,16 +80,14 @@ describe ConfiguratorBuilder do
80
80
  class RecordingFileList
81
81
  include Enumerable
82
82
 
83
- attr_reader :patterns, :excluded
83
+ attr_reader :patterns
84
84
 
85
85
  def initialize(found = [])
86
86
  @found = found
87
87
  @patterns = []
88
- @excluded = []
89
88
  end
90
89
 
91
90
  def include(*patterns) = @patterns.concat( patterns )
92
- def exclude(*files) = @excluded.concat( files )
93
91
  def resolve() = self
94
92
  def include?(file) = @found.include?( file )
95
93
  def each(&block) = @found.each( &block )
@@ -202,6 +200,17 @@ describe ConfiguratorBuilder do
202
200
  project_release_build_target: 'build/release/app.elf', project_release_build_map: 'build/release/app.map'
203
201
  )
204
202
  end
203
+
204
+ # The path handling audit around GH #1370: an absolute output names the release itself
205
+ it 'places a target named by an absolute or `~` path where it names, with its map beside it' do
206
+ output = File.expand_path( '/elsewhere/out/app.elf' )
207
+ expect(@builder.set_release_target( in_hash.merge( release_build_output: output ) )).to eq(
208
+ project_release_build_target: output, project_release_build_map: output.ext( '.map' )
209
+ )
210
+
211
+ expect(@builder.set_release_target( in_hash.merge( release_build_output: '~/out/app.elf' ) )[:project_release_build_target])
212
+ .to eq( File.join( Dir.home, 'out/app.elf' ) )
213
+ end
205
214
  end
206
215
 
207
216
  describe '#set_build_thread_counts' do
@@ -329,16 +338,38 @@ describe ConfiguratorBuilder do
329
338
  expect(revisions).to eq( ['+:a.s'] )
330
339
  end
331
340
 
332
- it 'collects sources, filtering out tests that overlapping paths also matched' do
333
- result, = collect( ['src/a.c', 'src/test_a.c'] ) { @builder.collect_source( in_hash, ['src/test_a.c'] ) }
341
+ it 'collects sources from source paths and revises them by :files ↳ :source' do
342
+ result, = collect { @builder.collect_source( in_hash, [] ) }
334
343
  file_list, revisions = result[:collection_all_source]
335
344
 
336
345
  expect(file_list.patterns).to eq( ['src/*.c'] )
337
- expect(file_list.excluded).to eq( ['src/test_a.c'] )
338
346
  expect(revisions).to eq( ['-:src/skip.c'] )
347
+ expect(@loginator).to_not have_received(:log)
348
+ end
349
+
350
+ # A test reaches the sources through overlapping paths, or a :files revision
351
+ it 'filters out of the revised sources any test, warning of the overlap' do
352
+ allow(@file_wrapper).to receive(:instantiate_file_list_literal) { |files| RecordingFileList.new( files ) }
353
+ result, = collect do
354
+ allow(@collection_utils).to receive(:revise_filelist).and_return( ['src/a.c', 'src/test_a.c'] )
355
+ @builder.collect_source( in_hash, ['src/test_a.c'] )
356
+ end
357
+
358
+ expect(result[:collection_all_source].to_a).to eq( ['src/a.c'] )
339
359
  expect(@loginator).to have_received(:log).with(/overlap/, Verbosity::COMPLAIN)
340
360
  end
341
361
 
362
+ it 'filters any test out of the release input, without warning again' do
363
+ allow(@file_wrapper).to receive(:instantiate_file_list_literal) { |files| RecordingFileList.new( files ) }
364
+ result, = collect do
365
+ allow(@collection_utils).to receive(:revise_filelist).and_return( ['src/a.c', 'test/test_a.c'] )
366
+ @builder.collect_release_build_input( in_hash.merge( collection_all_tests: ['test/test_a.c'] ) )
367
+ end
368
+
369
+ expect(result[:collection_release_build_input].to_a).to eq( ['src/a.c'] )
370
+ expect(@loginator).to_not have_received(:log)
371
+ end
372
+
342
373
  it 'collects headers from test, support, and include paths' do
343
374
  result, = collect { @builder.collect_headers( in_hash ) }
344
375