- break out config

- parsing happens before generator
- generator now uses hashed results

git-svn-id: http://cmock.svn.sourceforge.net/svnroot/cmock/trunk@9 bf332499-1b4d-0410-844d-d2d48d5cc64c
This commit is contained in:
mvandervoord
2008-06-01 20:28:44 +00:00
parent 8f27069690
commit ad2809c9cc
3 changed files with 283 additions and 293 deletions
+17
View File
@@ -0,0 +1,17 @@
class CMockConfig
attr_accessor :src_path, :mock_path, :tab, :includes, :use_cexception, :allow_ignore_mock, :call_count_type, :ignore_bool_type
def initialize(src_path='src', mock_path='mocks', includes=[], use_cexception=true, allow_ignore_mock=false, tab=' ')
@src_path = src_path
@mock_path = mock_path
@tab = tab
@throw_type = 'int'
@call_count_type = 'unsigned short'
@ignore_bool_type = 'unsigned char'
@includes = includes
@use_cexception = use_cexception
@allow_ignore_mock = allow_ignore_mock
end
end
+255 -289
View File
@@ -1,34 +1,34 @@
$here = File.dirname __FILE__
require "#{$here}/c_file_parser"
class CMockGenerator
attr_accessor :module_name, :src_path, :mock_path, :tab, :includes
attr_accessor :module_name, :module_name, parsed_stuff
require 'ftools'
def initialize(module_name=nil, src_path='src', mock_path='mocks', includes=[], use_cexception=true, allow_ignore_mock=false, tab=' ')
raise "Must at least specify a code module" if module_name.nil?
def initialize(config, module_name)
@config = config
@module_name = module_name
@src_path = src_path
@mock_path = mock_path
@tab = tab
@throw_type = 'int'
@call_count_type = 'unsigned short'
@ignore_bool = 'unsigned char'
@includes = includes
@use_cexception = use_cexception
@allow_ignore_mock = allow_ignore_mock
###Most likely going to move again
@src_path = @config.src_path
@mock_path = @config.mock_path
@tab = @config.tab
@throw_type = @config.throw_type
@call_count_type = @config.call_count_type
@ignore_bool = @config.ignore_bool_type
@includes = @config.includes
@use_cexception = @config.use_cexception
@allow_ignore_mock = @config.allow_ignore_mock
end
def create_mock
def create_mock(parsed_stuff)
update_vars
create_mock_header_file
create_mock_source_file
create_mock_header_file(parsed_stuff)
create_mock_source_file(parsed_stuff)
end
def update_vars
@parser = CFileParser.new(File.read("#{@src_path}/#{@module_name}.h"))
@mock_name = "Mock" + @module_name
@mock_header_name_dest = @mock_name + ".h"
@mock_imp_name_dest = @mock_name + ".c"
@@ -44,399 +44,365 @@ class CMockGenerator
File.delete(src)
end
def create_mock_header_file
File.open @mock_header_temp, 'w' do |header|
@header = header
create_mock_header_header(@mock_header_name_dest.gsub(/\.h/, "_h").upcase)
create_mock_header_externs
@parser.nondefine_functions.each do |function|
create_mock_header_function_declaration(function)
def create_mock_header_file(parsed_stuff)
File.open(@mock_header_temp, 'w') do |header|
create_mock_header_header(header, @mock_header_name_dest.gsub(/\.h/, "_h").upcase)
create_mock_header_externs(header, parsed_stuff)
parsed_stuff[:functions].each do |function|
function[:args_string_without_varargs] = function[:args_string].gsub(/\,\s*.../,'')
create_mock_header_function_declaration(header, function)
end
create_mock_header_footer
create_mock_header_footer(header)
end
update_file @mock_header_file_path, @mock_header_temp
update_file(@mock_header_file_path, @mock_header_temp)
end
def create_mock_source_file
File.open @mock_imp_temp, 'w' do |implementation|
@source = implementation
create_source_header_section
create_instance_structure
create_extern_declarations
create_mock_verify_function
create_mock_init_function
create_mock_destroy_function
def create_mock_source_file(parsed_stuff)
File.open(@mock_imp_temp, 'w') do |file|
create_source_header_section(file, parsed_stuff[:includes])
create_instance_structure(file, parsed_stuff[:functions])
create_extern_declarations(file, parsed_stuff[:externs])
create_mock_verify_function(file, parsed_stuff[:functions])
create_mock_init_function(file)
create_mock_destroy_function(file, parsed_stuff[:functions])
@parser.nondefine_functions.each do |function|
create_mock_implementation(function)
create_mock_function_expectation(function)
create_mock_function_expectation_with_throw(function) if (@use_cexception)
create_mock_function_ignore(function) if (@allow_ignore_mock)
create_mock_implementation(file, function)
create_mock_function_expectation(file, function)
create_mock_function_expectation_with_throw(file, function) if (@use_cexception)
create_mock_function_ignore(file, function) if (@allow_ignore_mock)
end
end
update_file @mock_imp_file_path, @mock_imp_temp
update_file(@mock_imp_file_path, @mock_imp_temp)
end
private
private ##############################
def create_mock_header_header(define_name)
@header << "/* AUTOGENERATED FILE. DO NOT EDIT. */\n"
@header << "#ifndef _#{define_name}\n"
@header << "#define _#{define_name}\n\n"
@header << "#include \"#{@mock_header_name_dest.gsub(/^Mock/, "")}\"\n\n"
@header << "void #{@mock_name}_Init(void);\n"
@header << "void #{@mock_name}_Destroy(void);\n"
@header << "void #{@mock_name}_Verify(void);\n\n"
def create_mock_header_header(header, define_name)
header << "/* AUTOGENERATED FILE. DO NOT EDIT. */\n"
header << "#ifndef _#{define_name}\n"
header << "#define _#{define_name}\n\n"
header << "#include \"#{@mock_header_name_dest.gsub(/^Mock/, "")}\"\n\n"
header << "void #{@mock_name}_Init(void);\n"
header << "void #{@mock_name}_Destroy(void);\n"
header << "void #{@mock_name}_Verify(void);\n\n"
end
def create_mock_header_externs
@parser.externs.each do |extern|
@header << extern << ";\n"
def create_mock_header_externs(header, parsed_stuff)
unless (parsed_stuff[:externs].empty?)
parsed_stuff[:externs].each do |extern|
header << extern << ";\n"
end
header << "\n"
end
@header << "\n" unless @parser.externs.empty?
end
def create_mock_header_function_declaration(function)
decl = parse_declaration(function)
def create_mock_header_function_declaration(header, function)
if decl[:args_no_var_args] == "void"
if decl[:return] == "void"
@header << "void #{decl[:function]}_Expect(void);\n"
if (function[:args].empty?)
if (function[:rettype] == 'void')
header << "void #{function[:name]}_Expect(void);\n"
else
@header << "void #{decl[:function]}_ExpectAndReturn(#{decl[:return]} toReturn);\n"
header << "void #{function[:name]}_ExpectAndReturn(#{function[:rettype]} toReturn);\n"
end
else
if decl[:return] == "void"
@header << "void #{decl[:function]}_Expect(#{decl[:args_no_var_args]});\n"
if (function[:rettype] == 'void')
header << "void #{function[:name]}_Expect(#{function[:args_string_without_varargs]});\n"
else
@header << "void #{decl[:function]}_ExpectAndReturn(#{decl[:args_no_var_args]}, #{decl[:return]} toReturn);\n"
header << "void #{function[:name]}_ExpectAndReturn(#{function[:args_string_without_varargs]}, #{function[:rettype]} toReturn);\n"
end
end
if (@use_cexception)
if decl[:args_no_var_args] == "void"
@header << "void #{decl[:function]}_ExpectAndThrow(int toThrow);\n"
if (function[:args].empty?)
header << "void #{function[:name]}_ExpectAndThrow(int toThrow);\n"
else
@header << "void #{decl[:function]}_ExpectAndThrow(#{decl[:args_no_var_args]}, int toThrow);\n"
header << "void #{function[:name]}_ExpectAndThrow(#{function[:args_string_without_varargs]}, int toThrow);\n"
end
end
if (@allow_ignore_mock)
if decl[:return] == "void"
@header << "void #{decl[:function]}_Ignore(void);\n"
if (function[:args].empty?)
header << "void #{function[:name]}_Ignore(void);\n"
else
@header << "void #{decl[:function]}_IgnoreAndReturn(#{decl[:return]} toReturn);\n"
header << "void #{function[:name]}_IgnoreAndReturn(#{function[:rettype]} toReturn);\n"
end
end
end
def create_mock_header_footer
@header << "\n#endif\n"
def create_mock_header_footer(header)
header << "\n#endif\n"
end
def create_source_header_section
@source << "/* AUTOGENERATED FILE. DO NOT EDIT. */\n"
@source << "#include <string.h>\n"
@source << "#include <stdlib.h>\n"
@source << "#include <setjmp.h>\n"
@source << "#include \"unity.h\"\n"
@source << "#include \"Exception.h\"\n" if (@use_cexception)
@includes.each {|include| @source << "#include \"#{include}\"\n"}
@source << "#include \"#{@mock_header_name_dest}\"\n\n"
def create_source_header_section(file, include_files)
file << "/* AUTOGENERATED FILE. DO NOT EDIT. */\n"
file << "#include <string.h>\n"
file << "#include <stdlib.h>\n"
file << "#include <setjmp.h>\n"
file << "#include \"unity.h\"\n"
file << "#include \"Exception.h\"\n" if (@use_cexception) ####MSV : REMOVE ME
include_files.each {|include| file << "#include \"#{include}\"\n"}
file << "#include \"#{@mock_header_name_dest}\"\n\n"
end
def create_instance_structure
@source << "static struct #{@mock_name}Instance\n"
@source << "{\n"
def create_instance_structure(file, functions)
file << "static struct #{@mock_name}Instance\n"
file << "{\n"
if @parser.nondefine_functions.length == 0
@source << "#{@tab}unsigned char placeHolder;\n"
if (functions.size == 0)
file << "#{@tab}unsigned char placeHolder;\n"
end
@source << "#{@tab}unsigned char allocFailure;\n"
file << "#{@tab}unsigned char allocFailure;\n"
@parser.nondefine_functions.each do |function|
decl = parse_declaration(function)
@source << "#{@tab}#{@call_count_type} #{decl[:function]}_CallCount;\n"
@source << "#{@tab}#{@call_count_type} #{decl[:function]}_CallsExpected;\n"
functions.each do |function|
file << "#{@tab}#{@call_count_type} #{function[:name]}_CallCount;\n"
file << "#{@tab}#{@call_count_type} #{function[:name]}_CallsExpected;\n"
if (@allow_ignore_mock)
@source << "#{@tab}#{@ignore_bool} #{decl[:function]}_IgnoreBool;\n"
file << "#{@tab}#{@ignore_bool} #{function[:name]}_IgnoreBool;\n"
end
@source << "#{@tab}#{@call_count_type} *#{decl[:function]}_ThrowOnCallCount;\n"
@source << "#{@tab}#{@call_count_type} *#{decl[:function]}_ThrowOnCallCount_Head;\n"
@source << "#{@tab}#{@call_count_type} *#{decl[:function]}_ThrowOnCallCount_HeadTail;\n"
@source << "#{@tab}#{@throw_type} *#{decl[:function]}_ThrowValue;\n"
@source << "#{@tab}#{@throw_type} *#{decl[:function]}_ThrowValue_Head;\n"
@source << "#{@tab}#{@throw_type} *#{decl[:function]}_ThrowValue_HeadTail;\n"
file << "#{@tab}#{@call_count_type} *#{function[:name]}_ThrowOnCallCount;\n"
file << "#{@tab}#{@call_count_type} *#{function[:name]}_ThrowOnCallCount_Head;\n"
file << "#{@tab}#{@call_count_type} *#{function[:name]}_ThrowOnCallCount_HeadTail;\n"
file << "#{@tab}#{@throw_type} *#{function[:name]}_ThrowValue;\n"
file << "#{@tab}#{@throw_type} *#{function[:name]}_ThrowValue_Head;\n"
file << "#{@tab}#{@throw_type} *#{function[:name]}_ThrowValue_HeadTail;\n"
if (decl[:return] != "void")
@source << "#{@tab}#{decl[:return]} *#{decl[:function]}_Return;\n"
@source << "#{@tab}#{decl[:return]} *#{decl[:function]}_Return_Head;\n"
@source << "#{@tab}#{decl[:return]} *#{decl[:function]}_Return_HeadTail;\n"
if (function[:rettype] != "void")
file << "#{@tab}#{function[:rettype]} *#{function[:name]}_Return;\n"
file << "#{@tab}#{function[:rettype]} *#{function[:name]}_Return_Head;\n"
file << "#{@tab}#{function[:rettype]} *#{function[:name]}_Return_HeadTail;\n"
end
if (decl[:args_no_var_args] != "void")
args = parse_args(decl[:args_no_var_args])
args.each do |arg|
type = arg[:type].sub(/const/, '').strip
@source << "#{@tab}#{type} *#{decl[:function]}_Expected_#{arg[:name]};\n"
@source << "#{@tab}#{type} *#{decl[:function]}_Expected_#{arg[:name]}_Head;\n"
@source << "#{@tab}#{type} *#{decl[:function]}_Expected_#{arg[:name]}_HeadTail;\n"
end
functions[:args].each do |arg|
type = arg[:type].sub(/const/, '').strip
file << "#{@tab}#{type} *#{function[:name]}_Expected_#{arg[:name]};\n"
file << "#{@tab}#{type} *#{function[:name]}_Expected_#{arg[:name]}_Head;\n"
file << "#{@tab}#{type} *#{function[:name]}_Expected_#{arg[:name]}_HeadTail;\n"
end
end
@source << "} Mock;\n\n"
file << "} Mock;\n\n"
end
def create_extern_declarations
@parser.externs.each do |extern|
@source << extern.gsub(/extern/,'') << ";\n"
end
@source << "extern jmp_buf AbortFrame;\n"
@source << "\n"
end
def create_mock_verify_function
@source << "void #{@mock_name}_Verify(void)\n{\n"
@source << "#{@tab}TEST_ASSERT_EQUAL(0, Mock.allocFailure);\n"
@parser.nondefine_functions.each do |function|
decl = parse_declaration(function)
@source << "#{@tab}TEST_ASSERT_EQUAL_MESSAGE(Mock.#{decl[:function]}_CallsExpected, Mock.#{decl[:function]}_CallCount, \"Function '#{decl[:function]}' called unexpected number of times.\");\n"
def create_extern_declarations(file, externs)
externs.each do |extern|
file << extern.gsub(/extern/,'') << ";\n"
end
@source << "}\n\n"
file << "extern jmp_buf AbortFrame;\n"
file << "\n"
end
def create_mock_init_function
@source << "void #{@mock_name}_Init(void)\n{\n"
@source << "#{@tab}#{@mock_name}_Destroy();\n"
@source << "}\n\n"
def create_mock_verify_function(file, functions)
file << "void #{@mock_name}_Verify(void)\n{\n"
file << "#{@tab}TEST_ASSERT_EQUAL(0, Mock.allocFailure);\n"
functions.each do |function|
file << "#{@tab}TEST_ASSERT_EQUAL_MESSAGE(Mock.#{function[:name]}_CallsExpected, Mock.#{function[:name]}_CallCount, \"Function '#{function[:name]}' called unexpected number of times.\");\n"
end
file << "}\n\n"
end
def create_mock_destroy_function
@source << "void #{@mock_name}_Destroy(void)\n{\n"
@parser.nondefine_functions.each do |function|
decl = parse_declaration(function)
if decl[:return] != "void"
@source << "#{@tab}if(Mock.#{decl[:function]}_Return_Head)\n"
@source << "#{@tab}{\n"
@source << "#{@tab}#{@tab}free(Mock.#{decl[:function]}_Return_Head);\n"
@source << "#{@tab}#{@tab}Mock.#{decl[:function]}_Return_Head=NULL;\n"
@source << "#{@tab}#{@tab}Mock.#{decl[:function]}_Return_HeadTail=NULL;\n"
@source << "#{@tab}}\n"
def create_mock_init_function(file)
file << "void #{@mock_name}_Init(void)\n{\n"
file << "#{@tab}#{@mock_name}_Destroy();\n"
file << "}\n\n"
end
def create_mock_destroy_function(file, functions)
file << "void #{@mock_name}_Destroy(void)\n{\n"
functions.each do |function|
if function[:rettype] != "void"
file << "#{@tab}if(Mock.#{function[:name]}_Return_Head)\n"
file << "#{@tab}{\n"
file << "#{@tab}#{@tab}free(Mock.#{function[:name]}_Return_Head);\n"
file << "#{@tab}#{@tab}Mock.#{function[:name]}_Return_Head=NULL;\n"
file << "#{@tab}#{@tab}Mock.#{function[:name]}_Return_HeadTail=NULL;\n"
file << "#{@tab}}\n"
end
if decl[:args_no_var_args] != "void"
args = parse_args(decl[:args_no_var_args])
args.each do |arg|
@source << "#{@tab}if(Mock.#{decl[:function]}_Expected_#{arg[:name]}_Head)\n"
@source << "#{@tab}{\n"
@source << "#{@tab}#{@tab}free(Mock.#{decl[:function]}_Expected_#{arg[:name]}_Head);\n"
@source << "#{@tab}#{@tab}Mock.#{decl[:function]}_Expected_#{arg[:name]}_Head=NULL;\n"
@source << "#{@tab}#{@tab}Mock.#{decl[:function]}_Expected_#{arg[:name]}_HeadTail=NULL;\n"
@source << "#{@tab}}\n"
end
function[:args].each do |arg|
file << "#{@tab}if(Mock.#{function[:name]}_Expected_#{arg[:name]}_Head)\n"
file << "#{@tab}{\n"
file << "#{@tab}#{@tab}free(Mock.#{function[:name]}_Expected_#{arg[:name]}_Head);\n"
file << "#{@tab}#{@tab}Mock.#{function[:name]}_Expected_#{arg[:name]}_Head=NULL;\n"
file << "#{@tab}#{@tab}Mock.#{function[:name]}_Expected_#{arg[:name]}_HeadTail=NULL;\n"
file << "#{@tab}}\n"
end
@source << "#{@tab}if(Mock.#{decl[:function]}_ThrowOnCallCount_Head)\n"
@source << "#{@tab}{\n"
@source << "#{@tab}#{@tab}free(Mock.#{decl[:function]}_ThrowOnCallCount_Head);\n"
@source << "#{@tab}#{@tab}Mock.#{decl[:function]}_ThrowOnCallCount_Head=NULL;\n"
@source << "#{@tab}#{@tab}Mock.#{decl[:function]}_ThrowOnCallCount_HeadTail=NULL;\n"
@source << "#{@tab}}\n"
file << "#{@tab}if(Mock.#{function[:name]}_ThrowOnCallCount_Head)\n"
file << "#{@tab}{\n"
file << "#{@tab}#{@tab}free(Mock.#{function[:name]}_ThrowOnCallCount_Head);\n"
file << "#{@tab}#{@tab}Mock.#{function[:name]}_ThrowOnCallCount_Head=NULL;\n"
file << "#{@tab}#{@tab}Mock.#{function[:name]}_ThrowOnCallCount_HeadTail=NULL;\n"
file << "#{@tab}}\n"
@source << "#{@tab}if(Mock.#{decl[:function]}_ThrowValue_Head)\n"
@source << "#{@tab}{\n"
@source << "#{@tab}#{@tab}free(Mock.#{decl[:function]}_ThrowValue_Head);\n"
@source << "#{@tab}#{@tab}Mock.#{decl[:function]}_ThrowValue_Head=NULL;\n"
@source << "#{@tab}#{@tab}Mock.#{decl[:function]}_ThrowValue_HeadTail=NULL;\n"
@source << "#{@tab}}\n"
file << "#{@tab}if(Mock.#{function[:name]}_ThrowValue_Head)\n"
file << "#{@tab}{\n"
file << "#{@tab}#{@tab}free(Mock.#{function[:name]}_ThrowValue_Head);\n"
file << "#{@tab}#{@tab}Mock.#{function[:name]}_ThrowValue_Head=NULL;\n"
file << "#{@tab}#{@tab}Mock.#{function[:name]}_ThrowValue_HeadTail=NULL;\n"
file << "#{@tab}}\n"
end
@source << "#{@tab}memset(&Mock, 0, sizeof(Mock));\n"
@source << "}\n\n"
file << "#{@tab}memset(&Mock, 0, sizeof(Mock));\n"
file << "}\n\n"
end
def create_mock_argument_verifier(arguments)
@source << "void AssertParameters_#{decl[:function]}(#{decl[:args_no_var_args]})\n{\n"
def create_mock_argument_verifier(file, func_name, argument_string, arguments)
file << "void AssertParameters_#{func_name}(#{argument_string})\n{\n"
arguments.each do |arg|
type = arg[:type].sub(/const/, '').strip
@source << make_handle_expected(decl[:function], type, arg[:name])
file << make_handle_expected(func_name, type, arg[:name])
end
@source << "}\n\n"
file << "}\n\n"
end
def create_call_list(decl)
args = parse_args(decl[:args_no_var_args])
call_list = ""
args.each do |arg|
if call_list.empty?
call_list = arg[:name]
else
call_list += ", " + arg[:name]
end
end
return call_list
end
def create_mock_implementation(function)
decl = parse_declaration(function)
def create_mock_implementation(file, function)
newtab = "#{@tab}"
# Create mock argument verifier, if necessary
if decl[:args] != "void"
args = parse_args(decl[:args_no_var_args])
create_mock_argument_verifier(args)
unless function[:args].empty?
create_mock_argument_verifier(file, function[:name], function[:args_string_without_varargs], function[:args])
end
# Create mock function
@source << "#{decl[:modifier]} " if (!decl[:modifier].nil? && decl[:modifier].length > 0)
@source << "#{decl[:return]} #{decl[:function]}(#{decl[:args]})\n"
@source << "{\n"
file << "#{function[:attributes]} " if (!function[:attributes].nil? && function[:attributes].length > 0)
file << "#{function[:rettype]} #{function[:name]}(#{function[:args_string]})\n"
file << "{\n"
# start ignore block
if (@allow_ignore_mock)
newtab = "#{@tab}#{@tab}"
@source << "#{@tab}if (!Mock.#{decl[:function]}_IgnoreBool)\n"
@source << "#{@tab}{\n"
file << "#{@tab}if (!Mock.#{function[:name]}_IgnoreBool)\n"
file << "#{@tab}{\n"
end
@source << "#{newtab}Mock.#{decl[:function]}_CallCount++;\n"
file << "#{newtab}Mock.#{function[:name]}_CallCount++;\n"
#create overcall protection
exp = "Mock.#{decl[:function]}_CallsExpected"
@source << "#{newtab}if (Mock.#{decl[:function]}_CallCount > Mock.#{decl[:function]}_CallsExpected)\n"
@source << "#{newtab}{\n"
@source << "#{newtab}#{@tab}TEST_THROW(\"#{decl[:function]} Called More Times Than Expected\");\n"
@source << "#{newtab}}\n"
exp = "Mock.#{function[:name]}_CallsExpected"
file << "#{newtab}if (Mock.#{function[:name]}_CallCount > Mock.#{function[:name]}_CallsExpected)\n"
file << "#{newtab}{\n"
file << "#{newtab}#{@tab}TEST_THROW(\"#{function[:name]} Called More Times Than Expected\");\n"
file << "#{newtab}}\n"
# Create call to argument verifier, if necessary
if decl[:args_no_var_args] != "void"
@source << "#{newtab}AssertParameters_#{decl[:function]}(#{create_call_list(decl)});\n"
unless function[:args].empty?
file << "#{newtab}AssertParameters_#{function[:name]}(#{function[:args_string]});\n"
end
# Throw exception, if appropriate
@source << make_handle_throw(decl[:function], @throw_type) if (@use_cexception)
file << make_handle_throw(function[:name], @throw_type) if (@use_cexception)
# end ignore block
if (@allow_ignore_mock)
@source << "#{@tab}}\n"
file << "#{@tab}}\n"
end
# Return expected value, if necessary
if decl[:return] != "void"
@source << make_handle_return(decl[:function], decl[:return])
if function[:rettype] != "void"
file << make_handle_return(function[:name], function[:rettype])
end
# Close out the function
@source << "}\n\n"
file << "}\n\n"
end
def create_mock_function_expectation(function)
decl = parse_declaration(function)
if decl[:args_no_var_args] == "void"
def create_mock_function_expectation(file, function)
if (function[:args].empty?)
# Function has void return type with no arguments
if decl[:return] == "void"
@source << "void #{decl[:function]}_Expect(void)\n"
@source << "{\n"
@source << "#{@tab}Mock.#{decl[:function]}_CallsExpected++;\n"
@source << "}\n\n"
if (function[:rettype] == "void")
file << "void #{function[:name]}_Expect(void)\n"
file << "{\n"
file << "#{@tab}Mock.#{function[:name]}_CallsExpected++;\n"
file << "}\n\n"
# Function has non-void return type with no arguments
else
@source << "void #{decl[:function]}_ExpectAndReturn(#{decl[:return]} toReturn)\n"
@source << "{\n"
@source << "#{@tab}Mock.#{decl[:function]}_CallsExpected++;\n"
@source << make_expand_array(decl[:return], "Mock.#{decl[:function]}_Return_Head", "toReturn")
@source << "#{@tab}Mock.#{decl[:function]}_Return = Mock.#{decl[:function]}_Return_Head;\n"
@source << "#{@tab}Mock.#{decl[:function]}_Return += Mock.#{decl[:function]}_CallCount;\n"
@source << "}\n\n"
file << "void #{function[:name]}_ExpectAndReturn(#{function[:rettype]} toReturn)\n"
file << "{\n"
file << "#{@tab}Mock.#{function[:name]}_CallsExpected++;\n"
file << make_expand_array(function[:rettype], "Mock.#{function[:name]}_Return_Head", "toReturn")
file << "#{@tab}Mock.#{function[:name]}_Return = Mock.#{function[:name]}_Return_Head;\n"
file << "#{@tab}Mock.#{function[:name]}_Return += Mock.#{function[:name]}_CallCount;\n"
file << "}\n\n"
end
else
# Parse function arguments
args = parse_args(decl[:args_no_var_args])
# Create parameter expectation function
@source << "void ExpectParameters_#{decl[:function]}(#{decl[:args_no_var_args]})\n"
@source << "{\n"
file << "void ExpectParameters_#{function[:name]}(#{function[:args_string_without_varargs]})\n"
file << "{\n"
args.each do |arg|
type = arg[:type].sub(/const/, '').strip
@source << make_add_new_expected(decl[:function], type, arg[:name])
file << make_add_new_expected(function[:name], type, arg[:name])
end
@source << "}\n\n"
file << "}\n\n"
# Function has void return type with arguments
if decl[:return] == "void"
@source << "void #{decl[:function]}_Expect(#{decl[:args_no_var_args]})\n"
@source << "{\n"
@source << "#{@tab}Mock.#{decl[:function]}_CallsExpected++;\n"
@source << "#{@tab}ExpectParameters_#{decl[:function]}(#{create_call_list(decl)});\n"
@source << "}\n\n"
if function[:rettype] == "void"
file << "void #{function[:name]}_Expect(#{function[:args_string_without_varargs]})\n"
file << "{\n"
file << "#{@tab}Mock.#{function[:name]}_CallsExpected++;\n"
file << "#{@tab}ExpectParameters_#{function[:name]}(#{function[:args_string_without_varargs]});\n"
file << "}\n\n"
# Function has non-void return type with arguments
else
@source << "void #{decl[:function]}_ExpectAndReturn(#{decl[:args_no_var_args]}, #{decl[:return]} toReturn)\n{\n"
@source << "#{@tab}Mock.#{decl[:function]}_CallsExpected++;\n"
@source << "#{@tab}ExpectParameters_#{decl[:function]}(#{create_call_list(decl)});\n"
@source << make_expand_array(decl[:return], "Mock.#{decl[:function]}_Return_Head", "toReturn")
@source << "#{@tab}Mock.#{decl[:function]}_Return = Mock.#{decl[:function]}_Return_Head;\n"
@source << "#{@tab}Mock.#{decl[:function]}_Return += Mock.#{decl[:function]}_CallCount;\n"
@source << "}\n\n"
file << "void #{function[:name]}_ExpectAndReturn(#{function[:args_string_without_varargs]}, #{function[:rettype]} toReturn)\n{\n"
file << "#{@tab}Mock.#{function[:name]}_CallsExpected++;\n"
file << "#{@tab}ExpectParameters_#{function[:name]}(#{function[:args_string_without_varargs]});\n"
file << make_expand_array(function[:rettype], "Mock.#{function[:name]}_Return_Head", "toReturn")
file << "#{@tab}Mock.#{function[:name]}_Return = Mock.#{function[:name]}_Return_Head;\n"
file << "#{@tab}Mock.#{function[:name]}_Return += Mock.#{function[:name]}_CallCount;\n"
file << "}\n\n"
end
end
end
def create_mock_function_expectation_with_throw(function)
decl = parse_declaration(function)
def create_mock_function_expectation_with_throw(file, function)
# function takes no arguments
if decl[:args_no_var_args] == "void"
@source << "void #{decl[:function]}_ExpectAndThrow(#{@throw_type} toThrow)\n"
@source << "{\n"
@source << "#{@tab}Mock.#{decl[:function]}_CallsExpected++;\n"
@source << make_expand_array(@call_count_type, "Mock.#{decl[:function]}_ThrowOnCallCount_Head", "Mock.#{decl[:function]}_CallsExpected")
@source << "#{@tab}Mock.#{decl[:function]}_ThrowOnCallCount = Mock.#{decl[:function]}_ThrowOnCallCount_Head;\n"
@source << "#{@tab}Mock.#{decl[:function]}_ThrowOnCallCount += Mock.#{decl[:function]}_CallCount;\n"
@source << make_expand_array(@throw_type, "Mock.#{decl[:function]}_ThrowValue_Head", "toThrow")
@source << "#{@tab}Mock.#{decl[:function]}_ThrowValue = Mock.#{decl[:function]}_ThrowValue_Head;\n"
@source << "#{@tab}Mock.#{decl[:function]}_ThrowValue += Mock.#{decl[:function]}_CallCount;\n"
@source << "}\n\n"
if (function[:args].empty?)
file << "void #{function[:name]}_ExpectAndThrow(#{@throw_type} toThrow)\n"
file << "{\n"
file << "#{@tab}Mock.#{function[:name]}_CallsExpected++;\n"
file << make_expand_array(@call_count_type, "Mock.#{function[:name]}_ThrowOnCallCount_Head", "Mock.#{function[:name]}_CallsExpected")
file << "#{@tab}Mock.#{function[:name]}_ThrowOnCallCount = Mock.#{function[:name]}_ThrowOnCallCount_Head;\n"
file << "#{@tab}Mock.#{function[:name]}_ThrowOnCallCount += Mock.#{function[:name]}_CallCount;\n"
file << make_expand_array(@throw_type, "Mock.#{function[:name]}_ThrowValue_Head", "toThrow")
file << "#{@tab}Mock.#{function[:name]}_ThrowValue = Mock.#{function[:name]}_ThrowValue_Head;\n"
file << "#{@tab}Mock.#{function[:name]}_ThrowValue += Mock.#{function[:name]}_CallCount;\n"
file << "}\n\n"
else
# Parse function arguments
args = parse_args(decl[:args_no_var_args])
@source << "void #{decl[:function]}_ExpectAndThrow(#{decl[:args_no_var_args]}, #{@throw_type} toThrow)\n"
@source << "{\n"
@source << "#{@tab}Mock.#{decl[:function]}_CallsExpected++;\n"
@source << make_expand_array(@call_count_type, "Mock.#{decl[:function]}_ThrowOnCallCount_Head", "Mock.#{decl[:function]}_CallsExpected")
@source << "#{@tab}Mock.#{decl[:function]}_ThrowOnCallCount = Mock.#{decl[:function]}_ThrowOnCallCount_Head;\n"
@source << "#{@tab}Mock.#{decl[:function]}_ThrowOnCallCount += Mock.#{decl[:function]}_CallCount;\n"
@source << make_expand_array(@throw_type, "Mock.#{decl[:function]}_ThrowValue_Head", "toThrow")
@source << "#{@tab}Mock.#{decl[:function]}_ThrowValue = Mock.#{decl[:function]}_ThrowValue_Head;\n"
@source << "#{@tab}Mock.#{decl[:function]}_ThrowValue += Mock.#{decl[:function]}_CallCount;\n"
@source << "#{@tab}ExpectParameters_#{decl[:function]}(#{create_call_list(decl)});\n"
@source << "}\n\n"
file << "void #{function[:name]}_ExpectAndThrow(#{function[:args_string_without_varargs]}, #{@throw_type} toThrow)\n"
file << "{\n"
file << "#{@tab}Mock.#{function[:name]}_CallsExpected++;\n"
file << make_expand_array(@call_count_type, "Mock.#{function[:name]}_ThrowOnCallCount_Head", "Mock.#{function[:name]}_CallsExpected")
file << "#{@tab}Mock.#{function[:name]}_ThrowOnCallCount = Mock.#{function[:name]}_ThrowOnCallCount_Head;\n"
file << "#{@tab}Mock.#{function[:name]}_ThrowOnCallCount += Mock.#{function[:name]}_CallCount;\n"
file << make_expand_array(@throw_type, "Mock.#{function[:name]}_ThrowValue_Head", "toThrow")
file << "#{@tab}Mock.#{function[:name]}_ThrowValue = Mock.#{function[:name]}_ThrowValue_Head;\n"
file << "#{@tab}Mock.#{function[:name]}_ThrowValue += Mock.#{function[:name]}_CallCount;\n"
file << "#{@tab}ExpectParameters_#{function[:name]}(#{function[:args_string_without_varargs]});\n"
file << "}\n\n"
end
end
def create_mock_function_ignore(function)
decl = parse_declaration(function)
def create_mock_function_ignore(file, function)
# Function has void return type with no arguments
if decl[:return] == "void"
@source << "void #{decl[:function]}_Ignore(void)\n"
@source << "{\n"
@source << "#{@tab}Mock.#{decl[:function]}_IgnoreBool = (unsigned char)1;\n"
@source << "}\n\n"
if function[:rettype] == "void"
file << "void #{function[:name]}_Ignore(void)\n"
file << "{\n"
file << "#{@tab}Mock.#{function[:name]}_IgnoreBool = (unsigned char)1;\n"
file << "}\n\n"
# Function has non-void return type with no arguments
else
@source << "void #{decl[:function]}_IgnoreAndReturn(#{decl[:return]} toReturn)\n"
@source << "{\n"
@source << "#{@tab}Mock.#{decl[:function]}_IgnoreBool = (unsigned char)1;\n"
@source << make_expand_array(decl[:return], "Mock.#{decl[:function]}_Return_Head", "toReturn")
@source << "#{@tab}Mock.#{decl[:function]}_Return = Mock.#{decl[:function]}_Return_Head;\n"
@source << "#{@tab}Mock.#{decl[:function]}_Return += Mock.#{decl[:function]}_CallCount;\n"
@source << "}\n\n"
file << "void #{function[:name]}_IgnoreAndReturn(#{function[:rettype]} toReturn)\n"
file << "{\n"
file << "#{@tab}Mock.#{function[:name]}_IgnoreBool = (unsigned char)1;\n"
file << make_expand_array(function[:rettype], "Mock.#{function[:name]}_Return_Head", "toReturn")
file << "#{@tab}Mock.#{function[:name]}_Return = Mock.#{function[:name]}_Return_Head;\n"
file << "#{@tab}Mock.#{function[:name]}_Return += Mock.#{function[:name]}_CallCount;\n"
file << "}\n\n"
end
end
@@ -480,12 +446,12 @@ EOS
#{newtab}if((Mock.#{method}_ThrowOnCallCount != Mock.#{method}_ThrowOnCallCount_HeadTail) &&
#{newtab}#{@tab}(Mock.#{method}_ThrowValue != Mock.#{method}_ThrowValue_HeadTail))
#{newtab}{
#{newtab}#{@tab}if (*Mock.#{decl[:function]}_ThrowOnCallCount &&
#{newtab}#{@tab}#{@tab}(Mock.#{decl[:function]}_CallCount == *Mock.#{decl[:function]}_ThrowOnCallCount))
#{newtab}#{@tab}if (*Mock.#{function[:name]}_ThrowOnCallCount &&
#{newtab}#{@tab}#{@tab}(Mock.#{function[:name]}_CallCount == *Mock.#{function[:name]}_ThrowOnCallCount))
#{newtab}#{@tab}{
#{newtab}#{@tab}#{@tab}#{throw_type} toThrow = *Mock.#{decl[:function]}_ThrowValue;
#{newtab}#{@tab}#{@tab}Mock.#{decl[:function]}_ThrowOnCallCount++;
#{newtab}#{@tab}#{@tab}Mock.#{decl[:function]}_ThrowValue++;
#{newtab}#{@tab}#{@tab}#{throw_type} toThrow = *Mock.#{function[:name]}_ThrowValue;
#{newtab}#{@tab}#{@tab}Mock.#{function[:name]}_ThrowOnCallCount++;
#{newtab}#{@tab}#{@tab}Mock.#{function[:name]}_ThrowValue++;
#{newtab}#{@tab}#{@tab}Throw(toThrow);
#{newtab}#{@tab}}
#{newtab}}
@@ -513,7 +479,7 @@ EOS
def make_add_new_expected(method, type, expected)
array = make_expand_array(type, "Mock.#{method}_Expected_#{expected}_Head", expected)
array = "#{array}" + "#{@tab}Mock.#{method}_Expected_#{expected} = Mock.#{method}_Expected_#{expected}_Head;\n"
return "#{array}" + "#{@tab}Mock.#{method}_Expected_#{expected} += Mock.#{decl[:function]}_CallCount;\n"
return "#{array}" + "#{@tab}Mock.#{method}_Expected_#{expected} += Mock.#{function[:name]}_CallCount;\n"
end
def make_handle_expected(method, type, actual)
+11 -4
View File
@@ -1,5 +1,7 @@
$here = File.dirname __FILE__
require "#{$here}/cmock_header_parser"
require "#{$here}/cmock_generator"
require "#{$here}/cmock_config"
class CMockSetup
@@ -23,9 +25,14 @@ class CMockSetup
def generate_mock(src)
name = File.basename(src, '.h')
path = File.dirname(src)
cmg = CMockGenerator.new(name, path, @mocks_path, @includes, @use_cexception, @allow_ignore_mock)
$stderr.puts "Creating mock for #{name}..."
$stderr.flush
cmg.create_mock
cmc = CMockConfig.new(path, @mocks_path, @includes, @use_cexception, @allow_ignore_mock)
cmp = CMockHeaderParser.new(File.read(src))
cmg = CMockGenerator.new(cmc, name)
puts "Creating mock for #{name}..."
flush
parsed_stuff = cmp.parse
cmg.create_mock(parsed_stuff)
end
end