diff --git a/tests/unity/.travis.yml b/tests/unity/.travis.yml index edf25ee..8ae9fa0 100644 --- a/tests/unity/.travis.yml +++ b/tests/unity/.travis.yml @@ -12,7 +12,9 @@ matrix: before_install: - if [ "$TRAVIS_OS_NAME" == "osx" ]; then rvm install 2.1 && rvm use 2.1 && ruby -v; fi - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install --assume-yes --quiet gcc-multilib; fi -install: gem install rspec +install: + - gem install rspec + - gem install rubocop script: - cd test && rake ci - make -s diff --git a/tests/unity/README.md b/tests/unity/README.md index 11759c8..17ab574 100644 --- a/tests/unity/README.md +++ b/tests/unity/README.md @@ -2,7 +2,7 @@ Unity Test API ============== [![Unity Build Status](https://api.travis-ci.org/ThrowTheSwitch/Unity.png?branch=master)](https://travis-ci.org/ThrowTheSwitch/Unity) -__Copyright (c) 2007 - 2014 Unity Project by Mike Karlesky, Mark VanderVoord, and Greg Williams__ +__Copyright (c) 2007 - 2017 Unity Project by Mike Karlesky, Mark VanderVoord, and Greg Williams__ Running Tests ------------- @@ -109,14 +109,6 @@ Compares two integers for equality and display errors as hexadecimal. Like the you can specify the size... here the size will also effect how many nibbles are shown (for example, `HEX16` will show 4 nibbles). - _ARRAY - -You can append `_ARRAY` to any of these macros to make an array comparison of that type. Here you will -need to care a bit more about the actual size of the value being checked. You will also specify an -additional argument which is the number of elements to compare. For example: - - TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, elements) - TEST_ASSERT_EQUAL(expected, actual) Another way of calling TEST_ASSERT_EQUAL_INT @@ -126,6 +118,23 @@ Another way of calling TEST_ASSERT_EQUAL_INT Asserts that the actual value is within plus or minus delta of the expected value. This also comes in size specific variants. +Arrays +------ + + _ARRAY + +You can append `_ARRAY` to any of these macros to make an array comparison of that type. Here you will +need to care a bit more about the actual size of the value being checked. You will also specify an +additional argument which is the number of elements to compare. For example: + + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, elements) + + _EACH_EQUAL + +Another array comparison option is to check that EVERY element of an array is equal to a single expected +value. You do this by specifying the EACH_EQUAL macro. For example: + + TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, elements) Numerical Assertions: Bitwise ----------------------------- diff --git a/tests/unity/auto/colour_prompt.rb b/tests/unity/auto/colour_prompt.rb index 8adab6e..0f1dc4e 100644 --- a/tests/unity/auto/colour_prompt.rb +++ b/tests/unity/auto/colour_prompt.rb @@ -4,63 +4,62 @@ # [Released under MIT License. Please refer to license.txt for details] # ========================================== -if RUBY_PLATFORM =~/(win|w)32$/ - begin - require 'Win32API' - rescue LoadError - puts "ERROR! \"Win32API\" library not found" - puts "\"Win32API\" is required for colour on a windows machine" - puts " try => \"gem install Win32API\" on the command line" - puts - end - # puts +if RUBY_PLATFORM =~ /(win|w)32$/ + begin + require 'Win32API' + rescue LoadError + puts 'ERROR! "Win32API" library not found' + puts '"Win32API" is required for colour on a windows machine' + puts ' try => "gem install Win32API" on the command line' + puts + end + # puts # puts 'Windows Environment Detected...' - # puts 'Win32API Library Found.' - # puts + # puts 'Win32API Library Found.' + # puts end class ColourCommandLine def initialize - if RUBY_PLATFORM =~/(win|w)32$/ - get_std_handle = Win32API.new("kernel32", "GetStdHandle", ['L'], 'L') - @set_console_txt_attrb = - Win32API.new("kernel32","SetConsoleTextAttribute",['L','N'], 'I') - @hout = get_std_handle.call(-11) - end + return unless RUBY_PLATFORM =~ /(win|w)32$/ + get_std_handle = Win32API.new('kernel32', 'GetStdHandle', ['L'], 'L') + @set_console_txt_attrb = + Win32API.new('kernel32', 'SetConsoleTextAttribute', %w(L N), 'I') + @hout = get_std_handle.call(-11) end def change_to(new_colour) - if RUBY_PLATFORM =~/(win|w)32$/ - @set_console_txt_attrb.call(@hout,self.win32_colour(new_colour)) + if RUBY_PLATFORM =~ /(win|w)32$/ + @set_console_txt_attrb.call(@hout, win32_colour(new_colour)) else - "\033[30;#{posix_colour(new_colour)};22m" - end + "\033[30;#{posix_colour(new_colour)};22m" + end end def win32_colour(colour) case colour - when :black then 0 - when :dark_blue then 1 - when :dark_green then 2 - when :dark_cyan then 3 - when :dark_red then 4 - when :dark_purple then 5 - when :dark_yellow, :narrative then 6 - when :default_white, :default, :dark_white then 7 - when :silver then 8 - when :blue then 9 - when :green, :success then 10 - when :cyan, :output then 11 - when :red, :failure then 12 - when :purple then 13 - when :yellow then 14 - when :white then 15 - else - 0 + when :black then 0 + when :dark_blue then 1 + when :dark_green then 2 + when :dark_cyan then 3 + when :dark_red then 4 + when :dark_purple then 5 + when :dark_yellow, :narrative then 6 + when :default_white, :default, :dark_white then 7 + when :silver then 8 + when :blue then 9 + when :green, :success then 10 + when :cyan, :output then 11 + when :red, :failure then 12 + when :purple then 13 + when :yellow then 14 + when :white then 15 + else + 0 end end - def posix_colour(colour) + def posix_colour(colour) # ANSI Escape Codes - Foreground colors # | Code | Color | # | 39 | Default foreground color | @@ -81,35 +80,39 @@ class ColourCommandLine # | 96 | Light cyan | # | 97 | White | - case colour - when :black then 30 - when :red, :failure then 31 - when :green, :success then 32 - when :yellow then 33 - when :blue, :narrative then 34 - when :purple, :magenta then 35 - when :cyan, :output then 36 - when :white, :default_white then 37 - when :default then 39 - else - 39 + case colour + when :black then 30 + when :red, :failure then 31 + when :green, :success then 32 + when :yellow then 33 + when :blue, :narrative then 34 + when :purple, :magenta then 35 + when :cyan, :output then 36 + when :white, :default_white then 37 + when :default then 39 + else + 39 end end def out_c(mode, colour, str) case RUBY_PLATFORM - when /(win|w)32$/ - change_to(colour) - $stdout.puts str if mode == :puts - $stdout.print str if mode == :print - change_to(:default_white) - else - $stdout.puts("#{change_to(colour)}#{str}\033[0m") if mode == :puts - $stdout.print("#{change_to(colour)}#{str}\033[0m") if mode == :print - end + when /(win|w)32$/ + change_to(colour) + $stdout.puts str if mode == :puts + $stdout.print str if mode == :print + change_to(:default_white) + else + $stdout.puts("#{change_to(colour)}#{str}\033[0m") if mode == :puts + $stdout.print("#{change_to(colour)}#{str}\033[0m") if mode == :print + end end end # ColourCommandLine -def colour_puts(role,str) ColourCommandLine.new.out_c(:puts, role, str) end -def colour_print(role,str) ColourCommandLine.new.out_c(:print, role, str) end +def colour_puts(role, str) + ColourCommandLine.new.out_c(:puts, role, str) +end +def colour_print(role, str) + ColourCommandLine.new.out_c(:print, role, str) +end diff --git a/tests/unity/auto/colour_reporter.rb b/tests/unity/auto/colour_reporter.rb index 5aa1d27..bb1fbfc 100644 --- a/tests/unity/auto/colour_reporter.rb +++ b/tests/unity/auto/colour_reporter.rb @@ -2,38 +2,38 @@ # Unity Project - A Test Framework for C # Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams # [Released under MIT License. Please refer to license.txt for details] -# ========================================== +# ========================================== require "#{File.expand_path(File.dirname(__FILE__))}/colour_prompt" $colour_output = true def report(message) - if not $colour_output + if !$colour_output $stdout.puts(message) else - message = message.join('\n') if (message.class == Array) + message = message.join('\n') if message.class == Array message.each_line do |line| line.chomp! - colour = case(line) - when /(?:total\s+)?tests:?\s+(\d+)\s+(?:total\s+)?failures:?\s+\d+\s+Ignored:?/i - ($1.to_i == 0) ? :green : :red - when /PASS/ - :green - when /^OK$/ - :green - when /(?:FAIL|ERROR)/ - :red - when /IGNORE/ - :yellow - when /^(?:Creating|Compiling|Linking)/ - :white - else - :silver - end + colour = case line + when /(?:total\s+)?tests:?\s+(\d+)\s+(?:total\s+)?failures:?\s+\d+\s+Ignored:?/i + Regexp.last_match(1).to_i.zero? ? :green : :red + when /PASS/ + :green + when /^OK$/ + :green + when /(?:FAIL|ERROR)/ + :red + when /IGNORE/ + :yellow + when /^(?:Creating|Compiling|Linking)/ + :white + else + :silver + end colour_puts(colour, line) end end $stdout.flush $stderr.flush -end \ No newline at end of file +end diff --git a/tests/unity/auto/generate_module.rb b/tests/unity/auto/generate_module.rb index 0fbaf55..ade4f1a 100644 --- a/tests/unity/auto/generate_module.rb +++ b/tests/unity/auto/generate_module.rb @@ -12,8 +12,8 @@ require 'rubygems' require 'fileutils' require 'pathname' -#TEMPLATE_TST -TEMPLATE_TST ||= %q[#include "unity.h" +# TEMPLATE_TST +TEMPLATE_TST ||= '#include "unity.h" %2$s#include "%1$s.h" void setUp(void) @@ -28,115 +28,118 @@ void test_%1$s_NeedToImplement(void) { TEST_IGNORE_MESSAGE("Need to Implement %1$s"); } -] +'.freeze -#TEMPLATE_SRC -TEMPLATE_SRC ||= %q[%2$s#include "%1$s.h" -] +# TEMPLATE_SRC +TEMPLATE_SRC ||= '%2$s#include "%1$s.h" +'.freeze -#TEMPLATE_INC -TEMPLATE_INC ||= %q[#ifndef _%3$s_H +# TEMPLATE_INC +TEMPLATE_INC ||= '#ifndef _%3$s_H #define _%3$s_H %2$s #endif // _%3$s_H -] +'.freeze class UnityModuleGenerator - ############################ - def initialize(options=nil) - + def initialize(options = nil) here = File.expand_path(File.dirname(__FILE__)) + '/' @options = UnityModuleGenerator.default_options - case(options) - when NilClass then @options - when String then @options.merge!(UnityModuleGenerator.grab_config(options)) - when Hash then @options.merge!(options) - else raise "If you specify arguments, it should be a filename or a hash of options" + case options + when NilClass then @options + when String then @options.merge!(UnityModuleGenerator.grab_config(options)) + when Hash then @options.merge!(options) + else raise 'If you specify arguments, it should be a filename or a hash of options' end # Create default file paths if none were provided - @options[:path_src] = here + "../src/" if @options[:path_src].nil? + @options[:path_src] = here + '../src/' if @options[:path_src].nil? @options[:path_inc] = @options[:path_src] if @options[:path_inc].nil? - @options[:path_tst] = here + "../test/" if @options[:path_tst].nil? - @options[:path_src] += '/' unless (@options[:path_src][-1] == 47) - @options[:path_inc] += '/' unless (@options[:path_inc][-1] == 47) - @options[:path_tst] += '/' unless (@options[:path_tst][-1] == 47) + @options[:path_tst] = here + '../test/' if @options[:path_tst].nil? + @options[:path_src] += '/' unless @options[:path_src][-1] == 47 + @options[:path_inc] += '/' unless @options[:path_inc][-1] == 47 + @options[:path_tst] += '/' unless @options[:path_tst][-1] == 47 - #Built in patterns - @patterns = { 'src' => {'' => { :inc => [] } }, - 'test'=> {'' => { :inc => [] } }, - 'dh' => {'Driver' => { :inc => [create_filename('%1$s','Hardware.h')] }, - 'Hardware' => { :inc => [] } - }, - 'dih' => {'Driver' => { :inc => [create_filename('%1$s','Hardware.h'), create_filename('%1$s','Interrupt.h')] }, - 'Interrupt'=> { :inc => [create_filename('%1$s','Hardware.h')] }, - 'Hardware' => { :inc => [] } - }, - 'mch' => {'Model' => { :inc => [] }, - 'Conductor'=> { :inc => [create_filename('%1$s','Model.h'), create_filename('%1$s','Hardware.h')] }, - 'Hardware' => { :inc => [] } - }, - 'mvp' => {'Model' => { :inc => [] }, - 'Presenter'=> { :inc => [create_filename('%1$s','Model.h'), create_filename('%1$s','View.h')] }, - 'View' => { :inc => [] } - } - } + # Built in patterns + @patterns = { + 'src' => { + '' => { inc: [] } + }, + 'test' => { + '' => { inc: [] } + }, + 'dh' => { + 'Driver' => { inc: [create_filename('%1$s', 'Hardware.h')] }, + 'Hardware' => { inc: [] } + }, + 'dih' => { + 'Driver' => { inc: [create_filename('%1$s', 'Hardware.h'), create_filename('%1$s', 'Interrupt.h')] }, + 'Interrupt' => { inc: [create_filename('%1$s', 'Hardware.h')] }, + 'Hardware' => { inc: [] } + }, + 'mch' => { + 'Model' => { inc: [] }, + 'Conductor' => { inc: [create_filename('%1$s', 'Model.h'), create_filename('%1$s', 'Hardware.h')] }, + 'Hardware' => { inc: [] } + }, + 'mvp' => { + 'Model' => { inc: [] }, + 'Presenter' => { inc: [create_filename('%1$s', 'Model.h'), create_filename('%1$s', 'View.h')] }, + 'View' => { inc: [] } + } + } end ############################ def self.default_options { - :pattern => "src", - :includes => - { - :src => [], - :inc => [], - :tst => [], + pattern: 'src', + includes: { + src: [], + inc: [], + tst: [] }, - :update_svn => false, - :boilerplates => {}, - :test_prefix => 'Test', - :mock_prefix => 'Mock', + update_svn: false, + boilerplates: {}, + test_prefix: 'Test', + mock_prefix: 'Mock' } end ############################ def self.grab_config(config_file) - options = self.default_options - unless (config_file.nil? or config_file.empty?) + options = default_options + unless config_file.nil? || config_file.empty? require 'yaml' yaml_guts = YAML.load_file(config_file) options.merge!(yaml_guts[:unity] || yaml_guts[:cmock]) raise "No :unity or :cmock section found in #{config_file}" unless options end - return(options) + options end ############################ - def files_to_operate_on(module_name, pattern=nil) - #strip any leading path information from the module name and save for later + def files_to_operate_on(module_name, pattern = nil) + # strip any leading path information from the module name and save for later subfolder = File.dirname(module_name) module_name = File.basename(module_name) - #create triad definition + # create triad definition prefix = @options[:test_prefix] || 'Test' - triad = [ { :ext => '.c', :path => @options[:path_src], :prefix => "", :template => TEMPLATE_SRC, :inc => :src, :boilerplate => @options[:boilerplates][:src] }, - { :ext => '.h', :path => @options[:path_inc], :prefix => "", :template => TEMPLATE_INC, :inc => :inc, :boilerplate => @options[:boilerplates][:inc] }, - { :ext => '.c', :path => @options[:path_tst], :prefix => prefix, :template => TEMPLATE_TST, :inc => :tst, :boilerplate => @options[:boilerplates][:tst] }, - ] + triad = [{ ext: '.c', path: @options[:path_src], prefix: '', template: TEMPLATE_SRC, inc: :src, boilerplate: @options[:boilerplates][:src] }, + { ext: '.h', path: @options[:path_inc], prefix: '', template: TEMPLATE_INC, inc: :inc, boilerplate: @options[:boilerplates][:inc] }, + { ext: '.c', path: @options[:path_tst], prefix: prefix, template: TEMPLATE_TST, inc: :tst, boilerplate: @options[:boilerplates][:tst] }] - #prepare the pattern for use + # prepare the pattern for use pattern = (pattern || @options[:pattern] || 'src').downcase patterns = @patterns[pattern] raise "ERROR: The design pattern '#{pattern}' specified isn't one that I recognize!" if patterns.nil? - #single file patterns (currently just 'test') can reject the other parts of the triad - if (pattern == 'test') - triad.reject!{|v| v[:inc] != :tst } - end + # single file patterns (currently just 'test') can reject the other parts of the triad + triad.select! { |v| v[:inc] == :tst } if pattern == 'test' # Assemble the path/names of the files we need to work with. files = [] @@ -145,26 +148,26 @@ class UnityModuleGenerator submodule_name = create_filename(module_name, pattern_file) filename = cfg[:prefix] + submodule_name + cfg[:ext] files << { - :path => (Pathname.new("#{cfg[:path]}#{subfolder}") + filename).cleanpath, - :name => submodule_name, - :template => cfg[:template], - :boilerplate => cfg[:boilerplate], - :includes => case(cfg[:inc]) - when :src then (@options[:includes][:src] || []) | pattern_traits[:inc].map{|f| f % [module_name]} - when :inc then (@options[:includes][:inc] || []) - when :tst then (@options[:includes][:tst] || []) | pattern_traits[:inc].map{|f| "#{@options[:mock_prefix]}#{f}" % [module_name]} - end + path: (Pathname.new("#{cfg[:path]}#{subfolder}") + filename).cleanpath, + name: submodule_name, + template: cfg[:template], + boilerplate: cfg[:boilerplate], + includes: case (cfg[:inc]) + when :src then (@options[:includes][:src] || []) | (pattern_traits[:inc].map { |f| format(f, module_name) }) + when :inc then (@options[:includes][:inc] || []) + when :tst then (@options[:includes][:tst] || []) | (pattern_traits[:inc].map { |f| format("#{@options[:mock_prefix]}#{f}", module_name) }) + end } end end - return files + files end ############################ - def create_filename(part1, part2="") + def create_filename(part1, part2 = '') if part2.empty? - case(@options[:naming]) + case (@options[:naming]) when 'bumpy' then part1 when 'camel' then part1 when 'snake' then part1.downcase @@ -172,49 +175,45 @@ class UnityModuleGenerator else part1.downcase end else - case(@options[:naming]) + case (@options[:naming]) when 'bumpy' then part1 + part2 when 'camel' then part1 + part2 - when 'snake' then part1.downcase + "_" + part2.downcase - when 'caps' then part1.upcase + "_" + part2.upcase - else part1.downcase + "_" + part2.downcase + when 'snake' then part1.downcase + '_' + part2.downcase + when 'caps' then part1.upcase + '_' + part2.upcase + else part1.downcase + '_' + part2.downcase end end end ############################ - def generate(module_name, pattern=nil) - + def generate(module_name, pattern = nil) files = files_to_operate_on(module_name, pattern) - #Abort if all of the module files already exist + # Abort if all of the module files already exist all_files_exist = true files.each do |file| - if not File.exist?(file[:path]) - all_files_exist = false - end + all_files_exist = false unless File.exist?(file[:path]) end raise "ERROR: File #{files[0][:name]} already exists. Exiting." if all_files_exist # Create Source Modules - files.each_with_index do |file, i| + files.each_with_index do |file, _i| # If this file already exists, don't overwrite it. if File.exist?(file[:path]) puts "File #{file[:path]} already exists!" next end # Create the path first if necessary. - FileUtils.mkdir_p(File.dirname(file[:path]), :verbose => false) + FileUtils.mkdir_p(File.dirname(file[:path]), verbose: false) File.open(file[:path], 'w') do |f| f.write("#{file[:boilerplate]}\n" % [file[:name]]) unless file[:boilerplate].nil? - f.write(file[:template] % [ file[:name], - file[:includes].map{|f| "#include \"#{f}\"\n"}.join, - file[:name].upcase ] - ) + f.write(file[:template] % [file[:name], + file[:includes].map { |ff| "#include \"#{ff}\"\n" }.join, + file[:name].upcase]) end - if (@options[:update_svn]) + if @options[:update_svn] `svn add \"#{file[:path]}\"` - if $?.exitstatus == 0 + if $!.exitstatus.zero? puts "File #{file[:path]} created and added to source control" else puts "File #{file[:path]} created but FAILED adding to source control!" @@ -227,8 +226,7 @@ class UnityModuleGenerator end ############################ - def destroy(module_name, pattern=nil) - + def destroy(module_name, pattern = nil) files_to_operate_on(module_name, pattern).each do |filespec| file = filespec[:path] if File.exist?(file) @@ -243,66 +241,65 @@ class UnityModuleGenerator puts "File #{file} does not exist so cannot be removed." end end - puts "Destroy Complete" + puts 'Destroy Complete' end - end ############################ -#Handle As Command Line If Called That Way -if ($0 == __FILE__) +# Handle As Command Line If Called That Way +if $0 == __FILE__ destroy = false - options = { } + options = {} module_name = nil # Parse the command line parameters. ARGV.each do |arg| - case(arg) - when /^-d/ then destroy = true - when /^-u/ then options[:update_svn] = true - when /^-p\"?(\w+)\"?/ then options[:pattern] = $1 - when /^-s\"?(.+)\"?/ then options[:path_src] = $1 - when /^-i\"?(.+)\"?/ then options[:path_inc] = $1 - when /^-t\"?(.+)\"?/ then options[:path_tst] = $1 - when /^-n\"?(.+)\"?/ then options[:naming] = $1 - when /^-y\"?(.+)\"?/ then options = UnityModuleGenerator.grab_config($1) - when /^(\w+)/ - raise "ERROR: You can't have more than one Module name specified!" unless module_name.nil? - module_name = arg - when /^-(h|-help)/ - ARGV = [] - else - raise "ERROR: Unknown option specified '#{arg}'" + case arg + when /^-d/ then destroy = true + when /^-u/ then options[:update_svn] = true + when /^-p\"?(\w+)\"?/ then options[:pattern] = Regexp.last_match(1) + when /^-s\"?(.+)\"?/ then options[:path_src] = Regexp.last_match(1) + when /^-i\"?(.+)\"?/ then options[:path_inc] = Regexp.last_match(1) + when /^-t\"?(.+)\"?/ then options[:path_tst] = Regexp.last_match(1) + when /^-n\"?(.+)\"?/ then options[:naming] = Regexp.last_match(1) + when /^-y\"?(.+)\"?/ then options = UnityModuleGenerator.grab_config(Regexp.last_match(1)) + when /^(\w+)/ + raise "ERROR: You can't have more than one Module name specified!" unless module_name.nil? + module_name = arg + when /^-(h|-help)/ + ARGV = [].freeze + else + raise "ERROR: Unknown option specified '#{arg}'" end end - if (!ARGV[0]) - puts [ "\nGENERATE MODULE\n-------- ------", - "\nUsage: ruby generate_module [options] module_name", - " -i\"include\" sets the path to output headers to 'include' (DEFAULT ../src)", - " -s\"../src\" sets the path to output source to '../src' (DEFAULT ../src)", - " -t\"C:/test\" sets the path to output source to 'C:/test' (DEFAULT ../test)", - " -p\"MCH\" sets the output pattern to MCH.", - " dh - driver hardware.", - " dih - driver interrupt hardware.", - " mch - model conductor hardware.", - " mvp - model view presenter.", - " src - just a source module, header and test. (DEFAULT)", - " test - just a test file.", - " -d destroy module instead of creating it.", - " -n\"camel\" sets the file naming convention.", - " bumpy - BumpyCaseFilenames.", - " camel - camelCaseFilenames.", - " snake - snake_case_filenames. (DEFAULT)", - " caps - CAPS_CASE_FILENAMES.", - " -u update subversion too (requires subversion command line)", - " -y\"my.yml\" selects a different yaml config file for module generation", - "" ].join("\n") + unless ARGV[0] + puts ["\nGENERATE MODULE\n-------- ------", + "\nUsage: ruby generate_module [options] module_name", + " -i\"include\" sets the path to output headers to 'include' (DEFAULT ../src)", + " -s\"../src\" sets the path to output source to '../src' (DEFAULT ../src)", + " -t\"C:/test\" sets the path to output source to 'C:/test' (DEFAULT ../test)", + ' -p"MCH" sets the output pattern to MCH.', + ' dh - driver hardware.', + ' dih - driver interrupt hardware.', + ' mch - model conductor hardware.', + ' mvp - model view presenter.', + ' src - just a source module, header and test. (DEFAULT)', + ' test - just a test file.', + ' -d destroy module instead of creating it.', + ' -n"camel" sets the file naming convention.', + ' bumpy - BumpyCaseFilenames.', + ' camel - camelCaseFilenames.', + ' snake - snake_case_filenames. (DEFAULT)', + ' caps - CAPS_CASE_FILENAMES.', + ' -u update subversion too (requires subversion command line)', + ' -y"my.yml" selects a different yaml config file for module generation', + ''].join("\n") exit end - raise "ERROR: You must have a Module name specified! (use option -h for help)" if module_name.nil? - if (destroy) + raise 'ERROR: You must have a Module name specified! (use option -h for help)' if module_name.nil? + if destroy UnityModuleGenerator.new(options).destroy(module_name) else UnityModuleGenerator.new(options).generate(module_name) diff --git a/tests/unity/auto/generate_test_runner.rb b/tests/unity/auto/generate_test_runner.rb index 8e8e5bb..2c5e56a 100644 --- a/tests/unity/auto/generate_test_runner.rb +++ b/tests/unity/auto/generate_test_runner.rb @@ -4,75 +4,70 @@ # [Released under MIT License. Please refer to license.txt for details] # ========================================== -$QUICK_RUBY_VERSION = RUBY_VERSION.split('.').inject(0){|vv,v| vv * 100 + v.to_i } -File.expand_path(File.join(File.dirname(__FILE__),'colour_prompt')) +File.expand_path(File.join(File.dirname(__FILE__), 'colour_prompt')) class UnityTestRunnerGenerator - def initialize(options = nil) @options = UnityTestRunnerGenerator.default_options - case(options) - when NilClass then @options - when String then @options.merge!(UnityTestRunnerGenerator.grab_config(options)) - when Hash then @options.merge!(options) - else raise "If you specify arguments, it should be a filename or a hash of options" + case options + when NilClass then @options + when String then @options.merge!(UnityTestRunnerGenerator.grab_config(options)) + when Hash then @options.merge!(options) + else raise 'If you specify arguments, it should be a filename or a hash of options' end require "#{File.expand_path(File.dirname(__FILE__))}/type_sanitizer" end def self.default_options { - :includes => [], - :defines => [], - :plugins => [], - :framework => :unity, - :test_prefix => "test|spec|should", - :setup_name => "setUp", - :teardown_name => "tearDown", - :main_name => "main", #set to :auto to automatically generate each time - :main_export_decl => "", - :cmdline_args => false, - :use_param_tests => false, + includes: [], + defines: [], + plugins: [], + framework: :unity, + test_prefix: 'test|spec|should', + mock_prefix: 'Mock', + setup_name: 'setUp', + teardown_name: 'tearDown', + main_name: 'main', # set to :auto to automatically generate each time + main_export_decl: '', + cmdline_args: false, + use_param_tests: false } end def self.grab_config(config_file) - options = self.default_options - unless (config_file.nil? or config_file.empty?) + options = default_options + unless config_file.nil? || config_file.empty? require 'yaml' yaml_guts = YAML.load_file(config_file) options.merge!(yaml_guts[:unity] || yaml_guts[:cmock]) raise "No :unity or :cmock section found in #{config_file}" unless options end - return(options) + options end - def run(input_file, output_file, options=nil) - tests = [] - testfile_includes = [] - used_mocks = [] - + def run(input_file, output_file, options = nil) @options.merge!(options) unless options.nil? - module_name = File.basename(input_file) - #pull required data from source file + # pull required data from source file source = File.read(input_file) - source = source.force_encoding("ISO-8859-1").encode("utf-8", :replace => nil) if ($QUICK_RUBY_VERSION > 10900) + source = source.force_encoding('ISO-8859-1').encode('utf-8', replace: nil) tests = find_tests(source) headers = find_includes(source) testfile_includes = (headers[:local] + headers[:system]) used_mocks = find_mocks(testfile_includes) testfile_includes = (testfile_includes - used_mocks) - testfile_includes.delete_if{|inc| inc =~ /(unity|cmock)/} + testfile_includes.delete_if { |inc| inc =~ /(unity|cmock)/ } - #build runner file + # build runner file generate(input_file, output_file, tests, used_mocks, testfile_includes) - #determine which files were used to return them + # determine which files were used to return them all_files_used = [input_file, output_file] - all_files_used += testfile_includes.map {|filename| filename + '.c'} unless testfile_includes.empty? + all_files_used += testfile_includes.map { |filename| filename + '.c' } unless testfile_includes.empty? all_files_used += @options[:includes] unless @options[:includes].empty? - return all_files_used.uniq + all_files_used += headers[:linkonly] unless headers[:linkonly].empty? + all_files_used.uniq end def generate(input_file, output_file, tests, used_mocks, testfile_includes) @@ -80,15 +75,16 @@ class UnityTestRunnerGenerator create_header(output, used_mocks, testfile_includes) create_externs(output, tests, used_mocks) create_mock_management(output, used_mocks) - create_suite_setup_and_teardown(output) + create_suite_setup(output) + create_suite_teardown(output) create_reset(output, used_mocks) create_main(output, input_file, tests, used_mocks) end - if (@options[:header_file] && !@options[:header_file].empty?) - File.open(@options[:header_file], 'w') do |output| - create_h_file(output, @options[:header_file], tests, testfile_includes, used_mocks) - end + return unless @options[:header_file] && !@options[:header_file].empty? + + File.open(@options[:header_file], 'w') do |output| + create_h_file(output, @options[:header_file], tests, testfile_includes, used_mocks) end end @@ -96,103 +92,102 @@ class UnityTestRunnerGenerator tests_and_line_numbers = [] source_scrubbed = source.clone - source_scrubbed = source_scrubbed.gsub(/"[^"\n]*"/, '') # remove things in strings + source_scrubbed = source_scrubbed.gsub(/"[^"\n]*"/, '') # remove things in strings source_scrubbed = source_scrubbed.gsub(/\/\/.*$/, '') # remove line comments source_scrubbed = source_scrubbed.gsub(/\/\*.*?\*\//m, '') # remove block comments lines = source_scrubbed.split(/(^\s*\#.*$) # Treat preprocessor directives as a logical line | (;|\{|\}) /x) # Match ;, {, and } as end of lines - lines.each_with_index do |line, index| - #find tests - if line =~ /^((?:\s*TEST_CASE\s*\(.*?\)\s*)*)\s*void\s+((?:#{@options[:test_prefix]}).*)\s*\(\s*(.*)\s*\)/ - arguments = $1 - name = $2 - call = $3 - params = $4 - args = nil - if (@options[:use_param_tests] and !arguments.empty?) - args = [] - arguments.scan(/\s*TEST_CASE\s*\((.*)\)\s*$/) {|a| args << a[0]} - end - tests_and_line_numbers << { :test => name, :args => args, :call => call, :params => params, :line_number => 0 } + lines.each_with_index do |line, _index| + # find tests + next unless line =~ /^((?:\s*TEST_CASE\s*\(.*?\)\s*)*)\s*void\s+((?:#{@options[:test_prefix]}).*)\s*\(\s*(.*)\s*\)/ + arguments = Regexp.last_match(1) + name = Regexp.last_match(2) + call = Regexp.last_match(3) + params = Regexp.last_match(4) + args = nil + if @options[:use_param_tests] && !arguments.empty? + args = [] + arguments.scan(/\s*TEST_CASE\s*\((.*)\)\s*$/) { |a| args << a[0] } end + tests_and_line_numbers << { test: name, args: args, call: call, params: params, line_number: 0 } end - tests_and_line_numbers.uniq! {|v| v[:test] } + tests_and_line_numbers.uniq! { |v| v[:test] } - #determine line numbers and create tests to run + # determine line numbers and create tests to run source_lines = source.split("\n") - source_index = 0; + source_index = 0 tests_and_line_numbers.size.times do |i| source_lines[source_index..-1].each_with_index do |line, index| - if (line =~ /#{tests_and_line_numbers[i][:test]}/) - source_index += index - tests_and_line_numbers[i][:line_number] = source_index + 1 - break - end + next unless line =~ /#{tests_and_line_numbers[i][:test]}/ + source_index += index + tests_and_line_numbers[i][:line_number] = source_index + 1 + break end end - return tests_and_line_numbers + tests_and_line_numbers end def find_includes(source) - - #remove comments (block and line, in three steps to ensure correct precedence) + # remove comments (block and line, in three steps to ensure correct precedence) source.gsub!(/\/\/(?:.+\/\*|\*(?:$|[^\/])).*$/, '') # remove line comments that comment out the start of blocks source.gsub!(/\/\*.*?\*\//m, '') # remove block comments source.gsub!(/\/\/.*$/, '') # remove line comments (all that remain) - #parse out includes + # parse out includes includes = { - :local => source.scan(/^\s*#include\s+\"\s*(.+)\.[hH]\s*\"/).flatten, - :system => source.scan(/^\s*#include\s+<\s*(.+)\s*>/).flatten.map { |inc| "<#{inc}>" } + local: source.scan(/^\s*#include\s+\"\s*(.+)\.[hH]\s*\"/).flatten, + system: source.scan(/^\s*#include\s+<\s*(.+)\s*>/).flatten.map { |inc| "<#{inc}>" }, + linkonly: source.scan(/^TEST_FILE\(\s*\"\s*(.+)\.[cC]\w*\s*\"/).flatten } - return includes + includes end def find_mocks(includes) mock_headers = [] includes.each do |include_path| include_file = File.basename(include_path) - mock_headers << include_path if (include_file =~ /^mock/i) + mock_headers << include_path if include_file =~ /^#{@options[:mock_prefix]}/i end - return mock_headers + mock_headers end - def create_header(output, mocks, testfile_includes=[]) + def create_header(output, mocks, testfile_includes = []) output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */') create_runtest(output, mocks) output.puts("\n/*=======Automagically Detected Files To Include=====*/") - output.puts("#include \"#{@options[:framework].to_s}.h\"") - output.puts('#include "cmock.h"') unless (mocks.empty?) + output.puts("#include \"#{@options[:framework]}.h\"") + output.puts('#include "cmock.h"') unless mocks.empty? output.puts('#include ') output.puts('#include ') - output.puts('#include "CException.h"') if @options[:plugins].include?(:cexception) - if (@options[:defines] && !@options[:defines].empty?) - @options[:defines].each {|d| output.puts("#define #{d}")} + if @options[:defines] && !@options[:defines].empty? + @options[:defines].each { |d| output.puts("#define #{d}") } end - if (@options[:header_file] && !@options[:header_file].empty?) + if @options[:header_file] && !@options[:header_file].empty? output.puts("#include \"#{File.basename(@options[:header_file])}\"") else @options[:includes].flatten.uniq.compact.each do |inc| - output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h','')}.h\""}") + output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}") end testfile_includes.each do |inc| - output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h','')}.h\""}") + output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}") end end mocks.each do |mock| - output.puts("#include \"#{mock.gsub('.h','')}.h\"") - end - if @options[:enforce_strict_ordering] - output.puts('') - output.puts('int GlobalExpectCount;') - output.puts('int GlobalVerifyOrder;') - output.puts('char* GlobalOrderError;') + output.puts("#include \"#{mock.gsub('.h', '')}.h\"") end + output.puts('#include "CException.h"') if @options[:plugins].include?(:cexception) + + return unless @options[:enforce_strict_ordering] + + output.puts('') + output.puts('int GlobalExpectCount;') + output.puts('int GlobalVerifyOrder;') + output.puts('char* GlobalOrderError;') end - def create_externs(output, tests, mocks) + def create_externs(output, tests, _mocks) output.puts("\n/*=======External Functions This Runner Calls=====*/") output.puts("extern void #{@options[:setup_name]}(void);") output.puts("extern void #{@options[:teardown_name]}(void);") @@ -203,55 +198,60 @@ class UnityTestRunnerGenerator end def create_mock_management(output, mock_headers) - unless (mock_headers.empty?) - output.puts("\n/*=======Mock Management=====*/") - output.puts("static void CMock_Init(void)") - output.puts("{") - if @options[:enforce_strict_ordering] - output.puts(" GlobalExpectCount = 0;") - output.puts(" GlobalVerifyOrder = 0;") - output.puts(" GlobalOrderError = NULL;") - end - mocks = mock_headers.map {|mock| File.basename(mock)} - mocks.each do |mock| - mock_clean = TypeSanitizer.sanitize_c_identifier(mock) - output.puts(" #{mock_clean}_Init();") - end - output.puts("}\n") + return if mock_headers.empty? - output.puts("static void CMock_Verify(void)") - output.puts("{") - mocks.each do |mock| - mock_clean = TypeSanitizer.sanitize_c_identifier(mock) - output.puts(" #{mock_clean}_Verify();") - end - output.puts("}\n") + output.puts("\n/*=======Mock Management=====*/") + output.puts('static void CMock_Init(void)') + output.puts('{') - output.puts("static void CMock_Destroy(void)") - output.puts("{") - mocks.each do |mock| - mock_clean = TypeSanitizer.sanitize_c_identifier(mock) - output.puts(" #{mock_clean}_Destroy();") - end - output.puts("}\n") + if @options[:enforce_strict_ordering] + output.puts(' GlobalExpectCount = 0;') + output.puts(' GlobalVerifyOrder = 0;') + output.puts(' GlobalOrderError = NULL;') end + + mocks = mock_headers.map { |mock| File.basename(mock) } + mocks.each do |mock| + mock_clean = TypeSanitizer.sanitize_c_identifier(mock) + output.puts(" #{mock_clean}_Init();") + end + output.puts("}\n") + + output.puts('static void CMock_Verify(void)') + output.puts('{') + mocks.each do |mock| + mock_clean = TypeSanitizer.sanitize_c_identifier(mock) + output.puts(" #{mock_clean}_Verify();") + end + output.puts("}\n") + + output.puts('static void CMock_Destroy(void)') + output.puts('{') + mocks.each do |mock| + mock_clean = TypeSanitizer.sanitize_c_identifier(mock) + output.puts(" #{mock_clean}_Destroy();") + end + output.puts("}\n") end - def create_suite_setup_and_teardown(output) - unless (@options[:suite_setup].nil?) - output.puts("\n/*=======Suite Setup=====*/") - output.puts("static void suite_setup(void)") - output.puts("{") - output.puts(@options[:suite_setup]) - output.puts("}") - end - unless (@options[:suite_teardown].nil?) - output.puts("\n/*=======Suite Teardown=====*/") - output.puts("static int suite_teardown(int num_failures)") - output.puts("{") - output.puts(@options[:suite_teardown]) - output.puts("}") - end + def create_suite_setup(output) + return if @options[:suite_setup].nil? + + output.puts("\n/*=======Suite Setup=====*/") + output.puts('static void suite_setup(void)') + output.puts('{') + output.puts(@options[:suite_setup]) + output.puts('}') + end + + def create_suite_teardown(output) + return if @options[:suite_teardown].nil? + + output.puts("\n/*=======Suite Teardown=====*/") + output.puts('static int suite_teardown(int num_failures)') + output.puts('{') + output.puts(@options[:suite_teardown]) + output.puts('}') end def create_runtest(output, used_mocks) @@ -259,124 +259,124 @@ class UnityTestRunnerGenerator va_args1 = @options[:use_param_tests] ? ', ...' : '' va_args2 = @options[:use_param_tests] ? '__VA_ARGS__' : '' output.puts("\n/*=======Test Runner Used To Run Each Test Below=====*/") - output.puts("#define RUN_TEST_NO_ARGS") if @options[:use_param_tests] + output.puts('#define RUN_TEST_NO_ARGS') if @options[:use_param_tests] output.puts("#define RUN_TEST(TestFunc, TestLineNum#{va_args1}) \\") - output.puts("{ \\") + output.puts('{ \\') output.puts(" Unity.CurrentTestName = #TestFunc#{va_args2.empty? ? '' : " \"(\" ##{va_args2} \")\""}; \\") - output.puts(" Unity.CurrentTestLineNumber = TestLineNum; \\") - output.puts(" if (UnityTestMatches()) { \\") if (@options[:cmdline_args]) - output.puts(" Unity.NumberOfTests++; \\") - output.puts(" CMock_Init(); \\") unless (used_mocks.empty?) - output.puts(" UNITY_CLR_DETAILS(); \\") unless (used_mocks.empty?) - output.puts(" if (TEST_PROTECT()) \\") - output.puts(" { \\") - output.puts(" CEXCEPTION_T e; \\") if cexception - output.puts(" Try { \\") if cexception + output.puts(' Unity.CurrentTestLineNumber = TestLineNum; \\') + output.puts(' if (UnityTestMatches()) { \\') if @options[:cmdline_args] + output.puts(' Unity.NumberOfTests++; \\') + output.puts(' CMock_Init(); \\') unless used_mocks.empty? + output.puts(' UNITY_CLR_DETAILS(); \\') unless used_mocks.empty? + output.puts(' if (TEST_PROTECT()) \\') + output.puts(' { \\') + output.puts(' CEXCEPTION_T e; \\') if cexception + output.puts(' Try { \\') if cexception output.puts(" #{@options[:setup_name]}(); \\") output.puts(" TestFunc(#{va_args2}); \\") - output.puts(" } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, \"Unhandled Exception!\"); } \\") if cexception - output.puts(" } \\") - output.puts(" if (TEST_PROTECT()) \\") - output.puts(" { \\") + output.puts(' } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \\') if cexception + output.puts(' } \\') + output.puts(' if (TEST_PROTECT()) \\') + output.puts(' { \\') output.puts(" #{@options[:teardown_name]}(); \\") - output.puts(" CMock_Verify(); \\") unless (used_mocks.empty?) - output.puts(" } \\") - output.puts(" CMock_Destroy(); \\") unless (used_mocks.empty?) - output.puts(" UnityConcludeTest(); \\") - output.puts(" } \\") if (@options[:cmdline_args]) + output.puts(' CMock_Verify(); \\') unless used_mocks.empty? + output.puts(' } \\') + output.puts(' CMock_Destroy(); \\') unless used_mocks.empty? + output.puts(' UnityConcludeTest(); \\') + output.puts(' } \\') if @options[:cmdline_args] output.puts("}\n") end def create_reset(output, used_mocks) output.puts("\n/*=======Test Reset Option=====*/") - output.puts("void resetTest(void);") - output.puts("void resetTest(void)") - output.puts("{") - output.puts(" CMock_Verify();") unless (used_mocks.empty?) - output.puts(" CMock_Destroy();") unless (used_mocks.empty?) + output.puts('void resetTest(void);') + output.puts('void resetTest(void)') + output.puts('{') + output.puts(' CMock_Verify();') unless used_mocks.empty? + output.puts(' CMock_Destroy();') unless used_mocks.empty? output.puts(" #{@options[:teardown_name]}();") - output.puts(" CMock_Init();") unless (used_mocks.empty?) + output.puts(' CMock_Init();') unless used_mocks.empty? output.puts(" #{@options[:setup_name]}();") - output.puts("}") + output.puts('}') end def create_main(output, filename, tests, used_mocks) output.puts("\n\n/*=======MAIN=====*/") - main_name = (@options[:main_name].to_sym == :auto) ? "main_#{filename.gsub('.c','')}" : "#{@options[:main_name]}" - if (@options[:cmdline_args]) - if (main_name != "main") + main_name = @options[:main_name].to_sym == :auto ? "main_#{filename.gsub('.c', '')}" : (@options[:main_name]).to_s + if @options[:cmdline_args] + if main_name != 'main' output.puts("#{@options[:main_export_decl]} int #{main_name}(int argc, char** argv);") end output.puts("#{@options[:main_export_decl]} int #{main_name}(int argc, char** argv)") - output.puts("{") - output.puts(" int parse_status = UnityParseOptions(argc, argv);") - output.puts(" if (parse_status != 0)") - output.puts(" {") - output.puts(" if (parse_status < 0)") - output.puts(" {") - output.puts(" UnityPrint(\"#{filename.gsub('.c','')}.\");") - output.puts(" UNITY_PRINT_EOL();") - if (@options[:use_param_tests]) + output.puts('{') + output.puts(' int parse_status = UnityParseOptions(argc, argv);') + output.puts(' if (parse_status != 0)') + output.puts(' {') + output.puts(' if (parse_status < 0)') + output.puts(' {') + output.puts(" UnityPrint(\"#{filename.gsub('.c', '')}.\");") + output.puts(' UNITY_PRINT_EOL();') + if @options[:use_param_tests] tests.each do |test| - if ((test[:args].nil?) or (test[:args].empty?)) + if test[:args].nil? || test[:args].empty? output.puts(" UnityPrint(\" #{test[:test]}(RUN_TEST_NO_ARGS)\");") - output.puts(" UNITY_PRINT_EOL();") + output.puts(' UNITY_PRINT_EOL();') else test[:args].each do |args| output.puts(" UnityPrint(\" #{test[:test]}(#{args})\");") - output.puts(" UNITY_PRINT_EOL();") + output.puts(' UNITY_PRINT_EOL();') end end end else - tests.each { |test| output.puts(" UnityPrint(\" #{test[:test]}\");\n UNITY_PRINT_EOL();")} + tests.each { |test| output.puts(" UnityPrint(\" #{test[:test]}\");\n UNITY_PRINT_EOL();") } end - output.puts(" return 0;") - output.puts(" }") - output.puts(" return parse_status;") - output.puts(" }") + output.puts(' return 0;') + output.puts(' }') + output.puts(' return parse_status;') + output.puts(' }') else - if (main_name != "main") + if main_name != 'main' output.puts("#{@options[:main_export_decl]} int #{main_name}(void);") end output.puts("int #{main_name}(void)") - output.puts("{") + output.puts('{') end - output.puts(" suite_setup();") unless @options[:suite_setup].nil? - output.puts(" UnityBegin(\"#{filename.gsub(/\\/,'\\\\\\')}\");") - if (@options[:use_param_tests]) + output.puts(' suite_setup();') unless @options[:suite_setup].nil? + output.puts(" UnityBegin(\"#{filename.gsub(/\\/, '\\\\\\')}\");") + if @options[:use_param_tests] tests.each do |test| - if ((test[:args].nil?) or (test[:args].empty?)) + if test[:args].nil? || test[:args].empty? output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]}, RUN_TEST_NO_ARGS);") else - test[:args].each {|args| output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]}, #{args});")} + test[:args].each { |args| output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]}, #{args});") } end end else - tests.each { |test| output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]});") } + tests.each { |test| output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]});") } end - output.puts() - output.puts(" CMock_Guts_MemFreeFinal();") unless used_mocks.empty? - output.puts(" return #{@options[:suite_teardown].nil? ? "" : "suite_teardown"}(UnityEnd());") - output.puts("}") + output.puts + output.puts(' CMock_Guts_MemFreeFinal();') unless used_mocks.empty? + output.puts(" return #{@options[:suite_teardown].nil? ? '' : 'suite_teardown'}(UnityEnd());") + output.puts('}') end def create_h_file(output, filename, tests, testfile_includes, used_mocks) - filename = File.basename(filename).gsub(/[-\/\\\.\,\s]/, "_").upcase - output.puts("/* AUTOGENERATED FILE. DO NOT EDIT. */") + filename = File.basename(filename).gsub(/[-\/\\\.\,\s]/, '_').upcase + output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */') output.puts("#ifndef _#{filename}") output.puts("#define _#{filename}\n\n") - output.puts("#include \"#{@options[:framework].to_s}.h\"") - output.puts('#include "cmock.h"') unless (used_mocks.empty?) + output.puts("#include \"#{@options[:framework]}.h\"") + output.puts('#include "cmock.h"') unless used_mocks.empty? @options[:includes].flatten.uniq.compact.each do |inc| - output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h','')}.h\""}") + output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}") end testfile_includes.each do |inc| - output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h','')}.h\""}") + output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h', '')}.h\""}") end output.puts "\n" tests.each do |test| - if ((test[:params].nil?) or (test[:params].empty?)) + if test[:params].nil? || test[:params].empty? output.puts("void #{test[:test]}(void);") else output.puts("void #{test[:test]}(#{test[:params]});") @@ -386,50 +386,52 @@ class UnityTestRunnerGenerator end end -if ($0 == __FILE__) - options = { :includes => [] } - yaml_file = nil +if $0 == __FILE__ + options = { includes: [] } - #parse out all the options first (these will all be removed as we go) + # parse out all the options first (these will all be removed as we go) ARGV.reject! do |arg| - case(arg) - when '-cexception' - options[:plugins] = [:cexception]; true - when /\.*\.ya?ml/ - options = UnityTestRunnerGenerator.grab_config(arg); true - when /--(\w+)=\"?(.*)\"?/ - options[$1.to_sym] = $2; true - when /\.*\.h/ - options[:includes] << arg; true - else false + case arg + when '-cexception' + options[:plugins] = [:cexception] + true + when /\.*\.ya?ml/ + options = UnityTestRunnerGenerator.grab_config(arg) + true + when /--(\w+)=\"?(.*)\"?/ + options[Regexp.last_match(1).to_sym] = Regexp.last_match(2) + true + when /\.*\.h/ + options[:includes] << arg + true + else false end end - #make sure there is at least one parameter left (the input file) - if !ARGV[0] + # make sure there is at least one parameter left (the input file) + unless ARGV[0] puts ["\nusage: ruby #{__FILE__} (files) (options) input_test_file (output)", - "\n input_test_file - this is the C file you want to create a runner for", - " output - this is the name of the runner file to generate", - " defaults to (input_test_file)_Runner", - " files:", - " *.yml / *.yaml - loads configuration from here in :unity or :cmock", - " *.h - header files are added as #includes in runner", - " options:", - " -cexception - include cexception support", - " --setup_name=\"\" - redefine setUp func name to something else", - " --teardown_name=\"\" - redefine tearDown func name to something else", - " --main_name=\"\" - redefine main func name to something else", - " --test_prefix=\"\" - redefine test prefix from default test|spec|should", - " --suite_setup=\"\" - code to execute for setup of entire suite", - " --suite_teardown=\"\" - code to execute for teardown of entire suite", - " --use_param_tests=1 - enable parameterized tests (disabled by default)", - " --header_file=\"\" - path/name of test header file to generate too" - ].join("\n") + "\n input_test_file - this is the C file you want to create a runner for", + ' output - this is the name of the runner file to generate', + ' defaults to (input_test_file)_Runner', + ' files:', + ' *.yml / *.yaml - loads configuration from here in :unity or :cmock', + ' *.h - header files are added as #includes in runner', + ' options:', + ' -cexception - include cexception support', + ' --setup_name="" - redefine setUp func name to something else', + ' --teardown_name="" - redefine tearDown func name to something else', + ' --main_name="" - redefine main func name to something else', + ' --test_prefix="" - redefine test prefix from default test|spec|should', + ' --suite_setup="" - code to execute for setup of entire suite', + ' --suite_teardown="" - code to execute for teardown of entire suite', + ' --use_param_tests=1 - enable parameterized tests (disabled by default)', + ' --header_file="" - path/name of test header file to generate too'].join("\n") exit 1 end - #create the default test runner name if not specified - ARGV[1] = ARGV[0].gsub(".c","_Runner.c") if (!ARGV[1]) + # create the default test runner name if not specified + ARGV[1] = ARGV[0].gsub('.c', '_Runner.c') unless ARGV[1] UnityTestRunnerGenerator.new(options).run(ARGV[0], ARGV[1]) end diff --git a/tests/unity/auto/parseOutput.rb b/tests/unity/auto/parseOutput.rb deleted file mode 100644 index e8dbf08..0000000 --- a/tests/unity/auto/parseOutput.rb +++ /dev/null @@ -1,224 +0,0 @@ -#============================================================ -# Author: John Theofanopoulos -# A simple parser. Takes the output files generated during the build process and -# extracts information relating to the tests. -# -# Notes: -# To capture an output file under VS builds use the following: -# devenv [build instructions] > Output.txt & type Output.txt -# -# To capture an output file under GCC/Linux builds use the following: -# make | tee Output.txt -# -# To use this parser use the following command -# ruby parseOutput.rb [options] [file] -# options: -xml : produce a JUnit compatible XML file -# file : file to scan for results -#============================================================ - - -class ParseOutput -# The following flag is set to true when a test is found or false otherwise. - @testFlag - @xmlOut - @arrayList - @totalTests - @classIndex - -# Set the flag to indicate if there will be an XML output file or not - def setXmlOutput() - @xmlOut = true - end - -# if write our output to XML - def writeXmlOuput() - output = File.open("report.xml", "w") - output << "\n" - @arrayList.each do |item| - output << item << "\n" - end - output << "\n" - end - -# This function will try and determine when the suite is changed. This is -# is the name that gets added to the classname parameter. - def testSuiteVerify(testSuiteName) - if @testFlag == false - @testFlag = true; - # Split the path name - testName = testSuiteName.split("/") - # Remove the extension - baseName = testName[testName.size - 1].split(".") - @testSuite = "test." + baseName[0] - printf "New Test: %s\n", @testSuite - end - end - - -# Test was flagged as having passed so format the output - def testPassed(array) - lastItem = array.length - 1 - testName = array[lastItem - 1] - testSuiteVerify(array[@className]) - printf "%-40s PASS\n", testName - if @xmlOut == true - @arrayList.push " " - end - end - -# Test was flagged as having passed so format the output. -# This is using the Unity fixture output and not the original Unity output. - def testPassedUnityFixture(array) - testSuite = array[0].sub("TEST(", "") - testSuite = testSuite.sub(",", "") - testName = array[1].sub(")", "") - if @xmlOut == true - @arrayList.push " " - end - end - -# Test was flagged as being ingored so format the output - def testIgnored(array) - lastItem = array.length - 1 - testName = array[lastItem - 2] - reason = array[lastItem].chomp - testSuiteVerify(array[@className]) - printf "%-40s IGNORED\n", testName - - if testName.start_with? "TEST(" - array2 = testName.split(" ") - @testSuite = array2[0].sub("TEST(", "") - @testSuite = @testSuite.sub(",", "") - testName = array2[1].sub(")", "") - end - - if @xmlOut == true - @arrayList.push " " - @arrayList.push " " + reason + " " - @arrayList.push " " - end - end - -# Test was flagged as having failed so format the line - def testFailed(array) - lastItem = array.length - 1 - testName = array[lastItem - 2] - reason = array[lastItem].chomp + " at line: " + array[lastItem - 3] - testSuiteVerify(array[@className]) - printf "%-40s FAILED\n", testName - - if testName.start_with? "TEST(" - array2 = testName.split(" ") - @testSuite = array2[0].sub("TEST(", "") - @testSuite = @testSuite.sub(",", "") - testName = array2[1].sub(")", "") - end - - if @xmlOut == true - @arrayList.push " " - @arrayList.push " " + reason + " " - @arrayList.push " " - end - end - - -# Figure out what OS we are running on. For now we are assuming if it's not Windows it must -# be Unix based. - def detectOS() - myOS = RUBY_PLATFORM.split("-") - if myOS.size == 2 - if myOS[1] == "mingw32" - @className = 1 - else - @className = 0 - end - else - @className = 0 - end - - end - -# Main function used to parse the file that was captured. - def process(name) - @testFlag = false - @arrayList = Array.new - - detectOS() - - puts "Parsing file: " + name - - - testPass = 0 - testFail = 0 - testIgnore = 0 - puts "" - puts "=================== RESULTS =====================" - puts "" - File.open(name).each do |line| - # Typical test lines look like this: - # /.c:36:test_tc1000_opsys:FAIL: Expected 1 Was 0 - # /.c:112:test_tc5004_initCanChannel:IGNORE: Not Yet Implemented - # /.c:115:test_tc5100_initCanVoidPtrs:PASS - # - # where path is different on Unix vs Windows devices (Windows leads with a drive letter) - lineArray = line.split(":") - lineSize = lineArray.size - # If we were able to split the line then we can look to see if any of our target words - # were found. Case is important. - if ((lineSize >= 4) || (line.start_with? "TEST(")) - # Determine if this test passed - if line.include? ":PASS" - testPassed(lineArray) - testPass += 1 - elsif line.include? ":FAIL:" - testFailed(lineArray) - testFail += 1 - elsif line.include? ":IGNORE:" - testIgnored(lineArray) - testIgnore += 1 - elsif line.start_with? "TEST(" - if line.include? " PASS" - lineArray = line.split(" ") - testPassedUnityFixture(lineArray) - testPass += 1 - end - # If none of the keywords are found there are no more tests for this suite so clear - # the test flag - else - @testFlag = false - end - else - @testFlag = false - end - end - puts "" - puts "=================== SUMMARY =====================" - puts "" - puts "Tests Passed : " + testPass.to_s - puts "Tests Failed : " + testFail.to_s - puts "Tests Ignored : " + testIgnore.to_s - @totalTests = testPass + testFail + testIgnore - if @xmlOut == true - heading = "" - @arrayList.insert(0, heading) - writeXmlOuput() - end - - # return result - end - - end - -# If the command line has no values in, used a default value of Output.txt -parseMyFile = ParseOutput.new - -if ARGV.size >= 1 - ARGV.each do |a| - if a == "-xml" - parseMyFile.setXmlOutput(); - else - parseMyFile.process(a) - break - end - end -end diff --git a/tests/unity/auto/parse_output.rb b/tests/unity/auto/parse_output.rb new file mode 100644 index 0000000..f16cdb0 --- /dev/null +++ b/tests/unity/auto/parse_output.rb @@ -0,0 +1,220 @@ +#============================================================ +# Author: John Theofanopoulos +# A simple parser. Takes the output files generated during the build process and +# extracts information relating to the tests. +# +# Notes: +# To capture an output file under VS builds use the following: +# devenv [build instructions] > Output.txt & type Output.txt +# +# To capture an output file under GCC/Linux builds use the following: +# make | tee Output.txt +# +# To use this parser use the following command +# ruby parseOutput.rb [options] [file] +# options: -xml : produce a JUnit compatible XML file +# file : file to scan for results +#============================================================ + +class ParseOutput + def initialize + @test_flag = false + @xml_out = false + @array_list = false + @total_tests = false + @class_index = false + end + + # Set the flag to indicate if there will be an XML output file or not + def set_xml_output + @xml_out = true + end + + # if write our output to XML + def write_xml_output + output = File.open('report.xml', 'w') + output << "\n" + @array_list.each do |item| + output << item << "\n" + end + output << "\n" + end + + # This function will try and determine when the suite is changed. This is + # is the name that gets added to the classname parameter. + def test_suite_verify(test_suite_name) + return if @test_flag + + @test_flag = true + # Split the path name + test_name = test_suite_name.split('/') + # Remove the extension + base_name = test_name[test_name.size - 1].split('.') + @test_suite = 'test.' + base_name[0] + printf "New Test: %s\n", @test_suite + end + + # Test was flagged as having passed so format the output + def test_passed(array) + last_item = array.length - 1 + test_name = array[last_item - 1] + test_suite_verify(array[@class_name]) + printf "%-40s PASS\n", test_name + + return unless @xml_out + + @array_list.push ' ' + end + + # Test was flagged as having passed so format the output. + # This is using the Unity fixture output and not the original Unity output. + def test_passed_unity_fixture(array) + test_suite = array[0].sub('TEST(', '') + test_suite = test_suite.sub(',', '') + test_name = array[1].sub(')', '') + + return unless @xml_out + + @array_list.push ' ' + end + + # Test was flagged as being ingored so format the output + def test_ignored(array) + last_item = array.length - 1 + test_name = array[last_item - 2] + reason = array[last_item].chomp + test_suite_verify(array[@class_name]) + printf "%-40s IGNORED\n", test_name + + if test_name.start_with? 'TEST(' + array2 = test_name.split(' ') + @test_suite = array2[0].sub('TEST(', '') + @test_suite = @test_suite.sub(',', '') + test_name = array2[1].sub(')', '') + end + + return unless @xml_out + + @array_list.push ' ' + @array_list.push ' ' + reason + ' ' + @array_list.push ' ' + end + + # Test was flagged as having failed so format the line + def test_failed(array) + last_item = array.length - 1 + test_name = array[last_item - 2] + reason = array[last_item].chomp + ' at line: ' + array[last_item - 3] + test_suite_verify(array[@class_name]) + printf "%-40s FAILED\n", test_name + + if test_name.start_with? 'TEST(' + array2 = test_name.split(' ') + @test_suite = array2[0].sub('TEST(', '') + @test_suite = @test_suite.sub(',', '') + test_name = array2[1].sub(')', '') + end + + return unless @xml_out + + @array_list.push ' ' + @array_list.push ' ' + reason + ' ' + @array_list.push ' ' + end + + # Figure out what OS we are running on. For now we are assuming if it's not Windows it must + # be Unix based. + def detect_os + os = RUBY_PLATFORM.split('-') + @class_name = if os.size == 2 + if os[1] == 'mingw32' + 1 + else + 0 + end + else + 0 + end + end + + # Main function used to parse the file that was captured. + def process(name) + @test_flag = false + @array_list = [] + + detect_os + + puts 'Parsing file: ' + name + + test_pass = 0 + test_fail = 0 + test_ignore = 0 + puts '' + puts '=================== RESULTS =====================' + puts '' + File.open(name).each do |line| + # Typical test lines look like this: + # /.c:36:test_tc1000_opsys:FAIL: Expected 1 Was 0 + # /.c:112:test_tc5004_initCanChannel:IGNORE: Not Yet Implemented + # /.c:115:test_tc5100_initCanVoidPtrs:PASS + # + # where path is different on Unix vs Windows devices (Windows leads with a drive letter) + line_array = line.split(':') + + # If we were able to split the line then we can look to see if any of our target words + # were found. Case is important. + if (line_array.size >= 4) || (line.start_with? 'TEST(') + # Determine if this test passed + if line.include? ':PASS' + test_passed(line_array) + test_pass += 1 + elsif line.include? ':FAIL:' + test_failed(line_array) + test_fail += 1 + elsif line.include? ':IGNORE:' + test_ignored(line_array) + test_ignore += 1 + elsif line.start_with? 'TEST(' + if line.include? ' PASS' + line_array = line.split(' ') + test_passed_unity_fixture(line_array) + test_pass += 1 + end + # If none of the keywords are found there are no more tests for this suite so clear + # the test flag + else + @test_flag = false + end + else + @test_flag = false + end + end + puts '' + puts '=================== SUMMARY =====================' + puts '' + puts 'Tests Passed : ' + test_pass.to_s + puts 'Tests Failed : ' + test_fail.to_s + puts 'Tests Ignored : ' + test_ignore.to_s + @total_tests = test_pass + test_fail + test_ignore + + return unless @xml_out + + heading = '' + @array_list.insert(0, heading) + write_xml_output + end +end + +# If the command line has no values in, used a default value of Output.txt +parse_my_file = ParseOutput.new + +if ARGV.size >= 1 + ARGV.each do |a| + if a == '-xml' + parse_my_file.set_xml_output + else + parse_my_file.process(a) + break + end + end +end diff --git a/tests/unity/auto/stylize_as_junit.rb b/tests/unity/auto/stylize_as_junit.rb index 27ac76d..b3d8f40 100644 --- a/tests/unity/auto/stylize_as_junit.rb +++ b/tests/unity/auto/stylize_as_junit.rb @@ -12,7 +12,6 @@ require 'pp' VERSION = 1.0 class ArgvParser - # # Return a structure describing the options. # @@ -20,41 +19,41 @@ class ArgvParser # The options specified on the command line will be collected in *options*. # We set default values here. options = OpenStruct.new - options.results_dir = "." - options.root_path = "." - options.out_file = "results.xml" + options.results_dir = '.' + options.root_path = '.' + options.out_file = 'results.xml' - opts = OptionParser.new do |opts| - opts.banner = "Usage: unity_to_junit.rb [options]" + opts = OptionParser.new do |o| + o.banner = 'Usage: unity_to_junit.rb [options]' - opts.separator "" - opts.separator "Specific options:" + o.separator '' + o.separator 'Specific options:' - opts.on("-r", "--results ", "Look for Unity Results files here.") do |results| - #puts "results #{results}" + o.on('-r', '--results ', 'Look for Unity Results files here.') do |results| + # puts "results #{results}" options.results_dir = results end - opts.on("-p", "--root_path ", "Prepend this path to files in results.") do |root_path| + o.on('-p', '--root_path ', 'Prepend this path to files in results.') do |root_path| options.root_path = root_path end - opts.on("-o", "--output ", "XML file to generate.") do |out_file| - #puts "out_file: #{out_file}" + o.on('-o', '--output ', 'XML file to generate.') do |out_file| + # puts "out_file: #{out_file}" options.out_file = out_file end - opts.separator "" - opts.separator "Common options:" + o.separator '' + o.separator 'Common options:' # No argument, shows at tail. This will print an options summary. - opts.on_tail("-h", "--help", "Show this message") do - puts opts + o.on_tail('-h', '--help', 'Show this message') do + puts o exit end # Another typical switch to print the version. - opts.on_tail("--version", "Show version") do + o.on_tail('--version', 'Show version') do puts "unity_to_junit.rb version #{VERSION}" exit end @@ -62,13 +61,13 @@ class ArgvParser opts.parse!(args) options - end # parse() - -end # class OptparseExample + end # parse() +end # class OptparseExample class UnityToJUnit include FileUtils::Verbose attr_reader :report, :total_tests, :failures, :ignored + attr_writer :targets, :root, :out_file def initialize @report = '' @@ -77,125 +76,115 @@ class UnityToJUnit def run # Clean up result file names - results = @targets.map {|target| target.gsub(/\\/,"/")} - #puts "Output File: #{@out_file}" - f = File.new(@out_file, "w") + results = @targets.map { |target| target.tr('\\', '/') } + # puts "Output File: #{@out_file}" + f = File.new(@out_file, 'w') write_xml_header(f) - write_suites_header( f ) + write_suites_header(f) results.each do |result_file| - lines = File.readlines(result_file).map { |line| line.chomp } - if lines.length == 0 - raise "Empty test result file: #{result_file}" - else - result_output = get_details(result_file, lines) - tests,failures,ignored = parse_test_summary(lines) - result_output[:counts][:total] = tests - result_output[:counts][:failed] = failures - result_output[:counts][:ignored] = ignored - result_output[:counts][:passed] = (result_output[:counts][:total] - result_output[:counts][:failed] - result_output[:counts][:ignored]) - end - #use line[0] from the test output to get the test_file path and name - test_file_str = lines[0].gsub("\\","/") - test_file_str = test_file_str.split(":") - test_file = if (test_file_str.length < 2) - result_file - else - test_file_str[0] + ':' + test_file_str[1] - end + lines = File.readlines(result_file).map(&:chomp) + + raise "Empty test result file: #{result_file}" if lines.empty? + + result_output = get_details(result_file, lines) + tests, failures, ignored = parse_test_summary(lines) + result_output[:counts][:total] = tests + result_output[:counts][:failed] = failures + result_output[:counts][:ignored] = ignored + result_output[:counts][:passed] = (result_output[:counts][:total] - result_output[:counts][:failed] - result_output[:counts][:ignored]) + + # use line[0] from the test output to get the test_file path and name + test_file_str = lines[0].tr('\\', '/') + test_file_str = test_file_str.split(':') + test_file = if test_file_str.length < 2 + result_file + else + test_file_str[0] + ':' + test_file_str[1] + end result_output[:source][:path] = File.dirname(test_file) result_output[:source][:file] = File.basename(test_file) # save result_output - @unit_name = File.basename(test_file, ".*") + @unit_name = File.basename(test_file, '.*') - write_suite_header( result_output[:counts], f) - write_failures( result_output, f ) - write_tests( result_output, f ) - write_ignored( result_output, f ) - write_suite_footer( f ) + write_suite_header(result_output[:counts], f) + write_failures(result_output, f) + write_tests(result_output, f) + write_ignored(result_output, f) + write_suite_footer(f) end - write_suites_footer( f ) + write_suites_footer(f) f.close end - def set_targets(target_array) - @targets = target_array - end - - def set_root_path(path) - @root = path - end - def set_out_file(filename) - @out_file = filename - end - def usage(err_msg=nil) + def usage(err_msg = nil) puts "\nERROR: " puts err_msg if err_msg - puts "Usage: unity_to_junit.rb [options]" - puts "" - puts "Specific options:" - puts " -r, --results Look for Unity Results files here." - puts " -p, --root_path Prepend this path to files in results." - puts " -o, --output XML file to generate." - puts "" - puts "Common options:" - puts " -h, --help Show this message" - puts " --version Show version" + puts 'Usage: unity_to_junit.rb [options]' + puts '' + puts 'Specific options:' + puts ' -r, --results Look for Unity Results files here.' + puts ' -p, --root_path Prepend this path to files in results.' + puts ' -o, --output XML file to generate.' + puts '' + puts 'Common options:' + puts ' -h, --help Show this message' + puts ' --version Show version' exit 1 end protected - def get_details(result_file, lines) - results = get_results_structure + + def get_details(_result_file, lines) + results = results_structure lines.each do |line| - line = line.gsub("\\","/") - src_file,src_line,test_name,status,msg = line.split(/:/) - line_out = ((@root and (@root != 0)) ? "#{@root}#{line}" : line ).gsub(/\//, "\\") - case(status) - when 'IGNORE' then results[:ignores] << {:test => test_name, :line => src_line, :message => msg} - when 'FAIL' then results[:failures] << {:test => test_name, :line => src_line, :message => msg} - when 'PASS' then results[:successes] << {:test => test_name, :line => src_line, :message => msg} + line = line.tr('\\', '/') + _src_file, src_line, test_name, status, msg = line.split(/:/) + case status + when 'IGNORE' then results[:ignores] << { test: test_name, line: src_line, message: msg } + when 'FAIL' then results[:failures] << { test: test_name, line: src_line, message: msg } + when 'PASS' then results[:successes] << { test: test_name, line: src_line, message: msg } end end - return results + results end def parse_test_summary(summary) - if summary.find { |v| v =~ /(\d+) Tests (\d+) Failures (\d+) Ignored/ } - [$1.to_i,$2.to_i,$3.to_i] - else - raise "Couldn't parse test results: #{summary}" - end + raise "Couldn't parse test results: #{summary}" unless summary.find { |v| v =~ /(\d+) Tests (\d+) Failures (\d+) Ignored/ } + [Regexp.last_match(1).to_i, Regexp.last_match(2).to_i, Regexp.last_match(3).to_i] + end + + def here + File.expand_path(File.dirname(__FILE__)) end - def here; File.expand_path(File.dirname(__FILE__)); end private - def get_results_structure - return { - :source => {:path => '', :file => ''}, - :successes => [], - :failures => [], - :ignores => [], - :counts => {:total => 0, :passed => 0, :failed => 0, :ignored => 0}, - :stdout => [], + def results_structure + { + source: { path: '', file: '' }, + successes: [], + failures: [], + ignores: [], + counts: { total: 0, passed: 0, failed: 0, ignored: 0 }, + stdout: [] } end - def write_xml_header( stream ) + def write_xml_header(stream) stream.puts "" end - def write_suites_header( stream ) - stream.puts "" + def write_suites_header(stream) + stream.puts '' end - def write_suite_header( counts, stream ) + def write_suite_header(counts, stream) stream.puts "\t" end - def write_failures( results, stream ) + def write_failures(results, stream) result = results[:failures] result.each do |item| filename = File.join(results[:source][:path], File.basename(results[:source][:file], '.*')) @@ -206,15 +195,14 @@ class UnityToJUnit end end - def write_tests( results, stream ) + def write_tests(results, stream) result = results[:successes] result.each do |item| - filename = File.join(results[:source][:path], File.basename(results[:source][:file], '.*')) stream.puts "\t\t" end end - def write_ignored( results, stream ) + def write_ignored(results, stream) result = results[:ignores] result.each do |item| filename = File.join(results[:source][:path], File.basename(results[:source][:file], '.*')) @@ -226,39 +214,39 @@ class UnityToJUnit end end - def write_suite_footer( stream ) + def write_suite_footer(stream) stream.puts "\t" end - def write_suites_footer( stream ) - stream.puts "" + def write_suites_footer(stream) + stream.puts '' end -end #UnityToJUnit +end # UnityToJUnit if __FILE__ == $0 - #parse out the command options + # parse out the command options options = ArgvParser.parse(ARGV) - #create an instance to work with + # create an instance to work with utj = UnityToJUnit.new begin - #look in the specified or current directory for result files - targets = "#{options.results_dir.gsub(/\\/, '/')}**/*.test*" + # look in the specified or current directory for result files + targets = "#{options.results_dir.tr('\\', '/')}**/*.test*" results = Dir[targets] raise "No *.testpass, *.testfail, or *.testresults files found in '#{targets}'" if results.empty? - utj.set_targets(results) + utj.targets = results - #set the root path - utj.set_root_path(options.root_path) + # set the root path + utj.root = options.root_path - #set the output XML file name - #puts "Output File from options: #{options.out_file}" - utj.set_out_file(options.out_file) + # set the output XML file name + # puts "Output File from options: #{options.out_file}" + utj.out_file = options.out_file - #run the summarizer + # run the summarizer puts utj.run - rescue Exception => e + rescue StandardError => e utj.usage e.message end end diff --git a/tests/unity/auto/test_file_filter.rb b/tests/unity/auto/test_file_filter.rb index 3dbc26a..aad28e3 100644 --- a/tests/unity/auto/test_file_filter.rb +++ b/tests/unity/auto/test_file_filter.rb @@ -2,7 +2,7 @@ # Unity Project - A Test Framework for C # Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams # [Released under MIT License. Please refer to license.txt for details] -# ========================================== +# ========================================== require'yaml' @@ -10,14 +10,16 @@ module RakefileHelpers class TestFileFilter def initialize(all_files = false) @all_files = all_files - if not @all_files == true - if File.exist?('test_file_filter.yml') - filters = YAML.load_file( 'test_file_filter.yml' ) - @all_files, @only_files, @exclude_files = - filters[:all_files], filters[:only_files], filters[:exclude_files] - end - end - end + + return false unless @all_files + return false unless File.exist?('test_file_filter.yml') + + filters = YAML.load_file('test_file_filter.yml') + @all_files = filters[:all_files] + @only_files = filters[:only_files] + @exclude_files = filters[:exclude_files] + end + attr_accessor :all_files, :only_files, :exclude_files end end diff --git a/tests/unity/auto/type_sanitizer.rb b/tests/unity/auto/type_sanitizer.rb index 7c2c0ac..dafb882 100644 --- a/tests/unity/auto/type_sanitizer.rb +++ b/tests/unity/auto/type_sanitizer.rb @@ -1,8 +1,6 @@ module TypeSanitizer - def self.sanitize_c_identifier(unsanitized) # convert filename to valid C identifier by replacing invalid chars with '_' - return unsanitized.gsub(/[-\/\\\.\,\s]/, "_") + unsanitized.gsub(/[-\/\\\.\,\s]/, '_') end - end diff --git a/tests/unity/auto/unity_test_summary.rb b/tests/unity/auto/unity_test_summary.rb index 8f992e5..b37dc5f 100644 --- a/tests/unity/auto/unity_test_summary.rb +++ b/tests/unity/auto/unity_test_summary.rb @@ -4,7 +4,7 @@ # [Released under MIT License. Please refer to license.txt for details] # ========================================== -#!/usr/bin/ruby +# !/usr/bin/ruby # # unity_test_summary.rb # @@ -15,37 +15,35 @@ class UnityTestSummary include FileUtils::Verbose attr_reader :report, :total_tests, :failures, :ignored + attr_writer :targets, :root - def initialize(opts = {}) + def initialize(_opts = {}) @report = '' @total_tests = 0 @failures = 0 @ignored = 0 - - end def run # Clean up result file names - results = @targets.map {|target| target.gsub(/\\/,'/')} + results = @targets.map { |target| target.tr('\\', '/') } # Dig through each result file, looking for details on pass/fail: failure_output = [] ignore_output = [] results.each do |result_file| - lines = File.readlines(result_file).map { |line| line.chomp } - if lines.length == 0 - raise "Empty test result file: #{result_file}" - else - output = get_details(result_file, lines) - failure_output << output[:failures] unless output[:failures].empty? - ignore_output << output[:ignores] unless output[:ignores].empty? - tests,failures,ignored = parse_test_summary(lines) - @total_tests += tests - @failures += failures - @ignored += ignored - end + lines = File.readlines(result_file).map(&:chomp) + + raise "Empty test result file: #{result_file}" if lines.empty? + + output = get_details(result_file, lines) + failure_output << output[:failures] unless output[:failures].empty? + ignore_output << output[:ignores] unless output[:ignores].empty? + tests, failures, ignored = parse_test_summary(lines) + @total_tests += tests + @failures += failures + @ignored += ignored end if @ignored > 0 @@ -72,77 +70,67 @@ class UnityTestSummary @report += "\n" end - def set_targets(target_array) - @targets = target_array - end - - def set_root_path(path) - @root = path - end - - def usage(err_msg=nil) + def usage(err_msg = nil) puts "\nERROR: " puts err_msg if err_msg puts "\nUsage: unity_test_summary.rb result_file_directory/ root_path/" - puts " result_file_directory - The location of your results files." - puts " Defaults to current directory if not specified." - puts " Should end in / if specified." - puts " root_path - Helpful for producing more verbose output if using relative paths." + puts ' result_file_directory - The location of your results files.' + puts ' Defaults to current directory if not specified.' + puts ' Should end in / if specified.' + puts ' root_path - Helpful for producing more verbose output if using relative paths.' exit 1 end protected - def get_details(result_file, lines) - results = { :failures => [], :ignores => [], :successes => [] } + def get_details(_result_file, lines) + results = { failures: [], ignores: [], successes: [] } lines.each do |line| - src_file,src_line,test_name,status,msg = line.split(/:/) - line_out = ((@root && (@root != 0)) ? "#{@root}#{line}" : line ).gsub(/\//, "\\") - case(status) - when 'IGNORE' then results[:ignores] << line_out - when 'FAIL' then results[:failures] << line_out - when 'PASS' then results[:successes] << line_out + _src_file, _src_line, _test_name, status, _msg = line.split(/:/) + line_out = (@root && (@root != 0) ? "#{@root}#{line}" : line).gsub(/\//, '\\') + case status + when 'IGNORE' then results[:ignores] << line_out + when 'FAIL' then results[:failures] << line_out + when 'PASS' then results[:successes] << line_out end end - return results + results end def parse_test_summary(summary) - if summary.find { |v| v =~ /(\d+) Tests (\d+) Failures (\d+) Ignored/ } - [$1.to_i,$2.to_i,$3.to_i] - else - raise "Couldn't parse test results: #{summary}" - end + raise "Couldn't parse test results: #{summary}" unless summary.find { |v| v =~ /(\d+) Tests (\d+) Failures (\d+) Ignored/ } + [Regexp.last_match(1).to_i, Regexp.last_match(2).to_i, Regexp.last_match(3).to_i] end - def here; File.expand_path(File.dirname(__FILE__)); end - + def here + File.expand_path(File.dirname(__FILE__)) + end end if $0 == __FILE__ - #parse out the command options - opts, args = ARGV.partition {|v| v =~ /^--\w+/} - opts.map! {|v| v[2..-1].to_sym } + # parse out the command options + opts, args = ARGV.partition { |v| v =~ /^--\w+/ } + opts.map! { |v| v[2..-1].to_sym } - #create an instance to work with + # create an instance to work with uts = UnityTestSummary.new(opts) begin - #look in the specified or current directory for result files + # look in the specified or current directory for result files args[0] ||= './' - targets = "#{ARGV[0].gsub(/\\/, '/')}**/*.test*" + targets = "#{ARGV[0].tr('\\', '/')}**/*.test*" results = Dir[targets] raise "No *.testpass, *.testfail, or *.testresults files found in '#{targets}'" if results.empty? - uts.set_targets(results) + uts.targets = results - #set the root path + # set the root path args[1] ||= Dir.pwd + '/' - uts.set_root_path(ARGV[1]) + uts.root = ARGV[1] - #run the summarizer + # run the summarizer puts uts.run - rescue Exception => e + rescue StandardError => e uts.usage e.message end end diff --git a/tests/unity/docs/ThrowTheSwitchCodingStandard.md b/tests/unity/docs/ThrowTheSwitchCodingStandard.md new file mode 100644 index 0000000..a85adef --- /dev/null +++ b/tests/unity/docs/ThrowTheSwitchCodingStandard.md @@ -0,0 +1,207 @@ +# ThrowTheSwitch.org Coding Standard + +Hi. Welcome to the coding standard for ThrowTheSwitch.org. For the most part, +we try to follow these standards to unify our contributors' code into a cohesive +unit (puns intended). You might find places where these standards aren't +followed. We're not perfect. Please be polite where you notice these discrepancies +and we'll try to be polite when we notice yours. + +;) + + +## Why Have A Coding Standard? + +Being consistent makes code easier to understand. We've made an attempt to keep +our standard simple because we also believe that we can only expect someone to +follow something that is understandable. Please do your best. + + +## Our Philosophy + +Before we get into details on syntax, let's take a moment to talk about our +vision for these tools. We're C developers and embedded software developers. +These tools are great to test any C code, but catering to embedded software has +made us more tolerant of compiler quirks. There are a LOT of quirky compilers +out there. By quirky I mean "doesn't follow standards because they feel like +they have a license to do as they wish." + +Our philosophy is "support every compiler we can". Most often, this means that +we aim for writing C code that is standards compliant (often C89... that seems +to be a sweet spot that is almost always compatible). But it also means these +tools are tolerant of things that aren't common. Some that aren't even +compliant. There are configuration options to override the size of standard +types. There are configuration options to force Unity to not use certain +standard library functions. A lot of Unity is configurable and we have worked +hard to make it not TOO ugly in the process. + +Similarly, our tools that parse C do their best. They aren't full C parsers +(yet) and, even if they were, they would still have to accept non-standard +additions like gcc extensions or specifying `@0x1000` to force a variable to +compile to a particular location. It's just what we do, because we like +everything to Just Workâ„¢. + +Speaking of having things Just Workâ„¢, that's our second philosophy. By that, we +mean that we do our best to have EVERY configuration option have a logical +default. We believe that if you're working with a simple compiler and target, +you shouldn't need to configure very much... we try to make the tools guess as +much as they can, but give the user the power to override it when it's wrong. + + +## Naming Things + +Let's talk about naming things. Programming is all about naming things. We name +files, functions, variables, and so much more. While we're not always going to +find the best name for something, we actually put quite a bit of effort into +finding *What Something WANTS to be Called*â„¢. + +When naming things, we more or less follow this hierarchy, the first being the +most important to us (but we do all four whenever possible): +1. Readable +2. Descriptive +3. Consistent +4. Memorable + + +#### Readable + +We want to read our code. This means we like names and flow that are more +naturally read. We try to avoid double negatives. We try to avoid cryptic +abbreviations (sticking to ones we feel are common). + + +#### Descriptive + +We like descriptive names for things, especially functions and variables. +Finding the right name for something is an important endeavor. You might notice +from poking around our code that this often results in names that are a little +longer than the average. Guilty. We're okay with a tiny bit more typing if it +means our code is easier to understand. + +There are two exceptions to this rule that we also stick to as religiously as +possible: + +First, while we realize hungarian notation (and similar systems for encoding +type information into variable names) is providing a more descriptive name, we +feel that (for the average developer) it takes away from readability and +therefore is to be avoided. + +Second, loop counters and other local throw-away variables often have a purpose +which is obvious. There's no need, therefore, to get carried away with complex +naming. We find i, j, and k are better loop counters than loopCounterVar or +whatnot. We only break this rule when we see that more description could improve +understanding of an algorithm. + + +#### Consistent + +We like consistency, but we're not really obsessed with it. We try to name our +configuration macros in a consistent fashion... you'll notice a repeated use of +UNITY_EXCLUDE_BLAH or UNITY_USES_BLAH macros. This helps users avoid having to +remember each macro's details. + + +#### Memorable + +Where ever it doesn't violate the above principles, we try to apply memorable +names. Sometimes this means using something that is simply descriptive, but +often we strive for descriptive AND unique... we like quirky names that stand +out in our memory and are easier to search for. Take a look through the file +names in Ceedling and you'll get a good idea of what we are talking about here. +Why use preprocess when you can use preprocessinator? Or what better describes a +module in charge of invoking tasks during releases than release_invoker? Don't +get carried away. The names are still descriptive and fulfill the above +requirements, but they don't feel stale. + + +## C and C++ Details + +We don't really want to add to the style battles out there. Tabs or spaces? +How many spaces? Where do the braces go? These are age-old questions that will +never be answered... or at least not answered in a way that will make everyone +happy. + +We've decided on our own style preferences. If you'd like to contribute to these +projects (and we hope that you do), then we ask if you do your best to follow +the same. It will only hurt a little. We promise. + + +#### Whitespace + +Our C-style is to use spaces and to use 4 of them per indent level. It's a nice +power-of-2 number that looks decent on a wide screen. We have no more reason +than that. We break that rule when we have lines that wrap (macros or function +arguments or whatnot). When that happens, we like to indent further to line +things up in nice tidy columns. + +```C + if (stuff_happened) + { + do_something(); + } +``` + + +#### Case + +- Files - all lower case with underscores. +- Variables - all lower case with underscores +- Macros - all caps with underscores. +- Typedefs - all caps with underscores. (also ends with _T). +- Functions - camel cased. Usually named ModuleName_FuncName +- Constants and Globals - camel cased. + + +#### Braces + +The left brace is on the next line after the declaration. The right brace is +directly below that. Everything in between in indented one level. If you're +catching an error and you have a one-line, go ahead and to it on the same line. + +```C + while (blah) + { + //Like so. Even if only one line, we use braces. + } +``` + + +#### Comments + +Do you know what we hate? Old-school C block comments. BUT, we're using them +anyway. As we mentioned, our goal is to support every compiler we can, +especially embedded compilers. There are STILL C compilers out there that only +support old-school block comments. So that is what we're using. We apologize. We +think they are ugly too. + + +## Ruby Details + +Is there really such thing as a Ruby coding standard? Ruby is such a free form +language, it seems almost sacrilegious to suggest that people should comply to +one method! We'll keep it really brief! + + +#### Whitespace + +Our Ruby style is to use spaces and to use 2 of them per indent level. It's a +nice power-of-2 number that really grooves with Ruby's compact style. We have no +more reason than that. We break that rule when we have lines that wrap. When +that happens, we like to indent further to line things up in nice tidy columns. + + +#### Case + +- Files - all lower case with underscores. +- Variables - all lower case with underscores +- Classes, Modules, etc - Camel cased. +- Functions - all lower case with underscores +- Constants - all upper case with underscores + + +## Documentation + +Egad. Really? We use markdown and we like pdf files because they can be made to +look nice while still being portable. Good enough? + + +*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)* diff --git a/tests/unity/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf b/tests/unity/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf index 2bce0ab..28f0c32 100644 Binary files a/tests/unity/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf and b/tests/unity/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf differ diff --git a/tests/unity/docs/UnityAssertionsReference.md b/tests/unity/docs/UnityAssertionsReference.md new file mode 100644 index 0000000..558f6db --- /dev/null +++ b/tests/unity/docs/UnityAssertionsReference.md @@ -0,0 +1,716 @@ +# Unity Assertions Reference + +## Background and Overview + +### Super Condensed Version + +- An assertion establishes truth (i.e. boolean True) for a single condition. +Upon boolean False, an assertion stops execution and reports the failure. +- Unity is mainly a rich collection of assertions and the support to gather up +and easily execute those assertions. +- The structure of Unity allows you to easily separate test assertions from +source code in, well, test code. +- Unity's assertions: +- Come in many, many flavors to handle different C types and assertion cases. +- Use context to provide detailed and helpful failure messages. +- Document types, expected values, and basic behavior in your source code for +free. + + +### Unity Is Several Things But Mainly It's Assertions + +One way to think of Unity is simply as a rich collection of assertions you can +use to establish whether your source code behaves the way you think it does. +Unity provides a framework to easily organize and execute those assertions in +test code separate from your source code. + + +### What's an Assertion? + +At their core, assertions are an establishment of truth - boolean truth. Was this +thing equal to that thing? Does that code doohickey have such-and-such property +or not? You get the idea. Assertions are executable code (to appreciate the big +picture on this read up on the difference between +[link:Dynamic Verification and Static Analysis]). A failing assertion stops +execution and reports an error through some appropriate I/O channel (e.g. +stdout, GUI, file, blinky light). + +Fundamentally, for dynamic verification all you need is a single assertion +mechanism. In fact, that's what the [assert() macro in C's standard library](http://en.wikipedia.org/en/wiki/Assert.h) +is for. So why not just use it? Well, we can do far better in the reporting +department. C's `assert()` is pretty dumb as-is and is particularly poor for +handling common data types like arrays, structs, etc. And, without some other +support, it's far too tempting to litter source code with C's `assert()`'s. It's +generally much cleaner, manageable, and more useful to separate test and source +code in the way Unity facilitates. + + +### Unity's Assertions: Helpful Messages _and_ Free Source Code Documentation + +Asserting a simple truth condition is valuable, but using the context of the +assertion is even more valuable. For instance, if you know you're comparing bit +flags and not just integers, then why not use that context to give explicit, +readable, bit-level feedback when an assertion fails? + +That's what Unity's collection of assertions do - capture context to give you +helpful, meaningful assertion failure messages. In fact, the assertions +themselves also serve as executable documentation about types and values in your +source code. So long as your tests remain current with your source and all those +tests pass, you have a detailed, up-to-date view of the intent and mechanisms in +your source code. And due to a wondrous mystery, well-tested code usually tends +to be well designed code. + + +## Assertion Conventions and Configurations + +### Naming and Parameter Conventions + +The convention of assertion parameters generally follows this order: + + TEST_ASSERT_X( {modifiers}, {expected}, actual, {size/count} ) + +The very simplest assertion possible uses only a single "actual" parameter (e.g. +a simple null check). + +"Actual" is the value being tested and unlike the other parameters in an +assertion construction is the only parameter present in all assertion variants. +"Modifiers" are masks, ranges, bit flag specifiers, floating point deltas. +"Expected" is your expected value (duh) to compare to an "actual" value; it's +marked as an optional parameter because some assertions only need a single +"actual" parameter (e.g. null check). +"Size/count" refers to string lengths, number of array elements, etc. + +Many of Unity's assertions are apparent duplications in that the same data type +is handled by several assertions. The differences among these are in how failure +messages are presented. For instance, a `_HEX` variant of an assertion prints +the expected and actual values of that assertion formatted as hexadecimal. + + +#### TEST_ASSERT_X_MESSAGE Variants + +_All_ assertions are complemented with a variant that includes a simple string +message as a final parameter. The string you specify is appended to an assertion +failure message in Unity output. + +For brevity, the assertion variants with a message parameter are not listed +below. Just tack on `_MESSAGE` as the final component to any assertion name in +the reference list below and add a string as the final parameter. + +_Example:_ + + TEST_ASSERT_X( {modifiers}, {expected}, actual, {size/count} ) + +becomes messageified like thus... + + TEST_ASSERT_X_MESSAGE( {modifiers}, {expected}, actual, {size/count}, message ) + + +#### TEST_ASSERT_X_ARRAY Variants + +Unity provides a collection of assertions for arrays containing a variety of +types. These are documented in the Array section below. These are almost on par +with the `_MESSAGE`variants of Unity's Asserts in that for pretty much any Unity +type assertion you can tack on `_ARRAY` and run assertions on an entire block of +memory. + + TEST_ASSERT_EQUAL_TYPEX_ARRAY( expected, actual, {size/count} ) + +"Expected" is an array itself. +"Size/count" is one or two parameters necessary to establish the number of array +elements and perhaps the length of elements within the array. + +Notes: +- The `_MESSAGE` variant convention still applies here to array assertions. The +`_MESSAGE` variants of the `_ARRAY` assertions have names ending with +`_ARRAY_MESSAGE`. +- Assertions for handling arrays of floating point values are grouped with float +and double assertions (see immediately following section). + + +### TEST_ASSERT_EACH_EQUAL_X Variants + +Unity provides a collection of assertions for arrays containing a variety of +types which can be compared to a single value as well. These are documented in +the Each Equal section below. these are almost on par with the `_MESSAGE` +variants of Unity's Asserts in that for pretty much any Unity type assertion you +can inject _EACH_EQUAL and run assertions on an entire block of memory. + + TEST_ASSERT_EACH_EQUAL_TYPEX( expected, actual, {size/count} ) + +"Expected" is a single value to compare to. +"Actual" is an array where each element will be compared to the expected value. +"Size/count" is one of two parameters necessary to establish the number of array +elements and perhaps the length of elements within the array. + +Notes: +- The `_MESSAGE` variant convention still applies here to Each Equal assertions. +- Assertions for handling Each Equal of floating point values are grouped with +float and double assertions (see immediately following section). + + +### Configuration + +#### Floating Point Support Is Optional + +Support for floating point types is configurable. That is, by defining the +appropriate preprocessor symbols, floats and doubles can be individually enabled +or disabled in Unity code. This is useful for embedded targets with no floating +point math support (i.e. Unity compiles free of errors for fixed point only +platforms). See Unity documentation for specifics. + + +#### Maximum Data Type Width Is Configurable + +Not all targets support 64 bit wide types or even 32 bit wide types. Define the +appropriate preprocessor symbols and Unity will omit all operations from +compilation that exceed the maximum width of your target. See Unity +documentation for specifics. + + +## The Assertions in All Their Blessed Glory + +### Basic Fail and Ignore + +##### `TEST_FAIL()` + +This fella is most often used in special conditions where your test code is +performing logic beyond a simple assertion. That is, in practice, `TEST_FAIL()` +will always be found inside a conditional code block. + +_Examples:_ +- Executing a state machine multiple times that increments a counter your test +code then verifies as a final step. +- Triggering an exception and verifying it (as in Try / Catch / Throw - see the +[CException](https://github.com/ThrowTheSwitch/CException) project). + +##### `TEST_IGNORE()` + +Marks a test case (i.e. function meant to contain test assertions) as ignored. +Usually this is employed as a breadcrumb to come back and implement a test case. +An ignored test case has effects if other assertions are in the enclosing test +case (see Unity documentation for more). + +### Boolean + +##### `TEST_ASSERT (condition)` + +##### `TEST_ASSERT_TRUE (condition)` + +##### `TEST_ASSERT_FALSE (condition)` + +##### `TEST_ASSERT_UNLESS (condition)` + +A simple wording variation on `TEST_ASSERT_FALSE`.The semantics of +`TEST_ASSERT_UNLESS` aid readability in certain test constructions or +conditional statements. + +##### `TEST_ASSERT_NULL (pointer)` + +##### `TEST_ASSERT_NOT_NULL (pointer)` + + +### Signed and Unsigned Integers (of all sizes) + +Large integer sizes can be disabled for build targets that do not support them. +For example, if your target only supports up to 16 bit types, by defining the +appropriate symbols Unity can be configured to omit 32 and 64 bit operations +that would break compilation (see Unity documentation for more). Refer to +Advanced Asserting later in this document for advice on dealing with other word +sizes. + +##### `TEST_ASSERT_EQUAL_INT (expected, actual)` + +##### `TEST_ASSERT_EQUAL_INT8 (expected, actual)` + +##### `TEST_ASSERT_EQUAL_INT16 (expected, actual)` + +##### `TEST_ASSERT_EQUAL_INT32 (expected, actual)` + +##### `TEST_ASSERT_EQUAL_INT64 (expected, actual)` + +##### `TEST_ASSERT_EQUAL (expected, actual)` + +##### `TEST_ASSERT_NOT_EQUAL (expected, actual)` + +##### `TEST_ASSERT_EQUAL_UINT (expected, actual)` + +##### `TEST_ASSERT_EQUAL_UINT8 (expected, actual)` + +##### `TEST_ASSERT_EQUAL_UINT16 (expected, actual)` + +##### `TEST_ASSERT_EQUAL_UINT32 (expected, actual)` + +##### `TEST_ASSERT_EQUAL_UINT64 (expected, actual)` + + +### Unsigned Integers (of all sizes) in Hexadecimal + +All `_HEX` assertions are identical in function to unsigned integer assertions +but produce failure messages with the `expected` and `actual` values formatted +in hexadecimal. Unity output is big endian. + +##### `TEST_ASSERT_EQUAL_HEX (expected, actual)` + +##### `TEST_ASSERT_EQUAL_HEX8 (expected, actual)` + +##### `TEST_ASSERT_EQUAL_HEX16 (expected, actual)` + +##### `TEST_ASSERT_EQUAL_HEX32 (expected, actual)` + +##### `TEST_ASSERT_EQUAL_HEX64 (expected, actual)` + + +### Masked and Bit-level Assertions + +Masked and bit-level assertions produce output formatted in hexadecimal. Unity +output is big endian. + + +##### `TEST_ASSERT_BITS (mask, expected, actual)` + +Only compares the masked (i.e. high) bits of `expected` and `actual` parameters. + + +##### `TEST_ASSERT_BITS_HIGH (mask, actual)` + +Asserts the masked bits of the `actual` parameter are high. + + +##### `TEST_ASSERT_BITS_LOW (mask, actual)` + +Asserts the masked bits of the `actual` parameter are low. + + +##### `TEST_ASSERT_BIT_HIGH (bit, actual)` + +Asserts the specified bit of the `actual` parameter is high. + + +##### `TEST_ASSERT_BIT_LOW (bit, actual)` + +Asserts the specified bit of the `actual` parameter is low. + + +### Integer Ranges (of all sizes) + +These assertions verify that the `expected` parameter is within +/- `delta` +(inclusive) of the `actual` parameter. For example, if the expected value is 10 +and the delta is 3 then the assertion will fail for any value outside the range +of 7 - 13. + +##### `TEST_ASSERT_INT_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_INT8_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_INT16_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_INT32_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_INT64_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_UINT_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_UINT8_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_UINT16_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_UINT32_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_UINT64_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_HEX_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_HEX8_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_HEX16_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_HEX32_WITHIN (delta, expected, actual)` + +##### `TEST_ASSERT_HEX64_WITHIN (delta, expected, actual)` + + +### Structs and Strings + +##### `TEST_ASSERT_EQUAL_PTR (expected, actual)` + +Asserts that the pointers point to the same memory location. + + +##### `TEST_ASSERT_EQUAL_STRING (expected, actual)` + +Asserts that the null terminated (`'\0'`)strings are identical. If strings are +of different lengths or any portion of the strings before their terminators +differ, the assertion fails. Two NULL strings (i.e. zero length) are considered +equivalent. + + +##### `TEST_ASSERT_EQUAL_MEMORY (expected, actual, len)` + +Asserts that the contents of the memory specified by the `expected` and `actual` +pointers is identical. The size of the memory blocks in bytes is specified by +the `len` parameter. + + +### Arrays + +`expected` and `actual` parameters are both arrays. `num_elements` specifies the +number of elements in the arrays to compare. + +`_HEX` assertions produce failure messages with expected and actual array +contents formatted in hexadecimal. + +For array of strings comparison behavior, see comments for +`TEST_ASSERT_EQUAL_STRING` in the preceding section. + +Assertions fail upon the first element in the compared arrays found not to +match. Failure messages specify the array index of the failed comparison. + +##### `TEST_ASSERT_EQUAL_INT_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_INT8_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_INT16_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_INT32_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_INT64_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_UINT_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_UINT8_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_UINT16_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_UINT32_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_UINT64_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_HEX_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_HEX8_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_HEX16_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_HEX32_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_HEX64_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_PTR_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_STRING_ARRAY (expected, actual, num_elements)` + +##### `TEST_ASSERT_EQUAL_MEMORY_ARRAY (expected, actual, len, num_elements)` + +`len` is the memory in bytes to be compared at each array element. + + +### Each Equal (Arrays to Single Value) + +`expected` are single values and `actual` are arrays. `num_elements` specifies +the number of elements in the arrays to compare. + +`_HEX` assertions produce failure messages with expected and actual array +contents formatted in hexadecimal. + +Assertions fail upon the first element in the compared arrays found not to +match. Failure messages specify the array index of the failed comparison. + +#### `TEST_ASSERT_EACH_EQUAL_INT (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_INT8 (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_INT16 (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_INT32 (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_INT64 (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_UINT (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_UINT8 (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_UINT16 (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_UINT32 (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_UINT64 (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_HEX (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_HEX8 (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_HEX16 (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_HEX32 (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_HEX64 (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_PTR (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_STRING (expected, actual, num_elements)` + +#### `TEST_ASSERT_EACH_EQUAL_MEMORY (expected, actual, len, num_elements)` + +`len` is the memory in bytes to be compared at each array element. + + +### Floating Point (If enabled) + +##### `TEST_ASSERT_FLOAT_WITHIN (delta, expected, actual)` + +Asserts that the `actual` value is within +/- `delta` of the `expected` value. +The nature of floating point representation is such that exact evaluations of +equality are not guaranteed. + + +##### `TEST_ASSERT_EQUAL_FLOAT (expected, actual)` + +Asserts that the ?actual?value is "close enough to be considered equal" to the +`expected` value. If you are curious about the details, refer to the Advanced +Asserting section for more details on this. Omitting a user-specified delta in a +floating point assertion is both a shorthand convenience and a requirement of +code generation conventions for CMock. + + +##### `TEST_ASSERT_EQUAL_FLOAT_ARRAY (expected, actual, num_elements)` + +See Array assertion section for details. Note that individual array element +float comparisons are executed using T?EST_ASSERT_EQUAL_FLOAT?.That is, user +specified delta comparison values requires a custom-implemented floating point +array assertion. + + +##### `TEST_ASSERT_FLOAT_IS_INF (actual)` + +Asserts that `actual` parameter is equivalent to positive infinity floating +point representation. + + +##### `TEST_ASSERT_FLOAT_IS_NEG_INF (actual)` + +Asserts that `actual` parameter is equivalent to negative infinity floating +point representation. + + +##### `TEST_ASSERT_FLOAT_IS_NAN (actual)` + +Asserts that `actual` parameter is a Not A Number floating point representation. + + +##### `TEST_ASSERT_FLOAT_IS_DETERMINATE (actual)` + +Asserts that ?actual?parameter is a floating point representation usable for +mathematical operations. That is, the `actual` parameter is neither positive +infinity nor negative infinity nor Not A Number floating point representations. + + +##### `TEST_ASSERT_FLOAT_IS_NOT_INF (actual)` + +Asserts that `actual` parameter is a value other than positive infinity floating +point representation. + + +##### `TEST_ASSERT_FLOAT_IS_NOT_NEG_INF (actual)` + +Asserts that `actual` parameter is a value other than negative infinity floating +point representation. + + +##### `TEST_ASSERT_FLOAT_IS_NOT_NAN (actual)` + +Asserts that `actual` parameter is a value other than Not A Number floating +point representation. + + +##### `TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE (actual)` + +Asserts that `actual` parameter is not usable for mathematical operations. That +is, the `actual` parameter is either positive infinity or negative infinity or +Not A Number floating point representations. + + +### Double (If enabled) + +##### `TEST_ASSERT_DOUBLE_WITHIN (delta, expected, actual)` + +Asserts that the `actual` value is within +/- `delta` of the `expected` value. +The nature of floating point representation is such that exact evaluations of +equality are not guaranteed. + + +##### `TEST_ASSERT_EQUAL_DOUBLE (expected, actual)` + +Asserts that the `actual` value is "close enough to be considered equal" to the +`expected` value. If you are curious about the details, refer to the Advanced +Asserting section for more details. Omitting a user-specified delta in a +floating point assertion is both a shorthand convenience and a requirement of +code generation conventions for CMock. + + +##### `TEST_ASSERT_EQUAL_DOUBLE_ARRAY (expected, actual, num_elements)` + +See Array assertion section for details. Note that individual array element +double comparisons are executed using `TEST_ASSERT_EQUAL_DOUBLE`.That is, user +specified delta comparison values requires a custom implemented double array +assertion. + + +##### `TEST_ASSERT_DOUBLE_IS_INF (actual)` + +Asserts that `actual` parameter is equivalent to positive infinity floating +point representation. + + +##### `TEST_ASSERT_DOUBLE_IS_NEG_INF (actual)` + +Asserts that `actual` parameter is equivalent to negative infinity floating point +representation. + + +##### `TEST_ASSERT_DOUBLE_IS_NAN (actual)` + +Asserts that `actual` parameter is a Not A Number floating point representation. + + +##### `TEST_ASSERT_DOUBLE_IS_DETERMINATE (actual)` + +Asserts that `actual` parameter is a floating point representation usable for +mathematical operations. That is, the ?actual?parameter is neither positive +infinity nor negative infinity nor Not A Number floating point representations. + + +##### `TEST_ASSERT_DOUBLE_IS_NOT_INF (actual)` + +Asserts that `actual` parameter is a value other than positive infinity floating +point representation. + + +##### `TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF (actual)` + +Asserts that `actual` parameter is a value other than negative infinity floating +point representation. + + +##### `TEST_ASSERT_DOUBLE_IS_NOT_NAN (actual)` + +Asserts that `actual` parameter is a value other than Not A Number floating +point representation. + + +##### `TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE (actual)` + +Asserts that `actual` parameter is not usable for mathematical operations. That +is, the `actual` parameter is either positive infinity or negative infinity or +Not A Number floating point representations. + + +## Advanced Asserting: Details On Tricky Assertions + +This section helps you understand how to deal with some of the trickier +assertion situations you may run into. It will give you a glimpse into some of +the under-the-hood details of Unity's assertion mechanisms. If you're one of +those people who likes to know what is going on in the background, read on. If +not, feel free to ignore the rest of this document until you need it. + + +### How do the EQUAL assertions work for FLOAT and DOUBLE? + +As you may know, directly checking for equality between a pair of floats or a +pair of doubles is sloppy at best and an outright no-no at worst. Floating point +values can often be represented in multiple ways, particularly after a series of +operations on a value. Initializing a variable to the value of 2.0 is likely to +result in a floating point representation of 2 x 20,but a series of +mathematical operations might result in a representation of 8 x 2-2 +that also evaluates to a value of 2. At some point repeated operations cause +equality checks to fail. + +So Unity doesn't do direct floating point comparisons for equality. Instead, it +checks if two floating point values are "really close." If you leave Unity +running with defaults, "really close" means "within a significant bit or two." +Under the hood, `TEST_ASSERT_EQUAL_FLOAT` is really `TEST_ASSERT_FLOAT_WITHIN` +with the `delta` parameter calculated on the fly. For single precision, delta is +the expected value multiplied by 0.00001, producing a very small proportional +range around the expected value. + +If you are expecting a value of 20,000.0 the delta is calculated to be 0.2. So +any value between 19,999.8 and 20,000.2 will satisfy the equality check. This +works out to be roughly a single bit of range for a single-precision number, and +that's just about as tight a tolerance as you can reasonably get from a floating +point value. + +So what happens when it's zero? Zero - even more than other floating point +values - can be represented many different ways. It doesn't matter if you have +0 x 20or 0 x 263.It's still zero, right? Luckily, if you +subtract these values from each other, they will always produce a difference of +zero, which will still fall between 0 plus or minus a delta of 0. So it still +works! + +Double precision floating point numbers use a much smaller multiplier, again +approximating a single bit of error. + +If you don't like these ranges and you want to make your floating point equality +assertions less strict, you can change these multipliers to whatever you like by +defining UNITY_FLOAT_PRECISION and UNITY_DOUBLE_PRECISION. See Unity +documentation for more. + + +### How do we deal with targets with non-standard int sizes? + +It's "fun" that C is a standard where something as fundamental as an integer +varies by target. According to the C standard, an `int` is to be the target's +natural register size, and it should be at least 16-bits and a multiple of a +byte. It also guarantees an order of sizes: + +```C +char <= short <= int <= long <= long long +``` + +Most often, `int` is 32-bits. In many cases in the embedded world, `int` is +16-bits. There are rare microcontrollers out there that have 24-bit integers, +and this remains perfectly standard C. + +To make things even more interesting, there are compilers and targets out there +that have a hard choice to make. What if their natural register size is 10-bits +or 12-bits? Clearly they can't fulfill _both_ the requirement to be at least +16-bits AND the requirement to match the natural register size. In these +situations, they often choose the natural register size, leaving us with +something like this: + +```C +char (8 bit) <= short (12 bit) <= int (12 bit) <= long (16 bit) +``` + +Um... yikes. It's obviously breaking a rule or two... but they had to break SOME +rules, so they made a choice. + +When the C99 standard rolled around, it introduced alternate standard-size types. +It also introduced macros for pulling in MIN/MAX values for your integer types. +It's glorious! Unfortunately, many embedded compilers can't be relied upon to +use the C99 types (Sometimes because they have weird register sizes as described +above. Sometimes because they don't feel like it?). + +A goal of Unity from the beginning was to support every combination of +microcontroller or microprocessor and C compiler. Over time, we've gotten really +close to this. There are a few tricks that you should be aware of, though, if +you're going to do this effectively on some of these more idiosyncratic targets. + +First, when setting up Unity for a new target, you're going to want to pay +special attention to the macros for automatically detecting types +(where available) or manually configuring them yourself. You can get information +on both of these in Unity's documentation. + +What about the times where you suddenly need to deal with something odd, like a +24-bit `int`? The simplest solution is to use the next size up. If you have a +24-bit `int`, configure Unity to use 32-bit integers. If you have a 12-bit +`int`, configure Unity to use 16 bits. There are two ways this is going to +affect you: + +1. When Unity displays errors for you, it's going to pad the upper unused bits +with zeros. +2. You're going to have to be careful of assertions that perform signed +operations, particularly `TEST_ASSERT_INT_WITHIN`.Such assertions might wrap +your `int` in the wrong place, and you could experience false failures. You can +always back down to a simple `TEST_ASSERT` and do the operations yourself. + + +*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)* diff --git a/tests/unity/docs/UnityAssertionsReference.pdf b/tests/unity/docs/UnityAssertionsReference.pdf deleted file mode 100644 index d8b10cc..0000000 Binary files a/tests/unity/docs/UnityAssertionsReference.pdf and /dev/null differ diff --git a/tests/unity/docs/UnityConfigurationGuide.md b/tests/unity/docs/UnityConfigurationGuide.md new file mode 100644 index 0000000..283d779 --- /dev/null +++ b/tests/unity/docs/UnityConfigurationGuide.md @@ -0,0 +1,398 @@ +# Unity Configuration Guide + +## C Standards, Compilers and Microcontrollers + +The embedded software world contains its challenges. Compilers support different +revisions of the C Standard. They ignore requirements in places, sometimes to +make the language more usable in some special regard. Sometimes it's to simplify +their support. Sometimes it's due to specific quirks of the microcontroller they +are targeting. Simulators add another dimension to this menagerie. + +Unity is designed to run on almost anything that is targeted by a C compiler. It +would be awesome if this could be done with zero configuration. While there are +some targets that come close to this dream, it is sadly not universal. It is +likely that you are going to need at least a couple of the configuration options +described in this document. + +All of Unity's configuration options are `#defines`. Most of these are simple +definitions. A couple are macros with arguments. They live inside the +unity_internals.h header file. We don't necessarily recommend opening that file +unless you really need to. That file is proof that a cross-platform library is +challenging to build. From a more positive perspective, it is also proof that a +great deal of complexity can be centralized primarily to one place in order to +provide a more consistent and simple experience elsewhere. + + +### Using These Options + +It doesn't matter if you're using a target-specific compiler and a simulator or +a native compiler. In either case, you've got a couple choices for configuring +these options: + +1. Because these options are specified via C defines, you can pass most of these +options to your compiler through command line compiler flags. Even if you're +using an embedded target that forces you to use their overbearing IDE for all +configuration, there will be a place somewhere in your project to configure +defines for your compiler. +2. You can create a custom `unity_config.h` configuration file (present in your +toolchain's search paths). In this file, you will list definitions and macros +specific to your target. All you must do is define `UNITY_INCLUDE_CONFIG_H` and +Unity will rely on `unity_config.h` for any further definitions it may need. + + +## The Options + +### Integer Types + +If you've been a C developer for long, you probably already know that C's +concept of an integer varies from target to target. The C Standard has rules +about the `int` matching the register size of the target microprocessor. It has +rules about the `int` and how its size relates to other integer types. An `int` +on one target might be 16 bits while on another target it might be 64. There are +more specific types in compilers compliant with C99 or later, but that's +certainly not every compiler you are likely to encounter. Therefore, Unity has a +number of features for helping to adjust itself to match your required integer +sizes. It starts off by trying to do it automatically. + + +##### `UNITY_EXCLUDE_STDINT_H` + +The first thing that Unity does to guess your types is check `stdint.h`. +This file includes defines like `UINT_MAX` that Unity can make use of to +learn a lot about your system. It's possible you don't want it to do this +(um. why not?) or (more likely) it's possible that your system doesn't +support `stdint.h`. If that's the case, you're going to want to define this. +That way, Unity will know to skip the inclusion of this file and you won't +be left with a compiler error. + +_Example:_ + #define UNITY_EXCLUDE_STDINT_H + + +##### `UNITY_EXCLUDE_LIMITS_H` + +The second attempt to guess your types is to check `limits.h`. Some compilers +that don't support `stdint.h` could include `limits.h` instead. If you don't +want Unity to check this file either, define this to make it skip the inclusion. + +_Example:_ + #define UNITY_EXCLUDE_LIMITS_H + + +##### `UNITY_EXCLUDE_SIZEOF` + +The third and final attempt to guess your types is to use the `sizeof()` +operator. Even if the first two options don't work, this one covers most cases. +There _is_ a rare compiler or two out there that doesn't support sizeof() in the +preprocessing stage, though. For these, you have the ability to disable this +feature as well. + +_Example:_ + #define UNITY_EXCLUDE_SIZEOF + +If you've disabled all of the automatic options above, you're going to have to +do the configuration yourself. Don't worry. Even this isn't too bad... there are +just a handful of defines that you are going to specify if you don't like the +defaults. + + +##### `UNITY_INT_WIDTH` + +Define this to be the number of bits an `int` takes up on your system. The +default, if not autodetected, is 32 bits. + +_Example:_ + #define UNITY_INT_WIDTH 16 + + +##### `UNITY_LONG_WIDTH` + +Define this to be the number of bits a `long` takes up on your system. The +default, if not autodetected, is 32 bits. This is used to figure out what kind +of 64-bit support your system can handle. Does it need to specify a `long` or a +`long long` to get a 64-bit value. On 16-bit systems, this option is going to be +ignored. + +_Example:_ + #define UNITY_LONG_WIDTH 16 + + +##### `UNITY_POINTER_WIDTH` + +Define this to be the number of bits a pointer takes up on your system. The +default, if not autodetected, is 32-bits. If you're getting ugly compiler +warnings about casting from pointers, this is the one to look at. + +_Example:_ + #define UNITY_POINTER_WIDTH 64 + + +##### `UNITY_INCLUDE_64` + +Unity will automatically include 64-bit support if it auto-detects it, or if +your `int`, `long`, or pointer widths are greater than 32-bits. Define this to +enable 64-bit support if none of the other options already did it for you. There +can be a significant size and speed impact to enabling 64-bit support on small +targets, so don't define it if you don't need it. + +_Example:_ + #define UNITY_INCLUDE_64 + + +### Floating Point Types + +In the embedded world, it's not uncommon for targets to have no support for +floating point operations at all or to have support that is limited to only +single precision. We are able to guess integer sizes on the fly because integers +are always available in at least one size. Floating point, on the other hand, is +sometimes not available at all. Trying to include `float.h` on these platforms +would result in an error. This leaves manual configuration as the only option. + + +##### `UNITY_INCLUDE_FLOAT` + +##### `UNITY_EXCLUDE_FLOAT` + +##### `UNITY_INCLUDE_DOUBLE` + +##### `UNITY_EXCLUDE_DOUBLE` + +By default, Unity guesses that you will want single precision floating point +support, but not double precision. It's easy to change either of these using the +include and exclude options here. You may include neither, either, or both, as +suits your needs. For features that are enabled, the following floating point +options also become available. + +_Example:_ + + //what manner of strange processor is this? + #define UNITY_EXCLUDE_FLOAT + #define UNITY_INCLUDE_DOUBLE + + +##### `UNITY_FLOAT_VERBOSE` + +##### `UNITY_DOUBLE_VERBOSE` + +Unity aims for as small of a footprint as possible and avoids most standard +library calls (some embedded platforms don't have a standard library!). Because +of this, its routines for printing integer values are minimalist and hand-coded. +To keep Unity universal, though, we chose to _not_ develop our own floating +point print routines. Instead, the display of floating point values during a +failure are optional. By default, Unity will not print the actual results of +floating point assertion failure. So a failed assertion will produce a message +like `"Values Not Within Delta"`. If you would like verbose failure messages for +floating point assertions, use these options to give more explicit failure +messages (e.g. `"Expected 4.56 Was 4.68"`). Note that this feature requires the +use of `sprintf` so might not be desirable in all cases. + +_Example:_ + #define UNITY_DOUBLE_VERBOSE + + +##### `UNITY_FLOAT_TYPE` + +If enabled, Unity assumes you want your `FLOAT` asserts to compare standard C +floats. If your compiler supports a specialty floating point type, you can +always override this behavior by using this definition. + +_Example:_ + #define UNITY_FLOAT_TYPE float16_t + + +##### `UNITY_DOUBLE_TYPE` + +If enabled, Unity assumes you want your `DOUBLE` asserts to compare standard C +doubles. If you would like to change this, you can specify something else by +using this option. For example, defining `UNITY_DOUBLE_TYPE` to `long double` +could enable gargantuan floating point types on your 64-bit processor instead of +the standard `double`. + +_Example:_ + #define UNITY_DOUBLE_TYPE long double + + +##### `UNITY_FLOAT_PRECISION` + +##### `UNITY_DOUBLE_PRECISION` + +If you look up `UNITY_ASSERT_EQUAL_FLOAT` and `UNITY_ASSERT_EQUAL_DOUBLE` as +documented in the big daddy Unity Assertion Guide, you will learn that they are +not really asserting that two values are equal but rather that two values are +"close enough" to equal. "Close enough" is controlled by these precision +configuration options. If you are working with 32-bit floats and/or 64-bit +doubles (the normal on most processors), you should have no need to change these +options. They are both set to give you approximately 1 significant bit in either +direction. The float precision is 0.00001 while the double is 10-12. +For further details on how this works, see the appendix of the Unity Assertion +Guide. + +_Example:_ + #define UNITY_FLOAT_PRECISION 0.001f + + +### Toolset Customization + +In addition to the options listed above, there are a number of other options +which will come in handy to customize Unity's behavior for your specific +toolchain. It is possible that you may not need to touch any of these... but +certain platforms, particularly those running in simulators, may need to jump +through extra hoops to operate properly. These macros will help in those +situations. + + +##### `UNITY_OUTPUT_CHAR(a)` + +##### `UNITY_OUTPUT_FLUSH()` + +##### `UNITY_OUTPUT_START()` + +##### `UNITY_OUTPUT_COMPLETE()` + +By default, Unity prints its results to `stdout` as it runs. This works +perfectly fine in most situations where you are using a native compiler for +testing. It works on some simulators as well so long as they have `stdout` +routed back to the command line. There are times, however, where the simulator +will lack support for dumping results or you will want to route results +elsewhere for other reasons. In these cases, you should define the +`UNITY_OUTPUT_CHAR` macro. This macro accepts a single character at a time (as +an `int`, since this is the parameter type of the standard C `putchar` function +most commonly used). You may replace this with whatever function call you like. + +_Example:_ +Say you are forced to run your test suite on an embedded processor with no +`stdout` option. You decide to route your test result output to a custom serial +`RS232_putc()` function you wrote like thus: + + #define UNITY_OUTPUT_CHAR(a) RS232_putc(a) + #define UNITY_OUTPUT_START() RS232_config(115200,1,8,0) + #define UNITY_OUTPUT_FLUSH() RS232_flush() + #define UNITY_OUTPUT_COMPLETE() RS232_close() + +_Note:_ +`UNITY_OUTPUT_FLUSH()` can be set to the standard out flush function simply by +specifying `UNITY_USE_FLUSH_STDOUT`. No other defines are required. If you +specify a custom flush function instead with `UNITY_OUTPUT_FLUSH` directly, it +will declare an instance of your function by default. If you want to disable +this behavior, add `UNITY_OMIT_OUTPUT_FLUSH_HEADER_DECLARATION`. + + +##### `UNITY_SUPPORT_WEAK` + +For some targets, Unity can make the otherwise required `setUp()` and +`tearDown()` functions optional. This is a nice convenience for test writers +since `setUp` and `tearDown` don't often actually _do_ anything. If you're using +gcc or clang, this option is automatically defined for you. Other compilers can +also support this behavior, if they support a C feature called weak functions. A +weak function is a function that is compiled into your executable _unless_ a +non-weak version of the same function is defined elsewhere. If a non-weak +version is found, the weak version is ignored as if it never existed. If your +compiler supports this feature, you can let Unity know by defining +`UNITY_SUPPORT_WEAK` as the function attributes that would need to be applied to +identify a function as weak. If your compiler lacks support for weak functions, +you will always need to define `setUp` and `tearDown` functions (though they can +be and often will be just empty). The most common options for this feature are: + +_Example:_ + #define UNITY_SUPPORT_WEAK weak + #define UNITY_SUPPORT_WEAK __attribute__((weak)) + + +##### `UNITY_PTR_ATTRIBUTE` + +Some compilers require a custom attribute to be assigned to pointers, like +`near` or `far`. In these cases, you can give Unity a safe default for these by +defining this option with the attribute you would like. + +_Example:_ + #define UNITY_PTR_ATTRIBUTE __attribute__((far)) + #define UNITY_PTR_ATTRIBUTE near + + +## Getting Into The Guts + +There will be cases where the options above aren't quite going to get everything +perfect. They are likely sufficient for any situation where you are compiling +and executing your tests with a native toolchain (e.g. clang on Mac). These +options may even get you through the majority of cases encountered in working +with a target simulator run from your local command line. But especially if you +must run your test suite on your target hardware, your Unity configuration will +require special help. This special help will usually reside in one of two +places: the `main()` function or the `RUN_TEST` macro. Let's look at how these +work. + + +##### `main()` + +Each test module is compiled and run on its own, separate from the other test +files in your project. Each test file, therefore, has a `main` function. This +`main` function will need to contain whatever code is necessary to initialize +your system to a workable state. This is particularly true for situations where +you must set up a memory map or initialize a communication channel for the +output of your test results. + +A simple main function looks something like this: + + int main(void) { + UNITY_BEGIN(); + RUN_TEST(test_TheFirst); + RUN_TEST(test_TheSecond); + RUN_TEST(test_TheThird); + return UNITY_END(); + } + +You can see that our main function doesn't bother taking any arguments. For our +most barebones case, we'll never have arguments because we just run all the +tests each time. Instead, we start by calling `UNITY_BEGIN`. We run each test +(in whatever order we wish). Finally, we call `UNITY_END`, returning its return +value (which is the total number of failures). + +It should be easy to see that you can add code before any test cases are run or +after all the test cases have completed. This allows you to do any needed +system-wide setup or teardown that might be required for your special +circumstances. + + +##### `RUN_TEST` + +The `RUN_TEST` macro is called with each test case function. Its job is to +perform whatever setup and teardown is necessary for executing a single test +case function. This includes catching failures, calling the test module's +`setUp()` and `tearDown()` functions, and calling `UnityConcludeTest()`. If +using CMock or test coverage, there will be additional stubs in use here. A +simple minimalist RUN_TEST macro looks something like this: + + #define RUN_TEST(testfunc) \ + UNITY_NEW_TEST(#testfunc) \ + if (TEST_PROTECT()) { \ + setUp(); \ + testfunc(); \ + } \ + if (TEST_PROTECT() && (!TEST_IS_IGNORED)) \ + tearDown(); \ + UnityConcludeTest(); + +So that's quite a macro, huh? It gives you a glimpse of what kind of stuff Unity +has to deal with for every single test case. For each test case, we declare that +it is a new test. Then we run `setUp` and our test function. These are run +within a `TEST_PROTECT` block, the function of which is to handle failures that +occur during the test. Then, assuming our test is still running and hasn't been +ignored, we run `tearDown`. No matter what, our last step is to conclude this +test before moving on to the next. + +Let's say you need to add a call to `fsync` to force all of your output data to +flush to a file after each test. You could easily insert this after your +`UnityConcludeTest` call. Maybe you want to write an xml tag before and after +each result set. Again, you could do this by adding lines to this macro. Updates +to this macro are for the occasions when you need an action before or after +every single test case throughout your entire suite of tests. + + +## Happy Porting + +The defines and macros in this guide should help you port Unity to just about +any C target we can imagine. If you run into a snag or two, don't be afraid of +asking for help on the forums. We love a good challenge! + + +*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)* diff --git a/tests/unity/docs/UnityConfigurationGuide.pdf b/tests/unity/docs/UnityConfigurationGuide.pdf deleted file mode 100644 index 5ca1a7f..0000000 Binary files a/tests/unity/docs/UnityConfigurationGuide.pdf and /dev/null differ diff --git a/tests/unity/docs/UnityGettingStartedGuide.md b/tests/unity/docs/UnityGettingStartedGuide.md new file mode 100644 index 0000000..50fc91c --- /dev/null +++ b/tests/unity/docs/UnityGettingStartedGuide.md @@ -0,0 +1,191 @@ +# Unity - Getting Started + +## Welcome + +Congratulations. You're now the proud owner of your very own pile of bits! What +are you going to do with all these ones and zeros? This document should be able +to help you decide just that. + +Unity is a unit test framework. The goal has been to keep it small and +functional. The core Unity test framework is three files: a single C file and a +couple header files. These team up to provide functions and macros to make +testing easier. + +Unity was designed to be cross platform. It works hard to stick with C standards +while still providing support for the many embedded C compilers that bend the +rules. Unity has been used with many compilers, including GCC, IAR, Clang, +Green Hills, Microchip, and MS Visual Studio. It's not much work to get it to +work with a new target. + + +### Overview of the Documents + +#### Unity Assertions reference + +This document will guide you through all the assertion options provided by +Unity. This is going to be your unit testing bread and butter. You'll spend more +time with assertions than any other part of Unity. + + +#### Unity Assertions Cheat Sheet + +This document contains an abridged summary of the assertions described in the +previous document. It's perfect for printing and referencing while you +familiarize yourself with Unity's options. + + +#### Unity Configuration Guide + +This document is the one to reference when you are going to use Unity with a new +target or compiler. It'll guide you through the configuration options and will +help you customize your testing experience to meet your needs. + + +#### Unity Helper Scripts + +This document describes the helper scripts that are available for simplifying +your testing workflow. It describes the collection of optional Ruby scripts +included in the auto directory of your Unity installation. Neither Ruby nor +these scripts are necessary for using Unity. They are provided as a convenience +for those who wish to use them. + + +#### Unity License + +What's an open source project without a license file? This brief document +describes the terms you're agreeing to when you use this software. Basically, we +want it to be useful to you in whatever context you want to use it, but please +don't blame us if you run into problems. + + +### Overview of the Folders + +If you have obtained Unity through Github or something similar, you might be +surprised by just how much stuff you suddenly have staring you in the face. +Don't worry, Unity itself is very small. The rest of it is just there to make +your life easier. You can ignore it or use it at your convenience. Here's an +overview of everything in the project. + +- `src` - This is the code you care about! This folder contains a C file and two +header files. These three files _are_ Unity. +- `docs` - You're reading this document, so it's possible you have found your way +into this folder already. This is where all the handy documentation can be +found. +- `examples` - This contains a few examples of using Unity. +- `extras` - These are optional add ons to Unity that are not part of the core +project. If you've reached us through James Grenning's book, you're going to +want to look here. +- `test` - This is how Unity and its scripts are all tested. If you're just using +Unity, you'll likely never need to go in here. If you are the lucky team member +who gets to port Unity to a new toolchain, this is a good place to verify +everything is configured properly. +- `auto` - Here you will find helpful Ruby scripts for simplifying your test +workflow. They are purely optional and are not required to make use of Unity. + + +## How to Create A Test File + +Test files are C files. Most often you will create a single test file for each C +module that you want to test. The test file should include unity.h and the +header for your C module to be tested. + +Next, a test file will include a `setUp()` and `tearDown()` function. The setUp +function can contain anything you would like to run before each test. The +tearDown function can contain anything you would like to run after each test. +Both functions accept no arguments and return nothing. You may leave either or +both of these blank if you have no need for them. If you're using a compiler +that is configured to make these functions optional, you may leave them off +completely. Not sure? Give it a try. If you compiler complains that it can't +find setUp or tearDown when it links, you'll know you need to at least include +an empty function for these. + +The majority of the file will be a series of test functions. Test functions +follow the convention of starting with the word "test" or "spec". You don't HAVE +to name them this way, but it makes it clear what functions are tests for other +developers. Test functions take no arguments and return nothing. All test +accounting is handled internally in Unity. + +Finally, at the bottom of your test file, you will write a `main()` function. +This function will call `UNITY_BEGIN()`, then `RUN_TEST` for each test, and +finally `UNITY_END()`.This is what will actually trigger each of those test +functions to run, so it is important that each function gets its own `RUN_TEST` +call. + +Remembering to add each test to the main function can get to be tedious. If you +enjoy using helper scripts in your build process, you might consider making use +of our handy generate_test_runner.rb script. This will create the main function +and all the calls for you, assuming that you have followed the suggested naming +conventions. In this case, there is no need for you to include the main function +in your test file at all. + +When you're done, your test file will look something like this: + +```C +#include "unity.h" +#include "file_to_test.h" + +void setUp(void) { + // set stuff up here +} + +void tearDown(void) { + // clean stuff up here +} + +void test_function_should_doBlahAndBlah(void) { + //test stuff +} + +void test_function_should_doAlsoDoBlah(void) { + //more test stuff +} + +int main(void) { + UNITY_BEGIN(); + RUN_TEST(test_function_should_doBlahAndBlah); + RUN_TEST(test_function_should_doAlsoDoBlah); + return UNITY_END(); +} +``` + +It's possible that you will require more customization than this, eventually. +For that sort of thing, you're going to want to look at the configuration guide. +This should be enough to get you going, though. + + +## How to Build and Run A Test File + +This is the single biggest challenge to picking up a new unit testing framework, +at least in a language like C or C++. These languages are REALLY good at getting +you "close to the metal" (why is the phrase metal? Wouldn't it be more accurate +to say "close to the silicon"?). While this feature is usually a good thing, it +can make testing more challenging. + +You have two really good options for toolchains. Depending on where you're +coming from, it might surprise you that neither of these options is running the +unit tests on your hardware. +There are many reasons for this, but here's a short version: +- On hardware, you have too many constraints (processing power, memory, etc), +- On hardware, you don't have complete control over all registers, +- On hardware, unit testing is more challenging, +- Unit testing isn't System testing. Keep them separate. + +Instead of running your tests on your actual hardware, most developers choose to +develop them as native applications (using gcc or MSVC for example) or as +applications running on a simulator. Either is a good option. Native apps have +the advantages of being faster and easier to set up. Simulator apps have the +advantage of working with the same compiler as your target application. The +options for configuring these are discussed in the configuration guide. + +To get either to work, you might need to make a few changes to the file +containing your register set (discussed later). + +In either case, a test is built by linking unity, the test file, and the C +file(s) being tested. These files create an executable which can be run as the +test set for that module. Then, this process is repeated for the next test file. +This flexibility of separating tests into individual executables allows us to +much more thoroughly unit test our system and it keeps all the test code out of +our final release! + + +*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)* diff --git a/tests/unity/docs/UnityGettingStartedGuide.pdf b/tests/unity/docs/UnityGettingStartedGuide.pdf deleted file mode 100644 index 9d03233..0000000 Binary files a/tests/unity/docs/UnityGettingStartedGuide.pdf and /dev/null differ diff --git a/tests/unity/docs/UnityHelperScriptsGuide.md b/tests/unity/docs/UnityHelperScriptsGuide.md new file mode 100644 index 0000000..3a93009 --- /dev/null +++ b/tests/unity/docs/UnityHelperScriptsGuide.md @@ -0,0 +1,242 @@ +# Unity Helper Scripts + +## With a Little Help From Our Friends + +Sometimes what it takes to be a really efficient C programmer is a little non-C. +The Unity project includes a couple Ruby scripts for making your life just a tad +easier. They are completely optional. If you choose to use them, you'll need a +copy of Ruby, of course. Just install whatever the latest version is, and it is +likely to work. You can find Ruby at [ruby-lang.org](https://ruby-labg.org/). + + +### `generate_test_runner.rb` + +Are you tired of creating your own `main` function in your test file? Do you +keep forgetting to add a `RUN_TEST` call when you add a new test case to your +suite? Do you want to use CMock or other fancy add-ons but don't want to figure +out how to create your own `RUN_TEST` macro? + +Well then we have the perfect script for you! + +The `generate_test_runner` script processes a given test file and automatically +creates a separate test runner file that includes ?main?to execute the test +cases within the scanned test file. All you do then is add the generated runner +to your list of files to be compiled and linked, and presto you're done! + +This script searches your test file for void function signatures having a +function name beginning with "test" or "spec". It treats each of these +functions as a test case and builds up a test suite of them. For example, the +following includes three test cases: + +```C +void testVerifyThatUnityIsAwesomeAndWillMakeYourLifeEasier(void) +{ + ASSERT_TRUE(1); +} +void test_FunctionName_should_WorkProperlyAndReturn8(void) { + ASSERT_EQUAL_INT(8, FunctionName()); +} +void spec_Function_should_DoWhatItIsSupposedToDo(void) { + ASSERT_NOT_NULL(Function(5)); +} +``` + +You can run this script a couple of ways. The first is from the command line: + +```Shell +ruby generate_test_runner.rb TestFile.c NameOfRunner.c +``` + +Alternatively, if you include only the test file parameter, the script will copy +the name of the test file and automatically append "_Runner" to the name of the +generated file. The example immediately below will create TestFile_Runner.c. + +```Shell +ruby generate_test_runner.rb TestFile.c +``` + +You can also add a [YAML](http://www.yaml.org/) file to configure extra options. +Conveniently, this YAML file is of the same format as that used by Unity and +CMock. So if you are using YAML files already, you can simply pass the very same +file into the generator script. + +```Shell +ruby generate_test_runner.rb TestFile.c my_config.yml +``` + +The contents of the YAML file `my_config.yml` could look something like the +example below. If you're wondering what some of these options do, you're going +to love the next section of this document. + +```YAML +:unity: + :includes: + - stdio.h + - microdefs.h + :cexception: 1 + :suit_setup: "blah = malloc(1024);" + :suite_teardown: "free(blah);" +``` + +If you would like to force your generated test runner to include one or more +header files, you can just include those at the command line too. Just make sure +these are _after_ the YAML file, if you are using one: + +```Shell +ruby generate_test_runner.rb TestFile.c my_config.yml extras.h +``` + +Another option, particularly if you are already using Ruby to orchestrate your +builds - or more likely the Ruby-based build tool Rake - is requiring this +script directly. Anything that you would have specified in a YAML file can be +passed to the script as part of a hash. Let's push the exact same requirement +set as we did above but this time through Ruby code directly: + +```Ruby +require "generate_test_runner.rb" +options = { + :includes => ["stdio.h", "microdefs.h"], + :cexception => 1, + :suite_setup => "blah = malloc(1024);", + :suite_teardown => "free(blah);" +} +UnityTestRunnerGenerator.new.run(testfile, runner_name, options) +``` + +If you have multiple files to generate in a build script (such as a Rakefile), +you might want to instantiate a generator object with your options and call it +to generate each runner thereafter. Like thus: + +```Ruby +gen = UnityTestRunnerGenerator.new(options) +test_files.each do |f| + gen.run(f, File.basename(f,'.c')+"Runner.c" +end +``` + +#### Options accepted by generate_test_runner.rb: + +The following options are available when executing `generate_test_runner`. You +may pass these as a Ruby hash directly or specify them in a YAML file, both of +which are described above. In the `examples` directory, Example 3's Rakefile +demonstrates using a Ruby hash. + + +##### `:includes` + +This option specifies an array of file names to be ?#include?'d at the top of +your runner C file. You might use it to reference custom types or anything else +universally needed in your generated runners. + + +##### `:suite_setup` + +Define this option with C code to be executed _before any_ test cases are run. + + +##### `:suite_teardown` + +Define this option with C code to be executed ?after all?test cases have +finished. + + +##### `:enforce_strict_ordering` + +This option should be defined if you have the strict order feature enabled in +CMock (see CMock documentation). This generates extra variables required for +everything to run smoothly. If you provide the same YAML to the generator as +used in CMock's configuration, you've already configured the generator properly. + + +##### `:plugins` + +This option specifies an array of plugins to be used (of course, the array can +contain only a single plugin). This is your opportunity to enable support for +CException support, which will add a check for unhandled exceptions in each +test, reporting a failure if one is detected. To enable this feature using Ruby: + +```Ruby +:plugins => [ :cexception ] +``` + +Or as a yaml file: + +```YAML +:plugins: + -:cexception +``` + +If you are using CMock, it is very likely that you are already passing an array +of plugins to CMock. You can just use the same array here. This script will just +ignore the plugins that don't require additional support. + + +### `unity_test_summary.rb` + +A Unity test file contains one or more test case functions. Each test case can +pass, fail, or be ignored. Each test file is run individually producing results +for its collection of test cases. A given project will almost certainly be +composed of multiple test files. Therefore, the suite of tests is comprised of +one or more test cases spread across one or more test files. This script +aggregates individual test file results to generate a summary of all executed +test cases. The output includes how many tests were run, how many were ignored, +and how many failed. In addition, the output includes a listing of which +specific tests were ignored and failed. A good example of the breadth and +details of these results can be found in the `examples` directory. Intentionally +ignored and failing tests in this project generate corresponding entries in the +summary report. + +If you're interested in other (prettier?) output formats, check into the +Ceedling build tool project (ceedling.sourceforge.net) that works with Unity and +CMock and supports xunit-style xml as well as other goodies. + +This script assumes the existence of files ending with the extensions +`.testpass` and `.testfail`.The contents of these files includes the test +results summary corresponding to each test file executed with the extension set +according to the presence or absence of failures for that test file. The script +searches a specified path for these files, opens each one it finds, parses the +results, and aggregates and prints a summary. Calling it from the command line +looks like this: + +```Shell +ruby unity_test_summary.rb build/test/ +``` + +You can optionally specify a root path as well. This is really helpful when you +are using relative paths in your tools' setup, but you want to pull the summary +into an IDE like Eclipse for clickable shortcuts. + +```Shell +ruby unity_test_summary.rb build/test/ ~/projects/myproject/ +``` + +Or, if you're more of a Windows sort of person: + +```Shell +ruby unity_test_summary.rb build\teat\ C:\projects\myproject\ +``` + +When configured correctly, you'll see a final summary, like so: + +```Shell +-------------------------- +UNITY IGNORED TEST SUMMARY +-------------------------- +blah.c:22:test_sandwiches_should_HaveBreadOnTwoSides:IGNORE + +------------------------- +UNITY FAILED TEST SUMMARY +------------------------- +blah.c:87:test_sandwiches_should_HaveCondiments:FAIL:Expected 1 was 0 +meh.c:38:test_soda_should_BeCalledPop:FAIL:Expected "pop" was "coke" + +-------------------------- +OVERALL UNITY TEST SUMMARY +-------------------------- +45 TOTAL TESTS 2 TOTAL FAILURES 1 IGNORED +``` + +How convenient is that? + + +*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)* diff --git a/tests/unity/docs/UnityHelperScriptsGuide.pdf b/tests/unity/docs/UnityHelperScriptsGuide.pdf deleted file mode 100644 index e1618d7..0000000 Binary files a/tests/unity/docs/UnityHelperScriptsGuide.pdf and /dev/null differ diff --git a/tests/unity/examples/example_3/rakefile.rb b/tests/unity/examples/example_3/rakefile.rb index 9f1dbeb..bf9f42b 100644 --- a/tests/unity/examples/example_3/rakefile.rb +++ b/tests/unity/examples/example_3/rakefile.rb @@ -3,41 +3,41 @@ UNITY_ROOT = File.expand_path(File.dirname(__FILE__)) + '/../..' require 'rake' require 'rake/clean' -require HERE+'rakefile_helper' +require HERE + 'rakefile_helper' TEMP_DIRS = [ - File.join(HERE, 'build') -] + File.join(HERE, 'build') +].freeze TEMP_DIRS.each do |dir| directory(dir) CLOBBER.include(dir) end -task :prepare_for_tests => TEMP_DIRS +task prepare_for_tests: TEMP_DIRS include RakefileHelpers # Load default configuration, for now -DEFAULT_CONFIG_FILE = 'target_gcc_32.yml' +DEFAULT_CONFIG_FILE = 'target_gcc_32.yml'.freeze configure_toolchain(DEFAULT_CONFIG_FILE) -task :unit => [:prepare_for_tests] do - run_tests get_unit_test_files +task unit: [:prepare_for_tests] do + run_tests unit_test_files end -desc "Generate test summary" +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 'Build and test Unity' +task all: %i(clean unit summary) +task default: %i(clobber all) +task ci: [:default] +task cruise: [:default] -desc "Load configuration" -task :config, :config_file do |t, args| +desc 'Load configuration' +task :config, :config_file do |_t, args| configure_toolchain(args[:config_file]) end diff --git a/tests/unity/examples/example_3/rakefile_helper.rb b/tests/unity/examples/example_3/rakefile_helper.rb index ed41d80..a186cf0 100644 --- a/tests/unity/examples/example_3/rakefile_helper.rb +++ b/tests/unity/examples/example_3/rakefile_helper.rb @@ -1,12 +1,11 @@ require 'yaml' require 'fileutils' -require UNITY_ROOT+'/auto/unity_test_summary' -require UNITY_ROOT+'/auto/generate_test_runner' -require UNITY_ROOT+'/auto/colour_reporter' +require UNITY_ROOT + '/auto/unity_test_summary' +require UNITY_ROOT + '/auto/generate_test_runner' +require UNITY_ROOT + '/auto/colour_reporter' module RakefileHelpers - - C_EXTENSION = '.c' + C_EXTENSION = '.c'.freeze def load_configuration(config_file) $cfg_file = config_file @@ -17,22 +16,22 @@ module RakefileHelpers CLEAN.include($cfg['compiler']['build_path'] + '*.*') unless $cfg['compiler']['build_path'].nil? end - def configure_toolchain(config_file=DEFAULT_CONFIG_FILE) + 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 + def unit_test_files path = $cfg['compiler']['unit_tests_path'] + 'Test*' + C_EXTENSION - path.gsub!(/\\/, '/') + path.tr!('\\', '/') FileList.new(path) end - def get_local_include_dirs + def local_include_dirs include_dirs = $cfg['compiler']['includes']['items'].dup - include_dirs.delete_if {|dir| dir.is_a?(Array)} - return include_dirs + include_dirs.delete_if { |dir| dir.is_a?(Array) } + include_dirs end def extract_headers(filename) @@ -40,129 +39,126 @@ 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 - return includes + 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 + return src_file if File.exist?(src_file) end - return nil + nil end def tackit(strings) - if strings.is_a?(Array) - result = "\"#{strings.join}\"" - else - result = strings - end - return result + result = if strings.is_a?(Array) + "\"#{strings.join}\"" + else + strings + end + result end def squash(prefix, items) result = '' items.each { |item| result += " #{prefix}#{tackit(item)}" } - return result + 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 + 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) - return {:command => command, :defines => defines, :options => options, :includes => includes} + + { command: command, defines: defines, options: options, includes: includes } end - def compile(file, defines=[]) + def compile(file, _defines = []) compiler = build_compiler_fields - cmd_str = "#{compiler[:command]}#{compiler[:defines]}#{compiler[:options]}#{compiler[:includes]} #{file} " + + 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) - return obj_file + 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} + 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.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR) + + { command: command, options: options, includes: includes } 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} "}).join + - $cfg['linker']['bin_files']['prefix'] + ' ' + - $cfg['linker']['bin_files']['destination'] + - exe_name + $cfg['linker']['bin_files']['extension'] + (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} + 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 } end - def execute(command_string, verbose=true, raise_on_fail=true) + def execute(command_string, verbose = true, raise_on_fail = true) report command_string output = `#{command_string}`.chomp - report(output) if (verbose && !output.nil? && (output.length > 0)) - if (($?.exitstatus != 0) and (raise_on_fail)) + report(output) if verbose && !output.nil? && !output.empty? + if !$?.exitstatus.zero? && raise_on_fail raise "Command failed. (Returned #{$?.exitstatus})" end - return output + output end def report_summary summary = UnityTestSummary.new - summary.set_root_path(HERE) + summary.root = HERE results_glob = "#{$cfg['compiler']['build_path']}*.test*" - results_glob.gsub!(/\\/, '/') + results_glob.tr!('\\', '/') results = Dir[results_glob] - summary.set_targets(results) + summary.targets = results summary.run - fail_out "FAIL: There were failures" if (summary.failures > 0) + fail_out 'FAIL: 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 @@ -171,7 +167,7 @@ module RakefileHelpers $cfg['compiler']['defines']['items'] = [] if $cfg['compiler']['defines']['items'].nil? $cfg['compiler']['defines']['items'] << 'TEST' - include_dirs = get_local_include_dirs + include_dirs = local_include_dirs # Build and execute each unit test test_files.each do |test| @@ -181,9 +177,7 @@ module RakefileHelpers extract_headers(test).each do |header| # Compile corresponding source file if it exists src_file = find_source_file(header, include_dirs) - if !src_file.nil? - obj_list << compile(src_file, test_defines) - end + obj_list << compile(src_file, test_defines) unless src_file.nil? end # Build the test runner (generate if configured to do so) @@ -208,25 +202,24 @@ module RakefileHelpers # 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 + cmd_str = if simulator.nil? + executable + else + "#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}" + end output = execute(cmd_str, true, false) test_results = $cfg['compiler']['build_path'] + test_base - if output.match(/OK$/m).nil? - test_results += '.testfail' - else - test_results += '.testpass' - end + test_results += if output.match(/OK$/m).nil? + '.testfail' + else + '.testpass' + end File.open(test_results, 'w') { |f| f.print output } end end def build_application(main) - - report "Building application..." + report 'Building application...' obj_list = [] load_configuration($cfg_file) @@ -236,9 +229,7 @@ module RakefileHelpers 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? - obj_list << compile(src_file) - end + obj_list << compile(src_file) unless src_file.nil? end # Build the main source file @@ -251,8 +242,8 @@ module RakefileHelpers def fail_out(msg) puts msg - puts "Not returning exit code so continuous integration can pass" -# exit(-1) # Only removed to pass example_3, which has failing tests on purpose. -# Still fail if the build fails for any other reason. + puts 'Not returning exit code so continuous integration can pass' + # exit(-1) # Only removed to pass example_3, which has failing tests on purpose. + # Still fail if the build fails for any other reason. end end diff --git a/tests/unity/extras/fixture/rakefile.rb b/tests/unity/extras/fixture/rakefile.rb index eb51d02..7603e57 100644 --- a/tests/unity/extras/fixture/rakefile.rb +++ b/tests/unity/extras/fixture/rakefile.rb @@ -12,34 +12,34 @@ require 'rake/testtask' require HERE + 'rakefile_helper' TEMP_DIRS = [ - File.join(HERE, 'build') -] + File.join(HERE, 'build') +].freeze TEMP_DIRS.each do |dir| directory(dir) CLOBBER.include(dir) end -task :prepare_for_tests => TEMP_DIRS +task prepare_for_tests: TEMP_DIRS include RakefileHelpers # Load default configuration, for now -DEFAULT_CONFIG_FILE = 'gcc_auto_stdint.yml' +DEFAULT_CONFIG_FILE = 'gcc_auto_stdint.yml'.freeze configure_toolchain(DEFAULT_CONFIG_FILE) -task :unit => [:prepare_for_tests] do +task unit: [:prepare_for_tests] do run_tests end -desc "Build and test Unity Framework" -task :all => [:clean, :unit] -task :default => [:clobber, :all] -task :ci => [:no_color, :default] -task :cruise => [:no_color, :default] +desc 'Build and test Unity Framework' +task all: %i(clean unit) +task default: %i(clobber all) +task ci: %i(no_color default) +task cruise: %i(no_color default) -desc "Load configuration" -task :config, :config_file do |t, args| +desc 'Load configuration' +task :config, :config_file do |_t, args| configure_toolchain(args[:config_file]) end diff --git a/tests/unity/extras/fixture/rakefile_helper.rb b/tests/unity/extras/fixture/rakefile_helper.rb index 85d714f..5aa8e56 100644 --- a/tests/unity/extras/fixture/rakefile_helper.rb +++ b/tests/unity/extras/fixture/rakefile_helper.rb @@ -6,28 +6,27 @@ require 'yaml' require 'fileutils' -require HERE+'../../auto/unity_test_summary' -require HERE+'../../auto/generate_test_runner' -require HERE+'../../auto/colour_reporter' +require HERE + '../../auto/unity_test_summary' +require HERE + '../../auto/generate_test_runner' +require HERE + '../../auto/colour_reporter' module RakefileHelpers - - C_EXTENSION = '.c' + C_EXTENSION = '.c'.freeze def load_configuration(config_file) - unless ($configured) - $cfg_file = HERE+"../../test/targets/#{config_file}" unless (config_file =~ /[\\|\/]/) - $cfg = YAML.load(File.read($cfg_file)) - $colour_output = false unless $cfg['colour'] - $configured = true if (config_file != DEFAULT_CONFIG_FILE) - end + return if $configured + + $cfg_file = HERE + "../../test/targets/#{config_file}" unless config_file =~ /[\\|\/]/ + $cfg = YAML.load(File.read($cfg_file)) + $colour_output = false unless $cfg['colour'] + $configured = true if config_file != DEFAULT_CONFIG_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) + def configure_toolchain(config_file = DEFAULT_CONFIG_FILE) config_file += '.yml' unless config_file =~ /\.yml$/ config_file = config_file unless config_file =~ /[\\|\/]/ load_configuration(config_file) @@ -35,105 +34,105 @@ module RakefileHelpers end def tackit(strings) - if strings.is_a?(Array) - result = "\"#{strings.join}\"" - else - result = strings - end - return result + result = if strings.is_a?(Array) + "\"#{strings.join}\"" + else + strings + end + result end def squash(prefix, items) result = '' items.each { |item| result += " #{prefix}#{tackit(item)}" } - return result + 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'] + ['UNITY_OUTPUT_CHAR=UnityOutputCharSpy_OutputChar']) - end + command = tackit($cfg['compiler']['path']) + defines = if $cfg['compiler']['defines']['items'].nil? + '' + else + squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items'] + ['UNITY_OUTPUT_CHAR=UnityOutputCharSpy_OutputChar']) + 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} + + { command: command, defines: defines, options: options, includes: includes } end - def compile(file, defines=[]) + def compile(file, _defines = []) compiler = build_compiler_fields - unity_include = $cfg['compiler']['includes']['prefix']+'../../src' - cmd_str = "#{compiler[:command]}#{compiler[:defines]}#{compiler[:options]}#{compiler[:includes]} #{unity_include} #{file} " + - "#{$cfg['compiler']['object_files']['prefix']}#{$cfg['compiler']['object_files']['destination']}" + - "#{File.basename(file, C_EXTENSION)}#{$cfg['compiler']['object_files']['extension']}" + unity_include = $cfg['compiler']['includes']['prefix'] + '../../src' + cmd_str = "#{compiler[:command]}#{compiler[:defines]}#{compiler[:options]}#{compiler[:includes]} #{unity_include} #{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} + 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.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR) + + { command: command, options: options, includes: includes } 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} "}).join + - $cfg['linker']['bin_files']['prefix'] + ' ' + - $cfg['linker']['bin_files']['destination'] + - exe_name + $cfg['linker']['bin_files']['extension'] + (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} + 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 } end - def execute(command_string, verbose=true) + 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 + report(output) if verbose && !output.nil? && !output.empty? + raise "Command failed. (Returned #{$?.exitstatus})" if $?.exitstatus != 0 + output end def report_summary summary = UnityTestSummary.new - summary.set_root_path(HERE) + summary.root = HERE results_glob = "#{$cfg['compiler']['build_path']}*.test*" - results_glob.gsub!(/\\/, '/') + results_glob.tr!('\\', '/') results = Dir[results_glob] - summary.set_targets(results) + summary.targets = results summary.run end @@ -146,34 +145,34 @@ module RakefileHelpers $cfg['compiler']['defines']['items'] = [] if $cfg['compiler']['defines']['items'].nil? # Get a list of all source files needed - src_files = Dir[HERE+'src/*.c'] - src_files += Dir[HERE+'test/*.c'] - src_files += Dir[HERE+'test/main/*.c'] + src_files = Dir[HERE + 'src/*.c'] + src_files += Dir[HERE + 'test/*.c'] + src_files += Dir[HERE + 'test/main/*.c'] src_files << '../../src/unity.c' # Build object files src_files.each { |f| compile(f, test_defines) } - obj_list = src_files.map {|f| File.basename(f.ext($cfg['compiler']['object_files']['extension'])) } + obj_list = src_files.map { |f| File.basename(f.ext($cfg['compiler']['object_files']['extension'])) } # Link the test executable - test_base = "framework_test" + test_base = 'framework_test' 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 + " -v -r" - else - cmd_str = "#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}" - end + cmd_str = if simulator.nil? + executable + ' -v -r' + else + "#{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 + test_results += if output.match(/OK$/m).nil? + '.testfail' + else + '.testpass' + end File.open(test_results, 'w') { |f| f.print output } end end diff --git a/tests/unity/extras/fixture/src/unity_fixture_malloc_overrides.h b/tests/unity/extras/fixture/src/unity_fixture_malloc_overrides.h index 1b176e7..7daba50 100644 --- a/tests/unity/extras/fixture/src/unity_fixture_malloc_overrides.h +++ b/tests/unity/extras/fixture/src/unity_fixture_malloc_overrides.h @@ -26,6 +26,7 @@ * For example, when using FreeRTOS UNITY_FIXTURE_MALLOC becomes pvPortMalloc() * and UNITY_FIXTURE_FREE becomes vPortFree(). */ #if !defined(UNITY_FIXTURE_MALLOC) || !defined(UNITY_FIXTURE_FREE) + #include #define UNITY_FIXTURE_MALLOC(size) malloc(size) #define UNITY_FIXTURE_FREE(ptr) free(ptr) #else diff --git a/tests/unity/release/version.info b/tests/unity/release/version.info index 0f19985..3b904b6 100644 --- a/tests/unity/release/version.info +++ b/tests/unity/release/version.info @@ -1,2 +1,2 @@ -2.4.0 +2.4.1 diff --git a/tests/unity/src/unity.c b/tests/unity/src/unity.c index 5266364..177af0f 100644 --- a/tests/unity/src/unity.c +++ b/tests/unity/src/unity.c @@ -539,7 +539,8 @@ void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, const UNITY_UINT32 num_elements, const char* msg, const UNITY_LINE_TYPE lineNumber, - const UNITY_DISPLAY_STYLE_T style) + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags) { UNITY_UINT32 elements = num_elements; unsigned int length = style & 0xF; @@ -569,17 +570,17 @@ void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected; actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual; break; - default: /* length 4 bytes */ - expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected; - actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual; - length = 4; - break; #ifdef UNITY_SUPPORT_64 case 8: expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)expected; actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)actual; break; #endif + default: /* length 4 bytes */ + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual; + length = 4; + break; } if (expect_val != actual_val) @@ -601,7 +602,10 @@ void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, UnityAddMsgIfSpecified(msg); UNITY_FAIL_AND_BAIL; } - expected = (UNITY_INTERNAL_PTR)(length + (const char*)expected); + if (flags == UNITY_ARRAY_TO_ARRAY) + { + expected = (UNITY_INTERNAL_PTR)(length + (const char*)expected); + } actual = (UNITY_INTERNAL_PTR)(length + (const char*)actual); } } @@ -645,7 +649,8 @@ void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, const UNITY_UINT32 num_elements, const char* msg, - const UNITY_LINE_TYPE lineNumber) + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) { UNITY_UINT32 elements = num_elements; UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_expected = expected; @@ -673,7 +678,10 @@ void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, UnityAddMsgIfSpecified(msg); UNITY_FAIL_AND_BAIL; } - ptr_expected++; + if (flags == UNITY_ARRAY_TO_ARRAY) + { + ptr_expected++; + } ptr_actual++; } } @@ -771,7 +779,8 @@ void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expecte UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, const UNITY_UINT32 num_elements, const char* msg, - const UNITY_LINE_TYPE lineNumber) + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) { UNITY_UINT32 elements = num_elements; UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_expected = expected; @@ -799,7 +808,10 @@ void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expecte UnityAddMsgIfSpecified(msg); UNITY_FAIL_AND_BAIL; } - ptr_expected++; + if (flags == UNITY_ARRAY_TO_ARRAY) + { + ptr_expected++; + } ptr_actual++; } } @@ -898,16 +910,16 @@ void UnityAssertNumbersWithin(const UNITY_UINT delta, if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) { if (actual > expected) - Unity.CurrentTestFailed = ((UNITY_UINT)(actual - expected) > delta); + Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(actual - expected) > delta); else - Unity.CurrentTestFailed = ((UNITY_UINT)(expected - actual) > delta); + Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(expected - actual) > delta); } else { if ((UNITY_UINT)actual > (UNITY_UINT)expected) - Unity.CurrentTestFailed = ((UNITY_UINT)(actual - expected) > delta); + Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(actual - expected) > delta); else - Unity.CurrentTestFailed = ((UNITY_UINT)(expected - actual) > delta); + Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(expected - actual) > delta); } if (Unity.CurrentTestFailed) @@ -1004,13 +1016,17 @@ void UnityAssertEqualStringLen(const char* expected, } /*-----------------------------------------------*/ -void UnityAssertEqualStringArray(const char** expected, +void UnityAssertEqualStringArray(UNITY_INTERNAL_PTR expected, const char** actual, const UNITY_UINT32 num_elements, const char* msg, - const UNITY_LINE_TYPE lineNumber) + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) { - UNITY_UINT32 i, j = 0; + UNITY_UINT32 i = 0; + UNITY_UINT32 j = 0; + const char* exp = NULL; + const char* act = NULL; RETURN_IF_FAIL_OR_IGNORE; @@ -1020,18 +1036,35 @@ void UnityAssertEqualStringArray(const char** expected, UnityPrintPointlessAndBail(); } - if (expected == actual) return; /* Both are NULL or same pointer */ + if ((const void*)expected == (const void*)actual) + { + return; /* Both are NULL or same pointer */ + } + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { UNITY_FAIL_AND_BAIL; + } + + if (flags != UNITY_ARRAY_TO_ARRAY) + { + exp = (const char*)expected; + } do { - /* if both pointers not null compare the strings */ - if (expected[j] && actual[j]) + act = actual[j]; + if (flags == UNITY_ARRAY_TO_ARRAY) { - for (i = 0; expected[j][i] || actual[j][i]; i++) + exp = ((const char* const*)expected)[j]; + } + + /* if both pointers not null compare the strings */ + if (exp && act) + { + for (i = 0; exp[i] || act[i]; i++) { - if (expected[j][i] != actual[j][i]) + if (exp[i] != act[i]) { Unity.CurrentTestFailed = 1; break; @@ -1040,7 +1073,7 @@ void UnityAssertEqualStringArray(const char** expected, } else { /* handle case of one pointers being null (if both null, test should pass) */ - if (expected[j] != actual[j]) + if (exp != act) { Unity.CurrentTestFailed = 1; } @@ -1054,7 +1087,7 @@ void UnityAssertEqualStringArray(const char** expected, UnityPrint(UnityStrElement); UnityPrintNumberUnsigned(j); } - UnityPrintExpectedAndActualStrings((const char*)(expected[j]), (const char*)(actual[j])); + UnityPrintExpectedAndActualStrings(exp, act); UnityAddMsgIfSpecified(msg); UNITY_FAIL_AND_BAIL; } @@ -1067,7 +1100,8 @@ void UnityAssertEqualMemory(UNITY_INTERNAL_PTR expected, const UNITY_UINT32 length, const UNITY_UINT32 num_elements, const char* msg, - const UNITY_LINE_TYPE lineNumber) + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) { UNITY_PTR_ATTRIBUTE const unsigned char* ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected; UNITY_PTR_ATTRIBUTE const unsigned char* ptr_act = (UNITY_PTR_ATTRIBUTE const unsigned char*)actual; @@ -1111,9 +1145,70 @@ void UnityAssertEqualMemory(UNITY_INTERNAL_PTR expected, ptr_exp++; ptr_act++; } + if (flags == UNITY_ARRAY_TO_VAL) + { + ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected; + } } } +/*-----------------------------------------------*/ + +static union +{ + UNITY_INT8 i8; + UNITY_INT16 i16; + UNITY_INT32 i32; +#ifdef UNITY_SUPPORT_64 + UNITY_INT64 i64; +#endif +#ifndef UNITY_EXCLUDE_FLOAT + float f; +#endif +#ifndef UNITY_EXCLUDE_DOUBLE + double d; +#endif +} UnityQuickCompare; + +UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size) +{ + switch(size) + { + case 1: + UnityQuickCompare.i8 = (UNITY_INT8)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i8); + + case 2: + UnityQuickCompare.i16 = (UNITY_INT16)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i16); + +#ifdef UNITY_SUPPORT_64 + case 8: + UnityQuickCompare.i64 = (UNITY_INT64)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i64); +#endif + default: /* 4 bytes */ + UnityQuickCompare.i32 = (UNITY_INT32)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i32); + } +} + +#ifndef UNITY_EXCLUDE_FLOAT +UNITY_INTERNAL_PTR UnityFloatToPtr(const float num) +{ + UnityQuickCompare.f = num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.f); +} +#endif + +#ifndef UNITY_EXCLUDE_DOUBLE +UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num) +{ + UnityQuickCompare.d = num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.d); +} +#endif + /*----------------------------------------------- * Control Functions *-----------------------------------------------*/ @@ -1177,6 +1272,7 @@ void UnityIgnore(const char* msg, const UNITY_LINE_TYPE line) #pragma weak tearDown void tearDown(void) { } #endif + /*-----------------------------------------------*/ void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum) { @@ -1309,9 +1405,9 @@ int UnityParseOptions(int argc, char** argv) int IsStringInBiggerString(const char* longstring, const char* shortstring) { - char* lptr = (char*)longstring; - char* sptr = (char*)shortstring; - char* lnext = lptr; + const char* lptr = longstring; + const char* sptr = shortstring; + const char* lnext = lptr; if (*sptr == '*') return 1; @@ -1343,7 +1439,7 @@ int IsStringInBiggerString(const char* longstring, const char* shortstring) /* Otherwise we start in the long pointer 1 character further and try again */ lptr = lnext; - sptr = (char*)shortstring; + sptr = shortstring; } return 0; } diff --git a/tests/unity/src/unity.h b/tests/unity/src/unity.h index 30d0e91..6434238 100644 --- a/tests/unity/src/unity.h +++ b/tests/unity/src/unity.h @@ -74,6 +74,10 @@ void tearDown(void); * This method allows you to abort a test immediately with a PASS state, ignoring the remainder of the test. */ #define TEST_PASS() TEST_ABORT() +/* This macro does nothing, but it is useful for build tools (like Ceedling) to make use of this to figure out + * which files should be linked to in order to perform a test. Use it like TEST_FILE("sandwiches.c") */ +#define TEST_FILE(a) + /*------------------------------------------------------- * Test Asserts (simple) *-------------------------------------------------------*/ @@ -153,10 +157,31 @@ void tearDown(void); #define TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) #define TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, NULL) +/* Arrays Compared To Single Value */ +#define TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, NULL) + /* Floating Point (If Enabled) */ #define TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, NULL) #define TEST_ASSERT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) #define TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, NULL) #define TEST_ASSERT_FLOAT_IS_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, NULL) #define TEST_ASSERT_FLOAT_IS_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, NULL) #define TEST_ASSERT_FLOAT_IS_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, NULL) @@ -170,6 +195,7 @@ void tearDown(void); #define TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, NULL) #define TEST_ASSERT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) #define TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, NULL) #define TEST_ASSERT_DOUBLE_IS_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, NULL) #define TEST_ASSERT_DOUBLE_IS_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, NULL) #define TEST_ASSERT_DOUBLE_IS_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, NULL) @@ -258,10 +284,31 @@ void tearDown(void); #define TEST_ASSERT_EQUAL_STRING_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) #define TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, (message)) +/* Arrays Compared To Single Value*/ +#define TEST_ASSERT_EACH_EQUAL_INT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_PTR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_STRING_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_MEMORY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, (message)) + /* Floating Point (If Enabled) */ #define TEST_ASSERT_FLOAT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, (message)) #define TEST_ASSERT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) #define TEST_ASSERT_EQUAL_FLOAT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_FLOAT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, (message)) #define TEST_ASSERT_FLOAT_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, (message)) #define TEST_ASSERT_FLOAT_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, (message)) #define TEST_ASSERT_FLOAT_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, (message)) @@ -275,6 +322,7 @@ void tearDown(void); #define TEST_ASSERT_DOUBLE_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, (message)) #define TEST_ASSERT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) #define TEST_ASSERT_EQUAL_DOUBLE_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_DOUBLE_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, (message)) #define TEST_ASSERT_DOUBLE_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, (message)) #define TEST_ASSERT_DOUBLE_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, (message)) #define TEST_ASSERT_DOUBLE_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, (message)) diff --git a/tests/unity/src/unity_internals.h b/tests/unity/src/unity_internals.h index 9cebdf1..2cc1973 100644 --- a/tests/unity/src/unity_internals.h +++ b/tests/unity/src/unity_internals.h @@ -250,14 +250,19 @@ extern void UNITY_OUTPUT_CHAR(int); #endif #ifndef UNITY_OUTPUT_FLUSH -/* Default to using fflush, which is defined in stdio.h */ +#ifdef UNITY_USE_FLUSH_STDOUT +/* We want to use the stdout flush utility */ #include #define UNITY_OUTPUT_FLUSH (void)fflush(stdout) #else - /* If defined as something else, make sure we declare it here so it's ready for use */ - #ifndef UNITY_OMIT_OUTPUT_FLUSH_HEADER_DECLARATION +/* We've specified nothing, therefore flush should just be ignored */ +#define UNITY_OUTPUT_FLUSH +#endif +#else +/* We've defined flush as something else, so make sure we declare it here so it's ready for use */ +#ifndef UNITY_OMIT_OUTPUT_FLUSH_HEADER_DECLARATION extern void UNITY_OUTPUT_FLUSH(void); - #endif +#endif #endif #ifndef UNITY_OUTPUT_FLUSH @@ -360,6 +365,12 @@ typedef enum UNITY_FLOAT_TRAIT } UNITY_FLOAT_TRAIT_T; #endif +typedef enum +{ + UNITY_ARRAY_TO_VAL = 0, + UNITY_ARRAY_TO_ARRAY +} UNITY_FLAGS_T; + struct UNITY_STORAGE_T { const char* TestFile; @@ -447,7 +458,8 @@ void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, const UNITY_UINT32 num_elements, const char* msg, const UNITY_LINE_TYPE lineNumber, - const UNITY_DISPLAY_STYLE_T style); + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags); void UnityAssertBits(const UNITY_INT mask, const UNITY_INT expected, @@ -466,18 +478,20 @@ void UnityAssertEqualStringLen(const char* expected, const char* msg, const UNITY_LINE_TYPE lineNumber); -void UnityAssertEqualStringArray( const char** expected, +void UnityAssertEqualStringArray( UNITY_INTERNAL_PTR expected, const char** actual, const UNITY_UINT32 num_elements, const char* msg, - const UNITY_LINE_TYPE lineNumber); + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); void UnityAssertEqualMemory( UNITY_INTERNAL_PTR expected, UNITY_INTERNAL_PTR actual, const UNITY_UINT32 length, const UNITY_UINT32 num_elements, const char* msg, - const UNITY_LINE_TYPE lineNumber); + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); void UnityAssertNumbersWithin(const UNITY_UINT delta, const UNITY_INT expected, @@ -501,7 +515,8 @@ void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, const UNITY_UINT32 num_elements, const char* msg, - const UNITY_LINE_TYPE lineNumber); + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); void UnityAssertFloatSpecial(const UNITY_FLOAT actual, const char* msg, @@ -520,7 +535,8 @@ void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expecte UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, const UNITY_UINT32 num_elements, const char* msg, - const UNITY_LINE_TYPE lineNumber); + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, const char* msg, @@ -528,6 +544,18 @@ void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, const UNITY_FLOAT_TRAIT_T style); #endif +/*------------------------------------------------------- + * Helpers + *-------------------------------------------------------*/ + +UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size); +#ifndef UNITY_EXCLUDE_FLOAT +UNITY_INTERNAL_PTR UnityFloatToPtr(const float num); +#endif +#ifndef UNITY_EXCLUDE_DOUBLE +UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num); +#endif + /*------------------------------------------------------- * Error Strings We Might Need *-------------------------------------------------------*/ @@ -637,30 +665,48 @@ int UnityTestMatches(void); #define UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, line, message) UnityAssertEqualNumber((UNITY_PTR_TO_INT)(expected), (UNITY_PTR_TO_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER) #define UNITY_TEST_ASSERT_EQUAL_STRING(expected, actual, line, message) UnityAssertEqualString((const char*)(expected), (const char*)(actual), (message), (UNITY_LINE_TYPE)(line)) #define UNITY_TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len, line, message) UnityAssertEqualStringLen((const char*)(expected), (const char*)(actual), (UNITY_UINT32)(len), (message), (UNITY_LINE_TYPE)(line)) -#define UNITY_TEST_ASSERT_EQUAL_MEMORY(expected, actual, len, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), 1, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_MEMORY(expected, actual, len, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), 1, (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) -#define UNITY_TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) -#define UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) -#define UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) -#define UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) -#define UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) -#define UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) -#define UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) -#define UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) -#define UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) -#define UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) -#define UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) -#define UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER) -#define UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((const char**)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line)) -#define UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) + +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) expected, sizeof(int)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )expected, 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )expected, 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )expected, 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) expected, sizeof(unsigned int)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT8 )expected, 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT16)expected, 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT32)expected, 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )expected, 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )expected, 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )expected, 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_PTR_TO_INT) expected, sizeof(int*)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) #ifdef UNITY_SUPPORT_64 #define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) #define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) #define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) -#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) -#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) -#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)expected, 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)expected, 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)expected, 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY) #define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) #define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) #define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) @@ -680,6 +726,7 @@ int UnityTestMatches(void); #define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) #define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) #define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) #define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) #define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) #define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) @@ -691,7 +738,8 @@ int UnityTestMatches(void); #else #define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line)) #define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message)) -#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualFloatArray((UNITY_FLOAT*)(expected), (UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualFloatArray((UNITY_FLOAT*)(expected), (UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UnityAssertEqualFloatArray(UnityFloatToPtr(expected), (UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) #define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) #define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) #define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) @@ -706,6 +754,7 @@ int UnityTestMatches(void); #define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) #define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) #define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) #define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) #define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) #define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) @@ -717,7 +766,8 @@ int UnityTestMatches(void); #else #define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)line) #define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)expected, (UNITY_DOUBLE)actual, (UNITY_LINE_TYPE)(line), message) -#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualDoubleArray((UNITY_DOUBLE*)(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)line) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualDoubleArray((UNITY_DOUBLE*)(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)line, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UnityAssertEqualDoubleArray(UnityDoubleToPtr(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)line, UNITY_ARRAY_TO_VAL) #define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) #define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) #define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) diff --git a/tests/unity/test/.rubocop.yml b/tests/unity/test/.rubocop.yml new file mode 100644 index 0000000..c074ca9 --- /dev/null +++ b/tests/unity/test/.rubocop.yml @@ -0,0 +1,58 @@ +# This is the configuration used to check the rubocop source code. + +#inherit_from: .rubocop_todo.yml + +AllCops: + TargetRubyVersion: 2.1 + +# These are areas where ThrowTheSwitch's coding style diverges from the Ruby standard +Style/SpecialGlobalVars: + EnforcedStyle: use_perl_names +Style/FormatString: + Enabled: false +Style/GlobalVars: + Enabled: false +Style/RegexpLiteral: + AllowInnerSlashes: true +Style/HashSyntax: + EnforcedStyle: no_mixed_keys + +# This is disabled because it seems to get confused over nested hashes +Style/AlignHash: + Enabled: false + EnforcedHashRocketStyle: table + EnforcedColonStyle: table + +# We purposefully use these insecure features because they're what makes Ruby awesome +Security/Eval: + Enabled: false +Security/YAMLLoad: + Enabled: false + +# At this point, we're not ready to enforce inline documentation requirements +Style/Documentation: + Enabled: false +Style/DocumentationMethod: + Enabled: false + +# At this point, we're not ready to enforce any metrics +Metrics/AbcSize: + Enabled: false +Metrics/BlockLength: + Enabled: false +Metrics/BlockNesting: + Enabled: false +Metrics/ClassLength: + Enabled: false +Metrics/CyclomaticComplexity: + Enabled: false +Metrics/LineLength: + Enabled: false +Metrics/MethodLength: + Enabled: false +Metrics/ModuleLength: + Enabled: false +Metrics/ParameterLists: + Enabled: false +Metrics/PerceivedComplexity: + Enabled: false diff --git a/tests/unity/test/rakefile b/tests/unity/test/rakefile index 000ab00..4a2f3d2 100644 --- a/tests/unity/test/rakefile +++ b/tests/unity/test/rakefile @@ -32,7 +32,7 @@ configure_toolchain(DEFAULT_CONFIG_FILE) desc "Test unity with its own unit tests" task :unit => [:prepare_for_tests] do - run_tests get_unit_test_files + run_tests unit_test_files end desc "Test unity's helper scripts" @@ -53,7 +53,7 @@ task :summary do end desc "Build and test Unity" -task :all => [:clean, :prepare_for_tests, :scripts, :unit, :summary] +task :all => [:clean, :prepare_for_tests, :scripts, :unit, :style, :summary] task :default => [:clobber, :all] task :ci => [:no_color, :default] task :cruise => [:no_color, :default] @@ -70,3 +70,56 @@ end task :verbose do $verbose = true end + +namespace :style do + desc "Check style" + task :check do + report "\nVERIFYING RUBY STYLE" + report execute("rubocop ../auto ../examples ../extras --config .rubocop.yml", true) + report "Styling Ruby:PASS" + end + + namespace :check do + Dir['../**/*.rb'].each do |f| + filename = File.basename(f, '.rb') + desc "Check Style of #{filename}" + task filename.to_sym => ['style:clean'] do + report execute("rubocop #{f} --color --config .rubocop.yml", true) + report "Style Checked for #{f}" + end + end + end + + desc "Fix Style of all C Code" + task :c do + run_astyle("../src/*.* ../extras/fixture/src/*.*") + end + + namespace :c do + Dir['../{src,extras/**}/*.{c,h}'].each do |f| + filename = File.basename(f)[0..-3] + desc "Check Style of #{filename}" + task filename.to_sym do + run_astyle f + end + end + end + + desc "Attempt to Autocorrect style" + task :auto => ['style:clean'] do + execute("rubocop ../auto ../examples ../extras --auto-correct --config .rubocop.yml") + report "Autocorrected What We Could." + end + + desc "Update style todo list" + task :todo => ['style:clean'] do + execute("rubocop ../auto ../examples ../extras --auto-gen-config --config .rubocop.yml") + report "Updated Style TODO List." + end + + task :clean do + File.delete(".rubocop_todo.yml") if File.exists?(".rubocop_todo.yml") + end +end + +task :style => ['style:check'] diff --git a/tests/unity/test/rakefile_helper.rb b/tests/unity/test/rakefile_helper.rb index 17bfb27..be5bf3e 100644 --- a/tests/unity/test/rakefile_helper.rb +++ b/tests/unity/test/rakefile_helper.rb @@ -11,39 +11,37 @@ require UNITY_ROOT + '../auto/generate_test_runner' require UNITY_ROOT + '../auto/colour_reporter' module RakefileHelpers - - C_EXTENSION = '.c' - + C_EXTENSION = '.c'.freeze def load_configuration(config_file) - unless ($configured) - $cfg_file = "targets/#{config_file}" unless (config_file =~ /[\\|\/]/) - $cfg = YAML.load(File.read($cfg_file)) - $colour_output = false unless $cfg['colour'] - $configured = true if (config_file != DEFAULT_CONFIG_FILE) - end + return if $configured + + $cfg_file = "targets/#{config_file}" unless config_file =~ /[\\|\/]/ + $cfg = YAML.load(File.read($cfg_file)) + $colour_output = false unless $cfg['colour'] + $configured = true if config_file != DEFAULT_CONFIG_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) + def configure_toolchain(config_file = DEFAULT_CONFIG_FILE) config_file += '.yml' unless config_file =~ /\.yml$/ config_file = config_file unless config_file =~ /[\\|\/]/ load_configuration(config_file) configure_clean end - def get_unit_test_files + def unit_test_files path = $cfg['compiler']['unit_tests_path'] + 'test*' + C_EXTENSION - path.gsub!(/\\/, '/') + path.tr!('\\', '/') FileList.new(path) end - def get_local_include_dirs + def local_include_dirs include_dirs = $cfg['compiler']['includes']['items'].dup - include_dirs.delete_if {|dir| dir.is_a?(Array)} - return include_dirs + include_dirs.delete_if { |dir| dir.is_a?(Array) } + include_dirs end def extract_headers(filename) @@ -51,41 +49,37 @@ 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 - return includes + 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 + return src_file if File.exist?(src_file) end - return nil + nil end def tackit(strings) - if strings.is_a?(Array) - result = "\"#{strings.join}\"" - else - result = strings - end - return result + result = if strings.is_a?(Array) + "\"#{strings.join}\"" + else + strings + end + result end def squash(prefix, items) result = '' items.each { |item| result += " #{prefix}#{tackit(item)}" } - return result + result end def should(behave, &block) if block - puts "Should " + behave + puts 'Should ' + behave yield block else puts "UNIMPLEMENTED CASE: Should #{behave}" @@ -93,91 +87,103 @@ module RakefileHelpers end def build_compiler_fields(inject_defines) - command = tackit($cfg['compiler']['path']) - if $cfg['compiler']['defines']['items'].nil? - defines = '' - else - defines = squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items'] + ['UNITY_OUTPUT_CHAR=putcharSpy'] + inject_defines) - end - options = squash('', $cfg['compiler']['options']) + command = tackit($cfg['compiler']['path']) + defines = if $cfg['compiler']['defines']['items'].nil? + '' + else + squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items'] + ['UNITY_OUTPUT_CHAR=putcharSpy'] + inject_defines) + 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} + + { :command => command, :defines => defines, :options => options, :includes => includes } end - def compile(file, defines=[]) + def compile(file, defines = []) compiler = build_compiler_fields(defines) - defines = - cmd_str = "#{compiler[:command]}#{compiler[:defines]}#{compiler[:options]}#{compiler[:includes]} #{file} " + + 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) - return obj_file + + 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} + 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.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR) + + { :command => command, :options => options, :includes => includes } 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} "}).join + - $cfg['linker']['bin_files']['prefix'] + ' ' + - $cfg['linker']['bin_files']['destination'] + - exe_name + $cfg['linker']['bin_files']['extension'] + (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} + 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 } end - def execute(command_string, ok_to_fail=false) + def run_astyle(style_what) + report "Styling C Code..." + command = "AStyle " \ + "--style=allman --indent=spaces=4 --indent-switches --indent-preproc-define --indent-preproc-block " \ + "--pad-oper --pad-comma --unpad-paren --pad-header " \ + "--align-pointer=type --align-reference=name " \ + "--add-brackets --mode=c --suffix=none " \ + "#{style_what}" + execute(command, false) + report "Styling C:PASS" + end + + def execute(command_string, ok_to_fail = false) report command_string if $verbose output = `#{command_string}`.chomp - report(output) if ($verbose && !output.nil? && (output.length > 0)) - if (($?.exitstatus != 0) && !ok_to_fail) - raise "Command failed. (Returned #{$?.exitstatus})" - end - return output + report(output) if $verbose && !output.nil? && !output.empty? + raise "Command failed. (Returned #{$?.exitstatus})" if !$?.exitstatus.zero? && !ok_to_fail + output end def report_summary summary = UnityTestSummary.new - summary.set_root_path(UNITY_ROOT) + summary.root = UNITY_ROOT results_glob = "#{$cfg['compiler']['build_path']}*.test*" - results_glob.gsub!(/\\/, '/') + results_glob.tr!('\\', '/') results = Dir[results_glob] - summary.set_targets(results) + summary.targets = results report summary.run end @@ -187,16 +193,16 @@ module RakefileHelpers # 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'] ||= [] $cfg['compiler']['defines']['items'] << 'TEST' - include_dirs = get_local_include_dirs + include_dirs = local_include_dirs # Build and execute each unit test test_files.each do |test| obj_list = [] - if !$cfg['compiler']['aux_sources'].nil? + unless $cfg['compiler']['aux_sources'].nil? $cfg['compiler']['aux_sources'].each do |aux| obj_list << compile(aux, test_defines) end @@ -206,25 +212,23 @@ module RakefileHelpers extract_headers(test).each do |header| # Compile corresponding source file if it exists src_file = find_source_file(header, include_dirs) - if !src_file.nil? - obj_list << compile(src_file, test_defines) - end + + obj_list << compile(src_file, test_defines) unless src_file.nil? end # Build the test runner (generate if configured to do so) test_base = File.basename(test, C_EXTENSION) runner_name = test_base + '_Runner.c' - runner_path = '' - if $cfg['compiler']['runner_path'].nil? - runner_path = $cfg['compiler']['build_path'] + runner_name - else - runner_path = $cfg['compiler']['runner_path'] + runner_name - end + runner_path = if $cfg['compiler']['runner_path'].nil? + $cfg['compiler']['build_path'] + runner_name + else + $cfg['compiler']['runner_path'] + runner_name + end options = $cfg[:unity] - options[:use_param_tests] = (test =~ /parameterized/) ? true : false + options[:use_param_tests] = test =~ /parameterized/ ? true : false UnityTestRunnerGenerator.new(options).run(test, runner_path) obj_list << compile(runner_path, test_defines) @@ -237,21 +241,20 @@ module RakefileHelpers # 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 + cmd_str = if simulator.nil? + executable + else + "#{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 - report output if (!$verbose) #verbose already prints this line, as does a failure + report output unless $verbose # Verbose already prints this line, as does a failure test_results += '.testpass' end File.open(test_results, 'w') { |f| f.print output } - end end end diff --git a/tests/unity/test/targets/clang_strict.yml b/tests/unity/test/targets/clang_strict.yml index b399d76..ee05b2a 100644 --- a/tests/unity/test/targets/clang_strict.yml +++ b/tests/unity/test/targets/clang_strict.yml @@ -36,7 +36,7 @@ compiler: - '-Wbad-function-cast' - '-fms-extensions' - '-fno-omit-frame-pointer' - - '-ffloat-store' + #- '-ffloat-store' - '-fno-common' - '-fstrict-aliasing' - '-std=gnu99' @@ -55,8 +55,6 @@ compiler: - UNITY_INCLUDE_DOUBLE - UNITY_SUPPORT_TEST_CASES - UNITY_SUPPORT_64 - - UNITY_OUTPUT_FLUSH - - UNITY_OMIT_OUTPUT_FLUSH_HEADER_DECLARATION object_files: prefix: '-o' extension: '.o' diff --git a/tests/unity/test/testdata/testRunnerGeneratorSmall.c b/tests/unity/test/testdata/testRunnerGeneratorSmall.c index 9f4ec19..c683749 100644 --- a/tests/unity/test/testdata/testRunnerGeneratorSmall.c +++ b/tests/unity/test/testdata/testRunnerGeneratorSmall.c @@ -4,6 +4,8 @@ #include "unity.h" #include "Defs.h" +TEST_FILE("some_file.c") + /* Notes about prefixes: test - normal default prefix. these are "always run" tests for this procedure spec - normal default prefix. required to run default setup/teardown calls. diff --git a/tests/unity/test/tests/test_generate_test_runner.rb b/tests/unity/test/tests/test_generate_test_runner.rb index 55a64c0..a3536d3 100644 --- a/tests/unity/test/tests/test_generate_test_runner.rb +++ b/tests/unity/test/tests/test_generate_test_runner.rb @@ -1170,11 +1170,11 @@ def runner_test(test, runner, expected, test_defines, cmdline_args) simulator = build_simulator_fields cmdline_args ||= "" executable = $cfg['linker']['bin_files']['destination'] + test_base + $cfg['linker']['bin_files']['extension'] + " #{cmdline_args}" - if simulator.nil? - cmd_str = executable - else - cmd_str = "#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}" - end + cmd_str = if simulator.nil? + executable + else + "#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}" + end output = execute(cmd_str, true) #compare to the expected pass/fail diff --git a/tests/unity/test/tests/testunity.c b/tests/unity/test/tests/testunity.c index f062894..3555fb2 100644 --- a/tests/unity/test/tests/testunity.c +++ b/tests/unity/test/tests/testunity.c @@ -1519,6 +1519,61 @@ void testNotEqualStringArrayLengthZero(void) VERIFY_FAILS_END } +void testEqualStringEachEqual(void) +{ + const char *testStrings1[] = { "foo", "foo", "foo", "foo" }; + const char *testStrings2[] = { "boo", "boo", "boo", "zoo" }; + const char *testStrings3[] = { "", "", "", "" }; + + TEST_ASSERT_EACH_EQUAL_STRING("foo", testStrings1, 4); + TEST_ASSERT_EACH_EQUAL_STRING("foo", testStrings1, 1); + TEST_ASSERT_EACH_EQUAL_STRING("boo", testStrings2, 3); + TEST_ASSERT_EACH_EQUAL_STRING("", testStrings3, 4); +} + +void testNotEqualStringEachEqual1(void) +{ + const char *testStrings[] = { "foo", "foo", "foo", "moo" }; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_STRING("foo", testStrings, 4); + VERIFY_FAILS_END +} + +void testNotEqualStringEachEqual2(void) +{ + const char *testStrings[] = { "boo", "foo", "foo", "foo" }; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_STRING("foo", testStrings, 4); + VERIFY_FAILS_END +} + +void testNotEqualStringEachEqual3(void) +{ + const char *testStrings[] = { "foo", "foo", "foo", NULL }; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_STRING("foo", testStrings, 4); + VERIFY_FAILS_END +} + +void testNotEqualStringEachEqual4(void) +{ + const char *testStrings[] = { "foo", "foo", "woo", "foo" }; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_STRING("foo", testStrings, 4); + VERIFY_FAILS_END +} + +void testNotEqualStringEachEqual5(void) +{ + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_STRING("foo", NULL, 1); + VERIFY_FAILS_END +} + void testEqualMemory(void) { const char *testString = "whatever"; @@ -1641,6 +1696,65 @@ void testNotEqualIntArraysLengthZero(void) VERIFY_FAILS_END } +void testEqualIntEachEqual(void) +{ + int p0[] = {1, 1, 1, 1}; + int p1[] = {987, 987, 987, 987}; + int p2[] = {-2, -2, -2, -3}; + int p3[] = {1, 5, 600, 700}; + + TEST_ASSERT_EACH_EQUAL_INT(1, p0, 1); + TEST_ASSERT_EACH_EQUAL_INT(1, p0, 4); + TEST_ASSERT_EACH_EQUAL_INT(987, p1, 4); + TEST_ASSERT_EACH_EQUAL_INT(-2, p2, 3); + TEST_ASSERT_EACH_EQUAL_INT(1, p3, 1); +} + +void testNotEqualIntEachEqualNullActual(void) +{ + int* p1 = NULL; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_INT(1, p1, 4); + VERIFY_FAILS_END +} + +void testNotEqualIntEachEqual1(void) +{ + int p0[] = {1, 1, 1, -2}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_INT(1, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualIntEachEqual2(void) +{ + int p0[] = {-5, -5, -1, -5}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_INT(-5, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualIntEachEqual3(void) +{ + int p0[] = {1, 88, 88, 88}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_INT(88, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualEachEqualLengthZero(void) +{ + UNITY_UINT32 p0[1] = {1}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_INT(0, p0, 0); + VERIFY_FAILS_END +} + void testEqualPtrArrays(void) { char A = 1; @@ -1721,6 +1835,77 @@ void testNotEqualPtrArrays3(void) VERIFY_FAILS_END } +void testEqualPtrEachEqual(void) +{ + char A = 1; + char B = 2; + char C = 3; + char* p0[] = {&A, &A, &A}; + char* p1[] = {&A, &B, &C, &A}; + char* p2[] = {&B, &B}; + char* p3[] = {&C}; + + TEST_ASSERT_EACH_EQUAL_PTR(&A, p0, 1); + TEST_ASSERT_EACH_EQUAL_PTR(&A, p0, 3); + TEST_ASSERT_EACH_EQUAL_PTR(&A, p1, 1); + TEST_ASSERT_EACH_EQUAL_PTR(&B, p2, 2); + TEST_ASSERT_EACH_EQUAL_PTR(&C, p3, 1); +} + +void testNotEqualPtrEachEqualNullExpected(void) +{ + char A = 1; + char B = 1; + char* p0[] = {&A, &B}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_PTR(&A, p0, 2); + VERIFY_FAILS_END +} + +void testNotEqualPtrEachEqualNullActual(void) +{ + char A = 1; + char** p0 = NULL; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_PTR(&A, p0, 2); + VERIFY_FAILS_END +} + +void testNotEqualPtrEachEqual1(void) +{ + char A = 1; + char B = 1; + char* p0[] = {&A, &A, &A, &B}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_PTR(&A, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualPtrEachEqual2(void) +{ + char A = 1; + char B = 1; + char* p0[] = {&B, &B, &A, &B}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_PTR(&B, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualPtrEachEqual3(void) +{ + char A = 1; + char B = 1; + char* p0[] = {&A, &B, &B, &B}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_PTR(&B, p0, 4); + VERIFY_FAILS_END +} + void testEqualInt8Arrays(void) { UNITY_INT8 p0[] = {1, 8, 117, -2}; @@ -1745,6 +1930,29 @@ void testNotEqualInt8Arrays(void) VERIFY_FAILS_END } +void testEqualInt8EachEqual(void) +{ + UNITY_INT8 p0[] = {1, 1, 1, 1}; + UNITY_INT8 p1[] = {117, 117, 117, -2}; + UNITY_INT8 p2[] = {-1, -1, 117, 2}; + UNITY_INT8 p3[] = {1, 50, 60, 70}; + + TEST_ASSERT_EACH_EQUAL_INT8(1, p0, 1); + TEST_ASSERT_EACH_EQUAL_INT8(1, p0, 4); + TEST_ASSERT_EACH_EQUAL_INT8(117, p1, 3); + TEST_ASSERT_EACH_EQUAL_INT8(-1, p2, 2); + TEST_ASSERT_EACH_EQUAL_INT8(1, p3, 1); +} + +void testNotEqualInt8EachEqual(void) +{ + UNITY_INT8 p0[] = {1, 8, 36, -2}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_INT8(1, p0, 2); + VERIFY_FAILS_END +} + void testEqualUIntArrays(void) { unsigned int p0[] = {1, 8, 987, 65132u}; @@ -1789,6 +1997,47 @@ void testNotEqualUIntArrays3(void) VERIFY_FAILS_END } +void testEqualUIntEachEqual(void) +{ + unsigned int p0[] = {1, 1, 1, 1}; + unsigned int p1[] = {65132u, 65132u, 65132u, 65132u}; + unsigned int p2[] = {8, 8, 987, 2}; + unsigned int p3[] = {1, 500, 600, 700}; + + TEST_ASSERT_EACH_EQUAL_UINT(1, p0, 1); + TEST_ASSERT_EACH_EQUAL_UINT(1, p0, 4); + TEST_ASSERT_EACH_EQUAL_UINT(65132u, p1, 4); + TEST_ASSERT_EACH_EQUAL_UINT(8, p2, 2); + TEST_ASSERT_EACH_EQUAL_UINT(1, p3, 1); +} + +void testNotEqualUIntEachEqual1(void) +{ + unsigned int p0[] = {1, 65132u, 65132u, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_UINT(65132u, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualUIntEachEqual2(void) +{ + unsigned int p0[] = {987, 8, 987, 987}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_UINT(987, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualUIntEachEqual3(void) +{ + unsigned int p0[] = {1, 1, 1, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_UINT(1, p0, 4); + VERIFY_FAILS_END +} + void testEqualInt16Arrays(void) { UNITY_INT16 p0[] = {1, 8, 117, 3}; @@ -1813,6 +2062,29 @@ void testNotEqualInt16Arrays(void) VERIFY_FAILS_END } +void testEqualInt16EachEqual(void) +{ + UNITY_INT16 p0[] = {1, 1, 1, 1}; + UNITY_INT16 p1[] = {32111, 32111, 32111, 3}; + UNITY_INT16 p2[] = {-1, -1, -1, 2}; + UNITY_INT16 p3[] = {1, 50, 60, 70}; + + TEST_ASSERT_EACH_EQUAL_INT16(1, p0, 1); + TEST_ASSERT_EACH_EQUAL_INT16(1, p0, 4); + TEST_ASSERT_EACH_EQUAL_INT16(32111, p1, 3); + TEST_ASSERT_EACH_EQUAL_INT16(-1, p2, 3); + TEST_ASSERT_EACH_EQUAL_INT16(1, p3, 1); +} + +void testNotEqualInt16EachEqual(void) +{ + UNITY_INT16 p0[] = {127, 127, 127, 3}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_INT16(127, p0, 4); + VERIFY_FAILS_END +} + void testEqualInt32Arrays(void) { UNITY_INT32 p0[] = {1, 8, 117, 3}; @@ -1837,6 +2109,29 @@ void testNotEqualInt32Arrays(void) VERIFY_FAILS_END } +void testEqualInt32EachEqual(void) +{ + UNITY_INT32 p0[] = {8, 8, 8, 8}; + UNITY_INT32 p1[] = {65537, 65537, 65537, 65537}; + UNITY_INT32 p2[] = {-3, -3, -3, 2}; + UNITY_INT32 p3[] = {1, 50, 60, 70}; + + TEST_ASSERT_EACH_EQUAL_INT32(8, p0, 1); + TEST_ASSERT_EACH_EQUAL_INT32(8, p0, 4); + TEST_ASSERT_EACH_EQUAL_INT32(65537, p1, 4); + TEST_ASSERT_EACH_EQUAL_INT32(-3, p2, 3); + TEST_ASSERT_EACH_EQUAL_INT32(1, p3, 1); +} + +void testNotEqualInt32EachEqual(void) +{ + UNITY_INT32 p0[] = {127, 8, 127, 127}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_INT32(127, p0, 4); + VERIFY_FAILS_END +} + void testEqualUINT8Arrays(void) { UNITY_UINT8 p0[] = {1, 8, 100, 127}; @@ -2104,10 +2399,10 @@ void testNotEqualHEX16Arrays3(void) void testEqualHEX8Arrays(void) { - unsigned short p0[] = {1, 8, 254u, 123}; - unsigned short p1[] = {1, 8, 254u, 123}; - unsigned short p2[] = {1, 8, 254u, 2}; - unsigned short p3[] = {1, 23, 25, 26}; + unsigned char p0[] = {1, 8, 254u, 123}; + unsigned char p1[] = {1, 8, 254u, 123}; + unsigned char p2[] = {1, 8, 254u, 2}; + unsigned char p3[] = {1, 23, 25, 26}; TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p0, 1); TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p0, 4); @@ -2146,6 +2441,293 @@ void testNotEqualHEX8Arrays3(void) VERIFY_FAILS_END } +void testEqualUINT8EachEqual(void) +{ + UNITY_UINT8 p0[] = {127u, 127u, 127u, 127u}; + UNITY_UINT8 p1[] = {1u, 1u, 1u, 1u}; + UNITY_UINT8 p2[] = {128u, 128u, 128u, 2u}; + UNITY_UINT8 p3[] = {1u, 50u, 60u, 70u}; + + TEST_ASSERT_EACH_EQUAL_UINT8(127u, p0, 1); + TEST_ASSERT_EACH_EQUAL_UINT8(127u, p0, 4); + TEST_ASSERT_EACH_EQUAL_UINT8(1u, p1, 4); + TEST_ASSERT_EACH_EQUAL_UINT8(128u, p2, 3); + TEST_ASSERT_EACH_EQUAL_UINT8(1u, p3, 1); +} + +void testNotEqualUINT8EachEqual1(void) +{ + unsigned char p0[] = {127u, 127u, 128u, 127u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_UINT8(127u, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualUINT8EachEqual2(void) +{ + unsigned char p0[] = {1, 1, 1, 127u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_UINT8(1, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualUINT8EachEqual3(void) +{ + unsigned char p0[] = {54u, 55u, 55u, 55u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_UINT8(55u, p0, 4); + VERIFY_FAILS_END +} + +void testEqualUINT16EachEqual(void) +{ + unsigned short p0[] = {65132u, 65132u, 65132u, 65132u}; + unsigned short p1[] = {987, 987, 987, 987}; + unsigned short p2[] = {1, 1, 1, 2}; + unsigned short p3[] = {1, 500, 600, 700}; + + TEST_ASSERT_EACH_EQUAL_UINT16(65132u, p0, 1); + TEST_ASSERT_EACH_EQUAL_UINT16(65132u, p0, 4); + TEST_ASSERT_EACH_EQUAL_UINT16(987, p1, 4); + TEST_ASSERT_EACH_EQUAL_UINT16(1, p2, 3); + TEST_ASSERT_EACH_EQUAL_UINT16(1, p3, 1); +} + +void testNotEqualUINT16EachEqual1(void) +{ + unsigned short p0[] = {1, 65132u, 65132u, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_UINT16(65132u, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualUINT16EachEqual2(void) +{ + unsigned short p0[] = {65132u, 65132u, 987, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_UINT16(65132u, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualUINT16EachEqual3(void) +{ + unsigned short p0[] = {65132u, 65132u, 65132u, 65133u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_UINT16(65132u, p0, 4); + VERIFY_FAILS_END +} + +void testEqualUINT32EachEqual(void) +{ + UNITY_UINT32 p0[] = {65132u, 65132u, 65132u, 65132u}; + UNITY_UINT32 p1[] = {987, 987, 987, 987}; + UNITY_UINT32 p2[] = {8, 8, 8, 2}; + UNITY_UINT32 p3[] = {1, 500, 600, 700}; + + TEST_ASSERT_EACH_EQUAL_UINT32(65132u, p0, 1); + TEST_ASSERT_EACH_EQUAL_UINT32(65132u, p0, 4); + TEST_ASSERT_EACH_EQUAL_UINT32(987, p1, 4); + TEST_ASSERT_EACH_EQUAL_UINT32(8, p2, 3); + TEST_ASSERT_EACH_EQUAL_UINT32(1, p3, 1); +} + +void testNotEqualUINT32EachEqual1(void) +{ + UNITY_UINT32 p0[] = {65132u, 65132u, 987, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_UINT32(65132u, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualUINT32EachEqual2(void) +{ + UNITY_UINT32 p0[] = {1, 987, 987, 987}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_UINT32(987, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualUINT32EachEqual3(void) +{ + UNITY_UINT32 p0[] = {1, 1, 1, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_UINT32(1, p0, 4); + VERIFY_FAILS_END +} + +void testEqualHEXEachEqual(void) +{ + UNITY_UINT32 p0[] = {65132u, 65132u, 65132u, 65132u}; + UNITY_UINT32 p1[] = {987, 987, 987, 987}; + UNITY_UINT32 p2[] = {8, 8, 8, 2}; + UNITY_UINT32 p3[] = {1, 500, 600, 700}; + + TEST_ASSERT_EACH_EQUAL_HEX(65132u, p0, 1); + TEST_ASSERT_EACH_EQUAL_HEX(65132u, p0, 4); + TEST_ASSERT_EACH_EQUAL_HEX(987, p1, 4); + TEST_ASSERT_EACH_EQUAL_HEX(8, p2, 3); + TEST_ASSERT_EACH_EQUAL_HEX(1, p3, 1); +} + +void testNotEqualHEXEachEqual1(void) +{ + UNITY_UINT32 p0[] = {1, 65132u, 65132u, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_HEX32(65132u, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualHEXEachEqual2(void) +{ + UNITY_UINT32 p0[] = {987, 987, 987, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_HEX32(987, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualHEXEachEqual3(void) +{ + UNITY_UINT32 p0[] = {8, 8, 987, 8}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_HEX(8, p0, 4); + VERIFY_FAILS_END +} + +void testEqualHEX32EachEqual(void) +{ + UNITY_UINT32 p0[] = {65132u, 65132u, 65132u, 65132u}; + UNITY_UINT32 p1[] = {987, 987, 987, 987}; + UNITY_UINT32 p2[] = {8, 8, 8, 2}; + UNITY_UINT32 p3[] = {1, 500, 600, 700}; + + TEST_ASSERT_EACH_EQUAL_HEX32(65132u, p0, 1); + TEST_ASSERT_EACH_EQUAL_HEX32(65132u, p0, 4); + TEST_ASSERT_EACH_EQUAL_HEX32(987, p1, 4); + TEST_ASSERT_EACH_EQUAL_HEX32(8, p2, 3); + TEST_ASSERT_EACH_EQUAL_HEX32(1, p3, 1); +} + +void testNotEqualHEX32EachEqual1(void) +{ + UNITY_UINT32 p0[] = {65132u, 8, 65132u, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_HEX32(65132u, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualHEX32EachEqual2(void) +{ + UNITY_UINT32 p0[] = {1, 987, 987, 987}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_HEX32(987, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualHEX32EachEqual3(void) +{ + UNITY_UINT32 p0[] = {8, 8, 8, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_HEX32(8, p0, 4); + VERIFY_FAILS_END +} + +void testEqualHEX16EachEqual(void) +{ + UNITY_UINT16 p0[] = {65132u, 65132u, 65132u, 65132u}; + UNITY_UINT16 p1[] = {987, 987, 987, 987}; + UNITY_UINT16 p2[] = {8, 8, 8, 2}; + UNITY_UINT16 p3[] = {1, 500, 600, 700}; + + TEST_ASSERT_EACH_EQUAL_HEX16(65132u, p0, 1); + TEST_ASSERT_EACH_EQUAL_HEX16(65132u, p0, 4); + TEST_ASSERT_EACH_EQUAL_HEX16(987, p1, 4); + TEST_ASSERT_EACH_EQUAL_HEX16(8, p2, 3); + TEST_ASSERT_EACH_EQUAL_HEX16(1, p3, 1); +} + +void testNotEqualHEX16EachEqual1(void) +{ + unsigned short p0[] = {65132u, 65132u, 987, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_HEX16(65132u, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualHEX16EachEqual2(void) +{ + unsigned short p0[] = {1, 987, 987, 987}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_HEX16(987, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualHEX16EachEqual3(void) +{ + unsigned short p0[] = {8, 8, 8, 65132u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_HEX16(8, p0, 4); + VERIFY_FAILS_END +} + +void testEqualHEX8EachEqual(void) +{ + unsigned char p0[] = {254u, 254u, 254u, 254u}; + unsigned char p1[] = {123, 123, 123, 123}; + unsigned char p2[] = {8, 8, 8, 2}; + unsigned char p3[] = {1, 23, 25, 26}; + + TEST_ASSERT_EACH_EQUAL_HEX8(254u, p0, 1); + TEST_ASSERT_EACH_EQUAL_HEX8(254u, p0, 4); + TEST_ASSERT_EACH_EQUAL_HEX8(123, p1, 4); + TEST_ASSERT_EACH_EQUAL_HEX8(8, p2, 3); + TEST_ASSERT_EACH_EQUAL_HEX8(1, p3, 1); +} + +void testNotEqualHEX8EachEqual1(void) +{ + unsigned char p0[] = {253u, 253u, 254u, 253u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_HEX8(253u, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualHEX8EachEqual2(void) +{ + unsigned char p0[] = {254u, 254u, 254u, 253u}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_HEX8(254u, p0, 4); + VERIFY_FAILS_END +} + +void testNotEqualHEX8EachEqual3(void) +{ + unsigned char p0[] = {1, 8, 8, 8}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_HEX8(8, p0, 4); + VERIFY_FAILS_END +} + void testEqualMemoryArrays(void) { int p0[] = {1, 8, 987, -2}; @@ -2210,6 +2792,71 @@ void testNotEqualMemoryArrays3(void) VERIFY_FAILS_END } +void testEqualMemoryEachEqual(void) +{ + int p0[] = {1, 8, 987, -2}; + int p1[] = {1, 8, 987, -2, 1, 8, 987, -2}; + int p2[] = {8, 8, 8, 2}; + int p3[] = {8, 500, 600, 700}; + int v = 8; + + TEST_ASSERT_EACH_EQUAL_MEMORY(p0, p0, sizeof(int)*4, 1); + TEST_ASSERT_EACH_EQUAL_MEMORY(p0, p1, sizeof(int)*4, 2); + TEST_ASSERT_EACH_EQUAL_MEMORY(p0, p1, sizeof(int)*4, 1); + TEST_ASSERT_EACH_EQUAL_MEMORY(&v, p2, sizeof(int), 3); + TEST_ASSERT_EACH_EQUAL_MEMORY(&v, p3, sizeof(int), 1); +} + +void testNotEqualMemoryEachEqualExpectedNull(void) +{ + int* p0 = NULL; + int p1[] = {1, 8, 987, 2}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_MEMORY(p0, p1, sizeof(int), 4); + VERIFY_FAILS_END +} + +void testNotEqualMemoryEachEqualActualNull(void) +{ + int p0[] = {1, 8, 987, -2}; + int* p1 = NULL; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_MEMORY(p0, p1, sizeof(int), 4); + VERIFY_FAILS_END +} + +void testNotEqualMemoryEachEqual1(void) +{ + int p0[] = {1, 8, 987, -2}; + int p1[] = {9, 8, 987, -2, 1, 8, 987, -2, 1, 8, 987, -2}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_MEMORY(p0, p1, sizeof(int)*4, 3); + VERIFY_FAILS_END +} + +void testNotEqualMemoryEachEqual2(void) +{ + int p0[] = {1, 8, 987, -2}; + int p1[] = {1, 8, 987, -2, 1, 8, 987, -2, 1, 8, 987, 9}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_MEMORY(p0, p1, sizeof(int)*4, 3); + VERIFY_FAILS_END +} + +void testNotEqualMemoryEachEqual3(void) +{ + int p0[] = {1, 8, 987, -2}; + int p1[] = {1, 8, 987, -2, 1, 9, 987, -2, 1, 8, 987, -2}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_MEMORY(p0, p1, sizeof(int)*4, 3); + VERIFY_FAILS_END +} + void testProtection(void) { volatile int mask = 0; @@ -3255,6 +3902,150 @@ void testNotEqualFloatArraysLengthZero(void) #endif } +void testEqualFloatEachEqual(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {1.0f, 1.0f, 1.0f, 1.0f}; + float p1[] = {-0.123f, -0.123f, -0.123f, -0.123f}; + float p2[] = {25.4f, 25.4f, 25.4f, -0.2f}; + float p3[] = {1.0f, -23.0f, 25.0f, -0.26f}; + + TEST_ASSERT_EACH_EQUAL_FLOAT(1.0f, p0, 1); + TEST_ASSERT_EACH_EQUAL_FLOAT(1.0f, p0, 4); + TEST_ASSERT_EACH_EQUAL_FLOAT(-0.123f, p1, 4); + TEST_ASSERT_EACH_EQUAL_FLOAT(25.4f, p2, 3); + TEST_ASSERT_EACH_EQUAL_FLOAT(1.0f, p3, 1); +#endif +} + +void testNotEqualFloatEachEqualActualNull(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float* p0 = NULL; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_FLOAT(5, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualFloatEachEqual1(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {0.253f, 8.0f, 0.253f, 0.253f}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_FLOAT(0.253f, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualFloatEachEqual2(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {8.0f, 8.0f, 8.0f, 0.253f}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_FLOAT(8.0f, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualFloatEachEqual3(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {1.0f, 1.0f, 1.0f, 0.253f}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_FLOAT(1.0f, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualFloatEachEqualNegative1(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {-1.0f, -0.253f, -0.253f, -0.253f}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_FLOAT(-0.253f, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualFloatEachEqualNegative2(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {-25.4f, -8.0f, -25.4f, -25.4f}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_FLOAT(-25.4f, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualFloatEachEqualNegative3(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {-8.0f, -8.0f, -8.0f, -0.253f}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_FLOAT(-8.0f, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testEqualFloatEachEqualNaN(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {0.0f / f_zero, 0.0f / f_zero, 0.0f / f_zero, 0.0f / f_zero}; + + TEST_ASSERT_EACH_EQUAL_FLOAT(0.0f / f_zero, p0, 4); +#endif +} + +void testEqualFloatEachEqualInf(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[] = {1.0f / f_zero, 1.0f / f_zero, 25.4f, 0.253f}; + + TEST_ASSERT_EACH_EQUAL_FLOAT(1.0f / f_zero, p0, 2); +#endif +} + +void testNotEqualFloatEachEqualLengthZero(void) +{ +#ifdef UNITY_EXCLUDE_FLOAT + TEST_IGNORE(); +#else + float p0[1] = {0.0f}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_FLOAT(0.0f, p0, 0); + VERIFY_FAILS_END +#endif +} + #define TEST_ASSERT_EQUAL_PRINT_FLOATING(expected, actual) { \ startPutcharSpy(); UnityPrintFloat((actual)); endPutcharSpy(); \ TEST_ASSERT_EQUAL_STRING((expected), getBufferPutcharSpy()); \ @@ -3953,6 +4744,150 @@ void testNotEqualDoubleArraysLengthZero(void) #endif } +void testEqualDoubleEachEqual(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {1.0, 1.0, 1.0, 1.0}; + double p1[] = {-0.123, -0.123, -0.123, -0.123}; + double p2[] = {25.4, 25.4, 25.4, -0.2}; + double p3[] = {1.0, -23.0, 25.0, -0.26}; + + TEST_ASSERT_EACH_EQUAL_DOUBLE(1.0, p0, 1); + TEST_ASSERT_EACH_EQUAL_DOUBLE(1.0, p0, 4); + TEST_ASSERT_EACH_EQUAL_DOUBLE(-0.123, p1, 4); + TEST_ASSERT_EACH_EQUAL_DOUBLE(25.4, p2, 3); + TEST_ASSERT_EACH_EQUAL_DOUBLE(1.0, p3, 1); +#endif +} + +void testNotEqualDoubleEachEqualActualNull(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double* p0 = NULL; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_DOUBLE(5, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualDoubleEachEqual1(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {0.253, 8.0, 0.253, 0.253}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_DOUBLE(0.253, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualDoubleEachEqual2(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {8.0, 8.0, 8.0, 0.253}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_DOUBLE(8.0, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualDoubleEachEqual3(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {1.0, 1.0, 1.0, 0.253}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_DOUBLE(1.0, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualDoubleEachEqualNegative1(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {-1.0, -0.253, -0.253, -0.253}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_DOUBLE(-0.253, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualDoubleEachEqualNegative2(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {-25.4, -8.0, -25.4, -25.4}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_DOUBLE(-25.4, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testNotEqualDoubleEachEqualNegative3(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {-8.0, -8.0, -8.0, -0.253}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_DOUBLE(-8.0, p0, 4); + VERIFY_FAILS_END +#endif +} + +void testEqualDoubleEachEqualNaN(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {0.0 / d_zero, 0.0 / d_zero, 0.0 / d_zero, 0.0 / d_zero}; + + TEST_ASSERT_EACH_EQUAL_DOUBLE(0.0 / d_zero, p0, 4); +#endif +} + +void testEqualDoubleEachEqualInf(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[] = {1.0 / d_zero, 1.0 / d_zero, 25.4, 0.253}; + + TEST_ASSERT_EACH_EQUAL_DOUBLE(1.0 / d_zero, p0, 2); +#endif +} + +void testNotEqualDoubleEachEqualLengthZero(void) +{ +#ifdef UNITY_EXCLUDE_DOUBLE + TEST_IGNORE(); +#else + double p0[1] = {0.0}; + + EXPECT_ABORT_BEGIN + TEST_ASSERT_EACH_EQUAL_DOUBLE(0.0, p0, 0); + VERIFY_FAILS_END +#endif +} + void testDoublePrinting(void) { #if defined(UNITY_EXCLUDE_FLOAT_PRINT) || defined(UNITY_EXCLUDE_DOUBLE) || !defined(USING_OUTPUT_SPY)