From b1a290ea7a051b82fbf6360aa02eec6de0f23ce0 Mon Sep 17 00:00:00 2001 From: mvandervoord Date: Sat, 19 Jul 2008 19:00:44 +0000 Subject: [PATCH] brought expectations out to a plugin also git-svn-id: http://cmock.svn.sourceforge.net/svnroot/cmock/trunk@20 bf332499-1b4d-0410-844d-d2d48d5cc64c --- lib/cmock_generator.rb | 181 +---------------------- lib/cmock_generator_plugin_cexception.rb | 10 +- lib/cmock_generator_plugin_expect.rb | 131 ++++++++++++++++ lib/cmock_generator_plugin_ignore.rb | 10 +- lib/cmock_generator_utils.rb | 21 +++ lib/cmock_plugin_manager.rb | 2 + 6 files changed, 173 insertions(+), 182 deletions(-) create mode 100644 lib/cmock_generator_plugin_expect.rb diff --git a/lib/cmock_generator.rb b/lib/cmock_generator.rb index 7a48a30..2578fbe 100644 --- a/lib/cmock_generator.rb +++ b/lib/cmock_generator.rb @@ -26,7 +26,7 @@ class CMockGenerator create_mock_header_header(file, filename) create_mock_header_externs(file, parsed_stuff) parsed_stuff[:functions].each do |function| - create_mock_header_function_declaration(file, function) + @plugins.each { |plugin| file << plugin.mock_function_declarations(function[:name], function[:args_string_without_varargs], function[:rettype]) } end create_mock_header_footer(file) end @@ -42,7 +42,6 @@ class CMockGenerator create_mock_destroy_function(file, parsed_stuff[:functions]) parsed_stuff[:functions].each do |function| create_mock_implementation(file, function) - create_mock_function_expectation(file, function) @plugins.each { |plugin| file << plugin.mock_interfaces( function[:name], function[:args_string_without_varargs], function[:args], function[:rettype]) } end end @@ -71,26 +70,6 @@ class CMockGenerator end end - def create_mock_header_function_declaration(header, function) - - if (function[:args].empty?) - if (function[:rettype] == 'void') - header << "void #{function[:name]}_Expect(void);\n" - else - header << "void #{function[:name]}_ExpectAndReturn(#{function[:rettype]} toReturn);\n" - end - else - if (function[:rettype] == 'void') - header << "void #{function[:name]}_Expect(#{function[:args_string_without_varargs]});\n" - else - header << "void #{function[:name]}_ExpectAndReturn(#{function[:args_string_without_varargs]}, #{function[:rettype]} toReturn);\n" - end - end - - @plugins.each { |plugin| header << plugin.mock_function_declarations(function[:name], function[:args_string_without_varargs], function[:rettype]) } - - end - def create_mock_header_footer(header) header << "\n#endif\n" end @@ -120,25 +99,7 @@ class CMockGenerator file << "#{@tab}unsigned char allocFailure;\n" functions.each do |function| - - file << "#{@tab}#{@config.call_count_type} #{function[:name]}_CallCount;\n" - file << "#{@tab}#{@config.call_count_type} #{function[:name]}_CallsExpected;\n" - - - @plugins.each { |plugin| file << plugin.instance_structure( function[:name] ) } - - if (function[:rettype] != "void") - file << "#{@tab}#{function[:rettype]} *#{function[:name]}_Return;\n" - file << "#{@tab}#{function[:rettype]} *#{function[:name]}_Return_Head;\n" - file << "#{@tab}#{function[:rettype]} *#{function[:name]}_Return_HeadTail;\n" - end - - function[:args].each do |arg| - type = arg[:type].sub(/const/, '').strip - file << "#{@tab}#{type} *#{function[:name]}_Expected_#{arg[:name]};\n" - file << "#{@tab}#{type} *#{function[:name]}_Expected_#{arg[:name]}_Head;\n" - file << "#{@tab}#{type} *#{function[:name]}_Expected_#{arg[:name]}_HeadTail;\n" - end + @plugins.each { |plugin| file << plugin.instance_structure( function[:name], function[:args], function[:rettype] ) } end file << "} Mock;\n\n" end @@ -155,7 +116,7 @@ class CMockGenerator file << "void #{@mock_name}_Verify(void)\n{\n" file << "#{@tab}TEST_ASSERT_EQUAL(0, Mock.allocFailure);\n" functions.each do |function| - file << "#{@tab}TEST_ASSERT_EQUAL_MESSAGE(Mock.#{function[:name]}_CallsExpected, Mock.#{function[:name]}_CallCount, \"Function '#{function[:name]}' called unexpected number of times.\");\n" + @plugins.each { |plugin| file << plugin.mock_verify(function[:name]) } end file << "}\n\n" end @@ -169,46 +130,13 @@ class CMockGenerator def create_mock_destroy_function(file, functions) file << "void #{@mock_name}_Destroy(void)\n{\n" functions.each do |function| - if function[:rettype] != "void" - file << "#{@tab}if(Mock.#{function[:name]}_Return_Head)\n" - file << "#{@tab}{\n" - file << "#{@tab}#{@tab}free(Mock.#{function[:name]}_Return_Head);\n" - file << "#{@tab}#{@tab}Mock.#{function[:name]}_Return_Head=NULL;\n" - file << "#{@tab}#{@tab}Mock.#{function[:name]}_Return_HeadTail=NULL;\n" - file << "#{@tab}}\n" - end - function[:args].each do |arg| - file << "#{@tab}if(Mock.#{function[:name]}_Expected_#{arg[:name]}_Head)\n" - file << "#{@tab}{\n" - file << "#{@tab}#{@tab}free(Mock.#{function[:name]}_Expected_#{arg[:name]}_Head);\n" - file << "#{@tab}#{@tab}Mock.#{function[:name]}_Expected_#{arg[:name]}_Head=NULL;\n" - file << "#{@tab}#{@tab}Mock.#{function[:name]}_Expected_#{arg[:name]}_HeadTail=NULL;\n" - file << "#{@tab}}\n" - end - - @plugins.each { |plugin| file << plugin.mock_destroy(function[:name]) } + @plugins.each { |plugin| file << plugin.mock_destroy(function[:name], function[:args], function[:rettype]) } end file << "#{@tab}memset(&Mock, 0, sizeof(Mock));\n" file << "}\n\n" end - def create_mock_argument_verifier(file, function) - file << "void AssertParameters_#{function[:name]}(#{function[:args_string_without_varargs]})\n{\n" - function[:args].each do |arg| - type = arg[:type].sub(/const/, '').strip - file << make_handle_expected(function, type, arg[:name]) - end - file << "}\n\n" - end - def create_mock_implementation(file, function) - - newtab = "#{@tab}" - - # Create mock argument verifier, if necessary - unless function[:args].empty? - create_mock_argument_verifier(file, function) - end # create return value combo if (function[:modifier].empty?) @@ -223,22 +151,7 @@ class CMockGenerator file << "{\n" @plugins.each { |plugin| file << plugin.mock_implementation_prefix(function[:name], function[:rettype]) } - - file << "#{newtab}Mock.#{function[:name]}_CallCount++;\n" - - #create overcall protection - exp = "Mock.#{function[:name]}_CallsExpected" - file << "#{newtab}if (Mock.#{function[:name]}_CallCount > Mock.#{function[:name]}_CallsExpected)\n" - file << "#{newtab}{\n" - file << "#{newtab}#{@tab}TEST_THROW(\"#{function[:name]} Called More Times Than Expected\");\n" - file << "#{newtab}}\n" - - # Create call to argument verifier, if necessary - unless function[:args].empty? - file << "#{newtab}AssertParameters_#{function[:name]}(#{@utils.create_call_list(function[:args])});\n" - end - - @plugins.each { |plugin| file << plugin.mock_implementation(function[:name]) } + @plugins.each { |plugin| file << plugin.mock_implementation(function[:name], function[:args]) } # Return expected value, if necessary if (function[:rettype] != "void") @@ -248,88 +161,4 @@ class CMockGenerator # Close out the function file << "}\n\n" end - - def create_mock_function_expectation(file, function) - - if (function[:args].empty?) - # Function has void return type with no arguments - if (function[:rettype] == "void") - file << "void #{function[:name]}_Expect(void)\n" - file << "{\n" - file << "#{@tab}Mock.#{function[:name]}_CallsExpected++;\n" - file << "}\n\n" - # Function has non-void return type with no arguments - else - file << "void #{function[:name]}_ExpectAndReturn(#{function[:rettype]} toReturn)\n" - file << "{\n" - file << "#{@tab}Mock.#{function[:name]}_CallsExpected++;\n" - file << @utils.make_expand_array(function[:rettype], "Mock.#{function[:name]}_Return_Head", "toReturn") - file << "#{@tab}Mock.#{function[:name]}_Return = Mock.#{function[:name]}_Return_Head;\n" - file << "#{@tab}Mock.#{function[:name]}_Return += Mock.#{function[:name]}_CallCount;\n" - file << "}\n\n" - end - else - # Create parameter expectation function - file << "void ExpectParameters_#{function[:name]}(#{function[:args_string_without_varargs]})\n" - file << "{\n" - function[:args].each do |arg| - type = arg[:type].sub(/const/, '').strip - file << make_add_new_expected(function, type, arg[:name]) - end - file << "}\n\n" - - # Function has void return type with arguments - if function[:rettype] == "void" - file << "void #{function[:name]}_Expect(#{function[:args_string_without_varargs]})\n" - file << "{\n" - file << "#{@tab}Mock.#{function[:name]}_CallsExpected++;\n" - file << "#{@tab}ExpectParameters_#{function[:name]}(#{@utils.create_call_list(function[:args])});\n" - file << "}\n\n" - # Function has non-void return type with arguments - else - file << "void #{function[:name]}_ExpectAndReturn(#{function[:args_string_without_varargs]}, #{function[:rettype]} toReturn)\n{\n" - file << "#{@tab}Mock.#{function[:name]}_CallsExpected++;\n" - file << "#{@tab}ExpectParameters_#{function[:name]}(#{@utils.create_call_list(function[:args])});\n" - file << @utils.make_expand_array(function[:rettype], "Mock.#{function[:name]}_Return_Head", "toReturn") - file << "#{@tab}Mock.#{function[:name]}_Return = Mock.#{function[:name]}_Return_Head;\n" - file << "#{@tab}Mock.#{function[:name]}_Return += Mock.#{function[:name]}_CallCount;\n" - file << "}\n\n" - end - end - end - - def make_add_new_expected(function, type, expected) - method = function[:name] - array = @utils.make_expand_array(type, "Mock.#{method}_Expected_#{expected}_Head", expected) - array = "#{array}" + "#{@tab}Mock.#{method}_Expected_#{expected} = Mock.#{method}_Expected_#{expected}_Head;\n" - return "#{array}" + "#{@tab}Mock.#{method}_Expected_#{expected} += Mock.#{function[:name]}_CallCount;\n" - end - - def make_handle_expected(function, type, actual) - - method = function[:name] - if (type == "char*" || type == "const char*") - code_block = < Mock.#{function_name}_CallsExpected)\n" + lines << "#{@tab}{\n" + lines << "#{@tab}#{@tab}TEST_THROW(\"#{function_name} Called More Times Than Expected\");\n" + lines << "#{@tab}}\n" + function_args_as_array.each do |arg| + function_return_type = arg[:type].sub(/const/, '').strip + lines << @utils.make_handle_expected(function_name, function_return_type, arg[:name]) + end + lines + end + + def mock_interfaces(function_name, function_args, function_args_as_array, function_return_type) + lines = [] + + # Parameter Helper Function + if (function_args != "void") + lines << "void ExpectParameters_#{function_name}(#{function_args})\n" + lines << "{\n" + function_args_as_array.each do |arg| + type = arg[:type].sub(/const/, '').strip + lines << @utils.make_add_new_expected(function_name, type, arg[:name]) + end + lines << "}\n\n" + end + + #Main Mock Interface + if (function_return_type == "void") + lines << "void #{function_name}_Expect(#{function_args})\n" + else + if (function_args == "void") + lines << "void #{function_name}_ExpectAndReturn(#{function_return_type} toReturn)\n" + else + lines << "void #{function_name}_ExpectAndReturn(#{function_args}, #{function_return_type} toReturn)\n" + end + end + lines << "{\n" + lines << "#{@tab}Mock.#{function_name}_CallsExpected++;\n" + + if (function_args != "void") + lines << "#{@tab}ExpectParameters_#{function_name}(#{@utils.create_call_list(function_args_as_array)});\n" + end + + if (function_return_type != "void") + lines << @utils.make_expand_array(function_return_type, "Mock.#{function_name}_Return_Head", "toReturn") + lines << "#{@tab}Mock.#{function_name}_Return = Mock.#{function_name}_Return_Head;\n" + lines << "#{@tab}Mock.#{function_name}_Return += Mock.#{function_name}_CallCount;\n" + end + lines << "}\n\n" + end + + def mock_verify(function_name) + return "#{@tab}TEST_ASSERT_EQUAL_MESSAGE(Mock.#{function_name}_CallsExpected, Mock.#{function_name}_CallCount, \"Function '#{function_name}' called unexpected number of times.\");\n" + end + + def mock_destroy(function_name, function_args_as_array, function_return_type) + lines = [] + if (function_return_type != "void") + lines << "#{@tab}if (Mock.#{function_name}_Return_Head)\n" + lines << "#{@tab}{\n" + lines << "#{@tab}#{@tab}free(Mock.#{function_name}_Return_Head);\n" + lines << "#{@tab}#{@tab}Mock.#{function_name}_Return_Head=NULL;\n" + lines << "#{@tab}#{@tab}Mock.#{function_name}_Return_HeadTail=NULL;\n" + lines << "#{@tab}}\n" + end + function_args_as_array.each do |arg| + lines << "#{@tab}if (Mock.#{function_name}_Expected_#{arg[:name]}_Head)\n" + lines << "#{@tab}{\n" + lines << "#{@tab}#{@tab}free(Mock.#{function_name}_Expected_#{arg[:name]}_Head);\n" + lines << "#{@tab}#{@tab}Mock.#{function_name}_Expected_#{arg[:name]}_Head=NULL;\n" + lines << "#{@tab}#{@tab}Mock.#{function_name}_Expected_#{arg[:name]}_HeadTail=NULL;\n" + lines << "#{@tab}}\n" + end + lines + end +end diff --git a/lib/cmock_generator_plugin_ignore.rb b/lib/cmock_generator_plugin_ignore.rb index cbb101b..af596db 100644 --- a/lib/cmock_generator_plugin_ignore.rb +++ b/lib/cmock_generator_plugin_ignore.rb @@ -11,7 +11,7 @@ class CMockGeneratorPluginIgnore [] end - def instance_structure(function_name) + def instance_structure(function_name, function_args_as_array, function_return_type) return "#{@tab}#{@config.ignore_bool_type} #{function_name}_IgnoreBool;\n" end @@ -31,7 +31,7 @@ class CMockGeneratorPluginIgnore lines << "#{@tab}}\n" end - def mock_implementation(function_name) + def mock_implementation(function_name, function_args_as_array) [] end @@ -54,7 +54,11 @@ class CMockGeneratorPluginIgnore return lines end - def mock_destroy(function_name) + def mock_verify(function_name) + [] + end + + def mock_destroy(function_name, function_args_as_array, function_return_type) [] end end diff --git a/lib/cmock_generator_utils.rb b/lib/cmock_generator_utils.rb index 36b41fe..be6afba 100644 --- a/lib/cmock_generator_utils.rb +++ b/lib/cmock_generator_utils.rb @@ -56,4 +56,25 @@ class CMockGeneratorUtils lines << "#{indent}#{@tab}return *Mock.#{function_name}_Return_Head;\n" lines << "#{indent}}\n" end + + def make_add_new_expected(function_name, arg_type, expected) + lines = [] + lines << make_expand_array(arg_type, "Mock.#{function_name}_Expected_#{expected}_Head", expected) + lines << "#{@tab}Mock.#{function_name}_Expected_#{expected} = Mock.#{function_name}_Expected_#{expected}_Head;\n" + lines << "#{@tab}Mock.#{function_name}_Expected_#{expected} += Mock.#{function_name}_CallCount;\n" + end + + def make_handle_expected(function_name, arg_type, actual) + lines = ["\n"] + lines << "#{@tab}if(Mock.#{function_name}_Expected_#{actual} != Mock.#{function_name}_Expected_#{actual}_HeadTail)\n" + lines << "#{@tab}{\n" + lines << "#{@tab}#{@tab}#{arg_type}* p_expected = Mock.#{function_name}_Expected_#{actual};\n" + lines << "#{@tab}#{@tab}Mock.#{function_name}_Expected_#{actual}++;\n" + if (arg_type == "char*" || arg_type == "const char*") + lines << "#{@tab}#{@tab}TEST_ASSERT_EQUAL_STRING_MESSAGE(*p_expected, #{actual}, \"Function '#{function_name}' called with unexpected string for parameter '#{actual}'.\");\n" + else + lines << "#{@tab}#{@tab}TEST_ASSERT_EQUAL_MESSAGE(*p_expected, #{actual}, \"Function '#{function_name}' called with unexpected value for parameter '#{actual}'.\");\n" + end + lines << "#{@tab}}\n" + end end \ No newline at end of file diff --git a/lib/cmock_plugin_manager.rb b/lib/cmock_plugin_manager.rb index ce92aaa..39678af 100644 --- a/lib/cmock_plugin_manager.rb +++ b/lib/cmock_plugin_manager.rb @@ -1,4 +1,5 @@ +require "#{$here}/cmock_generator_plugin_expect.rb" require "#{$here}/cmock_generator_plugin_ignore.rb" require "#{$here}/cmock_generator_plugin_cexception.rb" @@ -11,6 +12,7 @@ class CMockPluginManager def get_generator_plugins @plugins = [] + @plugins << CMockGeneratorPluginExpect.new( @config, @utils ) @plugins << CMockGeneratorPluginCException.new( @config, @utils ) if @config.use_cexception @plugins << CMockGeneratorPluginIgnore.new( @config, @utils ) if @config.allow_ignore_mock return @plugins