diff --git a/examples/temp_sensor/rakefile_helper.rb b/examples/temp_sensor/rakefile_helper.rb index d1dfcc9..55bea2d 100644 --- a/examples/temp_sensor/rakefile_helper.rb +++ b/examples/temp_sensor/rakefile_helper.rb @@ -24,30 +24,24 @@ module RakefileHelpers def load_configuration(config_file) $cfg_file = config_file - $cfg = load_yaml(File.read("../../test/targets/#{$cfg_file}")) $proj = load_yaml(File.read('./project.yml')) - # Apply project-level paths, overriding the test-system paths in the target file - $cfg['compiler']['source_path'] = $proj[:paths][:source].first - $cfg['compiler']['unit_tests_path'] = $proj[:paths][:test] - $cfg['compiler']['build_path'] = $proj[:project][:build_root] - $cfg['compiler']['object_files']['destination'] = $proj[:project][:build_root] - $cfg['linker']['object_files']['path'] = $proj[:project][:build_root] - $cfg['linker']['bin_files']['destination'] = $proj[:project][:build_root] + unity_target = "../../vendor/unity/test/targets/#{$cfg_file}" + cmock_target = "../../test/targets/#{$cfg_file}" - # Merge includes: preserve any target-specific items (tool paths, local headers), - # then add project.yml paths (| deduplicates) - $cfg['compiler']['includes']['items'] = ($cfg['compiler']['includes']['items'] || []) | $proj[:paths][:include] - - # Merge defines: target-specific first, then project common defines - $cfg['compiler']['defines']['items'] ||= [] - $cfg['compiler']['defines']['items'] |= $proj[:defines][:common] + if File.exist?(unity_target) + $unity_cfg = load_yaml(File.read(unity_target)) + $cmock_cfg = File.exist?(cmock_target) ? load_yaml(File.read(cmock_target)) : {} + else + $unity_cfg = load_yaml(File.read(cmock_target)) + $cmock_cfg = {} + end $colour_output = $proj[:project][:colour] end def configure_clean - CLEAN.include("#{$cfg['compiler']['build_path']}*.*") unless $cfg['compiler']['build_path'].nil? + CLEAN.include("#{$proj[:project][:build_root]}*.*") end def configure_toolchain(config_file = DEFAULT_CONFIG_FILE) @@ -57,15 +51,13 @@ module RakefileHelpers end def unit_test_files - path = $cfg['compiler']['unit_tests_path'] + "Test*#{C_EXTENSION}" + path = $proj[:paths][:test] + "Test*#{C_EXTENSION}" path.tr!('\\', '/') FileList.new(path) end def local_include_dirs - include_dirs = $cfg['compiler']['includes']['items'].dup - include_dirs.delete_if { |dir| dir.is_a?(Array) } - include_dirs + $proj[:paths][:include].reject { |dir| dir.is_a?(Array) } end def extract_headers(filename) @@ -73,9 +65,7 @@ module RakefileHelpers lines = File.readlines(filename) lines.each do |line| m = line.match(/^\s*#include\s+"\s*(.+\.[hH])\s*"/) - unless m.nil? - includes << m[1] - end + includes << m[1] unless m.nil? end includes end @@ -83,9 +73,7 @@ module RakefileHelpers def find_source_file(header, paths) paths.each do |dir| src_file = dir + header.ext(C_EXTENSION) - if File.exist?(src_file) - return src_file - end + return src_file if File.exist?(src_file) end nil end @@ -103,79 +91,85 @@ module RakefileHelpers end end - def squash(prefix, items) - result = '' - items.each { |item| result += " #{prefix}#{tackit(item)}" } - result + # All defines: project common + Unity target + CMock overlay + any extras + def all_defines(extra = []) + (($proj[:defines][:common] || []) + + ($unity_cfg[:defines][:test] || []) + + (($cmock_cfg[:defines] || {})[:test] || []) + + extra).uniq end - def build_compiler_fields - command = tackit($cfg['compiler']['path']) - defines = if $cfg['compiler']['defines']['items'].nil? - '' - else - squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items']) - end - options = squash('', $cfg['compiler']['options']) - includes = squash($cfg['compiler']['includes']['prefix'], $cfg['compiler']['includes']['items']) - includes = includes.gsub(/\\ /, ' ').gsub(/\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR) - { :command => command, :defines => defines, :options => options, :includes => includes } + # Toolchain-specific include paths: Array items in Unity's :paths: :test: + def toolchain_include_paths + if $unity_cfg[:paths] && $unity_cfg[:paths][:test] + $unity_cfg[:paths][:test] + else + [] + end end - def compile(file, _defines = []) - compiler = build_compiler_fields - cmd_str = "#{compiler[:command]}#{compiler[:defines]}#{compiler[:options]}#{compiler[:includes]} #{file} " \ - "#{$cfg['compiler']['object_files']['prefix']}#{$cfg['compiler']['object_files']['destination']}" - obj_file = "#{File.basename(file, C_EXTENSION)}#{$cfg['compiler']['object_files']['extension']}" - execute(cmd_str + obj_file) - obj_file + # Resolve Unity's argument template tokens into a flat argument string. + def build_argument_list(raw_args, toolchain_paths, project_paths, defines, input, output) + result = [] + raw_args.each do |arg| + if arg.is_a?(Array) + result << arg.join + elsif arg.include?('COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE') + toolchain_paths.each { |p| result << "-I\"#{p.is_a?(Array) ? p.join : p}\"" } + elsif arg.include?('COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR') + project_paths.each { |p| result << "-I\"#{p}\"" } + elsif arg.include?('COLLECTION_DEFINES_TEST_AND_VENDOR') + defines.each { |d| result << "-D#{d}" } + else + result << arg.gsub('${1}', input.to_s).gsub('${2}', output.to_s) + end + end + result.join(' ') end - def build_linker_fields - command = tackit($cfg['linker']['path']) - options = if $cfg['linker']['options'].nil? - '' - else - squash('', $cfg['linker']['options']) - end - includes = if $cfg['linker']['includes'].nil? || $cfg['linker']['includes']['items'].nil? - '' - else - squash($cfg['linker']['includes']['prefix'], $cfg['linker']['includes']['items']) - end - includes = includes.gsub(/\\ /, ' ').gsub(/\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR) - { :command => command, :options => options, :includes => includes } + def compile(file, extra_defines = []) + tool = $unity_cfg[:tools][:test_compiler] + ext = $unity_cfg[:extension][:object] + build_root = $proj[:project][:build_root] + obj_file = build_root + File.basename(file, C_EXTENSION) + ext + + cmd_str = "#{tackit(tool[:executable])} #{ + build_argument_list(tool[:arguments], + toolchain_include_paths, + $proj[:paths][:include], + all_defines(extra_defines), + file, obj_file)}" + execute(cmd_str) + File.basename(obj_file) end def link_it(exe_name, obj_list) - linker = build_linker_fields - cmd_str = "#{linker[:command]}#{linker[:includes]} " \ - "#{(obj_list.map { |obj| "#{$cfg['linker']['object_files']['path']}#{obj} " }).join}" \ - "#{$cfg['linker']['bin_files']['prefix']} " \ - "#{$cfg['linker']['bin_files']['destination']}" \ - "#{exe_name}#{$cfg['linker']['bin_files']['extension']} #{linker[:options]}" + tool = $unity_cfg[:tools][:test_linker] + ext = $unity_cfg[:extension][:executable] + build_root = $proj[:project][:build_root] + + input_files = obj_list.uniq.map { |obj| build_root + obj }.join(' ') + output_file = build_root + exe_name + ext + + cmd_str = "#{tackit(tool[:executable])} #{build_argument_list(tool[:arguments], [], [], [], input_files, output_file)}" execute(cmd_str) end def build_simulator_fields - return nil if $cfg['simulator'].nil? + return nil unless $unity_cfg[:tools][:test_fixture] - command = if $cfg['simulator']['path'].nil? - '' - else - "#{tackit($cfg['simulator']['path'])} " - end - pre_support = if $cfg['simulator']['pre_support'].nil? - '' - else - squash('', $cfg['simulator']['pre_support']) - end - post_support = if $cfg['simulator']['post_support'].nil? - '' - else - squash('', $cfg['simulator']['post_support']) - end - { :command => command, :pre_support => pre_support, :post_support => post_support } + tool = $unity_cfg[:tools][:test_fixture] + executable = tackit(tool[:executable]) + raw_args = tool[:arguments] || [] + idx = raw_args.index('${1}') + if idx + pre = raw_args[0...idx].map { |a| a.is_a?(Array) ? a.join : a }.join(' ') + post = raw_args[(idx + 1)..].map { |a| a.is_a?(Array) ? a.join : a }.join(' ') + else + pre = '' + post = raw_args.map { |a| a.is_a?(Array) ? a.join : a }.join(' ') + end + { command: "#{executable} ", pre_support: pre, post_support: post } end def execute(command_string, verbose = true, ok_to_fail = false) @@ -192,7 +186,7 @@ module RakefileHelpers def report_summary summary = UnityTestSummary.new summary.root = HERE - results_glob = "#{$cfg['compiler']['build_path']}*.test*" + results_glob = "#{$proj[:project][:build_root]}*.test*" results_glob.tr!('\\', '/') results = Dir[results_glob] summary.targets = results @@ -203,17 +197,13 @@ module RakefileHelpers def run_tests(test_files) report 'Running system tests...' - # Tack on TEST define for compiling unit tests load_configuration($cfg_file) - test_defines = ['TEST'] - $cfg['compiler']['defines']['items'] = [] if $cfg['compiler']['defines']['items'].nil? - $cfg['compiler']['defines']['items'] << 'TEST' include_dirs = local_include_dirs # Build and execute each unit test test_files.each do |test| - # Detect dependencies and build required required modules + # Detect dependencies and build required modules header_list = (extract_headers(test) + ['cmock.h'] + [($proj[:cmock] || {})[:unity_helper_path]]).compact.uniq header_list.each do |header| # create mocks if needed @@ -221,53 +211,42 @@ module RakefileHelpers require '../../lib/cmock' @cmock ||= CMock.new($proj[:cmock]) - @cmock.setup_mocks([$cfg['compiler']['source_path'] + header.gsub('Mock', '')]) + @cmock.setup_mocks([$proj[:paths][:source].first + header.gsub('Mock', '')]) end - # compile all mocks + # compile all mocks and dependencies obj_list = [] header_list.each do |header| - # compile source file header if it exists src_file = find_source_file(header, include_dirs) - unless src_file.nil? - obj_list << compile(src_file, test_defines) - end + obj_list << compile(src_file, ['TEST']) unless src_file.nil? end - # Build the test runner (generate if configured to do so) - test_base = File.basename(test, C_EXTENSION) + # Build the test runner + test_base = File.basename(test, C_EXTENSION) runner_name = "#{test_base}_Runner.c" - if $cfg['compiler']['runner_path'].nil? - runner_path = "#{$cfg['compiler']['build_path']}#{runner_name}" - test_gen = UnityTestRunnerGenerator.new($cfg) - test_gen.run(test, runner_path) - else - runner_path = $cfg['compiler']['runner_path'] + runner_name - end + runner_path = "#{$proj[:project][:build_root]}#{runner_name}" + UnityTestRunnerGenerator.new({}).run(test, runner_path) - obj_list << compile(runner_path, test_defines) + obj_list << compile(runner_path, ['TEST']) # Build the test module - obj_list << compile(test, test_defines) + obj_list << compile(test, ['TEST']) # Link the test executable link_it(test_base, obj_list) # Execute unit test and generate results file - simulator = build_simulator_fields - executable = $cfg['linker']['bin_files']['destination'] + test_base + $cfg['linker']['bin_files']['extension'] + simulator = build_simulator_fields + build_root = $proj[:project][:build_root] + executable = build_root + test_base + $unity_cfg[:extension][:executable] cmd_str = if simulator.nil? executable else "#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}" end output = execute(cmd_str, true) - test_results = $cfg['compiler']['build_path'] + test_base - test_results += if output.match(/OK$/m).nil? - '.testfail' - else - '.testpass' - end + test_results = build_root + test_base + test_results += output.match(/OK$/m).nil? ? '.testfail' : '.testpass' File.open(test_results, 'w') { |f| f.print output } end end @@ -277,22 +256,19 @@ module RakefileHelpers obj_list = [] load_configuration($cfg_file) - main_path = $cfg['compiler']['source_path'] + main + C_EXTENSION + main_path = $proj[:paths][:source].first + main + C_EXTENSION - # Detect dependencies and build required required modules + # Detect dependencies and build required modules include_dirs = local_include_dirs extract_headers(main_path).each do |header| src_file = find_source_file(header, include_dirs) - unless src_file.nil? - obj_list << compile(src_file) - end + obj_list << compile(src_file) unless src_file.nil? end # Build the main source file - main_base = File.basename(main_path, C_EXTENSION) obj_list << compile(main_path) # Create the executable - link_it(main_base, obj_list) + link_it(File.basename(main_path, C_EXTENSION), obj_list) end end diff --git a/test/project.yml b/test/project.yml index 83c3aa1..9b1123e 100644 --- a/test/project.yml +++ b/test/project.yml @@ -30,5 +30,4 @@ :defines: :common: - CMOCK - - UNITY_SUPPORT_64 diff --git a/test/rakefile b/test/rakefile index 1ccf5e4..c48f1d2 100644 --- a/test/rakefile +++ b/test/rakefile @@ -14,7 +14,7 @@ require './rakefile_helper' include RakefileHelpers -DEFAULT_CONFIG_FILE = 'gcc.yml' +DEFAULT_CONFIG_FILE = 'gcc_64.yml' CMOCK_TEST_ROOT = File.expand_path(File.dirname(__FILE__)) SYSTEM_TEST_SUPPORT_DIRS = [ @@ -30,7 +30,6 @@ end task :prep_system_tests => SYSTEM_TEST_SUPPORT_DIRS -configure_clean configure_toolchain(DEFAULT_CONFIG_FILE) task :default => [:test] @@ -67,7 +66,7 @@ namespace :test do desc "Run C Unit Tests" task :c => [:prep_system_tests] do - unless ($cfg['unsupported'].include? "C") + unless (unsupported_tests.include? "C") build_and_test_c_files end end @@ -75,9 +74,9 @@ namespace :test do desc "Run System Tests" task :system => [:clobber, :prep_system_tests] do #get a list of all system tests, removing unsupported tests for this compiler - sys_unsupported = $cfg['unsupported'].map {|a| 'system/test_interactions/'+a+'.yml'} + sys_unsupported = unsupported_tests.map {|a| 'system/test_interactions/'+a+'.yml'} sys_tests_to_run = FileList['system/test_interactions/*.yml'] - sys_unsupported - compile_unsupported = $cfg['unsupported'].map {|a| SYSTEST_COMPILE_MOCKABLES_PATH+a+'.h'} + compile_unsupported = unsupported_tests.map {|a| SYSTEST_COMPILE_MOCKABLES_PATH+a+'.h'} compile_tests_to_run = FileList[SYSTEST_COMPILE_MOCKABLES_PATH + '*.h'] - compile_unsupported unless (sys_unsupported.empty? and compile_unsupported.empty?) report "\nIgnoring these system tests..." @@ -134,7 +133,7 @@ namespace :style do desc "Attempt to Autocorrect style" task :auto => ['style:clean'] do - report execute("rubocop ../lib ../examples ../config ../scripts --auto-correct --config ../vendor/unity/test/.rubocop.yml", true) + report execute("rubocop ../lib ../examples ../config ../scripts --autocorrect --config ../vendor/unity/test/.rubocop.yml", true) report "Autocorrected What We Could." end diff --git a/test/rakefile_helper.rb b/test/rakefile_helper.rb index 1eb93f5..7f7723e 100644 --- a/test/rakefile_helper.rb +++ b/test/rakefile_helper.rb @@ -31,30 +31,26 @@ module RakefileHelpers def load_configuration(config_file) $cfg_file = config_file - $cfg = load_yaml('./targets/' + $cfg_file) $proj = load_yaml('./project.yml') - # Apply project-level paths, overriding any hardcoded paths in the target file - $cfg['compiler']['source_path'] = $proj[:paths][:source].first - $cfg['compiler']['build_path'] = $proj[:project][:build_root] - $cfg['compiler']['object_files']['destination'] = $proj[:project][:build_root] - $cfg['linker']['object_files']['path'] = $proj[:project][:build_root] - $cfg['linker']['bin_files']['destination'] = $proj[:project][:build_root] + unity_target = "../vendor/unity/test/targets/#{$cfg_file}" + cmock_target = "./targets/#{$cfg_file}" - # Merge includes: preserve any target-specific items (tool paths, local headers), - # then add project.yml paths (| deduplicates) - $cfg['compiler']['includes']['items'] = ($cfg['compiler']['includes']['items'] || []) | $proj[:paths][:include] - - # Merge defines: target-specific first, then project common defines - $cfg['compiler']['defines']['items'] ||= [] - $cfg['compiler']['defines']['items'] |= $proj[:defines][:common] + if File.exist?(unity_target) + # Load Unity base target, then CMock overlay (unsupported list, extra defines) + $unity_cfg = load_yaml(unity_target) + $cmock_cfg = File.exist?(cmock_target) ? load_yaml(cmock_target) : {} + else + # CMock-only target (no Unity equivalent); it uses Unity format directly + $unity_cfg = load_yaml(cmock_target) + $cmock_cfg = {} + end $colour_output = $proj[:project][:colour] end def configure_clean - CLEAN.include(SYSTEST_GENERATED_FILES_PATH + '*.*') - CLEAN.include(SYSTEST_BUILD_FILES_PATH + '*.*') + CLEAN.include($proj[:project][:build_root] + '*.*') end def configure_toolchain(config_file) @@ -63,9 +59,7 @@ module RakefileHelpers end def get_local_include_dirs - include_dirs = $cfg['compiler']['includes']['items'].dup - include_dirs.delete_if {|dir| dir.is_a?(Array)} - return include_dirs + $proj[:paths][:include].reject { |dir| dir.is_a?(Array) } end def extract_headers(filename) @@ -73,100 +67,123 @@ module RakefileHelpers lines = File.readlines(filename) lines.each do |line| m = line.match(/^\s*#include\s+\"\s*(.+\.[hH])\s*\"/) - if not m.nil? - includes << m[1] - end + includes << m[1] unless m.nil? end - includes << File.basename(filename,".c").slice(5,256) + "_unity_helper.h" + includes << File.basename(filename, ".c").slice(5, 256) + "_unity_helper.h" return includes end def find_source_file(header, paths) paths.each do |dir| src_file = dir + header.ext(C_EXTENSION) - if (File.exist?(src_file)) - return src_file + return src_file if File.exist?(src_file) + end + nil + end + + def tackit(strings) + case strings + when Array + "\"#{strings.join}\"" + when /^-/ + strings + when /\s/ + "\"#{strings}\"" + else + strings + end + end + + # All defines: project common + Unity target + CMock overlay + any extras + def all_defines(extra = []) + (($proj[:defines][:common] || []) + + ($unity_cfg[:defines][:test] || []) + + (($cmock_cfg[:defines] || {})[:test] || []) + + extra).uniq + end + + # Toolchain-specific include paths: Array items in Unity's :paths: :test: + # (e.g., IAR compiler include directories encoded as path-concatenation arrays) + def toolchain_include_paths + ($unity_cfg[:paths][:test] || []).select { |p| p.is_a?(Array) } + end + + # Returns the unsupported test list, regardless of whether it came from + # a CMock overlay or a CMock-only target file. + def unsupported_tests + $cmock_cfg[:unsupported] || $unity_cfg[:unsupported] || [] + end + + # Resolve Unity's argument template tokens and produce a flat argument string. + # COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE → -I per toolchain path (Arrays from :paths: :test:) + # COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR → -I per project include path + # COLLECTION_DEFINES_TEST_AND_VENDOR → -D per define + # ${1} → input file(s) + # ${2} → output file + def build_argument_list(raw_args, toolchain_paths, project_paths, defines, input, output) + result = [] + raw_args.each do |arg| + if arg.is_a?(Array) + result << arg.join + elsif arg.include?('COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE') + toolchain_paths.each { |p| result << "-I\"#{p.is_a?(Array) ? p.join : p}\"" } + elsif arg.include?('COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR') + project_paths.each { |p| result << "-I\"#{p}\"" } + elsif arg.include?('COLLECTION_DEFINES_TEST_AND_VENDOR') + defines.each { |d| result << "-D#{d}" } + else + result << arg.gsub('${1}', input.to_s).gsub('${2}', output.to_s) end end - return nil + result.join(' ') end - def squash(prefix, items) - result = '' - items.each { |item| result += " #{prefix}#{tackit(item)}" } - return result - end + def compile(file, extra_defines = []) + tool = $unity_cfg[:tools][:test_compiler] + ext = $unity_cfg[:extension][:object] + build_root = $proj[:project][:build_root] + obj_file = build_root + File.basename(file, C_EXTENSION) + ext - def build_compiler_fields - command = tackit($cfg['compiler']['path']) - if $cfg['compiler']['defines']['items'].nil? - defines = '' - else - defines = squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items']) - end - options = squash('', $cfg['compiler']['options']) - includes = squash($cfg['compiler']['includes']['prefix'], $cfg['compiler']['includes']['items']) - includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR) - return {:command => command, :defines => defines, :options => options, :includes => includes} - end - - def compile(file, defines=[]) - compiler = build_compiler_fields - cmd_str = "#{compiler[:command]}#{compiler[:defines]}#{defines.inject(''){|all, a| ' -D'+a+all }}#{compiler[:options]}#{compiler[:includes]} #{file} " + - "#{$cfg['compiler']['object_files']['prefix']}#{$cfg['compiler']['object_files']['destination']}" - obj_file = "#{File.basename(file, C_EXTENSION)}#{$cfg['compiler']['object_files']['extension']}" - execute(cmd_str + obj_file) - return obj_file - end - - def build_linker_fields - command = tackit($cfg['linker']['path']) - if $cfg['linker']['options'].nil? - options = '' - else - options = squash('', $cfg['linker']['options']) - end - if ($cfg['linker']['includes'].nil? || $cfg['linker']['includes']['items'].nil?) - includes = '' - else - includes = squash($cfg['linker']['includes']['prefix'], $cfg['linker']['includes']['items']) - end - includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR) - return {:command => command, :options => options, :includes => includes} + cmd_str = tackit(tool[:executable]) + ' ' + + build_argument_list(tool[:arguments], + toolchain_include_paths, + $proj[:paths][:include], + all_defines(extra_defines), + file, obj_file) + execute(cmd_str) + File.basename(obj_file) end def link_it(exe_name, obj_list) - linker = build_linker_fields - cmd_str = "#{linker[:command]}#{linker[:options]}#{linker[:includes]} " + - (obj_list.map{|obj|"#{$cfg['linker']['object_files']['path']}#{obj} "}).uniq.join + - $cfg['linker']['bin_files']['prefix'] + ' ' + - $cfg['linker']['bin_files']['destination'] + - exe_name + $cfg['linker']['bin_files']['extension'] + tool = $unity_cfg[:tools][:test_linker] + ext = $unity_cfg[:extension][:executable] + build_root = $proj[:project][:build_root] + + input_files = obj_list.uniq.map { |obj| build_root + obj }.join(' ') + output_file = build_root + exe_name + ext + + cmd_str = tackit(tool[:executable]) + ' ' + + build_argument_list(tool[:arguments], [], [], [], input_files, output_file) execute(cmd_str) end def build_simulator_fields - return nil if $cfg['simulator'].nil? - if $cfg['simulator']['path'].nil? - command = '' + return nil unless $unity_cfg[:tools][:test_fixture] + tool = $unity_cfg[:tools][:test_fixture] + executable = tackit(tool[:executable]) + raw_args = tool[:arguments] || [] + idx = raw_args.index('${1}') + if idx + pre = raw_args[0...idx].map { |a| a.is_a?(Array) ? a.join : a }.join(' ') + post = raw_args[(idx + 1)..].map { |a| a.is_a?(Array) ? a.join : a }.join(' ') else - command = (tackit($cfg['simulator']['path']) + ' ') + pre = '' + post = raw_args.map { |a| a.is_a?(Array) ? a.join : a }.join(' ') end - if $cfg['simulator']['pre_support'].nil? - pre_support = '' - else - pre_support = squash('', $cfg['simulator']['pre_support']) - end - if $cfg['simulator']['post_support'].nil? - post_support = '' - else - post_support = squash('', $cfg['simulator']['post_support']) - end - return {:command => command, :pre_support => pre_support, :post_support => post_support} + { command: "#{executable} ", pre_support: pre, post_support: post } end def execute(command_string, verbose=true, raise_on_failure=true) - #report command_string output = `#{command_string}`.chomp report(output) if (verbose && !output.nil? && (output.length > 0)) if ($?.exitstatus != 0) and (raise_on_failure) @@ -175,19 +192,6 @@ module RakefileHelpers return output end - def tackit(strings) - case(strings) - when Array - "\"#{strings.join}\"" - when /^-/ - strings - when /\s/ - "\"#{strings}\"" - else - strings - end - end - def run_astyle(style_what) report "Styling C Code..." command = "AStyle " \ @@ -203,7 +207,7 @@ module RakefileHelpers def report_summary summary = UnityTestSummary.new summary.root = File.expand_path(File.dirname(__FILE__)) + '/' - results_glob = "#{$cfg['compiler']['build_path']}*.test*" + results_glob = "#{$proj[:project][:build_root]}*.test*" results_glob.gsub!(/\\/, '/') results = Dir[results_glob] summary.targets = results @@ -218,7 +222,6 @@ module RakefileHelpers test_files = FileList.new(SYSTEST_GENERATED_FILES_PATH + 'test*.c') load_configuration($cfg_file) - $cfg['compiler']['defines']['items'] = [] if $cfg['compiler']['defines']['items'].nil? include_dirs = get_local_include_dirs @@ -232,25 +235,23 @@ module RakefileHelpers report "Executing system tests in #{File.basename(test)}..." - # Detect dependencies and build required required modules + # Detect dependencies and build required modules extract_headers(test).each do |header| # Generate any needed mocks - if header =~ /^mock_(.*)\.h/i + if header =~ /^mock_(.*)\.[hH]$/i module_name = $1 cmock = CMock.new(SYSTEST_GENERATED_FILES_PATH + cmock_config) - cmock.setup_mocks("#{$cfg['compiler']['source_path']}#{module_name}.h") + cmock.setup_mocks("#{$proj[:paths][:source].first}#{module_name}.h") end # Compile corresponding source file if it exists src_file = find_source_file(header, include_dirs) - if !src_file.nil? - obj_list << compile(src_file) - end + obj_list << compile(src_file) unless src_file.nil? end # Generate and build the test suite runner runner_name = test_base + '_runner.c' - runner_path = $cfg['compiler']['source_path'] + runner_name + runner_path = $proj[:paths][:source].first + runner_name UnityTestRunnerGenerator.new(SYSTEST_GENERATED_FILES_PATH + cmock_config).run(test, runner_path) obj_list << compile(runner_path) @@ -261,15 +262,17 @@ module RakefileHelpers link_it(test_base, obj_list) # Execute unit test and generate results file - simulator = build_simulator_fields - executable = $cfg['linker']['bin_files']['destination'] + test_base + $cfg['linker']['bin_files']['extension'] - if simulator.nil? - cmd_str = executable - else - cmd_str = "#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}" - end + simulator = build_simulator_fields + ext = $unity_cfg[:extension][:executable] + build_root = $proj[:project][:build_root] + executable = build_root + test_base + ext + cmd_str = if simulator.nil? + executable + else + "#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}" + end output = execute(cmd_str, false, false) - test_results = $cfg['compiler']['build_path'] + test_base + RESULT_EXTENSION + test_results = build_root + test_base + RESULT_EXTENSION File.open(test_results, 'w') { |f| f.print output } end @@ -284,10 +287,8 @@ module RakefileHelpers test_file = 'test_' + File.basename(test_case).ext(C_EXTENSION) result_file = test_file.ext(RESULT_EXTENSION) - test_results = File.readlines(SYSTEST_BUILD_FILES_PATH + result_file).reject {|line| line.size < 10 } # we're rejecting lines that are too short to be realistic, which handles line ending problems + test_results = File.readlines(SYSTEST_BUILD_FILES_PATH + result_file).reject {|line| line.size < 10 } tests.each_with_index do |test, index| - # compare test's intended pass/fail state with pass/fail state in actual results; - # if they don't match, the system test has failed this_failed = case(test[:pass]) when :ignore (test_results[index] =~ /:IGNORE/).nil? @@ -301,7 +302,6 @@ module RakefileHelpers test_results[index] =~ /test#{index+1}:(.+)/ failure_messages << "#{test_file}:test#{index+1}:should #{test[:should]}:#{$1}" end - # some tests have additional requirements to check for (checking the actual output message) if (test[:verify_error]) and not (test_results[index] =~ /test#{index+1}:.*#{test[:verify_error]}/) total_failures += 1 failure_messages << "#{test_file}:test#{index+1}:should #{test[:should]}:should have output matching '#{test[:verify_error]}' but was '#{test_results[index]}'" @@ -318,13 +318,10 @@ module RakefileHelpers if (failure_messages.size > 0) report 'System test failures:' - failure_messages.each do |failure| - report failure - end + failure_messages.each { |failure| report failure } end report '' - return total_failures end @@ -349,9 +346,7 @@ module RakefileHelpers def run_system_test_compilations(mockables) load '../lib/cmock.rb' - load_configuration($cfg_file) - $cfg['compiler']['defines']['items'] = [] if $cfg['compiler']['defines']['items'].nil? report "\n" report "------------------------------------\n" @@ -367,9 +362,7 @@ module RakefileHelpers def run_system_test_profiles(mockables) load '../lib/cmock.rb' - load_configuration($cfg_file) - $cfg['compiler']['defines']['items'] = [] if $cfg['compiler']['defines']['items'].nil? report "\n" report "--------------------------\n" @@ -392,23 +385,21 @@ module RakefileHelpers report "----------------\n" report "UNIT TEST C CODE\n" report "----------------\n" - errors = false + ext = $unity_cfg[:extension][:executable] + build_root = $proj[:project][:build_root] FileList.new("c/*.yml").each do |yaml_file| test = load_yaml(yaml_file) report "\nTesting #{yaml_file.sub('.yml','')}" report "(#{test[:options].join(', ')})" test[:files].each { |f| compile(f, test[:options]) } - obj_files = test[:files].map { |f| f.gsub!(/.*\//,'').gsub!(C_EXTENSION, $cfg['compiler']['object_files']['extension']) } + obj_files = test[:files].map { |f| f.gsub!(/.*\//,'').gsub!(C_EXTENSION, $unity_cfg[:extension][:object]) } link_it('TestCMockC', obj_files) - if $cfg['simulator'].nil? - execute($cfg['linker']['bin_files']['destination'] + 'TestCMockC' + $cfg['linker']['bin_files']['extension']) + simulator = build_simulator_fields + executable = build_root + 'TestCMockC' + ext + if simulator.nil? + execute(executable) else - execute(tackit($cfg['simulator']['path'].join) + ' ' + - $cfg['simulator']['pre_support'].map{|o| tackit(o)}.join(' ') + ' ' + - $cfg['linker']['bin_files']['destination'] + - 'TestCMockC' + - $cfg['linker']['bin_files']['extension'] + ' ' + - $cfg['simulator']['post_support'].map{|o| tackit(o)}.join(' ') ) + execute("#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}") end end end @@ -418,8 +409,8 @@ module RakefileHelpers report "-----------------\n" report "VALIDATE EXAMPLES\n" report "-----------------\n" - [ "cd #{File.join("..","examples","make_example")} && make clean && make setup && make test", - "cd #{File.join("..","examples","temp_sensor")} && rake ci" + [ "cd #{File.join("..", "examples", "make_example")} && make clean && make setup && make test", + "cd #{File.join("..", "examples", "temp_sensor")} && rake ci" ].each do |cmd| report "Testing '#{cmd}'" execute(cmd, verbose, raise_on_failure) @@ -431,4 +422,3 @@ module RakefileHelpers exit(-1) end end - diff --git a/test/system/systest_generator.rb b/test/system/systest_generator.rb index b82c52a..4568802 100644 --- a/test/system/systest_generator.rb +++ b/test/system/systest_generator.rb @@ -151,7 +151,7 @@ class SystemTestGenerator require 'cmock.rb' cmock = CMock.new(GENERATED_PATH + namix + 'cmock' + YAML_EXTENSION) - cmock.setup_skeletons("#{$cfg['compiler']['source_path']}#{name}.h") + cmock.setup_skeletons("#{$proj[:paths][:source].first}#{name}.h") end def write_header_file(filename, upcase_name, include_list=[]) diff --git a/test/targets/clang_strict.yml b/test/targets/clang_strict.yml index f2c4d93..9063f8c 100644 --- a/test/targets/clang_strict.yml +++ b/test/targets/clang_strict.yml @@ -5,73 +5,13 @@ # SPDX-License-Identifier: MIT # ========================================================================= ---- -compiler: - path: clang - options: - - '-c' - - '-Wall' - - '-Wextra' - - '-Werror' - #- '-Wcast-qual' - - '-Wconversion' - - '-Wtautological-compare' - #- '-Wtautological-pointer-compare' - - '-Wdisabled-optimization' - - '-Wformat=2' - - '-Winit-self' - - '-Winline' - - '-Winvalid-pch' - - '-Wmissing-declarations' - - '-Wmissing-include-dirs' - - '-Wmissing-prototypes' - - '-Wnonnull' - - '-Wpacked' - - '-Wpointer-arith' - - '-Wredundant-decls' - - '-Wswitch-default' - - '-Wstrict-aliasing=2' - - '-Wstrict-overflow=5' - - '-Wuninitialized' - - '-Wunused' - - '-Wunreachable-code' - - '-Wreturn-type' - - '-Wshadow' - - '-Wundef' - - '-Wwrite-strings' - - '-Wbad-function-cast' - - '-Wno-missing-prototypes' #we've been lazy about things like setUp and tearDown - - '-Wno-invalid-token-paste' - - '-fms-extensions' - - '-fno-omit-frame-pointer' - #- '-ffloat-store' - - '-fno-common' - - '-fstrict-aliasing' - - '-std=gnu99' - - '-pedantic' - - '-O0' - includes: - prefix: '-I' - defines: - prefix: '-D' - items: - - CMOCK - - 'UNITY_SUPPORT_64' - - 'UNITY_POINTER_WIDTH=64' - object_files: - prefix: '-o' - extension: '.o' +# CMock overlay for vendor/unity/test/targets/clang_strict.yml +# Only contains additions not present in the Unity base target. -linker: - path: gcc - options: - - -lm - object_files: - extension: '.o' - bin_files: - prefix: '-o' - extension: '.exe' +:defines: + :test: + - UNITY_POINTER_WIDTH=64 -unsupported: +:unsupported: - out_of_memory - callingconv diff --git a/test/targets/gcc.yml b/test/targets/gcc.yml index 5eace39..93e518d 100644 --- a/test/targets/gcc.yml +++ b/test/targets/gcc.yml @@ -6,40 +6,40 @@ # ========================================================================= --- -compiler: - path: gcc - options: - - '-c' - - '-Wall' - - '-Wextra' - - '-Wunused-parameter' - - '-Wno-address' - - '-Wno-invalid-token-paste' - - '-std=c99' - - '-pedantic' - - '-O0' - includes: - prefix: '-I' - defines: - prefix: '-D' - items: - - CMOCK - - 'UNITY_SUPPORT_64' - object_files: - prefix: '-o' - extension: '.o' - -linker: - path: gcc - options: - - -lm - object_files: - extension: '.o' - bin_files: - prefix: '-o' - extension: '.exe' - -unsupported: +colour: true +:tools: + :test_compiler: + :name: compiler + :executable: gcc + :arguments: + - "-c" + - "-Wall" + - "-Wextra" + - "-Wunused-parameter" + - "-Wno-address" + - "-Wno-invalid-token-paste" + - "-std=c99" + - "-pedantic" + - "-O0" + - '-I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE' + - '-I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR' + - "-D$: COLLECTION_DEFINES_TEST_AND_VENDOR" + - "${1}" + - "-o ${2}" + :test_linker: + :name: linker + :executable: gcc + :arguments: + - "${1}" + - "-lm" + - "-o ${2}" +:extension: + :object: ".o" + :executable: ".exe" +:defines: + :test: + - UNITY_SUPPORT_64 +:unsupported: - out_of_memory - unity_64bit_support - callingconv diff --git a/test/targets/gcc_64.yml b/test/targets/gcc_64.yml index b1ff927..61a9de9 100644 --- a/test/targets/gcc_64.yml +++ b/test/targets/gcc_64.yml @@ -5,41 +5,13 @@ # SPDX-License-Identifier: MIT # ========================================================================= ---- -compiler: - path: gcc - options: - - '-c' - - '-m64' - - '-Wall' - - '-Wunused-parameter' - - '-Wno-address' - - '-Wno-invalid-token-paste' - - '-std=c99' - - '-pedantic' - includes: - prefix: '-I' - defines: - prefix: '-D' - items: - - CMOCK - - 'UNITY_SUPPORT_64' - - 'UNITY_POINTER_WIDTH=64' - object_files: - prefix: '-o' - extension: '.o' +# CMock overlay for vendor/unity/test/targets/gcc_64.yml +# Only contains additions not present in the Unity base target. -linker: - path: gcc - options: - - -lm - - '-m64' - object_files: - extension: '.o' - bin_files: - prefix: '-o' - extension: '.exe' +:defines: + :test: + - UNITY_POINTER_WIDTH=64 -unsupported: +:unsupported: - out_of_memory - callingconv diff --git a/test/targets/gcc_tiny.yml b/test/targets/gcc_tiny.yml index 3d10c89..a8064da 100644 --- a/test/targets/gcc_tiny.yml +++ b/test/targets/gcc_tiny.yml @@ -6,41 +6,41 @@ # ========================================================================= --- -compiler: - path: gcc - options: - - '-c' - - '-Wall' - - '-Wextra' - - '-Wunused-parameter' - - '-Wno-address' - - '-Wno-invalid-token-paste' - - '-std=c99' - - '-pedantic' - - '-O0' - includes: - prefix: '-I' - defines: - prefix: '-D' - items: - - CMOCK - - 'CMOCK_MEM_STATIC' - - 'CMOCK_MEM_SIZE=1024' - object_files: - prefix: '-o' - extension: '.o' - -linker: - path: gcc - options: - - -lm - object_files: - extension: '.o' - bin_files: - prefix: '-o' - extension: '.exe' - -unsupported: +colour: true +:tools: + :test_compiler: + :name: compiler + :executable: gcc + :arguments: + - "-c" + - "-Wall" + - "-Wextra" + - "-Wunused-parameter" + - "-Wno-address" + - "-Wno-invalid-token-paste" + - "-std=c99" + - "-pedantic" + - "-O0" + - '-I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE' + - '-I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR' + - "-D$: COLLECTION_DEFINES_TEST_AND_VENDOR" + - "${1}" + - "-o ${2}" + :test_linker: + :name: linker + :executable: gcc + :arguments: + - "${1}" + - "-lm" + - "-o ${2}" +:extension: + :object: ".o" + :executable: ".exe" +:defines: + :test: + - CMOCK_MEM_STATIC + - CMOCK_MEM_SIZE=1024 +:unsupported: - all_plugins_but_other_limits - all_plugins_coexist - array_and_pointer_handling diff --git a/test/targets/iar_arm_v4.yml b/test/targets/iar_arm_v4.yml index 76c1bd1..2b46d6b 100644 --- a/test/targets/iar_arm_v4.yml +++ b/test/targets/iar_arm_v4.yml @@ -5,90 +5,10 @@ # SPDX-License-Identifier: MIT # ========================================================================= -tools_root: &tools_root 'C:\Program Files\IAR Systems\Embedded Workbench 4.0\' -compiler: - path: [*tools_root, 'arm\bin\iccarm.exe'] - options: - - --dlib_config - - [*tools_root, 'arm\lib\dl4tptinl8n.h'] - - -z3 - - --no_cse - - --no_unroll - - --no_inline - - --no_code_motion - - --no_tbaa - - --no_clustering - - --no_scheduling - - --debug - - --cpu_mode thumb - - --endian little - - --cpu ARM7TDMI - - --stack_align 4 - - --interwork - - -e - - --silent - - --warnings_are_errors - - --fpu None - #We are supressing some warnings here because we test CMock against some questionable code to make sure it still works - - --diag_suppress Pa050 - - --diag_suppress Pe191 - - --diag_suppress=Pe494 - - --diag_suppress=Pe083 - includes: - prefix: '-I' - items: - - [*tools_root, 'arm\inc\'] - defines: - prefix: '-D' - items: - - CMOCK - object_files: - prefix: '-o' - extension: '.r79' +# CMock overlay for vendor/unity/test/targets/iar_arm_v4.yml +# Only contains additions not present in the Unity base target. -linker: - path: [*tools_root, 'common\bin\xlink.exe'] - options: - - -rt - - [*tools_root, 'arm\lib\dl4tptinl8n.r79'] - - -D_L_EXTMEM_START=0 - - -D_L_EXTMEM_SIZE=0 - - -D_L_HEAP_SIZE=120 - - -D_L_STACK_SIZE=32 - - -e_small_write=_formatted_write - - -s - - __program_start - - '-f iar\iar_v4\Resource\at91SAM7X256_FLASH.xcl' - includes: - prefix: '-I' - items: - - [*tools_root, 'arm\config\'] - - [*tools_root, 'arm\lib\'] - object_files: - extension: '.r79' - bin_files: - prefix: '-o' - extension: '.d79' - -simulator: - path: [*tools_root, 'common\bin\CSpyBat.exe'] - pre_support: - - --silent - - [*tools_root, 'arm\bin\armproc.dll'] - - [*tools_root, 'arm\bin\armsim.dll'] - post_support: - - --plugin - - [*tools_root, 'arm\bin\armbat.dll'] - - --macro - - 'iar\iar_v4\Resource\SAM7_SIM.mac' - - --backend - - -B - - -p - - [*tools_root, 'arm\config\ioat91sam7X256.ddf'] - - -d - - sim - -unsupported: +:unsupported: - out_of_memory - nonstandard_parsed_stuff_1 - const diff --git a/test/targets/iar_arm_v5.yml b/test/targets/iar_arm_v5.yml index 0c57dea..443e5b2 100644 --- a/test/targets/iar_arm_v5.yml +++ b/test/targets/iar_arm_v5.yml @@ -5,79 +5,10 @@ # SPDX-License-Identifier: MIT # ========================================================================= -tools_root: &tools_root 'C:\Program Files\IAR Systems\Embedded Workbench 5.3\' -compiler: - path: [*tools_root, 'arm\bin\iccarm.exe'] - options: - - --dlib_config - - [*tools_root, 'arm\inc\DLib_Config_Normal.h'] - - --no_cse - - --no_unroll - - --no_inline - - --no_code_motion - - --no_tbaa - - --no_clustering - - --no_scheduling - - --debug - - --cpu_mode thumb - - --endian=little - - --cpu=ARM7TDMI - - --interwork - - --warnings_are_errors - - --fpu=None - - -e - - -On - #We are supressing some warnings here because we test CMock against some questionable code to make sure it still works - - --diag_suppress=Pa050 - - --diag_suppress=Pe191 - - --diag_suppress=Pe494 - - --diag_suppress=Pe083 - includes: - prefix: '-I' - items: - - [*tools_root, 'arm\inc\'] - - '.\iar\iar_v5\incIAR\' - defines: - prefix: '-D' - items: - - CMOCK - object_files: - prefix: '-o' - extension: '.r79' +# CMock overlay for vendor/unity/test/targets/iar_arm_v5.yml +# Only contains additions not present in the Unity base target. -linker: - path: [*tools_root, 'arm\bin\ilinkarm.exe'] - options: - - --redirect _Printf=_PrintfLarge - - --redirect _Scanf=_ScanfSmall - - --semihosting - - --entry __iar_program_start - - --config iar\iar_v5\Resource\at91SAM7X256_RAM.icf - object_files: - extension: '.o' - bin_files: - prefix: '-o' - extension: '.out' - -simulator: - path: [*tools_root, 'common\bin\CSpyBat.exe'] - pre_support: - - --silent - - [*tools_root, 'arm\bin\armproc.dll'] - - [*tools_root, 'arm\bin\armsim.dll'] - post_support: - - --plugin - - [*tools_root, 'arm\bin\armbat.dll'] - - --macro - - 'iar\iar_v5\Resource\SAM7_SIM.mac' - - --backend - - -B - - -p - - [*tools_root, 'arm\config\debugger\Atmel\ioat91sam7X256.ddf'] - - -d - - sim - -unsupported: +:unsupported: - out_of_memory - nonstandard_parsed_stuff_1 - const