Fix find_tests line-number search for test names at the start of a line

The line-number search in UnityTestRunnerGenerator#find_tests requires
whitespace before the test name. A definition written as

    void
    test_something(void)

puts the name at column 0, so the regex never matches the definition
line. The search then scans to the end of the file for every test,
O(tests x lines), and reports line number 0 for all of them.

Accept start-of-line as well as whitespace before the name, and compile
the regex once per test instead of once per line.
This commit is contained in:
joniumGit
2026-09-10 21:21:09 +03:00
parent 00124952ee
commit b5ebbd7474
2 changed files with 52 additions and 1 deletions
+3 -1
View File
@@ -200,8 +200,10 @@ class UnityTestRunnerGenerator
source_lines = source.split("\n")
source_index = 0
tests_and_line_numbers.size.times do |i|
# Compile once per test
name_regex = /(?:^|\s)#{tests_and_line_numbers[i][:test]}(?:\s|\()/
source_lines[source_index..].each_with_index do |line, index|
next unless line =~ /\s+#{tests_and_line_numbers[i][:test]}(?:\s|\()/
next unless line =~ name_regex
source_index += index
tests_and_line_numbers[i][:line_number] = source_index + 1
+49
View File
@@ -1334,6 +1334,55 @@ should 'GenerateSuiteTeardownWhenBeginAndEndAreOmitted' do
$generate_test_runner_tests += 1
end
should 'FindTestsLineNumbersWhenNameStartsTheLine' do
# The return type may sit on its own line, leaving the test name at column 0.
# The line search must still find the definition (and must not scan to the end
# of the file for every test, which is what made large files slow).
source = "#include \"unity.h\"\n" \
"\n" \
"void\n" \
"test_FirstAtColumnZero(void)\n" \
"{\n" \
"}\n" \
"\n" \
"void\n" \
"test_SecondAtColumnZero(void)\n" \
"{\n" \
"}\n"
found = UnityTestRunnerGenerator.new({}).find_tests(source).map { |t| [t[:test], t[:line_number]] }
expected = [['test_FirstAtColumnZero', 4], ['test_SecondAtColumnZero', 9]]
if found == expected
report 'Runner_FindTestsLineNumbersWhenNameStartsTheLine:PASS'
else
report " FAIL: expected #{expected.inspect}, got #{found.inspect}"
report 'Runner_FindTestsLineNumbersWhenNameStartsTheLine:FAIL'
$generate_test_runner_failures += 1
end
$generate_test_runner_tests += 1
end
should 'FindTestsLineNumbersWhenOneNameIsAPrefixOfAnother' do
# Issue #288: test_my_function must not be located inside
# test_my_function_invalid_behavior, which is defined first.
source = "void test_my_function_invalid_behavior(void)\n" \
"{\n" \
"}\n" \
"\n" \
"void test_my_function(void)\n" \
"{\n" \
"}\n"
found = UnityTestRunnerGenerator.new({}).find_tests(source).map { |t| [t[:test], t[:line_number]] }
expected = [['test_my_function_invalid_behavior', 1], ['test_my_function', 5]]
if found == expected
report 'Runner_FindTestsLineNumbersWhenOneNameIsAPrefixOfAnother:PASS'
else
report " FAIL: expected #{expected.inspect}, got #{found.inspect}"
report 'Runner_FindTestsLineNumbersWhenOneNameIsAPrefixOfAnother:FAIL'
$generate_test_runner_failures += 1
end
$generate_test_runner_tests += 1
end
RUNNER_TESTS.each do |testset|
basename = File.basename(testset[:testfile], C_EXTENSION)
testset_name = "Runner_#{basename}_#{testset[:name]}"