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
@@ -14,6 +14,8 @@ require 'ceedling/test_invoker/mock_locator'
14
14
  describe TestBuildSetup do
15
15
  before(:each) do
16
16
  @configurator = double( "Configurator" )
17
+ # Ceedling always defaults it, and the mock locator reads it
18
+ allow(@configurator).to receive(:cmock_mock_name_include_folder).and_return( true )
17
19
  @loginator = double( "Loginator" )
18
20
  @reportinator = double( "Reportinator" )
19
21
  @batchinator = double( "Batchinator" )
@@ -66,6 +68,9 @@ describe TestBuildSetup do
66
68
  allow(@configurator).to receive(:collection_paths_vendor).and_return( [] )
67
69
  allow(@configurator).to receive(:collection_paths_test_toolchain_include).and_return( [] )
68
70
 
71
+ @test_source_file_directive_resolver = double( "TestSourceFileDirectiveResolver" )
72
+ allow(@test_source_file_directive_resolver).to receive(:validate!)
73
+
69
74
  @mock_locator = MockLocator.new(
70
75
  configurator: @configurator, include_pathinator: @include_pathinator, file_finder: @file_finder, file_path_utils: @file_path_utils
71
76
  )
@@ -89,7 +94,8 @@ describe TestBuildSetup do
89
94
  :test_search_paths => TestSearchPaths.new(
90
95
  configurator: @configurator, include_pathinator: @include_pathinator, test_context_extractor: @test_context_extractor
91
96
  ),
92
- :mock_locator => @mock_locator
97
+ :mock_locator => @mock_locator,
98
+ :test_source_file_directive_resolver => @test_source_file_directive_resolver
93
99
  }
94
100
  )
95
101
 
@@ -119,15 +125,17 @@ describe TestBuildSetup do
119
125
  allow(@file_path_utils).to receive(:form_test_preprocess_files_directives_only_path).and_return( 'build/test/preprocess/directives/a_test' )
120
126
  allow(@file_path_utils).to receive(:form_test_preprocess_files_raw_directives_only_path).and_return( 'build/test/preprocess/raw/a_test' )
121
127
  allow(@file_path_utils).to receive(:form_test_preprocess_build_directives_path).and_return( 'build/test/preprocess/build_directives/a_test' )
128
+ allow(@file_path_utils).to receive(:form_test_name) { |filepath| filepath.to_s.ext( '' ).sub( '../', '_up_/' ) }
122
129
  allow(@file_wrapper).to receive(:mkdir)
130
+ allow(@configurator).to receive(:collection_all_tests).and_return( ['test/TestFoo.c'] )
123
131
  allow(@configurator).to receive(:project_use_mocks).and_return( false )
124
132
  allow(@configurator).to receive(:project_use_partials).and_return( false )
125
133
  allow(@configurator).to receive(:project_use_test_preprocessor).and_return( :none )
126
134
  end
127
135
 
128
- def prepare_state
136
+ def prepare_state(tests = ['test/TestFoo.c'])
129
137
  TestInvokerTypes::PipelineState.new(
130
- :tests => ['test/TestFoo.c'], :testables => {}, :context => :test, :options => [], :lock => Mutex.new
138
+ :tests => tests, :testables => {}, :context => :test, :options => [], :lock => Mutex.new
131
139
  )
132
140
  end
133
141
 
@@ -136,9 +144,53 @@ describe TestBuildSetup do
136
144
 
137
145
  @setup.stage_prepare_build_paths( state )
138
146
 
139
- testable = state.testables[:TestFoo]
147
+ testable = state.testables[:"test/TestFoo"]
140
148
  expect(testable.filepath).to eq( 'test/TestFoo.c' )
