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,228 @@
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/installation'
12
+
13
+ describe Installation do
14
+ # Each 1.x release shape of lib/version.rb, as published (stamped DEV) or built locally
15
+ VERSION_1_1 = <<~RUBY
16
+ module Ceedling
17
+ module Version
18
+ GEM = '1.1.10'
19
+ TAG = GEM
20
+ puts( TAG ) if (__FILE__ == $0)
21
+ end
22
+ end
23
+ RUBY
24
+
25
+ VERSION_1_2 = <<~RUBY
26
+ module Ceedling
27
+ module Version
28
+ BASE = '1.2.0'
29
+ DEV = '.dev'
30
+ GEM = BASE.end_with?( DEV ) ? BASE : "\#{BASE}\#{DEV}"
31
+ TAG = GEM
32
+ puts( TAG ) if (__FILE__ == $0)
33
+ end
34
+ end
35
+ RUBY
36
+
37
+ def write_version(root, text)
38
+ FileUtils.mkdir_p( File.join( root, 'lib' ) )
39
+ File.write( File.join( root, 'lib', 'version.rb' ), text )
40
+ end
41
+
42
+ describe '#version' do
43
+ it 'reads the GEM/TAG format of 1.0 and 1.1' do
44
+ Dir.mktmpdir do |root|
45
+ write_version( root, VERSION_1_1 )
46
+
47
+ expect(described_class.new( root ).version).to eq( '1.1.10' )
48
+ end
49
+ end
50
+
51
+ it 'reads the BASE/DEV format of 1.2 for a local build' do
52
+ Dir.mktmpdir do |root|
53
+ write_version( root, VERSION_1_2 )
54
+
55
+ expect(described_class.new( root ).version).to eq( '1.2.0.dev' )
56
+ end
57
+ end
58
+
59
+ it 'reads a release whose pipeline emptied DEV' do
60
+ Dir.mktmpdir do |root|
61
+ write_version( root, VERSION_1_2.sub( "DEV = '.dev'", "DEV = ''" ) )
62
+
63
+ expect(described_class.new( root ).version).to eq( '1.2.0' )
64
+ end
65
+ end
66
+
67
+ # GH #1365: the loaded constant belongs to whichever installation loaded first
68
+ it 'ignores the Ceedling::Version already loaded and leaves it untouched' do
69
+ Dir.mktmpdir do |root|
70
+ write_version( root, VERSION_1_1 )
71
+ stub_const( 'Ceedling::Version::TAG', '9.9.9' )
72
+
73
+ expect(described_class.new( root ).version).to eq( '1.1.10' )
74
+ expect(Ceedling::Version::TAG).to eq( '9.9.9' )
75
+ end
76
+ end
77
+
78
+ it 'is nil when the installation has no lib/version.rb' do
79
+ Dir.mktmpdir do |root|
80
+ expect(described_class.new( root ).version).to be_nil
81
+ end
82
+ end
83
+
84
+ it 'is nil when lib/version.rb defines no Ceedling::Version::TAG' do
85
+ Dir.mktmpdir do |root|
86
+ write_version( root, "module Other; end\n" )
87
+
88
+ expect(described_class.new( root ).version).to be_nil
89
+ end
90
+ end
91
+
92
+ it 'is nil when lib/version.rb cannot be evaluated' do
93
+ Dir.mktmpdir do |root|
94
+ write_version( root, "module Ceedling\n" )
95
+
96
+ expect(described_class.new( root ).version).to be_nil
97
+ end
98
+ end
99
+ end
100
+
101
+ describe 'paths' do
102
+ it 'expands its root and derives the launcher and rakefile beneath it' do
103
+ Dir.mktmpdir do |root|
104
+ installation = described_class.new( File.join( root, 'x', '..' ) )
105
+
106
+ expect(installation.root).to eq( File.expand_path( root ) )
107
+ expect(installation.bin_path).to eq( File.join( File.expand_path( root ), 'bin', 'ceedling' ) )
108
+ expect(installation.rakefile_path).to eq( File.join( File.expand_path( root ), 'lib', 'ceedling', 'rakefile.rb' ) )
109
+ end
110
+ end
111
+ end
112
+
113
+ describe '#==' do
114
+ it 'treats a symlinked path and a trailing slash as the same installation' do
115
+ Dir.mktmpdir do |dir|
116
+ real = File.join( dir, 'real' )
117
+ link = File.join( dir, 'link' )
118
+ FileUtils.mkdir_p( real )
119
+ File.symlink( real, link )
120
+
121
+ expect(described_class.new( link )).to eq( described_class.new( real + '/' ) )
122
+ end
123
+ end
124
+
125
+ it 'distinguishes different directories' do
126
+ Dir.mktmpdir do |a|
127
+ Dir.mktmpdir do |b|
128
+ expect(described_class.new( a )).not_to eq( described_class.new( b ) )
129
+ end
130
+ end
131
+ end
132
+
133
+ it 'compares a path that does not exist by its expanded form' do
134
+ expect(described_class.new( '/no/such/ceedling' )).to eq( described_class.new( '/no/such/ceedling/' ) )
135
+ expect(described_class.new( '/no/such/ceedling' )).not_to eq( described_class.new( '/no/such/other' ) )
136
+ end
137
+
138
+ it 'ignores case on Windows only' do
139
+ a = described_class.new( '/no/such/Ceedling' )
140
+ b = described_class.new( '/no/such/ceedling' )
141
+
142
+ allow(described_class).to receive(:windows?).and_return( true )
143
+ expect(a).to eq( b )
144
+
145
+ allow(described_class).to receive(:windows?).and_return( false )
146
+ expect(a).not_to eq( b )
147
+ end
148
+
149
+ it 'is never equal to something other than an Installation' do
150
+ expect(described_class.new( '/no/such/ceedling' )).not_to eq( '/no/such/ceedling' )
151
+ end
152
+ end
153
+
154
+ # GH #1365: copies vendored by 1.1.0 through 1.2.1 lack the built-in mixins their own launcher validates
155
+ describe '#missing_builtin_mixins?' do
156
+ def write_mixins_rb(root, text)
157
+ FileUtils.mkdir_p( File.join( root, 'bin' ) )
158
+ File.write( File.join( root, 'bin', 'mixins.rb' ), text )
159
+ end
160
+
161
+ BUILTIN = "BUILTIN_MIXIN_LOAD_PATHS = [ File.join( _vendor, UNITY_ROOT_PATH, 'test', 'targets' ) ].freeze\n"
162
+
163
+ it 'is true when the launcher validates built-in mixins the installation does not hold' do
164
+ Dir.mktmpdir do |root|
165
+ write_mixins_rb( root, BUILTIN )
166
+
167
+ expect(described_class.new( root ).missing_builtin_mixins?).to be( true )
168
+ end
169
+ end
170
+
171
+ it 'is false when the installation holds its built-in mixins' do
172
+ Dir.mktmpdir do |root|
173
+ write_mixins_rb( root, BUILTIN )
174
+ FileUtils.mkdir_p( File.join( root, 'vendor', 'unity', 'test', 'targets' ) )
175
+
176
+ expect(described_class.new( root ).missing_builtin_mixins?).to be( false )
177
+ end
178
+ end
179
+
180
+ it 'is false for a launcher with no built-in mixins, as before 1.1.0' do
181
+ Dir.mktmpdir do |root|
182
+ write_mixins_rb( root, "BUILTIN_MIXINS = {}\n" )
183
+
184
+ expect(described_class.new( root ).missing_builtin_mixins?).to be( false )
185
+ end
186
+ end
187
+
188
+ it 'is false for an installation with no bin/mixins.rb' do
189
+ Dir.mktmpdir do |root|
190
+ expect(described_class.new( root ).missing_builtin_mixins?).to be( false )
191
+ end
192
+ end
193
+ end
194
+
195
+ describe '#name' do
196
+ it 'is the noun and version, or the noun alone when the version cannot be read' do
197
+ Dir.mktmpdir do |root|
198
+ expect(described_class.new( root ).name).to eq( 'Ceedling' )
199
+
200
+ write_version( root, VERSION_1_1 )
201
+ expect(described_class.new( root ).name).to eq( 'Ceedling 1.1.10' )
202
+ expect(described_class.new( root ).name( 'Ceedling launcher' )).to eq( 'Ceedling launcher 1.1.10' )
203
+ end
204
+ end
205
+ end
206
+
207
+ describe '#describe' do
208
+ it 'names the version and root' do
209
+ Dir.mktmpdir do |root|
210
+ write_version( root, VERSION_1_1 )
211
+
212
+ expect(described_class.new( root ).describe).to eq( "Ceedling 1.1.10 at #{File.expand_path( root )}/" )
213
+ end
214
+ end
215
+
216
+ it 'leaves out a version it cannot read' do
217
+ Dir.mktmpdir do |root|
218
+ expect(described_class.new( root ).describe).to eq( "Ceedling at #{File.expand_path( root )}/" )
219
+ end
220
+ end
221
+
222
+ it 'takes a different leading noun' do
223
+ Dir.mktmpdir do |root|
224
+ expect(described_class.new( root ).describe( 'Ceedling launcher' )).to eq( "Ceedling launcher at #{File.expand_path( root )}/" )
225
+ end
226
+ end
227
+ end
228
+ end
@@ -0,0 +1,157 @@
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/file_wrapper'
12
+ require 'ceedling/filesystem/file_path_collection_utils'
13
+ require 'ceedling/filename_extension'
14
+ require 'ceedling/library_resolver'
15
+ require 'ceedling/defaults'
16
+
17
+ # GH #1368: a link tracked its libraries only by their -l and -L arguments, so a library
18
+ # rebuilt under the same name relinked nothing. The resolver finds the files they name.
19
+ describe LibraryResolver do
20
+ around(:each) do |example|
21
+ Dir.mktmpdir do |dir|
22
+ Dir.chdir( dir ) { example.run }
23
+ end
24
+ end
25
+
26
+ before(:each) do
27
+ stub_const( 'EXTENSION_LIBRARIES', FilenameExtension.new( ['.a', '.so'] ) )
28
+
29
+ file_wrapper = FileWrapper.new( {:loginator => double('loginator').as_null_object, :verbosinator => double('verbosinator').as_null_object} )
30
+ @resolver = described_class.new( {
31
+ :file_wrapper => file_wrapper,
32
+ :file_path_collection_utils => FilePathCollectionUtils.new( {:file_wrapper => file_wrapper} )
33
+ } )
34
+ end
35
+
36
+ def make(*files)
37
+ files.each { |file| FileUtils.mkdir_p( File.dirname( file ) ); File.write( file, '' ) }
38
+ end
39
+
40
+ def resolve(entries, search_paths: ['vendor/lib'], files: [])
41
+ @resolver.resolve( entries: entries, search_paths: search_paths, files: files )
42
+ end
43
+
44
+ it 'finds a bare name as a static or a shared library on the search paths' do
45
+ make( 'vendor/lib/libx.a', 'vendor/lib/liby.so' )
46
+
47
+ expect( resolve( ['x', 'y'] ) ).to eq( ['vendor/lib/libx.a', 'vendor/lib/liby.so'] )
48
+ end
49
+
50
+ it 'finds a bare name with the extensions toolchains add, and without the lib prefix' do
51
+ make( 'vendor/lib/libmac.dylib', 'vendor/lib/libmingw.dll.a', 'vendor/lib/msvc.lib' )
52
+
53
+ expect( resolve( ['mac', 'mingw', 'msvc'] ) ).to eq( ['vendor/lib/libmac.dylib', 'vendor/lib/libmingw.dll.a', 'vendor/lib/msvc.lib'] )
54
+ end
55
+
56
+ it 'finds the exact filename an `-l:` entry names' do
57
+ make( 'vendor/lib/libexact.so.1' )
58
+
59
+ expect( resolve( [':libexact.so.1'] ) ).to eq( ['vendor/lib/libexact.so.1'] )
60
+ end
61
+
62
+ it 'finds a path as given, or on the search paths' do
63
+ make( 'prebuilt/libp.a', 'vendor/lib/sub/libq.a' )
64
+
65
+ expect( resolve( ['prebuilt/libp.a', 'sub/libq.a'] ) ).to eq( ['prebuilt/libp.a', 'vendor/lib/sub/libq.a'] )
66
+ end
67
+
68
+ it 'finds an absolute path as given' do
69
+ make( 'abs/libz.a' )
70
+ absolute = File.expand_path( 'abs/libz.a' )
71
+
72
+ expect( resolve( [absolute] ) ).to eq( ['abs/libz.a'] )
73
+ end
74
+
75
+ it 'finds a name in every search path that holds it, since which one links is the toolchain\'s choice' do
76
+ make( 'one/libdup.a', 'two/libdup.a' )
77
+
78
+ expect( resolve( ['dup'], search_paths: ['one', 'two'] ) ).to eq( ['one/libdup.a', 'two/libdup.a'] )
79
+ end
80
+
81
+ it 'expands decorated and globbed search paths' do
82
+ make( 'deps/a/liba.a', 'deps/b/libb.a', 'deps/skip/libs.a' )
83
+
84
+ expect( resolve( ['a', 'b', 's'], search_paths: ['+:deps/**', '-:deps/skip'] ) ).to eq( ['deps/a/liba.a', 'deps/b/libb.a'] )
85
+ end
86
+
87
+ it 'finds nothing for a library only the toolchain\'s own search paths hold, so it never reads as changed' do
88
+ expect( resolve( ['m', 'missing.a', ':libnone.so'] ) ).to eq( [] )
89
+ end
90
+
91
+ it 'adds the existing files given directly, once each' do
92
+ make( 'vendor/lib/libx.a', 'build/deps/libfusion.so.1' )
93
+
94
+ expect( resolve( ['x'], files: ['build/deps/libfusion.so.1', 'build/deps/absent.a', 'vendor/lib/libx.a'] ) ).to eq(
95
+ ['vendor/lib/libx.a', 'build/deps/libfusion.so.1']
96
+ )
97
+ end
98
+
99
+ describe '#link_files' do
100
+ it 'resolves entries on the configured library paths, with the files plugins publish' do
101
+ make( 'vendor/lib/libx.a', 'build/deps/libfusion.so.1' )
102
+ stub_const( 'PATHS_LIBRARIES', ['vendor/lib'] )
103
+ stub_const( 'LIBRARIES_LINK_FILES', ['build/deps/libfusion.so.1'] )
104
+
105
+ expect( @resolver.link_files( ['x', 'm'] ) ).to eq( ['vendor/lib/libx.a', 'build/deps/libfusion.so.1'] )
106
+ end
107
+
108
+ it 'resolves nothing when neither library paths nor plugin files are configured' do
109
+ hide_const( 'PATHS_LIBRARIES' )
110
+ hide_const( 'LIBRARIES_LINK_FILES' )
111
+
112
+ expect( @resolver.link_files( ['x'] ) ).to eq( [] )
113
+ end
114
+ end
115
+
116
+ # The path handling audit around GH #1370: a library search path is configured like any
117
+ # other, with decorators and globs, and the linker reads neither
118
+ describe '#search_path_arguments' do
119
+ it 'gives the linker the directories a decorated, globbed library path names' do
120
+ FileUtils.mkdir_p( ['vendor/a', 'vendor/skip'] )
121
+ stub_const( 'PATHS_LIBRARIES', ['+:vendor/**', '-:vendor/skip'] )
122
+ stub_const( 'LIBRARIES_PATH_FLAG', '-L${1}' )
123
+
124
+ expect( @resolver.search_path_arguments ).to eq( ['-Lvendor', '-Lvendor/a'] )
125
+ end
126
+
127
+ # Quoted like every other default path argument, so a path with a space survives the shell
128
+ it 'quotes each directory under the default flag template' do
129
+ FileUtils.mkdir_p( 'vendor/third party/lib' )
130
+ stub_const( 'PATHS_LIBRARIES', ['vendor/third party/lib'] )
131
+ stub_const( 'LIBRARIES_PATH_FLAG', DEFAULT_CEEDLING_PROJECT_CONFIG[:libraries][:path_flag] )
132
+
133
+ expect( @resolver.search_path_arguments ).to eq( ['-L "vendor/third party/lib"'] )
134
+ end
135
+
136
+ # A plugin's library directories join :paths ↳ :libraries once configuration is done
137
+ it 'includes the directories a plugin adds to the library paths' do
138
+ FileUtils.mkdir_p( ['vendor/lib', 'build/deps'] )
139
+ stub_const( 'PATHS_LIBRARIES', ['vendor/lib'] )
140
+ stub_const( 'LIBRARIES_PATH_FLAG', '-L${1}' )
141
+ PATHS_LIBRARIES << 'build/deps'
142
+
143
+ expect( @resolver.search_path_arguments ).to eq( ['-Lvendor/lib', '-Lbuild/deps'] )
144
+ end
145
+
146
+ it 'gives no arguments without library paths' do
147
+ hide_const( 'PATHS_LIBRARIES' )
148
+
149
+ expect( @resolver.search_path_arguments ).to eq( [] )
150
+ end
151
+ end
152
+
153
+ it 'finds nothing without entries or search paths' do
154
+ expect( resolve( [], search_paths: [] ) ).to eq( [] )
155
+ expect( resolve( nil, search_paths: nil ) ).to eq( [] )
156
+ end
157
+ end
@@ -12,7 +12,7 @@ require 'ceedling/test_invoker/mock_locator'
12
12
 
