diff --git a/lib/cmock_config.rb b/lib/cmock_config.rb index 4eebab1..398c582 100644 --- a/lib/cmock_config.rb +++ b/lib/cmock_config.rb @@ -120,6 +120,8 @@ class CMockConfig 'UINT32' => 'HEX32', 'UINT32_T' => 'HEX32', 'void*' => 'HEX8_ARRAY', + 'void const*' => 'HEX8_ARRAY', + 'const void*' => 'HEX8_ARRAY', 'unsigned short' => 'HEX16', 'uint16' => 'HEX16', 'uint16_t' => 'HEX16', @@ -131,6 +133,8 @@ class CMockConfig 'UINT8' => 'HEX8', 'UINT8_T' => 'HEX8', 'char*' => 'STRING', + 'char const*' => 'STRING', + 'const char*' => 'STRING', 'pCHAR' => 'STRING', 'cstring' => 'STRING', 'CSTRING' => 'STRING', diff --git a/lib/cmock_generator.rb b/lib/cmock_generator.rb index 592e979..5cbafcd 100644 --- a/lib/cmock_generator.rb +++ b/lib/cmock_generator.rb @@ -247,10 +247,9 @@ class CMockGenerator file << " if (cmock_call_instance->CallOrder < GlobalVerifyOrder)\n" file << " UNITY_TEST_FAIL(cmock_line, CMockStringCalledLate);\n" end - return_type = function[:return][:const?] ? "(const #{function[:return][:type]})" : ((function[:return][:type] =~ /cmock/) ? "(#{function[:return][:type]})" : '') file << @plugins.run(:mock_implementation, function) file << " UNITY_CLR_DETAILS();\n" - file << " return #{return_type}cmock_call_instance->ReturnVal;\n" unless (function[:return][:void?]) + file << " return cmock_call_instance->ReturnVal;\n" unless (function[:return][:void?]) file << "}\n\n" end diff --git a/lib/cmock_generator_plugin_array.rb b/lib/cmock_generator_plugin_array.rb index 480c1df..3b73708 100644 --- a/lib/cmock_generator_plugin_array.rb +++ b/lib/cmock_generator_plugin_array.rb @@ -27,8 +27,8 @@ class CMockGeneratorPluginArray return nil unless function[:contains_ptr?] args_call = function[:args].map{|m| m[:ptr?] ? "#{m[:name]}, #{m[:name]}_Depth" : "#{m[:name]}"}.join(', ') args_string = function[:args].map do |m| - const_str = m[:const?] ? 'const ' : '' - m[:ptr?] ? "#{const_str}#{m[:type]} #{m[:name]}, int #{m[:name]}_Depth" : "#{const_str}#{m[:type]} #{m[:name]}" + type = @utils.arg_type_with_const(m) + m[:ptr?] ? "#{type} #{m[:name]}, int #{m[:name]}_Depth" : "#{type} #{m[:name]}" end.join(', ') if (function[:return][:void?]) return "#define #{function[:name]}_ExpectWithArray(#{args_call}) #{function[:name]}_CMockExpectWithArray(__LINE__, #{args_call})\n" + @@ -44,8 +44,8 @@ class CMockGeneratorPluginArray lines = [] func_name = function[:name] args_string = function[:args].map do |m| - const_str = m[:const?] ? 'const ' : '' - m[:ptr?] ? "#{const_str}#{m[:type]} #{m[:name]}, int #{m[:name]}_Depth" : "#{const_str}#{m[:type]} #{m[:name]}" + type = @utils.arg_type_with_const(m) + m[:ptr?] ? "#{type} #{m[:name]}, int #{m[:name]}_Depth" : "#{type} #{m[:name]}" end.join(', ') call_string = function[:args].map{|m| m[:ptr?] ? "#{m[:name]}, #{m[:name]}_Depth" : m[:name]}.join(', ') if (function[:return][:void?]) diff --git a/lib/cmock_generator_plugin_callback.rb b/lib/cmock_generator_plugin_callback.rb index 0731c13..da55085 100644 --- a/lib/cmock_generator_plugin_callback.rb +++ b/lib/cmock_generator_plugin_callback.rb @@ -33,7 +33,7 @@ class CMockGeneratorPluginCallback def mock_function_declarations(function) func_name = function[:name] - return_type = function[:return][:const?] ? "const #{function[:return][:type]}" : function[:return][:type] + return_type = function[:return][:type] style = (@include_count ? 1 : 0) | (function[:args].empty? ? 0 : 2) styles = [ "void", "int cmock_num_calls", function[:args_string], "#{function[:args_string]}, int cmock_num_calls" ] "typedef #{return_type} (* CMOCK_#{func_name}_CALLBACK)(#{styles[style]});\nvoid #{func_name}_StubWithCallback(CMOCK_#{func_name}_CALLBACK Callback);\n" @@ -41,7 +41,6 @@ class CMockGeneratorPluginCallback def mock_implementation_for_callbacks_after_arg_check(function) func_name = function[:name] - return_cast = function[:return][:const?] ? "(#{function[:return][:type]})" : "" style = (@include_count ? 1 : 0) | (function[:args].empty? ? 0 : 2) | (function[:return][:void?] ? 0 : 4) " if (Mock.#{func_name}_CallbackFunctionPointer != NULL)\n {\n" + case(style) @@ -49,16 +48,15 @@ class CMockGeneratorPluginCallback when 1 then " Mock.#{func_name}_CallbackFunctionPointer(Mock.#{func_name}_CallbackCalls++);\n }\n" when 2 then " Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')});\n }\n" when 3 then " Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')}, Mock.#{func_name}_CallbackCalls++);\n }\n" - when 4 then " cmock_call_instance->ReturnVal = #{return_cast}Mock.#{func_name}_CallbackFunctionPointer();\n }\n" - when 5 then " cmock_call_instance->ReturnVal = #{return_cast}Mock.#{func_name}_CallbackFunctionPointer(Mock.#{func_name}_CallbackCalls++);\n }\n" - when 6 then " cmock_call_instance->ReturnVal = #{return_cast}Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')});\n }\n" - when 7 then " cmock_call_instance->ReturnVal = #{return_cast}Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')}, Mock.#{func_name}_CallbackCalls++);\n }\n" + when 4 then " cmock_call_instance->ReturnVal = Mock.#{func_name}_CallbackFunctionPointer();\n }\n" + when 5 then " cmock_call_instance->ReturnVal = Mock.#{func_name}_CallbackFunctionPointer(Mock.#{func_name}_CallbackCalls++);\n }\n" + when 6 then " cmock_call_instance->ReturnVal = Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')});\n }\n" + when 7 then " cmock_call_instance->ReturnVal = Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')}, Mock.#{func_name}_CallbackCalls++);\n }\n" end end def mock_implementation_for_callbacks_without_arg_check(function) func_name = function[:name] - return_cast = function[:return][:const?] ? "(#{function[:return][:type]})" : "" style = (@include_count ? 1 : 0) | (function[:args].empty? ? 0 : 2) | (function[:return][:void?] ? 0 : 4) " if (Mock.#{func_name}_CallbackFunctionPointer != NULL)\n {\n" + case(style) @@ -66,10 +64,10 @@ class CMockGeneratorPluginCallback when 1 then " Mock.#{func_name}_CallbackFunctionPointer(Mock.#{func_name}_CallbackCalls++);\n return;\n }\n" when 2 then " Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')});\n return;\n }\n" when 3 then " Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')}, Mock.#{func_name}_CallbackCalls++);\n return;\n }\n" - when 4 then " return #{return_cast}Mock.#{func_name}_CallbackFunctionPointer();\n }\n" - when 5 then " return #{return_cast}Mock.#{func_name}_CallbackFunctionPointer(Mock.#{func_name}_CallbackCalls++);\n }\n" - when 6 then " return #{return_cast}Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')});\n }\n" - when 7 then " return #{return_cast}Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')}, Mock.#{func_name}_CallbackCalls++);\n }\n" + when 4 then " return Mock.#{func_name}_CallbackFunctionPointer();\n }\n" + when 5 then " return Mock.#{func_name}_CallbackFunctionPointer(Mock.#{func_name}_CallbackCalls++);\n }\n" + when 6 then " return Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')});\n }\n" + when 7 then " return Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')}, Mock.#{func_name}_CallbackCalls++);\n }\n" end end diff --git a/lib/cmock_generator_plugin_ignore.rb b/lib/cmock_generator_plugin_ignore.rb index c971830..a291dd4 100644 --- a/lib/cmock_generator_plugin_ignore.rb +++ b/lib/cmock_generator_plugin_ignore.rb @@ -40,10 +40,9 @@ class CMockGeneratorPluginIgnore lines << " return;\n }\n" else retval = function[:return].merge( { :name => "cmock_call_instance->ReturnVal"} ) - return_type = function[:return][:const?] ? "(const #{function[:return][:type]})" : ((function[:return][:type] =~ /cmock/) ? "(#{function[:return][:type]})" : '') - lines << " if (cmock_call_instance == NULL)\n return #{return_type}Mock.#{function[:name]}_FinalReturn;\n" + lines << " if (cmock_call_instance == NULL)\n return Mock.#{function[:name]}_FinalReturn;\n" lines << " " + @utils.code_assign_argument_quickly("Mock.#{function[:name]}_FinalReturn", retval) unless (retval[:void?]) - lines << " return #{return_type}cmock_call_instance->ReturnVal;\n }\n" + lines << " return cmock_call_instance->ReturnVal;\n }\n" end lines end diff --git a/lib/cmock_generator_utils.rb b/lib/cmock_generator_utils.rb index fde3338..eb12e23 100644 --- a/lib/cmock_generator_utils.rb +++ b/lib/cmock_generator_utils.rb @@ -22,6 +22,19 @@ class CMockGeneratorUtils @helpers = helpers end + def self.arg_type_with_const(arg) + # Restore any "const" that was removed in header parsing + if arg[:type].include?('*') + arg[:const_ptr?] ? "#{arg[:type]} const" : arg[:type] + else + arg[:const?] ? "const #{arg[:type]}" : arg[:type] + end + end + + def arg_type_with_const(arg) + self.class.arg_type_with_const(arg) + end + def code_verify_an_arg_expectation(function, arg) if (@arrays) case(@ptr_handling) @@ -58,7 +71,7 @@ class CMockGeneratorUtils def code_assign_argument_quickly(dest, arg) if (arg[:ptr?] or @treat_as.include?(arg[:type])) - " #{dest} = #{arg[:const?] ? "(#{arg[:type]})" : ''}#{arg[:name]};\n" + " #{dest} = #{arg[:name]};\n" else " memcpy(&#{dest}, &#{arg[:name]}, sizeof(#{arg[:type]}));\n" end @@ -68,8 +81,8 @@ class CMockGeneratorUtils if (function[:args_string] != "void") if (@arrays) args_string = function[:args].map do |m| - const_str = m[ :const? ] ? 'const ' : '' - m[:ptr?] ? "#{const_str}#{m[:type]} #{m[:name]}, int #{m[:name]}_Depth" : "#{const_str}#{m[:type]} #{m[:name]}" + type = arg_type_with_const(m) + m[:ptr?] ? "#{type} #{m[:name]}, int #{m[:name]}_Depth" : "#{type} #{m[:name]}" end.join(', ') "void CMockExpectParameters_#{function[:name]}(CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance, #{args_string})\n{\n" + function[:args].inject("") { |all, arg| all + code_add_an_arg_expectation(arg, (arg[:ptr?] ? "#{arg[:name]}_Depth" : 1) ) } + diff --git a/lib/cmock_header_parser.rb b/lib/cmock_header_parser.rb index 85154c7..ee0fe6a 100644 --- a/lib/cmock_header_parser.rb +++ b/lib/cmock_header_parser.rb @@ -140,24 +140,51 @@ class CMockHeaderParser return funcs end + def parse_type_and_name(arg) + # Split up words and remove known attributes. For pointer types, make sure + # to remove 'const' only when it applies to the pointer itself, not when it + # applies to the type pointed to. For non-pointer types, remove any + # occurrence of 'const'. + arg.gsub!(/(\w)\*/,'\1 *') # pull asterisks away from preceding word + arg.gsub!(/\*(\w)/,'* \1') # pull asterisks away from following word + arg_array = arg.split + arg_info = divine_ptr_and_const(arg) + arg_info[:name] = arg_array[-1] + + attributes = arg.include?('*') ? @c_attr_noconst : @c_attributes + attr_array = [] + type_array = [] + + arg_array[0..-2].each do |word| + if attributes.include?(word) + attr_array << word + elsif @c_calling_conventions.include?(word) + arg_info[:c_calling_convention] = word + else + type_array << word + end + end + + if arg_info[:const_ptr?] + attr_array << 'const' + type_array.delete_at(type_array.rindex('const')) + end + + arg_info[:modifier] = attr_array.join(' ') + arg_info[:type] = type_array.join(' ').gsub(/\s+\*/,'*') # remove space before asterisks + return arg_info + end + def parse_args(arg_list) args = [] arg_list.split(',').each do |arg| arg.strip! return args if (arg =~ /^\s*((\.\.\.)|(void))\s*$/) # we're done if we reach void by itself or ... - # Split up words and remove known attributes, but in case of pointer args, don't remove any - # 'const' from the type that it points to, since that may change the underlying assembly-code - # pointer type on some embedded platforms, making it point to RAM instead of ROM. (I.e. For - # pointer args, remove 'const' only when it applies to the pointer itself. For non-pointer - # args, remove 'const' regardless.) - # - arg_array = arg.split - ptr_const_info = divine_ptr_and_const(arg) - arg_elements = arg_array - (arg.include?('*') ? @c_attr_noconst : @c_attributes) - args << { :type => arg_elements[0..(ptr_const_info[:const_ptr?] ? -3 : -2)].join(' '), - :name => arg_elements[-1] - }.merge(ptr_const_info) + arg_info = parse_type_and_name(arg) + arg_info.delete(:modifier) # don't care about this + arg_info.delete(:c_calling_convention) # don't care about this + args << arg_info end return args end @@ -236,35 +263,24 @@ class CMockHeaderParser args = regex_match[2].strip #process function attributes, return type, and name - descriptors = regex_match[1] - descriptors.gsub!(/(\w)\*/,'\1 *') #pull asterisks away from preceding word - descriptors.gsub!(/\*(\w)/,'* \1') #pull asterisks away from following word - descriptors = descriptors.split #array of all descriptor strings + parsed = parse_type_and_name(regex_match[1]) - #grab name - decl[:name] = descriptors[-1] #snag name as last array item - - #build attribute and return type strings - decl[:modifier] = [] - rettype = [] - full_retval = descriptors[0..-2].join(' ') - descriptors[0..-2].each do |word| - if @c_attributes.include?(word) - decl[:modifier] << word - elsif @c_calling_conventions.include?(word) - decl[:c_calling_convention] = word - else - rettype << word - end + decl[:name] = parsed[:name] + decl[:modifier] = parsed[:modifier] + unless parsed[:c_calling_convention].nil? + decl[:c_calling_convention] = parsed[:c_calling_convention] end - decl[:modifier] = decl[:modifier].join(' ') - rettype = rettype.join(' ').gsub(/\s+\*/,'*') #remove space before asterisks + + rettype = parsed[:type] rettype = 'void' if (@local_as_void.include?(rettype.strip)) - decl[:return] = { :type => rettype, - :name => 'cmock_to_return', - :str => "#{rettype} cmock_to_return", - :void? => (rettype == 'void') - }.merge(divine_ptr_and_const(full_retval)) + decl[:return] = { :type => rettype, + :name => 'cmock_to_return', + :str => "#{rettype} cmock_to_return", + :void? => (rettype == 'void'), + :ptr? => parsed[:ptr?], + :const? => parsed[:const?], + :const_ptr? => parsed[:const_ptr?] + } #remove default argument statements from mock definitions args.gsub!(/=\s*[a-zA-Z0-9_\.]+\s*/, ' ') diff --git a/test/test_helper.rb b/test/test_helper.rb index 9bbe3b0..486196c 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -24,20 +24,21 @@ end def test_return { - :int => {:type => "int", :name => 'cmock_to_return', :ptr? => false, :const? => false, :void? => false, :str => 'int cmock_to_return'}, - :int_ptr => {:type => "int*", :name => 'cmock_to_return', :ptr? => true, :const? => false, :void? => false, :str => 'int* cmock_to_return'}, - :void => {:type => "void", :name => 'cmock_to_return', :ptr? => false, :const? => false, :void? => true, :str => 'void cmock_to_return'}, - :string => {:type => "char*", :name => 'cmock_to_return', :ptr? => false, :const? => true, :void? => false, :str => 'const char* cmock_to_return'}, + :int => {:type => "int", :name => 'cmock_to_return', :ptr? => false, :const? => false, :void? => false, :str => 'int cmock_to_return'}, + :int_ptr => {:type => "int*", :name => 'cmock_to_return', :ptr? => true, :const? => false, :void? => false, :str => 'int* cmock_to_return'}, + :void => {:type => "void", :name => 'cmock_to_return', :ptr? => false, :const? => false, :void? => true, :str => 'void cmock_to_return'}, + :string => {:type => "const char*", :name => 'cmock_to_return', :ptr? => false, :const? => true, :void? => false, :str => 'const char* cmock_to_return'}, } end def test_arg { - :int => {:type => "int", :name => 'MyInt', :ptr? => false, :const? => false}, - :int_ptr => {:type => "int*", :name => 'MyIntPtr', :ptr? => true, :const? => false}, - :mytype => {:type => "MY_TYPE", :name => 'MyMyType', :ptr? => false, :const? => true}, - :mytype_ptr => {:type => "MY_TYPE*", :name => 'MyMyTypePtr', :ptr? => true, :const? => false}, - :string => {:type => "char*", :name => 'MyStr', :ptr? => false, :const? => true}, + :int => {:type => "int", :name => 'MyInt', :ptr? => false, :const? => false, :const_ptr? => false}, + :int_ptr => {:type => "int*", :name => 'MyIntPtr', :ptr? => true, :const? => false, :const_ptr? => false}, + :const_ptr => {:type => "int*", :name => 'MyConstPtr', :ptr? => true, :const? => false, :const_ptr? => true}, + :double_ptr => {:type => "int const**", :name => 'MyDoublePtr', :ptr? => true, :const? => true, :const_ptr? => false}, + :mytype => {:type => "MY_TYPE", :name => 'MyMyType', :ptr? => false, :const? => true, :const_ptr? => false}, + :mytype_ptr => {:type => "MY_TYPE*", :name => 'MyMyTypePtr', :ptr? => true, :const? => false, :const_ptr? => false}, + :string => {:type => "const char*", :name => 'MyStr', :ptr? => false, :const? => true, :const_ptr? => false}, } end - diff --git a/test/unit/cmock_generator_plugin_array_test.rb b/test/unit/cmock_generator_plugin_array_test.rb index 3b0b4f8..8449616 100644 --- a/test/unit/cmock_generator_plugin_array_test.rb +++ b/test/unit/cmock_generator_plugin_array_test.rb @@ -6,21 +6,29 @@ require File.expand_path(File.dirname(__FILE__)) + "/../test_helper" require File.expand_path(File.dirname(__FILE__)) + '/../../lib/cmock_generator_plugin_array' +require File.expand_path(File.dirname(__FILE__)) + '/../../lib/cmock_generator_utils' + +class UtilsStub + def helpers + {} + end + def arg_type_with_const(arg) + CMockGeneratorUtils.arg_type_with_const(arg) + end + def code_add_base_expectation(func) + "mock_retval_0" + end +end describe CMockGeneratorPluginArray, "Verify CMockPGeneratorluginArray Module" do before do - create_mocks :utils - #no strict ordering @config = create_stub( :when_ptr => :compare_data, :enforce_strict_ordering => false, :respond_to? => true ) - @utils = create_stub( - :helpers => {}, - :code_add_base_expectation => "mock_retval_0" - ) + @utils = UtilsStub.new @cmock_generator_plugin_array = CMockGeneratorPluginArray.new(@config, @utils) end @@ -88,10 +96,10 @@ describe CMockGeneratorPluginArray, "Verify CMockPGeneratorluginArray Module" do it "add another mock function declaration for functions of style 'const char* func(const int* tofu)'" do function = {:name => "Pine", - :args => [{ :type => "int*", - :name => "tofu", - :ptr? => true, - :const? => true, + :args => [{ :type => "const int*", + :name => "tofu", + :ptr? => true, + :const? => true, }], :return => test_return[:string], :contains_ptr? => true } diff --git a/test/unit/cmock_generator_plugin_ignore_arg_test.rb b/test/unit/cmock_generator_plugin_ignore_arg_test.rb index ed556ea..8ac4648 100644 --- a/test/unit/cmock_generator_plugin_ignore_arg_test.rb +++ b/test/unit/cmock_generator_plugin_ignore_arg_test.rb @@ -21,9 +21,9 @@ describe CMockGeneratorPluginIgnoreArg, "Verify CMockGeneratorPluginIgnoreArg Mo :name => "chicken", :ptr? => false, }, - { :type => "int*", - :name => "beef", - :ptr? => true, + { :type => "const int*", + :name => "beef", + :ptr? => true, :const? => true, }, { :type => "int*", diff --git a/test/unit/cmock_generator_plugin_return_thru_ptr_test.rb b/test/unit/cmock_generator_plugin_return_thru_ptr_test.rb index 68d0fb8..f715880 100644 --- a/test/unit/cmock_generator_plugin_return_thru_ptr_test.rb +++ b/test/unit/cmock_generator_plugin_return_thru_ptr_test.rb @@ -27,9 +27,9 @@ describe CMockGeneratorPluginReturnThruPtr, "Verify CMockGeneratorPluginReturnTh :name => "chicken", :ptr? => false, }, - { :type => "int*", - :name => "beef", - :ptr? => true, + { :type => "const int*", + :name => "beef", + :ptr? => true, :const? => true, }, { :type => "int*", @@ -52,7 +52,7 @@ describe CMockGeneratorPluginReturnThruPtr, "Verify CMockGeneratorPluginReturnTh def complex_func_expect @utils.expect :ptr_or_str?, false, ['int'] - @utils.expect :ptr_or_str?, true, ['int*'] + @utils.expect :ptr_or_str?, true, ['const int*'] @utils.expect :ptr_or_str?, true, ['int*'] end diff --git a/test/unit/cmock_generator_utils_test.rb b/test/unit/cmock_generator_utils_test.rb index aad99ab..bd59749 100644 --- a/test/unit/cmock_generator_utils_test.rb +++ b/test/unit/cmock_generator_utils_test.rb @@ -20,7 +20,7 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do @config.expect :plugins, [] @config.expect :plugins, [] @config.expect :plugins, [] - @config.expect :treat_as, {'int' => 'INT','short' => 'INT16','long' => 'INT','char' => 'INT8','char*' => 'STRING'} + @config.expect :treat_as, {'int' => 'INT','short' => 'INT16','long' => 'INT','char' => 'INT8','const char*' => 'STRING'} @cmock_generator_utils_simple = CMockGeneratorUtils.new(@config, {:unity_helper => @unity_helper}) @config.expect :when_ptr, :smart @@ -31,7 +31,7 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do @config.expect :plugins, [:array, :cexception, :return_thru_ptr, :ignore_arg, :ignore] @config.expect :plugins, [:array, :cexception, :return_thru_ptr, :ignore_arg, :ignore] @config.expect :plugins, [:array, :cexception, :return_thru_ptr, :ignore_arg, :ignore] - @config.expect :treat_as, {'int' => 'INT','short' => 'INT16','long' => 'INT','char' => 'INT8','uint32_t' => 'HEX32','char*' => 'STRING'} + @config.expect :treat_as, {'int' => 'INT','short' => 'INT16','long' => 'INT','char' => 'INT8','uint32_t' => 'HEX32','const char*' => 'STRING'} @cmock_generator_utils_complex = CMockGeneratorUtils.new(@config, {:unity_helper => @unity_helper, :A=>1, :B=>2}) end @@ -99,8 +99,8 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do arg1 = { :name => "Orange", :const? => false, :type => 'int', :ptr? => false } expected1 = " cmock_call_instance->Expected_Orange = Orange;\n" - arg2 = { :name => "Lemon", :const? => true, :type => 'const char*', :ptr? => true } - expected2 = " cmock_call_instance->Expected_Lemon = (const char*)Lemon;\n" + arg2 = { :name => "Lemon", :const? => true, :type => 'const char*', :ptr? => false } + expected2 = " cmock_call_instance->Expected_Lemon = Lemon;\n" arg3 = { :name => "Kiwi", :const? => false, :type => 'KIWI_T*', :ptr? => true } expected3 = " cmock_call_instance->Expected_Kiwi = Kiwi;\n" @@ -119,8 +119,8 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do expected1 = " cmock_call_instance->Expected_Orange = Orange;\n" + " cmock_call_instance->IgnoreArg_Orange = 0;\n" - arg2 = { :name => "Lemon", :const? => true, :type => 'const char*', :ptr? => true } - expected2 = " cmock_call_instance->Expected_Lemon = (const char*)Lemon;\n" + + arg2 = { :name => "Lemon", :const? => true, :type => 'const char*', :ptr? => false } + expected2 = " cmock_call_instance->Expected_Lemon = Lemon;\n" + " cmock_call_instance->Expected_Lemon_Depth = Lemon_Depth;\n" + " cmock_call_instance->IgnoreArg_Lemon = 0;\n" @@ -154,7 +154,7 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do expected = "void CMockExpectParameters_Melon(CMOCK_Melon_CALL_INSTANCE* cmock_call_instance, stuff)\n{\n" + " cmock_call_instance->Expected_MyIntPtr = MyIntPtr;\n" + " memcpy(&cmock_call_instance->Expected_MyMyType, &MyMyType, sizeof(MY_TYPE));\n" + - " cmock_call_instance->Expected_MyStr = (char*)MyStr;\n" + + " cmock_call_instance->Expected_MyStr = MyStr;\n" + "}\n\n" assert_equal(expected, @cmock_generator_utils_simple.code_add_argument_loader(function)) end @@ -171,12 +171,29 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do " cmock_call_instance->ReturnThruPtr_MyIntPtr_Used = 0;\n" + " memcpy(&cmock_call_instance->Expected_MyMyType, &MyMyType, sizeof(MY_TYPE));\n" + " cmock_call_instance->IgnoreArg_MyMyType = 0;\n" + - " cmock_call_instance->Expected_MyStr = (char*)MyStr;\n" + + " cmock_call_instance->Expected_MyStr = MyStr;\n" + " cmock_call_instance->IgnoreArg_MyStr = 0;\n" + "}\n\n" assert_equal(expected, @cmock_generator_utils_complex.code_add_argument_loader(function)) end + it 'create an argument loader when the function has pointer arguments supporting arrays' do + function = { :name => "Melon", + :args_string => "stuff", + :args => [test_arg[:const_ptr], test_arg[:double_ptr]] + } + expected = "void CMockExpectParameters_Melon(CMOCK_Melon_CALL_INSTANCE* cmock_call_instance, int* const MyConstPtr, int MyConstPtr_Depth, int const** MyDoublePtr, int MyDoublePtr_Depth)\n{\n" + + " cmock_call_instance->Expected_MyConstPtr = MyConstPtr;\n" + + " cmock_call_instance->Expected_MyConstPtr_Depth = MyConstPtr_Depth;\n" + + " cmock_call_instance->IgnoreArg_MyConstPtr = 0;\n" + + " cmock_call_instance->ReturnThruPtr_MyConstPtr_Used = 0;\n" + + " cmock_call_instance->Expected_MyDoublePtr = MyDoublePtr;\n" + + " cmock_call_instance->Expected_MyDoublePtr_Depth = MyDoublePtr_Depth;\n" + + " cmock_call_instance->IgnoreArg_MyDoublePtr = 0;\n" + + "}\n\n" + assert_equal(expected, @cmock_generator_utils_complex.code_add_argument_loader(function)) + end + it "not call argument loader if there are no arguments to actually use for this function" do function = { :name => "Pineapple", :args_string => "void" } @@ -231,7 +248,7 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do " UNITY_TEST_ASSERT_EQUAL_STRING(cmock_call_instance->Expected_MyStr, MyStr, cmock_line, CMockStringMismatch);\n" + " }\n" @unity_helper.expect :nil?, false - @unity_helper.expect :get_helper, ['UNITY_TEST_ASSERT_EQUAL_STRING',''], ['char*'] + @unity_helper.expect :get_helper, ['UNITY_TEST_ASSERT_EQUAL_STRING',''], ['const char*'] assert_equal(expected, @cmock_generator_utils_simple.code_verify_an_arg_expectation(function, arg)) end @@ -311,7 +328,7 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do " UNITY_TEST_ASSERT_EQUAL_STRING(cmock_call_instance->Expected_MyStr, MyStr, cmock_line, CMockStringMismatch);\n" + " }\n" @unity_helper.expect :nil?, false - @unity_helper.expect :get_helper, ['UNITY_TEST_ASSERT_EQUAL_STRING',''], ['char*'] + @unity_helper.expect :get_helper, ['UNITY_TEST_ASSERT_EQUAL_STRING',''], ['const char*'] assert_equal(expected, @cmock_generator_utils_complex.code_verify_an_arg_expectation(function, arg)) end diff --git a/test/unit/cmock_header_parser_test.rb b/test/unit/cmock_header_parser_test.rb index c6cecc0..add920f 100644 --- a/test/unit/cmock_header_parser_test.rb +++ b/test/unit/cmock_header_parser_test.rb @@ -805,32 +805,57 @@ describe CMockHeaderParser, "Verify CMockHeaderParser Module" do assert_equal(expected, @parser.parse("module", source)[:functions]) end - it "should properly handle const before or after return type" do - + it "should properly handle const before return type" do sources = [ "const int * PorkRoast(void);\n", - "int const * PorkRoast(void);\n", "const int* PorkRoast(void);\n", + "const int *PorkRoast(void);\n" + ] + + expected = [{ :var_arg => nil, + :name => "PorkRoast", + :return => { :type => "const int*", + :name => 'cmock_to_return', + :ptr? => true, + :const? => true, + :const_ptr? => false, + :str => "const int* cmock_to_return", + :void? => false + }, + :modifier => "", + :contains_ptr? => false, + :args => [], + :args_string => "void", + :args_call => "" + }] + + sources.each do |source| + assert_equal(expected, @parser.parse("module", source)[:functions]) + end + end + + it "should properly handle const before return type" do + sources = [ + "int const * PorkRoast(void);\n", "int const* PorkRoast(void);\n", - "const int *PorkRoast(void);\n", "int const *PorkRoast(void);\n" ] - expected = [{ :var_arg=>nil, - :name=>"PorkRoast", - :return=> { :type => "int*", - :name => 'cmock_to_return', - :ptr? => true, - :const? => true, - :const_ptr? => false, - :str => "int* cmock_to_return", - :void? => false - }, - :modifier=>"const", + expected = [{ :var_arg => nil, + :name => "PorkRoast", + :return => { :type => "int const*", + :name => 'cmock_to_return', + :ptr? => true, + :const? => true, + :const_ptr? => false, + :str => "int const* cmock_to_return", + :void? => false + }, + :modifier => "", :contains_ptr? => false, - :args=>[], - :args_string=>"void", - :args_call=>"" + :args => [], + :args_string => "void", + :args_call => "" }] sources.each do |source|