From e2b3365b16c056a02a5dafb38ffb924179dd719f Mon Sep 17 00:00:00 2001 From: mvandervoord Date: Fri, 20 Feb 2009 04:01:04 +0000 Subject: [PATCH] * 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 --- lib/cmock_config.rb | 2 +- lib/cmock_generator_utils.rb | 10 ++-- lib/cmock_header_parser.rb | 13 +---- lib/cmock_unityhelper_parser.rb | 23 ++++---- test/unit/cmock_generator_utils_test.rb | 25 ++++----- test/unit/cmock_header_parser_test.rb | 12 ++-- test/unit/cmock_unityhelper_parser_test.rb | 65 +++++++++++++++++----- 7 files changed, 90 insertions(+), 60 deletions(-) diff --git a/lib/cmock_config.rb b/lib/cmock_config.rb index 76e2897..fd6e21e 100644 --- a/lib/cmock_config.rb +++ b/lib/cmock_config.rb @@ -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 = diff --git a/lib/cmock_generator_utils.rb b/lib/cmock_generator_utils.rb index e131e7e..483bf29 100644 --- a/lib/cmock_generator_utils.rb +++ b/lib/cmock_generator_utils.rb @@ -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" diff --git a/lib/cmock_header_parser.rb b/lib/cmock_header_parser.rb index bdf83a3..f8b5904 100644 --- a/lib/cmock_header_parser.rb +++ b/lib/cmock_header_parser.rb @@ -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 diff --git a/lib/cmock_unityhelper_parser.rb b/lib/cmock_unityhelper_parser.rb index abe6b64..65ca212 100644 --- a/lib/cmock_unityhelper_parser.rb +++ b/lib/cmock_unityhelper_parser.rb @@ -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 diff --git a/test/unit/cmock_generator_utils_test.rb b/test/unit/cmock_generator_utils_test.rb index 6bc9ab3..986cf37 100644 --- a/test/unit/cmock_generator_utils_test.rb +++ b/test/unit/cmock_generator_utils_test.rb @@ -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", diff --git a/test/unit/cmock_header_parser_test.rb b/test/unit/cmock_header_parser_test.rb index 2e7f1d0..7a8abcd 100644 --- a/test/unit/cmock_header_parser_test.rb +++ b/test/unit/cmock_header_parser_test.rb @@ -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" } diff --git a/test/unit/cmock_unityhelper_parser_test.rb b/test/unit/cmock_unityhelper_parser_test.rb index 7858566..1aae55f 100644 --- a/test/unit/cmock_unityhelper_parser_test.rb +++ b/test/unit/cmock_unityhelper_parser_test.rb @@ -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