- add ceedling/cmock/unity as testing framework and support
- unified makefile project for the whole repos - new separate project for tests
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
#include "CException.h"
|
||||
|
||||
volatile CEXCEPTION_FRAME_T CExceptionFrames[CEXCEPTION_NUM_ID] = { 0 };
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
// Throw
|
||||
//------------------------------------------------------------------------------------------
|
||||
void Throw(CEXCEPTION_T ExceptionID)
|
||||
{
|
||||
unsigned int MY_ID = CEXCEPTION_GET_ID;
|
||||
CExceptionFrames[MY_ID].Exception = ExceptionID;
|
||||
if (CExceptionFrames[MY_ID].pFrame)
|
||||
{
|
||||
longjmp(*CExceptionFrames[MY_ID].pFrame, 1);
|
||||
}
|
||||
CEXCEPTION_NO_CATCH_HANDLER(MY_ID);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
// Explanation of what it's all for:
|
||||
//------------------------------------------------------------------------------------------
|
||||
/*
|
||||
#define Try
|
||||
{ <- give us some local scope. most compilers are happy with this
|
||||
jmp_buf *PrevFrame, NewFrame; <- prev frame points to the last try block's frame. new frame gets created on stack for this Try block
|
||||
unsigned int MY_ID = CEXCEPTION_GET_ID; <- look up this task's id for use in frame array. always 0 if single-tasking
|
||||
PrevFrame = CExceptionFrames[CEXCEPTION_GET_ID].pFrame; <- set pointer to point at old frame (which array is currently pointing at)
|
||||
CExceptionFrames[MY_ID].pFrame = &NewFrame; <- set array to point at my new frame instead, now
|
||||
CExceptionFrames[MY_ID].Exception = CEXCEPTION_NONE; <- initialize my exception id to be NONE
|
||||
if (setjmp(NewFrame) == 0) { <- do setjmp. it returns 1 if longjump called, otherwise 0
|
||||
if (&PrevFrame) <- this is here to force proper scoping. it requires braces or a single line to be but after Try, otherwise won't compile. This is always true at this point.
|
||||
|
||||
#define Catch(e)
|
||||
else { } <- this also forces proper scoping. Without this they could stick their own 'else' in and it would get ugly
|
||||
CExceptionFrames[MY_ID].Exception = CEXCEPTION_NONE; <- no errors happened, so just set the exception id to NONE (in case it was corrupted)
|
||||
}
|
||||
else <- an exception occurred
|
||||
{ e = CExceptionFrames[MY_ID].Exception; e=e;} <- assign the caught exception id to the variable passed in.
|
||||
CExceptionFrames[MY_ID].pFrame = PrevFrame; <- make the pointer in the array point at the previous frame again, as if NewFrame never existed.
|
||||
} <- finish off that local scope we created to have our own variables
|
||||
if (CExceptionFrames[CEXCEPTION_GET_ID].Exception != CEXCEPTION_NONE) <- start the actual 'catch' processing if we have an exception id saved away
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
#ifndef _CEXCEPTION_H
|
||||
#define _CEXCEPTION_H
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
//To Use CException, you have a number of options:
|
||||
//1. Just include it and run with the defaults
|
||||
//2. Define any of the following symbols at the command line to override them
|
||||
//3. Include a header file before CException.h everywhere which defines any of these
|
||||
//4. Create an Exception.h in your path, and just define EXCEPTION_USE_CONFIG_FILE first
|
||||
|
||||
#ifdef CEXCEPTION_USE_CONFIG_FILE
|
||||
#include "CExceptionConfig.h"
|
||||
#endif
|
||||
|
||||
//This is the value to assign when there isn't an exception
|
||||
#ifndef CEXCEPTION_NONE
|
||||
#define CEXCEPTION_NONE (0x5A5A5A5A)
|
||||
#endif
|
||||
|
||||
//This is number of exception stacks to keep track of (one per task)
|
||||
#ifndef CEXCEPTION_NUM_ID
|
||||
#define CEXCEPTION_NUM_ID (1) //there is only the one stack by default
|
||||
#endif
|
||||
|
||||
//This is the method of getting the current exception stack index (0 if only one stack)
|
||||
#ifndef CEXCEPTION_GET_ID
|
||||
#define CEXCEPTION_GET_ID (0) //use the first index always because there is only one anyway
|
||||
#endif
|
||||
|
||||
//The type to use to store the exception values.
|
||||
#ifndef CEXCEPTION_T
|
||||
#define CEXCEPTION_T unsigned int
|
||||
#endif
|
||||
|
||||
//This is an optional special handler for when there is no global Catch
|
||||
#ifndef CEXCEPTION_NO_CATCH_HANDLER
|
||||
#define CEXCEPTION_NO_CATCH_HANDLER(id)
|
||||
#endif
|
||||
|
||||
//exception frame structures
|
||||
typedef struct {
|
||||
jmp_buf* pFrame;
|
||||
CEXCEPTION_T volatile Exception;
|
||||
} CEXCEPTION_FRAME_T;
|
||||
|
||||
//actual root frame storage (only one if single-tasking)
|
||||
extern volatile CEXCEPTION_FRAME_T CExceptionFrames[];
|
||||
|
||||
//Try (see C file for explanation)
|
||||
#define Try \
|
||||
{ \
|
||||
jmp_buf *PrevFrame, NewFrame; \
|
||||
unsigned int MY_ID = CEXCEPTION_GET_ID; \
|
||||
PrevFrame = CExceptionFrames[CEXCEPTION_GET_ID].pFrame; \
|
||||
CExceptionFrames[MY_ID].pFrame = (jmp_buf*)(&NewFrame); \
|
||||
CExceptionFrames[MY_ID].Exception = CEXCEPTION_NONE; \
|
||||
if (setjmp(NewFrame) == 0) { \
|
||||
if (&PrevFrame)
|
||||
|
||||
//Catch (see C file for explanation)
|
||||
#define Catch(e) \
|
||||
else { } \
|
||||
CExceptionFrames[MY_ID].Exception = CEXCEPTION_NONE; \
|
||||
} \
|
||||
else \
|
||||
{ e = CExceptionFrames[MY_ID].Exception; e=e; } \
|
||||
CExceptionFrames[MY_ID].pFrame = PrevFrame; \
|
||||
} \
|
||||
if (CExceptionFrames[CEXCEPTION_GET_ID].Exception != CEXCEPTION_NONE)
|
||||
|
||||
//Throw an Error
|
||||
void Throw(CEXCEPTION_T ExceptionID);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
|
||||
#endif // _CEXCEPTION_H
|
||||
@@ -0,0 +1,2 @@
|
||||
16
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
1.2
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# ==========================================
|
||||
# CMock Project - Automatic Mock Generation for C
|
||||
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
# [Released under MIT License. Please refer to license.txt for details]
|
||||
# ==========================================
|
||||
|
||||
# Setup our load path:
|
||||
[
|
||||
'lib',
|
||||
].each do |dir|
|
||||
$LOAD_PATH.unshift( File.join( File.expand_path(File.dirname(__FILE__)) + '/../', dir) )
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
# ==========================================
|
||||
# CMock Project - Automatic Mock Generation for C
|
||||
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
# [Released under MIT License. Please refer to license.txt for details]
|
||||
# ==========================================
|
||||
|
||||
# Setup our load path:
|
||||
[
|
||||
'lib',
|
||||
'vendor/behaviors/lib',
|
||||
'vendor/hardmock/lib',
|
||||
'vendor/unity/auto/',
|
||||
'test/system/'
|
||||
].each do |dir|
|
||||
$LOAD_PATH.unshift( File.join( File.expand_path(File.dirname(__FILE__) + "/../"), dir) )
|
||||
end
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
# ==========================================
|
||||
# CMock Project - Automatic Mock Generation for C
|
||||
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
# [Released under MIT License. Please refer to license.txt for details]
|
||||
# ==========================================
|
||||
|
||||
[ "../config/production_environment",
|
||||
"cmock_header_parser",
|
||||
"cmock_generator",
|
||||
"cmock_file_writer",
|
||||
"cmock_config",
|
||||
"cmock_plugin_manager",
|
||||
"cmock_generator_utils",
|
||||
"cmock_unityhelper_parser"].each {|req| require "#{File.expand_path(File.dirname(__FILE__))}/#{req}"}
|
||||
|
||||
class CMock
|
||||
|
||||
def initialize(options=nil)
|
||||
cm_config = CMockConfig.new(options)
|
||||
cm_unityhelper = CMockUnityHelperParser.new(cm_config)
|
||||
cm_writer = CMockFileWriter.new(cm_config)
|
||||
cm_gen_utils = CMockGeneratorUtils.new(cm_config, {:unity_helper => cm_unityhelper})
|
||||
cm_gen_plugins = CMockPluginManager.new(cm_config, cm_gen_utils)
|
||||
@cm_parser = CMockHeaderParser.new(cm_config)
|
||||
@cm_generator = CMockGenerator.new(cm_config, cm_writer, cm_gen_utils, cm_gen_plugins)
|
||||
@silent = (cm_config.verbosity < 2)
|
||||
end
|
||||
|
||||
def setup_mocks(files)
|
||||
[files].flatten.each do |src|
|
||||
generate_mock src
|
||||
end
|
||||
end
|
||||
|
||||
private ###############################
|
||||
|
||||
def generate_mock(src)
|
||||
name = File.basename(src, '.h')
|
||||
puts "Creating mock for #{name}..." unless @silent
|
||||
@cm_generator.create_mock(name, @cm_parser.parse(name, File.read(src)))
|
||||
end
|
||||
end
|
||||
|
||||
# Command Line Support ###############################
|
||||
|
||||
if ($0 == __FILE__)
|
||||
usage = "usage: ruby #{__FILE__} (-oOptionsFile) File(s)ToMock"
|
||||
|
||||
if (!ARGV[0])
|
||||
puts usage
|
||||
exit 1
|
||||
end
|
||||
|
||||
options = nil
|
||||
filelist = []
|
||||
ARGV.each do |arg|
|
||||
if (arg =~ /^-o(\w*)/)
|
||||
options = arg.gsub(/^-o/,'')
|
||||
else
|
||||
filelist << arg
|
||||
end
|
||||
end
|
||||
|
||||
CMock.new(options).setup_mocks(filelist)
|
||||
end
|
||||
@@ -0,0 +1,129 @@
|
||||
# ==========================================
|
||||
# CMock Project - Automatic Mock Generation for C
|
||||
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
# [Released under MIT License. Please refer to license.txt for details]
|
||||
# ==========================================
|
||||
|
||||
class CMockConfig
|
||||
|
||||
CMockDefaultOptions =
|
||||
{
|
||||
:framework => :unity,
|
||||
:mock_path => 'mocks',
|
||||
:mock_prefix => 'Mock',
|
||||
:plugins => [],
|
||||
:strippables => ['(?:__attribute__\s*\(+.*?\)+)'],
|
||||
:attributes => ['__ramfunc', '__irq', '__fiq', 'register', 'extern'],
|
||||
:c_calling_conventions => ['__stdcall', '__cdecl', '__fastcall'],
|
||||
:enforce_strict_ordering => false,
|
||||
:unity_helper_path => false,
|
||||
:treat_as => {},
|
||||
:treat_as_void => [],
|
||||
:memcmp_if_unknown => true,
|
||||
:when_no_prototypes => :warn, #the options being :ignore, :warn, or :error
|
||||
:when_ptr => :compare_data, #the options being :compare_ptr, :compare_data, or :smart
|
||||
:verbosity => 2, #the options being 0 errors only, 1 warnings and errors, 2 normal info, 3 verbose
|
||||
:treat_externs => :exclude, #the options being :include or :exclude
|
||||
:ignore => :args_and_calls, #the options being :args_and_calls or :args_only
|
||||
:callback_include_count => true,
|
||||
:callback_after_arg_check => false,
|
||||
:includes => nil,
|
||||
:includes_h_pre_orig_header => nil,
|
||||
:includes_h_post_orig_header => nil,
|
||||
:includes_c_pre_header => nil,
|
||||
:includes_c_post_header => nil
|
||||
}
|
||||
|
||||
def initialize(options=nil)
|
||||
case(options)
|
||||
when NilClass then options = CMockDefaultOptions.clone
|
||||
when String then options = CMockDefaultOptions.clone.merge(load_config_file_from_yaml(options))
|
||||
when Hash then options = CMockDefaultOptions.clone.merge(options)
|
||||
else raise "If you specify arguments, it should be a filename or a hash of options"
|
||||
end
|
||||
|
||||
#do some quick type verification
|
||||
[:plugins, :attributes, :treat_as_void].each do |opt|
|
||||
unless (options[opt].class == Array)
|
||||
options[opt] = []
|
||||
puts "WARNING: :#{opt.to_s} should be an array." unless (options[:verbosity] < 1)
|
||||
end
|
||||
end
|
||||
[:includes, :includes_h_pre_orig_header, :includes_h_post_orig_header, :includes_c_pre_header, :includes_c_post_header].each do |opt|
|
||||
unless (options[opt].nil? or (options[opt].class == Array))
|
||||
options[opt] = []
|
||||
puts "WARNING: :#{opt.to_s} should be an array." unless (options[:verbosity] < 1)
|
||||
end
|
||||
end
|
||||
options[:unity_helper_path] ||= options[:unity_helper]
|
||||
options[:plugins].compact!
|
||||
options[:plugins].map! {|p| p.to_sym}
|
||||
@options = options
|
||||
|
||||
treat_as_map = standard_treat_as_map()#.clone
|
||||
treat_as_map.merge!(@options[:treat_as])
|
||||
@options[:treat_as] = treat_as_map
|
||||
|
||||
@options.each_key { |key| eval("def #{key.to_s}() return @options[:#{key.to_s}] end") }
|
||||
end
|
||||
|
||||
def load_config_file_from_yaml yaml_filename
|
||||
require 'yaml'
|
||||
require 'fileutils'
|
||||
YAML.load_file(yaml_filename)[:cmock]
|
||||
end
|
||||
|
||||
def set_path(path)
|
||||
@src_path = path
|
||||
end
|
||||
|
||||
def load_unity_helper
|
||||
return File.new(@options[:unity_helper_path]).read if (@options[:unity_helper_path])
|
||||
return nil
|
||||
end
|
||||
|
||||
def standard_treat_as_map
|
||||
{
|
||||
'int' => 'INT',
|
||||
'char' => 'INT8',
|
||||
'short' => 'INT16',
|
||||
'long' => 'INT',
|
||||
'int8' => 'INT8',
|
||||
'int16' => 'INT16',
|
||||
'int32' => 'INT',
|
||||
'int8_t' => 'INT8',
|
||||
'int16_t' => 'INT16',
|
||||
'int32_t' => 'INT',
|
||||
'INT8_T' => 'INT8',
|
||||
'INT16_T' => 'INT16',
|
||||
'INT32_T' => 'INT',
|
||||
'bool' => 'INT',
|
||||
'bool_t' => 'INT',
|
||||
'BOOL' => 'INT',
|
||||
'BOOL_T' => 'INT',
|
||||
'unsigned int' => 'HEX32',
|
||||
'unsigned long' => 'HEX32',
|
||||
'uint32' => 'HEX32',
|
||||
'uint32_t' => 'HEX32',
|
||||
'UINT32' => 'HEX32',
|
||||
'UINT32_T' => 'HEX32',
|
||||
'void*' => 'PTR',
|
||||
'unsigned short' => 'HEX16',
|
||||
'uint16' => 'HEX16',
|
||||
'uint16_t' => 'HEX16',
|
||||
'UINT16' => 'HEX16',
|
||||
'UINT16_T' => 'HEX16',
|
||||
'unsigned char' => 'HEX8',
|
||||
'uint8' => 'HEX8',
|
||||
'uint8_t' => 'HEX8',
|
||||
'UINT8' => 'HEX8',
|
||||
'UINT8_T' => 'HEX8',
|
||||
'char*' => 'STRING',
|
||||
'pCHAR' => 'STRING',
|
||||
'cstring' => 'STRING',
|
||||
'CSTRING' => 'STRING',
|
||||
'float' => 'FLOAT',
|
||||
'double' => 'FLOAT'
|
||||
}
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,33 @@
|
||||
# ==========================================
|
||||
# CMock Project - Automatic Mock Generation for C
|
||||
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
# [Released under MIT License. Please refer to license.txt for details]
|
||||
# ==========================================
|
||||
|
||||
class CMockFileWriter
|
||||
|
||||
attr_reader :config
|
||||
|
||||
def initialize(config)
|
||||
@config = config
|
||||
end
|
||||
|
||||
def create_file(filename)
|
||||
raise "Where's the block of data to create?" unless block_given?
|
||||
full_file_name_temp = "#{@config.mock_path}/#{filename}.new"
|
||||
full_file_name_done = "#{@config.mock_path}/#{filename}"
|
||||
File.open(full_file_name_temp, 'w') do |file|
|
||||
yield(file, filename)
|
||||
end
|
||||
update_file(full_file_name_done, full_file_name_temp)
|
||||
end
|
||||
|
||||
private ###################################
|
||||
|
||||
def update_file(dest, src)
|
||||
require 'fileutils'
|
||||
FileUtils.rm(dest) if (File.exist?(dest))
|
||||
FileUtils.cp(src, dest)
|
||||
FileUtils.rm(src)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,194 @@
|
||||
# ==========================================
|
||||
# CMock Project - Automatic Mock Generation for C
|
||||
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
# [Released under MIT License. Please refer to license.txt for details]
|
||||
# ==========================================
|
||||
|
||||
$here = File.dirname __FILE__
|
||||
|
||||
class CMockGenerator
|
||||
|
||||
attr_accessor :config, :file_writer, :module_name, :mock_name, :utils, :plugins, :ordered
|
||||
|
||||
def initialize(config, file_writer, utils, plugins)
|
||||
@file_writer = file_writer
|
||||
@utils = utils
|
||||
@plugins = plugins
|
||||
@config = config
|
||||
@prefix = @config.mock_prefix
|
||||
@ordered = @config.enforce_strict_ordering
|
||||
@framework = @config.framework.to_s
|
||||
|
||||
@includes_h_pre_orig_header = (@config.includes || @config.includes_h_pre_orig_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""}
|
||||
@includes_h_post_orig_header = (@config.includes_h_post_orig_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""}
|
||||
@includes_c_pre_header = (@config.includes_c_pre_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""}
|
||||
@includes_c_post_header = (@config.includes_c_post_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""}
|
||||
end
|
||||
|
||||
def create_mock(module_name, parsed_stuff)
|
||||
@module_name = module_name
|
||||
@mock_name = @prefix + @module_name
|
||||
create_mock_header_file(parsed_stuff)
|
||||
create_mock_source_file(parsed_stuff)
|
||||
end
|
||||
|
||||
private if $ThisIsOnlyATest.nil? ##############################
|
||||
|
||||
def create_mock_header_file(parsed_stuff)
|
||||
@file_writer.create_file(@mock_name + ".h") do |file, filename|
|
||||
create_mock_header_header(file, filename)
|
||||
create_mock_header_service_call_declarations(file)
|
||||
create_typedefs(file, parsed_stuff[:typedefs])
|
||||
parsed_stuff[:functions].each do |function|
|
||||
file << @plugins.run(:mock_function_declarations, function)
|
||||
end
|
||||
create_mock_header_footer(file)
|
||||
end
|
||||
end
|
||||
|
||||
def create_mock_source_file(parsed_stuff)
|
||||
@file_writer.create_file(@mock_name + ".c") do |file, filename|
|
||||
create_source_header_section(file, filename)
|
||||
create_instance_structure(file, parsed_stuff[:functions])
|
||||
create_extern_declarations(file)
|
||||
create_mock_verify_function(file, parsed_stuff[:functions])
|
||||
create_mock_init_function(file)
|
||||
create_mock_destroy_function(file, parsed_stuff[:functions])
|
||||
parsed_stuff[:functions].each do |function|
|
||||
create_mock_implementation(file, function)
|
||||
create_mock_interfaces(file, function)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create_mock_header_header(file, filename)
|
||||
define_name = filename.gsub(/\.h/, "_h").upcase
|
||||
orig_filename = filename.gsub(@config.mock_prefix, "")
|
||||
file << "/* AUTOGENERATED FILE. DO NOT EDIT. */\n"
|
||||
file << "#ifndef _#{define_name}\n"
|
||||
file << "#define _#{define_name}\n\n"
|
||||
@includes_h_pre_orig_header.each {|inc| file << "#include #{inc}\n"}
|
||||
file << "#include \"#{orig_filename}\"\n"
|
||||
@includes_h_post_orig_header.each {|inc| file << "#include #{inc}\n"}
|
||||
plugin_includes = @plugins.run(:include_files)
|
||||
file << plugin_includes if (!plugin_includes.empty?)
|
||||
file << "\n"
|
||||
end
|
||||
|
||||
def create_typedefs(file, typedefs)
|
||||
file << "\n"
|
||||
typedefs.each {|typedef| file << "#{typedef}\n" }
|
||||
file << "\n\n"
|
||||
end
|
||||
|
||||
def create_mock_header_service_call_declarations(file)
|
||||
file << "void #{@mock_name}_Init(void);\n"
|
||||
file << "void #{@mock_name}_Destroy(void);\n"
|
||||
file << "void #{@mock_name}_Verify(void);\n\n"
|
||||
end
|
||||
|
||||
def create_mock_header_footer(header)
|
||||
header << "\n#endif\n"
|
||||
end
|
||||
|
||||
def create_source_header_section(file, filename)
|
||||
header_file = filename.gsub(".c",".h")
|
||||
file << "/* AUTOGENERATED FILE. DO NOT EDIT. */\n"
|
||||
file << "#include <string.h>\n"
|
||||
file << "#include <stdlib.h>\n"
|
||||
file << "#include <setjmp.h>\n"
|
||||
file << "#include \"#{@framework}.h\"\n"
|
||||
file << "#include \"cmock.h\"\n"
|
||||
@includes_c_pre_header.each {|inc| file << "#include #{inc}\n"}
|
||||
file << "#include \"#{header_file}\"\n"
|
||||
@includes_c_post_header.each {|inc| file << "#include #{inc}\n"}
|
||||
file << "\n"
|
||||
end
|
||||
|
||||
def create_instance_structure(file, functions)
|
||||
functions.each do |function|
|
||||
file << "typedef struct _CMOCK_#{function[:name]}_CALL_INSTANCE\n{\n"
|
||||
file << " UNITY_LINE_TYPE LineNumber;\n"
|
||||
file << @plugins.run(:instance_typedefs, function)
|
||||
file << "\n} CMOCK_#{function[:name]}_CALL_INSTANCE;\n\n"
|
||||
end
|
||||
file << "static struct #{@mock_name}Instance\n{\n"
|
||||
if (functions.size == 0)
|
||||
file << " unsigned char placeHolder;\n"
|
||||
end
|
||||
functions.each do |function|
|
||||
file << @plugins.run(:instance_structure, function)
|
||||
file << " CMOCK_MEM_INDEX_TYPE #{function[:name]}_CallInstance;\n"
|
||||
end
|
||||
file << "} Mock;\n\n"
|
||||
end
|
||||
|
||||
def create_extern_declarations(file)
|
||||
file << "extern jmp_buf AbortFrame;\n"
|
||||
if (@ordered)
|
||||
file << "extern int GlobalExpectCount;\n"
|
||||
file << "extern int GlobalVerifyOrder;\n"
|
||||
end
|
||||
file << "\n"
|
||||
end
|
||||
|
||||
def create_mock_verify_function(file, functions)
|
||||
file << "void #{@mock_name}_Verify(void)\n{\n"
|
||||
verifications = functions.collect {|function| @plugins.run(:mock_verify, function)}.join
|
||||
file << " UNITY_LINE_TYPE cmock_line = TEST_LINE_NUM;\n" unless verifications.empty?
|
||||
file << verifications
|
||||
file << "}\n\n"
|
||||
end
|
||||
|
||||
def create_mock_init_function(file)
|
||||
file << "void #{@mock_name}_Init(void)\n{\n"
|
||||
file << " #{@mock_name}_Destroy();\n"
|
||||
file << "}\n\n"
|
||||
end
|
||||
|
||||
def create_mock_destroy_function(file, functions)
|
||||
file << "void #{@mock_name}_Destroy(void)\n{\n"
|
||||
file << " CMock_Guts_MemFreeAll();\n"
|
||||
file << " memset(&Mock, 0, sizeof(Mock));\n"
|
||||
file << functions.collect {|function| @plugins.run(:mock_destroy, function)}.join
|
||||
if (@ordered)
|
||||
file << " GlobalExpectCount = 0;\n"
|
||||
file << " GlobalVerifyOrder = 0;\n"
|
||||
end
|
||||
file << "}\n\n"
|
||||
end
|
||||
|
||||
def create_mock_implementation(file, function)
|
||||
# prepare return value and arguments
|
||||
function_mod_and_rettype = (function[:modifier].empty? ? '' : "#{function[:modifier]} ") +
|
||||
(function[:return][:type]) +
|
||||
(function[:c_calling_convention] ? " #{function[:c_calling_convention]}" : '')
|
||||
args_string = function[:args_string]
|
||||
args_string += (", " + function[:var_arg]) unless (function[:var_arg].nil?)
|
||||
|
||||
# Create mock function
|
||||
file << "#{function_mod_and_rettype} #{function[:name]}(#{args_string})\n"
|
||||
file << "{\n"
|
||||
file << " UNITY_LINE_TYPE cmock_line = TEST_LINE_NUM;\n"
|
||||
file << " CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance = (CMOCK_#{function[:name]}_CALL_INSTANCE*)CMock_Guts_GetAddressFor(Mock.#{function[:name]}_CallInstance);\n"
|
||||
file << " Mock.#{function[:name]}_CallInstance = CMock_Guts_MemNext(Mock.#{function[:name]}_CallInstance);\n"
|
||||
file << @plugins.run(:mock_implementation_precheck, function)
|
||||
file << " UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, \"Function '#{function[:name]}' called more times than expected.\");\n"
|
||||
file << " cmock_line = cmock_call_instance->LineNumber;\n"
|
||||
if (@ordered)
|
||||
file << " if (cmock_call_instance->CallOrder > ++GlobalVerifyOrder)\n"
|
||||
file << " UNITY_TEST_FAIL(cmock_line, \"Function '#{function[:name]}' called earlier than expected.\");\n"
|
||||
file << " if (cmock_call_instance->CallOrder < GlobalVerifyOrder)\n"
|
||||
file << " UNITY_TEST_FAIL(cmock_line, \"Function '#{function[:name]}' called later than expected.\");\n"
|
||||
# file << " UNITY_TEST_ASSERT((cmock_call_instance->CallOrder == ++GlobalVerifyOrder), cmock_line, \"Out of order function calls. Function '#{function[:name]}'\");\n"
|
||||
end
|
||||
file << @plugins.run(:mock_implementation, function)
|
||||
file << " return cmock_call_instance->ReturnVal;\n" unless (function[:return][:void?])
|
||||
file << "}\n\n"
|
||||
end
|
||||
|
||||
def create_mock_interfaces(file, function)
|
||||
file << @utils.code_add_argument_loader(function)
|
||||
file << @plugins.run(:mock_interfaces, function)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,57 @@
|
||||
# ==========================================
|
||||
# CMock Project - Automatic Mock Generation for C
|
||||
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
# [Released under MIT License. Please refer to license.txt for details]
|
||||
# ==========================================
|
||||
|
||||
class CMockGeneratorPluginArray
|
||||
|
||||
attr_reader :priority
|
||||
attr_accessor :config, :utils, :unity_helper, :ordered
|
||||
def initialize(config, utils)
|
||||
@config = config
|
||||
@ptr_handling = @config.when_ptr
|
||||
@ordered = @config.enforce_strict_ordering
|
||||
@utils = utils
|
||||
@unity_helper = @utils.helpers[:unity_helper]
|
||||
@priority = 8
|
||||
end
|
||||
|
||||
def instance_typedefs(function)
|
||||
function[:args].inject("") do |all, arg|
|
||||
(arg[:ptr?]) ? all + " int Expected_#{arg[:name]}_Depth;\n" : all
|
||||
end
|
||||
end
|
||||
|
||||
def mock_function_declarations(function)
|
||||
return nil unless function[:contains_ptr?]
|
||||
args_call = function[:args].map{|m| m[:ptr?] ? "#{m[:name]}, #{m[:name]}_Depth" : "#{m[:name]}"}.join(', ')
|
||||
args_string = function[:args].map{|m| m[:ptr?] ? "#{m[:type]} #{m[:name]}, int #{m[:name]}_Depth" : "#{m[:type]} #{m[:name]}"}.join(', ')
|
||||
if (function[:return][:void?])
|
||||
return "#define #{function[:name]}_ExpectWithArray(#{args_call}) #{function[:name]}_CMockExpectWithArray(__LINE__, #{args_call})\n" +
|
||||
"void #{function[:name]}_CMockExpectWithArray(UNITY_LINE_TYPE cmock_line, #{args_string});\n"
|
||||
else
|
||||
return "#define #{function[:name]}_ExpectWithArrayAndReturn(#{args_call}, cmock_retval) #{function[:name]}_CMockExpectWithArrayAndReturn(__LINE__, #{args_call}, cmock_retval)\n" +
|
||||
"void #{function[:name]}_CMockExpectWithArrayAndReturn(UNITY_LINE_TYPE cmock_line, #{args_string}, #{function[:return][:str]});\n"
|
||||
end
|
||||
end
|
||||
|
||||
def mock_interfaces(function)
|
||||
return nil unless function[:contains_ptr?]
|
||||
lines = []
|
||||
func_name = function[:name]
|
||||
args_string = function[:args].map{|m| m[:ptr?] ? "#{m[:type]} #{m[:name]}, int #{m[:name]}_Depth" : "#{m[:type]} #{m[:name]}"}.join(', ')
|
||||
call_string = function[:args].map{|m| m[:ptr?] ? "#{m[:name]}, #{m[:name]}_Depth" : m[:name]}.join(', ')
|
||||
if (function[:return][:void?])
|
||||
lines << "void #{func_name}_CMockExpectWithArray(UNITY_LINE_TYPE cmock_line, #{args_string})\n"
|
||||
else
|
||||
lines << "void #{func_name}_CMockExpectWithArrayAndReturn(UNITY_LINE_TYPE cmock_line, #{args_string}, #{function[:return][:str]})\n"
|
||||
end
|
||||
lines << "{\n"
|
||||
lines << @utils.code_add_base_expectation(func_name)
|
||||
lines << " CMockExpectParameters_#{func_name}(cmock_call_instance, #{call_string});\n"
|
||||
lines << " cmock_call_instance->ReturnVal = cmock_to_return;\n" unless (function[:return][:void?])
|
||||
lines << "}\n\n"
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,78 @@
|
||||
# ==========================================
|
||||
# CMock Project - Automatic Mock Generation for C
|
||||
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
# [Released under MIT License. Please refer to license.txt for details]
|
||||
# ==========================================
|
||||
|
||||
class CMockGeneratorPluginCallback
|
||||
|
||||
attr_accessor :include_count
|
||||
attr_reader :priority
|
||||
attr_reader :config, :utils
|
||||
|
||||
def initialize(config, utils)
|
||||
@config = config
|
||||
@utils = utils
|
||||
@priority = 6
|
||||
|
||||
@include_count = @config.callback_include_count
|
||||
if (@config.callback_after_arg_check)
|
||||
alias :mock_implementation :mock_implementation_for_callbacks
|
||||
alias :mock_implementation_precheck :nothing
|
||||
else
|
||||
alias :mock_implementation_precheck :mock_implementation_for_callbacks
|
||||
alias :mock_implementation :nothing
|
||||
end
|
||||
end
|
||||
|
||||
def instance_structure(function)
|
||||
func_name = function[:name]
|
||||
" CMOCK_#{func_name}_CALLBACK #{func_name}_CallbackFunctionPointer;\n" +
|
||||
" int #{func_name}_CallbackCalls;\n"
|
||||
end
|
||||
|
||||
def mock_function_declarations(function)
|
||||
func_name = function[:name]
|
||||
return_type = function[:return][:const?] ? "const #{function[:return][:type]}" : function[:return][:type]
|
||||
style = (@include_count ? 1 : 0) | (function[:args].empty? ? 0 : 2)
|
||||
styles = [ "void", "int cmock_num_calls", function[:args_string], "#{function[:args_string]}, int cmock_num_calls" ]
|
||||
"typedef #{return_type} (* CMOCK_#{func_name}_CALLBACK)(#{styles[style]});\nvoid #{func_name}_StubWithCallback(CMOCK_#{func_name}_CALLBACK Callback);\n"
|
||||
end
|
||||
|
||||
def mock_implementation_for_callbacks(function)
|
||||
func_name = function[:name]
|
||||
style = (@include_count ? 1 : 0) | (function[:args].empty? ? 0 : 2) | (function[:return][:void?] ? 0 : 4)
|
||||
" if (Mock.#{func_name}_CallbackFunctionPointer != NULL)\n {\n" +
|
||||
case(style)
|
||||
when 0 then " Mock.#{func_name}_CallbackFunctionPointer();\n return;\n }\n"
|
||||
when 1 then " Mock.#{func_name}_CallbackFunctionPointer(Mock.#{func_name}_CallbackCalls++);\n return;\n }\n"
|
||||
when 2 then " Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')});\n return;\n }\n"
|
||||
when 3 then " Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')}, Mock.#{func_name}_CallbackCalls++);\n return;\n }\n"
|
||||
when 4 then " return Mock.#{func_name}_CallbackFunctionPointer();\n }\n"
|
||||
when 5 then " return Mock.#{func_name}_CallbackFunctionPointer(Mock.#{func_name}_CallbackCalls++);\n }\n"
|
||||
when 6 then " return Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')});\n }\n"
|
||||
when 7 then " return Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')}, Mock.#{func_name}_CallbackCalls++);\n }\n"
|
||||
end
|
||||
end
|
||||
|
||||
def nothing(function)
|
||||
return ""
|
||||
end
|
||||
|
||||
def mock_interfaces(function)
|
||||
func_name = function[:name]
|
||||
"void #{func_name}_StubWithCallback(CMOCK_#{func_name}_CALLBACK Callback)\n{\n" +
|
||||
" Mock.#{func_name}_CallbackFunctionPointer = Callback;\n}\n\n"
|
||||
end
|
||||
|
||||
def mock_destroy(function)
|
||||
" Mock.#{function[:name]}_CallbackFunctionPointer = NULL;\n" +
|
||||
" Mock.#{function[:name]}_CallbackCalls = 0;\n"
|
||||
end
|
||||
|
||||
def mock_verify(function)
|
||||
func_name = function[:name]
|
||||
" if (Mock.#{func_name}_CallbackFunctionPointer != NULL)\n Mock.#{func_name}_CallInstance = CMOCK_GUTS_NONE;\n"
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,51 @@
|
||||
# ==========================================
|
||||
# CMock Project - Automatic Mock Generation for C
|
||||
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
# [Released under MIT License. Please refer to license.txt for details]
|
||||
# ==========================================
|
||||
|
||||
class CMockGeneratorPluginCexception
|
||||
|
||||
attr_reader :priority
|
||||
attr_reader :config, :utils
|
||||
|
||||
def initialize(config, utils)
|
||||
@config = config
|
||||
@utils = utils
|
||||
@priority = 7
|
||||
end
|
||||
|
||||
def include_files
|
||||
return "#include \"CException.h\"\n"
|
||||
end
|
||||
|
||||
def instance_typedefs(function)
|
||||
" CEXCEPTION_T ExceptionToThrow;\n"
|
||||
end
|
||||
|
||||
def mock_function_declarations(function)
|
||||
if (function[:args_string] == "void")
|
||||
return "#define #{function[:name]}_ExpectAndThrow(cmock_to_throw) #{function[:name]}_CMockExpectAndThrow(__LINE__, cmock_to_throw)\n" +
|
||||
"void #{function[:name]}_CMockExpectAndThrow(UNITY_LINE_TYPE cmock_line, CEXCEPTION_T cmock_to_throw);\n"
|
||||
else
|
||||
return "#define #{function[:name]}_ExpectAndThrow(#{function[:args_call]}, cmock_to_throw) #{function[:name]}_CMockExpectAndThrow(__LINE__, #{function[:args_call]}, cmock_to_throw)\n" +
|
||||
"void #{function[:name]}_CMockExpectAndThrow(UNITY_LINE_TYPE cmock_line, #{function[:args_string]}, CEXCEPTION_T cmock_to_throw);\n"
|
||||
end
|
||||
end
|
||||
|
||||
def mock_implementation(function)
|
||||
" if (cmock_call_instance->ExceptionToThrow != CEXCEPTION_NONE)\n {\n" +
|
||||
" Throw(cmock_call_instance->ExceptionToThrow);\n }\n"
|
||||
end
|
||||
|
||||
def mock_interfaces(function)
|
||||
arg_insert = (function[:args_string] == "void") ? "" : "#{function[:args_string]}, "
|
||||
call_string = function[:args].map{|m| m[:name]}.join(', ')
|
||||
[ "void #{function[:name]}_CMockExpectAndThrow(UNITY_LINE_TYPE cmock_line, #{arg_insert}CEXCEPTION_T cmock_to_throw)\n{\n",
|
||||
@utils.code_add_base_expectation(function[:name]),
|
||||
@utils.code_call_argument_loader(function),
|
||||
" cmock_call_instance->ExceptionToThrow = cmock_to_throw;\n",
|
||||
"}\n\n" ].join
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,86 @@
|
||||
# ==========================================
|
||||
# CMock Project - Automatic Mock Generation for C
|
||||
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
# [Released under MIT License. Please refer to license.txt for details]
|
||||
# ==========================================
|
||||
|
||||
class CMockGeneratorPluginExpect
|
||||
|
||||
attr_reader :priority
|
||||
attr_accessor :config, :utils, :unity_helper, :ordered
|
||||
|
||||
def initialize(config, utils)
|
||||
@config = config
|
||||
@ptr_handling = @config.when_ptr
|
||||
@ordered = @config.enforce_strict_ordering
|
||||
@utils = utils
|
||||
@unity_helper = @utils.helpers[:unity_helper]
|
||||
@priority = 5
|
||||
end
|
||||
|
||||
def instance_typedefs(function)
|
||||
lines = ""
|
||||
lines << " #{function[:return][:type]} ReturnVal;\n" unless (function[:return][:void?])
|
||||
lines << " int CallOrder;\n" if (@ordered)
|
||||
function[:args].each do |arg|
|
||||
lines << " #{arg[:type]} Expected_#{arg[:name]};\n"
|
||||
end
|
||||
lines
|
||||
end
|
||||
|
||||
def mock_function_declarations(function)
|
||||
if (function[:args].empty?)
|
||||
if (function[:return][:void?])
|
||||
return "#define #{function[:name]}_Expect() #{function[:name]}_CMockExpect(__LINE__)\n" +
|
||||
"void #{function[:name]}_CMockExpect(UNITY_LINE_TYPE cmock_line);\n"
|
||||
else
|
||||
return "#define #{function[:name]}_ExpectAndReturn(cmock_retval) #{function[:name]}_CMockExpectAndReturn(__LINE__, cmock_retval)\n" +
|
||||
"void #{function[:name]}_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]});\n"
|
||||
end
|
||||
else
|
||||
if (function[:return][:void?])
|
||||
return "#define #{function[:name]}_Expect(#{function[:args_call]}) #{function[:name]}_CMockExpect(__LINE__, #{function[:args_call]})\n" +
|
||||
"void #{function[:name]}_CMockExpect(UNITY_LINE_TYPE cmock_line, #{function[:args_string]});\n"
|
||||
else
|
||||
return "#define #{function[:name]}_ExpectAndReturn(#{function[:args_call]}, cmock_retval) #{function[:name]}_CMockExpectAndReturn(__LINE__, #{function[:args_call]}, cmock_retval)\n" +
|
||||
"void #{function[:name]}_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:args_string]}, #{function[:return][:str]});\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def mock_implementation(function)
|
||||
lines = ""
|
||||
function[:args].each do |arg|
|
||||
lines << @utils.code_verify_an_arg_expectation(function, arg)
|
||||
end
|
||||
lines
|
||||
end
|
||||
|
||||
def mock_interfaces(function)
|
||||
lines = ""
|
||||
func_name = function[:name]
|
||||
if (function[:return][:void?])
|
||||
if (function[:args_string] == "void")
|
||||
lines << "void #{func_name}_CMockExpect(UNITY_LINE_TYPE cmock_line)\n{\n"
|
||||
else
|
||||
lines << "void #{func_name}_CMockExpect(UNITY_LINE_TYPE cmock_line, #{function[:args_string]})\n{\n"
|
||||
end
|
||||
else
|
||||
if (function[:args_string] == "void")
|
||||
lines << "void #{func_name}_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]})\n{\n"
|
||||
else
|
||||
lines << "void #{func_name}_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:args_string]}, #{function[:return][:str]})\n{\n"
|
||||
end
|
||||
end
|
||||
lines << @utils.code_add_base_expectation(func_name)
|
||||
lines << @utils.code_call_argument_loader(function)
|
||||
lines << @utils.code_assign_argument_quickly("cmock_call_instance->ReturnVal", function[:return]) unless (function[:return][:void?])
|
||||
lines << "}\n\n"
|
||||
end
|
||||
|
||||
def mock_verify(function)
|
||||
func_name = function[:name]
|
||||
" UNITY_TEST_ASSERT(CMOCK_GUTS_NONE == Mock.#{func_name}_CallInstance, cmock_line, \"Function '#{func_name}' called less times than expected.\");\n"
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,95 @@
|
||||
# ==========================================
|
||||
# CMock Project - Automatic Mock Generation for C
|
||||
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
# [Released under MIT License. Please refer to license.txt for details]
|
||||
# ==========================================
|
||||
|
||||
class CMockGeneratorPluginIgnore
|
||||
|
||||
attr_reader :priority
|
||||
attr_reader :config, :utils
|
||||
|
||||
def initialize(config, utils)
|
||||
@config = config
|
||||
if (@config.ignore == :args_and_calls)
|
||||
alias :mock_implementation_precheck :mock_implementation_for_ignores
|
||||
alias :mock_implementation :nothing
|
||||
alias :mock_verify :mock_conditionally_verify_counts
|
||||
else
|
||||
alias :mock_implementation :mock_implementation_for_ignores
|
||||
alias :mock_implementation_precheck :nothing
|
||||
alias :mock_verify :nothing
|
||||
end
|
||||
@utils = utils
|
||||
@priority = 2
|
||||
end
|
||||
|
||||
def instance_structure(function)
|
||||
if (function[:return][:void?])
|
||||
" int #{function[:name]}_IgnoreBool;\n"
|
||||
else
|
||||
" int #{function[:name]}_IgnoreBool;\n #{function[:return][:type]} #{function[:name]}_FinalReturn;\n"
|
||||
end
|
||||
end
|
||||
|
||||
def mock_function_declarations(function)
|
||||
if (function[:return][:void?])
|
||||
if (@config.ignore == :args_only)
|
||||
return "#define #{function[:name]}_Ignore() #{function[:name]}_CMockIgnore(__LINE__)\n" +
|
||||
"void #{function[:name]}_CMockIgnore(UNITY_LINE_TYPE cmock_line);\n"
|
||||
else
|
||||
return "#define #{function[:name]}_Ignore() #{function[:name]}_CMockIgnore()\n" +
|
||||
"void #{function[:name]}_CMockIgnore(void);\n"
|
||||
end
|
||||
else
|
||||
return "#define #{function[:name]}_IgnoreAndReturn(cmock_retval) #{function[:name]}_CMockIgnoreAndReturn(__LINE__, cmock_retval)\n" +
|
||||
"void #{function[:name]}_CMockIgnoreAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]});\n"
|
||||
end
|
||||
end
|
||||
|
||||
def mock_implementation_for_ignores(function)
|
||||
lines = " if (Mock.#{function[:name]}_IgnoreBool)\n {\n"
|
||||
if (function[:return][:void?])
|
||||
lines << " return;\n }\n"
|
||||
else
|
||||
retval = function[:return].merge( { :name => "cmock_call_instance->ReturnVal"} )
|
||||
lines << " if (cmock_call_instance == NULL)\n return Mock.#{function[:name]}_FinalReturn;\n"
|
||||
lines << " " + @utils.code_assign_argument_quickly("Mock.#{function[:name]}_FinalReturn", retval) unless (retval[:void?])
|
||||
lines << " return cmock_call_instance->ReturnVal;\n }\n"
|
||||
end
|
||||
lines
|
||||
end
|
||||
|
||||
def mock_interfaces(function)
|
||||
lines = ""
|
||||
args_only = (@config.ignore == :args_only)
|
||||
if (function[:return][:void?])
|
||||
if (args_only)
|
||||
lines << "void #{function[:name]}_CMockIgnore(UNITY_LINE_TYPE cmock_line)\n{\n"
|
||||
else
|
||||
lines << "void #{function[:name]}_CMockIgnore(void)\n{\n"
|
||||
end
|
||||
else
|
||||
lines << "void #{function[:name]}_CMockIgnoreAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]})\n{\n"
|
||||
end
|
||||
if (args_only)
|
||||
lines << @utils.code_add_base_expectation(function[:name], true)
|
||||
elsif (!function[:return][:void?])
|
||||
lines << @utils.code_add_base_expectation(function[:name], false)
|
||||
end
|
||||
unless (function[:return][:void?])
|
||||
lines << " cmock_call_instance->ReturnVal = cmock_to_return;\n"
|
||||
end
|
||||
lines << " Mock.#{function[:name]}_IgnoreBool = (int)1;\n"
|
||||
lines << "}\n\n"
|
||||
end
|
||||
|
||||
def mock_conditionally_verify_counts(function)
|
||||
func_name = function[:name]
|
||||
" if (Mock.#{func_name}_IgnoreBool)\n Mock.#{func_name}_CallInstance = CMOCK_GUTS_NONE;\n"
|
||||
end
|
||||
|
||||
def nothing(function)
|
||||
return ""
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,177 @@
|
||||
# ==========================================
|
||||
# CMock Project - Automatic Mock Generation for C
|
||||
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
# [Released under MIT License. Please refer to license.txt for details]
|
||||
# ==========================================
|
||||
|
||||
class CMockGeneratorUtils
|
||||
|
||||
attr_accessor :config, :helpers, :ordered, :ptr_handling, :arrays, :cexception
|
||||
|
||||
def initialize(config, helpers={})
|
||||
@config = config
|
||||
@ptr_handling = @config.when_ptr
|
||||
@ordered = @config.enforce_strict_ordering
|
||||
@arrays = @config.plugins.include? :array
|
||||
@cexception = @config.plugins.include? :cexception
|
||||
@treat_as = @config.treat_as
|
||||
@helpers = helpers
|
||||
|
||||
if (@arrays)
|
||||
case(@ptr_handling)
|
||||
when :smart then alias :code_verify_an_arg_expectation :code_verify_an_arg_expectation_with_smart_arrays
|
||||
when :compare_data then alias :code_verify_an_arg_expectation :code_verify_an_arg_expectation_with_normal_arrays
|
||||
when :compare_ptr then raise "ERROR: the array plugin doesn't enjoy working with :compare_ptr only. Disable one option."
|
||||
end
|
||||
else
|
||||
alias :code_verify_an_arg_expectation :code_verify_an_arg_expectation_with_no_arrays
|
||||
end
|
||||
end
|
||||
|
||||
def code_add_base_expectation(func_name, global_ordering_supported=true)
|
||||
lines = " CMOCK_MEM_INDEX_TYPE cmock_guts_index = CMock_Guts_MemNew(sizeof(CMOCK_#{func_name}_CALL_INSTANCE));\n"
|
||||
lines << " CMOCK_#{func_name}_CALL_INSTANCE* cmock_call_instance = (CMOCK_#{func_name}_CALL_INSTANCE*)CMock_Guts_GetAddressFor(cmock_guts_index);\n"
|
||||
lines << " UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, \"CMock has run out of memory. Please allocate more.\");\n"
|
||||
lines << " Mock.#{func_name}_CallInstance = CMock_Guts_MemChain(Mock.#{func_name}_CallInstance, cmock_guts_index);\n"
|
||||
lines << " cmock_call_instance->LineNumber = cmock_line;\n"
|
||||
lines << " cmock_call_instance->CallOrder = ++GlobalExpectCount;\n" if (@ordered and global_ordering_supported)
|
||||
lines << " cmock_call_instance->ExceptionToThrow = CEXCEPTION_NONE;\n" if (@cexception)
|
||||
lines
|
||||
end
|
||||
|
||||
def code_add_an_arg_expectation(arg, depth=1)
|
||||
lines = code_assign_argument_quickly("cmock_call_instance->Expected_#{arg[:name]}", arg)
|
||||
lines << " cmock_call_instance->Expected_#{arg[:name]}_Depth = #{arg[:name]}_Depth;\n" if (@arrays and (depth.class == String))
|
||||
lines
|
||||
end
|
||||
|
||||
def code_assign_argument_quickly(dest, arg)
|
||||
if (arg[:ptr?] or @treat_as.include?(arg[:type]))
|
||||
" #{dest} = #{arg[:const?] ? "(#{arg[:type]})" : ''}#{arg[:name]};\n"
|
||||
else
|
||||
" memcpy(&#{dest}, &#{arg[:name]}, sizeof(#{arg[:type]}));\n"
|
||||
end
|
||||
end
|
||||
|
||||
def code_add_argument_loader(function)
|
||||
if (function[:args_string] != "void")
|
||||
if (@arrays)
|
||||
args_string = function[:args].map do |m|
|
||||
const_str = m[ :const? ] ? 'const ' : ''
|
||||
m[:ptr?] ? "#{const_str}#{m[:type]} #{m[:name]}, int #{m[:name]}_Depth" : "#{const_str}#{m[:type]} #{m[:name]}"
|
||||
end.join(', ')
|
||||
"void CMockExpectParameters_#{function[:name]}(CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance, #{args_string})\n{\n" +
|
||||
function[:args].inject("") { |all, arg| all + code_add_an_arg_expectation(arg, (arg[:ptr?] ? "#{arg[:name]}_Depth" : 1) ) } +
|
||||
"}\n\n"
|
||||
else
|
||||
"void CMockExpectParameters_#{function[:name]}(CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance, #{function[:args_string]})\n{\n" +
|
||||
function[:args].inject("") { |all, arg| all + code_add_an_arg_expectation(arg) } +
|
||||
"}\n\n"
|
||||
end
|
||||
else
|
||||
""
|
||||
end
|
||||
end
|
||||
|
||||
def code_call_argument_loader(function)
|
||||
if (function[:args_string] != "void")
|
||||
args = function[:args].map do |m|
|
||||
(@arrays and m[:ptr?]) ? "#{m[:name]}, 1" : m[:name]
|
||||
end
|
||||
" CMockExpectParameters_#{function[:name]}(cmock_call_instance, #{args.join(', ')});\n"
|
||||
else
|
||||
""
|
||||
end
|
||||
end
|
||||
|
||||
#private ######################
|
||||
|
||||
def lookup_expect_type(function, arg)
|
||||
c_type = arg[:type]
|
||||
arg_name = arg[:name]
|
||||
expected = "cmock_call_instance->Expected_#{arg_name}"
|
||||
unity_func = if ((arg[:ptr?]) and ((c_type =~ /\*\*/) or (@ptr_handling == :compare_ptr)))
|
||||
['UNITY_TEST_ASSERT_EQUAL_PTR', '']
|
||||
else
|
||||
(@helpers.nil? or @helpers[:unity_helper].nil?) ? ["UNITY_TEST_ASSERT_EQUAL",''] : @helpers[:unity_helper].get_helper(c_type)
|
||||
end
|
||||
unity_msg = "Function '#{function[:name]}' called with unexpected value for argument '#{arg_name}'."
|
||||
return c_type, arg_name, expected, unity_func[0], unity_func[1], unity_msg
|
||||
end
|
||||
|
||||
def code_verify_an_arg_expectation_with_no_arrays(function, arg)
|
||||
c_type, arg_name, expected, unity_func, pre, unity_msg = lookup_expect_type(function, arg)
|
||||
case(unity_func)
|
||||
when "UNITY_TEST_ASSERT_EQUAL_MEMORY"
|
||||
c_type_local = c_type.gsub(/\*$/,'')
|
||||
return " UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type_local}), cmock_line, \"#{unity_msg}\");\n"
|
||||
when "UNITY_TEST_ASSERT_EQUAL_MEMORY"
|
||||
[ " if (#{pre}#{expected} == NULL)",
|
||||
" { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, \"Expected NULL. #{unity_msg}\"); }",
|
||||
" else",
|
||||
" { UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*','')}), cmock_line, \"#{unity_msg}\"); }\n"].join("\n")
|
||||
when /_ARRAY/
|
||||
[ " if (#{pre}#{expected} == NULL)",
|
||||
" { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, \"Expected NULL. #{unity_msg}\"); }",
|
||||
" else",
|
||||
" { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, 1, cmock_line, \"#{unity_msg}\"); }\n"].join("\n")
|
||||
else
|
||||
return " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, \"#{unity_msg}\");\n"
|
||||
end
|
||||
end
|
||||
|
||||
def code_verify_an_arg_expectation_with_normal_arrays(function, arg)
|
||||
c_type, arg_name, expected, unity_func, pre, unity_msg = lookup_expect_type(function, arg)
|
||||
depth_name = (arg[:ptr?]) ? "cmock_call_instance->Expected_#{arg_name}_Depth" : 1
|
||||
case(unity_func)
|
||||
when "UNITY_TEST_ASSERT_EQUAL_MEMORY"
|
||||
c_type_local = c_type.gsub(/\*$/,'')
|
||||
return " UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type_local}), cmock_line, \"#{unity_msg}\");\n"
|
||||
when "UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY"
|
||||
[ " if (#{pre}#{expected} == NULL)",
|
||||
" { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, \"Expected NULL. #{unity_msg}\"); }",
|
||||
" else",
|
||||
" { UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*','')}), #{depth_name}, cmock_line, \"#{unity_msg}\"); }\n"].compact.join("\n")
|
||||
when /_ARRAY/
|
||||
if (pre == '&')
|
||||
" #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, \"#{unity_msg}\");\n"
|
||||
else
|
||||
[ " if (#{pre}#{expected} == NULL)",
|
||||
" { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, \"Expected NULL. #{unity_msg}\"); }",
|
||||
" else",
|
||||
" { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, \"#{unity_msg}\"); }\n"].compact.join("\n")
|
||||
end
|
||||
else
|
||||
return " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, \"#{unity_msg}\");\n"
|
||||
end
|
||||
end
|
||||
|
||||
def code_verify_an_arg_expectation_with_smart_arrays(function, arg)
|
||||
c_type, arg_name, expected, unity_func, pre, unity_msg = lookup_expect_type(function, arg)
|
||||
depth_name = (arg[:ptr?]) ? "cmock_call_instance->Expected_#{arg_name}_Depth" : 1
|
||||
case(unity_func)
|
||||
when "UNITY_TEST_ASSERT_EQUAL_MEMORY"
|
||||
c_type_local = c_type.gsub(/\*$/,'')
|
||||
return " UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type_local}), cmock_line, \"#{unity_msg}\");\n"
|
||||
when "UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY"
|
||||
[ " if (#{pre}#{expected} == NULL)",
|
||||
" { UNITY_TEST_ASSERT_NULL(#{arg_name}, cmock_line, \"Expected NULL. #{unity_msg}\"); }",
|
||||
((depth_name != 1) ? " else if (#{depth_name} == 0)\n { UNITY_TEST_ASSERT_EQUAL_PTR(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, \"#{unity_msg}\"); }" : nil),
|
||||
" else",
|
||||
" { UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*','')}), #{depth_name}, cmock_line, \"#{unity_msg}\"); }\n"].compact.join("\n")
|
||||
when /_ARRAY/
|
||||
if (pre == '&')
|
||||
" #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, \"#{unity_msg}\");\n"
|
||||
else
|
||||
[ " if (#{pre}#{expected} == NULL)",
|
||||
" { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, \"Expected NULL. #{unity_msg}\"); }",
|
||||
((depth_name != 1) ? " else if (#{depth_name} == 0)\n { UNITY_TEST_ASSERT_EQUAL_PTR(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, \"#{unity_msg}\"); }" : nil),
|
||||
" else",
|
||||
" { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, \"#{unity_msg}\"); }\n"].compact.join("\n")
|
||||
end
|
||||
else
|
||||
return " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, \"#{unity_msg}\");\n"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,277 @@
|
||||
# ==========================================
|
||||
# CMock Project - Automatic Mock Generation for C
|
||||
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
# [Released under MIT License. Please refer to license.txt for details]
|
||||
# ==========================================
|
||||
|
||||
class CMockHeaderParser
|
||||
|
||||
attr_accessor :funcs, :c_attributes, :treat_as_void, :treat_externs
|
||||
|
||||
def initialize(cfg)
|
||||
@funcs = []
|
||||
@c_strippables = cfg.strippables
|
||||
@c_attributes = (['const'] + cfg.attributes).uniq
|
||||
@c_calling_conventions = cfg.c_calling_conventions.uniq
|
||||
@treat_as_void = (['void'] + cfg.treat_as_void).uniq
|
||||
@declaration_parse_matcher = /([\d\w\s\*\(\),\[\]]+??)\(([\d\w\s\*\(\),\.\[\]+-]*)\)$/m
|
||||
@standards = (['int','short','char','long','unsigned','signed'] + cfg.treat_as.keys).uniq
|
||||
@when_no_prototypes = cfg.when_no_prototypes
|
||||
@local_as_void = @treat_as_void
|
||||
@verbosity = cfg.verbosity
|
||||
@treat_externs = cfg.treat_externs
|
||||
@c_strippables += ['extern'] if (@treat_externs == :include) #we'll need to remove the attribute if we're allowing externs
|
||||
end
|
||||
|
||||
def parse(name, source)
|
||||
@module_name = name.gsub(/\W/,'')
|
||||
@typedefs = []
|
||||
@funcs = []
|
||||
function_names = []
|
||||
|
||||
parse_functions( import_source(source) ).map do |decl|
|
||||
func = parse_declaration(decl)
|
||||
unless (function_names.include? func[:name])
|
||||
@funcs << func
|
||||
function_names << func[:name]
|
||||
end
|
||||
end
|
||||
|
||||
{ :includes => nil,
|
||||
:functions => @funcs,
|
||||
:typedefs => @typedefs
|
||||
}
|
||||
end
|
||||
|
||||
private if $ThisIsOnlyATest.nil? ################
|
||||
|
||||
def import_source(source)
|
||||
|
||||
# void must be void for cmock _ExpectAndReturn calls to process properly, not some weird typedef which equates to void
|
||||
# to a certain extent, this action assumes we're chewing on pre-processed header files, otherwise we'll most likely just get stuff from @treat_as_void
|
||||
@local_as_void = @treat_as_void
|
||||
void_types = source.scan(/typedef\s+(?:\(\s*)?void(?:\s*\))?\s+([\w\d]+)\s*;/)
|
||||
if void_types
|
||||
@local_as_void += void_types.flatten.uniq.compact
|
||||
end
|
||||
|
||||
# smush multiline macros into single line (checking for continuation character at end of line '\')
|
||||
source.gsub!(/\s*\\\s*/m, ' ')
|
||||
|
||||
#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)
|
||||
|
||||
# remove assembler pragma sections
|
||||
source.gsub!(/^\s*#\s*pragma\s+asm\s+.*?#\s*pragma\s+endasm/m, '')
|
||||
|
||||
# remove gcc's __attribute__ tags
|
||||
source.gsub(/__attrbute__\s*\(\(\.*\)\)/, '')
|
||||
|
||||
# remove preprocessor statements and extern "C"
|
||||
source.gsub!(/^\s*#.*/, '')
|
||||
source.gsub!(/extern\s+\"C\"\s+\{/, '')
|
||||
|
||||
# enums, unions, structs, and typedefs can all contain things (e.g. function pointers) that parse like function prototypes, so yank them
|
||||
# forward declared structs are removed before struct definitions so they don't mess up real thing later. we leave structs keywords in function prototypes
|
||||
source.gsub!(/^[\w\s]*struct[^;\{\}\(\)]+;/m, '') # remove forward declared structs
|
||||
source.gsub!(/^[\w\s]*(enum|union|struct|typepdef)[\w\s]*\{[^\}]+\}[\w\s\*\,]*;/m, '') # remove struct, union, and enum definitions and typedefs with braces
|
||||
source.gsub!(/(\W)(?:register|auto|static|restrict)(\W)/, '\1\2') # remove problem keywords
|
||||
source.gsub!(/\s*=\s*['"a-zA-Z0-9_\.]+\s*/, '') # remove default value statements from argument lists
|
||||
source.gsub!(/^(?:[\w\s]*\W)?typedef\W.*/, '') # remove typedef statements
|
||||
source.gsub!(/(^|\W+)(?:#{@c_strippables.join('|')})(?=$|\W+)/,'\1') unless @c_strippables.empty? # remove known attributes slated to be stripped
|
||||
|
||||
#scan for functions which return function pointers, because they are a pain
|
||||
source.gsub!(/([\w\s\*]+)\(*\(\s*\*([\w\s\*]+)\s*\(([\w\s\*,]*)\)\)\s*\(([\w\s\*,]*)\)\)*/) do |m|
|
||||
functype = "cmock_#{@module_name}_func_ptr#{@typedefs.size + 1}"
|
||||
@typedefs << "typedef #{$1.strip}(*#{functype})(#{$4});"
|
||||
"#{functype} #{$2.strip}(#{$3});"
|
||||
end
|
||||
|
||||
#drop extra white space to make the rest go faster
|
||||
source.gsub!(/^\s+/, '') # remove extra white space from beginning of line
|
||||
source.gsub!(/\s+$/, '') # remove extra white space from end of line
|
||||
source.gsub!(/\s*\(\s*/, '(') # remove extra white space from before left parens
|
||||
source.gsub!(/\s*\)\s*/, ')') # remove extra white space from before right parens
|
||||
source.gsub!(/\s+/, ' ') # remove remaining extra white space
|
||||
|
||||
#split lines on semicolons and remove things that are obviously not what we are looking for
|
||||
src_lines = source.split(/\s*;\s*/)
|
||||
src_lines.delete_if {|line| line.strip.length == 0} # remove blank lines
|
||||
src_lines.delete_if {|line| !(line =~ /[\w\s\*]+\(+\s*\*[\*\s]*[\w\s]+(?:\[[\w\s]*\]\s*)+\)+\s*\((?:[\w\s\*]*,?)*\s*\)/).nil?} #remove function pointer arrays
|
||||
if (@treat_externs == :include)
|
||||
src_lines.delete_if {|line| !(line =~ /(?:^|\s+)(?:inline)\s+/).nil?} # remove inline functions
|
||||
else
|
||||
src_lines.delete_if {|line| !(line =~ /(?:^|\s+)(?:extern|inline)\s+/).nil?} # remove inline and extern functions
|
||||
end
|
||||
end
|
||||
|
||||
def parse_functions(source)
|
||||
funcs = []
|
||||
source.each {|line| funcs << line.strip.gsub(/\s+/, ' ') if (line =~ @declaration_parse_matcher)}
|
||||
if funcs.empty?
|
||||
case @when_no_prototypes
|
||||
when :error
|
||||
raise "ERROR: No function prototypes found!"
|
||||
when :warn
|
||||
puts "WARNING: No function prototypes found!" unless (@verbosity < 1)
|
||||
end
|
||||
end
|
||||
return funcs
|
||||
end
|
||||
|
||||
def parse_args(arg_list)
|
||||
args = []
|
||||
arg_list.split(',').each do |arg|
|
||||
arg.strip!
|
||||
return args if (arg =~ /^\s*((\.\.\.)|(void))\s*$/) # we're done if we reach void by itself or ...
|
||||
arg_array = arg.split
|
||||
arg_elements = arg_array - @c_attributes # split up words and remove known attributes
|
||||
args << { :type => (arg_type =arg_elements[0..-2].join(' ')),
|
||||
:name => arg_elements[-1],
|
||||
:ptr? => divine_ptr(arg_type),
|
||||
:const? => arg_array.include?('const')
|
||||
}
|
||||
end
|
||||
return args
|
||||
end
|
||||
|
||||
def divine_ptr(arg_type)
|
||||
return false unless arg_type.include? '*'
|
||||
return false if arg_type.gsub(/(const|char|\*|\s)+/,'').empty?
|
||||
return true
|
||||
end
|
||||
|
||||
def clean_args(arg_list)
|
||||
if ((@local_as_void.include?(arg_list.strip)) or (arg_list.empty?))
|
||||
return 'void'
|
||||
else
|
||||
c=0
|
||||
arg_list.gsub!(/(\w+)(?:\s*\[[\s\d\w+-]*\])+/,'*\1') # magically turn brackets into asterisks
|
||||
arg_list.gsub!(/\s+\*/,'*') # remove space to place asterisks with type (where they belong)
|
||||
arg_list.gsub!(/\*(\w)/,'* \1') # pull asterisks away from arg to place asterisks with type (where they belong)
|
||||
|
||||
#scan argument list for function pointers and replace them with custom types
|
||||
arg_list.gsub!(/([\w\s\*]+)\(+\s*\*[\*\s]*([\w\s]*)\s*\)+\s*\(((?:[\w\s\*]*,?)*)\s*\)*/) do |m|
|
||||
|
||||
functype = "cmock_#{@module_name}_func_ptr#{@typedefs.size + 1}"
|
||||
funcret = $1.strip
|
||||
funcname = $2.strip
|
||||
funcargs = $3.strip
|
||||
funconst = ''
|
||||
if (funcname.include? 'const')
|
||||
funcname.gsub!('const','').strip!
|
||||
funconst = 'const '
|
||||
end
|
||||
@typedefs << "typedef #{funcret}(*#{functype})(#{funcargs});"
|
||||
funcname = "cmock_arg#{c+=1}" if (funcname.empty?)
|
||||
"#{functype} #{funconst}#{funcname}"
|
||||
end
|
||||
|
||||
#automatically name unnamed arguments (those that only had a type)
|
||||
arg_list.split(/\s*,\s*/).map { |arg|
|
||||
parts = (arg.split - ['struct', 'union', 'enum', 'const', 'const*'])
|
||||
if ((parts.size < 2) or (parts[-1][-1].chr == '*') or (@standards.include?(parts[-1])))
|
||||
"#{arg} cmock_arg#{c+=1}"
|
||||
else
|
||||
arg
|
||||
end
|
||||
}.join(', ')
|
||||
end
|
||||
end
|
||||
|
||||
def parse_declaration(declaration)
|
||||
decl = {}
|
||||
|
||||
regex_match = @declaration_parse_matcher.match(declaration)
|
||||
raise "Failed parsing function declaration: '#{declaration}'" if regex_match.nil?
|
||||
|
||||
#grab argument list
|
||||
args = regex_match[2].strip
|
||||
|
||||
#process function attributes, return type, and name
|
||||
descriptors = regex_match[1]
|
||||
descriptors.gsub!(/\s+\*/,'*') #remove space to place asterisks with return type (where they belong)
|
||||
descriptors.gsub!(/\*(\w)/,'* \1') #pull asterisks away from function name to place asterisks with return type (where they belong)
|
||||
descriptors = descriptors.split #array of all descriptor strings
|
||||
|
||||
#grab name
|
||||
decl[:name] = descriptors[-1] #snag name as last array item
|
||||
|
||||
#build attribute and return type strings
|
||||
decl[:modifier] = []
|
||||
rettype = []
|
||||
descriptors[0..-2].each do |word|
|
||||
if @c_attributes.include?(word)
|
||||
decl[:modifier] << word
|
||||
elsif @c_calling_conventions.include?(word)
|
||||
decl[:c_calling_convention] = word
|
||||
else
|
||||
rettype << word
|
||||
end
|
||||
end
|
||||
decl[:modifier] = decl[:modifier].join(' ')
|
||||
rettype = rettype.join(' ')
|
||||
rettype = 'void' if (@local_as_void.include?(rettype.strip))
|
||||
decl[:return] = { :type => rettype,
|
||||
:name => 'cmock_to_return',
|
||||
:ptr? => divine_ptr(rettype),
|
||||
:const? => rettype.split(/\s/).include?('const'),
|
||||
:str => "#{rettype} cmock_to_return",
|
||||
:void? => (rettype == 'void')
|
||||
}
|
||||
|
||||
#remove default argument statements from mock definitions
|
||||
args.gsub!(/=\s*[a-zA-Z0-9_\.]+\s*/, ' ')
|
||||
|
||||
#check for var args
|
||||
if (args =~ /\.\.\./)
|
||||
decl[:var_arg] = args.match( /[\w\s]*\.\.\./ ).to_s.strip
|
||||
if (args =~ /\,[\w\s]*\.\.\./)
|
||||
args = args.gsub!(/\,[\w\s]*\.\.\./,'')
|
||||
else
|
||||
args = 'void'
|
||||
end
|
||||
else
|
||||
decl[:var_arg] = nil
|
||||
end
|
||||
args = clean_args(args)
|
||||
decl[:args_string] = args
|
||||
decl[:args] = parse_args(args)
|
||||
decl[:args_call] = decl[:args].map{|a| a[:name]}.join(', ')
|
||||
decl[:contains_ptr?] = decl[:args].inject(false) {|ptr, arg| arg[:ptr?] ? true : ptr }
|
||||
|
||||
if (decl[:return][:type].nil? or decl[:name].nil? or decl[:args].nil? or
|
||||
decl[:return][:type].empty? or decl[:name].empty?)
|
||||
raise "Failed Parsing Declaration Prototype!\n" +
|
||||
" declaration: '#{declaration}'\n" +
|
||||
" modifier: '#{decl[:modifier]}'\n" +
|
||||
" return: #{prototype_inspect_hash(decl[:return])}\n" +
|
||||
" function: '#{decl[:name]}'\n" +
|
||||
" args: #{prototype_inspect_array_of_hashes(decl[:args])}\n"
|
||||
end
|
||||
|
||||
return decl
|
||||
end
|
||||
|
||||
def prototype_inspect_hash(hash)
|
||||
pairs = []
|
||||
hash.each_pair { |name, value| pairs << ":#{name} => #{"'" if (value.class == String)}#{value}#{"'" if (value.class == String)}" }
|
||||
return "{#{pairs.join(', ')}}"
|
||||
end
|
||||
|
||||
def prototype_inspect_array_of_hashes(array)
|
||||
hashes = []
|
||||
array.each { |hash| hashes << prototype_inspect_hash(hash) }
|
||||
case (array.size)
|
||||
when 0
|
||||
return "[]"
|
||||
when 1
|
||||
return "[#{hashes[0]}]"
|
||||
else
|
||||
return "[\n #{hashes.join("\n ")}\n ]\n"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,40 @@
|
||||
# ==========================================
|
||||
# CMock Project - Automatic Mock Generation for C
|
||||
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
# [Released under MIT License. Please refer to license.txt for details]
|
||||
# ==========================================
|
||||
|
||||
class CMockPluginManager
|
||||
|
||||
attr_accessor :plugins
|
||||
|
||||
def initialize(config, utils)
|
||||
@plugins = []
|
||||
plugins_to_load = [:expect, config.plugins].flatten.uniq.compact
|
||||
plugins_to_load.each do |plugin|
|
||||
plugin_name = plugin.to_s
|
||||
object_name = "CMockGeneratorPlugin" + camelize(plugin_name)
|
||||
begin
|
||||
unless (Object.const_defined? object_name)
|
||||
require "#{File.expand_path(File.dirname(__FILE__))}/cmock_generator_plugin_#{plugin_name.downcase}.rb"
|
||||
end
|
||||
@plugins << eval("#{object_name}.new(config, utils)")
|
||||
rescue
|
||||
raise "ERROR: CMock unable to load plugin '#{plugin_name}'"
|
||||
end
|
||||
end
|
||||
@plugins.sort! {|a,b| a.priority <=> b.priority }
|
||||
end
|
||||
|
||||
def run(method, args=nil)
|
||||
if args.nil?
|
||||
return @plugins.collect{ |plugin| plugin.send(method) if plugin.respond_to?(method) }.flatten.join
|
||||
else
|
||||
return @plugins.collect{ |plugin| plugin.send(method, args) if plugin.respond_to?(method) }.flatten.join
|
||||
end
|
||||
end
|
||||
|
||||
def camelize(lower_case_and_underscored_word)
|
||||
lower_case_and_underscored_word.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,75 @@
|
||||
# ==========================================
|
||||
# CMock Project - Automatic Mock Generation for C
|
||||
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
# [Released under MIT License. Please refer to license.txt for details]
|
||||
# ==========================================
|
||||
|
||||
class CMockUnityHelperParser
|
||||
|
||||
attr_accessor :c_types
|
||||
|
||||
def initialize(config)
|
||||
@config = config
|
||||
@fallback = @config.plugins.include?(:array) ? 'UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY' : 'UNITY_TEST_ASSERT_EQUAL_MEMORY'
|
||||
@c_types = map_C_types.merge(import_source)
|
||||
end
|
||||
|
||||
def get_helper(ctype)
|
||||
lookup = ctype.gsub(/(?:^|(\S?)(\s*)|(\W))const(?:$|(\s*)(\S)|(\W))/,'\1\3\5\6').strip.gsub(/\s+/,'_')
|
||||
return [@c_types[lookup], ''] if (@c_types[lookup])
|
||||
if (lookup =~ /\*$/)
|
||||
lookup = lookup.gsub(/\*$/,'')
|
||||
return [@c_types[lookup], '*'] if (@c_types[lookup])
|
||||
else
|
||||
lookup = lookup + '*'
|
||||
return [@c_types[lookup], '&'] if (@c_types[lookup])
|
||||
end
|
||||
return ['UNITY_TEST_ASSERT_EQUAL_PTR', ''] if (ctype =~ /cmock_\w+_ptr\d+/)
|
||||
raise("Don't know how to test #{ctype} and memory tests are disabled!") unless @config.memcmp_if_unknown
|
||||
return (lookup =~ /\*$/) ? [@fallback, '&'] : [@fallback, '']
|
||||
end
|
||||
|
||||
private ###########################
|
||||
|
||||
def map_C_types
|
||||
c_types = {}
|
||||
@config.treat_as.each_pair do |ctype, expecttype|
|
||||
c_type = ctype.gsub(/\s+/,'_')
|
||||
if (expecttype =~ /\*/)
|
||||
c_types[c_type] = "UNITY_TEST_ASSERT_EQUAL_#{expecttype.gsub(/\*/,'')}_ARRAY"
|
||||
else
|
||||
c_types[c_type] = "UNITY_TEST_ASSERT_EQUAL_#{expecttype}"
|
||||
c_types[c_type+'*'] ||= "UNITY_TEST_ASSERT_EQUAL_#{expecttype}_ARRAY"
|
||||
end
|
||||
end
|
||||
c_types
|
||||
end
|
||||
|
||||
def import_source
|
||||
source = @config.load_unity_helper
|
||||
return {} if source.nil?
|
||||
c_types = {}
|
||||
source = source.gsub(/\/\/.*$/, '') #remove line comments
|
||||
source = source.gsub(/\/\*.*?\*\//m, '') #remove block comments
|
||||
|
||||
#scan for comparison helpers
|
||||
match_regex = Regexp.new('^\s*#define\s+(UNITY_TEST_ASSERT_EQUAL_(\w+))\s*\(' + Array.new(4,'\s*\w+\s*').join(',') + '\)')
|
||||
pairs = source.scan(match_regex).flatten.compact
|
||||
(pairs.size/2).times do |i|
|
||||
expect = pairs[i*2]
|
||||
ctype = pairs[(i*2)+1]
|
||||
c_types[ctype] = expect unless expect.include?("_ARRAY")
|
||||
end
|
||||
|
||||
#scan for array variants of those helpers
|
||||
match_regex = Regexp.new('^\s*#define\s+(UNITY_TEST_ASSERT_EQUAL_(\w+_ARRAY))\s*\(' + Array.new(5,'\s*\w+\s*').join(',') + '\)')
|
||||
pairs = source.scan(match_regex).flatten.compact
|
||||
(pairs.size/2).times do |i|
|
||||
expect = pairs[i*2]
|
||||
ctype = pairs[(i*2)+1]
|
||||
c_types[ctype.gsub('_ARRAY','*')] = expect
|
||||
end
|
||||
|
||||
c_types
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,2 @@
|
||||
212
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
2.0
|
||||
|
||||
+186
@@ -0,0 +1,186 @@
|
||||
/* ==========================================
|
||||
CMock Project - Automatic Mock Generation for C
|
||||
Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
[Released under MIT License. Please refer to license.txt for details]
|
||||
========================================== */
|
||||
|
||||
#include "unity.h"
|
||||
#include "cmock.h"
|
||||
|
||||
//define CMOCK_MEM_DYNAMIC to grab memory as needed with malloc
|
||||
//when you do that, CMOCK_MEM_SIZE is used for incremental size instead of total
|
||||
#ifdef CMOCK_MEM_STATIC
|
||||
#undef CMOCK_MEM_DYNAMIC
|
||||
#endif
|
||||
|
||||
#ifdef CMOCK_MEM_DYNAMIC
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
//this is used internally during pointer arithmetic. make sure this type is the same size as the target's pointer type
|
||||
#ifndef CMOCK_MEM_PTR_AS_INT
|
||||
#define CMOCK_MEM_PTR_AS_INT unsigned long
|
||||
#endif
|
||||
|
||||
//0 for no alignment, 1 for 16-bit, 2 for 32-bit, 3 for 64-bit
|
||||
#ifndef CMOCK_MEM_ALIGN
|
||||
#define CMOCK_MEM_ALIGN (2)
|
||||
#endif
|
||||
|
||||
//amount of memory to allow cmock to use in its internal heap
|
||||
#ifndef CMOCK_MEM_SIZE
|
||||
#define CMOCK_MEM_SIZE (32768)
|
||||
#endif
|
||||
|
||||
//automatically calculated defs for easier reading
|
||||
#define CMOCK_MEM_ALIGN_SIZE (1u << CMOCK_MEM_ALIGN)
|
||||
#define CMOCK_MEM_ALIGN_MASK (CMOCK_MEM_ALIGN_SIZE - 1)
|
||||
#define CMOCK_MEM_INDEX_SIZE ((sizeof(CMOCK_MEM_INDEX_TYPE) > CMOCK_MEM_ALIGN_SIZE) ? sizeof(CMOCK_MEM_INDEX_TYPE) : CMOCK_MEM_ALIGN_SIZE)
|
||||
|
||||
//private variables
|
||||
#ifdef CMOCK_MEM_DYNAMIC
|
||||
static unsigned char* CMock_Guts_Buffer = NULL;
|
||||
static CMOCK_MEM_INDEX_TYPE CMock_Guts_BufferSize = CMOCK_MEM_ALIGN_SIZE;
|
||||
static CMOCK_MEM_INDEX_TYPE CMock_Guts_FreePtr;
|
||||
#else
|
||||
static unsigned char CMock_Guts_Buffer[CMOCK_MEM_SIZE + CMOCK_MEM_ALIGN_SIZE];
|
||||
static CMOCK_MEM_INDEX_TYPE CMock_Guts_BufferSize = CMOCK_MEM_SIZE + CMOCK_MEM_ALIGN_SIZE;
|
||||
static CMOCK_MEM_INDEX_TYPE CMock_Guts_FreePtr;
|
||||
#endif
|
||||
//-------------------------------------------------------
|
||||
// CMock_Guts_MemNew
|
||||
//-------------------------------------------------------
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemNew(CMOCK_MEM_INDEX_TYPE size)
|
||||
{
|
||||
CMOCK_MEM_INDEX_TYPE index;
|
||||
|
||||
//verify arguments valid (we must be allocating space for at least 1 byte, and the existing chain must be in memory somewhere)
|
||||
if (size < 1)
|
||||
return CMOCK_GUTS_NONE;
|
||||
|
||||
//verify we have enough room
|
||||
size = size + CMOCK_MEM_INDEX_SIZE;
|
||||
if (size & CMOCK_MEM_ALIGN_MASK)
|
||||
size = (size + CMOCK_MEM_ALIGN_MASK) & ~CMOCK_MEM_ALIGN_MASK;
|
||||
if ((CMock_Guts_BufferSize - CMock_Guts_FreePtr) < size)
|
||||
{
|
||||
#ifdef CMOCK_MEM_DYNAMIC
|
||||
CMock_Guts_BufferSize += CMOCK_MEM_SIZE + size;
|
||||
CMock_Guts_Buffer = realloc(CMock_Guts_Buffer, CMock_Guts_BufferSize);
|
||||
if (CMock_Guts_Buffer == NULL)
|
||||
#endif //yes that if will continue to the return below if TRUE
|
||||
return CMOCK_GUTS_NONE;
|
||||
}
|
||||
|
||||
//determine where we're putting this new block, and init its pointer to be the end of the line
|
||||
index = CMock_Guts_FreePtr + CMOCK_MEM_INDEX_SIZE;
|
||||
*(CMOCK_MEM_INDEX_TYPE*)(&CMock_Guts_Buffer[CMock_Guts_FreePtr]) = CMOCK_GUTS_NONE;
|
||||
CMock_Guts_FreePtr += size;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// CMock_Guts_MemChain
|
||||
//-------------------------------------------------------
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemChain(CMOCK_MEM_INDEX_TYPE root_index, CMOCK_MEM_INDEX_TYPE obj_index)
|
||||
{
|
||||
CMOCK_MEM_INDEX_TYPE index;
|
||||
void* root;
|
||||
void* obj;
|
||||
void* next;
|
||||
|
||||
if (root_index == CMOCK_GUTS_NONE)
|
||||
{
|
||||
//if there is no root currently, we return this object as the root of the chain
|
||||
return obj_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
//reject illegal nodes
|
||||
if ((root_index < CMOCK_MEM_ALIGN_SIZE) || (root_index >= CMock_Guts_FreePtr))
|
||||
{
|
||||
return CMOCK_GUTS_NONE;
|
||||
}
|
||||
if ((obj_index < CMOCK_MEM_ALIGN_SIZE) || (obj_index >= CMock_Guts_FreePtr))
|
||||
{
|
||||
return CMOCK_GUTS_NONE;
|
||||
}
|
||||
|
||||
root = (void*)(&CMock_Guts_Buffer[root_index]);
|
||||
obj = (void*)(&CMock_Guts_Buffer[obj_index]);
|
||||
|
||||
//find the end of the existing chain and add us
|
||||
next = root;
|
||||
do {
|
||||
index = *(CMOCK_MEM_INDEX_TYPE*)((CMOCK_MEM_PTR_AS_INT)next - CMOCK_MEM_INDEX_SIZE);
|
||||
if (index >= CMock_Guts_FreePtr)
|
||||
return CMOCK_GUTS_NONE;
|
||||
if (index > 0)
|
||||
next = (void*)(&CMock_Guts_Buffer[index]);
|
||||
} while (index > 0);
|
||||
*(CMOCK_MEM_INDEX_TYPE*)((CMOCK_MEM_PTR_AS_INT)next - CMOCK_MEM_INDEX_SIZE) = ((CMOCK_MEM_PTR_AS_INT)obj - (CMOCK_MEM_PTR_AS_INT)CMock_Guts_Buffer);
|
||||
return root_index;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// CMock_Guts_MemNext
|
||||
//-------------------------------------------------------
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemNext(CMOCK_MEM_INDEX_TYPE previous_item_index)
|
||||
{
|
||||
CMOCK_MEM_INDEX_TYPE index;
|
||||
void* previous_item;
|
||||
|
||||
//There is nothing "next" if the pointer isn't from our buffer
|
||||
if ((previous_item_index < CMOCK_MEM_ALIGN_SIZE) || (previous_item_index >= CMock_Guts_FreePtr))
|
||||
return CMOCK_GUTS_NONE;
|
||||
previous_item = (void*)(&CMock_Guts_Buffer[previous_item_index]);
|
||||
|
||||
//if the pointer is good, then use it to look up the next index
|
||||
//(we know the first element always goes in zero, so NEXT must always be > 1)
|
||||
index = *(CMOCK_MEM_INDEX_TYPE*)((CMOCK_MEM_PTR_AS_INT)previous_item - CMOCK_MEM_INDEX_SIZE);
|
||||
if ((index > 1) && (index < CMock_Guts_FreePtr))
|
||||
return index;
|
||||
else
|
||||
return CMOCK_GUTS_NONE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// CMock_GetAddressFor
|
||||
//-------------------------------------------------------
|
||||
void* CMock_Guts_GetAddressFor(CMOCK_MEM_INDEX_TYPE index)
|
||||
{
|
||||
if ((index >= CMOCK_MEM_ALIGN_SIZE) && (index < CMock_Guts_FreePtr))
|
||||
{
|
||||
return (void*)(&CMock_Guts_Buffer[index]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// CMock_Guts_MemBytesFree
|
||||
//-------------------------------------------------------
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemBytesFree(void)
|
||||
{
|
||||
return CMock_Guts_BufferSize - CMock_Guts_FreePtr;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// CMock_Guts_MemBytesUsed
|
||||
//-------------------------------------------------------
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemBytesUsed(void)
|
||||
{
|
||||
return CMock_Guts_FreePtr - CMOCK_MEM_ALIGN_SIZE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// CMock_Guts_MemFreeAll
|
||||
//-------------------------------------------------------
|
||||
void CMock_Guts_MemFreeAll(void)
|
||||
{
|
||||
CMock_Guts_FreePtr = CMOCK_MEM_ALIGN_SIZE; //skip the very beginning
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/* ==========================================
|
||||
CMock Project - Automatic Mock Generation for C
|
||||
Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
[Released under MIT License. Please refer to license.txt for details]
|
||||
========================================== */
|
||||
|
||||
#ifndef CMOCK_FRAMEWORK_H
|
||||
#define CMOCK_FRAMEWORK_H
|
||||
|
||||
//should be big enough to index full range of CMOCK_MEM_MAX
|
||||
#ifndef CMOCK_MEM_INDEX_TYPE
|
||||
#define CMOCK_MEM_INDEX_TYPE unsigned int
|
||||
#endif
|
||||
|
||||
#define CMOCK_GUTS_NONE (0)
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Memory API
|
||||
//-------------------------------------------------------
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemNew(CMOCK_MEM_INDEX_TYPE size);
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemChain(CMOCK_MEM_INDEX_TYPE root_index, CMOCK_MEM_INDEX_TYPE obj_index);
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemNext(CMOCK_MEM_INDEX_TYPE previous_item_index);
|
||||
|
||||
void* CMock_Guts_GetAddressFor(CMOCK_MEM_INDEX_TYPE index);
|
||||
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemBytesFree(void);
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemBytesUsed(void);
|
||||
void CMock_Guts_MemFreeAll(void);
|
||||
|
||||
#endif //CMOCK_FRAMEWORK
|
||||
@@ -0,0 +1,127 @@
|
||||
CONSTRUCTOR_VERSION = '1.0.4' #:nodoc:#
|
||||
|
||||
class Class #:nodoc:#
|
||||
def constructor(*attrs, &block)
|
||||
call_block = ''
|
||||
if block_given?
|
||||
@constructor_block = block
|
||||
call_block = 'self.instance_eval(&self.class.constructor_block)'
|
||||
end
|
||||
# Look for embedded options in the listing:
|
||||
opts = attrs.find { |a| a.kind_of?(Hash) and attrs.delete(a) }
|
||||
do_acc = opts.nil? ? false : opts[:accessors] == true
|
||||
do_reader = opts.nil? ? false : opts[:readers] == true
|
||||
require_args = opts.nil? ? true : opts[:strict] != false
|
||||
super_args = opts.nil? ? nil : opts[:super]
|
||||
|
||||
# Incorporate superclass's constructor keys, if our superclass
|
||||
if superclass.constructor_keys
|
||||
similar_keys = superclass.constructor_keys & attrs
|
||||
raise "Base class already has keys #{similar_keys.inspect}" unless similar_keys.empty?
|
||||
attrs = [attrs,superclass.constructor_keys].flatten
|
||||
end
|
||||
# Generate ivar assigner code lines
|
||||
assigns = ''
|
||||
attrs.each do |k|
|
||||
assigns += "@#{k.to_s} = args[:#{k.to_s}]\n"
|
||||
end
|
||||
|
||||
# If accessors option is on, declare accessors for the attributes:
|
||||
if do_acc
|
||||
add_accessors = "attr_accessor " + attrs.reject {|x| superclass.constructor_keys.include?(x.to_sym)}.map {|x| ":#{x.to_s}"}.join(',')
|
||||
#add_accessors = "attr_accessor " + attrs.map {|x| ":#{x.to_s}"}.join(',')
|
||||
self.class_eval add_accessors
|
||||
end
|
||||
|
||||
# If readers option is on, declare readers for the attributes:
|
||||
if do_reader
|
||||
self.class_eval "attr_reader " + attrs.reject {|x| superclass.constructor_keys.include?(x.to_sym)}.map {|x| ":#{x.to_s}"}.join(',')
|
||||
end
|
||||
|
||||
# If user supplied super-constructor hints:
|
||||
super_call = ''
|
||||
if super_args
|
||||
list = super_args.map do |a|
|
||||
case a
|
||||
when String
|
||||
%|"#{a}"|
|
||||
when Symbol
|
||||
%|:#{a}|
|
||||
end
|
||||
end
|
||||
super_call = %|super(#{list.join(',')})|
|
||||
end
|
||||
|
||||
# If strict is on, define the constructor argument validator method,
|
||||
# and setup the initializer to invoke the validator method.
|
||||
# Otherwise, insert lax code into the initializer.
|
||||
validation_code = "return if args.nil?"
|
||||
if require_args
|
||||
self.class_eval do
|
||||
def _validate_constructor_args(args)
|
||||
# First, make sure we've got args of some kind
|
||||
unless args and args.keys and args.keys.size > 0
|
||||
raise ConstructorArgumentError.new(self.class.constructor_keys)
|
||||
end
|
||||
# Scan for missing keys in the argument hash
|
||||
a_keys = args.keys
|
||||
missing = []
|
||||
self.class.constructor_keys.each do |ck|
|
||||
unless a_keys.member?(ck)
|
||||
missing << ck
|
||||
end
|
||||
a_keys.delete(ck) # Delete inbound keys as we address them
|
||||
end
|
||||
if missing.size > 0 || a_keys.size > 0
|
||||
raise ConstructorArgumentError.new(missing,a_keys)
|
||||
end
|
||||
end
|
||||
end
|
||||
# Setup the code to insert into the initializer:
|
||||
validation_code = "_validate_constructor_args args "
|
||||
end
|
||||
|
||||
# Generate the initializer code
|
||||
self.class_eval %{
|
||||
def initialize(args=nil)
|
||||
#{super_call}
|
||||
#{validation_code}
|
||||
#{assigns}
|
||||
setup if respond_to?(:setup)
|
||||
#{call_block}
|
||||
end
|
||||
}
|
||||
|
||||
# Remember our constructor keys
|
||||
@_ctor_keys = attrs
|
||||
end
|
||||
|
||||
# Access the constructor keys for this class
|
||||
def constructor_keys; @_ctor_keys ||=[]; end
|
||||
|
||||
def constructor_block #:nodoc:#
|
||||
@constructor_block
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Fancy validation exception, based on missing and extraneous keys.
|
||||
class ConstructorArgumentError < RuntimeError #:nodoc:#
|
||||
def initialize(missing,rejected=[])
|
||||
err_msg = ''
|
||||
if missing.size > 0
|
||||
err_msg = "Missing constructor args [#{missing.join(',')}]"
|
||||
end
|
||||
if rejected.size > 0
|
||||
# Some inbound keys were not addressed earlier; this means they're unwanted
|
||||
if err_msg
|
||||
err_msg << "; " # Appending to earlier message about missing items
|
||||
else
|
||||
err_msg = ''
|
||||
end
|
||||
# Enumerate the rejected key names
|
||||
err_msg << "Rejected constructor args [#{rejected.join(',')}]"
|
||||
end
|
||||
super err_msg
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,33 @@
|
||||
class ConstructorStruct
|
||||
def self.new(*accessors, &block)
|
||||
defaults = {:accessors => true, :strict => false}
|
||||
|
||||
accessor_names = accessors.dup
|
||||
if accessors.last.is_a? Hash
|
||||
accessor_names.pop
|
||||
user_opts = accessors.last
|
||||
user_opts.delete(:accessors)
|
||||
defaults.each do |k,v|
|
||||
user_opts[k] ||= v
|
||||
end
|
||||
else
|
||||
accessors << defaults
|
||||
end
|
||||
|
||||
Class.new do
|
||||
constructor *accessors
|
||||
|
||||
class_eval(&block) if block
|
||||
|
||||
comparator_code = accessor_names.map { |fname| "self.#{fname} == o.#{fname}" }.join(" && ")
|
||||
eval %|
|
||||
def ==(o)
|
||||
(self.class == o.class) && #{comparator_code}
|
||||
end
|
||||
def eql?(o)
|
||||
(self.class == o.class) && #{comparator_code}
|
||||
end
|
||||
|
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,211 @@
|
||||
module DeepMerge
|
||||
|
||||
MAJOR_VERSION = 0
|
||||
MINOR_VERSION = 1
|
||||
FIX_VERSION = 0
|
||||
VERSION = "#{MAJOR_VERSION}.#{MINOR_VERSION}.#{FIX_VERSION}"
|
||||
|
||||
class InvalidParameter < StandardError; end
|
||||
|
||||
DEFAULT_FIELD_KNOCKOUT_PREFIX = '--'
|
||||
|
||||
module DeepMergeHash
|
||||
# ko_hash_merge! will merge and knockout elements prefixed with DEFAULT_FIELD_KNOCKOUT_PREFIX
|
||||
def ko_deep_merge!(source, options = {})
|
||||
default_opts = {:knockout_prefix => "--", :preserve_unmergeables => false}
|
||||
DeepMerge::deep_merge!(source, self, default_opts.merge(options))
|
||||
end
|
||||
|
||||
# deep_merge! will merge and overwrite any unmergeables in destination hash
|
||||
def deep_merge!(source, options = {})
|
||||
default_opts = {:preserve_unmergeables => false}
|
||||
DeepMerge::deep_merge!(source, self, default_opts.merge(options))
|
||||
end
|
||||
|
||||
# deep_merge will merge and skip any unmergeables in destination hash
|
||||
def deep_merge(source, options = {})
|
||||
default_opts = {:preserve_unmergeables => true}
|
||||
DeepMerge::deep_merge!(source, self, default_opts.merge(options))
|
||||
end
|
||||
|
||||
end # DeepMergeHashExt
|
||||
|
||||
# Deep Merge core documentation.
|
||||
# deep_merge! method permits merging of arbitrary child elements. The two top level
|
||||
# elements must be hashes. These hashes can contain unlimited (to stack limit) levels
|
||||
# of child elements. These child elements to not have to be of the same types.
|
||||
# Where child elements are of the same type, deep_merge will attempt to merge them together.
|
||||
# Where child elements are not of the same type, deep_merge will skip or optionally overwrite
|
||||
# the destination element with the contents of the source element at that level.
|
||||
# So if you have two hashes like this:
|
||||
# source = {:x => [1,2,3], :y => 2}
|
||||
# dest = {:x => [4,5,'6'], :y => [7,8,9]}
|
||||
# dest.deep_merge!(source)
|
||||
# Results: {:x => [1,2,3,4,5,'6'], :y => 2}
|
||||
# By default, "deep_merge!" will overwrite any unmergeables and merge everything else.
|
||||
# To avoid this, use "deep_merge" (no bang/exclamation mark)
|
||||
#
|
||||
# Options:
|
||||
# Options are specified in the last parameter passed, which should be in hash format:
|
||||
# hash.deep_merge!({:x => [1,2]}, {:knockout_prefix => '--'})
|
||||
# :preserve_unmergeables DEFAULT: false
|
||||
# Set to true to skip any unmergeable elements from source
|
||||
# :knockout_prefix DEFAULT: nil
|
||||
# Set to string value to signify prefix which deletes elements from existing element
|
||||
# :sort_merged_arrays DEFAULT: false
|
||||
# Set to true to sort all arrays that are merged together
|
||||
# :unpack_arrays DEFAULT: nil
|
||||
# Set to string value to run "Array::join" then "String::split" against all arrays
|
||||
# :merge_debug DEFAULT: false
|
||||
# Set to true to get console output of merge process for debugging
|
||||
#
|
||||
# Selected Options Details:
|
||||
# :knockout_prefix => The purpose of this is to provide a way to remove elements
|
||||
# from existing Hash by specifying them in a special way in incoming hash
|
||||
# source = {:x => ['--1', '2']}
|
||||
# dest = {:x => ['1', '3']}
|
||||
# dest.ko_deep_merge!(source)
|
||||
# Results: {:x => ['2','3']}
|
||||
# Additionally, if the knockout_prefix is passed alone as a string, it will cause
|
||||
# the entire element to be removed:
|
||||
# source = {:x => '--'}
|
||||
# dest = {:x => [1,2,3]}
|
||||
# dest.ko_deep_merge!(source)
|
||||
# Results: {:x => ""}
|
||||
# :unpack_arrays => The purpose of this is to permit compound elements to be passed
|
||||
# in as strings and to be converted into discrete array elements
|
||||
# irsource = {:x => ['1,2,3', '4']}
|
||||
# dest = {:x => ['5','6','7,8']}
|
||||
# dest.deep_merge!(source, {:unpack_arrays => ','})
|
||||
# Results: {:x => ['1','2','3','4','5','6','7','8'}
|
||||
# Why: If receiving data from an HTML form, this makes it easy for a checkbox
|
||||
# to pass multiple values from within a single HTML element
|
||||
#
|
||||
# There are many tests for this library - and you can learn more about the features
|
||||
# and usages of deep_merge! by just browsing the test examples
|
||||
def DeepMerge.deep_merge!(source, dest, options = {})
|
||||
# turn on this line for stdout debugging text
|
||||
merge_debug = options[:merge_debug] || false
|
||||
overwrite_unmergeable = !options[:preserve_unmergeables]
|
||||
knockout_prefix = options[:knockout_prefix] || nil
|
||||
if knockout_prefix == "" then raise InvalidParameter, "knockout_prefix cannot be an empty string in deep_merge!"; end
|
||||
if knockout_prefix && !overwrite_unmergeable then raise InvalidParameter, "overwrite_unmergeable must be true if knockout_prefix is specified in deep_merge!"; end
|
||||
# if present: we will split and join arrays on this char before merging
|
||||
array_split_char = options[:unpack_arrays] || false
|
||||
# request that we sort together any arrays when they are merged
|
||||
sort_merged_arrays = options[:sort_merged_arrays] || false
|
||||
di = options[:debug_indent] || ''
|
||||
# do nothing if source is nil
|
||||
if source.nil? || (source.respond_to?(:blank?) && source.blank?) then return dest; end
|
||||
# if dest doesn't exist, then simply copy source to it
|
||||
if dest.nil? && overwrite_unmergeable then dest = source; return dest; end
|
||||
|
||||
puts "#{di}Source class: #{source.class.inspect} :: Dest class: #{dest.class.inspect}" if merge_debug
|
||||
if source.kind_of?(Hash)
|
||||
puts "#{di}Hashes: #{source.inspect} :: #{dest.inspect}" if merge_debug
|
||||
source.each do |src_key, src_value|
|
||||
if dest.kind_of?(Hash)
|
||||
puts "#{di} looping: #{src_key.inspect} => #{src_value.inspect} :: #{dest.inspect}" if merge_debug
|
||||
if not dest[src_key].nil?
|
||||
puts "#{di} ==>merging: #{src_key.inspect} => #{src_value.inspect} :: #{dest[src_key].inspect}" if merge_debug
|
||||
dest[src_key] = deep_merge!(src_value, dest[src_key], options.merge(:debug_indent => di + ' '))
|
||||
else # dest[src_key] doesn't exist so we want to create and overwrite it (but we do this via deep_merge!)
|
||||
puts "#{di} ==>merging over: #{src_key.inspect} => #{src_value.inspect}" if merge_debug
|
||||
# note: we rescue here b/c some classes respond to "dup" but don't implement it (Numeric, TrueClass, FalseClass, NilClass among maybe others)
|
||||
begin
|
||||
src_dup = src_value.dup # we dup src_value if possible because we're going to merge into it (since dest is empty)
|
||||
rescue TypeError
|
||||
src_dup = src_value
|
||||
end
|
||||
dest[src_key] = deep_merge!(src_value, src_dup, options.merge(:debug_indent => di + ' '))
|
||||
end
|
||||
else # dest isn't a hash, so we overwrite it completely (if permitted)
|
||||
if overwrite_unmergeable
|
||||
puts "#{di} overwriting dest: #{src_key.inspect} => #{src_value.inspect} -over-> #{dest.inspect}" if merge_debug
|
||||
dest = overwrite_unmergeables(source, dest, options)
|
||||
end
|
||||
end
|
||||
end
|
||||
elsif source.kind_of?(Array)
|
||||
puts "#{di}Arrays: #{source.inspect} :: #{dest.inspect}" if merge_debug
|
||||
# if we are instructed, join/split any source arrays before processing
|
||||
if array_split_char
|
||||
puts "#{di} split/join on source: #{source.inspect}" if merge_debug
|
||||
source = source.join(array_split_char).split(array_split_char)
|
||||
if dest.kind_of?(Array) then dest = dest.join(array_split_char).split(array_split_char); end
|
||||
end
|
||||
# if there's a naked knockout_prefix in source, that means we are to truncate dest
|
||||
if source.index(knockout_prefix) then dest = clear_or_nil(dest); source.delete(knockout_prefix); end
|
||||
if dest.kind_of?(Array)
|
||||
if knockout_prefix
|
||||
print "#{di} knocking out: " if merge_debug
|
||||
# remove knockout prefix items from both source and dest
|
||||
source.delete_if do |ko_item|
|
||||
retval = false
|
||||
item = ko_item.respond_to?(:gsub) ? ko_item.gsub(%r{^#{knockout_prefix}}, "") : ko_item
|
||||
if item != ko_item
|
||||
print "#{ko_item} - " if merge_debug
|
||||
dest.delete(item)
|
||||
dest.delete(ko_item)
|
||||
retval = true
|
||||
end
|
||||
retval
|
||||
end
|
||||
puts if merge_debug
|
||||
end
|
||||
puts "#{di} merging arrays: #{source.inspect} :: #{dest.inspect}" if merge_debug
|
||||
dest = dest | source
|
||||
if sort_merged_arrays then dest.sort!; end
|
||||
elsif overwrite_unmergeable
|
||||
puts "#{di} overwriting dest: #{source.inspect} -over-> #{dest.inspect}" if merge_debug
|
||||
dest = overwrite_unmergeables(source, dest, options)
|
||||
end
|
||||
else # src_hash is not an array or hash, so we'll have to overwrite dest
|
||||
puts "#{di}Others: #{source.inspect} :: #{dest.inspect}" if merge_debug
|
||||
dest = overwrite_unmergeables(source, dest, options)
|
||||
end
|
||||
puts "#{di}Returning #{dest.inspect}" if merge_debug
|
||||
dest
|
||||
end # deep_merge!
|
||||
|
||||
# allows deep_merge! to uniformly handle overwriting of unmergeable entities
|
||||
def DeepMerge::overwrite_unmergeables(source, dest, options)
|
||||
merge_debug = options[:merge_debug] || false
|
||||
overwrite_unmergeable = !options[:preserve_unmergeables]
|
||||
knockout_prefix = options[:knockout_prefix] || false
|
||||
di = options[:debug_indent] || ''
|
||||
if knockout_prefix && overwrite_unmergeable
|
||||
if source.kind_of?(String) # remove knockout string from source before overwriting dest
|
||||
src_tmp = source.gsub(%r{^#{knockout_prefix}},"")
|
||||
elsif source.kind_of?(Array) # remove all knockout elements before overwriting dest
|
||||
src_tmp = source.delete_if {|ko_item| ko_item.kind_of?(String) && ko_item.match(%r{^#{knockout_prefix}}) }
|
||||
else
|
||||
src_tmp = source
|
||||
end
|
||||
if src_tmp == source # if we didn't find a knockout_prefix then we just overwrite dest
|
||||
puts "#{di}#{src_tmp.inspect} -over-> #{dest.inspect}" if merge_debug
|
||||
dest = src_tmp
|
||||
else # if we do find a knockout_prefix, then we just delete dest
|
||||
puts "#{di}\"\" -over-> #{dest.inspect}" if merge_debug
|
||||
dest = ""
|
||||
end
|
||||
elsif overwrite_unmergeable
|
||||
dest = source
|
||||
end
|
||||
dest
|
||||
end
|
||||
|
||||
def DeepMerge::clear_or_nil(obj)
|
||||
if obj.respond_to?(:clear)
|
||||
obj.clear
|
||||
else
|
||||
obj = nil
|
||||
end
|
||||
obj
|
||||
end
|
||||
|
||||
end # module DeepMerge
|
||||
|
||||
class Hash
|
||||
include DeepMerge::DeepMergeHash
|
||||
end
|
||||
+403
@@ -0,0 +1,403 @@
|
||||
require 'diy/factory.rb'
|
||||
require 'yaml'
|
||||
require 'set'
|
||||
|
||||
module DIY #:nodoc:#
|
||||
VERSION = '1.1.2'
|
||||
class Context
|
||||
|
||||
class << self
|
||||
# Enable / disable automatic requiring of libraries. Default: true
|
||||
attr_accessor :auto_require
|
||||
end
|
||||
@auto_require = true
|
||||
|
||||
# Accepts a Hash defining the object context (usually loaded from objects.yml), and an additional
|
||||
# Hash containing objects to inject into the context.
|
||||
def initialize(context_hash, extra_inputs={})
|
||||
raise "Nil context hash" unless context_hash
|
||||
raise "Need a hash" unless context_hash.kind_of?(Hash)
|
||||
[ "[]", "keys" ].each do |mname|
|
||||
unless extra_inputs.respond_to?(mname)
|
||||
raise "Extra inputs must respond to hash-like [] operator and methods #keys and #each"
|
||||
end
|
||||
end
|
||||
|
||||
# store extra inputs
|
||||
if extra_inputs.kind_of?(Hash)
|
||||
@extra_inputs= {}
|
||||
extra_inputs.each { |k,v| @extra_inputs[k.to_s] = v } # smooth out the names
|
||||
else
|
||||
@extra_inputs = extra_inputs
|
||||
end
|
||||
|
||||
collect_object_and_subcontext_defs context_hash
|
||||
|
||||
# init the cache
|
||||
@cache = {}
|
||||
@cache['this_context'] = self
|
||||
end
|
||||
|
||||
|
||||
# Convenience: create a new DIY::Context by loading from a String (or open file handle.)
|
||||
def self.from_yaml(io_or_string, extra_inputs={})
|
||||
raise "nil input to YAML" unless io_or_string
|
||||
Context.new(YAML.load(io_or_string), extra_inputs)
|
||||
end
|
||||
|
||||
# Convenience: create a new DIY::Context by loading from the named file.
|
||||
def self.from_file(fname, extra_inputs={})
|
||||
raise "nil file name" unless fname
|
||||
self.from_yaml(File.read(fname), extra_inputs)
|
||||
end
|
||||
|
||||
# Return a reference to the object named. If necessary, the object will
|
||||
# be instantiated on first use. If the object is non-singleton, a new
|
||||
# object will be produced each time.
|
||||
def get_object(obj_name)
|
||||
key = obj_name.to_s
|
||||
obj = @cache[key]
|
||||
unless obj
|
||||
if extra_inputs_has(key)
|
||||
obj = @extra_inputs[key]
|
||||
else
|
||||
case @defs[key]
|
||||
when MethodDef
|
||||
obj = construct_method(key)
|
||||
when FactoryDef
|
||||
obj = construct_factory(key)
|
||||
@cache[key] = obj
|
||||
else
|
||||
obj = construct_object(key)
|
||||
@cache[key] = obj if @defs[key].singleton?
|
||||
end
|
||||
end
|
||||
end
|
||||
obj
|
||||
end
|
||||
alias :[] :get_object
|
||||
|
||||
# Inject a named object into the Context. This must be done before the Context has instantiated the
|
||||
# object in question.
|
||||
def set_object(obj_name,obj)
|
||||
key = obj_name.to_s
|
||||
raise "object '#{key}' already exists in context" if @cache.keys.include?(key)
|
||||
@cache[key] = obj
|
||||
end
|
||||
alias :[]= :set_object
|
||||
|
||||
# Provide a listing of object names
|
||||
def keys
|
||||
(@defs.keys.to_set + @extra_inputs.keys.to_set).to_a
|
||||
end
|
||||
|
||||
# Instantiate and yield the named subcontext
|
||||
def within(sub_context_name)
|
||||
# Find the subcontext definitaion:
|
||||
context_def = @sub_context_defs[sub_context_name.to_s]
|
||||
raise "No sub-context named #{sub_context_name}" unless context_def
|
||||
# Instantiate a new context using self as parent:
|
||||
context = Context.new( context_def, self )
|
||||
|
||||
yield context
|
||||
end
|
||||
|
||||
# Returns true if the context contains an object with the given name
|
||||
def contains_object(obj_name)
|
||||
key = obj_name.to_s
|
||||
@defs.keys.member?(key) or extra_inputs_has(key)
|
||||
end
|
||||
|
||||
# Every top level object in the Context is instantiated. This is especially useful for
|
||||
# systems that have "floating observers"... objects that are never directly accessed, who
|
||||
# would thus never be instantiated by coincedence. This does not build any subcontexts
|
||||
# that may exist.
|
||||
def build_everything
|
||||
@defs.keys.each { |k| self[k] }
|
||||
end
|
||||
alias :build_all :build_everything
|
||||
alias :preinstantiate_singletons :build_everything
|
||||
|
||||
private
|
||||
|
||||
def collect_object_and_subcontext_defs(context_hash)
|
||||
@defs = {}
|
||||
@sub_context_defs = {}
|
||||
get_defs_from context_hash
|
||||
end
|
||||
|
||||
def get_defs_from(hash, namespace=nil)
|
||||
hash.each do |name,info|
|
||||
# we modify the info hash below so it's important to have a new
|
||||
# instance to play with
|
||||
info = info.dup if info
|
||||
|
||||
# see if we are building a factory
|
||||
if info and info.has_key?('builds')
|
||||
unless info.has_key?('auto_require')
|
||||
info['auto_require'] = self.class.auto_require
|
||||
end
|
||||
|
||||
if namespace
|
||||
info['builds'] = namespace.build_classname(info['builds'])
|
||||
end
|
||||
@defs[name] = FactoryDef.new({:name => name,
|
||||
:target => info['builds'],
|
||||
:library => info['library'],
|
||||
:auto_require => info['auto_require']})
|
||||
next
|
||||
end
|
||||
|
||||
name = name.to_s
|
||||
case name
|
||||
when /^\+/
|
||||
# subcontext
|
||||
@sub_context_defs[name.gsub(/^\+/,'')] = info
|
||||
|
||||
when /^using_namespace/
|
||||
# namespace: use a module(s) prefix for the classname of contained object defs
|
||||
# NOTE: namespacing is NOT scope... it's just a convenient way to setup class names for a group of objects.
|
||||
get_defs_from info, parse_namespace(name)
|
||||
when /^method\s/
|
||||
key_name = name.gsub(/^method\s/, "")
|
||||
@defs[key_name] = MethodDef.new(:name => key_name,
|
||||
:object => info['object'],
|
||||
:method => info['method'],
|
||||
:attach => info['attach'])
|
||||
else
|
||||
# Normal object def
|
||||
info ||= {}
|
||||
if extra_inputs_has(name)
|
||||
raise ConstructionError.new(name, "Object definition conflicts with parent context")
|
||||
end
|
||||
unless info.has_key?('auto_require')
|
||||
info['auto_require'] = self.class.auto_require
|
||||
end
|
||||
if namespace
|
||||
if info['class']
|
||||
info['class'] = namespace.build_classname(info['class'])
|
||||
else
|
||||
info['class'] = namespace.build_classname(name)
|
||||
end
|
||||
end
|
||||
|
||||
@defs[name] = ObjectDef.new(:name => name, :info => info)
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def construct_method(key)
|
||||
method_definition = @defs[key]
|
||||
object = get_object(method_definition.object)
|
||||
method = object.method(method_definition.method)
|
||||
|
||||
unless method_definition.attach.nil?
|
||||
instance_var_name = "@__diy_#{method_definition.object}"
|
||||
|
||||
method_definition.attach.each do |object_key|
|
||||
get_object(object_key).instance_eval do
|
||||
instance_variable_set(instance_var_name, object)
|
||||
eval %|def #{key}(*args)
|
||||
#{instance_var_name}.#{method_definition.method}(*args)
|
||||
end|
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return method
|
||||
rescue Exception => oops
|
||||
build_and_raise_construction_error(key, oops)
|
||||
end
|
||||
|
||||
def construct_object(key)
|
||||
# Find the object definition
|
||||
obj_def = @defs[key]
|
||||
raise "No object definition for '#{key}'" unless obj_def
|
||||
# If object def mentions a library, load it
|
||||
require obj_def.library if obj_def.library
|
||||
|
||||
# Resolve all components for the object
|
||||
arg_hash = {}
|
||||
obj_def.components.each do |name,value|
|
||||
case value
|
||||
when Lookup
|
||||
arg_hash[name.to_sym] = get_object(value.name)
|
||||
when StringValue
|
||||
arg_hash[name.to_sym] = value.literal_value
|
||||
else
|
||||
raise "Cannot cope with component definition '#{value.inspect}'"
|
||||
end
|
||||
end
|
||||
# Get a reference to the class for the object
|
||||
big_c = get_class_for_name_with_module_delimeters(obj_def.class_name)
|
||||
# Make and return the instance
|
||||
if obj_def.use_class_directly?
|
||||
return big_c
|
||||
elsif arg_hash.keys.size > 0
|
||||
return big_c.new(arg_hash)
|
||||
else
|
||||
return big_c.new
|
||||
end
|
||||
rescue Exception => oops
|
||||
build_and_raise_construction_error(key, oops)
|
||||
end
|
||||
|
||||
def build_and_raise_construction_error(key, oops)
|
||||
cerr = ConstructionError.new(key,oops)
|
||||
cerr.set_backtrace(oops.backtrace)
|
||||
raise cerr
|
||||
end
|
||||
|
||||
def get_class_for_name_with_module_delimeters(class_name)
|
||||
class_name.split(/::/).inject(Object) do |mod,const_name| mod.const_get(const_name) end
|
||||
end
|
||||
|
||||
def extra_inputs_has(key)
|
||||
if key.nil? or key.strip == ''
|
||||
raise ArgumentError.new("Cannot lookup objects with nil keys")
|
||||
end
|
||||
@extra_inputs.keys.member?(key) or @extra_inputs.keys.member?(key.to_sym)
|
||||
end
|
||||
|
||||
def parse_namespace(str)
|
||||
Namespace.new(str)
|
||||
end
|
||||
end
|
||||
|
||||
class Namespace #:nodoc:#
|
||||
def initialize(str)
|
||||
# 'using_namespace Animal Reptile'
|
||||
parts = str.split(/\s+/)
|
||||
raise "Namespace definitions must begin with 'using_namespace'" unless parts[0] == 'using_namespace'
|
||||
parts.shift
|
||||
|
||||
if parts.length > 0 and parts[0] =~ /::/
|
||||
parts = parts[0].split(/::/)
|
||||
end
|
||||
|
||||
raise NamespaceError, "Namespace needs to indicate a module" if parts.empty?
|
||||
|
||||
@module_nest = parts
|
||||
end
|
||||
|
||||
def build_classname(name)
|
||||
[ @module_nest, Infl.camelize(name) ].flatten.join("::")
|
||||
end
|
||||
end
|
||||
|
||||
class Lookup #:nodoc:
|
||||
attr_reader :name
|
||||
def initialize(obj_name)
|
||||
@name = obj_name
|
||||
end
|
||||
end
|
||||
|
||||
class MethodDef #:nodoc:
|
||||
attr_accessor :name, :object, :method, :attach
|
||||
|
||||
def initialize(opts)
|
||||
@name, @object, @method, @attach = opts[:name], opts[:object], opts[:method], opts[:attach]
|
||||
end
|
||||
end
|
||||
|
||||
class ObjectDef #:nodoc:
|
||||
attr_accessor :name, :class_name, :library, :components
|
||||
def initialize(opts)
|
||||
name = opts[:name]
|
||||
raise "Can't make an ObjectDef without a name" if name.nil?
|
||||
|
||||
info = opts[:info] || {}
|
||||
info = info.clone
|
||||
|
||||
@components = {}
|
||||
|
||||
# Object name
|
||||
@name = name
|
||||
|
||||
# Class name
|
||||
@class_name = info.delete 'class'
|
||||
@class_name ||= info.delete 'type'
|
||||
@class_name ||= Infl.camelize(@name)
|
||||
|
||||
# Auto Require
|
||||
@auto_require = info.delete 'auto_require'
|
||||
|
||||
# Library
|
||||
@library = info.delete 'library'
|
||||
@library ||= info.delete 'lib'
|
||||
@library ||= Infl.underscore(@class_name) if @auto_require
|
||||
|
||||
# Use Class Directly
|
||||
@use_class_directly = info.delete 'use_class_directly'
|
||||
|
||||
# Auto-compose
|
||||
compose = info.delete 'compose'
|
||||
if compose
|
||||
case compose
|
||||
when Array
|
||||
auto_names = compose.map { |x| x.to_s }
|
||||
when String
|
||||
auto_names = compose.split(',').map { |x| x.to_s.strip }
|
||||
when Symbol
|
||||
auto_names = [ compose.to_s ]
|
||||
else
|
||||
raise "Cannot auto compose object #{@name}, bad 'compose' format: #{compose.inspect}"
|
||||
end
|
||||
end
|
||||
auto_names ||= []
|
||||
auto_names.each do |cname|
|
||||
@components[cname] = Lookup.new(cname)
|
||||
end
|
||||
|
||||
# Singleton status
|
||||
if info['singleton'].nil?
|
||||
@singleton = true
|
||||
else
|
||||
@singleton = info['singleton']
|
||||
end
|
||||
info.delete 'singleton'
|
||||
|
||||
# Remaining keys
|
||||
info.each do |key,val|
|
||||
@components[key.to_s] = Lookup.new(val.to_s)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def singleton?
|
||||
@singleton
|
||||
end
|
||||
|
||||
def use_class_directly?
|
||||
@use_class_directly == true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class ConstructionError < RuntimeError #:nodoc:#
|
||||
def initialize(object_name, cause=nil)
|
||||
object_name = object_name
|
||||
cause = cause
|
||||
m = "Failed to construct '#{object_name}'"
|
||||
if cause
|
||||
m << "\n ...caused by:\n >>> #{cause}"
|
||||
end
|
||||
super m
|
||||
end
|
||||
end
|
||||
|
||||
class NamespaceError < RuntimeError #:nodoc:#
|
||||
end
|
||||
|
||||
module Infl #:nodoc:#
|
||||
# Ganked this from Inflector:
|
||||
def self.camelize(lower_case_and_underscored_word)
|
||||
lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
|
||||
end
|
||||
# Ganked this from Inflector:
|
||||
def self.underscore(camel_cased_word)
|
||||
camel_cased_word.to_s.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z])/,'\1_\2').gsub(/([a-z\d])([A-Z])/,'\1_\2').downcase
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,36 @@
|
||||
module DIY #:nodoc:#
|
||||
class FactoryDef #:nodoc:
|
||||
attr_accessor :name, :target, :class_name, :library
|
||||
|
||||
def initialize(opts)
|
||||
@name, @target, @library, @auto_require =
|
||||
opts[:name], opts[:target], opts[:library], opts[:auto_require]
|
||||
|
||||
@class_name = Infl.camelize(@target)
|
||||
@library ||= Infl.underscore(@class_name) if @auto_require
|
||||
end
|
||||
end
|
||||
|
||||
class Context
|
||||
def construct_factory(key)
|
||||
factory_def = @defs[key]
|
||||
# puts "requiring #{factory_def.library}"
|
||||
require factory_def.library if factory_def.library
|
||||
|
||||
big_c = get_class_for_name_with_module_delimeters(factory_def.class_name)
|
||||
|
||||
FactoryFactory.new(big_c)
|
||||
end
|
||||
end
|
||||
|
||||
class FactoryFactory
|
||||
def initialize(clazz)
|
||||
@class_to_create = clazz
|
||||
end
|
||||
|
||||
def create(*args)
|
||||
@class_to_create.new(*args)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
# ==========================================
|
||||
# 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]
|
||||
# ==========================================
|
||||
|
||||
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
|
||||
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
|
||||
end
|
||||
|
||||
def change_to(new_colour)
|
||||
if RUBY_PLATFORM =~/(win|w)32$/
|
||||
@set_console_txt_attrb.call(@hout,self.win32_colour(new_colour))
|
||||
else
|
||||
"\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
|
||||
end
|
||||
end
|
||||
|
||||
def posix_colour(colour)
|
||||
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, :default then 37
|
||||
else
|
||||
30
|
||||
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
|
||||
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
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
# ==========================================
|
||||
# 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
|
||||
$stdout.puts(message)
|
||||
else
|
||||
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_puts(colour, line)
|
||||
end
|
||||
end
|
||||
$stdout.flush
|
||||
$stderr.flush
|
||||
end
|
||||
@@ -0,0 +1,36 @@
|
||||
#this is a sample configuration file for generate_module
|
||||
#you would use it by calling generate_module with the -ygenerate_config.yml option
|
||||
#files like this are useful for customizing generate_module to your environment
|
||||
:generate_module:
|
||||
:defaults:
|
||||
#these defaults are used in place of any missing options at the command line
|
||||
:path_src: ../src/
|
||||
:path_inc: ../src/
|
||||
:path_tst: ../test/
|
||||
:update_svn: true
|
||||
:includes:
|
||||
#use [] for no additional includes, otherwise list the includes on separate lines
|
||||
:src:
|
||||
- Defs.h
|
||||
- Board.h
|
||||
:inc: []
|
||||
:tst:
|
||||
- Defs.h
|
||||
- Board.h
|
||||
- Exception.h
|
||||
:boilerplates:
|
||||
#these are inserted at the top of generated files.
|
||||
#just comment out or remove if not desired.
|
||||
#use %1$s where you would like the file name to appear (path/extension not included)
|
||||
:src: |
|
||||
//-------------------------------------------
|
||||
// %1$s.c
|
||||
//-------------------------------------------
|
||||
:inc: |
|
||||
//-------------------------------------------
|
||||
// %1$s.h
|
||||
//-------------------------------------------
|
||||
:tst: |
|
||||
//-------------------------------------------
|
||||
// Test%1$s.c : Units tests for %1$s.c
|
||||
//-------------------------------------------
|
||||
@@ -0,0 +1,202 @@
|
||||
# ==========================================
|
||||
# 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]
|
||||
# ==========================================
|
||||
|
||||
# This script creates all the files with start code necessary for a new module.
|
||||
# A simple module only requires a source file, header file, and test file.
|
||||
# Triad modules require a source, header, and test file for each triad type (like model, conductor, and hardware).
|
||||
|
||||
require 'rubygems'
|
||||
require 'fileutils'
|
||||
|
||||
HERE = File.expand_path(File.dirname(__FILE__)) + '/'
|
||||
|
||||
#help text when requested
|
||||
HELP_TEXT = [ "\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 single source module. (DEFAULT)",
|
||||
" -d destroy module instead of creating it.",
|
||||
" -u update subversion too (requires subversion command line)",
|
||||
" -y\"my.yml\" selects a different yaml config file for module generation",
|
||||
"" ].join("\n")
|
||||
|
||||
#Built in patterns
|
||||
PATTERNS = { 'src' => {'' => { :inc => [] } },
|
||||
'dh' => {'Driver' => { :inc => ['%1$sHardware.h'] },
|
||||
'Hardware' => { :inc => [] }
|
||||
},
|
||||
'dih' => {'Driver' => { :inc => ['%1$sHardware.h', '%1$sInterrupt.h'] },
|
||||
'Interrupt'=> { :inc => ['%1$sHardware.h'] },
|
||||
'Hardware' => { :inc => [] }
|
||||
},
|
||||
'mch' => {'Model' => { :inc => [] },
|
||||
'Conductor'=> { :inc => ['%1$sModel.h', '%1$sHardware.h'] },
|
||||
'Hardware' => { :inc => [] }
|
||||
},
|
||||
'mvp' => {'Model' => { :inc => [] },
|
||||
'Presenter'=> { :inc => ['%1$sModel.h', '%1$sView.h'] },
|
||||
'View' => { :inc => [] }
|
||||
}
|
||||
}
|
||||
|
||||
#TEMPLATE_TST
|
||||
TEMPLATE_TST = %q[#include "unity.h"
|
||||
%2$s#include "%1$s.h"
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void test_%1$s_NeedToImplement(void)
|
||||
{
|
||||
TEST_IGNORE();
|
||||
}
|
||||
]
|
||||
|
||||
#TEMPLATE_SRC
|
||||
TEMPLATE_SRC = %q[%2$s#include "%1$s.h"
|
||||
]
|
||||
|
||||
#TEMPLATE_INC
|
||||
TEMPLATE_INC = %q[#ifndef _%3$s_H
|
||||
#define _%3$s_H%2$s
|
||||
|
||||
#endif // _%3$s_H
|
||||
]
|
||||
|
||||
# Parse the command line parameters.
|
||||
ARGV.each do |arg|
|
||||
case(arg)
|
||||
when /^-d/ then @destroy = true
|
||||
when /^-u/ then @update_svn = true
|
||||
when /^-p(\w+)/ then @pattern = $1
|
||||
when /^-s(.+)/ then @path_src = $1
|
||||
when /^-i(.+)/ then @path_inc = $1
|
||||
when /^-t(.+)/ then @path_tst = $1
|
||||
when /^-y(.+)/ then @yaml_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)/
|
||||
puts HELP_TEXT
|
||||
exit
|
||||
else
|
||||
raise "ERROR: Unknown option specified '#{arg}'"
|
||||
end
|
||||
end
|
||||
raise "ERROR: You must have a Module name specified! (use option -h for help)" if @module_name.nil?
|
||||
|
||||
#load yaml file if one was requested
|
||||
if @yaml_config
|
||||
require 'yaml'
|
||||
cfg = YAML.load_file(HERE + @yaml_config)[:generate_module]
|
||||
@path_src = cfg[:defaults][:path_src] if @path_src.nil?
|
||||
@path_inc = cfg[:defaults][:path_inc] if @path_inc.nil?
|
||||
@path_tst = cfg[:defaults][:path_tst] if @path_tst.nil?
|
||||
@update_svn = cfg[:defaults][:update_svn] if @update_svn.nil?
|
||||
@extra_inc = cfg[:includes]
|
||||
@boilerplates = cfg[:boilerplates]
|
||||
else
|
||||
@boilerplates = {}
|
||||
end
|
||||
|
||||
# Create default file paths if none were provided
|
||||
@path_src = HERE + "../src/" if @path_src.nil?
|
||||
@path_inc = @path_src if @path_inc.nil?
|
||||
@path_tst = HERE + "../test/" if @path_tst.nil?
|
||||
@path_src += '/' unless (@path_src[-1] == 47)
|
||||
@path_inc += '/' unless (@path_inc[-1] == 47)
|
||||
@path_tst += '/' unless (@path_tst[-1] == 47)
|
||||
@pattern = 'src' if @pattern.nil?
|
||||
@includes = { :src => [], :inc => [], :tst => [] }
|
||||
@includes.merge!(@extra_inc) unless @extra_inc.nil?
|
||||
|
||||
#create triad definition
|
||||
TRIAD = [ { :ext => '.c', :path => @path_src, :template => TEMPLATE_SRC, :inc => :src, :boilerplate => @boilerplates[:src] },
|
||||
{ :ext => '.h', :path => @path_inc, :template => TEMPLATE_INC, :inc => :inc, :boilerplate => @boilerplates[:inc] },
|
||||
{ :ext => '.c', :path => @path_tst+'Test', :template => TEMPLATE_TST, :inc => :tst, :boilerplate => @boilerplates[:tst] },
|
||||
]
|
||||
|
||||
#prepare the pattern for use
|
||||
@patterns = PATTERNS[@pattern.downcase]
|
||||
raise "ERROR: The design pattern specified isn't one that I recognize!" if @patterns.nil?
|
||||
|
||||
# Assemble the path/names of the files we need to work with.
|
||||
files = []
|
||||
TRIAD.each do |triad|
|
||||
@patterns.each_pair do |pattern_file, pattern_traits|
|
||||
files << {
|
||||
:path => "#{triad[:path]}#{@module_name}#{pattern_file}#{triad[:ext]}",
|
||||
:name => "#{@module_name}#{pattern_file}",
|
||||
:template => triad[:template],
|
||||
:boilerplate => triad[:boilerplate],
|
||||
:includes => case(triad[:inc])
|
||||
when :src then @includes[:src] | pattern_traits[:inc].map{|f| f % [@module_name]}
|
||||
when :inc then @includes[:inc]
|
||||
when :tst then @includes[:tst] | pattern_traits[:inc].map{|f| "Mock#{f}"% [@module_name]}
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
# destroy files if that was what was requested
|
||||
if @destroy
|
||||
files.each do |filespec|
|
||||
file = filespec[:path]
|
||||
if File.exist?(file)
|
||||
if @update_svn
|
||||
`svn delete \"#{file}\" --force`
|
||||
puts "File #{file} deleted and removed from source control"
|
||||
else
|
||||
FileUtils.remove(file)
|
||||
puts "File #{file} deleted"
|
||||
end
|
||||
else
|
||||
puts "File #{file} does not exist so cannot be removed."
|
||||
end
|
||||
end
|
||||
puts "Destroy Complete"
|
||||
exit
|
||||
end
|
||||
|
||||
#Abort if any module already exists
|
||||
files.each do |file|
|
||||
raise "ERROR: File #{file[:name]} already exists. Exiting." if File.exist?(file[:path])
|
||||
end
|
||||
|
||||
# Create Source Modules
|
||||
files.each_with_index do |file, i|
|
||||
File.open(file[:path], 'w') do |f|
|
||||
f.write(file[:boilerplate] % [file[:name]]) unless file[:boilerplate].nil?
|
||||
f.write(file[:template] % [ file[:name],
|
||||
file[:includes].map{|f| "#include \"#{f}\"\n"}.join,
|
||||
file[:name].upcase ]
|
||||
)
|
||||
end
|
||||
if (@update_svn)
|
||||
`svn add \"#{file[:path]}\"`
|
||||
if $?.exitstatus == 0
|
||||
puts "File #{file[:path]} created and added to source control"
|
||||
else
|
||||
puts "File #{file[:path]} created but FAILED adding to source control!"
|
||||
end
|
||||
else
|
||||
puts "File #{file[:path]} created"
|
||||
end
|
||||
end
|
||||
|
||||
puts 'Generate Complete'
|
||||
@@ -0,0 +1,313 @@
|
||||
# ==========================================
|
||||
# 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]
|
||||
# ==========================================
|
||||
|
||||
File.expand_path(File.join(File.dirname(__FILE__),'colour_prompt'))
|
||||
|
||||
class UnityTestRunnerGenerator
|
||||
|
||||
def initialize(options = nil)
|
||||
@options = { :includes => [], :plugins => [], :framework => :unity }
|
||||
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
|
||||
end
|
||||
|
||||
def self.grab_config(config_file)
|
||||
options = { :includes => [], :plugins => [], :framework => :unity }
|
||||
unless (config_file.nil? or config_file.empty?)
|
||||
require 'yaml'
|
||||
yaml_guts = YAML.load_file(config_file)
|
||||
options.merge!(yaml_guts[:unity] ? yaml_guts[:unity] : yaml_guts[:cmock])
|
||||
raise "No :unity or :cmock section found in #{config_file}" unless options
|
||||
end
|
||||
return(options)
|
||||
end
|
||||
|
||||
def run(input_file, output_file, options=nil)
|
||||
tests = []
|
||||
testfile_includes = []
|
||||
used_mocks = []
|
||||
|
||||
@options.merge!(options) unless options.nil?
|
||||
module_name = File.basename(input_file)
|
||||
|
||||
#pull required data from source file
|
||||
File.open(input_file, 'r') do |input|
|
||||
tests = find_tests(input)
|
||||
testfile_includes = find_includes(input)
|
||||
used_mocks = find_mocks(testfile_includes)
|
||||
end
|
||||
|
||||
#build runner file
|
||||
generate(input_file, output_file, tests, used_mocks)
|
||||
|
||||
#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 += @options[:includes] unless @options[:includes].empty?
|
||||
return all_files_used.uniq
|
||||
end
|
||||
|
||||
def generate(input_file, output_file, tests, used_mocks)
|
||||
File.open(output_file, 'w') do |output|
|
||||
create_header(output, used_mocks)
|
||||
create_externs(output, tests, used_mocks)
|
||||
create_mock_management(output, used_mocks)
|
||||
create_suite_setup_and_teardown(output)
|
||||
create_reset(output, used_mocks)
|
||||
create_main(output, input_file, tests)
|
||||
end
|
||||
end
|
||||
|
||||
def find_tests(input_file)
|
||||
tests_raw = []
|
||||
tests_args = []
|
||||
tests_and_line_numbers = []
|
||||
|
||||
input_file.rewind
|
||||
source_raw = input_file.read
|
||||
source_scrubbed = source_raw.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+(test.*?)\s*\(\s*(.*)\s*\)/
|
||||
arguments = $1
|
||||
name = $2
|
||||
call = $3
|
||||
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, :line_number => 0 }
|
||||
tests_args = []
|
||||
end
|
||||
end
|
||||
|
||||
#determine line numbers and create tests to run
|
||||
source_lines = source_raw.split("\n")
|
||||
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
|
||||
end
|
||||
end
|
||||
|
||||
return tests_and_line_numbers
|
||||
end
|
||||
|
||||
def find_includes(input_file)
|
||||
input_file.rewind
|
||||
|
||||
#read in file
|
||||
source = input_file.read
|
||||
|
||||
#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
|
||||
return source.scan(/^\s*#include\s+\"\s*(.+)\.[hH]\s*\"/).flatten
|
||||
end
|
||||
|
||||
def find_mocks(includes)
|
||||
mock_headers = []
|
||||
includes.each do |include_file|
|
||||
mock_headers << File.basename(include_file) if (include_file =~ /^mock/i)
|
||||
end
|
||||
return mock_headers
|
||||
end
|
||||
|
||||
def create_header(output, mocks)
|
||||
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?)
|
||||
@options[:includes].flatten.uniq.compact.each do |inc|
|
||||
output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h','')}.h\""}")
|
||||
end
|
||||
output.puts('#include <setjmp.h>')
|
||||
output.puts('#include <stdio.h>')
|
||||
output.puts('#include "CException.h"') if @options[:plugins].include?(:cexception)
|
||||
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;')
|
||||
end
|
||||
end
|
||||
|
||||
def create_externs(output, tests, mocks)
|
||||
output.puts("\n//=======External Functions This Runner Calls=====")
|
||||
output.puts("extern void setUp(void);")
|
||||
output.puts("extern void tearDown(void);")
|
||||
tests.each do |test|
|
||||
output.puts("extern void #{test[:test]}(#{test[:call] || 'void'});")
|
||||
end
|
||||
output.puts('')
|
||||
end
|
||||
|
||||
def create_mock_management(output, mocks)
|
||||
unless (mocks.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.each do |mock|
|
||||
output.puts(" #{mock}_Init();")
|
||||
end
|
||||
output.puts("}\n")
|
||||
|
||||
output.puts("static void CMock_Verify(void)")
|
||||
output.puts("{")
|
||||
mocks.each do |mock|
|
||||
output.puts(" #{mock}_Verify();")
|
||||
end
|
||||
output.puts("}\n")
|
||||
|
||||
output.puts("static void CMock_Destroy(void)")
|
||||
output.puts("{")
|
||||
mocks.each do |mock|
|
||||
output.puts(" #{mock}_Destroy();")
|
||||
end
|
||||
output.puts("}\n")
|
||||
end
|
||||
end
|
||||
|
||||
def create_suite_setup_and_teardown(output)
|
||||
unless (@options[:suite_setup].nil?)
|
||||
output.puts("\n//=======Suite Setup=====")
|
||||
output.puts("static int 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
|
||||
end
|
||||
|
||||
def create_runtest(output, used_mocks)
|
||||
cexception = @options[:plugins].include? :cexception
|
||||
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(TestFunc, TestLineNum#{va_args1}) \\")
|
||||
output.puts("{ \\")
|
||||
output.puts(" Unity.CurrentTestName = #TestFunc#{va_args2.empty? ? '' : " \"(\" ##{va_args2} \")\""}; \\")
|
||||
output.puts(" Unity.CurrentTestLineNumber = TestLineNum; \\")
|
||||
output.puts(" Unity.NumberOfTests++; \\")
|
||||
output.puts(" if (TEST_PROTECT()) \\")
|
||||
output.puts(" { \\")
|
||||
output.puts(" CEXCEPTION_T e; \\") if cexception
|
||||
output.puts(" Try { \\") if cexception
|
||||
output.puts(" CMock_Init(); \\") unless (used_mocks.empty?)
|
||||
output.puts(" setUp(); \\")
|
||||
output.puts(" TestFunc(#{va_args2}); \\")
|
||||
output.puts(" CMock_Verify(); \\") unless (used_mocks.empty?)
|
||||
output.puts(" } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, \"Unhandled Exception!\"); } \\") if cexception
|
||||
output.puts(" } \\")
|
||||
output.puts(" CMock_Destroy(); \\") unless (used_mocks.empty?)
|
||||
output.puts(" if (TEST_PROTECT() && !TEST_IS_IGNORED) \\")
|
||||
output.puts(" { \\")
|
||||
output.puts(" tearDown(); \\")
|
||||
output.puts(" } \\")
|
||||
output.puts(" UnityConcludeTest(); \\")
|
||||
output.puts("}\n")
|
||||
end
|
||||
|
||||
def create_reset(output, used_mocks)
|
||||
output.puts("\n//=======Test Reset Option=====")
|
||||
output.puts("void resetTest()")
|
||||
output.puts("{")
|
||||
output.puts(" CMock_Verify();") unless (used_mocks.empty?)
|
||||
output.puts(" CMock_Destroy();") unless (used_mocks.empty?)
|
||||
output.puts(" tearDown();")
|
||||
output.puts(" CMock_Init();") unless (used_mocks.empty?)
|
||||
output.puts(" setUp();")
|
||||
output.puts("}")
|
||||
end
|
||||
|
||||
def create_main(output, filename, tests)
|
||||
output.puts("\n\n//=======MAIN=====")
|
||||
output.puts("int main(void)")
|
||||
output.puts("{")
|
||||
output.puts(" suite_setup();") unless @options[:suite_setup].nil?
|
||||
output.puts(" Unity.TestFile = \"#{filename}\";")
|
||||
output.puts(" UnityBegin();")
|
||||
if (@options[:use_param_tests])
|
||||
tests.each do |test|
|
||||
if ((test[:args].nil?) or (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});")}
|
||||
end
|
||||
end
|
||||
else
|
||||
tests.each { |test| output.puts(" RUN_TEST(#{test[:test]}, #{test[:line_number]});") }
|
||||
end
|
||||
output.puts()
|
||||
output.puts(" return #{@options[:suite_teardown].nil? ? "" : "suite_teardown"}(UnityEnd());")
|
||||
output.puts("}")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if ($0 == __FILE__)
|
||||
options = { :includes => [] }
|
||||
yaml_file = nil
|
||||
|
||||
#parse out all the options first
|
||||
ARGV.reject! do |arg|
|
||||
case(arg)
|
||||
when '-cexception'
|
||||
options[:plugins] = [:cexception]; true
|
||||
when /\.*\.yml/
|
||||
options = UnityTestRunnerGenerator.grab_config(arg); true
|
||||
else false
|
||||
end
|
||||
end
|
||||
|
||||
#make sure there is at least one parameter left (the input file)
|
||||
if !ARGV[0]
|
||||
puts ["usage: ruby #{__FILE__} (yaml) (options) input_test_file output_test_runner (includes)",
|
||||
" blah.yml - will use config options in the yml file (see docs)",
|
||||
" -cexception - include cexception support"].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])
|
||||
|
||||
#everything else is an include file
|
||||
options[:includes] ||= (ARGV.slice(2..-1).flatten.compact) if (ARGV.size > 2)
|
||||
|
||||
UnityTestRunnerGenerator.new(options).run(ARGV[0], ARGV[1])
|
||||
end
|
||||
@@ -0,0 +1,23 @@
|
||||
# ==========================================
|
||||
# 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'
|
||||
|
||||
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
|
||||
attr_accessor :all_files, :only_files, :exclude_files
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,139 @@
|
||||
# ==========================================
|
||||
# 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]
|
||||
# ==========================================
|
||||
|
||||
#!/usr/bin/ruby
|
||||
#
|
||||
# unity_test_summary.rb
|
||||
#
|
||||
require 'fileutils'
|
||||
require 'set'
|
||||
|
||||
class UnityTestSummary
|
||||
include FileUtils::Verbose
|
||||
|
||||
attr_reader :report, :total_tests, :failures, :ignored
|
||||
|
||||
def initialize
|
||||
@report = ''
|
||||
@total_tests = 0
|
||||
@failures = 0
|
||||
@ignored = 0
|
||||
end
|
||||
|
||||
def run
|
||||
# Clean up result file names
|
||||
results = @targets.map {|target| target.gsub(/\\/,'/')}
|
||||
|
||||
# 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
|
||||
end
|
||||
|
||||
if @ignored > 0
|
||||
@report += "\n"
|
||||
@report += "--------------------------\n"
|
||||
@report += "UNITY IGNORED TEST SUMMARY\n"
|
||||
@report += "--------------------------\n"
|
||||
@report += ignore_output.flatten.join("\n")
|
||||
end
|
||||
|
||||
if @failures > 0
|
||||
@report += "\n"
|
||||
@report += "--------------------------\n"
|
||||
@report += "UNITY FAILED TEST SUMMARY\n"
|
||||
@report += "--------------------------\n"
|
||||
@report += failure_output.flatten.join("\n")
|
||||
end
|
||||
|
||||
@report += "\n"
|
||||
@report += "--------------------------\n"
|
||||
@report += "OVERALL UNITY TEST SUMMARY\n"
|
||||
@report += "--------------------------\n"
|
||||
@report += "#{@total_tests} TOTAL TESTS #{@failures} TOTAL FAILURES #{@ignored} IGNORED\n"
|
||||
@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)
|
||||
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."
|
||||
exit 1
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
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 and (@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
|
||||
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
|
||||
end
|
||||
|
||||
def here; File.expand_path(File.dirname(__FILE__)); end
|
||||
|
||||
end
|
||||
|
||||
if $0 == __FILE__
|
||||
uts = UnityTestSummary.new
|
||||
begin
|
||||
#look in the specified or current directory for result files
|
||||
ARGV[0] ||= './'
|
||||
targets = "#{ARGV[0].gsub(/\\/, '/')}*.test*"
|
||||
results = Dir[targets]
|
||||
raise "No *.testpass or *.testfail files found in '#{targets}'" if results.empty?
|
||||
uts.set_targets(results)
|
||||
|
||||
#set the root path
|
||||
ARGV[1] ||= File.expand_path(File.dirname(__FILE__)) + '/'
|
||||
uts.set_root_path(ARGV[1])
|
||||
|
||||
#run the summarizer
|
||||
puts uts.run
|
||||
rescue Exception => e
|
||||
uts.usage e.message
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,9 @@
|
||||
Copyright (c) 2010 James Grenning and Contributed to Unity Project
|
||||
|
||||
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]
|
||||
|
||||
This Framework is an optional add-on to Unity. By including unity_framework.h in place of unity.h,
|
||||
you may now work with Unity in a manner similar to CppUTest. This framework adds the concepts of
|
||||
test groups and gives finer control of your tests over the command line.
|
||||
@@ -0,0 +1,377 @@
|
||||
//- Copyright (c) 2010 James Grenning and Contributed to Unity Project
|
||||
/* ==========================================
|
||||
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]
|
||||
========================================== */
|
||||
|
||||
#include "unity_fixture.h"
|
||||
#include "unity_internals.h"
|
||||
#include <string.h>
|
||||
|
||||
UNITY_FIXTURE_T UnityFixture;
|
||||
|
||||
//If you decide to use the function pointer approach.
|
||||
int (*outputChar)(int) = putchar;
|
||||
|
||||
int verbose = 0;
|
||||
|
||||
void setUp(void) { /*does nothing*/ }
|
||||
void tearDown(void) { /*does nothing*/ }
|
||||
|
||||
void announceTestRun(unsigned int runNumber)
|
||||
{
|
||||
UnityPrint("Unity test run ");
|
||||
UnityPrintNumber(runNumber+1);
|
||||
UnityPrint(" of ");
|
||||
UnityPrintNumber(UnityFixture.RepeatCount);
|
||||
UNITY_OUTPUT_CHAR('\n');
|
||||
}
|
||||
|
||||
int UnityMain(int argc, char* argv[], void (*runAllTests)())
|
||||
{
|
||||
int result = UnityGetCommandLineOptions(argc, argv);
|
||||
unsigned int r;
|
||||
if (result != 0)
|
||||
return result;
|
||||
|
||||
for (r = 0; r < UnityFixture.RepeatCount; r++)
|
||||
{
|
||||
announceTestRun(r);
|
||||
UnityBegin();
|
||||
runAllTests();
|
||||
UNITY_OUTPUT_CHAR('\n');
|
||||
UnityEnd();
|
||||
}
|
||||
|
||||
return UnityFailureCount();
|
||||
}
|
||||
|
||||
static int selected(const char * filter, const char * name)
|
||||
{
|
||||
if (filter == 0)
|
||||
return 1;
|
||||
return strstr(name, filter) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int testSelected(const char* test)
|
||||
{
|
||||
return selected(UnityFixture.NameFilter, test);
|
||||
}
|
||||
|
||||
static int groupSelected(const char* group)
|
||||
{
|
||||
return selected(UnityFixture.GroupFilter, group);
|
||||
}
|
||||
|
||||
static void runTestCase()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void UnityTestRunner(unityfunction* setup,
|
||||
unityfunction* testBody,
|
||||
unityfunction* teardown,
|
||||
const char * printableName,
|
||||
const char * group,
|
||||
const char * name,
|
||||
const char * file, int line)
|
||||
{
|
||||
if (testSelected(name) && groupSelected(group))
|
||||
{
|
||||
Unity.CurrentTestFailed = 0;
|
||||
Unity.TestFile = file;
|
||||
Unity.CurrentTestName = printableName;
|
||||
Unity.CurrentTestLineNumber = line;
|
||||
if (!UnityFixture.Verbose)
|
||||
UNITY_OUTPUT_CHAR('.');
|
||||
else
|
||||
UnityPrint(printableName);
|
||||
|
||||
Unity.NumberOfTests++;
|
||||
UnityMalloc_StartTest();
|
||||
UnityPointer_Init();
|
||||
|
||||
runTestCase();
|
||||
if (TEST_PROTECT())
|
||||
{
|
||||
setup();
|
||||
testBody();
|
||||
}
|
||||
if (TEST_PROTECT())
|
||||
{
|
||||
teardown();
|
||||
}
|
||||
if (TEST_PROTECT())
|
||||
{
|
||||
UnityPointer_UndoAllSets();
|
||||
if (!Unity.CurrentTestFailed)
|
||||
UnityMalloc_EndTest();
|
||||
}
|
||||
UnityConcludeFixtureTest();
|
||||
}
|
||||
}
|
||||
|
||||
void UnityIgnoreTest()
|
||||
{
|
||||
Unity.NumberOfTests++;
|
||||
Unity.CurrentTestIgnored = 1;
|
||||
UNITY_OUTPUT_CHAR('!');
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
//Malloc and free stuff
|
||||
//
|
||||
#define MALLOC_DONT_FAIL -1
|
||||
static int malloc_count;
|
||||
static int malloc_fail_countdown = MALLOC_DONT_FAIL;
|
||||
|
||||
void UnityMalloc_StartTest()
|
||||
{
|
||||
malloc_count = 0;
|
||||
malloc_fail_countdown = MALLOC_DONT_FAIL;
|
||||
}
|
||||
|
||||
void UnityMalloc_EndTest()
|
||||
{
|
||||
malloc_fail_countdown = MALLOC_DONT_FAIL;
|
||||
if (malloc_count != 0)
|
||||
{
|
||||
TEST_FAIL_MESSAGE("This test leaks!");
|
||||
}
|
||||
}
|
||||
|
||||
void UnityMalloc_MakeMallocFailAfterCount(int countdown)
|
||||
{
|
||||
malloc_fail_countdown = countdown;
|
||||
}
|
||||
|
||||
#ifdef malloc
|
||||
#undef malloc
|
||||
#endif
|
||||
|
||||
#ifdef free
|
||||
#undef free
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct GuardBytes
|
||||
{
|
||||
int size;
|
||||
char guard[sizeof(int)];
|
||||
} Guard;
|
||||
|
||||
|
||||
static const char * end = "END";
|
||||
|
||||
void * unity_malloc(size_t size)
|
||||
{
|
||||
char* mem;
|
||||
Guard* guard;
|
||||
|
||||
if (malloc_fail_countdown != MALLOC_DONT_FAIL)
|
||||
{
|
||||
if (malloc_fail_countdown == 0)
|
||||
return 0;
|
||||
malloc_fail_countdown--;
|
||||
}
|
||||
|
||||
malloc_count++;
|
||||
|
||||
guard = (Guard*)malloc(size + sizeof(Guard) + 4);
|
||||
guard->size = size;
|
||||
mem = (char*)&(guard[1]);
|
||||
memcpy(&mem[size], end, strlen(end) + 1);
|
||||
|
||||
return (void*)mem;
|
||||
}
|
||||
|
||||
static int isOverrun(void * mem)
|
||||
{
|
||||
Guard* guard = (Guard*)mem;
|
||||
char* memAsChar = (char*)mem;
|
||||
guard--;
|
||||
|
||||
return strcmp(&memAsChar[guard->size], end) != 0;
|
||||
}
|
||||
|
||||
static void release_memory(void * mem)
|
||||
{
|
||||
Guard* guard = (Guard*)mem;
|
||||
guard--;
|
||||
|
||||
malloc_count--;
|
||||
free(guard);
|
||||
}
|
||||
|
||||
void unity_free(void * mem)
|
||||
{
|
||||
int overrun = isOverrun(mem);//strcmp(&memAsChar[guard->size], end) != 0;
|
||||
release_memory(mem);
|
||||
if (overrun)
|
||||
{
|
||||
TEST_FAIL_MESSAGE("Buffer overrun detected during free()");
|
||||
}
|
||||
}
|
||||
|
||||
void* unity_calloc(size_t num, size_t size)
|
||||
{
|
||||
void* mem = unity_malloc(num * size);
|
||||
memset(mem, 0, num*size);
|
||||
return mem;
|
||||
}
|
||||
|
||||
void* unity_realloc(void * oldMem, size_t size)
|
||||
{
|
||||
Guard* guard = (Guard*)oldMem;
|
||||
// char* memAsChar = (char*)oldMem;
|
||||
void* newMem;
|
||||
|
||||
if (oldMem == 0)
|
||||
return unity_malloc(size);
|
||||
|
||||
guard--;
|
||||
if (isOverrun(oldMem))
|
||||
{
|
||||
release_memory(oldMem);
|
||||
TEST_FAIL_MESSAGE("Buffer overrun detected during realloc()");
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
release_memory(oldMem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (guard->size >= size)
|
||||
return oldMem;
|
||||
|
||||
newMem = unity_malloc(size);
|
||||
memcpy(newMem, oldMem, guard->size);
|
||||
unity_free(oldMem);
|
||||
return newMem;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------
|
||||
//Automatic pointer restoration functions
|
||||
typedef struct _PointerPair
|
||||
{
|
||||
struct _PointerPair * next;
|
||||
void ** pointer;
|
||||
void * old_value;
|
||||
} PointerPair;
|
||||
|
||||
enum {MAX_POINTERS=50};
|
||||
static PointerPair pointer_store[MAX_POINTERS];
|
||||
static int pointer_index = 0;
|
||||
|
||||
void UnityPointer_Init()
|
||||
{
|
||||
pointer_index = 0;
|
||||
}
|
||||
|
||||
void UnityPointer_Set(void ** pointer, void * newValue)
|
||||
{
|
||||
if (pointer_index >= MAX_POINTERS)
|
||||
TEST_FAIL_MESSAGE("Too many pointers set");
|
||||
|
||||
pointer_store[pointer_index].pointer = pointer;
|
||||
pointer_store[pointer_index].old_value = *pointer;
|
||||
*pointer = newValue;
|
||||
pointer_index++;
|
||||
}
|
||||
|
||||
void UnityPointer_UndoAllSets()
|
||||
{
|
||||
while (pointer_index > 0)
|
||||
{
|
||||
pointer_index--;
|
||||
*(pointer_store[pointer_index].pointer) =
|
||||
pointer_store[pointer_index].old_value;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int UnityFailureCount()
|
||||
{
|
||||
return Unity.TestFailures;
|
||||
}
|
||||
|
||||
int UnityGetCommandLineOptions(int argc, char* argv[])
|
||||
{
|
||||
int i;
|
||||
UnityFixture.Verbose = 0;
|
||||
UnityFixture.GroupFilter = 0;
|
||||
UnityFixture.NameFilter = 0;
|
||||
UnityFixture.RepeatCount = 1;
|
||||
|
||||
if (argc == 1)
|
||||
return 0;
|
||||
|
||||
for (i = 1; i < argc; )
|
||||
{
|
||||
if (strcmp(argv[i], "-v") == 0)
|
||||
{
|
||||
UnityFixture.Verbose = 1;
|
||||
i++;
|
||||
}
|
||||
else if (strcmp(argv[i], "-g") == 0)
|
||||
{
|
||||
i++;
|
||||
if (i >= argc)
|
||||
return 1;
|
||||
UnityFixture.GroupFilter = argv[i];
|
||||
i++;
|
||||
}
|
||||
else if (strcmp(argv[i], "-n") == 0)
|
||||
{
|
||||
i++;
|
||||
if (i >= argc)
|
||||
return 1;
|
||||
UnityFixture.NameFilter = argv[i];
|
||||
i++;
|
||||
}
|
||||
else if (strcmp(argv[i], "-r") == 0)
|
||||
{
|
||||
UnityFixture.RepeatCount = 2;
|
||||
i++;
|
||||
if (i < argc)
|
||||
{
|
||||
if (*(argv[i]) >= '0' && *(argv[i]) <= '9')
|
||||
{
|
||||
UnityFixture.RepeatCount = atoi(argv[i]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void UnityConcludeFixtureTest()
|
||||
{
|
||||
if (Unity.CurrentTestIgnored)
|
||||
{
|
||||
Unity.TestIgnores++;
|
||||
}
|
||||
else if (!Unity.CurrentTestFailed)
|
||||
{
|
||||
if (UnityFixture.Verbose)
|
||||
{
|
||||
UnityPrint(" PASS");
|
||||
UNITY_OUTPUT_CHAR('\n');
|
||||
}
|
||||
}
|
||||
else if (Unity.CurrentTestFailed)
|
||||
{
|
||||
Unity.TestFailures++;
|
||||
}
|
||||
|
||||
Unity.CurrentTestFailed = 0;
|
||||
Unity.CurrentTestIgnored = 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
//- Copyright (c) 2010 James Grenning and Contributed to Unity Project
|
||||
/* ==========================================
|
||||
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]
|
||||
========================================== */
|
||||
|
||||
#ifndef UNITY_FIXTURE_H_
|
||||
#define UNITY_FIXTURE_H_
|
||||
|
||||
#include "unity.h"
|
||||
#include "unity_internals.h"
|
||||
#include "unity_fixture_malloc_overrides.h"
|
||||
#include "unity_fixture_internals.h"
|
||||
|
||||
int UnityMain(int argc, char* argv[], void (*runAllTests)());
|
||||
|
||||
|
||||
#define TEST_GROUP(group)\
|
||||
int TEST_GROUP_##group = 0
|
||||
|
||||
#define TEST_SETUP(group) void TEST_##group##_SETUP()
|
||||
|
||||
#define TEST_TEAR_DOWN(group) void TEST_##group##_TEAR_DOWN()
|
||||
|
||||
|
||||
#define TEST(group, name) \
|
||||
void TEST_##group##_##name##_();\
|
||||
void TEST_##group##_##name##_run()\
|
||||
{\
|
||||
UnityTestRunner(TEST_##group##_SETUP,\
|
||||
TEST_##group##_##name##_,\
|
||||
TEST_##group##_TEAR_DOWN,\
|
||||
"TEST(" #group ", " #name ")",\
|
||||
#group, #name,\
|
||||
__FILE__, __LINE__);\
|
||||
}\
|
||||
void TEST_##group##_##name##_()
|
||||
|
||||
#define IGNORE_TEST(group, name) \
|
||||
void TEST_##group##_##name##_();\
|
||||
void TEST_##group##_##name##_run()\
|
||||
{\
|
||||
UnityIgnoreTest();\
|
||||
}\
|
||||
void TEST_##group##_##name##_()
|
||||
|
||||
#define DECLARE_TEST_CASE(group, name) \
|
||||
void TEST_##group##_##name##_run()
|
||||
|
||||
#define RUN_TEST_CASE(group, name) \
|
||||
DECLARE_TEST_CASE(group, name);\
|
||||
TEST_##group##_##name##_run();
|
||||
|
||||
//This goes at the bottom of each test file or in a separate c file
|
||||
#define TEST_GROUP_RUNNER(group)\
|
||||
void TEST_##group##_GROUP_RUNNER_runAll();\
|
||||
void TEST_##group##_GROUP_RUNNER()\
|
||||
{\
|
||||
TEST_##group##_GROUP_RUNNER_runAll();\
|
||||
}\
|
||||
void TEST_##group##_GROUP_RUNNER_runAll()
|
||||
|
||||
//Call this from main
|
||||
#define RUN_TEST_GROUP(group)\
|
||||
void TEST_##group##_GROUP_RUNNER();\
|
||||
TEST_##group##_GROUP_RUNNER();
|
||||
|
||||
//CppUTest Compatibility Macros
|
||||
#define UT_PTR_SET(ptr, newPointerValue) UnityPointer_Set((void**)&ptr, (void*)newPointerValue)
|
||||
#define TEST_ASSERT_POINTERS_EQUAL(expected, actual) TEST_ASSERT_EQUAL_PTR(expected, actual)
|
||||
#define TEST_ASSERT_BYTES_EQUAL(expected, actual) TEST_ASSERT_EQUAL_HEX8(0xff & (expected), 0xff & (actual))
|
||||
#define FAIL(message) TEST_FAIL((message))
|
||||
#define CHECK(condition) TEST_ASSERT_TRUE((condition))
|
||||
#define LONGS_EQUAL(expected, actual) TEST_ASSERT_EQUAL_INT((expected), (actual))
|
||||
#define STRCMP_EQUAL(expected, actual) TEST_ASSERT_EQUAL_STRING((expected), (actual))
|
||||
#define DOUBLES_EQUAL(expected, actual, delta) TEST_ASSERT_FLOAT_WITHIN(((expected), (actual), (delta))
|
||||
|
||||
void UnityMalloc_MakeMallocFailAfterCount(int count);
|
||||
|
||||
#endif /* UNITY_FIXTURE_H_ */
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
//- Copyright (c) 2010 James Grenning and Contributed to Unity Project
|
||||
/* ==========================================
|
||||
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]
|
||||
========================================== */
|
||||
|
||||
#ifndef UNITY_FIXTURE_INTERNALS_H_
|
||||
#define UNITY_FIXTURE_INTERNALS_H_
|
||||
|
||||
typedef struct _UNITY_FIXTURE_T
|
||||
{
|
||||
int Verbose;
|
||||
unsigned int RepeatCount;
|
||||
const char* NameFilter;
|
||||
const char* GroupFilter;
|
||||
} UNITY_FIXTURE_T;
|
||||
|
||||
typedef void unityfunction();
|
||||
void UnityTestRunner(unityfunction * setup,
|
||||
unityfunction * body,
|
||||
unityfunction * teardown,
|
||||
const char * printableName,
|
||||
const char * group,
|
||||
const char * name,
|
||||
const char * file, int line);
|
||||
|
||||
void UnityIgnoreTest();
|
||||
void UnityMalloc_StartTest();
|
||||
void UnityMalloc_EndTest();
|
||||
int UnityFailureCount();
|
||||
int UnityGetCommandLineOptions(int argc, char* argv[]);
|
||||
void UnityConcludeFixtureTest();
|
||||
|
||||
void UnityPointer_Set(void ** ptr, void * newValue);
|
||||
void UnityPointer_UndoAllSets();
|
||||
void UnityPointer_Init();
|
||||
|
||||
void UnityAssertEqualPointer(const void * expected,
|
||||
const void * actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber);
|
||||
|
||||
#endif /* UNITY_FIXTURE_INTERNALS_H_ */
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
//- Copyright (c) 2010 James Grenning and Contributed to Unity Project
|
||||
/* ==========================================
|
||||
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]
|
||||
========================================== */
|
||||
|
||||
#ifndef UNITY_FIXTURE_MALLOC_OVERRIDES_H_
|
||||
#define UNITY_FIXTURE_MALLOC_OVERRIDES_H_
|
||||
|
||||
#define malloc unity_malloc
|
||||
#define calloc unity_calloc
|
||||
#define realloc unity_realloc
|
||||
#define free unity_free
|
||||
|
||||
#endif /* UNITY_FIXTURE_MALLOC_OVERRIDES_H_ */
|
||||
@@ -0,0 +1,2 @@
|
||||
118
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
2.1.0
|
||||
|
||||
+979
@@ -0,0 +1,979 @@
|
||||
/* ==========================================
|
||||
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]
|
||||
========================================== */
|
||||
|
||||
#include "unity.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define UNITY_FAIL_AND_BAIL { Unity.CurrentTestFailed = 1; UNITY_OUTPUT_CHAR('\n'); longjmp(Unity.AbortFrame, 1); }
|
||||
#define UNITY_IGNORE_AND_BAIL { Unity.CurrentTestIgnored = 1; UNITY_OUTPUT_CHAR('\n'); longjmp(Unity.AbortFrame, 1); }
|
||||
/// return prematurely if we are already in failure or ignore state
|
||||
#define UNITY_SKIP_EXECUTION { if ((Unity.CurrentTestFailed != 0) || (Unity.CurrentTestIgnored != 0)) {return;} }
|
||||
#define UNITY_PRINT_EOL { UNITY_OUTPUT_CHAR('\n'); }
|
||||
|
||||
struct _Unity Unity = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , { 0 } };
|
||||
|
||||
const char* UnityStrNull = "NULL";
|
||||
const char* UnityStrSpacer = ". ";
|
||||
const char* UnityStrExpected = " Expected ";
|
||||
const char* UnityStrWas = " Was ";
|
||||
const char* UnityStrTo = " To ";
|
||||
const char* UnityStrElement = " Element ";
|
||||
const char* UnityStrByte = " Byte ";
|
||||
const char* UnityStrMemory = " Memory Mismatch.";
|
||||
const char* UnityStrDelta = " Values Not Within Delta ";
|
||||
const char* UnityStrPointless= " You Asked Me To Compare Nothing, Which Was Pointless.";
|
||||
const char* UnityStrNullPointerForExpected= " Expected pointer to be NULL";
|
||||
const char* UnityStrNullPointerForActual = " Actual pointer was NULL";
|
||||
|
||||
// compiler-generic print formatting masks
|
||||
const _U_UINT UnitySizeMask[] =
|
||||
{
|
||||
255u, // 0xFF
|
||||
65535u, // 0xFFFF
|
||||
65535u,
|
||||
4294967295u, // 0xFFFFFFFF
|
||||
4294967295u,
|
||||
4294967295u,
|
||||
4294967295u
|
||||
#ifdef UNITY_SUPPORT_64
|
||||
,0xFFFFFFFFFFFFFFFF
|
||||
#endif
|
||||
};
|
||||
|
||||
void UnityPrintFail(void);
|
||||
void UnityPrintOk(void);
|
||||
|
||||
//-----------------------------------------------
|
||||
// Pretty Printers & Test Result Output Handlers
|
||||
//-----------------------------------------------
|
||||
|
||||
void UnityPrint(const char* string)
|
||||
{
|
||||
const char* pch = string;
|
||||
|
||||
if (pch != NULL)
|
||||
{
|
||||
while (*pch)
|
||||
{
|
||||
// printable characters plus CR & LF are printed
|
||||
if ((*pch <= 126) && (*pch >= 32))
|
||||
{
|
||||
UNITY_OUTPUT_CHAR(*pch);
|
||||
}
|
||||
//write escaped carriage returns
|
||||
else if (*pch == 13)
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('\\');
|
||||
UNITY_OUTPUT_CHAR('r');
|
||||
}
|
||||
//write escaped line feeds
|
||||
else if (*pch == 10)
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('\\');
|
||||
UNITY_OUTPUT_CHAR('n');
|
||||
}
|
||||
// unprintable characters are shown as codes
|
||||
else
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('\\');
|
||||
UnityPrintNumberHex((_U_SINT)*pch, 2);
|
||||
}
|
||||
pch++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
void UnityPrintNumberByStyle(const _U_SINT number, const UNITY_DISPLAY_STYLE_T style)
|
||||
{
|
||||
if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT)
|
||||
{
|
||||
UnityPrintNumber(number);
|
||||
}
|
||||
else if ((style & UNITY_DISPLAY_RANGE_UINT) == UNITY_DISPLAY_RANGE_UINT)
|
||||
{
|
||||
UnityPrintNumberUnsigned( (_U_UINT)number & UnitySizeMask[((_U_UINT)style & (_U_UINT)0x0F) - 1] );
|
||||
}
|
||||
else
|
||||
{
|
||||
UnityPrintNumberHex((_U_UINT)number, (style & 0x000F) << 1);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
/// basically do an itoa using as little ram as possible
|
||||
void UnityPrintNumber(const _U_SINT number_to_print)
|
||||
{
|
||||
_U_SINT divisor = 1;
|
||||
_U_SINT next_divisor;
|
||||
_U_SINT number = number_to_print;
|
||||
|
||||
if (number < 0)
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('-');
|
||||
number = -number;
|
||||
}
|
||||
|
||||
// figure out initial divisor
|
||||
while (number / divisor > 9)
|
||||
{
|
||||
next_divisor = divisor * 10;
|
||||
if (next_divisor > divisor)
|
||||
divisor = next_divisor;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// now mod and print, then divide divisor
|
||||
do
|
||||
{
|
||||
UNITY_OUTPUT_CHAR((char)('0' + (number / divisor % 10)));
|
||||
divisor /= 10;
|
||||
}
|
||||
while (divisor > 0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
/// basically do an itoa using as little ram as possible
|
||||
void UnityPrintNumberUnsigned(const _U_UINT number)
|
||||
{
|
||||
_U_UINT divisor = 1;
|
||||
_U_UINT next_divisor;
|
||||
|
||||
// figure out initial divisor
|
||||
while (number / divisor > 9)
|
||||
{
|
||||
next_divisor = divisor * 10;
|
||||
if (next_divisor > divisor)
|
||||
divisor = next_divisor;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// now mod and print, then divide divisor
|
||||
do
|
||||
{
|
||||
UNITY_OUTPUT_CHAR((char)('0' + (number / divisor % 10)));
|
||||
divisor /= 10;
|
||||
}
|
||||
while (divisor > 0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
void UnityPrintNumberHex(const _U_UINT number, const char nibbles_to_print)
|
||||
{
|
||||
_U_UINT nibble;
|
||||
char nibbles = nibbles_to_print;
|
||||
UNITY_OUTPUT_CHAR('0');
|
||||
UNITY_OUTPUT_CHAR('x');
|
||||
|
||||
while (nibbles > 0)
|
||||
{
|
||||
nibble = (number >> (--nibbles << 2)) & 0x0000000F;
|
||||
if (nibble <= 9)
|
||||
{
|
||||
UNITY_OUTPUT_CHAR((char)('0' + nibble));
|
||||
}
|
||||
else
|
||||
{
|
||||
UNITY_OUTPUT_CHAR((char)('A' - 10 + nibble));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
void UnityPrintMask(const _U_UINT mask, const _U_UINT number)
|
||||
{
|
||||
_U_UINT current_bit = (_U_UINT)1 << (UNITY_INT_WIDTH - 1);
|
||||
_US32 i;
|
||||
|
||||
for (i = 0; i < UNITY_INT_WIDTH; i++)
|
||||
{
|
||||
if (current_bit & mask)
|
||||
{
|
||||
if (current_bit & number)
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('1');
|
||||
}
|
||||
else
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('0');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('X');
|
||||
}
|
||||
current_bit = current_bit >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
#ifdef UNITY_FLOAT_VERBOSE
|
||||
void UnityPrintFloat(_UF number)
|
||||
{
|
||||
char TempBuffer[32];
|
||||
sprintf(TempBuffer, "%.6f", number);
|
||||
UnityPrint(TempBuffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------
|
||||
|
||||
void UnityPrintFail(void)
|
||||
{
|
||||
UnityPrint("FAIL");
|
||||
}
|
||||
|
||||
void UnityPrintOk(void)
|
||||
{
|
||||
UnityPrint("OK");
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
void UnityTestResultsBegin(const char* file, const UNITY_LINE_TYPE line)
|
||||
{
|
||||
UnityPrint(file);
|
||||
UNITY_OUTPUT_CHAR(':');
|
||||
UnityPrintNumber(line);
|
||||
UNITY_OUTPUT_CHAR(':');
|
||||
UnityPrint(Unity.CurrentTestName);
|
||||
UNITY_OUTPUT_CHAR(':');
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
void UnityTestResultsFailBegin(const UNITY_LINE_TYPE line)
|
||||
{
|
||||
UnityTestResultsBegin(Unity.TestFile, line);
|
||||
UnityPrint("FAIL:");
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
void UnityConcludeTest(void)
|
||||
{
|
||||
if (Unity.CurrentTestIgnored)
|
||||
{
|
||||
Unity.TestIgnores++;
|
||||
}
|
||||
else if (!Unity.CurrentTestFailed)
|
||||
{
|
||||
UnityTestResultsBegin(Unity.TestFile, Unity.CurrentTestLineNumber);
|
||||
UnityPrint("PASS");
|
||||
UNITY_PRINT_EOL;
|
||||
}
|
||||
else
|
||||
{
|
||||
Unity.TestFailures++;
|
||||
}
|
||||
|
||||
Unity.CurrentTestFailed = 0;
|
||||
Unity.CurrentTestIgnored = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
void UnityAddMsgIfSpecified(const char* msg)
|
||||
{
|
||||
if (msg)
|
||||
{
|
||||
UnityPrint(UnityStrSpacer);
|
||||
UnityPrint(msg);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
void UnityPrintExpectedAndActualStrings(const char* expected, const char* actual)
|
||||
{
|
||||
UnityPrint(UnityStrExpected);
|
||||
if (expected != NULL)
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('\'');
|
||||
UnityPrint(expected);
|
||||
UNITY_OUTPUT_CHAR('\'');
|
||||
}
|
||||
else
|
||||
{
|
||||
UnityPrint(UnityStrNull);
|
||||
}
|
||||
UnityPrint(UnityStrWas);
|
||||
if (actual != NULL)
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('\'');
|
||||
UnityPrint(actual);
|
||||
UNITY_OUTPUT_CHAR('\'');
|
||||
}
|
||||
else
|
||||
{
|
||||
UnityPrint(UnityStrNull);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
// Assertion & Control Helpers
|
||||
//-----------------------------------------------
|
||||
|
||||
int UnityCheckArraysForNull(const void* expected, const void* actual, const UNITY_LINE_TYPE lineNumber, const char* msg)
|
||||
{
|
||||
//return true if they are both NULL
|
||||
if ((expected == NULL) && (actual == NULL))
|
||||
return 1;
|
||||
|
||||
//throw error if just expected is NULL
|
||||
if (expected == NULL)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrNullPointerForExpected);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
|
||||
//throw error if just actual is NULL
|
||||
if (actual == NULL)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrNullPointerForActual);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
|
||||
//return false if neither is NULL
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
// Assertion Functions
|
||||
//-----------------------------------------------
|
||||
|
||||
void UnityAssertBits(const _U_SINT mask,
|
||||
const _U_SINT expected,
|
||||
const _U_SINT actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber)
|
||||
{
|
||||
UNITY_SKIP_EXECUTION;
|
||||
|
||||
if ((mask & expected) != (mask & actual))
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrExpected);
|
||||
UnityPrintMask(mask, expected);
|
||||
UnityPrint(UnityStrWas);
|
||||
UnityPrintMask(mask, actual);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
void UnityAssertEqualNumber(const _U_SINT expected,
|
||||
const _U_SINT actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const UNITY_DISPLAY_STYLE_T style)
|
||||
{
|
||||
UNITY_SKIP_EXECUTION;
|
||||
|
||||
if (expected != actual)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrExpected);
|
||||
UnityPrintNumberByStyle(expected, style);
|
||||
UnityPrint(UnityStrWas);
|
||||
UnityPrintNumberByStyle(actual, style);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
void UnityAssertEqualIntArray(const _U_SINT* expected,
|
||||
const _U_SINT* actual,
|
||||
const _UU32 num_elements,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const UNITY_DISPLAY_STYLE_T style)
|
||||
{
|
||||
_UU32 elements = num_elements;
|
||||
const _US8* ptr_exp = (_US8*)expected;
|
||||
const _US8* ptr_act = (_US8*)actual;
|
||||
|
||||
UNITY_SKIP_EXECUTION;
|
||||
|
||||
if (elements == 0)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrPointless);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
|
||||
if (UnityCheckArraysForNull((void*)expected, (void*)actual, lineNumber, msg) == 1)
|
||||
return;
|
||||
|
||||
switch(style)
|
||||
{
|
||||
case UNITY_DISPLAY_STYLE_HEX8:
|
||||
case UNITY_DISPLAY_STYLE_INT8:
|
||||
case UNITY_DISPLAY_STYLE_UINT8:
|
||||
while (elements--)
|
||||
{
|
||||
if (*ptr_exp != *ptr_act)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrElement);
|
||||
UnityPrintNumberByStyle((num_elements - elements - 1), UNITY_DISPLAY_STYLE_UINT);
|
||||
UnityPrint(UnityStrExpected);
|
||||
UnityPrintNumberByStyle(*ptr_exp, style);
|
||||
UnityPrint(UnityStrWas);
|
||||
UnityPrintNumberByStyle(*ptr_act, style);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
ptr_exp += 1;
|
||||
ptr_act += 1;
|
||||
}
|
||||
break;
|
||||
case UNITY_DISPLAY_STYLE_HEX16:
|
||||
case UNITY_DISPLAY_STYLE_INT16:
|
||||
case UNITY_DISPLAY_STYLE_UINT16:
|
||||
while (elements--)
|
||||
{
|
||||
if (*(_US16*)ptr_exp != *(_US16*)ptr_act)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrElement);
|
||||
UnityPrintNumberByStyle((num_elements - elements - 1), UNITY_DISPLAY_STYLE_UINT);
|
||||
UnityPrint(UnityStrExpected);
|
||||
UnityPrintNumberByStyle(*(_US16*)ptr_exp, style);
|
||||
UnityPrint(UnityStrWas);
|
||||
UnityPrintNumberByStyle(*(_US16*)ptr_act, style);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
ptr_exp += 2;
|
||||
ptr_act += 2;
|
||||
}
|
||||
break;
|
||||
#ifdef UNITY_SUPPORT_64
|
||||
case UNITY_DISPLAY_STYLE_HEX64:
|
||||
case UNITY_DISPLAY_STYLE_INT64:
|
||||
case UNITY_DISPLAY_STYLE_UINT64:
|
||||
while (elements--)
|
||||
{
|
||||
if (*(_US64*)ptr_exp != *(_US64*)ptr_act)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrElement);
|
||||
UnityPrintNumberByStyle((num_elements - elements - 1), UNITY_DISPLAY_STYLE_UINT);
|
||||
UnityPrint(UnityStrExpected);
|
||||
UnityPrintNumberByStyle(*(_US64*)ptr_exp, style);
|
||||
UnityPrint(UnityStrWas);
|
||||
UnityPrintNumberByStyle(*(_US64*)ptr_act, style);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
ptr_exp += 8;
|
||||
ptr_act += 8;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
while (elements--)
|
||||
{
|
||||
if (*(_US32*)ptr_exp != *(_US32*)ptr_act)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrElement);
|
||||
UnityPrintNumberByStyle((num_elements - elements - 1), UNITY_DISPLAY_STYLE_UINT);
|
||||
UnityPrint(UnityStrExpected);
|
||||
UnityPrintNumberByStyle(*(_US32*)ptr_exp, style);
|
||||
UnityPrint(UnityStrWas);
|
||||
UnityPrintNumberByStyle(*(_US32*)ptr_act, style);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
ptr_exp += 4;
|
||||
ptr_act += 4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
#ifndef UNITY_EXCLUDE_FLOAT
|
||||
void UnityAssertEqualFloatArray(const _UF* expected,
|
||||
const _UF* actual,
|
||||
const _UU32 num_elements,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber)
|
||||
{
|
||||
_UU32 elements = num_elements;
|
||||
const _UF* ptr_expected = expected;
|
||||
const _UF* ptr_actual = actual;
|
||||
_UF diff, tol;
|
||||
|
||||
UNITY_SKIP_EXECUTION;
|
||||
|
||||
if (elements == 0)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrPointless);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
|
||||
if (UnityCheckArraysForNull((void*)expected, (void*)actual, lineNumber, msg) == 1)
|
||||
return;
|
||||
|
||||
while (elements--)
|
||||
{
|
||||
diff = *ptr_expected - *ptr_actual;
|
||||
if (diff < 0.0)
|
||||
diff = 0.0 - diff;
|
||||
tol = UNITY_FLOAT_PRECISION * *ptr_expected;
|
||||
if (tol < 0.0)
|
||||
tol = 0.0 - tol;
|
||||
if (diff > tol)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrElement);
|
||||
UnityPrintNumberByStyle((num_elements - elements - 1), UNITY_DISPLAY_STYLE_UINT);
|
||||
#ifdef UNITY_FLOAT_VERBOSE
|
||||
UnityPrint(UnityStrExpected);
|
||||
UnityPrintFloat(*ptr_expected);
|
||||
UnityPrint(UnityStrWas);
|
||||
UnityPrintFloat(*ptr_actual);
|
||||
#else
|
||||
UnityPrint(UnityStrDelta);
|
||||
#endif
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
ptr_expected++;
|
||||
ptr_actual++;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
void UnityAssertFloatsWithin(const _UF delta,
|
||||
const _UF expected,
|
||||
const _UF actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber)
|
||||
{
|
||||
_UF diff = actual - expected;
|
||||
_UF pos_delta = delta;
|
||||
|
||||
UNITY_SKIP_EXECUTION;
|
||||
|
||||
if (diff < 0)
|
||||
{
|
||||
diff = 0.0f - diff;
|
||||
}
|
||||
if (pos_delta < 0)
|
||||
{
|
||||
pos_delta = 0.0f - pos_delta;
|
||||
}
|
||||
|
||||
if (pos_delta < diff)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
#ifdef UNITY_FLOAT_VERBOSE
|
||||
UnityPrint(UnityStrExpected);
|
||||
UnityPrintFloat(expected);
|
||||
UnityPrint(UnityStrWas);
|
||||
UnityPrintFloat(actual);
|
||||
#else
|
||||
UnityPrint(UnityStrDelta);
|
||||
#endif
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //not UNITY_EXCLUDE_FLOAT
|
||||
|
||||
//-----------------------------------------------
|
||||
#ifndef UNITY_EXCLUDE_DOUBLE
|
||||
void UnityAssertEqualDoubleArray(const _UD* expected,
|
||||
const _UD* actual,
|
||||
const _UU32 num_elements,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber)
|
||||
{
|
||||
_UU32 elements = num_elements;
|
||||
const _UD* ptr_expected = expected;
|
||||
const _UD* ptr_actual = actual;
|
||||
_UD diff, tol;
|
||||
|
||||
UNITY_SKIP_EXECUTION;
|
||||
|
||||
if (elements == 0)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrPointless);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
|
||||
if (UnityCheckArraysForNull((void*)expected, (void*)actual, lineNumber, msg) == 1)
|
||||
return;
|
||||
|
||||
while (elements--)
|
||||
{
|
||||
diff = *ptr_expected - *ptr_actual;
|
||||
if (diff < 0.0)
|
||||
diff = 0.0 - diff;
|
||||
tol = UNITY_DOUBLE_PRECISION * *ptr_expected;
|
||||
if (tol < 0.0)
|
||||
tol = 0.0 - tol;
|
||||
if (diff > tol)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrElement);
|
||||
UnityPrintNumberByStyle((num_elements - elements - 1), UNITY_DISPLAY_STYLE_UINT);
|
||||
#ifdef UNITY_DOUBLE_VERBOSE
|
||||
UnityPrint(UnityStrExpected);
|
||||
UnityPrintFloat((float)(*ptr_expected));
|
||||
UnityPrint(UnityStrWas);
|
||||
UnityPrintFloat((float)(*ptr_actual));
|
||||
#else
|
||||
UnityPrint(UnityStrDelta);
|
||||
#endif
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
ptr_expected++;
|
||||
ptr_actual++;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
void UnityAssertDoublesWithin(const _UD delta,
|
||||
const _UD expected,
|
||||
const _UD actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber)
|
||||
{
|
||||
_UD diff = actual - expected;
|
||||
_UD pos_delta = delta;
|
||||
|
||||
UNITY_SKIP_EXECUTION;
|
||||
|
||||
if (diff < 0)
|
||||
{
|
||||
diff = 0.0f - diff;
|
||||
}
|
||||
if (pos_delta < 0)
|
||||
{
|
||||
pos_delta = 0.0f - pos_delta;
|
||||
}
|
||||
|
||||
if (pos_delta < diff)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
#ifdef UNITY_DOUBLE_VERBOSE
|
||||
UnityPrint(UnityStrExpected);
|
||||
UnityPrintFloat((float)expected);
|
||||
UnityPrint(UnityStrWas);
|
||||
UnityPrintFloat((float)actual);
|
||||
#else
|
||||
UnityPrint(UnityStrDelta);
|
||||
#endif
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // not UNITY_EXCLUDE_DOUBLE
|
||||
|
||||
//-----------------------------------------------
|
||||
void UnityAssertNumbersWithin( const _U_SINT delta,
|
||||
const _U_SINT expected,
|
||||
const _U_SINT actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const UNITY_DISPLAY_STYLE_T style)
|
||||
{
|
||||
UNITY_SKIP_EXECUTION;
|
||||
|
||||
if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT)
|
||||
{
|
||||
if (actual > expected)
|
||||
Unity.CurrentTestFailed = ((actual - expected) > delta);
|
||||
else
|
||||
Unity.CurrentTestFailed = ((expected - actual) > delta);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((_U_UINT)actual > (_U_UINT)expected)
|
||||
Unity.CurrentTestFailed = ((_U_UINT)(actual - expected) > (_U_UINT)delta);
|
||||
else
|
||||
Unity.CurrentTestFailed = ((_U_UINT)(expected - actual) > (_U_UINT)delta);
|
||||
}
|
||||
|
||||
if (Unity.CurrentTestFailed)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrDelta);
|
||||
UnityPrintNumberByStyle(delta, style);
|
||||
UnityPrint(UnityStrExpected);
|
||||
UnityPrintNumberByStyle(expected, style);
|
||||
UnityPrint(UnityStrWas);
|
||||
UnityPrintNumberByStyle(actual, style);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
void UnityAssertEqualString(const char* expected,
|
||||
const char* actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber)
|
||||
{
|
||||
_UU32 i;
|
||||
|
||||
UNITY_SKIP_EXECUTION;
|
||||
|
||||
// if both pointers not null compare the strings
|
||||
if (expected && actual)
|
||||
{
|
||||
for (i = 0; expected[i] || actual[i]; i++)
|
||||
{
|
||||
if (expected[i] != actual[i])
|
||||
{
|
||||
Unity.CurrentTestFailed = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // handle case of one pointers being null (if both null, test should pass)
|
||||
if (expected != actual)
|
||||
{
|
||||
Unity.CurrentTestFailed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (Unity.CurrentTestFailed)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrintExpectedAndActualStrings(expected, actual);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
void UnityAssertEqualStringArray( const char** expected,
|
||||
const char** actual,
|
||||
const _UU32 num_elements,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber)
|
||||
{
|
||||
_UU32 i, j = 0;
|
||||
|
||||
UNITY_SKIP_EXECUTION;
|
||||
|
||||
// if no elements, it's an error
|
||||
if (num_elements == 0)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrPointless);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
|
||||
if (UnityCheckArraysForNull((void*)expected, (void*)actual, lineNumber, msg) == 1)
|
||||
return;
|
||||
|
||||
do
|
||||
{
|
||||
// if both pointers not null compare the strings
|
||||
if (expected[j] && actual[j])
|
||||
{
|
||||
for (i = 0; expected[j][i] || actual[j][i]; i++)
|
||||
{
|
||||
if (expected[j][i] != actual[j][i])
|
||||
{
|
||||
Unity.CurrentTestFailed = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // handle case of one pointers being null (if both null, test should pass)
|
||||
if (expected[j] != actual[j])
|
||||
{
|
||||
Unity.CurrentTestFailed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (Unity.CurrentTestFailed)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
if (num_elements > 1)
|
||||
{
|
||||
UnityPrint(UnityStrElement);
|
||||
UnityPrintNumberByStyle((num_elements - j - 1), UNITY_DISPLAY_STYLE_UINT);
|
||||
}
|
||||
UnityPrintExpectedAndActualStrings((const char*)(expected[j]), (const char*)(actual[j]));
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
} while (++j < num_elements);
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
void UnityAssertEqualMemory( const void* expected,
|
||||
const void* actual,
|
||||
const _UU32 length,
|
||||
const _UU32 num_elements,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber)
|
||||
{
|
||||
unsigned char* ptr_exp = (unsigned char*)expected;
|
||||
unsigned char* ptr_act = (unsigned char*)actual;
|
||||
_UU32 elements = num_elements;
|
||||
_UU32 bytes;
|
||||
|
||||
UNITY_SKIP_EXECUTION;
|
||||
|
||||
if ((elements == 0) || (length == 0))
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrPointless);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
|
||||
if (UnityCheckArraysForNull((void*)expected, (void*)actual, lineNumber, msg) == 1)
|
||||
return;
|
||||
|
||||
while (elements--)
|
||||
{
|
||||
/////////////////////////////////////
|
||||
bytes = length;
|
||||
while (bytes--)
|
||||
{
|
||||
if (*ptr_exp != *ptr_act)
|
||||
{
|
||||
UnityTestResultsFailBegin(lineNumber);
|
||||
UnityPrint(UnityStrMemory);
|
||||
if (num_elements > 1)
|
||||
{
|
||||
UnityPrint(UnityStrElement);
|
||||
UnityPrintNumberByStyle((num_elements - elements - 1), UNITY_DISPLAY_STYLE_UINT);
|
||||
}
|
||||
UnityPrint(UnityStrByte);
|
||||
UnityPrintNumberByStyle((length - bytes - 1), UNITY_DISPLAY_STYLE_UINT);
|
||||
UnityPrint(UnityStrExpected);
|
||||
UnityPrintNumberByStyle(*ptr_exp, UNITY_DISPLAY_STYLE_HEX8);
|
||||
UnityPrint(UnityStrWas);
|
||||
UnityPrintNumberByStyle(*ptr_act, UNITY_DISPLAY_STYLE_HEX8);
|
||||
UnityAddMsgIfSpecified(msg);
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
ptr_exp += 1;
|
||||
ptr_act += 1;
|
||||
}
|
||||
/////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
// Control Functions
|
||||
//-----------------------------------------------
|
||||
|
||||
void UnityFail(const char* msg, const UNITY_LINE_TYPE line)
|
||||
{
|
||||
UNITY_SKIP_EXECUTION;
|
||||
|
||||
UnityTestResultsBegin(Unity.TestFile, line);
|
||||
UnityPrintFail();
|
||||
if (msg != NULL)
|
||||
{
|
||||
UNITY_OUTPUT_CHAR(':');
|
||||
if (msg[0] != ' ')
|
||||
{
|
||||
UNITY_OUTPUT_CHAR(' ');
|
||||
}
|
||||
UnityPrint(msg);
|
||||
}
|
||||
UNITY_FAIL_AND_BAIL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
void UnityIgnore(const char* msg, const UNITY_LINE_TYPE line)
|
||||
{
|
||||
UNITY_SKIP_EXECUTION;
|
||||
|
||||
UnityTestResultsBegin(Unity.TestFile, line);
|
||||
UnityPrint("IGNORE");
|
||||
if (msg != NULL)
|
||||
{
|
||||
UNITY_OUTPUT_CHAR(':');
|
||||
UNITY_OUTPUT_CHAR(' ');
|
||||
UnityPrint(msg);
|
||||
}
|
||||
UNITY_IGNORE_AND_BAIL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
void setUp(void);
|
||||
void tearDown(void);
|
||||
void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum)
|
||||
{
|
||||
Unity.CurrentTestName = FuncName;
|
||||
Unity.CurrentTestLineNumber = FuncLineNum;
|
||||
Unity.NumberOfTests++;
|
||||
if (TEST_PROTECT())
|
||||
{
|
||||
setUp();
|
||||
Func();
|
||||
}
|
||||
if (TEST_PROTECT() && !(Unity.CurrentTestIgnored))
|
||||
{
|
||||
tearDown();
|
||||
}
|
||||
UnityConcludeTest();
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
void UnityBegin(void)
|
||||
{
|
||||
Unity.NumberOfTests = 0;
|
||||
Unity.TestFailures = 0;
|
||||
Unity.TestIgnores = 0;
|
||||
Unity.CurrentTestFailed = 0;
|
||||
Unity.CurrentTestIgnored = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------
|
||||
int UnityEnd(void)
|
||||
{
|
||||
UnityPrint("-----------------------");
|
||||
UNITY_PRINT_EOL;
|
||||
UnityPrintNumber(Unity.NumberOfTests);
|
||||
UnityPrint(" Tests ");
|
||||
UnityPrintNumber(Unity.TestFailures);
|
||||
UnityPrint(" Failures ");
|
||||
UnityPrintNumber(Unity.TestIgnores);
|
||||
UnityPrint(" Ignored");
|
||||
UNITY_PRINT_EOL;
|
||||
if (Unity.TestFailures == 0U)
|
||||
{
|
||||
UnityPrintOk();
|
||||
}
|
||||
else
|
||||
{
|
||||
UnityPrintFail();
|
||||
}
|
||||
UNITY_PRINT_EOL;
|
||||
return Unity.TestFailures;
|
||||
}
|
||||
+232
@@ -0,0 +1,232 @@
|
||||
/* ==========================================
|
||||
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]
|
||||
========================================== */
|
||||
|
||||
#ifndef UNITY_FRAMEWORK_H
|
||||
#define UNITY_FRAMEWORK_H
|
||||
|
||||
#define UNITY
|
||||
|
||||
#include "unity_internals.h"
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Configuration Options
|
||||
//-------------------------------------------------------
|
||||
|
||||
// Integers
|
||||
// - Unity assumes 32 bit integers by default
|
||||
// - If your compiler treats ints of a different size, define UNITY_INT_WIDTH
|
||||
|
||||
// Floats
|
||||
// - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons
|
||||
// - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT
|
||||
// - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats
|
||||
// - define UNITY_FLOAT_VERBOSE to print floating point values in errors (uses sprintf)
|
||||
// - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons
|
||||
// - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default)
|
||||
// - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE
|
||||
// - define UNITY_DOUBLE_TYPE to specify something other than double
|
||||
// - define UNITY_DOUBLE_VERBOSE to print floating point values in errors (uses sprintf)
|
||||
|
||||
// Output
|
||||
// - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if desired
|
||||
|
||||
// Optimization
|
||||
// - by default, line numbers are stored in unsigned shorts. Define UNITY_LINE_TYPE with a different type if your files are huge
|
||||
// - by default, test and failure counters are unsigned shorts. Define UNITY_COUNTER_TYPE with a different type if you want to save space or have more than 65535 Tests.
|
||||
|
||||
// Test Cases
|
||||
// - define UNITY_SUPPORT_TEST_CASES to include the TEST_CASE macro, though really it's mostly about the runner generator script
|
||||
|
||||
// Parameterized Tests
|
||||
// - you'll want to create a define of TEST_CASE(...) which basically evaluates to nothing
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Test Running Macros
|
||||
//-------------------------------------------------------
|
||||
|
||||
#define TEST_PROTECT() (setjmp(Unity.AbortFrame) == 0)
|
||||
|
||||
#define TEST_ABORT() {longjmp(Unity.AbortFrame, 1);}
|
||||
|
||||
#ifndef RUN_TEST
|
||||
#define RUN_TEST(func, line_num) UnityDefaultTestRun(func, #func, line_num)
|
||||
#endif
|
||||
|
||||
#define TEST_LINE_NUM (Unity.CurrentTestLineNumber)
|
||||
#define TEST_IS_IGNORED (Unity.CurrentTestIgnored)
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Basic Fail and Ignore
|
||||
//-------------------------------------------------------
|
||||
|
||||
#define TEST_FAIL_MESSAGE(message) UNITY_TEST_FAIL(__LINE__, message)
|
||||
#define TEST_FAIL() UNITY_TEST_FAIL(__LINE__, NULL)
|
||||
#define TEST_IGNORE_MESSAGE(message) UNITY_TEST_IGNORE(__LINE__, message)
|
||||
#define TEST_IGNORE() UNITY_TEST_IGNORE(__LINE__, NULL)
|
||||
#define TEST_ONLY()
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Test Asserts (simple)
|
||||
//-------------------------------------------------------
|
||||
|
||||
//Boolean
|
||||
#define TEST_ASSERT(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expression Evaluated To FALSE")
|
||||
#define TEST_ASSERT_TRUE(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expected TRUE Was FALSE")
|
||||
#define TEST_ASSERT_UNLESS(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expression Evaluated To TRUE")
|
||||
#define TEST_ASSERT_FALSE(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expected FALSE Was TRUE")
|
||||
#define TEST_ASSERT_NULL(pointer) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, " Expected NULL")
|
||||
#define TEST_ASSERT_NOT_NULL(pointer) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, " Expected Non-NULL")
|
||||
|
||||
//Integers (of all sizes)
|
||||
#define TEST_ASSERT_EQUAL_INT(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_INT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_INT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_INT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_INT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal")
|
||||
#define TEST_ASSERT_EQUAL_UINT(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_UINT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_UINT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_UINT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_UINT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_HEX(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_HEX8(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_HEX16(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_HEX32(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_HEX64(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_BITS(mask, expected, actual) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_BITS_HIGH(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (_UU32)(-1), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_BITS_LOW(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (_UU32)(0), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_BIT_HIGH(bit, actual) UNITY_TEST_ASSERT_BITS(((_UU32)1 << bit), (_UU32)(-1), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_BIT_LOW(bit, actual) UNITY_TEST_ASSERT_BITS(((_UU32)1 << bit), (_UU32)(0), (actual), __LINE__, NULL)
|
||||
|
||||
//Integer Ranges (of all sizes)
|
||||
#define TEST_ASSERT_INT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT_WITHIN(delta, expected, actual, __LINE__, NULL)
|
||||
#define TEST_ASSERT_UINT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN(delta, expected, actual, __LINE__, NULL)
|
||||
#define TEST_ASSERT_HEX_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN(delta, expected, actual, __LINE__, NULL)
|
||||
#define TEST_ASSERT_HEX8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX8_WITHIN(delta, expected, actual, __LINE__, NULL)
|
||||
#define TEST_ASSERT_HEX16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX16_WITHIN(delta, expected, actual, __LINE__, NULL)
|
||||
#define TEST_ASSERT_HEX32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN(delta, expected, actual, __LINE__, NULL)
|
||||
#define TEST_ASSERT_HEX64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, __LINE__, NULL)
|
||||
|
||||
//Structs and Strings
|
||||
#define TEST_ASSERT_EQUAL_PTR(expected, actual) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_STRING(expected, actual) UNITY_TEST_ASSERT_EQUAL_STRING(expected, actual, __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_MEMORY(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_MEMORY(expected, actual, len, __LINE__, NULL)
|
||||
|
||||
//Arrays
|
||||
#define TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements, __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements, __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements, __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements, __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements, __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements, __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements, __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements, __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_HEX_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements, __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements, __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements, __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements, __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, __LINE__, NULL)
|
||||
#define TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements, __LINE__, NULL)
|
||||
#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)
|
||||
|
||||
//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)
|
||||
|
||||
//Double (If Enabled)
|
||||
#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)
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Test Asserts (with additional messages)
|
||||
//-------------------------------------------------------
|
||||
|
||||
//Boolean
|
||||
#define TEST_ASSERT_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, message)
|
||||
#define TEST_ASSERT_TRUE_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, message)
|
||||
#define TEST_ASSERT_UNLESS_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, message)
|
||||
#define TEST_ASSERT_FALSE_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, message)
|
||||
#define TEST_ASSERT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, message)
|
||||
#define TEST_ASSERT_NOT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, message)
|
||||
|
||||
//Integers (of all sizes)
|
||||
#define TEST_ASSERT_EQUAL_INT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_INT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_INT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_INT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_INT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, message)
|
||||
#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_UINT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_UINT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_UINT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_UINT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_HEX_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_HEX8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_HEX16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_HEX32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_HEX64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, message)
|
||||
#define TEST_ASSERT_BITS_MESSAGE(mask, expected, actual, message) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, message)
|
||||
#define TEST_ASSERT_BITS_HIGH_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (_UU32)(-1), (actual), __LINE__, message)
|
||||
#define TEST_ASSERT_BITS_LOW_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (_UU32)(0), (actual), __LINE__, message)
|
||||
#define TEST_ASSERT_BIT_HIGH_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((_UU32)1 << bit), (_UU32)(-1), (actual), __LINE__, message)
|
||||
#define TEST_ASSERT_BIT_LOW_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((_UU32)1 << bit), (_UU32)(0), (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)
|
||||
#define TEST_ASSERT_UINT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN(delta, expected, actual, __LINE__, message)
|
||||
#define TEST_ASSERT_HEX_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN(delta, expected, actual, __LINE__, message)
|
||||
#define TEST_ASSERT_HEX8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX8_WITHIN(delta, expected, actual, __LINE__, message)
|
||||
#define TEST_ASSERT_HEX16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX16_WITHIN(delta, expected, actual, __LINE__, message)
|
||||
#define TEST_ASSERT_HEX32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN(delta, expected, actual, __LINE__, message)
|
||||
#define TEST_ASSERT_HEX64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, __LINE__, message)
|
||||
|
||||
//Structs and Strings
|
||||
#define TEST_ASSERT_EQUAL_PTR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_STRING(expected, actual, __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_MEMORY_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_MEMORY(expected, actual, len, __LINE__, message)
|
||||
|
||||
//Arrays
|
||||
#define TEST_ASSERT_EQUAL_INT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements, __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_INT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements, __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_INT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements, __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_INT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements, __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_INT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_UINT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements, __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements, __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_UINT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements, __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_UINT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements, __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_UINT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_HEX_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements, __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_HEX8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements, __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_HEX16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements, __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_HEX32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements, __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_HEX64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, __LINE__, message)
|
||||
#define TEST_ASSERT_EQUAL_PTR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements, __LINE__, message)
|
||||
#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)
|
||||
|
||||
//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)
|
||||
|
||||
//Double (If Enabled)
|
||||
#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)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,512 @@
|
||||
/* ==========================================
|
||||
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]
|
||||
========================================== */
|
||||
|
||||
#ifndef UNITY_INTERNALS_H
|
||||
#define UNITY_INTERNALS_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
//stdint.h is often automatically included.
|
||||
//Unity uses it to guess at the sizes of integer types, etc.
|
||||
#ifdef UNITY_USE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#ifndef UNITY_EXCLUDE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Guess Widths If Not Specified
|
||||
//-------------------------------------------------------
|
||||
|
||||
// If the INT Width hasn't been specified,
|
||||
// We first try to guess based on UINT_MAX (if it exists)
|
||||
// Otherwise we fall back on assuming 32-bit
|
||||
#ifndef UNITY_INT_WIDTH
|
||||
#ifdef UINT_MAX
|
||||
#if (UINT_MAX == 0xFFFF)
|
||||
#define UNITY_INT_WIDTH (16)
|
||||
#elif (UINT_MAX == 0xFFFFFFFF)
|
||||
#define UNITY_INT_WIDTH (32)
|
||||
#elif (UINT_MAX == 0xFFFFFFFFFFFFFFFF)
|
||||
#define UNITY_INT_WIDTH (64)
|
||||
#ifndef UNITY_SUPPORT_64
|
||||
#define UNITY_SUPPORT_64
|
||||
#endif
|
||||
#else
|
||||
#define UNITY_INT_WIDTH (32)
|
||||
#endif
|
||||
#else
|
||||
#define UNITY_INT_WIDTH (32)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// If the Long Width hasn't been specified,
|
||||
// We first try to guess based on ULONG_MAX (if it exists)
|
||||
// Otherwise we fall back on assuming 32-bit
|
||||
#ifndef UNITY_LONG_WIDTH
|
||||
#ifdef ULONG_MAX
|
||||
#if (ULONG_MAX == 0xFFFF)
|
||||
#define UNITY_LONG_WIDTH (16)
|
||||
#elif (ULONG_MAX == 0xFFFFFFFF)
|
||||
#define UNITY_LONG_WIDTH (32)
|
||||
#elif (ULONG_MAX == 0xFFFFFFFFFFFFFFFF)
|
||||
#define UNITY_LONG_WIDTH (64)
|
||||
#else
|
||||
#define UNITY_LONG_WIDTH (32)
|
||||
#ifndef UNITY_SUPPORT_64
|
||||
#define UNITY_SUPPORT_64
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#define UNITY_LONG_WIDTH (32)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// If the Pointer Width hasn't been specified,
|
||||
// We first try to guess based on INTPTR_MAX (if it exists)
|
||||
// Otherwise we fall back on assuming 32-bit
|
||||
#ifndef UNITY_POINTER_WIDTH
|
||||
#ifdef UINTPTR_MAX
|
||||
#if (UINTPTR_MAX <= 0xFFFF)
|
||||
#define UNITY_POINTER_WIDTH (16)
|
||||
#elif (UINTPTR_MAX <= 0xFFFFFFFF)
|
||||
#define UNITY_POINTER_WIDTH (32)
|
||||
#elif (UINTPTR_MAX <= 0xFFFFFFFFFFFFFFFF)
|
||||
#define UNITY_POINTER_WIDTH (64)
|
||||
#ifndef UNITY_SUPPORT_64
|
||||
#define UNITY_SUPPORT_64
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#ifndef UNITY_POINTER_WIDTH
|
||||
#ifdef INTPTR_MAX
|
||||
#if (INTPTR_MAX <= 0x7FFF)
|
||||
#define UNITY_POINTER_WIDTH (16)
|
||||
#elif (INTPTR_MAX <= 0x7FFFFFFF)
|
||||
#define UNITY_POINTER_WIDTH (32)
|
||||
#elif (INTPTR_MAX <= 0x7FFFFFFFFFFFFFFF)
|
||||
#define UNITY_POINTER_WIDTH (64)
|
||||
#ifndef UNITY_SUPPORT_64
|
||||
#define UNITY_SUPPORT_64
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#ifndef UNITY_POINTER_WIDTH
|
||||
#define UNITY_POINTER_WIDTH (32)
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Int Support
|
||||
//-------------------------------------------------------
|
||||
|
||||
#if (UNITY_INT_WIDTH == 32)
|
||||
typedef unsigned char _UU8;
|
||||
typedef unsigned short _UU16;
|
||||
typedef unsigned int _UU32;
|
||||
typedef signed char _US8;
|
||||
typedef signed short _US16;
|
||||
typedef signed int _US32;
|
||||
#elif (UNITY_INT_WIDTH == 16)
|
||||
typedef unsigned char _UU8;
|
||||
typedef unsigned int _UU16;
|
||||
typedef unsigned long _UU32;
|
||||
typedef signed char _US8;
|
||||
typedef signed int _US16;
|
||||
typedef signed long _US32;
|
||||
#else
|
||||
#error Invalid UNITY_INT_WIDTH specified! (16 or 32 are supported)
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 64-bit Support
|
||||
//-------------------------------------------------------
|
||||
|
||||
#ifndef UNITY_SUPPORT_64
|
||||
|
||||
//No 64-bit Support
|
||||
typedef _UU32 _U_UINT;
|
||||
typedef _US32 _U_SINT;
|
||||
|
||||
#else
|
||||
|
||||
//64-bit Support
|
||||
#if (UNITY_LONG_WIDTH == 32)
|
||||
typedef unsigned long long _UU64;
|
||||
typedef signed long long _US64;
|
||||
#elif (UNITY_LONG_WIDTH == 64)
|
||||
typedef unsigned long _UU64;
|
||||
typedef signed long _US64;
|
||||
#else
|
||||
#error Invalid UNITY_LONG_WIDTH specified! (32 or 64 are supported)
|
||||
#endif
|
||||
typedef _UU64 _U_UINT;
|
||||
typedef _US64 _U_SINT;
|
||||
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Pointer Support
|
||||
//-------------------------------------------------------
|
||||
|
||||
#ifndef UNITY_POINTER_WIDTH
|
||||
#define UNITY_POINTER_WIDTH (32)
|
||||
#endif /* UNITY_POINTER_WIDTH */
|
||||
|
||||
#if (UNITY_POINTER_WIDTH == 32)
|
||||
typedef _UU32 _UP;
|
||||
#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX32
|
||||
#elif (UNITY_POINTER_WIDTH == 64)
|
||||
#ifndef UNITY_SUPPORT_64
|
||||
#error "You've Specified 64-bit pointers without enabling 64-bit Support. Define UNITY_SUPPORT_64"
|
||||
#endif
|
||||
typedef _UU64 _UP;
|
||||
#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX64
|
||||
#elif (UNITY_POINTER_WIDTH == 16)
|
||||
typedef _UU16 _UP;
|
||||
#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX16
|
||||
#else
|
||||
#error Invalid UNITY_POINTER_WIDTH specified! (16, 32 or 64 are supported)
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Float Support
|
||||
//-------------------------------------------------------
|
||||
|
||||
#ifdef UNITY_EXCLUDE_FLOAT
|
||||
|
||||
//No Floating Point Support
|
||||
#undef UNITY_FLOAT_PRECISION
|
||||
#undef UNITY_FLOAT_TYPE
|
||||
#undef UNITY_FLOAT_VERBOSE
|
||||
|
||||
#else
|
||||
|
||||
//Floating Point Support
|
||||
#ifndef UNITY_FLOAT_PRECISION
|
||||
#define UNITY_FLOAT_PRECISION (0.00001f)
|
||||
#endif
|
||||
#ifndef UNITY_FLOAT_TYPE
|
||||
#define UNITY_FLOAT_TYPE float
|
||||
#endif
|
||||
typedef UNITY_FLOAT_TYPE _UF;
|
||||
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Double Float Support
|
||||
//-------------------------------------------------------
|
||||
|
||||
//unlike FLOAT, we DON'T include by default
|
||||
#ifndef UNITY_EXCLUDE_DOUBLE
|
||||
#ifndef UNITY_INCLUDE_DOUBLE
|
||||
#define UNITY_EXCLUDE_DOUBLE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef UNITY_EXCLUDE_DOUBLE
|
||||
|
||||
//No Floating Point Support
|
||||
#undef UNITY_DOUBLE_PRECISION
|
||||
#undef UNITY_DOUBLE_TYPE
|
||||
#undef UNITY_DOUBLE_VERBOSE
|
||||
|
||||
#else
|
||||
|
||||
//Floating Point Support
|
||||
#ifndef UNITY_DOUBLE_PRECISION
|
||||
#define UNITY_DOUBLE_PRECISION (1e-12f)
|
||||
#endif
|
||||
#ifndef UNITY_DOUBLE_TYPE
|
||||
#define UNITY_DOUBLE_TYPE double
|
||||
#endif
|
||||
typedef UNITY_DOUBLE_TYPE _UD;
|
||||
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Output Method
|
||||
//-------------------------------------------------------
|
||||
|
||||
#ifndef UNITY_OUTPUT_CHAR
|
||||
//Default to using putchar, which is defined in stdio.h above
|
||||
#define UNITY_OUTPUT_CHAR(a) putchar(a)
|
||||
#else
|
||||
//If defined as something else, make sure we declare it here so it's ready for use
|
||||
extern int UNITY_OUTPUT_CHAR(int);
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Footprint
|
||||
//-------------------------------------------------------
|
||||
|
||||
#ifndef UNITY_LINE_TYPE
|
||||
#define UNITY_LINE_TYPE _U_UINT
|
||||
#endif
|
||||
|
||||
#ifndef UNITY_COUNTER_TYPE
|
||||
#define UNITY_COUNTER_TYPE _U_UINT
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Internal Structs Needed
|
||||
//-------------------------------------------------------
|
||||
|
||||
typedef void (*UnityTestFunction)(void);
|
||||
|
||||
#define UNITY_DISPLAY_RANGE_INT (0x10)
|
||||
#define UNITY_DISPLAY_RANGE_UINT (0x20)
|
||||
#define UNITY_DISPLAY_RANGE_HEX (0x40)
|
||||
#define UNITY_DISPLAY_RANGE_AUTO (0x80)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
#if (UNITY_INT_WIDTH == 16)
|
||||
UNITY_DISPLAY_STYLE_INT = 2 + UNITY_DISPLAY_RANGE_INT + UNITY_DISPLAY_RANGE_AUTO,
|
||||
#elif (UNITY_INT_WIDTH == 32)
|
||||
UNITY_DISPLAY_STYLE_INT = 4 + UNITY_DISPLAY_RANGE_INT + UNITY_DISPLAY_RANGE_AUTO,
|
||||
#elif (UNITY_INT_WIDTH == 64)
|
||||
UNITY_DISPLAY_STYLE_INT = 8 + UNITY_DISPLAY_RANGE_INT + UNITY_DISPLAY_RANGE_AUTO,
|
||||
#endif
|
||||
UNITY_DISPLAY_STYLE_INT8 = 1 + UNITY_DISPLAY_RANGE_INT,
|
||||
UNITY_DISPLAY_STYLE_INT16 = 2 + UNITY_DISPLAY_RANGE_INT,
|
||||
UNITY_DISPLAY_STYLE_INT32 = 4 + UNITY_DISPLAY_RANGE_INT,
|
||||
#ifdef UNITY_SUPPORT_64
|
||||
UNITY_DISPLAY_STYLE_INT64 = 8 + UNITY_DISPLAY_RANGE_INT,
|
||||
#endif
|
||||
|
||||
#if (UNITY_INT_WIDTH == 16)
|
||||
UNITY_DISPLAY_STYLE_UINT = 2 + UNITY_DISPLAY_RANGE_UINT + UNITY_DISPLAY_RANGE_AUTO,
|
||||
#elif (UNITY_INT_WIDTH == 32)
|
||||
UNITY_DISPLAY_STYLE_UINT = 4 + UNITY_DISPLAY_RANGE_UINT + UNITY_DISPLAY_RANGE_AUTO,
|
||||
#elif (UNITY_INT_WIDTH == 64)
|
||||
UNITY_DISPLAY_STYLE_UINT = 8 + UNITY_DISPLAY_RANGE_UINT + UNITY_DISPLAY_RANGE_AUTO,
|
||||
#endif
|
||||
UNITY_DISPLAY_STYLE_UINT8 = 1 + UNITY_DISPLAY_RANGE_UINT,
|
||||
UNITY_DISPLAY_STYLE_UINT16 = 2 + UNITY_DISPLAY_RANGE_UINT,
|
||||
UNITY_DISPLAY_STYLE_UINT32 = 4 + UNITY_DISPLAY_RANGE_UINT,
|
||||
#ifdef UNITY_SUPPORT_64
|
||||
UNITY_DISPLAY_STYLE_UINT64 = 8 + UNITY_DISPLAY_RANGE_UINT,
|
||||
#endif
|
||||
UNITY_DISPLAY_STYLE_HEX8 = 1 + UNITY_DISPLAY_RANGE_HEX,
|
||||
UNITY_DISPLAY_STYLE_HEX16 = 2 + UNITY_DISPLAY_RANGE_HEX,
|
||||
UNITY_DISPLAY_STYLE_HEX32 = 4 + UNITY_DISPLAY_RANGE_HEX,
|
||||
#ifdef UNITY_SUPPORT_64
|
||||
UNITY_DISPLAY_STYLE_HEX64 = 8 + UNITY_DISPLAY_RANGE_HEX,
|
||||
#endif
|
||||
UNITY_DISPLAY_STYLE_UNKNOWN
|
||||
} UNITY_DISPLAY_STYLE_T;
|
||||
|
||||
struct _Unity
|
||||
{
|
||||
const char* TestFile;
|
||||
const char* CurrentTestName;
|
||||
UNITY_LINE_TYPE CurrentTestLineNumber;
|
||||
UNITY_COUNTER_TYPE NumberOfTests;
|
||||
UNITY_COUNTER_TYPE TestFailures;
|
||||
UNITY_COUNTER_TYPE TestIgnores;
|
||||
UNITY_COUNTER_TYPE CurrentTestFailed;
|
||||
UNITY_COUNTER_TYPE CurrentTestIgnored;
|
||||
jmp_buf AbortFrame;
|
||||
};
|
||||
|
||||
extern struct _Unity Unity;
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Test Suite Management
|
||||
//-------------------------------------------------------
|
||||
|
||||
void UnityBegin(void);
|
||||
int UnityEnd(void);
|
||||
void UnityConcludeTest(void);
|
||||
void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum);
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Test Output
|
||||
//-------------------------------------------------------
|
||||
|
||||
void UnityPrint(const char* string);
|
||||
void UnityPrintMask(const _U_UINT mask, const _U_UINT number);
|
||||
void UnityPrintNumberByStyle(const _U_SINT number, const UNITY_DISPLAY_STYLE_T style);
|
||||
void UnityPrintNumber(const _U_SINT number);
|
||||
void UnityPrintNumberUnsigned(const _U_UINT number);
|
||||
void UnityPrintNumberHex(const _U_UINT number, const char nibbles);
|
||||
|
||||
#ifdef UNITY_FLOAT_VERBOSE
|
||||
void UnityPrintFloat(const _UF number);
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Test Assertion Fuctions
|
||||
//-------------------------------------------------------
|
||||
// Use the macros below this section instead of calling
|
||||
// these directly. The macros have a consistent naming
|
||||
// convention and will pull in file and line information
|
||||
// for you.
|
||||
|
||||
void UnityAssertEqualNumber(const _U_SINT expected,
|
||||
const _U_SINT actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const UNITY_DISPLAY_STYLE_T style);
|
||||
|
||||
void UnityAssertEqualIntArray(const _U_SINT* expected,
|
||||
const _U_SINT* actual,
|
||||
const _UU32 num_elements,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const UNITY_DISPLAY_STYLE_T style);
|
||||
|
||||
void UnityAssertBits(const _U_SINT mask,
|
||||
const _U_SINT expected,
|
||||
const _U_SINT actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber);
|
||||
|
||||
void UnityAssertEqualString(const char* expected,
|
||||
const char* actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber);
|
||||
|
||||
void UnityAssertEqualStringArray( const char** expected,
|
||||
const char** actual,
|
||||
const _UU32 num_elements,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber);
|
||||
|
||||
void UnityAssertEqualMemory( const void* expected,
|
||||
const void* actual,
|
||||
const _UU32 length,
|
||||
const _UU32 num_elements,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber);
|
||||
|
||||
void UnityAssertNumbersWithin(const _U_SINT delta,
|
||||
const _U_SINT expected,
|
||||
const _U_SINT actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber,
|
||||
const UNITY_DISPLAY_STYLE_T style);
|
||||
|
||||
void UnityFail(const char* message, const UNITY_LINE_TYPE line);
|
||||
|
||||
void UnityIgnore(const char* message, const UNITY_LINE_TYPE line);
|
||||
|
||||
#ifndef UNITY_EXCLUDE_FLOAT
|
||||
void UnityAssertFloatsWithin(const _UF delta,
|
||||
const _UF expected,
|
||||
const _UF actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber);
|
||||
|
||||
void UnityAssertEqualFloatArray(const _UF* expected,
|
||||
const _UF* actual,
|
||||
const _UU32 num_elements,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber);
|
||||
#endif
|
||||
|
||||
#ifndef UNITY_EXCLUDE_DOUBLE
|
||||
void UnityAssertDoublesWithin(const _UD delta,
|
||||
const _UD expected,
|
||||
const _UD actual,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber);
|
||||
|
||||
void UnityAssertEqualDoubleArray(const _UD* expected,
|
||||
const _UD* actual,
|
||||
const _UU32 num_elements,
|
||||
const char* msg,
|
||||
const UNITY_LINE_TYPE lineNumber);
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Basic Fail and Ignore
|
||||
//-------------------------------------------------------
|
||||
|
||||
#define UNITY_TEST_FAIL(line, message) UnityFail( (message), (UNITY_LINE_TYPE)line);
|
||||
#define UNITY_TEST_IGNORE(line, message) UnityIgnore( (message), (UNITY_LINE_TYPE)line);
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Test Asserts
|
||||
//-------------------------------------------------------
|
||||
|
||||
#define UNITY_TEST_ASSERT(condition, line, message) if (condition) {} else {UNITY_TEST_FAIL((UNITY_LINE_TYPE)line, message);}
|
||||
#define UNITY_TEST_ASSERT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) == NULL), (UNITY_LINE_TYPE)line, message)
|
||||
#define UNITY_TEST_ASSERT_NOT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) != NULL), (UNITY_LINE_TYPE)line, message)
|
||||
|
||||
#define UNITY_TEST_ASSERT_EQUAL_INT(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)line, UNITY_DISPLAY_STYLE_INT)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_INT8(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US8 )(expected), (_U_SINT)(_US8 )(actual), (message), (UNITY_LINE_TYPE)line, UNITY_DISPLAY_STYLE_INT)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_INT16(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US16)(expected), (_U_SINT)(_US16)(actual), (message), (UNITY_LINE_TYPE)line, UNITY_DISPLAY_STYLE_INT)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_INT32(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US32)(expected), (_U_SINT)(_US32)(actual), (message), (UNITY_LINE_TYPE)line, UNITY_DISPLAY_STYLE_INT)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_UINT(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)line, UNITY_DISPLAY_STYLE_UINT)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_UINT8(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US8 )(expected), (_U_SINT)(_US8 )(actual), (message), (UNITY_LINE_TYPE)line, UNITY_DISPLAY_STYLE_UINT)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_UINT16(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US16)(expected), (_U_SINT)(_US16)(actual), (message), (UNITY_LINE_TYPE)line, UNITY_DISPLAY_STYLE_UINT)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_UINT32(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US32)(expected), (_U_SINT)(_US32)(actual), (message), (UNITY_LINE_TYPE)line, UNITY_DISPLAY_STYLE_UINT)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_HEX8(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US8 )(expected), (_U_SINT)(_US8 )(actual), (message), (UNITY_LINE_TYPE)line, UNITY_DISPLAY_STYLE_HEX8)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_HEX16(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US16)(expected), (_U_SINT)(_US16)(actual), (message), (UNITY_LINE_TYPE)line, UNITY_DISPLAY_STYLE_HEX16)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_HEX32(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_US32)(expected), (_U_SINT)(_US32)(actual), (message), (UNITY_LINE_TYPE)line, UNITY_DISPLAY_STYLE_HEX32)
|
||||
#define UNITY_TEST_ASSERT_BITS(mask, expected, actual, line, message) UnityAssertBits((_U_SINT)(mask), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)line)
|
||||
|
||||
#define UNITY_TEST_ASSERT_INT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_U_SINT)(delta), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)line, UNITY_DISPLAY_STYLE_INT)
|
||||
#define UNITY_TEST_ASSERT_UINT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_U_SINT)(delta), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)line, UNITY_DISPLAY_STYLE_UINT)
|
||||
#define UNITY_TEST_ASSERT_HEX8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_U_SINT)(_U_UINT)(_UU8 )(delta), (_U_SINT)(_U_UINT)(_UU8 )(expected), (_U_SINT)(_U_UINT)(_UU8 )(actual), (message), (UNITY_LINE_TYPE)line, UNITY_DISPLAY_STYLE_HEX8)
|
||||
#define UNITY_TEST_ASSERT_HEX16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_U_SINT)(_U_UINT)(_UU16)(delta), (_U_SINT)(_U_UINT)(_UU16)(expected), (_U_SINT)(_U_UINT)(_UU16)(actual), (message), (UNITY_LINE_TYPE)line, UNITY_DISPLAY_STYLE_HEX16)
|
||||
#define UNITY_TEST_ASSERT_HEX32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_U_SINT)(_U_UINT)(_UU32)(delta), (_U_SINT)(_U_UINT)(_UU32)(expected), (_U_SINT)(_U_UINT)(_UU32)(actual), (message), (UNITY_LINE_TYPE)line, UNITY_DISPLAY_STYLE_HEX32)
|
||||
|
||||
#define UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(_UP)(expected), (_U_SINT)(_UP)(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_MEMORY(expected, actual, len, line, message) UnityAssertEqualMemory((void*)(expected), (void*)(actual), (_UU32)(len), 1, (message), (UNITY_LINE_TYPE)line)
|
||||
|
||||
#define UNITY_TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((const _U_SINT*)(expected), (const _U_SINT*)(actual), (_UU32)(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((const _U_SINT*)(expected), (const _U_SINT*)(actual), (_UU32)(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((const _U_SINT*)(expected), (const _U_SINT*)(actual), (_UU32)(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((const _U_SINT*)(expected), (const _U_SINT*)(actual), (_UU32)(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((const _U_SINT*)(expected), (const _U_SINT*)(actual), (_UU32)(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((const _U_SINT*)(expected), (const _U_SINT*)(actual), (_UU32)(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((const _U_SINT*)(expected), (const _U_SINT*)(actual), (_UU32)(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((const _U_SINT*)(expected), (const _U_SINT*)(actual), (_UU32)(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((const _U_SINT*)(expected), (const _U_SINT*)(actual), (_UU32)(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((const _U_SINT*)(expected), (const _U_SINT*)(actual), (_UU32)(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((const _U_SINT*)(expected), (const _U_SINT*)(actual), (_UU32)(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((const _U_SINT*)(_UP*)(expected), (const _U_SINT*)(_UP*)(actual), (_UU32)(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), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)line)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((void*)(expected), (void*)(actual), (_UU32)(len), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)line)
|
||||
|
||||
#ifdef UNITY_SUPPORT_64
|
||||
#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)line, UNITY_DISPLAY_STYLE_INT64)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)line, UNITY_DISPLAY_STYLE_UINT64)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UnityAssertEqualNumber((_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)line, UNITY_DISPLAY_STYLE_HEX64)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((const _U_SINT*)(expected), (const _U_SINT*)(actual), (_UU32)(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((const _U_SINT*)(expected), (const _U_SINT*)(actual), (_UU32)(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((const _U_SINT*)(expected), (const _U_SINT*)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)line, UNITY_DISPLAY_STYLE_HEX64)
|
||||
#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((_U_SINT)(delta), (_U_SINT)(expected), (_U_SINT)(actual), NULL, (UNITY_LINE_TYPE)line, UNITY_DISPLAY_STYLE_HEX64)
|
||||
#endif
|
||||
|
||||
#ifdef UNITY_EXCLUDE_FLOAT
|
||||
#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)line, "Unity Floating Point Disabled")
|
||||
#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)line, "Unity Floating Point Disabled")
|
||||
#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)line, "Unity Floating Point Disabled")
|
||||
#else
|
||||
#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsWithin((_UF)(delta), (_UF)(expected), (_UF)(actual), (message), (UNITY_LINE_TYPE)line)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((_UF)(expected) * (_UF)UNITY_FLOAT_PRECISION, (_UF)expected, (_UF)actual, (UNITY_LINE_TYPE)line, message)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualFloatArray((_UF*)(expected), (_UF*)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)line)
|
||||
#endif
|
||||
|
||||
#ifdef UNITY_EXCLUDE_DOUBLE
|
||||
#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)line, "Unity Double Precision Disabled")
|
||||
#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)line, "Unity Double Precision Disabled")
|
||||
#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)line, "Unity Double Precision Disabled")
|
||||
#else
|
||||
#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesWithin((_UD)(delta), (_UD)(expected), (_UD)(actual), (message), (UNITY_LINE_TYPE)line)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((_UF)(expected) * (_UD)UNITY_DOUBLE_PRECISION, (_UD)expected, (_UD)actual, (UNITY_LINE_TYPE)line, message)
|
||||
#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualDoubleArray((_UD*)(expected), (_UD*)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)line)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user