ceedling 1.1.2 → 1.1.4
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 +1 -1
- data/assets/fake_crash_test_fixture.rb +14 -0
- data/assets/partial_all_module.h +11 -0
- data/assets/run_with_ubsan.rb +15 -0
- data/assets/same_dir_pairing_module.c +4 -0
- data/assets/same_dir_pairing_module.h +8 -0
- data/assets/same_dir_pairing_module_func.h +6 -0
- data/assets/same_dir_pairing_other.c +4 -0
- data/assets/same_dir_pairing_other.h +8 -0
- data/assets/test_example_file_crash_sigsegv_with_param.c +32 -0
- data/assets/test_example_file_ub_shift_overflow.c +22 -0
- data/assets/test_partial_all_module.c +16 -0
- data/assets/test_same_dir_pairing.c +23 -0
- data/bin/actions_wrapper.rb +7 -6
- data/docs/Changelog.md +29 -1
- data/docs/mkdocs/configuration/reference/index.md +8 -0
- data/docs/mkdocs/configuration/reference/partials.md +38 -0
- data/examples/wondrous_forest/src/LightSensor.c +21 -4
- data/examples/wondrous_forest/src/LightSensor.h +12 -4
- data/examples/wondrous_forest/test/TestLightSensor.c +34 -4
- data/lib/ceedling/c_extractor/c_extractor.rb +37 -11
- data/lib/ceedling/c_extractor/c_extractor_constants.rb +0 -3
- data/lib/ceedling/c_extractor/c_extractor_declarations.rb +26 -25
- data/lib/ceedling/c_extractor/c_extractor_functions.rb +5 -12
- data/lib/ceedling/config/configurator.rb +8 -1
- data/lib/ceedling/config/configurator_setup.rb +26 -0
- data/lib/ceedling/defaults.rb +16 -2
- data/lib/ceedling/file_path_utils.rb +7 -0
- data/lib/ceedling/file_wrapper.rb +8 -0
- data/lib/ceedling/generators/generator.rb +15 -0
- data/lib/ceedling/generators/generator_helper.rb +25 -6
- data/lib/ceedling/generators/generator_partials.rb +84 -3
- data/lib/ceedling/generators/generator_test_results_backtrace.rb +268 -100
- data/lib/ceedling/generators/generator_test_runner.rb +20 -2
- data/lib/ceedling/includes/includes.rb +66 -11
- data/lib/ceedling/objects.yml +5 -0
- data/lib/ceedling/partials/partializer.rb +18 -3
- data/lib/ceedling/partials/partializer_utils.rb +6 -1
- data/lib/ceedling/preprocess/preprocessinator_includes_handler.rb +43 -16
- data/lib/ceedling/test_invoker/test_build_executor.rb +19 -8
- data/lib/version.rb +1 -1
- data/mkdocs.yml +1 -0
- data/plugins/gcov/lib/gcov.rb +2 -2
- data/site-local/404.html +30 -0
- data/site-local/configuration/environment-vars.html +30 -0
- data/site-local/configuration/global-collections.html +30 -0
- data/site-local/configuration/index.html +30 -0
- data/site-local/configuration/loading.html +30 -0
- data/site-local/configuration/mixins.html +30 -0
- data/site-local/configuration/parallel-builds.html +30 -0
- data/site-local/configuration/project-file.html +30 -0
- data/site-local/configuration/reference/cexception.html +30 -0
- data/site-local/configuration/reference/cmock.html +30 -0
- data/site-local/configuration/reference/defines.html +30 -0
- data/site-local/configuration/reference/environment.html +30 -0
- data/site-local/configuration/reference/extension.html +30 -0
- data/site-local/configuration/reference/files.html +30 -0
- data/site-local/configuration/reference/flags.html +30 -0
- data/site-local/configuration/reference/index.html +36 -0
- data/site-local/configuration/reference/libraries.html +30 -0
- data/site-local/configuration/reference/mixins.html +30 -0
- data/site-local/configuration/reference/partials.html +4257 -0
- data/site-local/configuration/reference/paths.html +30 -0
- data/site-local/configuration/reference/plugins.html +30 -0
- data/site-local/configuration/reference/project.html +30 -0
- data/site-local/configuration/reference/release-build.html +31 -1
- data/site-local/configuration/reference/test-build.html +31 -1
- data/site-local/configuration/reference/test-runner.html +30 -0
- data/site-local/configuration/reference/tools.html +30 -0
- data/site-local/configuration/reference/unity.html +30 -0
- data/site-local/configuration/which-ceedling.html +30 -0
- data/site-local/development/index.html +30 -0
- data/site-local/development/plugins/configuration.html +30 -0
- data/site-local/development/plugins/index.html +30 -0
- data/site-local/development/plugins/plugin-subclass.html +30 -0
- data/site-local/development/plugins/rake-tasks.html +30 -0
- data/site-local/development/workflow.html +30 -0
- data/site-local/getting-started/command-line.html +30 -0
- data/site-local/getting-started/example-projects/cipher-quest.html +30 -0
- data/site-local/getting-started/example-projects/index.html +30 -0
- data/site-local/getting-started/example-projects/temp-sensor.html +30 -0
- data/site-local/getting-started/example-projects/wondrous-forest.html +30 -0
- data/site-local/getting-started/index.html +30 -0
- data/site-local/getting-started/installation.html +30 -0
- data/site-local/getting-started/quick-start.html +30 -0
- data/site-local/help.html +30 -0
- data/site-local/index.html +30 -0
- data/site-local/overview/build-system.html +30 -0
- data/site-local/overview/index.html +30 -0
- data/site-local/overview/test-environments.html +30 -0
- data/site-local/overview/tools-and-frameworks.html +30 -0
- data/site-local/plugins/beep.html +30 -0
- data/site-local/plugins/bullseye.html +30 -0
- data/site-local/plugins/command-hooks.html +30 -0
- data/site-local/plugins/compile-commands-json-db.html +30 -0
- data/site-local/plugins/cppcheck.html +30 -0
- data/site-local/plugins/dependencies.html +30 -0
- data/site-local/plugins/fff.html +30 -0
- data/site-local/plugins/gcov/examples.html +30 -0
- data/site-local/plugins/gcov/gcovr.html +30 -0
- data/site-local/plugins/gcov/index.html +30 -0
- data/site-local/plugins/gcov/overview.html +30 -0
- data/site-local/plugins/gcov/reportgenerator.html +30 -0
- data/site-local/plugins/gcov/reporting.html +30 -0
- data/site-local/plugins/gcov/setup.html +30 -0
- data/site-local/plugins/gcov/tool-versions.html +30 -0
- data/site-local/plugins/gcov/troubleshooting.html +30 -0
- data/site-local/plugins/index.html +30 -0
- data/site-local/plugins/module-generator.html +30 -0
- data/site-local/plugins/report-build-warnings-log.html +30 -0
- data/site-local/plugins/report-tests-gtestlike-stdout.html +30 -0
- data/site-local/plugins/report-tests-ide-stdout.html +30 -0
- data/site-local/plugins/report-tests-log-factory.html +30 -0
- data/site-local/plugins/report-tests-pretty-stdout.html +30 -0
- data/site-local/plugins/report-tests-raw-output-log.html +30 -0
- data/site-local/plugins/report-tests-teamcity-stdout.html +30 -0
- data/site-local/plugins/valgrind.html +30 -0
- data/site-local/project/release-history.html +30 -0
- data/site-local/project/upgrade.html +30 -0
- data/site-local/reference/build-directives.html +30 -0
- data/site-local/reference/command-line.html +30 -0
- data/site-local/reference/environment-vars.html +30 -0
- data/site-local/reference/gcov-plugin.html +30 -0
- data/site-local/reference/global-collections.html +30 -0
- data/site-local/reference/index.html +30 -0
- data/site-local/reference/partials-macros.html +30 -0
- data/site-local/reference/project-configuration.html +30 -0
- data/site-local/sitemap.xml.gz +0 -0
- data/site-local/snapshot/examples/cipher_quest/index.html +30 -0
- data/site-local/snapshot/examples/temp_sensor/index.html +30 -0
- data/site-local/snapshot/examples/wondrous_forest/index.html +30 -0
- data/site-local/testing-guide/build-directives.html +30 -0
- data/site-local/testing-guide/conventions.html +30 -0
- data/site-local/testing-guide/frameworks.html +30 -0
- data/site-local/testing-guide/index.html +30 -0
- data/site-local/testing-guide/partials/configuration.html +30 -0
- data/site-local/testing-guide/partials/conventions.html +30 -0
- data/site-local/testing-guide/partials/directives.html +30 -0
- data/site-local/testing-guide/partials/example.html +30 -0
- data/site-local/testing-guide/partials/index.html +30 -0
- data/site-local/testing-guide/partials/overview.html +30 -0
- data/site-local/testing-guide/partials/variables.html +30 -0
- data/site-local/testing-guide/test-cases.html +30 -0
- data/site-local/testing-guide/test-sample.html +30 -0
- data/site-local/testing-guide/test-suite-anatomy.html +30 -0
- data/spec/support/system/spec_system_helper.rb +25 -0
- data/spec/support/system/system_context.rb +15 -0
- data/spec/system/deployment_as_gem_spec.rb +14 -0
- data/spec/system/deployment_as_vendor_spec.rb +19 -0
- data/spec/system/encoding_stress_spec.rb +4 -4
- data/spec/system/example_wondrous_forest_spec.rb +2 -2
- data/spec/system/support/common_test_cases.rb +227 -0
- data/spec/units/c_extractor/c_extractor_declarations_spec.rb +27 -4
- data/spec/units/c_extractor/c_extractor_functions_spec.rb +1 -11
- data/spec/units/c_extractor/c_extractor_integration_spec.rb +18 -11
- data/spec/units/c_extractor/c_extractor_spec.rb +57 -1
- data/spec/units/config/configurator_setup_spec.rb +61 -0
- data/spec/units/configurator_spec.rb +45 -0
- data/spec/units/file_path_utils_spec.rb +17 -0
- data/spec/units/generators/generator_helper_spec.rb +34 -7
- data/spec/units/generators/generator_partials_spec.rb +120 -12
- data/spec/units/generators/generator_test_results_backtrace_spec.rb +248 -41
- data/spec/units/generators/generator_test_runner_spec.rb +26 -2
- data/spec/units/includes/include_spec.rb +30 -18
- data/spec/units/includes/includes_spec.rb +100 -10
- data/spec/units/partials/partializer_spec.rb +113 -1
- data/spec/units/partials/partializer_utils_spec.rb +11 -0
- data/spec/units/preprocess/preprocessinator_includes_handler_spec.rb +96 -7
- data/spec/units/system_wrapper_spec.rb +72 -0
- data/spec/units/test_context_extractor_spec.rb +3 -3
- metadata +20 -2
|
@@ -111,20 +111,38 @@ describe "Includes serialization" do
|
|
|
111
111
|
expect(restored.map(&:filename)).to eq(["first.h", "second.h", "third.h", "fourth.h"])
|
|
112
112
|
end
|
|
113
113
|
|
|
114
|
-
it "handles includes with
|
|
114
|
+
it "handles includes with an include_path override during serialization" do
|
|
115
115
|
original = [
|
|
116
|
-
UserInclude.new("path/to/header.h",
|
|
117
|
-
SystemInclude.new("sys/stdio.h",
|
|
118
|
-
MockInclude.new("mocks/mock_module.h"
|
|
116
|
+
UserInclude.new("path/to/header.h", include_path: "path/to/header.h"),
|
|
117
|
+
SystemInclude.new("sys/stdio.h", include_path: "sys/stdio.h"),
|
|
118
|
+
MockInclude.new("mocks/mock_module.h")
|
|
119
119
|
]
|
|
120
|
-
|
|
120
|
+
|
|
121
121
|
hashes = Includes.to_hashes(original)
|
|
122
122
|
restored = Includes.from_hashes(hashes)
|
|
123
|
-
|
|
123
|
+
|
|
124
124
|
expect(restored.length).to eq(3)
|
|
125
125
|
expect(restored[0].filepath).to eq("path/to/header.h")
|
|
126
126
|
expect(restored[1].filepath).to eq("sys/stdio.h")
|
|
127
127
|
expect(restored[2].filepath).to eq("mocks/mock_module.h")
|
|
128
|
+
# `include_path` must itself round-trip, not merely `filepath` -- otherwise a cached
|
|
129
|
+
# build silently reverts to filename-only rendering on its next, cache-hit run.
|
|
130
|
+
expect("#{restored[0]}").to eq('#include "path/to/header.h"')
|
|
131
|
+
expect("#{restored[1]}").to eq('#include <sys/stdio.h>')
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
it "round-trips include_path, and has it take rendering precedence over filepath/filename" do
|
|
135
|
+
original = [
|
|
136
|
+
SystemInclude.new("/usr/include/x86_64-linux-gnu/sys/stat.h", include_path: "sys/stat.h")
|
|
137
|
+
]
|
|
138
|
+
|
|
139
|
+
hashes = Includes.to_hashes(original)
|
|
140
|
+
restored = Includes.from_hashes(hashes)
|
|
141
|
+
|
|
142
|
+
expect(restored.length).to eq(1)
|
|
143
|
+
expect(restored[0].filepath).to eq("/usr/include/x86_64-linux-gnu/sys/stat.h")
|
|
144
|
+
expect(restored[0].include_path).to eq("sys/stat.h")
|
|
145
|
+
expect("#{restored[0]}").to eq("#include <sys/stat.h>")
|
|
128
146
|
end
|
|
129
147
|
|
|
130
148
|
it "handles empty array" do
|
|
@@ -1054,16 +1072,88 @@ describe "Includes reconciliation" do
|
|
|
1054
1072
|
Include.new("subdir/header.h"),
|
|
1055
1073
|
Include.new("sys/types.h")
|
|
1056
1074
|
]
|
|
1057
|
-
|
|
1075
|
+
|
|
1058
1076
|
user = [UserInclude.new("header.h")]
|
|
1059
1077
|
system = [SystemInclude.new("types.h")]
|
|
1060
|
-
|
|
1078
|
+
|
|
1061
1079
|
result = Includes.reconcile(bare: bare, user: user, system: system)
|
|
1062
|
-
|
|
1080
|
+
|
|
1063
1081
|
# Should match by filename only
|
|
1064
1082
|
expect(result.length).to eq(2)
|
|
1065
1083
|
expect(result[0].filename).to eq("types.h")
|
|
1066
1084
|
expect(result[1].filename).to eq("header.h")
|
|
1067
1085
|
end
|
|
1086
|
+
|
|
1087
|
+
it "preserves a system include directive's original directory components instead of collapsing to its bare filename" do
|
|
1088
|
+
bare = [Include.new("sys/stat.h")]
|
|
1089
|
+
user = []
|
|
1090
|
+
system = [SystemInclude.new("/usr/include/x86_64-linux-gnu/sys/stat.h")]
|
|
1091
|
+
|
|
1092
|
+
result = Includes.reconcile(bare: bare, user: user, system: system)
|
|
1093
|
+
|
|
1094
|
+
expect(result.length).to eq(1)
|
|
1095
|
+
expect(result[0]).to be_a(SystemInclude)
|
|
1096
|
+
expect(result[0].filepath).to eq("/usr/include/x86_64-linux-gnu/sys/stat.h")
|
|
1097
|
+
expect("#{result[0]}").to eq("#include <sys/stat.h>")
|
|
1098
|
+
expect(Includes.from_hashes(Includes.to_hashes(result)).map(&:to_s)).to eq(["#include <sys/stat.h>"])
|
|
1099
|
+
end
|
|
1100
|
+
|
|
1101
|
+
it "prefers the more specific bare entry when a system header's basename collides with an unrelated bare entry" do
|
|
1102
|
+
# A project's own quoted `#include "stat.h"` sitting alongside a system
|
|
1103
|
+
# `#include <sys/stat.h>` in the same file: both reach `bare` as plain, untyped
|
|
1104
|
+
# Include objects, and the short entry trivially "corresponds" to any longer
|
|
1105
|
+
# resolved path ending in the same filename. The longer, genuinely-corresponding
|
|
1106
|
+
# entry must still win, regardless of which one happens to appear first in `bare`.
|
|
1107
|
+
bare = [
|
|
1108
|
+
Include.new("stat.h"),
|
|
1109
|
+
Include.new("sys/stat.h")
|
|
1110
|
+
]
|
|
1111
|
+
user = []
|
|
1112
|
+
system = [SystemInclude.new("/usr/include/x86_64-linux-gnu/sys/stat.h")]
|
|
1113
|
+
|
|
1114
|
+
result = Includes.reconcile(bare: bare, user: user, system: system)
|
|
1115
|
+
|
|
1116
|
+
expect(result.length).to eq(1)
|
|
1117
|
+
expect("#{result[0]}").to eq("#include <sys/stat.h>")
|
|
1118
|
+
end
|
|
1119
|
+
|
|
1120
|
+
it "falls back to a same-filename bare entry when nothing corresponds by path" do
|
|
1121
|
+
# The compiler's real search-path structure can diverge from a directive's own
|
|
1122
|
+
# literal spelling (a symlinked or vendored include root, for instance), so a
|
|
1123
|
+
# resolved system path may not share any trailing segment with its bare entry
|
|
1124
|
+
# beyond the filename itself. Rendering the bare entry's own spelling is still
|
|
1125
|
+
# strictly better than collapsing to the bare filename alone.
|
|
1126
|
+
bare = [Include.new("compat/stat.h")]
|
|
1127
|
+
user = []
|
|
1128
|
+
system = [SystemInclude.new("/usr/include/x86_64-linux-gnu/bits/stat.h")]
|
|
1129
|
+
|
|
1130
|
+
result = Includes.reconcile(bare: bare, user: user, system: system)
|
|
1131
|
+
|
|
1132
|
+
expect(result.length).to eq(1)
|
|
1133
|
+
expect("#{result[0]}").to eq("#include <compat/stat.h>")
|
|
1134
|
+
end
|
|
1135
|
+
|
|
1136
|
+
it "does not hard-error over two same-named system headers, a normal toolchain wrapper-chain pattern rather than a project-file conflict" do
|
|
1137
|
+
# e.g. a compiler-provided stdint.h #include_next-ing its libc counterpart --
|
|
1138
|
+
# both real, both legitimately entered, both sharing a basename, neither a
|
|
1139
|
+
# project file whose identity is actually in question.
|
|
1140
|
+
bare = [Include.new("stdint.h")]
|
|
1141
|
+
|
|
1142
|
+
user = []
|
|
1143
|
+
system = [
|
|
1144
|
+
SystemInclude.new("/usr/lib/gcc/x86_64-linux-gnu/14/include/stdint.h"),
|
|
1145
|
+
SystemInclude.new("/usr/include/stdint.h")
|
|
1146
|
+
]
|
|
1147
|
+
|
|
1148
|
+
result = nil
|
|
1149
|
+
expect {
|
|
1150
|
+
result = Includes.reconcile(bare: bare, user: user, system: system)
|
|
1151
|
+
}.not_to raise_error
|
|
1152
|
+
|
|
1153
|
+
expect(result.length).to eq(2)
|
|
1154
|
+
expect(result.map(&:filepath)).to include(
|
|
1155
|
+
"/usr/lib/gcc/x86_64-linux-gnu/14/include/stdint.h", "/usr/include/stdint.h"
|
|
1156
|
+
)
|
|
1157
|
+
end
|
|
1068
1158
|
end
|
|
1069
|
-
end
|
|
1159
|
+
end
|
|
@@ -522,6 +522,31 @@ describe Partializer do
|
|
|
522
522
|
expect(result).not_to include(UserInclude.new('partial1.h'))
|
|
523
523
|
expect(result).not_to include(UserInclude.new('partial2.h'))
|
|
524
524
|
end
|
|
525
|
+
|
|
526
|
+
it "appends the shared types header when one was generated for this module" do
|
|
527
|
+
includes = [UserInclude.new('header1.h')]
|
|
528
|
+
partials = {}
|
|
529
|
+
result = @partializer.remap_implementation_header_includes(
|
|
530
|
+
name: 'module',
|
|
531
|
+
includes: includes,
|
|
532
|
+
partials: partials,
|
|
533
|
+
types_header: 'ceedling_partial_module_types.h'
|
|
534
|
+
)
|
|
535
|
+
|
|
536
|
+
expect(result).to include(UserInclude.new('ceedling_partial_module_types.h'))
|
|
537
|
+
end
|
|
538
|
+
|
|
539
|
+
it "does not append a types header when the module has none" do
|
|
540
|
+
includes = [UserInclude.new('header1.h')]
|
|
541
|
+
partials = {}
|
|
542
|
+
result = @partializer.remap_implementation_header_includes(
|
|
543
|
+
name: 'module',
|
|
544
|
+
includes: includes,
|
|
545
|
+
partials: partials
|
|
546
|
+
)
|
|
547
|
+
|
|
548
|
+
expect(result).to match_array([UserInclude.new('header1.h')])
|
|
549
|
+
end
|
|
525
550
|
end
|
|
526
551
|
|
|
527
552
|
###
|
|
@@ -683,6 +708,31 @@ describe Partializer do
|
|
|
683
708
|
expect(result).not_to include(UserInclude.new('partial1.h'))
|
|
684
709
|
expect(result).not_to include(UserInclude.new('partial2.h'))
|
|
685
710
|
end
|
|
711
|
+
|
|
712
|
+
it "appends the shared types header when one was generated for this module" do
|
|
713
|
+
includes = [UserInclude.new('header1.h')]
|
|
714
|
+
partials = {}
|
|
715
|
+
result = @partializer.remap_interface_header_includes(
|
|
716
|
+
name: 'module',
|
|
717
|
+
includes: includes,
|
|
718
|
+
partials: partials,
|
|
719
|
+
types_header: 'ceedling_partial_module_types.h'
|
|
720
|
+
)
|
|
721
|
+
|
|
722
|
+
expect(result).to include(UserInclude.new('ceedling_partial_module_types.h'))
|
|
723
|
+
end
|
|
724
|
+
|
|
725
|
+
it "does not append a types header when the module has none" do
|
|
726
|
+
includes = [UserInclude.new('header1.h')]
|
|
727
|
+
partials = {}
|
|
728
|
+
result = @partializer.remap_interface_header_includes(
|
|
729
|
+
name: 'module',
|
|
730
|
+
includes: includes,
|
|
731
|
+
partials: partials
|
|
732
|
+
)
|
|
733
|
+
|
|
734
|
+
expect(result).to match_array([UserInclude.new('header1.h')])
|
|
735
|
+
end
|
|
686
736
|
end
|
|
687
737
|
|
|
688
738
|
###
|
|
@@ -1521,6 +1571,66 @@ describe Partializer do
|
|
|
1521
1571
|
expect(result).to eq(filtered)
|
|
1522
1572
|
end
|
|
1523
1573
|
|
|
1574
|
+
it "merges declaration-only functions into the DEDUCT candidate pool" do
|
|
1575
|
+
defn = double('inline_func', name: 'inline_fn')
|
|
1576
|
+
decl = double('proto_func', name: 'proto_fn')
|
|
1577
|
+
defs = [defn]
|
|
1578
|
+
decls = [decl]
|
|
1579
|
+
filtered = [double('iface_inline'), double('iface_proto')]
|
|
1580
|
+
pf = make_pf(type: Partials::DEDUCT)
|
|
1581
|
+
|
|
1582
|
+
expect(@partializer_helper).to receive(:filter_and_transform_funcs)
|
|
1583
|
+
.with([defn, decl], Partials::DEDUCT, :interface).and_return(filtered)
|
|
1584
|
+
allow(@partializer_helper).to receive(:subtract_funcs)
|
|
1585
|
+
.with(funcs: filtered, names: []).and_return(filtered)
|
|
1586
|
+
|
|
1587
|
+
result = @partializer.extract_interface_functions(
|
|
1588
|
+
test: 'test_mod', partial: 'mod',
|
|
1589
|
+
definitions: defs, declarations: decls, config: make_config(mocks: pf)
|
|
1590
|
+
)
|
|
1591
|
+
expect(result).to eq(filtered)
|
|
1592
|
+
end
|
|
1593
|
+
|
|
1594
|
+
it "merges declaration-only functions into the PUBLIC candidate pool too" do
|
|
1595
|
+
defn = double('def_func', name: 'pub_def')
|
|
1596
|
+
decl = double('decl_func', name: 'pub_decl')
|
|
1597
|
+
defs = [defn]
|
|
1598
|
+
decls = [decl]
|
|
1599
|
+
filtered = [double('iface_func')]
|
|
1600
|
+
pf = make_pf(type: Partials::PUBLIC)
|
|
1601
|
+
|
|
1602
|
+
expect(@partializer_helper).to receive(:filter_and_transform_funcs)
|
|
1603
|
+
.with([defn, decl], Partials::PUBLIC, :interface).and_return(filtered)
|
|
1604
|
+
allow(@partializer_helper).to receive(:subtract_funcs)
|
|
1605
|
+
.with(funcs: filtered, names: []).and_return(filtered)
|
|
1606
|
+
|
|
1607
|
+
result = @partializer.extract_interface_functions(
|
|
1608
|
+
test: 'test_mod', partial: 'mod',
|
|
1609
|
+
definitions: defs, declarations: decls, config: make_config(mocks: pf)
|
|
1610
|
+
)
|
|
1611
|
+
expect(result).to eq(filtered)
|
|
1612
|
+
end
|
|
1613
|
+
|
|
1614
|
+
it "excludes a declaration already present as a definition with the same name (dedup)" do
|
|
1615
|
+
defn = double('def_func', name: 'shared')
|
|
1616
|
+
decl = double('decl_func', name: 'shared') # e.g. header prototype for the same function
|
|
1617
|
+
defs = [defn]
|
|
1618
|
+
decls = [decl]
|
|
1619
|
+
filtered = [double('iface_func')]
|
|
1620
|
+
pf = make_pf(type: Partials::DEDUCT)
|
|
1621
|
+
|
|
1622
|
+
expect(@partializer_helper).to receive(:filter_and_transform_funcs)
|
|
1623
|
+
.with([defn], Partials::DEDUCT, :interface).and_return(filtered)
|
|
1624
|
+
allow(@partializer_helper).to receive(:subtract_funcs)
|
|
1625
|
+
.with(funcs: filtered, names: []).and_return(filtered)
|
|
1626
|
+
|
|
1627
|
+
result = @partializer.extract_interface_functions(
|
|
1628
|
+
test: 'test_mod', partial: 'mod',
|
|
1629
|
+
definitions: defs, declarations: decls, config: make_config(mocks: pf)
|
|
1630
|
+
)
|
|
1631
|
+
expect(result).to eq(filtered)
|
|
1632
|
+
end
|
|
1633
|
+
|
|
1524
1634
|
it "fills list from additions only for ACCUMULATE type" do
|
|
1525
1635
|
defs = [double('def', name: 'named')]
|
|
1526
1636
|
decls = []
|
|
@@ -1548,8 +1658,10 @@ describe Partializer do
|
|
|
1548
1658
|
found = double('iface_func', name: 'decl_only')
|
|
1549
1659
|
pf = make_pf(type: Partials::ACCUMULATE, additions: ['decl_only'])
|
|
1550
1660
|
|
|
1661
|
+
# candidates = definitions + declarations (ACCUMULATE ignores this list regardless --
|
|
1662
|
+
# it always starts empty -- but it's still built before the type check discards it).
|
|
1551
1663
|
allow(@partializer_helper).to receive(:filter_and_transform_funcs)
|
|
1552
|
-
.with(
|
|
1664
|
+
.with(decls, Partials::ACCUMULATE, :interface).and_return([])
|
|
1553
1665
|
expect(@partializer_helper).to receive(:find_and_transform_func)
|
|
1554
1666
|
.with(name: 'decl_only', primary_funcs: defs, secondary_funcs: decls, output_type: :interface)
|
|
1555
1667
|
.and_return(found)
|
|
@@ -166,6 +166,17 @@ describe PartializerUtils do
|
|
|
166
166
|
expect(result.signature).to eq(signature)
|
|
167
167
|
expect(result).not_to respond_to(:code_block)
|
|
168
168
|
end
|
|
169
|
+
|
|
170
|
+
it "strips a trailing semicolon from a declaration-sourced signature" do
|
|
171
|
+
# CFunctionDeclaration#signature_stripped always carries its own trailing
|
|
172
|
+
# semicolon (it's a bare prototype); CFunctionDefinition#signature_stripped never
|
|
173
|
+
# does. Callers render "#{signature};" uniformly, so this must not double up.
|
|
174
|
+
signature = 'void testFunc(int x);'
|
|
175
|
+
|
|
176
|
+
result = @utils.transform_function(mock_func, signature, :interface)
|
|
177
|
+
|
|
178
|
+
expect(result.signature).to eq('void testFunc(int x)')
|
|
179
|
+
end
|
|
169
180
|
end
|
|
170
181
|
|
|
171
182
|
context "when output_type is invalid" do
|
|
@@ -19,16 +19,20 @@ RSpec.describe PreprocessinatorIncludesHandler do
|
|
|
19
19
|
let(:real_parsing_parcels) { ParsingParcels.new }
|
|
20
20
|
|
|
21
21
|
before :each do
|
|
22
|
-
@configurator
|
|
23
|
-
@include_factory
|
|
24
|
-
@file_wrapper
|
|
25
|
-
@
|
|
26
|
-
@
|
|
27
|
-
@
|
|
22
|
+
@configurator = double('configurator')
|
|
23
|
+
@include_factory = double('include_factory')
|
|
24
|
+
@file_wrapper = double('file_wrapper')
|
|
25
|
+
@file_path_utils = double('file_path_utils')
|
|
26
|
+
@tool_executor = double('tool_executor')
|
|
27
|
+
@yaml_wrapper = double('yaml_wrapper')
|
|
28
|
+
@loginator = double('loginator')
|
|
29
|
+
@reportinator = double('reportinator')
|
|
28
30
|
@preprocessinator_line_marker_includes_extractor =
|
|
29
31
|
double('preprocessinator_line_marker_includes_extractor')
|
|
30
32
|
|
|
31
33
|
allow(@loginator).to receive(:log)
|
|
34
|
+
allow(@loginator).to receive(:lazy)
|
|
35
|
+
allow(@loginator).to receive(:log_list)
|
|
32
36
|
allow(@reportinator).to receive(:generate_module_progress).and_return('')
|
|
33
37
|
|
|
34
38
|
# Include factory helpers: return typed Include objects based on the path
|
|
@@ -50,8 +54,9 @@ RSpec.describe PreprocessinatorIncludesHandler do
|
|
|
50
54
|
include_factory: @include_factory,
|
|
51
55
|
preprocessinator_line_marker_includes_extractor:
|
|
52
56
|
@preprocessinator_line_marker_includes_extractor,
|
|
53
|
-
tool_executor:
|
|
57
|
+
tool_executor: @tool_executor,
|
|
54
58
|
file_wrapper: @file_wrapper,
|
|
59
|
+
file_path_utils: @file_path_utils,
|
|
55
60
|
yaml_wrapper: @yaml_wrapper,
|
|
56
61
|
parsing_parcels: real_parsing_parcels,
|
|
57
62
|
loginator: @loginator,
|
|
@@ -66,6 +71,90 @@ RSpec.describe PreprocessinatorIncludesHandler do
|
|
|
66
71
|
end
|
|
67
72
|
|
|
68
73
|
|
|
74
|
+
# ===========================================================================
|
|
75
|
+
describe '#extract_bare_includes' do
|
|
76
|
+
# ===========================================================================
|
|
77
|
+
# Extraction stages an isolated, sibling-free copy of the file being scanned before running
|
|
78
|
+
# GCC's bare-includes preprocessor pass, so that GCC's own directory-relative #include
|
|
79
|
+
# resolution has no real sibling header available to find and recurse into.
|
|
80
|
+
|
|
81
|
+
let(:test_name) { 'test_other' }
|
|
82
|
+
let(:filepath) { '/project/test/test_other.c' }
|
|
83
|
+
let(:isolation_parent) { '/project/build/test/preprocess/files/test_other' }
|
|
84
|
+
let(:isolation_dir) { "#{isolation_parent}/tmp1234" }
|
|
85
|
+
let(:isolated_filepath) { "#{isolation_dir}/test_other.c" }
|
|
86
|
+
let(:make_rules) do
|
|
87
|
+
"test_other.o: #{isolated_filepath} unity.h mock_foo_func.h other.h\n\n" \
|
|
88
|
+
"unity.h:\n\nmock_foo_func.h:\n\nother.h:\n"
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
before :each do
|
|
92
|
+
allow(@file_path_utils).to receive(:form_test_preprocess_files_path)
|
|
93
|
+
.with(test_name).and_return(isolation_parent)
|
|
94
|
+
allow(@file_wrapper).to receive(:mkdir_tmp)
|
|
95
|
+
.with(nil, isolation_parent).and_return(isolation_dir)
|
|
96
|
+
allow(@file_wrapper).to receive(:cp).with(filepath, isolated_filepath)
|
|
97
|
+
allow(@file_wrapper).to receive(:rm_rf).with(isolation_dir)
|
|
98
|
+
|
|
99
|
+
allow(@configurator).to receive(:tools_test_bare_includes_preprocessor).and_return(:bare_tool)
|
|
100
|
+
|
|
101
|
+
allow(@tool_executor).to receive(:build_command_line) do |tool, extra_args, fp, defs, flgs, paths|
|
|
102
|
+
{ options: {}, tool: tool, filepath: fp, defines: defs, flags: flgs, search_paths: paths }
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
allow(@tool_executor).to receive(:exec).and_return(output: make_rules)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def call_it
|
|
109
|
+
subject.extract_bare_includes(
|
|
110
|
+
test: test_name, filepath: filepath, search_paths: [], flags: [], defines: []
|
|
111
|
+
)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it 'stages a copy of the file into an isolated, sibling-free directory before extraction' do
|
|
115
|
+
call_it()
|
|
116
|
+
|
|
117
|
+
expect(@file_wrapper).to have_received(:mkdir_tmp).with(nil, isolation_parent)
|
|
118
|
+
expect(@file_wrapper).to have_received(:cp).with(filepath, isolated_filepath)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it 'builds the bare-includes command against the isolated staged path, not the original' do
|
|
122
|
+
call_it()
|
|
123
|
+
|
|
124
|
+
expect(@tool_executor).to have_received(:build_command_line)
|
|
125
|
+
.with(:bare_tool, [], isolated_filepath, [], [], [])
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it 'returns the includes parsed from the staged file make-rule output' do
|
|
129
|
+
result = call_it()
|
|
130
|
+
expect(result.map(&:filename)).to contain_exactly('unity.h', 'mock_foo_func.h', 'other.h')
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it 'cleans up the isolation directory after a successful run' do
|
|
134
|
+
call_it()
|
|
135
|
+
expect(@file_wrapper).to have_received(:rm_rf).with(isolation_dir)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it 'cleans up the isolation directory even when the tool executor raises' do
|
|
139
|
+
allow(@tool_executor).to receive(:exec).and_raise(StandardError.new('boom'))
|
|
140
|
+
|
|
141
|
+
expect { call_it() }.to raise_error(StandardError, 'boom')
|
|
142
|
+
|
|
143
|
+
expect(@file_wrapper).to have_received(:rm_rf).with(isolation_dir)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
it 'still cleans self-reference against the original filepath identity, not the staged copy' do
|
|
147
|
+
self_ref_rules =
|
|
148
|
+
"test_other.o: #{isolated_filepath} #{filepath} other.h\n\n#{filepath}:\n\nother.h:\n"
|
|
149
|
+
allow(@tool_executor).to receive(:exec).and_return(output: self_ref_rules)
|
|
150
|
+
|
|
151
|
+
result = call_it()
|
|
152
|
+
expect(result.map(&:filename)).to contain_exactly('other.h')
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
|
|
69
158
|
# ===========================================================================
|
|
70
159
|
describe '#extract_user_includes_from_text' do
|
|
71
160
|
# ===========================================================================
|
|
@@ -0,0 +1,72 @@
|
|
|
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 'spec_helper'
|
|
9
|
+
require 'ceedling/system_wrapper'
|
|
10
|
+
|
|
11
|
+
describe SystemWrapper do
|
|
12
|
+
before(:each) do
|
|
13
|
+
@sys_wrapper = described_class.new
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Portable, real subprocess invocations -- no shell scripting, no signals (those are
|
|
17
|
+
# covered where they're actually consumed, via doubles, in generator_helper_spec.rb).
|
|
18
|
+
# This spec exists to characterize shell_capture3's own contract: it is the sole place
|
|
19
|
+
# a subprocess's real Process::Status is captured, and the one thing downstream crash
|
|
20
|
+
# detection depends on entirely.
|
|
21
|
+
def ruby_command(code)
|
|
22
|
+
"#{RbConfig.ruby} -e #{code.inspect}"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
describe '#shell_capture3' do
|
|
26
|
+
context 'boom: false (the default, and how test-fixture execution always runs)' do
|
|
27
|
+
it 'forces exit_code to 0 even though the real subprocess exited nonzero' do
|
|
28
|
+
result = @sys_wrapper.shell_capture3( command: ruby_command('exit 3'), boom: false )
|
|
29
|
+
expect(result[:exit_code]).to eq(0)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'still relays the real, un-neutered Process::Status' do
|
|
33
|
+
result = @sys_wrapper.shell_capture3( command: ruby_command('exit 3'), boom: false )
|
|
34
|
+
expect(result[:status]).not_to be_nil
|
|
35
|
+
expect(result[:status].exitstatus).to eq(3)
|
|
36
|
+
expect(result[:status].success?).to be false
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it 'forces exit_code to 0 for a genuinely successful subprocess too' do
|
|
40
|
+
result = @sys_wrapper.shell_capture3( command: ruby_command('exit 0'), boom: false )
|
|
41
|
+
expect(result[:exit_code]).to eq(0)
|
|
42
|
+
expect(result[:status].success?).to be true
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context 'boom: true' do
|
|
47
|
+
it 'surfaces the real nonzero exit code' do
|
|
48
|
+
result = @sys_wrapper.shell_capture3( command: ruby_command('exit 3'), boom: true )
|
|
49
|
+
expect(result[:exit_code]).to eq(3)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'reports 0 for a genuinely successful subprocess' do
|
|
53
|
+
result = @sys_wrapper.shell_capture3( command: ruby_command('exit 0'), boom: true )
|
|
54
|
+
expect(result[:exit_code]).to eq(0)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'still relays the same real Process::Status as boom: false does' do
|
|
58
|
+
result = @sys_wrapper.shell_capture3( command: ruby_command('exit 3'), boom: true )
|
|
59
|
+
expect(result[:status].exitstatus).to eq(3)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'combines stdout and stderr into :output while keeping each stream separately available' do
|
|
64
|
+
result = @sys_wrapper.shell_capture3(
|
|
65
|
+
command: ruby_command('STDOUT.print "out"; STDERR.print "err"'), boom: false
|
|
66
|
+
)
|
|
67
|
+
expect(result[:stdout]).to eq('out')
|
|
68
|
+
expect(result[:stderr]).to eq('err')
|
|
69
|
+
expect(result[:output]).to eq('outerr')
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -391,8 +391,8 @@ describe TestContextExtractor do
|
|
|
391
391
|
@extractor.collect_context( filepath, input, TestContextExtractor::Context::TEST_RUNNER_DETAILS )
|
|
392
392
|
|
|
393
393
|
expected = [
|
|
394
|
-
{:line_number => 2, :test => 'test_this_function'},
|
|
395
|
-
{:line_number => 12, :test => 'test_another_function'},
|
|
394
|
+
{:line_number => 2, :test => 'test_this_function', :symbol => 'test_this_function'},
|
|
395
|
+
{:line_number => 12, :test => 'test_another_function', :symbol => 'test_another_function'},
|
|
396
396
|
]
|
|
397
397
|
|
|
398
398
|
expect( @extractor.lookup_test_cases( filepath ) ).to eq expected
|
|
@@ -411,7 +411,7 @@ describe TestContextExtractor do
|
|
|
411
411
|
@extractor.collect_context( filepath, input, TestContextExtractor::Context::TEST_RUNNER_DETAILS )
|
|
412
412
|
}.not_to raise_error
|
|
413
413
|
|
|
414
|
-
expected = [{ :line_number => 2, :test => 'test_this_function' }]
|
|
414
|
+
expected = [{ :line_number => 2, :test => 'test_this_function', :symbol => 'test_this_function' }]
|
|
415
415
|
expect( @extractor.lookup_test_cases( filepath ) ).to eq expected
|
|
416
416
|
end
|
|
417
417
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ceedling
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.1.
|
|
4
|
+
version: 1.1.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mark VanderVoord
|
|
@@ -10,7 +10,7 @@ authors:
|
|
|
10
10
|
autorequire:
|
|
11
11
|
bindir: bin
|
|
12
12
|
cert_chain: []
|
|
13
|
-
date: 2026-
|
|
13
|
+
date: 2026-08-14 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: rake
|
|
@@ -178,19 +178,31 @@ files:
|
|
|
178
178
|
- assets/example_file_with_statics.c
|
|
179
179
|
- assets/example_file_with_stdio.c
|
|
180
180
|
- assets/example_file_with_stdio.h
|
|
181
|
+
- assets/fake_crash_test_fixture.rb
|
|
182
|
+
- assets/partial_all_module.h
|
|
181
183
|
- assets/project.yml
|
|
184
|
+
- assets/run_with_ubsan.rb
|
|
185
|
+
- assets/same_dir_pairing_module.c
|
|
186
|
+
- assets/same_dir_pairing_module.h
|
|
187
|
+
- assets/same_dir_pairing_module_func.h
|
|
188
|
+
- assets/same_dir_pairing_other.c
|
|
189
|
+
- assets/same_dir_pairing_other.h
|
|
182
190
|
- assets/test_example_file.c
|
|
183
191
|
- assets/test_example_file_2.c
|
|
184
192
|
- assets/test_example_file_boom.c
|
|
185
193
|
- assets/test_example_file_crash_assert.c
|
|
186
194
|
- assets/test_example_file_crash_sigsegv.c
|
|
195
|
+
- assets/test_example_file_crash_sigsegv_with_param.c
|
|
187
196
|
- assets/test_example_file_source_include.c
|
|
188
197
|
- assets/test_example_file_success.c
|
|
198
|
+
- assets/test_example_file_ub_shift_overflow.c
|
|
189
199
|
- assets/test_example_file_unity_printf.c
|
|
190
200
|
- assets/test_example_file_verbose.c
|
|
191
201
|
- assets/test_example_file_with_mock.c
|
|
192
202
|
- assets/test_example_file_with_stdio.c
|
|
193
203
|
- assets/test_example_with_parameterized_tests.c
|
|
204
|
+
- assets/test_partial_all_module.c
|
|
205
|
+
- assets/test_same_dir_pairing.c
|
|
194
206
|
- assets/tests_with_defines/src/adc_hardware.c
|
|
195
207
|
- assets/tests_with_defines/src/adc_hardware.h
|
|
196
208
|
- assets/tests_with_defines/src/adc_hardware_configurator.c
|
|
@@ -281,6 +293,7 @@ files:
|
|
|
281
293
|
- docs/mkdocs/configuration/reference/index.md
|
|
282
294
|
- docs/mkdocs/configuration/reference/libraries.md
|
|
283
295
|
- docs/mkdocs/configuration/reference/mixins.md
|
|
296
|
+
- docs/mkdocs/configuration/reference/partials.md
|
|
284
297
|
- docs/mkdocs/configuration/reference/paths.md
|
|
285
298
|
- docs/mkdocs/configuration/reference/plugins.md
|
|
286
299
|
- docs/mkdocs/configuration/reference/project.md
|
|
@@ -807,6 +820,7 @@ files:
|
|
|
807
820
|
- site-local/configuration/reference/index.html
|
|
808
821
|
- site-local/configuration/reference/libraries.html
|
|
809
822
|
- site-local/configuration/reference/mixins.html
|
|
823
|
+
- site-local/configuration/reference/partials.html
|
|
810
824
|
- site-local/configuration/reference/paths.html
|
|
811
825
|
- site-local/configuration/reference/plugins.html
|
|
812
826
|
- site-local/configuration/reference/project.html
|
|
@@ -946,6 +960,7 @@ files:
|
|
|
946
960
|
- spec/units/c_extractor/c_extractor_integration_spec.rb
|
|
947
961
|
- spec/units/c_extractor/c_extractor_preprocessing_spec.rb
|
|
948
962
|
- spec/units/c_extractor/c_extractor_spec.rb
|
|
963
|
+
- spec/units/config/configurator_setup_spec.rb
|
|
949
964
|
- spec/units/config_matchinator_spec.rb
|
|
950
965
|
- spec/units/config_walkinator_spec.rb
|
|
951
966
|
- spec/units/configurator_builder_spec.rb
|
|
@@ -978,6 +993,7 @@ files:
|
|
|
978
993
|
- spec/units/reportinator_spec.rb
|
|
979
994
|
- spec/units/ruby_expandinator_spec.rb
|
|
980
995
|
- spec/units/system_utils_spec.rb
|
|
996
|
+
- spec/units/system_wrapper_spec.rb
|
|
981
997
|
- spec/units/test_build_executor_spec.rb
|
|
982
998
|
- spec/units/test_context_extractor_spec.rb
|
|
983
999
|
- spec/units/tool_executor_helper_spec.rb
|
|
@@ -1792,6 +1808,7 @@ test_files:
|
|
|
1792
1808
|
- spec/units/c_extractor/c_extractor_integration_spec.rb
|
|
1793
1809
|
- spec/units/c_extractor/c_extractor_preprocessing_spec.rb
|
|
1794
1810
|
- spec/units/c_extractor/c_extractor_spec.rb
|
|
1811
|
+
- spec/units/config/configurator_setup_spec.rb
|
|
1795
1812
|
- spec/units/config_matchinator_spec.rb
|
|
1796
1813
|
- spec/units/config_walkinator_spec.rb
|
|
1797
1814
|
- spec/units/configurator_builder_spec.rb
|
|
@@ -1824,6 +1841,7 @@ test_files:
|
|
|
1824
1841
|
- spec/units/reportinator_spec.rb
|
|
1825
1842
|
- spec/units/ruby_expandinator_spec.rb
|
|
1826
1843
|
- spec/units/system_utils_spec.rb
|
|
1844
|
+
- spec/units/system_wrapper_spec.rb
|
|
1827
1845
|
- spec/units/test_build_executor_spec.rb
|
|
1828
1846
|
- spec/units/test_context_extractor_spec.rb
|
|
1829
1847
|
- spec/units/tool_executor_helper_spec.rb
|