diff --git a/examples/gcc.yml b/examples/gcc.yml new file mode 100644 index 0000000..8afb404 --- /dev/null +++ b/examples/gcc.yml @@ -0,0 +1,42 @@ +compiler: + path: gcc + source_path: 'src/' + unit_tests_path: &unit_tests_path 'test/' + build_path: &build_path 'build/' + options: + - -c + includes: + prefix: '-I' + items: + - 'src/' + - '../src/' + - '../vendor/unity/src/' + - '../vendor/unity/examples/helper/' + - 'mocks/' + - *unit_tests_path + defines: + prefix: '-D' + items: + - __monitor + object_files: + prefix: '-o' + extension: '.o' + destination: *build_path +linker: + path: gcc + options: + - -lm + includes: + prefix: '-I' + object_files: + path: *build_path + extension: '.o' + bin_files: + prefix: '-o' + extension: '.exe' + destination: *build_path +:cmock: + :plugins: [] + :includes: + - Types.h + \ No newline at end of file diff --git a/examples/iar_v4.yml b/examples/iar_v4.yml new file mode 100644 index 0000000..78a7c7b --- /dev/null +++ b/examples/iar_v4.yml @@ -0,0 +1,91 @@ +tools_root: &tools_root 'C:\Program Files\IAR Systems\Embedded Workbench 4.0 Kickstart\' +compiler: + path: [*tools_root, 'arm\bin\iccarm.exe'] + source_path: 'src\' + unit_tests_path: &unit_tests_path 'test\' + build_path: &build_path 'build\' + 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 + - --diag_suppress Pa050 + includes: + prefix: '-I' + items: + - 'src/' + - '../src/' + - '../vendor/unity/src/' + - '../vendor/unity/examples/helper/' + - 'mocks/' + - [*tools_root, 'arm\inc\'] + - *unit_tests_path + defines: + prefix: '-D' + items: + object_files: + prefix: '-o' + extension: '.r79' + destination: *build_path +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 + - [*tools_root, '\arm\config\lnkarm.xcl'] + includes: + prefix: '-I' + items: + - [*tools_root, 'arm\config\'] + - [*tools_root, 'arm\lib\'] + object_files: + path: *build_path + extension: '.r79' + bin_files: + prefix: '-o' + extension: '.d79' + destination: *build_path +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'] + - --backend + - -B + - -p + - [*tools_root, 'arm\config\ioat91sam7X256.ddf'] + - -d + - sim +:cmock: + :plugins: [] + :includes: + - Types.h + \ No newline at end of file diff --git a/examples/iar_v5.yml b/examples/iar_v5.yml new file mode 100644 index 0000000..d99c5ed --- /dev/null +++ b/examples/iar_v5.yml @@ -0,0 +1,80 @@ +tools_root: &tools_root 'C:\Program Files\IAR Systems\Embedded Workbench 5.0 Kickstart\' +compiler: + path: [*tools_root, 'arm\bin\iccarm.exe'] + source_path: 'src\' + unit_tests_path: &unit_tests_path 'test\' + build_path: &build_path 'build\' + 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 + - --diag_suppress=Pa050 + - --diag_suppress=Pe111 + - -e + - -On + includes: + prefix: '-I' + items: + - 'src/' + - '../src/' + - '../vendor/unity/src/' + - '../vendor/unity/examples/helper/' + - 'mocks/' + - [*tools_root, 'arm\inc\'] + - *unit_tests_path + defines: + prefix: '-D' + items: + object_files: + prefix: '-o' + extension: '.r79' + destination: *build_path +linker: + path: [*tools_root, 'arm\bin\ilinkarm.exe'] + options: + - --redirect _Printf=_PrintfLarge + - --redirect _Scanf=_ScanfSmall + - --semihosting + - --entry __iar_program_start + - --config + - [*tools_root, 'arm\config\generic.icf'] + object_files: + path: *build_path + extension: '.o' + bin_files: + prefix: '-o' + extension: '.out' + destination: *build_path +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'] + - --backend + - -B + - -p + - [*tools_root, 'arm\config\debugger\atmel\ioat91sam7X256.ddf'] + - -d + - sim +:cmock: + :plugins: [] + :includes: + - Types.h + \ No newline at end of file diff --git a/examples/rakefile.rb b/examples/rakefile.rb new file mode 100644 index 0000000..c5851bc --- /dev/null +++ b/examples/rakefile.rb @@ -0,0 +1,33 @@ +HERE = File.expand_path(File.dirname(__FILE__)) + '/' + +#require HERE + 'config/environment' +require 'rake' +require 'rake/clean' +require 'rake/testtask' +require 'rakefile_helper' + +include RakefileHelpers + +# Load default configuration, for now +DEFAULT_CONFIG_FILE = 'gcc.yml' +configure_toolchain(DEFAULT_CONFIG_FILE) + +task :unit do + run_tests(get_unit_test_files) +end + +desc "Generate test summary" +task :summary do + report_summary +end + +desc "Build and test Unity" +task :all => [:clean, :unit, :summary] +task :default => [:clobber, :all] +task :ci => [:default] +task :cruise => [:default] + +desc "Load configuration" +task :config, :config_file do |t, args| + configure_toolchain(args[:config_file]) +end diff --git a/examples/rakefile_helper.rb b/examples/rakefile_helper.rb new file mode 100644 index 0000000..956bf87 --- /dev/null +++ b/examples/rakefile_helper.rb @@ -0,0 +1,265 @@ +require 'yaml' +require 'fileutils' +require '../vendor/unity/auto/unity_test_summary' +require '../vendor/unity/auto/generate_test_runner' +require '../vendor/unity/auto/colour_reporter' + +module RakefileHelpers + + C_EXTENSION = '.c' + + def load_configuration(config_file) + $cfg_file = config_file + $cfg = YAML.load(File.read($cfg_file)) + end + + def configure_clean + CLEAN.include($cfg['compiler']['build_path'] + '*.*') unless $cfg['compiler']['build_path'].nil? + end + + def configure_toolchain(config_file=DEFAULT_CONFIG_FILE) + config_file += '.yml' unless config_file =~ /\.yml$/ + load_configuration(config_file) + configure_clean + end + + def get_unit_test_files + path = $cfg['compiler']['unit_tests_path'] + 'Test*' + C_EXTENSION + path.gsub!(/\\/, '/') + FileList.new(path) + 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 + end + + def extract_headers(filename) + includes = [] + lines = File.readlines(filename) + lines.each do |line| + m = line.match(/#include \"(.*)\"/) + if not m.nil? + includes << m[1] + end + end + return includes + end + + def find_source_file(header, paths) + paths.each do |dir| + src_file = dir + header.ext(C_EXTENSION) + if (File.exists?(src_file)) + return src_file + end + end + return nil + end + + def tackit(strings) + if strings.is_a?(Array) + result = "\"#{strings.join}\"" + else + result = strings + end + return result + end + + def squash(prefix, items) + result = '' + items.each { |item| result += " #{prefix}#{tackit(item)}" } + return result + end + + 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]}#{compiler[:options]}#{compiler[:includes]} #{file} " + + "#{$cfg['compiler']['object_files']['prefix']}#{$cfg['compiler']['object_files']['destination']}" + + "#{File.basename(file, C_EXTENSION)}#{$cfg['compiler']['object_files']['extension']}" + execute(cmd_str) + 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} + end + + def link(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} "}).join + + $cfg['linker']['bin_files']['prefix'] + ' ' + + $cfg['linker']['bin_files']['destination'] + + exe_name + $cfg['linker']['bin_files']['extension'] + execute(cmd_str) + end + + def build_simulator_fields + return nil if $cfg['simulator'].nil? + if $cfg['simulator']['path'].nil? + command = '' + else + command = (tackit($cfg['simulator']['path']) + ' ') + 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} + end + + def execute(command_string, verbose=true) + report command_string + output = `#{command_string}`.chomp + report(output) if (verbose && !output.nil? && (output.length > 0)) + if $?.exitstatus != 0 + raise "Command failed. (Returned #{$?.exitstatus})" + end + return output + end + + def report_summary + summary = UnityTestSummary.new + summary.set_root_path(HERE) + results_glob = "#{$cfg['compiler']['build_path']}*.test*" + results_glob.gsub!(/\\/, '/') + results = Dir[results_glob] + summary.set_targets(results) + report summary.run + raise "There were failures" if (summary.failures > 0) + end + + 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 = get_local_include_dirs + + # Build and execute each unit test + test_files.each do |test| + obj_list = [] + + # Detect dependencies and build required required modules + header_list = extract_headers(test) + ['cmock.h'] + header_list.each do |header| + + #create mocks if needed + if (header =~ /Mock/) + require "../lib/cmock.rb" + @cmock ||= CMock.new($cfg_file) + @cmock.setup_mocks(['src/'+header.gsub('Mock','')]) + end + + # Compile corresponding source file if it exists + src_file = find_source_file(header, include_dirs) + if !src_file.nil? + compile(src_file, test_defines) + obj_list << header.ext($cfg['compiler']['object_files']['extension']) + end + end + + # Build the test runner (generate if configured to do so) + 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 + test_gen.run(test, runner_path) + else + runner_path = $cfg['compiler']['runner_path'] + runner_name + end + + compile(runner_path, test_defines) + obj_list << runner_name.ext($cfg['compiler']['object_files']['extension']) + + # Build the test module + compile(test, test_defines) + obj_list << test_base.ext($cfg['compiler']['object_files']['extension']) + + # Link the test executable + link(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 + output = execute(cmd_str) + test_results = $cfg['compiler']['build_path'] + test_base + if output.match(/OK$/m).nil? + test_results += '.testfail' + else + test_results += '.testpass' + end + File.open(test_results, 'w') { |f| f.print output } + end + end + + def build_application(main) + + report "Building application..." + + obj_list = [] + load_configuration($cfg_file) + main_path = $cfg['compiler']['source_path'] + main + C_EXTENSION + + # Detect dependencies and build required required modules + include_dirs = get_local_include_dirs + extract_headers(main_path).each do |header| + src_file = find_source_file(header, include_dirs) + if !src_file.nil? + compile(src_file) + obj_list << header.ext($cfg['compiler']['object_files']['extension']) + end + end + + # Build the main source file + main_base = File.basename(main_path, C_EXTENSION) + compile(main_path) + obj_list << main_base.ext($cfg['compiler']['object_files']['extension']) + + # Create the executable + link(main_base, obj_list) + end + +end diff --git a/examples/src/AdcModel.c b/examples/src/AdcModel.c index 4db67e3..b5b47f3 100644 --- a/examples/src/AdcModel.c +++ b/examples/src/AdcModel.c @@ -1,4 +1,3 @@ -#include "Types.h" #include "AdcModel.h" #include "TaskScheduler.h" #include "TemperatureCalculator.h" diff --git a/examples/src/AdcModel.h b/examples/src/AdcModel.h index 6dfb722..61f270b 100644 --- a/examples/src/AdcModel.h +++ b/examples/src/AdcModel.h @@ -1,6 +1,8 @@ #ifndef _ADCMODEL_H #define _ADCMODEL_H +#include "Types.h" + bool AdcModel_DoGetSample(void); void AdcModel_ProcessInput(uint16 millivolts); diff --git a/examples/src/TimerInterruptHandler.c b/examples/src/TimerInterruptHandler.c index 5327fa7..368f2ea 100644 --- a/examples/src/TimerInterruptHandler.c +++ b/examples/src/TimerInterruptHandler.c @@ -4,12 +4,12 @@ static uint32 systemTime; -__monitor void Timer_SetSystemTime(uint32 time) +void Timer_SetSystemTime(uint32 time) { systemTime = time; } -__monitor uint32 Timer_GetSystemTime(void) +uint32 Timer_GetSystemTime(void) { return systemTime; } diff --git a/examples/src/TimerInterruptHandler.h b/examples/src/TimerInterruptHandler.h index 7e94b85..1d4fda9 100644 --- a/examples/src/TimerInterruptHandler.h +++ b/examples/src/TimerInterruptHandler.h @@ -1,8 +1,10 @@ #ifndef _TIMERINTERRUPTHANDLER_H #define _TIMERINTERRUPTHANDLER_H -__monitor void Timer_SetSystemTime(uint32 time); -__monitor uint32 Timer_GetSystemTime(void); +#include "Types.h" + +void Timer_SetSystemTime(uint32 time); +uint32 Timer_GetSystemTime(void); void Timer_InterruptHandler(void); #endif // _TIMERINTERRUPTHANDLER_H diff --git a/examples/src/UsartHardware.h b/examples/src/UsartHardware.h index 4e2df2c..3261c82 100644 --- a/examples/src/UsartHardware.h +++ b/examples/src/UsartHardware.h @@ -1,6 +1,8 @@ #ifndef _USARTHARDWARE_H #define _USARTHARDWARE_H +#include "Types.h" + void UsartHardware_Init(uint8 baudRateRegisterSetting); void UsartHardware_TransmitString(char* data); diff --git a/examples/src/UsartModel.h b/examples/src/UsartModel.h index f2e1b73..724f548 100644 --- a/examples/src/UsartModel.h +++ b/examples/src/UsartModel.h @@ -1,6 +1,8 @@ #ifndef _USARTMODEL_H #define _USARTMODEL_H +#include "Types.h" + uint8 UsartModel_GetBaudRateRegisterSetting(void); char* UsartModel_GetFormattedTemperature(void); char* UsartModel_GetWakeupMessage(void); diff --git a/test/system/test_interactions/all_plugins_but_other_limits.yml b/test/system/test_interactions/all_plugins_but_other_limits.yml index fc927ed..052f883 100644 --- a/test/system/test_interactions/all_plugins_but_other_limits.yml +++ b/test/system/test_interactions/all_plugins_but_other_limits.yml @@ -292,7 +292,7 @@ } - :pass: TRUE - :should: 'that we can properly ignore first function but the other will work properly' + :should: 'properly ignore first function but the other will work properly' :code: | test() { @@ -304,7 +304,7 @@ } - :pass: TRUE - :should: 'that we can properly ignore last function but the other will work properly' + :should: 'properly ignore last function but the other will work properly' :code: | test() { @@ -315,7 +315,7 @@ } - :pass: TRUE - :should: 'that we are ok if we ignore a call each because we are counting calls' + :should: 'be ok if we ignore a call each because we are counting calls' :code: | test() { @@ -327,7 +327,7 @@ } - :pass: FALSE - :should: 'that we fail if we do not ignore a call once because we are counting calls' + :should: 'fail if we do not ignore a call once because we are counting calls' :code: | test() {