141
- expect(testable.name).to eq( 'TestFoo' )
149
+ expect(testable.name).to eq( 'test/TestFoo' )
150
+ end
151
+
152
+ # GH #1364: same-named tests at a root and below it
153
+ it "keeps same-named tests apart by their names" do
154
+ tests = ['test/test_calc.c', 'test/unit/test_calc.c']
155
+ allow(@configurator).to receive(:collection_all_tests).and_return( tests )
156
+ state = prepare_state( tests )
157
+
158
+ @setup.stage_prepare_build_paths( state )
159
+
160
+ expect(state.testables.keys).to contain_exactly( :'test/test_calc', :'test/unit/test_calc' )
161
+ expect(state.testables.values.map(&:filepath)).to contain_exactly( *tests )
162
+ end
163
+
164
+ # Two configured source extensions let one stem name two test files
165
+ it "stops a build with two test files differing only in extension, naming both" do
166
+ allow(@configurator).to receive(:collection_all_tests).and_return( ['test/test_a.c', 'test/test_a.cpp'] )
167
+
168
+ expect { @setup.stage_prepare_build_paths( prepare_state( ['test/test_a.c'] ) ) }.to raise_error( CeedlingException ) { |error|
169
+ expect(error.message).to include( 'test/test_a.c', 'test/test_a.cpp', '`test/test_a`' )
170
+ }
171
+ end
172
+
173
+ context "when two tests map to one name" do
174
+ before(:each) do
175
+ allow(@configurator).to receive(:collection_all_tests).and_return( ['../x/test_a.c', '_up_/x/test_a.c', 'test/test_b.c'] )
176
+ end
177
+
178
+ it "stops before making any directory or testable, naming both files" do
179
+ state = prepare_state( ['_up_/x/test_a.c'] )
180
+
181
+ expect(@file_wrapper).to_not receive(:mkdir)
182
+ expect { @setup.stage_prepare_build_paths( state ) }.to raise_error( CeedlingException ) { |error|
183
+ expect(error.message).to include( '../x/test_a.c', '_up_/x/test_a.c', '`_up_/x/test_a`' )
184
+ }
185
+ expect(state.testables).to be_empty
186
+ end
187
+
188
+ it "lets a build go ahead when neither test is in it" do
189
+ state = prepare_state( ['test/test_b.c'] )
190
+
191
+ expect { @setup.stage_prepare_build_paths( state ) }.to_not raise_error
192
+ expect(state.testables.keys).to eq( [:'test/test_b'] )
193
+ end
142
194
  end
143
195
 
144
196
  it "always assembles the build, results, dependencies, and runners paths" do
@@ -146,7 +198,7 @@ describe TestBuildSetup do
146
198
 
147
199
  @setup.stage_prepare_build_paths( state )
148
200
 
149
- paths = state.testables[:TestFoo].paths
201
+ paths = state.testables[:"test/TestFoo"].paths
150
202
  expect(paths[:build]).to eq( 'build/test/out/a_test' )
151
203
  expect(paths[:results]).to eq( 'build/test/results/a_test' )
152
204
  expect(paths[:dependencies]).to eq( 'build/test/dependencies/a_test' )
@@ -159,7 +211,7 @@ describe TestBuildSetup do
159
211
 
160
212
  @setup.stage_prepare_build_paths( state )
161
213
 
162
- expect(state.testables[:TestFoo].paths).to_not have_key( :mocks )
214
+ expect(state.testables[:"test/TestFoo"].paths).to_not have_key( :mocks )
163
215
  end
164
216
 
165
217
  it "assembles the mocks path when the project has mocking enabled" do
@@ -168,7 +220,7 @@ describe TestBuildSetup do
168
220
 
169
221
  @setup.stage_prepare_build_paths( state )
170
222
 
171
- expect(state.testables[:TestFoo].paths[:mocks]).to eq( 'build/test/mocks/a_test' )
223
+ expect(state.testables[:"test/TestFoo"].paths[:mocks]).to eq( 'build/test/mocks/a_test' )
172
224
  end
173
225
 
174
226
  it "omits the partials path when the project has Partials disabled" do
@@ -176,7 +228,7 @@ describe TestBuildSetup do
176
228
 
177
229
  @setup.stage_prepare_build_paths( state )
178
230
 
179
- expect(state.testables[:TestFoo].paths).to_not have_key( :partials )
231
+ expect(state.testables[:"test/TestFoo"].paths).to_not have_key( :partials )
180
232
  end
181
233
 
182
234
  it "assembles the partials path when the project has Partials enabled" do
@@ -185,7 +237,7 @@ describe TestBuildSetup do
185
237
 
186
238
  @setup.stage_prepare_build_paths( state )
187
239
 
188
- expect(state.testables[:TestFoo].paths[:partials]).to eq( 'build/test/partials/a_test' )
240
+ expect(state.testables[:"test/TestFoo"].paths[:partials]).to eq( 'build/test/partials/a_test' )
189
241
  end
190
242
 
191
243
  it "omits the preprocessing paths and scratch state when preprocessing is off" do
