Squashed 'tests/unity/' changes from 1f52255..f96c055

f96c055 this is a minor release
2c7629a Documentation Updates
b8bfb01 Add support for AStyle in test makefile. It’s going to assume you have it installed.
e36d8b5 Merge pull request #276 from wolf99/pdf-to-markdown
1e43967 Add EACH_EQUAL changes
e2cc679 Add newlines after headings for best practice, trim trailing spaces & convert sneaky incorrectly coded chars
192d517 Remove PDFs
c48f6c9 Add Github Markdown versions of documents
2a5b24f Finished updating all Ruby scripts to match our coding standard. Woo!
3e0a712 Started to flesh out rubocop settings for this project. Added rakefile tasks to do so. Updated first script to make it compliant.
23f9c16 Another round of fixing things that the stylizer “corrected” for me.
3a6cca3 Fixed things that the stylizer “autocorrected” to wrong. ;)
3062c39 Starting to enforce our coding style. The first step is that we’ve pulled in Rubocop to check out Ruby syntax. There is likely a bit of customization to do yet AND there is definitely that backlog of todo’s that we just told it to ignore.
550d58b Attempt to fix remaining issues with casting
ee038c2 Ha! Forgot to add the correct comment style
d6b3508 Clean up some const issues, particularly when moving between single and double pointers
4ffafce Finish updating documentation to match
083564b Update docs to also understand the new Each Equal handlers
0dddf49 also update strings to support each element of an array.
a11a137 Added memory each equal assertion
d8d67a7 Added each_equal assertions for float and double
b7956ea Added more tests for all the numerical types when performing each_equal assertions
7fe3191 Added some tests to prove this works. Still work in progress
56eeacd prepare for comparing value to array by setting up explicit compare of array to array in ints
7b80885 Merge pull request #272 from FSMaxB/gcc43-wconversion
0781e74 Add our coding standard to documentation
c3658a0 Dropped support for pre-2.0 versions of Ruby (not even rubylang supports them anymore)
8a45ccf Use custom mock prefix when searching for mock header files. #263
689610b reorder includes in generated test runners
43c7511 stdlib.h explicitly called in fixtures when malloc used, now. (Fixes issue #268)
1c556d2 Fix -Wconversion with gcc-4.3
8723d50 Turn UNITY_OUTPUT_FLUSH off by default. Added a quick-define for the most common case: UNITY_USE_FLUSH_STDOUT. Clarified documentation. Fixes issue #269
c67a4ff - Add ability to detect TEST_FILE(“filename.c”) specifications in test files
41ee499 Tiny tweaks to make Unity fit in more smoothly with Ceedling

git-subtree-dir: tests/unity
git-subtree-split: f96c05532b3e00c9ca77e58fc07f9401cd46510d
This commit is contained in:
Max Bruckner committed 2017-04-27 02:54:33 +02:00
1 parent 2c45ad7816
commit ab77a80e9b
38 files changed
+4251 -1278

No files matched your search

+235 -233
View File
@@ -4,75 +4,70 @@
# [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'))
File.expand_path(File.join(File.dirname(__FILE__), 'colour_prompt'))
class UnityTestRunnerGenerator
def initialize(options = nil)
@options = UnityTestRunnerGenerator.default_options
case(options)
when NilClass then @options
when String then @options.merge!(UnityTestRunnerGenerator.grab_config(options))
when Hash then @options.merge!(options)
else raise "If you specify arguments, it should be a filename or a hash of options"
case options
when NilClass then @options
when String then @options.merge!(UnityTestRunnerGenerator.grab_config(options))
when Hash then @options.merge!(options)
else raise 'If you specify arguments, it should be a filename or a hash of options'
end
require "#{File.expand_path(File.dirname(__FILE__))}/type_sanitizer"
end
def self.default_options
{
:includes => [],
:defines => [],
:plugins => [],
:framework => :unity,
:test_prefix => "test|spec|should",
:setup_name => "setUp",
:teardown_name => "tearDown",
:main_name => "main", #set to :auto to automatically generate each time
:main_export_decl => "",
:cmdline_args => false,
:use_param_tests => false,
includes: [],
defines: [],
plugins: [],
framework: :unity,
test_prefix: 'test|spec|should',
mock_prefix: 'Mock',
setup_name: 'setUp',
teardown_name: 'tearDown',
main_name: 'main', # set to :auto to automatically generate each time
main_export_decl: '',
cmdline_args: false,
use_param_tests: false
}
end
def self.grab_config(config_file)
options = self.default_options
unless (config_file.nil? or config_file.empty?)
options = default_options
unless config_file.nil? || config_file.empty?
require 'yaml'
yaml_guts = YAML.load_file(config_file)
options.merge!(yaml_guts[:unity] || yaml_guts[:cmock])
raise "No :unity or :cmock section found in #{config_file}" unless options
end
return(options)
options
end
def run(input_file, output_file, options=nil)
tests = []
testfile_includes = []
used_mocks = []
def run(input_file, output_file, options = nil)
@options.merge!(options) unless options.nil?
module_name = File.basename(input_file)
#pull required data from source file
# pull required data from source file
source = File.read(input_file)
source = source.force_encoding("ISO-8859-1").encode("utf-8", :replace => nil) if ($QUICK_RUBY_VERSION > 10900)
source = source.force_encoding('ISO-8859-1').encode('utf-8', replace: nil)
tests = find_tests(source)
headers = find_includes(source)
testfile_includes = (headers[:local] + headers[:system])
used_mocks = find_mocks(testfile_includes)
testfile_includes = (testfile_includes - used_mocks)
testfile_includes.delete_if{|inc| inc =~ /(unity|cmock)/}
testfile_includes.delete_if { |inc| inc =~ /(unity|cmock)/ }
#build runner file
# build runner file
generate(input_file, output_file, tests, used_mocks, testfile_includes)
#determine which files were used to return them
# 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 += testfile_includes.map { |filename| filename + '.c' } unless testfile_includes.empty?
all_files_used += @options[:includes] unless @options[:includes].empty?
return all_files_used.uniq
all_files_used += headers[:linkonly] unless headers[:linkonly].empty?
all_files_used.uniq
end
def generate(input_file, output_file, tests, used_mocks, testfile_includes)
@@ -80,15 +75,16 @@ class UnityTestRunnerGenerator
create_header(output, used_mocks, testfile_includes)
create_externs(output, tests, used_mocks)
create_mock_management(output, used_mocks)
create_suite_setup_and_teardown(output)
create_suite_setup(output)
create_suite_teardown(output)
create_reset(output, used_mocks)
create_main(output, input_file, tests, used_mocks)
end
if (@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)
end
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)
end
end
@@ -96,103 +92,102 @@ class UnityTestRunnerGenerator
tests_and_line_numbers = []
source_scrubbed = source.clone
source_scrubbed = source_scrubbed.gsub(/"[^"\n]*"/, '') # remove things in strings
source_scrubbed = source_scrubbed.gsub(/"[^"\n]*"/, '') # remove things in strings
source_scrubbed = source_scrubbed.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
lines.each_with_index do |line, index|
#find tests
if line =~ /^((?:\s*TEST_CASE\s*\(.*?\)\s*)*)\s*void\s+((?:#{@options[:test_prefix]}).*)\s*\(\s*(.*)\s*\)/
arguments = $1
name = $2
call = $3
params = $4
args = nil
if (@options[:use_param_tests] and !arguments.empty?)
args = []
arguments.scan(/\s*TEST_CASE\s*\((.*)\)\s*$/) {|a| args << a[0]}
end
tests_and_line_numbers << { :test => name, :args => args, :call => call, :params => params, :line_number => 0 }
lines.each_with_index do |line, _index|
# find tests
next unless line =~ /^((?:\s*TEST_CASE\s*\(.*?\)\s*)*)\s*void\s+((?:#{@options[:test_prefix]}).*)\s*\(\s*(.*)\s*\)/
arguments = Regexp.last_match(1)
name = Regexp.last_match(2)
call = Regexp.last_match(3)
params = Regexp.last_match(4)
args = nil
if @options[:use_param_tests] && !arguments.empty?
args = []
arguments.scan(/\s*TEST_CASE\s*\((.*)\)\s*$/) { |a| args << a[0] }
end
tests_and_line_numbers << { test: name, args: args, call: call, params: params, line_number: 0 }
end
tests_and_line_numbers.uniq! {|v| v[:test] }
tests_and_line_numbers.uniq! { |v| v[:test] }
#determine line numbers and create tests to run
# determine line numbers and create tests to run
source_lines = source.split("\n")
source_index = 0;
source_index = 0
tests_and_line_numbers.size.times do |i|
source_lines[source_index..-1].each_with_index do |line, index|
if (line =~ /#{tests_and_line_numbers[i][:test]}/)
source_index += index
tests_and_line_numbers[i][:line_number] = source_index + 1
break
end
next unless line =~ /#{tests_and_line_numbers[i][:test]}/
source_index += index
tests_and_line_numbers[i][:line_number] = source_index + 1
break
end
end
return tests_and_line_numbers
tests_and_line_numbers
end
def find_includes(source)
#remove comments (block and line, in three steps to ensure correct precedence)
# 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!(/\/\/.*$/, '') # remove line comments (all that remain)
#parse out includes
# parse out includes
includes = {
:local => source.scan(/^\s*#include\s+\"\s*(.+)\.[hH]\s*\"/).flatten,
:system => source.scan(/^\s*#include\s+<\s*(.+)\s*>/).flatten.map { |inc| "<#{inc}>" }
local: source.scan(/^\s*#include\s+\"\s*(.+)\.[hH]\s*\"/).flatten,
system: source.scan(/^\s*#include\s+<\s*(.+)\s*>/).flatten.map { |inc| "<#{inc}>" },
linkonly: source.scan(/^TEST_FILE\(\s*\"\s*(.+)\.[cC]\w*\s*\"/).flatten
}
return includes
includes
end
def find_mocks(includes)
mock_headers = []
includes.each do |include_path|
include_file = File.basename(include_path)
mock_headers << include_path if (include_file =~ /^mock/i)
mock_headers << include_path if include_file =~ /^#{@options[:mock_prefix]}/i
end
return mock_headers
mock_headers
end
def create_header(output, mocks, testfile_includes=[])
def create_header(output, mocks, testfile_includes = [])
output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */')
create_runtest(output, mocks)
output.puts("\n/*=======Automagically Detected Files To Include=====*/")
output.puts("#include \"#{@options[:framework].to_s}.h\"")
output.puts('#include "cmock.h"') unless (mocks.empty?)
output.puts("#include \"#{@options[:framework]}.h\"")
output.puts('#include "cmock.h"') unless mocks.empty?
output.puts('#include <setjmp.h>')
output.puts('#include <stdio.h>')
output.puts('#include "CException.h"') if @options[:plugins].include?(:cexception)
if (@options[:defines] && !@options[:defines].empty?)
@options[:defines].each {|d| output.puts("#define #{d}")}
if @options[:defines] && !@options[:defines].empty?
@options[:defines].each { |d| output.puts("#define #{d}") }
end
if (@options[:header_file] && !@options[:header_file].empty?)
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.gsub('.h','')}.h\""}")
output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}")
end
testfile_includes.each do |inc|
output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h','')}.h\""}")
output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}")
end
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("#include \"#{mock.gsub('.h', '')}.h\"")
end
output.puts('#include "CException.h"') if @options[:plugins].include?(:cexception)
return unless @options[:enforce_strict_ordering]
output.puts('')
output.puts('int GlobalExpectCount;')
output.puts('int GlobalVerifyOrder;')
output.puts('char* GlobalOrderError;')
end
def create_externs(output, tests, mocks)
def create_externs(output, tests, _mocks)
output.puts("\n/*=======External Functions This Runner Calls=====*/")
output.puts("extern void #{@options[:setup_name]}(void);")
output.puts("extern void #{@options[:teardown_name]}(void);")
@@ -203,55 +198,60 @@ class UnityTestRunnerGenerator
end
def create_mock_management(output, mock_headers)
unless (mock_headers.empty?)
output.puts("\n/*=======Mock Management=====*/")
output.puts("static void CMock_Init(void)")
output.puts("{")
if @options[:enforce_strict_ordering]
output.puts(" GlobalExpectCount = 0;")
output.puts(" GlobalVerifyOrder = 0;")
output.puts(" GlobalOrderError = NULL;")
end
mocks = mock_headers.map {|mock| File.basename(mock)}
mocks.each do |mock|
mock_clean = TypeSanitizer.sanitize_c_identifier(mock)
output.puts(" #{mock_clean}_Init();")
end
output.puts("}\n")
return if mock_headers.empty?
output.puts("static void CMock_Verify(void)")
output.puts("{")
mocks.each do |mock|
mock_clean = TypeSanitizer.sanitize_c_identifier(mock)
output.puts(" #{mock_clean}_Verify();")
end
output.puts("}\n")
output.puts("\n/*=======Mock Management=====*/")
output.puts('static void CMock_Init(void)')
output.puts('{')
output.puts("static void CMock_Destroy(void)")
output.puts("{")
mocks.each do |mock|
mock_clean = TypeSanitizer.sanitize_c_identifier(mock)
output.puts(" #{mock_clean}_Destroy();")
end
output.puts("}\n")
if @options[:enforce_strict_ordering]
output.puts(' GlobalExpectCount = 0;')
output.puts(' GlobalVerifyOrder = 0;')
output.puts(' GlobalOrderError = NULL;')
end
mocks = mock_headers.map { |mock| File.basename(mock) }
mocks.each do |mock|
mock_clean = TypeSanitizer.sanitize_c_identifier(mock)
output.puts(" #{mock_clean}_Init();")
end
output.puts("}\n")
output.puts('static void CMock_Verify(void)')
output.puts('{')
mocks.each do |mock|
mock_clean = TypeSanitizer.sanitize_c_identifier(mock)
output.puts(" #{mock_clean}_Verify();")
end
output.puts("}\n")
output.puts('static void CMock_Destroy(void)')
output.puts('{')
mocks.each do |mock|
mock_clean = TypeSanitizer.sanitize_c_identifier(mock)
output.puts(" #{mock_clean}_Destroy();")
end
output.puts("}\n")
end
def create_suite_setup_and_teardown(output)
unless (@options[:suite_setup].nil?)
output.puts("\n/*=======Suite Setup=====*/")
output.puts("static void suite_setup(void)")
output.puts("{")
output.puts(@options[:suite_setup])
output.puts("}")
end
unless (@options[:suite_teardown].nil?)
output.puts("\n/*=======Suite Teardown=====*/")
output.puts("static int suite_teardown(int num_failures)")
output.puts("{")
output.puts(@options[:suite_teardown])
output.puts("}")
end
def create_suite_setup(output)
return if @options[:suite_setup].nil?
output.puts("\n/*=======Suite Setup=====*/")
output.puts('static void suite_setup(void)')
output.puts('{')
output.puts(@options[:suite_setup])
output.puts('}')
end
def create_suite_teardown(output)
return if @options[:suite_teardown].nil?
output.puts("\n/*=======Suite Teardown=====*/")
output.puts('static int suite_teardown(int num_failures)')
output.puts('{')
output.puts(@options[:suite_teardown])
output.puts('}')
end
def create_runtest(output, used_mocks)
@@ -259,124 +259,124 @@ class UnityTestRunnerGenerator
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('{ \\')
output.puts(" Unity.CurrentTestName = #TestFunc#{va_args2.empty? ? '' : " \"(\" ##{va_args2} \")\""}; \\")
output.puts(" Unity.CurrentTestLineNumber = TestLineNum; \\")
output.puts(" if (UnityTestMatches()) { \\") if (@options[:cmdline_args])
output.puts(" Unity.NumberOfTests++; \\")
output.puts(" CMock_Init(); \\") unless (used_mocks.empty?)
output.puts(" UNITY_CLR_DETAILS(); \\") unless (used_mocks.empty?)
output.puts(" if (TEST_PROTECT()) \\")
output.puts(" { \\")
output.puts(" CEXCEPTION_T e; \\") if cexception
output.puts(" Try { \\") if cexception
output.puts(' Unity.CurrentTestLineNumber = TestLineNum; \\')
output.puts(' if (UnityTestMatches()) { \\') if @options[:cmdline_args]
output.puts(' Unity.NumberOfTests++; \\')
output.puts(' CMock_Init(); \\') unless used_mocks.empty?
output.puts(' UNITY_CLR_DETAILS(); \\') unless used_mocks.empty?
output.puts(' if (TEST_PROTECT()) \\')
output.puts(' { \\')
output.puts(' CEXCEPTION_T e; \\') if cexception
output.puts(' Try { \\') if cexception
output.puts(" #{@options[:setup_name]}(); \\")
output.puts(" TestFunc(#{va_args2}); \\")
output.puts(" } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, \"Unhandled Exception!\"); } \\") if cexception
output.puts(" } \\")
output.puts(" if (TEST_PROTECT()) \\")
output.puts(" { \\")
output.puts(' } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \\') if cexception
output.puts(' } \\')
output.puts(' if (TEST_PROTECT()) \\')
output.puts(' { \\')
output.puts(" #{@options[:teardown_name]}(); \\")
output.puts(" CMock_Verify(); \\") unless (used_mocks.empty?)
output.puts(" } \\")
output.puts(" CMock_Destroy(); \\") unless (used_mocks.empty?)
output.puts(" UnityConcludeTest(); \\")
output.puts(" } \\") if (@options[:cmdline_args])
output.puts(' CMock_Verify(); \\') unless used_mocks.empty?
output.puts(' } \\')
output.puts(' CMock_Destroy(); \\') unless used_mocks.empty?
output.puts(' UnityConcludeTest(); \\')
output.puts(' } \\') if @options[:cmdline_args]
output.puts("}\n")
end
def create_reset(output, used_mocks)
output.puts("\n/*=======Test Reset Option=====*/")
output.puts("void resetTest(void);")
output.puts("void resetTest(void)")
output.puts("{")
output.puts(" CMock_Verify();") unless (used_mocks.empty?)
output.puts(" CMock_Destroy();") unless (used_mocks.empty?)
output.puts('void resetTest(void);')
output.puts('void resetTest(void)')
output.puts('{')
output.puts(' CMock_Verify();') unless used_mocks.empty?
output.puts(' CMock_Destroy();') unless used_mocks.empty?
output.puts(" #{@options[:teardown_name]}();")
output.puts(" CMock_Init();") unless (used_mocks.empty?)
output.puts(' CMock_Init();') unless used_mocks.empty?
output.puts(" #{@options[:setup_name]}();")
output.puts("}")
output.puts('}')
end
def create_main(output, filename, tests, used_mocks)
output.puts("\n\n/*=======MAIN=====*/")
main_name = (@options[:main_name].to_sym == :auto) ? "main_#{filename.gsub('.c','')}" : "#{@options[:main_name]}"
if (@options[:cmdline_args])
if (main_name != "main")
main_name = @options[:main_name].to_sym == :auto ? "main_#{filename.gsub('.c', '')}" : (@options[:main_name]).to_s
if @options[:cmdline_args]
if main_name != 'main'
output.puts("#{@options[:main_export_decl]} int #{main_name}(int argc, char** argv);")
end
output.puts("#{@options[:main_export_decl]} int #{main_name}(int argc, char** argv)")
output.puts("{")
output.puts(" int parse_status = UnityParseOptions(argc, argv);")
output.puts(" if (parse_status != 0)")
output.puts(" {")
output.puts(" if (parse_status < 0)")
output.puts(" {")
output.puts(" UnityPrint(\"#{filename.gsub('.c','')}.\");")
output.puts(" UNITY_PRINT_EOL();")
if (@options[:use_param_tests])
output.puts('{')
output.puts(' int parse_status = UnityParseOptions(argc, argv);')
output.puts(' if (parse_status != 0)')
output.puts(' {')
output.puts(' if (parse_status < 0)')
output.puts(' {')
output.puts(" UnityPrint(\"#{filename.gsub('.c', '')}.\");")
output.puts(' UNITY_PRINT_EOL();')
if @options[:use_param_tests]
tests.each do |test|
if ((test[:args].nil?) or (test[:args].empty?))
if test[:args].nil? || test[:args].empty?
output.puts(" UnityPrint(\" #{test[:test]}(RUN_TEST_NO_ARGS)\");")
output.puts(" UNITY_PRINT_EOL();")
output.puts(' UNITY_PRINT_EOL();')
else
test[:args].each do |args|
output.puts(" UnityPrint(\" #{test[:test]}(#{args})\");")
output.puts(" UNITY_PRINT_EOL();")
output.puts(' UNITY_PRINT_EOL();')
end
end
end
else
tests.each { |test| output.puts(" UnityPrint(\" #{test[:test]}\");\n UNITY_PRINT_EOL();")}
tests.each { |test| output.puts(" UnityPrint(\" #{test[:test]}\");\n UNITY_PRINT_EOL();") }
end
output.puts(" return 0;")
output.puts(" }")
output.puts(" return parse_status;")
output.puts(" }")
output.puts(' return 0;')
output.puts(' }')
output.puts(' return parse_status;')
output.puts(' }')
else
if (main_name != "main")
if main_name != 'main'
output.puts("#{@options[:main_export_decl]} int #{main_name}(void);")
end
output.puts("int #{main_name}(void)")
output.puts("{")
output.puts('{')
end
output.puts(" suite_setup();") unless @options[:suite_setup].nil?
output.puts(" UnityBegin(\"#{filename.gsub(/\\/,'\\\\\\')}\");")
if (@options[:use_param_tests])
output.puts(' suite_setup();') unless @options[:suite_setup].nil?
output.puts(" UnityBegin(\"#{filename.gsub(/\\/, '\\\\\\')}\");")
if @options[:use_param_tests]
tests.each do |test|
if ((test[:args].nil?) or (test[:args].empty?))
if test[:args].nil? || test[:args].empty?
output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]}, RUN_TEST_NO_ARGS);")
else
test[:args].each {|args| output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]}, #{args});")}
test[:args].each { |args| output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]}, #{args});") }
end
end
else
tests.each { |test| output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]});") }
tests.each { |test| output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]});") }
end
output.puts()
output.puts(" CMock_Guts_MemFreeFinal();") unless used_mocks.empty?
output.puts(" return #{@options[:suite_teardown].nil? ? "" : "suite_teardown"}(UnityEnd());")
output.puts("}")
output.puts
output.puts(' CMock_Guts_MemFreeFinal();') unless used_mocks.empty?
output.puts(" return #{@options[:suite_teardown].nil? ? '' : 'suite_teardown'}(UnityEnd());")
output.puts('}')
end
def create_h_file(output, filename, tests, testfile_includes, used_mocks)
filename = File.basename(filename).gsub(/[-\/\\\.\,\s]/, "_").upcase
output.puts("/* AUTOGENERATED FILE. DO NOT EDIT. */")
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].to_s}.h\"")
output.puts('#include "cmock.h"') unless (used_mocks.empty?)
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.gsub('.h','')}.h\""}")
output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}")
end
testfile_includes.each do |inc|
output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h','')}.h\""}")
output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}")
end
output.puts "\n"
tests.each do |test|
if ((test[:params].nil?) or (test[:params].empty?))
if test[:params].nil? || test[:params].empty?
output.puts("void #{test[:test]}(void);")
else
output.puts("void #{test[:test]}(#{test[:params]});")
@@ -386,50 +386,52 @@ class UnityTestRunnerGenerator
end
end
if ($0 == __FILE__)
options = { :includes => [] }
yaml_file = nil
if $0 == __FILE__
options = { includes: [] }
#parse out all the options first (these will all be removed as we go)
# parse out all the options first (these will all be removed as we go)
ARGV.reject! do |arg|
case(arg)
when '-cexception'
options[:plugins] = [:cexception]; true
when /\.*\.ya?ml/
options = UnityTestRunnerGenerator.grab_config(arg); true
when /--(\w+)=\"?(.*)\"?/
options[$1.to_sym] = $2; true
when /\.*\.h/
options[:includes] << arg; true
else false
case arg
when '-cexception'
options[:plugins] = [:cexception]
true
when /\.*\.ya?ml/
options = UnityTestRunnerGenerator.grab_config(arg)
true
when /--(\w+)=\"?(.*)\"?/
options[Regexp.last_match(1).to_sym] = Regexp.last_match(2)
true
when /\.*\.h/
options[:includes] << arg
true
else false
end
end
#make sure there is at least one parameter left (the input file)
if !ARGV[0]
# make sure there is at least one parameter left (the input file)
unless ARGV[0]
puts ["\nusage: ruby #{__FILE__} (files) (options) input_test_file (output)",
"\n input_test_file - this is the C file you want to create a runner for",
" output - this is the name of the runner file to generate",
" defaults to (input_test_file)_Runner",
" files:",
" *.yml / *.yaml - loads configuration from here in :unity or :cmock",
" *.h - header files are added as #includes in runner",
" options:",
" -cexception - include cexception support",
" --setup_name=\"\" - redefine setUp func name to something else",
" --teardown_name=\"\" - redefine tearDown func name to something else",
" --main_name=\"\" - redefine main func name to something else",
" --test_prefix=\"\" - redefine test prefix from default test|spec|should",
" --suite_setup=\"\" - code to execute for setup of entire suite",
" --suite_teardown=\"\" - code to execute for teardown of entire suite",
" --use_param_tests=1 - enable parameterized tests (disabled by default)",
" --header_file=\"\" - path/name of test header file to generate too"
].join("\n")
"\n input_test_file - this is the C file you want to create a runner for",
' output - this is the name of the runner file to generate',
' defaults to (input_test_file)_Runner',
' files:',
' *.yml / *.yaml - loads configuration from here in :unity or :cmock',
' *.h - header files are added as #includes in runner',
' options:',
' -cexception - include cexception support',
' --setup_name="" - redefine setUp func name to something else',
' --teardown_name="" - redefine tearDown func name to something else',
' --main_name="" - redefine main func name to something else',
' --test_prefix="" - redefine test prefix from default test|spec|should',
' --suite_setup="" - code to execute for setup of entire suite',
' --suite_teardown="" - code to execute for teardown of entire suite',
' --use_param_tests=1 - enable parameterized tests (disabled by default)',
' --header_file="" - path/name of test header file to generate too'].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])
# create the default test runner name if not specified
ARGV[1] = ARGV[0].gsub('.c', '_Runner.c') unless ARGV[1]
UnityTestRunnerGenerator.new(options).run(ARGV[0], ARGV[1])
end