13
13
  describe MockLocator do
14
14
  before(:each) do
15
- @configurator = double( "Configurator", cmock_mock_prefix: 'Mock' )
15
+ @configurator = double( "Configurator", cmock_mock_prefix: 'Mock', cmock_mock_name_include_folder: true )
16
16
  @include_pathinator = double( "IncludePathinator" )
17
17
  @file_finder = double( "FileFinder" )
18
18
  @file_path_utils = double( "FilePathUtils" )
@@ -59,6 +59,21 @@ describe MockLocator do
59
59
  expect(@locator.directories( mocks, mocks_root: 'mocks', collection: [] )).to eq( ['mocks/drivers', 'mocks'] )
60
60
  end
61
61
 
62
+ # GH #1370's path handling audit: CMock's root plus a climbing folder must not leave the mock root
63
+ it "adds the root CMock climbs from for a mock whose #include folder climbs" do
64
+ allow(@file_finder).to receive(:resolve_mock).with( '../x/MockFoo.h', collection: [], complain: :error ).and_return( ['../x/foo.h', ''] )
65
+
66
+ expect(@locator.directories( [MockInclude.new( '../x/MockFoo.h' )], mocks_root: 'mocks', collection: [] ))
67
+ .to eq( ['mocks/_up_/x', 'mocks/_up_/_up_'] )
68
+ end
69
+
70
+ it "adds the directory a folder that ends the mirror leads down from" do
71
+ allow(@file_finder).to receive(:resolve_mock).with( 'uart/MockFoo.h', collection: [], complain: :error ).and_return( ['src/drivers/uart/foo.h', 'drivers/uart'] )
72
+
73
+ expect(@locator.directories( [MockInclude.new( 'uart/MockFoo.h' )], mocks_root: 'mocks', collection: [] ))
74
+ .to eq( ['mocks/drivers/uart', 'mocks/drivers'] )
75
+ end
76
+
62
77
  it "skips a Partial mock, which has no real header" do