@@ -193,7 +245,7 @@ describe TestBuildSetup do
193
245
 
194
246
  @setup.stage_prepare_build_paths( state )
195
247
 
196
- testable = state.testables[:TestFoo]
248
+ testable = state.testables[:"test/TestFoo"]
197
249
  expect(testable.paths).to_not have_key( :preprocess_includes )
198
250
  expect(testable.preprocess).to_not have_key( :includes )
199
251
  end
@@ -204,7 +256,7 @@ describe TestBuildSetup do
204
256
 
205
257
  @setup.stage_prepare_build_paths( state )
206
258
 
207
- testable = state.testables[:TestFoo]
259
+ testable = state.testables[:"test/TestFoo"]
208
260
  expect(testable.paths[:preprocess_includes]).to eq( 'build/test/preprocess/includes/a_test' )
209
261
  expect(testable.paths[:preprocess_files]).to eq( 'build/test/preprocess/files/a_test' )
210
262
  expect(testable.paths[:preprocess_files_full_expansion]).to eq( 'build/test/preprocess/full/a_test' )
@@ -312,6 +364,38 @@ describe TestBuildSetup do
312
364
 
313
365
  @setup.stage_collect_test_context( @state )
314
366
  end
367
+
368
+ # Stage 11, which checks entries otherwise, does not run without test preprocessing
369
+ it "checks each test's TEST_SOURCE_FILE() entries once, under its own name, scanned or cached" do
370
+ expect(@test_source_file_directive_resolver).to receive(:validate!).with( test: 'a_test', test_filepath: 'test/TestFoo.c', context: :test ).twice
371
+
372
+ [true, false].each do |stale|
373
+ allow(@dependinator).to receive(:stale?).and_return( stale )
374
+ @setup.stage_collect_test_context( @state )
375
+ end
376
+ end
377
+ end
378
+
379
+ # Only a scan without test preprocessing caches TEST_SOURCE_FILE() entries, so switching
380
+ # modes must rescan rather than recall a cache missing them
381
+ it "caches build directives against the test preprocessing mode that scanned them" do
382
+ [true, false].each do |preprocessing|
383
+ allow(@configurator).to receive(:project_use_test_preprocessor_tests).and_return( preprocessing )
384
+ expect(@dependinator).to receive(:register).with(
385
+ 'build/preprocess/build_directives/a_test/Foo.c.yml', files: ['test/TestFoo.c'], meta: { source_files_scanned: !preprocessing }
386
+ )
387
+
388
+ @setup.stage_collect_test_context( @state )
389
+ end
390
+ end
391
+
392
+ it "leaves TEST_SOURCE_FILE() entries to stage 11 when test preprocessing is on" do
393
+ allow(@configurator).to receive(:project_use_test_preprocessor_tests).and_return( true )
394
+ allow(@dependinator).to receive(:stale?).and_return( true )
395
+
396
+ expect(@test_source_file_directive_resolver).to_not receive(:validate!)
397
+
398
+ @setup.stage_collect_test_context( @state )
315
399
  end
316
400
 
317
401
  it "logs one summary line stating how many test files' build directives were recalled from cache" do
@@ -124,6 +124,17 @@ describe TestContextExtractor do
124
124
  end
125
125
  end
126
126
 
127
+ # GH #1370 audit (G10): a TEST_INCLUDE_PATH() spelled another way gave its headers a
128
+ # second spelling beside the collection's own
129
+ context "#ingest_build_directive_include_paths" do
130
+ it "records each path in the one spelling every collection uses" do
131
+ @extractor.ingest_build_directive_include_paths( "path", ["./include/dir", "include\\other/", File.join( Dir.pwd, "inc" )] )
132
+
133
+ expect( @extractor.lookup_include_paths_list( "path" ) ).to eq( ["include/dir", "include/other", "inc"] )
134
+ expect( @extractor.lookup_all_include_paths ).to eq( ["include/dir", "include/other", "inc"] )
135
+ end
136
+ end
137
+
127
138
  context "#store_build_directives_cache and #load_build_directives_cache" do
128
139
  it "writes the currently known source files and include paths for a test file to the given cache filepath" do
129
140
  @extractor.ingest_build_directive_source_files( "path", ["extra.c"] )
@@ -174,6 +185,20 @@ describe TestContextExtractor do
174
185
  expect{ @extractor.collect_context( "path", StringIO.new(), :bad ) }.to raise_error( CeedlingException )
