* split :args_only feature from :ignore plugin to be its own :expect_any_args plugin

* made :expect_any_args work with intermixed expects the way you would think it should work.
This commit is contained in:
Mark VanderVoord
2014-03-03 19:28:50 -05:00
parent 6bfe7ce784
commit 86594eea25
9 changed files with 409 additions and 285 deletions
+103 -108
View File
@@ -1,82 +1,82 @@
[All code is copyright © 2007-2010 Cmock Project [All code is copyright © 2007-2010 Cmock Project
by Mike Karlesky, Mark VanderVoord, and Greg Williams. by Mike Karlesky, Mark VanderVoord, and Greg Williams.
This Documentation Is Released Under a Creative Commons 3.0 This Documentation Is Released Under a Creative Commons 3.0
Attribution Share-Alike License] Attribution Share-Alike License]
What the What? What the What?
============== ==============
CMock is a nice little tool which takes your header files and creates CMock is a nice little tool which takes your header files and creates
a Mock interface for it so that you can more easily Unit test modules a Mock interface for it so that you can more easily Unit test modules
that touch other modules. For each function prototype in your that touch other modules. For each function prototype in your
header, like this one: header, like this one:
int DoesSomething(int a, int b); int DoesSomething(int a, int b);
...you get an automatically generated DoesSomething function
that you can link to instead of your real DoesSomething function.
By using this Mocked version, you can then verify that it receives
the data you want, and make it return whatever data you desire,
make it throw errors when you want, and more... Create these for
everything your latest real module touches, and you're suddenly
in a position of power: You can control and verify every detail
of your latest creation.
To make that easier, CMock also gives you a bunch of functions ...you get an automatically generated DoesSomething function
like the ones below, so you can tell that generated DoesSomething that you can link to instead of your real DoesSomething function.
function how to behave for each test: By using this Mocked version, you can then verify that it receives
the data you want, and make it return whatever data you desire,
make it throw errors when you want, and more... Create these for
everything your latest real module touches, and you're suddenly
in a position of power: You can control and verify every detail
of your latest creation.
To make that easier, CMock also gives you a bunch of functions
like the ones below, so you can tell that generated DoesSomething
function how to behave for each test:
void DoesSomething_ExpectAndReturn(int a, int b, int toReturn); void DoesSomething_ExpectAndReturn(int a, int b, int toReturn);
void DoesSomething_ExpectAndThrow(int a, int b, EXCEPTION_T error); void DoesSomething_ExpectAndThrow(int a, int b, EXCEPTION_T error);
void DoesSomething_StubWithCallback(CMOCK_DoesSomething_CALLBACK YourCallback); void DoesSomething_StubWithCallback(CMOCK_DoesSomething_CALLBACK YourCallback);
void DoesSomething_IgnoreAndReturn(int toReturn); void DoesSomething_IgnoreAndReturn(int toReturn);
You can pile a bunch of these back to back, and it remembers what
you wanted to pass when, like so: You can pile a bunch of these back to back, and it remembers what
you wanted to pass when, like so:
test_CallsDoesSomething_ShouldDoJustThat(void) test_CallsDoesSomething_ShouldDoJustThat(void)
{ {
DoesSomething_ExpectAndReturn(1,2,3); DoesSomething_ExpectAndReturn(1,2,3);
DoesSomething_ExpectAndReturn(4,5,6); DoesSomething_ExpectAndReturn(4,5,6);
DoesSomething_ExpectAndThrow(7,8, STATUS_ERROR_OOPS); DoesSomething_ExpectAndThrow(7,8, STATUS_ERROR_OOPS);
CallsDoesSomething( ); CallsDoesSomething( );
} }
This test will call CallsDoesSomething, which is the function
we are testing. We are expecting that function to call DoesSomething
three times. The first time, we check to make sure it's called
as DoesSomething(1, 2) and we'll magically return a 3. The second
time we check for DoesSomething(4, 5) and we'll return a 6. The
third time we verify DoesSomething(7, 8) and we'll throw an error
instead of returning anything. If CallsDoesSomething gets
any of this wrong, it fails the test. It will fail if you didn't
call DoesSomething enough, or too much, or with the wrong arguments,
or in the wrong order.
CMock is based on Unity, which it uses for all internal testing. This test will call CallsDoesSomething, which is the function
It uses Ruby to do all the main work (versions 1.8.6 through 1.9.2). we are testing. We are expecting that function to call DoesSomething
three times. The first time, we check to make sure it's called
as DoesSomething(1, 2) and we'll magically return a 3. The second
time we check for DoesSomething(4, 5) and we'll return a 6. The
third time we verify DoesSomething(7, 8) and we'll throw an error
instead of returning anything. If CallsDoesSomething gets
any of this wrong, it fails the test. It will fail if you didn't
call DoesSomething enough, or too much, or with the wrong arguments,
or in the wrong order.
CMock is based on Unity, which it uses for all internal testing.
It uses Ruby to do all the main work (versions 1.8.6 through 1.9.2).
Generated Mock Module Summary Generated Mock Module Summary
============================= =============================
In addition to the mocks themselves, CMock will generate the In addition to the mocks themselves, CMock will generate the
following functions for use in your tests. The expect functions following functions for use in your tests. The expect functions
are always generated. The other functions are only generated are always generated. The other functions are only generated
if those plugins are enabled: if those plugins are enabled:
Expect: Expect:
------- -------
Your basic staple Expects which will be used for most of your day Your basic staple Expects which will be used for most of your day
to day CMock work. to day CMock work.
* `void func(void)` => `void func_Expect(void)` * `void func(void)` => `void func_Expect(void)`
* `void func(params)` => `void func_Expect(expected_params)` * `void func(params)` => `void func_Expect(expected_params)`
@@ -87,9 +87,9 @@ to day CMock work.
Array: Array:
------ ------
An ExpectWithArray will check as many elements as you specify. An ExpectWithArray will check as many elements as you specify.
If you specify zero elements, it will check just the pointer if If you specify zero elements, it will check just the pointer if
`:smart` mode is configured or fail if `:compare_data` is set. `:smart` mode is configured or fail if `:compare_data` is set.
* `void func(void)` => (nothing. In fact, an additional function is only generated if the params list contains pointers) * `void func(void)` => (nothing. In fact, an additional function is only generated if the params list contains pointers)
* `void func(ptr * param, other)` => `void func_ExpectWithArray(ptr* param, int param_depth, other)` * `void func(ptr * param, other)` => `void func_ExpectWithArray(ptr* param, int param_depth, other)`
@@ -100,11 +100,11 @@ If you specify zero elements, it will check just the pointer if
Callback: Callback:
--------- ---------
As soon as you stub a callback in a test, it will call the callback 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 whenever the mock is encountered and return the retval returned
from the callback (if any) instead of performing the usual expect from the callback (if any) instead of performing the usual expect
checks. It can be configured to check the arguments first (like checks. It can be configured to check the arguments first (like
expects) or just jump directly to the callback. expects) or just jump directly to the callback.
* `void func(void)` => `void func_StubWithCallback(CMOCK_func_CALLBACK callback)` * `void func(void)` => `void func_StubWithCallback(CMOCK_func_CALLBACK callback)`
where `CMOCK_func_CALLBACK` looks like: `void func(int NumCalls)` where `CMOCK_func_CALLBACK` looks like: `void func(int NumCalls)`
@@ -119,10 +119,10 @@ where `CMOCK_func_CALLBACK` looks like: `retval func(params, int NumCalls)`
Cexception: Cexception:
----------- -----------
If you are using Cexception for error handling, you can use this If you are using Cexception for error handling, you can use this
to throw errors from inside mocks. Like Expects, it remembers to throw errors from inside mocks. Like Expects, it remembers
which call was supposed to throw the error, and it still checks which call was supposed to throw the error, and it still checks
parameters. parameters.
* `void func(void)` => `void func_ExpectAndThrow(value_to_throw)` * `void func(void)` => `void func_ExpectAndThrow(value_to_throw)`
* `void func(params)` => `void func_ExpectAndThrow(expected_params, value_to_throw)` * `void func(params)` => `void func_ExpectAndThrow(expected_params, value_to_throw)`
@@ -133,10 +133,10 @@ parameters.
Ignore: Ignore:
------- -------
This plugin supports two modes. You can use it to force CMock to This plugin supports two modes. You can use it to force CMock to
ignore calls to specific functions or to just ignore the arguments ignore calls to specific functions or to just ignore the arguments
passed to those functions. Either way you can specify multiple passed to those functions. Either way you can specify multiple
returns or a single value to always return, whichever you prefer. returns or a single value to always return, whichever you prefer.
* `void func(void)` => `void func_Ignore(void)` * `void func(void)` => `void func_Ignore(void)`
* `void func(params)` => `void func_Ignore(void)` * `void func(params)` => `void func_Ignore(void)`
@@ -147,59 +147,59 @@ returns or a single value to always return, whichever you prefer.
Running CMock Running CMock
============= =============
CMock is a Ruby script and class. You can therefore use it directly CMock is a Ruby script and class. You can therefore use it directly
from the command line, or include it in your own scripts or rakefiles. from the command line, or include it in your own scripts or rakefiles.
Mocking from the Command Line Mocking from the Command Line
----------------------------- -----------------------------
After unpacking CMock, you will find CMock.rb in the 'lib' directory. After unpacking CMock, you will find CMock.rb in the 'lib' directory.
This is the file that you want to run. It takes a list of header files This is the file that you want to run. It takes a list of header files
to be mocked, as well as an optional yaml file for a more detailed to be mocked, as well as an optional yaml file for a more detailed
configuration (see config options below). configuration (see config options below).
For example, this will create three mocks using the configuration For example, this will create three mocks using the configuration
specified in MyConfig.yml: specified in MyConfig.yml:
ruby cmock.rb -oMyConfig.yml super.h duper.h awesome.h ruby cmock.rb -oMyConfig.yml super.h duper.h awesome.h
And this will create two mocks using the default configuration: And this will create two mocks using the default configuration:
ruby cmock.rb ../mocking/stuff/is/fun.h ../try/it/yourself.h ruby cmock.rb ../mocking/stuff/is/fun.h ../try/it/yourself.h
Mocking From Scripts or Rake Mocking From Scripts or Rake
---------------------------- ----------------------------
CMock can be used directly from your own scripts or from a rakefile. CMock can be used directly from your own scripts or from a rakefile.
Start by including cmock.rb, then create an instance of CMock. Start by including cmock.rb, then create an instance of CMock.
When you create your instance, you may initialize it in one of When you create your instance, you may initialize it in one of
three ways. three ways.
You may specify nothing, allowing it to run with default settings: You may specify nothing, allowing it to run with default settings:
cmock = CMock.new cmock = CMock.new
You may specify a YAML file containing the configuration options You may specify a YAML file containing the configuration options
you desire: you desire:
cmock = CMock.new('../MyConfig.yml') cmock = CMock.new('../MyConfig.yml')
You may specify the options explicitly: You may specify the options explicitly:
cmock = Cmock.new(:plugins => [:cexception, :ignore], :mock_path => 'my/mocks/') cmock = Cmock.new(:plugins => [:cexception, :ignore], :mock_path => 'my/mocks/')
Config Options: Config Options:
The following configuration options can be specified in the The following configuration options can be specified in the
yaml file or directly when instantiating. yaml file or directly when instantiating.
Passed as Ruby, they look like this: Passed as Ruby, they look like this:
{ :attributes => [“__funky”, “__intrinsic”], :when_ptr => :compare } { :attributes => [“__funky”, “__intrinsic”], :when_ptr => :compare }
Defined in the yaml file, they look more like this: Defined in the yaml file, they look more like this:
:cmock: :cmock:
:attributes: :attributes:
- __funky - __funky
- __intrinsic - __intrinsic
@@ -238,11 +238,6 @@ Defined in the yaml file, they look more like this:
unity test frameworks (or if you write one for us), they'll get added unity test frameworks (or if you write one for us), they'll get added
here. here.
* `:ignore`:
Tell `:ignore` plugin to ignore `:args_only` or `:args_and_calls`
(default) where it doesn't even care how many times the mock was
called
* `:includes`: * `:includes`:
An array of additional include files which should be added to the An array of additional include files which should be added to the
mocks. Useful for global types and definitions used in your project. mocks. Useful for global types and definitions used in your project.
@@ -320,37 +315,37 @@ Defined in the yaml file, they look more like this:
Compiled Options: Compiled Options:
----------------- -----------------
A number of #defines also exist for customizing the cmock experience. A number of #defines also exist for customizing the cmock experience.
CMOCK_MEM_STATIC or CMOCK_MEM_DYNAMIC CMOCK_MEM_STATIC or CMOCK_MEM_DYNAMIC
Define one of these to determine if you want to dynamically add Define one of these to determine if you want to dynamically add
memory during tests as required from the heap. If static, you memory during tests as required from the heap. If static, you
can control the total footprint of Cmock. If dynamic, you will can control the total footprint of Cmock. If dynamic, you will
need to make sure you make some heap space available for Cmock. need to make sure you make some heap space available for Cmock.
CMOCK_MEM_SIZE CMOCK_MEM_SIZE
In static mode this is the total amount of memory you are allocating In static mode this is the total amount of memory you are allocating
to Cmock. In Dynamic mode this is the size of each chunk allocated to Cmock. In Dynamic mode this is the size of each chunk allocated
at once (larger numbers grab more memory but require less mallocs). at once (larger numbers grab more memory but require less mallocs).
CMOCK_MEM_ALIGN CMOCK_MEM_ALIGN
The way to align your data to. Not everything is as flexible as The way to align your data to. Not everything is as flexible as
a PC, as most embedded designers know. This defaults to 2, meaning a PC, as most embedded designers know. This defaults to 2, meaning
align to the closest 2^2 -> 4 bytes (32 bits). You can turn off alignment align to the closest 2^2 -> 4 bytes (32 bits). You can turn off alignment
by setting 0, force alignment to the closest uint16 with 1 or even by setting 0, force alignment to the closest uint16 with 1 or even
to the closest uint64 with 3. to the closest uint64 with 3.
CMOCK_MEM_PTR_AS_INT CMOCK_MEM_PTR_AS_INT
This is used internally to hold pointers... it needs to be big This is used internally to hold pointers... it needs to be big
enough. On most processors a pointer is the same as an unsigned enough. On most processors a pointer is the same as an unsigned
long... but maybe that's not true for yours? long... but maybe that's not true for yours?
CMOCK_MEM_INDEX_TYPE CMOCK_MEM_INDEX_TYPE
This needs to be something big enough to point anywhere in Cmock's This needs to be something big enough to point anywhere in Cmock's
memory space... usually it's an unsigned int. memory space... usually it's an unsigned int.
+16 -17
View File
@@ -2,11 +2,11 @@
# CMock Project - Automatic Mock Generation for C # CMock Project - Automatic Mock Generation for C
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams # Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
# [Released under MIT License. Please refer to license.txt for details] # [Released under MIT License. Please refer to license.txt for details]
# ========================================== # ==========================================
class CMockConfig class CMockConfig
CMockDefaultOptions = CMockDefaultOptions =
{ {
:framework => :unity, :framework => :unity,
:mock_path => 'mocks', :mock_path => 'mocks',
@@ -24,24 +24,23 @@ class CMockConfig
:when_ptr => :compare_data, #the options being :compare_ptr, :compare_data, or :smart :when_ptr => :compare_data, #the options being :compare_ptr, :compare_data, or :smart
:verbosity => 2, #the options being 0 errors only, 1 warnings and errors, 2 normal info, 3 verbose :verbosity => 2, #the options being 0 errors only, 1 warnings and errors, 2 normal info, 3 verbose
:treat_externs => :exclude, #the options being :include or :exclude :treat_externs => :exclude, #the options being :include or :exclude
:ignore => :args_and_calls, #the options being :args_and_calls or :args_only
:callback_include_count => true, :callback_include_count => true,
:callback_after_arg_check => false, :callback_after_arg_check => false,
:includes => nil, :includes => nil,
:includes_h_pre_orig_header => nil, :includes_h_pre_orig_header => nil,
:includes_h_post_orig_header => nil, :includes_h_post_orig_header => nil,
:includes_c_pre_header => nil, :includes_c_pre_header => nil,
:includes_c_post_header => nil :includes_c_post_header => nil
} }
def initialize(options=nil) def initialize(options=nil)
case(options) case(options)
when NilClass then options = CMockDefaultOptions.clone when NilClass then options = CMockDefaultOptions.clone
when String then options = CMockDefaultOptions.clone.merge(load_config_file_from_yaml(options)) when String then options = CMockDefaultOptions.clone.merge(load_config_file_from_yaml(options))
when Hash then options = CMockDefaultOptions.clone.merge(options) when Hash then options = CMockDefaultOptions.clone.merge(options)
else raise "If you specify arguments, it should be a filename or a hash of options" else raise "If you specify arguments, it should be a filename or a hash of options"
end end
#do some quick type verification #do some quick type verification
[:plugins, :attributes, :treat_as_void].each do |opt| [:plugins, :attributes, :treat_as_void].each do |opt|
unless (options[opt].class == Array) unless (options[opt].class == Array)
@@ -59,30 +58,30 @@ class CMockConfig
options[:plugins].compact! options[:plugins].compact!
options[:plugins].map! {|p| p.to_sym} options[:plugins].map! {|p| p.to_sym}
@options = options @options = options
treat_as_map = standard_treat_as_map()#.clone treat_as_map = standard_treat_as_map()#.clone
treat_as_map.merge!(@options[:treat_as]) treat_as_map.merge!(@options[:treat_as])
@options[:treat_as] = treat_as_map @options[:treat_as] = treat_as_map
@options.each_key { |key| eval("def #{key.to_s}() return @options[:#{key.to_s}] end") } @options.each_key { |key| eval("def #{key.to_s}() return @options[:#{key.to_s}] end") }
end end
def load_config_file_from_yaml yaml_filename def load_config_file_from_yaml yaml_filename
require 'yaml' require 'yaml'
require 'fileutils' require 'fileutils'
YAML.load_file(yaml_filename)[:cmock] YAML.load_file(yaml_filename)[:cmock]
end end
def set_path(path) def set_path(path)
@src_path = path @src_path = path
end end
def load_unity_helper def load_unity_helper
return File.new(@options[:unity_helper_path]).read if (@options[:unity_helper_path]) return File.new(@options[:unity_helper_path]).read if (@options[:unity_helper_path])
return nil return nil
end end
def standard_treat_as_map def standard_treat_as_map
{ {
'int' => 'INT', 'int' => 'INT',
'char' => 'INT8', 'char' => 'INT8',
@@ -0,0 +1,67 @@
# ==========================================
# CMock Project - Automatic Mock Generation for C
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
# [Released under MIT License. Please refer to license.txt for details]
# ==========================================
class CMockGeneratorPluginExpectAnyArgs
attr_reader :priority
attr_reader :config, :utils
def initialize(config, utils)
@config = config
@utils = utils
@priority = 3
end
def instance_structure(function)
if (function[:return][:void?]) || (@config.plugins.include? :ignore)
""
else
" #{function[:return][:type]} #{function[:name]}_FinalReturn;\n"
end
end
def instance_typedefs(function)
" CMOCK_ARG_MODE IgnoreMode;\n"
end
def mock_function_declarations(function)
if (function[:return][:void?])
return "#define #{function[:name]}_ExpectAnyArgs() #{function[:name]}_CMockExpectAnyArgs(__LINE__)\n" +
"void #{function[:name]}_CMockExpectAnyArgs(UNITY_LINE_TYPE cmock_line);\n"
else
return "#define #{function[:name]}_ExpectAnyArgsAndReturn(cmock_retval) #{function[:name]}_CMockExpectAnyArgsAndReturn(__LINE__, cmock_retval)\n" +
"void #{function[:name]}_CMockExpectAnyArgsAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]});\n"
end
end
def mock_implementation(function)
lines = " if (cmock_call_instance->IgnoreMode == CMOCK_ARG_NONE)\n {\n"
if (function[:return][:void?])
lines << " return;\n }\n"
else
retval = function[:return].merge( { :name => "cmock_call_instance->ReturnVal"} )
lines << " " + @utils.code_assign_argument_quickly("Mock.#{function[:name]}_FinalReturn", retval) unless (retval[:void?])
lines << " return cmock_call_instance->ReturnVal;\n }\n"
end
lines
end
def mock_interfaces(function)
lines = ""
if (function[:return][:void?])
lines << "void #{function[:name]}_CMockExpectAnyArgs(UNITY_LINE_TYPE cmock_line)\n{\n"
else
lines << "void #{function[:name]}_CMockExpectAnyArgsAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]})\n{\n"
end
lines << @utils.code_add_base_expectation(function[:name], true)
unless (function[:return][:void?])
lines << " cmock_call_instance->ReturnVal = cmock_to_return;\n"
end
lines << " cmock_call_instance->IgnoreMode = CMOCK_ARG_NONE;\n"
lines << "}\n\n"
end
end
+15 -40
View File
@@ -2,28 +2,19 @@
# CMock Project - Automatic Mock Generation for C # CMock Project - Automatic Mock Generation for C
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams # Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
# [Released under MIT License. Please refer to license.txt for details] # [Released under MIT License. Please refer to license.txt for details]
# ========================================== # ==========================================
class CMockGeneratorPluginIgnore class CMockGeneratorPluginIgnore
attr_reader :priority attr_reader :priority
attr_reader :config, :utils attr_reader :config, :utils
def initialize(config, utils) def initialize(config, utils)
@config = config @config = config
if (@config.ignore == :args_and_calls)
alias :mock_implementation_precheck :mock_implementation_for_ignores
alias :mock_implementation :nothing
alias :mock_verify :mock_conditionally_verify_counts
else
alias :mock_implementation :mock_implementation_for_ignores
alias :mock_implementation_precheck :nothing
alias :mock_verify :nothing
end
@utils = utils @utils = utils
@priority = 2 @priority = 2
end end
def instance_structure(function) def instance_structure(function)
if (function[:return][:void?]) if (function[:return][:void?])
" int #{function[:name]}_IgnoreBool;\n" " int #{function[:name]}_IgnoreBool;\n"
@@ -31,24 +22,19 @@ class CMockGeneratorPluginIgnore
" int #{function[:name]}_IgnoreBool;\n #{function[:return][:type]} #{function[:name]}_FinalReturn;\n" " int #{function[:name]}_IgnoreBool;\n #{function[:return][:type]} #{function[:name]}_FinalReturn;\n"
end end
end end
def mock_function_declarations(function) def mock_function_declarations(function)
if (function[:return][:void?]) if (function[:return][:void?])
if (@config.ignore == :args_only) return "#define #{function[:name]}_Ignore() #{function[:name]}_CMockIgnore()\n" +
return "#define #{function[:name]}_Ignore() #{function[:name]}_CMockIgnore(__LINE__)\n" + "void #{function[:name]}_CMockIgnore(void);\n"
"void #{function[:name]}_CMockIgnore(UNITY_LINE_TYPE cmock_line);\n" else
else
return "#define #{function[:name]}_Ignore() #{function[:name]}_CMockIgnore()\n" +
"void #{function[:name]}_CMockIgnore(void);\n"
end
else
return "#define #{function[:name]}_IgnoreAndReturn(cmock_retval) #{function[:name]}_CMockIgnoreAndReturn(__LINE__, cmock_retval)\n" + return "#define #{function[:name]}_IgnoreAndReturn(cmock_retval) #{function[:name]}_CMockIgnoreAndReturn(__LINE__, cmock_retval)\n" +
"void #{function[:name]}_CMockIgnoreAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]});\n" "void #{function[:name]}_CMockIgnoreAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]});\n"
end end
end end
def mock_implementation_for_ignores(function) def mock_implementation_precheck(function)
lines = " if (Mock.#{function[:name]}_IgnoreBool)\n {\n" lines = " if (Mock.#{function[:name]}_IgnoreBool)\n {\n"
if (function[:return][:void?]) if (function[:return][:void?])
lines << " return;\n }\n" lines << " return;\n }\n"
else else
@@ -59,22 +45,15 @@ class CMockGeneratorPluginIgnore
end end
lines lines
end end
def mock_interfaces(function) def mock_interfaces(function)
lines = "" lines = ""
args_only = (@config.ignore == :args_only)
if (function[:return][:void?]) if (function[:return][:void?])
if (args_only) lines << "void #{function[:name]}_CMockIgnore(void)\n{\n"
lines << "void #{function[:name]}_CMockIgnore(UNITY_LINE_TYPE cmock_line)\n{\n"
else
lines << "void #{function[:name]}_CMockIgnore(void)\n{\n"
end
else else
lines << "void #{function[:name]}_CMockIgnoreAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]})\n{\n" lines << "void #{function[:name]}_CMockIgnoreAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]})\n{\n"
end end
if (args_only) if (!function[:return][:void?])
lines << @utils.code_add_base_expectation(function[:name], true)
elsif (!function[:return][:void?])
lines << @utils.code_add_base_expectation(function[:name], false) lines << @utils.code_add_base_expectation(function[:name], false)
end end
unless (function[:return][:void?]) unless (function[:return][:void?])
@@ -84,12 +63,8 @@ class CMockGeneratorPluginIgnore
lines << "}\n\n" lines << "}\n\n"
end end
def mock_conditionally_verify_counts(function) def mock_conditionally_verify(function)
func_name = function[:name] func_name = function[:name]
" if (Mock.#{func_name}_IgnoreBool)\n Mock.#{func_name}_CallInstance = CMOCK_GUTS_NONE;\n" " if (Mock.#{func_name}_IgnoreBool)\n Mock.#{func_name}_CallInstance = CMOCK_GUTS_NONE;\n"
end end
def nothing(function)
return ""
end
end end
+26 -24
View File
@@ -2,7 +2,7 @@
# CMock Project - Automatic Mock Generation for C # CMock Project - Automatic Mock Generation for C
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams # Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
# [Released under MIT License. Please refer to license.txt for details] # [Released under MIT License. Please refer to license.txt for details]
# ========================================== # ==========================================
class CMockGeneratorUtils class CMockGeneratorUtils
@@ -14,22 +14,23 @@ class CMockGeneratorUtils
@ordered = @config.enforce_strict_ordering @ordered = @config.enforce_strict_ordering
@arrays = @config.plugins.include? :array @arrays = @config.plugins.include? :array
@cexception = @config.plugins.include? :cexception @cexception = @config.plugins.include? :cexception
@expect_any = @config.plugins.include? :expect_any_args
@return_thru_ptr = @config.plugins.include? :return_thru_ptr @return_thru_ptr = @config.plugins.include? :return_thru_ptr
@ignore_arg = @config.plugins.include? :ignore_arg @ignore_arg = @config.plugins.include? :ignore_arg
@treat_as = @config.treat_as @treat_as = @config.treat_as
@helpers = helpers @helpers = helpers
if (@arrays) if (@arrays)
case(@ptr_handling) case(@ptr_handling)
when :smart then alias :code_verify_an_arg_expectation :code_verify_an_arg_expectation_with_smart_arrays when :smart then alias :code_verify_an_arg_expectation :code_verify_an_arg_expectation_with_smart_arrays
when :compare_data then alias :code_verify_an_arg_expectation :code_verify_an_arg_expectation_with_normal_arrays when :compare_data then alias :code_verify_an_arg_expectation :code_verify_an_arg_expectation_with_normal_arrays
when :compare_ptr then raise "ERROR: the array plugin doesn't enjoy working with :compare_ptr only. Disable one option." when :compare_ptr then raise "ERROR: the array plugin doesn't enjoy working with :compare_ptr only. Disable one option."
end end
else else
alias :code_verify_an_arg_expectation :code_verify_an_arg_expectation_with_no_arrays alias :code_verify_an_arg_expectation :code_verify_an_arg_expectation_with_no_arrays
end end
end end
def code_add_base_expectation(func_name, global_ordering_supported=true) def code_add_base_expectation(func_name, global_ordering_supported=true)
lines = " CMOCK_MEM_INDEX_TYPE cmock_guts_index = CMock_Guts_MemNew(sizeof(CMOCK_#{func_name}_CALL_INSTANCE));\n" lines = " CMOCK_MEM_INDEX_TYPE cmock_guts_index = CMock_Guts_MemNew(sizeof(CMOCK_#{func_name}_CALL_INSTANCE));\n"
lines << " CMOCK_#{func_name}_CALL_INSTANCE* cmock_call_instance = (CMOCK_#{func_name}_CALL_INSTANCE*)CMock_Guts_GetAddressFor(cmock_guts_index);\n" lines << " CMOCK_#{func_name}_CALL_INSTANCE* cmock_call_instance = (CMOCK_#{func_name}_CALL_INSTANCE*)CMock_Guts_GetAddressFor(cmock_guts_index);\n"
@@ -38,37 +39,38 @@ class CMockGeneratorUtils
lines << " cmock_call_instance->LineNumber = cmock_line;\n" lines << " cmock_call_instance->LineNumber = cmock_line;\n"
lines << " cmock_call_instance->CallOrder = ++GlobalExpectCount;\n" if (@ordered and global_ordering_supported) lines << " cmock_call_instance->CallOrder = ++GlobalExpectCount;\n" if (@ordered and global_ordering_supported)
lines << " cmock_call_instance->ExceptionToThrow = CEXCEPTION_NONE;\n" if (@cexception) lines << " cmock_call_instance->ExceptionToThrow = CEXCEPTION_NONE;\n" if (@cexception)
lines << " cmock_call_instance->IgnoreMode = CMOCK_ARG_ALL;\n" if (@expect_any)
lines lines
end end
def code_add_an_arg_expectation(arg, depth=1) def code_add_an_arg_expectation(arg, depth=1)
lines = code_assign_argument_quickly("cmock_call_instance->Expected_#{arg[:name]}", arg) 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 << " cmock_call_instance->Expected_#{arg[:name]}_Depth = #{arg[:name]}_Depth;\n" if (@arrays and (depth.class == String))
lines << " cmock_call_instance->IgnoreArg_#{arg[:name]} = 0;\n" if (@ignore_arg) lines << " cmock_call_instance->IgnoreArg_#{arg[:name]} = 0;\n" if (@ignore_arg)
lines << " cmock_call_instance->ReturnThruPtr_#{arg[:name]}_Used = 0;\n" if (@return_thru_ptr and ptr_or_str?(arg[:type]) and not arg[:const?]) lines << " cmock_call_instance->ReturnThruPtr_#{arg[:name]}_Used = 0;\n" if (@return_thru_ptr and ptr_or_str?(arg[:type]) and not arg[:const?])
lines lines
end end
def code_assign_argument_quickly(dest, arg) def code_assign_argument_quickly(dest, arg)
if (arg[:ptr?] or @treat_as.include?(arg[:type])) if (arg[:ptr?] or @treat_as.include?(arg[:type]))
" #{dest} = #{arg[:const?] ? "(#{arg[:type]})" : ''}#{arg[:name]};\n" " #{dest} = #{arg[:const?] ? "(#{arg[:type]})" : ''}#{arg[:name]};\n"
else else
" memcpy(&#{dest}, &#{arg[:name]}, sizeof(#{arg[:type]}));\n" " memcpy(&#{dest}, &#{arg[:name]}, sizeof(#{arg[:type]}));\n"
end end
end end
def code_add_argument_loader(function) def code_add_argument_loader(function)
if (function[:args_string] != "void") if (function[:args_string] != "void")
if (@arrays) if (@arrays)
args_string = function[:args].map do |m| args_string = function[:args].map do |m|
const_str = m[ :const? ] ? 'const ' : '' const_str = m[ :const? ] ? 'const ' : ''
m[:ptr?] ? "#{const_str}#{m[:type]} #{m[:name]}, int #{m[:name]}_Depth" : "#{const_str}#{m[:type]} #{m[:name]}" m[:ptr?] ? "#{const_str}#{m[:type]} #{m[:name]}, int #{m[:name]}_Depth" : "#{const_str}#{m[:type]} #{m[:name]}"
end.join(', ') end.join(', ')
"void CMockExpectParameters_#{function[:name]}(CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance, #{args_string})\n{\n" + "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) ) } + function[:args].inject("") { |all, arg| all + code_add_an_arg_expectation(arg, (arg[:ptr?] ? "#{arg[:name]}_Depth" : 1) ) } +
"}\n\n" "}\n\n"
else else
"void CMockExpectParameters_#{function[:name]}(CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance, #{function[:args_string]})\n{\n" + "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) } + function[:args].inject("") { |all, arg| all + code_add_an_arg_expectation(arg) } +
"}\n\n" "}\n\n"
end end
@@ -76,25 +78,25 @@ class CMockGeneratorUtils
"" ""
end end
end end
def code_call_argument_loader(function) def code_call_argument_loader(function)
if (function[:args_string] != "void") if (function[:args_string] != "void")
args = function[:args].map do |m| args = function[:args].map do |m|
(@arrays and m[:ptr?]) ? "#{m[:name]}, 1" : m[:name] (@arrays and m[:ptr?]) ? "#{m[:name]}, 1" : m[:name]
end end
" CMockExpectParameters_#{function[:name]}(cmock_call_instance, #{args.join(', ')});\n" " CMockExpectParameters_#{function[:name]}(cmock_call_instance, #{args.join(', ')});\n"
else else
"" ""
end end
end end
def ptr_or_str?(arg_type) def ptr_or_str?(arg_type)
return (arg_type.include? '*' or return (arg_type.include? '*' or
@treat_as.fetch(arg_type, "").include? '*') @treat_as.fetch(arg_type, "").include? '*')
end end
#private ###################### #private ######################
def lookup_expect_type(function, arg) def lookup_expect_type(function, arg)
c_type = arg[:type] c_type = arg[:type]
arg_name = arg[:name] arg_name = arg[:name]
@@ -108,7 +110,7 @@ class CMockGeneratorUtils
unity_msg = "Function '#{function[:name]}' called with unexpected value for argument '#{arg_name}'." unity_msg = "Function '#{function[:name]}' called with unexpected value for argument '#{arg_name}'."
return c_type, arg_name, expected, ignore, unity_func[0], unity_func[1], unity_msg return c_type, arg_name, expected, ignore, unity_func[0], unity_func[1], unity_msg
end end
def code_verify_an_arg_expectation_with_no_arrays(function, arg) def code_verify_an_arg_expectation_with_no_arrays(function, arg)
c_type, arg_name, expected, ignore, unity_func, pre, unity_msg = lookup_expect_type(function, arg) c_type, arg_name, expected, ignore, unity_func, pre, unity_msg = lookup_expect_type(function, arg)
lines = "" lines = ""
@@ -129,12 +131,12 @@ class CMockGeneratorUtils
lines << " else\n" lines << " else\n"
lines << " { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, 1, cmock_line, \"#{unity_msg}\"); }\n" lines << " { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, 1, cmock_line, \"#{unity_msg}\"); }\n"
else else
lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, \"#{unity_msg}\");\n" lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, \"#{unity_msg}\");\n"
end end
lines << " }\n" lines << " }\n"
lines lines
end end
def code_verify_an_arg_expectation_with_normal_arrays(function, arg) def code_verify_an_arg_expectation_with_normal_arrays(function, arg)
c_type, arg_name, expected, ignore, unity_func, pre, unity_msg = lookup_expect_type(function, arg) c_type, arg_name, expected, ignore, unity_func, pre, unity_msg = lookup_expect_type(function, arg)
depth_name = (arg[:ptr?]) ? "cmock_call_instance->Expected_#{arg_name}_Depth" : 1 depth_name = (arg[:ptr?]) ? "cmock_call_instance->Expected_#{arg_name}_Depth" : 1
@@ -160,12 +162,12 @@ class CMockGeneratorUtils
lines << " { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, \"#{unity_msg}\"); }\n" lines << " { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, \"#{unity_msg}\"); }\n"
end end
else else
lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, \"#{unity_msg}\");\n" lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, \"#{unity_msg}\");\n"
end end
lines << " }\n" lines << " }\n"
lines lines
end end
def code_verify_an_arg_expectation_with_smart_arrays(function, arg) def code_verify_an_arg_expectation_with_smart_arrays(function, arg)
c_type, arg_name, expected, ignore, unity_func, pre, unity_msg = lookup_expect_type(function, arg) c_type, arg_name, expected, ignore, unity_func, pre, unity_msg = lookup_expect_type(function, arg)
depth_name = (arg[:ptr?]) ? "cmock_call_instance->Expected_#{arg_name}_Depth" : 1 depth_name = (arg[:ptr?]) ? "cmock_call_instance->Expected_#{arg_name}_Depth" : 1
@@ -193,10 +195,10 @@ class CMockGeneratorUtils
lines << " { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, \"#{unity_msg}\"); }\n" lines << " { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, \"#{unity_msg}\"); }\n"
end end
else else
lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, \"#{unity_msg}\");\n" lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, \"#{unity_msg}\");\n"
end end
lines << " }\n" lines << " }\n"
lines lines
end end
end end
+4
View File
@@ -14,6 +14,10 @@
#define CMOCK_GUTS_NONE (0) #define CMOCK_GUTS_NONE (0)
#define CMOCK_ARG_MODE CMOCK_MEM_INDEX_TYPE
#define CMOCK_ARG_ALL 0
#define CMOCK_ARG_NONE ((CMOCK_MEM_INDEX_TYPE)(~0))
//------------------------------------------------------- //-------------------------------------------------------
// Memory API // Memory API
//------------------------------------------------------- //-------------------------------------------------------
+54
View File
@@ -0,0 +1,54 @@
---
compiler:
path: gcc
source_path: &systest_generated_path 'test/system/generated/'
unit_tests_path: &unit_tests_path 'examples/test/'
mocks_path: &systest_mocks_path 'test/system/generated/'
build_path: &systest_build_path 'test/system/build/'
options:
- '-c'
- '-m64'
- '-Wall'
- '-Wunused-parameter'
- '-Wno-address'
- '-std=c99'
- '-pedantic'
includes:
prefix: '-I'
items:
- *systest_generated_path
- *unit_tests_path
- *systest_mocks_path
- 'src/'
- 'vendor/unity/src/'
- 'vendor/c_exception/lib/'
- 'test/system/test_compilation/'
- 'test/'
defines:
prefix: '-D'
items:
- 'UNITY_SUPPORT_64'
object_files:
prefix: '-o'
extension: '.o'
destination: *systest_build_path
linker:
path: gcc
options:
- -lm
- '-m64'
includes:
prefix: '-I'
object_files:
path: *systest_build_path
extension: '.o'
bin_files:
prefix: '-o'
extension: '.exe'
destination: *systest_build_path
unsupported:
- callingconv
colour: true
@@ -3,12 +3,12 @@
:cmock: :cmock:
:enforce_strict_ordering: 1 :enforce_strict_ordering: 1
:treat_externs: :include :treat_externs: :include
:ignore: :args_only
:plugins: :plugins:
- :array - :array
- :cexception - :cexception
- :ignore - :ignore
- :callback - :callback
- :expect_any_args
:systest: :systest:
:types: | :types: |
@@ -28,9 +28,9 @@
int mixed(int a, int* b, int c); int mixed(int a, int* b, int c);
void no_args(void); void no_args(void);
:source: :source:
:header: | :header: |
#include "CException.h" #include "CException.h"
void function_a(void); void function_a(void);
void function_b(void); void function_b(void);
void function_c(void); void function_c(void);
@@ -38,40 +38,40 @@
void function_e(void); void function_e(void);
:code: | :code: |
void function_a(void) void function_a(void)
{ {
foo(bar()); foo(bar());
} }
void function_b(void) { void function_b(void) {
fooa(bar()); fooa(bar());
} }
void function_c(void) { void function_c(void) {
CEXCEPTION_T e; CEXCEPTION_T e;
Try { Try {
foos(bars()); foos(bars());
} Catch(e) { foos("err"); } } Catch(e) { foos("err"); }
} }
int function_d(void) { int function_d(void) {
int test_list[] = { 1, 2, 3, 4, 5 }; int test_list[] = { 1, 2, 3, 4, 5 };
no_pointers(1, "silly"); no_pointers(1, "silly");
return mixed(6, test_list, 7); return mixed(6, test_list, 7);
} }
void function_e(void) { void function_e(void) {
foos("Hello"); foos("Hello");
foos("Tuna"); foos("Tuna");
foos("Oranges"); foos("Oranges");
} }
:tests: :tests:
:common: | :common: |
#include "CException.h" #include "CException.h"
void setUp(void) {} void setUp(void) {}
void tearDown(void) {} void tearDown(void) {}
:units: :units:
- :pass: TRUE - :pass: TRUE
:should: 'handle the situation where we pass nulls to pointers' :should: 'handle the situation where we pass nulls to pointers'
@@ -80,10 +80,10 @@
{ {
bar_ExpectAndReturn(NULL); bar_ExpectAndReturn(NULL);
foo_Expect(NULL); foo_Expect(NULL);
function_a(); function_a();
} }
- :pass: FALSE - :pass: FALSE
:should: 'handle the situation where we expected nulls to pointers but did not get that' :should: 'handle the situation where we expected nulls to pointers but did not get that'
:code: | :code: |
@@ -92,10 +92,10 @@
POINT_T pt = {1, 2}; POINT_T pt = {1, 2};
bar_ExpectAndReturn(&pt); bar_ExpectAndReturn(&pt);
foo_Expect(NULL); foo_Expect(NULL);
function_a(); function_a();
} }
- :pass: FALSE - :pass: FALSE
:should: 'handle the situation where we did not expect nulls to pointers but got null' :should: 'handle the situation where we did not expect nulls to pointers but got null'
:code: | :code: |
@@ -104,10 +104,10 @@
POINT_T ex = {1, 2}; POINT_T ex = {1, 2};
bar_ExpectAndReturn(NULL); bar_ExpectAndReturn(NULL);
foo_Expect(&ex); foo_Expect(&ex);
function_a(); function_a();
} }
- :pass: FALSE - :pass: FALSE
:should: 'handle the situation where we pass single object with expect and it is wrong' :should: 'handle the situation where we pass single object with expect and it is wrong'
:code: | :code: |
@@ -117,10 +117,10 @@
POINT_T ex = {1, 3}; POINT_T ex = {1, 3};
bar_ExpectAndReturn(&pt); bar_ExpectAndReturn(&pt);
foo_Expect(&ex); foo_Expect(&ex);
function_a(); function_a();
} }
- :pass: TRUE - :pass: TRUE
:should: 'handle the situation where we pass single object with expect and use array handler' :should: 'handle the situation where we pass single object with expect and use array handler'
:code: | :code: |
@@ -130,10 +130,10 @@
POINT_T ex = {1, 2}; POINT_T ex = {1, 2};
bar_ExpectAndReturn(&pt); bar_ExpectAndReturn(&pt);
foo_ExpectWithArray(&ex, 1); foo_ExpectWithArray(&ex, 1);
function_a(); function_a();
} }
- :pass: FALSE - :pass: FALSE
:should: 'handle the situation where we pass single object with expect and use array handler and it is wrong' :should: 'handle the situation where we pass single object with expect and use array handler and it is wrong'
:code: | :code: |
@@ -143,10 +143,10 @@
POINT_T ex = {1, 3}; POINT_T ex = {1, 3};
bar_ExpectAndReturn(&pt); bar_ExpectAndReturn(&pt);
foo_ExpectWithArray(&ex, 1); foo_ExpectWithArray(&ex, 1);
function_a(); function_a();
} }
- :pass: TRUE - :pass: TRUE
:should: 'handle the situation where we pass multiple objects with expect and use array handler' :should: 'handle the situation where we pass multiple objects with expect and use array handler'
:code: | :code: |
@@ -156,10 +156,10 @@
POINT_T ex[] = {{1, 2}, {3, 4}, {5, 6}}; POINT_T ex[] = {{1, 2}, {3, 4}, {5, 6}};
bar_ExpectAndReturn(pt); bar_ExpectAndReturn(pt);
foo_ExpectWithArray(ex, 3); foo_ExpectWithArray(ex, 3);
function_a(); function_a();
} }
- :pass: FALSE - :pass: FALSE
:should: 'handle the situation where we pass multiple objects with expect and use array handler and it is wrong at end' :should: 'handle the situation where we pass multiple objects with expect and use array handler and it is wrong at end'
:code: | :code: |
@@ -169,7 +169,7 @@
POINT_T ex[] = {{1, 2}, {3, 4}, {5, 9}}; POINT_T ex[] = {{1, 2}, {3, 4}, {5, 9}};
bar_ExpectAndReturn(pt); bar_ExpectAndReturn(pt);
foo_ExpectWithArray(ex, 3); foo_ExpectWithArray(ex, 3);
function_a(); function_a();
} }
@@ -182,7 +182,7 @@
POINT_T ex = {1, 2}; POINT_T ex = {1, 2};
bar_ExpectAndReturn(&pt); bar_ExpectAndReturn(&pt);
fooa_Expect(&ex); fooa_Expect(&ex);
function_b(); function_b();
} }
@@ -193,10 +193,10 @@
{ {
bars_ExpectAndReturn("This is a\0 silly string"); bars_ExpectAndReturn("This is a\0 silly string");
foos_Expect("This is a\0 wacky string"); foos_Expect("This is a\0 wacky string");
function_c(); function_c();
} }
- :pass: FALSE - :pass: FALSE
:should: 'handle standard c string as null terminated and not do crappy memory compares of a byte, finding failures' :should: 'handle standard c string as null terminated and not do crappy memory compares of a byte, finding failures'
:code: | :code: |
@@ -204,7 +204,7 @@
{ {
bars_ExpectAndReturn("This is a silly string"); bars_ExpectAndReturn("This is a silly string");
foos_Expect("This is a wacky string"); foos_Expect("This is a wacky string");
function_c(); function_c();
} }
@@ -216,7 +216,7 @@
int expect_list[] = { 1, 9 }; int expect_list[] = { 1, 9 };
no_pointers_Expect(1, "silly"); no_pointers_Expect(1, "silly");
mixed_ExpectAndReturn(6, expect_list, 7, 13); mixed_ExpectAndReturn(6, expect_list, 7, 13);
TEST_ASSERT_EQUAL(13, function_d()); TEST_ASSERT_EQUAL(13, function_d());
} }
@@ -228,7 +228,7 @@
int expect_list[] = { 9, 1 }; int expect_list[] = { 9, 1 };
no_pointers_Expect(1, "silly"); no_pointers_Expect(1, "silly");
mixed_ExpectAndReturn(6, expect_list, 7, 13); mixed_ExpectAndReturn(6, expect_list, 7, 13);
TEST_ASSERT_EQUAL(13, function_d()); TEST_ASSERT_EQUAL(13, function_d());
} }
@@ -240,7 +240,7 @@
int expect_list[] = { 1, 2, 3, 4, 6 }; int expect_list[] = { 1, 2, 3, 4, 6 };
no_pointers_Expect(1, "silly"); no_pointers_Expect(1, "silly");
mixed_ExpectWithArrayAndReturn(6, expect_list, 4, 7, 13); mixed_ExpectWithArrayAndReturn(6, expect_list, 4, 7, 13);
TEST_ASSERT_EQUAL(13, function_d()); TEST_ASSERT_EQUAL(13, function_d());
} }
@@ -252,7 +252,7 @@
int expect_list[] = { 1, 2, 3, 4, 6 }; int expect_list[] = { 1, 2, 3, 4, 6 };
no_pointers_Expect(1, "silly"); no_pointers_Expect(1, "silly");
mixed_ExpectWithArrayAndReturn(6, expect_list, 5, 7, 13); mixed_ExpectWithArrayAndReturn(6, expect_list, 5, 7, 13);
TEST_ASSERT_EQUAL(13, function_d()); TEST_ASSERT_EQUAL(13, function_d());
} }
@@ -264,7 +264,7 @@
bars_ExpectAndReturn("This is a\0 silly string"); bars_ExpectAndReturn("This is a\0 silly string");
foos_ExpectAndThrow("This is a\0 wacky string", 55); foos_ExpectAndThrow("This is a\0 wacky string", 55);
foos_Expect("err"); foos_Expect("err");
function_c(); function_c();
} }
@@ -276,7 +276,7 @@
bars_ExpectAndReturn("This is a\0 silly string"); bars_ExpectAndReturn("This is a\0 silly string");
foos_ExpectAndThrow("This is a\0 wacky string", 55); foos_ExpectAndThrow("This is a\0 wacky string", 55);
foos_Expect("wrong error"); foos_Expect("wrong error");
function_c(); function_c();
} }
@@ -288,53 +288,53 @@
int expect_list[] = { 1, 2, 3, 4, 6 }; int expect_list[] = { 1, 2, 3, 4, 6 };
mixed_ExpectWithArrayAndReturn(6, expect_list, 4, 7, 13); mixed_ExpectWithArrayAndReturn(6, expect_list, 4, 7, 13);
no_pointers_Expect(1, "silly"); no_pointers_Expect(1, "silly");
TEST_ASSERT_EQUAL(13, function_d()); TEST_ASSERT_EQUAL(13, function_d());
} }
- :pass: TRUE - :pass: TRUE
:should: 'properly ignore first function but the other will work properly' :should: 'properly ExpectAnyArgs first function but the other will work properly'
:code: | :code: |
test() test()
{ {
int expect_list[] = { 1, 2, 3, 4, 6 }; int expect_list[] = { 1, 2, 3, 4, 6 };
no_pointers_Ignore(); no_pointers_ExpectAnyArgs();
mixed_ExpectWithArrayAndReturn(6, expect_list, 4, 7, 13); mixed_ExpectWithArrayAndReturn(6, expect_list, 4, 7, 13);
TEST_ASSERT_EQUAL(13, function_d()); TEST_ASSERT_EQUAL(13, function_d());
} }
- :pass: TRUE - :pass: TRUE
:should: 'properly ignore last function but the other will work properly' :should: 'properly ExpectAnyArgs last function but the other will work properly'
:code: | :code: |
test() test()
{ {
no_pointers_Expect(1, "silly"); no_pointers_Expect(1, "silly");
mixed_IgnoreAndReturn(13); mixed_ExpectAnyArgsAndReturn(13);
TEST_ASSERT_EQUAL(13, function_d()); TEST_ASSERT_EQUAL(13, function_d());
} }
- :pass: TRUE - :pass: TRUE
:should: 'be ok if we ignore a call each because we are counting calls' :should: 'be ok if we ExpectAnyArgs a call each because we are counting calls'
:code: | :code: |
test() test()
{ {
foos_Ignore(); foos_ExpectAnyArgs();
foos_Ignore(); foos_ExpectAnyArgs();
foos_Ignore(); foos_ExpectAnyArgs();
function_e(); function_e();
} }
- :pass: FALSE - :pass: FALSE
:should: 'fail if we do not ignore a call once because we are counting calls' :should: 'fail if we do not ExpectAnyArgs a call once because we are counting calls'
:code: | :code: |
test() test()
{ {
foos_Ignore(); foos_ExpectAnyArgs();
foos_Ignore(); foos_ExpectAnyArgs();
function_e(); function_e();
} }
@@ -1,8 +1,7 @@
--- ---
:cmock: :cmock:
:plugins: :plugins:
- 'ignore' - 'expect_any_args'
:ignore: :args_only
:systest: :systest:
:types: | :types: |
@@ -14,12 +13,17 @@
:source: :source:
:header: | :header: |
int function(int a, int b, int c); int function(int a, int b, int c);
void func_b(int a);
:code: | :code: |
int function(int a, int b, int c) int function(int a, int b, int c)
{ {
bar(b); bar(b);
return foo(a) + foo(b) + foo(c); return foo(a) + foo(b) + foo(c);
} }
void func_b(int a)
{
bar(a);
}
:tests: :tests:
:common: | :common: |
@@ -39,50 +43,50 @@
} }
- :pass: TRUE - :pass: TRUE
:should: 'ignore foo() calls' :should: 'ignore foo() call details'
:code: | :code: |
test() test()
{ {
bar_Expect(4); bar_Expect(4);
foo_IgnoreAndReturn(10); foo_ExpectAnyArgsAndReturn(10);
foo_IgnoreAndReturn(40); foo_ExpectAnyArgsAndReturn(40);
foo_IgnoreAndReturn(80); foo_ExpectAnyArgsAndReturn(80);
TEST_ASSERT_EQUAL(130, function(3, 4, 3)); TEST_ASSERT_EQUAL(130, function(3, 4, 3));
} }
- :pass: FALSE - :pass: FALSE
:should: 'ignore foo() calls and notice if we called foo() more times than expected' :should: 'ignore foo() call details and notice if we called foo() more times than expected'
:code: | :code: |
test() test()
{ {
bar_Expect(4); bar_Expect(4);
foo_IgnoreAndReturn(20); foo_ExpectAnyArgsAndReturn(20);
foo_IgnoreAndReturn(30); foo_ExpectAnyArgsAndReturn(30);
TEST_ASSERT_EQUAL(50, function(3, 4, 9)); TEST_ASSERT_EQUAL(50, function(3, 4, 9));
} }
- :pass: FALSE - :pass: FALSE
:should: 'ignore foo() calls and notice if we called foo() less times than expected' :should: 'ignore foo() call details and notice if we called foo() less times than expected'
:code: | :code: |
test() test()
{ {
bar_Expect(4); bar_Expect(4);
foo_IgnoreAndReturn(20); foo_ExpectAnyArgsAndReturn(20);
foo_IgnoreAndReturn(10); foo_ExpectAnyArgsAndReturn(10);
foo_IgnoreAndReturn(50); foo_ExpectAnyArgsAndReturn(50);
foo_IgnoreAndReturn(60); foo_ExpectAnyArgsAndReturn(60);
TEST_ASSERT_EQUAL(70, function(3, 4, 9)); TEST_ASSERT_EQUAL(70, function(3, 4, 9));
} }
- :pass: TRUE - :pass: TRUE
:should: 'ignore bar() and foo() calls' :should: 'ignore bar() and foo() call details'
:code: | :code: |
test() test()
{ {
bar_Ignore(); bar_ExpectAnyArgs();
foo_IgnoreAndReturn(50); foo_ExpectAnyArgsAndReturn(50);
foo_IgnoreAndReturn(50); foo_ExpectAnyArgsAndReturn(50);
foo_IgnoreAndReturn(50); foo_ExpectAnyArgsAndReturn(50);
TEST_ASSERT_EQUAL(150, function(0, 0, 0)); TEST_ASSERT_EQUAL(150, function(0, 0, 0));
} }
@@ -91,9 +95,9 @@
:code: | :code: |
test() test()
{ {
bar_Ignore(); bar_ExpectAnyArgs();
foo_IgnoreAndReturn(50); foo_ExpectAnyArgsAndReturn(50);
foo_IgnoreAndReturn(50); foo_ExpectAnyArgsAndReturn(50);
foo_ExpectAndReturn(3, 50); foo_ExpectAndReturn(3, 50);
TEST_ASSERT_EQUAL(150, function(1, 2, 3)); TEST_ASSERT_EQUAL(150, function(1, 2, 3));
} }
@@ -103,10 +107,10 @@
:code: | :code: |
test() test()
{ {
bar_Ignore(); bar_ExpectAnyArgs();
foo_ExpectAndReturn(1, 50); foo_ExpectAndReturn(1, 50);
foo_IgnoreAndReturn(50); foo_ExpectAnyArgsAndReturn(50);
foo_IgnoreAndReturn(50); foo_ExpectAnyArgsAndReturn(50);
TEST_ASSERT_EQUAL(150, function(1, 2, 3)); TEST_ASSERT_EQUAL(150, function(1, 2, 3));
} }
@@ -115,52 +119,76 @@
:code: | :code: |
test() test()
{ {
bar_Ignore(); bar_ExpectAnyArgs();
foo_ExpectAndReturn(1, 50); foo_ExpectAndReturn(1, 50);
foo_IgnoreAndReturn(50); foo_ExpectAnyArgsAndReturn(50);
foo_ExpectAndReturn(3, 50); foo_ExpectAndReturn(3, 50);
TEST_ASSERT_EQUAL(150, function(1, 2, 3)); TEST_ASSERT_EQUAL(150, function(1, 2, 3));
} }
# TODO: THIS IS WHAT PEOPLE EXPECT, BUT IS NOT BEING MET YET.
- :pass: FALSE - :pass: FALSE
:should: 'be able to detect problems with an expect even when using ignores' :should: 'be able to detect problems with an expect even when using ignores'
:code: | :code: |
test() test()
{ {
bar_Ignore(); bar_ExpectAnyArgs();
foo_ExpectAndReturn(1, 50); foo_ExpectAndReturn(1, 50);
foo_IgnoreAndReturn(50); foo_ExpectAnyArgsAndReturn(50);
foo_ExpectAndReturn(4, 50); foo_ExpectAndReturn(4, 50);
TEST_ASSERT_EQUAL(150, function(1, 2, 3)); TEST_ASSERT_EQUAL(150, function(1, 2, 3));
} }
- :pass: TRUE
:should: 'be able to handle a lone ExpectAnyArg call'
:code: |
test()
{
bar_ExpectAnyArgs();
func_b(1);
}
- :pass: FALSE
:should: 'be able to handle a lone ExpectAnyArg call that does not get called'
:code: |
test()
{
bar_ExpectAnyArgs();
}
- :pass: FALSE
:should: 'be able to handle a missing ExpectAnyArg call'
:code: |
test()
{
func_b(1);
}
- :pass: TRUE - :pass: TRUE
:should: 'ignore foo() calls over multiple mock calls' :should: 'ignore foo() calls over multiple mock calls'
:code: | :code: |
test() test()
{ {
bar_Ignore(); bar_ExpectAnyArgs();
foo_IgnoreAndReturn(50); foo_ExpectAnyArgsAndReturn(50);
foo_IgnoreAndReturn(60); foo_ExpectAnyArgsAndReturn(60);
foo_IgnoreAndReturn(70); foo_ExpectAnyArgsAndReturn(70);
TEST_ASSERT_EQUAL(180, function(0, 0, 0)); TEST_ASSERT_EQUAL(180, function(0, 0, 0));
bar_Ignore(); bar_ExpectAnyArgs();
foo_IgnoreAndReturn(30); foo_ExpectAnyArgsAndReturn(30);
foo_IgnoreAndReturn(80); foo_ExpectAnyArgsAndReturn(80);
foo_IgnoreAndReturn(10); foo_ExpectAnyArgsAndReturn(10);
TEST_ASSERT_EQUAL(120, function(0, 0, 0)); TEST_ASSERT_EQUAL(120, function(0, 0, 0));
bar_Ignore(); bar_ExpectAnyArgs();
foo_IgnoreAndReturn(70); foo_ExpectAnyArgsAndReturn(70);
foo_IgnoreAndReturn(20); foo_ExpectAnyArgsAndReturn(20);
foo_IgnoreAndReturn(20); foo_ExpectAnyArgsAndReturn(20);
TEST_ASSERT_EQUAL(110, function(0, 0, 0)); TEST_ASSERT_EQUAL(110, function(0, 0, 0));
} }
- :pass: TRUE - :pass: TRUE
:should: 'multiple cycles of expects still pass when ignores enabled' :should: 'have multiple cycles of expects still pass when this plugin enabled'
:code: | :code: |
test() test()
{ {
@@ -184,7 +212,7 @@
} }
- :pass: FALSE - :pass: FALSE
:should: 'multiple cycles of expects still fail when ignores enabled' :should: 'have multiple cycles of expects still fail when this plugin enabled'
:code: | :code: |
test() test()
{ {