提交 39fbd13c 编写于 作者: J John Lindgren

Merge branch 'master' into float-printing

......@@ -14,7 +14,7 @@ before_install:
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install --assume-yes --quiet gcc-multilib; fi
install:
- gem install rspec
- gem install rubocop
- gem install rubocop -v 0.57.2
script:
- cd test && rake ci
- make -s
......
......@@ -9,7 +9,7 @@ Running Tests
RUN_TEST(func, linenum)
Each Test is run within the macro `RUN_TEST`. This macro performs necessary setup before the test is called and handles cleanup and result tabulation afterwards.
Each Test is run within the macro `RUN_TEST`. This macro performs necessary setup before the test is called and handles cleanup and result tabulation afterwards.
Ignoring Tests
--------------
......@@ -75,7 +75,7 @@ Another way of calling `TEST_ASSERT_FALSE`
TEST_FAIL()
TEST_FAIL_MESSAGE(message)
This test is automatically marked as a failure. The message is output stating why.
This test is automatically marked as a failure. The message is output stating why.
Numerical Assertions: Integers
------------------------------
......@@ -87,7 +87,7 @@ Numerical Assertions: Integers
TEST_ASSERT_EQUAL_INT64(expected, actual)
Compare two integers for equality and display errors as signed integers. A cast will be performed
to your natural integer size so often this can just be used. When you need to specify the exact size,
to your natural integer size so often this can just be used. When you need to specify the exact size,
like when comparing arrays, you can use a specific version:
TEST_ASSERT_EQUAL_UINT(expected, actual)
......@@ -96,7 +96,7 @@ like when comparing arrays, you can use a specific version:
TEST_ASSERT_EQUAL_UINT32(expected, actual)
TEST_ASSERT_EQUAL_UINT64(expected, actual)
Compare two integers for equality and display errors as unsigned integers. Like INT, there are
Compare two integers for equality and display errors as unsigned integers. Like INT, there are
variants for different sizes also.
TEST_ASSERT_EQUAL_HEX(expected, actual)
......@@ -105,7 +105,7 @@ variants for different sizes also.
TEST_ASSERT_EQUAL_HEX32(expected, actual)
TEST_ASSERT_EQUAL_HEX64(expected, actual)
Compares two integers for equality and display errors as hexadecimal. Like the other integer comparisons,
Compares two integers for equality and display errors as hexadecimal. Like the other integer comparisons,
you can specify the size... here the size will also effect how many nibbles are shown (for example, `HEX16`
will show 4 nibbles).
......@@ -115,7 +115,7 @@ Another way of calling TEST_ASSERT_EQUAL_INT
TEST_ASSERT_INT_WITHIN(delta, expected, actual)
Asserts that the actual value is within plus or minus delta of the expected value. This also comes in
Asserts that the actual value is within plus or minus delta of the expected value. This also comes in
size specific variants.
......@@ -199,12 +199,12 @@ Compare two null-terminate strings. Fail if any character is different or if th
TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message)
Compare two strings. Fail if any character is different, stop comparing after len characters. Output a custom message on failure.
Compare two strings. Fail if any character is different, stop comparing after len characters. Output a custom message on failure.
Pointer Assertions
------------------
Most pointer operations can be performed by simply using the integer comparisons above. However, a couple of special cases are added for clarity.
Most pointer operations can be performed by simply using the integer comparisons above. However, a couple of special cases are added for clarity.
TEST_ASSERT_NULL(pointer)
......
......@@ -24,7 +24,7 @@ class ColourCommandLine
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')
Win32API.new('kernel32', 'SetConsoleTextAttribute', %w[L N], 'I')
@hout = get_std_handle.call(-11)
end
......@@ -107,7 +107,7 @@ class ColourCommandLine
$stdout.print("#{change_to(colour)}#{str}\033[0m") if mode == :print
end
end
end # ColourCommandLine
end
def colour_puts(role, str)
ColourCommandLine.new.out_c(:puts, role, str)
......
......@@ -4,7 +4,7 @@
# [Released under MIT License. Please refer to license.txt for details]
# ==========================================
require "#{File.expand_path(File.dirname(__FILE__))}/colour_prompt"
require_relative 'colour_prompt'
$colour_output = true
......
......@@ -45,8 +45,6 @@ TEMPLATE_INC ||= '#ifndef _%3$s_H
class UnityModuleGenerator
############################
def initialize(options = nil)
here = File.expand_path(File.dirname(__FILE__)) + '/'
@options = UnityModuleGenerator.default_options
case options
when NilClass then @options
......@@ -56,9 +54,9 @@ class UnityModuleGenerator
end
# Create default file paths if none were provided
@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] = "#{__dir__}/../src/" if @options[:path_src].nil?
@options[:path_inc] = @options[:path_src] if @options[:path_inc].nil?
@options[:path_tst] = "#{__dir__}/../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
......
......@@ -4,8 +4,6 @@
# [Released under MIT License. Please refer to license.txt for details]
# ==========================================
File.expand_path(File.join(File.dirname(__FILE__), 'colour_prompt'))
class UnityTestRunnerGenerator
def initialize(options = nil)
@options = UnityTestRunnerGenerator.default_options
......@@ -15,7 +13,7 @@ class UnityTestRunnerGenerator
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"
require_relative 'type_sanitizer'
end
def self.default_options
......@@ -26,6 +24,7 @@ class UnityTestRunnerGenerator
framework: :unity,
test_prefix: 'test|spec|should',
mock_prefix: 'Mock',
mock_suffix: '',
setup_name: 'setUp',
teardown_name: 'tearDown',
main_name: 'main', # set to :auto to automatically generate each time
......@@ -148,7 +147,7 @@ class UnityTestRunnerGenerator
mock_headers = []
includes.each do |include_path|
include_file = File.basename(include_path)
mock_headers << include_path if include_file =~ /^#{@options[:mock_prefix]}/i
mock_headers << include_path if include_file =~ /^#{@options[:mock_prefix]}.*#{@options[:mock_suffix]}$/i
end
mock_headers
end
......@@ -162,7 +161,9 @@ class UnityTestRunnerGenerator
output.puts('#endif')
output.puts("#include \"#{@options[:framework]}.h\"")
output.puts('#include "cmock.h"') unless mocks.empty?
output.puts('#ifndef UNITY_EXCLUDE_SETJMP_H')
output.puts('#include <setjmp.h>')
output.puts('#endif')
output.puts('#include <stdio.h>')
if @options[:defines] && !@options[:defines].empty?
@options[:defines].each { |d| output.puts("#define #{d}") }
......@@ -194,9 +195,11 @@ class UnityTestRunnerGenerator
output.puts("\n/*=======External Functions This Runner Calls=====*/")
output.puts("extern void #{@options[:setup_name]}(void);")
output.puts("extern void #{@options[:teardown_name]}(void);")
output.puts("\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif") if @options[:externc]
tests.each do |test|
output.puts("extern void #{test[:test]}(#{test[:call] || 'void'});")
end
output.puts("#ifdef __cplusplus\n}\n#endif") if @options[:externc]
output.puts('')
end
......@@ -374,7 +377,7 @@ class UnityTestRunnerGenerator
end
output.puts
output.puts(' CMock_Guts_MemFreeFinal();') unless used_mocks.empty?
output.puts(" return suite_teardown(UnityEnd());")
output.puts(' return suite_teardown(UnityEnd());')
output.puts('}')
end
......@@ -436,6 +439,7 @@ if $0 == __FILE__
' *.h - header files are added as #includes in runner',
' options:',
' -cexception - include cexception support',
' -externc - add extern "C" for cpp 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',
......
#============================================================
# Author: John Theofanopoulos
# A simple parser. Takes the output files generated during the build process and
# extracts information relating to the tests.
# 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
# devenv [build instructions] > Output.txt & type Output.txt
#
# To capture an output file under GCC/Linux builds use the following:
# To capture an output file under Linux builds use the following:
# make | tee Output.txt
#
# This script can handle the following output formats:
# - normal output (raw unity)
# - fixture output (unity_fixture.h/.c)
# - fixture output with verbose flag set ("-v")
#
# 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
# options: -xml : produce a JUnit compatible XML file
# file: file to scan for results
#============================================================
# Parser class for handling the input file
class ParseOutput
def initialize
@test_flag = false
# internal data
@class_name_idx = 0
@path_delim = nil
# xml output related
@xml_out = false
@array_list = false
@total_tests = false
@class_index = false
# current suite name and statistics
@test_suite = nil
@total_tests = 0
@test_passed = 0
@test_failed = 0
@test_ignored = 0
end
# Set the flag to indicate if there will be an XML output file or not
# 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
# If write our output to XML
def write_xml_output
output = File.open('report.xml', 'w')
output << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
@array_list.each do |item|
output << item << "\n"
end
output << "</testsuite>\n"
end
# This function will try and determine when the suite is changed. This is
# Pushes the suite info as xml to the array list, which will be written later
def push_xml_output_suite_info
# Insert opening tag at front
heading = '<testsuite name="Unity" tests="' + @total_tests.to_s + '" failures="' + @test_failed.to_s + '"' + ' skips="' + @test_ignored.to_s + '">'
@array_list.insert(0, heading)
# Push back the closing tag
@array_list.push '</testsuite>'
end
# Pushes xml output data to the array list, which will be written later
def push_xml_output_passed(test_name)
@array_list.push ' <testcase classname="' + @test_suite + '" name="' + test_name + '"/>'
end
# Pushes xml output data to the array list, which will be written later
def push_xml_output_failed(test_name, reason)
@array_list.push ' <testcase classname="' + @test_suite + '" name="' + test_name + '">'
@array_list.push ' <failure type="ASSERT FAILED">' + reason + '</failure>'
@array_list.push ' </testcase>'
end
# Pushes xml output data to the array list, which will be written later
def push_xml_output_ignored(test_name, reason)
@array_list.push ' <testcase classname="' + @test_suite + '" name="' + test_name + '">'
@array_list.push ' <skipped type="TEST IGNORED">' + reason + '</skipped>'
@array_list.push ' </testcase>'
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]
test_name = test_suite_name.split(@path_delim)
# Remove the extension and extract the base_name
base_name = test_name[test_name.size - 1].split('.')[0]
# Return if the test suite hasn't changed
return unless base_name.to_s != @test_suite.to_s
@test_suite = base_name
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])
# Prepares the line for verbose fixture output ("-v")
def prepare_fixture_line(line)
line = line.sub('IGNORE_TEST(', '')
line = line.sub('TEST(', '')
line = line.sub(')', ',')
line = line.chomp
array = line.split(',')
array.map { |x| x.to_s.lstrip.chomp }
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)
class_name = array[0]
test_name = array[1]
test_suite_verify(class_name)
printf "%-40s PASS\n", test_name
return unless @xml_out
push_xml_output_passed(test_name) if @xml_out
end
# Test was flagged as having failed so format the output.
# This is using the Unity fixture output and not the original Unity output.
def test_failed_unity_fixture(array)
class_name = array[0]
test_name = array[1]
test_suite_verify(class_name)
reason_array = array[2].split(':')
reason = reason_array[-1].lstrip.chomp + ' at line: ' + reason_array[-4]
printf "%-40s FAILED\n", test_name
@array_list.push ' <testcase classname="' + @test_suite + '" name="' + test_name + '"/>'
push_xml_output_failed(test_name, reason) if @xml_out
end
# Test was flagged as having passed so format the output.
# Test was flagged as being ignored 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(')', '')
def test_ignored_unity_fixture(array)
class_name = array[0]
test_name = array[1]
reason = 'No reason given'
if array.size > 2
reason_array = array[2].split(':')
tmp_reason = reason_array[-1].lstrip.chomp
reason = tmp_reason == 'IGNORE' ? 'No reason given' : tmp_reason
end
test_suite_verify(class_name)
printf "%-40s IGNORED\n", test_name
push_xml_output_ignored(test_name, reason) if @xml_out
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_idx])
printf "%-40s PASS\n", test_name
return unless @xml_out
@array_list.push ' <testcase classname="' + test_suite + '" name="' + test_name + '"/>'
push_xml_output_passed(test_name) if @xml_out
end
# Test was flagged as being ingored so format the output
def test_ignored(array)
# 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
test_suite_verify(array[@class_name])
printf "%-40s IGNORED\n", test_name
reason = array[last_item].chomp.lstrip + ' at line: ' + array[last_item - 3]
class_name = array[@class_name_idx]
if test_name.start_with? 'TEST('
array2 = test_name.split(' ')
@test_suite = array2[0].sub('TEST(', '')
@test_suite = @test_suite.sub(',', '')
test_suite = array2[0].sub('TEST(', '')
test_suite = test_suite.sub(',', '')
class_name = test_suite
test_name = array2[1].sub(')', '')
end
return unless @xml_out
test_suite_verify(class_name)
printf "%-40s FAILED\n", test_name
@array_list.push ' <testcase classname="' + @test_suite + '" name="' + test_name + '">'
@array_list.push ' <skipped type="TEST IGNORED"> ' + reason + ' </skipped>'
@array_list.push ' </testcase>'
push_xml_output_failed(test_name, reason) if @xml_out
end
# Test was flagged as having failed so format the line
def test_failed(array)
# Test was flagged as being ignored so format the output
def test_ignored(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
reason = array[last_item].chomp.lstrip
class_name = array[@class_name_idx]
if test_name.start_with? 'TEST('
array2 = test_name.split(' ')
@test_suite = array2[0].sub('TEST(', '')
@test_suite = @test_suite.sub(',', '')
test_suite = array2[0].sub('TEST(', '')
test_suite = test_suite.sub(',', '')
class_name = test_suite
test_name = array2[1].sub(')', '')
end
return unless @xml_out
test_suite_verify(class_name)
printf "%-40s IGNORED\n", test_name
@array_list.push ' <testcase classname="' + @test_suite + '" name="' + test_name + '">'
@array_list.push ' <failure type="ASSERT FAILED"> ' + reason + ' </failure>'
@array_list.push ' </testcase>'
push_xml_output_ignored(test_name, reason) if @xml_out
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
# Adjusts the os specific members according to the current path style
# (Windows or Unix based)
def detect_os_specifics(line)
if line.include? '\\'
# Windows X:\Y\Z
@class_name_idx = 1
@path_delim = '\\'
else
# Unix Based /X/Y/Z
@class_name_idx = 0
@path_delim = '/'
end
end
# Main function used to parse the file that was captured.
def process(name)
@test_flag = false
def process(file_name)
@array_list = []
detect_os
puts 'Parsing file: ' + name
puts 'Parsing file: ' + file_name
test_pass = 0
test_fail = 0
test_ignore = 0
@test_passed = 0
@test_failed = 0
@test_ignored = 0
puts ''
puts '=================== RESULTS ====================='
puts ''
File.open(name).each do |line|
# Typical test lines look like this:
File.open(file_name).each do |line|
# Typical test lines look like these:
# ----------------------------------------------------
# 1. normal output:
# <path>/<test_file>.c:36:test_tc1000_opsys:FAIL: Expected 1 Was 0
# <path>/<test_file>.c:112:test_tc5004_initCanChannel:IGNORE: Not Yet Implemented
# <path>/<test_file>.c:115:test_tc5100_initCanVoidPtrs:PASS
#
# where path is different on Unix vs Windows devices (Windows leads with a drive letter)
# 2. fixture output
# <path>/<test_file>.c:63:TEST(<test_group>, <test_function>):FAIL: Expected 0x00001234 Was 0x00005A5A
# <path>/<test_file>.c:36:TEST(<test_group>, <test_function>):IGNORE
# Note: "PASS" information won't be generated in this mode
#
# 3. fixture output with verbose information ("-v")
# TEST(<test_group, <test_file>)<path>/<test_file>:168::FAIL: Expected 0x8D Was 0x8C
# TEST(<test_group>, <test_file>)<path>/<test_file>:22::IGNORE: This Test Was Ignored On Purpose
# IGNORE_TEST(<test_group, <test_file>)
# TEST(<test_group, <test_file>) PASS
#
# Note: Where path is different on Unix vs Windows devices (Windows leads with a drive letter)!
detect_os_specifics(line)
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
# were found. Case is important.
next unless (line_array.size >= 4) || (line.start_with? 'TEST(') || (line.start_with? 'IGNORE_TEST(')
# check if the output is fixture output (with verbose flag "-v")
if (line.start_with? 'TEST(') || (line.start_with? 'IGNORE_TEST(')
line_array = prepare_fixture_line(line)
if line.include? ' PASS'
test_passed_unity_fixture(line_array)
@test_passed += 1
elsif line.include? 'FAIL'
test_failed_unity_fixture(line_array)
@test_failed += 1
elsif line.include? 'IGNORE'
test_ignored_unity_fixture(line_array)
@test_ignored += 1
end
else
@test_flag = false
# normal output / fixture output (without verbose "-v")
elsif line.include? ':PASS'
test_passed(line_array)
@test_passed += 1
elsif line.include? ':FAIL'
test_failed(line_array)
@test_failed += 1
elsif line.include? ':IGNORE:'
test_ignored(line_array)
@test_ignored += 1
elsif line.include? ':IGNORE'
line_array.push('No reason given')
test_ignored(line_array)
@test_ignored += 1
end
@total_tests = @test_passed + @test_failed + @test_ignored
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
puts 'Tests Passed : ' + @test_passed.to_s
puts 'Tests Failed : ' + @test_failed.to_s
puts 'Tests Ignored : ' + @test_ignored.to_s
return unless @xml_out
heading = '<testsuite tests="' + @total_tests.to_s + '" failures="' + test_fail.to_s + '"' + ' skips="' + test_ignore.to_s + '">'
@array_list.insert(0, heading)
# push information about the suite
push_xml_output_suite_info
# write xml output file
write_xml_output
end
end
......@@ -209,11 +311,11 @@ end
parse_my_file = ParseOutput.new
if ARGV.size >= 1
ARGV.each do |a|
if a == '-xml'
ARGV.each do |arg|
if arg == '-xml'
parse_my_file.set_xml_output
else
parse_my_file.process(a)
parse_my_file.process(arg)
break
end
end
......
......@@ -61,8 +61,8 @@ class ArgvParser
opts.parse!(args)
options
end # parse()
end # class OptparseExample
end
end
class UnityToJUnit
include FileUtils::Verbose
......@@ -155,10 +155,6 @@ class UnityToJUnit
[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
private
def results_structure
......@@ -221,9 +217,9 @@ class UnityToJUnit
def write_suites_footer(stream)
stream.puts '</testsuites>'
end
end # UnityToJUnit
end
if __FILE__ == $0
if $0 == __FILE__
# parse out the command options
options = ArgvParser.parse(ARGV)
......
......@@ -11,8 +11,8 @@ module RakefileHelpers
def initialize(all_files = false)
@all_files = all_files
return false unless @all_files
return false unless File.exist?('test_file_filter.yml')
return unless @all_files
return unless File.exist?('test_file_filter.yml')
filters = YAML.load_file('test_file_filter.yml')
@all_files = filters[:all_files]
......
......@@ -101,10 +101,6 @@ class UnityTestSummary
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
end
if $0 == __FILE__
......
# ThrowTheSwitch.org Coding Standard
# 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
......@@ -11,7 +11,7 @@ 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
Being consistent makes code easier to understand. We've tried 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.
......@@ -51,11 +51,11 @@ much as they can, but give the user the power to override it when it's wrong.
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
find the best name for something, we actually put 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):
When naming things, we follow this hierarchy, the first being the
most important to us (but we do all four when possible):
1. Readable
2. Descriptive
3. Consistent
......@@ -74,7 +74,7 @@ abbreviations (sticking to ones we feel are common).
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
longer than the average. Guilty. We're okay with a 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
......@@ -82,8 +82,7 @@ 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.
feel that (for the average developer) it takes away from readability and 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
......@@ -128,7 +127,7 @@ 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
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.
......@@ -200,7 +199,7 @@ that happens, we like to indent further to line things up in nice tidy columns.
## Documentation
Egad. Really? We use markdown and we like pdf files because they can be made to
Egad. Really? We use mark down and we like pdf files because they can be made to
look nice while still being portable. Good enough?
......
......@@ -80,7 +80,7 @@ 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
Many of Unity's assertions are clear 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.
......@@ -104,6 +104,15 @@ becomes messageified like thus...
TEST_ASSERT_X_MESSAGE( {modifiers}, {expected}, actual, {size/count}, message )
Notes:
- The `_MESSAGE` variants intentionally do not support `printf` style formatting
since many embedded projects don't support or avoid `printf` for various reasons.
It is possible to use `sprintf` before the assertion to assemble a complex fail
message, if necessary.
- If you want to output a counter value within an assertion fail message (e.g. from
a loop) , building up an array of results and then using one of the `_ARRAY`
assertions (see below) might be a handy alternative to `sprintf`.
#### TEST_ASSERT_X_ARRAY Variants
......@@ -694,7 +703,7 @@ 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
0 x 20 or 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!
......
# Unity Configuration Guide
# Unity Configuration Guide
## C Standards, Compilers and Microcontrollers
......@@ -19,7 +19,7 @@ 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
great deal of complexity can be centralized primarily to one place to
provide a more consistent and simple experience elsewhere.
......@@ -58,7 +58,7 @@ 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
This file includes defines like `UINT_MAX` that Unity can use 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.
......@@ -215,6 +215,18 @@ Guide.
_Example:_
#define UNITY_FLOAT_PRECISION 0.001f
### Miscellaneous
##### `UNITY_EXCLUDE_STDDEF_H`
Unity uses the `NULL` macro, which defines the value of a null pointer constant,
defined in `stddef.h` by default. If you want to provide
your own macro for this, you should exclude the `stddef.h` header file by adding this
define to your configuration.
_Example:_
#define UNITY_EXCLUDE_STDDEF_H
### Toolset Customization
......@@ -222,7 +234,7 @@ 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
through extra hoops to run properly. These macros will help in those
situations.
......@@ -248,7 +260,8 @@ _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:
#include "RS232_header.h"
...
#define UNITY_OUTPUT_CHAR(a) RS232_putc(a)
#define UNITY_OUTPUT_START() RS232_config(115200,1,8,0)
#define UNITY_OUTPUT_FLUSH() RS232_flush()
......@@ -256,10 +269,7 @@ Say you are forced to run your test suite on an embedded processor with no
_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`.
specifying `UNITY_USE_FLUSH_STDOUT`. No other defines are required.
##### `UNITY_WEAK_ATTRIBUTE`
......
......@@ -11,7 +11,7 @@ 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
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
......@@ -100,10 +100,11 @@ 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
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.
developers. Also, the automated scripts that come with Unity or Ceedling will default
to looking for test functions to be prefixed this way. 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
......@@ -148,7 +149,7 @@ int main(void) {
}
```
It's possible that you will require more customization than this, eventually.
It's possible that you will need 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.
......
......@@ -3,7 +3,7 @@
## 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
The Unity project includes a couple of 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/).
......@@ -105,7 +105,7 @@ 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:
to generate each runner afterwards. Like thus:
```Ruby
gen = UnityTestRunnerGenerator.new(options)
......@@ -160,6 +160,18 @@ 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.
##### `:externc`
This option should be defined if you are mixing C and CPP and want your test
runners to automatically include extern "C" support when they are generated.
##### `:mock_prefix` and `:mock_suffix`
Unity automatically generates calls to Init, Verify and Destroy for every file
included in the main test file that starts with the given mock prefix and ends
with the given mock suffix, file extension not included. By default, Unity
assumes a `Mock` prefix and no suffix.
##### `:plugins`
This option specifies an array of plugins to be used (of course, the array can
......
......@@ -4,14 +4,14 @@
int Counter = 0;
int NumbersToFind[9] = { 0, 34, 55, 66, 32, 11, 1, 77, 888 }; /* some obnoxious array to search that is 1-based indexing instead of 0. */
/* This function is supposed to search through NumbersToFind and find a particular number.
* If it finds it, the index is returned. Otherwise 0 is returned which sorta makes sense since
* NumbersToFind is indexed from 1. Unfortunately it's broken
/* This function is supposed to search through NumbersToFind and find a particular number.
* If it finds it, the index is returned. Otherwise 0 is returned which sorta makes sense since
* NumbersToFind is indexed from 1. Unfortunately it's broken
* (and should therefore be caught by our tests) */
int FindFunction_WhichIsBroken(int NumberToFind)
{
int i = 0;
while (i <= 8) /* Notice I should have been in braces */
while (i < 8) /* Notice I should have been in braces */
i++;
if (NumbersToFind[i] == NumberToFind) /* Yikes! I'm getting run after the loop finishes instead of during it! */
return i;
......
HERE = File.expand_path(File.dirname(__FILE__)) + '/'
UNITY_ROOT = File.expand_path(File.dirname(__FILE__)) + '/../..'
require 'rake'
require 'rake/clean'
require HERE + 'rakefile_helper'
require_relative 'rakefile_helper'
TEMP_DIRS = [
File.join(HERE, 'build')
File.join(__dir__, 'build')
].freeze
TEMP_DIRS.each do |dir|
......@@ -32,8 +29,8 @@ task :summary do
end
desc 'Build and test Unity'
task all: %i(clean unit summary)
task default: %i(clobber all)
task all: %i[clean unit summary]
task default: %i[clobber all]
task ci: [:default]
task cruise: [:default]
......
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_relative '../../auto/unity_test_summary'
require_relative '../../auto/generate_test_runner'
require_relative '../../auto/colour_reporter'
module RakefileHelpers
C_EXTENSION = '.c'.freeze
......@@ -149,7 +149,7 @@ module RakefileHelpers
def report_summary
summary = UnityTestSummary.new
summary.root = HERE
summary.root = __dir__
results_glob = "#{$cfg['compiler']['build_path']}*.test*"
results_glob.tr!('\\', '/')
results = Dir[results_glob]
......
......@@ -236,4 +236,12 @@
/* #define UNITY_PTR_ATTRIBUTE __attribute__((far)) */
/* #define UNITY_PTR_ATTRIBUTE near */
/* Print execution time of each test when executed in verbose mode
*
* Example:
*
* TEST - PASS (10 ms)
*/
/* #define UNITY_INCLUDE_EXEC_TIME */
#endif /* UNITY_CONFIG_H */
......@@ -4,15 +4,13 @@
# [Released under MIT License. Please refer to license.txt for details]
# ==========================================
HERE = File.expand_path(File.dirname(__FILE__)) + '/'
require 'rake'
require 'rake/clean'
require 'rake/testtask'
require HERE + 'rakefile_helper'
require_relative 'rakefile_helper'
TEMP_DIRS = [
File.join(HERE, 'build')
File.join(__dir__, 'build')
].freeze
TEMP_DIRS.each do |dir|
......@@ -33,10 +31,10 @@ task unit: [:prepare_for_tests] do
end
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)
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|
......
......@@ -6,9 +6,9 @@
require 'yaml'
require 'fileutils'
require HERE + '../../auto/unity_test_summary'
require HERE + '../../auto/generate_test_runner'
require HERE + '../../auto/colour_reporter'
require_relative '../../auto/unity_test_summary'
require_relative '../../auto/generate_test_runner'
require_relative '../../auto/colour_reporter'
module RakefileHelpers
C_EXTENSION = '.c'.freeze
......@@ -16,7 +16,7 @@ module RakefileHelpers
def load_configuration(config_file)
return if $configured
$cfg_file = HERE + "../../test/targets/#{config_file}" unless config_file =~ /[\\|\/]/
$cfg_file = "#{__dir__}/../../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
......@@ -128,7 +128,7 @@ module RakefileHelpers
def report_summary
summary = UnityTestSummary.new
summary.root = HERE
summary.root = __dir__
results_glob = "#{$cfg['compiler']['build_path']}*.test*"
results_glob.tr!('\\', '/')
results = Dir[results_glob]
......@@ -145,9 +145,9 @@ 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["#{__dir__}/src/*.c"]
src_files += Dir["#{__dir__}/test/*.c"]
src_files += Dir["#{__dir__}/test/main/*.c"]
src_files << '../../src/unity.c'
# Build object files
......
......@@ -93,6 +93,8 @@ void UnityTestRunner(unityfunction* setup,
UnityMalloc_StartTest();
UnityPointer_Init();
UNITY_EXEC_TIME_START();
if (TEST_PROTECT())
{
setup();
......@@ -418,6 +420,8 @@ void UnityConcludeFixtureTest(void)
if (UnityFixture.Verbose)
{
UnityPrint(" PASS");
UNITY_EXEC_TIME_STOP();
UNITY_PRINT_EXEC_TIME();
UNITY_PRINT_EOL();
}
}
......
......@@ -78,6 +78,6 @@ int UnityMain(int argc, const char* argv[], void (*runAllTests)(void));
#endif
/* You must compile with malloc replacement, as defined in unity_fixture_malloc_overrides.h */
void UnityMalloc_MakeMallocFailAfterCount(int count);
void UnityMalloc_MakeMallocFailAfterCount(int countdown);
#endif /* UNITY_FIXTURE_H_ */
......@@ -24,7 +24,7 @@ extern struct UNITY_FIXTURE_T UnityFixture;
typedef void unityfunction(void);
void UnityTestRunner(unityfunction* setup,
unityfunction* body,
unityfunction* testBody,
unityfunction* teardown,
const char* printableName,
const char* group,
......@@ -37,7 +37,7 @@ void UnityMalloc_EndTest(void);
int UnityGetCommandLineOptions(int argc, const char* argv[]);
void UnityConcludeFixtureTest(void);
void UnityPointer_Set(void** ptr, void* newValue, UNITY_LINE_TYPE line);
void UnityPointer_Set(void** pointer, void* newValue, UNITY_LINE_TYPE line);
void UnityPointer_UndoAllSets(void);
void UnityPointer_Init(void);
#ifndef UNITY_MAX_POINTERS
......
......@@ -14,8 +14,8 @@ void UNITY_OUTPUT_CHAR(int);
#endif
/* Helpful macros for us to use here in Assert functions */
#define UNITY_FAIL_AND_BAIL { Unity.CurrentTestFailed = 1; TEST_ABORT(); }
#define UNITY_IGNORE_AND_BAIL { Unity.CurrentTestIgnored = 1; TEST_ABORT(); }
#define UNITY_FAIL_AND_BAIL { Unity.CurrentTestFailed = 1; UNITY_OUTPUT_FLUSH(); TEST_ABORT(); }
#define UNITY_IGNORE_AND_BAIL { Unity.CurrentTestIgnored = 1; UNITY_OUTPUT_FLUSH(); TEST_ABORT(); }
#define RETURN_IF_FAIL_OR_IGNORE if (Unity.CurrentTestFailed || Unity.CurrentTestIgnored) return
struct UNITY_STORAGE_T Unity;
......@@ -67,6 +67,7 @@ static const char UnityStrDetail2Name[] = " " UNITY_DETAIL2_NAME " ";
* Pretty Printers & Test Result Output Handlers
*-----------------------------------------------*/
/*-----------------------------------------------*/
void UnityPrint(const char* string)
{
const char* pch = string;
......@@ -116,6 +117,7 @@ void UnityPrint(const char* string)
}
}
/*-----------------------------------------------*/
void UnityPrintLen(const char* string, const UNITY_UINT32 length)
{
const char* pch = string;
......@@ -212,7 +214,9 @@ void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print)
int nibble;
char nibbles = nibbles_to_print;
if ((unsigned)nibbles > (2 * sizeof(number)))
{
nibbles = 2 * sizeof(number);
}
while (nibbles > 0)
{
......@@ -287,15 +291,24 @@ void UnityPrintFloat(const UNITY_DOUBLE input_number)
}
/* handle zero, NaN, and +/- infinity */
if (number == 0.0f) UnityPrint("0");
else if (isnan(number)) UnityPrint("nan");
else if (isinf(number)) UnityPrint("inf");
if (number == 0.0f)
{
UnityPrint("0");
}
else if (isnan(number))
{
UnityPrint("nan");
}
else if (isinf(number))
{
UnityPrint("inf");
}
else
{
UNITY_INT32 n_int = 0, n;
int exponent = 0;
int decimals, digits;
char buf[16];
char buf[16] = {0};
/*
* Scale up or down by powers of 10. To minimize rounding error,
......@@ -447,6 +460,7 @@ void UnityConcludeTest(void)
Unity.CurrentTestFailed = 0;
Unity.CurrentTestIgnored = 0;
UNITY_EXEC_TIME_RESET();
UNITY_PRINT_EOL();
UNITY_FLUSH_CALL();
}
......@@ -534,6 +548,7 @@ static void UnityPrintExpectedAndActualStringsLen(const char* expected,
* Assertion & Control Helpers
*-----------------------------------------------*/
/*-----------------------------------------------*/
static int UnityIsOneArrayNull(UNITY_INTERNAL_PTR expected,
UNITY_INTERNAL_PTR actual,
const UNITY_LINE_TYPE lineNumber,
......@@ -566,6 +581,7 @@ static int UnityIsOneArrayNull(UNITY_INTERNAL_PTR expected,
* Assertion Functions
*-----------------------------------------------*/
/*-----------------------------------------------*/
void UnityAssertBits(const UNITY_INT mask,
const UNITY_INT expected,
const UNITY_INT actual,
......@@ -672,11 +688,17 @@ void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected,
UnityPrintPointlessAndBail();
}
if (expected == actual) return; /* Both are NULL or same pointer */
if (expected == actual)
{
return; /* Both are NULL or same pointer */
}
if (UnityIsOneArrayNull(expected, actual, lineNumber, msg))
{
UNITY_FAIL_AND_BAIL;
}
while (elements--)
while ((elements > 0) && elements--)
{
UNITY_INT expect_val;
UNITY_INT actual_val;
......@@ -733,13 +755,13 @@ void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected,
/*-----------------------------------------------*/
#ifndef UNITY_EXCLUDE_FLOAT
/* Wrap this define in a function with variable types as float or double */
#define UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff) \
if (isinf(expected) && isinf(actual) && ((expected < 0) == (actual < 0))) return 1; \
if (UNITY_NAN_CHECK) return 1; \
diff = actual - expected; \
if (diff < 0) diff = -diff; \
if (delta < 0) delta = -delta; \
return !(isnan(diff) || isinf(diff) || (diff > delta))
#define UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff) \
if (isinf(expected) && isinf(actual) && (((expected) < 0) == ((actual) < 0))) return 1; \
if (UNITY_NAN_CHECK) return 1; \
(diff) = (actual) - (expected); \
if ((diff) < 0) (diff) = -(diff); \
if ((delta) < 0) (delta) = -(delta); \
return !(isnan(diff) || isinf(diff) || ((diff) > (delta)))
/* This first part of this condition will catch any NaN or Infinite values */
#ifndef UNITY_NAN_NOT_EQUAL_NAN
#define UNITY_NAN_CHECK isnan(expected) && isnan(actual)
......@@ -759,12 +781,14 @@ void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected,
UnityPrint(UnityStrDelta)
#endif /* UNITY_EXCLUDE_FLOAT_PRINT */
/*-----------------------------------------------*/
static int UnityFloatsWithin(UNITY_FLOAT delta, UNITY_FLOAT expected, UNITY_FLOAT actual)
{
UNITY_FLOAT diff;
UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff);
}
/*-----------------------------------------------*/
void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected,
UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual,
const UNITY_UINT32 num_elements,
......@@ -783,9 +807,15 @@ void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected,
UnityPrintPointlessAndBail();
}
if (expected == actual) return; /* Both are NULL or same pointer */
if (expected == actual)
{
return; /* Both are NULL or same pointer */
}
if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg))
{
UNITY_FAIL_AND_BAIL;
}
while (elements--)
{
......@@ -870,14 +900,18 @@ void UnityAssertFloatSpecial(const UNITY_FLOAT actual,
UnityTestResultsFailBegin(lineNumber);
UnityPrint(UnityStrExpected);
if (!should_be_trait)
{
UnityPrint(UnityStrNot);
}
UnityPrint(trait_names[trait_index]);
UnityPrint(UnityStrWas);
#ifndef UNITY_EXCLUDE_FLOAT_PRINT
UnityPrintFloat((UNITY_DOUBLE)actual);
#else
if (should_be_trait)
{
UnityPrint(UnityStrNot);
}
UnityPrint(trait_names[trait_index]);
#endif
UnityAddMsgIfSpecified(msg);
......@@ -895,6 +929,7 @@ static int UnityDoublesWithin(UNITY_DOUBLE delta, UNITY_DOUBLE expected, UNITY_D
UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff);
}
/*-----------------------------------------------*/
void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected,
UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual,
const UNITY_UINT32 num_elements,
......@@ -913,9 +948,15 @@ void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expecte
UnityPrintPointlessAndBail();
}
if (expected == actual) return; /* Both are NULL or same pointer */
if (expected == actual)
{
return; /* Both are NULL or same pointer */
}
if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg))
{
UNITY_FAIL_AND_BAIL;
}
while (elements--)
{
......@@ -955,7 +996,6 @@ void UnityAssertDoublesWithin(const UNITY_DOUBLE delta,
}
/*-----------------------------------------------*/
void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual,
const char* msg,
const UNITY_LINE_TYPE lineNumber,
......@@ -1000,14 +1040,18 @@ void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual,
UnityTestResultsFailBegin(lineNumber);
UnityPrint(UnityStrExpected);
if (!should_be_trait)
{
UnityPrint(UnityStrNot);
}
UnityPrint(trait_names[trait_index]);
UnityPrint(UnityStrWas);
#ifndef UNITY_EXCLUDE_FLOAT_PRINT
UnityPrintFloat(actual);
#else
if (should_be_trait)
{
UnityPrint(UnityStrNot);
}
UnityPrint(trait_names[trait_index]);
#endif
UnityAddMsgIfSpecified(msg);
......@@ -1030,16 +1074,24 @@ void UnityAssertNumbersWithin(const UNITY_UINT delta,
if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT)
{
if (actual > expected)
Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(actual - expected) > delta);
{
Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(actual - expected) > delta);
}
else
{
Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(expected - actual) > delta);
}
}
else
{
if ((UNITY_UINT)actual > (UNITY_UINT)expected)
{
Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(actual - expected) > delta);
}
else
{
Unity.CurrentTestFailed = (UNITY_UINT)((UNITY_UINT)(expected - actual) > delta);
}
}
if (Unity.CurrentTestFailed)
......@@ -1235,9 +1287,15 @@ void UnityAssertEqualMemory(UNITY_INTERNAL_PTR expected,
UnityPrintPointlessAndBail();
}
if (expected == actual) return; /* Both are NULL or same pointer */
if (expected == actual)
{
return; /* Both are NULL or same pointer */
}
if (UnityIsOneArrayNull(expected, actual, lineNumber, msg))
{
UNITY_FAIL_AND_BAIL;
}
while (elements--)
{
......@@ -1314,6 +1372,7 @@ UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size)
}
#ifndef UNITY_EXCLUDE_FLOAT
/*-----------------------------------------------*/
UNITY_INTERNAL_PTR UnityFloatToPtr(const float num)
{
UnityQuickCompare.f = num;
......@@ -1322,6 +1381,7 @@ UNITY_INTERNAL_PTR UnityFloatToPtr(const float num)
#endif
#ifndef UNITY_EXCLUDE_DOUBLE
/*-----------------------------------------------*/
UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num)
{
UnityQuickCompare.d = num;
......@@ -1333,6 +1393,7 @@ UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num)
* Control Functions
*-----------------------------------------------*/
/*-----------------------------------------------*/
void UnityFail(const char* msg, const UNITY_LINE_TYPE line)
{
RETURN_IF_FAIL_OR_IGNORE;
......@@ -1412,6 +1473,7 @@ void UnityBegin(const char* filename)
Unity.TestIgnores = 0;
Unity.CurrentTestFailed = 0;
Unity.CurrentTestIgnored = 0;
UNITY_EXEC_TIME_RESET();
UNITY_CLR_DETAILS();
UNITY_OUTPUT_START();
......@@ -1456,6 +1518,7 @@ char* UnityOptionIncludeNamed = NULL;
char* UnityOptionExcludeNamed = NULL;
int UnityVerbosity = 1;
/*-----------------------------------------------*/
int UnityParseOptions(int argc, char** argv)
{
UnityOptionIncludeNamed = NULL;
......@@ -1472,9 +1535,13 @@ int UnityParseOptions(int argc, char** argv)
case 'n': /* include tests with name including this string */
case 'f': /* an alias for -n */
if (argv[i][2] == '=')
{
UnityOptionIncludeNamed = &argv[i][3];
}
else if (++i < argc)
{
UnityOptionIncludeNamed = argv[i];
}
else
{
UnityPrint("ERROR: No Test String to Include Matches For");
......@@ -1490,9 +1557,13 @@ int UnityParseOptions(int argc, char** argv)
break;
case 'x': /* exclude tests with name including this string */
if (argv[i][2] == '=')
{
UnityOptionExcludeNamed = &argv[i][3];
}
else if (++i < argc)
{
UnityOptionExcludeNamed = argv[i];
}
else
{
UnityPrint("ERROR: No Test String to Exclude Matches For");
......@@ -1512,6 +1583,7 @@ int UnityParseOptions(int argc, char** argv)
return 0;
}
/*-----------------------------------------------*/
int IsStringInBiggerString(const char* longstring, const char* shortstring)
{
const char* lptr = longstring;
......@@ -1519,7 +1591,9 @@ int IsStringInBiggerString(const char* longstring, const char* shortstring)
const char* lnext = lptr;
if (*sptr == '*')
{
return 1;
}
while (*lptr)
{
......@@ -1550,9 +1624,11 @@ int IsStringInBiggerString(const char* longstring, const char* shortstring)
lptr = lnext;
sptr = shortstring;
}
return 0;
}
/*-----------------------------------------------*/
int UnityStringArgumentMatches(const char* str)
{
int retval;
......@@ -1565,7 +1641,9 @@ int UnityStringArgumentMatches(const char* str)
while (ptr1[0] != 0)
{
if ((ptr1[0] == '"') || (ptr1[0] == '\''))
{
ptr1++;
}
/* look for the start of the next partial */
ptr2 = ptr1;
......@@ -1574,26 +1652,37 @@ int UnityStringArgumentMatches(const char* str)
{
ptr2++;
if ((ptr2[0] == ':') && (ptr2[1] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ','))
{
ptrf = &ptr2[1];
}
} while ((ptr2[0] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ','));
while ((ptr2[0] != 0) && ((ptr2[0] == ':') || (ptr2[0] == '\'') || (ptr2[0] == '"') || (ptr2[0] == ',')))
{
ptr2++;
}
/* done if complete filename match */
retval = IsStringInBiggerString(Unity.TestFile, ptr1);
if (retval == 1)
{
return retval;
}
/* done if testname match after filename partial match */
if ((retval == 2) && (ptrf != 0))
{
if (IsStringInBiggerString(Unity.CurrentTestName, ptrf))
{
return 1;
}
}
/* done if complete testname match */
if (IsStringInBiggerString(Unity.CurrentTestName, ptr1) == 1)
{
return 1;
}
ptr1 = ptr2;
}
......@@ -1602,6 +1691,7 @@ int UnityStringArgumentMatches(const char* str)
return 0;
}
/*-----------------------------------------------*/
int UnityTestMatches(void)
{
/* Check if this test name matches the included test pattern */
......@@ -1611,14 +1701,19 @@ int UnityTestMatches(void)
retval = UnityStringArgumentMatches(UnityOptionIncludeNamed);
}
else
{
retval = 1;
}
/* Check if this test name matches the excluded test pattern */
if (UnityOptionExcludeNamed)
{
if (UnityStringArgumentMatches(UnityOptionExcludeNamed))
{
retval = 0;
}
}
return retval;
}
......
......@@ -402,8 +402,8 @@ int suiteTearDown(int num_failures);
#define TEST_ASSERT_LESS_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message))
#define TEST_ASSERT_LESS_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message))
/* Integer Ranges (of all sizes) */
#define TEST_ASSERT_INT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, (message))
......
此差异已折叠。
......@@ -18,7 +18,7 @@ Style/HashSyntax:
EnforcedStyle: no_mixed_keys
# This is disabled because it seems to get confused over nested hashes
Style/AlignHash:
Layout/AlignHash:
Enabled: false
EnforcedHashRocketStyle: table
EnforcedColonStyle: table
......
......@@ -15,6 +15,8 @@ CFLAGS += -Wbad-function-cast -Wcast-qual -Wold-style-definition -Wshadow -Wstri
CFLAGS += $(DEBUG)
DEFINES = -D UNITY_OUTPUT_CHAR=putcharSpy
DEFINES += -D UNITY_OUTPUT_CHAR_HEADER_DECLARATION=putcharSpy\(int\)
DEFINES += -D UNITY_OUTPUT_FLUSH=flushSpy
DEFINES += -D UNITY_OUTPUT_FLUSH_HEADER_DECLARATION=flushSpy\(void\)
DEFINES += $(UNITY_SUPPORT_64) $(UNITY_INCLUDE_DOUBLE)
UNITY_SUPPORT_64 = -D UNITY_SUPPORT_64
UNITY_INCLUDE_DOUBLE = -D UNITY_INCLUDE_DOUBLE
......
......@@ -4,17 +4,16 @@
# [Released under MIT License. Please refer to license.txt for details]
# ==========================================
UNITY_ROOT = File.expand_path(File.dirname(__FILE__)) + '/'
$verbose = false
require 'rake'
require 'rake/clean'
require UNITY_ROOT + 'rakefile_helper'
require_relative 'rakefile_helper'
require 'rspec/core/rake_task'
TEMP_DIRS = [
File.join(UNITY_ROOT, 'build'),
File.join(UNITY_ROOT, 'sandbox')
File.join(__dir__, 'build'),
File.join(__dir__, 'sandbox')
]
TEMP_DIRS.each do |dir|
......
......@@ -6,9 +6,9 @@
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_relative '../auto/unity_test_summary'
require_relative '../auto/generate_test_runner'
require_relative '../auto/colour_reporter'
module RakefileHelpers
C_EXTENSION = '.c'.freeze
......@@ -179,7 +179,7 @@ module RakefileHelpers
def report_summary
summary = UnityTestSummary.new
summary.root = UNITY_ROOT
summary.root = __dir__
results_glob = "#{$cfg['compiler']['build_path']}*.test*"
results_glob.tr!('\\', '/')
results = Dir[results_glob]
......
......@@ -21,7 +21,10 @@
/* Support for Meta Test Rig */
#define TEST_CASE(a)
void putcharSpy(int c) { (void)putchar(c);} // include passthrough for linking tests
/* Include Passthroughs for Linking Tests */
void putcharSpy(int c) { (void)putchar(c);}
void flushSpy(void) {}
/* Global Variables Used During These Tests */
int CounterSetup = 0;
......
......@@ -13,7 +13,10 @@ TEST_FILE("some_file.c")
/* Support for Meta Test Rig */
#define TEST_CASE(a)
void putcharSpy(int c) { (void)putchar(c);} // include passthrough for linking tests
/* Include Passthroughs for Linking Tests */
void putcharSpy(int c) { (void)putchar(c);}
void flushSpy(void) {}
/* Global Variables Used During These Tests */
int CounterSetup = 0;
......
......@@ -22,7 +22,10 @@
/* Support for Meta Test Rig */
#define TEST_CASE(a)
void putcharSpy(int c) { (void)putchar(c);} // include passthrough for linking tests
/* Include Passthroughs for Linking Tests */
void putcharSpy(int c) { (void)putchar(c);}
void flushSpy(void) {}
/* Global Variables Used During These Tests */
int CounterSetup = 0;
......
......@@ -8,10 +8,13 @@
#include <stdio.h>
#include "unity.h"
void putcharSpy(int c) { (void)putchar(c);} // include passthrough for linking tests
/* Support for Meta Test Rig */
#define TEST_CASE(...)
/* Include Passthroughs for Linking Tests */
void putcharSpy(int c) { (void)putchar(c);}
void flushSpy(void) {}
#define EXPECT_ABORT_BEGIN \
if (TEST_PROTECT()) \
{
......
......@@ -54,6 +54,10 @@ void startPutcharSpy(void);
void endPutcharSpy(void);
char* getBufferPutcharSpy(void);
void startFlushSpy(void);
void endFlushSpy(void);
int getFlushSpyCalls(void);
static int SetToOneToFailInTearDown;
static int SetToOneMeanWeAlreadyCheckedThisGuy;
......@@ -99,6 +103,10 @@ void testUnitySizeInitializationReminder(void)
UNITY_COUNTER_TYPE TestIgnores;
UNITY_COUNTER_TYPE CurrentTestFailed;
UNITY_COUNTER_TYPE CurrentTestIgnored;
#ifdef UNITY_INCLUDE_EXEC_TIME
UNITY_COUNTER_TYPE CurrentTestStartTime;
UNITY_COUNTER_TYPE CurrentTestStopTime;
#endif
#ifndef UNITY_EXCLUDE_SETJMP_H
jmp_buf AbortFrame;
#endif
......@@ -115,6 +123,10 @@ void testUnitySizeInitializationReminder(void)
UNITY_COUNTER_TYPE TestIgnores;
UNITY_COUNTER_TYPE CurrentTestFailed;
UNITY_COUNTER_TYPE CurrentTestIgnored;
#ifdef UNITY_INCLUDE_EXEC_TIME
UNITY_COUNTER_TYPE CurrentTestStartTime;
UNITY_COUNTER_TYPE CurrentTestStopTime;
#endif
#ifndef UNITY_EXCLUDE_SETJMP_H
jmp_buf AbortFrame;
#endif
......@@ -3335,14 +3347,35 @@ void putcharSpy(int c)
#endif
}
/* This is for counting the calls to the flushSpy */
static int flushSpyEnabled;
static int flushSpyCalls = 0;
void startFlushSpy(void) { flushSpyCalls = 0; flushSpyEnabled = 1; }
void endFlushSpy(void) { flushSpyCalls = 0; flushSpyEnabled = 0; }
int getFlushSpyCalls(void) { return flushSpyCalls; }
void flushSpy(void)
{
if (flushSpyEnabled){ flushSpyCalls++; }
}
void testFailureCountIncrementsAndIsReturnedAtEnd(void)
{
UNITY_UINT savedFailures = Unity.TestFailures;
Unity.CurrentTestFailed = 1;
startPutcharSpy(); // Suppress output
startFlushSpy();
TEST_ASSERT_EQUAL(0, getFlushSpyCalls());
UnityConcludeTest();
endPutcharSpy();
TEST_ASSERT_EQUAL(savedFailures + 1, Unity.TestFailures);
#if defined(UNITY_OUTPUT_FLUSH) && defined(UNITY_OUTPUT_FLUSH_HEADER_DECLARATION)
TEST_ASSERT_EQUAL(1, getFlushSpyCalls());
#else
TEST_ASSERT_EQUAL(0, getFlushSpyCalls());
#endif
endFlushSpy();
startPutcharSpy(); // Suppress output
int failures = UnityEnd();
......@@ -3412,6 +3445,7 @@ void testPrintNumbersUnsigned32(void)
#endif
}
// ===================== THESE TEST WILL RUN IF YOUR CONFIG INCLUDES 64 BIT SUPPORT ==================
void testPrintNumbersInt64(void)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册