Ram Gandikota
/
IOTMetronome
FRDM K64F Metronome
pal/Test/Unity/auto/generate_test_runner.rb@0:dbad57390bd1, 2017-05-14 (annotated)
- Committer:
- ram54288
- Date:
- Sun May 14 18:37:05 2017 +0000
- Revision:
- 0:dbad57390bd1
Initial commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
ram54288 | 0:dbad57390bd1 | 1 | # ========================================== |
ram54288 | 0:dbad57390bd1 | 2 | # Unity Project - A Test Framework for C |
ram54288 | 0:dbad57390bd1 | 3 | # Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams |
ram54288 | 0:dbad57390bd1 | 4 | # [Released under MIT License. Please refer to license.txt for details] |
ram54288 | 0:dbad57390bd1 | 5 | # ========================================== |
ram54288 | 0:dbad57390bd1 | 6 | |
ram54288 | 0:dbad57390bd1 | 7 | $QUICK_RUBY_VERSION = RUBY_VERSION.split('.').inject(0){|vv,v| vv * 100 + v.to_i } |
ram54288 | 0:dbad57390bd1 | 8 | File.expand_path(File.join(File.dirname(__FILE__),'colour_prompt')) |
ram54288 | 0:dbad57390bd1 | 9 | |
ram54288 | 0:dbad57390bd1 | 10 | class UnityTestRunnerGenerator |
ram54288 | 0:dbad57390bd1 | 11 | |
ram54288 | 0:dbad57390bd1 | 12 | def initialize(options = nil) |
ram54288 | 0:dbad57390bd1 | 13 | @options = UnityTestRunnerGenerator.default_options |
ram54288 | 0:dbad57390bd1 | 14 | case(options) |
ram54288 | 0:dbad57390bd1 | 15 | when NilClass then @options |
ram54288 | 0:dbad57390bd1 | 16 | when String then @options.merge!(UnityTestRunnerGenerator.grab_config(options)) |
ram54288 | 0:dbad57390bd1 | 17 | when Hash then @options.merge!(options) |
ram54288 | 0:dbad57390bd1 | 18 | else raise "If you specify arguments, it should be a filename or a hash of options" |
ram54288 | 0:dbad57390bd1 | 19 | end |
ram54288 | 0:dbad57390bd1 | 20 | require "#{File.expand_path(File.dirname(__FILE__))}/type_sanitizer" |
ram54288 | 0:dbad57390bd1 | 21 | end |
ram54288 | 0:dbad57390bd1 | 22 | |
ram54288 | 0:dbad57390bd1 | 23 | def self.default_options |
ram54288 | 0:dbad57390bd1 | 24 | { |
ram54288 | 0:dbad57390bd1 | 25 | :includes => [], |
ram54288 | 0:dbad57390bd1 | 26 | :plugins => [], |
ram54288 | 0:dbad57390bd1 | 27 | :framework => :unity, |
ram54288 | 0:dbad57390bd1 | 28 | :test_prefix => "test|spec|should", |
ram54288 | 0:dbad57390bd1 | 29 | :setup_name => "setUp", |
ram54288 | 0:dbad57390bd1 | 30 | :teardown_name => "tearDown", |
ram54288 | 0:dbad57390bd1 | 31 | :main_name => "main", |
ram54288 | 0:dbad57390bd1 | 32 | } |
ram54288 | 0:dbad57390bd1 | 33 | end |
ram54288 | 0:dbad57390bd1 | 34 | |
ram54288 | 0:dbad57390bd1 | 35 | def self.grab_config(config_file) |
ram54288 | 0:dbad57390bd1 | 36 | options = self.default_options |
ram54288 | 0:dbad57390bd1 | 37 | unless (config_file.nil? or config_file.empty?) |
ram54288 | 0:dbad57390bd1 | 38 | require 'yaml' |
ram54288 | 0:dbad57390bd1 | 39 | yaml_guts = YAML.load_file(config_file) |
ram54288 | 0:dbad57390bd1 | 40 | options.merge!(yaml_guts[:unity] || yaml_guts[:cmock]) |
ram54288 | 0:dbad57390bd1 | 41 | raise "No :unity or :cmock section found in #{config_file}" unless options |
ram54288 | 0:dbad57390bd1 | 42 | end |
ram54288 | 0:dbad57390bd1 | 43 | return(options) |
ram54288 | 0:dbad57390bd1 | 44 | end |
ram54288 | 0:dbad57390bd1 | 45 | |
ram54288 | 0:dbad57390bd1 | 46 | def run(input_file, output_file, options=nil) |
ram54288 | 0:dbad57390bd1 | 47 | tests = [] |
ram54288 | 0:dbad57390bd1 | 48 | testfile_includes = [] |
ram54288 | 0:dbad57390bd1 | 49 | used_mocks = [] |
ram54288 | 0:dbad57390bd1 | 50 | |
ram54288 | 0:dbad57390bd1 | 51 | @options.merge!(options) unless options.nil? |
ram54288 | 0:dbad57390bd1 | 52 | module_name = File.basename(input_file) |
ram54288 | 0:dbad57390bd1 | 53 | |
ram54288 | 0:dbad57390bd1 | 54 | #pull required data from source file |
ram54288 | 0:dbad57390bd1 | 55 | source = File.read(input_file) |
ram54288 | 0:dbad57390bd1 | 56 | source = source.force_encoding("ISO-8859-1").encode("utf-8", :replace => nil) if ($QUICK_RUBY_VERSION > 10900) |
ram54288 | 0:dbad57390bd1 | 57 | tests = find_tests(source) |
ram54288 | 0:dbad57390bd1 | 58 | headers = find_includes(source) |
ram54288 | 0:dbad57390bd1 | 59 | testfile_includes = (headers[:local] + headers[:system]) |
ram54288 | 0:dbad57390bd1 | 60 | used_mocks = find_mocks(testfile_includes) |
ram54288 | 0:dbad57390bd1 | 61 | testfile_includes = (testfile_includes - used_mocks) |
ram54288 | 0:dbad57390bd1 | 62 | testfile_includes.delete_if{|inc| inc =~ /(unity|cmock)/} |
ram54288 | 0:dbad57390bd1 | 63 | |
ram54288 | 0:dbad57390bd1 | 64 | #build runner file |
ram54288 | 0:dbad57390bd1 | 65 | generate(input_file, output_file, tests, used_mocks, testfile_includes) |
ram54288 | 0:dbad57390bd1 | 66 | |
ram54288 | 0:dbad57390bd1 | 67 | #determine which files were used to return them |
ram54288 | 0:dbad57390bd1 | 68 | all_files_used = [input_file, output_file] |
ram54288 | 0:dbad57390bd1 | 69 | all_files_used += testfile_includes.map {|filename| filename + '.c'} unless testfile_includes.empty? |
ram54288 | 0:dbad57390bd1 | 70 | all_files_used += @options[:includes] unless @options[:includes].empty? |
ram54288 | 0:dbad57390bd1 | 71 | return all_files_used.uniq |
ram54288 | 0:dbad57390bd1 | 72 | end |
ram54288 | 0:dbad57390bd1 | 73 | |
ram54288 | 0:dbad57390bd1 | 74 | def generate(input_file, output_file, tests, used_mocks, testfile_includes) |
ram54288 | 0:dbad57390bd1 | 75 | File.open(output_file, 'w') do |output| |
ram54288 | 0:dbad57390bd1 | 76 | create_header(output, used_mocks, testfile_includes) |
ram54288 | 0:dbad57390bd1 | 77 | create_externs(output, tests, used_mocks) |
ram54288 | 0:dbad57390bd1 | 78 | create_mock_management(output, used_mocks) |
ram54288 | 0:dbad57390bd1 | 79 | create_suite_setup_and_teardown(output) |
ram54288 | 0:dbad57390bd1 | 80 | create_reset(output, used_mocks) |
ram54288 | 0:dbad57390bd1 | 81 | create_main(output, input_file, tests, used_mocks) |
ram54288 | 0:dbad57390bd1 | 82 | end |
ram54288 | 0:dbad57390bd1 | 83 | |
ram54288 | 0:dbad57390bd1 | 84 | if (@options[:header_file] && !@options[:header_file].empty?) |
ram54288 | 0:dbad57390bd1 | 85 | File.open(@options[:header_file], 'w') do |output| |
ram54288 | 0:dbad57390bd1 | 86 | create_h_file(output, @options[:header_file], tests, testfile_includes, used_mocks) |
ram54288 | 0:dbad57390bd1 | 87 | end |
ram54288 | 0:dbad57390bd1 | 88 | end |
ram54288 | 0:dbad57390bd1 | 89 | end |
ram54288 | 0:dbad57390bd1 | 90 | |
ram54288 | 0:dbad57390bd1 | 91 | def find_tests(source) |
ram54288 | 0:dbad57390bd1 | 92 | tests_and_line_numbers = [] |
ram54288 | 0:dbad57390bd1 | 93 | |
ram54288 | 0:dbad57390bd1 | 94 | source_scrubbed = source.clone |
ram54288 | 0:dbad57390bd1 | 95 | source_scrubbed = source_scrubbed.gsub(/"[^"]*"/, '') # remove things in strings |
ram54288 | 0:dbad57390bd1 | 96 | source_scrubbed = source_scrubbed.gsub(/\/\/.*$/, '') # remove line comments |
ram54288 | 0:dbad57390bd1 | 97 | source_scrubbed = source_scrubbed.gsub(/\/\*.*?\*\//m, '') # remove block comments |
ram54288 | 0:dbad57390bd1 | 98 | lines = source_scrubbed.split(/(^\s*\#.*$) # Treat preprocessor directives as a logical line |
ram54288 | 0:dbad57390bd1 | 99 | | (;|\{|\}) /x) # Match ;, {, and } as end of lines |
ram54288 | 0:dbad57390bd1 | 100 | |
ram54288 | 0:dbad57390bd1 | 101 | lines.each_with_index do |line, index| |
ram54288 | 0:dbad57390bd1 | 102 | #find tests |
ram54288 | 0:dbad57390bd1 | 103 | if line =~ /^((?:\s*TEST_CASE\s*\(.*?\)\s*)*)\s*void\s+((?:#{@options[:test_prefix]}).*)\s*\(\s*(.*)\s*\)/ |
ram54288 | 0:dbad57390bd1 | 104 | arguments = $1 |
ram54288 | 0:dbad57390bd1 | 105 | name = $2 |
ram54288 | 0:dbad57390bd1 | 106 | call = $3 |
ram54288 | 0:dbad57390bd1 | 107 | params = $4 |
ram54288 | 0:dbad57390bd1 | 108 | args = nil |
ram54288 | 0:dbad57390bd1 | 109 | if (@options[:use_param_tests] and !arguments.empty?) |
ram54288 | 0:dbad57390bd1 | 110 | args = [] |
ram54288 | 0:dbad57390bd1 | 111 | arguments.scan(/\s*TEST_CASE\s*\((.*)\)\s*$/) {|a| args << a[0]} |
ram54288 | 0:dbad57390bd1 | 112 | end |
ram54288 | 0:dbad57390bd1 | 113 | tests_and_line_numbers << { :test => name, :args => args, :call => call, :params => params, :line_number => 0 } |
ram54288 | 0:dbad57390bd1 | 114 | end |
ram54288 | 0:dbad57390bd1 | 115 | end |
ram54288 | 0:dbad57390bd1 | 116 | tests_and_line_numbers.uniq! {|v| v[:test] } |
ram54288 | 0:dbad57390bd1 | 117 | |
ram54288 | 0:dbad57390bd1 | 118 | #determine line numbers and create tests to run |
ram54288 | 0:dbad57390bd1 | 119 | source_lines = source.split("\n") |
ram54288 | 0:dbad57390bd1 | 120 | source_index = 0; |
ram54288 | 0:dbad57390bd1 | 121 | tests_and_line_numbers.size.times do |i| |
ram54288 | 0:dbad57390bd1 | 122 | source_lines[source_index..-1].each_with_index do |line, index| |
ram54288 | 0:dbad57390bd1 | 123 | if (line =~ /#{tests_and_line_numbers[i][:test]}/) |
ram54288 | 0:dbad57390bd1 | 124 | source_index += index |
ram54288 | 0:dbad57390bd1 | 125 | tests_and_line_numbers[i][:line_number] = source_index + 1 |
ram54288 | 0:dbad57390bd1 | 126 | break |
ram54288 | 0:dbad57390bd1 | 127 | end |
ram54288 | 0:dbad57390bd1 | 128 | end |
ram54288 | 0:dbad57390bd1 | 129 | end |
ram54288 | 0:dbad57390bd1 | 130 | |
ram54288 | 0:dbad57390bd1 | 131 | return tests_and_line_numbers |
ram54288 | 0:dbad57390bd1 | 132 | end |
ram54288 | 0:dbad57390bd1 | 133 | |
ram54288 | 0:dbad57390bd1 | 134 | def find_includes(source) |
ram54288 | 0:dbad57390bd1 | 135 | |
ram54288 | 0:dbad57390bd1 | 136 | #remove comments (block and line, in three steps to ensure correct precedence) |
ram54288 | 0:dbad57390bd1 | 137 | source.gsub!(/\/\/(?:.+\/\*|\*(?:$|[^\/])).*$/, '') # remove line comments that comment out the start of blocks |
ram54288 | 0:dbad57390bd1 | 138 | source.gsub!(/\/\*.*?\*\//m, '') # remove block comments |
ram54288 | 0:dbad57390bd1 | 139 | source.gsub!(/\/\/.*$/, '') # remove line comments (all that remain) |
ram54288 | 0:dbad57390bd1 | 140 | |
ram54288 | 0:dbad57390bd1 | 141 | #parse out includes |
ram54288 | 0:dbad57390bd1 | 142 | includes = { |
ram54288 | 0:dbad57390bd1 | 143 | :local => source.scan(/^\s*#include\s+\"\s*(.+)\.[hH]\s*\"/).flatten, |
ram54288 | 0:dbad57390bd1 | 144 | :system => source.scan(/^\s*#include\s+<\s*(.+)\s*>/).flatten.map { |inc| "<#{inc}>" } |
ram54288 | 0:dbad57390bd1 | 145 | } |
ram54288 | 0:dbad57390bd1 | 146 | return includes |
ram54288 | 0:dbad57390bd1 | 147 | end |
ram54288 | 0:dbad57390bd1 | 148 | |
ram54288 | 0:dbad57390bd1 | 149 | def find_mocks(includes) |
ram54288 | 0:dbad57390bd1 | 150 | mock_headers = [] |
ram54288 | 0:dbad57390bd1 | 151 | includes.each do |include_path| |
ram54288 | 0:dbad57390bd1 | 152 | include_file = File.basename(include_path) |
ram54288 | 0:dbad57390bd1 | 153 | mock_headers << include_path if (include_file =~ /^mock/i) |
ram54288 | 0:dbad57390bd1 | 154 | end |
ram54288 | 0:dbad57390bd1 | 155 | return mock_headers |
ram54288 | 0:dbad57390bd1 | 156 | end |
ram54288 | 0:dbad57390bd1 | 157 | |
ram54288 | 0:dbad57390bd1 | 158 | def create_header(output, mocks, testfile_includes=[]) |
ram54288 | 0:dbad57390bd1 | 159 | output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */') |
ram54288 | 0:dbad57390bd1 | 160 | create_runtest(output, mocks) |
ram54288 | 0:dbad57390bd1 | 161 | output.puts("\n/*=======Automagically Detected Files To Include=====*/") |
ram54288 | 0:dbad57390bd1 | 162 | output.puts("#include \"#{@options[:framework].to_s}.h\"") |
ram54288 | 0:dbad57390bd1 | 163 | output.puts('#include "cmock.h"') unless (mocks.empty?) |
ram54288 | 0:dbad57390bd1 | 164 | output.puts('#include <setjmp.h>') |
ram54288 | 0:dbad57390bd1 | 165 | output.puts('#include <stdio.h>') |
ram54288 | 0:dbad57390bd1 | 166 | output.puts('#include "CException.h"') if @options[:plugins].include?(:cexception) |
ram54288 | 0:dbad57390bd1 | 167 | if (@options[:header_file] && !@options[:header_file].empty?) |
ram54288 | 0:dbad57390bd1 | 168 | output.puts("#include \"#{File.basename(@options[:header_file])}\"") |
ram54288 | 0:dbad57390bd1 | 169 | else |
ram54288 | 0:dbad57390bd1 | 170 | @options[:includes].flatten.uniq.compact.each do |inc| |
ram54288 | 0:dbad57390bd1 | 171 | output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h','')}.h\""}") |
ram54288 | 0:dbad57390bd1 | 172 | end |
ram54288 | 0:dbad57390bd1 | 173 | testfile_includes.each do |inc| |
ram54288 | 0:dbad57390bd1 | 174 | output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h','')}.h\""}") |
ram54288 | 0:dbad57390bd1 | 175 | end |
ram54288 | 0:dbad57390bd1 | 176 | end |
ram54288 | 0:dbad57390bd1 | 177 | mocks.each do |mock| |
ram54288 | 0:dbad57390bd1 | 178 | output.puts("#include \"#{mock.gsub('.h','')}.h\"") |
ram54288 | 0:dbad57390bd1 | 179 | end |
ram54288 | 0:dbad57390bd1 | 180 | if @options[:enforce_strict_ordering] |
ram54288 | 0:dbad57390bd1 | 181 | output.puts('') |
ram54288 | 0:dbad57390bd1 | 182 | output.puts('int GlobalExpectCount;') |
ram54288 | 0:dbad57390bd1 | 183 | output.puts('int GlobalVerifyOrder;') |
ram54288 | 0:dbad57390bd1 | 184 | output.puts('char* GlobalOrderError;') |
ram54288 | 0:dbad57390bd1 | 185 | end |
ram54288 | 0:dbad57390bd1 | 186 | end |
ram54288 | 0:dbad57390bd1 | 187 | |
ram54288 | 0:dbad57390bd1 | 188 | def create_externs(output, tests, mocks) |
ram54288 | 0:dbad57390bd1 | 189 | output.puts("\n/*=======External Functions This Runner Calls=====*/") |
ram54288 | 0:dbad57390bd1 | 190 | output.puts("extern void #{@options[:setup_name]}(void);") |
ram54288 | 0:dbad57390bd1 | 191 | output.puts("extern void #{@options[:teardown_name]}(void);") |
ram54288 | 0:dbad57390bd1 | 192 | tests.each do |test| |
ram54288 | 0:dbad57390bd1 | 193 | output.puts("extern void #{test[:test]}(#{test[:call] || 'void'});") |
ram54288 | 0:dbad57390bd1 | 194 | end |
ram54288 | 0:dbad57390bd1 | 195 | output.puts('') |
ram54288 | 0:dbad57390bd1 | 196 | end |
ram54288 | 0:dbad57390bd1 | 197 | |
ram54288 | 0:dbad57390bd1 | 198 | def create_mock_management(output, mock_headers) |
ram54288 | 0:dbad57390bd1 | 199 | unless (mock_headers.empty?) |
ram54288 | 0:dbad57390bd1 | 200 | output.puts("\n/*=======Mock Management=====*/") |
ram54288 | 0:dbad57390bd1 | 201 | output.puts("static void CMock_Init(void)") |
ram54288 | 0:dbad57390bd1 | 202 | output.puts("{") |
ram54288 | 0:dbad57390bd1 | 203 | if @options[:enforce_strict_ordering] |
ram54288 | 0:dbad57390bd1 | 204 | output.puts(" GlobalExpectCount = 0;") |
ram54288 | 0:dbad57390bd1 | 205 | output.puts(" GlobalVerifyOrder = 0;") |
ram54288 | 0:dbad57390bd1 | 206 | output.puts(" GlobalOrderError = NULL;") |
ram54288 | 0:dbad57390bd1 | 207 | end |
ram54288 | 0:dbad57390bd1 | 208 | mocks = mock_headers.map {|mock| File.basename(mock)} |
ram54288 | 0:dbad57390bd1 | 209 | mocks.each do |mock| |
ram54288 | 0:dbad57390bd1 | 210 | mock_clean = TypeSanitizer.sanitize_c_identifier(mock) |
ram54288 | 0:dbad57390bd1 | 211 | output.puts(" #{mock_clean}_Init();") |
ram54288 | 0:dbad57390bd1 | 212 | end |
ram54288 | 0:dbad57390bd1 | 213 | output.puts("}\n") |
ram54288 | 0:dbad57390bd1 | 214 | |
ram54288 | 0:dbad57390bd1 | 215 | output.puts("static void CMock_Verify(void)") |
ram54288 | 0:dbad57390bd1 | 216 | output.puts("{") |
ram54288 | 0:dbad57390bd1 | 217 | mocks.each do |mock| |
ram54288 | 0:dbad57390bd1 | 218 | mock_clean = TypeSanitizer.sanitize_c_identifier(mock) |
ram54288 | 0:dbad57390bd1 | 219 | output.puts(" #{mock_clean}_Verify();") |
ram54288 | 0:dbad57390bd1 | 220 | end |
ram54288 | 0:dbad57390bd1 | 221 | output.puts("}\n") |
ram54288 | 0:dbad57390bd1 | 222 | |
ram54288 | 0:dbad57390bd1 | 223 | output.puts("static void CMock_Destroy(void)") |
ram54288 | 0:dbad57390bd1 | 224 | output.puts("{") |
ram54288 | 0:dbad57390bd1 | 225 | mocks.each do |mock| |
ram54288 | 0:dbad57390bd1 | 226 | mock_clean = TypeSanitizer.sanitize_c_identifier(mock) |
ram54288 | 0:dbad57390bd1 | 227 | output.puts(" #{mock_clean}_Destroy();") |
ram54288 | 0:dbad57390bd1 | 228 | end |
ram54288 | 0:dbad57390bd1 | 229 | output.puts("}\n") |
ram54288 | 0:dbad57390bd1 | 230 | end |
ram54288 | 0:dbad57390bd1 | 231 | end |
ram54288 | 0:dbad57390bd1 | 232 | |
ram54288 | 0:dbad57390bd1 | 233 | def create_suite_setup_and_teardown(output) |
ram54288 | 0:dbad57390bd1 | 234 | unless (@options[:suite_setup].nil?) |
ram54288 | 0:dbad57390bd1 | 235 | output.puts("\n/*=======Suite Setup=====*/") |
ram54288 | 0:dbad57390bd1 | 236 | output.puts("static int suite_setup(void)") |
ram54288 | 0:dbad57390bd1 | 237 | output.puts("{") |
ram54288 | 0:dbad57390bd1 | 238 | output.puts(@options[:suite_setup]) |
ram54288 | 0:dbad57390bd1 | 239 | output.puts("}") |
ram54288 | 0:dbad57390bd1 | 240 | end |
ram54288 | 0:dbad57390bd1 | 241 | unless (@options[:suite_teardown].nil?) |
ram54288 | 0:dbad57390bd1 | 242 | output.puts("\n/*=======Suite Teardown=====*/") |
ram54288 | 0:dbad57390bd1 | 243 | output.puts("static int suite_teardown(int num_failures)") |
ram54288 | 0:dbad57390bd1 | 244 | output.puts("{") |
ram54288 | 0:dbad57390bd1 | 245 | output.puts(@options[:suite_teardown]) |
ram54288 | 0:dbad57390bd1 | 246 | output.puts("}") |
ram54288 | 0:dbad57390bd1 | 247 | end |
ram54288 | 0:dbad57390bd1 | 248 | end |
ram54288 | 0:dbad57390bd1 | 249 | |
ram54288 | 0:dbad57390bd1 | 250 | def create_runtest(output, used_mocks) |
ram54288 | 0:dbad57390bd1 | 251 | cexception = @options[:plugins].include? :cexception |
ram54288 | 0:dbad57390bd1 | 252 | va_args1 = @options[:use_param_tests] ? ', ...' : '' |
ram54288 | 0:dbad57390bd1 | 253 | va_args2 = @options[:use_param_tests] ? '__VA_ARGS__' : '' |
ram54288 | 0:dbad57390bd1 | 254 | output.puts("\n/*=======Test Runner Used To Run Each Test Below=====*/") |
ram54288 | 0:dbad57390bd1 | 255 | output.puts("#define RUN_TEST_NO_ARGS") if @options[:use_param_tests] |
ram54288 | 0:dbad57390bd1 | 256 | output.puts("#define RUN_TEST(TestFunc, TestLineNum#{va_args1}) \\") |
ram54288 | 0:dbad57390bd1 | 257 | output.puts("{ \\") |
ram54288 | 0:dbad57390bd1 | 258 | output.puts(" Unity.CurrentTestName = #TestFunc#{va_args2.empty? ? '' : " \"(\" ##{va_args2} \")\""}; \\") |
ram54288 | 0:dbad57390bd1 | 259 | output.puts(" Unity.CurrentTestLineNumber = TestLineNum; \\") |
ram54288 | 0:dbad57390bd1 | 260 | output.puts(" Unity.NumberOfTests++; \\") |
ram54288 | 0:dbad57390bd1 | 261 | output.puts(" CMock_Init(); \\") unless (used_mocks.empty?) |
ram54288 | 0:dbad57390bd1 | 262 | output.puts(" UNITY_CLR_DETAILS(); \\") unless (used_mocks.empty?) |
ram54288 | 0:dbad57390bd1 | 263 | output.puts(" if (TEST_PROTECT()) \\") |
ram54288 | 0:dbad57390bd1 | 264 | output.puts(" { \\") |
ram54288 | 0:dbad57390bd1 | 265 | output.puts(" CEXCEPTION_T e; \\") if cexception |
ram54288 | 0:dbad57390bd1 | 266 | output.puts(" Try { \\") if cexception |
ram54288 | 0:dbad57390bd1 | 267 | output.puts(" #{@options[:setup_name]}(); \\") |
ram54288 | 0:dbad57390bd1 | 268 | output.puts(" TestFunc(#{va_args2}); \\") |
ram54288 | 0:dbad57390bd1 | 269 | output.puts(" } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, \"Unhandled Exception!\"); } \\") if cexception |
ram54288 | 0:dbad57390bd1 | 270 | output.puts(" } \\") |
ram54288 | 0:dbad57390bd1 | 271 | output.puts(" if (TEST_PROTECT() && !TEST_IS_IGNORED) \\") |
ram54288 | 0:dbad57390bd1 | 272 | output.puts(" { \\") |
ram54288 | 0:dbad57390bd1 | 273 | output.puts(" #{@options[:teardown_name]}(); \\") |
ram54288 | 0:dbad57390bd1 | 274 | output.puts(" CMock_Verify(); \\") unless (used_mocks.empty?) |
ram54288 | 0:dbad57390bd1 | 275 | output.puts(" } \\") |
ram54288 | 0:dbad57390bd1 | 276 | output.puts(" CMock_Destroy(); \\") unless (used_mocks.empty?) |
ram54288 | 0:dbad57390bd1 | 277 | output.puts(" UnityConcludeTest(); \\") |
ram54288 | 0:dbad57390bd1 | 278 | output.puts("}\n") |
ram54288 | 0:dbad57390bd1 | 279 | end |
ram54288 | 0:dbad57390bd1 | 280 | |
ram54288 | 0:dbad57390bd1 | 281 | def create_reset(output, used_mocks) |
ram54288 | 0:dbad57390bd1 | 282 | output.puts("\n/*=======Test Reset Option=====*/") |
ram54288 | 0:dbad57390bd1 | 283 | output.puts("void resetTest(void);") |
ram54288 | 0:dbad57390bd1 | 284 | output.puts("void resetTest(void)") |
ram54288 | 0:dbad57390bd1 | 285 | output.puts("{") |
ram54288 | 0:dbad57390bd1 | 286 | output.puts(" CMock_Verify();") unless (used_mocks.empty?) |
ram54288 | 0:dbad57390bd1 | 287 | output.puts(" CMock_Destroy();") unless (used_mocks.empty?) |
ram54288 | 0:dbad57390bd1 | 288 | output.puts(" #{@options[:teardown_name]}();") |
ram54288 | 0:dbad57390bd1 | 289 | output.puts(" CMock_Init();") unless (used_mocks.empty?) |
ram54288 | 0:dbad57390bd1 | 290 | output.puts(" #{@options[:setup_name]}();") |
ram54288 | 0:dbad57390bd1 | 291 | output.puts("}") |
ram54288 | 0:dbad57390bd1 | 292 | end |
ram54288 | 0:dbad57390bd1 | 293 | |
ram54288 | 0:dbad57390bd1 | 294 | def create_main(output, filename, tests, used_mocks) |
ram54288 | 0:dbad57390bd1 | 295 | output.puts("\n\n/*=======MAIN=====*/") |
ram54288 | 0:dbad57390bd1 | 296 | if (@options[:main_name] != "main") |
ram54288 | 0:dbad57390bd1 | 297 | output.puts("int #{@options[:main_name]}(void);") |
ram54288 | 0:dbad57390bd1 | 298 | end |
ram54288 | 0:dbad57390bd1 | 299 | output.puts("int #{@options[:main_name]}(void)") |
ram54288 | 0:dbad57390bd1 | 300 | output.puts("{") |
ram54288 | 0:dbad57390bd1 | 301 | output.puts(" suite_setup();") unless @options[:suite_setup].nil? |
ram54288 | 0:dbad57390bd1 | 302 | output.puts(" UnityBegin(\"#{filename.gsub(/\\/,'\\\\')}\");") |
ram54288 | 0:dbad57390bd1 | 303 | if (@options[:use_param_tests]) |
ram54288 | 0:dbad57390bd1 | 304 | tests.each do |test| |
ram54288 | 0:dbad57390bd1 | 305 | if ((test[:args].nil?) or (test[:args].empty?)) |
ram54288 | 0:dbad57390bd1 | 306 | output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]}, RUN_TEST_NO_ARGS);") |
ram54288 | 0:dbad57390bd1 | 307 | else |
ram54288 | 0:dbad57390bd1 | 308 | test[:args].each {|args| output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]}, #{args});")} |
ram54288 | 0:dbad57390bd1 | 309 | end |
ram54288 | 0:dbad57390bd1 | 310 | end |
ram54288 | 0:dbad57390bd1 | 311 | else |
ram54288 | 0:dbad57390bd1 | 312 | tests.each { |test| output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]});") } |
ram54288 | 0:dbad57390bd1 | 313 | end |
ram54288 | 0:dbad57390bd1 | 314 | output.puts() |
ram54288 | 0:dbad57390bd1 | 315 | output.puts(" CMock_Guts_MemFreeFinal();") unless used_mocks.empty? |
ram54288 | 0:dbad57390bd1 | 316 | output.puts(" return #{@options[:suite_teardown].nil? ? "" : "suite_teardown"}(UnityEnd());") |
ram54288 | 0:dbad57390bd1 | 317 | output.puts("}") |
ram54288 | 0:dbad57390bd1 | 318 | end |
ram54288 | 0:dbad57390bd1 | 319 | |
ram54288 | 0:dbad57390bd1 | 320 | def create_h_file(output, filename, tests, testfile_includes, used_mocks) |
ram54288 | 0:dbad57390bd1 | 321 | filename = File.basename(filename).gsub(/[-\/\\\.\,\s]/, "_").upcase |
ram54288 | 0:dbad57390bd1 | 322 | output.puts("/* AUTOGENERATED FILE. DO NOT EDIT. */") |
ram54288 | 0:dbad57390bd1 | 323 | output.puts("#ifndef _#{filename}") |
ram54288 | 0:dbad57390bd1 | 324 | output.puts("#define _#{filename}\n\n") |
ram54288 | 0:dbad57390bd1 | 325 | output.puts("#include \"#{@options[:framework].to_s}.h\"") |
ram54288 | 0:dbad57390bd1 | 326 | output.puts('#include "cmock.h"') unless (used_mocks.empty?) |
ram54288 | 0:dbad57390bd1 | 327 | @options[:includes].flatten.uniq.compact.each do |inc| |
ram54288 | 0:dbad57390bd1 | 328 | output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h','')}.h\""}") |
ram54288 | 0:dbad57390bd1 | 329 | end |
ram54288 | 0:dbad57390bd1 | 330 | testfile_includes.each do |inc| |
ram54288 | 0:dbad57390bd1 | 331 | output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h','')}.h\""}") |
ram54288 | 0:dbad57390bd1 | 332 | end |
ram54288 | 0:dbad57390bd1 | 333 | output.puts "\n" |
ram54288 | 0:dbad57390bd1 | 334 | tests.each do |test| |
ram54288 | 0:dbad57390bd1 | 335 | if ((test[:params].nil?) or (test[:params].empty?)) |
ram54288 | 0:dbad57390bd1 | 336 | output.puts("void #{test[:test]}(void);") |
ram54288 | 0:dbad57390bd1 | 337 | else |
ram54288 | 0:dbad57390bd1 | 338 | output.puts("void #{test[:test]}(#{test[:params]});") |
ram54288 | 0:dbad57390bd1 | 339 | end |
ram54288 | 0:dbad57390bd1 | 340 | end |
ram54288 | 0:dbad57390bd1 | 341 | output.puts("#endif\n\n") |
ram54288 | 0:dbad57390bd1 | 342 | end |
ram54288 | 0:dbad57390bd1 | 343 | end |
ram54288 | 0:dbad57390bd1 | 344 | |
ram54288 | 0:dbad57390bd1 | 345 | if ($0 == __FILE__) |
ram54288 | 0:dbad57390bd1 | 346 | options = { :includes => [] } |
ram54288 | 0:dbad57390bd1 | 347 | yaml_file = nil |
ram54288 | 0:dbad57390bd1 | 348 | |
ram54288 | 0:dbad57390bd1 | 349 | #parse out all the options first (these will all be removed as we go) |
ram54288 | 0:dbad57390bd1 | 350 | ARGV.reject! do |arg| |
ram54288 | 0:dbad57390bd1 | 351 | case(arg) |
ram54288 | 0:dbad57390bd1 | 352 | when '-cexception' |
ram54288 | 0:dbad57390bd1 | 353 | options[:plugins] = [:cexception]; true |
ram54288 | 0:dbad57390bd1 | 354 | when /\.*\.ya?ml/ |
ram54288 | 0:dbad57390bd1 | 355 | options = UnityTestRunnerGenerator.grab_config(arg); true |
ram54288 | 0:dbad57390bd1 | 356 | when /--(\w+)=\"?(.*)\"?/ |
ram54288 | 0:dbad57390bd1 | 357 | options[$1.to_sym] = $2; true |
ram54288 | 0:dbad57390bd1 | 358 | when /\.*\.h/ |
ram54288 | 0:dbad57390bd1 | 359 | options[:includes] << arg; true |
ram54288 | 0:dbad57390bd1 | 360 | else false |
ram54288 | 0:dbad57390bd1 | 361 | end |
ram54288 | 0:dbad57390bd1 | 362 | end |
ram54288 | 0:dbad57390bd1 | 363 | |
ram54288 | 0:dbad57390bd1 | 364 | #make sure there is at least one parameter left (the input file) |
ram54288 | 0:dbad57390bd1 | 365 | if !ARGV[0] |
ram54288 | 0:dbad57390bd1 | 366 | puts ["\nusage: ruby #{__FILE__} (files) (options) input_test_file (output)", |
ram54288 | 0:dbad57390bd1 | 367 | "\n input_test_file - this is the C file you want to create a runner for", |
ram54288 | 0:dbad57390bd1 | 368 | " output - this is the name of the runner file to generate", |
ram54288 | 0:dbad57390bd1 | 369 | " defaults to (input_test_file)_Runner", |
ram54288 | 0:dbad57390bd1 | 370 | " files:", |
ram54288 | 0:dbad57390bd1 | 371 | " *.yml / *.yaml - loads configuration from here in :unity or :cmock", |
ram54288 | 0:dbad57390bd1 | 372 | " *.h - header files are added as #includes in runner", |
ram54288 | 0:dbad57390bd1 | 373 | " options:", |
ram54288 | 0:dbad57390bd1 | 374 | " -cexception - include cexception support", |
ram54288 | 0:dbad57390bd1 | 375 | " --setup_name=\"\" - redefine setUp func name to something else", |
ram54288 | 0:dbad57390bd1 | 376 | " --teardown_name=\"\" - redefine tearDown func name to something else", |
ram54288 | 0:dbad57390bd1 | 377 | " --main_name=\"\" - redefine main func name to something else", |
ram54288 | 0:dbad57390bd1 | 378 | " --test_prefix=\"\" - redefine test prefix from default test|spec|should", |
ram54288 | 0:dbad57390bd1 | 379 | " --suite_setup=\"\" - code to execute for setup of entire suite", |
ram54288 | 0:dbad57390bd1 | 380 | " --suite_teardown=\"\" - code to execute for teardown of entire suite", |
ram54288 | 0:dbad57390bd1 | 381 | " --use_param_tests=1 - enable parameterized tests (disabled by default)", |
ram54288 | 0:dbad57390bd1 | 382 | " --header_file=\"\" - path/name of test header file to generate too" |
ram54288 | 0:dbad57390bd1 | 383 | ].join("\n") |
ram54288 | 0:dbad57390bd1 | 384 | exit 1 |
ram54288 | 0:dbad57390bd1 | 385 | end |
ram54288 | 0:dbad57390bd1 | 386 | |
ram54288 | 0:dbad57390bd1 | 387 | #create the default test runner name if not specified |
ram54288 | 0:dbad57390bd1 | 388 | ARGV[1] = ARGV[0].gsub(".c","_Runner.c") if (!ARGV[1]) |
ram54288 | 0:dbad57390bd1 | 389 | |
ram54288 | 0:dbad57390bd1 | 390 | UnityTestRunnerGenerator.new(options).run(ARGV[0], ARGV[1]) |
ram54288 | 0:dbad57390bd1 | 391 | end |