175
186
  end
176
187
 
188
+ # A #include in a branch that is off, or a `..` spelling the mock search paths reach, both
189
+ # build, so a climbing mock #include is read like any other
190
+ it "resolves a mock #include that climbs with `..` against the test file's directory" do
191
+ @extractor.collect_context( "test/test_c.c", StringIO.new( "#include \"../x/mock_foo.h\"\n" ), TestContextExtractor::Context::INCLUDES )
192
+
193
+ expect( @extractor.lookup_mock_header_includes_list( "test/test_c.c" ) ).to eq( [MockInclude.new( 'x/mock_foo.h' )] )
194
+ end
195
+
196
+ it "keeps a non-mock #include that climbs with `..`, resolved against the test file's directory" do
197
+ @extractor.collect_context( "test/test_c.c", StringIO.new( "#include \"../inc/x/foo.h\"\n" ), TestContextExtractor::Context::INCLUDES )
198
+
199
+ expect( @extractor.lookup_all_header_includes_list( "test/test_c.c" ) ).to eq( [UserInclude.new( 'inc/x/foo.h' )] )
200
+ end
201
+
177
202
  # collect_context() + lookup_all_header_includes_list() + lookup_mock_header_includes_list()
178
203
  it "should extract contents of #include directives" do
179
204
  filepath = "path/tests/test_file.c"
@@ -156,10 +156,26 @@ describe TestFilePreprocessinator do
156
156
  it "validates a test's TEST_SOURCE_FILE() entries through the resolver, regardless of staleness" do
157
157
  allow(@dependinator).to receive(:stale?).and_return( false )
158
158
 
159
- expect(@test_source_file_directive_resolver).to receive(:validate!).with( test: 'a_test', filepath: 'test/TestFoo.c' )
159
+ expect(@test_source_file_directive_resolver).to receive(:validate!).with( test: 'a_test', test_filepath: 'test/TestFoo.c', context: :test )
160
160
 
161
161
  @preprocessinator_stage.preprocess( @state )
162
162
  end
163
+
164
+ # Each test checks its own entries, not every test's
165
+ it "validates each test's entries once, under that test's own name" do
166
+ allow(@dependinator).to receive(:stale?).and_return( false )
167
+ others = %w[b_test c_test].to_h do |name|
168
+ [name.to_sym, @testable.dup.tap { |testable| testable.name = name; testable.filepath = "test/#{name}.c" }]
169
+ end
170
+ @state.testables.merge!( others )
171
+
172
+ checked = []
173
+ allow(@test_source_file_directive_resolver).to receive(:validate!) { |test:, test_filepath:, context:| checked << [test, test_filepath, context] }
174
+
175
+ @preprocessinator_stage.preprocess( @state )
176
+
177
+ expect(checked).to contain_exactly( ['a_test', 'test/TestFoo.c', :test], ['b_test', 'test/b_test.c', :test], ['c_test', 'test/c_test.c', :test] )
178
+ end
163
179
  end
164
180
 
165
181
  # The full expansion reads every header the test reaches, so a change to one of them
@@ -18,6 +18,8 @@ require 'ceedling/test_invoker/standin_headerinator'
18
18
  describe TestIncludesExtractinator do
19
19
  before(:each) do
20
20
  @configurator = double( "Configurator" )
21
+ # Ceedling always defaults it, and the mock locator reads it
22
+ allow(@configurator).to receive(:cmock_mock_name_include_folder).and_return( true )
21
23
  @loginator = double( "Loginator" )
22
24
  @reportinator = double( "Reportinator" )
23
25
  @batchinator = double( "Batchinator" )
@@ -393,8 +395,10 @@ describe TestIncludesExtractinator do
393
395
  allow(@file_wrapper).to receive(:exist?).and_return( false )
394
396
  allow(@file_wrapper).to receive(:mkdir)
395
397
  allow(@file_wrapper).to receive(:write)
396
- allow(@file_path_utils).to receive(:form_mock_header_filepath).and_return( 'build/test/mocks/a_test/MockFoo.h' )
397
398
  allow(@file_finder).to receive(:resolve_mock).and_return( ['src/Foo.h', ''] )
