mirror of
https://github.com/ThrowTheSwitch/CMock.git
synced 2026-06-23 14:00:33 +00:00
Compare commits
66 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cb1ad78b97 | |||
| 2b4f9b43c7 | |||
| 2a2f19dfae | |||
| e42996ea67 | |||
| b9da6d6def | |||
| 0fc09121d7 | |||
| 4df347bf17 | |||
| e765181c8d | |||
| 6d1c0f97f5 | |||
| 488c469cdf | |||
| 3df5c035e6 | |||
| 1f87c158da | |||
| 76b6231f77 | |||
| ca05fe4285 | |||
| 37fcb8535a | |||
| 526668961a | |||
| 3b123fb533 | |||
| c725e4ddc6 | |||
| 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 |
+8
-9
@@ -1,29 +1,28 @@
|
||||
language: ruby
|
||||
|
||||
os:
|
||||
os:
|
||||
- osx
|
||||
- linux
|
||||
|
||||
|
||||
rvm:
|
||||
- "2.0.0"
|
||||
- "2.2.2"
|
||||
|
||||
|
||||
before_install:
|
||||
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then rvm install 2.1 && rvm use 2.1 && ruby -v; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install --assume-yes --quiet gcc-multilib; fi
|
||||
|
||||
|
||||
install:
|
||||
- bundle install
|
||||
- gem install rspec
|
||||
- gem install rubocop
|
||||
|
||||
|
||||
script:
|
||||
- cd test && rake ci
|
||||
- cd ..
|
||||
- cd examples && cd make_example
|
||||
- make clean
|
||||
- make setup
|
||||
- make clean
|
||||
- make setup
|
||||
- make test
|
||||
- cd ..
|
||||
- cd temp_sensor
|
||||
- cd temp_sensor
|
||||
- rake ci
|
||||
|
||||
@@ -7,17 +7,17 @@ Getting Started
|
||||
================
|
||||
|
||||
If you're using Ceedling, there is no need to install CMock. It will handle it for you.
|
||||
For everyone else, the simplest way is to grab it off github. You can also download it
|
||||
For everyone else, the simplest way is to grab it off github. You can also download it
|
||||
as a zip if you prefer. The Github method looks something like this:
|
||||
|
||||
> git clone --recursive https://github.com/throwtheswitch/cmock.git
|
||||
> cd cmock
|
||||
> bundle install # Ensures you have all RubyGems needed
|
||||
|
||||
|
||||
If you plan to help with the development of CMock (or just want to verify that it can
|
||||
perform its self tests on your system) then you can enter the test directory and then
|
||||
ask it to test:
|
||||
|
||||
|
||||
> rake # Run all CMock self tests
|
||||
|
||||
API Documentation
|
||||
|
||||
+76
-61
@@ -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
|
||||
using [Ceedling](https://throwtheswitch.org/ceedling). Please note that
|
||||
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 => [],
|
||||
@@ -119,6 +120,8 @@ class CMockConfig
|
||||
'UINT32' => 'HEX32',
|
||||
'UINT32_T' => 'HEX32',
|
||||
'void*' => 'HEX8_ARRAY',
|
||||
'void const*' => 'HEX8_ARRAY',
|
||||
'const void*' => 'HEX8_ARRAY',
|
||||
'unsigned short' => 'HEX16',
|
||||
'uint16' => 'HEX16',
|
||||
'uint16_t' => 'HEX16',
|
||||
@@ -130,6 +133,8 @@ class CMockConfig
|
||||
'UINT8' => 'HEX8',
|
||||
'UINT8_T' => 'HEX8',
|
||||
'char*' => 'STRING',
|
||||
'char const*' => 'STRING',
|
||||
'const char*' => 'STRING',
|
||||
'pCHAR' => 'STRING',
|
||||
'cstring' => 'STRING',
|
||||
'CSTRING' => 'STRING',
|
||||
|
||||
+18
-3
@@ -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,9 @@ 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 << "#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 6 || (__GNUC_MINOR__ == 6 && __GNUC_PATCHLEVEL__ > 0)))\n"
|
||||
file << "#pragma GCC diagnostic push\n"
|
||||
file << "#endif\n"
|
||||
file << "#if !defined(__clang__)\n"
|
||||
file << "#pragma GCC diagnostic ignored \"-Wpragmas\"\n"
|
||||
file << "#endif\n"
|
||||
@@ -124,7 +128,14 @@ 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 << "#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 6 || (__GNUC_MINOR__ == 6 && __GNUC_PATCHLEVEL__ > 0)))\n"
|
||||
header << "#pragma GCC diagnostic pop\n"
|
||||
header << "#endif\n"
|
||||
header << "#endif\n"
|
||||
header << "\n"
|
||||
header << "#endif\n"
|
||||
end
|
||||
|
||||
def create_source_header_section(file, filename, functions)
|
||||
@@ -196,6 +207,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"
|
||||
@@ -235,10 +251,9 @@ class CMockGenerator
|
||||
file << " if (cmock_call_instance->CallOrder < GlobalVerifyOrder)\n"
|
||||
file << " UNITY_TEST_FAIL(cmock_line, CMockStringCalledLate);\n"
|
||||
end
|
||||
return_type = function[:return][:const?] ? "(const #{function[:return][:type]})" : ((function[:return][:type] =~ /cmock/) ? "(#{function[:return][:type]})" : '')
|
||||
file << @plugins.run(:mock_implementation, function)
|
||||
file << " UNITY_CLR_DETAILS();\n"
|
||||
file << " return #{return_type}cmock_call_instance->ReturnVal;\n" unless (function[:return][:void?])
|
||||
file << " return cmock_call_instance->ReturnVal;\n" unless (function[:return][:void?])
|
||||
file << "}\n\n"
|
||||
end
|
||||
|
||||
|
||||
@@ -27,8 +27,8 @@ class CMockGeneratorPluginArray
|
||||
return nil unless function[:contains_ptr?]
|
||||
args_call = function[:args].map{|m| m[:ptr?] ? "#{m[:name]}, #{m[:name]}_Depth" : "#{m[:name]}"}.join(', ')
|
||||
args_string = function[:args].map do |m|
|
||||
const_str = m[:const?] ? 'const ' : ''
|
||||
m[:ptr?] ? "#{const_str}#{m[:type]} #{m[:name]}, int #{m[:name]}_Depth" : "#{const_str}#{m[:type]} #{m[:name]}"
|
||||
type = @utils.arg_type_with_const(m)
|
||||
m[:ptr?] ? "#{type} #{m[:name]}, int #{m[:name]}_Depth" : "#{type} #{m[:name]}"
|
||||
end.join(', ')
|
||||
if (function[:return][:void?])
|
||||
return "#define #{function[:name]}_ExpectWithArray(#{args_call}) #{function[:name]}_CMockExpectWithArray(__LINE__, #{args_call})\n" +
|
||||
@@ -44,8 +44,8 @@ class CMockGeneratorPluginArray
|
||||
lines = []
|
||||
func_name = function[:name]
|
||||
args_string = function[:args].map do |m|
|
||||
const_str = m[:const?] ? 'const ' : ''
|
||||
m[:ptr?] ? "#{const_str}#{m[:type]} #{m[:name]}, int #{m[:name]}_Depth" : "#{const_str}#{m[:type]} #{m[:name]}"
|
||||
type = @utils.arg_type_with_const(m)
|
||||
m[:ptr?] ? "#{type} #{m[:name]}, int #{m[:name]}_Depth" : "#{type} #{m[:name]}"
|
||||
end.join(', ')
|
||||
call_string = function[:args].map{|m| m[:ptr?] ? "#{m[:name]}, #{m[:name]}_Depth" : m[:name]}.join(', ')
|
||||
if (function[:return][:void?])
|
||||
|
||||
@@ -33,7 +33,7 @@ class CMockGeneratorPluginCallback
|
||||
|
||||
def mock_function_declarations(function)
|
||||
func_name = function[:name]
|
||||
return_type = function[:return][:const?] ? "const #{function[:return][:type]}" : function[:return][:type]
|
||||
return_type = function[:return][:type]
|
||||
style = (@include_count ? 1 : 0) | (function[:args].empty? ? 0 : 2)
|
||||
styles = [ "void", "int cmock_num_calls", function[:args_string], "#{function[:args_string]}, int cmock_num_calls" ]
|
||||
"typedef #{return_type} (* CMOCK_#{func_name}_CALLBACK)(#{styles[style]});\nvoid #{func_name}_StubWithCallback(CMOCK_#{func_name}_CALLBACK Callback);\n"
|
||||
@@ -41,7 +41,6 @@ class CMockGeneratorPluginCallback
|
||||
|
||||
def mock_implementation_for_callbacks_after_arg_check(function)
|
||||
func_name = function[:name]
|
||||
return_cast = function[:return][:const?] ? "(#{function[:return][:type]})" : ""
|
||||
style = (@include_count ? 1 : 0) | (function[:args].empty? ? 0 : 2) | (function[:return][:void?] ? 0 : 4)
|
||||
" if (Mock.#{func_name}_CallbackFunctionPointer != NULL)\n {\n" +
|
||||
case(style)
|
||||
@@ -49,16 +48,15 @@ class CMockGeneratorPluginCallback
|
||||
when 1 then " Mock.#{func_name}_CallbackFunctionPointer(Mock.#{func_name}_CallbackCalls++);\n }\n"
|
||||
when 2 then " Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')});\n }\n"
|
||||
when 3 then " Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')}, Mock.#{func_name}_CallbackCalls++);\n }\n"
|
||||
when 4 then " cmock_call_instance->ReturnVal = #{return_cast}Mock.#{func_name}_CallbackFunctionPointer();\n }\n"
|
||||
when 5 then " cmock_call_instance->ReturnVal = #{return_cast}Mock.#{func_name}_CallbackFunctionPointer(Mock.#{func_name}_CallbackCalls++);\n }\n"
|
||||
when 6 then " cmock_call_instance->ReturnVal = #{return_cast}Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')});\n }\n"
|
||||
when 7 then " cmock_call_instance->ReturnVal = #{return_cast}Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')}, Mock.#{func_name}_CallbackCalls++);\n }\n"
|
||||
when 4 then " cmock_call_instance->ReturnVal = Mock.#{func_name}_CallbackFunctionPointer();\n }\n"
|
||||
when 5 then " cmock_call_instance->ReturnVal = Mock.#{func_name}_CallbackFunctionPointer(Mock.#{func_name}_CallbackCalls++);\n }\n"
|
||||
when 6 then " cmock_call_instance->ReturnVal = Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')});\n }\n"
|
||||
when 7 then " cmock_call_instance->ReturnVal = Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')}, Mock.#{func_name}_CallbackCalls++);\n }\n"
|
||||
end
|
||||
end
|
||||
|
||||
def mock_implementation_for_callbacks_without_arg_check(function)
|
||||
func_name = function[:name]
|
||||
return_cast = function[:return][:const?] ? "(#{function[:return][:type]})" : ""
|
||||
style = (@include_count ? 1 : 0) | (function[:args].empty? ? 0 : 2) | (function[:return][:void?] ? 0 : 4)
|
||||
" if (Mock.#{func_name}_CallbackFunctionPointer != NULL)\n {\n" +
|
||||
case(style)
|
||||
@@ -66,10 +64,10 @@ class CMockGeneratorPluginCallback
|
||||
when 1 then " Mock.#{func_name}_CallbackFunctionPointer(Mock.#{func_name}_CallbackCalls++);\n return;\n }\n"
|
||||
when 2 then " Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')});\n return;\n }\n"
|
||||
when 3 then " Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')}, Mock.#{func_name}_CallbackCalls++);\n return;\n }\n"
|
||||
when 4 then " return #{return_cast}Mock.#{func_name}_CallbackFunctionPointer();\n }\n"
|
||||
when 5 then " return #{return_cast}Mock.#{func_name}_CallbackFunctionPointer(Mock.#{func_name}_CallbackCalls++);\n }\n"
|
||||
when 6 then " return #{return_cast}Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')});\n }\n"
|
||||
when 7 then " return #{return_cast}Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')}, Mock.#{func_name}_CallbackCalls++);\n }\n"
|
||||
when 4 then " return Mock.#{func_name}_CallbackFunctionPointer();\n }\n"
|
||||
when 5 then " return Mock.#{func_name}_CallbackFunctionPointer(Mock.#{func_name}_CallbackCalls++);\n }\n"
|
||||
when 6 then " return Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')});\n }\n"
|
||||
when 7 then " return Mock.#{func_name}_CallbackFunctionPointer(#{function[:args].map{|m| m[:name]}.join(', ')}, Mock.#{func_name}_CallbackCalls++);\n }\n"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -41,7 +41,6 @@ class CMockGeneratorPluginCexception
|
||||
|
||||
def mock_interfaces(function)
|
||||
arg_insert = (function[:args_string] == "void") ? "" : "#{function[:args_string]}, "
|
||||
call_string = function[:args].map{|m| m[:name]}.join(', ')
|
||||
[ "void #{function[:name]}_CMockExpectAndThrow(UNITY_LINE_TYPE cmock_line, #{arg_insert}CEXCEPTION_T cmock_to_throw)\n{\n",
|
||||
@utils.code_add_base_expectation(function[:name]),
|
||||
@utils.code_call_argument_loader(function),
|
||||
|
||||
@@ -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?])
|
||||
|
||||
@@ -40,10 +40,9 @@ class CMockGeneratorPluginIgnore
|
||||
lines << " return;\n }\n"
|
||||
else
|
||||
retval = function[:return].merge( { :name => "cmock_call_instance->ReturnVal"} )
|
||||
return_type = function[:return][:const?] ? "(const #{function[:return][:type]})" : ((function[:return][:type] =~ /cmock/) ? "(#{function[:return][:type]})" : '')
|
||||
lines << " if (cmock_call_instance == NULL)\n return #{return_type}Mock.#{function[:name]}_FinalReturn;\n"
|
||||
lines << " if (cmock_call_instance == NULL)\n return Mock.#{function[:name]}_FinalReturn;\n"
|
||||
lines << " " + @utils.code_assign_argument_quickly("Mock.#{function[:name]}_FinalReturn", retval) unless (retval[:void?])
|
||||
lines << " return #{return_type}cmock_call_instance->ReturnVal;\n }\n"
|
||||
lines << " return cmock_call_instance->ReturnVal;\n }\n"
|
||||
end
|
||||
lines
|
||||
end
|
||||
@@ -65,6 +64,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"
|
||||
|
||||
@@ -29,14 +29,12 @@ class CMockGeneratorPluginIgnoreArg
|
||||
lines = []
|
||||
func_name = function[:name]
|
||||
function[:args].each do |arg|
|
||||
arg_name = arg[:name]
|
||||
arg_type = arg[:type]
|
||||
lines << "void #{function[:name]}_CMockIgnoreArg_#{arg[:name]}(UNITY_LINE_TYPE cmock_line)\n"
|
||||
lines << "void #{func_name}_CMockIgnoreArg_#{arg[:name]}(UNITY_LINE_TYPE cmock_line)\n"
|
||||
lines << "{\n"
|
||||
lines << " CMOCK_#{func_name}_CALL_INSTANCE* cmock_call_instance = " +
|
||||
"(CMOCK_#{func_name}_CALL_INSTANCE*)CMock_Guts_GetAddressFor(CMock_Guts_MemEndOfChain(Mock.#{func_name}_CallInstance));\n"
|
||||
lines << " UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringIgnPreExp);\n"
|
||||
lines << " cmock_call_instance->IgnoreArg_#{arg_name} = 1;\n"
|
||||
lines << " cmock_call_instance->IgnoreArg_#{arg[:name]} = 1;\n"
|
||||
lines << "}\n\n"
|
||||
end
|
||||
lines
|
||||
|
||||
@@ -40,7 +40,6 @@ class CMockGeneratorPluginReturnThruPtr
|
||||
func_name = function[:name]
|
||||
function[:args].each do |arg|
|
||||
arg_name = arg[:name]
|
||||
arg_type = arg[:type]
|
||||
if (@utils.ptr_or_str?(arg[:type]) and not arg[:const?])
|
||||
lines << "void #{func_name}_CMockReturnMemThruPtr_#{arg_name}(UNITY_LINE_TYPE cmock_line, #{arg[:type]} #{arg_name}, int cmock_size)\n"
|
||||
lines << "{\n"
|
||||
@@ -60,7 +59,6 @@ class CMockGeneratorPluginReturnThruPtr
|
||||
lines = []
|
||||
function[:args].each do |arg|
|
||||
arg_name = arg[:name]
|
||||
arg_type = arg[:type]
|
||||
if (@utils.ptr_or_str?(arg[:type]) and not arg[:const?])
|
||||
lines << " if (cmock_call_instance->ReturnThruPtr_#{arg_name}_Used)\n"
|
||||
lines << " {\n"
|
||||
|
||||
@@ -22,6 +22,19 @@ class CMockGeneratorUtils
|
||||
@helpers = helpers
|
||||
end
|
||||
|
||||
def self.arg_type_with_const(arg)
|
||||
# Restore any "const" that was removed in header parsing
|
||||
if arg[:type].include?('*')
|
||||
arg[:const_ptr?] ? "#{arg[:type]} const" : arg[:type]
|
||||
else
|
||||
arg[:const?] ? "const #{arg[:type]}" : arg[:type]
|
||||
end
|
||||
end
|
||||
|
||||
def arg_type_with_const(arg)
|
||||
self.class.arg_type_with_const(arg)
|
||||
end
|
||||
|
||||
def code_verify_an_arg_expectation(function, arg)
|
||||
if (@arrays)
|
||||
case(@ptr_handling)
|
||||
@@ -58,7 +71,7 @@ class CMockGeneratorUtils
|
||||
|
||||
def code_assign_argument_quickly(dest, arg)
|
||||
if (arg[:ptr?] or @treat_as.include?(arg[:type]))
|
||||
" #{dest} = #{arg[:const?] ? "(#{arg[:type]})" : ''}#{arg[:name]};\n"
|
||||
" #{dest} = #{arg[:name]};\n"
|
||||
else
|
||||
" memcpy(&#{dest}, &#{arg[:name]}, sizeof(#{arg[:type]}));\n"
|
||||
end
|
||||
@@ -68,8 +81,8 @@ class CMockGeneratorUtils
|
||||
if (function[:args_string] != "void")
|
||||
if (@arrays)
|
||||
args_string = function[:args].map do |m|
|
||||
const_str = m[ :const? ] ? 'const ' : ''
|
||||
m[:ptr?] ? "#{const_str}#{m[:type]} #{m[:name]}, int #{m[:name]}_Depth" : "#{const_str}#{m[:type]} #{m[:name]}"
|
||||
type = arg_type_with_const(m)
|
||||
m[:ptr?] ? "#{type} #{m[:name]}, int #{m[:name]}_Depth" : "#{type} #{m[:name]}"
|
||||
end.join(', ')
|
||||
"void CMockExpectParameters_#{function[:name]}(CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance, #{args_string})\n{\n" +
|
||||
function[:args].inject("") { |all, arg| all + code_add_an_arg_expectation(arg, (arg[:ptr?] ? "#{arg[:name]}_Depth" : 1) ) } +
|
||||
@@ -112,12 +125,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 +164,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 +200,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
|
||||
|
||||
+80
-57
@@ -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, ";")
|
||||
@@ -132,51 +140,77 @@ class CMockHeaderParser
|
||||
return funcs
|
||||
end
|
||||
|
||||
def parse_type_and_name(arg)
|
||||
# Split up words and remove known attributes. For pointer types, make sure
|
||||
# to remove 'const' only when it applies to the pointer itself, not when it
|
||||
# applies to the type pointed to. For non-pointer types, remove any
|
||||
# occurrence of 'const'.
|
||||
arg.gsub!(/(\w)\*/,'\1 *') # pull asterisks away from preceding word
|
||||
arg.gsub!(/\*(\w)/,'* \1') # pull asterisks away from following word
|
||||
arg_array = arg.split
|
||||
arg_info = divine_ptr_and_const(arg)
|
||||
arg_info[:name] = arg_array[-1]
|
||||
|
||||
attributes = arg.include?('*') ? @c_attr_noconst : @c_attributes
|
||||
attr_array = []
|
||||
type_array = []
|
||||
|
||||
arg_array[0..-2].each do |word|
|
||||
if attributes.include?(word)
|
||||
attr_array << word
|
||||
elsif @c_calling_conventions.include?(word)
|
||||
arg_info[:c_calling_convention] = word
|
||||
else
|
||||
type_array << word
|
||||
end
|
||||
end
|
||||
|
||||
if arg_info[:const_ptr?]
|
||||
attr_array << 'const'
|
||||
type_array.delete_at(type_array.rindex('const'))
|
||||
end
|
||||
|
||||
arg_info[:modifier] = attr_array.join(' ')
|
||||
arg_info[:type] = type_array.join(' ').gsub(/\s+\*/,'*') # remove space before asterisks
|
||||
return arg_info
|
||||
end
|
||||
|
||||
def parse_args(arg_list)
|
||||
args = []
|
||||
arg_list.split(',').each do |arg|
|
||||
arg.strip!
|
||||
return args if (arg =~ /^\s*((\.\.\.)|(void))\s*$/) # we're done if we reach void by itself or ...
|
||||
arg_array = arg.split
|
||||
arg_elements = arg_array - @c_attributes # split up words and remove known attributes
|
||||
args << { :type => (arg_type = arg_elements[0..-2].join(' ')),
|
||||
:name => arg_elements[-1]
|
||||
}.merge(divine_ptr_and_const(arg))
|
||||
|
||||
arg_info = parse_type_and_name(arg)
|
||||
arg_info.delete(:modifier) # don't care about this
|
||||
arg_info.delete(:c_calling_convention) # don't care about this
|
||||
args << arg_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
|
||||
@@ -229,35 +263,24 @@ class CMockHeaderParser
|
||||
args = regex_match[2].strip
|
||||
|
||||
#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 = descriptors.split #array of all descriptor strings
|
||||
parsed = parse_type_and_name(regex_match[1])
|
||||
|
||||
#grab name
|
||||
decl[:name] = descriptors[-1] #snag name as last array item
|
||||
|
||||
#build attribute and return type strings
|
||||
decl[:modifier] = []
|
||||
rettype = []
|
||||
full_retval = descriptors[0..-2].join(' ')
|
||||
descriptors[0..-2].each do |word|
|
||||
if @c_attributes.include?(word)
|
||||
decl[:modifier] << word
|
||||
elsif @c_calling_conventions.include?(word)
|
||||
decl[:c_calling_convention] = word
|
||||
else
|
||||
rettype << word
|
||||
end
|
||||
decl[:name] = parsed[:name]
|
||||
decl[:modifier] = parsed[:modifier]
|
||||
unless parsed[:c_calling_convention].nil?
|
||||
decl[:c_calling_convention] = parsed[:c_calling_convention]
|
||||
end
|
||||
decl[:modifier] = decl[:modifier].join(' ')
|
||||
rettype = rettype.join(' ')
|
||||
|
||||
rettype = parsed[:type]
|
||||
rettype = 'void' if (@local_as_void.include?(rettype.strip))
|
||||
decl[:return] = { :type => rettype,
|
||||
:name => 'cmock_to_return',
|
||||
:str => "#{rettype} cmock_to_return",
|
||||
:void? => (rettype == 'void')
|
||||
}.merge(divine_ptr_and_const(full_retval))
|
||||
decl[:return] = { :type => rettype,
|
||||
:name => 'cmock_to_return',
|
||||
:str => "#{rettype} cmock_to_return",
|
||||
:void? => (rettype == 'void'),
|
||||
:ptr? => parsed[:ptr?],
|
||||
:const? => parsed[:const?],
|
||||
:const_ptr? => parsed[:const_ptr?]
|
||||
}
|
||||
|
||||
#remove default argument statements from mock definitions
|
||||
args.gsub!(/=\s*[a-zA-Z0-9_\.]+\s*/, ' ')
|
||||
|
||||
+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
|
||||
217
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
2.4.4
|
||||
2.4.6
|
||||
|
||||
|
||||
+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
|
||||
|
||||
+11
-6
@@ -48,12 +48,17 @@ CMOCK_MEM_INDEX_TYPE CMock_Guts_MemNew(CMOCK_MEM_INDEX_TYPE size)
|
||||
size = (size + CMOCK_MEM_ALIGN_MASK) & ~CMOCK_MEM_ALIGN_MASK;
|
||||
if ((CMock_Guts_BufferSize - CMock_Guts_FreePtr) < size)
|
||||
{
|
||||
#ifdef CMOCK_MEM_DYNAMIC
|
||||
CMock_Guts_BufferSize += CMOCK_MEM_SIZE + size;
|
||||
CMock_Guts_Buffer = realloc(CMock_Guts_Buffer, (size_t)CMock_Guts_BufferSize);
|
||||
if (CMock_Guts_Buffer == NULL)
|
||||
#endif //yes that if will continue to the return below if TRUE
|
||||
return CMOCK_GUTS_NONE;
|
||||
#ifndef CMOCK_MEM_DYNAMIC
|
||||
return CMOCK_GUTS_NONE; // nothing we can do; our static buffer is out of memory
|
||||
#else
|
||||
// our dynamic buffer does not have enough room; request more via realloc()
|
||||
CMOCK_MEM_INDEX_TYPE new_buffersize = CMock_Guts_BufferSize + CMOCK_MEM_SIZE + size;
|
||||
unsigned char* new_buffer = realloc(CMock_Guts_Buffer, (size_t)new_buffersize);
|
||||
if (new_buffer == NULL)
|
||||
return CMOCK_GUTS_NONE; // realloc() failed; out of memory
|
||||
CMock_Guts_Buffer = new_buffer;
|
||||
CMock_Guts_BufferSize = new_buffersize;
|
||||
#endif
|
||||
}
|
||||
|
||||
//determine where we're putting this new block, and init its pointer to be the end of the line
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
...
|
||||
+11
-10
@@ -24,20 +24,21 @@ end
|
||||
|
||||
def test_return
|
||||
{
|
||||
:int => {:type => "int", :name => 'cmock_to_return', :ptr? => false, :const? => false, :void? => false, :str => 'int cmock_to_return'},
|
||||
:int_ptr => {:type => "int*", :name => 'cmock_to_return', :ptr? => true, :const? => false, :void? => false, :str => 'int* cmock_to_return'},
|
||||
:void => {:type => "void", :name => 'cmock_to_return', :ptr? => false, :const? => false, :void? => true, :str => 'void cmock_to_return'},
|
||||
:string => {:type => "char*", :name => 'cmock_to_return', :ptr? => false, :const? => true, :void? => false, :str => 'const char* cmock_to_return'},
|
||||
:int => {:type => "int", :name => 'cmock_to_return', :ptr? => false, :const? => false, :void? => false, :str => 'int cmock_to_return'},
|
||||
:int_ptr => {:type => "int*", :name => 'cmock_to_return', :ptr? => true, :const? => false, :void? => false, :str => 'int* cmock_to_return'},
|
||||
:void => {:type => "void", :name => 'cmock_to_return', :ptr? => false, :const? => false, :void? => true, :str => 'void cmock_to_return'},
|
||||
:string => {:type => "const char*", :name => 'cmock_to_return', :ptr? => false, :const? => true, :void? => false, :str => 'const char* cmock_to_return'},
|
||||
}
|
||||
end
|
||||
|
||||
def test_arg
|
||||
{
|
||||
:int => {:type => "int", :name => 'MyInt', :ptr? => false, :const? => false},
|
||||
:int_ptr => {:type => "int*", :name => 'MyIntPtr', :ptr? => true, :const? => false},
|
||||
:mytype => {:type => "MY_TYPE", :name => 'MyMyType', :ptr? => false, :const? => true},
|
||||
:mytype_ptr => {:type => "MY_TYPE*", :name => 'MyMyTypePtr', :ptr? => true, :const? => false},
|
||||
:string => {:type => "char*", :name => 'MyStr', :ptr? => false, :const? => true},
|
||||
:int => {:type => "int", :name => 'MyInt', :ptr? => false, :const? => false, :const_ptr? => false},
|
||||
:int_ptr => {:type => "int*", :name => 'MyIntPtr', :ptr? => true, :const? => false, :const_ptr? => false},
|
||||
:const_ptr => {:type => "int*", :name => 'MyConstPtr', :ptr? => true, :const? => false, :const_ptr? => true},
|
||||
:double_ptr => {:type => "int const**", :name => 'MyDoublePtr', :ptr? => true, :const? => true, :const_ptr? => false},
|
||||
:mytype => {:type => "MY_TYPE", :name => 'MyMyType', :ptr? => false, :const? => true, :const_ptr? => false},
|
||||
:mytype_ptr => {:type => "MY_TYPE*", :name => 'MyMyTypePtr', :ptr? => true, :const? => false, :const_ptr? => false},
|
||||
:string => {:type => "const char*", :name => 'MyStr', :ptr? => false, :const? => true, :const_ptr? => false},
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
@@ -14,7 +14,8 @@ describe CMockConfig, "Verify CMockConfig Module" do
|
||||
it "use default settings when no parameters are specified" do
|
||||
config = CMockConfig.new
|
||||
assert_equal(CMockConfig::CMockDefaultOptions[:mock_path], config.mock_path)
|
||||
assert_equal(CMockConfig::CMockDefaultOptions[:includes], config.includes)
|
||||
assert_nil(CMockConfig::CMockDefaultOptions[:includes])
|
||||
assert_nil(config.includes)
|
||||
assert_equal(CMockConfig::CMockDefaultOptions[:attributes], config.attributes)
|
||||
assert_equal(CMockConfig::CMockDefaultOptions[:plugins], config.plugins)
|
||||
assert_equal(CMockConfig::CMockDefaultOptions[:treat_externs], config.treat_externs)
|
||||
@@ -35,7 +36,8 @@ describe CMockConfig, "Verify CMockConfig Module" do
|
||||
test_plugins = [:soda, :pizza]
|
||||
config = CMockConfig.new("#{File.expand_path(File.dirname(__FILE__))}/cmock_config_test.yml")
|
||||
assert_equal(CMockConfig::CMockDefaultOptions[:mock_path], config.mock_path)
|
||||
assert_equal(CMockConfig::CMockDefaultOptions[:includes], config.includes)
|
||||
assert_nil(CMockConfig::CMockDefaultOptions[:includes])
|
||||
assert_nil(config.includes)
|
||||
assert_equal(test_plugins, config.plugins)
|
||||
assert_equal(:include, config.treat_externs)
|
||||
end
|
||||
|
||||
@@ -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}"
|
||||
@@ -85,7 +87,6 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
@config.expect :weak, ""
|
||||
orig_filename = "PoutPoutFish.h"
|
||||
define_name = "MOCKPOUTPOUTFISH_H"
|
||||
mock_name = "MockPoutPoutFish"
|
||||
output = []
|
||||
expected = [
|
||||
"/* AUTOGENERATED FILE. DO NOT EDIT. */\n",
|
||||
@@ -98,6 +99,9 @@ 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",
|
||||
"#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 6 || (__GNUC_MINOR__ == 6 && __GNUC_PATCHLEVEL__ > 0)))\n",
|
||||
"#pragma GCC diagnostic push\n",
|
||||
"#endif\n",
|
||||
"#if !defined(__clang__)\n",
|
||||
"#pragma GCC diagnostic ignored \"-Wpragmas\"\n",
|
||||
"#endif\n",
|
||||
@@ -127,6 +131,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"
|
||||
@@ -137,7 +142,6 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
@config.expect :weak, ""
|
||||
orig_filename = "Pout-Pout Fish.h"
|
||||
define_name = "MOCKPOUT_POUT_FISH_H"
|
||||
mock_name = "MockPout_Pout_Fish"
|
||||
output = []
|
||||
expected = [
|
||||
"/* AUTOGENERATED FILE. DO NOT EDIT. */\n",
|
||||
@@ -150,6 +154,9 @@ 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",
|
||||
"#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 6 || (__GNUC_MINOR__ == 6 && __GNUC_PATCHLEVEL__ > 0)))\n",
|
||||
"#pragma GCC diagnostic push\n",
|
||||
"#endif\n",
|
||||
"#if !defined(__clang__)\n",
|
||||
"#pragma GCC diagnostic ignored \"-Wpragmas\"\n",
|
||||
"#endif\n",
|
||||
@@ -173,7 +180,6 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
@config.expect :weak, ""
|
||||
orig_filename = "PoutPoutFish.h"
|
||||
define_name = "MOCKPOUTPOUTFISH_H"
|
||||
mock_name = "MockPoutPoutFish"
|
||||
output = []
|
||||
expected = [
|
||||
"/* AUTOGENERATED FILE. DO NOT EDIT. */\n",
|
||||
@@ -185,6 +191,9 @@ 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",
|
||||
"#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 6 || (__GNUC_MINOR__ == 6 && __GNUC_PATCHLEVEL__ > 0)))\n",
|
||||
"#pragma GCC diagnostic push\n",
|
||||
"#endif\n",
|
||||
"#if !defined(__clang__)\n",
|
||||
"#pragma GCC diagnostic ignored \"-Wpragmas\"\n",
|
||||
"#endif\n",
|
||||
@@ -208,7 +217,6 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
@config.expect :weak, ""
|
||||
orig_filename = "PoutPoutFish.h"
|
||||
define_name = "MOCKPOUTPOUTFISH_H"
|
||||
mock_name = "MockPoutPoutFish"
|
||||
output = []
|
||||
expected = [
|
||||
"/* AUTOGENERATED FILE. DO NOT EDIT. */\n",
|
||||
@@ -221,6 +229,9 @@ 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",
|
||||
"#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 6 || (__GNUC_MINOR__ == 6 && __GNUC_PATCHLEVEL__ > 0)))\n",
|
||||
"#pragma GCC diagnostic push\n",
|
||||
"#endif\n",
|
||||
"#if !defined(__clang__)\n",
|
||||
"#pragma GCC diagnostic ignored \"-Wpragmas\"\n",
|
||||
"#endif\n",
|
||||
@@ -272,7 +283,15 @@ 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",
|
||||
"#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 6 || (__GNUC_MINOR__ == 6 && __GNUC_PATCHLEVEL__ > 0)))\n",
|
||||
"#pragma GCC diagnostic pop\n",
|
||||
"#endif\n",
|
||||
"#endif\n",
|
||||
"\n",
|
||||
"#endif\n"
|
||||
]
|
||||
|
||||
@cmock_generator.create_mock_header_footer(output)
|
||||
|
||||
|
||||
@@ -6,21 +6,29 @@
|
||||
|
||||
require File.expand_path(File.dirname(__FILE__)) + "/../test_helper"
|
||||
require File.expand_path(File.dirname(__FILE__)) + '/../../lib/cmock_generator_plugin_array'
|
||||
require File.expand_path(File.dirname(__FILE__)) + '/../../lib/cmock_generator_utils'
|
||||
|
||||
class UtilsStub
|
||||
def helpers
|
||||
{}
|
||||
end
|
||||
def arg_type_with_const(arg)
|
||||
CMockGeneratorUtils.arg_type_with_const(arg)
|
||||
end
|
||||
def code_add_base_expectation(func)
|
||||
"mock_retval_0"
|
||||
end
|
||||
end
|
||||
|
||||
describe CMockGeneratorPluginArray, "Verify CMockPGeneratorluginArray Module" do
|
||||
before do
|
||||
create_mocks :utils
|
||||
|
||||
#no strict ordering
|
||||
@config = create_stub(
|
||||
:when_ptr => :compare_data,
|
||||
:enforce_strict_ordering => false,
|
||||
:respond_to? => true )
|
||||
|
||||
@utils = create_stub(
|
||||
:helpers => {},
|
||||
:code_add_base_expectation => "mock_retval_0"
|
||||
)
|
||||
@utils = UtilsStub.new
|
||||
|
||||
@cmock_generator_plugin_array = CMockGeneratorPluginArray.new(@config, @utils)
|
||||
end
|
||||
@@ -29,8 +37,8 @@ describe CMockGeneratorPluginArray, "Verify CMockPGeneratorluginArray Module" do
|
||||
end
|
||||
|
||||
it "have set up internal priority" do
|
||||
assert_equal(nil, @cmock_generator_plugin_array.unity_helper)
|
||||
assert_equal(8, @cmock_generator_plugin_array.priority)
|
||||
assert_nil(@cmock_generator_plugin_array.unity_helper)
|
||||
assert_equal(8, @cmock_generator_plugin_array.priority)
|
||||
end
|
||||
|
||||
it "not include any additional include files" do
|
||||
@@ -88,10 +96,10 @@ describe CMockGeneratorPluginArray, "Verify CMockPGeneratorluginArray Module" do
|
||||
|
||||
it "add another mock function declaration for functions of style 'const char* func(const int* tofu)'" do
|
||||
function = {:name => "Pine",
|
||||
:args => [{ :type => "int*",
|
||||
:name => "tofu",
|
||||
:ptr? => true,
|
||||
:const? => true,
|
||||
:args => [{ :type => "const int*",
|
||||
:name => "tofu",
|
||||
:ptr? => true,
|
||||
:const? => true,
|
||||
}],
|
||||
:return => test_return[:string],
|
||||
:contains_ptr? => true }
|
||||
|
||||
@@ -26,8 +26,8 @@ describe CMockGeneratorPluginExpect, "Verify CMockGeneratorPluginExpect Module W
|
||||
end
|
||||
|
||||
it "have set up internal priority on init" do
|
||||
assert_equal(nil, @cmock_generator_plugin_expect.unity_helper)
|
||||
assert_equal(5, @cmock_generator_plugin_expect.priority)
|
||||
assert_nil(@cmock_generator_plugin_expect.unity_helper)
|
||||
assert_equal(5, @cmock_generator_plugin_expect.priority)
|
||||
end
|
||||
|
||||
it "not include any additional include files" do
|
||||
|
||||
@@ -26,8 +26,8 @@ describe CMockGeneratorPluginExpect, "Verify CMockGeneratorPluginExpect Module w
|
||||
end
|
||||
|
||||
it "have set up internal priority on init" do
|
||||
assert_equal(nil, @cmock_generator_plugin_expect.unity_helper)
|
||||
assert_equal(5, @cmock_generator_plugin_expect.priority)
|
||||
assert_nil(@cmock_generator_plugin_expect.unity_helper)
|
||||
assert_equal(5, @cmock_generator_plugin_expect.priority)
|
||||
end
|
||||
|
||||
it "not include any additional include files" do
|
||||
@@ -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
|
||||
|
||||
@@ -21,9 +21,9 @@ describe CMockGeneratorPluginIgnoreArg, "Verify CMockGeneratorPluginIgnoreArg Mo
|
||||
:name => "chicken",
|
||||
:ptr? => false,
|
||||
},
|
||||
{ :type => "int*",
|
||||
:name => "beef",
|
||||
:ptr? => true,
|
||||
{ :type => "const int*",
|
||||
:name => "beef",
|
||||
:ptr? => true,
|
||||
:const? => true,
|
||||
},
|
||||
{ :type => "int*",
|
||||
|
||||
@@ -27,9 +27,9 @@ describe CMockGeneratorPluginReturnThruPtr, "Verify CMockGeneratorPluginReturnTh
|
||||
:name => "chicken",
|
||||
:ptr? => false,
|
||||
},
|
||||
{ :type => "int*",
|
||||
:name => "beef",
|
||||
:ptr? => true,
|
||||
{ :type => "const int*",
|
||||
:name => "beef",
|
||||
:ptr? => true,
|
||||
:const? => true,
|
||||
},
|
||||
{ :type => "int*",
|
||||
@@ -52,7 +52,7 @@ describe CMockGeneratorPluginReturnThruPtr, "Verify CMockGeneratorPluginReturnTh
|
||||
|
||||
def complex_func_expect
|
||||
@utils.expect :ptr_or_str?, false, ['int']
|
||||
@utils.expect :ptr_or_str?, true, ['int*']
|
||||
@utils.expect :ptr_or_str?, true, ['const int*']
|
||||
@utils.expect :ptr_or_str?, true, ['int*']
|
||||
end
|
||||
|
||||
@@ -124,11 +124,13 @@ describe CMockGeneratorPluginReturnThruPtr, "Verify CMockGeneratorPluginReturnTh
|
||||
expected =
|
||||
" if (cmock_call_instance->ReturnThruPtr_tofu_Used)\n" +
|
||||
" {\n" +
|
||||
" memcpy(tofu, cmock_call_instance->ReturnThruPtr_tofu_Val,\n" +
|
||||
" UNITY_TEST_ASSERT_NOT_NULL(tofu, cmock_line, CMockStringPtrIsNULL);\n" +
|
||||
" memcpy((void*)tofu, (void*)cmock_call_instance->ReturnThruPtr_tofu_Val,\n" +
|
||||
" cmock_call_instance->ReturnThruPtr_tofu_Size);\n" +
|
||||
" }\n" +
|
||||
" }\n"
|
||||
|
||||
returned = @cmock_generator_plugin_return_thru_ptr.mock_implementation(@complex_func).join("")
|
||||
assert_equal(expected, returned)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -20,7 +20,7 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do
|
||||
@config.expect :plugins, []
|
||||
@config.expect :plugins, []
|
||||
@config.expect :plugins, []
|
||||
@config.expect :treat_as, {'int' => 'INT','short' => 'INT16','long' => 'INT','char' => 'INT8','char*' => 'STRING'}
|
||||
@config.expect :treat_as, {'int' => 'INT','short' => 'INT16','long' => 'INT','char' => 'INT8','const char*' => 'STRING'}
|
||||
@cmock_generator_utils_simple = CMockGeneratorUtils.new(@config, {:unity_helper => @unity_helper})
|
||||
|
||||
@config.expect :when_ptr, :smart
|
||||
@@ -31,7 +31,7 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do
|
||||
@config.expect :plugins, [:array, :cexception, :return_thru_ptr, :ignore_arg, :ignore]
|
||||
@config.expect :plugins, [:array, :cexception, :return_thru_ptr, :ignore_arg, :ignore]
|
||||
@config.expect :plugins, [:array, :cexception, :return_thru_ptr, :ignore_arg, :ignore]
|
||||
@config.expect :treat_as, {'int' => 'INT','short' => 'INT16','long' => 'INT','char' => 'INT8','uint32_t' => 'HEX32','char*' => 'STRING'}
|
||||
@config.expect :treat_as, {'int' => 'INT','short' => 'INT16','long' => 'INT','char' => 'INT8','uint32_t' => 'HEX32','const char*' => 'STRING'}
|
||||
@cmock_generator_utils_complex = CMockGeneratorUtils.new(@config, {:unity_helper => @unity_helper, :A=>1, :B=>2})
|
||||
end
|
||||
|
||||
@@ -99,8 +99,8 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do
|
||||
arg1 = { :name => "Orange", :const? => false, :type => 'int', :ptr? => false }
|
||||
expected1 = " cmock_call_instance->Expected_Orange = Orange;\n"
|
||||
|
||||
arg2 = { :name => "Lemon", :const? => true, :type => 'const char*', :ptr? => true }
|
||||
expected2 = " cmock_call_instance->Expected_Lemon = (const char*)Lemon;\n"
|
||||
arg2 = { :name => "Lemon", :const? => true, :type => 'const char*', :ptr? => false }
|
||||
expected2 = " cmock_call_instance->Expected_Lemon = Lemon;\n"
|
||||
|
||||
arg3 = { :name => "Kiwi", :const? => false, :type => 'KIWI_T*', :ptr? => true }
|
||||
expected3 = " cmock_call_instance->Expected_Kiwi = Kiwi;\n"
|
||||
@@ -119,8 +119,8 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do
|
||||
expected1 = " cmock_call_instance->Expected_Orange = Orange;\n" +
|
||||
" cmock_call_instance->IgnoreArg_Orange = 0;\n"
|
||||
|
||||
arg2 = { :name => "Lemon", :const? => true, :type => 'const char*', :ptr? => true }
|
||||
expected2 = " cmock_call_instance->Expected_Lemon = (const char*)Lemon;\n" +
|
||||
arg2 = { :name => "Lemon", :const? => true, :type => 'const char*', :ptr? => false }
|
||||
expected2 = " cmock_call_instance->Expected_Lemon = Lemon;\n" +
|
||||
" cmock_call_instance->Expected_Lemon_Depth = Lemon_Depth;\n" +
|
||||
" cmock_call_instance->IgnoreArg_Lemon = 0;\n"
|
||||
|
||||
@@ -154,7 +154,7 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do
|
||||
expected = "void CMockExpectParameters_Melon(CMOCK_Melon_CALL_INSTANCE* cmock_call_instance, stuff)\n{\n" +
|
||||
" cmock_call_instance->Expected_MyIntPtr = MyIntPtr;\n" +
|
||||
" memcpy(&cmock_call_instance->Expected_MyMyType, &MyMyType, sizeof(MY_TYPE));\n" +
|
||||
" cmock_call_instance->Expected_MyStr = (char*)MyStr;\n" +
|
||||
" cmock_call_instance->Expected_MyStr = MyStr;\n" +
|
||||
"}\n\n"
|
||||
assert_equal(expected, @cmock_generator_utils_simple.code_add_argument_loader(function))
|
||||
end
|
||||
@@ -171,12 +171,29 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do
|
||||
" cmock_call_instance->ReturnThruPtr_MyIntPtr_Used = 0;\n" +
|
||||
" memcpy(&cmock_call_instance->Expected_MyMyType, &MyMyType, sizeof(MY_TYPE));\n" +
|
||||
" cmock_call_instance->IgnoreArg_MyMyType = 0;\n" +
|
||||
" cmock_call_instance->Expected_MyStr = (char*)MyStr;\n" +
|
||||
" cmock_call_instance->Expected_MyStr = MyStr;\n" +
|
||||
" cmock_call_instance->IgnoreArg_MyStr = 0;\n" +
|
||||
"}\n\n"
|
||||
assert_equal(expected, @cmock_generator_utils_complex.code_add_argument_loader(function))
|
||||
end
|
||||
|
||||
it 'create an argument loader when the function has pointer arguments supporting arrays' do
|
||||
function = { :name => "Melon",
|
||||
:args_string => "stuff",
|
||||
:args => [test_arg[:const_ptr], test_arg[:double_ptr]]
|
||||
}
|
||||
expected = "void CMockExpectParameters_Melon(CMOCK_Melon_CALL_INSTANCE* cmock_call_instance, int* const MyConstPtr, int MyConstPtr_Depth, int const** MyDoublePtr, int MyDoublePtr_Depth)\n{\n" +
|
||||
" cmock_call_instance->Expected_MyConstPtr = MyConstPtr;\n" +
|
||||
" cmock_call_instance->Expected_MyConstPtr_Depth = MyConstPtr_Depth;\n" +
|
||||
" cmock_call_instance->IgnoreArg_MyConstPtr = 0;\n" +
|
||||
" cmock_call_instance->ReturnThruPtr_MyConstPtr_Used = 0;\n" +
|
||||
" cmock_call_instance->Expected_MyDoublePtr = MyDoublePtr;\n" +
|
||||
" cmock_call_instance->Expected_MyDoublePtr_Depth = MyDoublePtr_Depth;\n" +
|
||||
" cmock_call_instance->IgnoreArg_MyDoublePtr = 0;\n" +
|
||||
"}\n\n"
|
||||
assert_equal(expected, @cmock_generator_utils_complex.code_add_argument_loader(function))
|
||||
end
|
||||
|
||||
it "not call argument loader if there are no arguments to actually use for this function" do
|
||||
function = { :name => "Pineapple", :args_string => "void" }
|
||||
|
||||
@@ -231,7 +248,7 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do
|
||||
" UNITY_TEST_ASSERT_EQUAL_STRING(cmock_call_instance->Expected_MyStr, MyStr, cmock_line, CMockStringMismatch);\n" +
|
||||
" }\n"
|
||||
@unity_helper.expect :nil?, false
|
||||
@unity_helper.expect :get_helper, ['UNITY_TEST_ASSERT_EQUAL_STRING',''], ['char*']
|
||||
@unity_helper.expect :get_helper, ['UNITY_TEST_ASSERT_EQUAL_STRING',''], ['const char*']
|
||||
assert_equal(expected, @cmock_generator_utils_simple.code_verify_an_arg_expectation(function, arg))
|
||||
end
|
||||
|
||||
@@ -311,7 +328,7 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do
|
||||
" UNITY_TEST_ASSERT_EQUAL_STRING(cmock_call_instance->Expected_MyStr, MyStr, cmock_line, CMockStringMismatch);\n" +
|
||||
" }\n"
|
||||
@unity_helper.expect :nil?, false
|
||||
@unity_helper.expect :get_helper, ['UNITY_TEST_ASSERT_EQUAL_STRING',''], ['char*']
|
||||
@unity_helper.expect :get_helper, ['UNITY_TEST_ASSERT_EQUAL_STRING',''], ['const char*']
|
||||
assert_equal(expected, @cmock_generator_utils_complex.code_verify_an_arg_expectation(function, arg))
|
||||
end
|
||||
|
||||
|
||||
@@ -805,6 +805,64 @@ describe CMockHeaderParser, "Verify CMockHeaderParser Module" do
|
||||
assert_equal(expected, @parser.parse("module", source)[:functions])
|
||||
end
|
||||
|
||||
it "should properly handle const before return type" do
|
||||
sources = [
|
||||
"const int * PorkRoast(void);\n",
|
||||
"const int* PorkRoast(void);\n",
|
||||
"const int *PorkRoast(void);\n"
|
||||
]
|
||||
|
||||
expected = [{ :var_arg => nil,
|
||||
:name => "PorkRoast",
|
||||
:return => { :type => "const int*",
|
||||
:name => 'cmock_to_return',
|
||||
:ptr? => true,
|
||||
:const? => true,
|
||||
:const_ptr? => false,
|
||||
:str => "const int* cmock_to_return",
|
||||
:void? => false
|
||||
},
|
||||
:modifier => "",
|
||||
: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 before return type" do
|
||||
sources = [
|
||||
"int const * PorkRoast(void);\n",
|
||||
"int const* PorkRoast(void);\n",
|
||||
"int const *PorkRoast(void);\n"
|
||||
]
|
||||
|
||||
expected = [{ :var_arg => nil,
|
||||
:name => "PorkRoast",
|
||||
:return => { :type => "int const*",
|
||||
:name => 'cmock_to_return',
|
||||
:ptr? => true,
|
||||
:const? => true,
|
||||
:const_ptr? => false,
|
||||
:str => "int const* cmock_to_return",
|
||||
:void? => false
|
||||
},
|
||||
:modifier => "",
|
||||
: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 +886,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 +1025,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 +1173,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 +1189,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 +1528,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 +1631,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...287e076962
Reference in New Issue
Block a user