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
@@ -23,8 +23,9 @@
23
23
 
24
24
  require 'spec_helper'
25
25
  require 'spec_integration_helper'
26
+ require 'file_tree_helper'
26
27
  require 'actionator'
27
- require 'ceedling/file_wrapper'
28
+ require 'ceedling/filesystem/file_wrapper'
28
29
 
29
30
  describe 'Actionator file operations (integration)' do
30
31
  include IntegrationSpecHelpers
@@ -144,6 +145,95 @@ describe 'Actionator file operations (integration)' do
144
145
  ])
145
146
  end
146
147
  end
148
+
149
+ # Status lines follow a sorted listing of full paths, so a file sorts ahead of the
150
+ # contents of a directory named like it
151
+ it 'reports files in sorted path order' do
152
+ with_source_tree({ 'tree/a/b.c' => 'b', 'tree/a.c' => 'a', 'tree/a-z.c' => 'z' }) do |dir|
153
+ actionator = build_actionator( dir )
154
+
155
+ actionator.copy_directory( 'tree', File.join( dir, 'out' ), force: true )
156
+
157
+ expect(@loginator.lines).to eq([
158
+ ' create out',
159
+ ' create out/a-z.c',
160
+ ' create out/a.c',
161
+ ' create out/a/b.c',
162
+ ])
163
+ end
164
+ end
165
+
166
+ it 'leaves hidden files and hidden directories out' do
167
+ with_source_tree({ 'tree/keep.c' => 'k', 'tree/.rspec' => 'r', 'tree/.hidden/x.c' => 'x' }) do |dir|
168
+ actionator = build_actionator( dir )
169
+
170
+ actionator.copy_directory( 'tree', File.join( dir, 'out' ), force: true )
171
+
172
+ expect(Dir.children( File.join( dir, 'out' ) )).to eq( ['keep.c'] )
173
+ end
174
+ end
175
+
176
+ it 'never enters a hidden directory, so nothing inside one stops the copy' do
177
+ with_source_tree({ 'tree/keep.c' => 'k', 'tree/.venv/x.c' => 'x' }) do |dir|
178
+ begin
179
+ File.symlink( File.join( dir, 'nowhere' ), File.join( dir, 'tree', '.venv', 'dangling.c' ) )
180
+ rescue NotImplementedError, SystemCallError => e
181
+ skip "symlinks are unavailable here (#{e.class})"
182
+ end
183
+ actionator = build_actionator( dir )
184
+
185
+ actionator.copy_directory( 'tree', File.join( dir, 'out' ), force: true )
186
+
187
+ expect(Dir.children( File.join( dir, 'out' ) )).to eq( ['keep.c'] )
188
+ end
189
+ end
190
+
191
+ it 'copies a file below a directory named with glob metacharacters' do
192
+ with_source_tree({ 'tree/dir[1]/a{b}.c' => 'odd' }) do |dir|
193
+ actionator = build_actionator( dir )
194
+
195
+ actionator.copy_directory( 'tree', File.join( dir, 'out' ), force: true )
196
+
197
+ expect(File.read( File.join( dir, 'out', 'dir[1]', 'a{b}.c' ) )).to eq( 'odd' )
198
+ end
199
+ end
200
+
201
+ # GH #1376: the tree is listed and classified without lstat, and a linked directory's
202
+ # contents are copied
203
+ it 'descends a linked directory' do
204
+ with_source_tree({ 'elsewhere/inner.c' => 'inner', 'tree/keep.c' => 'k' }) do |dir|
205
+ begin
206
+ File.symlink( File.join( dir, 'elsewhere' ), File.join( dir, 'tree', 'linked' ) )
207
+ rescue NotImplementedError, SystemCallError => e
208
+ skip "symlinks are unavailable here (#{e.class})"
209
+ end
210
+ actionator = build_actionator( dir )
211
+
212
+ actionator.copy_directory( 'tree', File.join( dir, 'out' ), force: true )
213
+
214
+ expect(File.read( File.join( dir, 'out', 'linked', 'inner.c' ) )).to eq( 'inner' )
215
+ end
216
+ end
217
+
218
+ it 'copies every file as a file when lstat reports files as directories' do
219
+ with_source_tree({ 'tree/unity.c' => 'u', 'tree/sub/unity.h' => 'h' }) do |dir|
220
+ actionator = build_actionator( dir )
221
+ allow(File).to receive(:lstat).and_wrap_original do |original, path, *rest|
222
+ status = original.call( path, *rest )
223
+ path.to_s.include?( '/tree/' ) ? FileTreeHelper::LyingStat.new( status ) : status
224
+ end
225
+
226
+ begin
227
+ actionator.copy_directory( 'tree', File.join( dir, 'out' ), force: true )
228
+ ensure
229
+ # The temporary directory is removed by an lstat-based remover
230
+ allow(File).to receive(:lstat).and_call_original
231
+ end
232
+
233
+ expect(File.file?( File.join( dir, 'out', 'unity.c' ) )).to be true
234
+ expect(File.file?( File.join( dir, 'out', 'sub', 'unity.h' ) )).to be true
235
+ end
236
+ end
147
237
  end
