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,74 @@
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 'ceedling/exceptions'
9
+
10
+ # Coverage thresholds a gcovr run violated, one message each
11
+ class GcovrThresholdError < CeedlingException
12
+
13
+ attr_reader :violations
14
+
15
+ def initialize(violations)
16
+ @violations = violations
17
+ super( violations.join( "\n" ) )
18
+ end
19
+
20
+ end
21
+
22
+ # Decodes gcovr's exit status and stderr into the :fail_under_* thresholds a run violated.
23
+ # Each violated threshold sets a bit of the exit status and writes a line of its own to
24
+ # stderr. Bit 8 covers both condition and decision coverage, which from gcovr 8.7 may
25
+ # each write a line.
26
+ module GcovrThresholds
27
+
28
+ BITS = {
29
+ 2 => { option: :fail_under_line, label: 'Line', kinds: ['line'] },
30
+ 4 => { option: :fail_under_branch, label: 'Branch', kinds: ['branch'] },
31
+ 8 => { option: :fail_under_decision, label: 'Condition or decision', kinds: ['condition', 'decision'] },
32
+ 16 => { option: :fail_under_function, label: 'Function', kinds: ['function'] },
33
+ }.freeze
34
+
35
+ MESSAGE_PATTERN = /^\(?error\)?:?\s+(failed minimum (\w+) coverage.*?)\s*$/i
36
+
37
+ # Returns the violation messages, and the exit status bits no configured threshold explains
38
+ def self.decode(opts:, exitcode:, stderr:)
39
+ messages = messages_by_kind( stderr )
40
+ violations = []
41
+
42
+ BITS.each do |bit, threshold|
43
+ next unless (exitcode & bit) == bit && !opts[threshold[:option]].nil?
44
+
45
+ violations.concat( violations_for( threshold, opts, messages ) )
46
+ exitcode &= ~bit
47
+ end
48
+
49
+ return violations, exitcode
50
+ end
51
+
52
+ # gcovr's own messages, grouped by the coverage kind each names. Older gcovr writes them in
53
+ # lowercase, so the first letter is capitalized, and nothing else is touched.
54
+ def self.messages_by_kind(stderr)
55
+ messages = Hash.new { |hash, kind| hash[kind] = [] }
56
+
57
+ stderr.to_s.each_line do |line|
58
+ match = line.match( MESSAGE_PATTERN )
59
+ messages[match[2].downcase] << match[1].sub( /\A./ ) { |first| first.upcase } if match
60
+ end
61
+
62
+ return messages
63
+ end
64
+
65
+ def self.violations_for(threshold, opts, messages)
66
+ found = threshold[:kinds].flat_map { |kind| messages[kind] }
67
+ found = ["#{threshold[:label]} coverage is less than the configured minimum of #{opts[threshold[:option]]}%"] if found.empty?
68
+
69
+ return found.map { |message| "Gcovr ⏩️ #{message}" }
70
+ end
71
+
72
+ private_class_method :messages_by_kind, :violations_for
73
+
74
+ end
@@ -8,7 +8,7 @@
8
8
  require 'benchmark'
9
9
  require 'ceedling/constants'
10
10
  require 'ceedling/exceptions'
11
- require 'ceedling/file_path_utils'
11
+ require 'ceedling/filesystem/file_path_utils'
12
12
  require 'gcov_reportinator'
13
13
 
14
14
  class ReportGeneratorReportinator < GcovReportinator
@@ -110,7 +110,7 @@ class ModuleGenerator < Plugin
110
110
 
111
111
  @ceedling[:loginator].log(
112
112
  'Module Generator :update_svn is deprecated and ignored. Add generated files to source control with your own tools.',
113
- Verbosity::COMPLAIN, LogLabels::WARNING
113
+ Verbosity::COMPLAIN
114
114
  )
115
115
  end
116
116
 
@@ -119,7 +119,7 @@ class ModuleGenerator < Plugin
119
119
  project.same_named( files.map { |file| file[:path].to_s } ).each do |planned, existing|
120
120
  @ceedling[:loginator].log(
121
121
  "Module file `#{planned}` shares its name with #{existing.map { |path| "`#{path}`" }.join( ', ' )}.",
122
- Verbosity::COMPLAIN, LogLabels::WARNING
122
+ Verbosity::COMPLAIN
123
123
  )
124
124
  end
125
125
  end
