Merge pull request #237 from jlindgren90/ignore-with-callback-2

Add CheckWithCallback and IgnoreWithCallback.
This commit is contained in:
Mark VanderVoord
2019-09-09 10:44:54 -04:00
committed by GitHub
3 changed files with 109 additions and 88 deletions
+16 -7
View File
@@ -196,19 +196,28 @@ Callback:
If all those other options don't work, and you really need to do something custom, you
still have a choice. As soon as you stub a callback in a test, it will call the callback
whenever the mock is encountered and return the retval returned from the callback (if any)
instead of performing the usual expect checks. It can be configured to check the arguments
first (like expects) or just jump directly to the callback.
whenever the mock is encountered and return the retval returned from the callback (if any).
* `void func(void)` => `void func_StubWithCallback(CMOCK_func_CALLBACK callback)`
* `void func(void)` => `void func_[Check,Ignore]WithCallback(CMOCK_func_CALLBACK callback)`
where `CMOCK_func_CALLBACK` looks like: `void func(int NumCalls)`
* `void func(params)` => `void func_StubWithCallback(CMOCK_func_CALLBACK callback)`
* `void func(params)` => `void func_[Check,Ignore]WithCallback(CMOCK_func_CALLBACK callback)`
where `CMOCK_func_CALLBACK` looks like: `void func(params, int NumCalls)`
* `retval func(void)` => `void func_StubWithCallback(CMOCK_func_CALLBACK callback)`
* `retval func(void)` => `void func_[Check,Ignore]WithCallback(CMOCK_func_CALLBACK callback)`
where `CMOCK_func_CALLBACK` looks like: `retval func(int NumCalls)`
* `retval func(params)` => `void func_StubWithCallback(CMOCK_func_CALLBACK callback)`
* `retval func(params)` => `void func_[Check,Ignore]WithCallback(CMOCK_func_CALLBACK callback)`
where `CMOCK_func_CALLBACK` looks like: `retval func(params, int NumCalls)`
You can choose from two options:
* `func_CheckWithCallback` tells the mock to check its arguments and calling
order (based on any Expects you've set up) before calling the callback.
* `func_IgnoreWithCallback` tells the mock to skip all the normal checks (just
like Ignore) and jump directly to the callback instead.
There is also an older name, `func_StubWithCallback`, which is just an alias for
either `func_CheckWithCallback` or `func_IgnoreWithCallback` depending on
setting of the `:callback_after_arg_check` toggle.
Cexception:
-----------
+38 -48
View File
@@ -16,78 +16,68 @@ class CMockGeneratorPluginCallback
@priority = 6
@include_count = @config.callback_include_count
if (@config.callback_after_arg_check)
alias :mock_implementation :mock_implementation_for_callbacks_after_arg_check
alias :mock_implementation_precheck :nothing
else
alias :mock_implementation_precheck :mock_implementation_for_callbacks_without_arg_check
alias :mock_implementation :nothing
end
end
def instance_structure(function)
func_name = function[:name]
" CMOCK_#{func_name}_CALLBACK #{func_name}_CallbackFunctionPointer;\n" +
" int #{func_name}_IgnoreWithCallbackBool;\n" \
" CMOCK_#{func_name}_CALLBACK #{func_name}_CallbackFunctionPointer;\n" \
" int #{func_name}_CallbackCalls;\n"
end
def mock_function_declarations(function)
func_name = function[:name]
return_type = function[:return][:type]
action = @config.callback_after_arg_check ? 'Check' : 'Ignore'
style = (@include_count ? 1 : 0) | (function[:args].empty? ? 0 : 2)
styles = [ "void", "int cmock_num_calls", function[:args_string], "#{function[:args_string]}, int cmock_num_calls" ]
"typedef #{return_type} (* CMOCK_#{func_name}_CALLBACK)(#{styles[style]});\nvoid #{func_name}_StubWithCallback(CMOCK_#{func_name}_CALLBACK Callback);\n"
"typedef #{return_type} (* CMOCK_#{func_name}_CALLBACK)(#{styles[style]});\n" \
"void #{func_name}_CheckWithCallback(CMOCK_#{func_name}_CALLBACK Callback);\n" \
"void #{func_name}_IgnoreWithCallback(CMOCK_#{func_name}_CALLBACK Callback);\n" \
"#define #{func_name}_StubWithCallback #{func_name}_#{action}WithCallback\n"
end
def mock_implementation_for_callbacks_after_arg_check(function)
func_name = function[:name]
style = (@include_count ? 1 : 0) | (function[:args].empty? ? 0 : 2) | (function[:return][:void?] ? 0 : 4)
" if (Mock.#{func_name}_CallbackFunctionPointer != NULL)\n {\n" +
case(style)
when 0 then " Mock.#{func_name}_CallbackFunctionPointer();\n }\n"
when 1 then " Mock.#{func_name}_CallbackFunctionPointer(Mock.#{func_name}_CallbackCalls++);\n }\n"
when 2 then " Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')});\n }\n"
when 3 then " Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')}, Mock.#{func_name}_CallbackCalls++);\n }\n"
when 4 then " cmock_call_instance->ReturnVal = Mock.#{func_name}_CallbackFunctionPointer();\n }\n"
when 5 then " cmock_call_instance->ReturnVal = Mock.#{func_name}_CallbackFunctionPointer(Mock.#{func_name}_CallbackCalls++);\n }\n"
when 6 then " cmock_call_instance->ReturnVal = Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')});\n }\n"
when 7 then " cmock_call_instance->ReturnVal = Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')}, Mock.#{func_name}_CallbackCalls++);\n }\n"
end
def generate_call(function)
args = function[:args].map { |m| m[:name] }
args << "Mock.#{function[:name]}_CallbackCalls++" if @include_count
"Mock.#{function[:name]}_CallbackFunctionPointer(#{args.join(', ')})"
end
def mock_implementation_for_callbacks_without_arg_check(function)
func_name = function[:name]
style = (@include_count ? 1 : 0) | (function[:args].empty? ? 0 : 2) | (function[:return][:void?] ? 0 : 4)
" if (Mock.#{func_name}_CallbackFunctionPointer != NULL)\n {\n" +
case(style)
when 0 then " Mock.#{func_name}_CallbackFunctionPointer();\n return;\n }\n"
when 1 then " Mock.#{func_name}_CallbackFunctionPointer(Mock.#{func_name}_CallbackCalls++);\n return;\n }\n"
when 2 then " Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')});\n return;\n }\n"
when 3 then " Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')}, Mock.#{func_name}_CallbackCalls++);\n return;\n }\n"
when 4 then " return Mock.#{func_name}_CallbackFunctionPointer();\n }\n"
when 5 then " return Mock.#{func_name}_CallbackFunctionPointer(Mock.#{func_name}_CallbackCalls++);\n }\n"
when 6 then " return Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')});\n }\n"
when 7 then " return Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')}, Mock.#{func_name}_CallbackCalls++);\n }\n"
end
def mock_implementation(function)
" if (Mock.#{function[:name]}_CallbackFunctionPointer != NULL)\n {\n" +
if function[:return][:void?]
" #{generate_call(function)};\n }\n"
else
" cmock_call_instance->ReturnVal = #{generate_call(function)};\n }\n"
end
end
def nothing(function)
return ""
def mock_implementation_precheck(function)
" if (Mock.#{function[:name]}_IgnoreWithCallbackBool &&\n" \
" Mock.#{function[:name]}_CallbackFunctionPointer != NULL)\n {\n" +
if function[:return][:void?]
" #{generate_call(function)};\n" \
" UNITY_CLR_DETAILS();\n" \
" return;\n }\n"
else
" #{function[:return][:type]} ret = #{generate_call(function)};\n" \
" UNITY_CLR_DETAILS();\n" \
" return ret;\n }\n"
end
end
def mock_interfaces(function)
func_name = function[:name]
has_ignore = @config.plugins.include? :ignore
lines = ""
lines << "void #{func_name}_StubWithCallback(CMOCK_#{func_name}_CALLBACK Callback)\n{\n"
if @config.plugins.include? :ignore
lines << " Mock.#{func_name}_IgnoreBool = (int)0;\n"
end
lines << "void #{func_name}_CheckWithCallback(CMOCK_#{func_name}_CALLBACK Callback)\n{\n"
lines << " Mock.#{func_name}_IgnoreBool = (int)0;\n" if has_ignore
lines << " Mock.#{func_name}_IgnoreWithCallbackBool = (int)0;\n"
lines << " Mock.#{func_name}_CallbackFunctionPointer = Callback;\n}\n\n"
lines << "void #{func_name}_IgnoreWithCallback(CMOCK_#{func_name}_CALLBACK Callback)\n{\n"
lines << " Mock.#{func_name}_IgnoreBool = (int)0;\n" if has_ignore
lines << " Mock.#{func_name}_IgnoreWithCallbackBool = (int)1;\n"
lines << " Mock.#{func_name}_CallbackFunctionPointer = Callback;\n}\n\n"
end
def mock_destroy(function)
" Mock.#{function[:name]}_CallbackFunctionPointer = NULL;\n" +
" Mock.#{function[:name]}_CallbackCalls = 0;\n"
end
def mock_verify(function)
@@ -32,7 +32,8 @@ describe CMockGeneratorPluginCallback, "Verify CMockGeneratorPluginCallback Modu
it "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" +
expected = " int Oak_IgnoreWithCallbackBool;\n" +
" CMOCK_Oak_CALLBACK Oak_CallbackFunctionPointer;\n" +
" int Oak_CallbackCalls;\n"
returned = @cmock_generator_plugin_callback.instance_structure(function)
assert_equal(expected, returned)
@@ -41,7 +42,9 @@ describe CMockGeneratorPluginCallback, "Verify CMockGeneratorPluginCallback Modu
it "add mock function declaration for function without arguments" do
function = {:name => "Maple", :args_string => "void", :args => [], :return => test_return[:void]}
expected = [ "typedef void (* CMOCK_Maple_CALLBACK)(int cmock_num_calls);\n",
"void Maple_StubWithCallback(CMOCK_Maple_CALLBACK Callback);\n" ].join
"void Maple_CheckWithCallback(CMOCK_Maple_CALLBACK Callback);\n",
"void Maple_IgnoreWithCallback(CMOCK_Maple_CALLBACK Callback);\n",
"#define Maple_StubWithCallback Maple_IgnoreWithCallback\n" ].join
returned = @cmock_generator_plugin_callback.mock_function_declarations(function)
assert_equal(expected, returned)
end
@@ -49,7 +52,9 @@ describe CMockGeneratorPluginCallback, "Verify CMockGeneratorPluginCallback Modu
it "add mock function declaration for function without arguments when count is also turned off" do
function = {:name => "Maple", :args_string => "void", :args => [], :return => test_return[:void]}
expected = [ "typedef void (* CMOCK_Maple_CALLBACK)(void);\n",
"void Maple_StubWithCallback(CMOCK_Maple_CALLBACK Callback);\n" ].join
"void Maple_CheckWithCallback(CMOCK_Maple_CALLBACK Callback);\n",
"void Maple_IgnoreWithCallback(CMOCK_Maple_CALLBACK Callback);\n",
"#define Maple_StubWithCallback Maple_IgnoreWithCallback\n" ].join
@cmock_generator_plugin_callback.include_count = false
returned = @cmock_generator_plugin_callback.mock_function_declarations(function)
assert_equal(expected, returned)
@@ -58,7 +63,9 @@ describe CMockGeneratorPluginCallback, "Verify CMockGeneratorPluginCallback Modu
it "add mock function declaration for function with arguments" do
function = {:name => "Maple", :args_string => "int* tofu", :args => [1], :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
"void Maple_CheckWithCallback(CMOCK_Maple_CALLBACK Callback);\n",
"void Maple_IgnoreWithCallback(CMOCK_Maple_CALLBACK Callback);\n",
"#define Maple_StubWithCallback Maple_IgnoreWithCallback\n" ].join
returned = @cmock_generator_plugin_callback.mock_function_declarations(function)
assert_equal(expected, returned)
end
@@ -66,7 +73,9 @@ describe CMockGeneratorPluginCallback, "Verify CMockGeneratorPluginCallback Modu
it "add mock function declaration for function with return values" do
function = {:name => "Maple", :args_string => "int* tofu", :args => [1], :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
"void Maple_CheckWithCallback(CMOCK_Maple_CALLBACK Callback);\n",
"void Maple_IgnoreWithCallback(CMOCK_Maple_CALLBACK Callback);\n",
"#define Maple_StubWithCallback Maple_IgnoreWithCallback\n" ].join
returned = @cmock_generator_plugin_callback.mock_function_declarations(function)
assert_equal(expected, returned)
end
@@ -74,7 +83,9 @@ describe CMockGeneratorPluginCallback, "Verify CMockGeneratorPluginCallback Modu
it "add mock function declaration for function with return values and count is turned off" do
function = {:name => "Maple", :args_string => "int* tofu", :args => [1], :return => test_return[:string]}
expected = [ "typedef const char* (* CMOCK_Maple_CALLBACK)(int* tofu);\n",
"void Maple_StubWithCallback(CMOCK_Maple_CALLBACK Callback);\n" ].join
"void Maple_CheckWithCallback(CMOCK_Maple_CALLBACK Callback);\n",
"void Maple_IgnoreWithCallback(CMOCK_Maple_CALLBACK Callback);\n",
"#define Maple_StubWithCallback Maple_IgnoreWithCallback\n" ].join
@cmock_generator_plugin_callback.include_count = false
returned = @cmock_generator_plugin_callback.mock_function_declarations(function)
assert_equal(expected, returned)
@@ -87,7 +98,7 @@ describe CMockGeneratorPluginCallback, "Verify CMockGeneratorPluginCallback Modu
" Mock.Apple_CallbackFunctionPointer(Mock.Apple_CallbackCalls++);\n",
" }\n"
].join
returned = @cmock_generator_plugin_callback.mock_implementation_for_callbacks_after_arg_check(function)
returned = @cmock_generator_plugin_callback.mock_implementation(function)
assert_equal(expected, returned)
end
@@ -99,7 +110,7 @@ describe CMockGeneratorPluginCallback, "Verify CMockGeneratorPluginCallback Modu
" }\n"
].join
@cmock_generator_plugin_callback.include_count = false
returned = @cmock_generator_plugin_callback.mock_implementation_for_callbacks_after_arg_check(function)
returned = @cmock_generator_plugin_callback.mock_implementation(function)
assert_equal(expected, returned)
end
@@ -110,7 +121,7 @@ describe CMockGeneratorPluginCallback, "Verify CMockGeneratorPluginCallback Modu
" cmock_call_instance->ReturnVal = Mock.Apple_CallbackFunctionPointer(Mock.Apple_CallbackCalls++);\n",
" }\n"
].join
returned = @cmock_generator_plugin_callback.mock_implementation_for_callbacks_after_arg_check(function)
returned = @cmock_generator_plugin_callback.mock_implementation(function)
assert_equal(expected, returned)
end
@@ -125,7 +136,7 @@ describe CMockGeneratorPluginCallback, "Verify CMockGeneratorPluginCallback Modu
" Mock.Apple_CallbackFunctionPointer(steak, flag, Mock.Apple_CallbackCalls++);\n",
" }\n"
].join
returned = @cmock_generator_plugin_callback.mock_implementation_for_callbacks_after_arg_check(function)
returned = @cmock_generator_plugin_callback.mock_implementation(function)
assert_equal(expected, returned)
end
@@ -141,7 +152,7 @@ describe CMockGeneratorPluginCallback, "Verify CMockGeneratorPluginCallback Modu
" }\n"
].join
@cmock_generator_plugin_callback.include_count = false
returned = @cmock_generator_plugin_callback.mock_implementation_for_callbacks_after_arg_check(function)
returned = @cmock_generator_plugin_callback.mock_implementation(function)
assert_equal(expected, returned)
end
@@ -156,31 +167,36 @@ describe CMockGeneratorPluginCallback, "Verify CMockGeneratorPluginCallback Modu
" cmock_call_instance->ReturnVal = Mock.Apple_CallbackFunctionPointer(steak, flag, Mock.Apple_CallbackCalls++);\n",
" }\n"
].join
returned = @cmock_generator_plugin_callback.mock_implementation_for_callbacks_after_arg_check(function)
returned = @cmock_generator_plugin_callback.mock_implementation(function)
assert_equal(expected, returned)
end
it "add mock function implementation for functions without arg check and of style 'void func(void)' when count turned off" do
function = {:name => "Apple", :args => [], :args_string => "void", :return => test_return[:void]}
expected = [" if (Mock.Apple_CallbackFunctionPointer != NULL)\n",
expected = [" if (Mock.Apple_IgnoreWithCallbackBool &&\n",
" Mock.Apple_CallbackFunctionPointer != NULL)\n",
" {\n",
" Mock.Apple_CallbackFunctionPointer();\n",
" UNITY_CLR_DETAILS();\n",
" return;\n",
" }\n"
].join
@cmock_generator_plugin_callback.include_count = false
returned = @cmock_generator_plugin_callback.mock_implementation_for_callbacks_without_arg_check(function)
returned = @cmock_generator_plugin_callback.mock_implementation_precheck(function)
assert_equal(expected, returned)
end
it "add mock function implementation for functions without arg check and of style 'int func(void)'" do
function = {:name => "Apple", :args => [], :args_string => "void", :return => test_return[:int]}
expected = [" if (Mock.Apple_CallbackFunctionPointer != NULL)\n",
expected = [" if (Mock.Apple_IgnoreWithCallbackBool &&\n",
" Mock.Apple_CallbackFunctionPointer != NULL)\n",
" {\n",
" return Mock.Apple_CallbackFunctionPointer(Mock.Apple_CallbackCalls++);\n",
" int ret = Mock.Apple_CallbackFunctionPointer(Mock.Apple_CallbackCalls++);\n",
" UNITY_CLR_DETAILS();\n",
" return ret;\n",
" }\n"
].join
returned = @cmock_generator_plugin_callback.mock_implementation_for_callbacks_without_arg_check(function)
returned = @cmock_generator_plugin_callback.mock_implementation_precheck(function)
assert_equal(expected, returned)
end
@@ -190,13 +206,15 @@ describe CMockGeneratorPluginCallback, "Verify CMockGeneratorPluginCallback Modu
{ :type => 'uint8_t', :name => 'flag', :ptr? => false} ],
:args_string => "int* steak, uint8_t flag",
:return=> test_return[:void]}
expected = [" if (Mock.Apple_CallbackFunctionPointer != NULL)\n",
expected = [" if (Mock.Apple_IgnoreWithCallbackBool &&\n",
" Mock.Apple_CallbackFunctionPointer != NULL)\n",
" {\n",
" Mock.Apple_CallbackFunctionPointer(steak, flag, Mock.Apple_CallbackCalls++);\n",
" UNITY_CLR_DETAILS();\n",
" return;\n",
" }\n"
].join
returned = @cmock_generator_plugin_callback.mock_implementation_for_callbacks_without_arg_check(function)
returned = @cmock_generator_plugin_callback.mock_implementation_precheck(function)
assert_equal(expected, returned)
end
@@ -206,14 +224,16 @@ describe CMockGeneratorPluginCallback, "Verify CMockGeneratorPluginCallback Modu
{ :type => 'uint8_t', :name => 'flag', :ptr? => false} ],
:args_string => "int* steak, uint8_t flag",
:return=> test_return[:void]}
expected = [" if (Mock.Apple_CallbackFunctionPointer != NULL)\n",
expected = [" if (Mock.Apple_IgnoreWithCallbackBool &&\n",
" Mock.Apple_CallbackFunctionPointer != NULL)\n",
" {\n",
" Mock.Apple_CallbackFunctionPointer(steak, flag);\n",
" UNITY_CLR_DETAILS();\n",
" return;\n",
" }\n"
].join
@cmock_generator_plugin_callback.include_count = false
returned = @cmock_generator_plugin_callback.mock_implementation_for_callbacks_without_arg_check(function)
returned = @cmock_generator_plugin_callback.mock_implementation_precheck(function)
assert_equal(expected, returned)
end
@@ -223,12 +243,15 @@ describe CMockGeneratorPluginCallback, "Verify CMockGeneratorPluginCallback Modu
{ :type => 'uint8_t', :name => 'flag', :ptr? => false} ],
:args_string => "int* steak, uint8_t flag",
:return => test_return[:int]}
expected = [" if (Mock.Apple_CallbackFunctionPointer != NULL)\n",
expected = [" if (Mock.Apple_IgnoreWithCallbackBool &&\n",
" Mock.Apple_CallbackFunctionPointer != NULL)\n",
" {\n",
" return Mock.Apple_CallbackFunctionPointer(steak, flag, Mock.Apple_CallbackCalls++);\n",
" int ret = Mock.Apple_CallbackFunctionPointer(steak, flag, Mock.Apple_CallbackCalls++);\n",
" UNITY_CLR_DETAILS();\n",
" return ret;\n",
" }\n"
].join
returned = @cmock_generator_plugin_callback.mock_implementation_for_callbacks_without_arg_check(function)
returned = @cmock_generator_plugin_callback.mock_implementation_precheck(function)
assert_equal(expected, returned)
end
@@ -239,21 +262,20 @@ describe CMockGeneratorPluginCallback, "Verify CMockGeneratorPluginCallback Modu
:return => test_return[:int]
}
expected = ["void Lemon_StubWithCallback(CMOCK_Lemon_CALLBACK Callback)\n",
expected = ["void Lemon_CheckWithCallback(CMOCK_Lemon_CALLBACK Callback)\n",
"{\n",
" Mock.Lemon_IgnoreBool = (int)0;\n",
" Mock.Lemon_IgnoreWithCallbackBool = (int)0;\n",
" Mock.Lemon_CallbackFunctionPointer = Callback;\n",
"}\n\n",
"void Lemon_IgnoreWithCallback(CMOCK_Lemon_CALLBACK Callback)\n",
"{\n",
" Mock.Lemon_IgnoreBool = (int)0;\n",
" Mock.Lemon_IgnoreWithCallbackBool = (int)1;\n",
" Mock.Lemon_CallbackFunctionPointer = Callback;\n",
"}\n\n"
].join
returned = @cmock_generator_plugin_callback.mock_interfaces(function)
assert_equal(expected, returned)
end
it "add mock destroy for functions" do
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
end