From e79a5f13d1554f0155497ebbf3af009a5292e780 Mon Sep 17 00:00:00 2001 From: mvandervoord Date: Mon, 8 Mar 2010 13:32:31 +0000 Subject: [PATCH] - added cmock.c file for handling generic parts - switched to better memory management technique git-svn-id: http://cmock.svn.sourceforge.net/svnroot/cmock/trunk@155 bf332499-1b4d-0410-844d-d2d48d5cc64c --- gcc.yml | 3 +- iar_v4.yml | 7 +- iar_v5.yml | 7 +- lib/cmock_config.rb | 1 + lib/cmock_generator.rb | 57 +- lib/cmock_generator_plugin_array.rb | 67 +- lib/cmock_generator_plugin_callback.rb | 72 +-- lib/cmock_generator_plugin_cexception.rb | 81 +-- lib/cmock_generator_plugin_expect.rb | 151 +---- lib/cmock_generator_plugin_ignore.rb | 79 +-- lib/cmock_generator_utils.rb | 208 +++---- lib/cmock_header_parser.rb | 32 +- lib/cmock_unityhelper_parser.rb | 6 +- rakefile.rb | 42 +- rakefile_helper.rb | 38 +- src/cmock.c | 152 +++++ src/cmock.h | 14 + test/c/TestCMockC.c | 272 +++++++++ test/c/TestCMockC.yml | 12 + test/c/TestCMockCDynamic.c | 181 ++++++ test/c/TestCMockCDynamic.yml | 12 + test/c/TestCMockCDynamic_Runner.c | 41 ++ test/c/TestCMockC_Runner.c | 43 ++ test/system/systest_generator.rb | 3 +- test/system/test_compilation/const.h | 10 + test/system/test_compilation/parsing.h | 11 - .../test_interactions/all_plugins_coexist.yml | 18 +- .../array_and_pointer_handling.yml | 4 +- .../enforce_strict_ordering.yml | 6 +- .../test_interactions/expect_and_throw.yml | 2 +- .../fancy_pointer_handling.yml | 4 +- .../nonstandard_parsed_stuff_1.yml | 91 +++ .../stubs_with_callbacks.yml | 12 + test/test_helper.rb | 20 + test/unit/cmock_generator_main_test.rb | 148 +++-- .../unit/cmock_generator_plugin_array_test.rb | 68 +-- .../cmock_generator_plugin_callback_test.rb | 77 +-- .../cmock_generator_plugin_cexception_test.rb | 103 +--- .../cmock_generator_plugin_expect_test.rb | 296 +++------ .../cmock_generator_plugin_ignore_test.rb | 58 +- test/unit/cmock_generator_utils_test.rb | 572 ++++++++---------- test/unit/cmock_header_parser_test.rb | 188 ++++-- test/unit/cmock_unityhelper_parser_test.rb | 36 +- 43 files changed, 1797 insertions(+), 1508 deletions(-) create mode 100644 src/cmock.c create mode 100644 src/cmock.h create mode 100644 test/c/TestCMockC.c create mode 100644 test/c/TestCMockC.yml create mode 100644 test/c/TestCMockCDynamic.c create mode 100644 test/c/TestCMockCDynamic.yml create mode 100644 test/c/TestCMockCDynamic_Runner.c create mode 100644 test/c/TestCMockC_Runner.c create mode 100644 test/system/test_compilation/const.h create mode 100644 test/system/test_interactions/nonstandard_parsed_stuff_1.yml diff --git a/gcc.yml b/gcc.yml index 7c0d816..567ee5b 100644 --- a/gcc.yml +++ b/gcc.yml @@ -16,6 +16,7 @@ compiler: - *systest_generated_path - *unit_tests_path - *systest_mocks_path + - 'src/' - 'vendor/unity/src/' - 'vendor/c_exception/lib/' - 'test/system/test_compilation/' @@ -42,4 +43,4 @@ linker: extension: '.exe' destination: *systest_build_path - +unsupported: [] diff --git a/iar_v4.yml b/iar_v4.yml index 3e60dbb..41114d6 100644 --- a/iar_v4.yml +++ b/iar_v4.yml @@ -38,6 +38,7 @@ compiler: - *systest_generated_path - *unit_tests_path - *systest_mocks_path + - 'src/' - 'vendor/unity/src/' - 'vendor/c_exception/lib/' - 'test/system/test_compilation/' @@ -96,4 +97,8 @@ simulator: - -p - [*tools_root, 'arm\config\ioat91sam7X256.ddf'] - -d - - sim \ No newline at end of file + - sim + +unsupported: + - nonstandard_parsed_stuff_1 + - const \ No newline at end of file diff --git a/iar_v5.yml b/iar_v5.yml index a9e7eaf..ebb85f1 100644 --- a/iar_v5.yml +++ b/iar_v5.yml @@ -36,6 +36,7 @@ compiler: - *systest_generated_path - *unit_tests_path - *systest_mocks_path + - 'src/' - 'vendor/unity/src/' - 'vendor/c_exception/lib/' - 'iar\iar_v5\incIAR\' @@ -81,4 +82,8 @@ simulator: - -p - [*tools_root, 'arm\config\debugger\Atmel\ioat91sam7X256.ddf'] - -d - - sim \ No newline at end of file + - sim + +unsupported: + - nonstandard_parsed_stuff_1 + - const \ No newline at end of file diff --git a/lib/cmock_config.rb b/lib/cmock_config.rb index 471d7f1..9517a89 100644 --- a/lib/cmock_config.rb +++ b/lib/cmock_config.rb @@ -36,6 +36,7 @@ class CMockConfig end @options = options + @options[:treat_as].merge!(standard_treat_as_map) @options.each_key { |key| eval("def #{key}() return @options[:#{key}] end") } end diff --git a/lib/cmock_generator.rb b/lib/cmock_generator.rb index 4ae4bda..e2aafab 100644 --- a/lib/cmock_generator.rb +++ b/lib/cmock_generator.rb @@ -2,9 +2,9 @@ $here = File.dirname __FILE__ class CMockGenerator - attr_accessor :config, :file_writer, :module_name, :mock_name, :utils, :plugins + attr_accessor :config, :file_writer, :module_name, :mock_name, :utils, :plugins, :ordered - def initialize(config, file_writer, utils, plugins=[]) + def initialize(config, file_writer, utils, plugins) @file_writer = file_writer @utils = utils @plugins = plugins @@ -44,7 +44,7 @@ class CMockGenerator create_mock_destroy_function(file, parsed_stuff[:functions]) parsed_stuff[:functions].each do |function| create_mock_implementation(file, function) - file << @plugins.run(:mock_interfaces, function) + create_mock_interfaces(file, function) end end end @@ -81,6 +81,7 @@ class CMockGenerator file << "#include \n" file << "#include \n" file << "#include \"unity.h\"\n" + file << "#include \"cmock.h\"\n" file << @plugins.run(:include_files) includes = @config.includes includes.each {|inc| file << "#include \"#{inc}\"\n"} if (!includes.nil?) @@ -88,13 +89,20 @@ class CMockGenerator end def create_instance_structure(file, functions) - file << "static struct #{@mock_name}Instance\n" - file << "{\n" + functions.each do |function| + file << "typedef struct _CMOCK_#{function[:name]}_CALL_INSTANCE\n{\n" + stuff = @plugins.run(:instance_typedefs, function) + file << ((stuff.empty?) ? " char PlaceHolder;\n" : stuff) + file << "\n} CMOCK_#{function[:name]}_CALL_INSTANCE;\n\n" + end + file << "static struct #{@mock_name}Instance\n{\n" if (functions.size == 0) file << " unsigned char placeHolder;\n" end - file << " unsigned char allocFailure;\n" - file << functions.collect{|function| @plugins.run(:instance_structure, function)}.join + functions.each do |function| + file << @plugins.run(:instance_structure, function) + file << " CMOCK_#{function[:name]}_CALL_INSTANCE* #{function[:name]}_CallInstance;\n" + end file << "} Mock;\n\n" end @@ -110,14 +118,8 @@ class CMockGenerator def create_mock_verify_function(file, functions) file << "void #{@mock_name}_Verify(void)\n{\n" - file << " TEST_ASSERT_EQUAL_MESSAGE(0, Mock.allocFailure, \"Unable to allocate memory for mock\");\n" file << functions.collect {|function| @plugins.run(:mock_verify, function)}.join - if (@ordered) - file << " if (GlobalOrderError)\n" - file << " {\n" - file << " TEST_FAIL(GlobalOrderError);\n" - file << " }\n" - end + file << " TEST_ASSERT_NULL_MESSAGE(GlobalOrderError, GlobalOrderError);\n" if (@ordered) file << "}\n\n" end @@ -129,8 +131,9 @@ class CMockGenerator def create_mock_destroy_function(file, functions) file << "void #{@mock_name}_Destroy(void)\n{\n" - file << functions.collect {|function| @plugins.run(:mock_destroy, function) }.join + file << " CMock_Guts_MemFreeAll();\n" file << " memset(&Mock, 0, sizeof(Mock));\n" + file << functions.collect {|function| @plugins.run(:mock_destroy, function)}.join if (@ordered) file << " GlobalExpectCount = 0;\n" file << " GlobalVerifyOrder = 0;\n" @@ -144,13 +147,12 @@ class CMockGenerator end def create_mock_implementation(file, function) - # create return value combo + # prepare return value and arguments if (function[:modifier].empty?) - function_mod_and_rettype = function[:return_type] + function_mod_and_rettype = function[:return][:type] else - function_mod_and_rettype = function[:modifier] + ' ' + function[:return_type] + function_mod_and_rettype = function[:modifier] + ' ' + function[:return][:type] end - args_string = function[:args_string] args_string += (", " + function[:var_arg]) unless (function[:var_arg].nil?) @@ -158,14 +160,17 @@ class CMockGenerator file << "#{function[:attributes]} " if (!function[:attributes].nil? && function[:attributes].length > 0) file << "#{function_mod_and_rettype} #{function[:name]}(#{args_string})\n" file << "{\n" + file << " CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance = Mock.#{function[:name]}_CallInstance;\n" + file << " Mock.#{function[:name]}_CallInstance = (CMOCK_#{function[:name]}_CALL_INSTANCE*)CMock_Guts_MemNext(Mock.#{function[:name]}_CallInstance);\n" + file << @plugins.run(:mock_implementation_precheck, function) + file << " TEST_ASSERT_NOT_NULL_MESSAGE(cmock_call_instance, \"Function '#{function[:name]}' called more times than expected\");\n" file << @plugins.run(:mock_implementation, function) - - # Return expected value, if necessary - if (function[:return_type] != "void") - file << @utils.code_handle_return_value(function) - end - - # Close out the function + file << " return cmock_call_instance->ReturnVal;\n" unless (function[:return][:void?]) file << "}\n\n" end + + def create_mock_interfaces(file, function) + file << @utils.code_add_argument_loader(function) + file << @plugins.run(:mock_interfaces, function) + end end diff --git a/lib/cmock_generator_plugin_array.rb b/lib/cmock_generator_plugin_array.rb index 014770f..5af758b 100644 --- a/lib/cmock_generator_plugin_array.rb +++ b/lib/cmock_generator_plugin_array.rb @@ -11,91 +11,46 @@ class CMockGeneratorPluginArray @priority = 8 end - def instance_structure(function) - lines = "" - function[:args].each do |arg| - lines << INSTANCE_STRUCTURE_DEPTH_SNIPPET % "#{function[:name]}_Expected_#{arg[:name]}" if (arg[:ptr?]) + def instance_typedefs(function) + function[:args].inject("") do |all, arg| + (arg[:ptr?]) ? all + " int Expected_#{arg[:name]}_Depth;\n" : all end - lines end def mock_function_declarations(function) return nil unless function[:contains_ptr?] if (function[:args_string] == "void") - if (function[:return_type] == 'void') + if (function[:return][:void?]) return "void #{function[:name]}_ExpectWithArray(void);\n" else - return "void #{function[:name]}_ExpectWithArrayAndReturn(#{function[:return_string]});\n" + return "void #{function[:name]}_ExpectWithArrayAndReturn(#{function[:return][:str]});\n" end else args_string = function[:args].map{|m| m[:ptr?] ? "#{m[:type]} #{m[:name]}, int #{m[:name]}_Depth" : "#{m[:type]} #{m[:name]}"}.join(', ') - if (function[:return_type] == 'void') + if (function[:return][:void?]) return "void #{function[:name]}_ExpectWithArray(#{args_string});\n" else - return "void #{function[:name]}_ExpectWithArrayAndReturn(#{args_string}, #{function[:return_string]});\n" + return "void #{function[:name]}_ExpectWithArrayAndReturn(#{args_string}, #{function[:return][:str]});\n" end end end def mock_interfaces(function) return nil unless function[:contains_ptr?] - lines = [] func_name = function[:name] args_string = function[:args].map{|m| m[:ptr?] ? "#{m[:type]} #{m[:name]}, int #{m[:name]}_Depth" : "#{m[:type]} #{m[:name]}"}.join(', ') call_string = function[:args].map{|m| m[:ptr?] ? "#{m[:name]}, #{m[:name]}_Depth" : m[:name]}.join(', ') - - # Parameter Helper Function - if (function[:args_string] != "void") - lines << "void ExpectParametersWithArray_#{func_name}(#{args_string})\n{\n" - function[:args].each do |arg| - lines << @utils.code_add_an_arg_expectation(function, arg, arg[:ptr?] ? "#{arg[:name]}_Depth" : "1") - end - lines << "}\n\n" - end - - #Main Mock Interface - if (function[:return_type] == "void") + if (function[:return][:void?]) lines << "void #{func_name}_ExpectWithArray(#{args_string})\n" else - lines << "void #{func_name}_ExpectWithArrayAndReturn(#{args_string}, #{function[:return_string]})\n" + lines << "void #{func_name}_ExpectWithArrayAndReturn(#{args_string}, #{function[:return][:str]})\n" end lines << "{\n" lines << @utils.code_add_base_expectation(func_name) - lines << " ExpectParametersWithArray_#{func_name}(#{call_string});\n" - - if (function[:return_type] != "void") - lines << @utils.code_insert_item_into_expect_array(function[:return_type], "Mock.#{func_name}_Return", 'cmock_to_return') - lines << " Mock.#{func_name}_Return = Mock.#{func_name}_Return_Head;\n" - lines << " Mock.#{func_name}_Return += Mock.#{func_name}_CallCount;\n" - end + lines << " CMockExpectParameters_#{func_name}(cmock_call_instance, #{call_string});\n" + lines << " cmock_call_instance->ReturnVal = cmock_to_return;\n" unless (function[:return][:void?]) lines << "}\n\n" end - def mock_destroy(function) - lines = [] - function[:args].each do |arg| - lines << DESTROY_DEPTH_SNIPPET % "#{function[:name]}_Expected_#{arg[:name]}" if arg[:ptr?] - end - lines.flatten - end - - private ##################### - - INSTANCE_STRUCTURE_DEPTH_SNIPPET = %q[ - int* %1$s_Depth; - int* %1$s_Depth_Head; - int* %1$s_Depth_Tail; -] - - DESTROY_DEPTH_SNIPPET = %q[ - if (Mock.%1$s_Depth_Head) - { - free(Mock.%1$s_Depth_Head); - } - Mock.%1$s_Depth=NULL; - Mock.%1$s_Depth_Head=NULL; - Mock.%1$s_Depth_Tail=NULL; -] - end diff --git a/lib/cmock_generator_plugin_callback.rb b/lib/cmock_generator_plugin_callback.rb index cd1ab94..bd03280 100644 --- a/lib/cmock_generator_plugin_callback.rb +++ b/lib/cmock_generator_plugin_callback.rb @@ -10,70 +10,42 @@ class CMockGeneratorPluginCallback end def instance_structure(function) - INSTANCE_STRUCTURE_SNIPPET % [function[:name]] + func_name = function[:name] + " CMOCK_#{func_name}_CALLBACK #{func_name}_CallbackFunctionPointer;\n" + + " int #{func_name}_CallbackCalls;\n" end def mock_function_declarations(function) - if (function[:args_string] == "void") - MOCK_DECLARATION_SNIPPET % [function[:name], function[:return_type], ''] - else - MOCK_DECLARATION_SNIPPET % [function[:name], function[:return_type], function[:args_string] + ', '] - end + func_name = function[:name] + "typedef #{function[:return][:type]} (* CMOCK_#{func_name}_CALLBACK)(#{(function[:args_string] == "void") ? '' : function[:args_string] + ', '}int cmock_num_calls);\n" + + "void #{func_name}_StubWithCallback(CMOCK_#{func_name}_CALLBACK Callback);\n" end - def mock_implementation(function) + def mock_implementation_precheck(function) + func_name = function[:name] call_string = function[:args].empty? ? '' : function[:args].map{|m| m[:name]}.join(', ') + ', ' - if (function[:return_type] == 'void') - return MOCK_IMPLEMENTATION_NORET_SNIPPET % [function[:name], call_string] + " if (Mock.#{func_name}_CallbackFunctionPointer != NULL)\n {\n" + + if (function[:return][:void?]) + " Mock.#{func_name}_CallbackFunctionPointer(#{call_string}Mock.#{func_name}_CallbackCalls++);\n return;\n }\n" else - return MOCK_IMPLEMENTATION_RETVAL_SNIPPET % [function[:name], call_string] + " return Mock.#{func_name}_CallbackFunctionPointer(#{call_string}Mock.#{func_name}_CallbackCalls++);\n }\n" end end def mock_interfaces(function) - MOCK_INTERFACE_SNIPPET % [function[:name]] + func_name = function[:name] + "void #{func_name}_StubWithCallback(CMOCK_#{func_name}_CALLBACK Callback)\n{\n" + + " Mock.#{func_name}_CallbackFunctionPointer = Callback;\n}\n\n" end def mock_destroy(function) - MOCK_DESTROY_SNIPPET % function[:name] + " Mock.#{function[:name]}_CallbackFunctionPointer = NULL;\n" + + " Mock.#{function[:name]}_CallbackCalls = 0;\n" + end + + def mock_verify(function) + func_name = function[:name] + " if (Mock.#{func_name}_CallbackFunctionPointer != NULL)\n Mock.#{func_name}_CallInstance = NULL;\n" end - private ############ - - INSTANCE_STRUCTURE_SNIPPET = %q[ CMOCK_%1$s_CALLBACK %1$s_CallbackFunctionPointer; -] - - MOCK_DECLARATION_SNIPPET = %q[ -typedef %2$s (* CMOCK_%1$s_CALLBACK)(%3$sint NumCalls); -void %1$s_StubWithCallback(CMOCK_%1$s_CALLBACK Callback); -] - - MOCK_IMPLEMENTATION_NORET_SNIPPET = %q[ - if (Mock.%1$s_CallbackFunctionPointer != NULL) - { - Mock.%1$s_CallsExpected++; - Mock.%1$s_CallbackFunctionPointer(%2$sMock.%1$s_CallCount++); - return; - } -] - - MOCK_IMPLEMENTATION_RETVAL_SNIPPET = %q[ - if (Mock.%1$s_CallbackFunctionPointer != NULL) - { - Mock.%1$s_CallsExpected++; - return Mock.%1$s_CallbackFunctionPointer(%2$sMock.%1$s_CallCount++); - } -] - - MOCK_INTERFACE_SNIPPET = %q[ -void %1$s_StubWithCallback(CMOCK_%1$s_CALLBACK Callback) -{ - Mock.%1$s_CallbackFunctionPointer = Callback; -} -] - - MOCK_DESTROY_SNIPPET = %q[ - Mock.%1$s_CallbackFunctionPointer = NULL; -] - end diff --git a/lib/cmock_generator_plugin_cexception.rb b/lib/cmock_generator_plugin_cexception.rb index 799f88f..f9c9160 100644 --- a/lib/cmock_generator_plugin_cexception.rb +++ b/lib/cmock_generator_plugin_cexception.rb @@ -12,93 +12,34 @@ class CMockGeneratorPluginCexception end def include_files - include = @config.cexception_include - include = "CException.h" if (include.nil?) - return "#include \"#{include}\"\n" + return "#include \"#{@config.cexception_include || 'CException.h'}\"\n" end - def instance_structure(function) - INSTANCE_STRUCTURE_SNIPPET % function[:name] + def instance_typedefs(function) + " CEXCEPTION_T ExceptionToThrow;\n" end - + def mock_function_declarations(function) if (function[:args_string] == "void") - return "void #{function[:name]}_ExpectAndThrow(CEXCEPTION_T toThrow);\n" + return "void #{function[:name]}_ExpectAndThrow(CEXCEPTION_T cmock_to_throw);\n" else - return "void #{function[:name]}_ExpectAndThrow(#{function[:args_string]}, CEXCEPTION_T toThrow);\n" + return "void #{function[:name]}_ExpectAndThrow(#{function[:args_string]}, CEXCEPTION_T cmock_to_throw);\n" end end def mock_implementation(function) - MOCK_IMPLEMENTATION_SNIPPET % function[:name] + " if (cmock_call_instance->ExceptionToThrow != CEXCEPTION_NONE)\n {\n" + + " Throw(cmock_call_instance->ExceptionToThrow);\n }\n" end def mock_interfaces(function) arg_insert = (function[:args_string] == "void") ? "" : "#{function[:args_string]}, " call_string = function[:args].map{|m| m[:name]}.join(', ') - [ "void #{function[:name]}_ExpectAndThrow(#{arg_insert}CEXCEPTION_T toThrow)\n{\n", + [ "void #{function[:name]}_ExpectAndThrow(#{arg_insert}CEXCEPTION_T cmock_to_throw)\n{\n", @utils.code_add_base_expectation(function[:name]), - @utils.code_insert_item_into_expect_array('int', "Mock.#{function[:name]}_ThrowOnCallCount", "Mock.#{function[:name]}_CallsExpected"), - @utils.code_insert_item_into_expect_array('CEXCEPTION_T', "Mock.#{function[:name]}_ThrowValue", "toThrow"), - (MOCK_INTERFACE_THROW_HANDLING_SNIPPET % function[:name]), - (function[:args_string] != "void") ? " CMockExpectParameters_#{function[:name]}(#{call_string});\n" : nil, + @utils.code_call_argument_loader(function), + " cmock_call_instance->ExceptionToThrow = cmock_to_throw;\n", "}\n\n" ].join end - def mock_destroy(function) - MOCK_DESTROY_SNIPPET % function[:name] - end - - private ############ - - INSTANCE_STRUCTURE_SNIPPET = %q[ - int *%1$s_ThrowOnCallCount; - int *%1$s_ThrowOnCallCount_Head; - int *%1$s_ThrowOnCallCount_Tail; - CEXCEPTION_T *%1$s_ThrowValue; - CEXCEPTION_T *%1$s_ThrowValue_Head; - CEXCEPTION_T *%1$s_ThrowValue_Tail; -] - - MOCK_IMPLEMENTATION_SNIPPET = %q[ - if ((Mock.%1$s_ThrowOnCallCount != Mock.%1$s_ThrowOnCallCount_Tail) && - (Mock.%1$s_ThrowValue != Mock.%1$s_ThrowValue_Tail)) - { - if (*Mock.%1$s_ThrowOnCallCount && - (Mock.%1$s_CallCount == *Mock.%1$s_ThrowOnCallCount)) - { - CEXCEPTION_T toThrow = *Mock.%1$s_ThrowValue; - Mock.%1$s_ThrowOnCallCount++; - Mock.%1$s_ThrowValue++; - Throw(toThrow); - } - } -] - - MOCK_DESTROY_SNIPPET = %q[ - if(Mock.%1$s_ThrowOnCallCount_Head) - { - free(Mock.%1$s_ThrowOnCallCount_Head); - } - Mock.%1$s_ThrowOnCallCount=NULL; - Mock.%1$s_ThrowOnCallCount_Head=NULL; - Mock.%1$s_ThrowOnCallCount_Tail=NULL; - if(Mock.%1$s_ThrowValue_Head) - { - free(Mock.%1$s_ThrowValue_Head); - } - Mock.%1$s_ThrowValue=NULL; - Mock.%1$s_ThrowValue_Head=NULL; - Mock.%1$s_ThrowValue_Tail=NULL; -] - - MOCK_INTERFACE_THROW_HANDLING_SNIPPET = %q[ - Mock.%1$s_ThrowValue = Mock.%1$s_ThrowValue_Head; - Mock.%1$s_ThrowOnCallCount = Mock.%1$s_ThrowOnCallCount_Head; - while ((*Mock.%1$s_ThrowOnCallCount <= Mock.%1$s_CallCount) && (Mock.%1$s_ThrowOnCallCount < Mock.%1$s_ThrowOnCallCount_Tail)) - { - Mock.%1$s_ThrowValue++; - Mock.%1$s_ThrowOnCallCount++; - } -] end diff --git a/lib/cmock_generator_plugin_expect.rb b/lib/cmock_generator_plugin_expect.rb index 300f1e6..447e5ea 100644 --- a/lib/cmock_generator_plugin_expect.rb +++ b/lib/cmock_generator_plugin_expect.rb @@ -13,44 +13,36 @@ class CMockGeneratorPluginExpect @priority = 5 end - def instance_structure(function) - lines = INSTANCE_STRUCTURE_CALL_SNIPPET % function[:name] - - if (function[:return_type] != "void") - lines << INSTANCE_STRUCTURE_ITEM_SNIPPET % "#{function[:return_type]} *#{function[:name]}_Return" - end - - if (@ordered) - lines << INSTANCE_STRUCTURE_ITEM_SNIPPET % "int *#{function[:name]}_CallOrder" - end - + def instance_typedefs(function) + lines = "" + lines << " #{function[:return][:type]} ReturnVal;\n" unless (function[:return][:void?]) + lines << " int CallOrder;\n" if (@ordered) function[:args].each do |arg| - lines << INSTANCE_STRUCTURE_ITEM_SNIPPET % "#{arg[:type]} *#{function[:name]}_Expected_#{arg[:name]}" + lines << " #{arg[:type]} Expected_#{arg[:name]};\n" end lines end def mock_function_declarations(function) - if (function[:args_string] == "void") - if (function[:return_type] == 'void') + if (function[:args].empty?) + if (function[:return][:void?]) return "void #{function[:name]}_Expect(void);\n" else - return "void #{function[:name]}_ExpectAndReturn(#{function[:return_string]});\n" + return "void #{function[:name]}_ExpectAndReturn(#{function[:return][:str]});\n" end else - if (function[:return_type] == 'void') + if (function[:return][:void?]) return "void #{function[:name]}_Expect(#{function[:args_string]});\n" else - return "void #{function[:name]}_ExpectAndReturn(#{function[:args_string]}, #{function[:return_string]});\n" + return "void #{function[:name]}_ExpectAndReturn(#{function[:args_string]}, #{function[:return][:str]});\n" end end end def mock_implementation(function) - lines = MOCK_IMPLEMENT_SNIPPET % function[:name] + lines = "" if (@ordered) - err_msg = "Out of order function calls. Function '#{function[:name]}'" #would eventually like to be " expected to be call %i but was call %i" - lines << MOCK_IMPLEMENT_ORDERED_SNIPPET % [function[:name], err_msg, (err_msg.size + 1).to_s] + lines << " TEST_ASSERT_MESSAGE((cmock_call_instance->CallOrder == ++GlobalVerifyOrder), \"Out of order function calls. Function '#{function[:name]}'\");\n" end function[:args].each do |arg| lines << @utils.code_verify_an_arg_expectation(function, arg) @@ -59,129 +51,26 @@ class CMockGeneratorPluginExpect end def mock_interfaces(function) - lines = [] + lines = "" func_name = function[:name] - - # Parameter Helper Function - if (function[:args_string] != "void") - lines << "void CMockExpectParameters_#{func_name}(#{function[:args_string]})\n{\n" - function[:args].each do |arg| - lines << @utils.code_add_an_arg_expectation(function, arg) - end - lines << "}\n\n" - end - - #Main Mock Interface - if (function[:return_type] == "void") - lines << "void #{func_name}_Expect(#{function[:args_string]})\n" + if (function[:return][:void?]) + lines << "void #{func_name}_Expect(#{function[:args_string]})\n{\n" else if (function[:args_string] == "void") - lines << "void #{func_name}_ExpectAndReturn(#{function[:return_string]})\n" + lines << "void #{func_name}_ExpectAndReturn(#{function[:return][:str]})\n{\n" else - lines << "void #{func_name}_ExpectAndReturn(#{function[:args_string]}, #{function[:return_string]})\n" + lines << "void #{func_name}_ExpectAndReturn(#{function[:args_string]}, #{function[:return][:str]})\n{\n" end end - lines << "{\n" lines << @utils.code_add_base_expectation(func_name) - - if (function[:args_string] != "void") - lines << " CMockExpectParameters_#{func_name}(#{function[:args].map{|m| m[:name]}.join(', ')});\n" - end - - if (function[:return_type] != "void") - lines << @utils.code_insert_item_into_expect_array(function[:return_type], "Mock.#{func_name}_Return", 'cmock_to_return') - lines << " Mock.#{func_name}_Return = Mock.#{func_name}_Return_Head;\n" - lines << " Mock.#{func_name}_Return += Mock.#{func_name}_CallCount;\n" - end + lines << @utils.code_call_argument_loader(function) + lines << @utils.code_assign_argument_quickly("cmock_call_instance->ReturnVal", function[:return]) unless (function[:return][:void?]) lines << "}\n\n" end def mock_verify(function) func_name = function[:name] - " TEST_ASSERT_EQUAL_MESSAGE(Mock.#{func_name}_CallsExpected, Mock.#{func_name}_CallCount, \"Function '#{func_name}' called unexpected number of times.\");\n" + " TEST_ASSERT_NULL_MESSAGE(Mock.#{func_name}_CallInstance, \"Function '#{func_name}' called less times than expected.\");\n" end - - def mock_destroy(function) - lines = [] - func_name = function[:name] - if (function[:return_type] != "void") - lines << DESTROY_RETURN_SNIPPET % func_name - end - - if (@ordered) - lines << DESTROY_CALL_ORDER_SNIPPET % func_name - end - - function[:args].each do |arg| - lines << DESTROY_BASE_SNIPPET % "#{func_name}_Expected_#{arg[:name]}" - end - lines.flatten - end - - private ##################### - - INSTANCE_STRUCTURE_CALL_SNIPPET = %q[ - int %1$s_CallCount; - int %1$s_CallsExpected; -] - INSTANCE_STRUCTURE_ITEM_SNIPPET = %q[ - %1$s; - %1$s_Head; - %1$s_Tail; -] - - MOCK_IMPLEMENT_SNIPPET = %q[ - Mock.%1$s_CallCount++; - if (Mock.%1$s_CallCount > Mock.%1$s_CallsExpected) - { - TEST_FAIL("Function '%1$s' called more times than expected"); - } -] - - MOCK_IMPLEMENT_ORDERED_SNIPPET = %q[ { - int* cmock_val_expected = Mock.%1$s_CallOrder; - ++GlobalVerifyOrder; - if (Mock.%1$s_CallOrder != Mock.%1$s_CallOrder_Tail) - Mock.%1$s_CallOrder++; - if ((*cmock_val_expected != GlobalVerifyOrder) && (GlobalOrderError == NULL)) - { - const char* cmock_err_str = "%2$s"; - GlobalOrderError = malloc(%3$s); - if (GlobalOrderError) - strcpy(GlobalOrderError, cmock_err_str); - } - } -] - - DESTROY_RETURN_SNIPPET = %q[ - if (Mock.%1$s_Return_Head) - { - free(Mock.%1$s_Return_Head); - } - Mock.%1$s_Return=NULL; - Mock.%1$s_Return_Head=NULL; - Mock.%1$s_Return_Tail=NULL; -] - - DESTROY_CALL_ORDER_SNIPPET = %q[ - if (Mock.%1$s_CallOrder_Head) - { - free(Mock.%1$s_CallOrder_Head); - } - Mock.%1$s_CallOrder=NULL; - Mock.%1$s_CallOrder_Head=NULL; - Mock.%1$s_CallOrder_Tail=NULL; -] - - DESTROY_BASE_SNIPPET = %q[ - if (Mock.%1$s_Head) - { - free(Mock.%1$s_Head); - } - Mock.%1$s=NULL; - Mock.%1$s_Head=NULL; - Mock.%1$s_Tail=NULL; -] - end diff --git a/lib/cmock_generator_plugin_ignore.rb b/lib/cmock_generator_plugin_ignore.rb index 2d2665f..f45c4c7 100644 --- a/lib/cmock_generator_plugin_ignore.rb +++ b/lib/cmock_generator_plugin_ignore.rb @@ -11,70 +11,51 @@ class CMockGeneratorPluginIgnore end def instance_structure(function) - return " int #{function[:name]}_IgnoreBool;\n" + if (function[:return][:void?]) + " int #{function[:name]}_IgnoreBool;\n" + else + " int #{function[:name]}_IgnoreBool;\n #{function[:return][:type]} #{function[:name]}_FinalReturn;\n" + end end def mock_function_declarations(function) - if (function[:return_type] == "void") + if (function[:return][:void?]) return "void #{function[:name]}_Ignore(void);\n" else - return "void #{function[:name]}_IgnoreAndReturn(#{function[:return_string]});\n" + return "void #{function[:name]}_IgnoreAndReturn(#{function[:return][:str]});\n" end end - def mock_implementation(function) - lines = " if (Mock.#{function[:name]}_IgnoreBool)\n {" - if (function[:return_type] == "void") - lines << "\n return;\n" + def mock_implementation_precheck(function) + lines = " if (Mock.#{function[:name]}_IgnoreBool)\n {\n" + if (function[:return][:void?]) + lines << " return;\n }\n" else - lines << MOCK_IMPLEMENT_PREFIX_SNIPPET % [function[:name], function[:return_type]] + retval = function[:return].merge( { :name => "cmock_call_instance->ReturnVal"} ) + 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 cmock_call_instance->ReturnVal;\n }\n" end - lines << " }\n" + lines end def mock_interfaces(function) - if (function[:return_type] == "void") - MOCK_INTERFACE_VOID_SNIPPET % function[:name] + lines = "" + if (function[:return][:void?]) + lines << "void #{function[:name]}_Ignore(void)\n{\n" else - item_insert = @utils.code_insert_item_into_expect_array(function[:return_type], "Mock.#{function[:name]}_Return", 'cmock_to_return') - MOCK_INTERFACE_FULL_SNIPPET % [function[:name], function[:return_string], item_insert] + lines << "void #{function[:name]}_IgnoreAndReturn(#{function[:return][:str]})\n{\n" end + unless (function[:return][:void?]) + lines << @utils.code_add_base_expectation(function[:name], false) + lines << " cmock_call_instance->ReturnVal = cmock_to_return;\n" + end + lines << " Mock.#{function[:name]}_IgnoreBool = (int)1;\n" + lines << "}\n\n" end - - private ############## - - MOCK_IMPLEMENT_PREFIX_SNIPPET = %q[ - if (Mock.%1$s_Return != Mock.%1$s_Return_Tail) - { - %2$s cmock_to_return = *Mock.%1$s_Return; - Mock.%1$s_Return++; - Mock.%1$s_CallCount++; - Mock.%1$s_CallsExpected++; - return cmock_to_return; - } - else - { - return *(Mock.%1$s_Return_Tail - 1); - } -] - - MOCK_INTERFACE_VOID_SNIPPET = %q[ -void %1$s_Ignore(void) -{ - Mock.%1$s_IgnoreBool = (int)1; -} - -] - - MOCK_INTERFACE_FULL_SNIPPET = %q[ -void %1$s_IgnoreAndReturn(%2$s) -{ - Mock.%1$s_IgnoreBool = (int)1; -%3$s - Mock.%1$s_Return = Mock.%1$s_Return_Head; - Mock.%1$s_Return += Mock.%1$s_CallCount; -} - -] + def mock_verify(function) + func_name = function[:name] + " if (Mock.#{func_name}_IgnoreBool)\n Mock.#{func_name}_CallInstance = NULL;\n" + end end diff --git a/lib/cmock_generator_utils.rb b/lib/cmock_generator_utils.rb index 920c79c..88cad73 100644 --- a/lib/cmock_generator_utils.rb +++ b/lib/cmock_generator_utils.rb @@ -1,52 +1,76 @@ class CMockGeneratorUtils - attr_accessor :config, :helpers, :ordered, :ptr_handling, :arrays + attr_accessor :config, :helpers, :ordered, :ptr_handling, :arrays, :cexception def initialize(config, helpers={}) @config = config @ptr_handling = @config.when_ptr @ordered = @config.enforce_strict_ordering - @arrays = @config.plugins.include? :array + @arrays = @config.plugins.include? :array + @cexception = @config.plugins.include? :cexception + @treat_as = @config.treat_as @helpers = helpers end - def code_insert_item_into_expect_array(type, array, newValue) - INSERT_EXPECT_CODE_SNIPPET % [type, array, newValue] - end - - def code_add_an_arg_expectation(function, arg, depth=1) - var = "Mock.#{function[:name]}_Expected_#{arg[:name]}" - lines = code_insert_item_into_expect_array(arg[:type], var, arg[:name]) - lines << INSERT_EXPECT_SETUP_SNIPPET % [var, function[:name]] - if (@arrays and arg[:ptr?]) - var += '_Depth' - lines << INSERT_EXPECT_SHORT_CODE_SNIPPET % ['int', var, depth] - lines << INSERT_EXPECT_SETUP_SNIPPET % [var, function[:name]] - end + def code_add_base_expectation(func_name, global_ordering_supported=true) + lines = " CMOCK_#{func_name}_CALL_INSTANCE* cmock_call_instance = (CMOCK_#{func_name}_CALL_INSTANCE*)CMock_Guts_MemNew(sizeof(CMOCK_#{func_name}_CALL_INSTANCE));\n" + lines << " TEST_ASSERT_NOT_NULL_MESSAGE(cmock_call_instance, \"CMock has run out of memory. Please allocate more.\");\n" + lines << " Mock.#{func_name}_CallInstance = (CMOCK_#{func_name}_CALL_INSTANCE*)CMock_Guts_MemChain((void*)Mock.#{func_name}_CallInstance, (void*)cmock_call_instance);\n" + lines << " cmock_call_instance->CallOrder = ++GlobalExpectCount;\n" if (@ordered and global_ordering_supported) + lines << " cmock_call_instance->ExceptionToThrow = CEXCEPTION_NONE;\n" if (@cexception) lines end - def code_add_base_expectation(func_name) - lines = " Mock.#{func_name}_CallsExpected++;\n" - if (@ordered) - var = "Mock.#{func_name}_CallOrder" - lines << " ++GlobalExpectCount;\n" - lines << code_insert_item_into_expect_array('int', var, 'GlobalExpectCount') - lines << INSERT_EXPECT_SETUP_SNIPPET % [var, func_name] - end + def code_add_an_arg_expectation(arg, depth=1) + lines = code_assign_argument_quickly("cmock_call_instance->Expected_#{arg[:name]}", arg) + lines << " cmock_call_instance->Expected_#{arg[:name]}_Depth = #{arg[:name]}_Depth;\n" if (@arrays and (depth.class == String)) lines end - def code_verify_an_arg_expectation(function, arg) - (INSERT_ARG_VERIFY_START_SNIPPET % ["#{function[:name]}_Expected_#{arg[:name]}", arg[:type]]) + - expect_helper(arg, '*cmock_val_expected', "\"Function '#{function[:name]}' called with unexpected value for argument '#{arg[:name]}'.\"", "#{function[:name]}_Expected_#{arg[:name]}_Depth") + - "\n }\n" + def code_assign_argument_quickly(dest, arg) + if (arg[:ptr?] or @treat_as.include?(arg[:type])) + " #{dest} = #{arg[:const?] ? "(#{arg[:type]})" : ''}#{arg[:name]};\n" + else + " memcpy(&#{dest}, &#{arg[:name]}, sizeof(#{arg[:type]}));\n" + end end - def expect_helper(arg, expected, msg, depth_name='1') + def code_add_argument_loader(function) + if (function[:args_string] != "void") + if (@arrays) + args_string = function[:args].map{|m| m[:ptr?] ? "#{m[:type]} #{m[:name]}, int #{m[:name]}_Depth" : "#{m[:type]} #{m[:name]}"}.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) ) } + + "}\n\n" + else + "void CMockExpectParameters_#{function[:name]}(CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance, #{function[:args_string]})\n{\n" + + function[:args].inject("") { |all, arg| all + code_add_an_arg_expectation(arg) } + + "}\n\n" + end + else + "" + end + end + + def code_call_argument_loader(function) + if (function[:args_string] != "void") + args = function[:args].map do |m| + arg = m[:const?] ? "(#{m[:type]})#{m[:name]}" : m[:name] + (@arrays and m[:ptr?]) ? "#{arg}, 1" : arg + end + " CMockExpectParameters_#{function[:name]}(cmock_call_instance, #{args.join(', ')});\n" + else + "" + end + end + + def code_verify_an_arg_expectation(function, arg) c_type = arg[:type] - name = arg[:name] + arg_name = arg[:name] + expected = "cmock_call_instance->Expected_#{arg_name}" + msg = "\"Function '#{function[:name]}' called with unexpected value for argument '#{arg_name}'.\"" + depth_name = (arg[:ptr?]) ? "cmock_call_instance->Expected_#{arg_name}_Depth" : 1 if ((arg[:ptr?]) and (@ptr_handling == :compare_ptr)) unity_func = "TEST_ASSERT_EQUAL_HEX32_MESSAGE" else @@ -55,122 +79,38 @@ class CMockGeneratorUtils unity_msg = (unity_func =~ /_MESSAGE/) ? ", #{msg}" : '' case(unity_func) when "TEST_ASSERT_EQUAL_MEMORY_MESSAGE" - full_expected = (expected =~ /^\*/) ? expected.slice(1..-1) : "&(#{expected})" - return " TEST_ASSERT_EQUAL_MEMORY_MESSAGE((void*)#{full_expected}, (void*)&(#{name}), sizeof(#{c_type})#{unity_msg});\n" + full_expected = (expected =~ /^\*/) ? expected.slice(1..-1) : "(&#{expected})" + return " TEST_ASSERT_EQUAL_MEMORY_MESSAGE((void*)#{full_expected}, (void*)(&#{arg_name}), sizeof(#{c_type})#{unity_msg});\n" when "TEST_ASSERT_EQUAL_MEMORY_MESSAGE_ARRAY" if (@arrays) - [ (INSERT_ARG_DEPTH_START_SNIPPET % [depth_name]), - " if (*cmock_val_expected == NULL)", - " { TEST_ASSERT_NULL(#{name}); }", - ((@ptr_handling == :smart) ? " else if (cmock_depth == 0)\n { TEST_ASSERT_EQUAL_HEX32(*cmock_val_expected, #{name}); }" : nil), - " else", - " { TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE((void*)(#{expected}), (void*)#{name}, sizeof(#{c_type.sub('*','')}), cmock_depth#{unity_msg}); }"].compact.join("\n") + [ " if (#{expected} == NULL)", + " { TEST_ASSERT_NULL(#{arg_name}); }", + (((@ptr_handling == :smart) and (depth_name != 1)) ? " else if (#{depth_name} == 0)\n { TEST_ASSERT_EQUAL_HEX32(#{expected}, #{arg_name}); }" : nil), + " else", + " { TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE((void*)(#{expected}), (void*)#{arg_name}, sizeof(#{c_type.sub('*','')}), #{depth_name}#{unity_msg}); }\n"].compact.join("\n") else - [ " if (*cmock_val_expected == NULL)", - " { TEST_ASSERT_NULL(#{name}); }", - " else", - " { TEST_ASSERT_EQUAL_MEMORY_MESSAGE((void*)(#{expected}), (void*)#{name}, sizeof(#{c_type.sub('*','')})#{unity_msg}); }"].join("\n") + [ " if (#{expected} == NULL)", + " { TEST_ASSERT_NULL(#{arg_name}); }", + " else", + " { TEST_ASSERT_EQUAL_MEMORY_MESSAGE((void*)(#{expected}), (void*)#{arg_name}, sizeof(#{c_type.sub('*','')})#{unity_msg}); }\n"].join("\n") end when /_ARRAY/ if (@arrays) - [ (INSERT_ARG_DEPTH_START_SNIPPET % [depth_name]), - " if (*cmock_val_expected == NULL)", - " { TEST_ASSERT_NULL(#{name}); }", - ((@ptr_handling == :smart) ? " else if (cmock_depth == 0)\n { TEST_ASSERT_EQUAL_HEX32(*cmock_val_expected, #{name}); }" : nil), - " else", - " { #{unity_func}(#{expected}, #{name}, cmock_depth); }"].compact.join("\n") + [ " if (#{expected} == NULL)", + " { TEST_ASSERT_NULL(#{arg_name}); }", + (((@ptr_handling == :smart) and (depth_name != 1)) ? " else if (#{depth_name} == 0)\n { TEST_ASSERT_EQUAL_HEX32(#{expected}, #{arg_name}); }" : nil), + " else", + " { #{unity_func}(#{expected}, #{arg_name}, #{depth_name}); }\n"].compact.join("\n") else - [ " if (*cmock_val_expected == NULL)", - " { TEST_ASSERT_NULL(#{name}); }", - " else", - " { #{unity_func}(#{expected}, #{name}, 1); }"].join("\n") + [ " if (#{expected} == NULL)", + " { TEST_ASSERT_NULL(#{arg_name}); }", + " else", + " { #{unity_func}(#{expected}, #{arg_name}, 1); }\n"].join("\n") end else - return " #{unity_func}(#{expected}, #{name}#{unity_msg});\n" + return " #{unity_func}(#{expected}, #{arg_name}#{unity_msg});\n" end end - def code_handle_return_value(function) - INSERT_RETURN_TYPE_SNIPPET % [ function[:name], function[:return_type] ] - end - - private ################### - - INSERT_EXPECT_CODE_SNIPPET = %q[ - { - int sz = 0; - %1$s *cmock_pointer = %2$s_Head; - while (cmock_pointer && cmock_pointer != %2$s_Tail) { sz++; cmock_pointer++; } - if (sz == 0) - { - %2$s_Head = (%1$s*)malloc(2*sizeof(%1$s)); - if (!%2$s_Head) - Mock.allocFailure++; - } - else - { - %1$s *ptmp = (%1$s*)realloc(%2$s_Head, sizeof(%1$s) * (sz+1)); - if (!ptmp) - Mock.allocFailure++; - else - %2$s_Head = ptmp; - } - memcpy(&%2$s_Head[sz], &%3$s, sizeof(%1$s)); - %2$s_Tail = &%2$s_Head[sz+1]; - } -] - - INSERT_EXPECT_SHORT_CODE_SNIPPET = %q[ - { - int sz = 0; - %1$s *cmock_pointer = %2$s_Head; - while (cmock_pointer && cmock_pointer != %2$s_Tail) { sz++; cmock_pointer++; } - if (sz == 0) - { - %2$s_Head = (%1$s*)malloc(2*sizeof(%1$s)); - if (!%2$s_Head) - Mock.allocFailure++; - } - else - { - %1$s *ptmp = (%1$s*)realloc(%2$s_Head, sizeof(%1$s) * (sz+1)); - if (!ptmp) - Mock.allocFailure++; - else - %2$s_Head = ptmp; - } - %2$s_Head[sz] = %3$s; - %2$s_Tail = &%2$s_Head[sz+1]; - } -] - - INSERT_EXPECT_SETUP_SNIPPET = - " %1$s = %1$s_Head;\n %1$s += Mock.%2$s_CallCount;\n" - - INSERT_RETURN_TYPE_SNIPPET = %q[ - if (Mock.%1$s_Return != Mock.%1$s_Return_Tail) - { - %2$s cmock_to_return = *Mock.%1$s_Return; - Mock.%1$s_Return++; - return cmock_to_return; - } - else - { - return *(Mock.%1$s_Return_Tail - 1); - } -] - - INSERT_ARG_VERIFY_START_SNIPPET = %q[ - if (Mock.%1$s != Mock.%1$s_Tail) - { - %2$s* cmock_val_expected = Mock.%1$s; - Mock.%1$s++; -] - - INSERT_ARG_DEPTH_START_SNIPPET = %q[ - int cmock_depth = *Mock.%1$s; - Mock.%1$s++; -] - end \ No newline at end of file diff --git a/lib/cmock_header_parser.rb b/lib/cmock_header_parser.rb index 236e959..760e833 100644 --- a/lib/cmock_header_parser.rb +++ b/lib/cmock_header_parser.rb @@ -106,10 +106,12 @@ class CMockHeaderParser 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 ... - arg_elements = arg.split - @c_attributes # split up words and remove known attributes - args << { :type => (arg_type =arg_elements[0..-2].join(' ')), - :name => arg_elements[-1], - :ptr? => divine_ptr(arg_type) + arg_array = arg.split + arg_elements = arg_array - @c_attributes # split up words and remove known attributes + args << { :type => (arg_type =arg_elements[0..-2].join(' ')), + :name => arg_elements[-1], + :ptr? => divine_ptr(arg_type), + :const? => arg_array.include?('const') } end return args @@ -178,18 +180,24 @@ class CMockHeaderParser #build attribute and return type strings decl[:modifier] = [] - decl[:return_type] = [] + rettype = [] descriptors[0..-2].each do |word| if @c_attributes.include?(word) decl[:modifier] << word else - decl[:return_type] << word + rettype << word end end decl[:modifier] = decl[:modifier].join(' ') - decl[:return_type] = decl[:return_type].join(' ') - decl[:return_type] = 'void' if (@local_as_void.include?(decl[:return_type].strip)) - decl[:return_string] = decl[:return_type] + " cmock_to_return" + rettype = rettype.join(' ') + rettype = 'void' if (@local_as_void.include?(rettype.strip)) + decl[:return] = { :type => rettype, + :name => 'cmock_to_return', + :ptr? => divine_ptr(rettype), + :const? => rettype.split(/\s/).include?('const'), + :str => "#{rettype} cmock_to_return", + :void? => (rettype == 'void') + } #remove default argument statements from mock definitions args.gsub!(/=\s*[a-zA-Z0-9_\.]+\s*\,/, ',') @@ -211,12 +219,12 @@ class CMockHeaderParser decl[:args] = parse_args(args) decl[:contains_ptr?] = decl[:args].inject(false) {|ptr, arg| arg[:ptr?] ? true : ptr } - if (decl[:return_type].nil? or decl[:name].nil? or decl[:args].nil? or - decl[:return_type].empty? or decl[:name].empty?) + if (decl[:return][:type].nil? or decl[:name].nil? or decl[:args].nil? or + decl[:return][:type].empty? or decl[:name].empty?) raise "Failed Parsing Declaration Prototype!\n" + " declaration: #{declaration}\n" + " modifier: #{decl[:modifier]}\n" + - " return: #{decl[:return_type]}\n" + + " return: #{decl[:return]}\n" + " function: #{decl[:name]}\n" + " args:#{decl[:args]}\n" end diff --git a/lib/cmock_unityhelper_parser.rb b/lib/cmock_unityhelper_parser.rb index 6d9d719..fc00e7d 100644 --- a/lib/cmock_unityhelper_parser.rb +++ b/lib/cmock_unityhelper_parser.rb @@ -22,10 +22,8 @@ class CMockUnityHelperParser def map_C_types c_types = {} - [@config.standard_treat_as_map, @config.treat_as].each do |pairs| - pairs.each_pair do |ctype, expecttype| - c_types[ctype.gsub(/\s+/,'_')] = "TEST_ASSERT_EQUAL_#{expecttype}_MESSAGE" - end unless pairs.nil? + @config.treat_as.each_pair do |ctype, expecttype| + c_types[ctype.gsub(/\s+/,'_')] = "TEST_ASSERT_EQUAL_#{expecttype}_MESSAGE" end c_types end diff --git a/rakefile.rb b/rakefile.rb index ada23c4..1e1ba08 100644 --- a/rakefile.rb +++ b/rakefile.rb @@ -25,21 +25,53 @@ end namespace :test do desc "Run all unit and system tests" - task :all => ['test:units', 'test:system'] + task :all => [:clobber, 'test:units', 'test:c', 'test:system'] + desc "Run Unit Tests" Rake::TestTask.new('units') do |t| t.pattern = 'test/unit/*_test.rb' t.verbose = true end - desc "Run system tests" + #individual unit tests + FileList['test/unit/*_test.rb'].each do |test| + Rake::TestTask.new(File.basename(test,'.*')) do |t| + t.pattern = test + t.verbose = true + end + end + + desc "Run C Unit Tests" + task :c do + build_and_test_c_files + end + + #get a list of all system tests, removing unsupported tests for this compiler + sys_unsupported = $cfg['unsupported'].map {|a| 'test/system/test_interactions/'+a+'.yml'} + sys_tests_to_run = FileList['test/system/test_interactions/*.yml'] - sys_unsupported + compile_unsupported = $cfg['unsupported'].map {|a| SYSTEST_COMPILE_MOCKABLES_PATH+a+'.h'} + compile_tests_to_run = FileList[SYSTEST_COMPILE_MOCKABLES_PATH + '*.h'] - compile_unsupported + + desc "Run System Tests" task :system => [:clobber] do + unless (sys_unsupported.empty? and compile_unsupported.empty?) + report "\nIgnoring these system tests..." + sys_unsupported.each {|a| report a} + compile_unsupported.each {|a| report a} + end report "\nRunning system tests..." - - tests_failed = run_system_test_interactions(FileList['test/system/test_interactions/*.yml']) + tests_failed = run_system_test_interactions(sys_tests_to_run) raise "System tests failed." if (tests_failed > 0) - run_system_test_compilations(FileList[SYSTEST_COMPILE_MOCKABLES_PATH + '*.h']) + run_system_test_compilations(compile_tests_to_run) + end + + #individual system tests + sys_tests_to_run.each do |test| + desc "Run system test #{File.basename(test,'.*')}" + task "test:#{File.basename(test,'.*')}" do + run_system_test_interactions([test]) + end end desc "Profile Mock Generation" diff --git a/rakefile_helper.rb b/rakefile_helper.rb index 9e10cb8..cbeecb8 100644 --- a/rakefile_helper.rb +++ b/rakefile_helper.rb @@ -92,7 +92,7 @@ module RakefileHelpers def compile(file, defines=[]) compiler = build_compiler_fields - cmd_str = "#{compiler[:command]}#{compiler[:defines]}#{compiler[:options]}#{compiler[:includes]} #{file} " + + cmd_str = "#{compiler[:command]}#{compiler[:defines]}#{defines.inject(''){|all, a| ' -D'+a+all }}#{compiler[:options]}#{compiler[:includes]} #{file} " + "#{$cfg['compiler']['object_files']['prefix']}#{$cfg['compiler']['object_files']['destination']}" + "#{File.basename(file, C_EXTENSION)}#{$cfg['compiler']['object_files']['extension']}" execute(cmd_str) @@ -145,6 +145,7 @@ module RakefileHelpers end def execute(command_string, verbose=true) + #puts command_string output = `#{command_string}`.chomp report(output) if (verbose && !output.nil? && (output.length > 0)) if $?.exitstatus != 0 @@ -153,6 +154,15 @@ module RakefileHelpers return output end + def tackit(strings) + if strings.is_a?(Array) + result = "\"#{strings.join}\"" + else + result = strings + end + return result + end + def report_summary summary = UnityTestSummary.new summary.set_root_path(HERE) @@ -332,5 +342,31 @@ module RakefileHelpers compile(SYSTEST_GENERATED_FILES_PATH + mock_filename) end end + + def build_and_test_c_files + puts "\n" + puts "----------------\n" + puts "UNIT TEST C CODE\n" + puts "----------------\n" + errors = false + FileList.new("test/c/*.yml").each do |yaml_file| + test = YAML.load(File.read(yaml_file)) + puts "\nTesting #{yaml_file.sub('.yml','')}" + puts "(#{test[:options].join(', ')})" + test[:files].each { |f| compile(f, test[:options]) } + obj_files = test[:files].map { |f| f.gsub!(/.*\//,'').gsub!(C_EXTENSION, $cfg['compiler']['object_files']['extension']) } + link('TestCMockC', obj_files) + if $cfg['simulator'].nil? + execute($cfg['linker']['bin_files']['destination'] + 'TestCMockC' + $cfg['linker']['bin_files']['extension']) + else + execute(tackit($cfg['simulator']['path'].join) + ' ' + + $cfg['simulator']['pre_support'].map{|o| tackit(o)}.join(' ') + ' ' + + $cfg['linker']['bin_files']['destination'] + + 'TestCMockC' + + $cfg['linker']['bin_files']['extension'] + ' ' + + $cfg['simulator']['post_support'].map{|o| tackit(o)}.join(' ') ) + end + end + end end diff --git a/src/cmock.c b/src/cmock.c new file mode 100644 index 0000000..54b144d --- /dev/null +++ b/src/cmock.c @@ -0,0 +1,152 @@ +#include "unity.h" +#include "cmock.h" + +//define CMOCK_MEM_DYNAMIC to grab memory as needed with malloc +//when you do that, CMOCK_MEM_SIZE is used for incremental size instead of total +#ifdef CMOCK_MEM_STATIC +#undef CMOCK_MEM_DYNAMIC +#endif + +#ifdef CMOCK_MEM_DYNAMIC +#include +#endif + +//should be big enough to index full range of CMOCK_MEM_MAX +#ifndef CMOCK_MEM_INDEX_TYPE +#define CMOCK_MEM_INDEX_TYPE unsigned int +#endif + +//0 for no alignment, 1 for 16-bit, 2 for 32-bit, 3 for 64-bit +#ifndef CMOCK_MEM_ALIGN +#define CMOCK_MEM_ALIGN (2) +#endif + +//amount of memory to allow cmock to use in its internal heap +#ifndef CMOCK_MEM_SIZE +#define CMOCK_MEM_SIZE (32768) +#endif + +//automatically calculated defs for easier reading +#define CMOCK_MEM_INDEX_SIZE (sizeof(CMOCK_MEM_INDEX_TYPE)) +#define CMOCK_MEM_ALIGN_MASK ((1u << CMOCK_MEM_ALIGN) - 1) + +//private variables +#ifdef CMOCK_MEM_DYNAMIC +static unsigned char* CMock_Guts_Buffer = NULL; +static unsigned int CMock_Guts_BufferSize = 0; +static unsigned int CMock_Guts_FreePtr; +#else +static unsigned char CMock_Guts_Buffer[CMOCK_MEM_SIZE]; +static unsigned int CMock_Guts_BufferSize = CMOCK_MEM_SIZE; +static unsigned int CMock_Guts_FreePtr; +#endif +//------------------------------------------------------- +// CMock_Guts_MemNew +//------------------------------------------------------- +void* CMock_Guts_MemNew(unsigned int size) +{ + unsigned int index; + + //verify arguments valid (we must be allocating space for at least 1 byte, and the existing chain must be in memory somewhere) + if (size < 1) + return NULL; + + //verify we have enough room + size = size + CMOCK_MEM_INDEX_SIZE; + if (size & CMOCK_MEM_ALIGN_MASK) + size = (size + CMOCK_MEM_ALIGN_MASK) & ~CMOCK_MEM_ALIGN_MASK; + if ((CMock_Guts_BufferSize - CMock_Guts_FreePtr) < size) + { +#ifdef CMOCK_MEM_DYNAMIC + CMock_Guts_BufferSize += CMOCK_MEM_SIZE + size; + CMock_Guts_Buffer = realloc(CMock_Guts_Buffer, CMock_Guts_BufferSize); + if (CMock_Guts_Buffer == NULL) +#endif //yes that if will continue to the return below if TRUE + return NULL; + } + + //determine where we're putting this new block, and init its pointer to be the end of the line + index = CMock_Guts_FreePtr + CMOCK_MEM_INDEX_SIZE; + *(CMOCK_MEM_INDEX_TYPE*)(&CMock_Guts_Buffer[CMock_Guts_FreePtr]) = 0; + CMock_Guts_FreePtr += size; + + return (&CMock_Guts_Buffer[index]); +} + +//------------------------------------------------------- +// CMock_Guts_MemChain +//------------------------------------------------------- +void* CMock_Guts_MemChain(void* root, void* obj) +{ + unsigned int index; + void* next; + + if (root == NULL) + { + //if there is no root currently, we return this object as the root of the chain + return obj; + } + else + { + //reject illegal nodes + if ((root < (void*)CMock_Guts_Buffer) || (root >= (void*)(&CMock_Guts_Buffer[CMock_Guts_FreePtr]))) + return NULL; + if ((obj < (void*)CMock_Guts_Buffer) || (obj >= (void*)(&CMock_Guts_Buffer[CMock_Guts_FreePtr]))) + return NULL; + + //find the end of the existing chain and add us + next = root; + do { + index = *(CMOCK_MEM_INDEX_TYPE*)((unsigned int)next - CMOCK_MEM_INDEX_SIZE); + if (index >= CMock_Guts_FreePtr) + return NULL; + if (index > 0) + next = (void*)(&CMock_Guts_Buffer[index]); + } while (index > 0); + *(CMOCK_MEM_INDEX_TYPE*)((unsigned int)next - CMOCK_MEM_INDEX_SIZE) = ((unsigned int)obj - (unsigned int)CMock_Guts_Buffer); + return root; + } +} + +//------------------------------------------------------- +// CMock_Guts_MemNext +//------------------------------------------------------- +void* CMock_Guts_MemNext(void* previous_item) +{ + CMOCK_MEM_INDEX_TYPE index; + + //There is nothing "next" if the pointer isn't from our buffer + if ((previous_item < (void*)CMock_Guts_Buffer) || (previous_item >= (void*)(&CMock_Guts_Buffer[CMock_Guts_FreePtr]))) + return NULL; + + //if the pointer is good, then use it to look up the next index (we know the first element always goes in zero, so NEXT must always be > 1) + index = *(CMOCK_MEM_INDEX_TYPE*)((unsigned int)previous_item - CMOCK_MEM_INDEX_SIZE); + if ((index > 1) && (index < CMock_Guts_FreePtr)) + return (void*)(&CMock_Guts_Buffer[index]); + else + return NULL; +} + +//------------------------------------------------------- +// CMock_Guts_MemBytesFree +//------------------------------------------------------- +unsigned int CMock_Guts_MemBytesFree(void) +{ + return CMock_Guts_BufferSize - CMock_Guts_FreePtr; +} + +//------------------------------------------------------- +// CMock_Guts_MemBytesUsed +//------------------------------------------------------- +unsigned int CMock_Guts_MemBytesUsed(void) +{ + return CMock_Guts_FreePtr; +} + +//------------------------------------------------------- +// CMock_Guts_MemFreeAll +//------------------------------------------------------- +void CMock_Guts_MemFreeAll(void) +{ + CMock_Guts_FreePtr = 0; +} diff --git a/src/cmock.h b/src/cmock.h new file mode 100644 index 0000000..38935ae --- /dev/null +++ b/src/cmock.h @@ -0,0 +1,14 @@ +#ifndef CMOCK_FRAMEWORK_H +#define CMOCK_FRAMEWORK_H + +//------------------------------------------------------- +// Memory API +//------------------------------------------------------- +void* CMock_Guts_MemNew(unsigned int size); +void* CMock_Guts_MemChain(void* root, void* obj); +void* CMock_Guts_MemNext(void* previous_item); +unsigned int CMock_Guts_MemBytesFree(void); +unsigned int CMock_Guts_MemBytesUsed(void); +void CMock_Guts_MemFreeAll(void); + +#endif //CMOCK_FRAMEWORK diff --git a/test/c/TestCMockC.c b/test/c/TestCMockC.c new file mode 100644 index 0000000..4917bfb --- /dev/null +++ b/test/c/TestCMockC.c @@ -0,0 +1,272 @@ +#include "unity.h" +#include "cmock.h" + +#define TEST_MEM_INDEX_SIZE (sizeof(CMOCK_MEM_INDEX_TYPE)) + +void setUp(void) +{ + CMock_Guts_MemFreeAll(); +} + +void tearDown(void) +{ +} + +void test_MemNewWillReturnNullIfGivenIllegalSizes(void) +{ + TEST_ASSERT_NULL( CMock_Guts_MemNew(0) ); + TEST_ASSERT_NULL( CMock_Guts_MemNew(CMOCK_MEM_SIZE - TEST_MEM_INDEX_SIZE + 1) ); + + //verify we're cleared still + TEST_ASSERT_EQUAL(0, CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(CMOCK_MEM_SIZE, CMock_Guts_MemBytesFree()); +} + +void test_MemChainWillReturnNullAndDoNothingIfGivenIllegalInformation(void) +{ + unsigned int* next = CMock_Guts_MemNew(4); + TEST_ASSERT_EQUAL(4 + TEST_MEM_INDEX_SIZE, CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(CMOCK_MEM_SIZE - 4 - TEST_MEM_INDEX_SIZE, CMock_Guts_MemBytesFree()); + + TEST_ASSERT_NULL( CMock_Guts_MemChain((void*)((unsigned int)next + CMOCK_MEM_SIZE), next) ); + TEST_ASSERT_NULL( CMock_Guts_MemChain(next, (void*)((unsigned int)next + CMOCK_MEM_SIZE)) ); + + //verify we're still the same + TEST_ASSERT_EQUAL(4 + TEST_MEM_INDEX_SIZE, CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(CMOCK_MEM_SIZE - 4 - TEST_MEM_INDEX_SIZE, CMock_Guts_MemBytesFree()); +} + +void test_MemNextWillReturnNullIfGivenABadRoot(void) +{ + TEST_ASSERT_NULL( CMock_Guts_MemNext(NULL) ); + TEST_ASSERT_NULL( CMock_Guts_MemNext((void*)2) ); + TEST_ASSERT_NULL( CMock_Guts_MemNext((void*)0xFFFFFFFE) ); + + //verify we're cleared still + TEST_ASSERT_EQUAL(0, CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(CMOCK_MEM_SIZE, CMock_Guts_MemBytesFree()); +} + +void test_ThatWeCanClaimAndChainAFewElementsTogether(void) +{ + unsigned int i; + unsigned int* first = NULL; + unsigned int* next; + unsigned int* element[4]; + + //verify we're cleared first + TEST_ASSERT_EQUAL(0, CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(CMOCK_MEM_SIZE, CMock_Guts_MemBytesFree()); + + //first element + element[0] = CMock_Guts_MemNew(sizeof(unsigned int)); + TEST_ASSERT_NOT_NULL(element[0]); + first = CMock_Guts_MemChain(first, element[0]); + TEST_ASSERT_EQUAL(element[0], first); + *element[0] = 0; + + //verify we're using the right amount of memory + TEST_ASSERT_EQUAL(1 * (TEST_MEM_INDEX_SIZE + 4), CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(CMOCK_MEM_SIZE - 1 * (TEST_MEM_INDEX_SIZE + 4), CMock_Guts_MemBytesFree()); + + //second element + element[1] = CMock_Guts_MemNew(sizeof(unsigned int)); + TEST_ASSERT_NOT_NULL(element[1]); + TEST_ASSERT_NOT_EQUAL(element[0], element[1]); + TEST_ASSERT_EQUAL(first, CMock_Guts_MemChain(first, element[1])); + *element[1] = 1; + + //verify we're using the right amount of memory + TEST_ASSERT_EQUAL(2 * (TEST_MEM_INDEX_SIZE + 4), CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(CMOCK_MEM_SIZE - 2 * (TEST_MEM_INDEX_SIZE + 4), CMock_Guts_MemBytesFree()); + + //third element + element[2] = CMock_Guts_MemNew(sizeof(unsigned int)); + TEST_ASSERT_NOT_NULL(element[2]); + TEST_ASSERT_NOT_EQUAL(element[0], element[2]); + TEST_ASSERT_NOT_EQUAL(element[1], element[2]); + TEST_ASSERT_EQUAL(first, CMock_Guts_MemChain(first, element[2])); + *element[2] = 2; + + //verify we're using the right amount of memory + TEST_ASSERT_EQUAL(3 * (TEST_MEM_INDEX_SIZE + 4), CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(CMOCK_MEM_SIZE - 3 * (TEST_MEM_INDEX_SIZE + 4), CMock_Guts_MemBytesFree()); + + //fourth element + element[3] = CMock_Guts_MemNew(sizeof(unsigned int)); + TEST_ASSERT_NOT_NULL(element[3]); + TEST_ASSERT_NOT_EQUAL(element[0], element[3]); + TEST_ASSERT_NOT_EQUAL(element[1], element[3]); + TEST_ASSERT_NOT_EQUAL(element[2], element[3]); + TEST_ASSERT_EQUAL(first, CMock_Guts_MemChain(first, element[3])); + *element[3] = 3; + + //verify we're using the right amount of memory + TEST_ASSERT_EQUAL(4 * (TEST_MEM_INDEX_SIZE + 4), CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(CMOCK_MEM_SIZE - 4 * (TEST_MEM_INDEX_SIZE + 4), CMock_Guts_MemBytesFree()); + + //traverse list + next = first; + for (i = 0; i < 4; i++) + { + TEST_ASSERT_EQUAL(element[i], next); + TEST_ASSERT_EQUAL(i, *next); + next = CMock_Guts_MemNext(next); + } + + //verify we get a null at the end of the list + TEST_ASSERT_NULL(next); + + //verify we're using the right amount of memory + TEST_ASSERT_EQUAL(4 * (TEST_MEM_INDEX_SIZE + 4), CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(CMOCK_MEM_SIZE - 4 * (TEST_MEM_INDEX_SIZE + 4), CMock_Guts_MemBytesFree()); + + //Free it all + CMock_Guts_MemFreeAll(); + + //verify we're cleared + TEST_ASSERT_EQUAL(0, CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(CMOCK_MEM_SIZE, CMock_Guts_MemBytesFree()); +} + +void test_ThatCMockStopsReturningMoreDataWhenItRunsOutOfMemory(void) +{ + unsigned int i; + unsigned int* first = NULL; + unsigned int* next; + + //even though we are asking for one byte, we've told it to align to closest 4 bytes, therefore it will waste a byte each time + //so each call will use 8 bytes (4 for the index, 1 for the data, and 3 wasted). + //therefore we can safely allocated total/8 times. + for (i = 0; i < (CMOCK_MEM_SIZE / 8); i++) + { + TEST_ASSERT_EQUAL(i*8, CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(CMOCK_MEM_SIZE - i*8, CMock_Guts_MemBytesFree()); + + next = CMock_Guts_MemNew(1); + TEST_ASSERT_NOT_NULL(next); + + first = CMock_Guts_MemChain(first, next); + TEST_ASSERT_NOT_NULL(first); + } + + //verify we're at top of memory + TEST_ASSERT_EQUAL(CMOCK_MEM_SIZE, CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(0, CMock_Guts_MemBytesFree()); + + //The very next call will return a NULL, and any after that + TEST_ASSERT_NULL(CMock_Guts_MemNew(1)); + TEST_ASSERT_NULL(CMock_Guts_MemNew(1)); + TEST_ASSERT_NULL(CMock_Guts_MemNew(1)); + + //verify nothing has changed + TEST_ASSERT_EQUAL(CMOCK_MEM_SIZE, CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(0, CMock_Guts_MemBytesFree()); + + //verify we can still walk through the elements allocated + next = first; + for (i = 0; i < (CMOCK_MEM_SIZE / 8); i++) + { + TEST_ASSERT_NOT_NULL(next); + next = CMock_Guts_MemNext(next); + } + + //there aren't any after that + TEST_ASSERT_NULL(next); +} + +void test_ThatCMockStopsReturningMoreDataWhenAskForMoreThanItHasLeftEvenIfNotAtExactEnd(void) +{ + unsigned int i; + unsigned int* first = NULL; + unsigned int* next; + + //we're asking for 12 bytes each time now (4 for index, 8 for data). + //10 requests will give us 120 bytes used, which isn't enough for another 12 bytes if total memory is 128 + for (i = 0; i < 10; i++) + { + TEST_ASSERT_EQUAL(i*12, CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(CMOCK_MEM_SIZE - i*12, CMock_Guts_MemBytesFree()); + + next = CMock_Guts_MemNew(8); + TEST_ASSERT_NOT_NULL(next); + + first = CMock_Guts_MemChain(first, next); + TEST_ASSERT_NOT_NULL(first); + + //verify writing data won't screw us up + *(unsigned int*)next = i; + } + + //verify we're at top of memory + TEST_ASSERT_EQUAL(CMOCK_MEM_SIZE - 8, CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(8, CMock_Guts_MemBytesFree()); + + //The very next call will return a NULL, and any after that + TEST_ASSERT_NULL(CMock_Guts_MemNew(8)); + TEST_ASSERT_NULL(CMock_Guts_MemNew(5)); + + //verify nothing has changed + TEST_ASSERT_EQUAL(CMOCK_MEM_SIZE - 8, CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(8, CMock_Guts_MemBytesFree()); + + //verify we can still walk through the elements allocated + next = first; + for (i = 0; i < 10; i++) + { + TEST_ASSERT_NOT_NULL(next); + next = CMock_Guts_MemNext(next); + } + + //there aren't any after that + TEST_ASSERT_NULL(next); +} + +void test_ThatWeCanAskForAllSortsOfSizes(void) +{ + unsigned int i; + unsigned int* first = NULL; + unsigned int* next; + unsigned int sizes[5] = {3, 1, 80, 5, 4}; + unsigned int sizes_buffered[5] = {4, 4, 80, 8, 4}; + unsigned int sum = 0; + + for (i = 0; i < 5; i++) + { + next = CMock_Guts_MemNew(sizes[i]); + TEST_ASSERT_NOT_NULL(next); + + first = CMock_Guts_MemChain(first, next); + TEST_ASSERT_NOT_NULL(first); + + sum += sizes_buffered[i] + 4; + TEST_ASSERT_EQUAL(sum, CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(CMOCK_MEM_SIZE - sum, CMock_Guts_MemBytesFree()); + } + + //show that we can't ask for too much memory + TEST_ASSERT_NULL(CMock_Guts_MemNew(12)); + TEST_ASSERT_NULL(CMock_Guts_MemNew(5)); + + //but we CAN ask for something that will still fit + next = CMock_Guts_MemNew(4); + TEST_ASSERT_NOT_NULL(next); + + first = CMock_Guts_MemChain(first, next); + TEST_ASSERT_NOT_NULL(first); + + //verify we're used up now + TEST_ASSERT_EQUAL(CMOCK_MEM_SIZE, CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(0, CMock_Guts_MemBytesFree()); + + //verify we can still walk through the elements allocated + next = first; + for (i = 0; i < 6; i++) + { + TEST_ASSERT_NOT_NULL(next); + next = CMock_Guts_MemNext(next); + } + + //there aren't any after that + TEST_ASSERT_NULL(next); +} diff --git a/test/c/TestCMockC.yml b/test/c/TestCMockC.yml new file mode 100644 index 0000000..cd76154 --- /dev/null +++ b/test/c/TestCMockC.yml @@ -0,0 +1,12 @@ +--- +:files: + - 'src/cmock.c' + - 'test/c/TestCMockC.c' + - 'test/c/TestCMockC_Runner.c' + - 'vendor/unity/src/unity.c' +:options: + - 'TEST' + - 'CMOCK_MEM_SIZE=128' + - 'CMOCK_MEM_ALIGN=2' + - 'CMOCK_MEM_INDEX_TYPE=int' + diff --git a/test/c/TestCMockCDynamic.c b/test/c/TestCMockCDynamic.c new file mode 100644 index 0000000..2845d0a --- /dev/null +++ b/test/c/TestCMockCDynamic.c @@ -0,0 +1,181 @@ +#include "unity.h" +#include "cmock.h" + +#define TEST_MEM_INDEX_SIZE (sizeof(CMOCK_MEM_INDEX_TYPE)) +#define TEST_MEM_INDEX_PAD ((sizeof(CMOCK_MEM_INDEX_TYPE) + 3) & ~3) //round up to nearest 4 byte boundary + +unsigned int StartingSize; + +void setUp(void) +{ + CMock_Guts_MemFreeAll(); + StartingSize = CMock_Guts_MemBytesFree(); + TEST_ASSERT_EQUAL(0, CMock_Guts_MemBytesUsed()); +} + +void tearDown(void) +{ +} + +void test_MemNewWillReturnNullIfGivenIllegalSizes(void) +{ + TEST_ASSERT_NULL( CMock_Guts_MemNew(0) ); + + //verify we're cleared still + TEST_ASSERT_EQUAL(0, CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(0, CMock_Guts_MemBytesFree()); +} + +void test_MemNewWillNowSupportSizesGreaterThanTheDefinesCMockSize(void) +{ + TEST_ASSERT_EQUAL(0, CMock_Guts_MemBytesFree()); + + TEST_ASSERT_NOT_NULL(CMock_Guts_MemNew(CMOCK_MEM_SIZE - TEST_MEM_INDEX_SIZE + 1) ); + + TEST_ASSERT_EQUAL(CMOCK_MEM_SIZE + TEST_MEM_INDEX_PAD, CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(CMOCK_MEM_SIZE, CMock_Guts_MemBytesFree()); +} + +void test_MemChainWillReturnNullAndDoNothingIfGivenIllegalInformation(void) +{ + unsigned int* next = CMock_Guts_MemNew(4); + TEST_ASSERT_EQUAL(4 + TEST_MEM_INDEX_PAD, CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(StartingSize - 4 - TEST_MEM_INDEX_PAD, CMock_Guts_MemBytesFree()); + + TEST_ASSERT_NULL( CMock_Guts_MemChain((void*)((unsigned int)next + CMOCK_MEM_SIZE), next) ); + TEST_ASSERT_NULL( CMock_Guts_MemChain(next, (void*)((unsigned int)next + CMOCK_MEM_SIZE)) ); + + //verify we're still the same + TEST_ASSERT_EQUAL(4 + TEST_MEM_INDEX_PAD, CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(StartingSize - 4 - TEST_MEM_INDEX_PAD, CMock_Guts_MemBytesFree()); +} + +void test_MemNextWillReturnNullIfGivenABadRoot(void) +{ + TEST_ASSERT_NULL( CMock_Guts_MemNext(NULL) ); + TEST_ASSERT_NULL( CMock_Guts_MemNext((void*)2) ); + TEST_ASSERT_NULL( CMock_Guts_MemNext((void*)0xFFFFFFFE) ); + + //verify we're cleared still + TEST_ASSERT_EQUAL(0, CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(StartingSize, CMock_Guts_MemBytesFree()); +} + +void test_ThatWeCanClaimAndChainAFewElementsTogether(void) +{ + unsigned int i; + unsigned int* first = NULL; + unsigned int* next; + unsigned int* element[4]; + + //verify we're cleared first + TEST_ASSERT_EQUAL(0, CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(StartingSize, CMock_Guts_MemBytesFree()); + + //first element + element[0] = CMock_Guts_MemNew(sizeof(unsigned int)); + TEST_ASSERT_NOT_NULL(element[0]); + first = CMock_Guts_MemChain(first, element[0]); + TEST_ASSERT_EQUAL(element[0], first); + *element[0] = 0; + + //verify we're using the right amount of memory + TEST_ASSERT_EQUAL(1 * (TEST_MEM_INDEX_PAD + 4), CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(StartingSize - 1 * (TEST_MEM_INDEX_PAD + 4), CMock_Guts_MemBytesFree()); + + //second element + element[1] = CMock_Guts_MemNew(sizeof(unsigned int)); + TEST_ASSERT_NOT_NULL(element[1]); + TEST_ASSERT_NOT_EQUAL(element[0], element[1]); + TEST_ASSERT_EQUAL(first, CMock_Guts_MemChain(first, element[1])); + *element[1] = 1; + + //verify we're using the right amount of memory + TEST_ASSERT_EQUAL(2 * (TEST_MEM_INDEX_PAD + 4), CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(StartingSize - 2 * (TEST_MEM_INDEX_PAD + 4), CMock_Guts_MemBytesFree()); + + //third element + element[2] = CMock_Guts_MemNew(sizeof(unsigned int)); + TEST_ASSERT_NOT_NULL(element[2]); + TEST_ASSERT_NOT_EQUAL(element[0], element[2]); + TEST_ASSERT_NOT_EQUAL(element[1], element[2]); + TEST_ASSERT_EQUAL(first, CMock_Guts_MemChain(first, element[2])); + *element[2] = 2; + + //verify we're using the right amount of memory + TEST_ASSERT_EQUAL(3 * (TEST_MEM_INDEX_PAD + 4), CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(StartingSize - 3 * (TEST_MEM_INDEX_PAD + 4), CMock_Guts_MemBytesFree()); + + //fourth element + element[3] = CMock_Guts_MemNew(sizeof(unsigned int)); + TEST_ASSERT_NOT_NULL(element[3]); + TEST_ASSERT_NOT_EQUAL(element[0], element[3]); + TEST_ASSERT_NOT_EQUAL(element[1], element[3]); + TEST_ASSERT_NOT_EQUAL(element[2], element[3]); + TEST_ASSERT_EQUAL(first, CMock_Guts_MemChain(first, element[3])); + *element[3] = 3; + + //verify we're using the right amount of memory + TEST_ASSERT_EQUAL(4 * (TEST_MEM_INDEX_PAD + 4), CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(StartingSize - 4 * (TEST_MEM_INDEX_PAD + 4), CMock_Guts_MemBytesFree()); + + //traverse list + next = first; + for (i = 0; i < 4; i++) + { + TEST_ASSERT_EQUAL(element[i], next); + TEST_ASSERT_EQUAL(i, *next); + next = CMock_Guts_MemNext(next); + } + + //verify we get a null at the end of the list + TEST_ASSERT_NULL(next); + + //verify we're using the right amount of memory + TEST_ASSERT_EQUAL(4 * (TEST_MEM_INDEX_PAD + 4), CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(StartingSize - 4 * (TEST_MEM_INDEX_PAD + 4), CMock_Guts_MemBytesFree()); + + //Free it all + CMock_Guts_MemFreeAll(); + + //verify we're cleared + TEST_ASSERT_EQUAL(0, CMock_Guts_MemBytesUsed()); + TEST_ASSERT_EQUAL(StartingSize, CMock_Guts_MemBytesFree()); +} + +void test_ThatWeCanAskForAllSortsOfSizes(void) +{ + unsigned int i; + unsigned int* first = NULL; + unsigned int* next; + unsigned int sizes[10] = {3, 1, 80, 5, 4, 31, 7, 911, 2, 80}; + unsigned int sizes_buffered[10] = {8, 4, 84, 8, 8, 36, 12, 916, 4, 84}; //includes counter + unsigned int sum = 0; + unsigned int cap; + + for (i = 0; i < 10; i++) + { + next = CMock_Guts_MemNew(sizes[i]); + TEST_ASSERT_NOT_NULL(next); + + first = CMock_Guts_MemChain(first, next); + TEST_ASSERT_NOT_NULL(first); + + sum += sizes_buffered[i]; + cap = (StartingSize > (sum + CMOCK_MEM_SIZE)) ? StartingSize : (sum + CMOCK_MEM_SIZE); + TEST_ASSERT_EQUAL(sum, CMock_Guts_MemBytesUsed()); + TEST_ASSERT(0 <= CMock_Guts_MemBytesFree()); + TEST_ASSERT(cap >= CMock_Guts_MemBytesFree()); + } + + //verify we can still walk through the elements allocated + next = first; + for (i = 0; i < 10; i++) + { + TEST_ASSERT_NOT_NULL(next); + next = CMock_Guts_MemNext(next); + } + + //there aren't any after that + TEST_ASSERT_NULL(next); +} \ No newline at end of file diff --git a/test/c/TestCMockCDynamic.yml b/test/c/TestCMockCDynamic.yml new file mode 100644 index 0000000..5ac66d8 --- /dev/null +++ b/test/c/TestCMockCDynamic.yml @@ -0,0 +1,12 @@ +--- +:files: + - 'src/cmock.c' + - 'test/c/TestCMockCDynamic.c' + - 'test/c/TestCMockCDynamic_Runner.c' + - 'vendor/unity/src/unity.c' +:options: + - 'TEST' + - 'CMOCK_MEM_DYNAMIC' + - 'CMOCK_MEM_SIZE=64' + - 'CMOCK_MEM_ALIGN=2' + - 'CMOCK_MEM_INDEX_TYPE=short' diff --git a/test/c/TestCMockCDynamic_Runner.c b/test/c/TestCMockCDynamic_Runner.c new file mode 100644 index 0000000..cd04b8c --- /dev/null +++ b/test/c/TestCMockCDynamic_Runner.c @@ -0,0 +1,41 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ +#include "unity.h" + +extern void setUp(void); +extern void tearDown(void); + +extern void test_MemNewWillReturnNullIfGivenIllegalSizes(void); +extern void test_MemNewWillNowSupportSizesGreaterThanTheDefinesCMockSize(void); +extern void test_MemChainWillReturnNullAndDoNothingIfGivenIllegalInformation(void); +extern void test_MemNextWillReturnNullIfGivenABadRoot(void); +extern void test_ThatWeCanClaimAndChainAFewElementsTogether(void); +extern void test_ThatWeCanAskForAllSortsOfSizes(void); + +static void runTest(UnityTestFunction test) +{ + if (TEST_PROTECT()) + { + setUp(); + test(); + } + tearDown(); +} + + +int main(void) +{ + Unity.TestFile = __FILE__; + UnityBegin(); + + // RUN_TEST calls runTest + RUN_TEST(test_MemNewWillReturnNullIfGivenIllegalSizes); + RUN_TEST(test_MemNewWillNowSupportSizesGreaterThanTheDefinesCMockSize); + RUN_TEST(test_MemChainWillReturnNullAndDoNothingIfGivenIllegalInformation); + RUN_TEST(test_MemNextWillReturnNullIfGivenABadRoot); + RUN_TEST(test_ThatWeCanClaimAndChainAFewElementsTogether); + RUN_TEST(test_ThatWeCanAskForAllSortsOfSizes); + + UnityEnd(); + + return 0; +} diff --git a/test/c/TestCMockC_Runner.c b/test/c/TestCMockC_Runner.c new file mode 100644 index 0000000..5bdc5cb --- /dev/null +++ b/test/c/TestCMockC_Runner.c @@ -0,0 +1,43 @@ +/* AUTOGENERATED FILE. DO NOT EDIT. */ +#include "unity.h" + +extern void setUp(void); +extern void tearDown(void); + +extern void test_MemNewWillReturnNullIfGivenIllegalSizes(void); +extern void test_MemChainWillReturnNullAndDoNothingIfGivenIllegalInformation(void); +extern void test_MemNextWillReturnNullIfGivenABadRoot(void); +extern void test_ThatWeCanClaimAndChainAFewElementsTogether(void); +extern void test_ThatCMockStopsReturningMoreDataWhenItRunsOutOfMemory(void); +extern void test_ThatCMockStopsReturningMoreDataWhenAskForMoreThanItHasLeftEvenIfNotAtExactEnd(void); +extern void test_ThatWeCanAskForAllSortsOfSizes(void); + +static void runTest(UnityTestFunction test) +{ + if (TEST_PROTECT()) + { + setUp(); + test(); + } + tearDown(); +} + + +int main(void) +{ + Unity.TestFile = __FILE__; + UnityBegin(); + + // RUN_TEST calls runTest + RUN_TEST(test_MemNewWillReturnNullIfGivenIllegalSizes); + RUN_TEST(test_MemChainWillReturnNullAndDoNothingIfGivenIllegalInformation); + RUN_TEST(test_MemNextWillReturnNullIfGivenABadRoot); + RUN_TEST(test_ThatWeCanClaimAndChainAFewElementsTogether); + RUN_TEST(test_ThatCMockStopsReturningMoreDataWhenItRunsOutOfMemory); + RUN_TEST(test_ThatCMockStopsReturningMoreDataWhenAskForMoreThanItHasLeftEvenIfNotAtExactEnd); + RUN_TEST(test_ThatWeCanAskForAllSortsOfSizes); + + UnityEnd(); + + return 0; +} diff --git a/test/system/systest_generator.rb b/test/system/systest_generator.rb index feb295c..2c4b686 100644 --- a/test/system/systest_generator.rb +++ b/test/system/systest_generator.rb @@ -8,6 +8,7 @@ CASES_PATH = SYS_TEST_GEN_ROOT + 'cases/' TYPES_H = 'types.h' UNITY_H = 'unity.h' +CMOCK_H = 'cmock.h' UNITY_HELPER_H = 'unity_helper.h' UNITY_HELPER_C = 'unity_helper.c' MOCKABLE_H = 'mockable.h' @@ -97,7 +98,7 @@ class SystemTestGenerator tests = yaml_hash[:systest][:tests] return if tests.nil? - includes = [UNITY_H] + includes = [UNITY_H, CMOCK_H] includes << (namix + UNITY_HELPER_H) if not yaml_hash[:systest][:unity_helper].nil? includes << [MOCK_PREFIX + namix + MOCKABLE_H] includes << [name + H_EXTENSION] diff --git a/test/system/test_compilation/const.h b/test/system/test_compilation/const.h new file mode 100644 index 0000000..ab56018 --- /dev/null +++ b/test/system/test_compilation/const.h @@ -0,0 +1,10 @@ + +struct _DUMMY_T { unsigned int a; float b; }; + +void const_variants1( const char* a, int const, unsigned short const * c ); + +void const_variants2( + struct _DUMMY_T const * const param1, + const unsigned long int const * const param2, + const struct _DUMMY_T const * param3 ); + diff --git a/test/system/test_compilation/parsing.h b/test/system/test_compilation/parsing.h index dc9f4a4..8d5becc 100644 --- a/test/system/test_compilation/parsing.h +++ b/test/system/test_compilation/parsing.h @@ -12,9 +12,6 @@ typedef struct _POINT_T // not ANSI C but it has been done and will break cmock if not handled typedef void VOID_TYPE_CRAZINESS; -struct _DUMMY_T { unsigned int a; float b; }; - - /* fun parsing & mock generation cases */ void var_args1(int a, ...); @@ -42,12 +39,4 @@ unsigned int ** ptr_ptr_return4(unsigned int ** a); extern unsigned long int incredible_descriptors(register const unsigned short a); -void const_variants1( const char* a, int const, unsigned short const * c ); - -// crazy const magic fairy dust -void const_variants2( - struct _DUMMY_T const * const param1, - const unsigned long int const * const param2, - const struct _DUMMY_T const * param3 ); - int32_t example_c99_type(int32_t param1); diff --git a/test/system/test_interactions/all_plugins_coexist.yml b/test/system/test_interactions/all_plugins_coexist.yml index d4e80c6..6b13115 100644 --- a/test/system/test_interactions/all_plugins_coexist.yml +++ b/test/system/test_interactions/all_plugins_coexist.yml @@ -5,6 +5,7 @@ - :array - :cexception - :ignore + - :callback :systest: :types: | @@ -18,8 +19,8 @@ void foo(POINT_T* a); POINT_T* bar(void); void fooa(POINT_T a[]); - void foos(const char const * a); - const char const * bars(void); + void foos(const char * a); + const char * bars(void); void no_pointers(int a, char* b); int mixed(int a, int* b, int c); @@ -281,7 +282,7 @@ } - :pass: TRUE - :should: 'that we can properly ignore one of the function but the other will work properly' + :should: 'that we can properly ignore last function but the other will work properly' :code: | test() { @@ -292,4 +293,15 @@ TEST_ASSERT_EQUAL(13, function_d()); } + - :pass: TRUE + :should: 'that we can properly ignore first function but the other will work properly' + :code: | + test() + { + mixed_IgnoreAndReturn(13); + no_pointers_Expect(1, "silly"); + + TEST_ASSERT_EQUAL(13, function_d()); + } + ... diff --git a/test/system/test_interactions/array_and_pointer_handling.yml b/test/system/test_interactions/array_and_pointer_handling.yml index ccad016..4faac9b 100644 --- a/test/system/test_interactions/array_and_pointer_handling.yml +++ b/test/system/test_interactions/array_and_pointer_handling.yml @@ -15,8 +15,8 @@ void foo(POINT_T* a); POINT_T* bar(void); void fooa(POINT_T a[]); - void foos(const char const * a); - const char const * bars(void); + void foos(const char * a); + const char * bars(void); void no_pointers(int a, char* b); int mixed(int a, int* b, int c); diff --git a/test/system/test_interactions/enforce_strict_ordering.yml b/test/system/test_interactions/enforce_strict_ordering.yml index e80a7ab..c4ec640 100644 --- a/test/system/test_interactions/enforce_strict_ordering.yml +++ b/test/system/test_interactions/enforce_strict_ordering.yml @@ -2,8 +2,8 @@ :cmock: :enforce_strict_ordering: 1 :plugins: - - ignore - - cexception + - :ignore + - :cexception :systest: :types: | @@ -100,7 +100,7 @@ - :pass: FALSE :should: 'fail because bar() is called twice but is expected once' - :verify_error: 'called unexpected number of times' + :verify_error: 'called less times than expected' :code: | test() { diff --git a/test/system/test_interactions/expect_and_throw.yml b/test/system/test_interactions/expect_and_throw.yml index 997e9f3..35fe38a 100644 --- a/test/system/test_interactions/expect_and_throw.yml +++ b/test/system/test_interactions/expect_and_throw.yml @@ -1,7 +1,7 @@ --- :cmock: :plugins: - - cexception + - :cexception :systest: :types: | diff --git a/test/system/test_interactions/fancy_pointer_handling.yml b/test/system/test_interactions/fancy_pointer_handling.yml index b91fe41..32adabe 100644 --- a/test/system/test_interactions/fancy_pointer_handling.yml +++ b/test/system/test_interactions/fancy_pointer_handling.yml @@ -14,8 +14,8 @@ void foo(POINT_T* a); POINT_T* bar(void); void fooa(POINT_T a[]); - void foos(const char const * a); - const char const * bars(void); + void foos(const char *a); + const char* bars(void); :source: :header: | diff --git a/test/system/test_interactions/nonstandard_parsed_stuff_1.yml b/test/system/test_interactions/nonstandard_parsed_stuff_1.yml new file mode 100644 index 0000000..01538ea --- /dev/null +++ b/test/system/test_interactions/nonstandard_parsed_stuff_1.yml @@ -0,0 +1,91 @@ +--- +#The purpose of this test is to play with things like "const char const *" which isn't supported by some compilers +:cmock: + :enforce_strict_ordering: 1 + :plugins: + - :array + - :cexception + - :ignore + +:systest: + :types: | + typedef struct _POINT_T { + int x; + int y; + } POINT_T; + + :mockable: | + #include "CException.h" + void foos(const char const * a); + const char const * bars(void); + + :source: + :header: | + #include "CException.h" + void function_a(void); + void function_b(void); + void function_c(void); + int function_d(void); + + :code: | + void function_c(void) { + CEXCEPTION_T e; + Try { + foos(bars()); + } Catch(e) { foos("err"); } + } + + :tests: + :common: | + #include "CException.h" + void setUp(void) {} + void tearDown(void) {} + + :units: + - :pass: TRUE + :should: 'handle standard c string as null terminated on not do crappy memory compares of a byte, passing' + :code: | + test() + { + bars_ExpectAndReturn("This is a\0 silly string"); + foos_Expect("This is a\0 wacky string"); + + function_c(); + } + + - :pass: FALSE + :should: 'handle standard c string as null terminated on not do crappy memory compares of a byte, finding failures' + :code: | + test() + { + bars_ExpectAndReturn("This is a silly string"); + foos_Expect("This is a wacky string"); + + function_c(); + } + + - :pass: TRUE + :should: 'handle an exception being caught' + :code: | + test() + { + bars_ExpectAndReturn("This is a\0 silly string"); + foos_ExpectAndThrow("This is a\0 wacky string", 55); + foos_Expect("err"); + + function_c(); + } + + - :pass: FALSE + :should: 'handle an exception being caught but still catch following errors' + :code: | + test() + { + bars_ExpectAndReturn("This is a\0 silly string"); + foos_ExpectAndThrow("This is a\0 wacky string", 55); + foos_Expect("wrong error"); + + function_c(); + } + +... diff --git a/test/system/test_interactions/stubs_with_callbacks.yml b/test/system/test_interactions/stubs_with_callbacks.yml index 1e0c6d4..8ba671e 100644 --- a/test/system/test_interactions/stubs_with_callbacks.yml +++ b/test/system/test_interactions/stubs_with_callbacks.yml @@ -108,6 +108,18 @@ bar_StubWithCallback((CMOCK_bar_CALLBACK)FooAndBarHelper); TEST_ASSERT_EQUAL(12, function_b()); } + + - :pass: TRUE + :should: 'successfully exercise using some basic callbacks even if there were expects' + :code: | + test() + { + custom_type exp = 500; + foo_ExpectAndReturn(&exp, 10); + foo_StubWithCallback((CMOCK_foo_CALLBACK)FooAndBarHelper); + bar_StubWithCallback((CMOCK_bar_CALLBACK)FooAndBarHelper); + TEST_ASSERT_EQUAL(12, function_b()); + } - :pass: FALSE :should: 'successfully exercise using some basic callbacks and notice failures' diff --git a/test/test_helper.rb b/test/test_helper.rb index 82b508d..d760f40 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -14,4 +14,24 @@ require 'hardmock' class Test::Unit::TestCase extend Behaviors + #these are helpful test structures which can be used during tests + + 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 => "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 => "const MY_TYPE", :name => 'MyMyType', :ptr? => false, :const? => true}, + :mytype_ptr => {:type => "MY_TYPE*", :name => 'MyMyTypePtr', :ptr? => true, :const? => false}, + :string => {:type => "const char*", :name => 'MyStr', :ptr? => false, :const? => true}, + } + end end diff --git a/test/unit/cmock_generator_main_test.rb b/test/unit/cmock_generator_main_test.rb index 88f03d0..21f2f3e 100644 --- a/test/unit/cmock_generator_main_test.rb +++ b/test/unit/cmock_generator_main_test.rb @@ -125,6 +125,7 @@ class CMockGeneratorTest < Test::Unit::TestCase "#include \n", "#include \n", "#include \"unity.h\"\n", + "#include \"cmock.h\"\n", "#include \"PluginRequiredHeader.h\"\n", "#include \"ConfigRequiredHeader1.h\"\n", "#include \"ConfigRequiredHeader2.h\"\n", @@ -144,36 +145,42 @@ class CMockGeneratorTest < Test::Unit::TestCase expected = [ "static struct MockPoutPoutFishInstance\n", "{\n", " unsigned char placeHolder;\n", - " unsigned char allocFailure;\n", "", "} Mock;\n\n" - ] + ].join @cmock_generator.create_instance_structure(output, functions) - assert_equal(expected, output.flatten) + assert_equal(expected, output.join) end should "create the instance structure where it is needed when functions required" do output = [] - functions = [ { :name => "First", :args => "int Candy", :return_type => "int" }, - { :name => "Second", :args => "bool Smarty", :return_type => "char" } + functions = [ { :name => "First", :args => "int Candy", :return => test_return[:int] }, + { :name => "Second", :args => "bool Smarty", :return => test_return[:string] } ] - expected = [ "static struct MockPoutPoutFishInstance\n", - "{\n", - " unsigned char allocFailure;\n", - " Uno_First(int Candy, int)" + - " Dos_First(int Candy, int)" + - " Uno_Second(bool Smarty, char)" + - " Dos_Second(bool Smarty, char)", + expected = [ "typedef struct _CMOCK_First_CALL_INSTANCE\n{\n", + " b1 b2", + "\n} CMOCK_First_CALL_INSTANCE;\n\n", + "typedef struct _CMOCK_Second_CALL_INSTANCE\n{\n", + " char PlaceHolder;\n", + "\n} CMOCK_Second_CALL_INSTANCE;\n\n", + "static struct MockPoutPoutFishInstance\n{\n", + " d1", + " CMOCK_First_CALL_INSTANCE* First_CallInstance;\n", + " e1 e2 e3", + " CMOCK_Second_CALL_INSTANCE* Second_CallInstance;\n", "} Mock;\n\n" - ] - @plugins.expect.run(:instance_structure, functions[0]).returns([" Uno_First(int Candy, int)"," Dos_First(int Candy, int)"]) - @plugins.expect.run(:instance_structure, functions[1]).returns([" Uno_Second(bool Smarty, char)"," Dos_Second(bool Smarty, char)"]) + ].join + @plugins.expect.run(:instance_typedefs, functions[0]).returns([" b1"," b2"]) + @plugins.expect.run(:instance_typedefs, functions[1]).returns([]) + + @plugins.expect.run(:instance_structure, functions[0]).returns([" d1"]) + @plugins.expect.run(:instance_structure, functions[1]).returns([" e1"," e2"," e3"]) @cmock_generator.create_instance_structure(output, functions) - assert_equal(expected, output.flatten) + assert_equal(expected, output.join) end should "create extern declarations for source file" do @@ -202,33 +209,30 @@ class CMockGeneratorTest < Test::Unit::TestCase should "create mock verify functions in source file when no functions specified" do functions = [] output = [] - expected = [ "void MockPoutPoutFish_Verify(void)\n{\n", - " TEST_ASSERT_EQUAL_MESSAGE(0, Mock.allocFailure, \"Unable to allocate memory for mock\");\n", - "", - "}\n\n" - ] + expected = "void MockPoutPoutFish_Verify(void)\n{\n}\n\n" @cmock_generator.create_mock_verify_function(output, functions) - assert_equal(expected, output.flatten) + assert_equal(expected, output.join) end should "create mock verify functions in source file when extra functions specified" do - functions = [ { :name => "First", :args => "int Candy", :return_type => "int" }, - { :name => "Second", :args => "bool Smarty", :return_type => "char" } + functions = [ { :name => "First", :args => "int Candy", :return => test_return[:int] }, + { :name => "Second", :args => "bool Smarty", :return => test_return[:string] } ] output = [] expected = [ "void MockPoutPoutFish_Verify(void)\n{\n", - " TEST_ASSERT_EQUAL_MESSAGE(0, Mock.allocFailure, \"Unable to allocate memory for mock\");\n", " Uno_First" + " Dos_First" + " Uno_Second" + " Dos_Second", + " TEST_ASSERT_NULL_MESSAGE(GlobalOrderError, GlobalOrderError);\n", "}\n\n" ] @plugins.expect.run(:mock_verify, functions[0]).returns([" Uno_First"," Dos_First"]) @plugins.expect.run(:mock_verify, functions[1]).returns([" Uno_Second"," Dos_Second"]) + @cmock_generator.ordered = true @cmock_generator.create_mock_verify_function(output, functions) assert_equal(expected, output.flatten) @@ -240,58 +244,35 @@ class CMockGeneratorTest < Test::Unit::TestCase " MockPoutPoutFish_Destroy();\n", "}\n\n" ] - + @cmock_generator.create_mock_init_function(output) - assert_equal(expected, output) + assert_equal(expected.join, output.join) end - should "create mock destroy functions in source file when no functions specified" do + should "create mock destroy functions in source file" do functions = [] output = [] expected = [ "void MockPoutPoutFish_Destroy(void)\n{\n", - "", + " CMock_Guts_MemFreeAll();\n", " memset(&Mock, 0, sizeof(Mock));\n", "}\n\n" ] - + @cmock_generator.create_mock_destroy_function(output, functions) - - assert_equal(expected, output.flatten) + + assert_equal(expected.join, output.join) end - should "create mock destroy functions in source file when extra functions specified" do - functions = [ { :name => "First", :args => "int Candy", :return_type => "int" }, - { :name => "Second", :args => "bool Smarty", :return_type => "char" } + should "create mock destroy functions in source file when specified with strict ordering" do + functions = [ { :name => "First", :args => "int Candy", :return => test_return[:int] }, + { :name => "Second", :args => "bool Smarty", :return => test_return[:string] } ] output = [] expected = [ "void MockPoutPoutFish_Destroy(void)\n{\n", - " Uno_First(int Candy, int)" + - " Dos_First(int Candy, int)" + - " Uno_Second(bool Smarty, char)" + - " Dos_Second(bool Smarty, char)", - " memset(&Mock, 0, sizeof(Mock));\n", - "}\n\n" - ] - @plugins.expect.run(:mock_destroy, functions[0]).returns([" Uno_First(int Candy, int)"," Dos_First(int Candy, int)"]) - @plugins.expect.run(:mock_destroy, functions[1]).returns([" Uno_Second(bool Smarty, char)"," Dos_Second(bool Smarty, char)"]) - - @cmock_generator.create_mock_destroy_function(output, functions) - - assert_equal(expected, output.flatten) - end - - should "create mock destroy functions in source file when extra functions specified with strict ordering" do - functions = [ { :name => "First", :args => "int Candy", :return_type => "int" }, - { :name => "Second", :args => "bool Smarty", :return_type => "char" } - ] - output = [] - expected = [ "void MockPoutPoutFish_Destroy(void)\n{\n", - " Uno_First(int Candy, int)" + - " Dos_First(int Candy, int)" + - " Uno_Second(bool Smarty, char)" + - " Dos_Second(bool Smarty, char)", + " CMock_Guts_MemFreeAll();\n", " memset(&Mock, 0, sizeof(Mock));\n", + " uno", " GlobalExpectCount = 0;\n", " GlobalVerifyOrder = 0;\n", " if (GlobalOrderError)\n", @@ -301,17 +282,17 @@ class CMockGeneratorTest < Test::Unit::TestCase " }\n", "}\n\n" ] - @plugins.expect.run(:mock_destroy, functions[0]).returns([" Uno_First(int Candy, int)"," Dos_First(int Candy, int)"]) - @plugins.expect.run(:mock_destroy, functions[1]).returns([" Uno_Second(bool Smarty, char)"," Dos_Second(bool Smarty, char)"]) + @plugins.expect.run(:mock_destroy, functions[0]).returns([]) + @plugins.expect.run(:mock_destroy, functions[1]).returns([" uno"]) @cmock_generator_strict.create_mock_destroy_function(output, functions) - - assert_equal(expected, output.flatten) + + assert_equal(expected.join, output.join) end should "create mock implementation functions in source file" do function = { :modifier => "static", - :return_type => "bool", + :return => test_return[:int], :args_string => "uint32 sandwiches, const char* named", :args => ["uint32 sandwiches", "const char* named"], :var_arg => nil, @@ -319,25 +300,28 @@ class CMockGeneratorTest < Test::Unit::TestCase :attributes => "__inline" } output = [] - expected = [ "__inline ", - "static bool SupaFunction(uint32 sandwiches, const char* named)\n", + expected = [ "__inline static int SupaFunction(uint32 sandwiches, const char* named)\n", "{\n", - " MockSupaFunctionUno(uint32 sandwiches, const char* named)", - " MockSupaFunctionDos(uint32 sandwiches, const char* named)", - " UtilsSupaFunction.bool", + " CMOCK_SupaFunction_CALL_INSTANCE* cmock_call_instance = Mock.SupaFunction_CallInstance;\n", + " Mock.SupaFunction_CallInstance = (CMOCK_SupaFunction_CALL_INSTANCE*)CMock_Guts_MemNext(Mock.SupaFunction_CallInstance);\n", + " uno", + " TEST_ASSERT_NOT_NULL_MESSAGE(cmock_call_instance, \"Function 'SupaFunction' called more times than expected\");\n", + " dos", + " tres", + " return cmock_call_instance->ReturnVal;\n", "}\n\n" ] - @plugins.expect.run(:mock_implementation, function).returns([" MockSupaFunctionUno(uint32 sandwiches, const char* named)"," MockSupaFunctionDos(uint32 sandwiches, const char* named)"]) - @utils.expect.code_handle_return_value(function).returns([" UtilsSupaFunction.bool"]) + @plugins.expect.run(:mock_implementation_precheck, function).returns([" uno"]) + @plugins.expect.run(:mock_implementation, function).returns([" dos"," tres"]) @cmock_generator.create_mock_implementation(output, function) - assert_equal(expected, output.flatten) + assert_equal(expected.join, output.join) end should "create mock implementation functions in source file with different options" do function = { :modifier => "", - :return_type => "int", + :return => test_return[:int], :args_string => "uint32 sandwiches", :args => ["uint32 sandwiches"], :var_arg => "corn ...", @@ -347,16 +331,20 @@ class CMockGeneratorTest < Test::Unit::TestCase output = [] expected = [ "int SupaFunction(uint32 sandwiches, corn ...)\n", "{\n", - " MockSupaFunctionUno(uint32 sandwiches)", - " MockSupaFunctionDos(uint32 sandwiches)", - " UtilsSupaFunction.int", + " CMOCK_SupaFunction_CALL_INSTANCE* cmock_call_instance = Mock.SupaFunction_CallInstance;\n", + " Mock.SupaFunction_CallInstance = (CMOCK_SupaFunction_CALL_INSTANCE*)CMock_Guts_MemNext(Mock.SupaFunction_CallInstance);\n", + " uno", + " TEST_ASSERT_NOT_NULL_MESSAGE(cmock_call_instance, \"Function 'SupaFunction' called more times than expected\");\n", + " dos", + " tres", + " return cmock_call_instance->ReturnVal;\n", "}\n\n" ] - @plugins.expect.run(:mock_implementation, function).returns([" MockSupaFunctionUno(uint32 sandwiches)"," MockSupaFunctionDos(uint32 sandwiches)"]) - @utils.expect.code_handle_return_value(function).returns([" UtilsSupaFunction.int"]) + @plugins.expect.run(:mock_implementation_precheck, function).returns([" uno"]) + @plugins.expect.run(:mock_implementation, function).returns([" dos"," tres"]) @cmock_generator.create_mock_implementation(output, function) - assert_equal(expected, output.flatten) + assert_equal(expected.join, output.join) end end diff --git a/test/unit/cmock_generator_plugin_array_test.rb b/test/unit/cmock_generator_plugin_array_test.rb index bbe3518..fccd208 100644 --- a/test/unit/cmock_generator_plugin_array_test.rb +++ b/test/unit/cmock_generator_plugin_array_test.rb @@ -27,25 +27,21 @@ class CMockGeneratorPluginArrayTest < Test::Unit::TestCase assert(!@cmock_generator_plugin_array.respond_to?(:include_files)) end - should "not add to control structure for functions of style 'int* func(void)'" do - function = {:name => "Oak", :args => [], :return_type => "int*"} - returned = @cmock_generator_plugin_array.instance_structure(function) + should "not add to typedef structure for functions of style 'int* func(void)'" do + function = {:name => "Oak", :args => [], :return => test_return[:int_ptr]} + returned = @cmock_generator_plugin_array.instance_typedefs(function) assert_equal("", returned) end - should "add to control structure mock needs of functions of style 'void func(int chicken, int* pork)'" do - function = {:name => "Cedar", :args => [{ :name => "chicken", :type => "int", :ptr? => false}, { :name => "pork", :type => "int*", :ptr? => true}], :return_type => "void"} - expected = ["\n", - " int* Cedar_Expected_pork_Depth;\n", - " int* Cedar_Expected_pork_Depth_Head;\n", - " int* Cedar_Expected_pork_Depth_Tail;\n" - ].join - returned = @cmock_generator_plugin_array.instance_structure(function) + should "add to tyepdef structure mock needs of functions of style 'void func(int chicken, int* pork)'" do + function = {:name => "Cedar", :args => [{ :name => "chicken", :type => "int", :ptr? => false}, { :name => "pork", :type => "int*", :ptr? => true}], :return => test_return[:void]} + expected = " int Expected_pork_Depth;\n" + returned = @cmock_generator_plugin_array.instance_typedefs(function) assert_equal(expected, returned) end should "not add an additional mock interface for functions not containing pointers" do - function = {:name => "Maple", :args_string => "int blah", :return_type => "char*", :contains_ptr? => false} + function = {:name => "Maple", :args_string => "int blah", :return => test_return[:string], :contains_ptr? => false} returned = @cmock_generator_plugin_array.mock_function_declarations(function) assert_nil(returned) end @@ -56,8 +52,7 @@ class CMockGeneratorPluginArrayTest < Test::Unit::TestCase :name => "tofu", :ptr? => true, }], - :return_type => "void", - :return_string => "void", + :return => test_return[:void], :contains_ptr? => true } expected = "void #{function[:name]}_ExpectWithArray(int* tofu, int tofu_Depth);\n" @@ -71,8 +66,7 @@ class CMockGeneratorPluginArrayTest < Test::Unit::TestCase :name => "tofu", :ptr? => true, }], - :return_type => "const char*", - :return_string => "const char* cmock_to_return", + :return => test_return[:string], :contains_ptr? => true } expected = "void #{function[:name]}_ExpectWithArrayAndReturn(int* tofu, int tofu_Depth, const char* cmock_to_return);\n" @@ -85,58 +79,28 @@ class CMockGeneratorPluginArrayTest < Test::Unit::TestCase end should "not have a mock interfaces for functions of style 'int* func(void)'" do - function = {:name => "Pear", :args => [], :args_string => "void", :return_type => "int*"} + function = {:name => "Pear", :args => [], :args_string => "void", :return => test_return[:int_ptr]} returned = @cmock_generator_plugin_array.mock_interfaces(function) assert_nil(returned) end - should "add mock interfaces for functions of style 'int func(int* pescado, int pes)'" do + should "add mock interfaces for functions of style 'int* func(int* pescado, int pes)'" do function = {:name => "Lemon", :args => [{ :type => "int*", :name => "pescado", :ptr? => true}, { :type => "int", :name => "pes", :ptr? => false}], :args_string => "int* pescado, int pes", - :return_type => "int", - :return_string => "int cmock_to_return", + :return => test_return[:int_ptr], :contains_ptr? => true } - @utils.expect.code_add_an_arg_expectation(function, function[:args][0], "pescado_Depth").returns("mock_retval_2") - @utils.expect.code_add_an_arg_expectation(function, function[:args][1], "1").returns("mock_retval_3") @utils.expect.code_add_base_expectation("Lemon").returns("mock_retval_0") - @utils.expect.code_insert_item_into_expect_array(function[:return_type], "Mock.Lemon_Return", 'cmock_to_return').returns("mock_retval_1") - expected = ["void ExpectParametersWithArray_Lemon(int* pescado, int pescado_Depth, int pes)\n", - "{\n", - "mock_retval_2", - "mock_retval_3", - "}\n\n", - "void Lemon_ExpectWithArrayAndReturn(int* pescado, int pescado_Depth, int pes, int cmock_to_return)\n", + expected = ["void Lemon_ExpectWithArrayAndReturn(int* pescado, int pescado_Depth, int pes, int* cmock_to_return)\n", "{\n", "mock_retval_0", - " ExpectParametersWithArray_Lemon(pescado, pescado_Depth, pes);\n", - "mock_retval_1", - " Mock.Lemon_Return = Mock.Lemon_Return_Head;\n", - " Mock.Lemon_Return += Mock.Lemon_CallCount;\n", + " CMockExpectParameters_Lemon(cmock_call_instance, pescado, pescado_Depth, pes);\n", + " cmock_call_instance->ReturnVal = cmock_to_return;\n", "}\n\n" ].join returned = @cmock_generator_plugin_array.mock_interfaces(function).join assert_equal(expected, returned) end - should "only add destruction of Depth attributes" do - function = {:name => "Coconut", - :args => [ { :type => "uint32*", :name => "grease", :ptr? => true}, - { :type => "uint16", :name => "grime", :ptr? => false}], - :return_type => "int", - :contains_ptr? => true } - expected = [ %q[ - if (Mock.Coconut_Expected_grease_Depth_Head) - { - free(Mock.Coconut_Expected_grease_Depth_Head); - } - Mock.Coconut_Expected_grease_Depth=NULL; - Mock.Coconut_Expected_grease_Depth_Head=NULL; - Mock.Coconut_Expected_grease_Depth_Tail=NULL; -] ] - returned = @cmock_generator_plugin_array.mock_destroy(function) - assert_equal(expected, returned) - end - end diff --git a/test/unit/cmock_generator_plugin_callback_test.rb b/test/unit/cmock_generator_plugin_callback_test.rb index 40b7dd0..a0a06f8 100644 --- a/test/unit/cmock_generator_plugin_callback_test.rb +++ b/test/unit/cmock_generator_plugin_callback_test.rb @@ -21,64 +21,58 @@ class CMockGeneratorPluginCallbackTest < Test::Unit::TestCase assert(!@cmock_generator_plugin_callback.respond_to?(:include_files)) end - should "add to control structure" do - function = {:name => "Oak", :args => [:type => "int*", :name => "blah", :ptr? => true], :return_type => "int*"} - expected = " CMOCK_Oak_CALLBACK Oak_CallbackFunctionPointer;\n" + should "add to instance structure" do + function = {:name => "Oak", :args => [:type => "int*", :name => "blah", :ptr? => true], :return => test_return[:int_ptr]} + expected = " CMOCK_Oak_CALLBACK Oak_CallbackFunctionPointer;\n" + + " int Oak_CallbackCalls;\n" returned = @cmock_generator_plugin_callback.instance_structure(function) assert_equal(expected, returned) end should "add mock function declaration for function without arguments" do - function = {:name => "Maple", :args_string => "void", :return_type => "void"} - expected = [ "\n", - "typedef void (* CMOCK_Maple_CALLBACK)(int NumCalls);\n", + function = {:name => "Maple", :args_string => "void", :return => test_return[:void]} + expected = [ "typedef void (* CMOCK_Maple_CALLBACK)(int cmock_num_calls);\n", "void Maple_StubWithCallback(CMOCK_Maple_CALLBACK Callback);\n" ].join returned = @cmock_generator_plugin_callback.mock_function_declarations(function) assert_equal(expected, returned) end should "add mock function declaration for function with arguments" do - function = {:name => "Maple", :args_string => "int* tofu", :return_type => "void"} - expected = [ "\n", - "typedef void (* CMOCK_Maple_CALLBACK)(int* tofu, int NumCalls);\n", + function = {:name => "Maple", :args_string => "int* tofu", :return => test_return[:void]} + expected = [ "typedef void (* CMOCK_Maple_CALLBACK)(int* tofu, int cmock_num_calls);\n", "void Maple_StubWithCallback(CMOCK_Maple_CALLBACK Callback);\n" ].join returned = @cmock_generator_plugin_callback.mock_function_declarations(function) assert_equal(expected, returned) end should "add mock function declaration for function with return values" do - function = {:name => "Maple", :args_string => "int* tofu", :return_type => "char*"} - expected = [ "\n", - "typedef char* (* CMOCK_Maple_CALLBACK)(int* tofu, int NumCalls);\n", + function = {:name => "Maple", :args_string => "int* tofu", :return => test_return[:string]} + expected = [ "typedef const char* (* CMOCK_Maple_CALLBACK)(int* tofu, int cmock_num_calls);\n", "void Maple_StubWithCallback(CMOCK_Maple_CALLBACK Callback);\n" ].join returned = @cmock_generator_plugin_callback.mock_function_declarations(function) assert_equal(expected, returned) end should "add mock function implementation for functions of style 'void func(void)'" do - function = {:name => "Apple", :args => [], :args_string => "void", :return_type => "void"} - expected = ["\n", - " if (Mock.Apple_CallbackFunctionPointer != NULL)\n", + function = {:name => "Apple", :args => [], :args_string => "void", :return => test_return[:void]} + expected = [" if (Mock.Apple_CallbackFunctionPointer != NULL)\n", " {\n", - " Mock.Apple_CallsExpected++;\n", - " Mock.Apple_CallbackFunctionPointer(Mock.Apple_CallCount++);\n", + " Mock.Apple_CallbackFunctionPointer(Mock.Apple_CallbackCalls++);\n", " return;\n", " }\n" ].join - returned = @cmock_generator_plugin_callback.mock_implementation(function) + returned = @cmock_generator_plugin_callback.mock_implementation_precheck(function) assert_equal(expected, returned) end should "add mock function implementation for functions of style 'int func(void)'" do - function = {:name => "Apple", :args => [], :args_string => "void", :return_type => "int"} - expected = ["\n", - " if (Mock.Apple_CallbackFunctionPointer != NULL)\n", + function = {:name => "Apple", :args => [], :args_string => "void", :return => test_return[:int]} + expected = [" if (Mock.Apple_CallbackFunctionPointer != NULL)\n", " {\n", - " Mock.Apple_CallsExpected++;\n", - " return Mock.Apple_CallbackFunctionPointer(Mock.Apple_CallCount++);\n", + " return Mock.Apple_CallbackFunctionPointer(Mock.Apple_CallbackCalls++);\n", " }\n" ].join - returned = @cmock_generator_plugin_callback.mock_implementation(function) + returned = @cmock_generator_plugin_callback.mock_implementation_precheck(function) assert_equal(expected, returned) end @@ -87,16 +81,14 @@ class CMockGeneratorPluginCallbackTest < Test::Unit::TestCase :args => [ { :type => 'int*', :name => 'steak', :ptr? => true}, { :type => 'uint8_t', :name => 'flag', :ptr? => false} ], :args_string => "int* steak, uint8_t flag", - :return_type => "void"} - expected = ["\n", - " if (Mock.Apple_CallbackFunctionPointer != NULL)\n", + :return=> test_return[:void]} + expected = [" if (Mock.Apple_CallbackFunctionPointer != NULL)\n", " {\n", - " Mock.Apple_CallsExpected++;\n", - " Mock.Apple_CallbackFunctionPointer(steak, flag, Mock.Apple_CallCount++);\n", + " Mock.Apple_CallbackFunctionPointer(steak, flag, Mock.Apple_CallbackCalls++);\n", " return;\n", " }\n" ].join - returned = @cmock_generator_plugin_callback.mock_implementation(function) + returned = @cmock_generator_plugin_callback.mock_implementation_precheck(function) assert_equal(expected, returned) end @@ -105,15 +97,13 @@ class CMockGeneratorPluginCallbackTest < Test::Unit::TestCase :args => [ { :type => 'int*', :name => 'steak', :ptr? => true}, { :type => 'uint8_t', :name => 'flag', :ptr? => false} ], :args_string => "int* steak, uint8_t flag", - :return_type => "int16_t"} - expected = ["\n", - " if (Mock.Apple_CallbackFunctionPointer != NULL)\n", + :return => test_return[:int]} + expected = [" if (Mock.Apple_CallbackFunctionPointer != NULL)\n", " {\n", - " Mock.Apple_CallsExpected++;\n", - " return Mock.Apple_CallbackFunctionPointer(steak, flag, Mock.Apple_CallCount++);\n", + " return Mock.Apple_CallbackFunctionPointer(steak, flag, Mock.Apple_CallbackCalls++);\n", " }\n" ].join - returned = @cmock_generator_plugin_callback.mock_implementation(function) + returned = @cmock_generator_plugin_callback.mock_implementation_precheck(function) assert_equal(expected, returned) end @@ -121,23 +111,22 @@ class CMockGeneratorPluginCallbackTest < Test::Unit::TestCase function = {:name => "Lemon", :args => [{ :type => "char*", :name => "pescado"}], :args_string => "char* pescado", - :return_type => "int", - :return_string => "int cmock_to_return" } + :return => test_return[:int] + } - expected = ["\n", - "void Lemon_StubWithCallback(CMOCK_Lemon_CALLBACK Callback)\n", + expected = ["void Lemon_StubWithCallback(CMOCK_Lemon_CALLBACK Callback)\n", "{\n", " Mock.Lemon_CallbackFunctionPointer = Callback;\n", - "}\n" + "}\n\n" ].join returned = @cmock_generator_plugin_callback.mock_interfaces(function) assert_equal(expected, returned) end should "add mock destroy for functions" do - function = {:name => "Peach", :args => [], :return_type => "void" } - expected = ["\n", - " Mock.Peach_CallbackFunctionPointer = NULL;\n" ].join + function = {:name => "Peach", :args => [], :return => test_return[:void] } + expected = " Mock.Peach_CallbackFunctionPointer = NULL;\n" + + " Mock.Peach_CallbackCalls = 0;\n" returned = @cmock_generator_plugin_callback.mock_destroy(function) assert_equal(expected, returned) end diff --git a/test/unit/cmock_generator_plugin_cexception_test.rb b/test/unit/cmock_generator_plugin_cexception_test.rb index 3e5a43d..b24c328 100644 --- a/test/unit/cmock_generator_plugin_cexception_test.rb +++ b/test/unit/cmock_generator_plugin_cexception_test.rb @@ -31,73 +31,45 @@ class CMockGeneratorPluginCexceptionTest < Test::Unit::TestCase assert_equal(expected, returned) end - should "add to control structure mock needs" do - function = { :name => "Oak", :args => [], :return_type => "void" } - expected = ["\n", - " int *Oak_ThrowOnCallCount;\n", - " int *Oak_ThrowOnCallCount_Head;\n", - " int *Oak_ThrowOnCallCount_Tail;\n", - " CEXCEPTION_T *Oak_ThrowValue;\n", - " CEXCEPTION_T *Oak_ThrowValue_Head;\n", - " CEXCEPTION_T *Oak_ThrowValue_Tail;\n" - ].join - returned = @cmock_generator_plugin_cexception.instance_structure(function) + should "add to typedef structure mock needs" do + function = { :name => "Oak", :args => [], :return => test_return[:void] } + expected = " CEXCEPTION_T ExceptionToThrow;\n" + returned = @cmock_generator_plugin_cexception.instance_typedefs(function) assert_equal(expected, returned) end should "add mock function declarations for functions without arguments" do - function = { :name => "Spruce", :args_string => "void", :return_type => "void" } - expected = "void Spruce_ExpectAndThrow(CEXCEPTION_T toThrow);\n" + function = { :name => "Spruce", :args_string => "void", :return => test_return[:void] } + expected = "void Spruce_ExpectAndThrow(CEXCEPTION_T cmock_to_throw);\n" returned = @cmock_generator_plugin_cexception.mock_function_declarations(function) assert_equal(expected, returned) end should "add mock function declarations for functions with arguments" do - function = { :name => "Spruce", :args_string => "const char* Petunia, uint32_t Lily", :return_type => "void" } - expected = "void Spruce_ExpectAndThrow(const char* Petunia, uint32_t Lily, CEXCEPTION_T toThrow);\n" + function = { :name => "Spruce", :args_string => "const char* Petunia, uint32_t Lily", :return => test_return[:void] } + expected = "void Spruce_ExpectAndThrow(const char* Petunia, uint32_t Lily, CEXCEPTION_T cmock_to_throw);\n" returned = @cmock_generator_plugin_cexception.mock_function_declarations(function) assert_equal(expected, returned) end should "add a mock implementation" do - function = {:name => "Cherry", :args => [], :return_type => "void"} - expected = ["\n", - " if ((Mock.Cherry_ThrowOnCallCount != Mock.Cherry_ThrowOnCallCount_Tail) &&\n", - " (Mock.Cherry_ThrowValue != Mock.Cherry_ThrowValue_Tail))\n", - " {\n", - " if (*Mock.Cherry_ThrowOnCallCount &&\n", - " (Mock.Cherry_CallCount == *Mock.Cherry_ThrowOnCallCount))\n", - " {\n", - " CEXCEPTION_T toThrow = *Mock.Cherry_ThrowValue;\n", - " Mock.Cherry_ThrowOnCallCount++;\n", - " Mock.Cherry_ThrowValue++;\n", - " Throw(toThrow);\n", - " }\n", - " }\n" - ].join + function = {:name => "Cherry", :args => [], :return => test_return[:void]} + expected = " if (cmock_call_instance->ExceptionToThrow != CEXCEPTION_NONE)\n {\n" + + " Throw(cmock_call_instance->ExceptionToThrow);\n }\n" returned = @cmock_generator_plugin_cexception.mock_implementation(function) assert_equal(expected, returned) end should "add mock interfaces for functions without arguments" do - function = {:name => "Pear", :args_string => "void", :args => [], :return_type => "void"} + function = {:name => "Pear", :args_string => "void", :args => [], :return => test_return[:void]} @utils.expect.code_add_base_expectation("Pear").returns("mock_retval_0") - @utils.expect.code_insert_item_into_expect_array("int", "Mock.Pear_ThrowOnCallCount", "Mock.Pear_CallsExpected").returns("mock_return_1") - @utils.expect.code_insert_item_into_expect_array("CEXCEPTION_T", "Mock.Pear_ThrowValue", "toThrow").returns("mock_return_2") + @utils.expect.code_call_argument_loader(function).returns("") - expected = ["void Pear_ExpectAndThrow(CEXCEPTION_T toThrow)\n", + expected = ["void Pear_ExpectAndThrow(CEXCEPTION_T cmock_to_throw)\n", "{\n", "mock_retval_0", - "mock_return_1", - "mock_return_2", - "\n", - " Mock.Pear_ThrowValue = Mock.Pear_ThrowValue_Head;\n", - " Mock.Pear_ThrowOnCallCount = Mock.Pear_ThrowOnCallCount_Head;\n", - " while ((*Mock.Pear_ThrowOnCallCount <= Mock.Pear_CallCount) && (Mock.Pear_ThrowOnCallCount < Mock.Pear_ThrowOnCallCount_Tail))\n", - " {\n", - " Mock.Pear_ThrowValue++;\n", - " Mock.Pear_ThrowOnCallCount++;\n", - " }\n", + "", + " cmock_call_instance->ExceptionToThrow = cmock_to_throw;\n", "}\n\n" ].join returned = @cmock_generator_plugin_cexception.mock_interfaces(function) @@ -105,54 +77,19 @@ class CMockGeneratorPluginCexceptionTest < Test::Unit::TestCase end should "add a mock interfaces for functions with arguments" do - function = {:name => "Pear", :args_string => "int blah", :args => [{ :type => "int", :name => "blah" }], :return_type => "void"} + function = {:name => "Pear", :args_string => "int blah", :args => [{ :type => "int", :name => "blah" }], :return => test_return[:void]} @utils.expect.code_add_base_expectation("Pear").returns("mock_retval_0") - @utils.expect.code_insert_item_into_expect_array("int", "Mock.Pear_ThrowOnCallCount", "Mock.Pear_CallsExpected").returns("mock_return_1") - @utils.expect.code_insert_item_into_expect_array("CEXCEPTION_T", "Mock.Pear_ThrowValue", "toThrow").returns("mock_return_2") + @utils.expect.code_call_argument_loader(function).returns("mock_return_1") - expected = ["void Pear_ExpectAndThrow(int blah, CEXCEPTION_T toThrow)\n", + expected = ["void Pear_ExpectAndThrow(int blah, CEXCEPTION_T cmock_to_throw)\n", "{\n", "mock_retval_0", "mock_return_1", - "mock_return_2", - "\n", - " Mock.Pear_ThrowValue = Mock.Pear_ThrowValue_Head;\n", - " Mock.Pear_ThrowOnCallCount = Mock.Pear_ThrowOnCallCount_Head;\n", - " while ((*Mock.Pear_ThrowOnCallCount <= Mock.Pear_CallCount) && (Mock.Pear_ThrowOnCallCount < Mock.Pear_ThrowOnCallCount_Tail))\n", - " {\n", - " Mock.Pear_ThrowValue++;\n", - " Mock.Pear_ThrowOnCallCount++;\n", - " }\n", - " CMockExpectParameters_Pear(blah);\n", + " cmock_call_instance->ExceptionToThrow = cmock_to_throw;\n", "}\n\n" ].join returned = @cmock_generator_plugin_cexception.mock_interfaces(function) assert_equal(expected, returned) end - should "have nothing to say about verifying" do - assert(!@cmock_generator_plugin_cexception.respond_to?(:mock_verify)) - end - - should "add necessary baggage to destroy function" do - function = {:name => "Banana", :args_string => "", :args => [], :return_type => "void"} - expected = ["\n", - " if(Mock.Banana_ThrowOnCallCount_Head)\n", - " {\n", - " free(Mock.Banana_ThrowOnCallCount_Head);\n", - " }\n", - " Mock.Banana_ThrowOnCallCount=NULL;\n", - " Mock.Banana_ThrowOnCallCount_Head=NULL;\n", - " Mock.Banana_ThrowOnCallCount_Tail=NULL;\n", - " if(Mock.Banana_ThrowValue_Head)\n", - " {\n", - " free(Mock.Banana_ThrowValue_Head);\n", - " }\n", - " Mock.Banana_ThrowValue=NULL;\n", - " Mock.Banana_ThrowValue_Head=NULL;\n", - " Mock.Banana_ThrowValue_Tail=NULL;\n" - ].join - returned = @cmock_generator_plugin_cexception.mock_destroy(function) - assert_equal(expected, returned) - end end diff --git a/test/unit/cmock_generator_plugin_expect_test.rb b/test/unit/cmock_generator_plugin_expect_test.rb index 1cddcd3..66357f5 100644 --- a/test/unit/cmock_generator_plugin_expect_test.rb +++ b/test/unit/cmock_generator_plugin_expect_test.rb @@ -34,318 +34,162 @@ class CMockGeneratorPluginExpectTest < Test::Unit::TestCase assert(!@cmock_generator_plugin_expect.respond_to?(:include_files)) end - should "add to control structure mock needs of functions of style 'void func(void)'" do - function = {:name => "Oak", :args => [], :return_type => "void"} - expected = ["\n", - " int Oak_CallCount;\n", - " int Oak_CallsExpected;\n" - ].join - returned = @cmock_generator_plugin_expect.instance_structure(function) + should "add to typedef structure mock needs of functions of style 'void func(void)'" do + function = {:name => "Oak", :args => [], :return => test_return[:void]} + expected = "" + returned = @cmock_generator_plugin_expect.instance_typedefs(function) assert_equal(expected, returned) end - should "add to control structure mock needs of functions of style 'int func(void)'" do - function = {:name => "Elm", :args => [], :return_type => "int"} - expected = ["\n", - " int Elm_CallCount;\n", - " int Elm_CallsExpected;\n", - "\n", - " int *Elm_Return;\n", - " int *Elm_Return_Head;\n", - " int *Elm_Return_Tail;\n" - ].join - returned = @cmock_generator_plugin_expect.instance_structure(function) + should "add to typedef structure mock needs of functions of style 'int func(void)'" do + function = {:name => "Elm", :args => [], :return => test_return[:int]} + expected = " int ReturnVal;\n" + returned = @cmock_generator_plugin_expect.instance_typedefs(function) assert_equal(expected, returned) end - should "add to control structure mock needs of functions of style 'void func(int chicken, char* pork)'" do - function = {:name => "Cedar", :args => [{ :name => "chicken", :type => "int"}, { :name => "pork", :type => "char*"}], :return_type => "void"} - expected = ["\n", - " int Cedar_CallCount;\n", - " int Cedar_CallsExpected;\n", - "\n", - " int *Cedar_Expected_chicken;\n", - " int *Cedar_Expected_chicken_Head;\n", - " int *Cedar_Expected_chicken_Tail;\n", - "\n", - " char* *Cedar_Expected_pork;\n", - " char* *Cedar_Expected_pork_Head;\n", - " char* *Cedar_Expected_pork_Tail;\n" - ].join - returned = @cmock_generator_plugin_expect.instance_structure(function) + should "add to typedef structure mock needs of functions of style 'void func(int chicken, char* pork)'" do + function = {:name => "Cedar", :args => [{ :name => "chicken", :type => "int"}, { :name => "pork", :type => "char*"}], :return => test_return[:void]} + expected = " int Expected_chicken;\n char* Expected_pork;\n" + returned = @cmock_generator_plugin_expect.instance_typedefs(function) assert_equal(expected, returned) end - should "add to control structure mock needs of functions of style 'int func(float beef)'" do - function = {:name => "Birch", :args => [{ :name => "beef", :type => "float"}], :return_type => "int"} - expected = ["\n", - " int Birch_CallCount;\n", - " int Birch_CallsExpected;\n", - "\n", - " int *Birch_Return;\n", - " int *Birch_Return_Head;\n", - " int *Birch_Return_Tail;\n", - "\n", - " float *Birch_Expected_beef;\n", - " float *Birch_Expected_beef_Head;\n", - " float *Birch_Expected_beef_Tail;\n", - ].join - returned = @cmock_generator_plugin_expect.instance_structure(function) + should "add to typedef structure mock needs of functions of style 'int func(float beef)'" do + function = {:name => "Birch", :args => [{ :name => "beef", :type => "float"}], :return => test_return[:int]} + expected = " int ReturnVal;\n float Expected_beef;\n" + returned = @cmock_generator_plugin_expect.instance_typedefs(function) assert_equal(expected, returned) end - should "add to control structure mock needs of functions of style 'void func(void)' and global ordering" do - function = {:name => "Oak", :args => [], :return_type => "void"} - expected = ["\n", - " int Oak_CallCount;\n", - " int Oak_CallsExpected;\n", - "\n", - " int *Oak_CallOrder;\n", - " int *Oak_CallOrder_Head;\n", - " int *Oak_CallOrder_Tail;\n" - ].join - returned = @cmock_generator_plugin_expect_strict.instance_structure(function) + should "add to typedef structure mock needs of functions of style 'void func(void)' and global ordering" do + function = {:name => "Oak", :args => [], :return => test_return[:void]} + expected = " int CallOrder;\n" + returned = @cmock_generator_plugin_expect_strict.instance_typedefs(function) assert_equal(expected, returned) end should "add mock function declaration for functions of style 'void func(void)'" do - function = {:name => "Maple", :args_string => "void", :return_type => "void"} - expected = "void #{function[:name]}_Expect(#{function[:args_string]});\n" + function = {:name => "Maple", :args => [], :return => test_return[:void]} + expected = "void Maple_Expect(void);\n" returned = @cmock_generator_plugin_expect.mock_function_declarations(function) assert_equal(expected, returned) end should "add mock function declaration for functions of style 'int func(void)'" do - function = {:name => "Spruce", :args_string => "void", :return_string => "int cmock_to_return"} - - expected = "void #{function[:name]}_ExpectAndReturn(#{function[:return_string]});\n" + function = {:name => "Spruce", :args => [], :return => test_return[:int]} + expected = "void Spruce_ExpectAndReturn(int cmock_to_return);\n" returned = @cmock_generator_plugin_expect.mock_function_declarations(function) assert_equal(expected, returned) end should "add mock function declaration for functions of style 'const char* func(int tofu)'" do - function = {:name => "Pine", :args_string => "int tofu", :return_string => "const char* cmock_to_return"} - - expected = "void #{function[:name]}_ExpectAndReturn(#{function[:args_string]}, #{function[:return_string]});\n" + function = {:name => "Pine", :args => ["int tofu"], :args_string => "int tofu", :return => test_return[:string]} + expected = "void Pine_ExpectAndReturn(int tofu, const char* cmock_to_return);\n" returned = @cmock_generator_plugin_expect.mock_function_declarations(function) assert_equal(expected, returned) end should "add mock function implementation for functions of style 'void func(void)'" do - function = {:name => "Apple", :args => [], :return_type => "void"} - expected = ["\n", - " Mock.Apple_CallCount++;\n", - " if (Mock.Apple_CallCount > Mock.Apple_CallsExpected)\n", - " {\n", - " TEST_FAIL(\"Function 'Apple' called more times than expected\");\n", - " }\n" - ].join + function = {:name => "Apple", :args => [], :return => test_return[:void]} + expected = "" returned = @cmock_generator_plugin_expect.mock_implementation(function) assert_equal(expected, returned) end should "add mock function implementation for functions of style 'int func(int veal, unsigned int sushi)'" do - function = {:name => "Cherry", :args => [ { :type => "int", :name => "veal" }, { :type => "unsigned int", :name => "sushi" } ], :return_type => "int"} + function = {:name => "Cherry", :args => [ { :type => "int", :name => "veal" }, { :type => "unsigned int", :name => "sushi" } ], :return => test_return[:int]} - @utils.expect.code_verify_an_arg_expectation(function, function[:args][0]).returns("mocked_retval_1") - @utils.expect.code_verify_an_arg_expectation(function, function[:args][1]).returns("mocked_retval_2") - - expected = ["\n", - " Mock.Cherry_CallCount++;\n", - " if (Mock.Cherry_CallCount > Mock.Cherry_CallsExpected)\n", - " {\n", - " TEST_FAIL(\"Function 'Cherry' called more times than expected\");\n", - " }\n", - "mocked_retval_1", - "mocked_retval_2" - ].join + @utils.expect.code_verify_an_arg_expectation(function, function[:args][0]).returns(" mocked_retval_1") + @utils.expect.code_verify_an_arg_expectation(function, function[:args][1]).returns(" mocked_retval_2") + expected = " mocked_retval_1 mocked_retval_2" returned = @cmock_generator_plugin_expect.mock_implementation(function) assert_equal(expected, returned) end should "add mock function implementation using ordering if needed" do - function = {:name => "Apple", :args => [], :return_type => "void"} - expected = ["\n", - " Mock.Apple_CallCount++;\n", - " if (Mock.Apple_CallCount > Mock.Apple_CallsExpected)\n", - " {\n", - " TEST_FAIL(\"Function 'Apple' called more times than expected\");\n", - " }\n", - " {\n", - " int* cmock_val_expected = Mock.Apple_CallOrder;\n", - " ++GlobalVerifyOrder;\n", - " if (Mock.Apple_CallOrder != Mock.Apple_CallOrder_Tail)\n", - " Mock.Apple_CallOrder++;\n", - " if ((*cmock_val_expected != GlobalVerifyOrder) && (GlobalOrderError == NULL))\n", - " {\n", - " const char* cmock_err_str = \"Out of order function calls. Function 'Apple'\";\n", - " GlobalOrderError = malloc(46);\n", - " if (GlobalOrderError)\n", - " strcpy(GlobalOrderError, cmock_err_str);\n", - " }\n", - " }\n" - ].join + function = {:name => "Apple", :args => [], :return => test_return[:void]} + expected = " TEST_ASSERT_MESSAGE((cmock_call_instance->CallOrder == ++GlobalVerifyOrder), \"Out of order function calls. Function 'Apple'\");\n" @cmock_generator_plugin_expect.ordered = true returned = @cmock_generator_plugin_expect.mock_implementation(function) assert_equal(expected, returned) end - should "add mock function implementation for functions of style 'void func(void)' and strict ordering" do - function = {:name => "Apple", :args => [], :return_type => "void"} - expected = ["\n", - " Mock.Apple_CallCount++;\n", - " if (Mock.Apple_CallCount > Mock.Apple_CallsExpected)\n", - " {\n", - " TEST_FAIL(\"Function 'Apple' called more times than expected\");\n", - " }\n", - " {\n", - " int* cmock_val_expected = Mock.Apple_CallOrder;\n", - " ++GlobalVerifyOrder;\n", - " if (Mock.Apple_CallOrder != Mock.Apple_CallOrder_Tail)\n", - " Mock.Apple_CallOrder++;\n", - " if ((*cmock_val_expected != GlobalVerifyOrder) && (GlobalOrderError == NULL))\n", - " {\n", - " const char* cmock_err_str = \"Out of order function calls. Function 'Apple'\";\n", - " GlobalOrderError = malloc(46);\n", - " if (GlobalOrderError)\n", - " strcpy(GlobalOrderError, cmock_err_str);\n", - " }\n", - " }\n" - ].join + should "add mock function implementation for functions of style 'void func(int worm)' and strict ordering" do + function = {:name => "Apple", :args => [{ :type => "int", :name => "worm" }], :return => test_return[:void]} + @utils.expect.code_verify_an_arg_expectation(function, function[:args][0]).returns("mocked_retval_0") + expected = " TEST_ASSERT_MESSAGE((cmock_call_instance->CallOrder == ++GlobalVerifyOrder), \"Out of order function calls. Function 'Apple'\");\nmocked_retval_0" + @cmock_generator_plugin_expect.ordered = true returned = @cmock_generator_plugin_expect_strict.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", :return_type => "void"} + function = {:name => "Pear", :args => [], :args_string => "void", :return => test_return[:void]} + @utils.expect.code_add_base_expectation("Pear").returns("mock_retval_0 ") + @utils.expect.code_call_argument_loader(function).returns("mock_retval_1 ") expected = ["void Pear_Expect(void)\n", "{\n", - "mock_retval_0", + "mock_retval_0 ", + "mock_retval_1 ", "}\n\n" - ] + ].join returned = @cmock_generator_plugin_expect.mock_interfaces(function) assert_equal(expected, returned) end - should "add mock interfaces for functions of style 'unsigned short func(void)'" do - function = {:name => "Orange", :args => [], :args_string => "void", :return_type => "unsigned short", :return_string => "unsigned short cmock_to_return"} - @utils.expect.code_add_base_expectation("Orange").returns("mock_retval_0") - @utils.expect.code_insert_item_into_expect_array(function[:return_type], "Mock.Orange_Return","cmock_to_return").returns("mock_retval_1") - - expected = ["void Orange_ExpectAndReturn(unsigned short cmock_to_return)\n", + should "add mock interfaces for functions of style 'int func(void)'" do + function = {:name => "Orange", :args => [], :args_string => "void", :return => test_return[:int]} + @utils.expect.code_add_base_expectation("Orange").returns("mock_retval_0 ") + @utils.expect.code_call_argument_loader(function).returns("mock_retval_1 ") + @utils.expect.code_assign_argument_quickly("cmock_call_instance->ReturnVal", function[:return]).returns("mock_retval_2") + expected = ["void Orange_ExpectAndReturn(int cmock_to_return)\n", "{\n", - "mock_retval_0", - "mock_retval_1", - " Mock.Orange_Return = Mock.Orange_Return_Head;\n", - " Mock.Orange_Return += Mock.Orange_CallCount;\n", + "mock_retval_0 ", + "mock_retval_1 ", + "mock_retval_2", "}\n\n" - ] + ].join returned = @cmock_generator_plugin_expect.mock_interfaces(function) assert_equal(expected, returned) end 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", :return_type => "int", :return_string => "int cmock_to_return"} - @utils.expect.code_add_an_arg_expectation(function, {:type => "char*", :name => "pescado"}).returns("mock_retval_2") - @utils.expect.code_add_base_expectation("Lemon").returns("mock_retval_0") - @utils.expect.code_insert_item_into_expect_array(function[:return_type], "Mock.Lemon_Return", 'cmock_to_return').returns("mock_retval_1") - - expected = ["void CMockExpectParameters_Lemon(char* pescado)\n", + function = {:name => "Lemon", :args => [{ :type => "char*", :name => "pescado"}], :args_string => "char* pescado", :return => test_return[:int]} + @utils.expect.code_add_base_expectation("Lemon").returns("mock_retval_0 ") + @utils.expect.code_call_argument_loader(function).returns("mock_retval_1 ") + @utils.expect.code_assign_argument_quickly("cmock_call_instance->ReturnVal", function[:return]).returns("mock_retval_2") + expected = ["void Lemon_ExpectAndReturn(char* pescado, int cmock_to_return)\n", "{\n", + "mock_retval_0 ", + "mock_retval_1 ", "mock_retval_2", - "}\n\n", - "void Lemon_ExpectAndReturn(char* pescado, int cmock_to_return)\n", - "{\n", - "mock_retval_0", - " CMockExpectParameters_Lemon(pescado);\n", - "mock_retval_1", - " Mock.Lemon_Return = Mock.Lemon_Return_Head;\n", - " Mock.Lemon_Return += Mock.Lemon_CallCount;\n", "}\n\n" ].join - returned = @cmock_generator_plugin_expect.mock_interfaces(function).join + returned = @cmock_generator_plugin_expect.mock_interfaces(function) assert_equal(expected, returned) end should "add mock interfaces for functions when using ordering" do - function = {:name => "Pear", :args => [], :args_string => "void", :return_type => "void"} + function = {:name => "Pear", :args => [], :args_string => "void", :return => test_return[:void]} + @utils.expect.code_add_base_expectation("Pear").returns("mock_retval_0 ") + @utils.expect.code_call_argument_loader(function).returns("mock_retval_1 ") expected = ["void Pear_Expect(void)\n", "{\n", - "mock_retval_0", + "mock_retval_0 ", + "mock_retval_1 ", "}\n\n" - ] + ].join @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" } - - expected = " TEST_ASSERT_EQUAL_MESSAGE(Mock.Banana_CallsExpected, Mock.Banana_CallCount, \"Function 'Banana' called unexpected number of times.\");\n" + expected = " TEST_ASSERT_NULL_MESSAGE(Mock.Banana_CallInstance, \"Function 'Banana' called less times than expected.\");\n" returned = @cmock_generator_plugin_expect.mock_verify(function) assert_equal(expected, returned) end - should "add mock destroy for functions of style 'void func(void)'" do - function = {:name => "Peach", :args => [], :return_type => "void" } - expected = [] - returned = @cmock_generator_plugin_expect.mock_destroy(function) - assert_equal(expected, returned) - end - - should "add mock destroy for functions of style 'char func(void)'" do - function = {:name => "Palm", :args => [], :return_type => "char" } - expected = [ %q[ - if (Mock.Palm_Return_Head) - { - free(Mock.Palm_Return_Head); - } - Mock.Palm_Return=NULL; - Mock.Palm_Return_Head=NULL; - Mock.Palm_Return_Tail=NULL; -] ] - returned = @cmock_generator_plugin_expect.mock_destroy(function) - assert_equal(expected, returned) - end - - should "add mock destroy for functions of style 'int func(uint32 grease)'" do - function = {:name => "Coconut", :args => [{ :type => "uint32", :name => "grease"}], :return_type => "int" } - expected = [ %q[ - if (Mock.Coconut_Return_Head) - { - free(Mock.Coconut_Return_Head); - } - Mock.Coconut_Return=NULL; - Mock.Coconut_Return_Head=NULL; - Mock.Coconut_Return_Tail=NULL; -] , %q[ - if (Mock.Coconut_Expected_grease_Head) - { - free(Mock.Coconut_Expected_grease_Head); - } - Mock.Coconut_Expected_grease=NULL; - Mock.Coconut_Expected_grease_Head=NULL; - Mock.Coconut_Expected_grease_Tail=NULL; -] ] - returned = @cmock_generator_plugin_expect.mock_destroy(function) - assert_equal(expected, returned) - end - - should "add mock destroy for functions with strict ordering" do - function = {:name => "Peach", :args => [], :return_type => "void" } - expected = [ %q[ - if (Mock.Peach_CallOrder_Head) - { - free(Mock.Peach_CallOrder_Head); - } - Mock.Peach_CallOrder=NULL; - Mock.Peach_CallOrder_Head=NULL; - Mock.Peach_CallOrder_Tail=NULL; -] ] - returned = @cmock_generator_plugin_expect_strict.mock_destroy(function) - assert_equal(expected, returned) - end end diff --git a/test/unit/cmock_generator_plugin_ignore_test.rb b/test/unit/cmock_generator_plugin_ignore_test.rb index 4433ab8..98886bd 100644 --- a/test/unit/cmock_generator_plugin_ignore_test.rb +++ b/test/unit/cmock_generator_plugin_ignore_test.rb @@ -22,63 +22,56 @@ class CMockGeneratorPluginIgnoreTest < Test::Unit::TestCase end should "add a required variable to the instance structure" do - function = {:name => "Grass", :args => [], :return_type => "void"} + function = {:name => "Grass", :args => [], :return => test_return[:void]} expected = " int Grass_IgnoreBool;\n" returned = @cmock_generator_plugin_ignore.instance_structure(function) assert_equal(expected, returned) end should "handle function declarations for functions without return values" do - function = {:name => "Mold", :args_string => "void", :return_type => "void"} + function = {:name => "Mold", :args_string => "void", :return => test_return[:void]} expected = "void Mold_Ignore(void);\n" returned = @cmock_generator_plugin_ignore.mock_function_declarations(function) assert_equal(expected, returned) end should "handle function declarations for functions that returns something" do - function = {:name => "Fungus", :args_string => "void", :return_type => "const char*", :return_string => "const char* cmock_to_return"} + function = {:name => "Fungus", :args_string => "void", :return => test_return[:string]} expected = "void Fungus_IgnoreAndReturn(const char* cmock_to_return);\n" returned = @cmock_generator_plugin_ignore.mock_function_declarations(function) assert_equal(expected, returned) end should "add required code to implementation with void function" do - function = {:name => "Mold", :args_string => "void", :return_type => "void"} + function = {:name => "Mold", :args_string => "void", :return => test_return[:void]} expected = [" if (Mock.Mold_IgnoreBool)\n", " {\n", " return;\n", " }\n" ].join - returned = @cmock_generator_plugin_ignore.mock_implementation(function) + returned = @cmock_generator_plugin_ignore.mock_implementation_precheck(function) assert_equal(expected, returned) end should "add required code to implementation with return functions" do - function = {:name => "Fungus", :args_string => "void", :return_type => "int"} + function = {:name => "Fungus", :args_string => "void", :return => test_return[:int]} + retval = test_return[:int].merge({ :name => "cmock_call_instance->ReturnVal"}) + @utils.expect.code_assign_argument_quickly("Mock.Fungus_FinalReturn", retval).returns(' mock_retval_0') expected = [" if (Mock.Fungus_IgnoreBool)\n", " {\n", - " if (Mock.Fungus_Return != Mock.Fungus_Return_Tail)\n", - " {\n", - " int cmock_to_return = *Mock.Fungus_Return;\n", - " Mock.Fungus_Return++;\n", - " Mock.Fungus_CallCount++;\n", - " Mock.Fungus_CallsExpected++;\n", - " return cmock_to_return;\n", - " }\n", - " else\n", - " {\n", - " return *(Mock.Fungus_Return_Tail - 1);\n", - " }\n", + " if (cmock_call_instance == NULL)\n", + " return Mock.Fungus_FinalReturn;\n", + " mock_retval_0", + " return cmock_call_instance->ReturnVal;\n", " }\n" ].join - returned = @cmock_generator_plugin_ignore.mock_implementation(function) + returned = @cmock_generator_plugin_ignore.mock_implementation_precheck(function) assert_equal(expected, returned) end should "add a new mock interface for ignoring when function had no return value" do - function = {:name => "Slime", :args => [], :args_string => "void", :return_type => "void"} - expected = ["\n", - "void Slime_Ignore(void)\n", + function = {:name => "Slime", :args => [], :args_string => "void", :return => test_return[:void]} + expected = ["void Slime_Ignore(void)\n", "{\n", " Mock.Slime_IgnoreBool = (int)1;\n", "}\n\n" @@ -88,28 +81,17 @@ class CMockGeneratorPluginIgnoreTest < Test::Unit::TestCase end should "add a new mock interface for ignoring when function has return value" do - function = {:name => "Slime", :args => [], :args_string => "void", :return_type => "uint32", :return_string => "uint32 cmock_to_return"} - @utils.expect.code_insert_item_into_expect_array("uint32", "Mock.Slime_Return", "cmock_to_return").returns("mock_return_1") - - expected = ["\n", - "void Slime_IgnoreAndReturn(uint32 cmock_to_return)\n", + function = {:name => "Slime", :args => [], :args_string => "void", :return => test_return[:int]} + @utils.expect.code_add_base_expectation("Slime", false).returns("mock_return_1") + expected = ["void Slime_IgnoreAndReturn(int cmock_to_return)\n", "{\n", + "mock_return_1", + " cmock_call_instance->ReturnVal = cmock_to_return;\n", " Mock.Slime_IgnoreBool = (int)1;\n", - "mock_return_1\n", - " Mock.Slime_Return = Mock.Slime_Return_Head;\n", - " Mock.Slime_Return += Mock.Slime_CallCount;\n", "}\n\n" ].join returned = @cmock_generator_plugin_ignore.mock_interfaces(function) assert_equal(expected, returned) end - should "have nothing new for mock verify" do - assert(!@cmock_generator_plugin_ignore.respond_to?(:mock_verify)) - end - - - should "have nothing new for mock destroy" do - assert(!@cmock_generator_plugin_ignore.respond_to?(:mock_destroy)) - end end diff --git a/test/unit/cmock_generator_utils_test.rb b/test/unit/cmock_generator_utils_test.rb index fc1e7d9..498e69a 100644 --- a/test/unit/cmock_generator_utils_test.rb +++ b/test/unit/cmock_generator_utils_test.rb @@ -3,376 +3,282 @@ require 'cmock_generator_utils' class CMockGeneratorUtilsTest < Test::Unit::TestCase def setup - create_mocks :config, :unity_helper - @config.expect.when_ptr.returns(:compare_data) + create_mocks :config, :unity_helper, :unity_helper + + @config.expect.when_ptr.returns(:compare_ptr) @config.expect.enforce_strict_ordering.returns(false) @config.expect.plugins.returns([]) - @cmock_generator_utils = CMockGeneratorUtils.new(@config) + @config.expect.plugins.returns([]) + @config.expect.treat_as.returns(['int','short','long','char','const char*']) + @cmock_generator_utils_simple = CMockGeneratorUtils.new(@config, {:unity_helper => @unity_helper}) + + @config.expect.when_ptr.returns(:smart) + @config.expect.enforce_strict_ordering.returns(true) + @config.expect.plugins.returns([:array, :cexception]) + @config.expect.plugins.returns([:array, :cexception]) + @config.expect.treat_as.returns(['int','short','long','char','uint32_t','const char*']) + @cmock_generator_utils_complex = CMockGeneratorUtils.new(@config, {:unity_helper => @unity_helper, :A=>1, :B=>2}) end def teardown end should "have set up internal accessors correctly on init" do - assert_equal(@config, @cmock_generator_utils.config) - assert_equal({}, @cmock_generator_utils.helpers) - assert_equal(false, @cmock_generator_utils.arrays) + assert_equal(@config, @cmock_generator_utils_simple.config) + assert_equal({:unity_helper => @unity_helper}, @cmock_generator_utils_simple.helpers) + assert_equal(false, @cmock_generator_utils_simple.arrays) + assert_equal(false, @cmock_generator_utils_simple.cexception) end should "have set up internal accessors correctly on init, complete with passed helpers" do - create_mocks :config - @config.expect.when_ptr.returns(:compare_ptr) - @config.expect.enforce_strict_ordering.returns(false) - @config.expect.plugins.returns([:array]) - @cmock_generator_utils = CMockGeneratorUtils.new(@config, {:A=>1, :B=>2}) - assert_equal(@config, @cmock_generator_utils.config) - assert_equal({:A=>1, :B=>2},@cmock_generator_utils.helpers) - assert_equal(true, @cmock_generator_utils.arrays) + assert_equal(@config, @cmock_generator_utils_complex.config) + assert_equal({:unity_helper => @unity_helper, :A=>1, :B=>2},@cmock_generator_utils_complex.helpers) + assert_equal(true, @cmock_generator_utils_complex.arrays) + assert_equal(true, @cmock_generator_utils_complex.cexception) end - should "make expand array" do - the_type = "int" - the_array = "array" - new_value = "new_value" + should "add code for a base expectation with no plugins" do + expected = + " CMOCK_Apple_CALL_INSTANCE* cmock_call_instance = (CMOCK_Apple_CALL_INSTANCE*)CMock_Guts_MemNew(sizeof(CMOCK_Apple_CALL_INSTANCE));\n" + + " TEST_ASSERT_NOT_NULL_MESSAGE(cmock_call_instance, \"CMock has run out of memory. Please allocate more.\");\n" + + " Mock.Apple_CallInstance = (CMOCK_Apple_CALL_INSTANCE*)CMock_Guts_MemChain((void*)Mock.Apple_CallInstance, (void*)cmock_call_instance);\n" + output = @cmock_generator_utils_simple.code_add_base_expectation("Apple") + assert_equal(expected, output) + end + + should "add code for a base expectation with all plugins" do + expected = + " CMOCK_Apple_CALL_INSTANCE* cmock_call_instance = (CMOCK_Apple_CALL_INSTANCE*)CMock_Guts_MemNew(sizeof(CMOCK_Apple_CALL_INSTANCE));\n" + + " TEST_ASSERT_NOT_NULL_MESSAGE(cmock_call_instance, \"CMock has run out of memory. Please allocate more.\");\n" + + " Mock.Apple_CallInstance = (CMOCK_Apple_CALL_INSTANCE*)CMock_Guts_MemChain((void*)Mock.Apple_CallInstance, (void*)cmock_call_instance);\n" + + " cmock_call_instance->CallOrder = ++GlobalExpectCount;\n" + + " cmock_call_instance->ExceptionToThrow = CEXCEPTION_NONE;\n" + output = @cmock_generator_utils_complex.code_add_base_expectation("Apple", true) + assert_equal(expected, output) + end + + should "add code for a base expectation with all plugins and ordering not supported" do + expected = + " CMOCK_Apple_CALL_INSTANCE* cmock_call_instance = (CMOCK_Apple_CALL_INSTANCE*)CMock_Guts_MemNew(sizeof(CMOCK_Apple_CALL_INSTANCE));\n" + + " TEST_ASSERT_NOT_NULL_MESSAGE(cmock_call_instance, \"CMock has run out of memory. Please allocate more.\");\n" + + " Mock.Apple_CallInstance = (CMOCK_Apple_CALL_INSTANCE*)CMock_Guts_MemChain((void*)Mock.Apple_CallInstance, (void*)cmock_call_instance);\n" + + " cmock_call_instance->ExceptionToThrow = CEXCEPTION_NONE;\n" + output = @cmock_generator_utils_complex.code_add_base_expectation("Apple", false) + assert_equal(expected, output) + end + + should "add argument expectations for values when no array plugin" do + arg1 = { :name => "Orange", :const? => false, :type => 'int', :ptr? => false } + expected1 = " cmock_call_instance->Expected_Orange = Orange;\n" - expected = ["\n", - " {\n", - " int sz = 0;\n", - " int *cmock_pointer = array_Head;\n", - " while (cmock_pointer && cmock_pointer != array_Tail) { sz++; cmock_pointer++; }\n", - " if (sz == 0)\n", - " {\n", - " array_Head = (int*)malloc(2*sizeof(int));\n", - " if (!array_Head)\n", - " Mock.allocFailure++;\n", - " }\n", - " else\n", - " {\n", - " int *ptmp = (int*)realloc(array_Head, sizeof(int) * (sz+1));\n", - " if (!ptmp)\n", - " Mock.allocFailure++;\n", - " else\n", - " array_Head = ptmp;\n"," }\n", - " memcpy(&array_Head[sz], &new_value, sizeof(int));\n", - " array_Tail = &array_Head[sz+1];\n", - " }\n" - ].join - returned = @cmock_generator_utils.code_insert_item_into_expect_array(the_type, the_array, new_value) - assert_equal(expected, returned) - end - - should "make handle return" do - function = { :name => "Spatula", :return_type => "uint64"} - expected = ["\n", - " if (Mock.Spatula_Return != Mock.Spatula_Return_Tail)\n", - " {\n", - " uint64 cmock_to_return = *Mock.Spatula_Return;\n", - " Mock.Spatula_Return++;\n", - " return cmock_to_return;\n", - " }\n", - " else\n", - " {\n", - " return *(Mock.Spatula_Return_Tail - 1);\n", - " }\n" - ].join - returned = @cmock_generator_utils.code_handle_return_value(function) - assert_equal(expected, returned) - end - - should "add new expected handler" do - function = { :name => "PizzaCutter", :return_type => "uint64"} - var_type = "uint16" - var_name = "Spork" + arg2 = { :name => "Lemon", :const? => true, :type => 'const char*', :ptr? => true } + expected2 = " cmock_call_instance->Expected_Lemon = (const char*)Lemon;\n" - expected = ["\n", - " {\n", - " int sz = 0;\n", - " uint16 *cmock_pointer = Mock.PizzaCutter_Expected_Spork_Head;\n", - " while (cmock_pointer && cmock_pointer != Mock.PizzaCutter_Expected_Spork_Tail) { sz++; cmock_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", - " Mock.allocFailure++;\n", - " }\n", - " else\n", - " {\n", - " uint16 *ptmp = (uint16*)realloc(Mock.PizzaCutter_Expected_Spork_Head, sizeof(uint16) * (sz+1));\n", - " if (!ptmp)\n", - " Mock.allocFailure++;\n", - " else\n", - " Mock.PizzaCutter_Expected_Spork_Head = ptmp;\n", - " }\n", - " memcpy(&Mock.PizzaCutter_Expected_Spork_Head[sz], &Spork, sizeof(uint16));\n", - " Mock.PizzaCutter_Expected_Spork_Tail = &Mock.PizzaCutter_Expected_Spork_Head[sz+1];\n", - " }\n", - " Mock.PizzaCutter_Expected_Spork = Mock.PizzaCutter_Expected_Spork_Head;\n", - " Mock.PizzaCutter_Expected_Spork += Mock.PizzaCutter_CallCount;\n" - ].join - returned = @cmock_generator_utils.code_add_an_arg_expectation(function, {:type => var_type, :name => var_name}) - assert_equal(expected, returned) + arg3 = { :name => "Kiwi", :const? => false, :type => 'KIWI_T*', :ptr? => true } + expected3 = " cmock_call_instance->Expected_Kiwi = Kiwi;\n" + + arg4 = { :name => "Lime", :const? => false, :type => 'LIME_T', :ptr? => false } + expected4 = " memcpy(&cmock_call_instance->Expected_Lime, &Lime, sizeof(LIME_T));\n" + + assert_equal(expected1, @cmock_generator_utils_simple.code_add_an_arg_expectation(arg1)) + assert_equal(expected2, @cmock_generator_utils_simple.code_add_an_arg_expectation(arg2)) + assert_equal(expected3, @cmock_generator_utils_simple.code_add_an_arg_expectation(arg3)) + assert_equal(expected4, @cmock_generator_utils_simple.code_add_an_arg_expectation(arg4)) 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") + should "add argument expectations for values when array plugin enabled" do + arg1 = { :name => "Orange", :const? => false, :type => 'int', :ptr? => false } + expected1 = " cmock_call_instance->Expected_Orange = Orange;\n" - assert_equal(expected, returned) + arg2 = { :name => "Lemon", :const? => true, :type => 'const char*', :ptr? => true } + expected2 = " cmock_call_instance->Expected_Lemon = (const char*)Lemon;\n" + + " cmock_call_instance->Expected_Lemon_Depth = Lemon_Depth;\n" + + arg3 = { :name => "Kiwi", :const? => false, :type => 'KIWI_T*', :ptr? => true } + expected3 = " cmock_call_instance->Expected_Kiwi = Kiwi;\n" + + " cmock_call_instance->Expected_Kiwi_Depth = Kiwi_Depth;\n" + + arg4 = { :name => "Lime", :const? => false, :type => 'LIME_T', :ptr? => false } + expected4 = " memcpy(&cmock_call_instance->Expected_Lime, &Lime, sizeof(LIME_T));\n" + + assert_equal(expected1, @cmock_generator_utils_complex.code_add_an_arg_expectation(arg1)) + assert_equal(expected2, @cmock_generator_utils_complex.code_add_an_arg_expectation(arg2, 'Lemon_Depth')) + assert_equal(expected3, @cmock_generator_utils_complex.code_add_an_arg_expectation(arg3, 'Lemon_Depth')) + assert_equal(expected4, @cmock_generator_utils_complex.code_add_an_arg_expectation(arg4)) + end + + should 'not have an argument loader when the function has no arguments' do + function = { :name => "Melon", :args_string => "void" } + + assert_equal("", @cmock_generator_utils_complex.code_add_argument_loader(function)) + end + + should 'create an argument loader when the function has arguments' do + function = { :name => "Melon", + :args_string => "stuff", + :args => [test_arg[:int_ptr], test_arg[:mytype], test_arg[:string]] + } + 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(const MY_TYPE));\n" + + " cmock_call_instance->Expected_MyStr = (const char*)MyStr;\n" + + "}\n\n" + assert_equal(expected, @cmock_generator_utils_simple.code_add_argument_loader(function)) 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 *cmock_pointer = Mock.Nectarine_CallOrder_Head;\n", - " while (cmock_pointer && cmock_pointer != Mock.Nectarine_CallOrder_Tail) { sz++; cmock_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_CallCount;\n" ].join - @cmock_generator_utils.ordered = true - returned = @cmock_generator_utils.code_add_base_expectation("Nectarine") - assert_equal(expected, returned) + should 'create an argument loader when the function has arguments supporting arrays' do + function = { :name => "Melon", + :args_string => "stuff", + :args => [test_arg[:int_ptr], test_arg[:mytype], test_arg[:string]] + } + expected = "void CMockExpectParameters_Melon(CMOCK_Melon_CALL_INSTANCE* cmock_call_instance, int* MyIntPtr, int MyIntPtr_Depth, const MY_TYPE MyMyType, const char* MyStr)\n{\n" + + " cmock_call_instance->Expected_MyIntPtr = MyIntPtr;\n" + + " cmock_call_instance->Expected_MyIntPtr_Depth = MyIntPtr_Depth;\n" + + " memcpy(&cmock_call_instance->Expected_MyMyType, &MyMyType, sizeof(const MY_TYPE));\n" + + " cmock_call_instance->Expected_MyStr = (const char*)MyStr;\n" + + "}\n\n" + assert_equal(expected, @cmock_generator_utils_complex.code_add_argument_loader(function)) end - should "make handle expected when no helpers are available" do - function = { :name => "CanOpener", :return_type => "uint64"} - var_type = "uint16" - var_name = "CorkScrew" - - expected = ["\n", - " if (Mock.CanOpener_Expected_CorkScrew != Mock.CanOpener_Expected_CorkScrew_Tail)\n", - " {\n", - " uint16* cmock_val_expected = Mock.CanOpener_Expected_CorkScrew;\n", - " Mock.CanOpener_Expected_CorkScrew++;\n", - " TEST_ASSERT_EQUAL_MESSAGE(*cmock_val_expected, CorkScrew, \"Function 'CanOpener' called with unexpected value for argument 'CorkScrew'.\");\n\n", - " }\n" - ].join - returned = @cmock_generator_utils.code_verify_an_arg_expectation(function, {:type => var_type, :name => var_name}) - assert_equal(expected, returned) + should "not call argument loader if there are no arguments to actually use for this function" do + function = { :name => "Pineapple", :args_string => "void" } + + assert_equal("", @cmock_generator_utils_complex.code_call_argument_loader(function)) end - should "make handle expected for character strings" do - function = { :name => "MeasureCup", :return_type => "uint64"} - var_type = "const char*" - var_name = "TeaSpoon" - - @cmock_generator_utils.helpers = {:unity_helper => @unity_helper} - @unity_helper.expect.get_helper(var_type).returns("TEST_ASSERT_EQUAL_STRING_MESSAGE") - - expected = ["\n", - " if (Mock.MeasureCup_Expected_TeaSpoon != Mock.MeasureCup_Expected_TeaSpoon_Tail)\n", - " {\n", - " const char** cmock_val_expected = Mock.MeasureCup_Expected_TeaSpoon;\n", - " Mock.MeasureCup_Expected_TeaSpoon++;\n", - " TEST_ASSERT_EQUAL_STRING_MESSAGE(*cmock_val_expected, TeaSpoon, \"Function 'MeasureCup' called with unexpected value for argument 'TeaSpoon'.\");\n\n", - " }\n" - ].join - returned = @cmock_generator_utils.code_verify_an_arg_expectation(function, {:type => var_type, :name => var_name}) - assert_equal(expected, returned) - end - - should "make handle expected for custom types from unity helper" do - function = { :name => "TeaPot", :return_type => "uint64"} - var_type = "MANDELBROT_SET_T" - var_name = "TeaSpoon" - - @cmock_generator_utils.helpers = {:unity_helper => @unity_helper} - @unity_helper.expect.get_helper(var_type).returns("TEST_ASSERT_EQUAL_MANDELBROT_SET_T_MESSAGE") - - expected = ["\n", - " if (Mock.TeaPot_Expected_TeaSpoon != Mock.TeaPot_Expected_TeaSpoon_Tail)\n", - " {\n", - " MANDELBROT_SET_T* cmock_val_expected = Mock.TeaPot_Expected_TeaSpoon;\n", - " Mock.TeaPot_Expected_TeaSpoon++;\n", - " TEST_ASSERT_EQUAL_MANDELBROT_SET_T_MESSAGE(*cmock_val_expected, TeaSpoon, \"Function 'TeaPot' called with unexpected value for argument 'TeaSpoon'.\");\n\n", - " }\n" - ].join - returned = @cmock_generator_utils.code_verify_an_arg_expectation(function, {:type => var_type, :name => var_name}) - assert_equal(expected, returned) + should 'call an argument loader when the function has arguments' do + function = { :name => "Pineapple", + :args_string => "stuff", + :args => [test_arg[:int_ptr], test_arg[:mytype], test_arg[:string]] + } + expected = " CMockExpectParameters_Pineapple(cmock_call_instance, MyIntPtr, (const MY_TYPE)MyMyType, (const char*)MyStr);\n" + assert_equal(expected, @cmock_generator_utils_simple.code_call_argument_loader(function)) end - should "make handle default types with memory compares, which involves extra work" do - function = { :name => "Toaster", :return_type => "uint64"} - var_type = "SOME_STRUCT" - var_name = "Bread" - - @cmock_generator_utils.helpers = {:unity_helper => @unity_helper} - @unity_helper.expect.get_helper(var_type).returns("TEST_ASSERT_EQUAL_MEMORY_MESSAGE") - - expected = ["\n", - " if (Mock.Toaster_Expected_Bread != Mock.Toaster_Expected_Bread_Tail)\n", - " {\n", - " SOME_STRUCT* cmock_val_expected = Mock.Toaster_Expected_Bread;\n", - " Mock.Toaster_Expected_Bread++;\n", - " TEST_ASSERT_EQUAL_MEMORY_MESSAGE((void*)cmock_val_expected, (void*)&(Bread), sizeof(SOME_STRUCT), \"Function 'Toaster' called with unexpected value for argument 'Bread'.\");\n\n", - " }\n" - ].join - returned = @cmock_generator_utils.code_verify_an_arg_expectation(function, {:type => var_type, :name => var_name}) - assert_equal(expected, returned) + should 'call an argument loader when the function has arguments with arrays' do + function = { :name => "Pineapple", + :args_string => "stuff", + :args => [test_arg[:int_ptr], test_arg[:mytype], test_arg[:string]] + } + expected = " CMockExpectParameters_Pineapple(cmock_call_instance, MyIntPtr, 1, (const MY_TYPE)MyMyType, (const char*)MyStr);\n" + assert_equal(expected, @cmock_generator_utils_complex.code_call_argument_loader(function)) + end + + should 'handle a simple assert when requested' do + function = { :name => 'Pear' } + arg = test_arg[:int] + expected = " TEST_ASSERT_EQUAL_INT_MESSAGE(cmock_call_instance->Expected_MyInt, MyInt, \"Function 'Pear' called with unexpected value for argument 'MyInt'.\");\n" + @unity_helper.expect.get_helper('int').returns('TEST_ASSERT_EQUAL_INT_MESSAGE') + assert_equal(expected, @cmock_generator_utils_simple.code_verify_an_arg_expectation(function, arg)) end - should "make handle default types with memory compares and arrays, which involves extra work" do - function = { :name => "Toaster", :return_type => "uint64"} - var_type = "SOME_STRUCT*" - var_name = "Bread" - - @cmock_generator_utils.helpers = {:unity_helper => @unity_helper} - @unity_helper.expect.get_helper(var_type).returns("TEST_ASSERT_EQUAL_MEMORY_MESSAGE_ARRAY") - - expected = ["\n", - " if (Mock.Toaster_Expected_Bread != Mock.Toaster_Expected_Bread_Tail)\n", - " {\n", - " SOME_STRUCT** cmock_val_expected = Mock.Toaster_Expected_Bread;\n", - " Mock.Toaster_Expected_Bread++;\n", - " if (*cmock_val_expected == NULL)\n", - " { TEST_ASSERT_NULL(Bread); }\n", - " else\n", - " { TEST_ASSERT_EQUAL_MEMORY_MESSAGE((void*)(*cmock_val_expected), (void*)Bread, sizeof(SOME_STRUCT), \"Function 'Toaster' called with unexpected value for argument 'Bread'.\"); }\n", - " }\n" - ].join - returned = @cmock_generator_utils.code_verify_an_arg_expectation(function, {:type => var_type, :name => var_name}) - assert_equal(expected, returned) + should 'handle a pointer comparison when configured to do so' do + function = { :name => 'Pear' } + arg = test_arg[:int_ptr] + expected = " TEST_ASSERT_EQUAL_HEX32_MESSAGE(cmock_call_instance->Expected_MyIntPtr, MyIntPtr, \"Function 'Pear' called with unexpected value for argument 'MyIntPtr'.\");\n" + assert_equal(expected, @cmock_generator_utils_simple.code_verify_an_arg_expectation(function, arg)) + end + + should 'handle const char as string compares ' do + function = { :name => 'Pear' } + arg = test_arg[:string] + expected = " TEST_ASSERT_EQUAL_STRING_MESSAGE(cmock_call_instance->Expected_MyStr, MyStr, \"Function 'Pear' called with unexpected value for argument 'MyStr'.\");\n" + @unity_helper.expect.get_helper('const char*').returns('TEST_ASSERT_EQUAL_STRING_MESSAGE') + assert_equal(expected, @cmock_generator_utils_simple.code_verify_an_arg_expectation(function, arg)) end - should "make handle default types with array compares, which involves extra work" do - function = { :name => "Blender", :return_type => "uint16*"} - var_type = "FRUIT*" - var_name = "Strawberry" - - @cmock_generator_utils.helpers = {:unity_helper => @unity_helper} - @unity_helper.expect.get_helper(var_type).returns("TEST_ASSERT_EQUAL_FRUIT_ARRAY") - - expected = ["\n", - " if (Mock.Blender_Expected_Strawberry != Mock.Blender_Expected_Strawberry_Tail)\n", - " {\n", - " FRUIT** cmock_val_expected = Mock.Blender_Expected_Strawberry;\n", - " Mock.Blender_Expected_Strawberry++;\n", - " if (*cmock_val_expected == NULL)\n", - " { TEST_ASSERT_NULL(Strawberry); }\n", - " else\n", - " { TEST_ASSERT_EQUAL_FRUIT_ARRAY(*cmock_val_expected, Strawberry, 1); }\n", - " }\n" - ].join - returned = @cmock_generator_utils.code_verify_an_arg_expectation(function, {:type => var_type, :name => var_name}) - assert_equal(expected, returned) + should 'handle custom types as memory compares when we have no better way to do it' do + function = { :name => 'Pear' } + arg = test_arg[:mytype] + expected = " TEST_ASSERT_EQUAL_MEMORY_MESSAGE((void*)(&cmock_call_instance->Expected_MyMyType), (void*)(&MyMyType), sizeof(const MY_TYPE), \"Function 'Pear' called with unexpected value for argument 'MyMyType'.\");\n" + @unity_helper.expect.get_helper('const MY_TYPE').returns('TEST_ASSERT_EQUAL_MEMORY_MESSAGE') + assert_equal(expected, @cmock_generator_utils_simple.code_verify_an_arg_expectation(function, arg)) + end + + should 'handle custom types with custom handlers when available, even if they do not support the extra message' do + function = { :name => 'Pear' } + arg = test_arg[:mytype] + expected = " TEST_ASSERT_EQUAL_MY_TYPE(cmock_call_instance->Expected_MyMyType, MyMyType);\n" + @unity_helper.expect.get_helper('const MY_TYPE').returns('TEST_ASSERT_EQUAL_MY_TYPE') + assert_equal(expected, @cmock_generator_utils_simple.code_verify_an_arg_expectation(function, arg)) end - should "make handle default types with array compares using smart mode but only a single item" do - function = { :name => "Blender", :return_type => "uint16*"} - var_type = "FRUIT*" - var_name = "Strawberry" - - @cmock_generator_utils.ptr_handling = :smart - @cmock_generator_utils.helpers = {:unity_helper => @unity_helper} - @unity_helper.expect.get_helper(var_type).returns("TEST_ASSERT_EQUAL_FRUIT_ARRAY") - - expected = ["\n", - " if (Mock.Blender_Expected_Strawberry != Mock.Blender_Expected_Strawberry_Tail)\n", - " {\n", - " FRUIT** cmock_val_expected = Mock.Blender_Expected_Strawberry;\n", - " Mock.Blender_Expected_Strawberry++;\n", - " if (*cmock_val_expected == NULL)\n", - " { TEST_ASSERT_NULL(Strawberry); }\n", - " else\n", - " { TEST_ASSERT_EQUAL_FRUIT_ARRAY(*cmock_val_expected, Strawberry, 1); }\n", - " }\n" - ].join - returned = @cmock_generator_utils.code_verify_an_arg_expectation(function, {:type => var_type, :name => var_name}) - assert_equal(expected, returned) + should 'handle custom types with array handlers, even if the array extension is turned off' do + function = { :name => 'Pear' } + arg = test_arg[:mytype_ptr] + expected = " if (cmock_call_instance->Expected_MyMyTypePtr == NULL)\n" + + " { TEST_ASSERT_NULL(MyMyTypePtr); }\n" + + " else\n" + + " { TEST_ASSERT_EQUAL_MY_TYPE_ARRAY(cmock_call_instance->Expected_MyMyTypePtr, MyMyTypePtr, 1); }\n" + @cmock_generator_utils_simple.ptr_handling = :smart + @unity_helper.expect.get_helper('MY_TYPE*').returns('TEST_ASSERT_EQUAL_MY_TYPE_ARRAY') + assert_equal(expected, @cmock_generator_utils_simple.code_verify_an_arg_expectation(function, arg)) + end + + should 'handle a simple assert when requested with array plugin enabled' do + function = { :name => 'Pear' } + arg = test_arg[:int] + expected = " TEST_ASSERT_EQUAL_INT_MESSAGE(cmock_call_instance->Expected_MyInt, MyInt, \"Function 'Pear' called with unexpected value for argument 'MyInt'.\");\n" + @unity_helper.expect.get_helper('int').returns('TEST_ASSERT_EQUAL_INT_MESSAGE') + assert_equal(expected, @cmock_generator_utils_complex.code_verify_an_arg_expectation(function, arg)) end - should "make handle default types when working in cmock_pointer only mode" do - function = { :name => "Blender", :return_type => "uint16*"} - var_type = "FRUIT*" - var_name = "Strawberry" - - @cmock_generator_utils.ptr_handling = :compare_ptr - @cmock_generator_utils.arrays = true - @cmock_generator_utils.helpers = {:unity_helper => @unity_helper} - - expected = ["\n", - " if (Mock.Blender_Expected_Strawberry != Mock.Blender_Expected_Strawberry_Tail)\n", - " {\n", - " FRUIT** cmock_val_expected = Mock.Blender_Expected_Strawberry;\n", - " Mock.Blender_Expected_Strawberry++;\n", - " TEST_ASSERT_EQUAL_HEX32_MESSAGE(*cmock_val_expected, Strawberry, \"Function 'Blender' called with unexpected value for argument 'Strawberry'.\");\n\n", - " }\n" - ].join - returned = @cmock_generator_utils.code_verify_an_arg_expectation(function, {:type => var_type, :name => var_name, :ptr? => true}) - assert_equal(expected, returned) + should 'handle an array comparison with array plugin enabled' do + function = { :name => 'Pear' } + arg = test_arg[:int_ptr] + expected = " if (cmock_call_instance->Expected_MyIntPtr == NULL)\n" + + " { TEST_ASSERT_NULL(MyIntPtr); }\n" + + " else if (cmock_call_instance->Expected_MyIntPtr_Depth == 0)\n" + + " { TEST_ASSERT_EQUAL_HEX32(cmock_call_instance->Expected_MyIntPtr, MyIntPtr); }\n" + + " else\n" + + " { TEST_ASSERT_EQUAL_INT_ARRAY(cmock_call_instance->Expected_MyIntPtr, MyIntPtr, cmock_call_instance->Expected_MyIntPtr_Depth); }\n" + @unity_helper.expect.get_helper('int*').returns('TEST_ASSERT_EQUAL_INT_ARRAY') + assert_equal(expected, @cmock_generator_utils_complex.code_verify_an_arg_expectation(function, arg)) end - should "make handle default types with array compares using array mode and multiple items" do - function = { :name => "Blender", :return_type => "uint16*"} - var_type = "FRUIT*" - var_name = "Strawberry" - - @cmock_generator_utils.ptr_handling = :compare_data - @cmock_generator_utils.arrays = true - @cmock_generator_utils.helpers = {:unity_helper => @unity_helper} - @unity_helper.expect.get_helper(var_type).returns("TEST_ASSERT_EQUAL_FRUIT_ARRAY") - - expected = ["\n", - " if (Mock.Blender_Expected_Strawberry != Mock.Blender_Expected_Strawberry_Tail)\n", - " {\n", - " FRUIT** cmock_val_expected = Mock.Blender_Expected_Strawberry;\n", - " Mock.Blender_Expected_Strawberry++;\n\n", - " int cmock_depth = *Mock.Blender_Expected_Strawberry_Depth;\n", - " Mock.Blender_Expected_Strawberry_Depth++;\n\n", - " if (*cmock_val_expected == NULL)\n", - " { TEST_ASSERT_NULL(Strawberry); }\n", - " else\n", - " { TEST_ASSERT_EQUAL_FRUIT_ARRAY(*cmock_val_expected, Strawberry, cmock_depth); }\n", - " }\n" - ].join - returned = @cmock_generator_utils.code_verify_an_arg_expectation(function, {:type => var_type, :name => var_name, :ptr? => true}) - assert_equal(expected, returned) + should 'handle const char as string compares with array plugin enabled' do + function = { :name => 'Pear' } + arg = test_arg[:string] + expected = " TEST_ASSERT_EQUAL_STRING_MESSAGE(cmock_call_instance->Expected_MyStr, MyStr, \"Function 'Pear' called with unexpected value for argument 'MyStr'.\");\n" + @unity_helper.expect.get_helper('const char*').returns('TEST_ASSERT_EQUAL_STRING_MESSAGE') + assert_equal(expected, @cmock_generator_utils_complex.code_verify_an_arg_expectation(function, arg)) end - should "make handle default types with array compares using smart mode and multiple items" do - function = { :name => "Blender", :return_type => "uint16*"} - var_type = "FRUIT*" - var_name = "Strawberry" - - @cmock_generator_utils.ptr_handling = :smart - @cmock_generator_utils.arrays = true - @cmock_generator_utils.helpers = {:unity_helper => @unity_helper} - @unity_helper.expect.get_helper(var_type).returns("TEST_ASSERT_EQUAL_FRUIT_ARRAY") - - expected = ["\n", - " if (Mock.Blender_Expected_Strawberry != Mock.Blender_Expected_Strawberry_Tail)\n", - " {\n", - " FRUIT** cmock_val_expected = Mock.Blender_Expected_Strawberry;\n", - " Mock.Blender_Expected_Strawberry++;\n\n", - " int cmock_depth = *Mock.Blender_Expected_Strawberry_Depth;\n", - " Mock.Blender_Expected_Strawberry_Depth++;\n\n", - " if (*cmock_val_expected == NULL)\n", - " { TEST_ASSERT_NULL(Strawberry); }\n", - " else if (cmock_depth == 0)\n", - " { TEST_ASSERT_EQUAL_HEX32(*cmock_val_expected, Strawberry); }\n", - " else\n", - " { TEST_ASSERT_EQUAL_FRUIT_ARRAY(*cmock_val_expected, Strawberry, cmock_depth); }\n", - " }\n" - ].join - returned = @cmock_generator_utils.code_verify_an_arg_expectation(function, {:type => var_type, :name => var_name, :ptr? => true}) - assert_equal(expected, returned) + should 'handle custom types as memory compares when we have no better way to do it with array plugin enabled' do + function = { :name => 'Pear' } + arg = test_arg[:mytype] + expected = " TEST_ASSERT_EQUAL_MEMORY_MESSAGE((void*)(&cmock_call_instance->Expected_MyMyType), (void*)(&MyMyType), sizeof(const MY_TYPE), \"Function 'Pear' called with unexpected value for argument 'MyMyType'.\");\n" + @unity_helper.expect.get_helper('const MY_TYPE').returns('TEST_ASSERT_EQUAL_MEMORY_MESSAGE') + assert_equal(expected, @cmock_generator_utils_complex.code_verify_an_arg_expectation(function, arg)) end + + should 'handle custom types with custom handlers when available, even if they do not support the extra message with array plugin enabled' do + function = { :name => 'Pear' } + arg = test_arg[:mytype] + expected = " TEST_ASSERT_EQUAL_MY_TYPE(cmock_call_instance->Expected_MyMyType, MyMyType);\n" + @unity_helper.expect.get_helper('const MY_TYPE').returns('TEST_ASSERT_EQUAL_MY_TYPE') + assert_equal(expected, @cmock_generator_utils_complex.code_verify_an_arg_expectation(function, arg)) + end + + should 'handle custom types with array handlers when array plugin is enabled' do + function = { :name => 'Pear' } + arg = test_arg[:mytype_ptr] + expected = " if (cmock_call_instance->Expected_MyMyTypePtr == NULL)\n" + + " { TEST_ASSERT_NULL(MyMyTypePtr); }\n" + + " else if (cmock_call_instance->Expected_MyMyTypePtr_Depth == 0)\n" + + " { TEST_ASSERT_EQUAL_HEX32(cmock_call_instance->Expected_MyMyTypePtr, MyMyTypePtr); }\n" + + " else\n" + + " { TEST_ASSERT_EQUAL_MY_TYPE_ARRAY(cmock_call_instance->Expected_MyMyTypePtr, MyMyTypePtr, cmock_call_instance->Expected_MyMyTypePtr_Depth); }\n" + @unity_helper.expect.get_helper('MY_TYPE*').returns('TEST_ASSERT_EQUAL_MY_TYPE_ARRAY') + assert_equal(expected, @cmock_generator_utils_complex.code_verify_an_arg_expectation(function, arg)) + end + + #This is not yet supported +# should 'handle custom types with array handlers when array plugin is enabled for non-array types' do +# function = { :name => 'Pear' } +# arg = test_arg[:mytype] +# expected = " TEST_ASSERT_EQUAL_MY_TYPE_ARRAY(&cmock_call_instance->Expected_MyMyType, &MyMyType, 1);\n" +# @unity_helper.expect.get_helper('const MY_TYPE').returns('TEST_ASSERT_EQUAL_MY_TYPE_ARRAY') +# assert_equal(expected, @cmock_generator_utils_complex.code_verify_an_arg_expectation(function, arg)) +# end end diff --git a/test/unit/cmock_header_parser_test.rb b/test/unit/cmock_header_parser_test.rb index 69ed4bf..07f87df 100644 --- a/test/unit/cmock_header_parser_test.rb +++ b/test/unit/cmock_header_parser_test.rb @@ -1,3 +1,5 @@ +$ThisIsOnlyATest = true + require File.expand_path(File.dirname(__FILE__)) + "/../test_helper" require 'cmock_header_parser' @@ -263,12 +265,17 @@ class CMockHeaderParserTest < Test::Unit::TestCase should "handle odd case of typedef'd void returned" do source = "MY_FUNKY_VOID FunkyVoidReturned(int a)" expected = { :var_arg=>nil, - :return_string=>"void cmock_to_return", :name=>"FunkyVoidReturned", - :return_type=>"void", + :return=>{ :type => "void", + :name => 'cmock_to_return', + :ptr? => false, + :const? => false, + :str => "void cmock_to_return", + :void? => true + }, :modifier=>"", :contains_ptr? => false, - :args=>[{:type=>"int", :name=>"a", :ptr? => false}], + :args=>[{:type=>"int", :name=>"a", :ptr? => false, :const? => false}], :args_string=>"int a" } assert_equal(expected, @parser.parse_declaration(source)) end @@ -276,9 +283,14 @@ class CMockHeaderParserTest < Test::Unit::TestCase should "handle odd case of typedef'd void as arg" do source = "int FunkyVoidAsArg(MY_FUNKY_VOID)" expected = { :var_arg=>nil, - :return_string=>"int cmock_to_return", :name=>"FunkyVoidAsArg", - :return_type=>"int", + :return=>{ :type => "int", + :name => 'cmock_to_return', + :ptr? => false, + :const? => false, + :str => "int cmock_to_return", + :void? => false + }, :modifier=>"", :contains_ptr? => false, :args=>[], @@ -289,12 +301,17 @@ class CMockHeaderParserTest < Test::Unit::TestCase should "handle odd case of typedef'd void as arg pointer" do source = "char FunkyVoidPointer(MY_FUNKY_VOID* bluh)" expected = { :var_arg=>nil, - :return_string=>"char cmock_to_return", :name=>"FunkyVoidPointer", - :return_type=>"char", + :return=>{ :type => "char", + :name => 'cmock_to_return', + :ptr? => false, + :const? => false, + :str => "char cmock_to_return", + :void? => false + }, :modifier=>"", :contains_ptr? => true, - :args=>[{:type=>"MY_FUNKY_VOID*", :name=>"bluh", :ptr? => true}], + :args=>[{:type=>"MY_FUNKY_VOID*", :name=>"bluh", :ptr? => true, :const? => false}], :args_string=>"MY_FUNKY_VOID* bluh" } assert_equal(expected, @parser.parse_declaration(source)) end @@ -375,13 +392,18 @@ class CMockHeaderParserTest < Test::Unit::TestCase source = "int Foo(int a, unsigned int b)" expected = { :var_arg=>nil, - :return_string=>"int cmock_to_return", :name=>"Foo", - :return_type=>"int", + :return=>{ :type => "int", + :name => 'cmock_to_return', + :ptr? => false, + :const? => false, + :str => "int cmock_to_return", + :void? => false + }, :modifier=>"", :contains_ptr? => false, - :args=>[ {:type=>"int", :name=>"a", :ptr? => false}, - {:type=>"unsigned int", :name=>"b", :ptr? => false} + :args=>[ {:type=>"int", :name=>"a", :ptr? => false, :const? => false}, + {:type=>"unsigned int", :name=>"b", :ptr? => false, :const? => false} ], :args_string=>"int a, unsigned int b" } assert_equal(expected, @parser.parse_declaration(source)) @@ -391,14 +413,19 @@ class CMockHeaderParserTest < Test::Unit::TestCase source = "void FunkyChicken( uint la, int de, bool da)" expected = { :var_arg=>nil, - :return_string=>"void cmock_to_return", + :return=>{ :type => "void", + :name => 'cmock_to_return', + :ptr? => false, + :const? => false, + :str => "void cmock_to_return", + :void? => true + }, :name=>"FunkyChicken", - :return_type=>"void", :modifier=>"", :contains_ptr? => false, - :args=>[ {:type=>"uint", :name=>"la", :ptr? => false}, - {:type=>"int", :name=>"de", :ptr? => false}, - {:type=>"bool", :name=>"da", :ptr? => false} + :args=>[ {:type=>"uint", :name=>"la", :ptr? => false, :const? => false}, + {:type=>"int", :name=>"de", :ptr? => false, :const? => false}, + {:type=>"bool", :name=>"da", :ptr? => false, :const? => false} ], :args_string=>"uint la, int de, bool da" } assert_equal(expected, @parser.parse_declaration(source)) @@ -408,9 +435,14 @@ class CMockHeaderParserTest < Test::Unit::TestCase source = "void tat()" expected = { :var_arg=>nil, - :return_string=>"void cmock_to_return", + :return=>{ :type => "void", + :name => 'cmock_to_return', + :ptr? => false, + :const? => false, + :str => "void cmock_to_return", + :void? => true + }, :name=>"tat", - :return_type=>"void", :modifier=>"", :contains_ptr? => false, :args=>[ ], @@ -422,13 +454,18 @@ class CMockHeaderParserTest < Test::Unit::TestCase source = "const int TheMatrix(int Trinity, unsigned int * Neo)" expected = { :var_arg=>nil, - :return_string=>"int cmock_to_return", + :return=>{ :type => "int", + :name => 'cmock_to_return', + :ptr? => false, + :const? => false, + :str => "int cmock_to_return", + :void? => false + }, :name=>"TheMatrix", - :return_type=>"int", :modifier=>"const", :contains_ptr? => true, - :args=>[ {:type=>"int", :name=>"Trinity", :ptr? => false}, - {:type=>"unsigned int*", :name=>"Neo", :ptr? => true} + :args=>[ {:type=>"int", :name=>"Trinity", :ptr? => false, :const? => false}, + {:type=>"unsigned int*", :name=>"Neo", :ptr? => true, :const? => false} ], :args_string=>"int Trinity, unsigned int* Neo" } assert_equal(expected, @parser.parse_declaration(source)) @@ -440,23 +477,33 @@ class CMockHeaderParserTest < Test::Unit::TestCase "int Morpheus(int, unsigned int*);\n" expected = [{ :var_arg=>nil, - :return_string=>"int cmock_to_return", + :return=> { :type => "int", + :name => 'cmock_to_return', + :ptr? => false, + :const? => false, + :str => "int cmock_to_return", + :void? => false + }, :name=>"TheMatrix", - :return_type=>"int", :modifier=>"const", :contains_ptr? => true, - :args=>[ {:type=>"int", :name=>"Trinity", :ptr? => false}, - {:type=>"unsigned int*", :name=>"Neo", :ptr? => true} + :args=>[ {:type=>"int", :name=>"Trinity", :ptr? => false, :const? => false}, + {:type=>"unsigned int*", :name=>"Neo", :ptr? => true, :const? => false} ], :args_string=>"int Trinity, unsigned int* Neo" }, { :var_arg=>nil, - :return_string=>"int cmock_to_return", + :return=> { :type => "int", + :name => 'cmock_to_return', + :ptr? => false, + :const? => false, + :str => "int cmock_to_return", + :void? => false + }, :name=>"Morpheus", - :return_type=>"int", :modifier=>"", :contains_ptr? => true, - :args=>[ {:type=>"int", :name=>"cmock_arg1", :ptr? => false}, - {:type=>"unsigned int*", :name=>"cmock_arg2", :ptr? => true} + :args=>[ {:type=>"int", :name=>"cmock_arg1", :ptr? => false, :const? => false}, + {:type=>"unsigned int*", :name=>"cmock_arg2", :ptr? => true, :const? => false} ], :args_string=>"int cmock_arg1, unsigned int* cmock_arg2" }] @@ -469,13 +516,18 @@ class CMockHeaderParserTest < Test::Unit::TestCase "const int TheMatrix(int, unsigned int*);\n" expected = [{ :var_arg=>nil, - :return_string=>"int cmock_to_return", :name=>"TheMatrix", - :return_type=>"int", + :return=> { :type => "int", + :name => 'cmock_to_return', + :ptr? => false, + :const? => false, + :str => "int cmock_to_return", + :void? => false + }, :modifier=>"const", :contains_ptr? => true, - :args=>[ {:type=>"int", :name=>"Trinity", :ptr? => false}, - {:type=>"unsigned int*", :name=>"Neo", :ptr? => true} + :args=>[ {:type=>"int", :name=>"Trinity", :ptr? => false, :const? => false}, + {:type=>"unsigned int*", :name=>"Neo", :ptr? => true, :const? => false} ], :args_string=>"int Trinity, unsigned int* Neo" }] @@ -490,18 +542,28 @@ class CMockHeaderParserTest < Test::Unit::TestCase "int CaptainHammer(CHUNKY_VOID_T);\n" expected = [{ :var_arg=>nil, - :return_string=>"void cmock_to_return", :name=>"DrHorrible", - :return_type=>"void", + :return => { :type => "void", + :name => 'cmock_to_return', + :ptr? => false, + :const? => false, + :str => "void cmock_to_return", + :void? => true + }, :modifier=>"", - :contains_ptr? => false, - :args=>[ {:type=>"int", :name=>"SingAlong", :ptr? => false} ], + :contains_ptr? => false, + :args=>[ {:type=>"int", :name=>"SingAlong", :ptr? => false, :const? => false} ], :args_string=>"int SingAlong" }, { :var_arg=>nil, - :return_string=>"int cmock_to_return", + :return=> { :type => "int", + :name => 'cmock_to_return', + :ptr? => false, + :const? => false, + :str => "int cmock_to_return", + :void? => false + }, :name=>"CaptainHammer", - :return_type=>"int", :modifier=>"", :contains_ptr? => false, :args=>[ ], @@ -517,27 +579,42 @@ class CMockHeaderParserTest < Test::Unit::TestCase "struct TheseArentTheHammer CaptainHammer(void);\n" expected = [{ :var_arg=>nil, - :return_string=>"int cmock_to_return", + :return =>{ :type => "int", + :name => 'cmock_to_return', + :ptr? => false, + :const? => false, + :str => "int cmock_to_return", + :void? => false + }, :name=>"DrHorrible", - :return_type=>"int", :modifier=>"", :contains_ptr? => false, - :args=>[ {:type=>"struct SingAlong", :name=>"Blog", :ptr? => false} ], + :args=>[ {:type=>"struct SingAlong", :name=>"Blog", :ptr? => false, :const? => false} ], :args_string=>"struct SingAlong Blog" }, { :var_arg=>nil, - :return_string=>"void cmock_to_return", + :return=> { :type => "void", + :name => 'cmock_to_return', + :ptr? => false, + :const? => false, + :str => "void cmock_to_return", + :void? => true + }, :name=>"Penny", - :return_type=>"void", :modifier=>"", :contains_ptr? => true, - :args=>[ {:type=>"struct _KeepYourHeadUp_*", :name=>"BillyBuddy", :ptr? => true} ], + :args=>[ {:type=>"struct _KeepYourHeadUp_*", :name=>"BillyBuddy", :ptr? => true, :const? => true} ], :args_string=>"struct const _KeepYourHeadUp_* const BillyBuddy" }, { :var_arg=>nil, - :return_string=>"struct TheseArentTheHammer cmock_to_return", + :return=> { :type => "struct TheseArentTheHammer", + :name => 'cmock_to_return', + :ptr? => false, + :const? => false, + :str => "struct TheseArentTheHammer cmock_to_return", + :void? => false + }, :name=>"CaptainHammer", - :return_type=>"struct TheseArentTheHammer", :modifier=>"", :contains_ptr? => false, :args=>[ ], @@ -550,13 +627,18 @@ class CMockHeaderParserTest < Test::Unit::TestCase source = "int XFiles(int Scully, int Mulder, ...);\n" expected = [{ :var_arg=>"...", - :return_string=>"int cmock_to_return", + :return=> { :type => "int", + :name => 'cmock_to_return', + :ptr? => false, + :const? => false, + :str => "int cmock_to_return", + :void? => false + }, :name=>"XFiles", - :return_type=>"int", :modifier=>"", :contains_ptr? => false, - :args=>[ {:type=>"int", :name=>"Scully", :ptr? => false}, - {:type=>"int", :name=>"Mulder", :ptr? => false} + :args=>[ {:type=>"int", :name=>"Scully", :ptr? => false, :const? => false}, + {:type=>"int", :name=>"Mulder", :ptr? => false, :const? => false} ], :args_string=>"int Scully, int Mulder" }] diff --git a/test/unit/cmock_unityhelper_parser_test.rb b/test/unit/cmock_unityhelper_parser_test.rb index 12be59f..b65cf50 100644 --- a/test/unit/cmock_unityhelper_parser_test.rb +++ b/test/unit/cmock_unityhelper_parser_test.rb @@ -15,7 +15,6 @@ class CMockUnityHelperParserTest < Test::Unit::TestCase " abcd;\n" + "// #define TEST_ASSERT_EQUAL_CHICKENS(a,b) {...};\n" + "or maybe // #define TEST_ASSERT_EQUAL_CHICKENS(a,b) {...};\n\n" - @config.expects.standard_treat_as_map.returns({}) @config.expects.treat_as.returns({}) @config.expects.load_unity_helper.returns(source) @parser = CMockUnityHelperParser.new(@config) @@ -29,7 +28,6 @@ class CMockUnityHelperParserTest < Test::Unit::TestCase " abcd; /*\n" + "#define TEST_ASSERT_EQUAL_CHICKENS(a,b) {...};\n" + "#define TEST_ASSERT_EQUAL_CHICKENS(a,b) {...};\n */\n" - @config.expects.standard_treat_as_map.returns({}) @config.expects.treat_as.returns({}) @config.expect.load_unity_helper.returns(source) @parser = CMockUnityHelperParser.new(@config) @@ -47,7 +45,6 @@ class CMockUnityHelperParserTest < Test::Unit::TestCase "#define TEST_ASSERT_WRONG_NAME_EQUAL(a,b) {...};\n" + "#define TEST_ASSERT_EQUAL_unsigned_funky_rabbits(a,b) {...};\n" + "abcd;\n" - @config.expects.standard_treat_as_map.returns({}) @config.expects.treat_as.returns({}) @config.expect.load_unity_helper.returns(source) @parser = CMockUnityHelperParser.new(@config) @@ -68,7 +65,6 @@ class CMockUnityHelperParserTest < Test::Unit::TestCase "#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.standard_treat_as_map.returns({}) @config.expects.treat_as.returns({}) @config.expect.load_unity_helper.returns(source) @parser = CMockUnityHelperParser.new(@config) @@ -89,8 +85,7 @@ class CMockUnityHelperParserTest < Test::Unit::TestCase "UINT" => "TEST_ASSERT_EQUAL_HEX32_MESSAGE", "unsigned_long" => "TEST_ASSERT_EQUAL_HEX64_MESSAGE", } - @config.expects.standard_treat_as_map.returns(pairs) - @config.expects.treat_as.returns({}) + @config.expects.treat_as.returns(pairs) @config.expect.load_unity_helper.returns(nil) @parser = CMockUnityHelperParser.new(@config) @@ -106,7 +101,6 @@ class CMockUnityHelperParserTest < Test::Unit::TestCase "char*" => "TEST_ASSERT_EQUAL_STRING_MESSAGE", "unsigned_int" => "TEST_ASSERT_EQUAL_HEX32_MESSAGE", } - @config.expects.standard_treat_as_map.returns({}) @config.expects.treat_as.returns(pairs) @config.expect.load_unity_helper.returns(nil) @parser = CMockUnityHelperParser.new(@config) @@ -114,33 +108,7 @@ class CMockUnityHelperParserTest < Test::Unit::TestCase assert_equal(expected, @parser.c_types) end - should "merge standard and user specified helper into my list" do - default = { - "UINT" => "HEX32", - "unsigned int" => "HEX32", - } - user = { - "int" => "INT", - "unsigned char" => "HEX8", - } - source = "#define TEST_ASSERT_EQUAL_TURKEYS_ARRAY(a,b,c) {...};\n" - expected = { - "UINT" => "TEST_ASSERT_EQUAL_HEX32_MESSAGE", - "unsigned_int" => "TEST_ASSERT_EQUAL_HEX32_MESSAGE", - "int" => "TEST_ASSERT_EQUAL_INT_MESSAGE", - "unsigned_char" => "TEST_ASSERT_EQUAL_HEX8_MESSAGE", - "TURKEYS*" => "TEST_ASSERT_EQUAL_TURKEYS_ARRAY", - } - @config.expects.standard_treat_as_map.returns(default) - @config.expects.treat_as.returns(user) - @config.expect.load_unity_helper.returns(source) - @parser = CMockUnityHelperParser.new(@config) - - assert_equal(expected, @parser.c_types) - end - should "be able to fetch helpers on my list" do - @config.expects.standard_treat_as_map.returns({}) @config.expects.treat_as.returns({}) @config.expect.load_unity_helper.returns("") @parser = CMockUnityHelperParser.new(@config) @@ -160,7 +128,6 @@ class CMockUnityHelperParserTest < Test::Unit::TestCase end should "return memory comparison when asked to fetch helper of types not on my list" do - @config.expects.standard_treat_as_map.returns({}) @config.expects.treat_as.returns({}) @config.expects.load_unity_helper.returns("") @parser = CMockUnityHelperParser.new(@config) @@ -182,7 +149,6 @@ class CMockUnityHelperParserTest < Test::Unit::TestCase end should "raise error when asked to fetch helper of type not on my list and not allowed to mem check" do - @config.expects.standard_treat_as_map.returns({}) @config.expects.treat_as.returns({}) @config.expect.load_unity_helper.returns("") @config.expect.memcmp_if_unknown.returns(false)