Refactor generate_test_runner to clearly support system include with others... and to smooth some rough edges.

This commit is contained in:
Mark VanderVoord
2026-08-24 18:39:44 -04:00
parent 8500dd29c8
commit 4ad1309a85
+26 -22
View File
@@ -71,24 +71,30 @@ class UnityTestRunnerGenerator
source = File.read(input_file)
source = source.force_encoding('ISO-8859-1').encode('utf-8', replace: nil)
tests = find_tests(source)
headers = find_includes(source)
testfile_includes = @options[:use_system_files] ? (headers[:local] + headers[:system]) : headers[:local]
used_mocks = find_mocks(testfile_includes)
testfile_includes = (testfile_includes - used_mocks)
testfile_includes.delete_if { |inc| inc =~ /(unity|cmock)/ }
includes = find_includes(source)
headers = includes[:headers]
used_mocks = find_mocks(headers)
headers = (headers - used_mocks)
headers.delete_if { |inc| inc =~ /(unity|cmock)/ }
find_setup_and_teardown(source)
# build runner file
generate(input_file, output_file, tests, used_mocks, testfile_includes)
generate(input_file, output_file, tests, used_mocks, headers)
# determine which files were used to return them
all_files_used = [input_file, output_file]
all_files_used += testfile_includes.map { |filename| "#{filename}.c" } unless testfile_includes.empty?
all_files_used += headers.reject { |filename| filename =~ /^</ }.map { |filename| "#{filename}.c" } unless headers.empty?
all_files_used += @options[:includes] unless @options[:includes].empty?
all_files_used += headers[:linkonly] unless headers[:linkonly].empty?
all_files_used += includes[:linkonly] unless includes[:linkonly].empty?
all_files_used.uniq
end
# Generate a test file for the given features:
# input_file - the name of the test file this is based on
# output_file - the name of the test runner file to generate
# tests - an array of all the tests which can be run from this test runner
# used_mocks - an array of all mock files which are used by this test runner
# testfile_includes - an array of all included headers, in order, where system headers still have their <> attached
def generate(input_file, output_file, tests, used_mocks, testfile_includes)
File.open(output_file, 'w') do |output|
create_header(output, used_mocks, testfile_includes)
@@ -110,7 +116,7 @@ class UnityTestRunnerGenerator
return unless @options[:header_file] && !@options[:header_file].empty?
File.open(@options[:header_file], 'w') do |output|
create_h_file(output, @options[:header_file], tests, testfile_includes, used_mocks)
create_h_file(output, @options[:header_file], tests, headers, used_mocks)
end
end
@@ -212,10 +218,14 @@ class UnityTestRunnerGenerator
source.gsub!(/\/\*.*?\*\//m, '') # remove block comments
source.gsub!(/\/\/.*$/, '') # remove line comments (all that remain)
# parse out includes
# parse out includes (NOTICE: system includes KEEP the angle-brackets in the string, to preserve this information)
headers = if @options[:use_system_files]
source.scan(/^\s*#include\s+(?:(<)|")\s*(.+\.#{@options[:include_extensions]})\s*(?:(>)|")/).map(&:join).flatten
else
source.scan(/^\s*#include\s+"\s*(.+\.#{@options[:include_extensions]})\s*"/).flatten
end
{
local: source.scan(/^\s*#include\s+"\s*(.+\.#{@options[:include_extensions]})\s*"/).flatten,
system: source.scan(/^\s*#include\s+<\s*(.+)\s*>/).flatten.map { |inc| "<#{inc}>" },
headers: headers,
linkonly: source.scan(/^TEST_SOURCE_FILE\(\s*"\s*(.+\.#{@options[:source_extensions]})\s*"/).flatten
}
end
@@ -252,7 +262,7 @@ class UnityTestRunnerGenerator
end
end
def create_header(output, mocks, testfile_includes = [])
def create_header(output, mocks, headers = [])
output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */')
output.puts("\n/*=======Automagically Detected Files To Include=====*/")
output.puts('extern "C" {') if @options[:externcincludes]
@@ -275,10 +285,7 @@ class UnityTestRunnerGenerator
if @options[:header_file] && !@options[:header_file].empty?
output.puts("#include \"#{File.basename(@options[:header_file])}\"")
else
@options[:includes].flatten.uniq.compact.each do |inc|
output.puts("#include #{inc.include?('<') ? inc : "\"#{inc}\""}")
end
testfile_includes.each do |inc|
[@options[:includes], headers].flatten.uniq.compact.each do |inc|
output.puts("#include #{inc.include?('<') ? inc : "\"#{inc}\""}")
end
end
@@ -593,17 +600,14 @@ class UnityTestRunnerGenerator
output.puts('}')
end
def create_h_file(output, filename, tests, testfile_includes, used_mocks)
def create_h_file(output, filename, tests, headers, used_mocks)
filename = File.basename(filename).gsub(/[-\/\\.,\s]/, '_').upcase
output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */')
output.puts("#ifndef _#{filename}")
output.puts("#define _#{filename}\n\n")
output.puts("#include \"#{@options[:framework]}.h\"")
output.puts('#include "cmock.h"') unless used_mocks.empty?
@options[:includes].flatten.uniq.compact.each do |inc|
output.puts("#include #{inc.include?('<') ? inc : "\"#{inc}\""}")
end
testfile_includes.each do |inc|
[@options[:includes], headers].flatten.uniq.compact.each do |inc|
output.puts("#include #{inc.include?('<') ? inc : "\"#{inc}\""}")
end
output.puts "\n"