399
+ allow(@file_path_utils).to receive(:form_mock_output_path) { |root, subdir| subdir.to_s.empty? ? root : File.join( root, subdir ) }
400
+ # A test mocks only when its build mocks, which gives it a mock root
401
+ @testable.paths = { mocks: 'build/test/mocks/a_test' }
398
402
  end
399
403
 
400
404
  it "places a stand-in for each mock on a freshly extracted bare-includes list" do
@@ -19,10 +19,13 @@ describe 'Test pipeline object wiring' do
19
19
  test_invoker test_pipeline_manager test_build_setup test_includes_extractinator test_bare_includes_extractinator
20
20
  test_includes_preprocessinator test_includes_reconcilinator test_build_planner partials_manager
21
21
  test_build_executor test_file_preprocessinator test_runner_generatinator test_search_paths mock_locator
22
- standin_headerinator
23
- ].each do |name|
22
+ standin_headerinator test_source_file_directive_resolver
23
+ ].map { |name| [name, "ceedling/test_invoker/#{name}"] }.concat( [
24
+ ['build_log_writer', 'ceedling/build_log_writer'],
25
+ ['generator_test_results_backtrace', 'ceedling/generators/generator_test_results_backtrace']
26
+ ] ).each do |name, path|
24
27
  it "composes exactly what #{name}'s constructor takes" do
25
- require "ceedling/test_invoker/#{name}"
28
+ require path
26
29
  klass = Object.const_get( name.split( '_' ).map( &:capitalize ).join )
27
30
 
28
31
  expect(OBJECTS_WIRING.dig( name, 'compose' )).to match_array( klass.constructor_keys.map( &:to_s ) )
@@ -18,7 +18,9 @@ describe TestInvoker do
18
18
  @loginator = double( "Loginator" )
19
19
  @verbosinator = double( "Verbosinator" )
20
20
  @test_pipeline_manager = double( "TestPipelineManager" )
21
+ @include_pathinator = double( "IncludePathinator" )
21
22
 
23
+ allow(@include_pathinator).to receive(:forget_header_listings)
22
24
  allow(@plugin_manager).to receive(:pre_test_build)
23
25
  allow(@plugin_manager).to receive(:post_test_build)
24
26
  allow(@dependinator).to receive(:open)
@@ -32,7 +34,8 @@ describe TestInvoker do
32
34
  :dependinator => @dependinator,
33
35
  :loginator => @loginator,
34
36
  :verbosinator => @verbosinator,
35
- :test_pipeline_manager => @test_pipeline_manager
37
+ :test_pipeline_manager => @test_pipeline_manager,
38
+ :include_pathinator => @include_pathinator
36
39
  }
37
40
  )
38
41
  end
@@ -67,6 +70,16 @@ describe TestInvoker do
67
70
  @invoker.setup_and_invoke( tests: [] )
68
71
  end
69
72
 
73
+ # A header a `pre_test_build` hook writes is listed, and a later test build in the same
74
+ # process lists each directory afresh
75
+ it "forgets remembered header listings after the pre-test-build hook and before the run" do
76
+ expect(@plugin_manager).to receive(:pre_test_build).ordered
77
+ expect(@include_pathinator).to receive(:forget_header_listings).ordered
78
+ expect(@test_pipeline_manager).to receive(:run).ordered
79
+
80
+ @invoker.setup_and_invoke( tests: [] )
81
+ end
82
+
70
83
  # Isolates each pipeline identifier's own cache file (see Dependinator#open) --
71
84
  # sharing one cache file between, say, an ordinary test run and a plugin's own
72
85
  # context (:gcov, :valgrind, ...) would let one's full-run pruning flush (see
@@ -124,7 +124,7 @@ describe TestSourceFileDirectiveResolver do
124
124
  .with( filepath: 'foo.c', complain: :ignore, context: TEST_SYM ).and_return( 'src/foo.c' )
125
125
 
126
126
  expect {
127
- @resolver.validate!( test: 'TestFoo', filepath: 'test/TestFoo.c' )
127
+ @resolver.validate!( test: 'TestFoo', test_filepath: 'test/TestFoo.c', context: TEST_SYM )
128
128
  }.to_not raise_error
129
129
  end
130
130
 
@@ -135,7 +135,7 @@ describe TestSourceFileDirectiveResolver do
135
135
  .with( filepath: 'foo.c', complain: :ignore, context: TEST_SYM ).and_return( nil )
136
136
 
