* 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:
mvandervoord
2009-02-20 04:01:04 +00:00
parent 79ea4fa7fc
commit e2b3365b16
7 changed files with 90 additions and 60 deletions
+1 -1
View File
@@ -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 =
+5 -5
View File
@@ -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"
+3 -10
View File
@@ -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
+12 -11
View File
@@ -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
+12 -13
View File
@@ -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",
+6 -6
View File
@@ -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"
}
+51 -14
View File
@@ -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