ceedling 1.2.0 → 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 +57 -58
- data/Rakefile +5 -3
- 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 +35 -1
- data/bin/ceedling +13 -3
- data/bin/cli.rb +25 -6
- data/bin/cli_handler.rb +119 -73
- data/bin/cli_helper.rb +56 -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 +84 -3
- data/docs/KnownIssues.md +90 -4
- data/docs/ReleaseNotes.md +13 -0
- data/docs/overrides/main.html +11 -8
- 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 +19 -18
- 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 +39 -41
- 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} +65 -28
- 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/rake_app/test_task_name.rb +29 -0
- data/lib/ceedling/rakefile.rb +16 -1
- data/lib/ceedling/rakefiles/base/tasks_base.rake +1 -1
- data/lib/ceedling/rakefiles/release/rules_release.rake +4 -7
- data/lib/ceedling/rakefiles/tests/rules_tests.rake +3 -20
- data/lib/ceedling/rakefiles/tests/rules_tests_generate.rake +4 -30
- 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 +95 -87
- 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 +42 -41
- 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/bullseye.rake +6 -9
- 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/gcov.rake +6 -9
- 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/sanitize/sanitize.rake +6 -6
- data/plugins/valgrind/lib/valgrind.rb +14 -7
- data/plugins/valgrind/valgrind.rake +6 -6
- data/site-local/404.html +6 -20
- data/site-local/assets/javascripts/{bundle.d7400e89.min.js → bundle.c21346df.min.js} +3 -3
- data/site-local/assets/javascripts/{bundle.d7400e89.min.js.map → bundle.c21346df.min.js.map} +2 -2
- data/site-local/assets/javascripts/workers/{search.2c215733.min.js → search.a7633da7.min.js} +2 -2
- data/site-local/assets/javascripts/workers/{search.2c215733.min.js.map → search.a7633da7.min.js.map} +1 -1
- data/site-local/assets/stylesheets/main.57a0d79d.min.css +6 -0
- data/site-local/assets/stylesheets/main.57a0d79d.min.css.map +1 -0
- data/site-local/assets/stylesheets/palette.fb2fffe2.min.css +4 -0
- data/site-local/assets/stylesheets/palette.fb2fffe2.min.css.map +1 -0
- data/site-local/configuration/environment-vars.html +6 -20
- data/site-local/configuration/global-collections.html +6 -20
- data/site-local/configuration/index.html +6 -20
- data/site-local/configuration/loading.html +6 -20
- data/site-local/configuration/mixins.html +10 -24
- data/site-local/configuration/parallel-builds.html +6 -20
- data/site-local/configuration/project-file.html +8 -22
- data/site-local/configuration/reference/cexception.html +6 -20
- data/site-local/configuration/reference/cmock.html +8 -21
- data/site-local/configuration/reference/defines.html +16 -30
- data/site-local/configuration/reference/environment.html +10 -24
- data/site-local/configuration/reference/extension.html +6 -20
- data/site-local/configuration/reference/files.html +22 -30
- data/site-local/configuration/reference/flags.html +13 -27
- data/site-local/configuration/reference/index.html +6 -20
- data/site-local/configuration/reference/libraries.html +27 -23
- data/site-local/configuration/reference/mixins.html +6 -20
- data/site-local/configuration/reference/partials.html +6 -20
- data/site-local/configuration/reference/paths.html +38 -29
- data/site-local/configuration/reference/plugins.html +6 -20
- data/site-local/configuration/reference/project.html +32 -36
- data/site-local/configuration/reference/release-build.html +8 -20
- data/site-local/configuration/reference/test-build.html +6 -20
- data/site-local/configuration/reference/test-runner.html +6 -20
- data/site-local/configuration/reference/tools.html +27 -32
- data/site-local/configuration/reference/unity.html +6 -20
- data/site-local/configuration/which-ceedling.html +383 -37
- data/site-local/development/index.html +6 -20
- data/site-local/development/plugins/configuration.html +6 -20
- data/site-local/development/plugins/index.html +6 -20
- data/site-local/development/plugins/plugin-subclass.html +54 -68
- data/site-local/development/plugins/rake-tasks.html +8 -22
- data/site-local/development/releases.html +84 -29
- data/site-local/development/workflow.html +62 -71
- data/site-local/getting-started/builds.html +8 -20
- data/site-local/getting-started/command-line.html +62 -24
- data/site-local/getting-started/example-projects/cipher-quest.html +6 -20
- data/site-local/getting-started/example-projects/index.html +6 -20
- data/site-local/getting-started/example-projects/temp-sensor.html +6 -20
- data/site-local/getting-started/example-projects/wondrous-forest.html +6 -20
- data/site-local/getting-started/index.html +6 -20
- data/site-local/getting-started/installation.html +6 -20
- data/site-local/getting-started/quick-start.html +6 -20
- data/site-local/help.html +6 -20
- data/site-local/index.html +11 -24
- data/site-local/overview/build-system.html +6 -20
- data/site-local/overview/index.html +6 -20
- data/site-local/overview/test-environments.html +6 -20
- data/site-local/overview/tools-and-frameworks.html +6 -20
- data/site-local/plugins/beep.html +6 -20
- data/site-local/plugins/bullseye/index.html +13 -24
- data/site-local/plugins/bullseye/licensing.html +14 -28
- data/site-local/plugins/command-hooks.html +8 -22
- data/site-local/plugins/compile-commands-json-db.html +6 -20
- data/site-local/plugins/cppcheck.html +8 -22
- data/site-local/plugins/dependencies.html +16 -27
- data/site-local/plugins/fff.html +49 -32
- data/site-local/plugins/gcov/examples.html +7 -21
- data/site-local/plugins/gcov/gcovr.html +22 -33
- data/site-local/plugins/gcov/index.html +6 -20
- data/site-local/plugins/gcov/overview.html +9 -20
- data/site-local/plugins/gcov/reportgenerator.html +9 -23
- data/site-local/plugins/gcov/reporting.html +6 -20
- data/site-local/plugins/gcov/setup.html +8 -21
- data/site-local/plugins/gcov/tool-versions.html +6 -20
- data/site-local/plugins/gcov/troubleshooting.html +10 -24
- data/site-local/plugins/index.html +6 -20
- data/site-local/plugins/module-generator.html +21 -35
- data/site-local/plugins/report-build-warnings-log.html +53 -67
- data/site-local/plugins/report-tests-gtestlike-stdout.html +6 -20
- data/site-local/plugins/report-tests-ide-stdout.html +43 -57
- data/site-local/plugins/report-tests-log-factory.html +50 -64
- data/site-local/plugins/report-tests-pretty-stdout.html +7 -21
- data/site-local/plugins/report-tests-raw-output-log.html +9 -21
- data/site-local/plugins/report-tests-teamcity-stdout.html +20 -31
- data/site-local/plugins/sanitize.html +56 -65
- data/site-local/plugins/valgrind.html +49 -58
- data/site-local/project/index.html +6 -20
- data/site-local/project/release-history.html +6 -20
- data/site-local/project/sbom.html +6 -20
- data/site-local/project/upgrade.html +9 -20
- data/site-local/reference/build-directives.html +6 -20
- data/site-local/reference/command-line.html +15 -22
- data/site-local/reference/environment-vars.html +6 -20
- data/site-local/reference/gcov-plugin.html +6 -20
- data/site-local/reference/global-collections.html +6 -20
- data/site-local/reference/index.html +6 -20
- data/site-local/reference/partials-macros.html +6 -20
- data/site-local/reference/project-configuration.html +6 -20
- data/site-local/sitemap.xml.gz +0 -0
- data/site-local/snapshot/examples/cipher_quest/index.html +16 -30
- data/site-local/snapshot/examples/temp_sensor/index.html +8 -22
- data/site-local/snapshot/examples/wondrous_forest/index.html +6 -20
- 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/build-directives.html +14 -28
- data/site-local/testing-guide/conventions.html +66 -27
- data/site-local/testing-guide/frameworks.html +11 -25
- data/site-local/testing-guide/index.html +6 -20
- data/site-local/testing-guide/partials/configuration.html +8 -22
- data/site-local/testing-guide/partials/conventions.html +8 -22
- data/site-local/testing-guide/partials/directives.html +16 -30
- data/site-local/testing-guide/partials/example.html +14 -28
- data/site-local/testing-guide/partials/index.html +6 -20
- data/site-local/testing-guide/partials/overview.html +6 -20
- data/site-local/testing-guide/partials/variables.html +11 -25
- data/site-local/testing-guide/test-cases.html +13 -27
- data/site-local/testing-guide/test-sample.html +12 -26
- data/site-local/testing-guide/test-suite-anatomy.html +6 -20
- 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_pipeline_spec.rb +10 -0
- 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 +62 -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/rake_task_registry_plugins_spec.rb +95 -0
- 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 +192 -75
- data/spec/support/file_tree_helper.rb +88 -0
- data/spec/support/integration/configurator_integration_helper.rb +10 -7
- 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 +47 -0
- data/spec/units/bin/cli_handler_spec.rb +284 -7
- data/spec/units/bin/cli_helper_spec.rb +126 -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 +65 -103
- data/spec/units/config/configurator_spec.rb +37 -6
- 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} +154 -32
- 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/rake_app/test_task_name_spec.rb +47 -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 +107 -5
- 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 +122 -33
- data/lib/ceedling/file_path_collection_utils.rb +0 -164
- data/site-local/assets/stylesheets/main.ec1eaa64.min.css +0 -1
- data/site-local/assets/stylesheets/main.ec1eaa64.min.css.map +0 -1
- data/site-local/assets/stylesheets/palette.ab4e12ef.min.css +0 -1
- data/site-local/assets/stylesheets/palette.ab4e12ef.min.css.map +0 -1
|
@@ -0,0 +1,322 @@
|
|
|
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
|
+
# Path handling across project layouts and the spellings a project file may use for one
|
|
9
|
+
# place: through configuration, collection, build-path mapping, and the lookups that invert
|
|
10
|
+
# it. Every build file must land inside the build root, distinct inputs must stay distinct,
|
|
11
|
+
# and every spelling of one layout must place files alike.
|
|
12
|
+
#
|
|
13
|
+
# Each example names the gap it probes (GH #1370 and the path handling audit around it).
|
|
14
|
+
|
|
15
|
+
require 'spec_helper'
|
|
16
|
+
require 'path_scenario_harness'
|
|
17
|
+
|
|
18
|
+
describe 'Path scenarios (integration)' do
|
|
19
|
+
include PathScenarioHarness
|
|
20
|
+
|
|
21
|
+
TEST_C = "#include \"unity.h\"\nvoid setUp(void) {}\nvoid tearDown(void) {}\nvoid test_it(void) {}\n"
|
|
22
|
+
|
|
23
|
+
def c(name)
|
|
24
|
+
"int #{name}(void) { return 0; }\n"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def h(name)
|
|
28
|
+
"int #{name}(void);\n"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# --- Baseline -------------------------------------------------------------------------
|
|
32
|
+
|
|
33
|
+
it 'baseline: mirrors same-named files below one plain root, inside the build root' do
|
|
34
|
+
files = {
|
|
35
|
+
'app/src/a/util.c' => c( 'a' ), 'app/src/b/util.c' => c( 'b' ),
|
|
36
|
+
'app/src/a/util.h' => h( 'a' ), 'app/src/b/util.h' => h( 'b' ),
|
|
37
|
+
'app/test/test_u.c' => TEST_C
|
|
38
|
+
}
|
|
39
|
+
in_workspace( files ) do |ws, app|
|
|
40
|
+
scene = scenario( scenario_yaml( ws: ws, app: app, paths: { test: ['test/**'], source: ['src/**'], include: ['src/**'] } ) )
|
|
41
|
+
placed = placements( scene )
|
|
42
|
+
|
|
43
|
+
placed.each_value { |paths| expect_inside_build( paths ) }
|
|
44
|
+
expect_distinct( placed[:test_objects], 'test objects' )
|
|
45
|
+
expect_distinct( placed[:release_objects], 'release objects' )
|
|
46
|
+
expect_distinct( placed[:preprocessed], 'preprocessed headers' )
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# --- G1 (#1370): a `..` root beside a header outside the project ------------------------
|
|
51
|
+
|
|
52
|
+
# The report's vendor SDK sat at its drive's root, far above the project, so its headers'
|
|
53
|
+
# paths climb past the `..` root. A sibling one level up is truly below `..` and mirrors.
|
|
54
|
+
context 'G1 (#1370): a `..` root beside an include path far outside the project' do
|
|
55
|
+
def files
|
|
56
|
+
{
|
|
57
|
+
'app/src/main.c' => c( 'main' ), 'app/src/main.h' => h( 'main' ),
|
|
58
|
+
'app/test/test_m.c' => TEST_C,
|
|
59
|
+
'vendor/inc/cmsis.h' => h( 'cmsis' )
|
|
60
|
+
}
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
[
|
|
64
|
+
['an absolute vendor path far outside', '%{far}/inc'],
|
|
65
|
+
['a sibling vendor path', '../vendor/inc']
|
|
66
|
+
].each do |label, vendor|
|
|
67
|
+
it "places a mock of the vendor header inside the build root, with #{label}" do
|
|
68
|
+
in_workspace( files, far: { 'inc/sdk.h' => h( 'sdk' ) } ) do |ws, app|
|
|
69
|
+
scene = scenario( scenario_yaml( ws: ws, app: app, paths: { test: ['test/**'], source: ['src/**'], include: ['../**', vendor] } ) )
|
|
70
|
+
placed = placements( scene )
|
|
71
|
+
|
|
72
|
+
expect_inside_build( placed[:mocks] )
|
|
73
|
+
expect_inside_build( placed[:preprocessed] )
|
|
74
|
+
expect_inside_build( placed[:test_objects] )
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# --- G2: equivalent spellings of one root ------------------------------------------------
|
|
81
|
+
|
|
82
|
+
context 'G2: one layout under each spelling of its roots' do
|
|
83
|
+
def files
|
|
84
|
+
{
|
|
85
|
+
'app/src/a/util.c' => c( 'a' ), 'app/src/b/util.c' => c( 'b' ),
|
|
86
|
+
'app/src/a/util.h' => h( 'a' ), 'app/src/b/util.h' => h( 'b' ),
|
|
87
|
+
'app/test/test_u.c' => TEST_C
|
|
88
|
+
}
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def placed_with(spelling, ws, app)
|
|
92
|
+
spell = PathScenarioHarness::ROOT_SPELLINGS[spelling]
|
|
93
|
+
roots = ->(root) { [spell.call( root, ws: ws, app: app )] }
|
|
94
|
+
scene = scenario( scenario_yaml( ws: ws, app: app, paths: { test: roots.( 'test/**' ), source: roots.( 'src/**' ), include: roots.( 'src/**' ) } ) )
|
|
95
|
+
return [scene, relative_placements( scene )]
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
(PathScenarioHarness::ROOT_SPELLINGS.keys - [:plain]).each do |spelling|
|
|
99
|
+
it "places every build file as the plain spelling does, with #{spelling} roots" do
|
|
100
|
+
in_workspace( files, symlink: spelling == :symlink ) do |ws, app|
|
|
101
|
+
_, plain = placed_with( :plain, ws, app )
|
|
102
|
+
scene, spelled = placed_with( spelling, ws, app )
|
|
103
|
+
|
|
104
|
+
expect_one_spelling_each( scene[:configurator] )
|
|
105
|
+
expect(spelled).to eq( plain )
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# --- G3 and G13: exclusions ---------------------------------------------------------------
|
|
112
|
+
|
|
113
|
+
context 'G3 and G13: a `-:` exclusion' do
|
|
114
|
+
def files
|
|
115
|
+
{
|
|
116
|
+
'app/src/sub/x.c' => c( 'x1' ), 'app/src/exp/sub/x.c' => c( 'x2' ), 'app/src/exp/deep/y.c' => c( 'y' ),
|
|
117
|
+
'app/src/main.h' => h( 'main' ), 'app/test/test_m.c' => TEST_C
|
|
118
|
+
}
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it 'G13: excludes the whole subtree it names' do
|
|
122
|
+
in_workspace( files ) do |ws, app|
|
|
123
|
+
scene = scenario( scenario_yaml( ws: ws, app: app, paths: { test: ['test/**'], source: ['+:src/**', '-:src/exp'], include: ['src/**'] } ) )
|
|
124
|
+
|
|
125
|
+
expect(scene[:configurator].collection_all_source).to match_array( %w[src/sub/x.c] )
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# A file the exclusion fails to drop (G13) must not mirror below the exclusion itself
|
|
130
|
+
it 'G3: is never a root that kept files mirror below' do
|
|
131
|
+
in_workspace( files ) do |ws, app|
|
|
132
|
+
scene = scenario( scenario_yaml( ws: ws, app: app, paths: { test: ['test/**'], source: ['+:src/**', '-:src/exp'], include: ['src/**'] } ) )
|
|
133
|
+
placed = placements( scene )
|
|
134
|
+
|
|
135
|
+
expect_distinct( placed[:release_objects], 'release objects' )
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# --- G4: header-to-source correlation ---------------------------------------------------
|
|
141
|
+
|
|
142
|
+
context 'G4: a header found beside its source by convention' do
|
|
143
|
+
def files
|
|
144
|
+
{
|
|
145
|
+
'app/include/drv/x.h' => h( 'x' ), 'app/src/drv/x.c' => c( 'x' ),
|
|
146
|
+
'app/components/foo/include/foo.h' => h( 'foo' ), 'app/components/foo/src/foo.c' => c( 'foo' ),
|
|
147
|
+
'app/test/test_x.c' => TEST_C
|
|
148
|
+
}
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
{
|
|
152
|
+
'a plain include root' => ['include/**'],
|
|
153
|
+
'a `./` include root' => ['./include/**'],
|
|
154
|
+
'an absolute include root' => ['%{app}/include/**']
|
|
155
|
+
}.each do |label, include|
|
|
156
|
+
it "finds the source of a header below #{label}" do
|
|
157
|
+
in_workspace( files ) do |ws, app|
|
|
158
|
+
scene = scenario( scenario_yaml( ws: ws, app: app, paths: { test: ['test/**'], source: ['src/**'], include: include } ) )
|
|
159
|
+
|
|
160
|
+
expect(scene[:finder].find_build_input_file( filepath: 'include/drv/x.h', complain: :ignore, context: :test )).to eq( 'src/drv/x.c' )
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
it 'finds the source of a header below a glob-middle include root' do
|
|
166
|
+
in_workspace( files ) do |ws, app|
|
|
167
|
+
scene = scenario( scenario_yaml( ws: ws, app: app, paths: { test: ['test/**'], source: ['components/*/src'], include: ['components/*/include'] } ) )
|
|
168
|
+
|
|
169
|
+
expect(scene[:finder].find_build_input_file( filepath: 'components/foo/include/foo.h', complain: :ignore, context: :test )).to eq( 'components/foo/src/foo.c' )
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# --- G5 and G6: collisions --------------------------------------------------------------
|
|
175
|
+
|
|
176
|
+
context 'G5: the same relative path below two roots' do
|
|
177
|
+
it 'gives each source its own release object' do
|
|
178
|
+
files = { 'app/src/foo.c' => c( 'a' ), 'app/lib/foo.c' => c( 'b' ), 'app/src/foo.h' => h( 'a' ), 'app/test/test_f.c' => TEST_C }
|
|
179
|
+
in_workspace( files ) do |ws, app|
|
|
180
|
+
scene = scenario( scenario_yaml( ws: ws, app: app, paths: { test: ['test/**'], source: ['src/**', 'lib/**'], include: ['src/**'] } ) )
|
|
181
|
+
|
|
182
|
+
expect_distinct( placements( scene )[:release_objects], 'release objects' )
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
context 'G6: nested roots' do
|
|
188
|
+
it 'gives a file in the inner root and one in the outer root their own objects' do
|
|
189
|
+
files = { 'app/src/util.c' => c( 'a' ), 'app/src/legacy/util.c' => c( 'b' ), 'app/src/util.h' => h( 'a' ), 'app/test/test_u.c' => TEST_C }
|
|
190
|
+
in_workspace( files ) do |ws, app|
|
|
191
|
+
scene = scenario( scenario_yaml( ws: ws, app: app, paths: { test: ['test/**'], source: ['src/**', 'src/legacy/**'], include: ['src/**'] } ) )
|
|
192
|
+
placed = placements( scene )
|
|
193
|
+
|
|
194
|
+
expect_distinct( placed[:test_objects], 'test objects' )
|
|
195
|
+
expect_distinct( placed[:release_objects], 'release objects' )
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# --- G8: outside every root -------------------------------------------------------------
|
|
201
|
+
|
|
202
|
+
context 'G8: sources reached only through :files' do
|
|
203
|
+
it 'gives same-named files outside every root their own objects' do
|
|
204
|
+
files = { 'app/src/main.c' => c( 'main' ), 'app/src/main.h' => h( 'main' ), 'app/a/util.c' => c( 'a' ), 'app/b/util.c' => c( 'b' ), 'app/test/test_m.c' => TEST_C }
|
|
205
|
+
in_workspace( files ) do |ws, app|
|
|
206
|
+
scene = scenario( scenario_yaml( ws: ws, app: app, paths: { test: ['test/**'], source: ['src/**'], include: ['src/**'] }, files: { source: ['a/util.c', 'b/util.c'] } ) )
|
|
207
|
+
|
|
208
|
+
expect_distinct( placements( scene )[:release_objects], 'release objects' )
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# --- Sources outside the project --------------------------------------------------------
|
|
214
|
+
|
|
215
|
+
context 'sources and headers in a sibling directory' do
|
|
216
|
+
it 'places their build files inside the build root, each its own' do
|
|
217
|
+
files = {
|
|
218
|
+
'shared/src/a/util.c' => c( 'a' ), 'shared/src/b/util.c' => c( 'b' ),
|
|
219
|
+
'shared/src/a/util.h' => h( 'a' ), 'shared/src/b/util.h' => h( 'b' ),
|
|
220
|
+
'app/test/test_u.c' => TEST_C
|
|
221
|
+
}
|
|
222
|
+
in_workspace( files ) do |ws, app|
|
|
223
|
+
scene = scenario( scenario_yaml( ws: ws, app: app, paths: { test: ['test/**'], source: ['../shared/src/**'], include: ['../shared/src/**'] } ) )
|
|
224
|
+
placed = placements( scene )
|
|
225
|
+
|
|
226
|
+
placed.each_value { |paths| expect_inside_build( paths ) }
|
|
227
|
+
expect_distinct( placed[:release_objects], 'release objects' )
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# --- G15: a root above the build root --------------------------------------------------
|
|
233
|
+
|
|
234
|
+
context 'G15: a root that holds the build root' do
|
|
235
|
+
it 'collects nothing from an existing build directory' do
|
|
236
|
+
files = {
|
|
237
|
+
'app/src/main.c' => c( 'main' ), 'app/src/main.h' => h( 'main' ), 'app/test/test_m.c' => TEST_C,
|
|
238
|
+
'app/build/test/mocks/test/test_m/mock_main.h' => h( 'mock' ), 'app/build/test/runners/test/test_m/test_m_runner.c' => c( 'r' )
|
|
239
|
+
}
|
|
240
|
+
in_workspace( files ) do |ws, app|
|
|
241
|
+
scene = scenario( scenario_yaml( ws: ws, app: app, paths: { test: ['test/**'], source: ['src/**'], include: ['../**'] } ) )
|
|
242
|
+
|
|
243
|
+
expect_collections_outside_build( scene[:configurator] )
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
# A release compiles every collected source, so generated mocks and runners broke it
|
|
248
|
+
it 'collects nothing from an existing build directory through a `:files` glob' do
|
|
249
|
+
files = {
|
|
250
|
+
'app/src/main.c' => c( 'main' ), 'app/src/main.h' => h( 'main' ), 'app/test/test_m.c' => TEST_C,
|
|
251
|
+
'app/build/test/mocks/test/test_m/mock_main.c' => c( 'mock' ), 'app/build/vendor/unity/src/unity.c' => c( 'unity' )
|
|
252
|
+
}
|
|
253
|
+
in_workspace( files ) do |ws, app|
|
|
254
|
+
yaml = scenario_yaml( ws: ws, app: app, paths: { test: ['test/**'], source: ['src/**'], include: ['src/**'] }, files: { source: ['+:**/*.c'] } )
|
|
255
|
+
scene = scenario( yaml )
|
|
256
|
+
|
|
257
|
+
expect_collections_outside_build( scene[:configurator] )
|
|
258
|
+
expect(scene[:configurator].collection_release_build_input.to_a.grep( %r{\Abuild/} )).to be_empty
|
|
259
|
+
expect(scene[:configurator].collection_existing_test_build_input.to_a.grep( %r{\Abuild/test/} )).to be_empty
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
# Generated code may sit in the build root, beside the directories Ceedling creates there
|
|
264
|
+
it 'collects generated code an entry names in the build root, but nothing Ceedling created there' do
|
|
265
|
+
files = {
|
|
266
|
+
'app/src/main.c' => c( 'main' ), 'app/src/main.h' => h( 'main' ), 'app/test/test_m.c' => TEST_C,
|
|
267
|
+
'app/build/gen/table.c' => c( 'table' ), 'app/build/gen/table.h' => h( 'table' ),
|
|
268
|
+
'app/build/test/mocks/test/test_m/mock_main.c' => c( 'mock' ), 'app/build/test/mocks/test/test_m/mock_main.h' => h( 'mock' )
|
|
269
|
+
}
|
|
270
|
+
in_workspace( files ) do |ws, app|
|
|
271
|
+
paths = { test: ['test/**'], source: ['src/**', 'build/**'], include: ['src/**', 'build/gen'] }
|
|
272
|
+
yaml = scenario_yaml( ws: ws, app: app, paths: paths, files: { source: ['+:build/**/*.c'] } )
|
|
273
|
+
scene = scenario( yaml )
|
|
274
|
+
|
|
275
|
+
expect(scene[:configurator].collection_all_source.to_a).to contain_exactly( 'src/main.c', 'build/gen/table.c' )
|
|
276
|
+
expect(scene[:configurator].collection_all_headers.to_a).to include( 'build/gen/table.h' )
|
|
277
|
+
expect(scene[:configurator].collection_all_headers.to_a.grep( %r{\Abuild/test/} )).to be_empty
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
# --- Test files kept out of the sources and the release --------------------------------
|
|
283
|
+
|
|
284
|
+
context 'test files among the sources' do
|
|
285
|
+
# A release compiles every source it collects, and a test file holds a second main()
|
|
286
|
+
it 'collects no test file into the sources or the release through a `:files` glob' do
|
|
287
|
+
files = { 'app/src/main.c' => c( 'main' ), 'app/src/main.h' => h( 'main' ), 'app/test/test_m.c' => TEST_C }
|
|
288
|
+
in_workspace( files ) do |ws, app|
|
|
289
|
+
yaml = scenario_yaml( ws: ws, app: app, paths: { test: ['test/**'], source: ['src/**'], include: ['src/**'] }, files: { source: ['+:**/*.c'] } )
|
|
290
|
+
scene = scenario( yaml )
|
|
291
|
+
|
|
292
|
+
expect(scene[:configurator].collection_all_tests.to_a).to eq( ['test/test_m.c'] )
|
|
293
|
+
expect(scene[:configurator].collection_all_source.to_a).to eq( ['src/main.c'] )
|
|
294
|
+
expect(scene[:configurator].collection_release_build_input.to_a).to eq( ['src/main.c'] )
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
# A test root beside the sources reaches the release through :paths as well
|
|
299
|
+
it 'collects no test file into the release from a source root that holds the tests' do
|
|
300
|
+
files = { 'app/src/main.c' => c( 'main' ), 'app/src/main.h' => h( 'main' ), 'app/src/test/test_m.c' => TEST_C }
|
|
301
|
+
in_workspace( files ) do |ws, app|
|
|
302
|
+
scene = scenario( scenario_yaml( ws: ws, app: app, paths: { test: ['src/test/**'], source: ['src/**'], include: ['src/**'] } ) )
|
|
303
|
+
|
|
304
|
+
expect(scene[:configurator].collection_release_build_input.to_a).to eq( ['src/main.c'] )
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
# --- G12: the working directory reached through a symlink -------------------------------
|
|
311
|
+
|
|
312
|
+
context 'G12: absolute roots spelled through a symlink to the project' do
|
|
313
|
+
it 'collects each file once' do
|
|
314
|
+
files = { 'app/src/main.c' => c( 'main' ), 'app/src/main.h' => h( 'main' ), 'app/test/test_m.c' => TEST_C }
|
|
315
|
+
in_workspace( files, symlink: true ) do |ws, app|
|
|
316
|
+
scene = scenario( scenario_yaml( ws: ws, app: app, paths: { test: ['test/**'], source: ['src/**', '%{ws}/link/src/**'], include: ['src/**'] } ) )
|
|
317
|
+
|
|
318
|
+
expect_one_spelling_each( scene[:configurator] )
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
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
|
+
# The task registry decides from the requested task names whether a command builds tests or a
|
|
9
|
+
# release, and so whether build/vendor/ is populated (GH #1361). It reads that from the real
|
|
10
|
+
# .rake files. The first pass runs before plugin constants are loaded, so a plugin namespace
|
|
11
|
+
# such as `namespace GCOV_SYM do` is resolved by its NAME_SYM naming convention. The second
|
|
12
|
+
# pass resolves the constants themselves. Both must agree.
|
|
13
|
+
|
|
14
|
+
require 'spec_helper'
|
|
15
|
+
require 'ceedling/constants'
|
|
16
|
+
require 'ceedling/rake_app/rake_task_registry'
|
|
17
|
+
|
|
18
|
+
describe 'RakeTaskRegistry against the real rakefiles (integration)' do
|
|
19
|
+
REGISTRY_SPEC_ROOT = File.expand_path( '../..', __dir__ )
|
|
20
|
+
|
|
21
|
+
REGISTRY_SPEC_RAKEFILES = Dir.glob( File.join( REGISTRY_SPEC_ROOT, 'lib/ceedling/rakefiles/**/*.rake' ) ) +
|
|
22
|
+
%w[gcov valgrind sanitize bullseye].map { |plugin| File.join( REGISTRY_SPEC_ROOT, "plugins/#{plugin}/#{plugin}.rake" ) }
|
|
23
|
+
|
|
24
|
+
REGISTRY_SPEC_PLUGIN_CONSTANTS = {
|
|
25
|
+
'GCOV_SYM' => :gcov,
|
|
26
|
+
'VALGRIND_SYM' => :valgrind,
|
|
27
|
+
'SANITIZE_SYM' => :sanitize,
|
|
28
|
+
'BULLSEYE_SYM' => :bullseye
|
|
29
|
+
}.freeze
|
|
30
|
+
|
|
31
|
+
REGISTRY_SPEC_TEST_BUILDS = %w[
|
|
32
|
+
test test:all test:test_foo.c test:unit/test_foo.c
|
|
33
|
+
gen:mocks:test_foo.c
|
|
34
|
+
gcov:all gcov:test_foo.c gcov:test/test_foo.c
|
|
35
|
+
valgrind:all valgrind:test/test_foo.c
|
|
36
|
+
sanitize:all sanitize:test/test_foo.c
|
|
37
|
+
bullseye:all bullseye:test/test_foo.c
|
|
38
|
+
].freeze
|
|
39
|
+
|
|
40
|
+
REGISTRY_SPEC_NOT_BUILDS = %w[files:test dumpconfig clobber clean utils:gcov report:gcov module:create].freeze
|
|
41
|
+
|
|
42
|
+
def registry
|
|
43
|
+
registry = RakeTaskRegistry.new
|
|
44
|
+
registry.register_test_tasks( REGISTRY_SPEC_RAKEFILES )
|
|
45
|
+
registry.register_release_tasks( REGISTRY_SPEC_RAKEFILES )
|
|
46
|
+
return registry
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def expect_classified(registry)
|
|
50
|
+
REGISTRY_SPEC_TEST_BUILDS.each do |task|
|
|
51
|
+
expect( registry.task_is?( task, RakeTaskRegistry::TAG_TEST ) ).to be(true), "#{task} should be a test build"
|
|
52
|
+
expect( registry.task_is?( task, RakeTaskRegistry::TAG_BUILD ) ).to be(true), "#{task} should be a build"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
expect( registry.task_is?( 'release', RakeTaskRegistry::TAG_RELEASE ) ).to be(true)
|
|
56
|
+
expect( registry.task_is?( 'release', RakeTaskRegistry::TAG_TEST ) ).to be(false)
|
|
57
|
+
|
|
58
|
+
REGISTRY_SPEC_NOT_BUILDS.each do |task|
|
|
59
|
+
expect( registry.task_is?( task, RakeTaskRegistry::TAG_BUILD ) ).to be(false), "#{task} should not be a build"
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'finds every test-building plugin namespace before plugin constants are loaded' do
|
|
64
|
+
REGISTRY_SPEC_PLUGIN_CONSTANTS.each_key { |name| hide_const( name ) }
|
|
65
|
+
expect_classified( registry )
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# A build reached through a call the registry can't place would leave build/vendor
|
|
69
|
+
# unpopulated. Each call sits in a namespace, or in a top-level task (`task RELEASE_SYM`)
|
|
70
|
+
# named for a namespace the registry knows.
|
|
71
|
+
it 'places every test and release pipeline call where the registry finds it' do
|
|
72
|
+
registered = registry
|
|
73
|
+
markers = [RakeTaskRegistry::MARKER_TEST_TASKS_SETUP_AND_INVOKE, RakeTaskRegistry::MARKER_RELEASE_TASKS]
|
|
74
|
+
|
|
75
|
+
REGISTRY_SPEC_RAKEFILES.each do |rakefile|
|
|
76
|
+
lines = File.readlines( rakefile, encoding: 'bom|utf-8' )
|
|
77
|
+
lines.each_with_index do |line, index|
|
|
78
|
+
next unless markers.any? { |marker| line.match?( marker ) }
|
|
79
|
+
|
|
80
|
+
namespace = registered.send( :find_enclosing_namespace, lines, index )
|
|
81
|
+
task_line = lines[0...index].reverse.find { |prior| prior.match?( /\Atask\s/ ) }
|
|
82
|
+
task_name = task_line && task_line[/\Atask\s*\(?\s*:?([A-Za-z_]+)/, 1]
|
|
83
|
+
task_name = Object.const_get( task_name ).to_s if task_name&.match?( /\A[A-Z_]+\z/ )
|
|
84
|
+
found = !namespace.nil? || !registered.tags_for( task_name.to_s ).empty?
|
|
85
|
+
|
|
86
|
+
expect( found ).to be(true), "#{File.basename( rakefile )}:#{index + 1} runs a pipeline the registry cannot place"
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it 'finds every test-building plugin namespace once plugin constants are loaded' do
|
|
92
|
+
REGISTRY_SPEC_PLUGIN_CONSTANTS.each { |name, value| stub_const( name, value ) }
|
|
93
|
+
expect_classified( registry )
|
|
94
|
+
end
|
|
95
|
+
end
|
|
@@ -16,7 +16,7 @@ require 'open3'
|
|
|
16
16
|
require 'json'
|
|
17
17
|
require 'ceedling/constants'
|
|
18
18
|
require 'ceedling/plugins/plugin'
|
|
19
|
-
require 'ceedling/file_wrapper'
|
|
19
|
+
require 'ceedling/filesystem/file_wrapper'
|
|
20
20
|
|
|
21
21
|
$LOAD_PATH.unshift( File.expand_path( '../../plugins/report_build_warnings_log/lib', __dir__ ) )
|
|
22
22
|
|
|
@@ -16,7 +16,7 @@ require 'spec_helper'
|
|
|
16
16
|
require 'json'
|
|
17
17
|
require 'tmpdir'
|
|
18
18
|
require 'rexml/document'
|
|
19
|
-
require 'ceedling/file_wrapper'
|
|
19
|
+
require 'ceedling/filesystem/file_wrapper'
|
|
20
20
|
require 'ceedling/config/config_walkinator'
|
|
21
21
|
|
|
22
22
|
$: << File.expand_path('../../../plugins/report_tests_log_factory/lib', __FILE__)
|
|
@@ -14,7 +14,7 @@ require 'spec_integration_helper'
|
|
|
14
14
|
require 'open3'
|
|
15
15
|
require 'tmpdir'
|
|
16
16
|
require 'ceedling/constants'
|
|
17
|
-
require 'ceedling/file_wrapper'
|
|
17
|
+
require 'ceedling/filesystem/file_wrapper'
|
|
18
18
|
require 'ceedling/generators/generator'
|
|
19
19
|
require 'ceedling/system_wrapper'
|
|
20
20
|
require 'fileutils'
|
|
@@ -140,7 +140,8 @@ describe 'Test file #include extraction (integration)' do
|
|
|
140
140
|
|
|
141
141
|
extract_in_mode( tree, 'test_reader.c' ) do |harness, testable|
|
|
142
142
|
expect(harness.mocks( 'test/test_reader.c' )).to eq( ['mock_widget.h'] )
|
|
143
|
-
|
|
143
|
+
# The macro's #include resolves as `drivers/mock_widget.h`, reached from the mock root
|
|
144
|
+
expect(testable.mock_search_paths).to eq( ['build/mocks/test_reader/drivers', 'build/mocks/test_reader'] )
|
|
144
145
|
end
|
|
145
146
|
end
|
|
146
147
|
|
|
@@ -0,0 +1,198 @@
|
|
|
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
|
+
# How tests are named, across project layouts with same-named tests (GH #1364). A project's YAML runs through the real
|
|
9
|
+
# configuration pipeline in a temporary project, so test paths and collections come from
|
|
10
|
+
# real globs. A real FilePathUtils names each test, and a real TestBuildSetup prepares its
|
|
11
|
+
# directories, as stage 1 of a build does.
|
|
12
|
+
|
|
13
|
+
require 'spec_helper'
|
|
14
|
+
require 'configurator_integration_helper'
|
|
15
|
+
require 'ceedling/filesystem/file_path_utils'
|
|
16
|
+
require 'ceedling/filesystem/file_finder'
|
|
17
|
+
require 'ceedling/filesystem/file_finder_helper'
|
|
18
|
+
require 'ceedling/test_invoker/test_build_setup'
|
|
19
|
+
require 'ceedling/test_invoker/test_invoker_types'
|
|
20
|
+
|
|
21
|
+
describe 'Test naming (integration)' do
|
|
22
|
+
include ConfiguratorIntegrationHelpers
|
|
23
|
+
|
|
24
|
+
# Runs each test of a batch in turn, in place of the thread pool
|
|
25
|
+
class TestNamingBatchinator
|
|
26
|
+
def exec(things:, **_options)
|
|
27
|
+
things.each { |thing| yield thing }
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# name => [test paths, `:paths ↳ :test` entries, `:files ↳ :test` entries]
|
|
32
|
+
TEST_NAMING_LAYOUTS = {
|
|
33
|
+
'flat and nested under one root' => [%w[test/test_calc.c test/unit/test_calc.c], %w[test/**], []],
|
|
34
|
+
'the same subdirectory under two roots' => [%w[test/unit/test_calc.c extra/unit/test_calc.c], %w[test/unit/** extra/**], []],
|
|
35
|
+
'overlapping roots' => [%w[test/test_calc.c test/unit/test_calc.c], %w[test/** test/unit/**], []],
|
|
36
|
+
'the same layout under two roots' => [%w[test/foo/test_x.c extra/foo/test_x.c], %w[test/** extra/**], []],
|
|
37
|
+
'a :files test outside every root' => [%w[test/test_calc.c other/test_calc.c], %w[test/**], %w[other/test_calc.c]]
|
|
38
|
+
}.freeze
|
|
39
|
+
|
|
40
|
+
def project_yaml(test_paths, test_files)
|
|
41
|
+
return <<~YAML
|
|
42
|
+
:project:
|
|
43
|
+
:build_root: build
|
|
44
|
+
:paths:
|
|
45
|
+
:test: #{test_paths.inspect}
|
|
46
|
+
:source: [src/**]
|
|
47
|
+
:include: [src/**]
|
|
48
|
+
:files:
|
|
49
|
+
:test: #{test_files.inspect}
|
|
50
|
+
YAML
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def project_files(tests)
|
|
54
|
+
files = { 'src/calc.c' => "int calc(void) { return 1; }\n", 'src/calc.h' => "int calc(void);\n" }
|
|
55
|
+
tests.each { |test| files[test] = "#include \"unity.h\"\nvoid test_it(void) {}\n" }
|
|
56
|
+
return files
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Stage 1 of a build of `tests`, with real naming and real directories
|
|
60
|
+
def prepare(configurator, tests)
|
|
61
|
+
file_wrapper = FileWrapper.new( loginator: double( 'loginator', log: nil ), verbosinator: double( 'verbosinator', should_output?: false ) )
|
|
62
|
+
file_path_utils = FilePathUtils.new( configurator: configurator, file_wrapper: file_wrapper )
|
|
63
|
+
|
|
64
|
+
collaborators = TestBuildSetup.constructor_keys.to_h { |key| [key, double( key.to_s )] }
|
|
65
|
+
setup = TestBuildSetup.new( collaborators.merge(
|
|
66
|
+
configurator: configurator, file_wrapper: file_wrapper, file_path_utils: file_path_utils, batchinator: TestNamingBatchinator.new
|
|
67
|
+
) )
|
|
68
|
+
|
|
69
|
+
state = TestInvokerTypes::PipelineState.new( tests: tests, testables: {}, context: :test, options: [], lock: Mutex.new )
|
|
70
|
+
setup.stage_prepare_build_paths( state )
|
|
71
|
+
return [state, file_path_utils]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def finder(configurator, file_path_utils)
|
|
75
|
+
loginator = double( 'loginator', log: nil )
|
|
76
|
+
return FileFinder.new(
|
|
77
|
+
configurator: configurator, file_finder_helper: FileFinderHelper.new( loginator: loginator ), file_path_utils: file_path_utils,
|
|
78
|
+
file_wrapper: FileWrapper.new( loginator: loginator, verbosinator: double( 'verbosinator', should_output?: false ) ), yaml_wrapper: nil
|
|
79
|
+
)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Each test's own object resolves to that test, by name and from its object path alone
|
|
83
|
+
def expect_own_objects_resolve(configurator, state, file_path_utils)
|
|
84
|
+
finder = finder( configurator, file_path_utils )
|
|
85
|
+
state.testables.each_value do |testable|
|
|
86
|
+
object = File.join( testable.paths[:build], File.basename( testable.filepath ).ext( '.o' ) )
|
|
87
|
+
expect(finder.find_build_input_file( filepath: object, context: :test, test: testable.name )).to eq( testable.filepath )
|
|
88
|
+
expect(finder.find_build_input_file( filepath: object, context: :test )).to eq( testable.filepath )
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
TEST_NAMING_LAYOUTS.each do |layout, (tests, test_paths, test_files)|
|
|
93
|
+
context "with #{layout}" do
|
|
94
|
+
it 'names each test by its path, inside the build directory, with results where summaries look' do
|
|
95
|
+
in_temp_project( project_files( tests ) ) do
|
|
96
|
+
configurator = configure( project_yaml( test_paths, test_files ) )[:configurator]
|
|
97
|
+
expect(configurator.collection_all_tests).to match_array( tests )
|
|
98
|
+
|
|
99
|
+
state, file_path_utils = prepare( configurator, configurator.collection_all_tests )
|
|
100
|
+
|
|
101
|
+
expect(state.testables.keys.map( &:to_s )).to match_array( tests.map { |test| test.ext( '' ) } )
|
|
102
|
+
|
|
103
|
+
build = File.expand_path( 'build' ) + '/'
|
|
104
|
+
state.testables.each_value do |testable|
|
|
105
|
+
testable.paths.each_value { |path| expect(File.expand_path( path )).to start_with( build ) }
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
expected = state.testables.values.map { |testable| file_path_utils.form_pass_results_filepath( testable.paths[:results], testable.filepath ) }
|
|
109
|
+
expect(file_path_utils.form_pass_results_filelist( configurator.project_test_results_path, tests )).to match_array( expected )
|
|
110
|
+
expect(expected.uniq.size).to eq( tests.size )
|
|
111
|
+
|
|
112
|
+
expect_own_objects_resolve( configurator, state, file_path_utils )
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# One test's name continues another's, so its directories nest inside the other's
|
|
119
|
+
context 'with a test directory named like a test beside it' do
|
|
120
|
+
it "keeps each test's mocks its own" do
|
|
121
|
+
tests = %w[test/test_foo.c test/test_foo/test_bar.c]
|
|
122
|
+
in_temp_project( project_files( tests ) ) do
|
|
123
|
+
configurator = configure( project_yaml( %w[test/**], [] ) )[:configurator]
|
|
124
|
+
state, file_path_utils = prepare( configurator, configurator.collection_all_tests )
|
|
125
|
+
expect_own_objects_resolve( configurator, state, file_path_utils )
|
|
126
|
+
|
|
127
|
+
mock = "#{configurator.cmock_mock_prefix}widget"
|
|
128
|
+
state.testables.each_value do |testable|
|
|
129
|
+
FileUtils.mkdir_p( testable.paths[:mocks] )
|
|
130
|
+
File.write( File.join( testable.paths[:mocks], "#{mock}.c" ), "\n" )
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
finder = finder( configurator, file_path_utils )
|
|
134
|
+
state.testables.each_value do |testable|
|
|
135
|
+
object = File.join( testable.paths[:build], "#{mock}.o" )
|
|
136
|
+
expect(finder.find_build_input_file( filepath: object, context: :test, test: testable.name )).to eq( File.join( testable.paths[:mocks], "#{mock}.c" ) )
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
context 'with tests outside the project' do
|
|
143
|
+
def outside_files
|
|
144
|
+
return project_files( [] ).transform_keys { |path| File.join( 'app', path ) }.merge(
|
|
145
|
+
'shared/test/unit/test_s.c' => "void test_it(void) {}\n",
|
|
146
|
+
'other/test_o.c' => "void test_it(void) {}\n"
|
|
147
|
+
)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it 'keeps their names and directories inside the build directory' do
|
|
151
|
+
in_temp_project( outside_files ) do
|
|
152
|
+
Dir.chdir( 'app' ) do
|
|
153
|
+
configurator = configure( project_yaml( %w[../shared/test/**], %w[../other/test_o.c] ) )[:configurator]
|
|
154
|
+
|
|
155
|
+
state, file_path_utils = prepare( configurator, configurator.collection_all_tests )
|
|
156
|
+
|
|
157
|
+
expect(state.testables.keys.map( &:to_s )).to match_array( %w[_up_/shared/test/unit/test_s _up_/other/test_o] )
|
|
158
|
+
expect_own_objects_resolve( configurator, state, file_path_utils )
|
|
159
|
+
build = File.expand_path( 'build' ) + '/'
|
|
160
|
+
state.testables.each_value do |testable|
|
|
161
|
+
testable.paths.each_value { |path| expect(File.expand_path( path )).to start_with( build ) }
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# A project directory named like the marker a test outside the project is named by keeps
|
|
168
|
+
# a name of its own
|
|
169
|
+
it 'names a test below a project directory called `_up_` apart from one above the project' do
|
|
170
|
+
files = outside_files.merge( 'app/_up_/other/test_o.c' => "void test_it(void) {}\n" )
|
|
171
|
+
|
|
172
|
+
in_temp_project( files ) do
|
|
173
|
+
Dir.chdir( 'app' ) do
|
|
174
|
+
configurator = configure( project_yaml( %w[../shared/test/** _up_/**], %w[../other/test_o.c] ) )[:configurator]
|
|
175
|
+
|
|
176
|
+
state, _file_path_utils = prepare( configurator, ['_up_/other/test_o.c', '../other/test_o.c'] )
|
|
177
|
+
|
|
178
|
+
expect(state.testables.keys.map( &:to_s )).to match_array( %w[__up_/other/test_o _up_/other/test_o] )
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
it 'stops a build that has two tests sharing one name, naming both' do
|
|
184
|
+
files = outside_files.merge( 'app/test/test_d.c' => "void test_it(void) {}\n", 'app/test/test_d.cpp' => "void test_it(void) {}\n" )
|
|
185
|
+
|
|
186
|
+
in_temp_project( files ) do
|
|
187
|
+
Dir.chdir( 'app' ) do
|
|
188
|
+
yaml = project_yaml( %w[test/**], [] ) + ":extension:\n :source: ['.c', '.cpp']\n"
|
|
189
|
+
configurator = configure( yaml )[:configurator]
|
|
190
|
+
|
|
191
|
+
expect { prepare( configurator, ['test/test_d.c'] ) }.to raise_error( CeedlingException ) { |error|
|
|
192
|
+
expect(error.message).to include( 'test/test_d.c', 'test/test_d.cpp', '`test/test_d`' )
|
|
193
|
+
}
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end
|