19750e409Sopenharmony_ci# ========================================== 29750e409Sopenharmony_ci# Unity Project - A Test Framework for C 39750e409Sopenharmony_ci# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams 49750e409Sopenharmony_ci# [Released under MIT License. Please refer to license.txt for details] 59750e409Sopenharmony_ci# ========================================== 69750e409Sopenharmony_ci 79750e409Sopenharmony_cirequire 'yaml' 89750e409Sopenharmony_cirequire 'fileutils' 99750e409Sopenharmony_cirequire UNITY_ROOT + '../auto/unity_test_summary' 109750e409Sopenharmony_cirequire UNITY_ROOT + '../auto/generate_test_runner' 119750e409Sopenharmony_cirequire UNITY_ROOT + '../auto/colour_reporter' 129750e409Sopenharmony_ci 139750e409Sopenharmony_cimodule RakefileHelpers 149750e409Sopenharmony_ci C_EXTENSION = '.c'.freeze 159750e409Sopenharmony_ci def load_configuration(config_file) 169750e409Sopenharmony_ci return if $configured 179750e409Sopenharmony_ci 189750e409Sopenharmony_ci $cfg_file = "targets/#{config_file}" unless config_file =~ /[\\|\/]/ 199750e409Sopenharmony_ci $cfg = YAML.load(File.read($cfg_file)) 209750e409Sopenharmony_ci $colour_output = false unless $cfg['colour'] 219750e409Sopenharmony_ci $configured = true if config_file != DEFAULT_CONFIG_FILE 229750e409Sopenharmony_ci end 239750e409Sopenharmony_ci 249750e409Sopenharmony_ci def configure_clean 259750e409Sopenharmony_ci CLEAN.include($cfg['compiler']['build_path'] + '*.*') unless $cfg['compiler']['build_path'].nil? 269750e409Sopenharmony_ci end 279750e409Sopenharmony_ci 289750e409Sopenharmony_ci def configure_toolchain(config_file = DEFAULT_CONFIG_FILE) 299750e409Sopenharmony_ci config_file += '.yml' unless config_file =~ /\.yml$/ 309750e409Sopenharmony_ci config_file = config_file unless config_file =~ /[\\|\/]/ 319750e409Sopenharmony_ci load_configuration(config_file) 329750e409Sopenharmony_ci configure_clean 339750e409Sopenharmony_ci end 349750e409Sopenharmony_ci 359750e409Sopenharmony_ci def unit_test_files 369750e409Sopenharmony_ci path = $cfg['compiler']['unit_tests_path'] + 'test*' + C_EXTENSION 379750e409Sopenharmony_ci path.tr!('\\', '/') 389750e409Sopenharmony_ci FileList.new(path) 399750e409Sopenharmony_ci end 409750e409Sopenharmony_ci 419750e409Sopenharmony_ci def local_include_dirs 429750e409Sopenharmony_ci include_dirs = $cfg['compiler']['includes']['items'].dup 439750e409Sopenharmony_ci include_dirs.delete_if { |dir| dir.is_a?(Array) } 449750e409Sopenharmony_ci include_dirs 459750e409Sopenharmony_ci end 469750e409Sopenharmony_ci 479750e409Sopenharmony_ci def extract_headers(filename) 489750e409Sopenharmony_ci includes = [] 499750e409Sopenharmony_ci lines = File.readlines(filename) 509750e409Sopenharmony_ci lines.each do |line| 519750e409Sopenharmony_ci m = line.match(/^\s*#include\s+\"\s*(.+\.[hH])\s*\"/) 529750e409Sopenharmony_ci includes << m[1] unless m.nil? 539750e409Sopenharmony_ci end 549750e409Sopenharmony_ci includes 559750e409Sopenharmony_ci end 569750e409Sopenharmony_ci 579750e409Sopenharmony_ci def find_source_file(header, paths) 589750e409Sopenharmony_ci paths.each do |dir| 599750e409Sopenharmony_ci src_file = dir + header.ext(C_EXTENSION) 609750e409Sopenharmony_ci return src_file if File.exist?(src_file) 619750e409Sopenharmony_ci end 629750e409Sopenharmony_ci nil 639750e409Sopenharmony_ci end 649750e409Sopenharmony_ci 659750e409Sopenharmony_ci def tackit(strings) 669750e409Sopenharmony_ci result = if strings.is_a?(Array) 679750e409Sopenharmony_ci "\"#{strings.join}\"" 689750e409Sopenharmony_ci else 699750e409Sopenharmony_ci strings 709750e409Sopenharmony_ci end 719750e409Sopenharmony_ci result 729750e409Sopenharmony_ci end 739750e409Sopenharmony_ci 749750e409Sopenharmony_ci def squash(prefix, items) 759750e409Sopenharmony_ci result = '' 769750e409Sopenharmony_ci items.each { |item| result += " #{prefix}#{tackit(item)}" } 779750e409Sopenharmony_ci result 789750e409Sopenharmony_ci end 799750e409Sopenharmony_ci 809750e409Sopenharmony_ci def should(behave, &block) 819750e409Sopenharmony_ci if block 829750e409Sopenharmony_ci puts 'Should ' + behave 839750e409Sopenharmony_ci yield block 849750e409Sopenharmony_ci else 859750e409Sopenharmony_ci puts "UNIMPLEMENTED CASE: Should #{behave}" 869750e409Sopenharmony_ci end 879750e409Sopenharmony_ci end 889750e409Sopenharmony_ci 899750e409Sopenharmony_ci def build_compiler_fields(inject_defines) 909750e409Sopenharmony_ci command = tackit($cfg['compiler']['path']) 919750e409Sopenharmony_ci defines = if $cfg['compiler']['defines']['items'].nil? 929750e409Sopenharmony_ci '' 939750e409Sopenharmony_ci else 949750e409Sopenharmony_ci squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items'] + ['UNITY_OUTPUT_CHAR=putcharSpy'] + ['UNITY_OUTPUT_CHAR_HEADER_DECLARATION=putcharSpy\(int\)'] + inject_defines) 959750e409Sopenharmony_ci end 969750e409Sopenharmony_ci options = squash('', $cfg['compiler']['options']) 979750e409Sopenharmony_ci includes = squash($cfg['compiler']['includes']['prefix'], $cfg['compiler']['includes']['items']) 989750e409Sopenharmony_ci includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR) 999750e409Sopenharmony_ci 1009750e409Sopenharmony_ci { :command => command, :defines => defines, :options => options, :includes => includes } 1019750e409Sopenharmony_ci end 1029750e409Sopenharmony_ci 1039750e409Sopenharmony_ci def compile(file, defines = []) 1049750e409Sopenharmony_ci compiler = build_compiler_fields(defines) 1059750e409Sopenharmony_ci cmd_str = "#{compiler[:command]}#{compiler[:defines]}#{compiler[:options]}#{compiler[:includes]} #{file} " \ 1069750e409Sopenharmony_ci "#{$cfg['compiler']['object_files']['prefix']}#{$cfg['compiler']['object_files']['destination']}" 1079750e409Sopenharmony_ci obj_file = "#{File.basename(file, C_EXTENSION)}#{$cfg['compiler']['object_files']['extension']}" 1089750e409Sopenharmony_ci execute(cmd_str + obj_file) 1099750e409Sopenharmony_ci 1109750e409Sopenharmony_ci obj_file 1119750e409Sopenharmony_ci end 1129750e409Sopenharmony_ci 1139750e409Sopenharmony_ci def build_linker_fields 1149750e409Sopenharmony_ci command = tackit($cfg['linker']['path']) 1159750e409Sopenharmony_ci options = if $cfg['linker']['options'].nil? 1169750e409Sopenharmony_ci '' 1179750e409Sopenharmony_ci else 1189750e409Sopenharmony_ci squash('', $cfg['linker']['options']) 1199750e409Sopenharmony_ci end 1209750e409Sopenharmony_ci includes = if $cfg['linker']['includes'].nil? || $cfg['linker']['includes']['items'].nil? 1219750e409Sopenharmony_ci '' 1229750e409Sopenharmony_ci else 1239750e409Sopenharmony_ci squash($cfg['linker']['includes']['prefix'], $cfg['linker']['includes']['items']) 1249750e409Sopenharmony_ci end.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR) 1259750e409Sopenharmony_ci 1269750e409Sopenharmony_ci { :command => command, :options => options, :includes => includes } 1279750e409Sopenharmony_ci end 1289750e409Sopenharmony_ci 1299750e409Sopenharmony_ci def link_it(exe_name, obj_list) 1309750e409Sopenharmony_ci linker = build_linker_fields 1319750e409Sopenharmony_ci cmd_str = "#{linker[:command]}#{linker[:options]}#{linker[:includes]} " + 1329750e409Sopenharmony_ci (obj_list.map { |obj| "#{$cfg['linker']['object_files']['path']}#{obj} " }).join + 1339750e409Sopenharmony_ci $cfg['linker']['bin_files']['prefix'] + ' ' + 1349750e409Sopenharmony_ci $cfg['linker']['bin_files']['destination'] + 1359750e409Sopenharmony_ci exe_name + $cfg['linker']['bin_files']['extension'] 1369750e409Sopenharmony_ci execute(cmd_str) 1379750e409Sopenharmony_ci end 1389750e409Sopenharmony_ci 1399750e409Sopenharmony_ci def build_simulator_fields 1409750e409Sopenharmony_ci return nil if $cfg['simulator'].nil? 1419750e409Sopenharmony_ci command = if $cfg['simulator']['path'].nil? 1429750e409Sopenharmony_ci '' 1439750e409Sopenharmony_ci else 1449750e409Sopenharmony_ci (tackit($cfg['simulator']['path']) + ' ') 1459750e409Sopenharmony_ci end 1469750e409Sopenharmony_ci pre_support = if $cfg['simulator']['pre_support'].nil? 1479750e409Sopenharmony_ci '' 1489750e409Sopenharmony_ci else 1499750e409Sopenharmony_ci squash('', $cfg['simulator']['pre_support']) 1509750e409Sopenharmony_ci end 1519750e409Sopenharmony_ci post_support = if $cfg['simulator']['post_support'].nil? 1529750e409Sopenharmony_ci '' 1539750e409Sopenharmony_ci else 1549750e409Sopenharmony_ci squash('', $cfg['simulator']['post_support']) 1559750e409Sopenharmony_ci end 1569750e409Sopenharmony_ci 1579750e409Sopenharmony_ci { :command => command, :pre_support => pre_support, :post_support => post_support } 1589750e409Sopenharmony_ci end 1599750e409Sopenharmony_ci 1609750e409Sopenharmony_ci def run_astyle(style_what) 1619750e409Sopenharmony_ci report "Styling C Code..." 1629750e409Sopenharmony_ci command = "AStyle " \ 1639750e409Sopenharmony_ci "--style=allman --indent=spaces=4 --indent-switches --indent-preproc-define --indent-preproc-block " \ 1649750e409Sopenharmony_ci "--pad-oper --pad-comma --unpad-paren --pad-header " \ 1659750e409Sopenharmony_ci "--align-pointer=type --align-reference=name " \ 1669750e409Sopenharmony_ci "--add-brackets --mode=c --suffix=none " \ 1679750e409Sopenharmony_ci "#{style_what}" 1689750e409Sopenharmony_ci execute(command, false) 1699750e409Sopenharmony_ci report "Styling C:PASS" 1709750e409Sopenharmony_ci end 1719750e409Sopenharmony_ci 1729750e409Sopenharmony_ci def execute(command_string, ok_to_fail = false) 1739750e409Sopenharmony_ci report command_string if $verbose 1749750e409Sopenharmony_ci output = `#{command_string}`.chomp 1759750e409Sopenharmony_ci report(output) if $verbose && !output.nil? && !output.empty? 1769750e409Sopenharmony_ci raise "Command failed. (Returned #{$?.exitstatus})" if !$?.exitstatus.zero? && !ok_to_fail 1779750e409Sopenharmony_ci output 1789750e409Sopenharmony_ci end 1799750e409Sopenharmony_ci 1809750e409Sopenharmony_ci def report_summary 1819750e409Sopenharmony_ci summary = UnityTestSummary.new 1829750e409Sopenharmony_ci summary.root = UNITY_ROOT 1839750e409Sopenharmony_ci results_glob = "#{$cfg['compiler']['build_path']}*.test*" 1849750e409Sopenharmony_ci results_glob.tr!('\\', '/') 1859750e409Sopenharmony_ci results = Dir[results_glob] 1869750e409Sopenharmony_ci summary.targets = results 1879750e409Sopenharmony_ci report summary.run 1889750e409Sopenharmony_ci end 1899750e409Sopenharmony_ci 1909750e409Sopenharmony_ci def run_tests(test_files) 1919750e409Sopenharmony_ci report 'Running Unity system tests...' 1929750e409Sopenharmony_ci 1939750e409Sopenharmony_ci # Tack on TEST define for compiling unit tests 1949750e409Sopenharmony_ci load_configuration($cfg_file) 1959750e409Sopenharmony_ci test_defines = ['TEST'] 1969750e409Sopenharmony_ci $cfg['compiler']['defines']['items'] ||= [] 1979750e409Sopenharmony_ci $cfg['compiler']['defines']['items'] << 'TEST' 1989750e409Sopenharmony_ci 1999750e409Sopenharmony_ci include_dirs = local_include_dirs 2009750e409Sopenharmony_ci 2019750e409Sopenharmony_ci # Build and execute each unit test 2029750e409Sopenharmony_ci test_files.each do |test| 2039750e409Sopenharmony_ci obj_list = [] 2049750e409Sopenharmony_ci 2059750e409Sopenharmony_ci unless $cfg['compiler']['aux_sources'].nil? 2069750e409Sopenharmony_ci $cfg['compiler']['aux_sources'].each do |aux| 2079750e409Sopenharmony_ci obj_list << compile(aux, test_defines) 2089750e409Sopenharmony_ci end 2099750e409Sopenharmony_ci end 2109750e409Sopenharmony_ci 2119750e409Sopenharmony_ci # Detect dependencies and build required modules 2129750e409Sopenharmony_ci extract_headers(test).each do |header| 2139750e409Sopenharmony_ci # Compile corresponding source file if it exists 2149750e409Sopenharmony_ci src_file = find_source_file(header, include_dirs) 2159750e409Sopenharmony_ci 2169750e409Sopenharmony_ci obj_list << compile(src_file, test_defines) unless src_file.nil? 2179750e409Sopenharmony_ci end 2189750e409Sopenharmony_ci 2199750e409Sopenharmony_ci # Build the test runner (generate if configured to do so) 2209750e409Sopenharmony_ci test_base = File.basename(test, C_EXTENSION) 2219750e409Sopenharmony_ci 2229750e409Sopenharmony_ci runner_name = test_base + '_Runner.c' 2239750e409Sopenharmony_ci 2249750e409Sopenharmony_ci runner_path = if $cfg['compiler']['runner_path'].nil? 2259750e409Sopenharmony_ci $cfg['compiler']['build_path'] + runner_name 2269750e409Sopenharmony_ci else 2279750e409Sopenharmony_ci $cfg['compiler']['runner_path'] + runner_name 2289750e409Sopenharmony_ci end 2299750e409Sopenharmony_ci 2309750e409Sopenharmony_ci options = $cfg[:unity] 2319750e409Sopenharmony_ci options[:use_param_tests] = test =~ /parameterized/ ? true : false 2329750e409Sopenharmony_ci UnityTestRunnerGenerator.new(options).run(test, runner_path) 2339750e409Sopenharmony_ci obj_list << compile(runner_path, test_defines) 2349750e409Sopenharmony_ci 2359750e409Sopenharmony_ci # Build the test module 2369750e409Sopenharmony_ci obj_list << compile(test, test_defines) 2379750e409Sopenharmony_ci 2389750e409Sopenharmony_ci # Link the test executable 2399750e409Sopenharmony_ci link_it(test_base, obj_list) 2409750e409Sopenharmony_ci 2419750e409Sopenharmony_ci # Execute unit test and generate results file 2429750e409Sopenharmony_ci simulator = build_simulator_fields 2439750e409Sopenharmony_ci executable = $cfg['linker']['bin_files']['destination'] + test_base + $cfg['linker']['bin_files']['extension'] 2449750e409Sopenharmony_ci cmd_str = if simulator.nil? 2459750e409Sopenharmony_ci executable 2469750e409Sopenharmony_ci else 2479750e409Sopenharmony_ci "#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}" 2489750e409Sopenharmony_ci end 2499750e409Sopenharmony_ci output = execute(cmd_str) 2509750e409Sopenharmony_ci test_results = $cfg['compiler']['build_path'] + test_base 2519750e409Sopenharmony_ci if output.match(/OK$/m).nil? 2529750e409Sopenharmony_ci test_results += '.testfail' 2539750e409Sopenharmony_ci else 2549750e409Sopenharmony_ci report output unless $verbose # Verbose already prints this line, as does a failure 2559750e409Sopenharmony_ci test_results += '.testpass' 2569750e409Sopenharmony_ci end 2579750e409Sopenharmony_ci File.open(test_results, 'w') { |f| f.print output } 2589750e409Sopenharmony_ci end 2599750e409Sopenharmony_ci end 2609750e409Sopenharmony_ciend 261