提交 d3c18c26 编写于 作者: M Mark VanderVoord

support different encoding styles and force to something we can work with.

上级 aa36e555
......@@ -2,8 +2,9 @@
# Unity Project - A Test Framework for C
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
# [Released under MIT License. Please refer to license.txt for details]
# ==========================================
# ==========================================
$QUICK_RUBY_VERSION = RUBY_VERSION.split('.').inject(0){|vv,v| vv * 100 + v.to_i }
File.expand_path(File.join(File.dirname(__FILE__),'colour_prompt'))
class UnityTestRunnerGenerator
......@@ -17,7 +18,7 @@ class UnityTestRunnerGenerator
else raise "If you specify arguments, it should be a filename or a hash of options"
end
end
def self.grab_config(config_file)
options = { :includes => [], :plugins => [], :framework => :unity }
unless (config_file.nil? or config_file.empty?)
......@@ -33,27 +34,27 @@ class UnityTestRunnerGenerator
tests = []
testfile_includes = []
used_mocks = []
@options.merge!(options) unless options.nil?
module_name = File.basename(input_file)
#pull required data from source file
File.open(input_file, 'r') do |input|
tests = find_tests(input)
testfile_includes = find_includes(input)
used_mocks = find_mocks(testfile_includes)
end
source = File.read(input_file)
source = source.force_encoding("ISO-8859-1").encode("utf-8", replace: nil) if ($QUICK_RUBY_VERSION > 10900)
tests = find_tests(source)
testfile_includes = find_includes(source)
used_mocks = find_mocks(testfile_includes)
#build runner file
generate(input_file, output_file, tests, used_mocks, testfile_includes)
#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 += @options[:includes] unless @options[:includes].empty?
return all_files_used.uniq
end
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)
......@@ -64,15 +65,13 @@ class UnityTestRunnerGenerator
create_main(output, input_file, tests)
end
end
def find_tests(input_file)
def find_tests(source)
tests_raw = []
tests_args = []
tests_and_line_numbers = []
input_file.rewind
source_raw = input_file.read
source_scrubbed = source_raw.gsub(/\/\/.*$/, '') # remove line comments
source_scrubbed = source.gsub(/\/\/.*$/, '') # remove line comments
source_scrubbed = source_scrubbed.gsub(/\/\*.*?\*\//m, '') # remove block comments
lines = source_scrubbed.split(/(^\s*\#.*$) # Treat preprocessor directives as a logical line
| (;|\{|\}) /x) # Match ;, {, and } as end of lines
......@@ -94,7 +93,7 @@ class UnityTestRunnerGenerator
end
#determine line numbers and create tests to run
source_lines = source_raw.split("\n")
source_lines = source.split("\n")
source_index = 0;
tests_and_line_numbers.size.times do |i|
source_lines[source_index..-1].each_with_index do |line, index|
......@@ -105,36 +104,32 @@ class UnityTestRunnerGenerator
end
end
end
return tests_and_line_numbers
end
def find_includes(input_file)
input_file.rewind
#read in file
source = input_file.read
def find_includes(source)
#remove comments (block and line, in three steps to ensure correct precedence)
source.gsub!(/\/\/(?:.+\/\*|\*(?:$|[^\/])).*$/, '') # remove line comments that comment out the start of blocks
source.gsub!(/\/\*.*?\*\//m, '') # remove block comments
source.gsub!(/\/\*.*?\*\//m, '') # remove block comments
source.gsub!(/\/\/.*$/, '') # remove line comments (all that remain)
#parse out includes
includes = source.scan(/^\s*#include\s+\"\s*(.+)\.[hH]\s*\"/).flatten
brackets_includes = source.scan(/^\s*#include\s+<\s*(.+)\s*>/).flatten
brackets_includes.each { |inc| includes << '<' + inc +'>' }
return includes
includes = source.scan(/^\s*#include\s+\"\s*(.+)\.[hH]\s*\"/).flatten
brackets_includes = source.scan(/^\s*#include\s+<\s*(.+)\s*>/).flatten
brackets_includes.each { |inc| includes << '<' + inc +'>' }
return includes
end
def find_mocks(includes)
mock_headers = []
includes.each do |include_file|
mock_headers << File.basename(include_file) if (include_file =~ /^mock/i)
end
return mock_headers
return mock_headers
end
def create_header(output, mocks, testfile_includes)
output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */')
create_runtest(output, mocks)
......@@ -148,21 +143,21 @@ class UnityTestRunnerGenerator
output.puts('#include <stdio.h>')
output.puts('#include "CException.h"') if @options[:plugins].include?(:cexception)
testfile_includes.delete("unity").delete("cmock")
testrunner_includes = testfile_includes - mocks
testrunner_includes.each do |inc|
output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h','')}.h\""}")
testrunner_includes = testfile_includes - mocks
testrunner_includes.each do |inc|
output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h','')}.h\""}")
end
mocks.each do |mock|
output.puts("#include \"#{mock.gsub('.h','')}.h\"")
end
if @options[:enforce_strict_ordering]
output.puts('')
output.puts('int GlobalExpectCount;')
output.puts('int GlobalVerifyOrder;')
output.puts('char* GlobalOrderError;')
output.puts('')
output.puts('int GlobalExpectCount;')
output.puts('int GlobalVerifyOrder;')
output.puts('char* GlobalOrderError;')
end
end
def create_externs(output, tests, mocks)
output.puts("\n//=======External Functions This Runner Calls=====")
output.puts("extern void setUp(void);")
......@@ -172,7 +167,7 @@ class UnityTestRunnerGenerator
end
output.puts('')
end
def create_mock_management(output, mocks)
unless (mocks.empty?)
output.puts("\n//=======Mock Management=====")
......@@ -180,8 +175,8 @@ class UnityTestRunnerGenerator
output.puts("{")
if @options[:enforce_strict_ordering]
output.puts(" GlobalExpectCount = 0;")
output.puts(" GlobalVerifyOrder = 0;")
output.puts(" GlobalOrderError = NULL;")
output.puts(" GlobalVerifyOrder = 0;")
output.puts(" GlobalOrderError = NULL;")
end
mocks.each do |mock|
mock_clean = mock.gsub(/(?:-|\s+)/, "_")
......@@ -206,7 +201,7 @@ class UnityTestRunnerGenerator
output.puts("}\n")
end
end
def create_suite_setup_and_teardown(output)
unless (@options[:suite_setup].nil?)
output.puts("\n//=======Suite Setup=====")
......@@ -223,13 +218,13 @@ class UnityTestRunnerGenerator
output.puts("}")
end
end
def create_runtest(output, used_mocks)
cexception = @options[:plugins].include? :cexception
va_args1 = @options[:use_param_tests] ? ', ...' : ''
va_args2 = @options[:use_param_tests] ? '__VA_ARGS__' : ''
output.puts("\n//=======Test Runner Used To Run Each Test Below=====")
output.puts("#define RUN_TEST_NO_ARGS") if @options[:use_param_tests]
output.puts("#define RUN_TEST_NO_ARGS") if @options[:use_param_tests]
output.puts("#define RUN_TEST(TestFunc, TestLineNum#{va_args1}) \\")
output.puts("{ \\")
output.puts(" Unity.CurrentTestName = #TestFunc#{va_args2.empty? ? '' : " \"(\" ##{va_args2} \")\""}; \\")
......@@ -239,7 +234,7 @@ class UnityTestRunnerGenerator
output.puts(" { \\")
output.puts(" CEXCEPTION_T e; \\") if cexception
output.puts(" Try { \\") if cexception
output.puts(" CMock_Init(); \\") unless (used_mocks.empty?)
output.puts(" CMock_Init(); \\") unless (used_mocks.empty?)
output.puts(" setUp(); \\")
output.puts(" TestFunc(#{va_args2}); \\")
output.puts(" CMock_Verify(); \\") unless (used_mocks.empty?)
......@@ -253,7 +248,7 @@ class UnityTestRunnerGenerator
output.puts(" UnityConcludeTest(); \\")
output.puts("}\n")
end
def create_reset(output, used_mocks)
output.puts("\n//=======Test Reset Option=====")
output.puts("void resetTest()")
......@@ -261,11 +256,11 @@ class UnityTestRunnerGenerator
output.puts(" CMock_Verify();") unless (used_mocks.empty?)
output.puts(" CMock_Destroy();") unless (used_mocks.empty?)
output.puts(" tearDown();")
output.puts(" CMock_Init();") unless (used_mocks.empty?)
output.puts(" CMock_Init();") unless (used_mocks.empty?)
output.puts(" setUp();")
output.puts("}")
end
def create_main(output, filename, tests)
output.puts("\n\n//=======MAIN=====")
output.puts("int main(void)")
......@@ -294,18 +289,18 @@ end
if ($0 == __FILE__)
options = { :includes => [] }
yaml_file = nil
#parse out all the options first
ARGV.reject! do |arg|
ARGV.reject! do |arg|
case(arg)
when '-cexception'
when '-cexception'
options[:plugins] = [:cexception]; true
when /\.*\.yml/
options = UnityTestRunnerGenerator.grab_config(arg); true
else false
end
end
end
#make sure there is at least one parameter left (the input file)
if !ARGV[0]
puts ["usage: ruby #{__FILE__} (yaml) (options) input_test_file output_test_runner (includes)",
......@@ -313,12 +308,12 @@ if ($0 == __FILE__)
" -cexception - include cexception support"].join("\n")
exit 1
end
#create the default test runner name if not specified
ARGV[1] = ARGV[0].gsub(".c","_Runner.c") if (!ARGV[1])
#everything else is an include file
options[:includes] ||= (ARGV.slice(2..-1).flatten.compact) if (ARGV.size > 2)
UnityTestRunnerGenerator.new(options).run(ARGV[0], ARGV[1])
end
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册