63
78
  expect(@file_finder).to_not receive(:resolve_mock)
64
79
 
@@ -71,4 +86,64 @@ describe MockLocator do
71
86
  expect(@locator.directories( [MockInclude.new( 'MockGone.h' )], mocks_root: 'mocks', collection: [], complain: :ignore )).to eq( [] )
72
87
  end
73
88
  end
89
+ # CMock writes a mock below its root at the folder the #include names, and names the mock
90
+ # by that folder. The compiler reaches the mock through the #include as written, from
91
+ # the directory that folder leads down or climbs from (`reach`).
92
+ describe "#placement" do
93
+ def placement(include_path, subdir: 'drivers/uart')
94
+ @locator.placement( mocks_root: 'mocks/t', subdir: subdir, include_path: include_path )
95
+ end
96
+
97
+ it "keeps a bare #include's mock in its mirrored directory, with no folder" do
98
+ expect(placement( 'MockFoo.h' ).to_h).to eq( folder: nil, directory: 'mocks/t/drivers/uart', root: 'mocks/t/drivers/uart', reach: 'mocks/t/drivers/uart' )
99
+ end
100
+
101
+ it "roots CMock above a folder that ends the mirrored directory" do
102
+ expect(placement( 'uart/MockFoo.h' ).to_h).to eq( folder: 'uart', directory: 'mocks/t/drivers/uart', root: 'mocks/t/drivers', reach: 'mocks/t/drivers' )
103
+ expect(placement( 'drivers/uart/MockFoo.h' ).to_h).to eq( folder: 'drivers/uart', directory: 'mocks/t/drivers/uart', root: 'mocks/t', reach: 'mocks/t' )
104
+ end
105
+
106
+ # The mock root carries the test's name, which a folder must never be mistaken for ending
107
+ it "compares the folder with the header's mirrored subdirectory alone, not the mock root" do
108
+ spot = @locator.placement( mocks_root: 'mocks/test/test_c', subdir: '', include_path: 'test_c/MockFoo.h' )
109
+
110
+ expect(spot.to_h).to eq( folder: 'test_c', directory: 'mocks/test/test_c/test_c', root: 'mocks/test/test_c', reach: 'mocks/test/test_c' )
111
+ end
112
+
113
+ it "places the mock at the written path below the mock root for a folder longer than the mirror" do
114
+ expect(placement( 'more/sub/MockFoo.h', subdir: 'sub' ).to_h).to eq( folder: 'more/sub', directory: 'mocks/t/more/sub', root: 'mocks/t', reach: 'mocks/t' )
115
+ end
116
+
117
+ it "drops a leading ./ from the folder" do
118
+ expect(placement( './uart/MockFoo.h' ).folder).to eq( 'uart' )
119
+ end
120
+
121
+ it "passes no folder when :mock_name_include_folder is disabled, keeping the place the #include reaches" do
122
+ allow(@configurator).to receive(:cmock_mock_name_include_folder).and_return( false )
123
+
124
+ expect(placement( 'uart/MockFoo.h' ).to_h).to eq( folder: nil, directory: 'mocks/t/drivers/uart', root: 'mocks/t/drivers/uart', reach: 'mocks/t/drivers' )
125
+ expect(placement( 'more/sub/MockFoo.h', subdir: 'sub' ).to_h).to eq( folder: nil, directory: 'mocks/t/more/sub', root: 'mocks/t/more/sub', reach: 'mocks/t' )
126
+ end
127
+
128
+ it "keeps the mock of a folder that climbs below the mock root, reached from as deep as the climb" do
129
+ expect(placement( '../x/MockFoo.h', subdir: 'y' ).to_h).to eq( folder: '../x', directory: 'mocks/t/_up_/x', root: 'mocks/t/_up_/_up_', reach: 'mocks/t/_up_/_up_' )
130
+ expect(placement( '../../x/MockFoo.h', subdir: '' ).to_h)
131
+ .to eq( folder: '../../x', directory: 'mocks/t/_up_/_up_/x', root: 'mocks/t/_up_/_up_/_up_/_up_', reach: 'mocks/t/_up_/_up_/_up_/_up_' )
132
+ end
133
+
134
+ it "always writes the mock where CMock's root and its folder lead, and where the #include reaches" do
135
+ [true, false].each do |name_by_folder|
136
+ allow(@configurator).to receive(:cmock_mock_name_include_folder).and_return( name_by_folder )
137
+
138
+ ['MockFoo.h', 'uart/MockFoo.h', 'more/sub/MockFoo.h', '../x/MockFoo.h', '../../a/b/MockFoo.h', './uart/MockFoo.h'].each do |include_path|
139
+ spot = placement( include_path )
140
+ written = File.dirname( include_path )
141
+
142
+ expect(File.expand_path( File.join( *[spot.root, spot.folder].compact ), '/w' )).to eq( File.expand_path( spot.directory, '/w' ) ), include_path
143
+ expect(File.expand_path( File.join( spot.reach, written ), '/w' )).to eq( File.expand_path( spot.directory, '/w' ) ), include_path
144
+ [spot.directory, spot.root, spot.reach].each { |dir| expect(dir.split( '/' )).to_not include( '..' ), include_path }
145
+ end
146
+ end
147
+ end
148
+ end
74
149
  end