@@ -133,7 +133,7 @@ class ModuleGenerator < Plugin
133
133
  @ceedling[:loginator].log(
134
134
  "Generated test `#{path}` is wrapped in `##{options.test_guard} #{define}`, but its build does not " \
135
135
  "define #{define}. Add it under :defines ↳ :test, or the test compiles to nothing.",
136
- Verbosity::COMPLAIN, LogLabels::WARNING
136
+ Verbosity::COMPLAIN
137
137
  )
138
138
  end
139
139
  end
@@ -39,18 +39,13 @@ class ReportTestsTeamcityStdout < Plugin
39
39
  def pre_test(test)
40
40
  return if !@output_enabled
41
41
 
42
- # Generate a new Flow ID and store it in test hash
42
+ # Generate a new Flow ID and open the test's suite. A suite is named for its test,
43
+ # which tells same-named tests in different directories apart.
43
44
  @mutex.synchronize do
44
45
  @flowid_count += 1
45
- @suites[test] = { :flowid => @flowid_count }
46
- end
46
+ @suites[test] = { :flowid => @flowid_count, :name => escape( @ceedling[:file_path_utils].form_test_name( test ) ) }
47
47
 
48
- # Generate first TeamCity service message
49
- @mutex.synchronize do
50
- teamcity_service_message(
51
- "testSuiteStarted name='#{File.basename(test, '.*')}'",
52
- @suites[test][:flowid]
53
- )
48
+ teamcity_service_message( "testSuiteStarted name='#{@suites[test][:name]}'", @suites[test][:flowid] )
54
49
  end
55
50
  end
56
51
 
@@ -58,103 +53,81 @@ class ReportTestsTeamcityStdout < Plugin
58
53
  def post_test_fixture_execute(arg_hash)
59
54
  return if !@output_enabled
60
55
 
61
- flowId = nil
62
- test_key = arg_hash[:test_filepath]
63
-
64
- # Get unique Flow ID
65
- @mutex.synchronize do
66
- flowId = @suites[test_key][:flowid]
67
- end
56
+ flowId = @mutex.synchronize { @suites[arg_hash[:test_filepath]][:flowid] }
68
57
 
69
58
  # Gather test results for this test executable
70
59
  results = @ceedling[:plugin_reportinator].assemble_test_results( [arg_hash[:result_file]] )
71
-
72
- # Apportion total run time of test executable equally to each test case within it.
73
- duration_ms = results[:total_time] * 1000.0
74
- avg_duration = (duration_ms / [1, results[:counts][:passed] + results[:counts][:failed]].max).round
60
+ duration = average_duration( results )
75
61
 
76
62
  context = arg_hash[:context]
77
63
 
78
- # Handle test case successes within the test executable
79
- results[:successes].each do |success|
80
- filepath = File.join( success[:source][:dirname], File.basename( success[:source][:basename], '.*' ) )
64
+ report_successes( results[:successes], context, flowId, duration )
65
+ report_failures( results[:failures], context, flowId, duration )
66
+ report_ignores( results[:ignores], context, flowId )
67
+ end
81
68
 
82
- # puts(success)
83
- success[:collection].each do |test|
84
- _test = test[:test]
85
-
86
- # Create Java-like name per TeamCity convention `package_or_namespace.ClassName.TestName`
87
- # ==> `context.TestFilepath.TestCaseName`
88
- teamcity_service_message(
89
- "testStarted name='#{context}.#{filepath}.#{_test}'",
90
- flowId
91
- )
92
-
93
- teamcity_service_message(
94
- "testFinished name='#{context}.#{filepath}.#{_test}' duration='#{avg_duration}'",
95
- flowId
96
- )
97
- end
69
+ # `Plugin` build step hook
70
+ def post_test(test)
71
+ return if !@output_enabled
72
+
73
+ @mutex.synchronize do
74
+ teamcity_service_message(
75
+ "testSuiteFinished name='#{@suites[test][:name]}'",
76
+ @suites[test][:flowid]
77
+ )
98
78
  end
79
+ end
99
80
 
100
- # Handle test case failures within the test executable
101
- results[:failures].each do |failure|
102
- failure[:collection].each do |test|
103
- filepath = File.join( failure[:source][:dirname], File.basename( failure[:source][:basename], '.*' ) )
81
+ ### Private
104
82
 
105
- _test = test[:test]
106
- _message = test[:message]
83
+ private
107
84
 
