From 4ad1309a852d214543217d56333fc769b2b6b786 Mon Sep 17 00:00:00 2001 From: Mark VanderVoord Date: Mon, 24 Aug 2026 18:39:44 -0400 Subject: [PATCH] Refactor generate_test_runner to clearly support system include with others... and to smooth some rough edges. --- auto/generate_test_runner.rb | 48 +++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/auto/generate_test_runner.rb b/auto/generate_test_runner.rb index 62eaf95..eea2075 100755 --- a/auto/generate_test_runner.rb +++ b/auto/generate_test_runner.rb @@ -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 =~ /^ 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"