From 840e38998bcca5c58bb4f0dfb37c2a5e8e2684c1 Mon Sep 17 00:00:00 2001 From: mvandervoord Date: Mon, 19 Jul 2010 14:02:42 +0000 Subject: [PATCH] - support typedefs of pointer types in treat_as - fixed multi-line typedef declaration rejection git-svn-id: http://cmock.svn.sourceforge.net/svnroot/cmock/trunk@179 bf332499-1b4d-0410-844d-d2d48d5cc64c --- lib/cmock_header_parser.rb | 10 ++--- lib/cmock_unityhelper_parser.rb | 8 +++- .../fancy_pointer_handling.yml | 41 +++++++++++++++++++ test/unit/cmock_header_parser_test.rb | 26 +++++++++--- 4 files changed, 72 insertions(+), 13 deletions(-) diff --git a/lib/cmock_header_parser.rb b/lib/cmock_header_parser.rb index 5ecffff..2d37c6b 100644 --- a/lib/cmock_header_parser.rb +++ b/lib/cmock_header_parser.rb @@ -69,11 +69,11 @@ class CMockHeaderParser # 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)[\w\s]*\{[^\}]+\}[\w\s]*;/m, '') # remove struct definitions - source.gsub!(/(\W)(register|auto|static|restrict)(\W)/, '\1\3') # remove problem keywords - source.gsub!(/\s*=\s*['"a-zA-Z0-9_\.]+\s*/, '') # remove default value statements from argument lists - source.gsub!(/^(?:.*\W)?typedef\W.*/, '') # remove typedef statements + source.gsub!(/^[\w\s]*struct[^;\{\}\(\)]+;/m, '') # remove forward declared structs + source.gsub!(/^[\w\s]*(enum|union|struct|typepdef)[\w\s]*\{[^\}]+\}[\w\s\*\,]*;/m, '') # remove struct, union, and enum definitions and typedefs with braces + source.gsub!(/(\W)(register|auto|static|restrict)(\W)/, '\1\3') # remove problem keywords + source.gsub!(/\s*=\s*['"a-zA-Z0-9_\.]+\s*/, '') # remove default value statements from argument lists + source.gsub!(/^(?:[\w\s]*\W)?typedef\W.*/, '') # remove typedef statements #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| diff --git a/lib/cmock_unityhelper_parser.rb b/lib/cmock_unityhelper_parser.rb index 8aad8d8..d4c3ce8 100644 --- a/lib/cmock_unityhelper_parser.rb +++ b/lib/cmock_unityhelper_parser.rb @@ -33,8 +33,12 @@ class CMockUnityHelperParser def map_C_types c_types = {} @config.treat_as.each_pair do |ctype, expecttype| - c_types[ctype.gsub(/\s+/,'_')] = "UNITY_TEST_ASSERT_EQUAL_#{expecttype}" - c_types[ctype.gsub(/\s+/,'_')+'*'] = "UNITY_TEST_ASSERT_EQUAL_#{expecttype}_ARRAY" + if (expecttype =~ /\*/) + c_types[ctype.gsub(/\s+/,'_')] = "UNITY_TEST_ASSERT_EQUAL_#{expecttype.gsub(/\*/,'')}_ARRAY" + else + c_types[ctype.gsub(/\s+/,'_')] = "UNITY_TEST_ASSERT_EQUAL_#{expecttype}" + c_types[ctype.gsub(/\s+/,'_')+'*'] = "UNITY_TEST_ASSERT_EQUAL_#{expecttype}_ARRAY" + end end c_types end diff --git a/test/system/test_interactions/fancy_pointer_handling.yml b/test/system/test_interactions/fancy_pointer_handling.yml index 32adabe..e6e75e5 100644 --- a/test/system/test_interactions/fancy_pointer_handling.yml +++ b/test/system/test_interactions/fancy_pointer_handling.yml @@ -2,6 +2,8 @@ :cmock: :plugins: - # none + :treat_as: + INT_PTR: INT* :systest: :types: | @@ -9,6 +11,7 @@ int x; int y; } POINT_T; + typedef int* INT_PTR; :mockable: | void foo(POINT_T* a); @@ -16,12 +19,14 @@ void fooa(POINT_T a[]); void foos(const char *a); const char* bars(void); + INT_PTR zoink(INT_PTR a); :source: :header: | void function_a(void); void function_b(void); void function_c(void); + int function_d(void); :code: | void function_a(void) @@ -37,6 +42,12 @@ foos(bars()); } + int function_d(void) { + int i = 456; + INT_PTR ptr = (INT_PTR)(&i); + return (int)(*(zoink(ptr))); + } + :tests: :common: | void setUp(void) {} @@ -162,6 +173,36 @@ function_c(); } + + - :pass: TRUE + :should: 'handle handle typedefs that ARE pointers by using treat_as' + :code: | + test() + { + int e = 456; + int r = 789; + INT_PTR ptr_e = (INT_PTR)(&e); + INT_PTR ptr_r = (INT_PTR)(&r); + + zoink_ExpectAndReturn(ptr_e, ptr_r); + + TEST_ASSERT_EQUAL(r, function_d()); + } + + - :pass: FALSE + :should: 'handle handle typedefs that ARE pointers by using treat_as and catch failures' + :code: | + test() + { + int e = 457; + int r = 789; + INT_PTR ptr_e = (INT_PTR)(&e); + INT_PTR ptr_r = (INT_PTR)(&r); + + zoink_ExpectAndReturn(ptr_e, ptr_r); + + TEST_ASSERT_EQUAL(r, function_d()); + } ... diff --git a/test/unit/cmock_header_parser_test.rb b/test/unit/cmock_header_parser_test.rb index 6948229..2e56bfb 100644 --- a/test/unit/cmock_header_parser_test.rb +++ b/test/unit/cmock_header_parser_test.rb @@ -140,12 +140,25 @@ class CMockHeaderParserTest < Test::Unit::TestCase should "remove typedef statements" do source = "typedef uint32 (unsigned int);\n" + - "whack me! typedef int INT;\n" + + "const typedef int INT;\n" + "int notatypedef;\n" + "int typedef_isnt_me;\n" + " typedef who cares what really comes here \\\n" + # exercise multiline typedef " continuation;\n" + - "this should remain!\n" + "this should remain!;\n" + + "typedef blah bleh;\n" + + "typedef struct shell_command_struct {\n" + + " char_ptr COMMAND;\n" + + " int_32 (*SHELL_FUNC)(int_32 argc);\n" + + "} SHELL_COMMAND_STRUCT, * SHELL_COMMAND_PTR;\n" + + "typedef struct shell_command_struct {\n" + + " char_ptr COMMAND;\n" + + " int_32 (*SHELL_FUNC)(int_32 argc, char_ptr argv[]);\n" + + "} SHELL_COMMAND_STRUCT, * SHELL_COMMAND_PTR;\n" + + "typedef struct shell_command_struct {\n" + + " char_ptr COMMAND;\n" + + " int_32 (*SHELL_FUNC)(int_32 argc);\n" + + "};\n" expected = [ @@ -787,7 +800,7 @@ class CMockHeaderParserTest < Test::Unit::TestCase end should "handle arrays and treat them as pointers" do - source = "void KeyOperated(CUSTOM_TYPE thing1[], int thing2 [ ], char thing3 [][2 ][ 3])" + source = "void KeyOperated(CUSTOM_TYPE thing1[], int thing2 [ ], char thing3 [][2 ][ 3], int* thing4[4])" expected = [{:var_arg=>nil, :return=>{ :type => "void", :name => 'cmock_to_return', @@ -801,10 +814,11 @@ class CMockHeaderParserTest < Test::Unit::TestCase :contains_ptr? => true, :args=>[ {:type=>"CUSTOM_TYPE*", :name=>"thing1", :ptr? => true, :const? => false}, {:type=>"int*", :name=>"thing2", :ptr? => true, :const? => false}, - {:type=>"char*", :name=>"thing3", :ptr? => false, :const? => false} #THIS one will likely change in the future when we improve multidimensional array support + {:type=>"char*", :name=>"thing3", :ptr? => false, :const? => false}, #THIS one will likely change in the future when we improve multidimensional array support + {:type=>"int**", :name=>"thing4", :ptr? => true, :const? => false} #THIS one will likely change in the future when we improve multidimensional array support ], - :args_string=>"CUSTOM_TYPE* thing1, int* thing2, char* thing3", - :args_call=>"thing1, thing2, thing3" }] + :args_string=>"CUSTOM_TYPE* thing1, int* thing2, char* thing3, int** thing4", + :args_call=>"thing1, thing2, thing3, thing4" }] result = @parser.parse("module", source) assert_equal(expected, result[:functions]) end