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.
- checksums.yaml +4 -4
- data/GIT_COMMIT_SHA +1 -1
- data/README.md +11 -9
- data/Rakefile +2 -1
- data/assets/features/ceedling +1 -1
- data/assets/fixtures/test_source_file_duplicate_basenames/test_calc_typo.c +14 -0
- data/assets/fixtures/tests_with_duplicate_test_names/test_foo.c +21 -0
- data/bin/actionator.rb +6 -12
- data/bin/app_cfg.rb +14 -1
- data/bin/ceedling +13 -3
- data/bin/cli.rb +25 -6
- data/bin/cli_handler.rb +113 -73
- data/bin/cli_helper.rb +51 -78
- data/bin/installation_selector.rb +81 -0
- data/bin/launchinator.rb +69 -0
- data/bin/mixin_resolvinator.rb +26 -36
- data/bin/objects.yml +13 -0
- data/bin/path_validator.rb +25 -29
- data/bin/versionator.rb +47 -48
- data/ceedling.gemspec +19 -15
- data/docs/BreakingChanges.md +70 -1
- data/docs/Changelog.md +74 -3
- data/docs/KnownIssues.md +90 -4
- data/docs/ReleaseNotes.md +13 -0
- data/lib/ceedling/build_log_writer.rb +33 -0
- data/lib/ceedling/config/build_root_policy.rb +70 -0
- data/lib/ceedling/config/configurator.rb +14 -16
- data/lib/ceedling/config/configurator_builder.rb +58 -28
- data/lib/ceedling/config/configurator_paths_validator.rb +179 -0
- data/lib/ceedling/config/configurator_plugins.rb +1 -1
- data/lib/ceedling/config/configurator_setup.rb +15 -28
- data/lib/ceedling/config/configurator_validator.rb +1 -110
- data/lib/ceedling/defaults.rb +4 -4
- data/lib/ceedling/dependencies/README.md +18 -16
- data/lib/ceedling/dependencies/dependency_cache_store.rb +20 -3
- data/lib/ceedling/dependencies/dependency_hasher.rb +35 -1
- data/lib/ceedling/filename_extension.rb +7 -1
- data/lib/ceedling/filesystem/FILE_TREE.md +253 -0
- data/lib/ceedling/filesystem/PATH_HANDLING.md +304 -0
- data/lib/ceedling/filesystem/README.md +41 -0
- data/lib/ceedling/filesystem/build_subpath.rb +102 -0
- data/lib/ceedling/filesystem/destination_collision.rb +25 -0
- data/lib/ceedling/{file_finder.rb → filesystem/file_finder.rb} +159 -104
- data/lib/ceedling/{file_finder_helper.rb → filesystem/file_finder_helper.rb} +36 -31
- data/lib/ceedling/filesystem/file_path_collection_utils.rb +183 -0
- data/lib/ceedling/{file_path_utils.rb → filesystem/file_path_utils.rb} +108 -97
- data/lib/ceedling/{file_system_wrapper.rb → filesystem/file_system_wrapper.rb} +6 -5
- data/lib/ceedling/filesystem/file_tree.rb +241 -0
- data/lib/ceedling/{file_wrapper.rb → filesystem/file_wrapper.rb} +45 -38
- data/lib/ceedling/filesystem/path_exclusions.rb +30 -0
- data/lib/ceedling/{path_matcher.rb → filesystem/path_matcher.rb} +27 -23
- data/lib/ceedling/{path_mirror.rb → filesystem/path_mirror.rb} +19 -18
- data/lib/ceedling/filesystem/path_spellings.rb +55 -0
- data/lib/ceedling/filesystem/project_paths.rb +184 -0
- data/lib/ceedling/filesystem/working_dir.rb +40 -0
- data/lib/ceedling/generators/generator.rb +5 -6
- data/lib/ceedling/generators/generator_partials.rb +1 -1
- data/lib/ceedling/generators/generator_test_results_backtrace.rb +7 -7
- data/lib/ceedling/handoff.rb +121 -0
- data/lib/ceedling/includes/include_factory.rb +3 -3
- data/lib/ceedling/includes/include_pathinator.rb +67 -10
- data/lib/ceedling/includes/includes.rb +1 -1
- data/lib/ceedling/installation.rb +92 -0
- data/lib/ceedling/library_resolver.rb +99 -0
- data/lib/ceedling/objects.yml +23 -2
- data/lib/ceedling/partials/partializer.rb +4 -4
- data/lib/ceedling/partials/partializer_config.rb +3 -1
- data/lib/ceedling/plugins/report_log_writer_plugin.rb +3 -5
- data/lib/ceedling/preprocess/preprocessinator_file_assembler.rb +1 -1
- data/lib/ceedling/preprocess/preprocessinator_includes_handler.rb +1 -1
- data/lib/ceedling/preprocess/preprocessinator_line_marker_includes_extractor.rb +1 -1
- data/lib/ceedling/rake_app/rakefile_component_resolver.rb +10 -17
- data/lib/ceedling/rakefile.rb +15 -1
- data/lib/ceedling/rakefiles/base/tasks_base.rake +1 -1
- data/lib/ceedling/rakefiles/release/rules_release.rake +4 -7
- data/lib/ceedling/release_invoker/release_build_executor.rb +33 -44
- data/lib/ceedling/release_invoker/release_build_planner.rb +14 -6
- data/lib/ceedling/reportinator.rb +3 -4
- data/lib/ceedling/setupinator.rb +94 -90
- data/lib/ceedling/test_context_extractor.rb +5 -1
- data/lib/ceedling/test_invoker/PIPELINE.md +9 -7
- data/lib/ceedling/test_invoker/mock_locator.rb +60 -2
- data/lib/ceedling/test_invoker/partials_manager.rb +12 -0
- data/lib/ceedling/test_invoker/standin_headerinator.rb +22 -13
- data/lib/ceedling/test_invoker/test_build_executor.rb +24 -40
- data/lib/ceedling/test_invoker/test_build_planner.rb +37 -18
- data/lib/ceedling/test_invoker/test_build_setup.rb +17 -12
- data/lib/ceedling/test_invoker/test_build_validations.rb +16 -31
- data/lib/ceedling/test_invoker/test_file_preprocessinator.rb +1 -1
- data/lib/ceedling/test_invoker/test_invoker.rb +6 -1
- data/lib/ceedling/test_invoker/test_pipeline_helpers.rb +1 -1
- data/lib/ceedling/test_invoker/test_source_file_directive_resolver.rb +40 -20
- data/lib/ceedling/tool_executor.rb +9 -3
- data/lib/ceedling/yaml_wrapper.rb +3 -2
- data/lib/version.rb +1 -1
- data/plugins/bullseye/config/defaults_bullseye.rb +1 -1
- data/plugins/bullseye/lib/bullseye.rb +9 -7
- data/plugins/cppcheck/config/defaults_cppcheck.rb +1 -1
- data/plugins/dependencies/config/defaults.yml +6 -6
- data/plugins/dependencies/dependencies.rake +4 -1
- data/plugins/dependencies/lib/dependencies.rb +18 -8
- data/plugins/dependencies/lib/dependency_spec.rb +17 -5
- data/plugins/fff/lib/fff.rb +45 -39
- data/plugins/fff/spec/fff_cmock_wrapper_spec.rb +128 -0
- data/plugins/gcov/config/defaults_gcov.rb +1 -1
- data/plugins/gcov/lib/console_reportinator.rb +4 -18
- data/plugins/gcov/lib/gcov.rb +9 -2
- data/plugins/gcov/lib/gcovr_reportinator.rb +8 -40
- data/plugins/gcov/lib/gcovr_thresholds.rb +74 -0
- data/plugins/gcov/lib/reportgenerator_reportinator.rb +1 -1
- data/plugins/module_generator/lib/module_generator.rb +3 -3
- data/plugins/report_tests_teamcity_stdout/lib/report_tests_teamcity_stdout.rb +53 -80
- data/plugins/sanitize/lib/sanitize_records.rb +3 -6
- data/plugins/valgrind/lib/valgrind.rb +14 -7
- data/site-local/configuration/reference/cmock.html +2 -1
- data/site-local/configuration/reference/files.html +9 -3
- data/site-local/configuration/reference/libraries.html +21 -3
- data/site-local/configuration/reference/paths.html +29 -6
- data/site-local/configuration/reference/project.html +17 -7
- data/site-local/configuration/reference/release-build.html +2 -0
- data/site-local/configuration/reference/tools.html +9 -0
- data/site-local/configuration/which-ceedling.html +377 -17
- data/site-local/development/releases.html +5 -1
- data/site-local/development/workflow.html +48 -43
- data/site-local/getting-started/builds.html +2 -0
- data/site-local/getting-started/command-line.html +56 -4
- data/site-local/plugins/dependencies.html +6 -3
- data/site-local/plugins/fff.html +42 -11
- data/site-local/plugins/gcov/gcovr.html +15 -12
- data/site-local/plugins/gcov/setup.html +2 -1
- data/site-local/plugins/report-tests-raw-output-log.html +3 -1
- data/site-local/plugins/report-tests-teamcity-stdout.html +6 -3
- data/site-local/plugins/sanitize.html +7 -6
- data/site-local/plugins/valgrind.html +8 -7
- data/site-local/project/upgrade.html +3 -0
- data/site-local/reference/command-line.html +9 -2
- data/site-local/sitemap.xml.gz +0 -0
- data/site-local/snapshot/plugins/bullseye/config/defaults_bullseye.rb +1 -1
- data/site-local/snapshot/plugins/gcov/config/defaults_gcov.rb +1 -1
- data/site-local/testing-guide/conventions.html +53 -0
- data/spec/integration/actionator_file_operations_spec.rb +91 -1
- data/spec/integration/compile_commands_json_db_spec.rb +1 -1
- data/spec/integration/configurator_validation_spec.rb +1 -1
- data/spec/integration/dependencies/dependency_tracker_cache_hardening_spec.rb +26 -0
- data/spec/integration/dependencies/dependency_tracker_core_spec.rb +22 -0
- data/spec/integration/launcher_handoff_spec.rb +297 -0
- data/spec/integration/mixin_loading_spec.rb +1 -1
- data/spec/integration/module_generator_spec.rb +3 -3
- data/spec/integration/nested_test_artifacts_spec.rb +99 -0
- data/spec/integration/partials_module_resolution_spec.rb +7 -4
- data/spec/integration/path_intake_scenarios_spec.rb +101 -0
- data/spec/integration/path_scenarios_spec.rb +322 -0
- data/spec/integration/quote_include_isolator_spec.rb +1 -1
- data/spec/integration/report_build_warnings_log_spec.rb +1 -1
- data/spec/integration/report_tests_log_factory_spec.rb +1 -1
- data/spec/integration/test_executable_manifest_spec.rb +1 -1
- data/spec/integration/test_includes_extractinator_spec.rb +2 -1
- data/spec/integration/test_naming_spec.rb +198 -0
- data/spec/integration/test_source_file_checks_spec.rb +166 -0
- data/spec/integration/tool_validator_spec.rb +1 -1
- data/spec/integration/upgrade_docs_spec.rb +84 -0
- data/spec/integration/vendor_copy_transient_io_retry_spec.rb +74 -5
- data/spec/support/file_tree_helper.rb +88 -0
- data/spec/support/integration/configurator_integration_helper.rb +6 -6
- data/spec/support/integration/dependency_tracker_integration_helper.rb +1 -1
- data/spec/support/integration/partials_generation_integration_helper.rb +2 -2
- data/spec/support/integration/path_scenario_harness.rb +173 -0
- data/spec/support/integration/spec_integration_helper.rb +1 -1
- data/spec/support/integration/test_includes_harness.rb +13 -2
- data/spec/support/spec_helper.rb +2 -0
- data/spec/support/system/spec_system_helper.rb +7 -6
- data/spec/support/system/system_context.rb +21 -3
- data/spec/support/working_dir_tracking.rb +49 -0
- data/spec/system/build_output_mirroring_spec.rb +2 -2
- data/spec/system/conditional_mock_includes_spec.rb +1 -1
- data/spec/system/delta_builds_spec.rb +137 -11
- data/spec/system/gcov_deployment_spec.rb +1 -0
- data/spec/system/header_include_path_validation_spec.rb +4 -4
- data/spec/system/launcher_handoff_spec.rb +82 -0
- data/spec/system/mock_include_folders_spec.rb +91 -0
- data/spec/system/parent_directory_reference_spec.rb +5 -3
- data/spec/system/path_handling_probes_spec.rb +192 -0
- data/spec/system/preprocessing_parameterized_tests_spec.rb +1 -1
- data/spec/system/rake_release_task_path_disambiguation_spec.rb +6 -6
- data/spec/system/rake_test_task_path_disambiguation_spec.rb +85 -0
- data/spec/system/special_path_characters_spec.rb +86 -0
- data/spec/system/support/common_test_cases.rb +23 -21
- data/spec/system/support/gcov_common_test_cases.rb +37 -9
- data/spec/system/support/sanitize_common_test_cases.rb +2 -2
- data/spec/system/support/valgrind_common_test_cases.rb +12 -12
- data/spec/system/test_pipeline_stop_points_spec.rb +4 -4
- data/spec/system/test_runner_system_include_spec.rb +1 -1
- data/spec/system/test_source_file_directive_spec.rb +34 -5
- data/spec/units/bin/actionator_spec.rb +14 -17
- data/spec/units/bin/app_cfg_spec.rb +37 -0
- data/spec/units/bin/cli_handler_spec.rb +282 -6
- data/spec/units/bin/cli_helper_spec.rb +116 -45
- data/spec/units/bin/installation_selector_spec.rb +114 -0
- data/spec/units/bin/launchinator_spec.rb +171 -0
- data/spec/units/bin/path_validator_spec.rb +10 -0
- data/spec/units/bin/versionator_spec.rb +38 -6
- data/spec/units/build_log_writer_spec.rb +57 -0
- data/spec/units/config/build_root_policy_spec.rb +61 -0
- data/spec/units/config/configurator_builder_spec.rb +37 -6
- data/spec/units/config/configurator_paths_validator_spec.rb +292 -0
- data/spec/units/config/configurator_setup_spec.rb +9 -65
- data/spec/units/config/configurator_spec.rb +27 -5
- data/spec/units/config/configurator_validator_spec.rb +1 -172
- data/spec/units/default_tools_quoting_spec.rb +83 -0
- data/spec/units/dependencies/dependency_cache_store_spec.rb +33 -2
- data/spec/units/dependencies/dependency_debug_tree_spec.rb +1 -1
- data/spec/units/dependencies/dependency_hasher_spec.rb +42 -1
- data/spec/units/dependencies/dependency_path_normalizer_spec.rb +1 -1
- data/spec/units/dependencies/dependency_tracker_spec.rb +3 -1
- data/spec/units/filename_extension_spec.rb +11 -0
- data/spec/units/filesystem/build_subpath_spec.rb +122 -0
- data/spec/units/filesystem/destination_collision_spec.rb +30 -0
- data/spec/units/{file_finder_helper_spec.rb → filesystem/file_finder_helper_spec.rb} +46 -1
- data/spec/units/{file_finder_spec.rb → filesystem/file_finder_spec.rb} +188 -22
- data/spec/units/{file_path_collection_utils_spec.rb → filesystem/file_path_collection_utils_spec.rb} +181 -1
- data/spec/units/{file_path_utils_spec.rb → filesystem/file_path_utils_spec.rb} +204 -87
- data/spec/units/filesystem/file_system_wrapper_spec.rb +33 -0
- data/spec/units/filesystem/file_tree_spec.rb +511 -0
- data/spec/units/filesystem/file_tree_windows_spec.rb +78 -0
- data/spec/units/{file_wrapper_spec.rb → filesystem/file_wrapper_spec.rb} +95 -12
- data/spec/units/{path_matcher_spec.rb → filesystem/path_matcher_spec.rb} +12 -1
- data/spec/units/{path_mirror_spec.rb → filesystem/path_mirror_spec.rb} +32 -4
- data/spec/units/filesystem/project_paths_spec.rb +147 -0
- data/spec/units/filesystem/working_dir_spec.rb +71 -0
- data/spec/units/generators/generator_spec.rb +12 -6
- data/spec/units/generators/generator_test_results_backtrace_spec.rb +50 -46
- data/spec/units/generators/generator_test_results_spec.rb +1 -1
- data/spec/units/handoff_spec.rb +205 -0
- data/spec/units/includes/include_factory_spec.rb +3 -3
- data/spec/units/includes/include_pathinator_spec.rb +46 -0
- data/spec/units/installation_spec.rb +228 -0
- data/spec/units/library_resolver_spec.rb +157 -0
- data/spec/units/mock_locator_spec.rb +76 -1
- data/spec/units/partials/partializer_config_spec.rb +7 -0
- data/spec/units/partials/partializer_spec.rb +1 -0
- data/spec/units/partials_manager_spec.rb +17 -0
- data/spec/units/plugins/bullseye_spec.rb +15 -2
- data/spec/units/plugins/console_reportinator_spec.rb +18 -20
- data/spec/units/plugins/dependencies_spec.rb +33 -7
- data/spec/units/plugins/dependency_spec_spec.rb +17 -0
- data/spec/units/plugins/gcov_spec.rb +28 -3
- data/spec/units/plugins/gcovr_reportinator_spec.rb +19 -47
- data/spec/units/plugins/gcovr_thresholds_spec.rb +95 -0
- data/spec/units/plugins/module_generator_spec.rb +5 -5
- data/spec/units/plugins/report_build_warnings_log_spec.rb +3 -3
- data/spec/units/plugins/report_log_writer_plugin_spec.rb +10 -1
- data/spec/units/plugins/report_tests_raw_output_log_spec.rb +13 -2
- data/spec/units/plugins/report_tests_teamcity_stdout_spec.rb +77 -3
- data/spec/units/plugins/reportgenerator_reportinator_spec.rb +1 -1
- data/spec/units/plugins/sanitize_records_spec.rb +3 -1
- data/spec/units/plugins/sanitize_spec.rb +1 -1
- data/spec/units/plugins/valgrind_spec.rb +23 -8
- data/spec/units/preprocess/preprocessinator_comment_stripper_spec.rb +1 -1
- data/spec/units/rake_app/rakefile_component_resolver_spec.rb +21 -0
- data/spec/units/release_build_executor_spec.rb +53 -14
- data/spec/units/release_build_planner_spec.rb +15 -3
- data/spec/units/reportinator_spec.rb +5 -5
- data/spec/units/standin_headerinator_spec.rb +31 -1
- data/spec/units/test_build_executor_spec.rb +65 -3
- data/spec/units/test_build_planner_spec.rb +104 -2
- data/spec/units/test_build_setup_spec.rb +96 -12
- data/spec/units/test_context_extractor_spec.rb +25 -0
- data/spec/units/test_file_preprocessinator_spec.rb +17 -1
- data/spec/units/test_includes_extractinator_spec.rb +5 -1
- data/spec/units/test_invoker/objects_wiring_spec.rb +6 -3
- data/spec/units/test_invoker_spec.rb +14 -1
- data/spec/units/test_source_file_directive_resolver_spec.rb +38 -7
- data/spec/units/tool_executor_spec.rb +26 -0
- data/spec/units/yaml_wrapper_spec.rb +11 -0
- metadata +109 -25
- data/lib/ceedling/file_path_collection_utils.rb +0 -164
|
@@ -24,11 +24,11 @@ require 'ceedling/constants'
|
|
|
24
24
|
require 'ceedling/defaults'
|
|
25
25
|
require 'ceedling/system_utils'
|
|
26
26
|
require 'ceedling/system_wrapper'
|
|
27
|
-
require 'ceedling/file_wrapper'
|
|
27
|
+
require 'ceedling/filesystem/file_wrapper'
|
|
28
28
|
require 'ceedling/yaml_wrapper'
|
|
29
29
|
require 'ceedling/reportinator'
|
|
30
30
|
require 'ceedling/ruby_expandinator'
|
|
31
|
-
require 'ceedling/file_path_collection_utils'
|
|
31
|
+
require 'ceedling/filesystem/file_path_collection_utils'
|
|
32
32
|
require 'ceedling/tool_validator'
|
|
33
33
|
require 'ceedling/tool_executor'
|
|
34
34
|
require 'ceedling/tool_executor_helper'
|
|
@@ -39,6 +39,7 @@ require 'ceedling/config/configurator_setup'
|
|
|
39
39
|
require 'ceedling/config/configurator_builder'
|
|
40
40
|
require 'ceedling/config/configurator_plugins'
|
|
41
41
|
require 'ceedling/config/configurator_validator'
|
|
42
|
+
require 'ceedling/config/configurator_paths_validator'
|
|
42
43
|
|
|
43
44
|
module ConfiguratorIntegrationHelpers
|
|
44
45
|
|
|
@@ -58,11 +59,10 @@ module ConfiguratorIntegrationHelpers
|
|
|
58
59
|
|
|
59
60
|
o[:configurator_plugins] = ConfiguratorPlugins.new( o.slice( :file_wrapper, :system_wrapper ) )
|
|
60
61
|
o[:configurator_builder] = ConfiguratorBuilder.new( o.slice( :file_path_collection_utils, :loginator, :file_wrapper, :system_wrapper ) )
|
|
61
|
-
o[:configurator_validator] = ConfiguratorValidator.new(
|
|
62
|
-
|
|
63
|
-
)
|
|
62
|
+
o[:configurator_validator] = ConfiguratorValidator.new( o.slice( :config_walkinator, :loginator, :reportinator, :tool_validator ) )
|
|
63
|
+
o[:configurator_paths_validator] = ConfiguratorPathsValidator.new( o.slice( :config_walkinator, :file_wrapper, :loginator, :reportinator ) )
|
|
64
64
|
o[:configurator_setup] = ConfiguratorSetup.new(
|
|
65
|
-
o.slice( :configurator_builder, :configurator_validator, :loginator, :reportinator,
|
|
65
|
+
o.slice( :configurator_builder, :configurator_validator, :configurator_paths_validator, :loginator, :reportinator,
|
|
66
66
|
:file_wrapper, :system_wrapper, :tool_executor )
|
|
67
67
|
)
|
|
68
68
|
o[:configurator] = Configurator.new(
|
|
@@ -56,8 +56,8 @@ require 'ceedling/preprocess/preprocessinator_comment_stripper'
|
|
|
56
56
|
require 'ceedling/preprocess/c_comment_scanner'
|
|
57
57
|
require 'ceedling/preprocess/preprocessinator_file_assembler'
|
|
58
58
|
require 'ceedling/parsing_parcels'
|
|
59
|
-
require 'ceedling/file_path_utils'
|
|
60
|
-
require 'ceedling/file_wrapper'
|
|
59
|
+
require 'ceedling/filesystem/file_path_utils'
|
|
60
|
+
require 'ceedling/filesystem/file_wrapper'
|
|
61
61
|
require 'ceedling/includes/includes'
|
|
62
62
|
|
|
63
63
|
|
|
@@ -0,0 +1,173 @@
|
|
|
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
|
+
# Runs a project layout through configuration, collection, build-path mapping, and the
|
|
9
|
+
# lookups that invert that mapping, without compiling anything.
|
|
10
|
+
#
|
|
11
|
+
# A scenario is a workspace: the project in `app/`, with siblings beside it (`shared/`,
|
|
12
|
+
# `vendor/`) for paths that reach outside the project, and a separate directory elsewhere
|
|
13
|
+
# for paths far outside it, as a vendor SDK installed at a drive's root is. YAML may name
|
|
14
|
+
# absolute paths with `%{ws}`, `%{app}` and `%{far}`. The workspace is resolved through File.realpath first, so a
|
|
15
|
+
# system temp directory behind a symlink (macOS's /tmp) doesn't add a second spelling.
|
|
16
|
+
#
|
|
17
|
+
# Test preprocessing is off, so no preprocessor is probed, and nothing is built.
|
|
18
|
+
|
|
19
|
+
require 'tmpdir'
|
|
20
|
+
require 'fileutils'
|
|
21
|
+
require 'configurator_integration_helper'
|
|
22
|
+
require 'ceedling/filesystem/file_path_utils'
|
|
23
|
+
require 'ceedling/filesystem/file_finder'
|
|
24
|
+
require 'ceedling/filesystem/file_finder_helper'
|
|
25
|
+
require 'ceedling/test_invoker/test_build_setup'
|
|
26
|
+
require 'ceedling/test_invoker/test_invoker_types'
|
|
27
|
+
|
|
28
|
+
module PathScenarioHarness
|
|
29
|
+
include ConfiguratorIntegrationHelpers
|
|
30
|
+
|
|
31
|
+
# Runs each test of a batch in turn, in place of the thread pool
|
|
32
|
+
class SerialBatchinator
|
|
33
|
+
def exec(things:, **_options)
|
|
34
|
+
things.each { |thing| yield thing }
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# A root spelled each way a project file might, for one place in the workspace
|
|
39
|
+
ROOT_SPELLINGS = {
|
|
40
|
+
plain: ->(root, **) { root },
|
|
41
|
+
dot_slash: ->(root, **) { "./#{root}" },
|
|
42
|
+
absolute: ->(root, app:, **) { File.join( app, root ) },
|
|
43
|
+
backslash: ->(root, **) { root.tr( '/', '\\' ) },
|
|
44
|
+
symlink: ->(root, ws:, **) { File.join( ws, 'link', root ) }
|
|
45
|
+
}.freeze
|
|
46
|
+
|
|
47
|
+
# Runs the block in a workspace holding `files` (paths relative to the workspace), from
|
|
48
|
+
# `cwd` within it, with `far` files in a directory outside the workspace. A `link`
|
|
49
|
+
# symlink to `app/` is made when `symlink` is set.
|
|
50
|
+
def in_workspace(files, cwd: 'app', symlink: false, far: {})
|
|
51
|
+
Dir.mktmpdir do |dir|
|
|
52
|
+
Dir.mktmpdir do |far_dir|
|
|
53
|
+
ws = File.realpath( dir )
|
|
54
|
+
@far = File.join( File.realpath( far_dir ), 'deep', 'sdk' )
|
|
55
|
+
write_files( ws, files )
|
|
56
|
+
write_files( @far, far )
|
|
57
|
+
FileUtils.mkdir_p( File.join( ws, 'app' ) )
|
|
58
|
+
File.symlink( File.join( ws, 'app' ), File.join( ws, 'link' ) ) if symlink
|
|
59
|
+
|
|
60
|
+
Dir.chdir( File.join( ws, cwd ) ) { yield ws, File.join( ws, 'app' ) }
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def write_files(root, files)
|
|
66
|
+
files.each do |path, content|
|
|
67
|
+
FileUtils.mkdir_p( File.join( root, File.dirname( path ) ) )
|
|
68
|
+
File.write( File.join( root, path ), content )
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# A project file for a scenario. `paths` and `files` are the :paths and :files sections.
|
|
73
|
+
def scenario_yaml(ws:, app:, paths:, files: {}, project: {})
|
|
74
|
+
config = {
|
|
75
|
+
project: { build_root: 'build', use_test_preprocessor: :none, use_mocks: true, release_build: true }.merge( project ),
|
|
76
|
+
paths: paths,
|
|
77
|
+
files: files
|
|
78
|
+
}
|
|
79
|
+
# Psych writes Symbol keys and values in the `:key:` form a project file uses
|
|
80
|
+
return YAML.dump( placed( config, ws: ws, app: app ) )
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Fills `%{ws}`, `%{app}` and `%{far}` in every string with the workspace's absolute paths
|
|
84
|
+
def placed(value, ws:, app:)
|
|
85
|
+
case value
|
|
86
|
+
when Hash then value.transform_values { |item| placed( item, ws: ws, app: app ) }
|
|
87
|
+
when Array then value.map { |item| placed( item, ws: ws, app: app ) }
|
|
88
|
+
when String then value.gsub( '%{ws}', ws ).gsub( '%{app}', app ).gsub( '%{far}', @far.to_s )
|
|
89
|
+
else value
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Configures the project, and prepares every test's build paths, as stage 1 of a build does
|
|
94
|
+
def scenario(yaml)
|
|
95
|
+
configurator = configure( yaml )[:configurator]
|
|
96
|
+
|
|
97
|
+
file_wrapper = FileWrapper.new( loginator: double( 'loginator', log: nil ), verbosinator: double( 'verbosinator', should_output?: false ) )
|
|
98
|
+
file_path_utils = FilePathUtils.new( configurator: configurator, file_wrapper: file_wrapper )
|
|
99
|
+
|
|
100
|
+
collaborators = TestBuildSetup.constructor_keys.to_h { |key| [key, double( key.to_s )] }
|
|
101
|
+
setup = TestBuildSetup.new( collaborators.merge(
|
|
102
|
+
configurator: configurator, file_wrapper: file_wrapper, file_path_utils: file_path_utils, batchinator: SerialBatchinator.new
|
|
103
|
+
) )
|
|
104
|
+
state = TestInvokerTypes::PipelineState.new( tests: configurator.collection_all_tests, testables: {}, context: :test, options: [], lock: Mutex.new )
|
|
105
|
+
setup.stage_prepare_build_paths( state )
|
|
106
|
+
|
|
107
|
+
finder = FileFinder.new(
|
|
108
|
+
configurator: configurator, file_finder_helper: FileFinderHelper.new( loginator: double( 'loginator', log: nil ) ),
|
|
109
|
+
file_path_utils: file_path_utils, file_wrapper: file_wrapper, yaml_wrapper: nil
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
return { configurator: configurator, state: state, paths: file_path_utils, finder: finder }
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Every build file a scenario's sources and headers map to, by kind
|
|
116
|
+
def placements(scene)
|
|
117
|
+
configurator, state, paths = scene.values_at( :configurator, :state, :paths )
|
|
118
|
+
testable = state.testables.values.first
|
|
119
|
+
sources = configurator.collection_all_source
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
test_objects: paths.form_test_build_objects_filelist( testable.paths[:build], sources ),
|
|
123
|
+
release_objects: paths.form_release_build_objects_filelist( sources ),
|
|
124
|
+
preprocessed: configurator.collection_all_headers.map { |header| paths.form_preprocessed_file_filepath( header, testable.name ) },
|
|
125
|
+
mocks: configurator.collection_all_headers.map { |header| mock_output_path( scene, testable, header ) }
|
|
126
|
+
}
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Where a mock of `header` is generated, through the lookup a build's mock stage makes
|
|
130
|
+
def mock_output_path(scene, testable, header)
|
|
131
|
+
mock = "#{scene[:configurator].cmock_mock_prefix}#{File.basename( header )}"
|
|
132
|
+
_source, subdir = scene[:finder].resolve_mock( mock, complain: :ignore )
|
|
133
|
+
return nil if subdir.nil?
|
|
134
|
+
|
|
135
|
+
return scene[:paths].form_mock_output_path( testable.paths[:mocks], subdir )
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Every path lies within the build root, by real containment
|
|
139
|
+
def expect_inside_build(paths, build: File.expand_path( 'build' ))
|
|
140
|
+
paths.compact.each do |path|
|
|
141
|
+
expanded = File.expand_path( path )
|
|
142
|
+
expect(expanded).to start_with( build + '/' ), "#{path} lies outside #{build}/"
|
|
143
|
+
expect(path.split( %r{[\\/]} )).to_not include( '..' ), "#{path} holds `..`"
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Distinct inputs map to distinct build files
|
|
148
|
+
def expect_distinct(paths, label)
|
|
149
|
+
duplicates = paths.compact.group_by { |path| File.expand_path( path ) }.select { |_, group| group.size > 1 }.keys
|
|
150
|
+
expect(duplicates).to be_empty, "#{label} collide: #{duplicates.join( ', ' )}"
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# No collection holds a file under the build root
|
|
154
|
+
def expect_collections_outside_build(configurator, build: File.expand_path( 'build' ))
|
|
155
|
+
entries = configurator.collection_all_source + configurator.collection_all_headers + configurator.collection_all_tests
|
|
156
|
+
inside = entries.select { |entry| File.expand_path( entry ).start_with?( build + '/' ) }
|
|
157
|
+
expect(inside).to be_empty, "collected from the build root: #{inside.join( ', ' )}"
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# No file is collected twice, under two spellings
|
|
161
|
+
def expect_one_spelling_each(configurator)
|
|
162
|
+
entries = configurator.collection_all_source + configurator.collection_all_headers
|
|
163
|
+
twice = entries.group_by { |entry| File.realpath( entry ) rescue File.expand_path( entry ) }.select { |_, group| group.size > 1 }
|
|
164
|
+
expect(twice).to be_empty, "collected twice: #{twice.values.map { |group| group.join( ' and ' ) }.join( '; ' )}"
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Build placements relative to the build root, comparable across spellings
|
|
168
|
+
def relative_placements(scene, build: File.expand_path( 'build' ))
|
|
169
|
+
return placements( scene ).transform_values do |paths|
|
|
170
|
+
paths.compact.map { |path| File.expand_path( path ).delete_prefix( build + '/' ) }.sort
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
@@ -25,7 +25,7 @@ require 'fileutils'
|
|
|
25
25
|
|
|
26
26
|
require 'ceedling/constants'
|
|
27
27
|
require 'ceedling/defaults'
|
|
28
|
-
require 'ceedling/file_wrapper'
|
|
28
|
+
require 'ceedling/filesystem/file_wrapper'
|
|
29
29
|
require 'ceedling/yaml_wrapper'
|
|
30
30
|
require 'ceedling/parsing_parcels'
|
|
31
31
|
require 'ceedling/includes/includes'
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
|
|
22
22
|
require 'spec_integration_helper'
|
|
23
23
|
require 'ceedling/filename_extension'
|
|
24
|
-
require 'ceedling/file_finder'
|
|
25
|
-
require 'ceedling/file_finder_helper'
|
|
24
|
+
require 'ceedling/filesystem/file_finder'
|
|
25
|
+
require 'ceedling/filesystem/file_finder_helper'
|
|
26
26
|
require 'ceedling/test_context_extractor'
|
|
27
27
|
require 'ceedling/test_invoker/test_invoker_types'
|
|
28
28
|
require 'ceedling/test_invoker/test_search_paths'
|
|
@@ -52,6 +52,10 @@ module IntegrationSpecHelpers
|
|
|
52
52
|
def get_cmock_config
|
|
53
53
|
{}
|
|
54
54
|
end
|
|
55
|
+
|
|
56
|
+
def cmock_mock_name_include_folder
|
|
57
|
+
true
|
|
58
|
+
end
|
|
55
59
|
def project_use_mocks
|
|
56
60
|
true
|
|
57
61
|
end
|
|
@@ -86,6 +90,13 @@ module IntegrationSpecHelpers
|
|
|
86
90
|
def paths_include
|
|
87
91
|
['src']
|
|
88
92
|
end
|
|
93
|
+
# The canonical roots configuration computes from the three above
|
|
94
|
+
def collection_mirror_roots_headers
|
|
95
|
+
['test', 'src']
|
|
96
|
+
end
|
|
97
|
+
def collection_mirror_roots_include
|
|
98
|
+
['src']
|
|
99
|
+
end
|
|
89
100
|
def collection_paths_support
|
|
90
101
|
[]
|
|
91
102
|
end
|
data/spec/support/spec_helper.rb
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
# SPDX-License-Identifier: MIT
|
|
6
6
|
# =========================================================================
|
|
7
7
|
|
|
8
|
+
require 'digest'
|
|
8
9
|
require 'fileutils'
|
|
9
10
|
require 'tmpdir'
|
|
10
11
|
require 'open3'
|
|
@@ -142,6 +143,7 @@ RSpec.configure do |config|
|
|
|
142
143
|
$stderr.puts "\n" + ("=" * 72)
|
|
143
144
|
$stderr.puts "FAILED: #{format_description.call(example)}"
|
|
144
145
|
$stderr.puts "Temp dir: #{@c.dir}"
|
|
146
|
+
$stderr.puts "Project: #{@proj_name}" if defined?(@proj_name) && @proj_name
|
|
145
147
|
$stderr.puts "Log file: #{log_path}"
|
|
146
148
|
if @c.respond_to?(:console_summary) && !@c.console_summary.nil?
|
|
147
149
|
$stderr.puts "-" * 72
|
|
@@ -259,13 +261,12 @@ def html_docs_bundle_available?
|
|
|
259
261
|
Dir.exist?(File.join(File.dirname(__FILE__), '..', '..', '..', 'site-local'))
|
|
260
262
|
end
|
|
261
263
|
|
|
264
|
+
# A project directory name unique to the current example, kept short because Windows
|
|
265
|
+
# paths stop at 260 characters and a project's deepest build file sits well over 100
|
|
266
|
+
# below it. The full description, nested groups and all, tells apart same-named examples
|
|
267
|
+
# sharing one spec file's temp dir. Failure reports print the name beside the example.
|
|
262
268
|
def unique_proj_name(prefix)
|
|
263
|
-
|
|
264
|
-
.downcase
|
|
265
|
-
.gsub(/[^a-z0-9]+/, '_')
|
|
266
|
-
.gsub(/\A_+|_+\z/, '')
|
|
267
|
-
.slice(0, 60)
|
|
268
|
-
"#{prefix}_#{safe}"
|
|
269
|
+
"#{prefix}_#{Digest::SHA256.hexdigest( RSpec.current_example.full_description )[0, 8]}"
|
|
269
270
|
end
|
|
270
271
|
|
|
271
272
|
def convert_slashes(path)
|
|
@@ -6,9 +6,11 @@
|
|
|
6
6
|
# =========================================================================
|
|
7
7
|
|
|
8
8
|
require 'fileutils'
|
|
9
|
+
require 'securerandom'
|
|
10
|
+
require 'tmpdir'
|
|
9
11
|
require 'bundler'
|
|
10
12
|
require 'ceedling/encodinator'
|
|
11
|
-
require 'ceedling/file_wrapper'
|
|
13
|
+
require 'ceedling/filesystem/file_wrapper'
|
|
12
14
|
require 'ceedling/verbosinator'
|
|
13
15
|
require 'ceedling/yaml_wrapper'
|
|
14
16
|
require_relative 'gem_dir_layout'
|
|
@@ -145,13 +147,29 @@ class SystemContext
|
|
|
145
147
|
# or fail/) is determined by done!.
|
|
146
148
|
base = File.join(Dir.pwd, ARTIFACTS_DIR, 'proj')
|
|
147
149
|
FileUtils.mkdir_p(base)
|
|
148
|
-
@dir =
|
|
150
|
+
@dir = self.class.brief_tmpdir(base)
|
|
149
151
|
else
|
|
150
|
-
@dir = Dir.
|
|
152
|
+
@dir = self.class.brief_tmpdir(Dir.tmpdir)
|
|
151
153
|
end
|
|
152
154
|
@gem = GemDirLayout.new(@dir)
|
|
153
155
|
end
|
|
154
156
|
|
|
157
|
+
# A new directory below `base` with a 7-character name, where Dir.mktmpdir's runs to
|
|
158
|
+
# 22. Windows paths stop at 260 characters, and a project's deepest build file sits
|
|
159
|
+
# well over 100 below this directory. Dir.mkdir is atomic, so concurrent runs never
|
|
160
|
+
# share one.
|
|
161
|
+
def self.brief_tmpdir(base)
|
|
162
|
+
loop do
|
|
163
|
+
dir = File.join(base, "s#{SecureRandom.hex(3)}")
|
|
164
|
+
begin
|
|
165
|
+
Dir.mkdir(dir)
|
|
166
|
+
return dir
|
|
167
|
+
rescue Errno::EEXIST
|
|
168
|
+
next
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
155
173
|
def done!
|
|
156
174
|
if keep_all? || (keep_failures_only? && @failed)
|
|
157
175
|
# 'all' mode: preserve pass and fail artifacts for post-run inspection.
|
|
@@ -0,0 +1,49 @@
|
|
|
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/filesystem/working_dir'
|
|
9
|
+
|
|
10
|
+
# WorkingDir reads the working directory once, and Ceedling changes directory only through
|
|
11
|
+
# WorkingDir.chdir. Specs change directory in-process with Dir.chdir all the time, so here
|
|
12
|
+
# every Dir.chdir forgets the working directory too, and each spec's paths resolve against
|
|
13
|
+
# the directory it is in. `untracked` suspends that, so a spec can show what Ceedling
|
|
14
|
+
# itself does.
|
|
15
|
+
module WorkingDirTracking
|
|
16
|
+
|
|
17
|
+
@paused = false
|
|
18
|
+
|
|
19
|
+
def self.untracked
|
|
20
|
+
previous = @paused
|
|
21
|
+
@paused = true
|
|
22
|
+
yield
|
|
23
|
+
ensure
|
|
24
|
+
@paused = previous
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def self.forget
|
|
28
|
+
WorkingDir.forget unless @paused
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
module DirChdir
|
|
32
|
+
def chdir(*args)
|
|
33
|
+
WorkingDirTracking.forget
|
|
34
|
+
return super unless block_given?
|
|
35
|
+
|
|
36
|
+
super( *args ) do |*yielded|
|
|
37
|
+
WorkingDirTracking.forget
|
|
38
|
+
yield( *yielded )
|
|
39
|
+
ensure
|
|
40
|
+
WorkingDirTracking.forget
|
|
41
|
+
end
|
|
42
|
+
ensure
|
|
43
|
+
WorkingDirTracking.forget
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
Dir.singleton_class.prepend( WorkingDirTracking::DirChdir )
|
|
@@ -62,8 +62,8 @@ ceedling_system_tests do
|
|
|
62
62
|
expect(output).to_not match(/Ambiguous/)
|
|
63
63
|
expect(output).to match(/^Linking /)
|
|
64
64
|
|
|
65
|
-
expect(File.exist?('build/release/out/foo/bar.o')).to be true
|
|
66
|
-
expect(File.exist?('build/release/out/baz/bar.o')).to be true
|
|
65
|
+
expect(File.exist?('build/release/out/src/foo/bar.o')).to be true
|
|
66
|
+
expect(File.exist?('build/release/out/src/baz/bar.o')).to be true
|
|
67
67
|
|
|
68
68
|
binary = Dir.glob('build/artifacts/release/*.out').first
|
|
69
69
|
run_output = `#{binary}`
|
|
@@ -128,7 +128,7 @@ ceedling_system_tests do
|
|
|
128
128
|
|
|
129
129
|
# The runner initializes and verifies the newly enabled module's mock
|
|
130
130
|
in_project do
|
|
131
|
-
expect(File.read( 'build/test/runners/test_Case_02_runner.c' )).to include( 'mock_MyModulePart2' )
|
|
131
|
+
expect(File.read( 'build/test/runners/test/test_Case_02_runner.c' )).to include( 'mock_MyModulePart2' )
|
|
132
132
|
end
|
|
133
133
|
end
|
|
134
134
|
|
|
@@ -123,9 +123,9 @@ ceedling_system_tests do
|
|
|
123
123
|
# so none of this test's mocks are considered stale purely from that
|
|
124
124
|
# unrelated cache miss. Only a change to the header a mock actually
|
|
125
125
|
# mocks, or to the mock's own config meta, can make it regenerate.
|
|
126
|
-
expect(rebuild).to_not match(/Generating mock for TestAdcModel::TaskScheduler\.h/)
|
|
127
|
-
expect(rebuild).to_not match(/Generating mock for TestAdcModel::TemperatureCalculator\.h/)
|
|
128
|
-
expect(rebuild).to_not match(/Generating mock for TestAdcModel::TemperatureFilter\.h/)
|
|
126
|
+
expect(rebuild).to_not match(/Generating mock for test\/adc\/TestAdcModel::TaskScheduler\.h/)
|
|
127
|
+
expect(rebuild).to_not match(/Generating mock for test\/adc\/TestAdcModel::TemperatureCalculator\.h/)
|
|
128
|
+
expect(rebuild).to_not match(/Generating mock for test\/adc\/TestAdcModel::TemperatureFilter\.h/)
|
|
129
129
|
|
|
130
130
|
expect(rebuild).to match(/^Compiling TestAdcModel\.c/)
|
|
131
131
|
expect(rebuild).to match(/^Linking TestAdcModel\.out/)
|
|
@@ -147,7 +147,7 @@ ceedling_system_tests do
|
|
|
147
147
|
expect(rebuild).to_not match(/^Compiling .*TimerModel/)
|
|
148
148
|
expect(rebuild).to_not match(/^Linking .*Usart/)
|
|
149
149
|
expect(rebuild).to_not match(/^Linking .*Timer/)
|
|
150
|
-
expect(rebuild).to_not match(/Generating mock for TestUsartConductor/)
|
|
150
|
+
expect(rebuild).to_not match(/Generating mock for test\/TestUsartConductor/)
|
|
151
151
|
end
|
|
152
152
|
end
|
|
153
153
|
end
|
|
@@ -220,6 +220,24 @@ ceedling_system_tests do
|
|
|
220
220
|
end
|
|
221
221
|
end
|
|
222
222
|
|
|
223
|
+
# Every remaining object is unchanged, so only the list of objects shows the change. A
|
|
224
|
+
# stale executable would still hold the source's code and report its cached pass.
|
|
225
|
+
it "relinks a test whose source leaves the build, failing at link without it" do
|
|
226
|
+
@c.with_context do
|
|
227
|
+
Dir.chdir "temp_sensor" do
|
|
228
|
+
@c.ceedling_build_exec("test:all")
|
|
229
|
+
|
|
230
|
+
@c.merge_project_yml_for_test({ :files => { :source => ['-:src/TemperatureFilter.c'] } })
|
|
231
|
+
rebuild = @c.ceedling_build_exec("test:TestTemperatureFilter.c")
|
|
232
|
+
|
|
233
|
+
expect(@c.last_exit_status).to_not eq(0)
|
|
234
|
+
expect(rebuild).to_not match(/^Compiling /)
|
|
235
|
+
expect(rebuild).to match(/^Linking TestTemperatureFilter\.out/)
|
|
236
|
+
expect(rebuild).to match(/undefined reference|Undefined symbols/)
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
223
241
|
it "clobber removes the dependency cache and forces a full rebuild afterward" do
|
|
224
242
|
@c.with_context do
|
|
225
243
|
Dir.chdir "temp_sensor" do
|
|
@@ -429,6 +447,95 @@ ceedling_system_tests do
|
|
|
429
447
|
end
|
|
430
448
|
end
|
|
431
449
|
|
|
450
|
+
# GH #1368: a link tracked its libraries only by their -l and -L arguments, so a library
|
|
451
|
+
# rebuilt under the same name relinked nothing. A test kept its cached result against the
|
|
452
|
+
# old library, and a release kept the old library's code. `m` is on no library path the
|
|
453
|
+
# project configures, so it is never tracked, and never relinks an unchanged build.
|
|
454
|
+
describe "Delta builds: linked libraries" do
|
|
455
|
+
before { @proj_name = unique_proj_name("delta_libs") }
|
|
456
|
+
|
|
457
|
+
def build_library!(value)
|
|
458
|
+
FileUtils.mkdir_p( ['vendor/lib', 'vendor/obj'] )
|
|
459
|
+
File.write( 'vendor/obj/x.c', "int lib_value(void) { return #{value}; }\n" )
|
|
460
|
+
FileUtils.rm_f( 'vendor/lib/libx.a' )
|
|
461
|
+
system( 'gcc', '-c', 'vendor/obj/x.c', '-o', 'vendor/obj/x.o' ) or raise 'Could not compile the library'
|
|
462
|
+
system( 'ar', 'rcs', 'vendor/lib/libx.a', 'vendor/obj/x.o' ) or raise 'Could not archive the library'
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
def deploy_library_project!
|
|
466
|
+
@c.ceedling_appcmd_exec("new #{@proj_name}")
|
|
467
|
+
|
|
468
|
+
Dir.chdir @proj_name do
|
|
469
|
+
build_library!( 1 )
|
|
470
|
+
File.write( 'src/x.h', "int lib_value(void);\n" )
|
|
471
|
+
File.write( 'src/main.c', "#include \"x.h\"\nint main(void) { return lib_value(); }\n" )
|
|
472
|
+
File.write( 'test/test_lib.c', <<~C )
|
|
473
|
+
#include "unity.h"
|
|
474
|
+
#include "x.h"
|
|
475
|
+
void setUp(void) {}
|
|
476
|
+
void tearDown(void) {}
|
|
477
|
+
void test_value(void) { TEST_ASSERT_EQUAL_INT(1, lib_value()); }
|
|
478
|
+
C
|
|
479
|
+
@c.merge_project_yml_for_test( {
|
|
480
|
+
:project => { :release_build => true },
|
|
481
|
+
:paths => { :libraries => ['vendor/lib'] },
|
|
482
|
+
:libraries => { :test => ['x', 'm'], :release => ['x', 'm'] }
|
|
483
|
+
} )
|
|
484
|
+
end
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
it "relinks a test when a library it links is rebuilt under the same name" do
|
|
488
|
+
@c.with_context do
|
|
489
|
+
deploy_library_project!
|
|
490
|
+
|
|
491
|
+
Dir.chdir @proj_name do
|
|
492
|
+
baseline = @c.ceedling_build_exec("test:all")
|
|
493
|
+
expect(baseline).to match(/PASSED:\s+1/)
|
|
494
|
+
|
|
495
|
+
build_library!( 2 )
|
|
496
|
+
rebuild = @c.ceedling_build_exec("test:all")
|
|
497
|
+
|
|
498
|
+
expect(rebuild).to_not match(/^Compiling /)
|
|
499
|
+
expect(rebuild).to match(/^Linking test_lib\.out/)
|
|
500
|
+
expect(rebuild).to match(/FAILED:\s+1/)
|
|
501
|
+
end
|
|
502
|
+
end
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
it "relinks a release when a library it links is rebuilt under the same name" do
|
|
506
|
+
@c.with_context do
|
|
507
|
+
deploy_library_project!
|
|
508
|
+
|
|
509
|
+
Dir.chdir @proj_name do
|
|
510
|
+
@c.ceedling_build_exec("release")
|
|
511
|
+
|
|
512
|
+
build_library!( 2 )
|
|
513
|
+
rebuild = @c.ceedling_build_exec("release")
|
|
514
|
+
|
|
515
|
+
expect(rebuild).to_not match(/^Compiling /)
|
|
516
|
+
expect(rebuild).to match(/^Linking /)
|
|
517
|
+
end
|
|
518
|
+
end
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
it "relinks nothing when no library changed, whatever libraries it can't find" do
|
|
522
|
+
@c.with_context do
|
|
523
|
+
deploy_library_project!
|
|
524
|
+
|
|
525
|
+
Dir.chdir @proj_name do
|
|
526
|
+
@c.ceedling_build_exec("test:all")
|
|
527
|
+
@c.ceedling_build_exec("release")
|
|
528
|
+
|
|
529
|
+
tests = @c.ceedling_build_exec("test:all")
|
|
530
|
+
release = @c.ceedling_build_exec("release")
|
|
531
|
+
|
|
532
|
+
expect(tests).to_not match(/^Linking /)
|
|
533
|
+
expect(release).to_not match(/^Linking /)
|
|
534
|
+
end
|
|
535
|
+
end
|
|
536
|
+
end
|
|
537
|
+
end
|
|
538
|
+
|
|
432
539
|
# :unity ↳ :shuffle_tests decides test-case execution order at runtime, inside
|
|
433
540
|
# the compiled executable's own main() -- not at compile or link time. So an
|
|
434
541
|
# executable delta builds correctly judge unchanged (same source, same flags,
|
|
@@ -528,7 +635,7 @@ ceedling_system_tests do
|
|
|
528
635
|
|
|
529
636
|
rebuild = @c.ceedling_build_exec("test:all")
|
|
530
637
|
|
|
531
|
-
expect(rebuild).to match(/^Compiling TestSoilMoisture::SoilMoisture\.c/)
|
|
638
|
+
expect(rebuild).to match(/^Compiling test\/TestSoilMoisture::SoilMoisture\.c/)
|
|
532
639
|
expect(rebuild).to match(/^Linking TestSoilMoisture\.out/)
|
|
533
640
|
expect(rebuild).to match(/^Running TestSoilMoisture\.out/)
|
|
534
641
|
|
|
@@ -563,7 +670,7 @@ ceedling_system_tests do
|
|
|
563
670
|
|
|
564
671
|
rebuild = @c.ceedling_build_exec("test:all")
|
|
565
672
|
|
|
566
|
-
expect(rebuild).to match(/^Compiling TestForestMonitor::ForestMonitor\.c/)
|
|
673
|
+
expect(rebuild).to match(/^Compiling test\/TestForestMonitor::ForestMonitor\.c/)
|
|
567
674
|
|
|
568
675
|
expect(rebuild).to_not match(/^Compiling.*SoilMoisture/)
|
|
569
676
|
expect(rebuild).to_not match(/^Compiling.*TemperatureSensor/)
|
|
@@ -631,11 +738,11 @@ ceedling_system_tests do
|
|
|
631
738
|
|
|
632
739
|
rebuild = @c.ceedling_build_exec("test:all")
|
|
633
740
|
|
|
634
|
-
expect(rebuild).to match(/Preprocessing partial (header|source) for TestSoilMoisture/)
|
|
635
|
-
expect(rebuild).to match(/Preprocessing partial (header|source) for TestForestMonitor/)
|
|
636
|
-
expect(rebuild).to match(/Generating Partial implementation for TestSoilMoisture/)
|
|
637
|
-
expect(rebuild).to match(/Generating Partial implementation for TestForestMonitor/)
|
|
638
|
-
expect(rebuild).to match(/Generating Partial mockable interface for TestForestMonitor/)
|
|
741
|
+
expect(rebuild).to match(/Preprocessing partial (header|source) for test\/TestSoilMoisture/)
|
|
742
|
+
expect(rebuild).to match(/Preprocessing partial (header|source) for test\/TestForestMonitor/)
|
|
743
|
+
expect(rebuild).to match(/Generating Partial implementation for test\/TestSoilMoisture/)
|
|
744
|
+
expect(rebuild).to match(/Generating Partial implementation for test\/TestForestMonitor/)
|
|
745
|
+
expect(rebuild).to match(/Generating Partial mockable interface for test\/TestForestMonitor/)
|
|
639
746
|
|
|
640
747
|
expect(rebuild).to match(/TESTED:\s+71/)
|
|
641
748
|
expect(rebuild).to match(/PASSED:\s+71/)
|
|
@@ -704,6 +811,25 @@ ceedling_system_tests do
|
|
|
704
811
|
end
|
|
705
812
|
end
|
|
706
813
|
|
|
814
|
+
# main.c is unchanged, so only the list of objects shows the change. A stale artifact
|
|
815
|
+
# would still hold the analyzer's code.
|
|
816
|
+
it "relinks when a source leaves the build, failing at link without it" do
|
|
817
|
+
@c.with_context do
|
|
818
|
+
Dir.chdir "cipher_quest" do
|
|
819
|
+
enable_release_features!
|
|
820
|
+
@c.ceedling_build_exec("release")
|
|
821
|
+
|
|
822
|
+
@c.merge_project_yml_for_test({ :files => { :source => ['-:src/analyzer.c'] } })
|
|
823
|
+
rebuild = @c.ceedling_build_exec("release")
|
|
824
|
+
|
|
825
|
+
expect(@c.last_exit_status).to_not eq(0)
|
|
826
|
+
expect(rebuild).to_not match(/^Compiling main\.c/)
|
|
827
|
+
expect(rebuild).to match(/^Linking /)
|
|
828
|
+
expect(rebuild).to match(/undefined reference|Undefined symbols/)
|
|
829
|
+
end
|
|
830
|
+
end
|
|
831
|
+
end
|
|
832
|
+
|
|
707
833
|
it "recompiles every object whose source #includes a changed header, via .d-file-derived transitive tracking, leaving unrelated objects untouched" do
|
|
708
834
|
@c.with_context do
|
|
709
835
|
Dir.chdir "cipher_quest" do
|
|
@@ -53,6 +53,7 @@ ceedling_system_tests do
|
|
|
53
53
|
test_case :project_with_gcov_untested_sources_compile_failure
|
|
54
54
|
test_case :project_with_gcov_untested_sources_standalone_task
|
|
55
55
|
test_case :project_with_gcov_untested_sources_compiled_with_matched_defines
|
|
56
|
+
test_case :project_with_gcov_untested_sources_sharing_a_name
|
|
56
57
|
test_case :help_tasks_include_gcov
|
|
57
58
|
test_case :create_html_report
|
|
58
59
|
test_case :create_html_report_with_gcovr_custom_args
|