137
137
  expect {
138
- @resolver.validate!( test: 'TestFoo', filepath: 'test/TestFoo.c' )
138
+ @resolver.validate!( test: 'TestFoo', test_filepath: 'test/TestFoo.c', context: TEST_SYM )
139
139
  }.to raise_error( CeedlingException, /'foo\.c'.*cannot be found in the source file collection/ )
140
140
  end
141
141
 
@@ -144,7 +144,7 @@ describe TestSourceFileDirectiveResolver do
144
144
  .with( 'test/TestFoo.c' ).and_return( ['-:foo.txt'] )
145
145
 
146
146
  expect {
147
- @resolver.validate!( test: 'TestFoo', filepath: 'test/TestFoo.c' )
147
+ @resolver.validate!( test: 'TestFoo', test_filepath: 'test/TestFoo.c', context: TEST_SYM )
148
148
  }.to raise_error( CeedlingException, /'foo\.txt'.*not a .*\.c.*source file/ )
149
149
  end
150
150
 
@@ -155,10 +155,41 @@ describe TestSourceFileDirectiveResolver do
155
155
  .with( filepath: 'foo.c', complain: :ignore, context: TEST_SYM ).and_return( nil )
156
156
 
157
157
  expect {
158
- @resolver.validate!( test: 'TestFoo', filepath: 'test/TestFoo.c' )
158
+ @resolver.validate!( test: 'TestFoo', test_filepath: 'test/TestFoo.c', context: TEST_SYM )
159
159
  }.to raise_error( CeedlingException, /^File 'foo\.c'/ )
160
160
  end
161
161
 
162
+ # The check and the build find an entry the same way, so an entry the build uses passes
163
+ it "anchors a .. entry to the test's own directory, as the build does" do
164
+ allow(@test_context_extractor).to receive(:lookup_build_directive_sources_list)
165
+ .with( 'test/unit/TestFoo.c' ).and_return( ['../common/extra.c'] )
166
+ expect(@file_finder).to receive(:find_build_input_file)
167
+ .with( filepath: 'test/common/extra.c', complain: :ignore, context: TEST_SYM ).and_return( 'test/common/extra.c' )
168
+
169
+ expect {
170
+ @resolver.validate!( test: 'TestFoo', test_filepath: 'test/unit/TestFoo.c', context: TEST_SYM )
171
+ }.to_not raise_error
172
+ end
173
+
174
+ it "looks entries up in the build's own context" do
175
+ allow(@test_context_extractor).to receive(:lookup_build_directive_sources_list)
176
+ .with( 'test/TestFoo.c' ).and_return( ['foo.c'] )
177
+ expect(@file_finder).to receive(:find_build_input_file)
178
+ .with( filepath: 'foo.c', complain: :ignore, context: :gcov ).and_return( 'src/foo.c' )
179
+
180
+ @resolver.validate!( test: 'TestFoo', test_filepath: 'test/TestFoo.c', context: :gcov )
181
+ end
182
+
183
+ it "names the test it was given in its error" do
184
+ allow(@test_context_extractor).to receive(:lookup_build_directive_sources_list)
185
+ .with( 'test/m13/test_m13.c' ).and_return( ['mod_13_typo.c'] )
186
+ allow(@file_finder).to receive(:find_build_input_file).and_return( nil )
187
+
188
+ expect {
189
+ @resolver.validate!( test: 'test/m13/test_m13', test_filepath: 'test/m13/test_m13.c', context: TEST_SYM )
190
+ }.to raise_error( CeedlingException, %r{'mod_13_typo\.c' specified with TEST_SOURCE_FILE\(\) in test/m13/test_m13 cannot be found} )
191
+ end
192
+
162
193
  context "when assembly support is enabled" do
163
194
  before(:each) do
164
195
  allow(@configurator).to receive(:test_build_use_assembly).and_return( true )
@@ -172,7 +203,7 @@ describe TestSourceFileDirectiveResolver do
172
203
  .with( filepath: 'foo.asm', complain: :ignore, context: TEST_SYM ).and_return( 'src/foo.asm' )
173
204
 
174
205
  expect {
175
- @resolver.validate!( test: 'TestFoo', filepath: 'test/TestFoo.c' )
206
+ @resolver.validate!( test: 'TestFoo', test_filepath: 'test/TestFoo.c', context: TEST_SYM )
176
207
  }.to_not raise_error
177
208
  end
178
209
 
