summaryrefslogtreecommitdiff
path: root/FreeRTOS-Plus/Test/CMock/lib
diff options
context:
space:
mode:
Diffstat (limited to 'FreeRTOS-Plus/Test/CMock/lib')
-rw-r--r--FreeRTOS-Plus/Test/CMock/lib/cmock.rb104
-rw-r--r--FreeRTOS-Plus/Test/CMock/lib/cmock_config.rb173
-rw-r--r--FreeRTOS-Plus/Test/CMock/lib/cmock_file_writer.rb48
-rw-r--r--FreeRTOS-Plus/Test/CMock/lib/cmock_generator.rb333
-rw-r--r--FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_array.rb63
-rw-r--r--FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_callback.rb88
-rw-r--r--FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_cexception.rb49
-rw-r--r--FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_expect.rb100
-rw-r--r--FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_expect_any_args.rb50
-rw-r--r--FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_ignore.rb88
-rw-r--r--FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_ignore_arg.rb42
-rw-r--r--FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_return_thru_ptr.rb79
-rw-r--r--FreeRTOS-Plus/Test/CMock/lib/cmock_generator_utils.rb247
-rw-r--r--FreeRTOS-Plus/Test/CMock/lib/cmock_header_parser.rb595
-rw-r--r--FreeRTOS-Plus/Test/CMock/lib/cmock_plugin_manager.rb50
-rw-r--r--FreeRTOS-Plus/Test/CMock/lib/cmock_unityhelper_parser.rb77
16 files changed, 2186 insertions, 0 deletions
diff --git a/FreeRTOS-Plus/Test/CMock/lib/cmock.rb b/FreeRTOS-Plus/Test/CMock/lib/cmock.rb
new file mode 100644
index 000000000..b4dbab57d
--- /dev/null
+++ b/FreeRTOS-Plus/Test/CMock/lib/cmock.rb
@@ -0,0 +1,104 @@
+# ==========================================
+# 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 "#{__dir__}/#{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
+
+ def setup_skeletons(files)
+ [files].flatten.each do |src|
+ generate_skeleton src
+ end
+ end
+
+ private ###############################
+
+ def generate_mock(src)
+ name = File.basename(src, '.*')
+ ext = File.extname(src)
+ puts "Creating mock for #{name}..." unless @silent
+ @cm_generator.create_mock(name, @cm_parser.parse(name, File.read(src)), ext)
+ end
+
+ def generate_skeleton(src)
+ name = File.basename(src, '.*')
+ puts "Creating skeleton for #{name}..." unless @silent
+ @cm_generator.create_skeleton(name, @cm_parser.parse(name, File.read(src)))
+ end
+end
+
+def option_maker(options, key, val)
+ options ||= {}
+ options[key.to_sym] =
+ if val.chr == ':'
+ val[1..-1].to_sym
+ elsif val.include? ';'
+ val.split(';')
+ elsif val == 'true'
+ true
+ elsif val == 'false'
+ false
+ elsif val =~ /^\d+$/
+ val.to_i
+ else
+ val
+ end
+ options
+end
+
+# Command Line Support ###############################
+
+if $0 == __FILE__
+ usage = "usage: ruby #{__FILE__} (-oOptionsFile) File(s)ToMock"
+
+ unless ARGV[0]
+ puts usage
+ exit 1
+ end
+
+ options = {}
+ filelist = []
+ ARGV.each do |arg|
+ if arg =~ /^-o\"?([a-zA-Z0-9._\\\/:\s]+)\"?/
+ options.merge! CMockConfig.load_config_file_from_yaml(arg.gsub(/^-o/, ''))
+ elsif arg == '--skeleton'
+ options[:skeleton] = true
+ elsif arg =~ /^--([a-zA-Z0-9._\\\/:\s]+)=\"?([a-zA-Z0-9._\-\\\/:\s\;]+)\"?/
+ options = option_maker(options, Regexp.last_match(1), Regexp.last_match(2))
+ else
+ filelist << arg
+ end
+ end
+
+ if options[:skeleton]
+ CMock.new(options).setup_skeletons(filelist)
+ else
+ CMock.new(options).setup_mocks(filelist)
+ end
+end
diff --git a/FreeRTOS-Plus/Test/CMock/lib/cmock_config.rb b/FreeRTOS-Plus/Test/CMock/lib/cmock_config.rb
new file mode 100644
index 000000000..9515481c9
--- /dev/null
+++ b/FreeRTOS-Plus/Test/CMock/lib/cmock_config.rb
@@ -0,0 +1,173 @@
+# ==========================================
+# 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
+ CMOCK_DEFAULT_OPTIONS =
+ {
+ :framework => :unity,
+ :mock_path => 'mocks',
+ :mock_prefix => 'Mock',
+ :mock_suffix => '',
+ :skeleton_path => '',
+ :weak => '',
+ :subdir => nil,
+ :plugins => [],
+ :strippables => ['(?:__attribute__\s*\(+.*?\)+)'],
+ :attributes => %w[__ramfunc __irq __fiq register extern],
+ :c_calling_conventions => %w[__stdcall __cdecl __fastcall],
+ :enforce_strict_ordering => false,
+ :fail_on_unexpected_calls => true,
+ :unity_helper_path => false,
+ :treat_as => {},
+ :treat_as_array => {},
+ :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
+ :treat_inlines => :exclude, # the options being :include or :exclude
+ :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,
+ :orig_header_include_fmt => '#include "%s"',
+ :array_size_type => [],
+ :array_size_name => 'size|len',
+ :skeleton => false,
+
+ # Format to look for inline functions.
+ # This is a combination of "static" and "inline" keywords ("static inline", "inline static", "inline", "static")
+ # There are several possibilities:
+ # - sometimes they appear together, sometimes individually,
+ # - The keywords can appear before or after the return type (this is a compiler warning but people do weird stuff),
+ # so we check for word boundaries when searching for them
+ # - We first remove "static inline" combinations and boil down to single inline or static statements
+ :inline_function_patterns => ['(static\s+inline|inline\s+static)\s*', '(\bstatic\b|\binline\b)\s*'] # Last part (\s*) is just to remove whitespaces (only to prettify the output)
+ }.freeze
+
+ def initialize(options = nil)
+ case options
+ when NilClass then options = CMOCK_DEFAULT_OPTIONS.dup
+ when String then options = CMOCK_DEFAULT_OPTIONS.dup.merge(load_config_file_from_yaml(options))
+ when Hash then options = CMOCK_DEFAULT_OPTIONS.dup.merge(options)
+ else raise 'If you specify arguments, it should be a filename or a hash of options'
+ end
+
+ # do some quick type verification
+ %i[plugins attributes treat_as_void].each do |opt|
+ unless options[opt].class == Array
+ options[opt] = []
+ puts "WARNING: :#{opt} should be an array." unless options[:verbosity] < 1
+ end
+ end
+ %i[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? || (options[opt].class == Array)
+ options[opt] = []
+ puts "WARNING: :#{opt} should be an array." unless options[:verbosity] < 1
+ end
+ end
+ options[:unity_helper_path] ||= options[:unity_helper]
+ options[:unity_helper_path] = [options[:unity_helper_path]] if options[:unity_helper_path].is_a? String
+
+ if options[:unity_helper_path]
+ require 'pathname'
+ includes1 = options[:includes_c_post_header] || []
+ includes2 = options[:unity_helper_path].map do |path|
+ Pathname(path).relative_path_from(Pathname(options[:mock_path])).to_s
+ end
+ options[:includes_c_post_header] = (includes1 + includes2).uniq
+ end
+
+ options[:plugins].compact!
+ options[:plugins].map!(&: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 do |key|
+ unless methods.include?(key)
+ eval("def #{key}() return @options[:#{key}] end")
+ end
+ end
+ end
+
+ def load_config_file_from_yaml(yaml_filename)
+ self.class.load_config_file_from_yaml yaml_filename
+ end
+
+ def self.load_config_file_from_yaml(yaml_filename)
+ require 'yaml'
+ require 'fileutils'
+ YAML.load_file(yaml_filename)[:cmock]
+ end
+
+ def path(new_path)
+ @src_path = new_path
+ end
+
+ def load_unity_helper
+ return nil unless @options[:unity_helper_path]
+
+ @options[:unity_helper_path].inject('') do |unity_helper, filename|
+ unity_helper + "\n" + File.new(filename).read
+ end
+ 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*' => 'HEX8_ARRAY',
+ 'void const*' => 'HEX8_ARRAY',
+ 'const void*' => 'HEX8_ARRAY',
+ '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',
+ 'char const*' => 'STRING',
+ 'const char*' => 'STRING',
+ 'pCHAR' => 'STRING',
+ 'cstring' => 'STRING',
+ 'CSTRING' => 'STRING',
+ 'float' => 'FLOAT',
+ 'double' => 'FLOAT'
+ }
+ end
+end
diff --git a/FreeRTOS-Plus/Test/CMock/lib/cmock_file_writer.rb b/FreeRTOS-Plus/Test/CMock/lib/cmock_file_writer.rb
new file mode 100644
index 000000000..787d688e1
--- /dev/null
+++ b/FreeRTOS-Plus/Test/CMock/lib/cmock_file_writer.rb
@@ -0,0 +1,48 @@
+# ==========================================
+# 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_subdir(subdir)
+ require 'fileutils'
+ FileUtils.mkdir_p "#{@config.mock_path}/" unless Dir.exist?("#{@config.mock_path}/")
+ FileUtils.mkdir_p "#{@config.mock_path}/#{subdir + '/' if subdir}" if subdir && !Dir.exist?("#{@config.mock_path}/#{subdir + '/' if subdir}")
+ end
+
+ def create_file(filename, subdir)
+ raise "Where's the block of data to create?" unless block_given?
+
+ full_file_name_temp = "#{@config.mock_path}/#{subdir + '/' if subdir}#{filename}.new"
+ full_file_name_done = "#{@config.mock_path}/#{subdir + '/' if subdir}#{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
+
+ def append_file(filename, subdir)
+ raise "Where's the block of data to create?" unless block_given?
+
+ full_file_name = "#{@config.skeleton_path}/#{subdir + '/' if subdir}#{filename}"
+ File.open(full_file_name, 'a') do |file|
+ yield(file, filename)
+ end
+ 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
diff --git a/FreeRTOS-Plus/Test/CMock/lib/cmock_generator.rb b/FreeRTOS-Plus/Test/CMock/lib/cmock_generator.rb
new file mode 100644
index 000000000..f08cadd77
--- /dev/null
+++ b/FreeRTOS-Plus/Test/CMock/lib/cmock_generator.rb
@@ -0,0 +1,333 @@
+# ==========================================
+# 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 CMockGenerator
+ attr_accessor :config, :file_writer, :module_name, :module_ext, :clean_mock_name, :mock_name, :utils, :plugins, :weak, :ordered
+
+ def initialize(config, file_writer, utils, plugins)
+ @file_writer = file_writer
+ @utils = utils
+ @plugins = plugins
+ @config = config
+ @prefix = @config.mock_prefix
+ @suffix = @config.mock_suffix
+ @weak = @config.weak
+ @include_inline = @config.treat_inlines
+ @ordered = @config.enforce_strict_ordering
+ @framework = @config.framework.to_s
+ @fail_on_unexpected_calls = @config.fail_on_unexpected_calls
+
+ @subdir = @config.subdir
+
+ @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}\"" }
+
+ here = File.dirname __FILE__
+ unity_path_in_ceedling = "#{here}/../../unity" # path to Unity from within Ceedling
+ unity_path_in_cmock = "#{here}/../vendor/unity" # path to Unity from within CMock
+ # path to Unity as specified by env var
+ unity_path_in_env = ENV.key?('UNITY_DIR') ? File.expand_path(ENV.fetch('UNITY_DIR')) : nil
+
+ if unity_path_in_env && File.exist?(unity_path_in_env)
+ require "#{unity_path_in_env}/auto/type_sanitizer"
+ elsif File.exist? unity_path_in_ceedling
+ require "#{unity_path_in_ceedling}/auto/type_sanitizer"
+ elsif File.exist? unity_path_in_cmock
+ require "#{unity_path_in_cmock}/auto/type_sanitizer"
+ else
+ raise 'Failed to find an instance of Unity to pull in type_sanitizer module!'
+ end
+ end
+
+ def create_mock(module_name, parsed_stuff, module_ext = nil)
+ @module_name = module_name
+ @module_ext = module_ext || '.h'
+ @mock_name = @prefix + @module_name + @suffix
+ @clean_mock_name = TypeSanitizer.sanitize_c_identifier(@mock_name)
+ create_mock_subdir
+ create_mock_header_file(parsed_stuff)
+ create_mock_source_file(parsed_stuff)
+ end
+
+ def create_skeleton(module_name, parsed_stuff)
+ @module_name = module_name
+ create_skeleton_source_file(parsed_stuff)
+ end
+
+ private if $ThisIsOnlyATest.nil? ##############################
+
+ def create_mock_subdir
+ @file_writer.create_subdir(@subdir)
+ end
+
+ def create_using_statement(file, function)
+ file << "using namespace #{function[:namespace].join('::')};\n" unless function[:namespace].empty?
+ end
+
+ def create_mock_header_file(parsed_stuff)
+ if @include_inline == :include
+ @file_writer.create_file(@module_name + (@module_ext || '.h'), @subdir) do |file, _filename|
+ file << parsed_stuff[:normalized_source]
+ end
+ end
+
+ @file_writer.create_file(@mock_name + (@module_ext || '.h'), @subdir) 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|
+ create_using_statement(file, 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', @subdir) do |file, filename|
+ create_source_header_section(file, filename, parsed_stuff[:functions])
+ 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_skeleton_source_file(parsed_stuff)
+ filename = "#{@config.mock_path}/#{@subdir + '/' if @subdir}#{module_name}.c"
+ existing = File.exist?(filename) ? File.read(filename) : ''
+ @file_writer.append_file(@module_name + '.c', @subdir) do |file, fullname|
+ create_source_header_section(file, fullname, []) if existing.empty?
+ parsed_stuff[:functions].each do |function|
+ create_function_skeleton(file, function, existing)
+ end
+ end
+ end
+
+ def create_mock_header_header(file, _filename)
+ define_name = @clean_mock_name.upcase
+ orig_filename = (@subdir ? @subdir + '/' : '') + @module_name + (@module_ext || '.h')
+ file << "/* AUTOGENERATED FILE. DO NOT EDIT. */\n"
+ file << "#ifndef _#{define_name}_H\n"
+ file << "#define _#{define_name}_H\n\n"
+ file << "#include \"#{@framework}.h\"\n"
+ @includes_h_pre_orig_header.each { |inc| file << "#include #{inc}\n" }
+ file << @config.orig_header_include_fmt.gsub(/%s/, orig_filename.to_s) + "\n"
+ @includes_h_post_orig_header.each { |inc| file << "#include #{inc}\n" }
+ plugin_includes = @plugins.run(:include_files)
+ file << plugin_includes unless plugin_includes.empty?
+ file << "\n"
+ file << "/* Ignore the following warnings, since we are copying code */\n"
+ file << "#if defined(__GNUC__) && !defined(__ICC) && !defined(__TMS470__)\n"
+ file << "#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 6 || (__GNUC_MINOR__ == 6 && __GNUC_PATCHLEVEL__ > 0)))\n"
+ file << "#pragma GCC diagnostic push\n"
+ file << "#endif\n"
+ file << "#if !defined(__clang__)\n"
+ file << "#pragma GCC diagnostic ignored \"-Wpragmas\"\n"
+ file << "#endif\n"
+ file << "#pragma GCC diagnostic ignored \"-Wunknown-pragmas\"\n"
+ file << "#pragma GCC diagnostic ignored \"-Wduplicate-decl-specifier\"\n"
+ file << "#endif\n"
+ 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 #{@clean_mock_name}_Init(void);\n"
+ file << "void #{@clean_mock_name}_Destroy(void);\n"
+ file << "void #{@clean_mock_name}_Verify(void);\n\n"
+ end
+
+ def create_mock_header_footer(header)
+ header << "\n"
+ header << "#if defined(__GNUC__) && !defined(__ICC) && !defined(__TMS470__)\n"
+ header << "#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 6 || (__GNUC_MINOR__ == 6 && __GNUC_PATCHLEVEL__ > 0)))\n"
+ header << "#pragma GCC diagnostic pop\n"
+ header << "#endif\n"
+ header << "#endif\n"
+ header << "\n"
+ header << "#endif\n"
+ end
+
+ def create_source_header_section(file, filename, functions)
+ header_file = (@subdir ? @subdir + '/' : '') + filename.gsub('.c', (@module_ext || '.h'))
+ file << "/* AUTOGENERATED FILE. DO NOT EDIT. */\n" unless functions.empty?
+ file << "#include <string.h>\n"
+ file << "#include <stdlib.h>\n"
+ file << "#include <setjmp.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"
+ strs = []
+ functions.each do |func|
+ strs << func[:name]
+ func[:args].each { |arg| strs << arg[:name] }
+ end
+ strs.uniq.sort.each do |str|
+ file << "static const char* CMockString_#{str} = \"#{str}\";\n"
+ end
+ 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 #{@clean_mock_name}Instance\n{\n"
+ if functions.empty?
+ 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 #{@clean_mock_name}_Verify(void)\n{\n"
+ verifications = functions.collect do |function|
+ v = @plugins.run(:mock_verify, function)
+ v.empty? ? v : [" call_instance = Mock.#{function[:name]}_CallInstance;\n", v]
+ end.join
+ unless verifications.empty?
+ file << " UNITY_LINE_TYPE cmock_line = TEST_LINE_NUM;\n"
+ file << " CMOCK_MEM_INDEX_TYPE call_instance;\n"
+ file << verifications
+ end
+ file << "}\n\n"
+ end
+
+ def create_mock_init_function(file)
+ file << "void #{@clean_mock_name}_Init(void)\n{\n"
+ file << " #{@clean_mock_name}_Destroy();\n"
+ file << "}\n\n"
+ end
+
+ def create_mock_destroy_function(file, functions)
+ file << "void #{@clean_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
+
+ unless @fail_on_unexpected_calls
+ file << functions.collect { |function| @plugins.run(:mock_ignore, function) }.join
+ end
+
+ 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?
+
+ # Encapsulate in namespace(s) if applicable
+ function[:namespace].each do |ns|
+ file << "namespace #{ns} {\n"
+ end
+
+ # Determine class prefix (if any)
+ cls_pre = ''
+ unless function[:class].nil?
+ cls_pre = "#{function[:class]}::"
+ end
+
+ # Create mock function
+ unless @weak.empty?
+ file << "#if defined (__IAR_SYSTEMS_ICC__)\n"
+ file << "#pragma weak #{function[:unscoped_name]}\n"
+ file << "#else\n"
+ file << "#{function_mod_and_rettype} #{function[:unscoped_name]}(#{args_string}) #{weak};\n"
+ file << "#endif\n\n"
+ end
+ file << "#{function_mod_and_rettype} #{cls_pre}#{function[:unscoped_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;\n"
+ file << " UNITY_SET_DETAIL(CMockString_#{function[:name]});\n"
+ file << " 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, CMockStringCalledMore);\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, CMockStringCalledEarly);\n"
+ file << " if (cmock_call_instance->CallOrder < GlobalVerifyOrder)\n"
+ file << " UNITY_TEST_FAIL(cmock_line, CMockStringCalledLate);\n"
+ end
+ file << @plugins.run(:mock_implementation, function)
+ file << " UNITY_CLR_DETAILS();\n"
+ file << " return cmock_call_instance->ReturnVal;\n" unless function[:return][:void?]
+ file << "}\n"
+
+ # Close any namespace(s) opened above
+ function[:namespace].each do
+ file << "}\n"
+ end
+
+ file << "\n"
+ end
+
+ def create_mock_interfaces(file, function)
+ file << @utils.code_add_argument_loader(function)
+ file << @plugins.run(:mock_interfaces, function)
+ end
+
+ def create_function_skeleton(file, function, existing)
+ # 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?
+
+ decl = "#{function_mod_and_rettype} #{function[:name]}(#{args_string})"
+
+ return if existing.include?(decl)
+
+ file << "#{decl}\n"
+ file << "{\n"
+ file << " /*TODO: Implement Me!*/\n"
+ function[:args].each { |arg| file << " (void)#{arg[:name]};\n" }
+ file << " return (#{(function[:return][:type])})0;\n" unless function[:return][:void?]
+ file << "}\n\n"
+ end
+end
diff --git a/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_array.rb b/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_array.rb
new file mode 100644
index 000000000..a9864ab74
--- /dev/null
+++ b/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_array.rb
@@ -0,0 +1,63 @@
+# ==========================================
+# 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]).to_s }.join(', ')
+ args_string = function[:args].map do |m|
+ type = @utils.arg_type_with_const(m)
+ m[:ptr?] ? "#{type} #{m[:name]}, int #{m[:name]}_Depth" : "#{type} #{m[:name]}"
+ end.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 do |m|
+ type = @utils.arg_type_with_const(m)
+ m[:ptr?] ? "#{type} #{m[:name]}, int #{m[:name]}_Depth" : "#{type} #{m[:name]}"
+ end.join(', ')
+ call_string = function[:args].map { |m| m[:ptr?] ? "#{m[:name]}, #{m[:name]}_Depth" : m[:name] }.join(', ')
+ lines << if function[:return][:void?]
+ "void #{func_name}_CMockExpectWithArray(UNITY_LINE_TYPE cmock_line, #{args_string})\n"
+ else
+ "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
diff --git a/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_callback.rb b/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_callback.rb
new file mode 100644
index 000000000..6ba8e9bd9
--- /dev/null
+++ b/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_callback.rb
@@ -0,0 +1,88 @@
+# ==========================================
+# 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
+ end
+
+ def instance_structure(function)
+ func_name = function[:name]
+ " char #{func_name}_CallbackBool;\n" \
+ " 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][:type]
+ action = @config.callback_after_arg_check ? 'AddCallback' : 'Stub'
+ 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]});\n" \
+ "void #{func_name}_AddCallback(CMOCK_#{func_name}_CALLBACK Callback);\n" \
+ "void #{func_name}_Stub(CMOCK_#{func_name}_CALLBACK Callback);\n" \
+ "#define #{func_name}_StubWithCallback #{func_name}_#{action}\n"
+ end
+
+ def generate_call(function)
+ args = function[:args].map { |m| m[:name] }
+ args << "Mock.#{function[:name]}_CallbackCalls++" if @include_count
+ "Mock.#{function[:name]}_CallbackFunctionPointer(#{args.join(', ')})"
+ end
+
+ def mock_implementation(function)
+ " if (Mock.#{function[:name]}_CallbackFunctionPointer != NULL)\n {\n" +
+ if function[:return][:void?]
+ " #{generate_call(function)};\n }\n"
+ else
+ " cmock_call_instance->ReturnVal = #{generate_call(function)};\n }\n"
+ end
+ end
+
+ def mock_implementation_precheck(function)
+ " if (!Mock.#{function[:name]}_CallbackBool &&\n" \
+ " Mock.#{function[:name]}_CallbackFunctionPointer != NULL)\n {\n" +
+ if function[:return][:void?]
+ " #{generate_call(function)};\n" \
+ " UNITY_CLR_DETAILS();\n" \
+ " return;\n }\n"
+ else
+ " #{function[:return][:type]} cmock_cb_ret = #{generate_call(function)};\n" \
+ " UNITY_CLR_DETAILS();\n" \
+ " return cmock_cb_ret;\n }\n"
+ end
+ end
+
+ def mock_interfaces(function)
+ func_name = function[:name]
+ has_ignore = @config.plugins.include? :ignore
+ lines = ''
+ lines << "void #{func_name}_AddCallback(CMOCK_#{func_name}_CALLBACK Callback)\n{\n"
+ lines << " Mock.#{func_name}_IgnoreBool = (char)0;\n" if has_ignore
+ lines << " Mock.#{func_name}_CallbackBool = (char)1;\n"
+ lines << " Mock.#{func_name}_CallbackFunctionPointer = Callback;\n}\n\n"
+ lines << "void #{func_name}_Stub(CMOCK_#{func_name}_CALLBACK Callback)\n{\n"
+ lines << " Mock.#{func_name}_IgnoreBool = (char)0;\n" if has_ignore
+ lines << " Mock.#{func_name}_CallbackBool = (char)0;\n"
+ lines << " Mock.#{func_name}_CallbackFunctionPointer = Callback;\n}\n\n"
+ end
+
+ def mock_verify(function)
+ func_name = function[:name]
+ " if (Mock.#{func_name}_CallbackFunctionPointer != NULL)\n {\n" \
+ " call_instance = CMOCK_GUTS_NONE;\n" \
+ " (void)call_instance;\n }\n"
+ end
+end
diff --git a/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_cexception.rb b/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_cexception.rb
new file mode 100644
index 000000000..a757669e6
--- /dev/null
+++ b/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_cexception.rb
@@ -0,0 +1,49 @@
+# ==========================================
+# 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
+ "#include \"CException.h\"\n"
+ end
+
+ def instance_typedefs(_function)
+ " CEXCEPTION_T ExceptionToThrow;\n"
+ end
+
+ def mock_function_declarations(function)
+ if function[:args_string] == 'void'
+ "#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
+ "#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" \
+ " UNITY_CLR_DETAILS();\n" \
+ " Throw(cmock_call_instance->ExceptionToThrow);\n }\n"
+ end
+
+ def mock_interfaces(function)
+ arg_insert = function[:args_string] == 'void' ? '' : "#{function[:args_string]}, "
+ ["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
diff --git a/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_expect.rb b/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_expect.rb
new file mode 100644
index 000000000..3a79c1a4d
--- /dev/null
+++ b/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_expect.rb
@@ -0,0 +1,100 @@
+# ==========================================
+# 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
+
+ if @config.plugins.include? :expect_any_args
+ alias :mock_implementation :mock_implementation_might_check_args
+ else
+ alias :mock_implementation :mock_implementation_always_check_args
+ end
+ 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?]
+ "#define #{function[:name]}_Expect() #{function[:name]}_CMockExpect(__LINE__)\n" \
+ "void #{function[:name]}_CMockExpect(UNITY_LINE_TYPE cmock_line);\n"
+ else
+ "#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
+ elsif function[:return][:void?]
+ "#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
+ "#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
+
+ def mock_implementation_always_check_args(function)
+ lines = ''
+ function[:args].each do |arg|
+ lines << @utils.code_verify_an_arg_expectation(function, arg)
+ end
+ lines
+ end
+
+ def mock_implementation_might_check_args(function)
+ return '' if function[:args].empty?
+
+ lines = " if (!cmock_call_instance->ExpectAnyArgsBool)\n {\n"
+ function[:args].each do |arg|
+ lines << @utils.code_verify_an_arg_expectation(function, arg)
+ end
+ lines << " }\n"
+ lines
+ end
+
+ def mock_interfaces(function)
+ lines = ''
+ func_name = function[:name]
+ lines << if function[:return][:void?]
+ if function[:args_string] == 'void'
+ "void #{func_name}_CMockExpect(UNITY_LINE_TYPE cmock_line)\n{\n"
+ else
+ "void #{func_name}_CMockExpect(UNITY_LINE_TYPE cmock_line, #{function[:args_string]})\n{\n"
+ end
+ elsif function[:args_string] == 'void'
+ "void #{func_name}_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]})\n{\n"
+ else
+ "void #{func_name}_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:args_string]}, #{function[:return][:str]})\n{\n"
+ 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)
+ " if (CMOCK_GUTS_NONE != call_instance)\n" \
+ " {\n" \
+ " UNITY_SET_DETAIL(CMockString_#{function[:name]});\n" \
+ " UNITY_TEST_FAIL(cmock_line, CMockStringCalledLess);\n" \
+ " }\n"
+ end
+end
diff --git a/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_expect_any_args.rb b/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_expect_any_args.rb
new file mode 100644
index 000000000..0fc88e124
--- /dev/null
+++ b/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_expect_any_args.rb
@@ -0,0 +1,50 @@
+# ==========================================
+# 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 CMockGeneratorPluginExpectAnyArgs
+ attr_reader :priority
+ attr_reader :config, :utils
+
+ def initialize(config, utils)
+ @config = config
+ @utils = utils
+ @priority = 3
+ end
+
+ def instance_typedefs(_function)
+ " char ExpectAnyArgsBool;\n"
+ end
+
+ def mock_function_declarations(function)
+ if function[:args].empty?
+ ''
+ elsif function[:return][:void?]
+ "#define #{function[:name]}_ExpectAnyArgs() #{function[:name]}_CMockExpectAnyArgs(__LINE__)\n" \
+ "void #{function[:name]}_CMockExpectAnyArgs(UNITY_LINE_TYPE cmock_line);\n"
+ else
+ "#define #{function[:name]}_ExpectAnyArgsAndReturn(cmock_retval) #{function[:name]}_CMockExpectAnyArgsAndReturn(__LINE__, cmock_retval)\n" \
+ "void #{function[:name]}_CMockExpectAnyArgsAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]});\n"
+ end
+ end
+
+ def mock_interfaces(function)
+ lines = ''
+ unless function[:args].empty?
+ lines << if function[:return][:void?]
+ "void #{function[:name]}_CMockExpectAnyArgs(UNITY_LINE_TYPE cmock_line)\n{\n"
+ else
+ "void #{function[:name]}_CMockExpectAnyArgsAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]})\n{\n"
+ end
+ lines << @utils.code_add_base_expectation(function[:name], true)
+ unless function[:return][:void?]
+ lines << " cmock_call_instance->ReturnVal = cmock_to_return;\n"
+ end
+ lines << " cmock_call_instance->ExpectAnyArgsBool = (char)1;\n"
+ lines << "}\n\n"
+ end
+ lines
+ end
+end
diff --git a/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_ignore.rb b/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_ignore.rb
new file mode 100644
index 000000000..b292f3d4f
--- /dev/null
+++ b/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_ignore.rb
@@ -0,0 +1,88 @@
+# ==========================================
+# 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
+ @utils = utils
+ @priority = 2
+ end
+
+ def instance_structure(function)
+ if function[:return][:void?]
+ " char #{function[:name]}_IgnoreBool;\n"
+ else
+ " char #{function[:name]}_IgnoreBool;\n #{function[:return][:type]} #{function[:name]}_FinalReturn;\n"
+ end
+ end
+
+ def mock_function_declarations(function)
+ lines = if function[:return][:void?]
+ "#define #{function[:name]}_Ignore() #{function[:name]}_CMockIgnore()\n" \
+ "void #{function[:name]}_CMockIgnore(void);\n"
+ else
+ "#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
+
+ # Add stop ignore function. it does not matter if there are any args
+ lines << "#define #{function[:name]}_StopIgnore() #{function[:name]}_CMockStopIgnore()\n" \
+ "void #{function[:name]}_CMockStopIgnore(void);\n"
+ lines
+ end
+
+ def mock_implementation_precheck(function)
+ lines = " if (Mock.#{function[:name]}_IgnoreBool)\n {\n"
+ lines << " UNITY_CLR_DETAILS();\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 = ''
+ lines << if function[:return][:void?]
+ "void #{function[:name]}_CMockIgnore(void)\n{\n"
+ else
+ "void #{function[:name]}_CMockIgnoreAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]})\n{\n"
+ end
+ unless 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 = (char)1;\n"
+ lines << "}\n\n"
+
+ # Add stop ignore function. it does not matter if there are any args
+ lines << "void #{function[:name]}_CMockStopIgnore(void)\n{\n"
+ unless function[:return][:void?]
+ lines << " if(Mock.#{function[:name]}_IgnoreBool)\n"
+ lines << " Mock.#{function[:name]}_CallInstance = CMock_Guts_MemNext(Mock.#{function[:name]}_CallInstance);\n"
+ end
+ lines << " Mock.#{function[:name]}_IgnoreBool = (char)0;\n"
+ lines << "}\n\n"
+ end
+
+ def mock_ignore(function)
+ " Mock.#{function[:name]}_IgnoreBool = (char) 1;\n"
+ end
+
+ def mock_verify(function)
+ func_name = function[:name]
+ " if (Mock.#{func_name}_IgnoreBool)\n call_instance = CMOCK_GUTS_NONE;\n"
+ end
+end
diff --git a/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_ignore_arg.rb b/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_ignore_arg.rb
new file mode 100644
index 000000000..d55e84c25
--- /dev/null
+++ b/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_ignore_arg.rb
@@ -0,0 +1,42 @@
+class CMockGeneratorPluginIgnoreArg
+ attr_reader :priority
+ attr_accessor :utils
+
+ def initialize(_config, utils)
+ @utils = utils
+ @priority = 10
+ end
+
+ def instance_typedefs(function)
+ lines = ''
+ function[:args].each do |arg|
+ lines << " char IgnoreArg_#{arg[:name]};\n"
+ end
+ lines
+ end
+
+ def mock_function_declarations(function)
+ lines = ''
+ function[:args].each do |arg|
+ lines << "#define #{function[:name]}_IgnoreArg_#{arg[:name]}()"
+ lines << " #{function[:name]}_CMockIgnoreArg_#{arg[:name]}(__LINE__)\n"
+ lines << "void #{function[:name]}_CMockIgnoreArg_#{arg[:name]}(UNITY_LINE_TYPE cmock_line);\n"
+ end
+ lines
+ end
+
+ def mock_interfaces(function)
+ lines = []
+ func_name = function[:name]
+ function[:args].each do |arg|
+ lines << "void #{func_name}_CMockIgnoreArg_#{arg[:name]}(UNITY_LINE_TYPE cmock_line)\n"
+ lines << "{\n"
+ lines << " CMOCK_#{func_name}_CALL_INSTANCE* cmock_call_instance = " \
+ "(CMOCK_#{func_name}_CALL_INSTANCE*)CMock_Guts_GetAddressFor(CMock_Guts_MemEndOfChain(Mock.#{func_name}_CallInstance));\n"
+ lines << " UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringIgnPreExp);\n"
+ lines << " cmock_call_instance->IgnoreArg_#{arg[:name]} = 1;\n"
+ lines << "}\n\n"
+ end
+ lines
+ end
+end
diff --git a/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_return_thru_ptr.rb b/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_return_thru_ptr.rb
new file mode 100644
index 000000000..932155936
--- /dev/null
+++ b/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_plugin_return_thru_ptr.rb
@@ -0,0 +1,79 @@
+class CMockGeneratorPluginReturnThruPtr
+ attr_reader :priority
+ attr_accessor :utils
+
+ def initialize(_config, utils)
+ @utils = utils
+ @priority = 9
+ end
+
+ def instance_typedefs(function)
+ lines = ''
+ function[:args].each do |arg|
+ next unless @utils.ptr_or_str?(arg[:type]) && !(arg[:const?])
+
+ lines << " char ReturnThruPtr_#{arg[:name]}_Used;\n"
+ lines << " #{arg[:type]} ReturnThruPtr_#{arg[:name]}_Val;\n"
+ lines << " int ReturnThruPtr_#{arg[:name]}_Size;\n"
+ end
+ lines
+ end
+
+ def mock_function_declarations(function)
+ lines = ''
+ function[:args].each do |arg|
+ next unless @utils.ptr_or_str?(arg[:type]) && !(arg[:const?])
+
+ lines << "#define #{function[:name]}_ReturnThruPtr_#{arg[:name]}(#{arg[:name]})"
+ # If the pointer type actually contains an asterisk, we can do sizeof the type (super safe), otherwise
+ # we need to do a sizeof the dereferenced pointer (which could be a problem if give the wrong size
+ lines << if arg[:type][-1] == '*'
+ " #{function[:name]}_CMockReturnMemThruPtr_#{arg[:name]}(__LINE__, #{arg[:name]}, sizeof(#{arg[:type][0..-2]}))\n"
+ else
+ " #{function[:name]}_CMockReturnMemThruPtr_#{arg[:name]}(__LINE__, #{arg[:name]}, sizeof(*#{arg[:name]}))\n"
+ end
+ lines << "#define #{function[:name]}_ReturnArrayThruPtr_#{arg[:name]}(#{arg[:name]}, cmock_len)"
+ lines << " #{function[:name]}_CMockReturnMemThruPtr_#{arg[:name]}(__LINE__, #{arg[:name]}, (int)(cmock_len * (int)sizeof(*#{arg[:name]})))\n"
+ lines << "#define #{function[:name]}_ReturnMemThruPtr_#{arg[:name]}(#{arg[:name]}, cmock_size)"
+ lines << " #{function[:name]}_CMockReturnMemThruPtr_#{arg[:name]}(__LINE__, #{arg[:name]}, cmock_size)\n"
+ lines << "void #{function[:name]}_CMockReturnMemThruPtr_#{arg[:name]}(UNITY_LINE_TYPE cmock_line, #{arg[:type]} #{arg[:name]}, int cmock_size);\n"
+ end
+ lines
+ end
+
+ def mock_interfaces(function)
+ lines = []
+ func_name = function[:name]
+ function[:args].each do |arg|
+ arg_name = arg[:name]
+ next unless @utils.ptr_or_str?(arg[:type]) && !(arg[:const?])
+
+ lines << "void #{func_name}_CMockReturnMemThruPtr_#{arg_name}(UNITY_LINE_TYPE cmock_line, #{arg[:type]} #{arg_name}, int cmock_size)\n"
+ lines << "{\n"
+ lines << " CMOCK_#{func_name}_CALL_INSTANCE* cmock_call_instance = " \
+ "(CMOCK_#{func_name}_CALL_INSTANCE*)CMock_Guts_GetAddressFor(CMock_Guts_MemEndOfChain(Mock.#{func_name}_CallInstance));\n"
+ lines << " UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringPtrPreExp);\n"
+ lines << " cmock_call_instance->ReturnThruPtr_#{arg_name}_Used = 1;\n"
+ lines << " cmock_call_instance->ReturnThruPtr_#{arg_name}_Val = #{arg_name};\n"
+ lines << " cmock_call_instance->ReturnThruPtr_#{arg_name}_Size = cmock_size;\n"
+ lines << "}\n\n"
+ end
+ lines
+ end
+
+ def mock_implementation(function)
+ lines = []
+ function[:args].each do |arg|
+ arg_name = arg[:name]
+ next unless @utils.ptr_or_str?(arg[:type]) && !(arg[:const?])
+
+ lines << " if (cmock_call_instance->ReturnThruPtr_#{arg_name}_Used)\n"
+ lines << " {\n"
+ lines << " UNITY_TEST_ASSERT_NOT_NULL(#{arg_name}, cmock_line, CMockStringPtrIsNULL);\n"
+ lines << " memcpy((void*)#{arg_name}, (void*)cmock_call_instance->ReturnThruPtr_#{arg_name}_Val,\n"
+ lines << " cmock_call_instance->ReturnThruPtr_#{arg_name}_Size);\n"
+ lines << " }\n"
+ end
+ lines
+ end
+end
diff --git a/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_utils.rb b/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_utils.rb
new file mode 100644
index 000000000..11225d6ee
--- /dev/null
+++ b/FreeRTOS-Plus/Test/CMock/lib/cmock_generator_utils.rb
@@ -0,0 +1,247 @@
+# ==========================================
+# 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
+ @expect_any = @config.plugins.include? :expect_any_args
+ @return_thru_ptr = @config.plugins.include? :return_thru_ptr
+ @ignore_arg = @config.plugins.include? :ignore_arg
+ @ignore = @config.plugins.include? :ignore
+ @treat_as = @config.treat_as
+ @helpers = helpers
+ end
+
+ def self.arg_type_with_const(arg)
+ # Restore any "const" that was removed in header parsing
+ if arg[:type].include?('*')
+ arg[:const_ptr?] ? "#{arg[:type]} const" : arg[:type]
+ else
+ arg[:const?] ? "const #{arg[:type]}" : arg[:type]
+ end
+ end
+
+ def arg_type_with_const(arg)
+ self.class.arg_type_with_const(arg)
+ end
+
+ def code_verify_an_arg_expectation(function, arg)
+ if @arrays
+ case @ptr_handling
+ when :smart then code_verify_an_arg_expectation_with_smart_arrays(function, arg)
+ when :compare_data then code_verify_an_arg_expectation_with_normal_arrays(function, arg)
+ when :compare_ptr then raise "ERROR: the array plugin doesn't enjoy working with :compare_ptr only. Disable one option."
+ end
+ else
+ code_verify_an_arg_expectation_with_no_arrays(function, arg)
+ 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, CMockStringOutOfMemory);\n"
+ lines << " memset(cmock_call_instance, 0, sizeof(*cmock_call_instance));\n"
+ lines << " Mock.#{func_name}_CallInstance = CMock_Guts_MemChain(Mock.#{func_name}_CallInstance, cmock_guts_index);\n"
+ lines << " Mock.#{func_name}_IgnoreBool = (char)0;\n" if @ignore
+ lines << " cmock_call_instance->LineNumber = cmock_line;\n"
+ lines << " cmock_call_instance->CallOrder = ++GlobalExpectCount;\n" if @ordered && global_ordering_supported
+ lines << " cmock_call_instance->ExceptionToThrow = CEXCEPTION_NONE;\n" if @cexception
+ lines << " cmock_call_instance->ExpectAnyArgsBool = (char)0;\n" if @expect_any
+ 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 && (depth.class == String)
+ lines << " cmock_call_instance->IgnoreArg_#{arg[:name]} = 0;\n" if @ignore_arg
+ lines << " cmock_call_instance->ReturnThruPtr_#{arg[:name]}_Used = 0;\n" if @return_thru_ptr && ptr_or_str?(arg[:type]) && !(arg[:const?])
+ lines
+ end
+
+ def code_assign_argument_quickly(dest, arg)
+ if arg[:ptr?] || @treat_as.include?(arg[:type])
+ " #{dest} = #{arg[:name]};\n"
+ else
+ assert_expr = "sizeof(#{arg[:name]}) == sizeof(#{arg[:type]}) ? 1 : -1"
+ comment = "/* add #{arg[:type]} to :treat_as_array if this causes an error */"
+ " memcpy((void*)(&#{dest}), (void*)(&#{arg[:name]}),\n" \
+ " sizeof(#{arg[:type]}[#{assert_expr}])); #{comment}\n"
+ end
+ end
+
+ def code_add_argument_loader(function)
+ if function[:args_string] != 'void'
+ if @arrays
+ args_string = function[:args].map do |m|
+ type = arg_type_with_const(m)
+ m[:ptr?] ? "#{type} #{m[:name]}, int #{m[:name]}_Depth" : "#{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|
+ if @arrays && m[:ptr?] && !(m[:array_data?])
+ "#{m[:name]}, 1"
+ elsif @arrays && m[:array_size?]
+ "#{m[:name]}, #{m[:name]}"
+ else
+ m[:name]
+ end
+ end
+ " CMockExpectParameters_#{function[:name]}(cmock_call_instance, #{args.join(', ')});\n"
+ else
+ ''
+ end
+ end
+
+ def ptr_or_str?(arg_type)
+ (arg_type.include?('*') ||
+ @treat_as.fetch(arg_type, '').include?('*'))
+ end
+
+ # private ######################
+
+ def lookup_expect_type(_function, arg)
+ c_type = arg[:type]
+ arg_name = arg[:name]
+ expected = "cmock_call_instance->Expected_#{arg_name}"
+ ignore = "cmock_call_instance->IgnoreArg_#{arg_name}"
+ unity_func = if (arg[:ptr?]) && ((c_type =~ /\*\*/) || (@ptr_handling == :compare_ptr))
+ ['UNITY_TEST_ASSERT_EQUAL_PTR', '']
+ else
+ @helpers.nil? || @helpers[:unity_helper].nil? ? ['UNITY_TEST_ASSERT_EQUAL', ''] : @helpers[:unity_helper].get_helper(c_type)
+ end
+ [c_type, arg_name, expected, ignore, unity_func[0], unity_func[1]]
+ end
+
+ def code_verify_an_arg_expectation_with_no_arrays(function, arg)
+ c_type, arg_name, expected, ignore, unity_func, pre = lookup_expect_type(function, arg)
+ lines = ''
+ lines << " if (!#{ignore})\n" if @ignore_arg
+ lines << " {\n"
+ lines << " UNITY_SET_DETAILS(CMockString_#{function[:name]},CMockString_#{arg_name});\n"
+ case unity_func
+ when 'UNITY_TEST_ASSERT_EQUAL_MEMORY'
+ c_type_local = c_type.gsub(/\*$/, '')
+ lines << " UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type_local}), cmock_line, CMockStringMismatch);\n"
+ when 'UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY'
+ if pre == '&'
+ lines << " UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*', '')}), cmock_line, CMockStringMismatch);\n"
+ else
+ lines << " if (#{pre}#{expected} == NULL)\n"
+ lines << " { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
+ lines << " else\n"
+ lines << " { UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*', '')}), cmock_line, CMockStringMismatch); }\n"
+ end
+ when /_ARRAY/
+ if pre == '&'
+ lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, 1, cmock_line, CMockStringMismatch);\n"
+ else
+ lines << " if (#{pre}#{expected} == NULL)\n"
+ lines << " { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
+ lines << " else\n"
+ lines << " { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, 1, cmock_line, CMockStringMismatch); }\n"
+ end
+ else
+ lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch);\n"
+ end
+ lines << " }\n"
+ lines
+ end
+
+ def code_verify_an_arg_expectation_with_normal_arrays(function, arg)
+ c_type, arg_name, expected, ignore, unity_func, pre = lookup_expect_type(function, arg)
+ depth_name = arg[:ptr?] ? "cmock_call_instance->Expected_#{arg_name}_Depth" : 1
+ lines = ''
+ lines << " if (!#{ignore})\n" if @ignore_arg
+ lines << " {\n"
+ lines << " UNITY_SET_DETAILS(CMockString_#{function[:name]},CMockString_#{arg_name});\n"
+ case unity_func
+ when 'UNITY_TEST_ASSERT_EQUAL_MEMORY'
+ c_type_local = c_type.gsub(/\*$/, '')
+ lines << " UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type_local}), cmock_line, CMockStringMismatch);\n"
+ when 'UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY'
+ if pre == '&'
+ lines << " UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*', '')}), cmock_line, CMockStringMismatch);\n"
+ else
+ lines << " if (#{pre}#{expected} == NULL)\n"
+ lines << " { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
+ lines << " else\n"
+ lines << " { UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*', '')}), #{depth_name}, cmock_line, CMockStringMismatch); }\n"
+ end
+ when /_ARRAY/
+ if pre == '&'
+ lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, CMockStringMismatch);\n"
+ else
+ lines << " if (#{pre}#{expected} == NULL)\n"
+ lines << " { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
+ lines << " else\n"
+ lines << " { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, CMockStringMismatch); }\n"
+ end
+ else
+ lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch);\n"
+ end
+ lines << " }\n"
+ lines
+ end
+
+ def code_verify_an_arg_expectation_with_smart_arrays(function, arg)
+ c_type, arg_name, expected, ignore, unity_func, pre = lookup_expect_type(function, arg)
+ depth_name = arg[:ptr?] ? "cmock_call_instance->Expected_#{arg_name}_Depth" : 1
+ lines = ''
+ lines << " if (!#{ignore})\n" if @ignore_arg
+ lines << " {\n"
+ lines << " UNITY_SET_DETAILS(CMockString_#{function[:name]},CMockString_#{arg_name});\n"
+ case unity_func
+ when 'UNITY_TEST_ASSERT_EQUAL_MEMORY'
+ c_type_local = c_type.gsub(/\*$/, '')
+ lines << " UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type_local}), cmock_line, CMockStringMismatch);\n"
+ when 'UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY'
+ if pre == '&'
+ lines << " UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*', '')}), #{depth_name}, cmock_line, CMockStringMismatch);\n"
+ else
+ lines << " if (#{pre}#{expected} == NULL)\n"
+ lines << " { UNITY_TEST_ASSERT_NULL(#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
+ lines << (depth_name != 1 ? " else if (#{depth_name} == 0)\n { UNITY_TEST_ASSERT_EQUAL_PTR(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch); }\n" : '')
+ lines << " else\n"
+ lines << " { UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*', '')}), #{depth_name}, cmock_line, CMockStringMismatch); }\n"
+ end
+ when /_ARRAY/
+ if pre == '&'
+ lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, CMockStringMismatch);\n"
+ else
+ lines << " if (#{pre}#{expected} == NULL)\n"
+ lines << " { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
+ lines << (depth_name != 1 ? " else if (#{depth_name} == 0)\n { UNITY_TEST_ASSERT_EQUAL_PTR(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch); }\n" : '')
+ lines << " else\n"
+ lines << " { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, CMockStringMismatch); }\n"
+ end
+ else
+ lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch);\n"
+ end
+ lines << " }\n"
+ lines
+ end
+end
diff --git a/FreeRTOS-Plus/Test/CMock/lib/cmock_header_parser.rb b/FreeRTOS-Plus/Test/CMock/lib/cmock_header_parser.rb
new file mode 100644
index 000000000..8638a04f9
--- /dev/null
+++ b/FreeRTOS-Plus/Test/CMock/lib/cmock_header_parser.rb
@@ -0,0 +1,595 @@
+# ==========================================
+# 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_attr_noconst, :c_attributes, :treat_as_void, :treat_externs, :treat_inlines, :inline_function_patterns
+
+ def initialize(cfg)
+ @funcs = []
+ @c_strippables = cfg.strippables
+ @c_attr_noconst = cfg.attributes.uniq - ['const']
+ @c_attributes = ['const'] + c_attr_noconst
+ @c_calling_conventions = cfg.c_calling_conventions.uniq
+ @treat_as_array = cfg.treat_as_array
+ @treat_as_void = (['void'] + cfg.treat_as_void).uniq
+ @function_declaration_parse_base_match = '([\w\s\*\(\),\[\]]+??)\(([\w\s\*\(\),\.\[\]+\-\/]*)\)'
+ @declaration_parse_matcher = /#{@function_declaration_parse_base_match}$/m
+ @standards = (%w[int short char long unsigned signed] + cfg.treat_as.keys).uniq
+ @array_size_name = cfg.array_size_name
+ @array_size_type = (%w[int size_t] + cfg.array_size_type).uniq
+ @when_no_prototypes = cfg.when_no_prototypes
+ @local_as_void = @treat_as_void
+ @verbosity = cfg.verbosity
+ @treat_externs = cfg.treat_externs
+ @treat_inlines = cfg.treat_inlines
+ @inline_function_patterns = cfg.inline_function_patterns
+ @c_strippables += ['extern'] if @treat_externs == :include # we'll need to remove the attribute if we're allowing externs
+ @c_strippables += ['inline'] if @treat_inlines == :include # we'll need to remove the attribute if we're allowing inlines
+ end
+
+ def parse(name, source)
+ @module_name = name.gsub(/\W/, '')
+ @typedefs = []
+ @funcs = []
+ @normalized_source = nil
+ function_names = []
+
+ all_funcs = parse_functions(import_source(source)).map { |item| [item] }
+ all_funcs += parse_cpp_functions(import_source(source, true))
+ all_funcs.map do |decl|
+ func = parse_declaration(*decl)
+ unless function_names.include? func[:name]
+ @funcs << func
+ function_names << func[:name]
+ end
+ end
+
+ @normalized_source = if @treat_inlines == :include
+ transform_inline_functions(source)
+ else
+ ''
+ end
+
+ { :includes => nil,
+ :functions => @funcs,
+ :typedefs => @typedefs,
+ :normalized_source => @normalized_source }
+ end
+
+ private if $ThisIsOnlyATest.nil? ################
+
+ def remove_nested_pairs_of_braces(source)
+ # remove nested pairs of braces because no function declarations will be inside of them (leave outer pair for function definition detection)
+ if RUBY_VERSION.split('.')[0].to_i > 1
+ # we assign a string first because (no joke) if Ruby 1.9.3 sees this line as a regex, it will crash.
+ r = '\\{([^\\{\\}]*|\\g<0>)*\\}'
+ source.gsub!(/#{r}/m, '{ }')
+ else
+ while source.gsub!(/\{[^\{\}]*\{[^\{\}]*\}[^\{\}]*\}/m, '{ }')
+ end
+ end
+
+ source
+ end
+
+ # Return the number of pairs of braces/square brackets in the function provided by the user
+ # +source+:: String containing the function to be processed
+ def count_number_of_pairs_of_braces_in_function(source)
+ is_function_start_found = false
+ curr_level = 0
+ total_pairs = 0
+
+ source.each_char do |c|
+ if c == '{'
+ curr_level += 1
+ total_pairs += 1
+ is_function_start_found = true
+ elsif c == '}'
+ curr_level -= 1
+ end
+
+ break if is_function_start_found && curr_level == 0 # We reached the end of the inline function body
+ end
+
+ if curr_level != 0
+ total_pairs = 0 # Something is fishy about this source, not enough closing braces?
+ end
+
+ total_pairs
+ end
+
+ # Transform inline functions to regular functions in the source by the user
+ # +source+:: String containing the source to be processed
+ def transform_inline_functions(source)
+ inline_function_regex_formats = []
+ square_bracket_pair_regex_format = /\{[^\{\}]*\}/ # Regex to match one whole block enclosed by two square brackets
+
+ # Convert user provided string patterns to regex
+ # Use word bounderies before and after the user regex to limit matching to actual word iso part of a word
+ @inline_function_patterns.each do |user_format_string|
+ user_regex = Regexp.new(user_format_string)
+ word_boundary_before_user_regex = /\b/
+ cleanup_spaces_after_user_regex = /[ ]*\b/
+ inline_function_regex_formats << Regexp.new(word_boundary_before_user_regex.source + user_regex.source + cleanup_spaces_after_user_regex.source)
+ end
+
+ # let's clean up the encoding in case they've done anything weird with the characters we might find
+ source = source.force_encoding('ISO-8859-1').encode('utf-8', :replace => nil)
+
+ # smush multiline macros into single line (checking for continuation character at end of line '\')
+ # If the user uses a macro to declare an inline function,
+ # smushing the macros makes it easier to recognize them as a macro and if required,
+ # remove them later on in this function
+ source.gsub!(/\s*\\\s*/m, ' ')
+
+ # Just looking for static|inline in the gsub is a bit too aggressive (functions that are named like this, ...), so we try to be a bit smarter
+ # Instead, look for an inline pattern (f.e. "static inline") and parse it.
+ # Below is a small explanation on how the general mechanism works:
+ # - Everything before the match should just be copied, we don't want
+ # to touch anything but the inline functions.
+ # - Remove the implementation of the inline function (this is enclosed
+ # in square brackets) and replace it with ";" to complete the
+ # transformation to normal/non-inline function.
+ # To ensure proper removal of the function body, we count the number of square-bracket pairs
+ # and remove the pairs one-by-one.
+ # - Copy everything after the inline function implementation and start the parsing of the next inline function
+ # There are ofcourse some special cases (inline macro declarations, inline function declarations, ...) which are handled and explained below
+ inline_function_regex_formats.each do |format|
+ loop do
+ inline_function_match = source.match(/#{format}/) # Search for inline function declaration
+
+ break if inline_function_match.nil? # No inline functions so nothing to do
+
+ # 1. Determine if we are dealing with a user defined macro to declare inline functions
+ # If the end of the pre-match string is a macro-declaration-like string,
+ # we are dealing with a user defined macro to declare inline functions
+ if /(#define\s*)\z/ =~ inline_function_match.pre_match
+ # Remove the macro from the source
+ stripped_pre_match = inline_function_match.pre_match.sub(/(#define\s*)\z/, '')
+ stripped_post_match = inline_function_match.post_match.sub(/\A(.*[\n]?)/, '')
+ source = stripped_pre_match + stripped_post_match
+ next
+ end
+
+ # 2. Determine if we are dealing with an inline function declaration iso function definition
+ # If the start of the post-match string is a function-declaration-like string (something ending with semicolon after the function arguments),
+ # we are dealing with a inline function declaration
+ if /\A#{@function_declaration_parse_base_match}\s*;/m =~ inline_function_match.post_match
+ # Only remove the inline part from the function declaration, leaving the function declaration won't do any harm
+ source = inline_function_match.pre_match + inline_function_match.post_match
+ next
+ end
+
+ # 3. If we get here, we found an inline function declaration AND inline function body.
+ # Remove the function body to transform it into a 'normal' function.
+ total_pairs_to_remove = count_number_of_pairs_of_braces_in_function(inline_function_match.post_match)
+
+ break if total_pairs_to_remove == 0 # Bad source?
+
+ inline_function_stripped = inline_function_match.post_match
+
+ total_pairs_to_remove.times do
+ inline_function_stripped.sub!(/\s*#{square_bracket_pair_regex_format}/, ';') # Remove inline implementation (+ some whitespace because it's prettier)
+ end
+
+ source = inline_function_match.pre_match + inline_function_stripped # Make new source with the inline function removed and move on to the next
+ end
+ end
+
+ source
+ end
+
+ def import_source(source, cpp = false)
+ # let's clean up the encoding in case they've done anything weird with the characters we might find
+ source = source.force_encoding('ISO-8859-1').encode('utf-8', :replace => nil)
+
+ # 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]+)\s*;/)
+ if void_types
+ @local_as_void += void_types.flatten.uniq.compact
+ end
+
+ # If user wants to mock inline functions,
+ # remove the (user specific) inline keywords before removing anything else to avoid missing an inline function
+ if @treat_inlines == :include
+ @inline_function_patterns.each do |user_format_string|
+ source.gsub!(/#{user_format_string}/, '') # remove user defined inline function patterns
+ end
+ 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!(/__attribute(?:__)?\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|typedef)[\w\s]*\{[^\}]+\}[\w\s\*\,]*;/m, '') # remove struct, union, and enum definitions and typedefs with braces
+ # remove problem keywords
+ source.gsub!(/(\W)(?:register|auto|restrict)(\W)/, '\1\2')
+ source.gsub!(/(\W)(?:static)(\W)/, '\1\2') unless cpp
+
+ source.gsub!(/\s*=\s*['"a-zA-Z0-9_\.]+\s*/, '') # remove default value statements from argument lists
+ source.gsub!(/^(?:[\w\s]*\W)?typedef\W[^;]*/m, '') # remove typedef statements
+ source.gsub!(/\)(\w)/, ') \1') # add space between parenthese and alphanumeric
+ source.gsub!(/(^|\W+)(?:#{@c_strippables.join('|')})(?=$|\W+)/, '\1') unless @c_strippables.empty? # remove known attributes slated to be stripped
+
+ # scan standalone function pointers and remove them, because they can just be ignored
+ source.gsub!(/\w+\s*\(\s*\*\s*\w+\s*\)\s*\([^)]*\)\s*;/, ';')
+
+ # 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}"
+ unless cpp # only collect once
+ @typedefs << "typedef #{Regexp.last_match(1).strip}(*#{functype})(#{Regexp.last_match(4)});"
+ "#{functype} #{Regexp.last_match(2).strip}(#{Regexp.last_match(3)});"
+ end
+ end
+
+ source = remove_nested_pairs_of_braces(source) unless cpp
+
+ if @treat_inlines == :include
+ # Functions having "{ }" at this point are/were inline functions,
+ # User wants them in so 'disguise' them as normal functions with the ";"
+ source.gsub!('{ }', ';')
+ end
+
+ # remove function definitions by stripping off the arguments right now
+ source.gsub!(/\([^\)]*\)\s*\{[^\}]*\}/m, ';')
+
+ # 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 = src_lines.uniq unless cpp # must retain closing braces for class/namespace
+ src_lines.delete_if { |line| line.strip.empty? } # 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
+
+ unless @treat_externs == :include
+ src_lines.delete_if { |line| !(line =~ /(?:^|\s+)(?:extern)\s+/).nil? } # remove extern functions
+ end
+
+ unless @treat_inlines == :include
+ src_lines.delete_if { |line| !(line =~ /(?:^|\s+)(?:inline)\s+/).nil? } # remove inline functions
+ end
+
+ src_lines.delete_if(&:empty?) # drop empty lines
+ end
+
+ # Rudimentary C++ parser - does not handle all situations - e.g.:
+ # * A namespace function appears after a class with private members (should be parsed)
+ # * Anonymous namespace (shouldn't parse anything - no matter how nested - within it)
+ # * A class nested within another class
+ def parse_cpp_functions(source)
+ funcs = []
+
+ ns = []
+ pub = false
+ source.each do |line|
+ # Search for namespace, class, opening and closing braces
+ line.scan(/(?:(?:\b(?:namespace|class)\s+(?:\S+)\s*)?{)|}/).each do |item|
+ if item == '}'
+ ns.pop
+ else
+ token = item.strip.sub(/\s+/, ' ')
+ ns << token
+
+ pub = false if token.start_with? 'class'
+ pub = true if token.start_with? 'namespace'
+ end
+ end
+
+ pub = true if line =~ /public:/
+ pub = false if line =~ /private:/ || line =~ /protected:/
+
+ # ignore non-public and non-static
+ next unless pub
+ next unless line =~ /\bstatic\b/
+
+ line.sub!(/^.*static/, '')
+ next unless line =~ @declaration_parse_matcher
+
+ tmp = ns.reject { |item| item == '{' }
+
+ # Identify class name, if any
+ cls = nil
+ if tmp[-1].start_with? 'class '
+ cls = tmp.pop.sub(/class (\S+) {/, '\1')
+ end
+
+ # Assemble list of namespaces
+ tmp.each { |item| item.sub!(/(?:namespace|class) (\S+) {/, '\1') }
+
+ funcs << [line.strip.gsub(/\s+/, ' '), tmp, cls]
+ end
+ funcs
+ 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
+ funcs
+ end
+
+ def parse_type_and_name(arg)
+ # Split up words and remove known attributes. For pointer types, make sure
+ # to remove 'const' only when it applies to the pointer itself, not when it
+ # applies to the type pointed to. For non-pointer types, remove any
+ # occurrence of 'const'.
+ arg.gsub!(/(\w)\*/, '\1 *') # pull asterisks away from preceding word
+ arg.gsub!(/\*(\w)/, '* \1') # pull asterisks away from following word
+ arg_array = arg.split
+ arg_info = divine_ptr_and_const(arg)
+ arg_info[:name] = arg_array[-1]
+
+ attributes = arg.include?('*') ? @c_attr_noconst : @c_attributes
+ attr_array = []
+ type_array = []
+
+ arg_array[0..-2].each do |word|
+ if attributes.include?(word)
+ attr_array << word
+ elsif @c_calling_conventions.include?(word)
+ arg_info[:c_calling_convention] = word
+ else
+ type_array << word
+ end
+ end
+
+ if arg_info[:const_ptr?]
+ attr_array << 'const'
+ type_array.delete_at(type_array.rindex('const'))
+ end
+
+ arg_info[:modifier] = attr_array.join(' ')
+ arg_info[:type] = type_array.join(' ').gsub(/\s+\*/, '*') # remove space before asterisks
+ arg_info
+ 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_info = parse_type_and_name(arg)
+ arg_info.delete(:modifier) # don't care about this
+ arg_info.delete(:c_calling_convention) # don't care about this
+
+ # in C, array arguments implicitly degrade to pointers
+ # make the translation explicit here to simplify later logic
+ if @treat_as_array[arg_info[:type]] && !(arg_info[:ptr?])
+ arg_info[:type] = "#{@treat_as_array[arg_info[:type]]}*"
+ arg_info[:type] = "const #{arg_info[:type]}" if arg_info[:const?]
+ arg_info[:ptr?] = true
+ end
+
+ args << arg_info
+ end
+
+ # Try to find array pair in parameters following this pattern : <type> * <name>, <@array_size_type> <@array_size_name>
+ args.each_with_index do |val, index|
+ next_index = index + 1
+ next unless args.length > next_index
+
+ if (val[:ptr?] == true) && args[next_index][:name].match(@array_size_name) && @array_size_type.include?(args[next_index][:type])
+ val[:array_data?] = true
+ args[next_index][:array_size?] = true
+ end
+ end
+
+ args
+ end
+
+ def divine_ptr(arg)
+ return false unless arg.include? '*'
+ # treat "const char *" and similar as a string, not a pointer
+ return false if /(^|\s)(const\s+)?char(\s+const)?\s*\*(?!.*\*)/ =~ arg
+
+ true
+ end
+
+ def divine_const(arg)
+ # a non-pointer arg containing "const" is a constant
+ # an arg containing "const" before the last * is a pointer to a constant
+ if arg.include?('*') ? (/(^|\s|\*)const(\s(\w|\s)*)?\*(?!.*\*)/ =~ arg) : (/(^|\s)const(\s|$)/ =~ arg)
+ true
+ else
+ false
+ end
+ end
+
+ def divine_ptr_and_const(arg)
+ divination = {}
+
+ divination[:ptr?] = divine_ptr(arg)
+ divination[:const?] = divine_const(arg)
+
+ # an arg containing "const" after the last * is a constant pointer
+ divination[:const_ptr?] = /\*(?!.*\*)\s*const(\s|$)/ =~ arg ? true : false
+
+ divination
+ end
+
+ def clean_args(arg_list)
+ if @local_as_void.include?(arg_list.strip) || arg_list.empty?
+ 'void'
+ else
+ c = 0
+ # magically turn brackets into asterisks, also match for parentheses that come from macros
+ arg_list.gsub!(/(\w+)(?:\s*\[[^\[\]]*\])+/, '*\1')
+ # remove space to place asterisks with type (where they belong)
+ arg_list.gsub!(/\s+\*/, '*')
+ # pull asterisks away from arg to place asterisks with type (where they belong)
+ arg_list.gsub!(/\*(\w)/, '* \1')
+
+ # 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 = Regexp.last_match(1).strip
+ funcname = Regexp.last_match(2).strip
+ funcargs = Regexp.last_match(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
+
+ # scan argument list for function pointers with shorthand notation and replace them with custom types
+ arg_list.gsub!(/([\w\s\*]+)+\s+(\w+)\s*\(((?:[\w\s\*]*,?)*)\s*\)*/) do |_m|
+ functype = "cmock_#{@module_name}_func_ptr#{@typedefs.size + 1}"
+ funcret = Regexp.last_match(1).strip
+ funcname = Regexp.last_match(2).strip
+ funcargs = Regexp.last_match(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 do |arg|
+ parts = (arg.split - ['struct', 'union', 'enum', 'const', 'const*'])
+ if (parts.size < 2) || (parts[-1][-1].chr == '*') || @standards.include?(parts[-1])
+ "#{arg} cmock_arg#{c += 1}"
+ else
+ arg
+ end
+ end.join(', ')
+ end
+ end
+
+ def parse_declaration(declaration, namespace = [], classname = nil)
+ decl = {}
+ decl[:namespace] = namespace
+ decl[:class] = classname
+
+ 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
+ parsed = parse_type_and_name(regex_match[1])
+
+ # Record original name without scope prefix
+ decl[:unscoped_name] = parsed[:name]
+
+ # Prefix name with namespace scope (if any) and then class
+ decl[:name] = namespace.join('_')
+ unless classname.nil?
+ decl[:name] << '_' unless decl[:name].empty?
+ decl[:name] << classname
+ end
+ # Add original name to complete fully scoped name
+ decl[:name] << '_' unless decl[:name].empty?
+ decl[:name] << decl[:unscoped_name]
+
+ decl[:modifier] = parsed[:modifier]
+ unless parsed[:c_calling_convention].nil?
+ decl[:c_calling_convention] = parsed[:c_calling_convention]
+ end
+
+ rettype = parsed[:type]
+ rettype = 'void' if @local_as_void.include?(rettype.strip)
+ decl[:return] = { :type => rettype,
+ :name => 'cmock_to_return',
+ :str => "#{rettype} cmock_to_return",
+ :void? => (rettype == 'void'),
+ :ptr? => parsed[:ptr?] || false,
+ :const? => parsed[:const?] || false,
+ :const_ptr? => parsed[:const_ptr?] || false }
+
+ # 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
+ args = if args =~ /\,[\w\s]*\.\.\./
+ args.gsub!(/\,[\w\s]*\.\.\./, '')
+ else
+ '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? || decl[:name].nil? || decl[:args].nil? ||
+ decl[:return][:type].empty? || 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
+
+ decl
+ end
+
+ def prototype_inspect_hash(hash)
+ pairs = []
+ hash.each_pair { |name, value| pairs << ":#{name} => #{"'" if value.class == String}#{value}#{"'" if value.class == String}" }
+ "{#{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
diff --git a/FreeRTOS-Plus/Test/CMock/lib/cmock_plugin_manager.rb b/FreeRTOS-Plus/Test/CMock/lib/cmock_plugin_manager.rb
new file mode 100644
index 000000000..342014e22
--- /dev/null
+++ b/FreeRTOS-Plus/Test/CMock/lib/cmock_plugin_manager.rb
@@ -0,0 +1,50 @@
+# ==========================================
+# 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)
+ self.class.mutex.synchronize { load_plugin(plugin_name, object_name, config, utils) }
+ end
+ @plugins.sort! { |a, b| a.priority <=> b.priority }
+ end
+
+ def run(method, args = nil)
+ if args.nil?
+ @plugins.collect { |plugin| plugin.send(method) if plugin.respond_to?(method) }.flatten.join
+ else
+ @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(/\/(.?)/) { '::' + Regexp.last_match(1).upcase }.gsub(/(^|_)(.)/) { Regexp.last_match(2).upcase }
+ end
+
+ def self.mutex
+ @mutex ||= Mutex.new
+ end
+
+ private
+
+ def load_plugin(plugin_name, object_name, config, utils)
+ unless Object.const_defined? object_name
+ file_name = "#{__dir__}/cmock_generator_plugin_#{plugin_name.downcase}.rb"
+ require file_name
+ end
+ class_name = Object.const_get(object_name)
+ @plugins << class_name.new(config, utils)
+ rescue StandardError
+ file_name = "#{__dir__}/cmock_generator_plugin_#{plugin_name.downcase}.rb"
+ raise "ERROR: CMock unable to load plugin '#{plugin_name}' '#{object_name}' #{file_name}"
+ end
+end
diff --git a/FreeRTOS-Plus/Test/CMock/lib/cmock_unityhelper_parser.rb b/FreeRTOS-Plus/Test/CMock/lib/cmock_unityhelper_parser.rb
new file mode 100644
index 000000000..9f4beb770
--- /dev/null
+++ b/FreeRTOS-Plus/Test/CMock/lib/cmock_unityhelper_parser.rb
@@ -0,0 +1,77 @@
+# ==========================================
+# 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 += '*'
+ 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
+
+ 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.delete('*')}_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