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,166 @@
|
|
|
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
|
+
# Checking TEST_SOURCE_FILE() entries against a real project. Real test files are scanned by
|
|
9
|
+
# the real context extractor, and the real resolver looks each entry up through the real
|
|
10
|
+
# file finder in a temporary project configured by the real configuration pipeline.
|
|
11
|
+
#
|
|
12
|
+
# Each test's entries are checked once, under that test's own name, with test preprocessing
|
|
13
|
+
# on or off, so a misspelled entry stops the build naming the test that holds it (GH #1364).
|
|
14
|
+
|
|
15
|
+
require 'spec_helper'
|
|
16
|
+
require 'configurator_integration_helper'
|
|
17
|
+
require 'ceedling/parsing_parcels'
|
|
18
|
+
require 'ceedling/includes/include_factory'
|
|
19
|
+
require 'ceedling/filesystem/file_finder'
|
|
20
|
+
require 'ceedling/filesystem/file_finder_helper'
|
|
21
|
+
require 'ceedling/filesystem/file_path_utils'
|
|
22
|
+
require 'ceedling/test_context_extractor'
|
|
23
|
+
require 'ceedling/test_invoker/test_source_file_directive_resolver'
|
|
24
|
+
require 'ceedling/test_invoker/test_build_setup'
|
|
25
|
+
require 'ceedling/test_invoker/test_invoker_types'
|
|
26
|
+
|
|
27
|
+
describe 'TEST_SOURCE_FILE() checks (integration)' do
|
|
28
|
+
include ConfiguratorIntegrationHelpers
|
|
29
|
+
|
|
30
|
+
# Runs each test of a batch in turn, in place of the thread pool
|
|
31
|
+
class TestSourceFileChecksBatchinator
|
|
32
|
+
def exec(things:, **_options)
|
|
33
|
+
things.each { |key, value| yield key, value }
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def test_file(entries)
|
|
38
|
+
lines = entries.map { |entry| "TEST_SOURCE_FILE(\"#{entry}\")\n" }.join
|
|
39
|
+
return "#include \"unity.h\"\n#{lines}void test_it(void) {}\n"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def project_files
|
|
43
|
+
return {
|
|
44
|
+
'src/calc.c' => "int calc(void) { return 1; }\n",
|
|
45
|
+
'src/calc.h' => "int calc(void);\n",
|
|
46
|
+
'src/a/dup.c' => "int dup(void) { return 1; }\n",
|
|
47
|
+
'lib/a/dup.c' => "int dup(void) { return 2; }\n",
|
|
48
|
+
'lib/extra.c' => "int extra(void) { return 7; }\n",
|
|
49
|
+
'test/test_m1.c' => test_file( ['calc.c'] ),
|
|
50
|
+
'test/test_m2.c' => test_file( ['calc.c'] ),
|
|
51
|
+
'test/unit/test_m3.c' => test_file( ['../../lib/extra.c'] )
|
|
52
|
+
}
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def project_yaml(preprocessor: :none)
|
|
56
|
+
return <<~YAML
|
|
57
|
+
:project:
|
|
58
|
+
:build_root: build
|
|
59
|
+
:use_test_preprocessor: :#{preprocessor}
|
|
60
|
+
:paths:
|
|
61
|
+
:test: [test/**]
|
|
62
|
+
:source: [src/**, lib/**]
|
|
63
|
+
:include: [src/**]
|
|
64
|
+
YAML
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def objects
|
|
68
|
+
graph = configure( project_yaml )
|
|
69
|
+
configurator = graph[:configurator]
|
|
70
|
+
loginator = graph[:loginator]
|
|
71
|
+
file_wrapper = graph[:file_wrapper]
|
|
72
|
+
|
|
73
|
+
file_path_utils = FilePathUtils.new( configurator: configurator, file_wrapper: file_wrapper )
|
|
74
|
+
file_finder = FileFinder.new(
|
|
75
|
+
configurator: configurator, file_finder_helper: FileFinderHelper.new( loginator: loginator ),
|
|
76
|
+
file_path_utils: file_path_utils, file_wrapper: file_wrapper, yaml_wrapper: graph[:yaml_wrapper]
|
|
77
|
+
)
|
|
78
|
+
extractor = TestContextExtractor.new(
|
|
79
|
+
configurator: configurator, parsing_parcels: ParsingParcels.new, include_factory: IncludeFactory.new( configurator: configurator ),
|
|
80
|
+
partializer_config: double( 'partializer_config' ).as_null_object, file_path_utils: file_path_utils, file_wrapper: file_wrapper,
|
|
81
|
+
yaml_wrapper: graph[:yaml_wrapper], loginator: loginator
|
|
82
|
+
)
|
|
83
|
+
resolver = TestSourceFileDirectiveResolver.new(
|
|
84
|
+
test_context_extractor: extractor, file_finder: file_finder, configurator: configurator, loginator: loginator
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
return { configurator: configurator, file_path_utils: file_path_utils, file_finder: file_finder, extractor: extractor, resolver: resolver }
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def scan(extractor, tests)
|
|
91
|
+
tests.each { |test| extractor.collect_simple_context_from_file( test, nil, TestContextExtractor::Context::BUILD_DIRECTIVE_SOURCE_FILES ) }
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it "passes a test's real entries, including one reached through .." do
|
|
95
|
+
in_temp_project( project_files ) do
|
|
96
|
+
o = objects
|
|
97
|
+
tests = %w[test/test_m1.c test/test_m2.c test/unit/test_m3.c]
|
|
98
|
+
scan( o[:extractor], tests )
|
|
99
|
+
|
|
100
|
+
tests.each do |test|
|
|
101
|
+
expect { o[:resolver].validate!( test: test.ext( '' ), test_filepath: test, context: :test ) }.to_not raise_error
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it 'names the test that holds a missing entry' do
|
|
107
|
+
in_temp_project( project_files.merge( 'test/test_m2.c' => test_file( ['calc_typo.c'] ) ) ) do
|
|
108
|
+
o = objects
|
|
109
|
+
scan( o[:extractor], %w[test/test_m1.c test/test_m2.c] )
|
|
110
|
+
|
|
111
|
+
expect { o[:resolver].validate!( test: 'test/test_m1', test_filepath: 'test/test_m1.c', context: :test ) }.to_not raise_error
|
|
112
|
+
expect { o[:resolver].validate!( test: 'test/test_m2', test_filepath: 'test/test_m2.c', context: :test ) }.to raise_error(
|
|
113
|
+
CeedlingException, %r{'calc_typo\.c' specified with TEST_SOURCE_FILE\(\) in test/test_m2 cannot be found}
|
|
114
|
+
)
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it 'stops for a misspelled removal entry, which otherwise leaves its file in the build' do
|
|
119
|
+
in_temp_project( project_files.merge( 'test/test_m1.c' => test_file( ['-:clac.c'] ) ) ) do
|
|
120
|
+
o = objects
|
|
121
|
+
scan( o[:extractor], %w[test/test_m1.c] )
|
|
122
|
+
|
|
123
|
+
expect { o[:resolver].validate!( test: 'test/test_m1', test_filepath: 'test/test_m1.c', context: :test ) }.to raise_error(
|
|
124
|
+
CeedlingException, /'clac\.c'.*cannot be found/
|
|
125
|
+
)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it 'notes an entry matching several files once, however many tests name it' do
|
|
130
|
+
files = project_files.merge( %w[test/test_m1.c test/test_m2.c test/unit/test_m3.c].to_h { |test| [test, test_file( ['a/dup.c'] )] } )
|
|
131
|
+
|
|
132
|
+
in_temp_project( files ) do
|
|
133
|
+
o = objects
|
|
134
|
+
tests = %w[test/test_m1.c test/test_m2.c test/unit/test_m3.c]
|
|
135
|
+
scan( o[:extractor], tests )
|
|
136
|
+
|
|
137
|
+
tests.each do |test|
|
|
138
|
+
o[:resolver].validate!( test: test.ext( '' ), test_filepath: test, context: :test )
|
|
139
|
+
o[:resolver].resolve( test, :test )
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
expect( logged.grep( /Multiple files matched 'a\/dup\.c'/ ).size ).to eq( 1 )
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Without test preprocessing, stage 2 scans the entries and checks them
|
|
147
|
+
it 'checks each test under its own name in stage 2 without test preprocessing' do
|
|
148
|
+
in_temp_project( project_files.merge( 'test/unit/test_m3.c' => test_file( ['nowhere.c'] ) ) ) do
|
|
149
|
+
o = objects
|
|
150
|
+
setup = TestBuildSetup.new( TestBuildSetup.constructor_keys.to_h { |key| [key, double( key.to_s ).as_null_object] }.merge(
|
|
151
|
+
configurator: o[:configurator], batchinator: TestSourceFileChecksBatchinator.new, test_context_extractor: o[:extractor],
|
|
152
|
+
file_path_utils: o[:file_path_utils], file_finder: o[:file_finder], test_source_file_directive_resolver: o[:resolver],
|
|
153
|
+
file_wrapper: FileWrapper.new( loginator: double( 'loginator', log: nil ), verbosinator: double( 'verbosinator', should_output?: false ) ),
|
|
154
|
+
dependinator: double( 'dependinator', register: nil, stale?: true, mark_fresh: nil ),
|
|
155
|
+
reportinator: double( 'reportinator', generate_progress: '', generate_skip_summary: nil )
|
|
156
|
+
) )
|
|
157
|
+
tests = %w[test/test_m1.c test/test_m2.c test/unit/test_m3.c]
|
|
158
|
+
state = TestInvokerTypes::PipelineState.new( tests: tests, testables: {}, context: :test, options: [], lock: Mutex.new )
|
|
159
|
+
setup.stage_prepare_build_paths( state )
|
|
160
|
+
|
|
161
|
+
expect { setup.stage_collect_test_context( state ) }.to raise_error(
|
|
162
|
+
CeedlingException, %r{'nowhere\.c' specified with TEST_SOURCE_FILE\(\) in test/unit/test_m3 cannot be found}
|
|
163
|
+
)
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
@@ -17,7 +17,7 @@ require 'spec_helper'
|
|
|
17
17
|
require 'spec_integration_helper'
|
|
18
18
|
require 'fileutils'
|
|
19
19
|
require 'ceedling/tool_validator'
|
|
20
|
-
require 'ceedling/file_wrapper'
|
|
20
|
+
require 'ceedling/filesystem/file_wrapper'
|
|
21
21
|
require 'ceedling/system_wrapper'
|
|
22
22
|
require 'ceedling/ruby_expandinator'
|
|
23
23
|
require 'ceedling/filename_extension'
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# =========================================================================
|
|
2
|
+
# Ceedling - Test-Centered Build System for C
|
|
3
|
+
# ThrowTheSwitch.org
|
|
4
|
+
# Copyright (c) 2010-26 Mike Karlesky, Mark VanderVoord, & Greg Williams
|
|
5
|
+
# SPDX-License-Identifier: MIT
|
|
6
|
+
# =========================================================================
|
|
7
|
+
|
|
8
|
+
# GH #1371: `upgrade` never refreshed documentation that `new --docs` exported, because it
|
|
9
|
+
# looked for a file exports stopped writing in 1.1.0. For a 1.0.x export, which it did
|
|
10
|
+
# find, it removed all of docs/, the project's own files included.
|
|
11
|
+
#
|
|
12
|
+
# These run the real launcher against real projects. Nothing compiles, so no toolchain is
|
|
13
|
+
# needed.
|
|
14
|
+
|
|
15
|
+
require 'spec_helper'
|
|
16
|
+
require 'tmpdir'
|
|
17
|
+
require 'fileutils'
|
|
18
|
+
require 'open3'
|
|
19
|
+
require 'rbconfig'
|
|
20
|
+
|
|
21
|
+
describe '`upgrade` and exported documentation' do
|
|
22
|
+
REPO = File.expand_path( '../..', __dir__ )
|
|
23
|
+
UNITY_PAGE = File.join( 'unity', 'UnityGettingStartedGuide.md' )
|
|
24
|
+
|
|
25
|
+
def ceedling(*args)
|
|
26
|
+
stdout, stderr, status = Open3.capture3(
|
|
27
|
+
{'CEEDLING_DECORATORS' => 'false'}, RbConfig.ruby, File.join( REPO, 'bin', 'ceedling' ), *args, chdir: @tmp
|
|
28
|
+
)
|
|
29
|
+
raise "`ceedling #{args.join( ' ' )}` failed:\n#{stdout}#{stderr}" unless status.success?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def docs(*entry)
|
|
33
|
+
return File.join( @tmp, 'proj', 'docs', *entry )
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def write(entry, text='')
|
|
37
|
+
FileUtils.mkdir_p( File.dirname( docs( entry ) ) )
|
|
38
|
+
File.write( docs( entry ), text )
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
around(:each) do |example|
|
|
42
|
+
Dir.mktmpdir( 'upgrade_docs' ) { |dir| @tmp = dir; example.run }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'refreshes an export of 1.1.0 or later and keeps the project\'s own files' do
|
|
46
|
+
ceedling( 'new', '--local', '--docs', 'proj' )
|
|
47
|
+
write( 'notes.md', 'mine' )
|
|
48
|
+
write( File.join( 'unity', 'stale.md' ) )
|
|
49
|
+
write( UNITY_PAGE, 'edited' )
|
|
50
|
+
|
|
51
|
+
ceedling( 'upgrade', 'proj' )
|
|
52
|
+
|
|
53
|
+
expect(File.exist?( docs( 'unity', 'stale.md' ) )).to be( false )
|
|
54
|
+
expect(File.read( docs( UNITY_PAGE ) )).to eq( File.read( File.join( REPO, 'vendor', 'unity', 'docs', 'UnityGettingStartedGuide.md' ) ) )
|
|
55
|
+
expect(File.read( docs( 'notes.md' ) )).to eq( 'mine' )
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'replaces a 1.0.x export with the current layout and keeps the project\'s own files' do
|
|
59
|
+
ceedling( 'new', '--local', 'proj' )
|
|
60
|
+
write( 'CeedlingPacket.md' )
|
|
61
|
+
write( 'Changelog.md' )
|
|
62
|
+
write( File.join( 'plugins', 'gcov.md' ) )
|
|
63
|
+
write( File.join( 'unity', 'stale.md' ) )
|
|
64
|
+
write( 'license.txt' )
|
|
65
|
+
write( 'notes.md', 'mine' )
|
|
66
|
+
|
|
67
|
+
ceedling( 'upgrade', 'proj' )
|
|
68
|
+
|
|
69
|
+
['CeedlingPacket.md', 'Changelog.md', 'plugins', File.join( 'unity', 'stale.md' )].each do |entry|
|
|
70
|
+
expect(File.exist?( docs( entry ) )).to be( false ), entry
|
|
71
|
+
end
|
|
72
|
+
expect(File.exist?( docs( UNITY_PAGE ) )).to be( true )
|
|
73
|
+
expect(File.read( docs( 'notes.md' ) )).to eq( 'mine' )
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it 'leaves a docs/ holding only the project\'s own files alone' do
|
|
77
|
+
ceedling( 'new', '--local', 'proj' )
|
|
78
|
+
write( 'notes.md', 'mine' )
|
|
79
|
+
|
|
80
|
+
ceedling( 'upgrade', 'proj' )
|
|
81
|
+
|
|
82
|
+
expect(Dir.children( docs )).to eq( ['notes.md'] )
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -5,126 +5,243 @@
|
|
|
5
5
|
# SPDX-License-Identifier: MIT
|
|
6
6
|
# =========================================================================
|
|
7
7
|
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
8
|
+
# ConfiguratorSetup#vendor_frameworks_and_support_files with a real FileWrapper on a real
|
|
9
|
+
# filesystem. A build brings build/vendor up to date with the gem's frameworks. It writes only
|
|
10
|
+
# a file that differs from its source, and replaces it whole by renaming a temporary copy over
|
|
11
|
+
# it, so a concurrent build never reads a half-written header (GH #1361). An entry of the
|
|
12
|
+
# wrong type, such as a directory where a file belongs, is replaced (GH #1292, #1376). A
|
|
13
|
+
# transient copy fault, such as a scanner holding a file open, is retried, and one that never
|
|
14
|
+
# clears names the destination.
|
|
14
15
|
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
# (matched by destination path) so the fault is deterministic. Faulting at #cp_r rather
|
|
18
|
-
# than #cp_r_with_retry itself matters here -- cp_r_with_retry's own retry loop (already
|
|
19
|
-
# proven exhaustively in file_wrapper_spec.rb) is exactly the mechanism this spec needs
|
|
20
|
-
# to actually run.
|
|
16
|
+
# Faults are injected at FileWrapper#replace_file, the one write of each file, so the retry
|
|
17
|
+
# loop in FileTree is what runs.
|
|
21
18
|
|
|
22
19
|
require 'spec_helper'
|
|
23
20
|
require 'spec_integration_helper'
|
|
21
|
+
require 'file_tree_helper'
|
|
24
22
|
require 'ceedling/config/configurator_setup'
|
|
25
23
|
require 'ceedling/constants'
|
|
26
24
|
|
|
27
|
-
describe 'Vendor
|
|
25
|
+
describe 'Vendor copy into build/vendor (integration)' do
|
|
28
26
|
include IntegrationSpecHelpers
|
|
27
|
+
include FileTreeHelper
|
|
29
28
|
|
|
30
|
-
# A real FileWrapper whose #
|
|
31
|
-
# times
|
|
32
|
-
#
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
# classes would otherwise let the second file's definition silently clobber the first's.
|
|
36
|
-
class CpRFaultingFileWrapper < FileWrapper
|
|
37
|
-
def initialize(fault_dest:, raises_left: 1, error: Errno::EISDIR, **kwargs)
|
|
29
|
+
# A real FileWrapper whose #replace_file raises for files beneath `fault_dir` the first
|
|
30
|
+
# `raises_left` times. Named apart from other specs' faulting wrappers, since top-level
|
|
31
|
+
# classes share one RSpec process.
|
|
32
|
+
class ReplaceFaultingFileWrapper < FileWrapper
|
|
33
|
+
def initialize(fault_dir:, raises_left: 1, error: Errno::EACCES, **kwargs)
|
|
38
34
|
super(**kwargs)
|
|
39
|
-
@
|
|
35
|
+
@fault_dir = fault_dir
|
|
40
36
|
@raises_left = raises_left
|
|
41
37
|
@error = error
|
|
42
38
|
end
|
|
43
39
|
|
|
44
|
-
def
|
|
45
|
-
if destination
|
|
40
|
+
def replace_file(source, destination)
|
|
41
|
+
if destination.start_with?( @fault_dir ) && @raises_left > 0
|
|
46
42
|
@raises_left -= 1
|
|
47
|
-
raise @error, "simulated
|
|
43
|
+
raise @error, "simulated fault on #{destination}"
|
|
48
44
|
end
|
|
49
45
|
super
|
|
50
46
|
end
|
|
51
47
|
end
|
|
52
48
|
|
|
53
|
-
|
|
54
|
-
|
|
49
|
+
def file_wrapper(**fault)
|
|
50
|
+
options = { loginator: IntegrationSpecHelpers::NULL, verbosinator: IntegrationSpecHelpers::NULL }
|
|
51
|
+
return fault.empty? ? FileWrapper.new( options ) : ReplaceFaultingFileWrapper.new( **fault, **options )
|
|
52
|
+
end
|
|
53
|
+
|
|
55
54
|
def build_configurator_setup(file_wrapper)
|
|
56
55
|
ConfiguratorSetup.new(
|
|
57
56
|
configurator_builder: IntegrationSpecHelpers::NULL,
|
|
58
57
|
configurator_validator: IntegrationSpecHelpers::NULL,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
58
|
+
configurator_paths_validator: IntegrationSpecHelpers::NULL,
|
|
59
|
+
loginator: IntegrationSpecHelpers::NULL,
|
|
60
|
+
reportinator: IntegrationSpecHelpers::NULL,
|
|
61
|
+
file_wrapper: file_wrapper,
|
|
62
|
+
system_wrapper: IntegrationSpecHelpers::NULL,
|
|
63
|
+
tool_executor: IntegrationSpecHelpers::NULL
|
|
64
64
|
)
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
-
# A
|
|
68
|
-
# real file, so a real FileUtils.cp_r has real directory-tree content to walk.
|
|
67
|
+
# A stand-in for the gem's vendor/unity/src, with a nested file to show subdirectories copy
|
|
69
68
|
def flattened_config(dir)
|
|
70
|
-
unity_src = File.join(dir, 'gem_vendor', 'unity', 'src')
|
|
71
|
-
FileUtils.mkdir_p(unity_src)
|
|
72
|
-
File.write(File.join(unity_src, 'unity.c'), "// stand-in for
|
|
69
|
+
unity_src = File.join( dir, 'gem_vendor', 'unity', 'src' )
|
|
70
|
+
FileUtils.mkdir_p( File.join( unity_src, 'internal' ) )
|
|
71
|
+
File.write( File.join( unity_src, 'unity.c' ), "// stand-in for unity.c\n" )
|
|
72
|
+
File.write( File.join( unity_src, 'unity.h' ), "// stand-in for unity.h\n" )
|
|
73
|
+
File.write( File.join( unity_src, 'internal', 'unity_internals.h' ), "// stand-in\n" )
|
|
73
74
|
|
|
74
75
|
{
|
|
75
|
-
# UNITY_LIB_PATH ('unity/src')
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
project_use_partials: false,
|
|
76
|
+
# UNITY_LIB_PATH ('unity/src') joins this vendor root
|
|
77
|
+
unity_vendor_path: File.join( dir, 'gem_vendor' ),
|
|
78
|
+
project_build_vendor_unity_path: File.join( dir, 'build', 'vendor', 'unity', 'src' ),
|
|
79
|
+
project_use_mocks: false,
|
|
80
|
+
project_use_exceptions: false,
|
|
81
|
+
project_use_backtrace: :none,
|
|
82
|
+
project_use_partials: false,
|
|
83
83
|
}
|
|
84
84
|
end
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
def vendor(file_wrapper, dir, config)
|
|
87
|
+
build_configurator_setup( file_wrapper ).vendor_frameworks_and_support_files( dir, config, test_build: true, release_build: false )
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def snapshot(dest)
|
|
91
|
+
return Dir.glob( File.join( dest, '**', '*' ) ).select { |path| File.file?( path ) }.to_h do |path|
|
|
92
|
+
stat = File.stat( path )
|
|
93
|
+
[path, [stat.ino, stat.mtime]]
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def leftovers(dest)
|
|
98
|
+
return Dir.glob( File.join( dest, '**', '*' ), File::FNM_DOTMATCH ).select { |path| File.basename( path ).include?( '.tmp' ) }
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it "copies every file, including those in subdirectories, into a fresh destination" do
|
|
87
102
|
with_source_tree({}) do |dir|
|
|
88
|
-
config = flattened_config(dir)
|
|
103
|
+
config = flattened_config( dir )
|
|
89
104
|
dest = config[:project_build_vendor_unity_path]
|
|
90
|
-
# Real usage always runs build_directory_structure (which mkdir_p's every
|
|
91
|
-
# vendor destination) before this copy -- match that precondition here so the
|
|
92
|
-
# only fault in play is the one this spec injects, not a missing parent dir.
|
|
93
|
-
FileUtils.mkdir_p(dest)
|
|
94
|
-
|
|
95
|
-
# Exactly one raise, well within cp_r_with_retry's own retry budget -- the
|
|
96
|
-
# source is otherwise 100% fine, the real copy proceeds either way.
|
|
97
|
-
faulting_fw = CpRFaultingFileWrapper.new(
|
|
98
|
-
fault_dest: dest, raises_left: 1,
|
|
99
|
-
loginator: IntegrationSpecHelpers::NULL, verbosinator: IntegrationSpecHelpers::NULL
|
|
100
|
-
)
|
|
101
|
-
setup = build_configurator_setup(faulting_fw)
|
|
102
105
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
+
vendor( file_wrapper, dir, config )
|
|
107
|
+
|
|
108
|
+
expect( File.read( File.join( dest, 'unity.h' ) ) ).to eq( "// stand-in for unity.h\n" )
|
|
109
|
+
expect( File.exist?( File.join( dest, 'internal', 'unity_internals.h' ) ) ).to be(true)
|
|
110
|
+
expect( leftovers( dest ) ).to be_empty
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "rewrites nothing when the destination already matches" do
|
|
115
|
+
with_source_tree({}) do |dir|
|
|
116
|
+
config = flattened_config( dir )
|
|
117
|
+
dest = config[:project_build_vendor_unity_path]
|
|
118
|
+
vendor( file_wrapper, dir, config )
|
|
119
|
+
before = snapshot( dest )
|
|
120
|
+
sleep( 1.1 ) # Past the coarsest file modification time resolution
|
|
106
121
|
|
|
107
|
-
|
|
122
|
+
vendor( file_wrapper, dir, config )
|
|
123
|
+
|
|
124
|
+
expect( snapshot( dest ) ).to eq( before )
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it "restores an edited file by replacing it whole, and leaves matching files alone" do
|
|
129
|
+
with_source_tree({}) do |dir|
|
|
130
|
+
config = flattened_config( dir )
|
|
131
|
+
dest = config[:project_build_vendor_unity_path]
|
|
132
|
+
vendor( file_wrapper, dir, config )
|
|
133
|
+
edited = File.join( dest, 'unity.h' )
|
|
134
|
+
File.write( edited, "// an errant edit\n" )
|
|
135
|
+
before = snapshot( dest )
|
|
136
|
+
|
|
137
|
+
vendor( file_wrapper, dir, config )
|
|
138
|
+
|
|
139
|
+
expect( File.read( edited ) ).to eq( "// stand-in for unity.h\n" )
|
|
140
|
+
expect( File.stat( edited ).ino ).not_to eq( before[edited].first ) unless SystemWrapper.windows?
|
|
141
|
+
untouched = File.join( dest, 'unity.c' )
|
|
142
|
+
expect( snapshot( dest )[untouched] ).to eq( before[untouched] )
|
|
143
|
+
expect( leftovers( dest ) ).to be_empty
|
|
108
144
|
end
|
|
109
145
|
end
|
|
110
146
|
|
|
111
|
-
it "
|
|
147
|
+
it "restores a missing file" do
|
|
112
148
|
with_source_tree({}) do |dir|
|
|
113
|
-
config = flattened_config(dir)
|
|
149
|
+
config = flattened_config( dir )
|
|
114
150
|
dest = config[:project_build_vendor_unity_path]
|
|
115
|
-
|
|
151
|
+
vendor( file_wrapper, dir, config )
|
|
152
|
+
FileUtils.rm( File.join( dest, 'internal', 'unity_internals.h' ) )
|
|
153
|
+
|
|
154
|
+
vendor( file_wrapper, dir, config )
|
|
155
|
+
|
|
156
|
+
expect( File.exist?( File.join( dest, 'internal', 'unity_internals.h' ) ) ).to be(true)
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
it "recovers from a transient copy failure instead of crashing the build" do
|
|
161
|
+
with_source_tree({}) do |dir|
|
|
162
|
+
config = flattened_config( dir )
|
|
163
|
+
dest = config[:project_build_vendor_unity_path]
|
|
164
|
+
|
|
165
|
+
expect { vendor( file_wrapper( fault_dir: dest, raises_left: 1 ), dir, config ) }.not_to raise_error
|
|
116
166
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
167
|
+
expect( File.exist?( File.join( dest, 'unity.c' ) ) ).to be(true)
|
|
168
|
+
expect( leftovers( dest ) ).to be_empty
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
it "raises a clear, path-naming CeedlingException when the fault never clears" do
|
|
173
|
+
with_source_tree({}) do |dir|
|
|
174
|
+
config = flattened_config( dir )
|
|
175
|
+
dest = config[:project_build_vendor_unity_path]
|
|
124
176
|
|
|
125
177
|
expect {
|
|
126
|
-
|
|
127
|
-
}.to raise_error(CeedlingException, /#{Regexp.escape(dest)}/)
|
|
178
|
+
vendor( file_wrapper( fault_dir: dest, raises_left: 999 ), dir, config )
|
|
179
|
+
}.to raise_error( CeedlingException, /#{Regexp.escape( dest )}/ )
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
# GH #1376: a deduplicated file the reporter's lstat called a directory left one where any
|
|
183
|
+
# vendored file belongs, not only the framework's own .c file
|
|
184
|
+
it "replaces a directory where any vendored file belongs" do
|
|
185
|
+
with_source_tree({}) do |dir|
|
|
186
|
+
config = flattened_config( dir )
|
|
187
|
+
dest = config[:project_build_vendor_unity_path]
|
|
188
|
+
FileUtils.mkdir_p( File.join( dest, 'unity.h' ) )
|
|
189
|
+
write( File.join( dest, 'internal', 'unity_internals.h', 'junk' ) )
|
|
190
|
+
|
|
191
|
+
vendor( file_wrapper, dir, config )
|
|
192
|
+
|
|
193
|
+
expect( File.read( File.join( dest, 'unity.h' ) ) ).to eq( "// stand-in for unity.h\n" )
|
|
194
|
+
expect( File.file?( File.join( dest, 'internal', 'unity_internals.h' ) ) ).to be(true)
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
it "vendors every file as a file when lstat reports files as directories" do
|
|
199
|
+
with_source_tree({}) do |dir|
|
|
200
|
+
config = flattened_config( dir )
|
|
201
|
+
dest = config[:project_build_vendor_unity_path]
|
|
202
|
+
lie_about_lstat( %r{gem_vendor/} )
|
|
203
|
+
|
|
204
|
+
begin
|
|
205
|
+
vendor( file_wrapper, dir, config )
|
|
206
|
+
ensure
|
|
207
|
+
# The temporary directory is removed by an lstat-based remover
|
|
208
|
+
allow(File).to receive(:lstat).and_call_original
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
expect( File.file?( File.join( dest, 'unity.c' ) ) ).to be(true)
|
|
212
|
+
expect( File.file?( File.join( dest, 'internal', 'unity_internals.h' ) ) ).to be(true)
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# A read-only gem install would otherwise vendor read-only files, which Windows will not
|
|
217
|
+
# let a later rename replace
|
|
218
|
+
it "vendors owner-writable files from a read-only source, and replaces a read-only destination" do
|
|
219
|
+
with_source_tree({}) do |dir|
|
|
220
|
+
config = flattened_config( dir )
|
|
221
|
+
dest = config[:project_build_vendor_unity_path]
|
|
222
|
+
source = File.join( config[:unity_vendor_path], 'unity', 'src', 'unity.h' )
|
|
223
|
+
File.chmod( 0o444, source )
|
|
224
|
+
vendor( file_wrapper, dir, config )
|
|
225
|
+
expect( File.stat( File.join( dest, 'unity.h' ) ).mode & 0o200 ).to eq( 0o200 )
|
|
226
|
+
|
|
227
|
+
File.chmod( 0o644, source )
|
|
228
|
+
File.write( source, "// a newer unity.h\n" )
|
|
229
|
+
File.chmod( 0o444, File.join( dest, 'unity.h' ) )
|
|
230
|
+
vendor( file_wrapper, dir, config )
|
|
231
|
+
|
|
232
|
+
expect( File.read( File.join( dest, 'unity.h' ) ) ).to eq( "// a newer unity.h\n" )
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
it "fails at once on an error retrying cannot clear" do
|
|
237
|
+
with_source_tree({}) do |dir|
|
|
238
|
+
config = flattened_config( dir )
|
|
239
|
+
dest = config[:project_build_vendor_unity_path]
|
|
240
|
+
faulting = file_wrapper( fault_dir: dest, raises_left: 999, error: Errno::ENOSPC )
|
|
241
|
+
allow(faulting).to receive(:sleep)
|
|
242
|
+
|
|
243
|
+
expect { vendor( faulting, dir, config ) }.to raise_error( Errno::ENOSPC )
|
|
244
|
+
expect(faulting).not_to have_received(:sleep)
|
|
128
245
|
end
|
|
129
246
|
end
|
|
130
247
|
end
|
|
@@ -0,0 +1,88 @@
|
|
|
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 'delegate'
|
|
9
|
+
require 'fileutils'
|
|
10
|
+
require 'tmpdir'
|
|
11
|
+
|
|
12
|
+
# Support for specs that copy real file trees (`filesystem: true`).
|
|
13
|
+
#
|
|
14
|
+
# CEEDLING_TEST_FS_ROOT names a directory on another filesystem, such as a tmpfs, a vfat
|
|
15
|
+
# image, a UNC share, or a VHD volume. These specs then build their trees there instead of
|
|
16
|
+
# the system temp directory, so CI can run one suite on several filesystems.
|
|
17
|
+
module FileTreeHelper
|
|
18
|
+
ROOT_ENV = 'CEEDLING_TEST_FS_ROOT'
|
|
19
|
+
|
|
20
|
+
# A stat result that claims a directory. Reproduces a filesystem whose `lstat` reports a
|
|
21
|
+
# regular file as a directory.
|
|
22
|
+
class LyingStat < SimpleDelegator
|
|
23
|
+
def directory?
|
|
24
|
+
true
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def file?
|
|
28
|
+
false
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def symlink?
|
|
32
|
+
false
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def ftype
|
|
36
|
+
'directory'
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def mode
|
|
40
|
+
(__getobj__.mode & ~0o170000) | 0o040000
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# A temporary directory on the filesystem under test, removed afterwards
|
|
45
|
+
def with_tree_root
|
|
46
|
+
root = ENV[ROOT_ENV].to_s
|
|
47
|
+
dir = root.empty? ? Dir.mktmpdir( 'tree' ) : Dir.mktmpdir( 'tree', root )
|
|
48
|
+
yield File.realpath( dir )
|
|
49
|
+
ensure
|
|
50
|
+
FileUtils.rm_rf( dir ) if dir
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def write(path, content = File.basename( path ))
|
|
54
|
+
FileUtils.mkdir_p( File.dirname( path ) )
|
|
55
|
+
File.binwrite( path, content )
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def symlink_or_skip(target, link)
|
|
59
|
+
File.symlink( target, link )
|
|
60
|
+
rescue NotImplementedError, SystemCallError => e
|
|
61
|
+
skip "symlinks are unavailable here (#{e.class})"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Every entry below `dir`, dotfiles included, as sorted relative paths
|
|
65
|
+
def tree_of(dir)
|
|
66
|
+
Dir.glob( '**/*', File::FNM_DOTMATCH, base: dir ).reject { |path| path == '.' || path.end_with?( '/.' ) }.sort
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Makes `File.lstat` lie, claiming a directory, for each path matching `pattern`
|
|
70
|
+
def lie_about_lstat(pattern)
|
|
71
|
+
allow(File).to receive(:lstat).and_wrap_original do |original, path, *rest|
|
|
72
|
+
status = original.call( path, *rest )
|
|
73
|
+
path.to_s.match?( pattern ) ? LyingStat.new( status ) : status
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Fails any `File.lstat` call, proving code under test never classifies by it
|
|
78
|
+
def forbid_lstat
|
|
79
|
+
allow(File).to receive(:lstat).and_raise( RuntimeError, 'File.lstat must not be called' )
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# The publish step FileWrapper#replace_file performs: a whole copy renamed into place
|
|
83
|
+
PUBLISH = lambda do |source, destination|
|
|
84
|
+
temp = "#{destination}.publishing"
|
|
85
|
+
FileUtils.cp( source, temp )
|
|
86
|
+
File.rename( temp, destination )
|
|
87
|
+
end
|
|
88
|
+
end
|