108
- teamcity_service_message(
109
- "testStarted name='#{context}.#{filepath}.#{_test}'",
110
- flowId
111
- )
85
+ # Total run time of a test executable, apportioned equally to each test case within it, in ms
86
+ def average_duration(results)
87
+ duration_ms = results[:total_time] * 1000.0
112
88
 
113
- # Create Java-like name per TeamCity convention `package_or_namespace.ClassName.TestName`
114
- # ==> `context.TestFilepath.TestCaseName`
115
- _message =
116
- "testFailed name='#{context}.#{filepath}.#{_test}' " +
117
- "message='#{escape(_message)}' " +
118
- "details='File: #{failure[:source][:file]} Line: #{test[:line]}'"
89
+ return (duration_ms / [1, results[:counts][:passed] + results[:counts][:failed]].max).round
90
+ end
119
91
 
120
- teamcity_service_message( _message, flowId )
92
+ def report_successes(successes, context, flowId, duration)
93
+ successes.each do |success|
94
+ success[:collection].each do |test|
95
+ name = test_name( context, success[:source], test[:test] )
121
96
 
122
- teamcity_service_message(
123
- "testFinished name='#{context}.#{filepath}.#{_test}' duration='#{avg_duration}'",
124
- flowId
125
- )
97
+ teamcity_service_message( "testStarted name='#{name}'", flowId )
98
+ teamcity_service_message( "testFinished name='#{name}' duration='#{duration}'", flowId )
126
99
  end
127
100
  end
101
+ end
128
102
 
129
- # Handle ignored tests
130
- results[:ignores].each do |ignored|
131
- ignored[:collection].each do |test|
132
- filepath = File.join( ignored[:source][:dirname], File.basename( ignored[:source][:basename], '.*' ) )
133
- _test = test[:test]
134
-
135
- service_message = "testIgnored name='#{context}.#{filepath}.#{_test}'"
103
+ def report_failures(failures, context, flowId, duration)
104
+ failures.each do |failure|
105
+ failure[:collection].each do |test|
106
+ name = test_name( context, failure[:source], test[:test] )
107
+ details = escape( "File: #{failure[:source][:file]} Line: #{test[:line]}" )
136
108
 
137
- teamcity_service_message( service_message, flowId )
109
+ teamcity_service_message( "testStarted name='#{name}'", flowId )
110
+ teamcity_service_message( "testFailed name='#{name}' message='#{escape( test[:message] )}' details='#{details}'", flowId )
111
+ teamcity_service_message( "testFinished name='#{name}' duration='#{duration}'", flowId )
138
112
  end
139
113
  end
140
-
141
114
  end
142
115
 
143
- # `Plugin` build step hook
144
- def post_test(test)
145
- return if !@output_enabled
146
-
147
- @mutex.synchronize do
148
- teamcity_service_message(
149
- "testSuiteFinished name='#{File.basename(test, '.*')}'",
150
- @suites[test][:flowid]
151
- )
116
+ def report_ignores(ignores, context, flowId)
117
+ ignores.each do |ignored|
118
+ ignored[:collection].each do |test|
119
+ teamcity_service_message( "testIgnored name='#{test_name( context, ignored[:source], test[:test] )}'", flowId )
120
+ end
152
121
  end
153
122
  end
154
123
 
155
- ### Private
124
+ # A Java-like name per TeamCity convention `package_or_namespace.ClassName.TestName`
125
+ # ==> `context.TestFilepath.TestCaseName`, escaped
126
+ def test_name(context, source, test)
127
+ filepath = File.join( source[:dirname], File.basename( source[:basename], '.*' ) )
156
128
 
157
- private
129
+ return escape( "#{context}.#{filepath}.#{test}" )
130
+ end
158
131
 
159
132
  def escape(string)
160
133
  # https://www.jetbrains.com/help/teamcity/service-messages.html#Escaped+Values
@@ -6,6 +6,7 @@
6
6
  # =========================================================================
7
7
 
8
8
  require 'ceedling/constants'
9
+ require 'ceedling/build_log_writer'
9
10
  require 'sanitize_constants'
10
11
  require 'sanitize_reports'
11
12
 
@@ -20,7 +21,7 @@ class SanitizeRecords
20
21
  @loginator = loginator
21
22
  @reports = reports
22
23
  @records = []
23
- @logged_tests = []
24
+ @log_writer = BuildLogWriter.new( file_wrapper: file_wrapper )
24
25
  @written = []
25
26
  @mutex = Mutex.new
