1# ========================================== 2# Unity Project - A Test Framework for C 3# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams 4# [Released under MIT License. Please refer to license.txt for details] 5# ========================================== 6 7require 'yaml' 8require 'fileutils' 9require 'rbconfig' 10require_relative '../../auto/unity_test_summary' 11require_relative '../../auto/generate_test_runner' 12require_relative '../../auto/colour_reporter' 13 14$is_windows = (RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/) 15 16C_EXTENSION = '.c'.freeze 17 18def load_configuration(config_file) 19 return if $configured 20 21 $cfg_file = "#{__dir__}/../../test/targets/#{config_file}" unless config_file =~ /[\\|\/]/ 22 $cfg = YAML.load(File.read($cfg_file)) 23 $colour_output = false unless $cfg['colour'] 24 $configured = true if config_file != DEFAULT_CONFIG_FILE 25end 26 27def configure_clean 28 CLEAN.include($cfg['compiler']['build_path'] + '*.*') unless $cfg['compiler']['build_path'].nil? 29end 30 31def configure_toolchain(config_file = DEFAULT_CONFIG_FILE) 32 config_file += '.yml' unless config_file =~ /\.yml$/ 33 config_file = config_file unless config_file =~ /[\\|\/]/ 34 load_configuration(config_file) 35 configure_clean 36end 37 38def tackit(strings) 39 result = if strings.is_a?(Array) 40 "\"#{strings.join}\"" 41 else 42 strings 43 end 44 result 45end 46 47def squash(prefix, items) 48 result = '' 49 items.each { |item| result += " #{prefix}#{tackit(item)}" } 50 result 51end 52 53def build_compiler_fields 54 command = tackit($cfg['compiler']['path']) 55 defines = if $cfg['compiler']['defines']['items'].nil? 56 '' 57 else 58 decl = if $is_windows 59 'UNITY_OUTPUT_CHAR_HEADER_DECLARATION=UnityOutputCharSpy_OutputChar(int)' 60 else 61 'UNITY_OUTPUT_CHAR_HEADER_DECLARATION=UnityOutputCharSpy_OutputChar\(int\)' 62 end 63 squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items'] + ['UNITY_OUTPUT_CHAR=UnityOutputCharSpy_OutputChar'] + [decl]) 64 end 65 options = squash('', $cfg['compiler']['options']) 66 includes = squash($cfg['compiler']['includes']['prefix'], $cfg['compiler']['includes']['items']) 67 includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR) 68 69 { command: command, defines: defines, options: options, includes: includes } 70end 71 72def compile(file, _defines = []) 73 compiler = build_compiler_fields 74 unity_include = $cfg['compiler']['includes']['prefix'] + '../../src' 75 cmd_str = "#{compiler[:command]}#{compiler[:defines]}#{compiler[:options]}#{compiler[:includes]} #{unity_include} #{file} " \ 76 "#{$cfg['compiler']['object_files']['prefix']}#{$cfg['compiler']['object_files']['destination']}" \ 77 "#{File.basename(file, C_EXTENSION)}#{$cfg['compiler']['object_files']['extension']}" 78 79 execute(cmd_str) 80end 81 82def build_linker_fields 83 command = tackit($cfg['linker']['path']) 84 options = if $cfg['linker']['options'].nil? 85 '' 86 else 87 squash('', $cfg['linker']['options']) 88 end 89 includes = if $cfg['linker']['includes'].nil? || $cfg['linker']['includes']['items'].nil? 90 '' 91 else 92 squash($cfg['linker']['includes']['prefix'], $cfg['linker']['includes']['items']) 93 end.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR) 94 95 { command: command, options: options, includes: includes } 96end 97 98def link_it(exe_name, obj_list) 99 linker = build_linker_fields 100 cmd_str = "#{linker[:command]}#{linker[:options]}#{linker[:includes]} " + 101 (obj_list.map { |obj| "#{$cfg['linker']['object_files']['path']}#{obj} " }).join + 102 $cfg['linker']['bin_files']['prefix'] + ' ' + 103 $cfg['linker']['bin_files']['destination'] + 104 exe_name + $cfg['linker']['bin_files']['extension'] 105 execute(cmd_str) 106end 107 108def build_simulator_fields 109 return nil if $cfg['simulator'].nil? 110 111 command = if $cfg['simulator']['path'].nil? 112 '' 113 else 114 (tackit($cfg['simulator']['path']) + ' ') 115 end 116 pre_support = if $cfg['simulator']['pre_support'].nil? 117 '' 118 else 119 squash('', $cfg['simulator']['pre_support']) 120 end 121 post_support = if $cfg['simulator']['post_support'].nil? 122 '' 123 else 124 squash('', $cfg['simulator']['post_support']) 125 end 126 { command: command, pre_support: pre_support, post_support: post_support } 127end 128 129def execute(command_string, verbose = true) 130 report command_string 131 output = `#{command_string}`.chomp 132 report(output) if verbose && !output.nil? && !output.empty? 133 134 raise "Command failed. (Returned #{$?.exitstatus})" if $?.exitstatus != 0 135 136 output 137end 138 139def report_summary 140 summary = UnityTestSummary.new 141 summary.root = __dir__ 142 results_glob = "#{$cfg['compiler']['build_path']}*.test*" 143 results_glob.tr!('\\', '/') 144 results = Dir[results_glob] 145 summary.targets = results 146 summary.run 147end 148 149def run_tests(exclude_stdlib=false) 150 report 'Running Unity system tests...' 151 152 # Tack on TEST define for compiling unit tests 153 load_configuration($cfg_file) 154 test_defines = ['TEST'] 155 $cfg['compiler']['defines']['items'] = [] if $cfg['compiler']['defines']['items'].nil? 156 $cfg['compiler']['defines']['items'] << 'UNITY_EXCLUDE_STDLIB_MALLOC' if exclude_stdlib 157 158 # Get a list of all source files needed 159 src_files = Dir["#{__dir__}/src/*.c"] 160 src_files += Dir["#{__dir__}/test/*.c"] 161 src_files << '../../src/unity.c' 162 163 # Build object files 164 src_files.each { |f| compile(f, test_defines) } 165 obj_list = src_files.map { |f| File.basename(f.ext($cfg['compiler']['object_files']['extension'])) } 166 167 # Link the test executable 168 test_base = 'framework_test' 169 link_it(test_base, obj_list) 170 171 # Execute unit test and generate results file 172 simulator = build_simulator_fields 173 executable = $cfg['linker']['bin_files']['destination'] + test_base + $cfg['linker']['bin_files']['extension'] 174 cmd_str = if simulator.nil? 175 executable + ' -v -r' 176 else 177 "#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}" 178 end 179 output = execute(cmd_str) 180 test_results = $cfg['compiler']['build_path'] + test_base 181 test_results += if output.match(/OK$/m).nil? 182 '.testfail' 183 else 184 '.testpass' 185 end 186 File.open(test_results, 'w') { |f| f.print output } 187end 188