ceedling 1.2.1 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/GIT_COMMIT_SHA +1 -1
- data/README.md +11 -9
- data/Rakefile +2 -1
- data/assets/features/ceedling +1 -1
- data/assets/fixtures/test_source_file_duplicate_basenames/test_calc_typo.c +14 -0
- data/assets/fixtures/tests_with_duplicate_test_names/test_foo.c +21 -0
- data/bin/actionator.rb +6 -12
- data/bin/app_cfg.rb +14 -1
- data/bin/ceedling +13 -3
- data/bin/cli.rb +25 -6
- data/bin/cli_handler.rb +113 -73
- data/bin/cli_helper.rb +51 -78
- data/bin/installation_selector.rb +81 -0
- data/bin/launchinator.rb +69 -0
- data/bin/mixin_resolvinator.rb +26 -36
- data/bin/objects.yml +13 -0
- data/bin/path_validator.rb +25 -29
- data/bin/versionator.rb +47 -48
- data/ceedling.gemspec +19 -15
- data/docs/BreakingChanges.md +70 -1
- data/docs/Changelog.md +74 -3
- data/docs/KnownIssues.md +90 -4
- data/docs/ReleaseNotes.md +13 -0
- data/lib/ceedling/build_log_writer.rb +33 -0
- data/lib/ceedling/config/build_root_policy.rb +70 -0
- data/lib/ceedling/config/configurator.rb +14 -16
- data/lib/ceedling/config/configurator_builder.rb +58 -28
- data/lib/ceedling/config/configurator_paths_validator.rb +179 -0
- data/lib/ceedling/config/configurator_plugins.rb +1 -1
- data/lib/ceedling/config/configurator_setup.rb +15 -28
- data/lib/ceedling/config/configurator_validator.rb +1 -110
- data/lib/ceedling/defaults.rb +4 -4
- data/lib/ceedling/dependencies/README.md +18 -16
- data/lib/ceedling/dependencies/dependency_cache_store.rb +20 -3
- data/lib/ceedling/dependencies/dependency_hasher.rb +35 -1
- data/lib/ceedling/filename_extension.rb +7 -1
- data/lib/ceedling/filesystem/FILE_TREE.md +253 -0
- data/lib/ceedling/filesystem/PATH_HANDLING.md +304 -0
- data/lib/ceedling/filesystem/README.md +41 -0
- data/lib/ceedling/filesystem/build_subpath.rb +102 -0
- data/lib/ceedling/filesystem/destination_collision.rb +25 -0
- data/lib/ceedling/{file_finder.rb → filesystem/file_finder.rb} +159 -104
- data/lib/ceedling/{file_finder_helper.rb → filesystem/file_finder_helper.rb} +36 -31
- data/lib/ceedling/filesystem/file_path_collection_utils.rb +183 -0
- data/lib/ceedling/{file_path_utils.rb → filesystem/file_path_utils.rb} +108 -97
- data/lib/ceedling/{file_system_wrapper.rb → filesystem/file_system_wrapper.rb} +6 -5
- data/lib/ceedling/filesystem/file_tree.rb +241 -0
- data/lib/ceedling/{file_wrapper.rb → filesystem/file_wrapper.rb} +45 -38
- data/lib/ceedling/filesystem/path_exclusions.rb +30 -0
- data/lib/ceedling/{path_matcher.rb → filesystem/path_matcher.rb} +27 -23
- data/lib/ceedling/{path_mirror.rb → filesystem/path_mirror.rb} +19 -18
- data/lib/ceedling/filesystem/path_spellings.rb +55 -0
- data/lib/ceedling/filesystem/project_paths.rb +184 -0
- data/lib/ceedling/filesystem/working_dir.rb +40 -0
- data/lib/ceedling/generators/generator.rb +5 -6
- data/lib/ceedling/generators/generator_partials.rb +1 -1
- data/lib/ceedling/generators/generator_test_results_backtrace.rb +7 -7
- data/lib/ceedling/handoff.rb +121 -0
- data/lib/ceedling/includes/include_factory.rb +3 -3
- data/lib/ceedling/includes/include_pathinator.rb +67 -10
- data/lib/ceedling/includes/includes.rb +1 -1
- data/lib/ceedling/installation.rb +92 -0
- data/lib/ceedling/library_resolver.rb +99 -0
- data/lib/ceedling/objects.yml +23 -2
- data/lib/ceedling/partials/partializer.rb +4 -4
- data/lib/ceedling/partials/partializer_config.rb +3 -1
- data/lib/ceedling/plugins/report_log_writer_plugin.rb +3 -5
- data/lib/ceedling/preprocess/preprocessinator_file_assembler.rb +1 -1
- data/lib/ceedling/preprocess/preprocessinator_includes_handler.rb +1 -1
- data/lib/ceedling/preprocess/preprocessinator_line_marker_includes_extractor.rb +1 -1
- data/lib/ceedling/rake_app/rakefile_component_resolver.rb +10 -17
- data/lib/ceedling/rakefile.rb +15 -1
- data/lib/ceedling/rakefiles/base/tasks_base.rake +1 -1
- data/lib/ceedling/rakefiles/release/rules_release.rake +4 -7
- data/lib/ceedling/release_invoker/release_build_executor.rb +33 -44
- data/lib/ceedling/release_invoker/release_build_planner.rb +14 -6
- data/lib/ceedling/reportinator.rb +3 -4
- data/lib/ceedling/setupinator.rb +94 -90
- data/lib/ceedling/test_context_extractor.rb +5 -1
- data/lib/ceedling/test_invoker/PIPELINE.md +9 -7
- data/lib/ceedling/test_invoker/mock_locator.rb +60 -2
- data/lib/ceedling/test_invoker/partials_manager.rb +12 -0
- data/lib/ceedling/test_invoker/standin_headerinator.rb +22 -13
- data/lib/ceedling/test_invoker/test_build_executor.rb +24 -40
- data/lib/ceedling/test_invoker/test_build_planner.rb +37 -18
- data/lib/ceedling/test_invoker/test_build_setup.rb +17 -12
- data/lib/ceedling/test_invoker/test_build_validations.rb +16 -31
- data/lib/ceedling/test_invoker/test_file_preprocessinator.rb +1 -1
- data/lib/ceedling/test_invoker/test_invoker.rb +6 -1
- data/lib/ceedling/test_invoker/test_pipeline_helpers.rb +1 -1
- data/lib/ceedling/test_invoker/test_source_file_directive_resolver.rb +40 -20
- data/lib/ceedling/tool_executor.rb +9 -3
- data/lib/ceedling/yaml_wrapper.rb +3 -2
- data/lib/version.rb +1 -1
- data/plugins/bullseye/config/defaults_bullseye.rb +1 -1
- data/plugins/bullseye/lib/bullseye.rb +9 -7
- data/plugins/cppcheck/config/defaults_cppcheck.rb +1 -1
- data/plugins/dependencies/config/defaults.yml +6 -6
- data/plugins/dependencies/dependencies.rake +4 -1
- data/plugins/dependencies/lib/dependencies.rb +18 -8
- data/plugins/dependencies/lib/dependency_spec.rb +17 -5
- data/plugins/fff/lib/fff.rb +45 -39
- data/plugins/fff/spec/fff_cmock_wrapper_spec.rb +128 -0
- data/plugins/gcov/config/defaults_gcov.rb +1 -1
- data/plugins/gcov/lib/console_reportinator.rb +4 -18
- data/plugins/gcov/lib/gcov.rb +9 -2
- data/plugins/gcov/lib/gcovr_reportinator.rb +8 -40
- data/plugins/gcov/lib/gcovr_thresholds.rb +74 -0
- data/plugins/gcov/lib/reportgenerator_reportinator.rb +1 -1
- data/plugins/module_generator/lib/module_generator.rb +3 -3
- data/plugins/report_tests_teamcity_stdout/lib/report_tests_teamcity_stdout.rb +53 -80
- data/plugins/sanitize/lib/sanitize_records.rb +3 -6
- data/plugins/valgrind/lib/valgrind.rb +14 -7
- data/site-local/configuration/reference/cmock.html +2 -1
- data/site-local/configuration/reference/files.html +9 -3
- data/site-local/configuration/reference/libraries.html +21 -3
- data/site-local/configuration/reference/paths.html +29 -6
- data/site-local/configuration/reference/project.html +17 -7
- data/site-local/configuration/reference/release-build.html +2 -0
- data/site-local/configuration/reference/tools.html +9 -0
- data/site-local/configuration/which-ceedling.html +377 -17
- data/site-local/development/releases.html +5 -1
- data/site-local/development/workflow.html +48 -43
- data/site-local/getting-started/builds.html +2 -0
- data/site-local/getting-started/command-line.html +56 -4
- data/site-local/plugins/dependencies.html +6 -3
- data/site-local/plugins/fff.html +42 -11
- data/site-local/plugins/gcov/gcovr.html +15 -12
- data/site-local/plugins/gcov/setup.html +2 -1
- data/site-local/plugins/report-tests-raw-output-log.html +3 -1
- data/site-local/plugins/report-tests-teamcity-stdout.html +6 -3
- data/site-local/plugins/sanitize.html +7 -6
- data/site-local/plugins/valgrind.html +8 -7
- data/site-local/project/upgrade.html +3 -0
- data/site-local/reference/command-line.html +9 -2
- data/site-local/sitemap.xml.gz +0 -0
- data/site-local/snapshot/plugins/bullseye/config/defaults_bullseye.rb +1 -1
- data/site-local/snapshot/plugins/gcov/config/defaults_gcov.rb +1 -1
- data/site-local/testing-guide/conventions.html +53 -0
- data/spec/integration/actionator_file_operations_spec.rb +91 -1
- data/spec/integration/compile_commands_json_db_spec.rb +1 -1
- data/spec/integration/configurator_validation_spec.rb +1 -1
- data/spec/integration/dependencies/dependency_tracker_cache_hardening_spec.rb +26 -0
- data/spec/integration/dependencies/dependency_tracker_core_spec.rb +22 -0
- data/spec/integration/launcher_handoff_spec.rb +297 -0
- data/spec/integration/mixin_loading_spec.rb +1 -1
- data/spec/integration/module_generator_spec.rb +3 -3
- data/spec/integration/nested_test_artifacts_spec.rb +99 -0
- data/spec/integration/partials_module_resolution_spec.rb +7 -4
- data/spec/integration/path_intake_scenarios_spec.rb +101 -0
- data/spec/integration/path_scenarios_spec.rb +322 -0
- data/spec/integration/quote_include_isolator_spec.rb +1 -1
- data/spec/integration/report_build_warnings_log_spec.rb +1 -1
- data/spec/integration/report_tests_log_factory_spec.rb +1 -1
- data/spec/integration/test_executable_manifest_spec.rb +1 -1
- data/spec/integration/test_includes_extractinator_spec.rb +2 -1
- data/spec/integration/test_naming_spec.rb +198 -0
- data/spec/integration/test_source_file_checks_spec.rb +166 -0
- data/spec/integration/tool_validator_spec.rb +1 -1
- data/spec/integration/upgrade_docs_spec.rb +84 -0
- data/spec/integration/vendor_copy_transient_io_retry_spec.rb +74 -5
- data/spec/support/file_tree_helper.rb +88 -0
- data/spec/support/integration/configurator_integration_helper.rb +6 -6
- data/spec/support/integration/dependency_tracker_integration_helper.rb +1 -1
- data/spec/support/integration/partials_generation_integration_helper.rb +2 -2
- data/spec/support/integration/path_scenario_harness.rb +173 -0
- data/spec/support/integration/spec_integration_helper.rb +1 -1
- data/spec/support/integration/test_includes_harness.rb +13 -2
- data/spec/support/spec_helper.rb +2 -0
- data/spec/support/system/spec_system_helper.rb +7 -6
- data/spec/support/system/system_context.rb +21 -3
- data/spec/support/working_dir_tracking.rb +49 -0
- data/spec/system/build_output_mirroring_spec.rb +2 -2
- data/spec/system/conditional_mock_includes_spec.rb +1 -1
- data/spec/system/delta_builds_spec.rb +137 -11
- data/spec/system/gcov_deployment_spec.rb +1 -0
- data/spec/system/header_include_path_validation_spec.rb +4 -4
- data/spec/system/launcher_handoff_spec.rb +82 -0
- data/spec/system/mock_include_folders_spec.rb +91 -0
- data/spec/system/parent_directory_reference_spec.rb +5 -3
- data/spec/system/path_handling_probes_spec.rb +192 -0
- data/spec/system/preprocessing_parameterized_tests_spec.rb +1 -1
- data/spec/system/rake_release_task_path_disambiguation_spec.rb +6 -6
- data/spec/system/rake_test_task_path_disambiguation_spec.rb +85 -0
- data/spec/system/special_path_characters_spec.rb +86 -0
- data/spec/system/support/common_test_cases.rb +23 -21
- data/spec/system/support/gcov_common_test_cases.rb +37 -9
- data/spec/system/support/sanitize_common_test_cases.rb +2 -2
- data/spec/system/support/valgrind_common_test_cases.rb +12 -12
- data/spec/system/test_pipeline_stop_points_spec.rb +4 -4
- data/spec/system/test_runner_system_include_spec.rb +1 -1
- data/spec/system/test_source_file_directive_spec.rb +34 -5
- data/spec/units/bin/actionator_spec.rb +14 -17
- data/spec/units/bin/app_cfg_spec.rb +37 -0
- data/spec/units/bin/cli_handler_spec.rb +282 -6
- data/spec/units/bin/cli_helper_spec.rb +116 -45
- data/spec/units/bin/installation_selector_spec.rb +114 -0
- data/spec/units/bin/launchinator_spec.rb +171 -0
- data/spec/units/bin/path_validator_spec.rb +10 -0
- data/spec/units/bin/versionator_spec.rb +38 -6
- data/spec/units/build_log_writer_spec.rb +57 -0
- data/spec/units/config/build_root_policy_spec.rb +61 -0
- data/spec/units/config/configurator_builder_spec.rb +37 -6
- data/spec/units/config/configurator_paths_validator_spec.rb +292 -0
- data/spec/units/config/configurator_setup_spec.rb +9 -65
- data/spec/units/config/configurator_spec.rb +27 -5
- data/spec/units/config/configurator_validator_spec.rb +1 -172
- data/spec/units/default_tools_quoting_spec.rb +83 -0
- data/spec/units/dependencies/dependency_cache_store_spec.rb +33 -2
- data/spec/units/dependencies/dependency_debug_tree_spec.rb +1 -1
- data/spec/units/dependencies/dependency_hasher_spec.rb +42 -1
- data/spec/units/dependencies/dependency_path_normalizer_spec.rb +1 -1
- data/spec/units/dependencies/dependency_tracker_spec.rb +3 -1
- data/spec/units/filename_extension_spec.rb +11 -0
- data/spec/units/filesystem/build_subpath_spec.rb +122 -0
- data/spec/units/filesystem/destination_collision_spec.rb +30 -0
- data/spec/units/{file_finder_helper_spec.rb → filesystem/file_finder_helper_spec.rb} +46 -1
- data/spec/units/{file_finder_spec.rb → filesystem/file_finder_spec.rb} +188 -22
- data/spec/units/{file_path_collection_utils_spec.rb → filesystem/file_path_collection_utils_spec.rb} +181 -1
- data/spec/units/{file_path_utils_spec.rb → filesystem/file_path_utils_spec.rb} +204 -87
- data/spec/units/filesystem/file_system_wrapper_spec.rb +33 -0
- data/spec/units/filesystem/file_tree_spec.rb +511 -0
- data/spec/units/filesystem/file_tree_windows_spec.rb +78 -0
- data/spec/units/{file_wrapper_spec.rb → filesystem/file_wrapper_spec.rb} +95 -12
- data/spec/units/{path_matcher_spec.rb → filesystem/path_matcher_spec.rb} +12 -1
- data/spec/units/{path_mirror_spec.rb → filesystem/path_mirror_spec.rb} +32 -4
- data/spec/units/filesystem/project_paths_spec.rb +147 -0
- data/spec/units/filesystem/working_dir_spec.rb +71 -0
- data/spec/units/generators/generator_spec.rb +12 -6
- data/spec/units/generators/generator_test_results_backtrace_spec.rb +50 -46
- data/spec/units/generators/generator_test_results_spec.rb +1 -1
- data/spec/units/handoff_spec.rb +205 -0
- data/spec/units/includes/include_factory_spec.rb +3 -3
- data/spec/units/includes/include_pathinator_spec.rb +46 -0
- data/spec/units/installation_spec.rb +228 -0
- data/spec/units/library_resolver_spec.rb +157 -0
- data/spec/units/mock_locator_spec.rb +76 -1
- data/spec/units/partials/partializer_config_spec.rb +7 -0
- data/spec/units/partials/partializer_spec.rb +1 -0
- data/spec/units/partials_manager_spec.rb +17 -0
- data/spec/units/plugins/bullseye_spec.rb +15 -2
- data/spec/units/plugins/console_reportinator_spec.rb +18 -20
- data/spec/units/plugins/dependencies_spec.rb +33 -7
- data/spec/units/plugins/dependency_spec_spec.rb +17 -0
- data/spec/units/plugins/gcov_spec.rb +28 -3
- data/spec/units/plugins/gcovr_reportinator_spec.rb +19 -47
- data/spec/units/plugins/gcovr_thresholds_spec.rb +95 -0
- data/spec/units/plugins/module_generator_spec.rb +5 -5
- data/spec/units/plugins/report_build_warnings_log_spec.rb +3 -3
- data/spec/units/plugins/report_log_writer_plugin_spec.rb +10 -1
- data/spec/units/plugins/report_tests_raw_output_log_spec.rb +13 -2
- data/spec/units/plugins/report_tests_teamcity_stdout_spec.rb +77 -3
- data/spec/units/plugins/reportgenerator_reportinator_spec.rb +1 -1
- data/spec/units/plugins/sanitize_records_spec.rb +3 -1
- data/spec/units/plugins/sanitize_spec.rb +1 -1
- data/spec/units/plugins/valgrind_spec.rb +23 -8
- data/spec/units/preprocess/preprocessinator_comment_stripper_spec.rb +1 -1
- data/spec/units/rake_app/rakefile_component_resolver_spec.rb +21 -0
- data/spec/units/release_build_executor_spec.rb +53 -14
- data/spec/units/release_build_planner_spec.rb +15 -3
- data/spec/units/reportinator_spec.rb +5 -5
- data/spec/units/standin_headerinator_spec.rb +31 -1
- data/spec/units/test_build_executor_spec.rb +65 -3
- data/spec/units/test_build_planner_spec.rb +104 -2
- data/spec/units/test_build_setup_spec.rb +96 -12
- data/spec/units/test_context_extractor_spec.rb +25 -0
- data/spec/units/test_file_preprocessinator_spec.rb +17 -1
- data/spec/units/test_includes_extractinator_spec.rb +5 -1
- data/spec/units/test_invoker/objects_wiring_spec.rb +6 -3
- data/spec/units/test_invoker_spec.rb +14 -1
- data/spec/units/test_source_file_directive_resolver_spec.rb +38 -7
- data/spec/units/tool_executor_spec.rb +26 -0
- data/spec/units/yaml_wrapper_spec.rb +11 -0
- metadata +109 -25
- data/lib/ceedling/file_path_collection_utils.rb +0 -164
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
:name: 'Dependencies archiver'
|
|
27
27
|
:optional: true # Checked when :build_lib archives, not by every Ceedling command
|
|
28
28
|
:arguments:
|
|
29
|
-
- rcs
|
|
30
|
-
- ${2}
|
|
31
|
-
- ${1}
|
|
29
|
+
- rcs
|
|
30
|
+
- '"${2}"' # Library
|
|
31
|
+
- '"${1}"' # Objects
|
|
32
32
|
|
|
33
33
|
:deps_zip:
|
|
34
34
|
:executable: unzip
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
:optional: true
|
|
37
37
|
:arguments:
|
|
38
38
|
- -o
|
|
39
|
-
- ${1} # Filepath
|
|
39
|
+
- '"${1}"' # Filepath
|
|
40
40
|
|
|
41
41
|
:deps_targzip:
|
|
42
42
|
:executable: tar
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
- clone
|
|
58
58
|
- ${1} # Optional branch with `-b` flag
|
|
59
59
|
- ${2} # Optional depth with `--depth` flag
|
|
60
|
-
- ${3} # Repository source
|
|
60
|
+
- '"${3}"' # Repository source
|
|
61
61
|
- .
|
|
62
62
|
|
|
63
63
|
:deps_git_checkout:
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
:arguments:
|
|
76
76
|
- checkout
|
|
77
77
|
- ${1} # Optional branch with `--revision` flag
|
|
78
|
-
- ${2} # Repository source
|
|
78
|
+
- '"${2}"' # Repository source
|
|
79
79
|
- .
|
|
80
80
|
|
|
81
81
|
...
|
|
@@ -89,12 +89,15 @@
|
|
|
89
89
|
task :prepare => all_deps
|
|
90
90
|
end
|
|
91
91
|
|
|
92
|
-
# Dependency libraries join the library names and paths test and release builds link with
|
|
92
|
+
# Dependency libraries join the library names and paths test and release builds link with,
|
|
93
|
+
# and their files join those the links depend on
|
|
93
94
|
link_libraries = @ceedling[DEPENDENCIES_SYM].link_libraries
|
|
94
95
|
PATHS_LIBRARIES ||= []
|
|
95
96
|
PATHS_LIBRARIES.concat( link_libraries[:paths] ).uniq!
|
|
96
97
|
LIBRARIES_SYSTEM ||= []
|
|
97
98
|
LIBRARIES_SYSTEM.concat( link_libraries[:names] ).uniq!
|
|
99
|
+
LIBRARIES_LINK_FILES ||= []
|
|
100
|
+
LIBRARIES_LINK_FILES.concat( link_libraries[:files] ).uniq!
|
|
98
101
|
|
|
99
102
|
# Add any artifact:include or :source folders to our release & test includes paths so linking and mocking work.
|
|
100
103
|
@ceedling[DEPENDENCIES_SYM].add_headers_and_sources()
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
require 'ceedling/plugins/plugin'
|
|
9
9
|
require 'ceedling/constants'
|
|
10
10
|
require 'ceedling/exceptions'
|
|
11
|
+
require 'ceedling/filesystem/project_paths'
|
|
12
|
+
require 'ceedling/filesystem/working_dir'
|
|
11
13
|
require 'dependency_spec'
|
|
12
14
|
require 'dependency_commands'
|
|
13
15
|
require 'dependency_environment'
|
|
@@ -121,13 +123,15 @@ class Dependencies < Plugin
|
|
|
121
123
|
end
|
|
122
124
|
end
|
|
123
125
|
|
|
124
|
-
# Library names and their directories, for test and release linking
|
|
126
|
+
# Library names and their directories, for test and release linking, and the library files
|
|
127
|
+
# themselves, which those links depend on
|
|
125
128
|
def link_libraries
|
|
126
129
|
libraries = @specs.flat_map { |spec| spec.static_libraries + spec.dynamic_libraries }
|
|
127
130
|
|
|
128
131
|
return {
|
|
129
132
|
names: libraries.map { |library| File.basename( library, '.*' ).delete_prefix( 'lib' ) }.reject( &:empty? ).uniq,
|
|
130
|
-
paths: libraries.map { |library| File.dirname( library ) }.reject( &:empty? ).uniq
|
|
133
|
+
paths: libraries.map { |library| File.dirname( library ) }.reject( &:empty? ).uniq,
|
|
134
|
+
files: libraries.uniq
|
|
131
135
|
}
|
|
132
136
|
end
|
|
133
137
|
|
|
@@ -173,7 +177,7 @@ class Dependencies < Plugin
|
|
|
173
177
|
|
|
174
178
|
# The one place this plugin changes directory, around a dependency's own commands
|
|
175
179
|
def in_directory(path, &block)
|
|
176
|
-
|
|
180
|
+
WorkingDir.chdir( path, &block )
|
|
177
181
|
end
|
|
178
182
|
|
|
179
183
|
# A fetch path that already holds files is taken as fetched, so fetching again, or
|
|
@@ -273,7 +277,7 @@ class Dependencies < Plugin
|
|
|
273
277
|
end
|
|
274
278
|
|
|
275
279
|
def compile(spec, source, search_paths)
|
|
276
|
-
object =
|
|
280
|
+
object = prepared_object( spec, source )
|
|
277
281
|
@ceedling[:generator].generate_object_file_c(
|
|
278
282
|
tool: TOOLS_DEPS_COMPILER,
|
|
279
283
|
module_name: File.basename( source ).ext,
|
|
@@ -283,13 +287,13 @@ class Dependencies < Plugin
|
|
|
283
287
|
search_paths: search_paths,
|
|
284
288
|
flags: spec.flags,
|
|
285
289
|
defines: spec.defines,
|
|
286
|
-
list: @ceedling[:file_path_utils].form_release_build_list_filepath(
|
|
290
|
+
list: @ceedling[:file_path_utils].form_release_build_list_filepath( object )
|
|
287
291
|
)
|
|
288
292
|
return object
|
|
289
293
|
end
|
|
290
294
|
|
|
291
295
|
def assemble(spec, source)
|
|
292
|
-
object =
|
|
296
|
+
object = prepared_object( spec, source )
|
|
293
297
|
@ceedling[:generator].generate_object_file_asm(
|
|
294
298
|
tool: TOOLS_DEPS_ASSEMBLER, module_name: File.basename( source ).ext, context: DEPENDENCIES_SYM,
|
|
295
299
|
source: source, object: object
|
|
@@ -297,8 +301,14 @@ class Dependencies < Plugin
|
|
|
297
301
|
return object
|
|
298
302
|
end
|
|
299
303
|
|
|
300
|
-
|
|
301
|
-
|
|
304
|
+
# A source's object sits at the source's own path below the dependency's source path, so
|
|
305
|
+
# same-named sources in different directories keep apart. Its directory is made here.
|
|
306
|
+
def prepared_object(spec, source)
|
|
307
|
+
subdir = ProjectPaths.subdir_below( spec.source_path, File.dirname( source ) ) || ''
|
|
308
|
+
object = File.join( spec.build_path, subdir, File.basename( source ).ext( EXTENSION_OBJECT.primary ) )
|
|
309
|
+
|
|
310
|
+
@ceedling[:file_wrapper].mkdir( File.dirname( object ) )
|
|
311
|
+
return object
|
|
302
312
|
end
|
|
303
313
|
|
|
304
314
|
def copy_library(built, destination)
|
|
@@ -6,14 +6,15 @@
|
|
|
6
6
|
# =========================================================================
|
|
7
7
|
|
|
8
8
|
require 'ceedling/exceptions'
|
|
9
|
+
require 'ceedling/filesystem/project_paths'
|
|
9
10
|
|
|
10
11
|
# One configured dependency, validated and normalized.
|
|
11
12
|
#
|
|
12
13
|
# Each dependency names its paths under :paths, and each path falls back to another when
|
|
13
14
|
# left out: :source and :fetch to each other, :build to :source then :fetch, :artifact to
|
|
14
15
|
# :build. With none configured, every path is `dependencies/<task name>`. Artifacts
|
|
15
|
-
# (libraries, executables, includes, sources) live under the artifact path
|
|
16
|
-
# :deploy path receives deployed copies.
|
|
16
|
+
# (libraries, executables, includes, sources) live under the artifact path, unless named by
|
|
17
|
+
# an absolute path. An optional :deploy path receives deployed copies.
|
|
17
18
|
#
|
|
18
19
|
# The task name is the configured name's word characters, which `dependencies:*` tasks
|
|
19
20
|
# use, so it must be non-empty and unique among dependencies.
|
|
@@ -47,7 +48,7 @@ class DependencySpec
|
|
|
47
48
|
@name = dep[:name] or raise CeedlingException.new( 'Each dependency must have a :name.' )
|
|
48
49
|
@task_name = task_name_for( @name )
|
|
49
50
|
@fetch = dep[:fetch] || {}
|
|
50
|
-
@paths = dep[:paths] || {}
|
|
51
|
+
@paths = standardized( dep[:paths] || {} )
|
|
51
52
|
@artifacts = dep[:artifacts] || {}
|
|
52
53
|
|
|
53
54
|
problem = fetch_problem
|
|
@@ -106,7 +107,7 @@ class DependencySpec
|
|
|
106
107
|
# glob expands through `collector` against the disk, and anything else is a directory.
|
|
107
108
|
def include_directories(collector)
|
|
108
109
|
return Array( @artifacts[:includes] ).flat_map do |include|
|
|
109
|
-
path =
|
|
110
|
+
path = artifact_at( include )
|
|
110
111
|
if include.end_with?( '.h' ) then [File.dirname( path )]
|
|
111
112
|
elsif include.match?( INCLUDE_GLOB ) then collector.call( path )
|
|
112
113
|
else [path]
|
|
@@ -128,7 +129,18 @@ class DependencySpec
|
|
|
128
129
|
end
|
|
129
130
|
|
|
130
131
|
def artifacts(kind)
|
|
131
|
-
return Array( @artifacts[kind] ).map { |path|
|
|
132
|
+
return Array( @artifacts[kind] ).map { |path| artifact_at( path ) }
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Configured paths, read as every configured path is read
|
|
136
|
+
def standardized(paths)
|
|
137
|
+
return paths.transform_values { |path| path.is_a?( String ) ? ProjectPaths.standardize( path ) : path }
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# An artifact below the artifact path, or one named by an absolute path as written
|
|
141
|
+
def artifact_at(path)
|
|
142
|
+
path = ProjectPaths.standardize( path )
|
|
143
|
+
return ProjectPaths.absolute?( path ) ? path : File.join( artifact_path, path )
|
|
132
144
|
end
|
|
133
145
|
|
|
134
146
|
# What is wrong with the fetch configuration, or nil
|
data/plugins/fff/lib/fff.rb
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
# ⏩️ https://github.com/ElectronVector/fake_function_framework
|
|
11
11
|
# =========================================================================
|
|
12
12
|
|
|
13
|
+
require 'fileutils'
|
|
13
14
|
require 'ceedling/plugins/plugin'
|
|
14
15
|
require 'fff_mock_generator'
|
|
15
16
|
|
|
@@ -36,16 +37,17 @@ end # class Fff
|
|
|
36
37
|
|
|
37
38
|
class FffCMockWrapper
|
|
38
39
|
|
|
39
|
-
|
|
40
|
+
def initialize(options=nil)
|
|
40
41
|
@cm_config = CMockConfig.new(options)
|
|
41
42
|
@cm_parser = CMockHeaderParser.new(@cm_config)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
@
|
|
47
|
-
@
|
|
48
|
-
@
|
|
43
|
+
# CMock's levels: 0 errors only, 1 warnings, 2 normal, 3 verbose
|
|
44
|
+
@verbosity = @cm_config.verbosity
|
|
45
|
+
|
|
46
|
+
# The additional files to include in the fake files, gathered as CMock gathers them
|
|
47
|
+
@includes_h_pre_orig_header = quoted( @cm_config.includes, @cm_config.includes_h_pre_orig_header )
|
|
48
|
+
@includes_h_post_orig_header = quoted( @cm_config.includes_h_post_orig_header )
|
|
49
|
+
@includes_c_pre_header = quoted( @cm_config.includes_c_pre_header )
|
|
50
|
+
@includes_c_post_header = quoted( @cm_config.includes_c_post_header )
|
|
49
51
|
end
|
|
50
52
|
|
|
51
53
|
# Matches CMock's own entry point, which Ceedling calls with the folder a mock's
|
|
@@ -57,37 +59,14 @@ class FffCMockWrapper
|
|
|
57
59
|
end
|
|
58
60
|
|
|
59
61
|
def generate_mock(header_file_to_mock, folder=nil)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
full_path_for_mock = "#{mock_path}/#{mock_name}"
|
|
69
|
-
c_name = c_name_for(mock_name, folder)
|
|
70
|
-
|
|
71
|
-
# Parse the header file so we know what to mock.
|
|
72
|
-
parsed_header = @cm_parser.parse(module_name, File.read(header_file_to_mock))
|
|
73
|
-
|
|
74
|
-
# Create the directory if it doesn't exist.
|
|
75
|
-
mkdir_p full_path_for_mock.pathmap("%d")
|
|
76
|
-
|
|
77
|
-
# Generate the fake function header file.
|
|
78
|
-
puts( "Creating fake functions: #{full_path_for_mock}.h" )
|
|
79
|
-
|
|
80
|
-
# Create the mock header.
|
|
81
|
-
File.open("#{full_path_for_mock}.h", 'w') do |f|
|
|
82
|
-
f.write(FffMockGenerator.create_mock_header(module_name, mock_name, parsed_header,
|
|
83
|
-
@includes_h_pre_orig_header, @includes_h_post_orig_header, c_name: c_name))
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
# Create the mock source file.
|
|
87
|
-
File.open("#{full_path_for_mock}.c", 'w') do |f|
|
|
88
|
-
f.write(FffMockGenerator.create_mock_source(mock_name, parsed_header,
|
|
89
|
-
@includes_c_pre_orig_header, @includes_c_post_orig_header, c_name: c_name))
|
|
90
|
-
end
|
|
62
|
+
module_name = File.basename(header_file_to_mock, '.h')
|
|
63
|
+
puts( "Creating fake functions for #{module_name}..." ) unless @verbosity < 2
|
|
64
|
+
mock_name = @cm_config.mock_prefix + module_name + @cm_config.mock_suffix
|
|
65
|
+
|
|
66
|
+
# Parse the header file so we know what to mock.
|
|
67
|
+
parsed_header = @cm_parser.parse(module_name, File.read(header_file_to_mock))
|
|
68
|
+
|
|
69
|
+
write_fake( "#{mock_path_for( folder )}/#{mock_name}", module_name, mock_name, parsed_header, c_name_for( mock_name, folder ) )
|
|
91
70
|
end
|
|
92
71
|
|
|
93
72
|
# The name for a fake's guard and control functions, as CMock forms it. With
|
|
@@ -103,6 +82,33 @@ class FffCMockWrapper
|
|
|
103
82
|
return identity.gsub( %r{[-/\\.,\s]}, '_' )
|
|
104
83
|
end
|
|
105
84
|
|
|
85
|
+
private
|
|
86
|
+
|
|
87
|
+
# The directory a fake is written to: the mock root, the folder its #include names,
|
|
88
|
+
# then any configured :subdir
|
|
89
|
+
def mock_path_for(folder)
|
|
90
|
+
mock_path = folder.nil? ? @cm_config.mock_path : File.join( @cm_config.mock_path, folder )
|
|
91
|
+
return @cm_config.subdir ? "#{mock_path}/#{@cm_config.subdir}" : mock_path
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Writes the fake's header and source at `path`, which ends in the mock's name
|
|
95
|
+
def write_fake(path, module_name, mock_name, parsed_header, c_name)
|
|
96
|
+
FileUtils.mkdir_p( File.dirname( path ) )
|
|
97
|
+
|
|
98
|
+
puts( "Creating fake functions: #{path}.h and #{path}.c" ) unless @verbosity < 3
|
|
99
|
+
File.write( "#{path}.h", FffMockGenerator.create_mock_header( module_name, mock_name, parsed_header,
|
|
100
|
+
@includes_h_pre_orig_header, @includes_h_post_orig_header, c_name: c_name ) )
|
|
101
|
+
|
|
102
|
+
File.write( "#{path}.c", FffMockGenerator.create_mock_source( mock_name, parsed_header,
|
|
103
|
+
@includes_c_pre_header, @includes_c_post_header, c_name: c_name ) )
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Joins include lists, each named once, as #include operands. A name holding `<` is
|
|
107
|
+
# kept as written, and any other is quoted, as CMock does.
|
|
108
|
+
def quoted(*lists)
|
|
109
|
+
return lists.compact.flatten.uniq.map { |name| name.match?( /</ ) ? name : "\"#{name}\"" }
|
|
110
|
+
end
|
|
111
|
+
|
|
106
112
|
end
|
|
107
113
|
|
|
108
114
|
# Switch out the CMock with FFF Mock Generator
|
|
@@ -0,0 +1,128 @@
|
|
|
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 'tmpdir'
|
|
9
|
+
require 'fileutils'
|
|
10
|
+
|
|
11
|
+
repo_root = File.expand_path( '../../..', __dir__ )
|
|
12
|
+
$LOAD_PATH.unshift( File.join( repo_root, 'lib' ), File.join( repo_root, 'vendor/cmock/lib' ) )
|
|
13
|
+
|
|
14
|
+
require 'fff.rb'
|
|
15
|
+
|
|
16
|
+
# GH #1377: A fake gets the extra includes CMock would give a mock of the same header.
|
|
17
|
+
# Each example runs the wrapper Ceedling swaps in for CMock, with Ceedling's own
|
|
18
|
+
# :includes default, and reads back the files it writes.
|
|
19
|
+
describe FffCMockWrapper do
|
|
20
|
+
|
|
21
|
+
around(:each) do |example|
|
|
22
|
+
Dir.mktmpdir do |root|
|
|
23
|
+
@root = root
|
|
24
|
+
@header = File.join( root, 'src', 'bar.h' )
|
|
25
|
+
FileUtils.mkdir_p( File.dirname( @header ) )
|
|
26
|
+
File.write( @header, "void bar_turn_on(void);\n" )
|
|
27
|
+
example.run
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def fake(options = {})
|
|
32
|
+
mock_path = File.join( @root, 'mocks' )
|
|
33
|
+
config = { :mock_prefix => 'mock_', :mock_path => mock_path, :includes => [], :verbosity => 0 }
|
|
34
|
+
FffCMockWrapper.new( config.merge( options ) ).setup_mocks( @header )
|
|
35
|
+
return {
|
|
36
|
+
:h => File.readlines( File.join( mock_path, 'mock_bar.h' ), chomp: true ),
|
|
37
|
+
:c => File.readlines( File.join( mock_path, 'mock_bar.c' ), chomp: true )
|
|
38
|
+
}
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def position(lines, line)
|
|
42
|
+
index = lines.index( line )
|
|
43
|
+
expect( index ).not_to be_nil, "expected #{line.inspect} in:\n#{lines.join( "\n" )}"
|
|
44
|
+
return index
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def extra_includes(lines)
|
|
48
|
+
standard = ['#include <string.h>', '#include "fff.h"', '#include "fff_unity_helper.h"', '#include "bar.h"', '#include "mock_bar.h"']
|
|
49
|
+
return lines.grep( /\A#include / ) - standard
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'adds no includes when no setting names any' do
|
|
53
|
+
files = fake
|
|
54
|
+
|
|
55
|
+
expect( extra_includes( files[:h] ) ).to eq( [] )
|
|
56
|
+
expect( extra_includes( files[:c] ) ).to eq( [] )
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it 'includes :includes_c_pre_header in the source before the fake header' do
|
|
60
|
+
files = fake( :includes_c_pre_header => ['extra_c.h'] )
|
|
61
|
+
|
|
62
|
+
expect( position( files[:c], '#include "extra_c.h"' ) ).to be < position( files[:c], '#include "mock_bar.h"' )
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it 'includes :includes_c_post_header in the source after the fake header' do
|
|
66
|
+
files = fake( :includes_c_post_header => ['extra_c.h'] )
|
|
67
|
+
|
|
68
|
+
expect( position( files[:c], '#include "extra_c.h"' ) ).to be > position( files[:c], '#include "mock_bar.h"' )
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'includes :includes_h_pre_orig_header in the header before the original header' do
|
|
72
|
+
files = fake( :includes_h_pre_orig_header => ['extra_h.h'] )
|
|
73
|
+
|
|
74
|
+
expect( position( files[:h], '#include "extra_h.h"' ) ).to be < position( files[:h], '#include "bar.h"' )
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it 'includes :includes_h_post_orig_header in the header after the original header' do
|
|
78
|
+
files = fake( :includes_h_post_orig_header => ['extra_h.h'] )
|
|
79
|
+
|
|
80
|
+
expect( position( files[:h], '#include "extra_h.h"' ) ).to be > position( files[:h], '#include "bar.h"' )
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it 'merges :includes with :includes_h_pre_orig_header, :includes first, each once' do
|
|
84
|
+
files = fake( :includes => ['first.h', 'both.h'], :includes_h_pre_orig_header => ['both.h', 'second.h'] )
|
|
85
|
+
|
|
86
|
+
expect( extra_includes( files[:h] ) ).to eq( ['#include "first.h"', '#include "both.h"', '#include "second.h"'] )
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it 'keeps an angle-bracket include as written and quotes a bare name' do
|
|
90
|
+
files = fake( :includes_c_pre_header => ['<stdint.h>', 'extra_c.h'] )
|
|
91
|
+
|
|
92
|
+
expect( extra_includes( files[:c] ) ).to eq( ['#include <stdint.h>', '#include "extra_c.h"'] )
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it 'includes a Unity helper in the source after the fake header, by its path from the mock root' do
|
|
96
|
+
helper = File.join( @root, 'support', 'helper.h' )
|
|
97
|
+
FileUtils.mkdir_p( File.dirname( helper ) )
|
|
98
|
+
File.write( helper, "\n" )
|
|
99
|
+
|
|
100
|
+
files = fake( :unity_helper_path => [helper] )
|
|
101
|
+
|
|
102
|
+
expect( position( files[:c], '#include "../support/helper.h"' ) ).to be > position( files[:c], '#include "mock_bar.h"' )
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# CMock's :verbosity levels: 0 errors only, 1 warnings, 2 normal, 3 verbose
|
|
106
|
+
context 'at CMock\'s verbosity levels' do
|
|
107
|
+
|
|
108
|
+
it 'prints nothing for errors only or warnings' do
|
|
109
|
+
expect { fake( :verbosity => 0 ) }.not_to output.to_stdout
|
|
110
|
+
expect { fake( :verbosity => 1 ) }.not_to output.to_stdout
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it 'announces each fake at normal verbosity, as CMock announces each mock' do
|
|
114
|
+
expect { fake( :verbosity => 2 ) }.to output( "Creating fake functions for bar...\n" ).to_stdout
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it 'also names the files written at verbose' do
|
|
118
|
+
path = File.join( @root, 'mocks', 'mock_bar' )
|
|
119
|
+
|
|
120
|
+
expect { fake( :verbosity => 3 ) }.to output(
|
|
121
|
+
"Creating fake functions for bar...\n" \
|
|
122
|
+
"Creating fake functions: #{path}.h and #{path}.c\n"
|
|
123
|
+
).to_stdout
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
end
|
|
@@ -41,7 +41,7 @@ DEFAULT_GCOV_LINKER_TOOL = {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
DEFAULT_GCOV_FIXTURE_TOOL = {
|
|
44
|
-
:executable => '${1}'.freeze,
|
|
44
|
+
:executable => '"${1}"'.freeze, # Test executable, quoted as a path
|
|
45
45
|
:name => 'default_gcov_fixture'.freeze,
|
|
46
46
|
:optional => false.freeze,
|
|
47
47
|
:arguments => [].freeze
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# =========================================================================
|
|
7
7
|
|
|
8
8
|
require 'ceedling/constants'
|
|
9
|
-
require 'ceedling/path_mirror'
|
|
9
|
+
require 'ceedling/filesystem/path_mirror'
|
|
10
10
|
require 'gcov_reportinator'
|
|
11
11
|
|
|
12
12
|
class ConsoleReportinator < GcovReportinator
|
|
@@ -173,22 +173,8 @@ class ConsoleReportinator < GcovReportinator
|
|
|
173
173
|
def run_gcov_summary(test, source, opts)
|
|
174
174
|
filename = File.basename(source)
|
|
175
175
|
|
|
176
|
-
#
|
|
177
|
-
|
|
178
|
-
# compile step already follows -- so the directory gcov is told to search must include that
|
|
179
|
-
# mirrored subdirectory too, not just the flat <build>/gcov/out/<test name> root.
|
|
180
|
-
# A generated Partial sits below its own test's Partials build root rather than a
|
|
181
|
-
# configured source root, so the source roots mirror nothing for it. Its own root is
|
|
182
|
-
# what carries the module's subdirectory.
|
|
183
|
-
roots =
|
|
184
|
-
if File.basename(source).match?(PATTERNS::PARTIAL_IMPL_FILENAME)
|
|
185
|
-
[File.join( @configurator.project_test_partials_path, test )]
|
|
186
|
-
else
|
|
187
|
-
@configurator.paths_source + @configurator.paths_support
|
|
188
|
-
end
|
|
189
|
-
|
|
190
|
-
subdir = PathMirror.relative_subdir( source, roots )
|
|
191
|
-
obj_dir = subdir.empty? ? File.join(GCOV_BUILD_OUTPUT_PATH, test) : File.join(GCOV_BUILD_OUTPUT_PATH, test, subdir)
|
|
176
|
+
# The coverage data sits beside the object, wherever the test's build placed it
|
|
177
|
+
obj_dir = File.dirname( @file_path_utils.form_test_object_filepath( source, name: test, context: GCOV_SYM ) )
|
|
192
178
|
|
|
193
179
|
# Run gcov to extract the coverage summary
|
|
194
180
|
command = @tool_executor.build_command_line(
|
|
@@ -197,7 +183,7 @@ class ConsoleReportinator < GcovReportinator
|
|
|
197
183
|
(opts[:gcov_mcdc] ? ['-g'] : []),
|
|
198
184
|
# Argument replacement
|
|
199
185
|
filename, # .c source file compiled with coverage
|
|
200
|
-
obj_dir # <build>/gcov/out/<test name>[/
|
|
186
|
+
obj_dir # <build>/gcov/out/<test name>[/source directory] for coverage data files
|
|
201
187
|
)
|
|
202
188
|
|
|
203
189
|
# Do not raise an exception if `gcov` terminates with a non-zero exit code, just note it and move on.
|
data/plugins/gcov/lib/gcov.rb
CHANGED
|
@@ -12,6 +12,7 @@ require 'gcov_constants'
|
|
|
12
12
|
require 'gcov_types'
|
|
13
13
|
require 'gcov_reportinator'
|
|
14
14
|
require 'console_reportinator'
|
|
15
|
+
require 'gcovr_thresholds'
|
|
15
16
|
require 'gcovr_reportinator'
|
|
16
17
|
require 'reportgenerator_reportinator'
|
|
17
18
|
|
|
@@ -141,7 +142,7 @@ class Gcov < Plugin
|
|
|
141
142
|
|
|
142
143
|
# Full filepaths (not basenames)
|
|
143
144
|
header = "Untested source files not in the coverage report (:untested_sources is :list):"
|
|
144
|
-
@loginator.log_list( untested_sources.sort, header, Verbosity::COMPLAIN
|
|
145
|
+
@loginator.log_list( untested_sources.sort, header, Verbosity::COMPLAIN )
|
|
145
146
|
|
|
146
147
|
when GCOV_UNTESTED_SOURCES_COMPILE
|
|
147
148
|
validate_mcdc_gcc_version!
|
|
@@ -163,7 +164,7 @@ class Gcov < Plugin
|
|
|
163
164
|
untested_sources.each do |filepath|
|
|
164
165
|
filename = File.basename(filepath)
|
|
165
166
|
object = @file_path_utils.form_test_object_filepath( filepath, context:GCOV_SYM )
|
|
166
|
-
dependencies = @file_path_utils.form_test_dependencies_filepath(
|
|
167
|
+
dependencies = @file_path_utils.form_test_dependencies_filepath( object, context:GCOV_SYM )
|
|
167
168
|
search_paths = @configurator.collection_paths_include
|
|
168
169
|
# Defines and flags resolve as a tested source's do, against this source's filepath
|
|
169
170
|
defines = @test_build_setup.context_defines( context:GCOV_SYM, filepath:filepath )
|
|
@@ -196,6 +197,9 @@ class Gcov < Plugin
|
|
|
196
197
|
next
|
|
197
198
|
end
|
|
198
199
|
|
|
200
|
+
@file_wrapper.mkdir( File.dirname( object ) )
|
|
201
|
+
@file_wrapper.mkdir( File.dirname( dependencies ) )
|
|
202
|
+
|
|
199
203
|
begin
|
|
200
204
|
@generator.generate_object_file_c(
|
|
201
205
|
tool: TOOLS_GCOV_COMPILER,
|
|
@@ -382,6 +386,9 @@ class Gcov < Plugin
|
|
|
382
386
|
|
|
383
387
|
begin
|
|
384
388
|
reportinator.generate_reports( @configurator.project_config_hash )
|
|
389
|
+
rescue GcovrThresholdError => ex
|
|
390
|
+
# Each violated threshold is its own build failure
|
|
391
|
+
ex.violations.each { |violation| @ceedling[:plugin_manager].register_build_failure( GCOV_SYM, violation ) }
|
|
385
392
|
rescue => ex
|
|
386
393
|
# Register the exception as a build failure
|
|
387
394
|
@ceedling[:plugin_manager].register_build_failure( GCOV_SYM, ex.message )
|
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
|
|
8
8
|
require 'ceedling/exceptions'
|
|
9
9
|
require 'ceedling/constants'
|
|
10
|
+
require 'ceedling/filename_extension'
|
|
10
11
|
require 'gcov_types'
|
|
11
12
|
require 'gcov_reportinator'
|
|
13
|
+
require 'gcovr_thresholds'
|
|
12
14
|
|
|
13
15
|
class GcovrReportinator < GcovReportinator
|
|
14
16
|
|
|
@@ -507,9 +509,8 @@ class GcovrReportinator < GcovReportinator
|
|
|
507
509
|
data = build_exclusion_data
|
|
508
510
|
patterns = []
|
|
509
511
|
|
|
510
|
-
# A source extension can be configured as more than one string, so
|
|
511
|
-
|
|
512
|
-
src_extension_alternation = data[:src_extension].to_a.map { |ext| Regexp.escape(ext) }.join('|')
|
|
512
|
+
# A source extension can be configured as more than one string, so any one of them matches
|
|
513
|
+
src_extension_alternation = FilenameExtension.new( data[:src_extension] ).pattern
|
|
513
514
|
test_prefix = Regexp.escape(data[:test_prefix].to_s)
|
|
514
515
|
build_root = Regexp.escape(strip_leading_dot_slash(data[:build_root].to_s))
|
|
515
516
|
|
|
@@ -576,23 +577,6 @@ class GcovrReportinator < GcovReportinator
|
|
|
576
577
|
end
|
|
577
578
|
|
|
578
579
|
|
|
579
|
-
# Returns the error message text from gcovr stderr, or nil if none found.
|
|
580
|
-
# Matches lines beginning with "error" or "(ERROR)" and extracts the trailing message.
|
|
581
|
-
def extract_gcovr_error_message(shell_result)
|
|
582
|
-
return nil if shell_result.nil?
|
|
583
|
-
|
|
584
|
-
stderr = shell_result[:stderr]
|
|
585
|
-
return nil if stderr.nil? || stderr.empty?
|
|
586
|
-
|
|
587
|
-
stderr.each_line do |line|
|
|
588
|
-
match = line.match( /^\(?error\S*\s+(.+)/i )
|
|
589
|
-
return match[1].strip.capitalize if match
|
|
590
|
-
end
|
|
591
|
-
|
|
592
|
-
nil
|
|
593
|
-
end
|
|
594
|
-
|
|
595
|
-
|
|
596
580
|
# Extract the last contiguous block of lines containing '%' from gcovr stdout.
|
|
597
581
|
# gcovr --print-summary emits lines like "lines: 69.6% (80 out of 115)" — this
|
|
598
582
|
# locates that block generically without depending on exact line labels.
|
|
@@ -620,33 +604,17 @@ class GcovrReportinator < GcovReportinator
|
|
|
620
604
|
end
|
|
621
605
|
|
|
622
606
|
|
|
623
|
-
#
|
|
624
|
-
#
|
|
625
|
-
# gcovr's composite exit code bit-ORs every violated :fail_under_* threshold together --
|
|
626
|
-
# every violated bit is collected and reported, not just whichever is checked first.
|
|
607
|
+
# Reports every :fail_under_* threshold a gcovr run violated, raising when boom is set and
|
|
608
|
+
# logging otherwise. Returns whether the exit code holds a problem no threshold explains.
|
|
627
609
|
def gcovr_exec_exception?(opts, exitcode, boom, shell_result=nil)
|
|
628
|
-
violations =
|
|
629
|
-
|
|
630
|
-
{
|
|
631
|
-
2 => [:fail_under_line, 'Line'],
|
|
632
|
-
4 => [:fail_under_branch, 'Branch'],
|
|
633
|
-
8 => [:fail_under_decision, 'Decision'],
|
|
634
|
-
16 => [:fail_under_function, 'Function'],
|
|
635
|
-
}.each do |bit, (option, label)|
|
|
636
|
-
next unless ((exitcode & bit) == bit) && !opts[option].nil?
|
|
637
|
-
|
|
638
|
-
fallback = "#{label} coverage is less than the configured minimum of #{opts[option]}%"
|
|
639
|
-
violations << "Gcovr ⏩️ #{extract_gcovr_error_message( shell_result ) || fallback}"
|
|
640
|
-
exitcode &= ~bit
|
|
641
|
-
end
|
|
610
|
+
violations, exitcode = GcovrThresholds.decode( opts: opts, exitcode: exitcode, stderr: shell_result&.dig( :stderr ) )
|
|
642
611
|
|
|
643
612
|
if boom
|
|
644
|
-
raise
|
|
613
|
+
raise GcovrThresholdError.new( violations ) unless violations.empty?
|
|
645
614
|
else
|
|
646
615
|
violations.each { |msg| @loginator.log( msg, Verbosity::COMPLAIN ) }
|
|
647
616
|
end
|
|
648
617
|
|
|
649
|
-
# A non-zero exit code is a problem
|
|
650
618
|
return (exitcode != 0)
|
|
651
619
|
end
|
|
652
620
|
|