26
27
  end
@@ -101,11 +102,7 @@ class SanitizeRecords
101
102
 
102
103
  # A build's first report for a test replaces the last build's log, and later ones follow it
103
104
  def write_log(log, findings)
104
- first = @mutex.synchronize { !@logged_tests.include?( log ) && @logged_tests << log }
105
- text = findings.map( &:text ).join( "\n" )
106
-
107
- @file_wrapper.mkdir( File.dirname( log ) )
108
- @file_wrapper.write( log, first ? text : "\n#{text}", first ? 'w' : 'a' )
105
+ @log_writer.write( log, findings.map( &:text ).join( "\n" ), separator: "\n" )
109
106
  end
110
107
 
111
108
  def pluralize(count, word)
@@ -152,7 +152,7 @@ class Valgrind < Plugin
152
152
 
153
153
  test_name = arg_hash[:test_name]
154
154
  path = report_filepath( test_name )
155
- return unless @file_wrapper.exist?( path )
155
+ return unless report_written?( path )
156
156
 
157
157
  cause = ValgrindReport.first_error( @file_wrapper.read( path ), xml: xml_report_enabled? )
158
158
  return if cause.nil?
@@ -230,7 +230,14 @@ class Valgrind < Plugin
230
230
  return xml_report_enabled? ? xml_filepath( test_name ) : log_filepath( test_name )
231
231
  end
232
232
 
233
- # Assembles the full Valgrind argument list for one test.
233
+ # Valgrind wrote the report moments ago in another process, so a miss is retried before
234
+ # it is believed
235
+ def report_written?(path)
236
+ return @file_wrapper.exist_with_retry?( path )
237
+ end
238
+
239
+ # Assembles the full Valgrind argument list for one test, making the directories its
240
+ # reports go in. A nested test's reports sit in subdirectories, and Valgrind makes none.
234
241
  #
235
242
  # Suppression files lead so a user's own :arguments entries can still override
236
243
  # anything they set. `${1}` is the test executable substitution token and is always
@@ -240,15 +247,15 @@ class Valgrind < Plugin
240
247
 
241
248
  arguments = Array( config[:valgrind_suppressions] ).map { |file| "--suppressions=\"#{file}\"" }
242
249
 
243
- arguments << "--log-file=\"#{log_filepath( test_name )}\""
250
+ arguments << "--log-file=\"#{@file_wrapper.mkdir_for( log_filepath( test_name ) )}\""
244
251
 
245
252
  if xml_report_enabled?
246
253
  arguments << '--xml=yes'
247
- arguments << "--xml-file=\"#{xml_filepath( test_name )}\""
254
+ arguments << "--xml-file=\"#{@file_wrapper.mkdir_for( xml_filepath( test_name ) )}\""
248
255
  end
249
256
 
250
257
  arguments += Array( config[:valgrind_arguments] )
251
- arguments << '${1}'
258
+ arguments << '"${1}"'
252
259
 
253
260
  return arguments
254
261
  end
@@ -260,11 +267,11 @@ class Valgrind < Plugin
260
267
  def count_errors(test_name)
261
268
  path = report_filepath( test_name )
262
269
 
263
- unless @file_wrapper.exist?( path )
270
+ unless report_written?( path )
264
271
  # A silent skip here reads exactly like a clean result. It is not one. The
265
272
  # memory error status of this test is unknown.
266
273
  msg = "Valgrind wrote no report for #{test_name} at #{path}. Memory error status is unknown."
267
- @loginator.log( msg, Verbosity::COMPLAIN, LogLabels::WARNING )
274
+ @loginator.log( msg, Verbosity::COMPLAIN )
268
275
  return nil
269
276
  end
270
277
 
@@ -4586,7 +4586,8 @@ for more details.</p>
4586
4586
  <p><code>:unity_helper_path</code> may be a single string or a list. Each value must be a
4587
4587
  relative path from your Ceedling working directory to a Unity helper header file
4588
4588
  (these are typically organized within containing Ceedling <code>:paths</code> ↳ <code>:support</code>
4589
- directories).</p>
4589
+ directories). A test build compiles the source file beside each helper header,
4590
+ of the same name, when one exists.</p>
4590
4591
  <p><strong>Default</strong>: <code>[]</code> (empty)</p>
4591
4592
  <h2 id="includes"><code>:includes</code></h2>
4592
4593
  <p>In certain advanced testing scenarios, you may need to inject additional header