148
238
 
149
239
  describe 'copy_file' do
@@ -17,7 +17,7 @@ require 'json'
17
17
  require 'tmpdir'
18
18
  require 'ceedling/constants'
19
19
  require 'ceedling/plugins/plugin'
20
- require 'ceedling/file_wrapper'
20
+ require 'ceedling/filesystem/file_wrapper'
21
21
 
22
22
  $: << File.expand_path('../../../plugins/compile_commands_json_db/lib', __FILE__)
23
23
  require 'compile_commands_json_db'
@@ -20,7 +20,7 @@ describe 'Configurator validation (integration)' do
20
20
  include ConfigYamlHelper
21
21
  include ConfiguratorIntegrationHelpers
22
22
 
23
- let(:validator) { configurator_objects( quiet_loginator )[:configurator_validator] }
23
+ let(:validator) { configurator_objects( quiet_loginator )[:configurator_paths_validator] }
24
24
 
25
25
  let(:files) do
26
26
  {
@@ -161,6 +161,32 @@ describe 'DependencyTracker cache hardening (integration)' do
161
161
  end
162
162
  end
163
163
 
164
+ # GH #1364: a build after upgrading from a version-1 layout rebuilds everything once, and
165
+ # the next build trusts the cache it then wrote
166
+ it 'rebuilds once after an upgrade from the version-1 build layout, then trusts its own cache' do
167
+ in_temp_dir do |dir|
168
+ store_path = File.join(dir, '.dep_cache.json')
169
+ target = write_fixture( File.join(dir, 'foo.o'), 'object bytes' )
170
+
171
+ write_fixture( store_path, JSON.generate(
172
+ 'schema_version' => 1, 'hash_algorithm' => DependencyHasher::HASH_ALGORITHM,
173
+ 'entries' => { target => { 'self_hash' => real_sha256(target), 'meta_hash' => nil, 'deps' => {} } }
174
+ ) )
175
+
176
+ upgraded = build_dependency_tracker( store_path: store_path )
177
+ upgraded.register( target, files: [] )
178
+ expect( upgraded.stale?( target ) ).to be(true)
179
+ upgraded.mark_fresh( target )
180
+ upgraded.flush
181
+
182
+ expect( JSON.parse( File.read( store_path ) )['schema_version'] ).to eq( DependencyCacheStore::CACHE_SCHEMA_VERSION )
183
+
184
+ rebuilt = build_dependency_tracker( store_path: store_path )
185
+ rebuilt.register( target, files: [] )
186
+ expect( rebuilt.stale?( target ) ).to be(false)
187
+ end
188
+ end
189
+
164
190
  # Same principle, but for a mismatched hash_algorithm field rather than
165
191
  # schema_version -- the two are independent, both-checked axes.
166
192
  it 'discards an entire cache whose hash_algorithm does not match' do
@@ -242,6 +242,28 @@ describe 'DependencyTracker core tracking (integration)' do
242
242
  end
243
243
  end
244
244
 
245
+ # Staleness checks only the dependencies registered this build, so one dropped from the list
246
+ # leaves the rest as they were. A link registers the list itself as meta, which a shorter list
247
+ # changes, for when a source leaves the build.
248
+ it 'is stale when a dependency drops out of a list registered as meta' do
249
+ in_temp_dir do |dir|
250
+ store_path = File.join(dir, '.dep_cache.json')
251
+ kept = write_fixture( File.join(dir, 'kept.o'), 'kept object' )
252
+ dropped = write_fixture( File.join(dir, 'dropped.o'), 'dropped object' )
253
+ listed = write_fixture( File.join(dir, 'listed.out'), 'executable bytes' )
254
+
255
+ first_run = build_dependency_tracker( store_path: store_path )
256
+ first_run.register( listed, files: [kept, dropped], meta: { objects: [kept, dropped] } )
257
+ first_run.mark_fresh( listed )
258
+ first_run.flush
259
+
260
+ second_run = build_dependency_tracker( store_path: store_path )
261
+ second_run.register( listed, files: [kept], meta: { objects: [kept] } )
262
+
263
+ expect( second_run.stale?( listed ) ).to be(true)
264
+ end
265
+ end
266
+
245
267
  # A delta build skips running an unchanged test executable and reports its cached results.
246
268
  # An executable linked with command line arguments enabled is identical with or without a
247
269
  # test case filter, so the fixture's own metadata must carry the filter (GH #1360).
@@ -0,0 +1,297 @@
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
+ # GH #1365: a launcher ran another installation's application inside its own process,
9
+ # so the application ran on a mix of both installations' code. Each command must now
10
+ # run whole in the installation it selects.
11
+ #
12
+ # The second installation is real: `new --local` vendors this repository into a
13
+ # project, and the copy gains the assets and examples a vendored copy leaves out, so
14
+ # it can also run `new` and `examples`. Two markers make it distinguishable from the
15
+ # launcher:
16
+ # - Its lib/version.rb reports 9.9.9.
17
+ # - Its bin/ceedling reports, on exit, how many of the launcher's own files its
18
+ # process loaded. A whole hand-off loads none.
19
+ #
20
+ # Every command here stops short of compiling, so no toolchain is needed.
21
+
22
+ require 'spec_helper'
23
+ require 'tmpdir'
24
+ require 'fileutils'
25
+ require 'open3'
26
+ require 'rbconfig'
27
+ require 'yaml'
28
+ require 'ceedling/installation'
29
+
30
+ describe 'Launcher hand-off' do
31
+ REPO_ROOT = File.expand_path( '../..', __dir__ )
32
+ LAUNCHER_VERSION = Installation.new( REPO_ROOT ).version
33
+
34
+ # Registered as the copy's launcher starts, so it reports on every exit, failures
35
+ # included. It prints to stderr, so `dumpconfig --stdout` output stays pure YAML.
36
+ MARKER = <<~RUBY
37
+ at_exit {
38
+ launcher_files = $LOADED_FEATURES.count { |f| f.start_with?( '%<lib>s' ) or f.start_with?( '%<bin>s' ) }
39
+ $stderr.puts( "LAUNCHER FILES LOADED: \#{launcher_files}" )
40
+ }
41
+ RUBY
42
+
43
+ def ceedling(*args, env: {}, dir: @project)
44
+ stdout, stderr, status = Open3.capture3(
45
+ {'CEEDLING_DECORATORS' => 'false'}.merge( env ),
46
+ RbConfig.ruby, File.join( REPO_ROOT, 'bin', 'ceedling' ), *args,
47
+ chdir: dir
48
+ )
49
+ return stdout, stderr, status
50
+ end
51
+
52
+ # The copy ran its own command, loading none of the launcher's files
53
+ def expect_copy_ran(stderr)
54
+ expect(stderr).to include( 'LAUNCHER FILES LOADED: 0' )
55
+ end
56
+
57
+ before(:all) do
58
+ @tmp = Dir.mktmpdir( 'handoff' )
59
+ _, stderr, status = ceedling( 'new', '--local', 'proj', dir: @tmp )
60
+ raise "Could not create a vendored project:\n#{stderr}" unless status.success?
61
+
62
+ @project = File.join( @tmp, 'proj' )
63
+ @copy = File.join( @project, 'vendor', 'ceedling' )
64
+
65
+ version_rb = File.join( @copy, 'lib', 'version.rb' )
66
+ File.write( version_rb, File.read( version_rb ).sub( /BASE = '[^']+'/, "BASE = '9.9.9'" ) )
67
+ marker = format( MARKER, lib: File.join( REPO_ROOT, 'lib', 'ceedling' ), bin: File.join( REPO_ROOT, 'bin' ) )
68
+ launcher = File.join( @copy, 'bin', 'ceedling' )
69
+ shebang, rest = File.read( launcher ).split( "\n", 2 )
70
+ File.write( launcher, [shebang, marker, rest].join( "\n" ) )
71
+
72
+ ['assets', 'examples'].each { |dir| FileUtils.cp_r( File.join( REPO_ROOT, dir ), @copy ) }
73
+
74
+ @copy_version = Installation.new( @copy ).version
75
+ end
76
+
77
+ after(:all) do
78
+ FileUtils.rm_rf( @tmp )
79
+ end
80
+
81
+ it 'gives the copy a distinct version' do
82
+ expect(@copy_version).to eq( '9.9.9.dev' )
83
+ expect(@copy_version).to_not eq( LAUNCHER_VERSION )
84
+ end
85
+
86
+ describe '`version`' do
87
+ it 'reports both installations for a project whose :which_ceedling selects the copy' do
88
+ stdout, _, status = ceedling( 'version' )
89
+
90
+ expect(status.exitstatus).to eq( 0 )
91
+ expect(stdout).to include( "Ceedling Launcher => #{LAUNCHER_VERSION}" )
92
+ expect(stdout).to include( "Ceedling App => #{@copy_version}" )
93
+ end
94
+
95
+ it 'reports the copy that WHICH_CEEDLING selects, with no project' do
96
+ stdout, _, _ = ceedling( 'version', env: {'WHICH_CEEDLING' => @copy}, dir: @tmp )
97
+
98
+ expect(stdout).to include( "Ceedling App => #{@copy_version}" )
99
+ end
100
+
101
+ it 'reports the copy that a project named with --project selects, from elsewhere' do
102
+ Dir.mktmpdir do |elsewhere|
103
+ # :which_ceedling resolves against the working directory, so name the copy absolutely
104
+ mixin = File.join( elsewhere, 'which.yml' )
105
+ File.write( mixin, {:project => {:which_ceedling => @copy}}.to_yaml )
106
+
107
+ stdout, _, _ = ceedling( 'version', '--project', File.join( @project, 'project.yml' ), '--mixin', mixin, dir: elsewhere )
108
+
109
+ expect(stdout).to include( "Ceedling App => #{@copy_version}" )
110
+ end
111
+ end
112
+
113
+ it 'never hands off' do
114
+ _, stderr, _ = ceedling( 'version' )
115
+
116
+ expect(stderr).to_not include( 'LAUNCHER FILES LOADED' )
117
+ end
118
+ end
119
+
120
+ describe 'project commands' do
121
+ it '`check` runs in the copy, with notices from both sides naming both versions' do
122
+ stdout, stderr, status = ceedling( 'check' )
123
+
124
+ expect(status.exitstatus).to eq( 0 ), stdout + stderr
125
+ expect_copy_ran( stderr )
126
+ expect(stdout).to include( "Ceedling launcher #{LAUNCHER_VERSION} at #{REPO_ROOT}/ is handing off to Ceedling #{@copy_version} at #{File.realpath( @copy )}/" ).or(
127
+ include( "Ceedling launcher #{LAUNCHER_VERSION} at #{REPO_ROOT}/ is handing off to Ceedling #{@copy_version} at #{@copy}/" )
128
+ )
129
+ expect(stdout).to match( /Ceedling #{Regexp.escape( @copy_version )} at .+ is now running, launched from Ceedling #{Regexp.escape( LAUNCHER_VERSION )} at #{Regexp.escape( REPO_ROOT )}\// )
130
+ end
131
+
132
+ ['environment', 'help', '-T'].each do |command|
133
+ it "`#{command}` runs in the copy" do
134
+ stdout, stderr, status = ceedling( command )
135
+
136
+ expect(status.exitstatus).to eq( 0 ), stdout + stderr
137
+ expect_copy_ran( stderr )
138
+ end
139
+ end
140
+
141
+ it '`help` shows the copy\'s version in its footer' do
142
+ stdout, _, _ = ceedling( 'help' )
143
+
144
+ expect(stdout).to include( "Ceedling Packet User Manual (v#{@copy_version})" )
145
+ end
146
+
147
+ it '`dumpconfig --stdout` runs in the copy and writes nothing but YAML to stdout' do
148
+ stdout, stderr, status = ceedling( 'dumpconfig', '--stdout' )
149
+
150
+ expect(status.exitstatus).to eq( 0 ), stdout + stderr
151
+ expect_copy_ran( stderr )
152
+ expect(YAML.safe_load( stdout, permitted_classes: [Symbol] )).to include( :project )
153
+ end
154
+
155
+ it '`dumpconfig --no-app` runs in the copy' do
156
+ _, stderr, status = ceedling( 'dumpconfig', '--no-app', File.join( @tmp, 'dump.yml' ) )
157
+
158
+ expect(status.exitstatus).to eq( 0 ), stderr
159
+ expect_copy_ran( stderr )
160
+ end
161
+
162
+ it 'exits with the copy\'s failing status' do
163
+ Dir.mktmpdir do |mixins|
164
+ bad = File.join( mixins, 'bad.yml' )
165
+ File.write( bad, {:plugins => {:enabled => ['no_such_plugin']}}.to_yaml )
166
+
167
+ _, stderr, status = ceedling( 'check', '--mixin', bad )
168
+
169
+ expect(status.exitstatus).to eq( 1 )
170
+ expect_copy_ran( stderr )
171
+ end
172
+ end
173
+ end
174
+
175
+ describe 'commands without a project' do
176
+ it '`new` runs in the copy WHICH_CEEDLING selects, which vendors itself' do
177
+ Dir.mktmpdir do |dir|
178
+ _, stderr, status = ceedling( 'new', '--local', 'other', env: {'WHICH_CEEDLING' => @copy}, dir: dir )
179
+
180
+ expect(status.exitstatus).to eq( 0 ), stderr
181
+ expect_copy_ran( stderr )
182
+ expect(Installation.new( File.join( dir, 'other', 'vendor', 'ceedling' ) ).version).to eq( @copy_version )
183
+ expect(File.read( File.join( dir, 'other', 'project.yml' ) )).to include( ":ceedling_version: #{@copy_version}" )
184
+ end
185
+ end
186
+
187
+ it '`examples` runs in the copy WHICH_CEEDLING selects' do
188
+ Dir.mktmpdir do |dir|
189
+ _, stderr, _ = ceedling( 'examples', env: {'WHICH_CEEDLING' => @copy}, dir: dir )
190
+
191
+ expect_copy_ran( stderr )
192
+ end
193
+ end
194
+
195
+ it '`docs` exports the launcher\'s documentation, saying so, since the copy holds none' do
196
+ Dir.mktmpdir do |dir|
197
+ stdout, stderr, status = ceedling( 'docs', 'out', env: {'WHICH_CEEDLING' => @copy}, dir: dir )
198
+
199
+ expect(status.exitstatus).to eq( 0 ), stdout + stderr
200
+ expect(stderr).to_not include( 'LAUNCHER FILES LOADED' )
201
+ expect(stdout).to include( "Ceedling #{@copy_version} at" )
202
+ expect(stdout).to include( "Exporting the documentation of Ceedling launcher #{LAUNCHER_VERSION} at #{REPO_ROOT}/ instead." )
203
+ end
204
+ end
205
+ end
206
+
207
+ describe '`upgrade`' do
208
+ it 'refuses to re-vendor a project from its own vendored copy' do
209
+ stdout, stderr, status = ceedling( 'upgrade', '.', env: {'WHICH_CEEDLING' => 'vendor/ceedling'} )
210
+
211
+ expect(status.exitstatus).to eq( 1 )
212
+ expect(stdout + stderr).to include( 'from itself' )
213
+ expect(File.directory?( @copy )).to be( true )
214
+ end
215
+ end
216
+
217
+ # A launcher before 1.2.2 loads the application into its own process. The application
218
+ # finishes the hand-off itself.
219
+ describe 'an application loaded into an older launcher\'s process' do
220
+ # Stands in for every 1.x launcher before 1.2.2: it builds its bin/ objects before
221
+ # Thor consumes ARGV, hands them over in CEEDLING_HANDOFF_OBJECTS, and requires the
222
+ # application's rakefile. Docker runs the real 1.0.0 through 1.2.1 launchers.
223
+ OLD_LAUNCHER = <<~RUBY
224
+ repo, app = ARGV.shift( 2 )
225
+ $LOAD_PATH.unshift( File.join( repo, 'bin' ) )
226
+ require 'app_cfg'
227
+ CEEDLING_APPCFG = CeedlingAppConfig.new
228
+ lib = CEEDLING_APPCFG[:ceedling_lib_path]
229
+ $LOAD_PATH.unshift( CEEDLING_APPCFG[:ceedling_lib_base_path], lib, File.join( lib, 'config' ), File.join( lib, 'filesystem' ),
230
+ File.join( lib, 'rake_app' ), File.join( CEEDLING_APPCFG[:ceedling_vendor_path], 'diy', 'lib' ) )
231
+ require 'constructor'
232
+ require 'ceedling/constants'
233
+ require 'diy'
234
+ objects = DIY::Context.from_yaml( File.read( File.join( repo, 'bin', 'objects.yml' ) ) )
235
+ objects.build_everything
236
+ CEEDLING_HANDOFF_OBJECTS = [:rake_task_registry, :reportinator, :loginator, :file_wrapper, :yaml_wrapper,
237
+ :ruby_expandinator, :config_walkinator, :system_wrapper, :verbosinator].to_h { |n| [n, objects[n]] }
238
+ def boom_handler(_loginator, exception) = $stderr.puts( exception.message )
239
+ objects[:cli_helper].set_verbosity( Verbosity::NORMAL )
240
+ CEEDLING_APPCFG.set_paths( app )
241
+ require CEEDLING_APPCFG[:ceedling_rakefile_filepath]
242
+ RUBY
243
+
244
+ it 'restarts in its own process, with the original command line, saying so on both sides' do
245
+ script = File.join( @tmp, 'old_launcher.rb' )
246
+ File.write( script, OLD_LAUNCHER )
247
+
248
+ stdout, stderr, status = Open3.capture3(
249
+ {'CEEDLING_DECORATORS' => 'false'}, RbConfig.ruby, script, REPO_ROOT, @copy, 'check', chdir: @project
250
+ )
251
+
252
+ expect(status.exitstatus).to eq( 0 ), stdout + stderr
253
+ expect_copy_ran( stderr )
254
+ expect(stdout).to include( "Ceedling launcher #{LAUNCHER_VERSION} at #{REPO_ROOT}/ loaded Ceedling #{@copy_version}" )
255
+ expect(stdout).to include( "Restarting in Ceedling #{@copy_version}'s own process." )
256
+ expect(stdout).to include( 'Project configuration processed.' )
257
+ end
258
+
259
+ it 'warns and continues in that process when a hand-off already brought it there' do
260
+ stdout, stderr, status = ceedling(
261
+ 'check', env: {'CEEDLING_HANDOFF_LAUNCHER' => '/elsewhere', 'CEEDLING_HANDOFF_TARGET' => REPO_ROOT}
262
+ )
263
+
264
+ expect(status.exitstatus).to eq( 0 ), stdout + stderr
265
+ expect(stderr).to_not include( 'LAUNCHER FILES LOADED' )
266
+ expect(stdout).to include( "Ceedling #{LAUNCHER_VERSION} at #{REPO_ROOT}/ is now running, launched from Ceedling at #{File.expand_path( '/elsewhere' )}/." )
267
+ expect(stdout).to include( "loaded Ceedling #{@copy_version}" )
268
+ expect(stdout).to include( "Continuing in the launcher's process" )
269
+ end
270
+ end
271
+
272
+ describe 'the vendored copy' do
273
+ it 'runs on its own, holding the built-in mixins its launcher validates' do
274
+ stdout, stderr, status = Open3.capture3(
275
+ {'CEEDLING_DECORATORS' => 'false'}, RbConfig.ruby, File.join( @copy, 'bin', 'ceedling' ), 'check', chdir: @project
276
+ )
277
+
278
+ expect(status.exitstatus).to eq( 0 ), stdout + stderr
279
+ expect(File.directory?( File.join( @copy, Installation::BUILTIN_MIXINS_DIR ) )).to be( true )
280
+ end
281
+
282
+ # Windows has ceedling.cmd, whose %* passes the command tail intact
283
+ it 'takes arguments through its ./ceedling launch script exactly as typed', unless: Installation.windows? do
284
+ Dir.mktmpdir do |dir|
285
+ dump = File.join( dir, 'dump with spaces.yml' )
286
+
287
+ stdout, stderr, status = Open3.capture3(
288
+ {'CEEDLING_DECORATORS' => 'false'}, './ceedling', 'dumpconfig', '--no-app', '--mixin', "=:project:\n :name: Two Words", dump,
289
+ chdir: @project
290
+ )
291
+
292
+ expect(status.exitstatus).to eq( 0 ), stdout + stderr
293
+ expect(YAML.safe_load_file( dump, permitted_classes: [Symbol] )[:project][:name]).to eq( 'Two Words' )
294
+ end
295
+ end
296
+ end
297
+ end
@@ -50,7 +50,7 @@ require 'spec_helper'
50
50
  require 'tmpdir'
51
51
  require 'fileutils'
52
52
  require 'ceedling/constants'
53
- require 'ceedling/file_wrapper'
53
+ require 'ceedling/filesystem/file_wrapper'
54
54
  require 'ceedling/yaml_wrapper'
55
55
  require 'ceedling/ruby_expandinator'
56
56
  require 'ceedling/reportinator'
@@ -21,8 +21,8 @@ require 'yaml' # a Ceedling build always has YAML loaded
21
21
  require 'ceedling/constants'
22
22
  require 'ceedling/exceptions'
23
23
  require 'ceedling/plugins/plugin'
24
- require 'ceedling/file_finder_helper'
25
- require 'ceedling/file_wrapper'
24
+ require 'ceedling/filesystem/file_finder_helper'
25
+ require 'ceedling/filesystem/file_wrapper'
26
26
  require 'ceedling/config/config_matchinator'
27
27
  require 'ceedling/defineinator'
28
28
 
@@ -249,7 +249,7 @@ describe 'Module Generator plugin (integration)' do
249
249
  File.write( 'src/old/a_file.c', '' )
250
250
  plugin = plugin_for( config )
251
251
  loginator = plugin.instance_variable_get( :@ceedling )[:loginator]
252
- expect(loginator).to receive(:log).with( /`src\/a_file.c`.*`src\/old\/a_file.c`/, anything, anything )
252
+ expect(loginator).to receive(:log).with( /`src\/a_file.c`.*`src\/old\/a_file.c`/, Verbosity::COMPLAIN )
253
253
 
254
254
  capture_stdout { plugin.create( ModuleGeneratorRequest.new( name: 'a_file' ) ) }
255
255
 
@@ -0,0 +1,99 @@
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
+ # Per-test logs placed by a test's name, written with real file I/O in a temporary project.
9
+ # A test's name is its path from the project root, so its logs sit in subdirectories that
10
+ # must exist before anything writes there (GH #1364). Same-named tests keep separate gdb
11
+ # logs, each holding only its latest build's crash.
12
+
13
+ require 'spec_helper'
14
+ require 'tmpdir'
15
+ require 'ceedling/constants'
16
+ require 'ceedling/plugins/plugin'
17
+ require 'ceedling/filesystem/file_wrapper'
18
+ require 'ceedling/filesystem/file_path_utils'
19
+ require 'ceedling/build_log_writer'
20
+
21
+ $LOAD_PATH.unshift( File.expand_path( '../../plugins/report_tests_raw_output_log/lib', __dir__ ) )
22
+ $LOAD_PATH.unshift( File.expand_path( '../../plugins/valgrind/lib', __dir__ ) )
23
+
24
+ # Ceedling runtime path constants the plugins need at require time
25
+ PROJECT_BUILD_ROOT = 'build' unless defined?(PROJECT_BUILD_ROOT)
26
+ PROJECT_BUILD_ARTIFACTS_ROOT = 'artifacts' unless defined?(PROJECT_BUILD_ARTIFACTS_ROOT)
27
+ PROJECT_TEST_RESULTS_PATH = 'build/test/results' unless defined?(PROJECT_TEST_RESULTS_PATH)
28
+
29
+ require 'report_tests_raw_output_log'
30
+ require 'valgrind'
31
+
32
+ describe 'Per-test logs of nested tests (integration)' do
33
+ let(:loginator) { double( 'loginator', log: nil ) }
34
+ let(:file_wrapper) { FileWrapper.new( { loginator: loginator, verbosinator: double( 'verbosinator', should_output?: false ) } ) }
35
+
36
+ def in_project
37
+ Dir.mktmpdir( 'nested' ) do |root|
38
+ Dir.chdir( root ) do
39
+ stub_const( 'PROJECT_BUILD_ARTIFACTS_ROOT', 'build/artifacts' )
40
+ stub_const( 'VALGRIND_ARTIFACTS_PATH', 'build/artifacts/valgrind' )
41
+ yield
42
+ end
43
+ end
44
+ end
45
+
46
+ it 'writes the raw-output log of a test below its root' do
47
+ in_project do
48
+ objects = { file_wrapper: file_wrapper, loginator: loginator, reportinator: double( 'reportinator', generate_heading: '', generate_progress: '' ) }
49
+ plugin = ReportTestsRawOutputLog.new( objects, 'report_tests_raw_output_log', '/plugins/report_tests_raw_output_log' )
50
+
51
+ plugin.post_test_fixture_execute( context: :test, test_name: 'test/unit/test_calc', shell_result: { output: "hello\n" } )
52
+ plugin.post_build( 0 )
53
+
54
+ expect( File.read( 'build/artifacts/test/test/unit/test_calc.raw.log' ) ).to include( 'hello' )
55
+ end
56
+ end
57
+
58
+ # Valgrind writes its own report at the --log-file path a build hands it
59
+ it "reads the Valgrind report of a test below its root" do
60
+ in_project do
61
+ stub_const( 'TOOLS_VALGRIND', { name: 'valgrind', executable: 'valgrind', arguments: [] } )
62
+ valgrind = Valgrind.allocate
63
+ {
64
+ configurator: double( 'configurator', project_config_hash: {} ), loginator: loginator, file_wrapper: file_wrapper,
65
+ dependinator: double( 'dependinator', register: nil ), mutex: Mutex.new, result_list: [], memory_errors: 0,
66
+ tests_processed: 0, reports_read: 0, explained: []
67
+ }.each { |name, value| valgrind.instance_variable_set( "@#{name}", value ) }
68
+
69
+ arg_hash = { context: VALGRIND_SYM, test_name: 'test/unit/test_calc', target: 'build/valgrind/out/test/unit/test_calc/test_calc.out', tool: {} }
70
+ valgrind.pre_test_fixture_register( arg_hash )
71
+
72
+ report = arg_hash[:tool][:arguments].find { |argument| argument.start_with?( '--log-file=' ) }[/"(.+)"/, 1]
73
+ File.write( report, "==1== ERROR SUMMARY: 2 errors from 2 contexts\n" )
74
+
75
+ valgrind.post_test_fixture_execute( context: VALGRIND_SYM, test_name: 'test/unit/test_calc', result_file: 'test_calc.pass' )
76
+
77
+ expect( report ).to eq( 'build/artifacts/valgrind/test/unit/test_calc.log' )
78
+ expect( valgrind.instance_variable_get( :@reports_read ) ).to eq( 1 )
79
+ expect( valgrind.instance_variable_get( :@memory_errors ) ).to eq( 2 )
80
+ end
81
+ end
82
+
83
+ it 'keeps the gdb logs of same-named tests apart, each holding only the latest build' do
84
+ in_project do
85
+ paths = FilePathUtils.new( configurator: double( 'configurator', project_log_path: 'build/logs' ), file_wrapper: file_wrapper )
86
+ logs = ['test/a/test_crash', 'test/b/test_crash'].map { |name| paths.form_test_gdb_log( name, context: :test, name: 'test_boom' ) }
87
+
88
+ 2.times do |build|
89
+ writer = BuildLogWriter.new( file_wrapper: file_wrapper )
90
+ logs.each { |log| writer.write( log, "=== test_boom ===\nbuild #{build} #{log}\n" ) }
91
+ end
92
+
93
+ expect( logs.uniq.size ).to eq( 2 )
94
+ logs.each do |log|
95
+ expect( File.read( log ) ).to eq( "=== test_boom ===\nbuild 1 #{log}\n" )
96
+ end
97
+ end
98
+ end
99
+ end
@@ -20,11 +20,11 @@
20
20
  # sharing a basename in different directories.
21
21
 
22
22
  require 'spec_helper'
23
- require 'ceedling/file_finder'
24
- require 'ceedling/file_finder_helper'
23
+ require 'ceedling/filesystem/file_finder'
24
+ require 'ceedling/filesystem/file_finder_helper'
25
25
  require 'ceedling/filename_extension'
26
- require 'ceedling/path_matcher'
27
- require 'ceedling/file_path_utils'
26
+ require 'ceedling/filesystem/path_matcher'
27
+ require 'ceedling/filesystem/file_path_utils'
28
28
  require 'ceedling/constants'
29
29
 
30
30
  describe 'Partial module resolution (integration)' do
@@ -50,6 +50,7 @@ describe 'Partial module resolution (integration)' do
50
50
  allow(@configurator).to receive(:extension_source).and_return( FilenameExtension.new('.c') )
51
51
  allow(@configurator).to receive(:collection_all_headers).and_return( RESOLUTION_HEADERS )
52
52
  allow(@configurator).to receive(:collection_all_source).and_return( RESOLUTION_SOURCES )
53
+ allow(@configurator).to receive(:collection_all_tests).and_return( [] )
53
54
 
54
55
  @finder = FileFinder.new({
55
56
  :configurator => @configurator,
@@ -134,6 +135,8 @@ describe 'Partial module resolution (integration)' do
134
135
  before(:each) do
135
136
  allow(@configurator).to receive(:project_build_root).and_return('build')
136
137
  allow(@configurator).to receive(:paths_include).and_return( ['include/**'] )
138
+ allow(@configurator).to receive(:collection_mirror_roots_include).and_return( ['include'] )
139
+ allow(@configurator).to receive(:collection_mirror_roots_headers).and_return( ['include'] )
137
140
  allow(@configurator).to receive(:paths_source).and_return( ['src/**'] )
138
141
  allow(@configurator).to receive(:paths_support).and_return( [] )
139
142
  allow(@configurator).to receive(:release_build_use_assembly).and_return( false )