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
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
|
|
8
8
|
require 'spec_helper'
|
|
9
9
|
require 'ceedling/generators/generator_test_results_backtrace'
|
|
10
|
+
require 'ceedling/generators/generator_helper'
|
|
10
11
|
require 'ceedling/constants'
|
|
12
|
+
require 'ceedling/exceptions'
|
|
11
13
|
|
|
12
14
|
# ── Representative gdb output constants ──────────────────────────────────────
|
|
13
15
|
|
|
@@ -65,6 +67,19 @@ GDB_NO_SIGNAL_OUTPUT = <<~GDB.freeze
|
|
|
65
67
|
Inferior 1 (process 12345) exited with code 0139.
|
|
66
68
|
GDB
|
|
67
69
|
|
|
70
|
+
# Parameterized test crash (issue #1185): the crashing frame names the generated
|
|
71
|
+
# wrapper function (`runner_args1_test_value_out_of_range_good`), not the human-facing
|
|
72
|
+
# test name (`test_value_out_of_range_good(101, 1)`) that Unity reports at runtime.
|
|
73
|
+
GDB_SIGSEGV_PARAM_OUTPUT = <<~GDB.freeze
|
|
74
|
+
[Thread debugging using libthread_db enabled]
|
|
75
|
+
|
|
76
|
+
Program received signal SIGSEGV, Segmentation fault.
|
|
77
|
+
0x00005618066ea1fb in runner_args1_test_value_out_of_range_good () at test/test_module_d.c:157
|
|
78
|
+
157 int invalid = 1 / 0;
|
|
79
|
+
#0 0x00005618066ea1fb in runner_args1_test_value_out_of_range_good () at test/test_module_d.c:157
|
|
80
|
+
#1 0x00005618066eb4de in run_test (func=0x5618066ea1e7 <runner_args1_test_value_out_of_range_good>, name=0x5618066eb2e0 "test_value_out_of_range_good(101, 1)", line_num=157) at build/test/runners/test_module_d_runner.c:76
|
|
81
|
+
GDB
|
|
82
|
+
|
|
68
83
|
# Windows SIGSEGV — Thread N prefix, space-padded source line, DLL frames
|
|
69
84
|
# Single-quoted heredoc: backslashes in Windows paths are literal, not escape sequences
|
|
70
85
|
GDB_WINDOWS_SIGSEGV_OUTPUT = <<~'GDB'.freeze
|
|
@@ -112,9 +127,9 @@ SIMPLE_ASSERT_CRASH_OUTPUT =
|
|
|
112
127
|
"test_lib.out: src/lib.c:5: asserting: Assertion `0' failed.\n" \
|
|
113
128
|
"Aborted (core dumped)\n"
|
|
114
129
|
|
|
115
|
-
SIMPLE_PASS_OUTPUT = "test_lib.c:3:test_empty:PASS\n"
|
|
116
|
-
SIMPLE_FAIL_OUTPUT = "test_lib.c:8:test_bad:FAIL: Expected 1 Was 2\n"
|
|
117
|
-
SIMPLE_IGNORE_OUTPUT = "test_lib.c:12:test_skip:IGNORE\n"
|
|
130
|
+
SIMPLE_PASS_OUTPUT = "test_lib.c:3:test_empty:PASS\n---------\n1 Tests 0 Failures 0 Ignored\nOK\n"
|
|
131
|
+
SIMPLE_FAIL_OUTPUT = "test_lib.c:8:test_bad:FAIL: Expected 1 Was 2\n---------\n1 Tests 1 Failures 0 Ignored\nFAIL\n"
|
|
132
|
+
SIMPLE_IGNORE_OUTPUT = "test_lib.c:12:test_skip:IGNORE\n---------\n1 Tests 0 Failures 1 Ignored\nOK\n"
|
|
118
133
|
|
|
119
134
|
|
|
120
135
|
describe GeneratorTestResultsBacktrace do
|
|
@@ -127,16 +142,28 @@ describe GeneratorTestResultsBacktrace do
|
|
|
127
142
|
@generator_test_results = instance_double('GeneratorTestResults')
|
|
128
143
|
@file_path_utils = instance_double('FilePathUtils')
|
|
129
144
|
@file_wrapper = instance_double('FileWrapper')
|
|
145
|
+
@loginator = double('loginator').as_null_object
|
|
146
|
+
# A real GeneratorHelper, not a double -- these tests exercise the actual crash
|
|
147
|
+
# detection logic a retry's status is checked against, not a stubbed stand-in for it.
|
|
148
|
+
@generator_helper = GeneratorHelper.new({ :loginator => @loginator })
|
|
130
149
|
|
|
131
150
|
@backtrace = described_class.new({
|
|
132
151
|
:configurator => @configurator,
|
|
133
152
|
:tool_executor => @tool_executor,
|
|
134
153
|
:generator_test_results => @generator_test_results,
|
|
154
|
+
:generator_helper => @generator_helper,
|
|
135
155
|
:file_path_utils => @file_path_utils,
|
|
136
|
-
:file_wrapper => @file_wrapper
|
|
156
|
+
:file_wrapper => @file_wrapper,
|
|
157
|
+
:loginator => @loginator
|
|
137
158
|
})
|
|
138
159
|
@backtrace.setup()
|
|
139
160
|
|
|
161
|
+
# A healthy retry sub-process status -- the common case for most stubs below. Crash
|
|
162
|
+
# scenarios that already resolve via a missing result-line match (the pre-existing
|
|
163
|
+
# "unresolved" path) don't depend on this value at all; it's included on every stub
|
|
164
|
+
# anyway so `crash_result[:status]` is never unexpectedly missing.
|
|
165
|
+
@ok_status = double('status', signaled?: false, success?: true, exitstatus: 0, termsig: nil)
|
|
166
|
+
|
|
140
167
|
# Standard stubs used by most tests
|
|
141
168
|
allow(@tool_executor).to receive(:build_command_line).and_return({ options: {} })
|
|
142
169
|
allow(@file_path_utils).to receive(:form_test_gdb_log) do |test, context:, name:|
|
|
@@ -153,52 +180,128 @@ describe GeneratorTestResultsBacktrace do
|
|
|
153
180
|
let(:filename) { 'test_lib.c' }
|
|
154
181
|
let(:executable) { 'build/test/out/test_lib/test_lib.out' }
|
|
155
182
|
let(:shell_result){ { exit_code: 1, output: '', time: 0.0 } }
|
|
156
|
-
let(:test_cases) { [{ test: 'test_asserting', line_number: 8 }] }
|
|
183
|
+
let(:test_cases) { [{ test: 'test_asserting', symbol: 'test_asserting', line_number: 8 }] }
|
|
157
184
|
|
|
158
185
|
before(:each) do
|
|
159
186
|
allow(@configurator).to receive(:project_build_tests_root).and_return('build/test')
|
|
160
187
|
allow(@configurator).to receive(:tools_test_backtrace_gdb).and_return({})
|
|
161
188
|
end
|
|
162
189
|
|
|
190
|
+
# Companion helper: a genuinely-crashing group paired alongside the group under
|
|
191
|
+
# test, matching realistic multi-test-case usage -- do_gdb only ever runs because
|
|
192
|
+
# the main run already crashed, so an isolated group with nothing but a clean match
|
|
193
|
+
# is indistinguishable from the #1198 bug pattern (every retry legitimately clean,
|
|
194
|
+
# contradicting the crash that triggered this method) and correctly falls back on
|
|
195
|
+
# its own, tested separately below.
|
|
196
|
+
let(:companion_case) { { test: 'test_crashes_elsewhere', symbol: 'test_crashes_elsewhere', line_number: 20 } }
|
|
197
|
+
|
|
163
198
|
it 'handles a PASS test case and does not write a log' do
|
|
164
|
-
allow(@tool_executor).to receive(:exec)
|
|
165
|
-
|
|
199
|
+
allow(@tool_executor).to receive(:exec).and_return(
|
|
200
|
+
{ output: GDB_NO_SIGNAL_OUTPUT, time: 0.1, exit_code: 1, stderr: '', status: @ok_status },
|
|
201
|
+
{ output: "test_lib.c:9:test_asserting:PASS\n---------\n1 Tests 0 Failures 0 Ignored\nOK\n",
|
|
202
|
+
time: 0.1, exit_code: 0, stderr: '', status: @ok_status }
|
|
203
|
+
)
|
|
166
204
|
|
|
167
|
-
expect(@file_wrapper).
|
|
205
|
+
expect(@file_wrapper).to receive(:write).once.with(%r{test_crashes_elsewhere}, anything, anything)
|
|
168
206
|
|
|
169
|
-
|
|
207
|
+
expected_output_lines = []
|
|
208
|
+
allow(@generator_test_results).to receive(:regenerate_test_executable_stdout) do |**kwargs|
|
|
209
|
+
expected_output_lines = kwargs[:output]
|
|
210
|
+
'regenerated'
|
|
211
|
+
end
|
|
170
212
|
|
|
171
|
-
|
|
213
|
+
@backtrace.do_gdb( filename, executable, shell_result, [companion_case] + test_cases, context: :test )
|
|
214
|
+
|
|
215
|
+
expect(expected_output_lines).to include('test_lib.c:9:test_asserting:PASS')
|
|
172
216
|
end
|
|
173
217
|
|
|
174
218
|
it 'handles an IGNORE test case and does not write a log' do
|
|
175
|
-
allow(@tool_executor).to receive(:exec)
|
|
176
|
-
|
|
219
|
+
allow(@tool_executor).to receive(:exec).and_return(
|
|
220
|
+
{ output: GDB_NO_SIGNAL_OUTPUT, time: 0.1, exit_code: 1, stderr: '', status: @ok_status },
|
|
221
|
+
{ output: "test_lib.c:9:test_asserting:IGNORE\n---------\n1 Tests 0 Failures 1 Ignored\nOK\n",
|
|
222
|
+
time: 0.1, exit_code: 0, stderr: '', status: @ok_status }
|
|
223
|
+
)
|
|
177
224
|
|
|
178
|
-
expect(@file_wrapper).
|
|
225
|
+
expect(@file_wrapper).to receive(:write).once.with(%r{test_crashes_elsewhere}, anything, anything)
|
|
179
226
|
|
|
180
|
-
|
|
227
|
+
expected_output_lines = []
|
|
228
|
+
allow(@generator_test_results).to receive(:regenerate_test_executable_stdout) do |**kwargs|
|
|
229
|
+
expected_output_lines = kwargs[:output]
|
|
230
|
+
'regenerated'
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
@backtrace.do_gdb( filename, executable, shell_result, [companion_case] + test_cases, context: :test )
|
|
181
234
|
|
|
182
|
-
expect(
|
|
235
|
+
expect(expected_output_lines).to include('test_lib.c:9:test_asserting:IGNORE')
|
|
183
236
|
end
|
|
184
237
|
|
|
185
238
|
it 'handles a FAIL test case and does not write a log' do
|
|
186
|
-
allow(@tool_executor).to receive(:exec)
|
|
187
|
-
|
|
239
|
+
allow(@tool_executor).to receive(:exec).and_return(
|
|
240
|
+
{ output: GDB_NO_SIGNAL_OUTPUT, time: 0.1, exit_code: 1, stderr: '', status: @ok_status },
|
|
241
|
+
{ output: "test_lib.c:9:test_asserting:FAIL: Expected 1 Was 2\n---------\n1 Tests 1 Failures 0 Ignored\nFAIL\n",
|
|
242
|
+
time: 0.1, exit_code: 1, stderr: '', status: @ok_status }
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
expect(@file_wrapper).to receive(:write).once.with(%r{test_crashes_elsewhere}, anything, anything)
|
|
246
|
+
|
|
247
|
+
expected_output_lines = []
|
|
248
|
+
allow(@generator_test_results).to receive(:regenerate_test_executable_stdout) do |**kwargs|
|
|
249
|
+
expected_output_lines = kwargs[:output]
|
|
250
|
+
'regenerated'
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
@backtrace.do_gdb( filename, executable, shell_result, [companion_case] + test_cases, context: :test )
|
|
254
|
+
|
|
255
|
+
expect(expected_output_lines).to include('test_lib.c:9:test_asserting:FAIL: Expected 1 Was 2')
|
|
256
|
+
end
|
|
188
257
|
|
|
189
|
-
|
|
258
|
+
it "does not trust a matched PASS line when the retry's own real status contradicts it" do
|
|
259
|
+
# Regression test for issue #1198: a diagnostic retry can print a clean Unity
|
|
260
|
+
# result line while its own real process outcome says otherwise.
|
|
261
|
+
bad_status = double('status', signaled?: false, success?: false, exitstatus: 1, termsig: nil)
|
|
262
|
+
|
|
263
|
+
allow(@tool_executor).to receive(:exec).and_return({
|
|
264
|
+
output: "test_lib.c:9:test_asserting:PASS\n---------\n1 Tests 0 Failures 0 Ignored\nOK\n",
|
|
265
|
+
time: 0.1, exit_code: 0, stderr: '', status: bad_status
|
|
266
|
+
})
|
|
267
|
+
|
|
268
|
+
expected_output_lines = []
|
|
269
|
+
allow(@generator_test_results).to receive(:regenerate_test_executable_stdout) do |**kwargs|
|
|
270
|
+
expected_output_lines = kwargs[:output]
|
|
271
|
+
'regenerated'
|
|
272
|
+
end
|
|
190
273
|
|
|
191
274
|
result = @backtrace.do_gdb( filename, executable, shell_result, test_cases, context: :test )
|
|
192
275
|
|
|
193
276
|
expect(result[:exit_code]).to eq(1)
|
|
277
|
+
expect(expected_output_lines.first).to include(':FAIL:')
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
it 'falls back to a whole-file crash failure when no retry ever reproduces the crash the main run detected' do
|
|
281
|
+
# Regression test for issue #1198: every retry can legitimately pass in its own,
|
|
282
|
+
# differently-configured environment even though the main run genuinely crashed.
|
|
283
|
+
# An all-clean diagnostic must not be allowed to overrule that.
|
|
284
|
+
allow(@tool_executor).to receive(:exec).and_return({
|
|
285
|
+
output: "test_lib.c:9:test_asserting:PASS\n---------\n1 Tests 0 Failures 0 Ignored\nOK\n",
|
|
286
|
+
time: 0.1, exit_code: 0, stderr: '', status: @ok_status
|
|
287
|
+
})
|
|
288
|
+
|
|
289
|
+
fallback_result = { output: 'crash-failure-output', exit_code: 1 }
|
|
290
|
+
expect(@generator_test_results).to receive(:create_crash_failure)
|
|
291
|
+
.with(filename, shell_result, test_cases)
|
|
292
|
+
.and_return(fallback_result)
|
|
293
|
+
|
|
294
|
+
result = @backtrace.do_gdb( filename, executable, shell_result, test_cases, context: :test )
|
|
295
|
+
|
|
296
|
+
expect(result).to eq(fallback_result)
|
|
194
297
|
end
|
|
195
298
|
|
|
196
299
|
it 'handles a SIGSEGV crash — writes log, includes signal label, backtick source line, and log path' do
|
|
197
|
-
test_cases_sigsegv = [{ test: 'testCrash', line_number: 37 }]
|
|
300
|
+
test_cases_sigsegv = [{ test: 'testCrash', symbol: 'testCrash', line_number: 37 }]
|
|
198
301
|
filename_sigsegv = 'TestUsartModel.c'
|
|
199
302
|
|
|
200
303
|
allow(@tool_executor).to receive(:exec)
|
|
201
|
-
.and_return({ output: GDB_SIGSEGV_OUTPUT, time: 0.5, exit_code: 139 })
|
|
304
|
+
.and_return({ output: GDB_SIGSEGV_OUTPUT, time: 0.5, exit_code: 139, stderr: '', status: @ok_status })
|
|
202
305
|
|
|
203
306
|
expected_output_lines = []
|
|
204
307
|
allow(@generator_test_results).to receive(:regenerate_test_executable_stdout) do |**kwargs|
|
|
@@ -219,11 +322,42 @@ describe GeneratorTestResultsBacktrace do
|
|
|
219
322
|
expect(crash_line).to include('(/build/logs/test/TestUsartModel/testCrash.gdb.log)')
|
|
220
323
|
end
|
|
221
324
|
|
|
222
|
-
it '
|
|
223
|
-
|
|
325
|
+
it 'attributes a crash in a parameterized test to its wrapper symbol, not its display name' do
|
|
326
|
+
test_cases_param = [{
|
|
327
|
+
test: 'test_value_out_of_range_good(101, 1)',
|
|
328
|
+
symbol: 'runner_args1_test_value_out_of_range_good',
|
|
329
|
+
line_number: 157
|
|
330
|
+
}]
|
|
331
|
+
filename_param = 'test_module_d.c'
|
|
332
|
+
|
|
333
|
+
allow(@tool_executor).to receive(:exec)
|
|
334
|
+
.and_return({ output: GDB_SIGSEGV_PARAM_OUTPUT, time: 0.5, exit_code: 139, stderr: '', status: @ok_status })
|
|
335
|
+
|
|
336
|
+
expected_output_lines = []
|
|
337
|
+
allow(@generator_test_results).to receive(:regenerate_test_executable_stdout) do |**kwargs|
|
|
338
|
+
expected_output_lines = kwargs[:output]
|
|
339
|
+
'regenerated'
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
expect(@file_wrapper).to receive(:write)
|
|
343
|
+
.with('/build/logs/test/test_module_d/test_value_out_of_range_good(101, 1).gdb.log', /=== test_value_out_of_range_good\(101, 1\) ===/, 'a')
|
|
344
|
+
|
|
345
|
+
@backtrace.do_gdb( filename_param, executable, shell_result, test_cases_param, context: :test )
|
|
346
|
+
|
|
347
|
+
crash_line = expected_output_lines.first
|
|
348
|
+
# The FAIL line reports the human-facing display name (with args)...
|
|
349
|
+
expect(crash_line).to start_with('test_module_d.c:157:test_value_out_of_range_good(101, 1):FAIL: Test case crashed')
|
|
350
|
+
# ...but the crash frame was still correctly located via the wrapper symbol.
|
|
351
|
+
expect(crash_line).to include('>> [SIGSEGV] Segmentation fault')
|
|
352
|
+
expect(crash_line).to include("#{NEWLINE_TOKEN}`int invalid = 1 / 0;`")
|
|
353
|
+
expect(crash_line).not_to include('failed to extract')
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
it 'handles a SIGABRT crash from assert() — shows assertion text, no source line' do
|
|
357
|
+
test_cases_assert = [{ test: 'test_asserting', symbol: 'test_asserting', line_number: 8 }]
|
|
224
358
|
|
|
225
359
|
allow(@tool_executor).to receive(:exec)
|
|
226
|
-
.and_return({ output: GDB_SIGABRT_ASSERT_OUTPUT, time: 0.3, exit_code: 134 })
|
|
360
|
+
.and_return({ output: GDB_SIGABRT_ASSERT_OUTPUT, time: 0.3, exit_code: 134, stderr: '', status: @ok_status })
|
|
227
361
|
|
|
228
362
|
expected_output_lines = []
|
|
229
363
|
allow(@generator_test_results).to receive(:regenerate_test_executable_stdout) do |**kwargs|
|
|
@@ -244,7 +378,7 @@ describe GeneratorTestResultsBacktrace do
|
|
|
244
378
|
|
|
245
379
|
it 'handles a crash with no identifiable signal — fallback message, log path without "log: " prefix' do
|
|
246
380
|
allow(@tool_executor).to receive(:exec)
|
|
247
|
-
.and_return({ output: GDB_NO_SIGNAL_OUTPUT, time: 0.1, exit_code: 1 })
|
|
381
|
+
.and_return({ output: GDB_NO_SIGNAL_OUTPUT, time: 0.1, exit_code: 1, stderr: '', status: @ok_status })
|
|
248
382
|
|
|
249
383
|
expected_output_lines = []
|
|
250
384
|
allow(@generator_test_results).to receive(:regenerate_test_executable_stdout) do |**kwargs|
|
|
@@ -273,42 +407,115 @@ describe GeneratorTestResultsBacktrace do
|
|
|
273
407
|
allow(@configurator).to receive(:tools_test_fixture_simple_backtrace).and_return({})
|
|
274
408
|
end
|
|
275
409
|
|
|
410
|
+
# Each of the three cases below is paired with a companion group that genuinely
|
|
411
|
+
# crashes -- a realistic multi-test-case file, where the group under test is only
|
|
412
|
+
# one of several. Without a companion, an isolated group with nothing but a clean
|
|
413
|
+
# match is indistinguishable from the #1198 bug pattern (every retry legitimately
|
|
414
|
+
# clean, contradicting the crash do_simple only ever runs because of) and correctly
|
|
415
|
+
# triggers the whole-file fallback tested below in its own right.
|
|
416
|
+
|
|
276
417
|
it 'handles a PASS test case' do
|
|
277
|
-
|
|
278
|
-
.and_return({ output: SIMPLE_PASS_OUTPUT, time: 0.05, exit_code: 0 })
|
|
418
|
+
test_cases_multi = [{ test: 'test_crashes_elsewhere', line_number: 20 }] + test_cases
|
|
279
419
|
|
|
280
|
-
|
|
420
|
+
allow(@tool_executor).to receive(:exec).and_return(
|
|
421
|
+
{ output: SIMPLE_ASSERT_CRASH_OUTPUT, time: 0.1, exit_code: 134, stderr: '', status: @ok_status },
|
|
422
|
+
{ output: SIMPLE_PASS_OUTPUT, time: 0.05, exit_code: 0, stderr: '', status: @ok_status }
|
|
423
|
+
)
|
|
281
424
|
|
|
282
|
-
|
|
425
|
+
expected_output_lines = []
|
|
426
|
+
allow(@generator_test_results).to receive(:regenerate_test_executable_stdout) do |**kwargs|
|
|
427
|
+
expected_output_lines = kwargs[:output]
|
|
428
|
+
'regenerated'
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
@backtrace.do_simple( filename, executable, shell_result, test_cases_multi, context: :test )
|
|
432
|
+
|
|
433
|
+
expect(expected_output_lines).to include('test_lib.c:3:test_empty:PASS')
|
|
283
434
|
end
|
|
284
435
|
|
|
285
436
|
it 'handles a FAIL test case with a message' do
|
|
286
|
-
test_cases_fail = [{ test: 'test_bad', line_number: 8 }]
|
|
437
|
+
test_cases_fail = [{ test: 'test_crashes_elsewhere', line_number: 20 }, { test: 'test_bad', line_number: 8 }]
|
|
287
438
|
|
|
288
|
-
allow(@tool_executor).to receive(:exec)
|
|
289
|
-
|
|
439
|
+
allow(@tool_executor).to receive(:exec).and_return(
|
|
440
|
+
{ output: SIMPLE_ASSERT_CRASH_OUTPUT, time: 0.1, exit_code: 134, stderr: '', status: @ok_status },
|
|
441
|
+
{ output: SIMPLE_FAIL_OUTPUT, time: 0.05, exit_code: 1, stderr: '', status: @ok_status }
|
|
442
|
+
)
|
|
290
443
|
|
|
291
|
-
|
|
444
|
+
expected_output_lines = []
|
|
445
|
+
allow(@generator_test_results).to receive(:regenerate_test_executable_stdout) do |**kwargs|
|
|
446
|
+
expected_output_lines = kwargs[:output]
|
|
447
|
+
'regenerated'
|
|
448
|
+
end
|
|
292
449
|
|
|
293
|
-
|
|
450
|
+
@backtrace.do_simple( filename, executable, shell_result, test_cases_fail, context: :test )
|
|
451
|
+
|
|
452
|
+
expect(expected_output_lines).to include('test_lib.c:8:test_bad:FAIL: Expected 1 Was 2')
|
|
294
453
|
end
|
|
295
454
|
|
|
296
455
|
it 'handles an IGNORE test case' do
|
|
297
|
-
test_cases_ignore = [{ test: 'test_skip', line_number: 12 }]
|
|
456
|
+
test_cases_ignore = [{ test: 'test_crashes_elsewhere', line_number: 20 }, { test: 'test_skip', line_number: 12 }]
|
|
457
|
+
|
|
458
|
+
allow(@tool_executor).to receive(:exec).and_return(
|
|
459
|
+
{ output: SIMPLE_ASSERT_CRASH_OUTPUT, time: 0.1, exit_code: 134, stderr: '', status: @ok_status },
|
|
460
|
+
{ output: SIMPLE_IGNORE_OUTPUT, time: 0.02, exit_code: 0, stderr: '', status: @ok_status }
|
|
461
|
+
)
|
|
462
|
+
|
|
463
|
+
expected_output_lines = []
|
|
464
|
+
allow(@generator_test_results).to receive(:regenerate_test_executable_stdout) do |**kwargs|
|
|
465
|
+
expected_output_lines = kwargs[:output]
|
|
466
|
+
'regenerated'
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
@backtrace.do_simple( filename, executable, shell_result, test_cases_ignore, context: :test )
|
|
470
|
+
|
|
471
|
+
expect(expected_output_lines).to include('test_lib.c:12:test_skip:IGNORE')
|
|
472
|
+
end
|
|
473
|
+
|
|
474
|
+
it "does not trust a matched PASS line when the retry's own real status contradicts it" do
|
|
475
|
+
# Regression test for issue #1198: a diagnostic retry can print a clean Unity
|
|
476
|
+
# result line while its own real process outcome says otherwise.
|
|
477
|
+
bad_status = double('status', signaled?: false, success?: false, exitstatus: 1, termsig: nil)
|
|
298
478
|
|
|
299
479
|
allow(@tool_executor).to receive(:exec)
|
|
300
|
-
.and_return({ output:
|
|
480
|
+
.and_return({ output: SIMPLE_PASS_OUTPUT, time: 0.05, exit_code: 0, stderr: '', status: bad_status })
|
|
301
481
|
|
|
302
|
-
|
|
482
|
+
expected_output_lines = []
|
|
483
|
+
allow(@generator_test_results).to receive(:regenerate_test_executable_stdout) do |**kwargs|
|
|
484
|
+
expected_output_lines = kwargs[:output]
|
|
485
|
+
'regenerated'
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
result = @backtrace.do_simple( filename, executable, shell_result, test_cases, context: :test )
|
|
489
|
+
|
|
490
|
+
expect(result[:exit_code]).to eq(1)
|
|
491
|
+
expect(expected_output_lines.first).to include(':FAIL:')
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
it 'falls back to a whole-file crash failure when no retry ever reproduces the crash the main run detected' do
|
|
495
|
+
# Regression test for issue #1198: the exact reported scenario -- a custom
|
|
496
|
+
# :test_fixture wrapper enables sanitizer halt-on-error and the main run crashes,
|
|
497
|
+
# but the unrelated, independently-configured test_fixture_simple_backtrace tool
|
|
498
|
+
# runs the same executable directly, without the wrapper, and it legitimately
|
|
499
|
+
# passes. Every retry can be entirely clean and still must not overrule a crash
|
|
500
|
+
# Ceedling already established.
|
|
501
|
+
allow(@tool_executor).to receive(:exec)
|
|
502
|
+
.and_return({ output: SIMPLE_PASS_OUTPUT, time: 0.05, exit_code: 0, stderr: '', status: @ok_status })
|
|
503
|
+
|
|
504
|
+
fallback_result = { output: 'crash-failure-output', exit_code: 1 }
|
|
505
|
+
expect(@generator_test_results).to receive(:create_crash_failure)
|
|
506
|
+
.with(filename, shell_result, test_cases)
|
|
507
|
+
.and_return(fallback_result)
|
|
508
|
+
|
|
509
|
+
result = @backtrace.do_simple( filename, executable, shell_result, test_cases, context: :test )
|
|
303
510
|
|
|
304
|
-
expect(result
|
|
511
|
+
expect(result).to eq(fallback_result)
|
|
305
512
|
end
|
|
306
513
|
|
|
307
514
|
it 'handles a crash and includes extra executable output in the failure message' do
|
|
308
515
|
test_cases_crash = [{ test: 'test_asserting', line_number: 8 }]
|
|
309
516
|
|
|
310
517
|
allow(@tool_executor).to receive(:exec)
|
|
311
|
-
.and_return({ output: SIMPLE_ASSERT_CRASH_OUTPUT, time: 0.1, exit_code: 134 })
|
|
518
|
+
.and_return({ output: SIMPLE_ASSERT_CRASH_OUTPUT, time: 0.1, exit_code: 134, stderr: '', status: @ok_status })
|
|
312
519
|
|
|
313
520
|
expected_output_lines = []
|
|
314
521
|
allow(@generator_test_results).to receive(:regenerate_test_executable_stdout) do |**kwargs|
|
|
@@ -328,7 +535,7 @@ describe GeneratorTestResultsBacktrace do
|
|
|
328
535
|
test_cases_crash = [{ test: 'test_asserting', line_number: 8 }]
|
|
329
536
|
|
|
330
537
|
allow(@tool_executor).to receive(:exec)
|
|
331
|
-
.and_return({ output: "\n\n\n", time: 0.1, exit_code: 134 })
|
|
538
|
+
.and_return({ output: "\n\n\n", time: 0.1, exit_code: 134, stderr: '', status: @ok_status })
|
|
332
539
|
|
|
333
540
|
expected_output_lines = []
|
|
334
541
|
allow(@generator_test_results).to receive(:regenerate_test_executable_stdout) do |**kwargs|
|
|
@@ -460,7 +667,7 @@ describe GeneratorTestResultsBacktrace do
|
|
|
460
667
|
|
|
461
668
|
describe '#do_gdb with brief Windows assert (no crash frame)' do
|
|
462
669
|
let(:filename_assert) { 'test_example_file_crash_assert.c' }
|
|
463
|
-
let(:test_cases_assert) { [{ test: 'test_add_numbers_triggers_assert', line_number: 20 }] }
|
|
670
|
+
let(:test_cases_assert) { [{ test: 'test_add_numbers_triggers_assert', symbol: 'test_add_numbers_triggers_assert', line_number: 20 }] }
|
|
464
671
|
let(:executable) { 'build/test/out/test_example_file_crash_assert/test_example_file_crash_assert.out' }
|
|
465
672
|
let(:shell_result) { { exit_code: 1, output: '', time: 0.0 } }
|
|
466
673
|
|
|
@@ -471,7 +678,7 @@ describe GeneratorTestResultsBacktrace do
|
|
|
471
678
|
|
|
472
679
|
it 'uses assertion label and metadata line number when no crash location frame is found' do
|
|
473
680
|
allow(@tool_executor).to receive(:exec)
|
|
474
|
-
.and_return({ output: GDB_WINDOWS_ASSERT_BRIEF_OUTPUT, time: 0.1, exit_code: 3 })
|
|
681
|
+
.and_return({ output: GDB_WINDOWS_ASSERT_BRIEF_OUTPUT, time: 0.1, exit_code: 3, stderr: '', status: @ok_status })
|
|
475
682
|
|
|
476
683
|
expected_output_lines = []
|
|
477
684
|
allow(@generator_test_results).to receive(:regenerate_test_executable_stdout) do |**kwargs|
|
|
@@ -96,7 +96,7 @@ describe GeneratorTestRunner do
|
|
|
96
96
|
|
|
97
97
|
runner = build_runner( test_file_contents: source )
|
|
98
98
|
|
|
99
|
-
expect( runner.test_cases ).to eq( [ { test: 'test_ShouldDoSomething', line_number: 2 } ] )
|
|
99
|
+
expect( runner.test_cases ).to eq( [ { test: 'test_ShouldDoSomething', symbol: 'test_ShouldDoSomething', line_number: 2 } ] )
|
|
100
100
|
end
|
|
101
101
|
|
|
102
102
|
it 'remaps line numbers back to the original file when preprocessed content is given' do
|
|
@@ -114,7 +114,31 @@ describe GeneratorTestRunner do
|
|
|
114
114
|
|
|
115
115
|
runner = build_runner( test_file_contents: original, preprocessed_file_contents: preprocessed )
|
|
116
116
|
|
|
117
|
-
expect( runner.test_cases ).to eq( [ { test: 'test_ShouldDoSomething', line_number: 3 } ] )
|
|
117
|
+
expect( runner.test_cases ).to eq( [ { test: 'test_ShouldDoSomething', symbol: 'test_ShouldDoSomething', line_number: 3 } ] )
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it 'expands a parameterized test into one entry per TEST_CASE, carrying the runtime name and wrapper symbol' do
|
|
121
|
+
source = <<~SOURCE
|
|
122
|
+
void setUp(void) {}
|
|
123
|
+
void tearDown(void) {}
|
|
124
|
+
|
|
125
|
+
TEST_CASE(101, 1)
|
|
126
|
+
TEST_CASE(-1, 1)
|
|
127
|
+
void test_value_out_of_range_good(int a, int expected) {}
|
|
128
|
+
SOURCE
|
|
129
|
+
|
|
130
|
+
runner = described_class.new(
|
|
131
|
+
config: { use_param_tests: true },
|
|
132
|
+
test_file_contents: source,
|
|
133
|
+
parsing_parcels: @parsing_parcels
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
expect( runner.test_cases ).to eq(
|
|
137
|
+
[
|
|
138
|
+
{ test: 'test_value_out_of_range_good(101, 1)', symbol: 'runner_args1_test_value_out_of_range_good', line_number: 6 },
|
|
139
|
+
{ test: 'test_value_out_of_range_good(-1, 1)', symbol: 'runner_args2_test_value_out_of_range_good', line_number: 6 }
|
|
140
|
+
]
|
|
141
|
+
)
|
|
118
142
|
end
|
|
119
143
|
end
|
|
120
144
|
end
|
|
@@ -30,9 +30,9 @@ describe UserInclude do
|
|
|
30
30
|
expect(include_obj).to eq('header.h')
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
it "creates a UserInclude with
|
|
34
|
-
include_obj = UserInclude.new("path/to/header.h",
|
|
35
|
-
|
|
33
|
+
it "creates a UserInclude with an include_path override used in string expansion" do
|
|
34
|
+
include_obj = UserInclude.new("path/to/header.h", include_path: "path/to/header.h")
|
|
35
|
+
|
|
36
36
|
expect(include_obj.filename).to eq("header.h")
|
|
37
37
|
expect(include_obj.filepath).to eq("path/to/header.h")
|
|
38
38
|
expect("#{include_obj}").to eq('#include "path/to/header.h"')
|
|
@@ -110,14 +110,26 @@ describe SystemInclude do
|
|
|
110
110
|
expect(include_obj).to eq('header.h')
|
|
111
111
|
end
|
|
112
112
|
|
|
113
|
-
it "creates a SystemInclude with
|
|
114
|
-
include_obj = SystemInclude.new("path/to/header.h",
|
|
115
|
-
|
|
113
|
+
it "creates a SystemInclude with an include_path override used in string expansion" do
|
|
114
|
+
include_obj = SystemInclude.new("path/to/header.h", include_path: "path/to/header.h")
|
|
115
|
+
|
|
116
116
|
expect(include_obj.filename).to eq("header.h")
|
|
117
117
|
expect(include_obj.filepath).to eq("path/to/header.h")
|
|
118
118
|
expect("#{include_obj}").to eq('#include <path/to/header.h>')
|
|
119
119
|
expect(include_obj).to eq('path/to/header.h')
|
|
120
120
|
end
|
|
121
|
+
|
|
122
|
+
it "renders include_path instead of the bare filename, while filepath/filename keep the resolved identity" do
|
|
123
|
+
include_obj = SystemInclude.new(
|
|
124
|
+
"/usr/include/x86_64-linux-gnu/sys/stat.h", include_path: "sys/stat.h"
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
expect(include_obj.filepath).to eq("/usr/include/x86_64-linux-gnu/sys/stat.h")
|
|
128
|
+
expect(include_obj.filename).to eq("stat.h")
|
|
129
|
+
expect(include_obj.include_path).to eq("sys/stat.h")
|
|
130
|
+
expect("#{include_obj}").to eq('#include <sys/stat.h>')
|
|
131
|
+
expect(include_obj).to eq('sys/stat.h')
|
|
132
|
+
end
|
|
121
133
|
end
|
|
122
134
|
|
|
123
135
|
describe "Graceful handling of input" do
|
|
@@ -189,9 +201,9 @@ describe "Include equality" do
|
|
|
189
201
|
end
|
|
190
202
|
|
|
191
203
|
it "compares not equal to another UserInclude with same filename but different paths" do
|
|
192
|
-
include1 = UserInclude.new("path1/header.h",
|
|
193
|
-
include2 = UserInclude.new("path2/header.h",
|
|
194
|
-
|
|
204
|
+
include1 = UserInclude.new("path1/header.h", include_path: "path1/header.h")
|
|
205
|
+
include2 = UserInclude.new("path2/header.h", include_path: "path2/header.h")
|
|
206
|
+
|
|
195
207
|
expect(include1).not_to eq(include2)
|
|
196
208
|
expect(include2).not_to eq(include1)
|
|
197
209
|
end
|
|
@@ -266,9 +278,9 @@ describe "Include equality" do
|
|
|
266
278
|
end
|
|
267
279
|
|
|
268
280
|
it "compares not equal to another SystemInclude with same filename but different paths" do
|
|
269
|
-
include1 = SystemInclude.new("sys/stdio.h",
|
|
270
|
-
include2 = SystemInclude.new("other/stdio.h",
|
|
271
|
-
|
|
281
|
+
include1 = SystemInclude.new("sys/stdio.h", include_path: "sys/stdio.h")
|
|
282
|
+
include2 = SystemInclude.new("other/stdio.h", include_path: "other/stdio.h")
|
|
283
|
+
|
|
272
284
|
expect(include1).not_to eq(include2)
|
|
273
285
|
expect(include2).not_to eq(include1)
|
|
274
286
|
end
|
|
@@ -342,9 +354,9 @@ describe "Include equality" do
|
|
|
342
354
|
end
|
|
343
355
|
|
|
344
356
|
it "compares not equal to another MockInclude with same filename but different paths" do
|
|
345
|
-
include1 = MockInclude.new("mocks/mock_module.h",
|
|
346
|
-
include2 = MockInclude.new("test/mocks/mock_module.h",
|
|
347
|
-
|
|
357
|
+
include1 = MockInclude.new("mocks/mock_module.h", include_path: "mocks/mock_module.h")
|
|
358
|
+
include2 = MockInclude.new("test/mocks/mock_module.h", include_path: "test/mocks/mock_module.h")
|
|
359
|
+
|
|
348
360
|
expect(include1).not_to eq(include2)
|
|
349
361
|
expect(include2).not_to eq(include1)
|
|
350
362
|
end
|
|
@@ -547,9 +559,9 @@ describe "Include string coercion (to_str)" do
|
|
|
547
559
|
expect(include_obj.to_str).to eq("header.h")
|
|
548
560
|
end
|
|
549
561
|
|
|
550
|
-
it "returns the
|
|
551
|
-
include_obj = UserInclude.new("sub/dir/header.h",
|
|
552
|
-
# to_str always returns @filename (the basename) regardless of
|
|
562
|
+
it "returns the basename even when constructed with an include_path override" do
|
|
563
|
+
include_obj = UserInclude.new("sub/dir/header.h", include_path: "sub/dir/header.h")
|
|
564
|
+
# to_str always returns @filename (the basename) regardless of include_path
|
|
553
565
|
expect(include_obj.to_str).to eq("header.h")
|
|
554
566
|
end
|
|
555
567
|
end
|