@@ -4673,8 +4673,13 @@ builds.</p>
4673
4673
  <p><strong>Default</strong>: <code>[]</code> (empty)</p>
4674
4674
  <h2 id="files-options-notes"><code>:files</code> options &amp; notes</h2>
4675
4675
  <ol>
4676
- <li>A path can be absolute (fully qualified) or relative.</li>
4677
- <li>A path can include a glob matcher (more on this below).</li>
4676
+ <li>A path can be absolute (fully qualified) or relative. A relative path is relative to
4677
+ the working directory, where you run <code>ceedling</code>.</li>
4678
+ <li><code>~</code> at the start of a path names your home directory.</li>
4679
+ <li>A path can include a glob matcher (more on this below). A glob based above the build
4680
+ root, such as <code>+:**/*.c</code>, adds nothing from it.</li>
4681
+ <li>An entry within the build root adds from it with a warning, but no entry adds a file
4682
+ from the directories Ceedling and its plugins create there, or from the mocks directory.</li>
4678
4683
  <li>A path can use <a href="../project-file.html#inline-ruby-string-expansion">inline Ruby string expansion</a>.</li>
4679
4684
  <li>Subtractive paths prepended with a <code>-:</code> decorator are possible and useful.
4680
4685
  See the documentation below.</li>
@@ -4708,7 +4713,8 @@ that they ignore directory paths. Only filepaths are recognized.</p>
4708
4713
  <h2 id="subtractive-files-entries">Subtractive <code>:files</code> entries</h2>
4709
4714
  <p>Tailoring a file collection includes adding to it but also subtracting from it.</p>
4710
4715
  <p>Put simply, with an optional preceding decorator <code>-:</code>, you can instruct Ceedling
4711
- to remove certain file paths from a collection after it builds that collection.</p>
4716
+ to remove certain file paths from a collection after it builds that collection.
4717
+ A subtractive entry that names no file logs a warning, except below the build root.</p>
4712
4718
  <p>By default, paths are additive. For pretty alignment in your YAML, you may also
4713
4719
  use <code>+:</code>, but strictly speaking, it’s not necessary.</p>
4714
4720
  <p>Subtractive paths may be simple paths or globs just like any other path entry.</p>
@@ -4528,14 +4528,32 @@ command line argument will be <code>-lm</code>.</p>
4528
4528
  <p><strong>Default</strong>: <code>-l${1}</code> (GCC format)</p>
4529
4529
  <h2 id="path_flag"><code>:path_flag</code></h2>
4530
4530
  <p>Command line argument format for adding a library search path.</p>
4531
- <p>Library search paths may be added to your project with <code>:paths</code> ↳ <code>:libraries</code>.</p>
4531
+ <p>Library search paths may be added to your project with <code>:paths</code> ↳ <code>:libraries</code>.
4532
+ Each directory those entries collect becomes one argument, as for any <code>:paths</code>
4533
+ entry. A glob names each directory it matches, and a <code>-:</code> entry removes
4534
+ directories. An entry that collects no existing directory adds no argument.</p>
4532
4535
  <p><strong>Default</strong>: <code>-L "${1}"</code> (GCC format)</p>
4533
4536
  <h2 id="libraries-notes"><code>:libraries</code> notes</h2>
4534
4537
  <ul>
4535
- <li>If you've specified your own link step, you are going to want to add <code>${4}</code> to
4538
+ <li>
4539
+ <p>A <a href="../../getting-started/builds.html#delta-build-special-cases">delta build</a>
4540
+ relinks when a library file entry in <code>:libraries</code> changes names or paths.
4541
+ A library Ceedling cannot find, such as one internal to your toolchain’s
4542
+ search paths, is not tracked. Ceedling looks for named libraries within
4543
+ <code>:paths</code> ↳ <code>:libraries</code>:</p>
4544
+ <ul>
4545
+ <li>A bare name such as <code>m</code> as <code>libm.a</code>, <code>libm.so</code>, and the other typical
4546
+ names toolchains use.</li>
4547
+ <li>An entry such as <code>:libm.a</code> as that exact filename.</li>
4548
+ <li>And a full filepath as itself.</li>
4549
+ </ul>
4550
+ </li>
4551
+ <li>
4552
+ <p>If you've specified your own link step, you are going to want to add <code>${4}</code> to
4536
4553
  your argument list in the position where library files should be added to the
4537
4554
  command line. For <code>gcc</code>, this is often at the very end. Other tools may vary.
4538
- See the <code>:tools</code> section for more.</li>
4555
+ See the <code>:tools</code> section for more.</p>
4556
+ </li>
4539
4557
  </ul>
4540
4558
  <p><br/><br/></p>
4541
4559
 
@@ -4831,7 +4831,19 @@ files contained in those paths. A custom list is just that — a custom list of
4831
4831
  paths.</p>
4832
4832
  <h2 id="paths-configuration-options-notes"><code>:paths</code> configuration options &amp; notes</h2>
4833
4833
  <ol>
4834
- <li>A path can be absolute (fully qualified) or relative.</li>
4834
+ <li>A path can be absolute (fully qualified) or relative. A relative path is relative to
4835
+ the working directory, where you run <code>ceedling</code>, not to your project file’s
4836
+ directory. For a project file named with <code>--project</code> from another directory, write
4837
+ its paths relative to that other directory.</li>
4838
+ <li><code>~</code> at the start of a path names your home directory. <code>~user</code> is a directory named
4839
+ <code>~user</code>.</li>
4840
+ <li>A path reached through a symlink names the place the symlink leads to, so two
4841
+ entries reaching one directory collect it once. Directories found below an entry
4842
+ keep the spelling they are found by, as an <code>#include</code> reaches them.</li>
4843
+ <li>An entry based above the build root, such as <code>./**</code> or <code>../**</code>, collects nothing
4844
+ from it. An entry within the build root collects from it with a warning, but no entry
4845
+ collects from the directories Ceedling and its plugins create, such as <code>test/</code>,
4846
+ <code>release/</code>, <code>vendor/</code>, and <code>artifacts/</code> below the build root, or the mocks directory.</li>
4835
4847
  <li>A path can include a glob matcher (more on this below).</li>
4836
4848
  <li>A path can use <a href="../project-file.html#inline-ruby-string-expansion">inline Ruby string expansion</a>.</li>
4837
4849
  <li>Subtractive paths are possible and useful. See the documentation below.</li>
@@ -4883,6 +4895,17 @@ collection.</p>
4883
4895
  <p>By default, paths are additive. For pretty alignment in your YAML, you may also
4884
4896
  use <code>+:</code>, but strictly speaking, it’s not necessary.</p>
4885
4897
  <p>Subtractive paths may be simple paths or globs just like any other path entry.</p>
4898
+ <p>A subtractive entry removes the directories it names and every directory below them.
4899
+ An additive entry naming one of those directories more closely keeps it:</p>
4900
+ <div class="highlight"><pre><span></span><code><a id="__codelineno-5-1" name="__codelineno-5-1" href="#__codelineno-5-1"></a><span class="nt">:paths</span><span class="p">:</span>
4901
+ <a id="__codelineno-5-2" name="__codelineno-5-2" href="#__codelineno-5-2"></a><span class="w"> </span><span class="nt">:source</span><span class="p">:</span>
4902
+ <a id="__codelineno-5-3" name="__codelineno-5-3" href="#__codelineno-5-3"></a><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">src/**</span>
4903
+ <a id="__codelineno-5-4" name="__codelineno-5-4" href="#__codelineno-5-4"></a><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">-:src/legacy</span><span class="w"> </span><span class="c1"># Removes src/legacy/ and every directory below it...</span>
4904
+ <a id="__codelineno-5-5" name="__codelineno-5-5" href="#__codelineno-5-5"></a><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">src/legacy/keep</span><span class="w"> </span><span class="c1"># ...except src/legacy/keep/, which this entry names</span>
4905
+ </code></pre></div>
4906
+ <p>A subtractive entry that names nothing logs a warning, so a mistyped entry does
4907
+ not pass unnoticed. Below the build root, where nothing exists before a first
4908
+ build, it passes without a word.</p>
4886
4909
  <div class="admonition warning">
4887
4910
  <p class="admonition-title">Quote the whole entry, decoration included</p>
4888
4911
  <p>YAML keeps quote marks that begin partway through a value as part of the
@@ -4890,11 +4913,11 @@ value. Quoting only the path leaves quote marks in the path, and
4890
4913
  Ceedling rejects the entry. Quote an entry whenever it holds <code>#{…}</code>
4891
4914
  <a href="../project-file.html#inline-ruby-string-expansion">inline Ruby string expansion</a>, because YAML
4892
4915
  otherwise reads the <code>#</code> as the start of a comment.</p>
4893
- <div class="highlight"><pre><span></span><code><a id="__codelineno-5-1" name="__codelineno-5-1" href="#__codelineno-5-1"></a><span class="c1"># Correct</span>
4894
- <a id="__codelineno-5-2" name="__codelineno-5-2" href="#__codelineno-5-2"></a><span class="p p-Indicator">-</span><span class="w"> </span><span class="s">"-:#{ENV['SRC_ROOT']}/vendor/legacy"</span>
4895
- <a id="__codelineno-5-3" name="__codelineno-5-3" href="#__codelineno-5-3"></a>
4896
- <a id="__codelineno-5-4" name="__codelineno-5-4" href="#__codelineno-5-4"></a><span class="c1"># Incorrect -- the quote marks become part of the path</span>
4897
- <a id="__codelineno-5-5" name="__codelineno-5-5" href="#__codelineno-5-5"></a><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">-:"#{ENV['SRC_ROOT']}/vendor/legacy"</span>
4916
+ <div class="highlight"><pre><span></span><code><a id="__codelineno-6-1" name="__codelineno-6-1" href="#__codelineno-6-1"></a><span class="c1"># Correct</span>
4917
+ <a id="__codelineno-6-2" name="__codelineno-6-2" href="#__codelineno-6-2"></a><span class="p p-Indicator">-</span><span class="w"> </span><span class="s">"-:#{ENV['SRC_ROOT']}/vendor/legacy"</span>
4918
+ <a id="__codelineno-6-3" name="__codelineno-6-3" href="#__codelineno-6-3"></a>
4919
+ <a id="__codelineno-6-4" name="__codelineno-6-4" href="#__codelineno-6-4"></a><span class="c1"># Incorrect -- the quote marks become part of the path</span>
4920
+ <a id="__codelineno-6-5" name="__codelineno-6-5" href="#__codelineno-6-5"></a><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">-:"#{ENV['SRC_ROOT']}/vendor/legacy"</span>
4898
4921
  </code></pre></div>
4899
4922
  </div>
4900
4923
  <div class="admonition note">
@@ -4743,6 +4743,13 @@ output with the project name.</p>
4743
4743
  </code></pre></div></p>
4744
4744
  <h2 id="build_root"><code>:build_root</code></h2>
4745
4745
  <p>Top level directory into which generated path structure and files are placed.</p>
4746
+ <p><code>ceedling clobber</code> empties the build root’s test and release trees, so Ceedling refuses a
4747
+ build root that is empty, the project directory, or a directory above it.</p>
4748
+ <p>An entry based above the build root, such as the <code>:paths</code> entry <code>../**</code> or the <code>:files</code>
4749
+ glob <code>+:**/*.c</code>, collects nothing from it. A <code>:paths</code> or <code>:files</code> entry within the build
4750
+ root, such as one naming generated code in <code>build/gen</code>, collects from it with a warning.
4751
+ No entry collects from the directories Ceedling and its plugins create there, such as
4752
+ <code>test/</code>, <code>release/</code>, <code>vendor/</code>, and <code>artifacts/</code>.</p>
4746
4753
  <div class="admonition note">
