mirror of
https://github.com/ThrowTheSwitch/CMock.git
synced 2026-06-23 14:00:33 +00:00
Compare commits
48 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6e03886f25 | |||
| 50adf82ed4 | |||
| f2ea4284a6 | |||
| fb96bb3033 | |||
| 9a44444f8b | |||
| 725641409b | |||
| c4cd7d54a9 | |||
| aed11e6d0d | |||
| 51b327042f | |||
| ef04f4ab7f | |||
| 27c5a9cff5 | |||
| 43fa31380d | |||
| 413c803543 | |||
| ee45a7b1e7 | |||
| 699563e503 | |||
| 454fcfb7a3 | |||
| 4b441eafea | |||
| a04e3f160c | |||
| df7c67c445 | |||
| 9c9f08c48b | |||
| 55462aef40 | |||
| 42dab4836d | |||
| 693c658780 | |||
| 7eb7e14fbc | |||
| 846423768b | |||
| 9e69cfb9b1 | |||
| 53d6a7c0e4 | |||
| a604fb71a4 | |||
| 46f609efee | |||
| 5ee669ecc0 | |||
| 02aeab8fef | |||
| 9e33ff32cf | |||
| 295fe3be4e | |||
| 73a6aa003b | |||
| 725bfd93a0 | |||
| 0b303dba29 | |||
| c61a35d2a5 | |||
| 1ffba4383c | |||
| 08b255868a | |||
| f0a9b5930e | |||
| 33dabf8338 | |||
| 7cd25b07a1 | |||
| b58f15d0be | |||
| 58971b15db | |||
| 4bda2b21d4 | |||
| 14ba424b02 | |||
| 6dff24ecda | |||
| 4bd12aaaf6 |
+75
-60
@@ -68,15 +68,15 @@ Installing
|
||||
==========
|
||||
|
||||
The first thing you need to do to install CMock is to get yourself
|
||||
a copy of Ruby. If you're on linux or osx, you probably already
|
||||
a copy of Ruby. If you're on linux or osx, you probably already
|
||||
have it. You can prove it by typing the following:
|
||||
|
||||
ruby --version
|
||||
|
||||
|
||||
|
||||
If it replied in a way that implies ignorance, then you're going to
|
||||
need to install it. You can go to [ruby-lang](https://ruby-lang.org)
|
||||
to get the latest version. You're also going to need to do that if it
|
||||
need to install it. You can go to [ruby-lang](https://ruby-lang.org)
|
||||
to get the latest version. You're also going to need to do that if it
|
||||
replied with a version that is older than 2.0.0. Go ahead. We'll wait.
|
||||
|
||||
Once you have Ruby, you have three options:
|
||||
@@ -128,12 +128,12 @@ if there are some.
|
||||
Array:
|
||||
------
|
||||
|
||||
An ExpectWithArray is another variant of Expect. Like expect, it cares about
|
||||
the number of times a mock is called, the arguments it is called with, and the
|
||||
values it is to return. This variant has another feature, though. For anything
|
||||
that resembles a pointer or array, it breaks the argument into TWO arguments.
|
||||
An ExpectWithArray is another variant of Expect. Like expect, it cares about
|
||||
the number of times a mock is called, the arguments it is called with, and the
|
||||
values it is to return. This variant has another feature, though. For anything
|
||||
that resembles a pointer or array, it breaks the argument into TWO arguments.
|
||||
The first is the original pointer. The second specify the number of elements
|
||||
it is to verify of that array. If you specify 1, it'll check one object. If 2,
|
||||
it is to verify of that array. If you specify 1, it'll check one object. If 2,
|
||||
it'll assume your pointer is pointing at the first of two elements in an array.
|
||||
If you specify zero elements, it will check just the pointer if
|
||||
`:smart` mode is configured or fail if `:compare_data` is set.
|
||||
@@ -151,9 +151,9 @@ Maybe you don't care about the number of times a particular function is called o
|
||||
the actual arguments it is called with. In that case, you want to use Ignore. Ignore
|
||||
only needs to be called once per test. It will then ignore any further calls to that
|
||||
particular mock. The IgnoreAndReturn works similarly, except that it has the added
|
||||
benefit of knowing what to return when that call happens. If the mock is called more
|
||||
benefit of knowing what to return when that call happens. If the mock is called more
|
||||
times than IgnoreAndReturn was called, it will keep returning the last value without
|
||||
complaint. If it's called less times, it will also ignore that. You SAID you didn't
|
||||
complaint. If it's called less times, it will also ignore that. You SAID you didn't
|
||||
care how many times it was called, right?
|
||||
|
||||
* `void func(void)` => `void func_Ignore(void)`
|
||||
@@ -179,7 +179,7 @@ ReturnThruPtr:
|
||||
--------------
|
||||
|
||||
Another option which operates on a particular argument of a function is the ReturnThruPtr
|
||||
plugin. For every argument that resembles a pointer or reference, CMock generates an
|
||||
plugin. For every argument that resembles a pointer or reference, CMock generates an
|
||||
instance of this function. Just as the AndReturn functions support injecting one or more
|
||||
return values into a queue, this function lets you specify one or more return values which
|
||||
are queued up and copied into the space being pointed at each time the mock is called.
|
||||
@@ -195,7 +195,7 @@ 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
|
||||
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.
|
||||
|
||||
* `void func(void)` => `void func_StubWithCallback(CMOCK_func_CALLBACK callback)`
|
||||
@@ -211,8 +211,8 @@ where `CMOCK_func_CALLBACK` looks like: `retval func(params, int NumCalls)`
|
||||
Cexception:
|
||||
-----------
|
||||
|
||||
Finally, if you are using Cexception for error handling, you can use this to throw errors
|
||||
from inside mocks. Like Expects, it remembers which call was supposed to throw the error,
|
||||
Finally, if you are using Cexception for error handling, you can use this to throw errors
|
||||
from inside mocks. Like Expects, it remembers which call was supposed to throw the error,
|
||||
and it still checks parameters first.
|
||||
|
||||
* `void func(void)` => `void func_ExpectAndThrow(value_to_throw)`
|
||||
@@ -295,8 +295,8 @@ from the defaults. We've tried to specify what the defaults are below.
|
||||
These are attributes that CMock should ignore for you for testing
|
||||
purposes. Custom compiler extensions and externs are handy things to
|
||||
put here. If your compiler is choking on some extended syntax, this
|
||||
is often a good place to look.
|
||||
|
||||
is often a good place to look.
|
||||
|
||||
* defaults: ['__ramfunc', '__irq', '__fiq', 'register', 'extern']
|
||||
* **note:** this option will reinsert these attributes onto the mock's calls.
|
||||
If that isn't what you are looking for, check out :strippables.
|
||||
@@ -306,16 +306,16 @@ from the defaults. We've tried to specify what the defaults are below.
|
||||
might show up in your codebase. If it encounters something it doesn't
|
||||
recognize, it's not going to mock it. We have the most common covered,
|
||||
but there are many compilers out there, and therefore many other options.
|
||||
|
||||
|
||||
* defaults: ['__stdcall', '__cdecl', '__fastcall']
|
||||
* **note:** this option will reinsert these attributes onto the mock's calls.
|
||||
If that isn't what you are looking for, check out :strippables.
|
||||
|
||||
* `:callback_after_arg_check`:
|
||||
Tell `:callback` plugin to do the normal argument checking **before** it
|
||||
calls the callback function by setting this to true. WHen false, the
|
||||
calls the callback function by setting this to true. When false, the
|
||||
callback function is called **instead** of the argument verification.
|
||||
|
||||
|
||||
* default: false
|
||||
|
||||
* `:callback_include_count`:
|
||||
@@ -323,14 +323,14 @@ from the defaults. We've tried to specify what the defaults are below.
|
||||
number of times the callback has been called. If set to false, the
|
||||
callback has the same interface as the mocked function. This can be
|
||||
handy when you're wanting to use callback as a stub.
|
||||
|
||||
|
||||
* default: true
|
||||
|
||||
* `:cexception_include`:
|
||||
Tell `:cexception` plugin where to find CException.h... You only need to
|
||||
define this if it's not in your build path already... which it usually
|
||||
will be for the purpose of your builds.
|
||||
|
||||
|
||||
* default: *nil*
|
||||
|
||||
* `:enforce_strict_ordering`:
|
||||
@@ -339,14 +339,14 @@ from the defaults. We've tried to specify what the defaults are below.
|
||||
will verify that the sizes are in the order you specified. You might
|
||||
*also* want to make sure that all different functions are called in a
|
||||
particular order. If so, set this to true.
|
||||
|
||||
|
||||
* default: false
|
||||
|
||||
* `:framework`:
|
||||
Currently the only option is `:unity.` Eventually if we support other
|
||||
unity test frameworks (or if you write one for us), they'll get added
|
||||
here.
|
||||
|
||||
|
||||
: default: :unity
|
||||
|
||||
* `:includes`:
|
||||
@@ -354,11 +354,11 @@ from the defaults. We've tried to specify what the defaults are below.
|
||||
mocks. Useful for global types and definitions used in your project.
|
||||
There are more specific versions if you care WHERE in the mock files
|
||||
the includes get placed. You can define any or all of these options.
|
||||
|
||||
|
||||
* `:includes`
|
||||
* `:includes_h_pre_orig_header`
|
||||
* `:includes_h_post_orig_header`
|
||||
* `:includes_c_pre_header`
|
||||
* `:includes_c_pre_header`
|
||||
* `:includes_c_post_header`
|
||||
* default: nil #for all 5 options
|
||||
|
||||
@@ -368,60 +368,60 @@ from the defaults. We've tried to specify what the defaults are below.
|
||||
the time (though it tries its best). If it comes across a type it doesn't
|
||||
recognize, you have a choice on how you want it to handle it. It can either
|
||||
perform a raw memory comparison and report any differences, or it can fail
|
||||
with a meaningful message. Either way, this feature will only happen after
|
||||
with a meaningful message. Either way, this feature will only happen after
|
||||
all other mechanisms have failed (The thing encountered isn't a standard
|
||||
type. It isn't in the :treat_as list. It isn't in a custom unity_helper).
|
||||
|
||||
* default: true
|
||||
|
||||
|
||||
* `:mock_path`:
|
||||
The directory where you would like the mock files generated to be
|
||||
placed.
|
||||
|
||||
|
||||
* default: mocks
|
||||
|
||||
* `:mock_prefix`:
|
||||
The prefix to prepend to your mock files. For example, if it's “Mock”, a file
|
||||
“USART.h” will get a mock called “MockUSART.c”. This CAN be used with a suffix
|
||||
at the same time.
|
||||
|
||||
|
||||
* default: Mock
|
||||
|
||||
* `:mock_suffix`:
|
||||
The suffix to append to your mock files. For example, it it's "_Mock", a file
|
||||
"USART.h" will get a mock called "USART_Mock.h". This CAN be used with a prefix
|
||||
at the same time.
|
||||
|
||||
|
||||
* default: ""
|
||||
|
||||
* `:plugins`:
|
||||
An array of which plugins to enable. ':expect' is always active. Also
|
||||
available currently:
|
||||
|
||||
* `:ignore`
|
||||
* `:ignore_arg`
|
||||
|
||||
* `:ignore`
|
||||
* `:ignore_arg`
|
||||
* `:expect_any_args`
|
||||
* `:array`
|
||||
* `:cexception`
|
||||
* `:callback`
|
||||
* `:cexception`
|
||||
* `:callback`
|
||||
* `:return_thru_ptr`
|
||||
|
||||
* `:strippables`:
|
||||
An array containing a list of items to remove from the header
|
||||
before deciding what should be mocked. This can be something simple
|
||||
like a compiler extension CMock wouldn't recognize, or could be a
|
||||
regex to reject certain function name patterns. This is a great way to
|
||||
regex to reject certain function name patterns. This is a great way to
|
||||
get rid of compiler extensions when your test compiler doesn't support
|
||||
them. For example, use `:strippables: ['(?:functionName\s*\(+.*?\)+)']`
|
||||
to prevent a function `functionName` from being mocked. By default, it
|
||||
is ignoring all gcc attribute extensions.
|
||||
|
||||
|
||||
* default: ['(?:__attribute__\s*\(+.*?\)+)']
|
||||
|
||||
|
||||
* `:subdir`:
|
||||
This is a relative subdirectory for your mocks. Set this to e.g. "sys" in
|
||||
This is a relative subdirectory for your mocks. Set this to e.g. "sys" in
|
||||
order to create a mock for `sys/types.h` in `(:mock_path)/sys/`.
|
||||
|
||||
|
||||
* default: ""
|
||||
|
||||
* `:treat_as`:
|
||||
@@ -432,11 +432,11 @@ from the defaults. We've tried to specify what the defaults are below.
|
||||
did that one for you). Maybe you have a type that is a pointer to an
|
||||
array of unsigned characters? No problem, just add 'UINT8_T*' =>
|
||||
'HEX8*'
|
||||
|
||||
* NOTE: unlike the other options, your specifications MERGE with the
|
||||
|
||||
* NOTE: unlike the other options, your specifications MERGE with the
|
||||
default list. Therefore, if you want to override something, you must
|
||||
reassign it to something else (or to *nil* if you don't want it)
|
||||
|
||||
|
||||
* default:
|
||||
* 'int': 'INT'
|
||||
* 'char': 'INT8'
|
||||
@@ -483,14 +483,14 @@ from the defaults. We've tried to specify what the defaults are below.
|
||||
We've seen "fun" legacy systems typedef 'void' with a custom type,
|
||||
like MY_VOID. Add any instances of those to this list to help CMock
|
||||
understand how to deal with your code.
|
||||
|
||||
|
||||
* default: []
|
||||
|
||||
* `:treat_externs`:
|
||||
This specifies how you want CMock to handle functions that have been
|
||||
marked as extern in the header file. Should it mock them?
|
||||
|
||||
* `:include` will mock externed functions
|
||||
|
||||
* `:include` will mock externed functions
|
||||
* `:exclude` will ignore externed functions (default).
|
||||
|
||||
* `:unity_helper_path`:
|
||||
@@ -500,23 +500,23 @@ from the defaults. We've tried to specify what the defaults are below.
|
||||
trick is that you make sure you follow the naming convention:
|
||||
`UNITY_TEST_ASSERT_EQUAL_YourType`. If it finds macros of the right
|
||||
shape that match that pattern, it'll use them.
|
||||
|
||||
|
||||
* default: []
|
||||
|
||||
* `:verbosity`:
|
||||
How loud shoudl CMock be?
|
||||
|
||||
How loud should CMock be?
|
||||
|
||||
* 0 for errors only
|
||||
* 1 for errors and warnings
|
||||
* 2 for normal (default)
|
||||
* 2 for normal (default)
|
||||
* 3 for verbose
|
||||
|
||||
* `:weak`:
|
||||
When set this to some value, the generated mocks are defined as weak
|
||||
When set this to some value, the generated mocks are defined as weak
|
||||
symbols using the configured format. This allows them to be overridden
|
||||
in particular tests.
|
||||
|
||||
* Set to '__attribute ((weak))' for weak mocks when using GCC.
|
||||
in particular tests.
|
||||
|
||||
* Set to '__attribute ((weak))' for weak mocks when using GCC.
|
||||
* Set to any non-empty string for weak mocks when using IAR.
|
||||
* default: ""
|
||||
|
||||
@@ -525,7 +525,7 @@ from the defaults. We've tried to specify what the defaults are below.
|
||||
it, it usually contains function prototypes (otherwise what was the
|
||||
point?). You can control what happens when this isn't true. You can
|
||||
set this to `:warn,` `:ignore,` or `:error`
|
||||
|
||||
|
||||
* default: :warn
|
||||
|
||||
* `:when_ptr`:
|
||||
@@ -538,15 +538,30 @@ from the defaults. We've tried to specify what the defaults are below.
|
||||
single element of what is being pointed to. So if you have a pointer
|
||||
to a struct called ORGAN_T, it will compare one ORGAN_T (whatever that
|
||||
is).
|
||||
|
||||
|
||||
* default: :smart
|
||||
|
||||
* `:fail_on_unexpected_calls`:
|
||||
By default, CMock will fail a test if a mock is called without _Expect and _Ignore
|
||||
called first. While this forces test writers to be more explicit in their expectations,
|
||||
it can clutter tests with _Expect or _Ignore calls for functions which are not the focus
|
||||
of the test. While this is a good indicator that this module should be refactored, some
|
||||
users are not fans of the additional noise.
|
||||
|
||||
Therefore, :fail_on_unexpected_calls can be set to false to force all mocks to start with
|
||||
the assumption that they are operating as _Ignore unless otherwise specified.
|
||||
|
||||
* default: true
|
||||
* **note:**
|
||||
If this option is disabled, the mocked functions will return
|
||||
a default value (0) when called (and only if they have to return something of course).
|
||||
|
||||
|
||||
Compiled Options:
|
||||
-----------------
|
||||
|
||||
A number of #defines also exist for customizing the cmock experience.
|
||||
Feel free to pass these into your compiler or whatever is most
|
||||
Feel free to pass these into your compiler or whatever is most
|
||||
convenient. CMock will otherwise do its best to guess what you want
|
||||
based on other settings, particularly Unity's settings.
|
||||
|
||||
@@ -580,9 +595,9 @@ based on other settings, particularly Unity's settings.
|
||||
Examples
|
||||
========
|
||||
|
||||
You can look in the examples directory for a couple of examples on how
|
||||
You can look in the [examples directory](/examples/) for a couple of examples on how
|
||||
you might tool CMock into your build process. You may also want to consider
|
||||
using [Ceedling](https://throwtheswitch.org/Ceedling). Please note that
|
||||
these examples are meant to show how the build process works. They have
|
||||
these examples are meant to show how the build process works. They have
|
||||
failing tests ON PURPOSE to show what that would look like. Don't be alarmed. ;)
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ class CMockConfig
|
||||
:attributes => ['__ramfunc', '__irq', '__fiq', 'register', 'extern'],
|
||||
:c_calling_conventions => ['__stdcall', '__cdecl', '__fastcall'],
|
||||
:enforce_strict_ordering => false,
|
||||
:fail_on_unexpected_calls => true,
|
||||
:unity_helper_path => false,
|
||||
:treat_as => {},
|
||||
:treat_as_void => [],
|
||||
|
||||
+13
-1
@@ -18,6 +18,7 @@ class CMockGenerator
|
||||
@weak = @config.weak
|
||||
@ordered = @config.enforce_strict_ordering
|
||||
@framework = @config.framework.to_s
|
||||
@fail_on_unexpected_calls = @config.fail_on_unexpected_calls
|
||||
|
||||
@subdir = @config.subdir
|
||||
|
||||
@@ -102,6 +103,7 @@ class CMockGenerator
|
||||
file << "\n"
|
||||
file << "/* Ignore the following warnings, since we are copying code */\n"
|
||||
file << "#if defined(__GNUC__) && !defined(__ICC) && !defined(__TMS470__)\n"
|
||||
file << "#pragma GCC diagnostic push\n"
|
||||
file << "#if !defined(__clang__)\n"
|
||||
file << "#pragma GCC diagnostic ignored \"-Wpragmas\"\n"
|
||||
file << "#endif\n"
|
||||
@@ -124,7 +126,12 @@ class CMockGenerator
|
||||
end
|
||||
|
||||
def create_mock_header_footer(header)
|
||||
header << "\n#endif\n"
|
||||
header << "\n"
|
||||
header << "#if defined(__GNUC__) && !defined(__ICC) && !defined(__TMS470__)\n"
|
||||
header << "#pragma GCC diagnostic pop\n"
|
||||
header << "#endif\n"
|
||||
header << "\n"
|
||||
header << "#endif\n"
|
||||
end
|
||||
|
||||
def create_source_header_section(file, filename, functions)
|
||||
@@ -196,6 +203,11 @@ class CMockGenerator
|
||||
file << " CMock_Guts_MemFreeAll();\n"
|
||||
file << " memset(&Mock, 0, sizeof(Mock));\n"
|
||||
file << functions.collect {|function| @plugins.run(:mock_destroy, function)}.join
|
||||
|
||||
unless (@fail_on_unexpected_calls)
|
||||
file << functions.collect {|function| @plugins.run(:mock_ignore, function)}.join
|
||||
end
|
||||
|
||||
if (@ordered)
|
||||
file << " GlobalExpectCount = 0;\n"
|
||||
file << " GlobalVerifyOrder = 0;\n"
|
||||
|
||||
@@ -68,7 +68,7 @@ class CMockGeneratorPluginExpect
|
||||
function[:args].each do |arg|
|
||||
lines << @utils.code_verify_an_arg_expectation(function, arg)
|
||||
end
|
||||
lines << "\n }\n"
|
||||
lines << " }\n"
|
||||
lines
|
||||
end
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ class CMockGeneratorPluginExpectAnyArgs
|
||||
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"
|
||||
@@ -38,19 +37,6 @@ class CMockGeneratorPluginExpectAnyArgs
|
||||
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?])
|
||||
# return_type = function[:return][:const?] ? "(const #{function[:return][:type]})" : ((function[:return][:type] =~ /cmock/) ? "(#{function[:return][:type]})" : '')
|
||||
# lines << " return #{return_type}cmock_call_instance->ReturnVal;\n }\n"
|
||||
# end
|
||||
# lines
|
||||
# end
|
||||
|
||||
def mock_interfaces(function)
|
||||
lines = ""
|
||||
if (function[:return][:void?])
|
||||
|
||||
@@ -65,6 +65,10 @@ class CMockGeneratorPluginIgnore
|
||||
lines << "}\n\n"
|
||||
end
|
||||
|
||||
def mock_ignore(function)
|
||||
" Mock.#{function[:name]}_IgnoreBool = (int) 1;\n"
|
||||
end
|
||||
|
||||
def mock_verify(function)
|
||||
func_name = function[:name]
|
||||
" if (Mock.#{func_name}_IgnoreBool)\n Mock.#{func_name}_CallInstance = CMOCK_GUTS_NONE;\n"
|
||||
|
||||
@@ -112,12 +112,11 @@ class CMockGeneratorUtils
|
||||
else
|
||||
(@helpers.nil? or @helpers[:unity_helper].nil?) ? ["UNITY_TEST_ASSERT_EQUAL",''] : @helpers[:unity_helper].get_helper(c_type)
|
||||
end
|
||||
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]
|
||||
end
|
||||
|
||||
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 = lookup_expect_type(function, arg)
|
||||
lines = ""
|
||||
lines << " if (!#{ignore})\n" if @ignore_arg
|
||||
lines << " {\n"
|
||||
@@ -152,7 +151,7 @@ class CMockGeneratorUtils
|
||||
end
|
||||
|
||||
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 = lookup_expect_type(function, arg)
|
||||
depth_name = (arg[:ptr?]) ? "cmock_call_instance->Expected_#{arg_name}_Depth" : 1
|
||||
lines = ""
|
||||
lines << " if (!#{ignore})\n" if @ignore_arg
|
||||
@@ -188,7 +187,7 @@ class CMockGeneratorUtils
|
||||
end
|
||||
|
||||
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 = lookup_expect_type(function, arg)
|
||||
depth_name = (arg[:ptr?]) ? "cmock_call_instance->Expected_#{arg_name}_Depth" : 1
|
||||
lines = ""
|
||||
lines << " if (!#{ignore})\n" if @ignore_arg
|
||||
|
||||
+39
-32
@@ -6,12 +6,13 @@
|
||||
|
||||
class CMockHeaderParser
|
||||
|
||||
attr_accessor :funcs, :c_attributes, :treat_as_void, :treat_externs
|
||||
attr_accessor :funcs, :c_attr_noconst, :c_attributes, :treat_as_void, :treat_externs
|
||||
|
||||
def initialize(cfg)
|
||||
@funcs = []
|
||||
@c_strippables = cfg.strippables
|
||||
@c_attributes = (['const'] + cfg.attributes).uniq
|
||||
@c_attr_noconst = cfg.attributes.uniq - ['const']
|
||||
@c_attributes = ['const'] + c_attr_noconst
|
||||
@c_calling_conventions = cfg.c_calling_conventions.uniq
|
||||
@treat_as_void = (['void'] + cfg.treat_as_void).uniq
|
||||
@declaration_parse_matcher = /([\d\w\s\*\(\),\[\]]+??)\(([\d\w\s\*\(\),\.\[\]+-]*)\)$/m
|
||||
@@ -79,7 +80,7 @@ class CMockHeaderParser
|
||||
# enums, unions, structs, and typedefs can all contain things (e.g. function pointers) that parse like function prototypes, so yank them
|
||||
# forward declared structs are removed before struct definitions so they don't mess up real thing later. we leave structs keywords in function prototypes
|
||||
source.gsub!(/^[\w\s]*struct[^;\{\}\(\)]+;/m, '') # remove forward declared structs
|
||||
source.gsub!(/^[\w\s]*(enum|union|struct|typepdef)[\w\s]*\{[^\}]+\}[\w\s\*\,]*;/m, '') # remove struct, union, and enum definitions and typedefs with braces
|
||||
source.gsub!(/^[\w\s]*(enum|union|struct|typedef)[\w\s]*\{[^\}]+\}[\w\s\*\,]*;/m, '') # remove struct, union, and enum definitions and typedefs with braces
|
||||
source.gsub!(/(\W)(?:register|auto|static|restrict)(\W)/, '\1\2') # remove problem keywords
|
||||
source.gsub!(/\s*=\s*['"a-zA-Z0-9_\.]+\s*/, '') # remove default value statements from argument lists
|
||||
source.gsub!(/^(?:[\w\s]*\W)?typedef\W[^;]*/m, '') # remove typedef statements
|
||||
@@ -94,7 +95,14 @@ class CMockHeaderParser
|
||||
end
|
||||
|
||||
# remove nested pairs of braces because no function declarations will be inside of them (leave outer pair for function definition detection)
|
||||
source.gsub!(/\{([^\{\}]*|\g<0>)*\}/m, '{ }')
|
||||
if (RUBY_VERSION.split('.')[0].to_i > 1)
|
||||
#we assign a string first because (no joke) if Ruby 1.9.3 sees this line as a regex, it will crash.
|
||||
r = "\\{([^\\{\\}]*|\\g<0>)*\\}"
|
||||
source.gsub!(/#{r}/m, '{ }')
|
||||
else
|
||||
while source.gsub!(/\{[^\{\}]*\{[^\{\}]*\}[^\{\}]*\}/m, '{ }')
|
||||
end
|
||||
end
|
||||
|
||||
# remove function definitions by stripping off the arguments right now
|
||||
source.gsub!(/\([^\)]*\)\s*\{[^\}]*\}/m, ";")
|
||||
@@ -137,46 +145,45 @@ 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 ...
|
||||
|
||||
# Split up words and remove known attributes, but in case of pointer args, don't remove any
|
||||
# 'const' from the type that it points to, since that may change the underlying assembly-code
|
||||
# pointer type on some embedded platforms, making it point to RAM instead of ROM. (I.e. For
|
||||
# pointer args, remove 'const' only when it applies to the pointer itself. For non-pointer
|
||||
# args, remove 'const' regardless.)
|
||||
#
|
||||
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(' ')),
|
||||
ptr_const_info = divine_ptr_and_const(arg)
|
||||
arg_elements = arg_array - (arg.include?('*') ? @c_attr_noconst : @c_attributes)
|
||||
args << { :type => arg_elements[0..(ptr_const_info[:const_ptr?] ? -3 : -2)].join(' '),
|
||||
:name => arg_elements[-1]
|
||||
}.merge(divine_ptr_and_const(arg))
|
||||
}.merge(ptr_const_info)
|
||||
end
|
||||
return args
|
||||
end
|
||||
|
||||
def divine_ptr(arg_type)
|
||||
return false unless arg_type.include? '*'
|
||||
return false if arg_type.gsub(/(const|char|\*|\s)+/,'').empty?
|
||||
def divine_ptr(arg)
|
||||
return false unless arg.include? '*'
|
||||
# treat "const char *" and similar as a string, not a pointer
|
||||
return false if /(^|\s)(const\s+)?char(\s+const)?\s*\*(?!.*\*)/ =~ arg
|
||||
return true
|
||||
end
|
||||
|
||||
def divine_const(arg)
|
||||
return false if !(/(?:^|\s|\*)const(?:\*|\s|$)/ =~ arg) # check for const as part of a larger word
|
||||
return true if (/const(?:\w|\s)*\*/ =~ arg) # check const comes before * indicating const data
|
||||
return false if (/\*\s*const/ =~ arg) # check const comes after * indicating const ptr
|
||||
return true
|
||||
# a non-pointer arg containing "const" is a constant
|
||||
# an arg containing "const" before the last * is a pointer to a constant
|
||||
return ( arg.include?('*') ? (/(^|\s|\*)const(\s(\w|\s)*)?\*(?!.*\*)/ =~ arg)
|
||||
: (/(^|\s)const(\s|$)/ =~ arg) ) ? true : false
|
||||
end
|
||||
|
||||
def divine_ptr_and_const(arg)
|
||||
divination = { :ptr? => false, :const? => false, :const_ptr? => false }
|
||||
divination = {}
|
||||
|
||||
#first check if there is a pointer present and that it's not part of a C string or function definition
|
||||
#divination[:ptr?] = (arg.split[0..-2].join.include?('*') && !arg.gsub(/(const|char|\*|\s)+/,'').empty?)
|
||||
divination[:ptr?] = (arg.include?('*') && !arg.gsub(/(const|char|\*|\s)+/,'').empty?)
|
||||
divination[:ptr?] = divine_ptr(arg)
|
||||
divination[:const?] = divine_const(arg)
|
||||
|
||||
#if there isn't a const that isn't part of a larger word, we're done
|
||||
return divination if !(/(?:^|\s|\*)const(?:\*|\s|$)/ =~ arg)
|
||||
divination[:const?] = true
|
||||
|
||||
# check const comes after * indicating const ptr
|
||||
if (/\*\s*const/ =~ arg)
|
||||
divination[:const_ptr?] = true
|
||||
|
||||
#check const comes before * indicating also const data
|
||||
divination[:const?] = (/const(?:\w|\s)*\*/ =~ arg) ? true : false
|
||||
end
|
||||
# an arg containing "const" after the last * is a constant pointer
|
||||
divination[:const_ptr?] = (/\*(?!.*\*)\s*const(\s|$)/ =~ arg) ? true : false
|
||||
|
||||
return divination
|
||||
end
|
||||
@@ -230,8 +237,8 @@ class CMockHeaderParser
|
||||
|
||||
#process function attributes, return type, and name
|
||||
descriptors = regex_match[1]
|
||||
descriptors.gsub!(/\s+\*/,'*') #remove space to place asterisks with return type (where they belong)
|
||||
descriptors.gsub!(/\*(\w)/,'* \1') #pull asterisks away from function name to place asterisks with return type (where they belong)
|
||||
descriptors.gsub!(/(\w)\*/,'\1 *') #pull asterisks away from preceding word
|
||||
descriptors.gsub!(/\*(\w)/,'* \1') #pull asterisks away from following word
|
||||
descriptors = descriptors.split #array of all descriptor strings
|
||||
|
||||
#grab name
|
||||
@@ -251,7 +258,7 @@ class CMockHeaderParser
|
||||
end
|
||||
end
|
||||
decl[:modifier] = decl[:modifier].join(' ')
|
||||
rettype = rettype.join(' ')
|
||||
rettype = rettype.join(' ').gsub(/\s+\*/,'*') #remove space before asterisks
|
||||
rettype = 'void' if (@local_as_void.include?(rettype.strip))
|
||||
decl[:return] = { :type => rettype,
|
||||
:name => 'cmock_to_return',
|
||||
|
||||
+27
-12
@@ -2,30 +2,25 @@
|
||||
# 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]
|
||||
# ==========================================
|
||||
# ==========================================
|
||||
|
||||
require 'thread'
|
||||
|
||||
class CMockPluginManager
|
||||
|
||||
attr_accessor :plugins
|
||||
|
||||
|
||||
def initialize(config, utils)
|
||||
@plugins = []
|
||||
plugins_to_load = [:expect, config.plugins].flatten.uniq.compact
|
||||
plugins_to_load.each do |plugin|
|
||||
plugin_name = plugin.to_s
|
||||
object_name = "CMockGeneratorPlugin" + camelize(plugin_name)
|
||||
begin
|
||||
unless (Object.const_defined? object_name)
|
||||
require "#{File.expand_path(File.dirname(__FILE__))}/cmock_generator_plugin_#{plugin_name.downcase}.rb"
|
||||
end
|
||||
@plugins << eval("#{object_name}.new(config, utils)")
|
||||
rescue
|
||||
raise "ERROR: CMock unable to load plugin '#{plugin_name}'"
|
||||
end
|
||||
self.class.plugin_require_mutex.synchronize { load_plugin(plugin_name, object_name, config, utils) }
|
||||
end
|
||||
@plugins.sort! {|a,b| a.priority <=> b.priority }
|
||||
end
|
||||
|
||||
|
||||
def run(method, args=nil)
|
||||
if args.nil?
|
||||
return @plugins.collect{ |plugin| plugin.send(method) if plugin.respond_to?(method) }.flatten.join
|
||||
@@ -33,8 +28,28 @@ class CMockPluginManager
|
||||
return @plugins.collect{ |plugin| plugin.send(method, args) if plugin.respond_to?(method) }.flatten.join
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def camelize(lower_case_and_underscored_word)
|
||||
lower_case_and_underscored_word.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.plugin_require_mutex
|
||||
@mutex ||= Mutex.new
|
||||
end
|
||||
|
||||
def load_plugin(plugin_name, object_name, config, utils)
|
||||
begin
|
||||
unless (Object.const_defined? object_name)
|
||||
file_name = "#{File.expand_path(File.dirname(__FILE__))}/cmock_generator_plugin_#{plugin_name.downcase}.rb"
|
||||
require file_name
|
||||
end
|
||||
class_name = Object.const_get(object_name)
|
||||
@plugins << class_name.new(config, utils)
|
||||
rescue
|
||||
file_name = "#{File.expand_path(File.dirname(__FILE__))}/cmock_generator_plugin_#{plugin_name.downcase}.rb"
|
||||
raise "ERROR: CMock unable to load plugin '#{plugin_name}' '#{object_name}' #{file_name}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
215
|
||||
216
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
2.4.4
|
||||
2.4.5
|
||||
|
||||
|
||||
+42
-17
@@ -18,8 +18,9 @@ RUNNERS_DIR = File.join(TEST_BUILD_DIR, 'runners')
|
||||
MOCKS_DIR = File.join(TEST_BUILD_DIR, 'mocks')
|
||||
TEST_BIN_DIR = TEST_BUILD_DIR
|
||||
MOCK_PREFIX = ENV.fetch('TEST_MOCK_PREFIX', 'mock_')
|
||||
MOCK_SUFFIX = ENV.fetch('TEST_MOCK_SUFFIX', '')
|
||||
TEST_MAKEFILE = ENV.fetch('TEST_MAKEFILE', File.join(TEST_BUILD_DIR, 'MakefileTestSupport'))
|
||||
MOCK_MATCHER = /#{MOCK_PREFIX}[A-Za-z_][A-Za-z0-9_\-\.]+/
|
||||
MOCK_MATCHER = /#{MOCK_PREFIX}[A-Za-z_][A-Za-z0-9_\-\.]+#{MOCK_SUFFIX}/
|
||||
|
||||
[TEST_BUILD_DIR, OBJ_DIR, RUNNERS_DIR, MOCKS_DIR, TEST_BIN_DIR].each do |dir|
|
||||
FileUtils.mkdir_p dir
|
||||
@@ -58,7 +59,8 @@ File.open(TEST_MAKEFILE, "w") do |mkfile|
|
||||
test_sources = Dir["#{TEST_DIR}/**/test_*.c"]
|
||||
test_targets = []
|
||||
generator = UnityTestRunnerGenerator.new
|
||||
all_headers = Dir["#{SRC_DIR}/**/*.h"]
|
||||
all_headers = Dir["#{SRC_DIR}/**/{[!#{MOCK_PREFIX}]}*{[!#{MOCK_SUFFIX}]}.h"] #headers that begin with prefix or end with suffix are not included
|
||||
makefile_targets = []
|
||||
|
||||
test_sources.each do |test|
|
||||
module_name = File.basename(test, '.c')
|
||||
@@ -67,14 +69,39 @@ File.open(TEST_MAKEFILE, "w") do |mkfile|
|
||||
runner_source = File.join(RUNNERS_DIR, "runner_#{module_name}.c")
|
||||
runner_obj = File.join(OBJ_DIR, "runner_#{module_name}.o")
|
||||
test_bin = File.join(TEST_BIN_DIR, module_name)
|
||||
test_results = File.join(TEST_BIN_DIR, module_name + '.result')
|
||||
test_results = File.join(TEST_BIN_DIR, module_name + '.testresult')
|
||||
|
||||
cfg = {
|
||||
src: test,
|
||||
includes: generator.find_includes(File.readlines(test).join(''))
|
||||
}
|
||||
|
||||
# Build main project modules, with TEST defined
|
||||
module_src = File.join(SRC_DIR, "#{src_module_name}.c")
|
||||
module_obj = File.join(OBJ_DIR, "#{src_module_name}.o")
|
||||
mkfile.puts "#{module_obj}: #{module_src}"
|
||||
mkfile.puts "\t${CC} -o $@ -c $< -DTEST -I #{SRC_DIR}"
|
||||
mkfile.puts ""
|
||||
if not makefile_targets.include? module_obj
|
||||
makefile_targets.push(module_obj)
|
||||
mkfile.puts "#{module_obj}: #{module_src}"
|
||||
mkfile.puts "\t${CC} -o $@ -c $< ${TEST_CFLAGS} -I #{SRC_DIR} ${INCLUDE_PATH}"
|
||||
mkfile.puts ""
|
||||
end
|
||||
|
||||
# process link-only files
|
||||
linkonly = cfg[:includes][:linkonly]
|
||||
linkonly_objs = []
|
||||
linkonly.each do |linkonlyfile|
|
||||
linkonlybase = File.basename(linkonlyfile)
|
||||
linkonlymodule_src = File.join(SRC_DIR, "#{linkonlyfile}.c")
|
||||
linkonlymodule_obj = File.join(OBJ_DIR, "#{linkonlybase}.o")
|
||||
linkonly_objs.push(linkonlymodule_obj)
|
||||
#only create the target if we didn't already
|
||||
if not makefile_targets.include? linkonlymodule_obj
|
||||
makefile_targets.push(linkonlymodule_obj)
|
||||
mkfile.puts "#{linkonlymodule_obj}: #{linkonlymodule_src}"
|
||||
mkfile.puts "\t${CC} -o $@ -c $< ${TEST_CFLAGS} -I #{SRC_DIR} ${INCLUDE_PATH}"
|
||||
mkfile.puts ""
|
||||
end
|
||||
end
|
||||
|
||||
# Create runners
|
||||
mkfile.puts "#{runner_source}: #{test}"
|
||||
@@ -83,17 +110,14 @@ File.open(TEST_MAKEFILE, "w") do |mkfile|
|
||||
|
||||
# Build runner
|
||||
mkfile.puts "#{runner_obj}: #{runner_source}"
|
||||
mkfile.puts "\t${CC} -o $@ -c $< ${TEST_CFLAGS} -I #{SRC_DIR} -I #{MOCKS_DIR} -I #{UNITY_SRC} -I #{CMOCK_SRC}"
|
||||
mkfile.puts "\t${CC} -o $@ -c $< ${TEST_CFLAGS} -I #{SRC_DIR} -I #{MOCKS_DIR} -I #{UNITY_SRC} -I #{CMOCK_SRC} ${INCLUDE_PATH}"
|
||||
mkfile.puts ""
|
||||
|
||||
# Collect mocks to generate
|
||||
cfg = {
|
||||
src: test,
|
||||
includes: generator.find_includes(File.readlines(test).join(''))
|
||||
}
|
||||
system_mocks = cfg[:includes][:system].select{|name| name =~ MOCK_MATCHER}
|
||||
raise "Mocking of system headers is not yet supported!" if !system_mocks.empty?
|
||||
local_mocks = cfg[:includes][:local].select{|name| name =~ MOCK_MATCHER}
|
||||
|
||||
module_names_to_mock = local_mocks.map{|name| "#{name.sub(/#{MOCK_PREFIX}/,'')}.h"}
|
||||
headers_to_mock = []
|
||||
module_names_to_mock.each do |name|
|
||||
@@ -107,6 +131,7 @@ File.open(TEST_MAKEFILE, "w") do |mkfile|
|
||||
raise "Module header '#{name}' not found to mock!" unless header_to_mock
|
||||
headers_to_mock << header_to_mock
|
||||
end
|
||||
|
||||
all_headers_to_mock += headers_to_mock
|
||||
mock_objs = headers_to_mock.map do |hdr|
|
||||
mock_name = MOCK_PREFIX + File.basename(hdr, '.h')
|
||||
@@ -116,18 +141,18 @@ File.open(TEST_MAKEFILE, "w") do |mkfile|
|
||||
|
||||
# Build test suite
|
||||
mkfile.puts "#{test_obj}: #{test} #{module_obj} #{mock_objs.join(' ')}"
|
||||
mkfile.puts "\t${CC} -o $@ -c $< ${TEST_CFLAGS} -I #{SRC_DIR} -I #{UNITY_SRC} -I #{CMOCK_SRC} -I #{MOCKS_DIR}"
|
||||
mkfile.puts "\t${CC} -o $@ -c $< ${TEST_CFLAGS} -I #{SRC_DIR} -I #{UNITY_SRC} -I #{CMOCK_SRC} -I #{MOCKS_DIR} ${INCLUDE_PATH}"
|
||||
mkfile.puts ""
|
||||
|
||||
# Build test suite executable
|
||||
test_objs = "#{test_obj} #{runner_obj} #{module_obj} #{mock_objs.join(' ')} #{UNITY_OBJ} #{CMOCK_OBJ}"
|
||||
test_objs = "#{test_obj} #{runner_obj} #{module_obj} #{mock_objs.join(' ')} #{linkonly_objs.join(' ')} #{UNITY_OBJ} #{CMOCK_OBJ}"
|
||||
mkfile.puts "#{test_bin}: #{test_objs}"
|
||||
mkfile.puts "\t${CC} -o $@ #{test_objs}"
|
||||
mkfile.puts "\t${CC} -o $@ ${LDFLAGS} #{test_objs}"
|
||||
mkfile.puts ""
|
||||
|
||||
# Run test suite and generate report
|
||||
mkfile.puts "#{test_results}: #{test_bin}"
|
||||
mkfile.puts "\t-#{test_bin} &> #{test_results}"
|
||||
mkfile.puts "\t-#{test_bin} > #{test_results} 2>&1"
|
||||
mkfile.puts ""
|
||||
|
||||
test_targets << test_bin
|
||||
@@ -145,7 +170,7 @@ File.open(TEST_MAKEFILE, "w") do |mkfile|
|
||||
mkfile.puts ""
|
||||
|
||||
mkfile.puts "#{mock_obj}: #{mock_src} #{mock_header}"
|
||||
mkfile.puts "\t${CC} -o $@ -c $< ${TEST_CFLAGS} -I #{MOCKS_DIR} -I #{SRC_DIR} -I #{UNITY_SRC} -I #{CMOCK_SRC}"
|
||||
mkfile.puts "\t${CC} -o $@ -c $< ${TEST_CFLAGS} -I #{MOCKS_DIR} -I #{SRC_DIR} -I #{UNITY_SRC} -I #{CMOCK_SRC} ${INCLUDE_PATH}"
|
||||
mkfile.puts ""
|
||||
end
|
||||
|
||||
@@ -157,7 +182,7 @@ File.open(TEST_MAKEFILE, "w") do |mkfile|
|
||||
mkfile.puts ""
|
||||
|
||||
# Create target to run all tests
|
||||
mkfile.puts "test: #{test_targets.map{|t| t + '.result'}.join(' ')} test_summary"
|
||||
mkfile.puts "test: #{test_targets.map{|t| t + '.testresult'}.join(' ')} test_summary"
|
||||
mkfile.puts ""
|
||||
|
||||
end
|
||||
|
||||
@@ -7,7 +7,7 @@ begin
|
||||
build_dir = ENV.fetch('BUILD_DIR', './build')
|
||||
test_build_dir = ENV.fetch('TEST_BUILD_DIR', File.join(build_dir, 'test'))
|
||||
|
||||
results = Dir["#{test_build_dir}/*.result"]
|
||||
results = Dir["#{test_build_dir}/*.testresult"]
|
||||
parser = UnityTestSummary.new
|
||||
parser.targets = results
|
||||
parser.run
|
||||
|
||||
@@ -159,4 +159,171 @@
|
||||
TEST_ASSERT_EQUAL(110, function(0, 8, 9));
|
||||
}
|
||||
|
||||
- :pass: FALSE
|
||||
:should: 'With "fail_on_unexpected_calls" enabled, Expect/Ignore/... of bar is required and test fails.'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
function(1, 2, 3);
|
||||
}
|
||||
|
||||
- :pass: TRUE
|
||||
:should: 'we can override an ignore with an expect and pass'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
bar_Ignore();
|
||||
|
||||
bar_Expect(2);
|
||||
foo_ExpectAndReturn(1, 50);
|
||||
foo_ExpectAndReturn(2, 60);
|
||||
foo_ExpectAndReturn(3, 70);
|
||||
TEST_ASSERT_EQUAL(180, function(1, 2, 3));
|
||||
|
||||
bar_Expect(5);
|
||||
foo_ExpectAndReturn(4, 30);
|
||||
foo_ExpectAndReturn(5, 80);
|
||||
foo_ExpectAndReturn(6, 10);
|
||||
TEST_ASSERT_EQUAL(120, function(4, 5, 6));
|
||||
|
||||
bar_Expect(8);
|
||||
foo_ExpectAndReturn(7, 70);
|
||||
foo_ExpectAndReturn(8, 20);
|
||||
foo_ExpectAndReturn(9, 20);
|
||||
TEST_ASSERT_EQUAL(110, function(7, 8, 9));
|
||||
}
|
||||
|
||||
- :pass: FALSE
|
||||
:should: 'we can override an ignore with an expect and fail'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
bar_Ignore();
|
||||
|
||||
bar_Expect(2);
|
||||
foo_ExpectAndReturn(1, 50);
|
||||
foo_ExpectAndReturn(2, 60);
|
||||
foo_ExpectAndReturn(3, 70);
|
||||
TEST_ASSERT_EQUAL(180, function(1, 2, 3));
|
||||
|
||||
bar_Expect(5);
|
||||
foo_ExpectAndReturn(4, 30);
|
||||
foo_ExpectAndReturn(5, 80);
|
||||
foo_ExpectAndReturn(6, 10);
|
||||
TEST_ASSERT_EQUAL(120, function(4, 5, 6));
|
||||
|
||||
bar_Expect(9);
|
||||
foo_ExpectAndReturn(7, 70);
|
||||
foo_ExpectAndReturn(8, 20);
|
||||
foo_ExpectAndReturn(9, 20);
|
||||
TEST_ASSERT_EQUAL(110, function(7, 8, 9));
|
||||
}
|
||||
|
||||
- :pass: TRUE
|
||||
:should: 'we can override an ignore and return with an expect and pass'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
bar_Ignore();
|
||||
foo_IgnoreAndReturn(30);
|
||||
TEST_ASSERT_EQUAL(90, function(1, 2, 3));
|
||||
|
||||
bar_Expect(5);
|
||||
foo_ExpectAndReturn(4, 30);
|
||||
foo_ExpectAndReturn(5, 80);
|
||||
foo_ExpectAndReturn(6, 10);
|
||||
TEST_ASSERT_EQUAL(120, function(4, 5, 6));
|
||||
|
||||
bar_Expect(8);
|
||||
foo_ExpectAndReturn(7, 70);
|
||||
foo_ExpectAndReturn(8, 20);
|
||||
foo_ExpectAndReturn(9, 20);
|
||||
TEST_ASSERT_EQUAL(110, function(7, 8, 9));
|
||||
}
|
||||
|
||||
- :pass: FALSE
|
||||
:should: 'we can override an ignore and return with an expect and fail'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
bar_Ignore();
|
||||
foo_IgnoreAndReturn(0);
|
||||
TEST_ASSERT_EQUAL(0, function(1, 2, 3));
|
||||
|
||||
bar_Expect(5);
|
||||
foo_ExpectAndReturn(4, 30);
|
||||
foo_ExpectAndReturn(5, 80);
|
||||
foo_ExpectAndReturn(6, 10);
|
||||
TEST_ASSERT_EQUAL(120, function(4, 5, 6));
|
||||
|
||||
bar_Expect(9);
|
||||
foo_ExpectAndReturn(7, 70);
|
||||
foo_ExpectAndReturn(8, 20);
|
||||
foo_ExpectAndReturn(9, 20);
|
||||
TEST_ASSERT_EQUAL(110, function(7, 8, 9));
|
||||
}
|
||||
|
||||
- :pass: TRUE
|
||||
:should: 'we can override an an expect with an ignore'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
bar_Expect(5);
|
||||
bar_Ignore();
|
||||
foo_ExpectAndReturn(1, 50);
|
||||
foo_ExpectAndReturn(2, 60);
|
||||
foo_ExpectAndReturn(3, 70);
|
||||
TEST_ASSERT_EQUAL(180, function(1, 2, 3));
|
||||
}
|
||||
|
||||
- :pass: TRUE
|
||||
:should: 'we can override an expect with an ignore and return and pass'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
bar_Ignore();
|
||||
foo_IgnoreAndReturn(0);
|
||||
TEST_ASSERT_EQUAL(0, function(1, 2, 3));
|
||||
|
||||
bar_Expect(5);
|
||||
foo_ExpectAndReturn(4, 30);
|
||||
foo_ExpectAndReturn(5, 80);
|
||||
foo_IgnoreAndReturn(10);
|
||||
TEST_ASSERT_EQUAL(120, function(4, 5, 6));
|
||||
|
||||
bar_Ignore();
|
||||
foo_IgnoreAndReturn(60);
|
||||
TEST_ASSERT_EQUAL(180, function(7, 8, 9));
|
||||
}
|
||||
|
||||
- :pass: FALSE
|
||||
:should: 'we can override an expect with an ignore and return and fail after'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
bar_Expect(5);
|
||||
foo_ExpectAndReturn(4, 30);
|
||||
foo_ExpectAndReturn(5, 50);
|
||||
foo_IgnoreAndReturn(20);
|
||||
TEST_ASSERT_EQUAL(100, function(4, 5, 6));
|
||||
|
||||
bar_Expect(5);
|
||||
foo_ExpectAndReturn(9, 30); //THIS ONE WILL FAIL
|
||||
foo_ExpectAndReturn(2, 80);
|
||||
foo_ExpectAndReturn(3, 60);
|
||||
TEST_ASSERT_EQUAL(170, function(1, 2, 3));
|
||||
}
|
||||
|
||||
- :pass: TRUE
|
||||
:should: 'we can override an expect with an ignore and return and the expected values are ignored'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
bar_Expect(5);
|
||||
foo_ExpectAndReturn(2, 30); //NOTE THIS WOULD NORMALLY FAIL
|
||||
foo_ExpectAndReturn(5, 50);
|
||||
foo_IgnoreAndReturn(20); //BUT WE SAID WE NO LONGER CARE
|
||||
TEST_ASSERT_EQUAL(100, function(4, 5, 6));
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
:cmock:
|
||||
:plugins:
|
||||
- 'ignore'
|
||||
:fail_on_unexpected_calls: FALSE
|
||||
|
||||
:systest:
|
||||
:types: |
|
||||
|
||||
:mockable: |
|
||||
int foo(int a);
|
||||
void bar(int b);
|
||||
|
||||
:source:
|
||||
:header: |
|
||||
int function(int a, int b, int c);
|
||||
:code: |
|
||||
int function(int a, int b, int c)
|
||||
{
|
||||
bar(b);
|
||||
return foo(a) + foo(b) + foo(c);
|
||||
}
|
||||
|
||||
:tests:
|
||||
:common: |
|
||||
void setUp(void) {}
|
||||
void tearDown(void) {}
|
||||
:units:
|
||||
- :pass: TRUE
|
||||
:should: 'With "fail_on_unexpected_calls" disabled, Expect/Ignore/... of bar is NOT required.'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
function(1, 2, 3);
|
||||
}
|
||||
|
||||
...
|
||||
@@ -53,6 +53,7 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
@config.expect :includes_c_pre_header, nil
|
||||
@config.expect :includes_c_post_header, nil
|
||||
@config.expect :subdir, nil
|
||||
@config.expect :fail_on_unexpected_calls, true
|
||||
@cmock_generator = CMockGenerator.new(@config, @file_writer, @utils, @plugins)
|
||||
@cmock_generator.module_name = @module_name
|
||||
@cmock_generator.mock_name = "Mock#{@module_name}"
|
||||
@@ -70,6 +71,7 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
@config.expect :includes_c_pre_header, nil
|
||||
@config.expect :includes_c_post_header, nil
|
||||
@config.expect :subdir, nil
|
||||
@config.expect :fail_on_unexpected_calls, true
|
||||
@cmock_generator_strict = CMockGenerator.new(@config, @file_writer, @utils, @plugins)
|
||||
@cmock_generator_strict.module_name = @module_name
|
||||
@cmock_generator_strict.mock_name = "Mock#{@module_name}"
|
||||
@@ -98,6 +100,7 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
"\n",
|
||||
"/* Ignore the following warnings, since we are copying code */\n",
|
||||
"#if defined(__GNUC__) && !defined(__ICC) && !defined(__TMS470__)\n",
|
||||
"#pragma GCC diagnostic push\n",
|
||||
"#if !defined(__clang__)\n",
|
||||
"#pragma GCC diagnostic ignored \"-Wpragmas\"\n",
|
||||
"#endif\n",
|
||||
@@ -127,6 +130,7 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
@config.expect :includes_c_pre_header, nil
|
||||
@config.expect :includes_c_post_header, nil
|
||||
@config.expect :subdir, nil
|
||||
@config.expect :fail_on_unexpected_calls, true
|
||||
@cmock_generator2 = CMockGenerator.new(@config, @file_writer, @utils, @plugins)
|
||||
@cmock_generator2.module_name = "Pout-Pout Fish"
|
||||
@cmock_generator2.mock_name = "MockPout-Pout Fish"
|
||||
@@ -150,6 +154,7 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
"\n",
|
||||
"/* Ignore the following warnings, since we are copying code */\n",
|
||||
"#if defined(__GNUC__) && !defined(__ICC) && !defined(__TMS470__)\n",
|
||||
"#pragma GCC diagnostic push\n",
|
||||
"#if !defined(__clang__)\n",
|
||||
"#pragma GCC diagnostic ignored \"-Wpragmas\"\n",
|
||||
"#endif\n",
|
||||
@@ -185,6 +190,7 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
"\n",
|
||||
"/* Ignore the following warnings, since we are copying code */\n",
|
||||
"#if defined(__GNUC__) && !defined(__ICC) && !defined(__TMS470__)\n",
|
||||
"#pragma GCC diagnostic push\n",
|
||||
"#if !defined(__clang__)\n",
|
||||
"#pragma GCC diagnostic ignored \"-Wpragmas\"\n",
|
||||
"#endif\n",
|
||||
@@ -221,6 +227,7 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
"\n",
|
||||
"/* Ignore the following warnings, since we are copying code */\n",
|
||||
"#if defined(__GNUC__) && !defined(__ICC) && !defined(__TMS470__)\n",
|
||||
"#pragma GCC diagnostic push\n",
|
||||
"#if !defined(__clang__)\n",
|
||||
"#pragma GCC diagnostic ignored \"-Wpragmas\"\n",
|
||||
"#endif\n",
|
||||
@@ -272,7 +279,13 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
|
||||
it "append the proper footer to the header file" do
|
||||
output = []
|
||||
expected = ["\n#endif\n"]
|
||||
expected = ["\n",
|
||||
"#if defined(__GNUC__) && !defined(__ICC) && !defined(__TMS470__)\n",
|
||||
"#pragma GCC diagnostic pop\n",
|
||||
"#endif\n",
|
||||
"\n",
|
||||
"#endif\n"
|
||||
]
|
||||
|
||||
@cmock_generator.create_mock_header_footer(output)
|
||||
|
||||
|
||||
@@ -96,11 +96,12 @@ describe CMockGeneratorPluginExpect, "Verify CMockGeneratorPluginExpect Module w
|
||||
it "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 => test_return[:int]}
|
||||
|
||||
@utils.expect :code_verify_an_arg_expectation, " mocked_retval_1", [function, function[:args][0]]
|
||||
@utils.expect :code_verify_an_arg_expectation, " mocked_retval_2", [function, function[:args][1]]
|
||||
@utils.expect :code_verify_an_arg_expectation, "mocked_retval_1\n", [function, function[:args][0]]
|
||||
@utils.expect :code_verify_an_arg_expectation, "mocked_retval_2\n", [function, function[:args][1]]
|
||||
expected = " if (cmock_call_instance->IgnoreMode != CMOCK_ARG_NONE)\n" +
|
||||
" {\n" +
|
||||
" mocked_retval_1 mocked_retval_2\n" +
|
||||
"mocked_retval_1\n" +
|
||||
"mocked_retval_2\n" +
|
||||
" }\n"
|
||||
returned = @cmock_generator_plugin_expect.mock_implementation(function)
|
||||
assert_equal(expected, returned)
|
||||
@@ -116,7 +117,7 @@ describe CMockGeneratorPluginExpect, "Verify CMockGeneratorPluginExpect Module w
|
||||
|
||||
it "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, "mocked_retval_0", [function, function[:args][0]]
|
||||
@utils.expect :code_verify_an_arg_expectation, "mocked_retval_0\n", [function, function[:args][0]]
|
||||
expected = " if (cmock_call_instance->IgnoreMode != CMOCK_ARG_NONE)\n" +
|
||||
" {\n" +
|
||||
"mocked_retval_0\n" +
|
||||
@@ -128,12 +129,12 @@ describe CMockGeneratorPluginExpect, "Verify CMockGeneratorPluginExpect Module w
|
||||
|
||||
it "add mock interfaces for functions of style 'void func(void)'" do
|
||||
function = {:name => "Pear", :args => [], :args_string => "void", :return => test_return[:void]}
|
||||
@utils.expect :code_add_base_expectation, "mock_retval_0 ", ["Pear"]
|
||||
@utils.expect :code_call_argument_loader, "mock_retval_1 ", [function]
|
||||
@utils.expect :code_add_base_expectation, "mock_retval_0\n", ["Pear"]
|
||||
@utils.expect :code_call_argument_loader, "mock_retval_1\n", [function]
|
||||
expected = ["void Pear_CMockExpect(UNITY_LINE_TYPE cmock_line)\n",
|
||||
"{\n",
|
||||
"mock_retval_0 ",
|
||||
"mock_retval_1 ",
|
||||
"mock_retval_0\n",
|
||||
"mock_retval_1\n",
|
||||
" UNITY_CLR_DETAILS();\n",
|
||||
"}\n\n"
|
||||
].join
|
||||
@@ -143,14 +144,14 @@ describe CMockGeneratorPluginExpect, "Verify CMockGeneratorPluginExpect Module w
|
||||
|
||||
it "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, "mock_retval_0 ", ["Orange"]
|
||||
@utils.expect :code_call_argument_loader, "mock_retval_1 ", [function]
|
||||
@utils.expect :code_assign_argument_quickly, "mock_retval_2", ["cmock_call_instance->ReturnVal", function[:return]]
|
||||
@utils.expect :code_add_base_expectation, "mock_retval_0\n", ["Orange"]
|
||||
@utils.expect :code_call_argument_loader, "mock_retval_1\n", [function]
|
||||
@utils.expect :code_assign_argument_quickly, "mock_retval_2\n", ["cmock_call_instance->ReturnVal", function[:return]]
|
||||
expected = ["void Orange_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, int cmock_to_return)\n",
|
||||
"{\n",
|
||||
"mock_retval_0 ",
|
||||
"mock_retval_1 ",
|
||||
"mock_retval_2",
|
||||
"mock_retval_0\n",
|
||||
"mock_retval_1\n",
|
||||
"mock_retval_2\n",
|
||||
" UNITY_CLR_DETAILS();\n",
|
||||
"}\n\n"
|
||||
].join
|
||||
@@ -160,14 +161,14 @@ describe CMockGeneratorPluginExpect, "Verify CMockGeneratorPluginExpect Module w
|
||||
|
||||
it "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 => test_return[:int]}
|
||||
@utils.expect :code_add_base_expectation, "mock_retval_0 ", ["Lemon"]
|
||||
@utils.expect :code_call_argument_loader, "mock_retval_1 ", [function]
|
||||
@utils.expect :code_assign_argument_quickly, "mock_retval_2", ["cmock_call_instance->ReturnVal", function[:return]]
|
||||
@utils.expect :code_add_base_expectation, "mock_retval_0\n", ["Lemon"]
|
||||
@utils.expect :code_call_argument_loader, "mock_retval_1\n", [function]
|
||||
@utils.expect :code_assign_argument_quickly, "mock_retval_2\n", ["cmock_call_instance->ReturnVal", function[:return]]
|
||||
expected = ["void Lemon_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, char* pescado, int cmock_to_return)\n",
|
||||
"{\n",
|
||||
"mock_retval_0 ",
|
||||
"mock_retval_1 ",
|
||||
"mock_retval_2",
|
||||
"mock_retval_0\n",
|
||||
"mock_retval_1\n",
|
||||
"mock_retval_2\n",
|
||||
" UNITY_CLR_DETAILS();\n",
|
||||
"}\n\n"
|
||||
].join
|
||||
@@ -177,12 +178,12 @@ describe CMockGeneratorPluginExpect, "Verify CMockGeneratorPluginExpect Module w
|
||||
|
||||
it "add mock interfaces for functions when using ordering" do
|
||||
function = {:name => "Pear", :args => [], :args_string => "void", :return => test_return[:void]}
|
||||
@utils.expect :code_add_base_expectation, "mock_retval_0 ", ["Pear"]
|
||||
@utils.expect :code_call_argument_loader, "mock_retval_1 ", [function]
|
||||
@utils.expect :code_add_base_expectation, "mock_retval_0\n", ["Pear"]
|
||||
@utils.expect :code_call_argument_loader, "mock_retval_1\n", [function]
|
||||
expected = ["void Pear_CMockExpect(UNITY_LINE_TYPE cmock_line)\n",
|
||||
"{\n",
|
||||
"mock_retval_0 ",
|
||||
"mock_retval_1 ",
|
||||
"mock_retval_0\n",
|
||||
"mock_retval_1\n",
|
||||
" UNITY_CLR_DETAILS();\n",
|
||||
"}\n\n"
|
||||
].join
|
||||
|
||||
@@ -805,6 +805,39 @@ describe CMockHeaderParser, "Verify CMockHeaderParser Module" do
|
||||
assert_equal(expected, @parser.parse("module", source)[:functions])
|
||||
end
|
||||
|
||||
it "should properly handle const before or after return type" do
|
||||
|
||||
sources = [
|
||||
"const int * PorkRoast(void);\n",
|
||||
"int const * PorkRoast(void);\n",
|
||||
"const int* PorkRoast(void);\n",
|
||||
"int const* PorkRoast(void);\n",
|
||||
"const int *PorkRoast(void);\n",
|
||||
"int const *PorkRoast(void);\n"
|
||||
]
|
||||
|
||||
expected = [{ :var_arg=>nil,
|
||||
:name=>"PorkRoast",
|
||||
:return=> { :type => "int*",
|
||||
:name => 'cmock_to_return',
|
||||
:ptr? => true,
|
||||
:const? => true,
|
||||
:const_ptr? => false,
|
||||
:str => "int* cmock_to_return",
|
||||
:void? => false
|
||||
},
|
||||
:modifier=>"const",
|
||||
:contains_ptr? => false,
|
||||
:args=>[],
|
||||
:args_string=>"void",
|
||||
:args_call=>""
|
||||
}]
|
||||
|
||||
sources.each do |source|
|
||||
assert_equal(expected, @parser.parse("module", source)[:functions])
|
||||
end
|
||||
end
|
||||
|
||||
it "should properly handle const applied after asterisk in return type (not legal C, but sometimes used)" do
|
||||
|
||||
source = "int * const PorkRoast(void);\n"
|
||||
@@ -828,6 +861,69 @@ describe CMockHeaderParser, "Verify CMockHeaderParser Module" do
|
||||
assert_equal(expected, @parser.parse("module", source)[:functions])
|
||||
end
|
||||
|
||||
it "properly parse const and pointer argument types with no arg names" do
|
||||
|
||||
source = "void foo(int const*, int*const, const int*, const int*const, int const*const, int*, int, const int);\n"
|
||||
|
||||
expected = [{ :name => "foo",
|
||||
:modifier => "",
|
||||
:return => { :type => "void",
|
||||
:name => "cmock_to_return",
|
||||
:str => "void cmock_to_return",
|
||||
:void? => true,
|
||||
:ptr? => false,
|
||||
:const? => false,
|
||||
:const_ptr? => false
|
||||
},
|
||||
:var_arg => nil,
|
||||
:args_string => "int const* cmock_arg1, int* const cmock_arg2, const int* cmock_arg3, const int* const cmock_arg4, " +
|
||||
"int const* const cmock_arg5, int* cmock_arg6, int cmock_arg7, const int cmock_arg8",
|
||||
:args => [{ :type=>"int const*", :name => "cmock_arg1", :ptr? => true, :const? => true, :const_ptr? => false },
|
||||
{ :type=>"int*", :name => "cmock_arg2", :ptr? => true, :const? => false, :const_ptr? => true },
|
||||
{ :type=>"const int*", :name => "cmock_arg3", :ptr? => true, :const? => true, :const_ptr? => false },
|
||||
{ :type=>"const int*", :name => "cmock_arg4", :ptr? => true, :const? => true, :const_ptr? => true },
|
||||
{ :type=>"int const*", :name => "cmock_arg5", :ptr? => true, :const? => true, :const_ptr? => true },
|
||||
{ :type=>"int*", :name => "cmock_arg6", :ptr? => true, :const? => false, :const_ptr? => false },
|
||||
{ :type=>"int", :name => "cmock_arg7", :ptr? => false, :const? => false, :const_ptr? => false },
|
||||
{ :type=>"int", :name => "cmock_arg8", :ptr? => false, :const? => true, :const_ptr? => false }],
|
||||
:args_call => "cmock_arg1, cmock_arg2, cmock_arg3, cmock_arg4, cmock_arg5, cmock_arg6, cmock_arg7, cmock_arg8",
|
||||
:contains_ptr? => true
|
||||
}]
|
||||
assert_equal(expected, @parser.parse("module", source)[:functions])
|
||||
end
|
||||
|
||||
it "properly parse const and pointer argument types with arg names" do
|
||||
|
||||
source = "void bar(int const* param1, int*const param2, const int* param3, const int*const param4,\n" +
|
||||
" int const*const param5, int*param6, int param7, const int param8);\n"
|
||||
|
||||
expected = [{ :name => "bar",
|
||||
:modifier => "",
|
||||
:return => { :type => "void",
|
||||
:name => "cmock_to_return",
|
||||
:str => "void cmock_to_return",
|
||||
:void? => true,
|
||||
:ptr? => false,
|
||||
:const? => false,
|
||||
:const_ptr? => false
|
||||
},
|
||||
:var_arg => nil,
|
||||
:args_string => "int const* param1, int* const param2, const int* param3, const int* const param4, " +
|
||||
"int const* const param5, int* param6, int param7, const int param8",
|
||||
:args => [{ :type=>"int const*", :name => "param1", :ptr? => true, :const? => true, :const_ptr? => false },
|
||||
{ :type=>"int*", :name => "param2", :ptr? => true, :const? => false, :const_ptr? => true },
|
||||
{ :type=>"const int*", :name => "param3", :ptr? => true, :const? => true, :const_ptr? => false },
|
||||
{ :type=>"const int*", :name => "param4", :ptr? => true, :const? => true, :const_ptr? => true },
|
||||
{ :type=>"int const*", :name => "param5", :ptr? => true, :const? => true, :const_ptr? => true },
|
||||
{ :type=>"int*", :name => "param6", :ptr? => true, :const? => false, :const_ptr? => false },
|
||||
{ :type=>"int", :name => "param7", :ptr? => false, :const? => false, :const_ptr? => false },
|
||||
{ :type=>"int", :name => "param8", :ptr? => false, :const? => true, :const_ptr? => false }],
|
||||
:args_call => "param1, param2, param3, param4, param5, param6, param7, param8",
|
||||
:contains_ptr? => true
|
||||
}]
|
||||
assert_equal(expected, @parser.parse("module", source)[:functions])
|
||||
end
|
||||
|
||||
it "properly detect typedef'd variants of void and use those" do
|
||||
|
||||
source = "typedef (void) FUNKY_VOID_T;\n" +
|
||||
@@ -904,7 +1000,7 @@ describe CMockHeaderParser, "Verify CMockHeaderParser Module" do
|
||||
:name=>"Penny",
|
||||
:modifier=>"",
|
||||
:contains_ptr? => true,
|
||||
:args=>[ {:type=>"struct _KeepYourHeadUp_*", :name=>"BillyBuddy", :ptr? => true, :const? => true, :const_ptr? => true} ],
|
||||
:args=>[ {:type=>"struct const _KeepYourHeadUp_*", :name=>"BillyBuddy", :ptr? => true, :const? => true, :const_ptr? => true} ],
|
||||
:args_string=>"struct const _KeepYourHeadUp_* const BillyBuddy",
|
||||
:args_call=>"BillyBuddy"
|
||||
},
|
||||
@@ -1052,7 +1148,7 @@ describe CMockHeaderParser, "Verify CMockHeaderParser Module" do
|
||||
assert_equal(expected, result[:functions])
|
||||
end
|
||||
|
||||
it "handle arrays and treat them as pointers" do
|
||||
it "handle arrays and treat them as pointers or strings" do
|
||||
source = "void KeyOperated(CUSTOM_TYPE thing1[], int thing2 [ ], char thing3 [][2 ][ 3], int* thing4[4])"
|
||||
expected = [{:var_arg=>nil,
|
||||
:return=>{ :type => "void",
|
||||
@@ -1068,7 +1164,7 @@ describe CMockHeaderParser, "Verify CMockHeaderParser Module" do
|
||||
:contains_ptr? => true,
|
||||
:args=>[ {:type=>"CUSTOM_TYPE*", :name=>"thing1", :ptr? => true, :const? => false, :const_ptr? => false},
|
||||
{:type=>"int*", :name=>"thing2", :ptr? => true, :const? => false, :const_ptr? => false},
|
||||
{:type=>"char*", :name=>"thing3", :ptr? => true, :const? => false, :const_ptr? => false}, #THIS one will likely change in the future when we improve multidimensional array support
|
||||
{:type=>"char*", :name=>"thing3", :ptr? => false, :const? => false, :const_ptr? => false}, #THIS one will likely change in the future when we improve multidimensional array support
|
||||
{:type=>"int**", :name=>"thing4", :ptr? => true, :const? => false, :const_ptr? => false} #THIS one will likely change in the future when we improve multidimensional array support
|
||||
],
|
||||
:args_string=>"CUSTOM_TYPE* thing1, int* thing2, char* thing3, int** thing4",
|
||||
@@ -1407,7 +1503,7 @@ describe CMockHeaderParser, "Verify CMockHeaderParser Module" do
|
||||
:contains_ptr? => true,
|
||||
:args=>[ {:type=>"sqlite3_stmt*", :name=>"cmock_arg2", :ptr? => true, :const? => false, :const_ptr? => false},
|
||||
{:type=>"int", :name=>"cmock_arg3", :ptr? => false, :const? => false, :const_ptr? => false},
|
||||
{:type=>"char*", :name=>"cmock_arg4", :ptr? => true, :const? => true, :const_ptr? => false},
|
||||
{:type=>"const char*", :name=>"cmock_arg4", :ptr? => false, :const? => true, :const_ptr? => false},
|
||||
{:type=>"int", :name=>"n", :ptr? => false, :const? => false, :const_ptr? => false},
|
||||
{:type=>"cmock_module_func_ptr1", :name=>"cmock_arg1", :ptr? => false, :const? => false, :const_ptr? => false}
|
||||
],
|
||||
@@ -1510,4 +1606,69 @@ describe CMockHeaderParser, "Verify CMockHeaderParser Module" do
|
||||
assert_equal(expected, @parser.parse("module", source)[:functions])
|
||||
end
|
||||
|
||||
it "divines all permutations of ptr, const, and const_ptr correctly" do
|
||||
truth_table = [
|
||||
# argument ptr const const_ptr
|
||||
[ "constNOTconst constNOTconst", false, false, false ],
|
||||
[ "const constNOTconst constNOTconst", false, true, false ],
|
||||
[ "constNOTconst const constNOTconst", false, true, false ],
|
||||
[ "constNOTconst *constNOTconst", true, false, false ],
|
||||
[ "const constNOTconst *constNOTconst", true, true, false ],
|
||||
[ "constNOTconst const *constNOTconst", true, true, false ],
|
||||
[ "constNOTconst *const constNOTconst", true, false, true ],
|
||||
[ "const constNOTconst *const constNOTconst", true, true, true ],
|
||||
[ "constNOTconst const *const constNOTconst", true, true, true ],
|
||||
[ "constNOTconst **constNOTconst", true, false, false ],
|
||||
[ "const constNOTconst **constNOTconst", true, false, false ],
|
||||
[ "constNOTconst const **constNOTconst", true, false, false ],
|
||||
[ "constNOTconst *const *constNOTconst", true, true, false ],
|
||||
[ "const constNOTconst *const *constNOTconst", true, true, false ],
|
||||
[ "constNOTconst const *const *constNOTconst", true, true, false ],
|
||||
[ "constNOTconst **const constNOTconst", true, false, true ],
|
||||
[ "const constNOTconst **const constNOTconst", true, false, true ],
|
||||
[ "constNOTconst const **const constNOTconst", true, false, true ],
|
||||
[ "constNOTconst *const *const constNOTconst", true, true, true ],
|
||||
[ "const constNOTconst *const *const constNOTconst", true, true, true ],
|
||||
[ "constNOTconst const *const *const constNOTconst", true, true, true ]
|
||||
]
|
||||
|
||||
truth_table.each do |entry|
|
||||
assert_equal(@parser.divine_ptr(entry[0]), entry[1])
|
||||
assert_equal(@parser.divine_const(entry[0]), entry[2])
|
||||
assert_equal(@parser.divine_ptr_and_const(entry[0]),
|
||||
{ ptr?: entry[1], const?: entry[2], const_ptr?: entry[3] })
|
||||
end
|
||||
end
|
||||
|
||||
it "divines ptr correctly for string types" do
|
||||
truth_table = [
|
||||
# argument ptr
|
||||
[ "char s", false ],
|
||||
[ "const char s", false ],
|
||||
[ "char const s", false ],
|
||||
[ "char *s", false ],
|
||||
[ "const char *s", false ],
|
||||
[ "char const *s", false ],
|
||||
[ "char *const s", false ],
|
||||
[ "const char *const s", false ],
|
||||
[ "char const *const s", false ],
|
||||
[ "char **s", true ],
|
||||
[ "const char **s", true ],
|
||||
[ "char const **s", true ],
|
||||
[ "char *const *s", true ],
|
||||
[ "const char *const *s", true ],
|
||||
[ "char const *const *s", true ],
|
||||
[ "char **const s", true ],
|
||||
[ "const char **const s", true ],
|
||||
[ "char const **const s", true ],
|
||||
[ "char *const *const s", true ],
|
||||
[ "const char *const *const s", true ],
|
||||
[ "char const *const *const s", true ]
|
||||
]
|
||||
|
||||
truth_table.each do |entry|
|
||||
assert_equal(@parser.divine_ptr(entry[0]), entry[1])
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Vendored
+1
-1
Submodule vendor/unity updated: f96c05532b...60b13f0685
Reference in New Issue
Block a user