@@ -183,7 +214,7 @@ describe TestSourceFileDirectiveResolver do
183
214
  .with( filepath: 'foo.c', complain: :ignore, context: TEST_SYM ).and_return( 'src/foo.c' )
184
215
 
185
216
  expect {
186
- @resolver.validate!( test: 'TestFoo', filepath: 'test/TestFoo.c' )
217
+ @resolver.validate!( test: 'TestFoo', test_filepath: 'test/TestFoo.c', context: TEST_SYM )
187
218
  }.to_not raise_error
188
219
  end
189
220
 
@@ -192,7 +223,7 @@ describe TestSourceFileDirectiveResolver do
192
223
  .with( 'test/TestFoo.c' ).and_return( ['foo.txt'] )
193
224
 
194
225
  expect {
195
- @resolver.validate!( test: 'TestFoo', filepath: 'test/TestFoo.c' )
226
+ @resolver.validate!( test: 'TestFoo', test_filepath: 'test/TestFoo.c', context: TEST_SYM )
196
227
  }.to raise_error( CeedlingException, /not a \.c or \.asm source file/ )
197
228
  end
198
229
  end
@@ -81,6 +81,15 @@ describe ToolExecutor do
81
81
 
82
82
  expect(command[:line]).to include('--flag=2')
83
83
  end
84
+
85
+ # GH #1373: a value was a replacement string, so its \0, \1 and \\ were read as back-references
86
+ it 'substitutes a value holding backslash sequences exactly as given' do
87
+ tool_config = { :name => 't', :executable => 'exe', :arguments => [ { '-I"$"' => ['C:\proj\2024\0x', 'a\\\\b'] } ] }
88
+
89
+ command = @tool_executor.build_command_line( tool_config, [] )
90
+
91
+ expect(command[:line]).to eq( 'exe -I"C:\proj\2024\0x" -I"a\\\\b"' )
92
+ end
84
93
  end
85
94
 
86
95
  # A command run with :boom false always reports an :exit_code of 0, so a caller handling
@@ -453,6 +462,23 @@ describe ToolExecutor do
453
462
  expect(command[:line]).to include('-o "out.o"')
454
463
  end
455
464
 
465
+ # GH #1373: a value was a replacement string, so its \0, \1 and \\ were read as back-references
466
+ it 'substitutes a value holding backslash sequences exactly as given' do
467
+ tool_config = { :name => 't', :executable => 'exe', :arguments => ['-c "${1}"', '${2}'] }
468
+
469
+ command = @tool_executor.build_command_line(tool_config, [], 'C:\proj\2024\0x', 'a\\\\b\&c')
470
+
471
+ expect(command[:line]).to eq( 'exe -c "C:\proj\2024\0x" a\\\\b\&c' )
472
+ end
473
+
474
+ it 'substitutes each value of an Array exactly as given' do
475
+ tool_config = { :name => 't', :executable => 'exe', :arguments => ['"${1}"'] }
476
+
477
+ command = @tool_executor.build_command_line(tool_config, [], ['C:\a\1', 'C:\b\0'])
478
+
479
+ expect(command[:line]).to eq( 'exe "C:\a\1" "C:\b\0"' )
480
+ end
481
+
456
482
  it 'raises CeedlingException when args is empty but a ${n} element is present' do
457
483
  tool_config = { :name => 'my_tool', :executable => 'exe', :arguments => ['${1}'] }
458
484
 
@@ -65,6 +65,17 @@ describe YamlWrapper do
65
65
  end
66
66
  end
67
67
 
68
+ # Ruby's ArgumentError, not the constructor gem's same-named class every DIY object sees
69
+ it 'reports a Psych that rejects safe_load\'s arguments as :incompatible' do
70
+ allow(YAML).to receive(:safe_load).and_raise( ::ArgumentError.new( 'unknown keyword: :aliases' ) )
71
+
72
+ expect { @yaml_wrapper.load_string("a: 1\n", source_label: 'my_project.yml') }.to raise_error(YamlLoadException) do |e|
73
+ expect(e.reason).to eq(:incompatible)
74
+ expect(e.message).to match(/does not support a safe-loading feature.*unknown keyword: :aliases/)
75
+ expect(e.original_error).to be_a( ::ArgumentError )
76
+ end
77
+ end
78
+
68
79
  it 'embeds the source_label in the underlying Psych message' do
69
80
  yaml = "a: [1, 2\n"
70
81