4747
4754
  <p class="admonition-title">Build configuration requirement</p>
4748
4755
  <p>This is one of the handful of configuration values that must be set for
@@ -4855,9 +4862,11 @@ upon by test executables.</p>
4855
4862
  <p><strong>Default</strong>: 1</p>
4856
4863
  <h2 id="which_ceedling"><code>:which_ceedling</code></h2>
4857
4864
  <p>This is an advanced project option primarily meant for development work on
4858
- Ceedling itself. This setting tells the code that launches the Ceedling
4859
- application where to find the code to launch.</p>
4860
- <p>This entry can be either a directory path or <code>gem</code>.</p>
4865
+ Ceedling itself. This setting selects the Ceedling installation that runs
4866
+ your project’s commands. The <code>ceedling</code> command you run hands each command off to
4867
+ that installation’s own launcher.</p>
4868
+ <p>This entry can be either a directory path or <code>gem</code>. A relative path is
4869
+ relative to your working directory.</p>
4861
4870
  <p>See the section <a href="../which-ceedling.html">Which Ceedling</a> for full details.</p>
4862
4871
  <p><strong>Default</strong>: <code>gem</code></p>
4863
4872
  <h2 id="use_backtrace"><code>:use_backtrace</code></h2>
@@ -4941,9 +4950,10 @@ with an error at startup.</p>
4941
4950
  extracted from the <code>gdb</code> report. Ceedling will attempt to surface in the