@@ -76,6 +76,13 @@ describe PartializerConfig do
76
76
  expect( result['drivers/uart/config'].module ).to eq( 'drivers/uart/config' )
77
77
  end
78
78
 
79
+ # GH #1370 audit: a `.` segment names nothing, so `./drivers/uart` is `drivers/uart`
80
+ it "keys the config on the directory without its `.` segments" do
81
+ result = @config.extract_configs('TEST_PARTIAL_PUBLIC_MODULE_AT(./drivers/./uart, config)')
82
+
83
+ expect( result.keys ).to eq( ['drivers/uart/config'] )
84
+ end
85
+
79
86
  it "keeps two modules sharing a basename distinct" do
80
87
  result = @config.extract_configs(
81
88
  "TEST_PARTIAL_ALL_MODULE_AT(drivers/uart, config)\n" \
@@ -31,6 +31,7 @@ describe Partializer do
31
31
  allow(@configurator).to receive(:paths_test).and_return( ['test'] )
32
32
  allow(@configurator).to receive(:paths_support).and_return( [] )
33
33
  allow(@configurator).to receive(:paths_include).and_return( ['include'] )
34
+ allow(@configurator).to receive(:collection_mirror_roots_headers).and_return( ['test', 'include'] )
34
35
 
35
36
  @partializer = described_class.new(
36
37
  {
@@ -364,6 +364,23 @@ describe PartialsManager do
364
364
  expect( @testable.partials.mocks ).to eq( ['Foo'] )
365
365
  end
366
366
 
367
+ # Build threads finish in any order, and a test's link records its objects in order
368
+ it "keeps a test's Partial modules in configuration order, however the batch finishes" do
369
+ allow(@partializer).to receive(:extract_implementation_functions).and_return( [double("FunctionDefinition")] )
370
+ allow(@partializer).to receive(:extract_interface_functions).and_return( [double("FunctionDeclaration")] )
371
+ allow(@batchinator).to receive(:exec) do |workload:, things:, &block|
372
+ things.reverse_each { |thing| block.call( thing ) }
373
+ end
374
+ @testable.partials.configs = %w[Alpha Beta Gamma].to_h do |name|
375
+ [name, Partials::Config.new( module: name, header: @config.header, source: @config.source )]
376
+ end
377
+
378
+ @manager.stage_generate_partials( @state )
379
+
380
+ expect( @testable.partials.tests ).to eq( %w[Alpha Beta Gamma] )
381
+ expect( @testable.partials.mocks ).to eq( %w[Alpha Beta Gamma] )
382
+ end
383
+
367
384
  it "does not add to tests when no implementation is extracted" do
368
385
  allow(@partializer).to receive(:extract_implementation_functions).and_return( nil )
369
386
  allow(@partializer).to receive(:extract_interface_functions).and_return( [double("FunctionDeclaration")] )
@@ -831,7 +831,7 @@ describe Bullseye do
831
831
  ceedling: services,
832
832
  configurator: configurator,
833
833
  test_invoker: test_invoker,
834
- file_wrapper: double('file_wrapper', exist?: false)
834
+ file_wrapper: double('file_wrapper', exist?: false, mkdir: nil)
835
835
  }.merge(ivars)
836
836
  )
837
837
  end
@@ -861,7 +861,7 @@ describe Bullseye do
861
861
  bullseye = build_process_bullseye({ bullseye_untested_sources: BULLSEYE_UNTESTED_SOURCES_LIST })
862
862
 
863
863
  expect(loginator).to receive(:log_list)
864
- .with(['src/a.c', 'src/b.c'], kind_of(String), Verbosity::COMPLAIN, LogLabels::WARNING)
864
+ .with(['src/a.c', 'src/b.c'], kind_of(String), Verbosity::COMPLAIN)
865
865
  expect(generator).to_not receive(:generate_object_file_c)
866
866
 
867
867
  bullseye.process_untested_sources(sources: ['src/b.c', 'src/a.c'])
@@ -883,6 +883,19 @@ describe Bullseye do
883
883
  bullseye.process_untested_sources(sources: [])
884
884
  end
885
885
 
886
+ # An untested source's object sits at its path below the output root, in a
887
+ # directory no test build made
888
+ it 'makes the object\'s and dependencies file\'s directories before compiling' do
889
+ allow(dependinator).to receive(:stale?).and_return(true)
890
+ untested_wrapper = double('file_wrapper', exist?: false)
891
+ bullseye = build_process_bullseye({ bullseye_untested_sources: BULLSEYE_UNTESTED_SOURCES_COMPILE }, file_wrapper: untested_wrapper)
892
+
893
+ expect(untested_wrapper).to receive(:mkdir).with('build/bullseye/out/src').twice.ordered
894
+ expect(generator).to receive(:generate_object_file_c).ordered
895
+
896
+ bullseye.process_untested_sources(sources: ['src/a.c'])
897
+ end
898
+
886
899
  it 'skips compilation for an already-fresh object' do
887
900
  allow(dependinator).to receive(:stale?).and_return(false)
888
901
  bullseye = build_process_bullseye({ bullseye_untested_sources: BULLSEYE_UNTESTED_SOURCES_COMPILE })
@@ -9,8 +9,8 @@ require 'spec_helper'
9
9
  require 'ceedling/tool_executor'
10
10
  require 'ceedling/constants'
11
11
  require 'ceedling/exceptions'
12
- require 'ceedling/path_mirror'
13
- require 'ceedling/file_path_utils'
12
+ require 'ceedling/filesystem/path_mirror'
13
+ require 'ceedling/filesystem/file_path_utils'
14
14
 
15
15
  PROJECT_BUILD_ROOT = 'build' unless defined?(PROJECT_BUILD_ROOT)
16
16
  PROJECT_BUILD_ARTIFACTS_ROOT = 'artifacts' unless defined?(PROJECT_BUILD_ARTIFACTS_ROOT)
@@ -30,12 +30,18 @@ describe ConsoleReportinator do
30
30
  let(:test_invoker) { double('test_invoker') }
31
31
  let(:tool_executor) { double('tool_executor') }
32
32
  let(:configurator) do
33
- double('configurator', paths_source: ['src'], paths_support: ['support'], cmock_mock_prefix: 'mock_')
33
+ double(
34
+ 'configurator',
35
+ paths_source: ['src'], paths_support: ['support'], cmock_mock_prefix: 'mock_',
36
+ project_build_root: 'build', extension_object: FilenameExtension.new('.o'),
37
+ project_use_partials: true, project_use_mocks: true,
38
+ project_test_partials_path: 'build/test/partials', cmock_mock_path: 'build/test/mocks'
39
+ )
34
40
  end
35
- # Real, so reversing a generated Partial filename here exercises the same code that
36
- # builds those filenames rather than a restatement of it. Touches no filesystem.
41
+ # Real, so reversing a generated Partial filename, or placing an object, exercises the
42
+ # same code the build uses rather than a restatement of it. Touches no filesystem.
37
43
  let(:file_path_utils) do
38
- FilePathUtils.new({ configurator: configurator, file_wrapper: double('file_wrapper') })
44
+ FilePathUtils.new({ configurator: configurator, file_wrapper: double('file_wrapper', check_path_length: nil) })
39
45
  end
40
46
  let(:system_objects) do
41
47
  {
@@ -195,33 +201,28 @@ describe ConsoleReportinator do
195
201
  reportinator.send(:run_gcov_summary, 'test_foo', 'src/foo.c', {})
196
202
  end
197
203
 
198
- it 'searches a nested source\'s mirrored subdirectory, not the flat test-output root' do
199
- allow(configurator).to receive(:paths_source).and_return(['src'])
200
- allow(configurator).to receive(:paths_support).and_return([])
204
+ # The test's build placed the object, and its coverage data, at the source's path from
205
+ # the project root
206
+ it 'searches the directory its test\'s build placed the source\'s object in' do
201
207
  stub_exec(exit_code: 0, output: 'coverage text')
202
208
  expect(tool_executor).to receive(:build_command_line)
203
- .with(TOOLS_GCOV_SUMMARY, [], 'foo.c', File.join('build/gcov/out/test_foo', 'nested'))
209
+ .with(TOOLS_GCOV_SUMMARY, [], 'foo.c', 'build/gcov/out/test_foo/src/nested')
204
210
  .and_return({ options: {} })
205
211
  reportinator.send(:run_gcov_summary, 'test_foo', 'src/nested/foo.c', {})
206
212
  end
207
213
 
208
- it 'searches the flat test-output root for a source directly under a configured path' do
209
- allow(configurator).to receive(:paths_source).and_return(['src'])
210
- allow(configurator).to receive(:paths_support).and_return([])
214
+ it 'searches the test-output root for a source at the project root' do
211
215
  stub_exec(exit_code: 0, output: 'coverage text')
212
216
  expect(tool_executor).to receive(:build_command_line)
213
217
  .with(TOOLS_GCOV_SUMMARY, [], 'foo.c', 'build/gcov/out/test_foo')
214
218
  .and_return({ options: {} })
215
- reportinator.send(:run_gcov_summary, 'test_foo', 'src/foo.c', {})
219
+ reportinator.send(:run_gcov_summary, 'test_foo', 'foo.c', {})
216
220
  end
217
221
 
218
222
  # A generated Partial sits below its own test's Partials build root, not a configured
219
223
  # source root, so measuring against the source roots yields no subdirectory at all and
220
224
  # gcov is pointed at the flat root while the coverage data sits one level down.
221
225
  it 'searches a generated Partial\'s own mirrored subdirectory' do
222
- allow(configurator).to receive(:paths_source).and_return(['src'])
223
- allow(configurator).to receive(:paths_support).and_return([])
224
- allow(configurator).to receive(:project_test_partials_path).and_return('build/test/partials')
225
226
  stub_exec(exit_code: 0, output: 'coverage text')
226
227
 
227
228
  expect(tool_executor).to receive(:build_command_line)
@@ -238,9 +239,6 @@ describe ConsoleReportinator do
238
239
  end
239
240
 
240
241
  it 'searches the flat root for a Partial of a module named without a directory' do
241
- allow(configurator).to receive(:paths_source).and_return(['src'])
242
- allow(configurator).to receive(:paths_support).and_return([])
243
- allow(configurator).to receive(:project_test_partials_path).and_return('build/test/partials')
244
242
  stub_exec(exit_code: 0, output: 'coverage text')
245
243
 
246
244
  expect(tool_executor).to receive(:build_command_line)