From 8fb0ca9d499b38c06d789f1d95d5d813430d1381 Mon Sep 17 00:00:00 2001 From: mvandervoord Date: Sat, 11 Apr 2009 03:06:09 +0000 Subject: [PATCH] - added strict ordering support option - updated yaml config file to use symbol for root (to be consistent with other places). git-svn-id: http://cmock.svn.sourceforge.net/svnroot/cmock/trunk@72 bf332499-1b4d-0410-844d-d2d48d5cc64c --- gcc.yml | 2 +- iar_v4.yml | 2 +- iar_v5.yml | 2 +- lib/cmock_config.rb | 4 +- lib/cmock_generator.rb | 2 + lib/cmock_generator_plugin_cexception.rb | 88 +++++++++---------- lib/cmock_generator_plugin_expect.rb | 86 ++++++++++-------- lib/cmock_generator_plugin_ignore.rb | 37 ++++---- lib/cmock_generator_utils.rb | 57 +++++++----- lib/cmock_unityhelper_parser.rb | 2 +- test/unit/cmock_config_test.yml | 2 +- test/unit/cmock_generator_main_test.rb | 12 ++- .../cmock_generator_plugin_cexception_test.rb | 8 +- .../cmock_generator_plugin_expect_test.rb | 44 +++++++++- test/unit/cmock_generator_utils_test.rb | 40 +++++++++ test/unit/cmock_plugin_manager_test.rb | 1 + test/unit/cmock_unityhelper_parser_test.rb | 4 +- 17 files changed, 250 insertions(+), 143 deletions(-) diff --git a/gcc.yml b/gcc.yml index 7d3a6a3..4dfb130 100644 --- a/gcc.yml +++ b/gcc.yml @@ -33,7 +33,7 @@ linker: prefix: '-o' extension: '.exe' destination: *build_path -cmock: +:cmock: :mock_path: 'examples/mocks/' :includes: - 'Types.h' diff --git a/iar_v4.yml b/iar_v4.yml index 498e952..d3fdc35 100644 --- a/iar_v4.yml +++ b/iar_v4.yml @@ -84,7 +84,7 @@ simulator: - [*tools_root, 'arm\config\ioat91sam7X256.ddf'] - -d - sim -cmock: +:cmock: :mock_path: 'examples/mocks/' :includes: - 'Types.h' diff --git a/iar_v5.yml b/iar_v5.yml index 7b6fe2c..6a3157e 100644 --- a/iar_v5.yml +++ b/iar_v5.yml @@ -73,7 +73,7 @@ simulator: - [*tools_root, 'arm\config\debugger\Atmel\ioat91sam7X256.ddf'] - -d - sim -cmock: +:cmock: :mock_path: 'examples/mocks/' :includes: - 'Types.h' diff --git a/lib/cmock_config.rb b/lib/cmock_config.rb index 134648b..f48a68d 100644 --- a/lib/cmock_config.rb +++ b/lib/cmock_config.rb @@ -15,7 +15,7 @@ class CMockConfig :cexception_throw_type => 'int', :unity_helper => false, :treat_as => {}, - :memcpy_if_unknown => true, + :memcmp_if_unknown => true, :when_ptr_star =>:compare_data, #the options being :compare_ptr, :compare_data, :compare_array :when_ptr_brackets => :compare_array, #not really supported yet } @@ -34,7 +34,7 @@ class CMockConfig def load_config_file_from_yaml yaml_filename require 'yaml' require 'fileutils' - YAML.load(File.read(yaml_filename))['cmock'] + YAML.load_file(yaml_filename)[:cmock] end def set_path(path) diff --git a/lib/cmock_generator.rb b/lib/cmock_generator.rb index b0dcf26..7837ee0 100644 --- a/lib/cmock_generator.rb +++ b/lib/cmock_generator.rb @@ -100,6 +100,8 @@ class CMockGenerator def create_extern_declarations(file, externs) file << externs.collect {|extern| extern.gsub(/extern\s*/,'') << ";\n"}.flatten file << "extern jmp_buf AbortFrame;\n" + file << "extern int GlobalExpectOrder;\n" + file << "extern int GlobalVerifyOrder;\n" file << "\n" end diff --git a/lib/cmock_generator_plugin_cexception.rb b/lib/cmock_generator_plugin_cexception.rb index 7b27356..7b2109d 100644 --- a/lib/cmock_generator_plugin_cexception.rb +++ b/lib/cmock_generator_plugin_cexception.rb @@ -20,15 +20,14 @@ class CMockGeneratorPluginCException end def instance_structure(function) - lines = [] call_count_type = @config.cexception_call_count_type throw_type = @config.cexception_throw_type - lines << "#{@tab}#{call_count_type} *#{function[:name]}_ThrowOnCallCount;\n" - lines << "#{@tab}#{call_count_type} *#{function[:name]}_ThrowOnCallCount_Head;\n" - lines << "#{@tab}#{call_count_type} *#{function[:name]}_ThrowOnCallCount_Tail;\n" - lines << "#{@tab}#{throw_type} *#{function[:name]}_ThrowValue;\n" - lines << "#{@tab}#{throw_type} *#{function[:name]}_ThrowValue_Head;\n" - lines << "#{@tab}#{throw_type} *#{function[:name]}_ThrowValue_Tail;\n" + [ "#{@tab}#{call_count_type} *#{function[:name]}_ThrowOnCallCount;\n", + "#{@tab}#{call_count_type} *#{function[:name]}_ThrowOnCallCount_Head;\n", + "#{@tab}#{call_count_type} *#{function[:name]}_ThrowOnCallCount_Tail;\n", + "#{@tab}#{throw_type} *#{function[:name]}_ThrowValue;\n", + "#{@tab}#{throw_type} *#{function[:name]}_ThrowValue_Head;\n", + "#{@tab}#{throw_type} *#{function[:name]}_ThrowValue_Tail;\n" ] end def mock_function_declarations(function) @@ -40,53 +39,50 @@ class CMockGeneratorPluginCException end def mock_implementation(function) - lines = ["\n"] - lines << "#{@tab}if((Mock.#{function[:name]}_ThrowOnCallCount != Mock.#{function[:name]}_ThrowOnCallCount_Tail) &&\n" - lines << "#{@tab}#{@tab}(Mock.#{function[:name]}_ThrowValue != Mock.#{function[:name]}_ThrowValue_Tail))\n" - lines << "#{@tab}{\n" - lines << "#{@tab}#{@tab}if (*Mock.#{function[:name]}_ThrowOnCallCount && \n" - lines << "#{@tab}#{@tab}#{@tab}(Mock.#{function[:name]}_CallCount == *Mock.#{function[:name]}_ThrowOnCallCount))\n" - lines << "#{@tab}#{@tab}{\n" - lines << "#{@tab}#{@tab}#{@tab}#{@config.cexception_throw_type} toThrow = *Mock.#{function[:name]}_ThrowValue;\n" - lines << "#{@tab}#{@tab}#{@tab}Mock.#{function[:name]}_ThrowOnCallCount++;\n" - lines << "#{@tab}#{@tab}#{@tab}Mock.#{function[:name]}_ThrowValue++;\n" - lines << "#{@tab}#{@tab}#{@tab}Throw(toThrow);\n" - lines << "#{@tab}#{@tab}}\n" - lines << "#{@tab}}\n" + [ "\n", + "#{@tab}if((Mock.#{function[:name]}_ThrowOnCallCount != Mock.#{function[:name]}_ThrowOnCallCount_Tail) &&\n", + "#{@tab}#{@tab}(Mock.#{function[:name]}_ThrowValue != Mock.#{function[:name]}_ThrowValue_Tail))\n", + "#{@tab}{\n", + "#{@tab}#{@tab}if (*Mock.#{function[:name]}_ThrowOnCallCount && \n", + "#{@tab}#{@tab}#{@tab}(Mock.#{function[:name]}_CallCount == *Mock.#{function[:name]}_ThrowOnCallCount))\n", + "#{@tab}#{@tab}{\n", + "#{@tab}#{@tab}#{@tab}#{@config.cexception_throw_type} toThrow = *Mock.#{function[:name]}_ThrowValue;\n", + "#{@tab}#{@tab}#{@tab}Mock.#{function[:name]}_ThrowOnCallCount++;\n", + "#{@tab}#{@tab}#{@tab}Mock.#{function[:name]}_ThrowValue++;\n", + "#{@tab}#{@tab}#{@tab}Throw(toThrow);\n", + "#{@tab}#{@tab}}\n", + "#{@tab}}\n" ] end def mock_interfaces(function) arg_insert = (function[:args_string] == "void") ? "" : "#{function[:args_string]}, " call_count_type = @config.cexception_call_count_type throw_type = @config.cexception_throw_type - lines = [] - lines << "void #{function[:name]}_ExpectAndThrow(#{arg_insert}#{throw_type} toThrow)\n" - lines << "{\n" - lines << "#{@tab}Mock.#{function[:name]}_CallsExpected++;\n" - lines << @utils.code_insert_item_into_expect_array(call_count_type, "Mock.#{function[:name]}_ThrowOnCallCount_Head", "Mock.#{function[:name]}_CallsExpected") - lines << "#{@tab}Mock.#{function[:name]}_ThrowOnCallCount = Mock.#{function[:name]}_ThrowOnCallCount_Head;\n" - lines << "#{@tab}Mock.#{function[:name]}_ThrowOnCallCount += Mock.#{function[:name]}_CallCount;\n" - lines << @utils.code_insert_item_into_expect_array(throw_type, "Mock.#{function[:name]}_ThrowValue_Head", "toThrow") - lines << "#{@tab}Mock.#{function[:name]}_ThrowValue = Mock.#{function[:name]}_ThrowValue_Head;\n" - lines << "#{@tab}Mock.#{function[:name]}_ThrowValue += Mock.#{function[:name]}_CallCount;\n" - lines << "#{@tab}ExpectParameters_#{function[:name]}(#{@utils.create_call_list(function)});\n" if (function[:args_string] != "void") - lines << "}\n\n" + [ "void #{function[:name]}_ExpectAndThrow(#{arg_insert}#{throw_type} toThrow)\n", + "{\n", + @utils.code_add_base_expectation(function[:name]), + @utils.code_insert_item_into_expect_array(call_count_type, "Mock.#{function[:name]}_ThrowOnCallCount_Head", "Mock.#{function[:name]}_CallsExpected"), + "#{@tab}Mock.#{function[:name]}_ThrowOnCallCount = Mock.#{function[:name]}_ThrowOnCallCount_Head;\n", + "#{@tab}Mock.#{function[:name]}_ThrowOnCallCount += Mock.#{function[:name]}_CallCount;\n", + @utils.code_insert_item_into_expect_array(throw_type, "Mock.#{function[:name]}_ThrowValue_Head", "toThrow"), + "#{@tab}Mock.#{function[:name]}_ThrowValue = Mock.#{function[:name]}_ThrowValue_Head;\n", + "#{@tab}Mock.#{function[:name]}_ThrowValue += Mock.#{function[:name]}_CallCount;\n", + (function[:args_string] != "void") ? "#{@tab}ExpectParameters_#{function[:name]}(#{@utils.create_call_list(function)});\n" : nil, + "}\n\n" ].compact end def mock_destroy(function) - lines = [] - lines << "#{@tab}if(Mock.#{function[:name]}_ThrowOnCallCount_Head)\n" - lines << "#{@tab}{\n" - lines << "#{@tab}#{@tab}free(Mock.#{function[:name]}_ThrowOnCallCount_Head);\n" - lines << "#{@tab}#{@tab}Mock.#{function[:name]}_ThrowOnCallCount_Head=NULL;\n" - lines << "#{@tab}#{@tab}Mock.#{function[:name]}_ThrowOnCallCount_Tail=NULL;\n" - lines << "#{@tab}}\n" - - lines << "#{@tab}if(Mock.#{function[:name]}_ThrowValue_Head)\n" - lines << "#{@tab}{\n" - lines << "#{@tab}#{@tab}free(Mock.#{function[:name]}_ThrowValue_Head);\n" - lines << "#{@tab}#{@tab}Mock.#{function[:name]}_ThrowValue_Head=NULL;\n" - lines << "#{@tab}#{@tab}Mock.#{function[:name]}_ThrowValue_Tail=NULL;\n" - lines << "#{@tab}}\n" + [ "#{@tab}if(Mock.#{function[:name]}_ThrowOnCallCount_Head)\n", + "#{@tab}{\n", + "#{@tab}#{@tab}free(Mock.#{function[:name]}_ThrowOnCallCount_Head);\n", + "#{@tab}#{@tab}Mock.#{function[:name]}_ThrowOnCallCount_Head=NULL;\n", + "#{@tab}#{@tab}Mock.#{function[:name]}_ThrowOnCallCount_Tail=NULL;\n", + "#{@tab}}\n", + "#{@tab}if(Mock.#{function[:name]}_ThrowValue_Head)\n", + "#{@tab}{\n", + "#{@tab}#{@tab}free(Mock.#{function[:name]}_ThrowValue_Head);\n", + "#{@tab}#{@tab}Mock.#{function[:name]}_ThrowValue_Head=NULL;\n", + "#{@tab}#{@tab}Mock.#{function[:name]}_ThrowValue_Tail=NULL;\n", + "#{@tab}}\n" ] end end diff --git a/lib/cmock_generator_plugin_expect.rb b/lib/cmock_generator_plugin_expect.rb index 053bfed..5afd304 100644 --- a/lib/cmock_generator_plugin_expect.rb +++ b/lib/cmock_generator_plugin_expect.rb @@ -1,35 +1,41 @@ class CMockGeneratorPluginExpect - attr_reader :config, :utils, :tab, :unity_helper + attr_accessor :config, :utils, :tab, :unity_helper, :ordered def initialize(config, utils) - @config = config - @tab = @config.tab + @config = config + @tab = @config.tab @ptr_handling = @config.when_ptr_star - @utils = utils + @ordered = @config.enforce_strict_ordering + @utils = utils @unity_helper = @utils.helpers[:unity_helper] end def instance_structure(function) call_count_type = @config.expect_call_count_type - lines = [] - lines << "#{@tab}#{call_count_type} #{function[:name]}_CallCount;\n" - lines << "#{@tab}#{call_count_type} #{function[:name]}_CallsExpected;\n" + lines = [ "#{@tab}#{call_count_type} #{function[:name]}_CallCount;\n", + "#{@tab}#{call_count_type} #{function[:name]}_CallsExpected;\n" ] if (function[:rettype] != "void") - lines << "#{@tab}#{function[:rettype]} *#{function[:name]}_Return;\n" - lines << "#{@tab}#{function[:rettype]} *#{function[:name]}_Return_Head;\n" - lines << "#{@tab}#{function[:rettype]} *#{function[:name]}_Return_Tail;\n" + lines << [ "#{@tab}#{function[:rettype]} *#{function[:name]}_Return;\n", + "#{@tab}#{function[:rettype]} *#{function[:name]}_Return_Head;\n", + "#{@tab}#{function[:rettype]} *#{function[:name]}_Return_Tail;\n" ] end + if (@ordered) + lines << [ "#{@tab}#{function[:rettype]} *#{function[:name]}_CallOrder;\n", + "#{@tab}#{function[:rettype]} *#{function[:name]}_CallOrder_Head;\n", + "#{@tab}#{function[:rettype]} *#{function[:name]}_CallOrder_Tail;\n" ] + end + function[:args].each do |arg| type = arg[:type].sub(/const/, '').strip - lines << "#{@tab}#{type} *#{function[:name]}_Expected_#{arg[:name]};\n" - lines << "#{@tab}#{type} *#{function[:name]}_Expected_#{arg[:name]}_Head;\n" - lines << "#{@tab}#{type} *#{function[:name]}_Expected_#{arg[:name]}_Tail;\n" + lines << [ "#{@tab}#{type} *#{function[:name]}_Expected_#{arg[:name]};\n", + "#{@tab}#{type} *#{function[:name]}_Expected_#{arg[:name]}_Head;\n", + "#{@tab}#{type} *#{function[:name]}_Expected_#{arg[:name]}_Tail;\n" ] end - lines + lines.flatten end def mock_function_declarations(function) @@ -49,17 +55,27 @@ class CMockGeneratorPluginExpect end def mock_implementation(function) - lines = [] - lines << "#{@tab}Mock.#{function[:name]}_CallCount++;\n" - lines << "#{@tab}if (Mock.#{function[:name]}_CallCount > Mock.#{function[:name]}_CallsExpected)\n" - lines << "#{@tab}{\n" - lines << "#{@tab}#{@tab}TEST_FAIL(\"#{function[:name]} Called More Times Than Expected\");\n" - lines << "#{@tab}}\n" + lines = [ "#{@tab}Mock.#{function[:name]}_CallCount++;\n", + "#{@tab}if (Mock.#{function[:name]}_CallCount > Mock.#{function[:name]}_CallsExpected)\n", + "#{@tab}{\n", + "#{@tab}#{@tab}TEST_FAIL(\"#{function[:name]} Called More Times Than Expected\");\n", + "#{@tab}}\n" ] + + if (@ordered) + lines << [ "#{@tab}{\n", + "#{@tab}#{@tab}int* p_expected = Mock.#{function[:name]}_CallOrder;\n", + "#{@tab}#{@tab}++GlobalVerifyOrder;\n", + "#{@tab}#{@tab}if (Mock.#{function[:name]}_CallOrder != Mock.#{function[:name]}_CallOrder_Tail)\n", + "#{@tab}#{@tab}#{@tab}Mock.#{function[:name]}_CallOrder++;\n", + @utils.expect_helper('int', '*p_expected', 'GlobalVerifyOrder', "\"Function '#{function[:name]}' Called Out Of Order.\"","#{@tab}#{@tab}"), + "#{@tab}}\n" ] + end + function[:args].each do |arg| arg_return_type = arg[:type].sub(/const/, '').strip lines << @utils.code_verify_an_arg_expectation(function, arg_return_type, arg[:name]) end - lines + lines.flatten end def mock_interfaces(function) @@ -87,7 +103,7 @@ class CMockGeneratorPluginExpect end end lines << "{\n" - lines << "#{@tab}Mock.#{function[:name]}_CallsExpected++;\n" + lines << @utils.code_add_base_expectation(function[:name]) if (function[:args_string] != "void") lines << "#{@tab}ExpectParameters_#{function[:name]}(#{@utils.create_call_list(function)});\n" @@ -108,21 +124,21 @@ class CMockGeneratorPluginExpect def mock_destroy(function) lines = [] if (function[:rettype] != "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_Tail=NULL;\n" - lines << "#{@tab}}\n" + lines << [ "#{@tab}if (Mock.#{function[:name]}_Return_Head)\n", + "#{@tab}{\n", + "#{@tab}#{@tab}free(Mock.#{function[:name]}_Return_Head);\n", + "#{@tab}#{@tab}Mock.#{function[:name]}_Return_Head=NULL;\n", + "#{@tab}#{@tab}Mock.#{function[:name]}_Return_Tail=NULL;\n", + "#{@tab}}\n" ] end function[:args].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]}_Tail=NULL;\n" - lines << "#{@tab}}\n" + lines << [ "#{@tab}if (Mock.#{function[:name]}_Expected_#{arg[:name]}_Head)\n", + "#{@tab}{\n", + "#{@tab}#{@tab}free(Mock.#{function[:name]}_Expected_#{arg[:name]}_Head);\n", + "#{@tab}#{@tab}Mock.#{function[:name]}_Expected_#{arg[:name]}_Head=NULL;\n", + "#{@tab}#{@tab}Mock.#{function[:name]}_Expected_#{arg[:name]}_Tail=NULL;\n", + "#{@tab}}\n" ] end - lines + lines.flatten end end diff --git a/lib/cmock_generator_plugin_ignore.rb b/lib/cmock_generator_plugin_ignore.rb index 273a29b..65a3849 100644 --- a/lib/cmock_generator_plugin_ignore.rb +++ b/lib/cmock_generator_plugin_ignore.rb @@ -26,33 +26,26 @@ class CMockGeneratorPluginIgnore end def mock_implementation_prefix(function) - lines = [] - lines << "#{@tab}if (Mock.#{function[:name]}_IgnoreBool)\n" - lines << "#{@tab}{\n" - if (function[:rettype] == "void") - lines << "#{@tab}#{@tab}return;\n" - else - lines << @utils.code_handle_return_value(function, "#{@tab}#{@tab}") - end - lines << "#{@tab}}\n" + [ "#{@tab}if (Mock.#{function[:name]}_IgnoreBool)\n", + "#{@tab}{\n", + (function[:rettype] == "void") ? "#{@tab}#{@tab}return;\n" : @utils.code_handle_return_value(function, "#{@tab}#{@tab}"), + "#{@tab}}\n" ] end def mock_interfaces(function) - lines = [] if (function[:rettype] == "void") - lines << "void #{function[:name]}_Ignore(void)\n" - lines << "{\n" - lines << "#{@tab}Mock.#{function[:name]}_IgnoreBool = (unsigned char)1;\n" - lines << "}\n\n" + [ "void #{function[:name]}_Ignore(void)\n", + "{\n", + "#{@tab}Mock.#{function[:name]}_IgnoreBool = (unsigned char)1;\n", + "}\n\n" ] else - lines << "void #{function[:name]}_IgnoreAndReturn(#{function[:rettype]} toReturn)\n" - lines << "{\n" - lines << "#{@tab}Mock.#{function[:name]}_IgnoreBool = (unsigned char)1;\n" - lines << @utils.code_insert_item_into_expect_array(function[:rettype], "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" - lines << "}\n\n" + [ "void #{function[:name]}_IgnoreAndReturn(#{function[:rettype]} toReturn)\n", + "{\n", + "#{@tab}Mock.#{function[:name]}_IgnoreBool = (unsigned char)1;\n", + @utils.code_insert_item_into_expect_array(function[:rettype], "Mock.#{function[:name]}_Return_Head", "toReturn"), + "#{@tab}Mock.#{function[:name]}_Return = Mock.#{function[:name]}_Return_Head;\n", + "#{@tab}Mock.#{function[:name]}_Return += Mock.#{function[:name]}_CallCount;\n", + "}\n\n" ] end - return lines end end diff --git a/lib/cmock_generator_utils.rb b/lib/cmock_generator_utils.rb index aff3ed7..9aeadcf 100644 --- a/lib/cmock_generator_utils.rb +++ b/lib/cmock_generator_utils.rb @@ -1,12 +1,13 @@ class CMockGeneratorUtils - attr_accessor :config, :tab, :helpers + attr_accessor :config, :tab, :helpers, :ordered def initialize(config, helpers={}) @config = config @tab = @config.tab @ptr_handling = @config.when_ptr_star + @ordered = @config.enforce_strict_ordering @helpers = helpers end @@ -48,37 +49,33 @@ class CMockGeneratorUtils lines << "#{@tab}}\n" end - def code_handle_return_value(function, indent) - lines = ["\n"] - lines << "#{indent}if (Mock.#{function[:name]}_Return != Mock.#{function[:name]}_Return_Tail)\n" - lines << "#{indent}{\n" - lines << "#{indent}#{@tab}#{function[:rettype]} toReturn = *Mock.#{function[:name]}_Return;\n" - lines << "#{indent}#{@tab}Mock.#{function[:name]}_Return++;\n" - lines << "#{indent}#{@tab}return toReturn;\n" - lines << "#{indent}}\n" - lines << "#{indent}else\n" - lines << "#{indent}{\n" - lines << "#{indent}#{@tab}return *Mock.#{function[:name]}_Return_Head;\n" - lines << "#{indent}}\n" - end - def code_add_an_arg_expectation(function, arg_type, expected) lines = code_insert_item_into_expect_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 code_verify_an_arg_expectation(function, arg_type, actual) - lines = ["\n"] - lines << "#{@tab}if (Mock.#{function[:name]}_Expected_#{actual} != Mock.#{function[:name]}_Expected_#{actual}_Tail)\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" - lines << expect_helper(arg_type, '*p_expected', actual, "\"Function '#{function[:name]}' called with unexpected value for parameter '#{actual}'.\"","#{@tab}#{@tab}") - lines << "#{@tab}}\n" + def code_add_base_expectation(func_name) + lines = ["#{@tab}Mock.#{func_name}_CallsExpected++;\n"] + if (@ordered) + lines << [ "#{@tab}++GlobalExpectCount;\n", + code_insert_item_into_expect_array("int", "Mock.#{func_name}_CallOrder_Head", "GlobalExpectCount"), + "#{@tab}Mock.#{func_name}_CallOrder = Mock.#{func_name}_CallOrder_Head;\n", + "#{@tab}Mock.#{func_name}_CallOrder += Mock.#{func_name}_CallOrder;\n" ] + end lines.flatten end + def code_verify_an_arg_expectation(function, arg_type, actual) + [ "\n", + "#{@tab}if (Mock.#{function[:name]}_Expected_#{actual} != Mock.#{function[:name]}_Expected_#{actual}_Tail)\n", + "#{@tab}{\n", + "#{@tab}#{@tab}#{arg_type}* p_expected = Mock.#{function[:name]}_Expected_#{actual};\n", + "#{@tab}#{@tab}Mock.#{function[:name]}_Expected_#{actual}++;\n", + expect_helper(arg_type, '*p_expected', actual, "\"Function '#{function[:name]}' called with unexpected value for parameter '#{actual}'.\"","#{@tab}#{@tab}"), + "#{@tab}}\n" ].flatten + end + def expect_helper(c_type, expected, actual, msg, indent) if ((c_type.strip[-1] == 42) and (@ptr_handling == :compare_ptr)) unity_func = "TEST_ASSERT_EQUAL_INT_MESSAGE" @@ -99,4 +96,18 @@ class CMockGeneratorUtils return "#{indent}#{unity_func}(#{expected}, #{actual}#{unity_msg});\n" end end + + def code_handle_return_value(function, indent) + [ "\n", + "#{indent}if (Mock.#{function[:name]}_Return != Mock.#{function[:name]}_Return_Tail)\n", + "#{indent}{\n", + "#{indent}#{@tab}#{function[:rettype]} toReturn = *Mock.#{function[:name]}_Return;\n", + "#{indent}#{@tab}Mock.#{function[:name]}_Return++;\n", + "#{indent}#{@tab}return toReturn;\n", + "#{indent}}\n", + "#{indent}else\n", + "#{indent}{\n", + "#{indent}#{@tab}return *Mock.#{function[:name]}_Return_Head;\n", + "#{indent}}\n" ] + end end \ No newline at end of file diff --git a/lib/cmock_unityhelper_parser.rb b/lib/cmock_unityhelper_parser.rb index 2ba6113..4828c04 100644 --- a/lib/cmock_unityhelper_parser.rb +++ b/lib/cmock_unityhelper_parser.rb @@ -10,7 +10,7 @@ class CMockUnityHelperParser def get_helper(ctype) lookup = ctype.gsub(/const\s+/,'').strip.gsub(/\s+/,'_') 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 + raise("Don't know how to test #{ctype} and memory tests are disabled!") unless @config.memcmp_if_unknown return 'TEST_ASSERT_EQUAL_MEMORY_MESSAGE' end diff --git a/test/unit/cmock_config_test.yml b/test/unit/cmock_config_test.yml index 183666c..6990ea9 100644 --- a/test/unit/cmock_config_test.yml +++ b/test/unit/cmock_config_test.yml @@ -1,4 +1,4 @@ -cmock: +:cmock: :plugins: - 'soda' - 'pizza' diff --git a/test/unit/cmock_generator_main_test.rb b/test/unit/cmock_generator_main_test.rb index 581225f..34705fa 100644 --- a/test/unit/cmock_generator_main_test.rb +++ b/test/unit/cmock_generator_main_test.rb @@ -166,7 +166,10 @@ class CMockGeneratorTest < Test::Unit::TestCase should "create extern declarations for source file if no extra externs requested" do externs = [] output = [] - expected = [ "extern jmp_buf AbortFrame;\n","\n" ] + expected = [ "extern jmp_buf AbortFrame;\n", + "extern int GlobalExpectOrder;\n", + "extern int GlobalVerifyOrder;\n", + "\n" ] @cmock_generator.create_extern_declarations(output, externs) @@ -176,7 +179,12 @@ class CMockGeneratorTest < Test::Unit::TestCase should "create extern declarations for source file if extra externs requested" do externs = ["extern int whatever", "extern short somethingelse"] output = [] - expected = [ "int whatever;\n", "short somethingelse;\n", "extern jmp_buf AbortFrame;\n","\n"] + expected = [ "int whatever;\n", + "short somethingelse;\n", + "extern jmp_buf AbortFrame;\n", + "extern int GlobalExpectOrder;\n", + "extern int GlobalVerifyOrder;\n", + "\n"] @cmock_generator.create_extern_declarations(output, externs) diff --git a/test/unit/cmock_generator_plugin_cexception_test.rb b/test/unit/cmock_generator_plugin_cexception_test.rb index 42ee0a1..5065323 100644 --- a/test/unit/cmock_generator_plugin_cexception_test.rb +++ b/test/unit/cmock_generator_plugin_cexception_test.rb @@ -92,16 +92,17 @@ class CMockGeneratorPluginCExceptionTest < Test::Unit::TestCase assert_equal(expected, returned) end - should "add a mock interfaces for functions without arguments" do + should "add mock interfaces for functions without arguments" do function = {:name => "Pear", :args_string => "void", :args => [], :rettype => "void"} @config.expect.cexception_call_count_type.returns("uint32") @config.expect.cexception_throw_type.returns("EXCEPTION_TYPE") + @utils.expect.code_add_base_expectation("Pear").returns("mock_retval_0") @utils.expect.code_insert_item_into_expect_array("uint32", "Mock.Pear_ThrowOnCallCount_Head", "Mock.Pear_CallsExpected").returns("mock_return_1") @utils.expect.code_insert_item_into_expect_array("EXCEPTION_TYPE", "Mock.Pear_ThrowValue_Head", "toThrow").returns("mock_return_2") expected = ["void Pear_ExpectAndThrow(EXCEPTION_TYPE toThrow)\n", "{\n", - " Mock.Pear_CallsExpected++;\n", + "mock_retval_0", "mock_return_1", " Mock.Pear_ThrowOnCallCount = Mock.Pear_ThrowOnCallCount_Head;\n", " Mock.Pear_ThrowOnCallCount += Mock.Pear_CallCount;\n", @@ -118,13 +119,14 @@ class CMockGeneratorPluginCExceptionTest < Test::Unit::TestCase function = {:name => "Pear", :args_string => "int blah", :args => [{ :type => "int", :name => "blah" }], :rettype => "void"} @config.expect.cexception_call_count_type.returns("uint32") @config.expect.cexception_throw_type.returns("EXCEPTION_TYPE") + @utils.expect.code_add_base_expectation("Pear").returns("mock_retval_0") @utils.expect.code_insert_item_into_expect_array("uint32", "Mock.Pear_ThrowOnCallCount_Head", "Mock.Pear_CallsExpected").returns("mock_return_1") @utils.expect.code_insert_item_into_expect_array("EXCEPTION_TYPE", "Mock.Pear_ThrowValue_Head", "toThrow").returns("mock_return_2") @utils.expect.create_call_list(function).returns("mock_return_3") expected = ["void Pear_ExpectAndThrow(int blah, EXCEPTION_TYPE toThrow)\n", "{\n", - " Mock.Pear_CallsExpected++;\n", + "mock_retval_0", "mock_return_1", " Mock.Pear_ThrowOnCallCount = Mock.Pear_ThrowOnCallCount_Head;\n", " Mock.Pear_ThrowOnCallCount += Mock.Pear_CallCount;\n", diff --git a/test/unit/cmock_generator_plugin_expect_test.rb b/test/unit/cmock_generator_plugin_expect_test.rb index 067b6d6..2477d50 100644 --- a/test/unit/cmock_generator_plugin_expect_test.rb +++ b/test/unit/cmock_generator_plugin_expect_test.rb @@ -6,6 +6,7 @@ class CMockGeneratorPluginExpectTest < Test::Unit::TestCase create_mocks :config, :utils @config.expect.tab.returns(" ") @config.expect.when_ptr_star.returns(:compare_data) + @config.expect.enforce_strict_ordering.returns(false) @config.stubs!(:respond_to?).returns(true) @utils.expect.helpers.returns({}) @cmock_generator_plugin_expect = CMockGeneratorPluginExpect.new(@config, @utils) @@ -145,11 +146,33 @@ class CMockGeneratorPluginExpectTest < Test::Unit::TestCase assert_equal(expected, returned) end + should "add mock function implementation using ordering if needed" do + @utils.expect.expect_helper('int','*p_expected','GlobalVerifyOrder',"\"Function 'Apple' Called Out Of Order.\"", ' ').returns(" mocked_retval") + function = {:name => "Apple", :args => [], :rettype => "void"} + expected = [" Mock.Apple_CallCount++;\n", + " if (Mock.Apple_CallCount > Mock.Apple_CallsExpected)\n", + " {\n", + " TEST_FAIL(\"Apple Called More Times Than Expected\");\n", + " }\n", + " {\n", + " int* p_expected = Mock.Apple_CallOrder;\n", + " ++GlobalVerifyOrder;\n", + " if (Mock.Apple_CallOrder != Mock.Apple_CallOrder_Tail)\n", + " Mock.Apple_CallOrder++;\n", + " mocked_retval", + " }\n" + ] + @cmock_generator_plugin_expect.ordered = true + returned = @cmock_generator_plugin_expect.mock_implementation(function) + assert_equal(expected, returned) + end + should "add mock interfaces for functions of style 'void func(void)'" do + @utils.expect.code_add_base_expectation("Pear").returns("mock_retval_0") function = {:name => "Pear", :args => [], :args_string => "void", :rettype => "void"} expected = ["void Pear_Expect(void)\n", "{\n", - " Mock.Pear_CallsExpected++;\n", + "mock_retval_0", "}\n\n" ] returned = @cmock_generator_plugin_expect.mock_interfaces(function) @@ -158,11 +181,12 @@ class CMockGeneratorPluginExpectTest < Test::Unit::TestCase should "add mock interfaces for functions of style 'unsigned short func(void)'" do function = {:name => "Orange", :args => [], :args_string => "void", :rettype => "unsigned short"} + @utils.expect.code_add_base_expectation("Orange").returns("mock_retval_0") @utils.expect.code_insert_item_into_expect_array(function[:rettype], "Mock.Orange_Return_Head","toReturn").returns("mock_retval_1") expected = ["void Orange_ExpectAndReturn(unsigned short toReturn)\n", "{\n", - " Mock.Orange_CallsExpected++;\n", + "mock_retval_0", "mock_retval_1", " Mock.Orange_Return = Mock.Orange_Return_Head;\n", " Mock.Orange_Return += Mock.Orange_CallCount;\n", @@ -175,6 +199,7 @@ class CMockGeneratorPluginExpectTest < Test::Unit::TestCase should "add mock interfaces for functions of style 'int func(char* pescado)'" do function = {:name => "Lemon", :args => [{ :type => "char*", :name => "pescado"}], :args_string => "char* pescado", :rettype => "int"} @utils.expect.code_add_an_arg_expectation(function, "char*", "pescado").returns("mock_retval_2") + @utils.expect.code_add_base_expectation("Lemon").returns("mock_retval_0") @utils.expect.create_call_list(function).returns("mock_retval_3") @utils.expect.code_insert_item_into_expect_array(function[:rettype], "Mock.Lemon_Return_Head","toReturn").returns("mock_retval_1") @@ -184,7 +209,7 @@ class CMockGeneratorPluginExpectTest < Test::Unit::TestCase "}\n\n", "void Lemon_ExpectAndReturn(char* pescado, int toReturn)\n", "{\n", - " Mock.Lemon_CallsExpected++;\n", + "mock_retval_0", " ExpectParameters_Lemon(mock_retval_3);\n", "mock_retval_1", " Mock.Lemon_Return = Mock.Lemon_Return_Head;\n", @@ -195,6 +220,19 @@ class CMockGeneratorPluginExpectTest < Test::Unit::TestCase assert_equal(expected, returned) end + should "add mock interfaces for functions when using ordering" do + function = {:name => "Pear", :args => [], :args_string => "void", :rettype => "void"} + expected = ["void Pear_Expect(void)\n", + "{\n", + "mock_retval_0", + "}\n\n" + ] + @cmock_generator_plugin_expect.ordered = true + @utils.expect.code_add_base_expectation("Pear").returns("mock_retval_0") + returned = @cmock_generator_plugin_expect.mock_interfaces(function) + assert_equal(expected, returned) + end + should "add mock verify lines" do function = {:name => "Banana" } diff --git a/test/unit/cmock_generator_utils_test.rb b/test/unit/cmock_generator_utils_test.rb index dc69572..2267aff 100644 --- a/test/unit/cmock_generator_utils_test.rb +++ b/test/unit/cmock_generator_utils_test.rb @@ -6,6 +6,7 @@ class CMockGeneratorUtilsTest < Test::Unit::TestCase create_mocks :config, :unity_helper @config.expect.tab.returns(" ") @config.expect.when_ptr_star.returns(:compare_data) + @config.expect.enforce_strict_ordering.returns(false) @cmock_generator_utils = CMockGeneratorUtils.new(@config) end @@ -22,6 +23,7 @@ class CMockGeneratorUtilsTest < Test::Unit::TestCase create_mocks :config @config.expect.tab.returns(" ") @config.expect.when_ptr_star.returns(:compare_ptr) + @config.expect.enforce_strict_ordering.returns(false) @cmock_generator_utils = CMockGeneratorUtils.new(@config, {:A, :B}) assert_equal(@config, @cmock_generator_utils.config) assert_equal(" ", @cmock_generator_utils.tab) @@ -133,6 +135,44 @@ class CMockGeneratorUtilsTest < Test::Unit::TestCase assert_equal(expected, returned) end + should "add base expectations, with nothing else when strict ordering not turned on" do + expected = [" Mock.Nectarine_CallsExpected++;\n"] + returned = @cmock_generator_utils.code_add_base_expectation("Nectarine") + + assert_equal(expected, returned) end + + should "add base expectations, with stuff for strict ordering turned on" do + expected = [" Mock.Nectarine_CallsExpected++;\n", + " ++GlobalExpectCount;\n", + "\n", + " {\n", + " int sz = 0;\n", + " int *pointer = Mock.Nectarine_CallOrder_Head;\n", + " while (pointer && pointer != Mock.Nectarine_CallOrder_Tail) { sz++; pointer++; }\n", + " if (sz == 0)\n", + " {\n", + " Mock.Nectarine_CallOrder_Head = (int*)malloc(2*sizeof(int));\n", + " if (!Mock.Nectarine_CallOrder_Head)\n", + " Mock.allocFailure++;\n", + " }\n", + " else\n", + " {\n", + " int *ptmp = (int*)realloc(Mock.Nectarine_CallOrder_Head, sizeof(int) * (sz+1));\n", + " if (!ptmp)\n", + " Mock.allocFailure++;\n", + " else\n", + " Mock.Nectarine_CallOrder_Head = ptmp;\n", + " }\n", + " memcpy(&Mock.Nectarine_CallOrder_Head[sz], &GlobalExpectCount, sizeof(int));\n", + " Mock.Nectarine_CallOrder_Tail = &Mock.Nectarine_CallOrder_Head[sz+1];\n", + " }\n", + " Mock.Nectarine_CallOrder = Mock.Nectarine_CallOrder_Head;\n", + " Mock.Nectarine_CallOrder += Mock.Nectarine_CallOrder;\n" ] + @cmock_generator_utils.ordered = true + returned = @cmock_generator_utils.code_add_base_expectation("Nectarine") + assert_equal(expected, returned) + end + should "make handle expected when no helpers are available" do function = { :name => "CanOpener", :rettype => "uint64"} var_type = "uint16" diff --git a/test/unit/cmock_plugin_manager_test.rb b/test/unit/cmock_plugin_manager_test.rb index 26742dd..b4d8c0e 100644 --- a/test/unit/cmock_plugin_manager_test.rb +++ b/test/unit/cmock_plugin_manager_test.rb @@ -6,6 +6,7 @@ class CMockPluginManagerTest < Test::Unit::TestCase create_mocks :config, :utils, :pluginA, :pluginB @config.stubs!(:respond_to?).returns(true) @config.stubs!(:when_ptr_star).returns(:compare_data) + @config.stubs!(:enforce_strict_ordering).returns(false) end def teardown diff --git a/test/unit/cmock_unityhelper_parser_test.rb b/test/unit/cmock_unityhelper_parser_test.rb index 5af8aab..d6d8783 100644 --- a/test/unit/cmock_unityhelper_parser_test.rb +++ b/test/unit/cmock_unityhelper_parser_test.rb @@ -171,7 +171,7 @@ class CMockUnityHelperParserTest < Test::Unit::TestCase } ["UINT16","UINT8*","SPINACH_T","SALAD","PINEAPPLE"].each do |ctype| - @config.expect.memcpy_if_unknown.returns(true) + @config.expect.memcmp_if_unknown.returns(true) assert_equal("TEST_ASSERT_EQUAL_MEMORY_MESSAGE", @parser.get_helper(ctype)) end end @@ -180,7 +180,7 @@ class CMockUnityHelperParserTest < Test::Unit::TestCase @config.expects.standard_treat_as_map.returns({}) @config.expects.treat_as.returns({}) @config.expect.load_unity_helper.returns("") - @config.expect.memcpy_if_unknown.returns(false) + @config.expect.memcmp_if_unknown.returns(false) @parser = CMockUnityHelperParser.new(@config) @parser.c_types = { 'UINT8' => "TEST_ASSERT_EQUAL_UINT8_MESSAGE",