4942
4951
  summary the offending line of code or failing <code>assert()</code> from the report.</p>
4943
4952
  <p>The full <code>gdb</code> report is captured to a log file, and the log filepath is
4944
- provided in the crash summary. The log filepath will comprise the containing
4945
- test executable as a subdirectory and the name of the crashing test case
4946
- function as the filename.</p>
4953
+ provided in the crash summary. The log filepath comprises the <a href="../../testing-guide/conventions.html#test-names-build-output">test’s name</a>,
4954
+ its path from your project’s root, as a subdirectory plus the name of the crashing
4955
+ test case function as the filename. A build that logs a test case’s crash replaces
4956
+ that log; a log holds only the latest crash.</p>
4947
4957
  <div class="admonition warning">
4948
4958
  <p class="admonition-title">macOS: a working <code>gdb</code> can stop attaching to processes</p>
4949
4959
  <p>macOS restricts which debuggers may attach to a process. A Homebrew <code>gdb</code>
@@ -4969,7 +4979,7 @@ build. To restore <code>:gdb</code> backtraces, re-codesign <code>gdb</code> fol
4969
4979
  <a id="__codelineno-6-10" name="__codelineno-6-10" href="#__codelineno-6-10"></a> Test: testCrash
4970
4980
  <a id="__codelineno-6-11" name="__codelineno-6-11" href="#__codelineno-6-11"></a> At line (40): "Test case crashed &gt;&gt; [SIGSEGV] Segmentation fault
