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
|
@@ -1865,6 +1865,8 @@
|
|
|
1865
1865
|
|
|
1866
1866
|
|
|
1867
1867
|
|
|
1868
|
+
|
|
1869
|
+
|
|
1868
1870
|
|
|
1869
1871
|
|
|
1870
1872
|
|
|
@@ -2012,6 +2014,34 @@
|
|
|
2012
2014
|
|
|
2013
2015
|
|
|
2014
2016
|
|
|
2017
|
+
<li class="md-nav__item">
|
|
2018
|
+
<a href="../configuration/reference/partials.html" class="md-nav__link">
|
|
2019
|
+
|
|
2020
|
+
|
|
2021
|
+
|
|
2022
|
+
<span class="md-ellipsis">
|
|
2023
|
+
|
|
2024
|
+
|
|
2025
|
+
Partials Settings
|
|
2026
|
+
|
|
2027
|
+
|
|
2028
|
+
|
|
2029
|
+
</span>
|
|
2030
|
+
|
|
2031
|
+
|
|
2032
|
+
|
|
2033
|
+
</a>
|
|
2034
|
+
</li>
|
|
2035
|
+
|
|
2036
|
+
|
|
2037
|
+
|
|
2038
|
+
|
|
2039
|
+
|
|
2040
|
+
|
|
2041
|
+
|
|
2042
|
+
|
|
2043
|
+
|
|
2044
|
+
|
|
2015
2045
|
<li class="md-nav__item">
|
|
2016
2046
|
<a href="../configuration/reference/release-build.html" class="md-nav__link">
|
|
2017
2047
|
|
|
@@ -1876,6 +1876,8 @@
|
|
|
1876
1876
|
|
|
1877
1877
|
|
|
1878
1878
|
|
|
1879
|
+
|
|
1880
|
+
|
|
1879
1881
|
|
|
1880
1882
|
|
|
1881
1883
|
|
|
@@ -2023,6 +2025,34 @@
|
|
|
2023
2025
|
|
|
2024
2026
|
|
|
2025
2027
|
|
|
2028
|
+
<li class="md-nav__item">
|
|
2029
|
+
<a href="../configuration/reference/partials.html" class="md-nav__link">
|
|
2030
|
+
|
|
2031
|
+
|
|
2032
|
+
|
|
2033
|
+
<span class="md-ellipsis">
|
|
2034
|
+
|
|
2035
|
+
|
|
2036
|
+
Partials Settings
|
|
2037
|
+
|
|
2038
|
+
|
|
2039
|
+
|
|
2040
|
+
</span>
|
|
2041
|
+
|
|
2042
|
+
|
|
2043
|
+
|
|
2044
|
+
</a>
|
|
2045
|
+
</li>
|
|
2046
|
+
|
|
2047
|
+
|
|
2048
|
+
|
|
2049
|
+
|
|
2050
|
+
|
|
2051
|
+
|
|
2052
|
+
|
|
2053
|
+
|
|
2054
|
+
|
|
2055
|
+
|
|
2026
2056
|
<li class="md-nav__item">
|
|
2027
2057
|
<a href="../configuration/reference/release-build.html" class="md-nav__link">
|
|
2028
2058
|
|
|
@@ -185,6 +185,21 @@ def valgrind_available?
|
|
|
185
185
|
tool_available?('valgrind --version 2>&1')
|
|
186
186
|
end
|
|
187
187
|
|
|
188
|
+
# Real UBSan support is Linux-specific in practice for this test suite -- macOS's
|
|
189
|
+
# system `gcc` is really Clang under a compatibility shim with different sanitizer
|
|
190
|
+
# runtime behavior, and MinGW gcc on Windows doesn't ship the sanitizer runtime at
|
|
191
|
+
# all. Restricting to Linux avoids flaky, platform-dependent compiler probing.
|
|
192
|
+
def ubsan_available?
|
|
193
|
+
return false unless RUBY_PLATFORM.downcase.include?('linux')
|
|
194
|
+
|
|
195
|
+
Dir.mktmpdir do |dir|
|
|
196
|
+
source = File.join(dir, 'ubsan_check.c')
|
|
197
|
+
binary = File.join(dir, 'ubsan_check')
|
|
198
|
+
File.write(source, "int main(void) { return 0; }\n")
|
|
199
|
+
tool_available?(%(gcc -fsanitize=undefined -o "#{binary}" "#{source}" 2>&1))
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
188
203
|
RSpec.shared_context "requires gdb" do
|
|
189
204
|
before :all do
|
|
190
205
|
@gdb_available = gdb_available?
|
|
@@ -204,3 +219,13 @@ RSpec.shared_context "requires valgrind" do
|
|
|
204
219
|
skip "valgrind is not installed or not in PATH" unless @valgrind_available
|
|
205
220
|
end
|
|
206
221
|
end
|
|
222
|
+
|
|
223
|
+
RSpec.shared_context "requires gcc with UBSan" do
|
|
224
|
+
before :all do
|
|
225
|
+
@ubsan_available = ubsan_available?
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
before do
|
|
229
|
+
skip "gcc UBSan support not available (Linux + gcc -fsanitize=undefined required)" unless @ubsan_available
|
|
230
|
+
end
|
|
231
|
+
end
|
|
@@ -279,6 +279,21 @@ class SystemContext
|
|
|
279
279
|
sections << stderr.strip
|
|
280
280
|
end
|
|
281
281
|
|
|
282
|
+
# Loginator routes `Verbosity::DEBUG` messages (including the backtrace
|
|
283
|
+
# `log_debug_backtrace` emits for a caught exception) to stdout rather than
|
|
284
|
+
# stderr, and this method's stdout scan above only pulls lines containing
|
|
285
|
+
# the literal substrings 'ERROR'/'EXCEPTION' -- a bare backtrace line
|
|
286
|
+
# (file:line:in `method') contains neither, so without surfacing it here
|
|
287
|
+
# explicitly, the one piece of stdout most useful for diagnosing *why* a
|
|
288
|
+
# command failed would otherwise only ever reach the full raw-output log
|
|
289
|
+
# file, not this console-visible summary (what CI output actually shows).
|
|
290
|
+
label = 'Debug Backtrace ==>'
|
|
291
|
+
backtrace_block = extract_section(stdout, label)
|
|
292
|
+
unless backtrace_block.empty?
|
|
293
|
+
sections << ">> DEBUG BACKTRACE"
|
|
294
|
+
sections.concat(backtrace_block)
|
|
295
|
+
end
|
|
296
|
+
|
|
282
297
|
label = 'FAILED TEST SUMMARY'
|
|
283
298
|
failed_block = extract_section(stdout, label)
|
|
284
299
|
unless failed_block.empty?
|
|
@@ -62,6 +62,11 @@ ceedling_system_tests do
|
|
|
62
62
|
test_case :test_project_with_preprocessing_for_mocks
|
|
63
63
|
test_case :test_project_with_preprocessing_for_missing_mock
|
|
64
64
|
test_case :test_project_with_preprocessing_all
|
|
65
|
+
test_case :test_project_preprocessing_same_dir_mock_pairing
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
describe "Partials" do
|
|
69
|
+
test_case :test_project_partial_all_module_mocks_declaration_only_function
|
|
65
70
|
end
|
|
66
71
|
|
|
67
72
|
describe "Defines and configuration" do
|
|
@@ -91,6 +96,14 @@ ceedling_system_tests do
|
|
|
91
96
|
test_case :crash_none_writes_fail_results_file
|
|
92
97
|
test_case :crash_simple_sigsegv_all_test_cases
|
|
93
98
|
test_case :crash_simple_sigabrt_assert_failure
|
|
99
|
+
test_case :crash_simple_sigsegv_with_parameterized_test
|
|
100
|
+
test_case :crash_simple_diagnostic_retry_disagrees_with_main_fixture
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
describe "Crash handling with real UBSan" do
|
|
104
|
+
include_context "requires gcc with UBSan"
|
|
105
|
+
|
|
106
|
+
test_case :crash_simple_ubsan_diagnostic_retry_disagrees_with_main_fixture
|
|
94
107
|
end
|
|
95
108
|
|
|
96
109
|
describe "Backtrace with GDB" do
|
|
@@ -100,6 +113,7 @@ ceedling_system_tests do
|
|
|
100
113
|
test_case :crash_gdb_sigsegv_targets_test_case_filter
|
|
101
114
|
test_case :crash_gdb_sigsegv_excludes_test_case_filter
|
|
102
115
|
test_case :crash_gdb_sigabrt_assert_failure
|
|
116
|
+
test_case :crash_gdb_sigsegv_with_parameterized_test
|
|
103
117
|
end
|
|
104
118
|
|
|
105
119
|
describe "Test filtering" do
|
|
@@ -65,6 +65,11 @@ ceedling_system_tests do
|
|
|
65
65
|
test_case :test_project_with_preprocessing_for_mocks
|
|
66
66
|
test_case :test_project_with_preprocessing_for_missing_mock
|
|
67
67
|
test_case :test_project_with_preprocessing_all
|
|
68
|
+
test_case :test_project_preprocessing_same_dir_mock_pairing
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
describe "Partials" do
|
|
72
|
+
test_case :test_project_partial_all_module_mocks_declaration_only_function
|
|
68
73
|
end
|
|
69
74
|
|
|
70
75
|
describe "Defines and configuration" do
|
|
@@ -94,6 +99,14 @@ ceedling_system_tests do
|
|
|
94
99
|
test_case :crash_none_writes_fail_results_file
|
|
95
100
|
test_case :crash_simple_sigsegv_all_test_cases
|
|
96
101
|
test_case :crash_simple_sigabrt_assert_failure
|
|
102
|
+
test_case :crash_simple_sigsegv_with_parameterized_test
|
|
103
|
+
test_case :crash_simple_diagnostic_retry_disagrees_with_main_fixture
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
describe "Crash handling with real UBSan" do
|
|
107
|
+
include_context "requires gcc with UBSan"
|
|
108
|
+
|
|
109
|
+
test_case :crash_simple_ubsan_diagnostic_retry_disagrees_with_main_fixture
|
|
97
110
|
end
|
|
98
111
|
|
|
99
112
|
describe "Backtrace with GDB" do
|
|
@@ -103,6 +116,7 @@ ceedling_system_tests do
|
|
|
103
116
|
test_case :crash_gdb_sigsegv_targets_test_case_filter
|
|
104
117
|
test_case :crash_gdb_sigsegv_excludes_test_case_filter
|
|
105
118
|
test_case :crash_gdb_sigabrt_assert_failure
|
|
119
|
+
test_case :crash_gdb_sigsegv_with_parameterized_test
|
|
106
120
|
end
|
|
107
121
|
|
|
108
122
|
describe "Test filtering" do
|
|
@@ -170,6 +184,11 @@ ceedling_system_tests do
|
|
|
170
184
|
test_case :test_project_with_preprocessing_for_mocks
|
|
171
185
|
test_case :test_project_with_preprocessing_for_missing_mock
|
|
172
186
|
test_case :test_project_with_preprocessing_all
|
|
187
|
+
test_case :test_project_preprocessing_same_dir_mock_pairing
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
describe "Partials" do
|
|
191
|
+
test_case :test_project_partial_all_module_mocks_declaration_only_function
|
|
173
192
|
end
|
|
174
193
|
|
|
175
194
|
describe "Defines and configuration" do
|
|
@@ -131,8 +131,8 @@ ceedling_system_tests do
|
|
|
131
131
|
@c.merge_project_yml_for_test({ :test_build => { :preprocess_force_fallback => false } })
|
|
132
132
|
output = @c.ceedling_build_exec("test:all")
|
|
133
133
|
expect(@c.last_exit_status).to eq(0)
|
|
134
|
-
expect(output).to match(/TESTED:\s+
|
|
135
|
-
expect(output).to match(/PASSED:\s+
|
|
134
|
+
expect(output).to match(/TESTED:\s+67/)
|
|
135
|
+
expect(output).to match(/PASSED:\s+67/)
|
|
136
136
|
end
|
|
137
137
|
end
|
|
138
138
|
end
|
|
@@ -144,8 +144,8 @@ ceedling_system_tests do
|
|
|
144
144
|
@c.merge_project_yml_for_test({ :test_build => { :preprocess_force_fallback => true } })
|
|
145
145
|
output = @c.ceedling_build_exec("test:all")
|
|
146
146
|
expect(@c.last_exit_status).to eq(0)
|
|
147
|
-
expect(output).to match(/TESTED:\s+
|
|
148
|
-
expect(output).to match(/PASSED:\s+
|
|
147
|
+
expect(output).to match(/TESTED:\s+67/)
|
|
148
|
+
expect(output).to match(/PASSED:\s+67/)
|
|
149
149
|
end
|
|
150
150
|
end
|
|
151
151
|
end
|
|
@@ -46,8 +46,8 @@ ceedling_system_tests do
|
|
|
46
46
|
@c.with_context do
|
|
47
47
|
Dir.chdir "wondrous_forest" do
|
|
48
48
|
@output = @c.ceedling_build_exec("test:all")
|
|
49
|
-
expect(@output).to match(/TESTED:\s+
|
|
50
|
-
expect(@output).to match(/PASSED:\s+
|
|
49
|
+
expect(@output).to match(/TESTED:\s+67/)
|
|
50
|
+
expect(@output).to match(/PASSED:\s+67/)
|
|
51
51
|
expect(@output).to match(/FAILED:\s+0/)
|
|
52
52
|
end
|
|
53
53
|
end
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
# SPDX-License-Identifier: MIT
|
|
6
6
|
# =========================================================================
|
|
7
7
|
|
|
8
|
+
require 'rbconfig'
|
|
9
|
+
|
|
8
10
|
module CommonSystemTestCases
|
|
9
11
|
def can_report_version_no_git_commit_sha
|
|
10
12
|
@c.with_context do
|
|
@@ -437,6 +439,69 @@ module CommonSystemTestCases
|
|
|
437
439
|
end
|
|
438
440
|
end
|
|
439
441
|
|
|
442
|
+
# A module splits its function declarations (same_dir_pairing_module_func.h, mocked by
|
|
443
|
+
# this test) from its type declarations (same_dir_pairing_module.h, reached only
|
|
444
|
+
# transitively via same_dir_pairing_other.h, never included directly by the test). All
|
|
445
|
+
# of these files are colocated in the test's own directory, which is what exercises
|
|
446
|
+
# GCC's same-directory quoted #include resolution during bare-includes extraction.
|
|
447
|
+
# Auto source-pairing must not pull the real source implementing the type header's
|
|
448
|
+
# like-named stem into this build alongside its mock of the differently-named header.
|
|
449
|
+
def test_project_preprocessing_same_dir_mock_pairing
|
|
450
|
+
@c.with_context do
|
|
451
|
+
Dir.chdir @proj_name do
|
|
452
|
+
FileUtils.cp test_asset_path("same_dir_pairing_module.h"), 'test/'
|
|
453
|
+
FileUtils.cp test_asset_path("same_dir_pairing_module_func.h"), 'test/'
|
|
454
|
+
FileUtils.cp test_asset_path("same_dir_pairing_module.c"), 'test/'
|
|
455
|
+
FileUtils.cp test_asset_path("same_dir_pairing_other.h"), 'test/'
|
|
456
|
+
FileUtils.cp test_asset_path("same_dir_pairing_other.c"), 'test/'
|
|
457
|
+
FileUtils.cp test_asset_path("test_same_dir_pairing.c"), 'test/'
|
|
458
|
+
|
|
459
|
+
settings = {
|
|
460
|
+
:project => { :use_test_preprocessor => :all },
|
|
461
|
+
:paths => {
|
|
462
|
+
:source => ['src/**', 'test/**'],
|
|
463
|
+
:include => ['src/**', 'test/**']
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
@c.merge_project_yml_for_test(settings)
|
|
467
|
+
|
|
468
|
+
output = @c.ceedling_build_exec("test:same_dir_pairing")
|
|
469
|
+
expect(@c.last_exit_status).to eq(0) # Successful build and tests
|
|
470
|
+
expect(output).to match(/TESTED:\s+1/)
|
|
471
|
+
expect(output).to match(/PASSED:\s+1/)
|
|
472
|
+
expect(output).to match(/FAILED:\s+0/)
|
|
473
|
+
expect(output).not_to match(/multiple definition|duplicate symbol/)
|
|
474
|
+
end
|
|
475
|
+
end
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
# A module header with both a plain (non-inline) function prototype and a `static
|
|
479
|
+
# inline` function, with no paired .c source providing a body for the plain prototype
|
|
480
|
+
# (so it exists only as a bare declaration, never a definition). MOCK_PARTIAL_ALL_MODULE()
|
|
481
|
+
# must mock both functions, not just the one with a body.
|
|
482
|
+
def test_project_partial_all_module_mocks_declaration_only_function
|
|
483
|
+
@c.with_context do
|
|
484
|
+
Dir.chdir @proj_name do
|
|
485
|
+
FileUtils.cp test_asset_path("partial_all_module.h"), 'src/'
|
|
486
|
+
FileUtils.cp test_asset_path("test_partial_all_module.c"), 'test/'
|
|
487
|
+
|
|
488
|
+
settings = {
|
|
489
|
+
:project => {
|
|
490
|
+
:use_partials => true,
|
|
491
|
+
:use_test_preprocessor => :all
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
@c.merge_project_yml_for_test(settings)
|
|
495
|
+
|
|
496
|
+
output = @c.ceedling_build_exec("test:partial_all_module")
|
|
497
|
+
expect(@c.last_exit_status).to eq(0) # Successful build and tests
|
|
498
|
+
expect(output).to match(/TESTED:\s+1/)
|
|
499
|
+
expect(output).to match(/PASSED:\s+1/)
|
|
500
|
+
expect(output).to match(/FAILED:\s+0/)
|
|
501
|
+
end
|
|
502
|
+
end
|
|
503
|
+
end
|
|
504
|
+
|
|
440
505
|
def test_project_fail
|
|
441
506
|
@c.with_context do
|
|
442
507
|
Dir.chdir @proj_name do
|
|
@@ -892,6 +957,168 @@ module CommonSystemTestCases
|
|
|
892
957
|
end
|
|
893
958
|
end
|
|
894
959
|
|
|
960
|
+
# Regression test for issue #1185: a parameterized test (TEST_CASE) defined after a
|
|
961
|
+
# crashing test in the same file must still report its own real PASS results instead
|
|
962
|
+
# of being swept up as "crashed" alongside the actual crash. Uses :use_backtrace => :simple
|
|
963
|
+
# (Ceedling's default), which is the mode in which the bug was reported.
|
|
964
|
+
def crash_simple_sigsegv_with_parameterized_test
|
|
965
|
+
@c.with_context do
|
|
966
|
+
Dir.chdir @proj_name do
|
|
967
|
+
FileUtils.cp test_asset_path("example_file.h"), 'src/'
|
|
968
|
+
FileUtils.cp test_asset_path("example_file.c"), 'src/'
|
|
969
|
+
FileUtils.cp test_asset_path("test_example_file_crash_sigsegv_with_param.c"), 'test/'
|
|
970
|
+
|
|
971
|
+
@c.merge_project_yml_for_test({
|
|
972
|
+
:project => { :use_backtrace => :simple },
|
|
973
|
+
:unity => { :use_param_tests => true }
|
|
974
|
+
})
|
|
975
|
+
|
|
976
|
+
output = @c.ceedling_build_exec("test:all")
|
|
977
|
+
expect(@c.last_exit_status).to eq(1) # Test should fail because of crash
|
|
978
|
+
expect(output).to match(/Unit test failures/)
|
|
979
|
+
# 1 crashing test + 3 parameterized cases
|
|
980
|
+
expect(output).to match(/TESTED:\s+4/)
|
|
981
|
+
expect(output).to match(/PASSED:\s+3/)
|
|
982
|
+
expect(output).to match(/FAILED:\s+1/)
|
|
983
|
+
expect(output).to match(/IGNORED:\s+0/)
|
|
984
|
+
|
|
985
|
+
result_file = './build/test/results/test_example_file_crash_sigsegv_with_param.fail'
|
|
986
|
+
expect(File.exist?(result_file)).to be(true)
|
|
987
|
+
results = YamlWrapper.new.load(result_file)
|
|
988
|
+
|
|
989
|
+
# Only the truly crashing test is reported as a failure/crash
|
|
990
|
+
expect(results[:failures].map { |f| f[:test] }).to eq(['test_add_numbers_will_fail'])
|
|
991
|
+
expect(results[:failures].first[:message]).to match(/Test case crashed/)
|
|
992
|
+
|
|
993
|
+
# Each parameterized case reports its own real (passing) result, by name, not a crash
|
|
994
|
+
expect(results[:successes].map { |s| s[:test] }).to contain_exactly(
|
|
995
|
+
'test_difference_between_numbers_is_correct(5, 3, 2)',
|
|
996
|
+
'test_difference_between_numbers_is_correct(10, 4, 6)',
|
|
997
|
+
'test_difference_between_numbers_is_correct(0, 0, 0)'
|
|
998
|
+
)
|
|
999
|
+
end
|
|
1000
|
+
end
|
|
1001
|
+
end
|
|
1002
|
+
|
|
1003
|
+
# Same regression coverage as `crash_simple_sigsegv_with_parameterized_test`, but for
|
|
1004
|
+
# :use_backtrace => :gdb: confirms gdb-based isolation also correctly distinguishes the
|
|
1005
|
+
# crashing test from the unrelated parameterized test, and still attributes the crash to
|
|
1006
|
+
# the correct source line (exercising the gdb crash-frame symbol matching fix).
|
|
1007
|
+
def crash_gdb_sigsegv_with_parameterized_test
|
|
1008
|
+
@c.with_context do
|
|
1009
|
+
Dir.chdir @proj_name do
|
|
1010
|
+
FileUtils.cp test_asset_path("example_file.h"), 'src/'
|
|
1011
|
+
FileUtils.cp test_asset_path("example_file.c"), 'src/'
|
|
1012
|
+
FileUtils.cp test_asset_path("test_example_file_crash_sigsegv_with_param.c"), 'test/'
|
|
1013
|
+
|
|
1014
|
+
@c.merge_project_yml_for_test({
|
|
1015
|
+
:project => { :use_backtrace => :gdb },
|
|
1016
|
+
:unity => { :use_param_tests => true }
|
|
1017
|
+
})
|
|
1018
|
+
|
|
1019
|
+
output = @c.ceedling_build_exec("test:all")
|
|
1020
|
+
expect(@c.last_exit_status).to eq(1) # Test should fail because of crash
|
|
1021
|
+
expect(output).to match(/Unit test failures/)
|
|
1022
|
+
expect(output).to match(/TESTED:\s+4/)
|
|
1023
|
+
expect(output).to match(/PASSED:\s+3/)
|
|
1024
|
+
expect(output).to match(/FAILED:\s+1/)
|
|
1025
|
+
expect(output).to match(/IGNORED:\s+0/)
|
|
1026
|
+
|
|
1027
|
+
result_file = './build/test/results/test_example_file_crash_sigsegv_with_param.fail'
|
|
1028
|
+
expect(File.exist?(result_file)).to be(true)
|
|
1029
|
+
results = YamlWrapper.new.load(result_file)
|
|
1030
|
+
|
|
1031
|
+
# Only the truly crashing test is reported as a failure/crash
|
|
1032
|
+
expect(results[:failures].map { |f| f[:test] }).to eq(['test_add_numbers_will_fail'])
|
|
1033
|
+
expect(results[:failures].first[:message]).to match(/Test case crashed/)
|
|
1034
|
+
expect(results[:failures].first[:message]).to match(/SIGSEGV/i)
|
|
1035
|
+
|
|
1036
|
+
# Each parameterized case reports its own real (passing) result, by name, not a crash
|
|
1037
|
+
expect(results[:successes].map { |s| s[:test] }).to contain_exactly(
|
|
1038
|
+
'test_difference_between_numbers_is_correct(5, 3, 2)',
|
|
1039
|
+
'test_difference_between_numbers_is_correct(10, 4, 6)',
|
|
1040
|
+
'test_difference_between_numbers_is_correct(0, 0, 0)'
|
|
1041
|
+
)
|
|
1042
|
+
|
|
1043
|
+
log_path = './build/logs/test/test_example_file_crash_sigsegv_with_param/test_add_numbers_will_fail.gdb.log'
|
|
1044
|
+
expect(File.exist?(log_path)).to be(true)
|
|
1045
|
+
expect(File.read(log_path)).to match(/SIGSEGV|Segmentation fault/i)
|
|
1046
|
+
end
|
|
1047
|
+
end
|
|
1048
|
+
end
|
|
1049
|
+
|
|
1050
|
+
# Regression test for issue #1198: a custom :test_fixture tool (e.g. a wrapper
|
|
1051
|
+
# enabling a sanitizer's halt-on-error) can correctly detect a crash on the main run,
|
|
1052
|
+
# only for that crash to be silently overwritten by a :simple backtrace diagnostic
|
|
1053
|
+
# retry that runs through a *different*, independently-configured tool
|
|
1054
|
+
# (test_fixture_simple_backtrace) and behaves differently there -- legitimately
|
|
1055
|
+
# passing in that other environment. fake_crash_test_fixture.rb reproduces the
|
|
1056
|
+
# mismatch without needing a real sanitizer: it always exits nonzero without ever
|
|
1057
|
+
# running the real, bug-free test executable it's given, while the unmodified default
|
|
1058
|
+
# backtrace retry tool runs that same executable directly and passes.
|
|
1059
|
+
def crash_simple_diagnostic_retry_disagrees_with_main_fixture
|
|
1060
|
+
@c.with_context do
|
|
1061
|
+
Dir.chdir @proj_name do
|
|
1062
|
+
FileUtils.cp test_asset_path("example_file.h"), 'src/'
|
|
1063
|
+
FileUtils.cp test_asset_path("example_file.c"), 'src/'
|
|
1064
|
+
FileUtils.cp test_asset_path("test_example_file_success.c"), 'test/'
|
|
1065
|
+
FileUtils.cp test_asset_path("fake_crash_test_fixture.rb"), 'test/'
|
|
1066
|
+
|
|
1067
|
+
@c.merge_project_yml_for_test({
|
|
1068
|
+
:project => { :use_backtrace => :simple },
|
|
1069
|
+
:tools => {
|
|
1070
|
+
:test_fixture => {
|
|
1071
|
+
:executable => RbConfig.ruby,
|
|
1072
|
+
:arguments => ['test/fake_crash_test_fixture.rb']
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
})
|
|
1076
|
+
|
|
1077
|
+
output = @c.ceedling_build_exec("test:all")
|
|
1078
|
+
expect(@c.last_exit_status).not_to eq(0)
|
|
1079
|
+
expect(output).to match(/Unit test failures/)
|
|
1080
|
+
expect(output).not_to match(/PASSED:\s+1/)
|
|
1081
|
+
end
|
|
1082
|
+
end
|
|
1083
|
+
end
|
|
1084
|
+
|
|
1085
|
+
# Same regression coverage as crash_simple_diagnostic_retry_disagrees_with_main_fixture
|
|
1086
|
+
# above, but with a real UBSan-triggered crash (matching issue #1198's own
|
|
1087
|
+
# reproduction exactly) instead of the portable simulated fixture. UBSan doesn't
|
|
1088
|
+
# produce an OS-level crash signal the way a segfault does -- run_with_ubsan.rb's
|
|
1089
|
+
# halt_on_error setting is what turns the undefined behavior into a hard stop, and
|
|
1090
|
+
# only the main :test_fixture invocation goes through that wrapper. Requires a Linux
|
|
1091
|
+
# gcc toolchain with -fsanitize=undefined support -- see "requires gcc with UBSan".
|
|
1092
|
+
def crash_simple_ubsan_diagnostic_retry_disagrees_with_main_fixture
|
|
1093
|
+
@c.with_context do
|
|
1094
|
+
Dir.chdir @proj_name do
|
|
1095
|
+
FileUtils.cp test_asset_path("test_example_file_ub_shift_overflow.c"), 'test/'
|
|
1096
|
+
FileUtils.cp test_asset_path("run_with_ubsan.rb"), 'test/'
|
|
1097
|
+
|
|
1098
|
+
@c.merge_project_yml_for_test({
|
|
1099
|
+
:project => { :use_backtrace => :simple },
|
|
1100
|
+
:flags => {
|
|
1101
|
+
:test => {
|
|
1102
|
+
:compile => { '*' => ['-fsanitize=undefined'] },
|
|
1103
|
+
:link => { '*' => ['-fsanitize=undefined'] }
|
|
1104
|
+
}
|
|
1105
|
+
},
|
|
1106
|
+
:tools => {
|
|
1107
|
+
:test_fixture => {
|
|
1108
|
+
:executable => RbConfig.ruby,
|
|
1109
|
+
:arguments => ['test/run_with_ubsan.rb', '${1}']
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
})
|
|
1113
|
+
|
|
1114
|
+
output = @c.ceedling_build_exec("test:all")
|
|
1115
|
+
expect(@c.last_exit_status).not_to eq(0)
|
|
1116
|
+
expect(output).to match(/Unit test failures/)
|
|
1117
|
+
expect(output).not_to match(/PASSED:\s+1/)
|
|
1118
|
+
end
|
|
1119
|
+
end
|
|
1120
|
+
end
|
|
1121
|
+
|
|
895
1122
|
def project_with_test_file_directly_including_source_file
|
|
896
1123
|
@c.with_context do
|
|
897
1124
|
Dir.chdir @proj_name do
|
|
@@ -19,11 +19,10 @@ describe CExtractorDeclarations do
|
|
|
19
19
|
describe "#try_extract_variable" do
|
|
20
20
|
# Helper to create extractor and test variable extraction
|
|
21
21
|
let(:extract_variable) do
|
|
22
|
-
->(content
|
|
22
|
+
->(content) do
|
|
23
23
|
scanner = StringScanner.new(content)
|
|
24
24
|
declarations = CExtractorDeclarations.new({ c_extractor_code_text: CExtractorCodeText.new() })
|
|
25
25
|
declarations.setup()
|
|
26
|
-
declarations.max_line_length = max_line_length
|
|
27
26
|
success, variable = declarations.try_extract_variable(scanner)
|
|
28
27
|
return [success, variable, scanner.pos, scanner.rest]
|
|
29
28
|
end
|
|
@@ -194,11 +193,35 @@ describe CExtractorDeclarations do
|
|
|
194
193
|
success, variable, pos, rest = extract_variable.call(content)
|
|
195
194
|
|
|
196
195
|
expect(success).to be true
|
|
197
|
-
# Leading `const` is a decorator;
|
|
198
|
-
|
|
196
|
+
# Leading `const` (qualifying `int`) is a decorator; the second `const`
|
|
197
|
+
# (qualifying the pointer itself) is part of the declarator and stays put
|
|
198
|
+
check_single(variable, name: 'ptr', type: 'int* const', decorators: ['const'], text: 'int* const ptr;')
|
|
199
199
|
expect(pos).to eq(21)
|
|
200
200
|
expect(rest).to eq("")
|
|
201
201
|
end
|
|
202
|
+
|
|
203
|
+
it "extracts volatile pointer to volatile" do
|
|
204
|
+
content = "volatile int* volatile ptr;"
|
|
205
|
+
success, variable, pos, rest = extract_variable.call(content)
|
|
206
|
+
|
|
207
|
+
expect(success).to be true
|
|
208
|
+
# Same as const/const above: only the leading qualifier is a decorator
|
|
209
|
+
check_single(variable, name: 'ptr', type: 'int* volatile', decorators: ['volatile'], text: 'int* volatile ptr;')
|
|
210
|
+
expect(pos).to eq(27)
|
|
211
|
+
expect(rest).to eq("")
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
it "extracts static const pointer to const" do
|
|
215
|
+
content = "static const int* const ptr;"
|
|
216
|
+
success, variable, pos, rest = extract_variable.call(content)
|
|
217
|
+
|
|
218
|
+
expect(success).to be true
|
|
219
|
+
# `static` and the leading `const` are decorators; the trailing `const`
|
|
220
|
+
# on the pointer itself is retained in both `.type` and `.text`
|
|
221
|
+
check_single(variable, name: 'ptr', type: 'int* const', decorators: ['static', 'const'], text: 'int* const ptr;')
|
|
222
|
+
expect(pos).to eq(28)
|
|
223
|
+
expect(rest).to eq("")
|
|
224
|
+
end
|
|
202
225
|
end
|
|
203
226
|
|
|
204
227
|
context "array variable declarations" do
|
|
@@ -20,11 +20,10 @@ describe CExtractorFunctions do
|
|
|
20
20
|
describe "#extract_function_signature (private method testing)" do
|
|
21
21
|
# Helper to access private method
|
|
22
22
|
let(:extract_signature) do
|
|
23
|
-
->(content, type
|
|
23
|
+
->(content, type) do
|
|
24
24
|
scanner = StringScanner.new(content)
|
|
25
25
|
functions = CExtractorFunctions.new({ c_extractor_code_text: CExtractorCodeText.new() })
|
|
26
26
|
functions.setup()
|
|
27
|
-
functions.max_line_length = max_line_length
|
|
28
27
|
signature = functions.send( :extract_function_signature, scanner, type )
|
|
29
28
|
return [signature, scanner.pos, scanner.rest]
|
|
30
29
|
end
|
|
@@ -797,7 +796,6 @@ describe CExtractorFunctions do
|
|
|
797
796
|
->(signature) do
|
|
798
797
|
functions = CExtractorFunctions.new({ c_extractor_code_text: CExtractorCodeText.new() })
|
|
799
798
|
functions.setup()
|
|
800
|
-
functions.max_line_length = 1000
|
|
801
799
|
name = functions.send( :extract_function_name, signature )
|
|
802
800
|
return name
|
|
803
801
|
end
|
|
@@ -1485,7 +1483,6 @@ describe CExtractorFunctions do
|
|
|
1485
1483
|
scanner = StringScanner.new(content)
|
|
1486
1484
|
functions = CExtractorFunctions.new({ c_extractor_code_text: CExtractorCodeText.new() })
|
|
1487
1485
|
functions.setup()
|
|
1488
|
-
functions.max_line_length = 1000
|
|
1489
1486
|
success, func = functions.try_extract_function_definition( scanner, filepath )
|
|
1490
1487
|
return [success, func, scanner.pos, scanner.rest]
|
|
1491
1488
|
end
|
|
@@ -2036,7 +2033,6 @@ describe CExtractorFunctions do
|
|
|
2036
2033
|
scanner = StringScanner.new(content)
|
|
2037
2034
|
functions = CExtractorFunctions.new({ c_extractor_code_text: CExtractorCodeText.new() })
|
|
2038
2035
|
functions.setup()
|
|
2039
|
-
functions.max_line_length = 1000
|
|
2040
2036
|
|
|
2041
2037
|
success1, func1 = functions.try_extract_function_definition(scanner, filepath)
|
|
2042
2038
|
expect(success1).to be true
|
|
@@ -2067,7 +2063,6 @@ describe CExtractorFunctions do
|
|
|
2067
2063
|
code_text = CExtractorCodeText.new()
|
|
2068
2064
|
functions = CExtractorFunctions.new({ c_extractor_code_text: code_text })
|
|
2069
2065
|
functions.setup()
|
|
2070
|
-
functions.max_line_length = 1000
|
|
2071
2066
|
|
|
2072
2067
|
success1, func1 = functions.try_extract_function_definition(scanner, filepath)
|
|
2073
2068
|
expect(success1).to be true
|
|
@@ -2106,7 +2101,6 @@ describe CExtractorFunctions do
|
|
|
2106
2101
|
scanner = StringScanner.new(content)
|
|
2107
2102
|
functions = CExtractorFunctions.new({ c_extractor_code_text: CExtractorCodeText.new() })
|
|
2108
2103
|
functions.setup()
|
|
2109
|
-
functions.max_line_length = 1000
|
|
2110
2104
|
|
|
2111
2105
|
success1, func1 = functions.try_extract_function_definition(scanner, filepath)
|
|
2112
2106
|
expect(success1).to be true
|
|
@@ -2130,7 +2124,6 @@ describe CExtractorFunctions do
|
|
|
2130
2124
|
let(:functions) do
|
|
2131
2125
|
f = CExtractorFunctions.new({ c_extractor_code_text: CExtractorCodeText.new() })
|
|
2132
2126
|
f.setup()
|
|
2133
|
-
f.max_line_length = 1000
|
|
2134
2127
|
f
|
|
2135
2128
|
end
|
|
2136
2129
|
|
|
@@ -2364,7 +2357,6 @@ describe CExtractorFunctions do
|
|
|
2364
2357
|
let(:functions) do
|
|
2365
2358
|
f = CExtractorFunctions.new({ c_extractor_code_text: CExtractorCodeText.new() })
|
|
2366
2359
|
f.setup()
|
|
2367
|
-
f.max_line_length = 1000
|
|
2368
2360
|
f
|
|
2369
2361
|
end
|
|
2370
2362
|
|
|
@@ -2482,7 +2474,6 @@ describe CExtractorFunctions do
|
|
|
2482
2474
|
scanner = StringScanner.new(content)
|
|
2483
2475
|
functions = CExtractorFunctions.new({ c_extractor_code_text: CExtractorCodeText.new() })
|
|
2484
2476
|
functions.setup()
|
|
2485
|
-
functions.max_line_length = 1000
|
|
2486
2477
|
success, decl = functions.try_extract_function_declaration(scanner)
|
|
2487
2478
|
return [success, decl, scanner.pos, scanner.rest]
|
|
2488
2479
|
end
|
|
@@ -2711,7 +2702,6 @@ describe CExtractorFunctions do
|
|
|
2711
2702
|
scanner = StringScanner.new(content)
|
|
2712
2703
|
functions = CExtractorFunctions.new({ c_extractor_code_text: CExtractorCodeText.new() })
|
|
2713
2704
|
functions.setup()
|
|
2714
|
-
functions.max_line_length = 1000
|
|
2715
2705
|
success, func = functions.try_extract_function_definition( scanner, filepath )
|
|
2716
2706
|
return [success, func]
|
|
2717
2707
|
end
|