mirror of
https://github.com/ThrowTheSwitch/CMock.git
synced 2026-08-09 20:57:51 +00:00
* configurable to complain or use memcompare when can't find good helper
* fixed parser bug: * is now always with type, not argument * more robust struct detection. now can find pointers as _ARRAY helpers * other minor fixes git-svn-id: http://cmock.svn.sourceforge.net/svnroot/cmock/trunk@61 bf332499-1b4d-0410-844d-d2d48d5cc64c
This commit is contained in:
+1
-1
@@ -9,7 +9,7 @@ class CMockConfig
|
||||
'HEX32' => ['unsigned int', 'unsigned long', 'uint32', 'uint32_t', 'UINT32','UINT32_T'],
|
||||
'HEX16' => ['unsigned short', 'uint16', 'uint16_t', 'UINT16', 'UINT16_T'],
|
||||
'HEX8' => ['unsigned char', 'uint8', 'uint8_t', 'UINT8', 'UINT8_T'],
|
||||
'STRING'=> ['char*', 'const char*', 'pCHAR', 'cstring', 'CSTRING']
|
||||
'STRING'=> ['char*', 'pCHAR', 'cstring', 'CSTRING']
|
||||
}
|
||||
|
||||
CMockDefaultOptions =
|
||||
|
||||
@@ -26,17 +26,17 @@ class CMockGeneratorUtils
|
||||
lines << "#{@tab}{\n"
|
||||
lines << "#{@tab}#{@tab}int sz = 0;\n"
|
||||
lines << "#{@tab}#{@tab}#{type} *pointer = #{array};\n"
|
||||
lines << "#{@tab}#{@tab}while(pointer && pointer != #{array}Tail) { sz++; pointer++; }\n"
|
||||
lines << "#{@tab}#{@tab}if(sz == 0)\n"
|
||||
lines << "#{@tab}#{@tab}while (pointer && pointer != #{array}Tail) { sz++; pointer++; }\n"
|
||||
lines << "#{@tab}#{@tab}if (sz == 0)\n"
|
||||
lines << "#{@tab}#{@tab}{\n"
|
||||
lines << "#{@tab}#{@tab}#{@tab}#{array} = (#{type}*)malloc(2*sizeof(#{type}));\n"
|
||||
lines << "#{@tab}#{@tab}#{@tab}if(!#{array})\n"
|
||||
lines << "#{@tab}#{@tab}#{@tab}if (!#{array})\n"
|
||||
lines << "#{@tab}#{@tab}#{@tab}#{@tab}Mock.allocFailure++;\n"
|
||||
lines << "#{@tab}#{@tab}}\n"
|
||||
lines << "#{@tab}#{@tab}else\n"
|
||||
lines << "#{@tab}#{@tab}{\n"
|
||||
lines << "#{@tab}#{@tab}#{@tab}#{type} *ptmp = (#{type}*)realloc(#{array}, sizeof(#{type}) * (sz+1));\n"
|
||||
lines << "#{@tab}#{@tab}#{@tab}if(!ptmp)\n"
|
||||
lines << "#{@tab}#{@tab}#{@tab}if (!ptmp)\n"
|
||||
lines << "#{@tab}#{@tab}#{@tab}#{@tab}Mock.allocFailure++;\n"
|
||||
lines << "#{@tab}#{@tab}#{@tab}else\n"
|
||||
lines << "#{@tab}#{@tab}#{@tab}#{@tab}#{array} = ptmp;\n"
|
||||
@@ -48,7 +48,7 @@ class CMockGeneratorUtils
|
||||
|
||||
def code_handle_return_value(function, indent)
|
||||
lines = ["\n"]
|
||||
lines << "#{indent}if(Mock.#{function[:name]}_Return != Mock.#{function[:name]}_Return_HeadTail)\n"
|
||||
lines << "#{indent}if (Mock.#{function[:name]}_Return != Mock.#{function[:name]}_Return_HeadTail)\n"
|
||||
lines << "#{indent}{\n"
|
||||
lines << "#{indent}#{@tab}#{function[:rettype]} toReturn = *Mock.#{function[:name]}_Return;\n"
|
||||
lines << "#{indent}#{@tab}Mock.#{function[:name]}_Return++;\n"
|
||||
|
||||
@@ -105,16 +105,9 @@ class CMockHeaderParser
|
||||
arg_list.split(',').each do |arg|
|
||||
arg = arg.strip
|
||||
return args if ((arg == '...') || (arg == 'void'))
|
||||
arg_match = arg.match /^(.+)\s+(\*?\w+)$/
|
||||
raise "Failed parsing argument list at argument: '#{arg}'" if arg_match.nil?
|
||||
|
||||
#put the asterisk with the type (where it belongs)
|
||||
if (arg_match[-1][0] == '*')
|
||||
arg_match[1] << '*'
|
||||
arg_match[-1].slice!(0)
|
||||
end
|
||||
|
||||
args << {:type => arg_match[1], :name => arg_match[-1]}
|
||||
arg_match = arg.match /^(.+\s+\*?)(\w+)$/
|
||||
raise "Failed parsing argument list at argument: '#{arg}'" if arg_match.nil?
|
||||
args << {:type => arg_match[1].strip.gsub(/\s+\*/,'*'), :name => arg_match[-1].strip}
|
||||
end
|
||||
return args
|
||||
end
|
||||
|
||||
@@ -3,12 +3,14 @@ class CMockUnityHelperParser
|
||||
attr_accessor :c_types
|
||||
|
||||
def initialize(config)
|
||||
@config = config
|
||||
@c_types = map_C_types(config.treat_as).merge(import_source(config.load_unity_helper))
|
||||
end
|
||||
|
||||
def get_helper(ctype)
|
||||
lookup = ctype.gsub('const','').strip.gsub(/\s+/,'_')
|
||||
lookup = ctype.gsub(/const\s+/,'').strip.gsub(/\s+/,'_')#.gsub(/\*$/,'_ARRAY')
|
||||
return @c_types[lookup] if (@c_types[lookup])
|
||||
raise("Don't know how to test #{ctype} and memory tests are disabled!") unless @config.memcpy_if_unknown
|
||||
return 'TEST_ASSERT_EQUAL_MEMORY_MESSAGE'
|
||||
end
|
||||
|
||||
@@ -25,21 +27,20 @@ class CMockUnityHelperParser
|
||||
def import_source(source=nil)
|
||||
return {} if source.nil?
|
||||
|
||||
a = []
|
||||
c_types = {}
|
||||
source = source.gsub(/\/\/.*$/, '') #remove line comments
|
||||
source = source.gsub(/\/\*.*?\*\//m, '') #remove block comments
|
||||
|
||||
|
||||
#scan for comparison helpers
|
||||
m = Regexp.new('^\s*#define\s+(TEST_ASSERT_EQUAL_(\w+)_MESSAGE|TEST_ASSERT_EQUAL_(\w+))\s*\(' + Array.new(2,'\s*\w+\s*').join(',') + '\)')
|
||||
a += source.scan(m).flatten.compact.reject {|helper| helper.include? "_ARRAY"}
|
||||
|
||||
a = source.scan(m).flatten.compact
|
||||
a.each_slice(2) {|expect, ctype| c_types[ctype] = expect unless expect.include?("_ARRAY")}
|
||||
|
||||
#scan for array variants of those helpers
|
||||
m = Regexp.new('^\s*#define\s+(TEST_ASSERT_EQUAL_(\w+)_ARRAY_MESSAGE|TEST_ASSERT_EQUAL_(\w+)_ARRAY)\s*\(' + Array.new(3,'\s*\w+\s*').join(',') + '\)')
|
||||
a += source.scan(m).flatten.compact
|
||||
|
||||
#add to c_types
|
||||
c_types = {}
|
||||
a.each_slice(2) {|expect, ctype| c_types[ctype] = expect}
|
||||
m = Regexp.new('^\s*#define\s+(TEST_ASSERT_EQUAL_(\w+_ARRAY)_MESSAGE|TEST_ASSERT_EQUAL_(\w+_ARRAY))\s*\(' + Array.new(3,'\s*\w+\s*').join(',') + '\)')
|
||||
a = source.scan(m).flatten.compact
|
||||
a.each_slice(2) {|expect, ctype| c_types[ctype.gsub('_ARRAY','*')] = expect}
|
||||
|
||||
c_types
|
||||
end
|
||||
end
|
||||
|
||||
@@ -56,17 +56,17 @@ class CMockGeneratorUtilsTest < Test::Unit::TestCase
|
||||
" {\n",
|
||||
" int sz = 0;\n",
|
||||
" int *pointer = array;\n",
|
||||
" while(pointer && pointer != arrayTail) { sz++; pointer++; }\n",
|
||||
" if(sz == 0)\n",
|
||||
" while (pointer && pointer != arrayTail) { sz++; pointer++; }\n",
|
||||
" if (sz == 0)\n",
|
||||
" {\n",
|
||||
" array = (int*)malloc(2*sizeof(int));\n",
|
||||
" if(!array)\n",
|
||||
" if (!array)\n",
|
||||
" Mock.allocFailure++;\n",
|
||||
" }\n",
|
||||
" else\n",
|
||||
" {\n",
|
||||
" int *ptmp = (int*)realloc(array, sizeof(int) * (sz+1));\n",
|
||||
" if(!ptmp)\n",
|
||||
" if (!ptmp)\n",
|
||||
" Mock.allocFailure++;\n",
|
||||
" else\n",
|
||||
" array = ptmp;\n"," }\n",
|
||||
@@ -82,17 +82,16 @@ class CMockGeneratorUtilsTest < Test::Unit::TestCase
|
||||
function = { :name => "Spatula", :rettype => "uint64"}
|
||||
indent = "[tab]"
|
||||
expected = ["\n",
|
||||
"[tab]uint64 toReturn;\n",
|
||||
"[tab]if (Mock.Spatula_Return != Mock.Spatula_Return_HeadTail)\n",
|
||||
"[tab]{\n",
|
||||
"[tab] memcpy(&toReturn, Mock.Spatula_Return, sizeof(uint64));\n",
|
||||
"[tab] uint64 toReturn = *Mock.Spatula_Return;\n",
|
||||
"[tab] Mock.Spatula_Return++;\n",
|
||||
"[tab] return toReturn;\n",
|
||||
"[tab]}\n",
|
||||
"[tab]else\n",
|
||||
"[tab]{\n",
|
||||
"[tab] memcpy(&toReturn, Mock.Spatula_Return_Head, sizeof(uint64));\n",
|
||||
"[tab]}\n",
|
||||
"[tab]return toReturn;\n"
|
||||
"[tab] return *Mock.Spatula_Return_Head;\n",
|
||||
"[tab]}\n"
|
||||
]
|
||||
returned = @cmock_generator_utils.code_handle_return_value(function, indent)
|
||||
assert_equal(expected, returned)
|
||||
@@ -107,17 +106,17 @@ class CMockGeneratorUtilsTest < Test::Unit::TestCase
|
||||
" {\n",
|
||||
" int sz = 0;\n",
|
||||
" uint16 *pointer = Mock.PizzaCutter_Expected_Spork_Head;\n",
|
||||
" while(pointer && pointer != Mock.PizzaCutter_Expected_Spork_HeadTail) { sz++; pointer++; }\n",
|
||||
" if(sz == 0)\n",
|
||||
" while (pointer && pointer != Mock.PizzaCutter_Expected_Spork_HeadTail) { sz++; pointer++; }\n",
|
||||
" if (sz == 0)\n",
|
||||
" {\n",
|
||||
" Mock.PizzaCutter_Expected_Spork_Head = (uint16*)malloc(2*sizeof(uint16));\n",
|
||||
" if(!Mock.PizzaCutter_Expected_Spork_Head)\n",
|
||||
" if (!Mock.PizzaCutter_Expected_Spork_Head)\n",
|
||||
" Mock.allocFailure++;\n",
|
||||
" }\n",
|
||||
" else\n",
|
||||
" {\n",
|
||||
" uint16 *ptmp = (uint16*)realloc(Mock.PizzaCutter_Expected_Spork_Head, sizeof(uint16) * (sz+1));\n",
|
||||
" if(!ptmp)\n",
|
||||
" if (!ptmp)\n",
|
||||
" Mock.allocFailure++;\n",
|
||||
" else\n",
|
||||
" Mock.PizzaCutter_Expected_Spork_Head = ptmp;\n",
|
||||
|
||||
@@ -300,7 +300,7 @@ class CMockHeaderParserTest < Test::Unit::TestCase
|
||||
:args_string => "char * const format",
|
||||
:rettype => "int",
|
||||
:var_arg => "...",
|
||||
:args => [{:type => "char * const", :name => "format"}],
|
||||
:args => [{:type => "char* const", :name => "format"}],
|
||||
:name => "printf"
|
||||
},
|
||||
{
|
||||
@@ -320,7 +320,7 @@ class CMockHeaderParserTest < Test::Unit::TestCase
|
||||
|
||||
source =
|
||||
"MY_STRUCT* HooWah(char * format);\n" +
|
||||
"bool* HotShot(HIS_STRUCT *p, unsigned int * pint);\n"
|
||||
"bool* HotShot(HIS_STRUCT *p, unsigned int* pint);\n"
|
||||
|
||||
@parser = CMockHeaderParser.new(source)
|
||||
parsed_stuff = @parser.parse
|
||||
@@ -332,19 +332,19 @@ class CMockHeaderParserTest < Test::Unit::TestCase
|
||||
:args_string => "char * format",
|
||||
:rettype => "MY_STRUCT*",
|
||||
:var_arg => nil,
|
||||
:args => [{:type => "char *", :name => "format"}],
|
||||
:args => [{:type => "char*", :name => "format"}],
|
||||
:name => "HooWah"
|
||||
},
|
||||
|
||||
{
|
||||
:modifier => "",
|
||||
:args_string => "HIS_STRUCT *p, unsigned int * pint",
|
||||
:args_string => "HIS_STRUCT *p, unsigned int* pint",
|
||||
:rettype => "bool*",
|
||||
:var_arg => nil,
|
||||
:args =>
|
||||
[
|
||||
{:type => "HIS_STRUCT", :name => "*p"},
|
||||
{:type => "unsigned int *", :name => "pint"}
|
||||
{:type => "HIS_STRUCT*", :name => "p"},
|
||||
{:type => "unsigned int*", :name => "pint"}
|
||||
],
|
||||
:name => "HotShot"
|
||||
}
|
||||
|
||||
@@ -55,22 +55,46 @@ class CMockUnityHelperParserTest < Test::Unit::TestCase
|
||||
|
||||
assert_equal(expected, @parser.c_types)
|
||||
end
|
||||
|
||||
should "notice equal helpers that contain arrays" do
|
||||
source =
|
||||
"abcd;\n" +
|
||||
"#define TEST_ASSERT_EQUAL_TURKEYS_ARRAY(a,b,c) {...};\n" +
|
||||
"abcd;\n" +
|
||||
"#define TEST_ASSERT_EQUAL_WRONG_NUM_ARGS_ARRAY(a,b,c,d) {...};\n" +
|
||||
"#define TEST_ASSERT_WRONG_NAME_EQUAL_ARRAY(a,b,c) {...};\n" +
|
||||
"#define TEST_ASSERT_EQUAL_unsigned_funky_rabbits_ARRAY(a,b,c) {...};\n" +
|
||||
"abcd;\n"
|
||||
@config.expects.treat_as.returns({})
|
||||
@config.expect.load_unity_helper.returns(source)
|
||||
@parser = CMockUnityHelperParser.new(@config)
|
||||
expected = {
|
||||
'TURKEYS*' => "TEST_ASSERT_EQUAL_TURKEYS_ARRAY",
|
||||
'unsigned_funky_rabbits*' => "TEST_ASSERT_EQUAL_unsigned_funky_rabbits_ARRAY"
|
||||
}
|
||||
|
||||
assert_equal(expected, @parser.c_types)
|
||||
end
|
||||
|
||||
should "be able to fetch helpers on my list" do
|
||||
@config.expects.treat_as.returns({})
|
||||
@config.expect.load_unity_helper.returns("")
|
||||
@parser = CMockUnityHelperParser.new(@config)
|
||||
@parser.c_types = {
|
||||
'UINT8' => "TEST_ASSERT_EQUAL_UINT8_MESSAGE",
|
||||
'UINT16*' => "TEST_ASSERT_EQUAL_UINT16_ARRAY",
|
||||
'SPINACH' => "TEST_ASSERT_EQUAL_SPINACH",
|
||||
'UINT8' => "TEST_ASSERT_EQUAL_UINT8_MESSAGE",
|
||||
'UINT16*' => "TEST_ASSERT_EQUAL_UINT16_ARRAY",
|
||||
'SPINACH' => "TEST_ASSERT_EQUAL_SPINACH",
|
||||
'LONG_LONG' => "TEST_ASSERT_EQUAL_LONG_LONG"
|
||||
}
|
||||
|
||||
assert_equal("TEST_ASSERT_EQUAL_UINT8_MESSAGE", @parser.get_helper("UINT8"))
|
||||
assert_equal("TEST_ASSERT_EQUAL_UINT16_ARRAY", @parser.get_helper("UINT16*"))
|
||||
assert_equal("TEST_ASSERT_EQUAL_SPINACH", @parser.get_helper("SPINACH"))
|
||||
end
|
||||
|
||||
[["UINT8","UINT8_MESSAGE"],
|
||||
["UINT16*","UINT16_ARRAY"],
|
||||
["const SPINACH","SPINACH"],
|
||||
["LONG LONG","LONG_LONG"] ].each do |ctype, exptype|
|
||||
assert_equal("TEST_ASSERT_EQUAL_#{exptype}", @parser.get_helper(ctype))
|
||||
end
|
||||
end
|
||||
|
||||
should "return memory comparison when asked to fetch helper of types not on my list" do
|
||||
@config.expects.treat_as.returns({})
|
||||
@config.expect.load_unity_helper.returns("")
|
||||
@@ -80,11 +104,24 @@ class CMockUnityHelperParserTest < Test::Unit::TestCase
|
||||
'UINT16*' => "TEST_ASSERT_EQUAL_UINT16_ARRAY",
|
||||
'SPINACH' => "TEST_ASSERT_EQUAL_SPINACH",
|
||||
}
|
||||
|
||||
assert_equal("TEST_ASSERT_EQUAL_MEMORY_MESSAGE", @parser.get_helper("UINT16"))
|
||||
assert_equal("TEST_ASSERT_EQUAL_MEMORY_MESSAGE", @parser.get_helper("UINT8*"))
|
||||
assert_equal("TEST_ASSERT_EQUAL_MEMORY_MESSAGE", @parser.get_helper("SPINACH_T"))
|
||||
assert_equal("TEST_ASSERT_EQUAL_MEMORY_MESSAGE", @parser.get_helper("SALAD"))
|
||||
assert_equal("TEST_ASSERT_EQUAL_MEMORY_MESSAGE", @parser.get_helper("PINEAPPLE"))
|
||||
|
||||
["UINT16","UINT8*","SPINACH_T","SALAD","PINEAPPLE"].each do |ctype|
|
||||
@config.expect.memcpy_if_unknown.returns(true)
|
||||
assert_equal("TEST_ASSERT_EQUAL_MEMORY_MESSAGE", @parser.get_helper(ctype))
|
||||
end
|
||||
end
|
||||
|
||||
should "raise error when asked to fetch helper of type not on my list and not allowed to mem check" do
|
||||
@config.expects.treat_as.returns({})
|
||||
@config.expect.load_unity_helper.returns("")
|
||||
@config.expect.memcpy_if_unknown.returns(false)
|
||||
@parser = CMockUnityHelperParser.new(@config)
|
||||
@parser.c_types = {
|
||||
'UINT8' => "TEST_ASSERT_EQUAL_UINT8_MESSAGE",
|
||||
'UINT16*' => "TEST_ASSERT_EQUAL_UINT16_ARRAY",
|
||||
'SPINACH' => "TEST_ASSERT_EQUAL_SPINACH",
|
||||
}
|
||||
|
||||
assert_raise(RuntimeError) { @parser.get_helper("UINT16") }
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user