4971
4981
  <a id="__codelineno-6-12" name="__codelineno-6-12" href="#__codelineno-6-12"></a> `uint32_t i = *null_ptr;`
4972
- <a id="__codelineno-6-13" name="__codelineno-6-13" href="#__codelineno-6-13"></a> (build/logs/test/TestUsartModel/testCrash.gdb.log)"
4982
+ <a id="__codelineno-6-13" name="__codelineno-6-13" href="#__codelineno-6-13"></a> (build/logs/test/test/TestUsartModel/testCrash.gdb.log)"
4973
4983
  <a id="__codelineno-6-14" name="__codelineno-6-14" href="#__codelineno-6-14"></a>
4974
4984
  <a id="__codelineno-6-15" name="__codelineno-6-15" href="#__codelineno-6-15"></a>-----------------------
4975
4985
  <a id="__codelineno-6-16" name="__codelineno-6-16" href="#__codelineno-6-16"></a>❌ OVERALL TEST SUMMARY
@@ -4444,6 +4444,8 @@ precedence.</p>
4444
4444
  <em>&lt;build path&gt;/artifacts/release/</em>. Ceedling sets the default artifact
4445
4445
  file extension to that as is explicitly specified in the <code>:extension</code>
4446
4446
  section or as is system specific otherwise.</p>
4447
+ <p>An absolute path, or one beginning with <code>~</code>, names the release itself. Its
4448
+ map file sits beside it.</p>
4447
4449
  <p><strong>Default</strong>: <code>project.exe</code> or <code>project.out</code></p>
4448
4450
  <h2 id="use_assembly"><code>:use_assembly</code></h2>
4449
4451
  <p>This option causes Ceedling to enable an assembler tool and add any
@@ -5074,6 +5074,15 @@ the name quoted, add escaped quotes in the YAML:</p>
5074
5074
  <li>
5075
5075
  <p><code>:arguments</code> - List (array of strings) of command line arguments and
5076
5076
  substitutions (required).</p>
5077
+ <div class="admonition tip">
5078
+ <p class="admonition-title">Quote the paths your tools name</p>
5079
+ <p>Ceedling runs each tool’s command line through your system’s shell, which
5080
+ reads a space, an apostrophe, and other characters in a path as part of
5081
+ the command. Wrap each path argument in escaped quotes, as Ceedling’s
5082
+ own tools do, for example <code>"-c \"${1}\""</code>. Quoting protects most
5083
+ characters. On Linux and macOS, a path holding <code>"</code>, <code>$</code>, a backtick, or
5084
+ <code>\</code> can still break a command.</p>
5085
+ </div>
5077
5086
  </li>
5078
5087
  <li>
5079
5088
  <p><code>:name</code> - Simple name (i.e. "nickname") of tool beyond its executable name.