mirror of
https://github.com/ThrowTheSwitch/CMock.git
synced 2026-06-23 14:00:33 +00:00
Compare commits
174 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 27bca0c3c4 | |||
| 9bb250ea4a | |||
| 9d092898ef | |||
| dd00b96f0d | |||
| aa5113e012 | |||
| 325b6b333a | |||
| 73fd65928c | |||
| 3eccb8e3d4 | |||
| 1f939c9005 | |||
| 9e1c6c068d | |||
| 4ae268dbbe | |||
| d847e6777c | |||
| dcde998087 | |||
| 38d6dccc8e | |||
| 03acc531bf | |||
| 45920ed724 | |||
| c4842fad0c | |||
| 9f3cee70cd | |||
| 4dd557f2df | |||
| af1818a652 | |||
| e352bb8c3b | |||
| 63f5e2f962 | |||
| 5eec2510b1 | |||
| f5984f44e8 | |||
| 9c1c6a05dc | |||
| 70d5750659 | |||
| 72f1c9e2b8 | |||
| 334f46781a | |||
| ea061bbb50 | |||
| 21d181380f | |||
| 72b356b97d | |||
| 22a7228bbc | |||
| afa294982e | |||
| 44f126878b | |||
| 1987138e81 | |||
| baa946a05f | |||
| d304ff273a | |||
| 56faeb935f | |||
| 61ed5cc7f8 | |||
| 496cabff10 | |||
| 94ca645061 | |||
| d36662da2a | |||
| b735d09603 | |||
| 5f8ec6da7f | |||
| 3e28a5412d | |||
| 5f8e90b82a | |||
| 541e7034ad | |||
| eeecc49ce8 | |||
| 175a834574 | |||
| ec6fa2c516 | |||
| 7ee27d6891 | |||
| 2568a3657f | |||
| 150573c742 | |||
| 7ec556d209 | |||
| 6259630f00 | |||
| a262194af8 | |||
| fb8f48a10d | |||
| b30c22780e | |||
| 0d593c60d3 | |||
| 555b608116 | |||
| 3c3dad1eb2 | |||
| 7bfa02cd23 | |||
| 1f16f4b5a3 | |||
| 553dc94b76 | |||
| b6a6bd0a11 | |||
| d0214e4e9d | |||
| ee412d296a | |||
| e06540f3d7 | |||
| 7fbeb40965 | |||
| b32e3cd601 | |||
| cfcca2e43e | |||
| 80d2c3a4e9 | |||
| aaeae0e217 | |||
| d78b5e4ab6 | |||
| 2bbf3ab5e5 | |||
| 2bd9128689 | |||
| 24daea45ab | |||
| 382c196379 | |||
| 586ec41c26 | |||
| 11a278eebf | |||
| 69ad84b06b | |||
| 13ee7c9eec | |||
| 1bdb299566 | |||
| 4706da4453 | |||
| 44c8d4718a | |||
| 9b393ad4fb | |||
| 67858837d1 | |||
| 9f8624a722 | |||
| 0f196a52cf | |||
| 8885be7e55 | |||
| ae677d6481 | |||
| 6aafb8184f | |||
| bd0a8bfd38 | |||
| 300ebb86fd | |||
| 3cfa437460 | |||
| f5abf20f4b | |||
| 2eb209b2a8 | |||
| ccfe2690f4 | |||
| 46db68699c | |||
| 4d0ea1afda | |||
| a1b6da1773 | |||
| 3093a440dd | |||
| 574d532df7 | |||
| 87cae74434 | |||
| fda0b13fe5 | |||
| 1c67efc485 | |||
| 9571c52d70 | |||
| faceb864b8 | |||
| cf0e55b6e4 | |||
| cfe1b4ef3d | |||
| 3254aef5e5 | |||
| 7a5d712d79 | |||
| 550e141c59 | |||
| 972814622f | |||
| c7f24da4f7 | |||
| f291ed217c | |||
| bd5fbc30eb | |||
| 81345af180 | |||
| 649005a917 | |||
| 1e6634ca93 | |||
| ddf9030b9a | |||
| 532ddd2c3d | |||
| 7035578605 | |||
| 91d5e578d8 | |||
| 2afdebd228 | |||
| 615b3874b8 | |||
| a6ec9f968a | |||
| 03ddcb9bad | |||
| 7dcb78c629 | |||
| c0162e1ea6 | |||
| 02cf882d36 | |||
| cb55b73522 | |||
| 0f6e4604ff | |||
| 31244992db | |||
| 56bad95cf7 | |||
| d5a8fcb6a2 | |||
| 27002370dd | |||
| 9bc3f25281 | |||
| 8a7c45c20b | |||
| 73fa7a6bb2 | |||
| 21e37780fa | |||
| 543c230f33 | |||
| 968d3f6ec4 | |||
| 0c45d26a28 | |||
| 811b85e1b1 | |||
| 759d1826c8 | |||
| 60a1829acf | |||
| 8ba3ed99a1 | |||
| 0af0e20d15 | |||
| 2def6c4f21 | |||
| d403eb88c8 | |||
| 18b2deca85 | |||
| bd91eb4cca | |||
| fe829f2d8a | |||
| 5650b79dcd | |||
| 9908930bc5 | |||
| b256013c5e | |||
| 927ca1bec0 | |||
| e1c6851492 | |||
| e0a61d484e | |||
| 431c5c678a | |||
| 3a07201a3f | |||
| 11dfb9c668 | |||
| 27e89dd05e | |||
| 237c02dade | |||
| 5ee470d7e4 | |||
| 79ee5b8419 | |||
| fba3bc22a2 | |||
| 01536c4a67 | |||
| 7a32429bd2 | |||
| dbb2f4964c | |||
| 2817da62db | |||
| ee3ae84e64 | |||
| 0cdc742538 |
@@ -0,0 +1,42 @@
|
||||
---
|
||||
# Continuous Integration Workflow: Test case suite run + validation build check
|
||||
name: CI
|
||||
|
||||
# Controls when the action will run.
|
||||
# Triggers the workflow on push or pull request events but only for the master branch
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
# Job: Unit test suite
|
||||
unit-tests:
|
||||
name: "Unit Tests"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Install Multilib
|
||||
- name: Install Multilib
|
||||
run: |
|
||||
sudo apt-get update --assume-yes
|
||||
sudo apt-get install --assume-yes --quiet gcc-multilib
|
||||
|
||||
# Checks out repository under $GITHUB_WORKSPACE
|
||||
- name: Checkout Latest Repo
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
# Install Ruby Testing Tools
|
||||
- name: Setup Ruby Testing Tools
|
||||
run: |
|
||||
sudo gem install bundler
|
||||
sudo gem install rspec
|
||||
sudo gem install rubocop -v 0.57.2
|
||||
bundle install
|
||||
|
||||
# Run Tests
|
||||
- name: Run All Unit Tests
|
||||
run: |
|
||||
cd test && rake ci
|
||||
@@ -1,8 +1,10 @@
|
||||
test/system/build
|
||||
test/system/generated
|
||||
*.sublime-project
|
||||
*.sublime-workspace
|
||||
Gemfile.lock
|
||||
.rake_t_cache
|
||||
.DS_Store
|
||||
*.swp
|
||||
examples/make_example/build
|
||||
examples/temp_sensor/build
|
||||
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
language: ruby
|
||||
|
||||
os:
|
||||
- linux
|
||||
|
||||
rvm:
|
||||
- "2.3"
|
||||
- "2.4"
|
||||
- "2.6"
|
||||
|
||||
before_install:
|
||||
- sudo apt-get install --assume-yes --quiet gcc-multilib
|
||||
|
||||
install:
|
||||
- bundle install
|
||||
- gem install rspec
|
||||
- gem install rubocop -v 0.57.2
|
||||
|
||||
script:
|
||||
- cd test && rake ci
|
||||
- cd ..
|
||||
- cd examples && cd make_example
|
||||
- make clean
|
||||
- make setup
|
||||
- make test
|
||||
- cd ..
|
||||
- cd temp_sensor
|
||||
- rake ci
|
||||
@@ -1,8 +1,7 @@
|
||||
source "http://rubygems.org/"
|
||||
|
||||
gem "bundler", "~> 1.1.rc.7"
|
||||
gem "rake", ">= 0.9.2.2"
|
||||
|
||||
gem "bundler"
|
||||
gem "rake"
|
||||
gem "minitest"
|
||||
gem "require_all"
|
||||
gem "constructor"
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
CMock - Mock/stub generator for C
|
||||
=================================
|
||||
CMock 
|
||||
=====
|
||||
CMock is a mock and stub generator and runtime for unit testing C. It's been designed
|
||||
to work smoothly with Unity Test, another of the embedded-software testing tools
|
||||
developed by ThrowTheSwitch.org. CMock automagically parses your C headers and creates
|
||||
useful and usable mock interfaces for unit testing. Give it a try!
|
||||
|
||||
[](https://travis-ci.org/ThrowTheSwitch/CMock)
|
||||
If you don't care to manage unit testing builds yourself, consider checking out Ceedling,
|
||||
a test-centered build manager for unit testing C code.
|
||||
|
||||
Getting Started
|
||||
================
|
||||
|
||||
@@ -2,13 +2,11 @@
|
||||
# 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]
|
||||
# ==========================================
|
||||
|
||||
# ==========================================
|
||||
|
||||
# Setup our load path:
|
||||
[
|
||||
'lib',
|
||||
[
|
||||
'lib'
|
||||
].each do |dir|
|
||||
$LOAD_PATH.unshift( File.join( File.expand_path(File.dirname(__FILE__)) + '/../', dir) )
|
||||
$:.unshift(File.join(__dir__ + '/../', dir))
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -12,5 +12,5 @@
|
||||
'./vendor/unity/auto/',
|
||||
'./test/system/'
|
||||
].each do |dir|
|
||||
$LOAD_PATH.unshift( File.join( File.expand_path(File.dirname(__FILE__) + "/../"), dir) )
|
||||
$:.unshift(File.join(File.expand_path(File.dirname(__FILE__) + '/../'), dir))
|
||||
end
|
||||
|
||||
+152
-10
@@ -161,6 +161,35 @@ care how many times it was called, right?
|
||||
* `retval func(void)` => `void func_IgnoreAndReturn(retval_to_return)`
|
||||
* `retval func(params)` => `void func_IgnoreAndReturn(retval_to_return)`
|
||||
|
||||
StopIgnore:
|
||||
-------
|
||||
|
||||
Maybe you want to ignore a particular function for part of a test but dont want to
|
||||
ignore it later on. In that case, you want to use StopIgnore which will cancel the
|
||||
previously called Ignore or IgnoreAndReturn requiring you to Expect or otherwise
|
||||
handle the call to a function.
|
||||
|
||||
* `void func(void)` => `void func_StopIgnore(void)`
|
||||
* `void func(params)` => `void func_StopIgnore(void)`
|
||||
* `retval func(void)` => `void func_StopIgnore(void)`
|
||||
* `retval func(params)` => `void func_StopIgnore(void)`
|
||||
|
||||
IgnoreStateless:
|
||||
----------------
|
||||
|
||||
This plugin is similar to the Ignore plugin, but the IgnoreAndReturn functions are
|
||||
stateless. So the Ignored function will always return the last specified return value
|
||||
and does not queue the return values as the IgnoreAndReturn of the default plugin will.
|
||||
|
||||
To stop ignoring a function you can call StopIgnore or simply overwrite the Ignore
|
||||
(resp. IgnoreAndReturn) with an Expect (resp. ExpectAndReturn). Note that calling
|
||||
Ignore (resp IgnoreAndReturn) will clear your previous called Expect
|
||||
(resp. ExpectAndReturn), so they are not restored after StopIgnore is called.
|
||||
|
||||
You can use this plugin by using `:ignore_stateless` instead of `:ignore` in your
|
||||
CMock configuration file.
|
||||
|
||||
The generated functions are the same as **Ignore** and **StopIgnore** above.
|
||||
|
||||
Ignore Arg:
|
||||
------------
|
||||
@@ -282,6 +311,22 @@ You may specify the options explicitly:
|
||||
|
||||
cmock = Cmock.new(:plugins => [:cexception, :ignore], :mock_path => 'my/mocks/')
|
||||
|
||||
Creating Skeletons:
|
||||
-------------------
|
||||
|
||||
Not only is CMock able to generate mock files from a header file, but it is also able
|
||||
to generate (and update) skeleton C files from headers. It does this by creating a
|
||||
(mostly) empty implementation for every function that is declared in the header. If you later
|
||||
add to that header list, just run this feature again and it will add prototypes for the missing
|
||||
functions!
|
||||
|
||||
Like the normal usecase for CMock, this feature can be used from the command line
|
||||
or from within its ruby API. For example, from the command line, add `--skeleton` to
|
||||
generate a skeleton instead:
|
||||
|
||||
```
|
||||
ruby cmock.rb --skeleton ../create/c/for/this.h
|
||||
```
|
||||
|
||||
Config Options:
|
||||
---------------
|
||||
@@ -394,14 +439,14 @@ from the defaults. We've tried to specify what the defaults are below.
|
||||
* default: mocks
|
||||
|
||||
* `:mock_prefix`:
|
||||
The prefix to prepend to your mock files. For example, if it's “Mock”, a file
|
||||
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
|
||||
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.
|
||||
|
||||
@@ -412,6 +457,7 @@ from the defaults. We've tried to specify what the defaults are below.
|
||||
available currently:
|
||||
|
||||
* `:ignore`
|
||||
* `:ignore_stateless`
|
||||
* `:ignore_arg`
|
||||
* `:expect_any_args`
|
||||
* `:array`
|
||||
@@ -429,7 +475,14 @@ from the defaults. We've tried to specify what the defaults are below.
|
||||
to prevent a function `functionName` from being mocked. By default, it
|
||||
is ignoring all gcc attribute extensions.
|
||||
|
||||
* default: ['(?:__attribute__\s*\(+.*?\)+)']
|
||||
* default: `['(?:__attribute__\s*\(+.*?\)+)']`
|
||||
|
||||
* `:exclude_setjmp_h`:
|
||||
Some embedded systems don't have <setjmp.h> available. Setting this to true
|
||||
removes references to this header file and the ability to use cexception.
|
||||
|
||||
* default: false
|
||||
|
||||
|
||||
* `:subdir`:
|
||||
This is a relative subdirectory for your mocks. Set this to e.g. "sys" in
|
||||
@@ -518,6 +571,45 @@ from the defaults. We've tried to specify what the defaults are below.
|
||||
* `:include` will mock externed functions
|
||||
* `:exclude` will ignore externed functions (default).
|
||||
|
||||
* `:treat_inlines`:
|
||||
This specifies how you want CMock to handle functions that have been
|
||||
marked as inline in the header file. Should it mock them?
|
||||
|
||||
* `:include` will mock inlined functions
|
||||
* `:exclude` will ignore inlined functions (default).
|
||||
|
||||
CMock will look for the following default patterns (simplified from the actual regex):
|
||||
- "static inline"
|
||||
- "inline static"
|
||||
- "inline"
|
||||
- "static"
|
||||
You can override these patterns, check out :inline_function_patterns.
|
||||
|
||||
Enabling this feature does require a change in the build system that
|
||||
is using CMock. To understand why, we need to give some more info
|
||||
on how we are handling inline functions internally.
|
||||
Let's say we want to mock a header called example.h. example.h
|
||||
contains inline functions, we cannot include this header in the
|
||||
mocks or test code if we want to mock the inline functions simply
|
||||
because the inline functions contain an implementation that we want
|
||||
to override in our mocks!
|
||||
So, to circumvent this, we generate a new header, also named
|
||||
example.h, in the same directory as mock_example.h/c . This newly
|
||||
generated header should/is exactly the same as the original header,
|
||||
only difference is the inline functions are transformed to 'normal'
|
||||
functions declarations. Placing the new header in the same
|
||||
directory as mock_example.h/c ensures that they will include the new
|
||||
header and not the old one.
|
||||
However, CMock has no control in how the build system is configured
|
||||
and which include paths the test code is compiled with. In order
|
||||
for the test code to also see the newly generated header ,and not
|
||||
the old header with inline functions, the build system has to add
|
||||
the mock folder to the include paths.
|
||||
Furthermore, we need to keep the order of include paths in mind. We
|
||||
have to set the mock folder before the other includes to avoid the
|
||||
test code including the original header instead of the newly
|
||||
generated header (without inline functions).
|
||||
|
||||
* `:unity_helper_path`:
|
||||
If you have created a header with your own extensions to unity to
|
||||
handle your own types, you can set this argument to that path. CMock
|
||||
@@ -598,8 +690,8 @@ from the defaults. We've tried to specify what the defaults are below.
|
||||
Parameters must match *both* `:array_size_type` and `:array_size_name` (and
|
||||
must come right after a pointer parameter) to be treated as an array size.
|
||||
|
||||
Once you've told it how to recognize your arrays, CMock will give you _Expect
|
||||
calls that work more like _ExpectWithArray, and compare an array of objects
|
||||
Once you've told it how to recognize your arrays, CMock will give you `_Expect`
|
||||
calls that work more like `_ExpectWithArray`, and compare an array of objects
|
||||
rather than just a single object.
|
||||
|
||||
For example, if you write the following, CMock will check that GoBananas is
|
||||
@@ -614,20 +706,35 @@ from the defaults. We've tried to specify what the defaults are below.
|
||||
GoBananas_ExpectWithArray(b, 2, 2);
|
||||
|
||||
* `:fail_on_unexpected_calls`:
|
||||
By default, CMock will fail a test if a mock is called without _Expect and _Ignore
|
||||
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
|
||||
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.
|
||||
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).
|
||||
|
||||
* `:inline_function_patterns`:
|
||||
An array containing a list of strings to detect inline functions.
|
||||
This option is only taken into account if you enable :treat_inlines.
|
||||
These strings are interpreted as regex patterns so be sure to escape
|
||||
certain characters. For example, use `:inline_function_patterns: ['static inline __attribute__ \(\(always_inline\)\)']`
|
||||
to recognize `static inline __attribute__ ((always_inline)) int my_func(void)`
|
||||
as an inline function.
|
||||
The default patterns are are:
|
||||
|
||||
* default: ['(static\s+inline|inline\s+static)\s*', '(\bstatic\b|\binline\b)\s*']
|
||||
* **note:**
|
||||
The order of patterns is important here!
|
||||
We go from specific patterns ('static inline') to general patterns ('inline'),
|
||||
otherwise we would miss functions that use 'static inline' iso 'inline'.
|
||||
|
||||
|
||||
Compiled Options:
|
||||
-----------------
|
||||
@@ -662,7 +769,7 @@ based on other settings, particularly Unity's settings.
|
||||
|
||||
* `CMOCK_MEM_INDEX_TYPE`
|
||||
This needs to be something big enough to point anywhere in Cmock's
|
||||
memory space... usually it's an unsigned int.
|
||||
memory space... usually it's a size_t.
|
||||
|
||||
Other Tips
|
||||
==========
|
||||
@@ -678,6 +785,42 @@ themselves. Call it during a test to have CMock validate everything to this poin
|
||||
and start over clean. This is really useful when wanting to test a function in
|
||||
an iterative manner with different arguments.
|
||||
|
||||
C++ Support
|
||||
---------
|
||||
C++ unit test/mocking frameworks often use a completely different approach (vs.
|
||||
CMock) that relies on overloading virtual class members and does not support
|
||||
directly mocking static class member methods or free functions (i.e., functions
|
||||
in plain C). One workaround is to wrap the non-virtual functions in an object
|
||||
that exposes them as virtual methods and modify your code to inject mocks at
|
||||
run-time... but there is another way!
|
||||
|
||||
Simply use CMock to mock the static member methods and a C++ mocking framework
|
||||
to handle the virtual methods. (Yes, you can mix mocks from CMock and a C++
|
||||
mocking framework together in the same test!)
|
||||
|
||||
Keep in mind that since C++ mocking frameworks often link the real object to the
|
||||
unit test too, we need to resolve multiple definition errors with something like
|
||||
the following in the source of the real implementation for any functions that
|
||||
CMock mocks:
|
||||
|
||||
#if defined(TEST)
|
||||
__attribute__((weak))
|
||||
#endif
|
||||
|
||||
To address potential issues with re-using the same function name in different
|
||||
namespaces/classes, the generated function names include the namespace(s) and
|
||||
class. For example:
|
||||
|
||||
namespace MyNamespace {
|
||||
class MyClass {
|
||||
static int DoesSomething(int a, int b);
|
||||
};
|
||||
}
|
||||
|
||||
Will generate functions like
|
||||
|
||||
void MyNamespace_MyClass_DoesSomething_ExpectAndReturn(int a, int b, int toReturn);
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
@@ -686,4 +829,3 @@ 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
|
||||
failing tests ON PURPOSE to show what that would look like. Don't be alarmed. ;)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
HERE = File.expand_path(File.dirname(__FILE__)) + '/'
|
||||
HERE = __dir__ + '/'
|
||||
|
||||
require 'rake'
|
||||
require 'rake/clean'
|
||||
@@ -7,36 +7,36 @@ require './rakefile_helper'
|
||||
|
||||
include RakefileHelpers
|
||||
|
||||
REQUIRED_DIRS = [ './build', './build/mocks' ]
|
||||
REQUIRED_DIRS = ['./build', './build/mocks'].freeze
|
||||
REQUIRED_DIRS.each do |v|
|
||||
directory v
|
||||
end
|
||||
|
||||
# Load default configuration, for now
|
||||
DEFAULT_CONFIG_FILE = 'gcc.yml'
|
||||
DEFAULT_CONFIG_FILE = 'gcc.yml'.freeze
|
||||
configure_toolchain(DEFAULT_CONFIG_FILE)
|
||||
|
||||
task :unit do
|
||||
run_tests(get_unit_test_files)
|
||||
run_tests(unit_test_files)
|
||||
end
|
||||
|
||||
desc "Generate test summary"
|
||||
desc 'Generate test summary'
|
||||
task :summary do
|
||||
report_summary
|
||||
end
|
||||
|
||||
desc "Build and test Unity"
|
||||
task :all => [:clean, :unit, :summary]
|
||||
task :default => REQUIRED_DIRS + [:clobber, :all]
|
||||
desc 'Build and test Unity'
|
||||
task :all => %i[clean unit summary]
|
||||
task :default => REQUIRED_DIRS + %i[clobber all]
|
||||
task :ci => [:default]
|
||||
task :cruise => [:default]
|
||||
|
||||
desc "Load configuration"
|
||||
task :config, :config_file do |t, args|
|
||||
desc 'Load configuration'
|
||||
task :config, :config_file do |_t, args|
|
||||
configure_toolchain(args[:config_file])
|
||||
end
|
||||
|
||||
desc "Return error on Failures"
|
||||
desc 'Return error on Failures'
|
||||
task :strict do
|
||||
$return_error_on_failures = true
|
||||
end
|
||||
|
||||
@@ -5,10 +5,9 @@ require '../../vendor/unity/auto/generate_test_runner'
|
||||
require '../../vendor/unity/auto/colour_reporter'
|
||||
|
||||
module RakefileHelpers
|
||||
|
||||
$return_error_on_failures = false
|
||||
|
||||
C_EXTENSION = '.c'
|
||||
C_EXTENSION = '.c'.freeze
|
||||
|
||||
def load_configuration(config_file)
|
||||
$cfg_file = config_file
|
||||
@@ -20,22 +19,22 @@ module RakefileHelpers
|
||||
CLEAN.include($cfg['compiler']['build_path'] + '*.*') unless $cfg['compiler']['build_path'].nil?
|
||||
end
|
||||
|
||||
def configure_toolchain(config_file=DEFAULT_CONFIG_FILE)
|
||||
def configure_toolchain(config_file = DEFAULT_CONFIG_FILE)
|
||||
config_file += '.yml' unless config_file =~ /\.yml$/
|
||||
load_configuration(config_file)
|
||||
configure_clean
|
||||
end
|
||||
|
||||
def get_unit_test_files
|
||||
def unit_test_files
|
||||
path = $cfg['compiler']['unit_tests_path'] + 'Test*' + C_EXTENSION
|
||||
path.gsub!(/\\/, '/')
|
||||
path.tr!('\\', '/')
|
||||
FileList.new(path)
|
||||
end
|
||||
|
||||
def get_local_include_dirs
|
||||
def local_include_dirs
|
||||
include_dirs = $cfg['compiler']['includes']['items'].dup
|
||||
include_dirs.delete_if {|dir| dir.is_a?(Array)}
|
||||
return include_dirs
|
||||
include_dirs.delete_if { |dir| dir.is_a?(Array) }
|
||||
include_dirs
|
||||
end
|
||||
|
||||
def extract_headers(filename)
|
||||
@@ -43,133 +42,134 @@ module RakefileHelpers
|
||||
lines = File.readlines(filename)
|
||||
lines.each do |line|
|
||||
m = line.match(/^\s*#include\s+\"\s*(.+\.[hH])\s*\"/)
|
||||
if not m.nil?
|
||||
unless m.nil?
|
||||
includes << m[1]
|
||||
end
|
||||
end
|
||||
return includes
|
||||
includes
|
||||
end
|
||||
|
||||
def find_source_file(header, paths)
|
||||
paths.each do |dir|
|
||||
src_file = dir + header.ext(C_EXTENSION)
|
||||
if (File.exists?(src_file))
|
||||
if File.exist?(src_file)
|
||||
return src_file
|
||||
end
|
||||
end
|
||||
return nil
|
||||
nil
|
||||
end
|
||||
|
||||
def tackit(strings)
|
||||
case(strings)
|
||||
when Array
|
||||
"\"#{strings.join}\""
|
||||
when /^-/
|
||||
strings
|
||||
when /\s/
|
||||
"\"#{strings}\""
|
||||
else
|
||||
strings
|
||||
case strings
|
||||
when Array
|
||||
"\"#{strings.join}\""
|
||||
when /^-/
|
||||
strings
|
||||
when /\s/
|
||||
"\"#{strings}\""
|
||||
else
|
||||
strings
|
||||
end
|
||||
end
|
||||
|
||||
def squash(prefix, items)
|
||||
result = ''
|
||||
items.each { |item| result += " #{prefix}#{tackit(item)}" }
|
||||
return result
|
||||
result
|
||||
end
|
||||
|
||||
def build_compiler_fields
|
||||
command = tackit($cfg['compiler']['path'])
|
||||
if $cfg['compiler']['defines']['items'].nil?
|
||||
defines = ''
|
||||
else
|
||||
defines = squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items'])
|
||||
end
|
||||
options = squash('', $cfg['compiler']['options'])
|
||||
command = tackit($cfg['compiler']['path'])
|
||||
defines = if $cfg['compiler']['defines']['items'].nil?
|
||||
''
|
||||
else
|
||||
squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items'])
|
||||
end
|
||||
options = squash('', $cfg['compiler']['options'])
|
||||
includes = squash($cfg['compiler']['includes']['prefix'], $cfg['compiler']['includes']['items'])
|
||||
includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR)
|
||||
return {:command => command, :defines => defines, :options => options, :includes => includes}
|
||||
{ :command => command, :defines => defines, :options => options, :includes => includes }
|
||||
end
|
||||
|
||||
def compile(file, defines=[])
|
||||
def compile(file, _defines = [])
|
||||
compiler = build_compiler_fields
|
||||
cmd_str = "#{compiler[:command]}#{compiler[:defines]}#{compiler[:options]}#{compiler[:includes]} #{file} " +
|
||||
cmd_str = "#{compiler[:command]}#{compiler[:defines]}#{compiler[:options]}#{compiler[:includes]} #{file} " \
|
||||
"#{$cfg['compiler']['object_files']['prefix']}#{$cfg['compiler']['object_files']['destination']}"
|
||||
obj_file = "#{File.basename(file, C_EXTENSION)}#{$cfg['compiler']['object_files']['extension']}"
|
||||
execute(cmd_str + obj_file)
|
||||
return obj_file
|
||||
obj_file
|
||||
end
|
||||
|
||||
def build_linker_fields
|
||||
command = tackit($cfg['linker']['path'])
|
||||
if $cfg['linker']['options'].nil?
|
||||
options = ''
|
||||
else
|
||||
options = squash('', $cfg['linker']['options'])
|
||||
end
|
||||
if ($cfg['linker']['includes'].nil? || $cfg['linker']['includes']['items'].nil?)
|
||||
includes = ''
|
||||
else
|
||||
includes = squash($cfg['linker']['includes']['prefix'], $cfg['linker']['includes']['items'])
|
||||
end
|
||||
command = tackit($cfg['linker']['path'])
|
||||
options = if $cfg['linker']['options'].nil?
|
||||
''
|
||||
else
|
||||
squash('', $cfg['linker']['options'])
|
||||
end
|
||||
includes = if $cfg['linker']['includes'].nil? || $cfg['linker']['includes']['items'].nil?
|
||||
''
|
||||
else
|
||||
squash($cfg['linker']['includes']['prefix'], $cfg['linker']['includes']['items'])
|
||||
end
|
||||
includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR)
|
||||
return {:command => command, :options => options, :includes => includes}
|
||||
{ :command => command, :options => options, :includes => includes }
|
||||
end
|
||||
|
||||
def link_it(exe_name, obj_list)
|
||||
linker = build_linker_fields
|
||||
cmd_str = "#{linker[:command]}#{linker[:includes]} " +
|
||||
(obj_list.map{|obj|"#{$cfg['linker']['object_files']['path']}#{obj} "}).join +
|
||||
$cfg['linker']['bin_files']['prefix'] + ' ' +
|
||||
$cfg['linker']['bin_files']['destination'] +
|
||||
exe_name + $cfg['linker']['bin_files']['extension'] + " #{linker[:options]}"
|
||||
(obj_list.map { |obj| "#{$cfg['linker']['object_files']['path']}#{obj} " }).join +
|
||||
$cfg['linker']['bin_files']['prefix'] + ' ' +
|
||||
$cfg['linker']['bin_files']['destination'] +
|
||||
exe_name + $cfg['linker']['bin_files']['extension'] + " #{linker[:options]}"
|
||||
execute(cmd_str)
|
||||
end
|
||||
|
||||
def build_simulator_fields
|
||||
return nil if $cfg['simulator'].nil?
|
||||
if $cfg['simulator']['path'].nil?
|
||||
command = ''
|
||||
else
|
||||
command = (tackit($cfg['simulator']['path']) + ' ')
|
||||
end
|
||||
if $cfg['simulator']['pre_support'].nil?
|
||||
pre_support = ''
|
||||
else
|
||||
pre_support = squash('', $cfg['simulator']['pre_support'])
|
||||
end
|
||||
if $cfg['simulator']['post_support'].nil?
|
||||
post_support = ''
|
||||
else
|
||||
post_support = squash('', $cfg['simulator']['post_support'])
|
||||
end
|
||||
return {:command => command, :pre_support => pre_support, :post_support => post_support}
|
||||
|
||||
command = if $cfg['simulator']['path'].nil?
|
||||
''
|
||||
else
|
||||
(tackit($cfg['simulator']['path']) + ' ')
|
||||
end
|
||||
pre_support = if $cfg['simulator']['pre_support'].nil?
|
||||
''
|
||||
else
|
||||
squash('', $cfg['simulator']['pre_support'])
|
||||
end
|
||||
post_support = if $cfg['simulator']['post_support'].nil?
|
||||
''
|
||||
else
|
||||
squash('', $cfg['simulator']['post_support'])
|
||||
end
|
||||
{ :command => command, :pre_support => pre_support, :post_support => post_support }
|
||||
end
|
||||
|
||||
def execute(command_string, verbose=true, ok_to_fail=false)
|
||||
def execute(command_string, verbose = true, ok_to_fail = false)
|
||||
report command_string
|
||||
output = `#{command_string}`.chomp
|
||||
report(output) if (verbose && !output.nil? && (output.length > 0))
|
||||
report(output) if verbose && !output.nil? && !output.empty?
|
||||
unless (!$?.nil? && $?.exitstatus.zero?) || ok_to_fail
|
||||
raise "Command failed. (Returned #{$?.exitstatus})"
|
||||
end
|
||||
return output
|
||||
|
||||
output
|
||||
end
|
||||
|
||||
def report_summary
|
||||
summary = UnityTestSummary.new
|
||||
summary.root = HERE
|
||||
results_glob = "#{$cfg['compiler']['build_path']}*.test*"
|
||||
results_glob.gsub!(/\\/, '/')
|
||||
results_glob.tr!('\\', '/')
|
||||
results = Dir[results_glob]
|
||||
summary.targets = results
|
||||
report summary.run
|
||||
raise "There were failures" if (summary.failures > 0) && $return_error_on_failures
|
||||
raise 'There were failures' if (summary.failures > 0) && $return_error_on_failures
|
||||
end
|
||||
|
||||
def run_tests(test_files)
|
||||
|
||||
report 'Running system tests...'
|
||||
|
||||
# Tack on TEST define for compiling unit tests
|
||||
@@ -178,30 +178,28 @@ module RakefileHelpers
|
||||
$cfg['compiler']['defines']['items'] = [] if $cfg['compiler']['defines']['items'].nil?
|
||||
$cfg['compiler']['defines']['items'] << 'TEST'
|
||||
|
||||
include_dirs = get_local_include_dirs
|
||||
include_dirs = local_include_dirs
|
||||
|
||||
# Build and execute each unit test
|
||||
test_files.each do |test|
|
||||
obj_list = []
|
||||
|
||||
# Detect dependencies and build required required modules
|
||||
header_list = (extract_headers(test) + ['cmock.h'] + [ $cfg[:cmock][:unity_helper_path] ]).compact.uniq
|
||||
header_list = (extract_headers(test) + ['cmock.h'] + [$cfg[:cmock][:unity_helper_path]]).compact.uniq
|
||||
header_list.each do |header|
|
||||
# create mocks if needed
|
||||
next unless header =~ /Mock/
|
||||
|
||||
#create mocks if needed
|
||||
if (header =~ /Mock/)
|
||||
require "../../lib/cmock.rb"
|
||||
@cmock ||= CMock.new($cfg_file)
|
||||
@cmock.setup_mocks([$cfg['compiler']['source_path']+header.gsub('Mock','')])
|
||||
end
|
||||
|
||||
require '../../lib/cmock.rb'
|
||||
@cmock ||= CMock.new($cfg_file)
|
||||
@cmock.setup_mocks([$cfg['compiler']['source_path'] + header.gsub('Mock', '')])
|
||||
end
|
||||
|
||||
#compile all mocks
|
||||
# compile all mocks
|
||||
header_list.each do |header|
|
||||
#compile source file header if it exists
|
||||
# compile source file header if it exists
|
||||
src_file = find_source_file(header, include_dirs)
|
||||
if !src_file.nil?
|
||||
unless src_file.nil?
|
||||
obj_list << compile(src_file, test_defines)
|
||||
end
|
||||
end
|
||||
@@ -228,35 +226,34 @@ module RakefileHelpers
|
||||
# Execute unit test and generate results file
|
||||
simulator = build_simulator_fields
|
||||
executable = $cfg['linker']['bin_files']['destination'] + test_base + $cfg['linker']['bin_files']['extension']
|
||||
if simulator.nil?
|
||||
cmd_str = executable
|
||||
else
|
||||
cmd_str = "#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}"
|
||||
end
|
||||
cmd_str = if simulator.nil?
|
||||
executable
|
||||
else
|
||||
"#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}"
|
||||
end
|
||||
output = execute(cmd_str, true, true)
|
||||
test_results = $cfg['compiler']['build_path'] + test_base
|
||||
if output.match(/OK$/m).nil?
|
||||
test_results += '.testfail'
|
||||
else
|
||||
test_results += '.testpass'
|
||||
end
|
||||
test_results += if output.match(/OK$/m).nil?
|
||||
'.testfail'
|
||||
else
|
||||
'.testpass'
|
||||
end
|
||||
File.open(test_results, 'w') { |f| f.print output }
|
||||
end
|
||||
end
|
||||
|
||||
def build_application(main)
|
||||
|
||||
report "Building application..."
|
||||
report 'Building application...'
|
||||
|
||||
obj_list = []
|
||||
load_configuration($cfg_file)
|
||||
main_path = $cfg['compiler']['source_path'] + main + C_EXTENSION
|
||||
|
||||
# Detect dependencies and build required required modules
|
||||
include_dirs = get_local_include_dirs
|
||||
include_dirs = local_include_dirs
|
||||
extract_headers(main_path).each do |header|
|
||||
src_file = find_source_file(header, include_dirs)
|
||||
if !src_file.nil?
|
||||
unless src_file.nil?
|
||||
obj_list << compile(src_file)
|
||||
end
|
||||
end
|
||||
@@ -268,5 +265,4 @@ module RakefileHelpers
|
||||
# Create the executable
|
||||
link_it(main_base, obj_list)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
+53
-28
@@ -4,49 +4,63 @@
|
||||
# [Released under MIT License. Please refer to license.txt for details]
|
||||
# ==========================================
|
||||
|
||||
[ "../config/production_environment",
|
||||
"cmock_header_parser",
|
||||
"cmock_generator",
|
||||
"cmock_file_writer",
|
||||
"cmock_config",
|
||||
"cmock_plugin_manager",
|
||||
"cmock_generator_utils",
|
||||
"cmock_unityhelper_parser"].each {|req| require "#{File.expand_path(File.dirname(__FILE__))}/#{req}"}
|
||||
['../config/production_environment',
|
||||
'cmock_header_parser',
|
||||
'cmock_generator',
|
||||
'cmock_file_writer',
|
||||
'cmock_config',
|
||||
'cmock_plugin_manager',
|
||||
'cmock_generator_utils',
|
||||
'cmock_unityhelper_parser'].each { |req| require "#{__dir__}/#{req}" }
|
||||
|
||||
class CMock
|
||||
|
||||
def initialize(options=nil)
|
||||
def initialize(options = nil)
|
||||
cm_config = CMockConfig.new(options)
|
||||
cm_unityhelper = CMockUnityHelperParser.new(cm_config)
|
||||
cm_writer = CMockFileWriter.new(cm_config)
|
||||
cm_gen_utils = CMockGeneratorUtils.new(cm_config, {:unity_helper => cm_unityhelper})
|
||||
cm_gen_utils = CMockGeneratorUtils.new(cm_config,
|
||||
:unity_helper => cm_unityhelper)
|
||||
cm_gen_plugins = CMockPluginManager.new(cm_config, cm_gen_utils)
|
||||
@cm_parser = CMockHeaderParser.new(cm_config)
|
||||
@cm_generator = CMockGenerator.new(cm_config, cm_writer, cm_gen_utils, cm_gen_plugins)
|
||||
@cm_generator = CMockGenerator.new(cm_config, cm_writer, cm_gen_utils,
|
||||
cm_gen_plugins)
|
||||
@silent = (cm_config.verbosity < 2)
|
||||
end
|
||||
|
||||
def setup_mocks(files)
|
||||
def setup_mocks(files, folder = nil)
|
||||
[files].flatten.each do |src|
|
||||
generate_mock src
|
||||
generate_mock(src, folder)
|
||||
end
|
||||
end
|
||||
|
||||
def setup_skeletons(files)
|
||||
[files].flatten.each do |src|
|
||||
generate_skeleton src
|
||||
end
|
||||
end
|
||||
|
||||
private ###############################
|
||||
|
||||
def generate_mock(src)
|
||||
name = File.basename(src, '.h')
|
||||
def generate_mock(src, folder)
|
||||
name = File.basename(src, '.*')
|
||||
ext = File.extname(src)
|
||||
puts "Creating mock for #{name}..." unless @silent
|
||||
@cm_generator.create_mock(name, @cm_parser.parse(name, File.read(src)))
|
||||
@cm_generator.create_mock(name, @cm_parser.parse(name, File.read(src)), ext, folder)
|
||||
end
|
||||
|
||||
def generate_skeleton(src)
|
||||
name = File.basename(src, '.*')
|
||||
puts "Creating skeleton for #{name}..." unless @silent
|
||||
@cm_generator.create_skeleton(name, @cm_parser.parse(name, File.read(src)))
|
||||
end
|
||||
end
|
||||
|
||||
def option_maker(options, key, val)
|
||||
options = options || {}
|
||||
options ||= {}
|
||||
options[key.to_sym] =
|
||||
if val.chr == ":"
|
||||
if val.chr == ':'
|
||||
val[1..-1].to_sym
|
||||
elsif val.include? ";"
|
||||
elsif val.include? ';'
|
||||
val.split(';')
|
||||
elsif val == 'true'
|
||||
true
|
||||
@@ -60,12 +74,12 @@ def option_maker(options, key, val)
|
||||
options
|
||||
end
|
||||
|
||||
# Command Line Support ###############################
|
||||
# Command Line Support ###############################
|
||||
|
||||
if ($0 == __FILE__)
|
||||
if $0 == __FILE__
|
||||
usage = "usage: ruby #{__FILE__} (-oOptionsFile) File(s)ToMock"
|
||||
|
||||
if (!ARGV[0])
|
||||
unless ARGV[0]
|
||||
puts usage
|
||||
exit 1
|
||||
end
|
||||
@@ -73,14 +87,25 @@ if ($0 == __FILE__)
|
||||
options = {}
|
||||
filelist = []
|
||||
ARGV.each do |arg|
|
||||
if (arg =~ /^-o\"?([a-zA-Z0-9._\\\/:\s]+)\"?/)
|
||||
options.merge! CMockConfig.load_config_file_from_yaml( arg.gsub(/^-o/,'') )
|
||||
elsif (arg =~ /^--([a-zA-Z0-9._\\\/:\s]+)=\"?([a-zA-Z0-9._\-\\\/:\s\;]+)\"?/)
|
||||
options = option_maker(options, $1, $2)
|
||||
if arg =~ /^-o\"?([a-zA-Z0-9@._\\\/:\s]+)\"?/
|
||||
options.merge! CMockConfig.load_config_file_from_yaml(arg.gsub(/^-o/, ''))
|
||||
elsif arg == '--skeleton'
|
||||
options[:skeleton] = true
|
||||
elsif arg =~ /^--strippables=\"?(.*)\"?/
|
||||
# --strippables are dealt with separately since the user is allowed to
|
||||
# enter any valid regular expression as argument
|
||||
options = option_maker(options, 'strippables', Regexp.last_match(1))
|
||||
elsif arg =~ /^--([a-zA-Z0-9._\\\/:\s]+)=\"?([a-zA-Z0-9._\-\\\/:\s\;]*)\"?/x
|
||||
options = option_maker(options, Regexp.last_match(1),
|
||||
Regexp.last_match(2))
|
||||
else
|
||||
filelist << arg
|
||||
end
|
||||
end
|
||||
|
||||
CMock.new(options).setup_mocks(filelist)
|
||||
if options[:skeleton]
|
||||
CMock.new(options).setup_skeletons(filelist)
|
||||
else
|
||||
CMock.new(options).setup_mocks(filelist)
|
||||
end
|
||||
end
|
||||
|
||||
+78
-57
@@ -5,99 +5,120 @@
|
||||
# ==========================================
|
||||
|
||||
class CMockConfig
|
||||
CMOCK_DEFAULT_OPTIONS =
|
||||
{
|
||||
:framework => :unity,
|
||||
:mock_path => 'mocks',
|
||||
:mock_prefix => 'Mock',
|
||||
:mock_suffix => '',
|
||||
:skeleton_path => '',
|
||||
:weak => '',
|
||||
:subdir => nil,
|
||||
:plugins => [],
|
||||
:strippables => ['(?:__attribute__\s*\(+.*?\)+)'],
|
||||
:attributes => %w[__ramfunc __irq __fiq register extern],
|
||||
:c_calling_conventions => %w[__stdcall __cdecl __fastcall],
|
||||
:enforce_strict_ordering => false,
|
||||
:fail_on_unexpected_calls => true,
|
||||
:unity_helper_path => false,
|
||||
:treat_as => {},
|
||||
:treat_as_array => {},
|
||||
:treat_as_void => [],
|
||||
:memcmp_if_unknown => true,
|
||||
:when_no_prototypes => :warn, # the options being :ignore, :warn, or :error
|
||||
:when_ptr => :compare_data, # the options being :compare_ptr, :compare_data, or :smart
|
||||
:verbosity => 2, # the options being 0 errors only, 1 warnings and errors, 2 normal info, 3 verbose
|
||||
:treat_externs => :exclude, # the options being :include or :exclude
|
||||
:treat_inlines => :exclude, # the options being :include or :exclude
|
||||
:callback_include_count => true,
|
||||
:callback_after_arg_check => false,
|
||||
:includes => nil,
|
||||
:includes_h_pre_orig_header => nil,
|
||||
:includes_h_post_orig_header => nil,
|
||||
:includes_c_pre_header => nil,
|
||||
:includes_c_post_header => nil,
|
||||
:orig_header_include_fmt => '#include "%s"',
|
||||
:array_size_type => [],
|
||||
:array_size_name => 'size|len',
|
||||
:skeleton => false,
|
||||
:exclude_setjmp_h => false,
|
||||
|
||||
CMockDefaultOptions =
|
||||
{
|
||||
:framework => :unity,
|
||||
:mock_path => 'mocks',
|
||||
:mock_prefix => 'Mock',
|
||||
:mock_suffix => '',
|
||||
:weak => '',
|
||||
:subdir => nil,
|
||||
:plugins => [],
|
||||
:strippables => ['(?:__attribute__\s*\(+.*?\)+)'],
|
||||
: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_array => {},
|
||||
:treat_as_void => [],
|
||||
:memcmp_if_unknown => true,
|
||||
:when_no_prototypes => :warn, #the options being :ignore, :warn, or :error
|
||||
:when_ptr => :compare_data, #the options being :compare_ptr, :compare_data, or :smart
|
||||
:verbosity => 2, #the options being 0 errors only, 1 warnings and errors, 2 normal info, 3 verbose
|
||||
:treat_externs => :exclude, #the options being :include or :exclude
|
||||
:callback_include_count => true,
|
||||
:callback_after_arg_check => false,
|
||||
:includes => nil,
|
||||
:includes_h_pre_orig_header => nil,
|
||||
:includes_h_post_orig_header => nil,
|
||||
:includes_c_pre_header => nil,
|
||||
:includes_c_post_header => nil,
|
||||
:orig_header_include_fmt => "#include \"%s\"",
|
||||
:array_size_type => [],
|
||||
:array_size_name => 'size|len',
|
||||
}
|
||||
# Format to look for inline functions.
|
||||
# This is a combination of "static" and "inline" keywords ("static inline", "inline static", "inline", "static")
|
||||
# There are several possibilities:
|
||||
# - sometimes they appear together, sometimes individually,
|
||||
# - The keywords can appear before or after the return type (this is a compiler warning but people do weird stuff),
|
||||
# so we check for word boundaries when searching for them
|
||||
# - We first remove "static inline" combinations and boil down to single inline or static statements
|
||||
:inline_function_patterns => ['(static\s+inline|inline\s+static)\s*', '(\bstatic\b|\binline\b)\s*'] # Last part (\s*) is just to remove whitespaces (only to prettify the output)
|
||||
}.freeze
|
||||
|
||||
def initialize(options=nil)
|
||||
case(options)
|
||||
when NilClass then options = CMockDefaultOptions.clone
|
||||
when String then options = CMockDefaultOptions.clone.merge(load_config_file_from_yaml(options))
|
||||
when Hash then options = CMockDefaultOptions.clone.merge(options)
|
||||
else raise "If you specify arguments, it should be a filename or a hash of options"
|
||||
def initialize(options = nil)
|
||||
case options
|
||||
when NilClass then options = CMOCK_DEFAULT_OPTIONS.dup
|
||||
when String then options = CMOCK_DEFAULT_OPTIONS.dup.merge(load_config_file_from_yaml(options))
|
||||
when Hash then options = CMOCK_DEFAULT_OPTIONS.dup.merge(options)
|
||||
else raise 'If you specify arguments, it should be a filename or a hash of options'
|
||||
end
|
||||
|
||||
#do some quick type verification
|
||||
[:plugins, :attributes, :treat_as_void].each do |opt|
|
||||
unless (options[opt].class == Array)
|
||||
# do some quick type verification
|
||||
%i[plugins attributes treat_as_void].each do |opt|
|
||||
unless options[opt].class == Array
|
||||
options[opt] = []
|
||||
puts "WARNING: :#{opt.to_s} should be an array." unless (options[:verbosity] < 1)
|
||||
puts "WARNING: :#{opt} should be an array." unless options[:verbosity] < 1
|
||||
end
|
||||
end
|
||||
[:includes, :includes_h_pre_orig_header, :includes_h_post_orig_header, :includes_c_pre_header, :includes_c_post_header].each do |opt|
|
||||
unless (options[opt].nil? or (options[opt].class == Array))
|
||||
%i[includes includes_h_pre_orig_header includes_h_post_orig_header includes_c_pre_header includes_c_post_header].each do |opt|
|
||||
unless options[opt].nil? || (options[opt].class == Array)
|
||||
options[opt] = []
|
||||
puts "WARNING: :#{opt.to_s} should be an array." unless (options[:verbosity] < 1)
|
||||
puts "WARNING: :#{opt} should be an array." unless options[:verbosity] < 1
|
||||
end
|
||||
end
|
||||
options[:unity_helper_path] ||= options[:unity_helper]
|
||||
options[:unity_helper_path] = [options[:unity_helper_path]] if options[:unity_helper_path].is_a? String
|
||||
options[:includes_c_post_header] = ((options[:includes_c_post_header] || []) + (options[:unity_helper_path] || [])).uniq
|
||||
|
||||
if options[:unity_helper_path]
|
||||
require 'pathname'
|
||||
includes1 = options[:includes_c_post_header] || []
|
||||
includes2 = options[:unity_helper_path].map do |path|
|
||||
Pathname(path).relative_path_from(Pathname(options[:mock_path])).to_s
|
||||
end
|
||||
options[:includes_c_post_header] = (includes1 + includes2).uniq
|
||||
end
|
||||
|
||||
options[:plugins].compact!
|
||||
options[:plugins].map! {|p| p.to_sym}
|
||||
options[:plugins].map!(&:to_sym)
|
||||
@options = options
|
||||
|
||||
treat_as_map = standard_treat_as_map()#.clone
|
||||
treat_as_map = standard_treat_as_map # .clone
|
||||
treat_as_map.merge!(@options[:treat_as])
|
||||
@options[:treat_as] = treat_as_map
|
||||
|
||||
@options.each_key do |key|
|
||||
unless methods.include?(key)
|
||||
eval("def #{key.to_s}() return @options[:#{key.to_s}] end")
|
||||
eval("def #{key}() return @options[:#{key}] end")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def load_config_file_from_yaml yaml_filename
|
||||
def load_config_file_from_yaml(yaml_filename)
|
||||
self.class.load_config_file_from_yaml yaml_filename
|
||||
end
|
||||
|
||||
def self.load_config_file_from_yaml yaml_filename
|
||||
def self.load_config_file_from_yaml(yaml_filename)
|
||||
require 'yaml'
|
||||
require 'fileutils'
|
||||
YAML.load_file(yaml_filename)[:cmock]
|
||||
end
|
||||
|
||||
def set_path(path)
|
||||
@src_path = path
|
||||
def path(new_path)
|
||||
@src_path = new_path
|
||||
end
|
||||
|
||||
def load_unity_helper
|
||||
return nil unless (@options[:unity_helper_path])
|
||||
return nil unless @options[:unity_helper_path]
|
||||
|
||||
return @options[:unity_helper_path].inject("") do |unity_helper, filename|
|
||||
@options[:unity_helper_path].inject('') do |unity_helper, filename|
|
||||
unity_helper + "\n" + File.new(filename).read
|
||||
end
|
||||
end
|
||||
|
||||
+17
-14
@@ -5,7 +5,6 @@
|
||||
# ==========================================
|
||||
|
||||
class CMockFileWriter
|
||||
|
||||
attr_reader :config
|
||||
|
||||
def initialize(config)
|
||||
@@ -13,32 +12,36 @@ class CMockFileWriter
|
||||
end
|
||||
|
||||
def create_subdir(subdir)
|
||||
if !Dir.exists?("#{@config.mock_path}/")
|
||||
require 'fileutils'
|
||||
FileUtils.mkdir_p "#{@config.mock_path}/"
|
||||
end
|
||||
if subdir && !Dir.exists?("#{@config.mock_path}/#{subdir+'/' if subdir}")
|
||||
require 'fileutils'
|
||||
FileUtils.mkdir_p "#{@config.mock_path}/#{subdir+'/' if subdir}"
|
||||
end
|
||||
require 'fileutils'
|
||||
FileUtils.mkdir_p "#{@config.mock_path}/" unless Dir.exist?("#{@config.mock_path}/")
|
||||
FileUtils.mkdir_p "#{@config.mock_path}/#{subdir + '/' if subdir}" if subdir && !Dir.exist?("#{@config.mock_path}/#{subdir + '/' if subdir}")
|
||||
end
|
||||
|
||||
def create_file(filename, subdir)
|
||||
raise "Where's the block of data to create?" unless block_given?
|
||||
full_file_name_temp = "#{@config.mock_path}/#{subdir+'/' if subdir}#{filename}.new"
|
||||
full_file_name_done = "#{@config.mock_path}/#{subdir+'/' if subdir}#{filename}"
|
||||
|
||||
full_file_name_temp = "#{@config.mock_path}/#{subdir + '/' if subdir}#{filename}.new"
|
||||
full_file_name_done = "#{@config.mock_path}/#{subdir + '/' if subdir}#{filename}"
|
||||
File.open(full_file_name_temp, 'w') do |file|
|
||||
yield(file, filename)
|
||||
end
|
||||
update_file(full_file_name_done, full_file_name_temp)
|
||||
end
|
||||
|
||||
def append_file(filename, subdir)
|
||||
raise "Where's the block of data to create?" unless block_given?
|
||||
|
||||
full_file_name = "#{@config.skeleton_path}/#{subdir + '/' if subdir}#{filename}"
|
||||
File.open(full_file_name, 'a') do |file|
|
||||
yield(file, filename)
|
||||
end
|
||||
end
|
||||
|
||||
private ###################################
|
||||
|
||||
def update_file(dest, src)
|
||||
require 'fileutils'
|
||||
FileUtils.rm(dest) if (File.exist?(dest))
|
||||
FileUtils.cp(src, dest)
|
||||
FileUtils.rm(src)
|
||||
FileUtils.rm(dest, :force => true)
|
||||
FileUtils.mv(src, dest)
|
||||
end
|
||||
end
|
||||
|
||||
+186
-86
@@ -5,8 +5,7 @@
|
||||
# ==========================================
|
||||
|
||||
class CMockGenerator
|
||||
|
||||
attr_accessor :config, :file_writer, :module_name, :clean_mock_name, :mock_name, :utils, :plugins, :weak, :ordered
|
||||
attr_accessor :config, :file_writer, :module_name, :module_ext, :clean_mock_name, :mock_name, :utils, :plugins, :weak, :ordered
|
||||
|
||||
def initialize(config, file_writer, utils, plugins)
|
||||
@file_writer = file_writer
|
||||
@@ -16,89 +15,147 @@ class CMockGenerator
|
||||
@prefix = @config.mock_prefix
|
||||
@suffix = @config.mock_suffix
|
||||
@weak = @config.weak
|
||||
@ordered = @config.enforce_strict_ordering
|
||||
@framework = @config.framework.to_s
|
||||
@include_inline = @config.treat_inlines
|
||||
@ordered = @config.enforce_strict_ordering
|
||||
@framework = @config.framework.to_s
|
||||
@fail_on_unexpected_calls = @config.fail_on_unexpected_calls
|
||||
@exclude_setjmp_h = @config.exclude_setjmp_h
|
||||
@subdir = @config.subdir
|
||||
|
||||
@subdir = @config.subdir
|
||||
|
||||
@includes_h_pre_orig_header = (@config.includes || @config.includes_h_pre_orig_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""}
|
||||
@includes_h_post_orig_header = (@config.includes_h_post_orig_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""}
|
||||
@includes_c_pre_header = (@config.includes_c_pre_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""}
|
||||
@includes_c_post_header = (@config.includes_c_post_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""}
|
||||
@includes_h_pre_orig_header = (@config.includes || @config.includes_h_pre_orig_header || []).map { |h| h =~ /</ ? h : "\"#{h}\"" }
|
||||
@includes_h_post_orig_header = (@config.includes_h_post_orig_header || []).map { |h| h =~ /</ ? h : "\"#{h}\"" }
|
||||
@includes_c_pre_header = (@config.includes_c_pre_header || []).map { |h| h =~ /</ ? h : "\"#{h}\"" }
|
||||
@includes_c_post_header = (@config.includes_c_post_header || []).map { |h| h =~ /</ ? h : "\"#{h}\"" }
|
||||
|
||||
here = File.dirname __FILE__
|
||||
unity_path_in_ceedling = "#{here}/../../unity" # path to Unity from within Ceedling
|
||||
unity_path_in_cmock = "#{here}/../vendor/unity" # path to Unity from within CMock
|
||||
# path to Unity as specified by env var
|
||||
unity_path_in_env = ENV.has_key?("UNITY_DIR") ? File.expand_path(ENV.fetch("UNITY_DIR")) : nil
|
||||
unity_path_in_env = ENV.key?('UNITY_DIR') ? File.expand_path(ENV.fetch('UNITY_DIR')) : nil
|
||||
|
||||
if unity_path_in_env and File.exist? unity_path_in_env
|
||||
if unity_path_in_env && File.exist?(unity_path_in_env)
|
||||
require "#{unity_path_in_env}/auto/type_sanitizer"
|
||||
elsif File.exist? unity_path_in_ceedling
|
||||
require "#{unity_path_in_ceedling}/auto/type_sanitizer"
|
||||
elsif File.exist? unity_path_in_cmock
|
||||
require "#{unity_path_in_cmock}/auto/type_sanitizer"
|
||||
else
|
||||
raise "Failed to find an instance of Unity to pull in type_sanitizer module!"
|
||||
raise 'Failed to find an instance of Unity to pull in type_sanitizer module!'
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def create_mock(module_name, parsed_stuff)
|
||||
@module_name = module_name
|
||||
@mock_name = @prefix + @module_name + @suffix
|
||||
@clean_mock_name = TypeSanitizer.sanitize_c_identifier(@mock_name)
|
||||
create_mock_subdir()
|
||||
create_mock_header_file(parsed_stuff)
|
||||
create_mock_source_file(parsed_stuff)
|
||||
def create_mock(module_name, parsed_stuff, module_ext = nil, folder = nil)
|
||||
# determine the name for our new mock
|
||||
mock_name = @prefix + module_name + @suffix
|
||||
|
||||
# determine the folder our mock will reside
|
||||
mock_folder = if folder && @subdir
|
||||
File.join(@subdir, folder)
|
||||
elsif @subdir
|
||||
@subdir
|
||||
else
|
||||
folder
|
||||
end
|
||||
|
||||
# adds a trailing slash to the folder output
|
||||
mock_folder = File.join(mock_folder, '') if mock_folder
|
||||
|
||||
# create out mock project from incoming data
|
||||
mock_project = {
|
||||
:module_name => module_name,
|
||||
:module_ext => (module_ext || '.h'),
|
||||
:mock_name => mock_name,
|
||||
:clean_name => TypeSanitizer.sanitize_c_identifier(mock_name),
|
||||
:folder => mock_folder,
|
||||
:parsed_stuff => parsed_stuff,
|
||||
:skeleton => false
|
||||
}
|
||||
|
||||
create_mock_subdir(mock_project)
|
||||
create_mock_header_file(mock_project)
|
||||
create_mock_source_file(mock_project)
|
||||
end
|
||||
|
||||
def create_skeleton(module_name, parsed_stuff)
|
||||
mock_project = {
|
||||
:module_name => module_name,
|
||||
:module_ext => '.h',
|
||||
:parsed_stuff => parsed_stuff,
|
||||
:skeleton => true
|
||||
}
|
||||
|
||||
create_skeleton_source_file(mock_project)
|
||||
end
|
||||
|
||||
private if $ThisIsOnlyATest.nil? ##############################
|
||||
|
||||
def create_mock_subdir()
|
||||
@file_writer.create_subdir(@subdir)
|
||||
def create_mock_subdir(mock_project)
|
||||
@file_writer.create_subdir(mock_project[:folder])
|
||||
end
|
||||
|
||||
def create_mock_header_file(parsed_stuff)
|
||||
@file_writer.create_file(@mock_name + ".h", @subdir) do |file, filename|
|
||||
create_mock_header_header(file, filename)
|
||||
create_mock_header_service_call_declarations(file)
|
||||
create_typedefs(file, parsed_stuff[:typedefs])
|
||||
parsed_stuff[:functions].each do |function|
|
||||
def create_using_statement(file, function)
|
||||
file << "using namespace #{function[:namespace].join('::')};\n" unless function[:namespace].empty?
|
||||
end
|
||||
|
||||
def create_mock_header_file(mock_project)
|
||||
if @include_inline == :include
|
||||
@file_writer.create_file(mock_project[:module_name] + (mock_project[:module_ext]), mock_project[:folder]) do |file, _filename|
|
||||
file << mock_project[:parsed_stuff][:normalized_source]
|
||||
end
|
||||
end
|
||||
|
||||
@file_writer.create_file(mock_project[:mock_name] + mock_project[:module_ext], mock_project[:folder]) do |file, filename|
|
||||
create_mock_header_header(file, filename, mock_project)
|
||||
create_mock_header_service_call_declarations(file, mock_project)
|
||||
create_typedefs(file, mock_project)
|
||||
mock_project[:parsed_stuff][:functions].each do |function|
|
||||
create_using_statement(file, function)
|
||||
file << @plugins.run(:mock_function_declarations, function)
|
||||
end
|
||||
create_mock_header_footer(file)
|
||||
end
|
||||
end
|
||||
|
||||
def create_mock_source_file(parsed_stuff)
|
||||
@file_writer.create_file(@mock_name + ".c", @subdir) do |file, filename|
|
||||
create_source_header_section(file, filename, parsed_stuff[:functions])
|
||||
create_instance_structure(file, parsed_stuff[:functions])
|
||||
def create_mock_source_file(mock_project)
|
||||
@file_writer.create_file(mock_project[:mock_name] + '.c', mock_project[:folder]) do |file, filename|
|
||||
create_source_header_section(file, filename, mock_project)
|
||||
create_instance_structure(file, mock_project)
|
||||
create_extern_declarations(file)
|
||||
create_mock_verify_function(file, parsed_stuff[:functions])
|
||||
create_mock_init_function(file)
|
||||
create_mock_destroy_function(file, parsed_stuff[:functions])
|
||||
parsed_stuff[:functions].each do |function|
|
||||
create_mock_verify_function(file, mock_project)
|
||||
create_mock_init_function(file, mock_project)
|
||||
create_mock_destroy_function(file, mock_project)
|
||||
mock_project[:parsed_stuff][:functions].each do |function|
|
||||
create_mock_implementation(file, function)
|
||||
create_mock_interfaces(file, function)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create_mock_header_header(file, filename)
|
||||
define_name = @clean_mock_name.upcase
|
||||
orig_filename = (@subdir ? @subdir + "/" : "") + @module_name + ".h"
|
||||
def create_skeleton_source_file(mock_project)
|
||||
filename = "#{@config.mock_path}/#{@subdir + '/' if @subdir}#{mock_project[:module_name]}.c"
|
||||
existing = File.exist?(filename) ? File.read(filename) : ''
|
||||
@file_writer.append_file(mock_project[:module_name] + '.c', @subdir) do |file, fullname|
|
||||
blank_project = mock_project.clone
|
||||
blank_project[:parsed_stuff] = { :functions => [] }
|
||||
create_source_header_section(file, fullname, blank_project) if existing.empty?
|
||||
mock_project[:parsed_stuff][:functions].each do |function|
|
||||
create_function_skeleton(file, function, existing)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create_mock_header_header(file, _filename, mock_project)
|
||||
define_name = mock_project[:clean_name].upcase
|
||||
orig_filename = (mock_project[:folder] || '') + mock_project[:module_name] + mock_project[:module_ext]
|
||||
file << "/* AUTOGENERATED FILE. DO NOT EDIT. */\n"
|
||||
file << "#ifndef _#{define_name}_H\n"
|
||||
file << "#define _#{define_name}_H\n\n"
|
||||
file << "#include \"#{@framework}.h\"\n"
|
||||
@includes_h_pre_orig_header.each {|inc| file << "#include #{inc}\n"}
|
||||
file << @config.orig_header_include_fmt.gsub(/%s/, "#{orig_filename}") + "\n"
|
||||
@includes_h_post_orig_header.each {|inc| file << "#include #{inc}\n"}
|
||||
@includes_h_pre_orig_header.each { |inc| file << "#include #{inc}\n" }
|
||||
file << @config.orig_header_include_fmt.gsub(/%s/, orig_filename.to_s) + "\n"
|
||||
@includes_h_post_orig_header.each { |inc| file << "#include #{inc}\n" }
|
||||
plugin_includes = @plugins.run(:include_files)
|
||||
file << plugin_includes if (!plugin_includes.empty?)
|
||||
file << plugin_includes unless plugin_includes.empty?
|
||||
file << "\n"
|
||||
file << "/* Ignore the following warnings, since we are copying code */\n"
|
||||
file << "#if defined(__GNUC__) && !defined(__ICC) && !defined(__TMS470__)\n"
|
||||
@@ -114,16 +171,16 @@ class CMockGenerator
|
||||
file << "\n"
|
||||
end
|
||||
|
||||
def create_typedefs(file, typedefs)
|
||||
def create_typedefs(file, mock_project)
|
||||
file << "\n"
|
||||
typedefs.each {|typedef| file << "#{typedef}\n" }
|
||||
mock_project[:parsed_stuff][:typedefs].each { |typedef| file << "#{typedef}\n" }
|
||||
file << "\n\n"
|
||||
end
|
||||
|
||||
def create_mock_header_service_call_declarations(file)
|
||||
file << "void #{@clean_mock_name}_Init(void);\n"
|
||||
file << "void #{@clean_mock_name}_Destroy(void);\n"
|
||||
file << "void #{@clean_mock_name}_Verify(void);\n\n"
|
||||
def create_mock_header_service_call_declarations(file, mock_project)
|
||||
file << "void #{mock_project[:clean_name]}_Init(void);\n"
|
||||
file << "void #{mock_project[:clean_name]}_Destroy(void);\n"
|
||||
file << "void #{mock_project[:clean_name]}_Verify(void);\n\n"
|
||||
end
|
||||
|
||||
def create_mock_header_footer(header)
|
||||
@@ -137,21 +194,23 @@ class CMockGenerator
|
||||
header << "#endif\n"
|
||||
end
|
||||
|
||||
def create_source_header_section(file, filename, functions)
|
||||
header_file = (@subdir ? @subdir + '/' : '') + filename.gsub(".c",".h")
|
||||
file << "/* AUTOGENERATED FILE. DO NOT EDIT. */\n"
|
||||
def create_source_header_section(file, filename, mock_project)
|
||||
header_file = (mock_project[:folder] || '') + filename.gsub('.c', mock_project[:module_ext])
|
||||
file << "/* AUTOGENERATED FILE. DO NOT EDIT. */\n" unless mock_project[:parsed_stuff][:functions].empty?
|
||||
file << "#include <string.h>\n"
|
||||
file << "#include <stdlib.h>\n"
|
||||
file << "#include <setjmp.h>\n"
|
||||
unless @exclude_setjmp_h
|
||||
file << "#include <setjmp.h>\n"
|
||||
end
|
||||
file << "#include \"cmock.h\"\n"
|
||||
@includes_c_pre_header.each {|inc| file << "#include #{inc}\n"}
|
||||
@includes_c_pre_header.each { |inc| file << "#include #{inc}\n" }
|
||||
file << "#include \"#{header_file}\"\n"
|
||||
@includes_c_post_header.each {|inc| file << "#include #{inc}\n"}
|
||||
@includes_c_post_header.each { |inc| file << "#include #{inc}\n" }
|
||||
file << "\n"
|
||||
strs = []
|
||||
functions.each do |func|
|
||||
mock_project[:parsed_stuff][:functions].each do |func|
|
||||
strs << func[:name]
|
||||
func[:args].each {|arg| strs << arg[:name] }
|
||||
func[:args].each { |arg| strs << arg[:name] }
|
||||
end
|
||||
strs.uniq.sort.each do |str|
|
||||
file << "static const char* CMockString_#{str} = \"#{str}\";\n"
|
||||
@@ -159,15 +218,16 @@ class CMockGenerator
|
||||
file << "\n"
|
||||
end
|
||||
|
||||
def create_instance_structure(file, functions)
|
||||
def create_instance_structure(file, mock_project)
|
||||
functions = mock_project[:parsed_stuff][:functions]
|
||||
functions.each do |function|
|
||||
file << "typedef struct _CMOCK_#{function[:name]}_CALL_INSTANCE\n{\n"
|
||||
file << " UNITY_LINE_TYPE LineNumber;\n"
|
||||
file << @plugins.run(:instance_typedefs, function)
|
||||
file << "\n} CMOCK_#{function[:name]}_CALL_INSTANCE;\n\n"
|
||||
end
|
||||
file << "static struct #{@clean_mock_name}Instance\n{\n"
|
||||
if (functions.size == 0)
|
||||
file << "static struct #{mock_project[:clean_name]}Instance\n{\n"
|
||||
if functions.empty?
|
||||
file << " unsigned char placeHolder;\n"
|
||||
end
|
||||
functions.each do |function|
|
||||
@@ -178,17 +238,19 @@ class CMockGenerator
|
||||
end
|
||||
|
||||
def create_extern_declarations(file)
|
||||
file << "extern jmp_buf AbortFrame;\n"
|
||||
if (@ordered)
|
||||
unless @exclude_setjmp_h
|
||||
file << "extern jmp_buf AbortFrame;\n"
|
||||
end
|
||||
if @ordered
|
||||
file << "extern int GlobalExpectCount;\n"
|
||||
file << "extern int GlobalVerifyOrder;\n"
|
||||
end
|
||||
file << "\n"
|
||||
end
|
||||
|
||||
def create_mock_verify_function(file, functions)
|
||||
file << "void #{@clean_mock_name}_Verify(void)\n{\n"
|
||||
verifications = functions.collect do |function|
|
||||
def create_mock_verify_function(file, mock_project)
|
||||
file << "void #{mock_project[:clean_name]}_Verify(void)\n{\n"
|
||||
verifications = mock_project[:parsed_stuff][:functions].collect do |function|
|
||||
v = @plugins.run(:mock_verify, function)
|
||||
v.empty? ? v : [" call_instance = Mock.#{function[:name]}_CallInstance;\n", v]
|
||||
end.join
|
||||
@@ -200,23 +262,23 @@ class CMockGenerator
|
||||
file << "}\n\n"
|
||||
end
|
||||
|
||||
def create_mock_init_function(file)
|
||||
file << "void #{@clean_mock_name}_Init(void)\n{\n"
|
||||
file << " #{@clean_mock_name}_Destroy();\n"
|
||||
def create_mock_init_function(file, mock_project)
|
||||
file << "void #{mock_project[:clean_name]}_Init(void)\n{\n"
|
||||
file << " #{mock_project[:clean_name]}_Destroy();\n"
|
||||
file << "}\n\n"
|
||||
end
|
||||
|
||||
def create_mock_destroy_function(file, functions)
|
||||
file << "void #{@clean_mock_name}_Destroy(void)\n{\n"
|
||||
def create_mock_destroy_function(file, mock_project)
|
||||
file << "void #{mock_project[:clean_name]}_Destroy(void)\n{\n"
|
||||
file << " CMock_Guts_MemFreeAll();\n"
|
||||
file << " memset(&Mock, 0, sizeof(Mock));\n"
|
||||
file << functions.collect {|function| @plugins.run(:mock_destroy, function)}.join
|
||||
file << mock_project[:parsed_stuff][:functions].collect { |function| @plugins.run(:mock_destroy, function) }.join
|
||||
|
||||
unless (@fail_on_unexpected_calls)
|
||||
file << functions.collect {|function| @plugins.run(:mock_ignore, function)}.join
|
||||
unless @fail_on_unexpected_calls
|
||||
file << mock_project[:parsed_stuff][:functions].collect { |function| @plugins.run(:mock_ignore, function) }.join
|
||||
end
|
||||
|
||||
if (@ordered)
|
||||
if @ordered
|
||||
file << " GlobalExpectCount = 0;\n"
|
||||
file << " GlobalVerifyOrder = 0;\n"
|
||||
end
|
||||
@@ -229,17 +291,28 @@ class CMockGenerator
|
||||
(function[:return][:type]) +
|
||||
(function[:c_calling_convention] ? " #{function[:c_calling_convention]}" : '')
|
||||
args_string = function[:args_string]
|
||||
args_string += (", " + function[:var_arg]) unless (function[:var_arg].nil?)
|
||||
args_string += (', ' + function[:var_arg]) unless function[:var_arg].nil?
|
||||
|
||||
# Encapsulate in namespace(s) if applicable
|
||||
function[:namespace].each do |ns|
|
||||
file << "namespace #{ns} {\n"
|
||||
end
|
||||
|
||||
# Determine class prefix (if any)
|
||||
cls_pre = ''
|
||||
unless function[:class].nil?
|
||||
cls_pre = "#{function[:class]}::"
|
||||
end
|
||||
|
||||
# Create mock function
|
||||
if (not @weak.empty?)
|
||||
file << "#if defined (__IAR_SYSTEMS_ICC__)\n"
|
||||
file << "#pragma weak #{function[:name]}\n"
|
||||
file << "#else\n"
|
||||
file << "#{function_mod_and_rettype} #{function[:name]}(#{args_string}) #{weak};\n"
|
||||
file << "#endif\n\n"
|
||||
unless @weak.empty?
|
||||
file << "#if defined (__IAR_SYSTEMS_ICC__)\n"
|
||||
file << "#pragma weak #{function[:unscoped_name]}\n"
|
||||
file << "#else\n"
|
||||
file << "#{function_mod_and_rettype} #{function[:unscoped_name]}(#{args_string}) #{weak};\n"
|
||||
file << "#endif\n\n"
|
||||
end
|
||||
file << "#{function_mod_and_rettype} #{function[:name]}(#{args_string})\n"
|
||||
file << "#{function_mod_and_rettype} #{cls_pre}#{function[:unscoped_name]}(#{args_string})\n"
|
||||
file << "{\n"
|
||||
file << " UNITY_LINE_TYPE cmock_line = TEST_LINE_NUM;\n"
|
||||
file << " CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance;\n"
|
||||
@@ -249,7 +322,7 @@ class CMockGenerator
|
||||
file << @plugins.run(:mock_implementation_precheck, function)
|
||||
file << " UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringCalledMore);\n"
|
||||
file << " cmock_line = cmock_call_instance->LineNumber;\n"
|
||||
if (@ordered)
|
||||
if @ordered
|
||||
file << " if (cmock_call_instance->CallOrder > ++GlobalVerifyOrder)\n"
|
||||
file << " UNITY_TEST_FAIL(cmock_line, CMockStringCalledEarly);\n"
|
||||
file << " if (cmock_call_instance->CallOrder < GlobalVerifyOrder)\n"
|
||||
@@ -257,12 +330,39 @@ class CMockGenerator
|
||||
end
|
||||
file << @plugins.run(:mock_implementation, function)
|
||||
file << " UNITY_CLR_DETAILS();\n"
|
||||
file << " return cmock_call_instance->ReturnVal;\n" unless (function[:return][:void?])
|
||||
file << "}\n\n"
|
||||
file << " return cmock_call_instance->ReturnVal;\n" unless function[:return][:void?]
|
||||
file << "}\n"
|
||||
|
||||
# Close any namespace(s) opened above
|
||||
function[:namespace].each do
|
||||
file << "}\n"
|
||||
end
|
||||
|
||||
file << "\n"
|
||||
end
|
||||
|
||||
def create_mock_interfaces(file, function)
|
||||
file << @utils.code_add_argument_loader(function)
|
||||
file << @plugins.run(:mock_interfaces, function)
|
||||
end
|
||||
|
||||
def create_function_skeleton(file, function, existing)
|
||||
# prepare return value and arguments
|
||||
function_mod_and_rettype = (function[:modifier].empty? ? '' : "#{function[:modifier]} ") +
|
||||
(function[:return][:type]) +
|
||||
(function[:c_calling_convention] ? " #{function[:c_calling_convention]}" : '')
|
||||
args_string = function[:args_string]
|
||||
args_string += (', ' + function[:var_arg]) unless function[:var_arg].nil?
|
||||
|
||||
decl = "#{function_mod_and_rettype} #{function[:name]}(#{args_string})"
|
||||
|
||||
return if existing.include?(decl)
|
||||
|
||||
file << "#{decl}\n"
|
||||
file << "{\n"
|
||||
file << " /*TODO: Implement Me!*/\n"
|
||||
function[:args].each { |arg| file << " (void)#{arg[:name]};\n" }
|
||||
file << " return (#{(function[:return][:type])})0;\n" unless function[:return][:void?]
|
||||
file << "}\n\n"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# ==========================================
|
||||
|
||||
class CMockGeneratorPluginArray
|
||||
|
||||
attr_reader :priority
|
||||
attr_accessor :config, :utils, :unity_helper, :ordered
|
||||
def initialize(config, utils)
|
||||
@@ -18,46 +17,47 @@ class CMockGeneratorPluginArray
|
||||
end
|
||||
|
||||
def instance_typedefs(function)
|
||||
function[:args].inject("") do |all, arg|
|
||||
(arg[:ptr?]) ? all + " int Expected_#{arg[:name]}_Depth;\n" : all
|
||||
function[:args].inject('') do |all, arg|
|
||||
arg[:ptr?] ? all + " int Expected_#{arg[:name]}_Depth;\n" : all
|
||||
end
|
||||
end
|
||||
|
||||
def mock_function_declarations(function)
|
||||
return nil unless function[:contains_ptr?]
|
||||
args_call = function[:args].map{|m| m[:ptr?] ? "#{m[:name]}, #{m[:name]}_Depth" : "#{m[:name]}"}.join(', ')
|
||||
|
||||
args_call = function[:args].map { |m| m[:ptr?] ? "#{m[:name]}, #{m[:name]}_Depth" : (m[:name]).to_s }.join(', ')
|
||||
args_string = function[:args].map do |m|
|
||||
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" +
|
||||
if function[:return][:void?]
|
||||
return "#define #{function[:name]}_ExpectWithArray(#{args_call}) #{function[:name]}_CMockExpectWithArray(__LINE__, #{args_call})\n" \
|
||||
"void #{function[:name]}_CMockExpectWithArray(UNITY_LINE_TYPE cmock_line, #{args_string});\n"
|
||||
else
|
||||
return "#define #{function[:name]}_ExpectWithArrayAndReturn(#{args_call}, cmock_retval) #{function[:name]}_CMockExpectWithArrayAndReturn(__LINE__, #{args_call}, cmock_retval)\n" +
|
||||
return "#define #{function[:name]}_ExpectWithArrayAndReturn(#{args_call}, cmock_retval) #{function[:name]}_CMockExpectWithArrayAndReturn(__LINE__, #{args_call}, cmock_retval)\n" \
|
||||
"void #{function[:name]}_CMockExpectWithArrayAndReturn(UNITY_LINE_TYPE cmock_line, #{args_string}, #{function[:return][:str]});\n"
|
||||
end
|
||||
end
|
||||
|
||||
def mock_interfaces(function)
|
||||
return nil unless function[:contains_ptr?]
|
||||
|
||||
lines = []
|
||||
func_name = function[:name]
|
||||
args_string = function[:args].map do |m|
|
||||
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?])
|
||||
lines << "void #{func_name}_CMockExpectWithArray(UNITY_LINE_TYPE cmock_line, #{args_string})\n"
|
||||
else
|
||||
lines << "void #{func_name}_CMockExpectWithArrayAndReturn(UNITY_LINE_TYPE cmock_line, #{args_string}, #{function[:return][:str]})\n"
|
||||
end
|
||||
call_string = function[:args].map { |m| m[:ptr?] ? "#{m[:name]}, #{m[:name]}_Depth" : m[:name] }.join(', ')
|
||||
lines << if function[:return][:void?]
|
||||
"void #{func_name}_CMockExpectWithArray(UNITY_LINE_TYPE cmock_line, #{args_string})\n"
|
||||
else
|
||||
"void #{func_name}_CMockExpectWithArrayAndReturn(UNITY_LINE_TYPE cmock_line, #{args_string}, #{function[:return][:str]})\n"
|
||||
end
|
||||
lines << "{\n"
|
||||
lines << @utils.code_add_base_expectation(func_name)
|
||||
lines << " CMockExpectParameters_#{func_name}(cmock_call_instance, #{call_string});\n"
|
||||
lines << " cmock_call_instance->ReturnVal = cmock_to_return;\n" unless (function[:return][:void?])
|
||||
lines << " cmock_call_instance->ReturnVal = cmock_to_return;\n" unless function[:return][:void?]
|
||||
lines << "}\n\n"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# ==========================================
|
||||
|
||||
class CMockGeneratorPluginCallback
|
||||
|
||||
attr_accessor :include_count
|
||||
attr_reader :priority
|
||||
attr_reader :config, :utils
|
||||
@@ -20,7 +19,7 @@ class CMockGeneratorPluginCallback
|
||||
|
||||
def instance_structure(function)
|
||||
func_name = function[:name]
|
||||
" int #{func_name}_CallbackBool;\n" \
|
||||
" char #{func_name}_CallbackBool;\n" \
|
||||
" CMOCK_#{func_name}_CALLBACK #{func_name}_CallbackFunctionPointer;\n" \
|
||||
" int #{func_name}_CallbackCalls;\n"
|
||||
end
|
||||
@@ -30,7 +29,7 @@ class CMockGeneratorPluginCallback
|
||||
return_type = function[:return][:type]
|
||||
action = @config.callback_after_arg_check ? 'AddCallback' : 'Stub'
|
||||
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" ]
|
||||
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]});\n" \
|
||||
"void #{func_name}_AddCallback(CMOCK_#{func_name}_CALLBACK Callback);\n" \
|
||||
"void #{func_name}_Stub(CMOCK_#{func_name}_CALLBACK Callback);\n" \
|
||||
@@ -60,29 +59,30 @@ class CMockGeneratorPluginCallback
|
||||
" UNITY_CLR_DETAILS();\n" \
|
||||
" return;\n }\n"
|
||||
else
|
||||
" #{function[:return][:type]} ret = #{generate_call(function)};\n" \
|
||||
" #{function[:return][:type]} cmock_cb_ret = #{generate_call(function)};\n" \
|
||||
" UNITY_CLR_DETAILS();\n" \
|
||||
" return ret;\n }\n"
|
||||
" return cmock_cb_ret;\n }\n"
|
||||
end
|
||||
end
|
||||
|
||||
def mock_interfaces(function)
|
||||
func_name = function[:name]
|
||||
has_ignore = @config.plugins.include? :ignore
|
||||
lines = ""
|
||||
lines = ''
|
||||
lines << "void #{func_name}_AddCallback(CMOCK_#{func_name}_CALLBACK Callback)\n{\n"
|
||||
lines << " Mock.#{func_name}_IgnoreBool = (int)0;\n" if has_ignore
|
||||
lines << " Mock.#{func_name}_CallbackBool = (int)1;\n"
|
||||
lines << " Mock.#{func_name}_IgnoreBool = (char)0;\n" if has_ignore
|
||||
lines << " Mock.#{func_name}_CallbackBool = (char)1;\n"
|
||||
lines << " Mock.#{func_name}_CallbackFunctionPointer = Callback;\n}\n\n"
|
||||
lines << "void #{func_name}_Stub(CMOCK_#{func_name}_CALLBACK Callback)\n{\n"
|
||||
lines << " Mock.#{func_name}_IgnoreBool = (int)0;\n" if has_ignore
|
||||
lines << " Mock.#{func_name}_CallbackBool = (int)0;\n"
|
||||
lines << " Mock.#{func_name}_IgnoreBool = (char)0;\n" if has_ignore
|
||||
lines << " Mock.#{func_name}_CallbackBool = (char)0;\n"
|
||||
lines << " Mock.#{func_name}_CallbackFunctionPointer = Callback;\n}\n\n"
|
||||
end
|
||||
|
||||
def mock_verify(function)
|
||||
func_name = function[:name]
|
||||
" if (Mock.#{func_name}_CallbackFunctionPointer != NULL)\n call_instance = CMOCK_GUTS_NONE;\n"
|
||||
" if (Mock.#{func_name}_CallbackFunctionPointer != NULL)\n {\n" \
|
||||
" call_instance = CMOCK_GUTS_NONE;\n" \
|
||||
" (void)call_instance;\n }\n"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# ==========================================
|
||||
|
||||
class CMockGeneratorPluginCexception
|
||||
|
||||
attr_reader :priority
|
||||
attr_reader :config, :utils
|
||||
|
||||
@@ -13,39 +12,39 @@ class CMockGeneratorPluginCexception
|
||||
@config = config
|
||||
@utils = utils
|
||||
@priority = 7
|
||||
raise 'Error: cexception is not supported without setjmp support' if @config.exclude_setjmp_h
|
||||
end
|
||||
|
||||
def include_files
|
||||
return "#include \"CException.h\"\n"
|
||||
"#include \"CException.h\"\n"
|
||||
end
|
||||
|
||||
def instance_typedefs(function)
|
||||
def instance_typedefs(_function)
|
||||
" CEXCEPTION_T ExceptionToThrow;\n"
|
||||
end
|
||||
|
||||
def mock_function_declarations(function)
|
||||
if (function[:args_string] == "void")
|
||||
return "#define #{function[:name]}_ExpectAndThrow(cmock_to_throw) #{function[:name]}_CMockExpectAndThrow(__LINE__, cmock_to_throw)\n" +
|
||||
if function[:args_string] == 'void'
|
||||
"#define #{function[:name]}_ExpectAndThrow(cmock_to_throw) #{function[:name]}_CMockExpectAndThrow(__LINE__, cmock_to_throw)\n" \
|
||||
"void #{function[:name]}_CMockExpectAndThrow(UNITY_LINE_TYPE cmock_line, CEXCEPTION_T cmock_to_throw);\n"
|
||||
else
|
||||
return "#define #{function[:name]}_ExpectAndThrow(#{function[:args_call]}, cmock_to_throw) #{function[:name]}_CMockExpectAndThrow(__LINE__, #{function[:args_call]}, cmock_to_throw)\n" +
|
||||
"#define #{function[:name]}_ExpectAndThrow(#{function[:args_call]}, cmock_to_throw) #{function[:name]}_CMockExpectAndThrow(__LINE__, #{function[:args_call]}, cmock_to_throw)\n" \
|
||||
"void #{function[:name]}_CMockExpectAndThrow(UNITY_LINE_TYPE cmock_line, #{function[:args_string]}, CEXCEPTION_T cmock_to_throw);\n"
|
||||
end
|
||||
end
|
||||
|
||||
def mock_implementation(function)
|
||||
" if (cmock_call_instance->ExceptionToThrow != CEXCEPTION_NONE)\n {\n" +
|
||||
" UNITY_CLR_DETAILS();\n" +
|
||||
" Throw(cmock_call_instance->ExceptionToThrow);\n }\n"
|
||||
def mock_implementation(_function)
|
||||
" if (cmock_call_instance->ExceptionToThrow != CEXCEPTION_NONE)\n {\n" \
|
||||
" UNITY_CLR_DETAILS();\n" \
|
||||
" Throw(cmock_call_instance->ExceptionToThrow);\n }\n"
|
||||
end
|
||||
|
||||
def mock_interfaces(function)
|
||||
arg_insert = (function[:args_string] == "void") ? "" : "#{function[:args_string]}, "
|
||||
[ "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),
|
||||
" cmock_call_instance->ExceptionToThrow = cmock_to_throw;\n",
|
||||
"}\n\n" ].join
|
||||
arg_insert = function[:args_string] == 'void' ? '' : "#{function[:args_string]}, "
|
||||
["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),
|
||||
" cmock_call_instance->ExceptionToThrow = cmock_to_throw;\n",
|
||||
"}\n\n"].join
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# ==========================================
|
||||
|
||||
class CMockGeneratorPluginExpect
|
||||
|
||||
attr_reader :priority
|
||||
attr_accessor :config, :utils, :unity_helper, :ordered
|
||||
|
||||
@@ -17,7 +16,7 @@ class CMockGeneratorPluginExpect
|
||||
@unity_helper = @utils.helpers[:unity_helper]
|
||||
@priority = 5
|
||||
|
||||
if (@config.plugins.include? :expect_any_args)
|
||||
if @config.plugins.include? :expect_any_args
|
||||
alias :mock_implementation :mock_implementation_might_check_args
|
||||
else
|
||||
alias :mock_implementation :mock_implementation_always_check_args
|
||||
@@ -25,9 +24,9 @@ class CMockGeneratorPluginExpect
|
||||
end
|
||||
|
||||
def instance_typedefs(function)
|
||||
lines = ""
|
||||
lines << " #{function[:return][:type]} ReturnVal;\n" unless (function[:return][:void?])
|
||||
lines << " int CallOrder;\n" if (@ordered)
|
||||
lines = ''
|
||||
lines << " #{function[:return][:type]} ReturnVal;\n" unless function[:return][:void?]
|
||||
lines << " int CallOrder;\n" if @ordered
|
||||
function[:args].each do |arg|
|
||||
lines << " #{arg[:type]} Expected_#{arg[:name]};\n"
|
||||
end
|
||||
@@ -35,27 +34,25 @@ class CMockGeneratorPluginExpect
|
||||
end
|
||||
|
||||
def mock_function_declarations(function)
|
||||
if (function[:args].empty?)
|
||||
if (function[:return][:void?])
|
||||
return "#define #{function[:name]}_Expect() #{function[:name]}_CMockExpect(__LINE__)\n" +
|
||||
if function[:args].empty?
|
||||
if function[:return][:void?]
|
||||
"#define #{function[:name]}_Expect() #{function[:name]}_CMockExpect(__LINE__)\n" \
|
||||
"void #{function[:name]}_CMockExpect(UNITY_LINE_TYPE cmock_line);\n"
|
||||
else
|
||||
return "#define #{function[:name]}_ExpectAndReturn(cmock_retval) #{function[:name]}_CMockExpectAndReturn(__LINE__, cmock_retval)\n" +
|
||||
"#define #{function[:name]}_ExpectAndReturn(cmock_retval) #{function[:name]}_CMockExpectAndReturn(__LINE__, cmock_retval)\n" \
|
||||
"void #{function[:name]}_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]});\n"
|
||||
end
|
||||
elsif function[:return][:void?]
|
||||
"#define #{function[:name]}_Expect(#{function[:args_call]}) #{function[:name]}_CMockExpect(__LINE__, #{function[:args_call]})\n" \
|
||||
"void #{function[:name]}_CMockExpect(UNITY_LINE_TYPE cmock_line, #{function[:args_string]});\n"
|
||||
else
|
||||
if (function[:return][:void?])
|
||||
return "#define #{function[:name]}_Expect(#{function[:args_call]}) #{function[:name]}_CMockExpect(__LINE__, #{function[:args_call]})\n" +
|
||||
"void #{function[:name]}_CMockExpect(UNITY_LINE_TYPE cmock_line, #{function[:args_string]});\n"
|
||||
else
|
||||
return "#define #{function[:name]}_ExpectAndReturn(#{function[:args_call]}, cmock_retval) #{function[:name]}_CMockExpectAndReturn(__LINE__, #{function[:args_call]}, cmock_retval)\n" +
|
||||
"void #{function[:name]}_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:args_string]}, #{function[:return][:str]});\n"
|
||||
end
|
||||
"#define #{function[:name]}_ExpectAndReturn(#{function[:args_call]}, cmock_retval) #{function[:name]}_CMockExpectAndReturn(__LINE__, #{function[:args_call]}, cmock_retval)\n" \
|
||||
"void #{function[:name]}_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:args_string]}, #{function[:return][:str]});\n"
|
||||
end
|
||||
end
|
||||
|
||||
def mock_implementation_always_check_args(function)
|
||||
lines = ""
|
||||
lines = ''
|
||||
function[:args].each do |arg|
|
||||
lines << @utils.code_verify_an_arg_expectation(function, arg)
|
||||
end
|
||||
@@ -63,7 +60,8 @@ class CMockGeneratorPluginExpect
|
||||
end
|
||||
|
||||
def mock_implementation_might_check_args(function)
|
||||
return "" if (function[:args].empty?)
|
||||
return '' if function[:args].empty?
|
||||
|
||||
lines = " if (!cmock_call_instance->ExpectAnyArgsBool)\n {\n"
|
||||
function[:args].each do |arg|
|
||||
lines << @utils.code_verify_an_arg_expectation(function, arg)
|
||||
@@ -73,31 +71,30 @@ class CMockGeneratorPluginExpect
|
||||
end
|
||||
|
||||
def mock_interfaces(function)
|
||||
lines = ""
|
||||
lines = ''
|
||||
func_name = function[:name]
|
||||
if (function[:return][:void?])
|
||||
if (function[:args_string] == "void")
|
||||
lines << "void #{func_name}_CMockExpect(UNITY_LINE_TYPE cmock_line)\n{\n"
|
||||
else
|
||||
lines << "void #{func_name}_CMockExpect(UNITY_LINE_TYPE cmock_line, #{function[:args_string]})\n{\n"
|
||||
end
|
||||
else
|
||||
if (function[:args_string] == "void")
|
||||
lines << "void #{func_name}_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]})\n{\n"
|
||||
else
|
||||
lines << "void #{func_name}_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:args_string]}, #{function[:return][:str]})\n{\n"
|
||||
end
|
||||
end
|
||||
lines << if function[:return][:void?]
|
||||
if function[:args_string] == 'void'
|
||||
"void #{func_name}_CMockExpect(UNITY_LINE_TYPE cmock_line)\n{\n"
|
||||
else
|
||||
"void #{func_name}_CMockExpect(UNITY_LINE_TYPE cmock_line, #{function[:args_string]})\n{\n"
|
||||
end
|
||||
elsif function[:args_string] == 'void'
|
||||
"void #{func_name}_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]})\n{\n"
|
||||
else
|
||||
"void #{func_name}_CMockExpectAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:args_string]}, #{function[:return][:str]})\n{\n"
|
||||
end
|
||||
lines << @utils.code_add_base_expectation(func_name)
|
||||
lines << @utils.code_call_argument_loader(function)
|
||||
lines << @utils.code_assign_argument_quickly("cmock_call_instance->ReturnVal", function[:return]) unless (function[:return][:void?])
|
||||
lines << @utils.code_assign_argument_quickly('cmock_call_instance->ReturnVal', function[:return]) unless function[:return][:void?]
|
||||
lines << "}\n\n"
|
||||
end
|
||||
|
||||
def mock_verify(function)
|
||||
" UNITY_SET_DETAIL(CMockString_#{function[:name]});\n" +
|
||||
" UNITY_TEST_ASSERT(CMOCK_GUTS_NONE == call_instance, cmock_line, CMockStringCalledLess);\n" +
|
||||
" UNITY_CLR_DETAILS();\n"
|
||||
" if (CMOCK_GUTS_NONE != call_instance)\n" \
|
||||
" {\n" \
|
||||
" UNITY_SET_DETAIL(CMockString_#{function[:name]});\n" \
|
||||
" UNITY_TEST_FAIL(cmock_line, CMockStringCalledLess);\n" \
|
||||
" }\n"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# ==========================================
|
||||
|
||||
class CMockGeneratorPluginExpectAnyArgs
|
||||
|
||||
attr_reader :priority
|
||||
attr_reader :config, :utils
|
||||
|
||||
@@ -15,39 +14,37 @@ class CMockGeneratorPluginExpectAnyArgs
|
||||
@priority = 3
|
||||
end
|
||||
|
||||
def instance_typedefs(function)
|
||||
" int ExpectAnyArgsBool;\n"
|
||||
def instance_typedefs(_function)
|
||||
" char ExpectAnyArgsBool;\n"
|
||||
end
|
||||
|
||||
def mock_function_declarations(function)
|
||||
unless (function[:args].empty?)
|
||||
if (function[:return][:void?])
|
||||
return "#define #{function[:name]}_ExpectAnyArgs() #{function[:name]}_CMockExpectAnyArgs(__LINE__)\n" +
|
||||
"void #{function[:name]}_CMockExpectAnyArgs(UNITY_LINE_TYPE cmock_line);\n"
|
||||
else
|
||||
return "#define #{function[:name]}_ExpectAnyArgsAndReturn(cmock_retval) #{function[:name]}_CMockExpectAnyArgsAndReturn(__LINE__, cmock_retval)\n" +
|
||||
"void #{function[:name]}_CMockExpectAnyArgsAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]});\n"
|
||||
end
|
||||
if function[:args].empty?
|
||||
''
|
||||
elsif function[:return][:void?]
|
||||
"#define #{function[:name]}_ExpectAnyArgs() #{function[:name]}_CMockExpectAnyArgs(__LINE__)\n" \
|
||||
"void #{function[:name]}_CMockExpectAnyArgs(UNITY_LINE_TYPE cmock_line);\n"
|
||||
else
|
||||
""
|
||||
"#define #{function[:name]}_ExpectAnyArgsAndReturn(cmock_retval) #{function[:name]}_CMockExpectAnyArgsAndReturn(__LINE__, cmock_retval)\n" \
|
||||
"void #{function[:name]}_CMockExpectAnyArgsAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]});\n"
|
||||
end
|
||||
end
|
||||
|
||||
def mock_interfaces(function)
|
||||
lines = ""
|
||||
unless (function[:args].empty?)
|
||||
if (function[:return][:void?])
|
||||
lines << "void #{function[:name]}_CMockExpectAnyArgs(UNITY_LINE_TYPE cmock_line)\n{\n"
|
||||
else
|
||||
lines << "void #{function[:name]}_CMockExpectAnyArgsAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]})\n{\n"
|
||||
end
|
||||
lines = ''
|
||||
unless function[:args].empty?
|
||||
lines << if function[:return][:void?]
|
||||
"void #{function[:name]}_CMockExpectAnyArgs(UNITY_LINE_TYPE cmock_line)\n{\n"
|
||||
else
|
||||
"void #{function[:name]}_CMockExpectAnyArgsAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]})\n{\n"
|
||||
end
|
||||
lines << @utils.code_add_base_expectation(function[:name], true)
|
||||
unless (function[:return][:void?])
|
||||
unless function[:return][:void?]
|
||||
lines << " cmock_call_instance->ReturnVal = cmock_to_return;\n"
|
||||
end
|
||||
lines << " cmock_call_instance->ExpectAnyArgsBool = (int)1;\n"
|
||||
lines << " cmock_call_instance->ExpectAnyArgsBool = (char)1;\n"
|
||||
lines << "}\n\n"
|
||||
end
|
||||
return lines
|
||||
lines
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# ==========================================
|
||||
|
||||
class CMockGeneratorPluginIgnore
|
||||
|
||||
attr_reader :priority
|
||||
attr_reader :config, :utils
|
||||
|
||||
@@ -16,56 +15,70 @@ class CMockGeneratorPluginIgnore
|
||||
end
|
||||
|
||||
def instance_structure(function)
|
||||
if (function[:return][:void?])
|
||||
" int #{function[:name]}_IgnoreBool;\n"
|
||||
if function[:return][:void?]
|
||||
" char #{function[:name]}_IgnoreBool;\n"
|
||||
else
|
||||
" int #{function[:name]}_IgnoreBool;\n #{function[:return][:type]} #{function[:name]}_FinalReturn;\n"
|
||||
" char #{function[:name]}_IgnoreBool;\n #{function[:return][:type]} #{function[:name]}_FinalReturn;\n"
|
||||
end
|
||||
end
|
||||
|
||||
def mock_function_declarations(function)
|
||||
if (function[:return][:void?])
|
||||
return "#define #{function[:name]}_Ignore() #{function[:name]}_CMockIgnore()\n" +
|
||||
"void #{function[:name]}_CMockIgnore(void);\n"
|
||||
else
|
||||
return "#define #{function[:name]}_IgnoreAndReturn(cmock_retval) #{function[:name]}_CMockIgnoreAndReturn(__LINE__, cmock_retval)\n" +
|
||||
"void #{function[:name]}_CMockIgnoreAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]});\n"
|
||||
end
|
||||
lines = if function[:return][:void?]
|
||||
"#define #{function[:name]}_Ignore() #{function[:name]}_CMockIgnore()\n" \
|
||||
"void #{function[:name]}_CMockIgnore(void);\n"
|
||||
else
|
||||
"#define #{function[:name]}_IgnoreAndReturn(cmock_retval) #{function[:name]}_CMockIgnoreAndReturn(__LINE__, cmock_retval)\n" \
|
||||
"void #{function[:name]}_CMockIgnoreAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]});\n"
|
||||
end
|
||||
|
||||
# Add stop ignore function. it does not matter if there are any args
|
||||
lines << "#define #{function[:name]}_StopIgnore() #{function[:name]}_CMockStopIgnore()\n" \
|
||||
"void #{function[:name]}_CMockStopIgnore(void);\n"
|
||||
lines
|
||||
end
|
||||
|
||||
def mock_implementation_precheck(function)
|
||||
lines = " if (Mock.#{function[:name]}_IgnoreBool)\n {\n"
|
||||
lines << " UNITY_CLR_DETAILS();\n"
|
||||
if (function[:return][:void?])
|
||||
if function[:return][:void?]
|
||||
lines << " return;\n }\n"
|
||||
else
|
||||
retval = function[:return].merge( { :name => "cmock_call_instance->ReturnVal"} )
|
||||
retval = function[:return].merge(:name => 'cmock_call_instance->ReturnVal')
|
||||
lines << " if (cmock_call_instance == NULL)\n return Mock.#{function[:name]}_FinalReturn;\n"
|
||||
lines << " " + @utils.code_assign_argument_quickly("Mock.#{function[:name]}_FinalReturn", retval) unless (retval[:void?])
|
||||
lines << ' ' + @utils.code_assign_argument_quickly("Mock.#{function[:name]}_FinalReturn", retval) unless retval[:void?]
|
||||
lines << " return cmock_call_instance->ReturnVal;\n }\n"
|
||||
end
|
||||
lines
|
||||
end
|
||||
|
||||
def mock_interfaces(function)
|
||||
lines = ""
|
||||
if (function[:return][:void?])
|
||||
lines << "void #{function[:name]}_CMockIgnore(void)\n{\n"
|
||||
else
|
||||
lines << "void #{function[:name]}_CMockIgnoreAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]})\n{\n"
|
||||
end
|
||||
if (!function[:return][:void?])
|
||||
lines = ''
|
||||
lines << if function[:return][:void?]
|
||||
"void #{function[:name]}_CMockIgnore(void)\n{\n"
|
||||
else
|
||||
"void #{function[:name]}_CMockIgnoreAndReturn(UNITY_LINE_TYPE cmock_line, #{function[:return][:str]})\n{\n"
|
||||
end
|
||||
unless function[:return][:void?]
|
||||
lines << @utils.code_add_base_expectation(function[:name], false)
|
||||
end
|
||||
unless (function[:return][:void?])
|
||||
unless function[:return][:void?]
|
||||
lines << " cmock_call_instance->ReturnVal = cmock_to_return;\n"
|
||||
end
|
||||
lines << " Mock.#{function[:name]}_IgnoreBool = (int)1;\n"
|
||||
lines << " Mock.#{function[:name]}_IgnoreBool = (char)1;\n"
|
||||
lines << "}\n\n"
|
||||
|
||||
# Add stop ignore function. it does not matter if there are any args
|
||||
lines << "void #{function[:name]}_CMockStopIgnore(void)\n{\n"
|
||||
unless function[:return][:void?]
|
||||
lines << " if(Mock.#{function[:name]}_IgnoreBool)\n"
|
||||
lines << " Mock.#{function[:name]}_CallInstance = CMock_Guts_MemNext(Mock.#{function[:name]}_CallInstance);\n"
|
||||
end
|
||||
lines << " Mock.#{function[:name]}_IgnoreBool = (char)0;\n"
|
||||
lines << "}\n\n"
|
||||
end
|
||||
|
||||
def mock_ignore(function)
|
||||
" Mock.#{function[:name]}_IgnoreBool = (int) 1;\n"
|
||||
" Mock.#{function[:name]}_IgnoreBool = (char) 1;\n"
|
||||
end
|
||||
|
||||
def mock_verify(function)
|
||||
|
||||
@@ -2,21 +2,21 @@ class CMockGeneratorPluginIgnoreArg
|
||||
attr_reader :priority
|
||||
attr_accessor :utils
|
||||
|
||||
def initialize(config, utils)
|
||||
def initialize(_config, utils)
|
||||
@utils = utils
|
||||
@priority = 10
|
||||
end
|
||||
|
||||
def instance_typedefs(function)
|
||||
lines = ""
|
||||
lines = ''
|
||||
function[:args].each do |arg|
|
||||
lines << " int IgnoreArg_#{arg[:name]};\n"
|
||||
lines << " char IgnoreArg_#{arg[:name]};\n"
|
||||
end
|
||||
lines
|
||||
end
|
||||
|
||||
def mock_function_declarations(function)
|
||||
lines = ""
|
||||
lines = ''
|
||||
function[:args].each do |arg|
|
||||
lines << "#define #{function[:name]}_IgnoreArg_#{arg[:name]}()"
|
||||
lines << " #{function[:name]}_CMockIgnoreArg_#{arg[:name]}(__LINE__)\n"
|
||||
@@ -31,8 +31,8 @@ class CMockGeneratorPluginIgnoreArg
|
||||
function[:args].each do |arg|
|
||||
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 << " 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 << "}\n\n"
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
# ==========================================
|
||||
# CMock Project - Automatic Mock Generation for C
|
||||
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
# [Released under MIT License. Please refer to license.txt for details]
|
||||
# ==========================================
|
||||
|
||||
class CMockGeneratorPluginIgnoreStateless
|
||||
attr_reader :priority
|
||||
attr_reader :config, :utils
|
||||
|
||||
def initialize(config, utils)
|
||||
@config = config
|
||||
@utils = utils
|
||||
@priority = 2
|
||||
end
|
||||
|
||||
def instance_structure(function)
|
||||
if function[:return][:void?]
|
||||
" char #{function[:name]}_IgnoreBool;\n"
|
||||
else
|
||||
" char #{function[:name]}_IgnoreBool;\n #{function[:return][:type]} #{function[:name]}_FinalReturn;\n"
|
||||
end
|
||||
end
|
||||
|
||||
def mock_function_declarations(function)
|
||||
lines = if function[:return][:void?]
|
||||
"#define #{function[:name]}_Ignore() #{function[:name]}_CMockIgnore()\n" \
|
||||
"void #{function[:name]}_CMockIgnore(void);\n"
|
||||
else
|
||||
"#define #{function[:name]}_IgnoreAndReturn(cmock_retval) #{function[:name]}_CMockIgnoreAndReturn(cmock_retval)\n" \
|
||||
"void #{function[:name]}_CMockIgnoreAndReturn(#{function[:return][:str]});\n"
|
||||
end
|
||||
|
||||
# Add stop ignore function. it does not matter if there are any args
|
||||
lines << "#define #{function[:name]}_StopIgnore() #{function[:name]}_CMockStopIgnore()\n" \
|
||||
"void #{function[:name]}_CMockStopIgnore(void);\n"
|
||||
lines
|
||||
end
|
||||
|
||||
def mock_implementation_precheck(function)
|
||||
lines = " if (Mock.#{function[:name]}_IgnoreBool)\n {\n"
|
||||
lines << " UNITY_CLR_DETAILS();\n"
|
||||
if function[:return][:void?]
|
||||
lines << " return;\n }\n"
|
||||
else
|
||||
retval = function[:return].merge(:name => 'cmock_call_instance->ReturnVal')
|
||||
lines << " if (cmock_call_instance == NULL)\n return Mock.#{function[:name]}_FinalReturn;\n"
|
||||
lines << ' ' + @utils.code_assign_argument_quickly("Mock.#{function[:name]}_FinalReturn", retval) unless retval[:void?]
|
||||
lines << " return cmock_call_instance->ReturnVal;\n }\n"
|
||||
end
|
||||
lines
|
||||
end
|
||||
|
||||
# this function is adjusted
|
||||
def mock_interfaces(function)
|
||||
lines = ''
|
||||
lines << if function[:return][:void?]
|
||||
"void #{function[:name]}_CMockIgnore(void)\n{\n"
|
||||
else
|
||||
"void #{function[:name]}_CMockIgnoreAndReturn(#{function[:return][:str]})\n{\n"
|
||||
end
|
||||
unless function[:return][:void?]
|
||||
lines << " Mock.#{function[:name]}_CallInstance = CMOCK_GUTS_NONE;\n"
|
||||
lines << " Mock.#{function[:name]}_FinalReturn = cmock_to_return;\n"
|
||||
end
|
||||
lines << " Mock.#{function[:name]}_IgnoreBool = (char)1;\n"
|
||||
lines << "}\n\n"
|
||||
|
||||
# Add stop ignore function. it does not matter if there are any args
|
||||
lines << "void #{function[:name]}_CMockStopIgnore(void)\n{\n"
|
||||
lines << " Mock.#{function[:name]}_IgnoreBool = (char)0;\n"
|
||||
lines << "}\n\n"
|
||||
|
||||
lines
|
||||
end
|
||||
|
||||
def mock_ignore(function)
|
||||
" Mock.#{function[:name]}_IgnoreBool = (char)1;\n"
|
||||
end
|
||||
|
||||
def mock_verify(function)
|
||||
func_name = function[:name]
|
||||
" if (Mock.#{func_name}_IgnoreBool)\n call_instance = CMOCK_GUTS_NONE;\n"
|
||||
end
|
||||
end
|
||||
@@ -2,41 +2,41 @@ class CMockGeneratorPluginReturnThruPtr
|
||||
attr_reader :priority
|
||||
attr_accessor :utils
|
||||
|
||||
def initialize(config, utils)
|
||||
def initialize(_config, utils)
|
||||
@utils = utils
|
||||
@priority = 9
|
||||
end
|
||||
|
||||
def instance_typedefs(function)
|
||||
lines = ""
|
||||
lines = ''
|
||||
function[:args].each do |arg|
|
||||
if (@utils.ptr_or_str?(arg[:type]) and not arg[:const?])
|
||||
lines << " int ReturnThruPtr_#{arg[:name]}_Used;\n"
|
||||
lines << " #{arg[:type]} ReturnThruPtr_#{arg[:name]}_Val;\n"
|
||||
lines << " int ReturnThruPtr_#{arg[:name]}_Size;\n"
|
||||
end
|
||||
next unless @utils.ptr_or_str?(arg[:type]) && !(arg[:const?])
|
||||
|
||||
lines << " char ReturnThruPtr_#{arg[:name]}_Used;\n"
|
||||
lines << " #{arg[:type]} ReturnThruPtr_#{arg[:name]}_Val;\n"
|
||||
lines << " size_t ReturnThruPtr_#{arg[:name]}_Size;\n"
|
||||
end
|
||||
lines
|
||||
end
|
||||
|
||||
def mock_function_declarations(function)
|
||||
lines = ""
|
||||
lines = ''
|
||||
function[:args].each do |arg|
|
||||
if (@utils.ptr_or_str?(arg[:type]) and not arg[:const?])
|
||||
lines << "#define #{function[:name]}_ReturnThruPtr_#{arg[:name]}(#{arg[:name]})"
|
||||
# If the pointer type actually contains an asterisk, we can do sizeof the type (super safe), otherwise
|
||||
# we need to do a sizeof the dereferenced pointer (which could be a problem if give the wrong size
|
||||
if (arg[:type][-1] == '*')
|
||||
lines << " #{function[:name]}_CMockReturnMemThruPtr_#{arg[:name]}(__LINE__, #{arg[:name]}, sizeof(#{arg[:type][0..-2]}))\n"
|
||||
else
|
||||
lines << " #{function[:name]}_CMockReturnMemThruPtr_#{arg[:name]}(__LINE__, #{arg[:name]}, sizeof(*#{arg[:name]}))\n"
|
||||
end
|
||||
lines << "#define #{function[:name]}_ReturnArrayThruPtr_#{arg[:name]}(#{arg[:name]}, cmock_len)"
|
||||
lines << " #{function[:name]}_CMockReturnMemThruPtr_#{arg[:name]}(__LINE__, #{arg[:name]}, (int)(cmock_len * (int)sizeof(*#{arg[:name]})))\n"
|
||||
lines << "#define #{function[:name]}_ReturnMemThruPtr_#{arg[:name]}(#{arg[:name]}, cmock_size)"
|
||||
lines << " #{function[:name]}_CMockReturnMemThruPtr_#{arg[:name]}(__LINE__, #{arg[:name]}, cmock_size)\n"
|
||||
lines << "void #{function[:name]}_CMockReturnMemThruPtr_#{arg[:name]}(UNITY_LINE_TYPE cmock_line, #{arg[:type]} #{arg[:name]}, int cmock_size);\n"
|
||||
end
|
||||
next unless @utils.ptr_or_str?(arg[:type]) && !(arg[:const?])
|
||||
|
||||
lines << "#define #{function[:name]}_ReturnThruPtr_#{arg[:name]}(#{arg[:name]})"
|
||||
# If the pointer type actually contains an asterisk, we can do sizeof the type (super safe), otherwise
|
||||
# we need to do a sizeof the dereferenced pointer (which could be a problem if give the wrong size
|
||||
lines << if arg[:type][-1] == '*'
|
||||
" #{function[:name]}_CMockReturnMemThruPtr_#{arg[:name]}(__LINE__, #{arg[:name]}, sizeof(#{arg[:type][0..-2]}))\n"
|
||||
else
|
||||
" #{function[:name]}_CMockReturnMemThruPtr_#{arg[:name]}(__LINE__, #{arg[:name]}, sizeof(*#{arg[:name]}))\n"
|
||||
end
|
||||
lines << "#define #{function[:name]}_ReturnArrayThruPtr_#{arg[:name]}(#{arg[:name]}, cmock_len)"
|
||||
lines << " #{function[:name]}_CMockReturnMemThruPtr_#{arg[:name]}(__LINE__, #{arg[:name]}, cmock_len * sizeof(*#{arg[:name]}))\n"
|
||||
lines << "#define #{function[:name]}_ReturnMemThruPtr_#{arg[:name]}(#{arg[:name]}, cmock_size)"
|
||||
lines << " #{function[:name]}_CMockReturnMemThruPtr_#{arg[:name]}(__LINE__, #{arg[:name]}, cmock_size)\n"
|
||||
lines << "void #{function[:name]}_CMockReturnMemThruPtr_#{arg[:name]}(UNITY_LINE_TYPE cmock_line, #{arg[:type]} #{arg[:name]}, size_t cmock_size);\n"
|
||||
end
|
||||
lines
|
||||
end
|
||||
@@ -46,17 +46,17 @@ class CMockGeneratorPluginReturnThruPtr
|
||||
func_name = function[:name]
|
||||
function[:args].each do |arg|
|
||||
arg_name = arg[:name]
|
||||
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"
|
||||
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, CMockStringPtrPreExp);\n"
|
||||
lines << " cmock_call_instance->ReturnThruPtr_#{arg_name}_Used = 1;\n"
|
||||
lines << " cmock_call_instance->ReturnThruPtr_#{arg_name}_Val = #{arg_name};\n"
|
||||
lines << " cmock_call_instance->ReturnThruPtr_#{arg_name}_Size = cmock_size;\n"
|
||||
lines << "}\n\n"
|
||||
end
|
||||
next unless @utils.ptr_or_str?(arg[:type]) && !(arg[:const?])
|
||||
|
||||
lines << "void #{func_name}_CMockReturnMemThruPtr_#{arg_name}(UNITY_LINE_TYPE cmock_line, #{arg[:type]} #{arg_name}, size_t cmock_size)\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, CMockStringPtrPreExp);\n"
|
||||
lines << " cmock_call_instance->ReturnThruPtr_#{arg_name}_Used = 1;\n"
|
||||
lines << " cmock_call_instance->ReturnThruPtr_#{arg_name}_Val = #{arg_name};\n"
|
||||
lines << " cmock_call_instance->ReturnThruPtr_#{arg_name}_Size = cmock_size;\n"
|
||||
lines << "}\n\n"
|
||||
end
|
||||
lines
|
||||
end
|
||||
@@ -65,14 +65,14 @@ class CMockGeneratorPluginReturnThruPtr
|
||||
lines = []
|
||||
function[:args].each do |arg|
|
||||
arg_name = arg[:name]
|
||||
if (@utils.ptr_or_str?(arg[:type]) and not arg[:const?])
|
||||
lines << " if (cmock_call_instance->ReturnThruPtr_#{arg_name}_Used)\n"
|
||||
lines << " {\n"
|
||||
lines << " UNITY_TEST_ASSERT_NOT_NULL(#{arg_name}, cmock_line, CMockStringPtrIsNULL);\n"
|
||||
lines << " memcpy((void*)#{arg_name}, (void*)cmock_call_instance->ReturnThruPtr_#{arg_name}_Val,\n"
|
||||
lines << " cmock_call_instance->ReturnThruPtr_#{arg_name}_Size);\n"
|
||||
lines << " }\n"
|
||||
end
|
||||
next unless @utils.ptr_or_str?(arg[:type]) && !(arg[:const?])
|
||||
|
||||
lines << " if (cmock_call_instance->ReturnThruPtr_#{arg_name}_Used)\n"
|
||||
lines << " {\n"
|
||||
lines << " UNITY_TEST_ASSERT_NOT_NULL(#{arg_name}, cmock_line, CMockStringPtrIsNULL);\n"
|
||||
lines << " memcpy((void*)#{arg_name}, (void*)cmock_call_instance->ReturnThruPtr_#{arg_name}_Val,\n"
|
||||
lines << " cmock_call_instance->ReturnThruPtr_#{arg_name}_Size);\n"
|
||||
lines << " }\n"
|
||||
end
|
||||
lines
|
||||
end
|
||||
|
||||
+122
-125
@@ -5,10 +5,9 @@
|
||||
# ==========================================
|
||||
|
||||
class CMockGeneratorUtils
|
||||
|
||||
attr_accessor :config, :helpers, :ordered, :ptr_handling, :arrays, :cexception
|
||||
|
||||
def initialize(config, helpers={})
|
||||
def initialize(config, helpers = {})
|
||||
@config = config
|
||||
@ptr_handling = @config.when_ptr
|
||||
@ordered = @config.enforce_strict_ordering
|
||||
@@ -16,9 +15,10 @@ class CMockGeneratorUtils
|
||||
@cexception = @config.plugins.include? :cexception
|
||||
@expect_any = @config.plugins.include? :expect_any_args
|
||||
@return_thru_ptr = @config.plugins.include? :return_thru_ptr
|
||||
@ignore_arg = @config.plugins.include? :ignore_arg
|
||||
@ignore = @config.plugins.include? :ignore
|
||||
@treat_as = @config.treat_as
|
||||
@ignore_arg = @config.plugins.include? :ignore_arg
|
||||
@ignore = @config.plugins.include? :ignore
|
||||
@ignore_stateless = @config.plugins.include? :ignore_stateless
|
||||
@treat_as = @config.treat_as
|
||||
@helpers = helpers
|
||||
end
|
||||
|
||||
@@ -36,78 +36,78 @@ class CMockGeneratorUtils
|
||||
end
|
||||
|
||||
def code_verify_an_arg_expectation(function, arg)
|
||||
if (@arrays)
|
||||
case(@ptr_handling)
|
||||
when :smart then code_verify_an_arg_expectation_with_smart_arrays(function, arg)
|
||||
when :compare_data then code_verify_an_arg_expectation_with_normal_arrays(function, arg)
|
||||
when :compare_ptr then raise "ERROR: the array plugin doesn't enjoy working with :compare_ptr only. Disable one option."
|
||||
if @arrays
|
||||
case @ptr_handling
|
||||
when :smart then code_verify_an_arg_expectation_with_smart_arrays(function, arg)
|
||||
when :compare_data then code_verify_an_arg_expectation_with_normal_arrays(function, arg)
|
||||
when :compare_ptr then raise "ERROR: the array plugin doesn't enjoy working with :compare_ptr only. Disable one option."
|
||||
end
|
||||
else
|
||||
code_verify_an_arg_expectation_with_no_arrays(function, arg)
|
||||
end
|
||||
end
|
||||
|
||||
def code_add_base_expectation(func_name, global_ordering_supported=true)
|
||||
def code_add_base_expectation(func_name, global_ordering_supported = true)
|
||||
lines = " CMOCK_MEM_INDEX_TYPE cmock_guts_index = CMock_Guts_MemNew(sizeof(CMOCK_#{func_name}_CALL_INSTANCE));\n"
|
||||
lines << " CMOCK_#{func_name}_CALL_INSTANCE* cmock_call_instance = (CMOCK_#{func_name}_CALL_INSTANCE*)CMock_Guts_GetAddressFor(cmock_guts_index);\n"
|
||||
lines << " UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringOutOfMemory);\n"
|
||||
lines << " memset(cmock_call_instance, 0, sizeof(*cmock_call_instance));\n"
|
||||
lines << " Mock.#{func_name}_CallInstance = CMock_Guts_MemChain(Mock.#{func_name}_CallInstance, cmock_guts_index);\n"
|
||||
lines << " Mock.#{func_name}_IgnoreBool = (int)0;\n" if (@ignore)
|
||||
lines << " Mock.#{func_name}_IgnoreBool = (char)0;\n" if @ignore || @ignore_stateless
|
||||
lines << " cmock_call_instance->LineNumber = cmock_line;\n"
|
||||
lines << " cmock_call_instance->CallOrder = ++GlobalExpectCount;\n" if (@ordered and global_ordering_supported)
|
||||
lines << " cmock_call_instance->ExceptionToThrow = CEXCEPTION_NONE;\n" if (@cexception)
|
||||
lines << " cmock_call_instance->ExpectAnyArgsBool = (int)0;\n" if (@expect_any)
|
||||
lines << " cmock_call_instance->CallOrder = ++GlobalExpectCount;\n" if @ordered && global_ordering_supported
|
||||
lines << " cmock_call_instance->ExceptionToThrow = CEXCEPTION_NONE;\n" if @cexception
|
||||
lines << " cmock_call_instance->ExpectAnyArgsBool = (char)0;\n" if @expect_any
|
||||
lines
|
||||
end
|
||||
|
||||
def code_add_an_arg_expectation(arg, depth=1)
|
||||
def code_add_an_arg_expectation(arg, depth = 1)
|
||||
lines = code_assign_argument_quickly("cmock_call_instance->Expected_#{arg[:name]}", arg)
|
||||
lines << " cmock_call_instance->Expected_#{arg[:name]}_Depth = #{arg[:name]}_Depth;\n" if (@arrays and (depth.class == String))
|
||||
lines << " cmock_call_instance->IgnoreArg_#{arg[:name]} = 0;\n" if (@ignore_arg)
|
||||
lines << " cmock_call_instance->ReturnThruPtr_#{arg[:name]}_Used = 0;\n" if (@return_thru_ptr and ptr_or_str?(arg[:type]) and not arg[:const?])
|
||||
lines << " cmock_call_instance->Expected_#{arg[:name]}_Depth = #{arg[:name]}_Depth;\n" if @arrays && (depth.class == String)
|
||||
lines << " cmock_call_instance->IgnoreArg_#{arg[:name]} = 0;\n" if @ignore_arg
|
||||
lines << " cmock_call_instance->ReturnThruPtr_#{arg[:name]}_Used = 0;\n" if @return_thru_ptr && ptr_or_str?(arg[:type]) && !(arg[:const?])
|
||||
lines
|
||||
end
|
||||
|
||||
def code_assign_argument_quickly(dest, arg)
|
||||
if (arg[:ptr?] or @treat_as.include?(arg[:type]))
|
||||
if arg[:ptr?] || @treat_as.include?(arg[:type])
|
||||
" #{dest} = #{arg[:name]};\n"
|
||||
else
|
||||
assert_expr = "sizeof(#{arg[:name]}) == sizeof(#{arg[:type]}) ? 1 : -1"
|
||||
comment = "/* add #{arg[:type]} to :treat_as_array if this causes an error */"
|
||||
" memcpy((void*)(&#{dest}), (void*)(&#{arg[:name]}),\n" +
|
||||
" sizeof(#{arg[:type]}[#{assert_expr}])); #{comment}\n"
|
||||
" memcpy((void*)(&#{dest}), (void*)(&#{arg[:name]}),\n" \
|
||||
" sizeof(#{arg[:type]}[#{assert_expr}])); #{comment}\n"
|
||||
end
|
||||
end
|
||||
|
||||
def code_add_argument_loader(function)
|
||||
if (function[:args_string] != "void")
|
||||
if (@arrays)
|
||||
if function[:args_string] != 'void'
|
||||
if @arrays
|
||||
args_string = function[:args].map do |m|
|
||||
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" +
|
||||
"void CMockExpectParameters_#{function[:name]}(CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance, #{args_string})\n{\n" +
|
||||
function[:args].inject("") { |all, arg| all + code_add_an_arg_expectation(arg, (arg[:ptr?] ? "#{arg[:name]}_Depth" : 1) ) } +
|
||||
"}\n\n"
|
||||
"void CMockExpectParameters_#{function[:name]}(CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance, #{args_string});\n" \
|
||||
"void CMockExpectParameters_#{function[:name]}(CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance, #{args_string})\n{\n" +
|
||||
function[:args].inject('') { |all, arg| all + code_add_an_arg_expectation(arg, (arg[:ptr?] ? "#{arg[:name]}_Depth" : 1)) } +
|
||||
"}\n\n"
|
||||
else
|
||||
"void CMockExpectParameters_#{function[:name]}(CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance, #{function[:args_string]});\n" +
|
||||
"void CMockExpectParameters_#{function[:name]}(CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance, #{function[:args_string]})\n{\n" +
|
||||
function[:args].inject("") { |all, arg| all + code_add_an_arg_expectation(arg) } +
|
||||
"}\n\n"
|
||||
"void CMockExpectParameters_#{function[:name]}(CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance, #{function[:args_string]});\n" \
|
||||
"void CMockExpectParameters_#{function[:name]}(CMOCK_#{function[:name]}_CALL_INSTANCE* cmock_call_instance, #{function[:args_string]})\n{\n" +
|
||||
function[:args].inject('') { |all, arg| all + code_add_an_arg_expectation(arg) } +
|
||||
"}\n\n"
|
||||
end
|
||||
else
|
||||
""
|
||||
''
|
||||
end
|
||||
end
|
||||
|
||||
def code_call_argument_loader(function)
|
||||
if (function[:args_string] != "void")
|
||||
if function[:args_string] != 'void'
|
||||
args = function[:args].map do |m|
|
||||
if (@arrays and m[:ptr?] and not m[:array_data?])
|
||||
if @arrays && m[:ptr?] && !(m[:array_data?])
|
||||
"#{m[:name]}, 1"
|
||||
elsif (@arrays and m[:array_size?])
|
||||
elsif @arrays && m[:array_size?]
|
||||
"#{m[:name]}, #{m[:name]}"
|
||||
else
|
||||
m[:name]
|
||||
@@ -115,60 +115,60 @@ class CMockGeneratorUtils
|
||||
end
|
||||
" CMockExpectParameters_#{function[:name]}(cmock_call_instance, #{args.join(', ')});\n"
|
||||
else
|
||||
""
|
||||
''
|
||||
end
|
||||
end
|
||||
|
||||
def ptr_or_str?(arg_type)
|
||||
return (arg_type.include? '*' or
|
||||
@treat_as.fetch(arg_type, "").include? '*')
|
||||
(arg_type.include?('*') ||
|
||||
@treat_as.fetch(arg_type, '').include?('*'))
|
||||
end
|
||||
|
||||
#private ######################
|
||||
# private ######################
|
||||
|
||||
def lookup_expect_type(function, arg)
|
||||
def lookup_expect_type(_function, arg)
|
||||
c_type = arg[:type]
|
||||
arg_name = arg[:name]
|
||||
expected = "cmock_call_instance->Expected_#{arg_name}"
|
||||
ignore = "cmock_call_instance->IgnoreArg_#{arg_name}"
|
||||
unity_func = if ((arg[:ptr?]) and ((c_type =~ /\*\*/) or (@ptr_handling == :compare_ptr)))
|
||||
unity_func = if (arg[:ptr?]) && ((c_type =~ /\*\*/) || (@ptr_handling == :compare_ptr))
|
||||
['UNITY_TEST_ASSERT_EQUAL_PTR', '']
|
||||
else
|
||||
(@helpers.nil? or @helpers[:unity_helper].nil?) ? ["UNITY_TEST_ASSERT_EQUAL",''] : @helpers[:unity_helper].get_helper(c_type)
|
||||
@helpers.nil? || @helpers[:unity_helper].nil? ? ['UNITY_TEST_ASSERT_EQUAL', ''] : @helpers[:unity_helper].get_helper(c_type)
|
||||
end
|
||||
return c_type, arg_name, expected, ignore, unity_func[0], unity_func[1]
|
||||
[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 = lookup_expect_type(function, arg)
|
||||
lines = ""
|
||||
lines = ''
|
||||
lines << " if (!#{ignore})\n" if @ignore_arg
|
||||
lines << " {\n"
|
||||
lines << " UNITY_SET_DETAILS(CMockString_#{function[:name]},CMockString_#{arg_name});\n"
|
||||
case(unity_func)
|
||||
when "UNITY_TEST_ASSERT_EQUAL_MEMORY"
|
||||
c_type_local = c_type.gsub(/\*$/,'')
|
||||
lines << " UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type_local}), cmock_line, CMockStringMismatch);\n"
|
||||
when "UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY"
|
||||
if (pre == '&')
|
||||
lines << " UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*','')}), cmock_line, CMockStringMismatch);\n"
|
||||
else
|
||||
lines << " if (#{pre}#{expected} == NULL)\n"
|
||||
lines << " { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
|
||||
lines << " else\n"
|
||||
lines << " { UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*','')}), cmock_line, CMockStringMismatch); }\n"
|
||||
end
|
||||
when /_ARRAY/
|
||||
if (pre == '&')
|
||||
lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, 1, cmock_line, CMockStringMismatch);\n"
|
||||
else
|
||||
lines << " if (#{pre}#{expected} == NULL)\n"
|
||||
lines << " { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
|
||||
lines << " else\n"
|
||||
lines << " { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, 1, cmock_line, CMockStringMismatch); }\n"
|
||||
end
|
||||
case unity_func
|
||||
when 'UNITY_TEST_ASSERT_EQUAL_MEMORY'
|
||||
c_type_local = c_type.gsub(/\*$/, '')
|
||||
lines << " UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type_local}), cmock_line, CMockStringMismatch);\n"
|
||||
when 'UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY'
|
||||
if pre == '&'
|
||||
lines << " UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*', '')}), cmock_line, CMockStringMismatch);\n"
|
||||
else
|
||||
lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch);\n"
|
||||
lines << " if (#{pre}#{expected} == NULL)\n"
|
||||
lines << " { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
|
||||
lines << " else\n"
|
||||
lines << " { UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*', '')}), cmock_line, CMockStringMismatch); }\n"
|
||||
end
|
||||
when /_ARRAY/
|
||||
if pre == '&'
|
||||
lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, 1, cmock_line, CMockStringMismatch);\n"
|
||||
else
|
||||
lines << " if (#{pre}#{expected} == NULL)\n"
|
||||
lines << " { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
|
||||
lines << " else\n"
|
||||
lines << " { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, 1, cmock_line, CMockStringMismatch); }\n"
|
||||
end
|
||||
else
|
||||
lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch);\n"
|
||||
end
|
||||
lines << " }\n"
|
||||
lines
|
||||
@@ -176,78 +176,75 @@ class CMockGeneratorUtils
|
||||
|
||||
def code_verify_an_arg_expectation_with_normal_arrays(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 = ""
|
||||
depth_name = arg[:ptr?] ? "cmock_call_instance->Expected_#{arg_name}_Depth" : 1
|
||||
lines = ''
|
||||
lines << " if (!#{ignore})\n" if @ignore_arg
|
||||
lines << " {\n"
|
||||
lines << " UNITY_SET_DETAILS(CMockString_#{function[:name]},CMockString_#{arg_name});\n"
|
||||
lines << " if (#{pre}#{expected} != #{pre}#{arg_name}) {\n"
|
||||
case(unity_func)
|
||||
when "UNITY_TEST_ASSERT_EQUAL_MEMORY"
|
||||
c_type_local = c_type.gsub(/\*$/,'')
|
||||
lines << " UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type_local}), cmock_line, CMockStringMismatch);\n"
|
||||
when "UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY"
|
||||
if (pre == '&')
|
||||
lines << " UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*','')}), cmock_line, CMockStringMismatch);\n"
|
||||
else
|
||||
lines << " if (#{pre}#{expected} == NULL)\n"
|
||||
lines << " { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
|
||||
lines << " else\n"
|
||||
lines << " { UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*','')}), #{depth_name}, cmock_line, CMockStringMismatch); }\n"
|
||||
end
|
||||
when /_ARRAY/
|
||||
if (pre == '&')
|
||||
lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, CMockStringMismatch);\n"
|
||||
else
|
||||
lines << " if (#{pre}#{expected} == NULL)\n"
|
||||
lines << " { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
|
||||
lines << " else\n"
|
||||
lines << " { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, CMockStringMismatch); }\n"
|
||||
end
|
||||
case unity_func
|
||||
when 'UNITY_TEST_ASSERT_EQUAL_MEMORY'
|
||||
c_type_local = c_type.gsub(/\*$/, '')
|
||||
lines << " UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type_local}), cmock_line, CMockStringMismatch);\n"
|
||||
when 'UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY'
|
||||
if pre == '&'
|
||||
lines << " UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*', '')}), cmock_line, CMockStringMismatch);\n"
|
||||
else
|
||||
lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch);\n"
|
||||
lines << " if (#{pre}#{expected} == NULL)\n"
|
||||
lines << " { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
|
||||
lines << " else\n"
|
||||
lines << " { UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*', '')}), #{depth_name}, cmock_line, CMockStringMismatch); }\n"
|
||||
end
|
||||
when /_ARRAY/
|
||||
if pre == '&'
|
||||
lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, CMockStringMismatch);\n"
|
||||
else
|
||||
lines << " if (#{pre}#{expected} == NULL)\n"
|
||||
lines << " { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
|
||||
lines << " else\n"
|
||||
lines << " { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, CMockStringMismatch); }\n"
|
||||
end
|
||||
else
|
||||
lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch);\n"
|
||||
end
|
||||
lines << " }\n }\n"
|
||||
lines << " }\n"
|
||||
lines
|
||||
end
|
||||
|
||||
def code_verify_an_arg_expectation_with_smart_arrays(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 = ""
|
||||
depth_name = arg[:ptr?] ? "cmock_call_instance->Expected_#{arg_name}_Depth" : 1
|
||||
lines = ''
|
||||
lines << " if (!#{ignore})\n" if @ignore_arg
|
||||
lines << " {\n"
|
||||
lines << " UNITY_SET_DETAILS(CMockString_#{function[:name]},CMockString_#{arg_name});\n"
|
||||
lines << " if (#{pre}#{expected} != #{pre}#{arg_name}) {\n"
|
||||
case(unity_func)
|
||||
when "UNITY_TEST_ASSERT_EQUAL_MEMORY"
|
||||
c_type_local = c_type.gsub(/\*$/,'')
|
||||
lines << " UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type_local}), cmock_line, CMockStringMismatch);\n"
|
||||
when "UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY"
|
||||
if (pre == '&')
|
||||
lines << " UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*','')}), #{depth_name}, cmock_line, CMockStringMismatch);\n"
|
||||
else
|
||||
lines << " if (#{pre}#{expected} == NULL)\n"
|
||||
lines << " { UNITY_TEST_ASSERT_NULL(#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
|
||||
lines << ((depth_name != 1) ? " else if (#{depth_name} == 0)\n { UNITY_TEST_ASSERT_EQUAL_PTR(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch); }\n" : "")
|
||||
lines << " else\n"
|
||||
lines << " { UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*','')}), #{depth_name}, cmock_line, CMockStringMismatch); }\n"
|
||||
end
|
||||
when /_ARRAY/
|
||||
if (pre == '&')
|
||||
lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, CMockStringMismatch);\n"
|
||||
else
|
||||
lines << " if (#{pre}#{expected} == NULL)\n"
|
||||
lines << " { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
|
||||
lines << ((depth_name != 1) ? " else if (#{depth_name} == 0)\n { UNITY_TEST_ASSERT_EQUAL_PTR(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch); }\n" : "")
|
||||
lines << " else\n"
|
||||
lines << " { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, CMockStringMismatch); }\n"
|
||||
end
|
||||
case unity_func
|
||||
when 'UNITY_TEST_ASSERT_EQUAL_MEMORY'
|
||||
c_type_local = c_type.gsub(/\*$/, '')
|
||||
lines << " UNITY_TEST_ASSERT_EQUAL_MEMORY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type_local}), cmock_line, CMockStringMismatch);\n"
|
||||
when 'UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY'
|
||||
if pre == '&'
|
||||
lines << " UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*', '')}), #{depth_name}, cmock_line, CMockStringMismatch);\n"
|
||||
else
|
||||
lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch);\n"
|
||||
lines << " if (#{pre}#{expected} == NULL)\n"
|
||||
lines << " { UNITY_TEST_ASSERT_NULL(#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
|
||||
lines << (depth_name != 1 ? " else if (#{depth_name} == 0)\n { UNITY_TEST_ASSERT_EQUAL_PTR(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch); }\n" : '')
|
||||
lines << " else\n"
|
||||
lines << " { UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((void*)(#{pre}#{expected}), (void*)(#{pre}#{arg_name}), sizeof(#{c_type.sub('*', '')}), #{depth_name}, cmock_line, CMockStringMismatch); }\n"
|
||||
end
|
||||
when /_ARRAY/
|
||||
if pre == '&'
|
||||
lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, CMockStringMismatch);\n"
|
||||
else
|
||||
lines << " if (#{pre}#{expected} == NULL)\n"
|
||||
lines << " { UNITY_TEST_ASSERT_NULL(#{pre}#{arg_name}, cmock_line, CMockStringExpNULL); }\n"
|
||||
lines << (depth_name != 1 ? " else if (#{depth_name} == 0)\n { UNITY_TEST_ASSERT_EQUAL_PTR(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch); }\n" : '')
|
||||
lines << " else\n"
|
||||
lines << " { #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, #{depth_name}, cmock_line, CMockStringMismatch); }\n"
|
||||
end
|
||||
else
|
||||
lines << " #{unity_func}(#{pre}#{expected}, #{pre}#{arg_name}, cmock_line, CMockStringMismatch);\n"
|
||||
end
|
||||
lines << " }\n }\n"
|
||||
lines << " }\n"
|
||||
lines
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
+396
-137
@@ -5,54 +5,217 @@
|
||||
# ==========================================
|
||||
|
||||
class CMockHeaderParser
|
||||
|
||||
attr_accessor :funcs, :c_attr_noconst, :c_attributes, :treat_as_void, :treat_externs
|
||||
attr_accessor :funcs, :c_attr_noconst, :c_attributes, :treat_as_void, :treat_externs, :treat_inlines, :inline_function_patterns
|
||||
|
||||
def initialize(cfg)
|
||||
@funcs = []
|
||||
@c_strippables = cfg.strippables
|
||||
@c_attr_noconst = cfg.attributes.uniq - ['const']
|
||||
@c_attributes = ['const'] + c_attr_noconst
|
||||
@c_calling_conventions = cfg.c_calling_conventions.uniq
|
||||
@treat_as_array = cfg.treat_as_array
|
||||
@treat_as_void = (['void'] + cfg.treat_as_void).uniq
|
||||
@declaration_parse_matcher = /([\w\s\*\(\),\[\]]+??)\(([\w\s\*\(\),\.\[\]+-]*)\)$/m
|
||||
@standards = (['int','short','char','long','unsigned','signed'] + cfg.treat_as.keys).uniq
|
||||
@function_declaration_parse_base_match = '([\w\s\*\(\),\[\]]+??)\(([\w\s\*\(\),\.\[\]+\-\/]*)\)'
|
||||
@declaration_parse_matcher = /#{@function_declaration_parse_base_match}$/m
|
||||
@standards = (%w[int short char long unsigned signed] + cfg.treat_as.keys).uniq
|
||||
@array_size_name = cfg.array_size_name
|
||||
@array_size_type = (['int', 'size_t'] + cfg.array_size_type).uniq
|
||||
@array_size_type = (%w[int size_t] + cfg.array_size_type).uniq
|
||||
@when_no_prototypes = cfg.when_no_prototypes
|
||||
@local_as_void = @treat_as_void
|
||||
@verbosity = cfg.verbosity
|
||||
@treat_externs = cfg.treat_externs
|
||||
@c_strippables += ['extern'] if (@treat_externs == :include) #we'll need to remove the attribute if we're allowing externs
|
||||
@treat_inlines = cfg.treat_inlines
|
||||
@inline_function_patterns = cfg.inline_function_patterns
|
||||
@c_strippables += ['extern'] if @treat_externs == :include # we'll need to remove the attribute if we're allowing externs
|
||||
@c_strippables += ['inline'] if @treat_inlines == :include # we'll need to remove the attribute if we're allowing inlines
|
||||
end
|
||||
|
||||
def parse(name, source)
|
||||
@module_name = name.gsub(/\W/,'')
|
||||
@typedefs = []
|
||||
@funcs = []
|
||||
parse_project = {
|
||||
:module_name => name.gsub(/\W/, ''),
|
||||
:typedefs => [],
|
||||
:functions => [],
|
||||
:normalized_source => nil
|
||||
}
|
||||
|
||||
function_names = []
|
||||
|
||||
parse_functions( import_source(source) ).map do |decl|
|
||||
func = parse_declaration(decl)
|
||||
unless (function_names.include? func[:name])
|
||||
@funcs << func
|
||||
all_funcs = parse_functions(import_source(source, parse_project)).map { |item| [item] }
|
||||
all_funcs += parse_cpp_functions(import_source(source, parse_project, true))
|
||||
all_funcs.map do |decl|
|
||||
func = parse_declaration(parse_project, *decl)
|
||||
unless function_names.include? func[:name]
|
||||
parse_project[:functions] << func
|
||||
function_names << func[:name]
|
||||
end
|
||||
end
|
||||
|
||||
parse_project[:normalized_source] = if @treat_inlines == :include
|
||||
transform_inline_functions(source)
|
||||
else
|
||||
''
|
||||
end
|
||||
|
||||
{ :includes => nil,
|
||||
:functions => @funcs,
|
||||
:typedefs => @typedefs
|
||||
}
|
||||
:functions => parse_project[:functions],
|
||||
:typedefs => parse_project[:typedefs],
|
||||
:normalized_source => parse_project[:normalized_source] }
|
||||
end
|
||||
|
||||
private if $ThisIsOnlyATest.nil? ################
|
||||
|
||||
def import_source(source)
|
||||
# Remove C/C++ comments from a string
|
||||
# +source+:: String which will have the comments removed
|
||||
def remove_comments_from_source(source)
|
||||
# remove comments (block and line, in three steps to ensure correct precedence)
|
||||
source.gsub!(/(?<!\*)\/\/(?:.+\/\*|\*(?:$|[^\/])).*$/, '') # remove line comments that comment out the start of blocks
|
||||
source.gsub!(/\/\*.*?\*\//m, '') # remove block comments
|
||||
source.gsub!(/\/\/.*$/, '') # remove line comments (all that remain)
|
||||
end
|
||||
|
||||
def remove_nested_pairs_of_braces(source)
|
||||
# remove nested pairs of braces because no function declarations will be inside of them (leave outer pair for function definition detection)
|
||||
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
|
||||
|
||||
source
|
||||
end
|
||||
|
||||
# Return the number of pairs of braces/square brackets in the function provided by the user
|
||||
# +source+:: String containing the function to be processed
|
||||
def count_number_of_pairs_of_braces_in_function(source)
|
||||
is_function_start_found = false
|
||||
curr_level = 0
|
||||
total_pairs = 0
|
||||
|
||||
source.each_char do |c|
|
||||
if c == '{'
|
||||
curr_level += 1
|
||||
total_pairs += 1
|
||||
is_function_start_found = true
|
||||
elsif c == '}'
|
||||
curr_level -= 1
|
||||
end
|
||||
|
||||
break if is_function_start_found && curr_level == 0 # We reached the end of the inline function body
|
||||
end
|
||||
|
||||
if curr_level != 0
|
||||
total_pairs = 0 # Something is fishy about this source, not enough closing braces?
|
||||
end
|
||||
|
||||
total_pairs
|
||||
end
|
||||
|
||||
# Transform inline functions to regular functions in the source by the user
|
||||
# +source+:: String containing the source to be processed
|
||||
def transform_inline_functions(source)
|
||||
inline_function_regex_formats = []
|
||||
square_bracket_pair_regex_format = /\{[^\{\}]*\}/ # Regex to match one whole block enclosed by two square brackets
|
||||
|
||||
# Convert user provided string patterns to regex
|
||||
# Use word bounderies before and after the user regex to limit matching to actual word iso part of a word
|
||||
@inline_function_patterns.each do |user_format_string|
|
||||
user_regex = Regexp.new(user_format_string)
|
||||
word_boundary_before_user_regex = /\b/
|
||||
cleanup_spaces_after_user_regex = /[ ]*\b/
|
||||
inline_function_regex_formats << Regexp.new(word_boundary_before_user_regex.source + user_regex.source + cleanup_spaces_after_user_regex.source)
|
||||
end
|
||||
|
||||
# let's clean up the encoding in case they've done anything weird with the characters we might find
|
||||
source = source.force_encoding("ISO-8859-1").encode("utf-8", :replace => nil)
|
||||
source = source.force_encoding('ISO-8859-1').encode('utf-8', :replace => nil)
|
||||
|
||||
# Comments can contain words that will trigger the parser (static|inline|<user_defined_static_keyword>)
|
||||
remove_comments_from_source(source)
|
||||
|
||||
# smush multiline macros into single line (checking for continuation character at end of line '\')
|
||||
# If the user uses a macro to declare an inline function,
|
||||
# smushing the macros makes it easier to recognize them as a macro and if required,
|
||||
# remove them later on in this function
|
||||
source.gsub!(/\s*\\\s*/m, ' ')
|
||||
|
||||
# Just looking for static|inline in the gsub is a bit too aggressive (functions that are named like this, ...), so we try to be a bit smarter
|
||||
# Instead, look for an inline pattern (f.e. "static inline") and parse it.
|
||||
# Below is a small explanation on how the general mechanism works:
|
||||
# - Everything before the match should just be copied, we don't want
|
||||
# to touch anything but the inline functions.
|
||||
# - Remove the implementation of the inline function (this is enclosed
|
||||
# in square brackets) and replace it with ";" to complete the
|
||||
# transformation to normal/non-inline function.
|
||||
# To ensure proper removal of the function body, we count the number of square-bracket pairs
|
||||
# and remove the pairs one-by-one.
|
||||
# - Copy everything after the inline function implementation and start the parsing of the next inline function
|
||||
# There are ofcourse some special cases (inline macro declarations, inline function declarations, ...) which are handled and explained below
|
||||
inline_function_regex_formats.each do |format|
|
||||
inspected_source = ''
|
||||
regex_matched = false
|
||||
loop do
|
||||
inline_function_match = source.match(/#{format}/) # Search for inline function declaration
|
||||
|
||||
if inline_function_match.nil? # No inline functions so nothing to do
|
||||
# Join pre and post match stripped parts for the next inline function detection regex
|
||||
source = inspected_source + source if regex_matched == true
|
||||
break
|
||||
end
|
||||
|
||||
regex_matched = true
|
||||
# 1. Determine if we are dealing with a user defined macro to declare inline functions
|
||||
# If the end of the pre-match string is a macro-declaration-like string,
|
||||
# we are dealing with a user defined macro to declare inline functions
|
||||
if /(#define\s*)\z/ =~ inline_function_match.pre_match
|
||||
# Remove the macro from the source
|
||||
stripped_pre_match = inline_function_match.pre_match.sub(/(#define\s*)\z/, '')
|
||||
stripped_post_match = inline_function_match.post_match.sub(/\A(.*[\n]?)/, '')
|
||||
inspected_source += stripped_pre_match
|
||||
source = stripped_post_match
|
||||
next
|
||||
end
|
||||
|
||||
# 2. Determine if we are dealing with an inline function declaration iso function definition
|
||||
# If the start of the post-match string is a function-declaration-like string (something ending with semicolon after the function arguments),
|
||||
# we are dealing with a inline function declaration
|
||||
if /\A#{@function_declaration_parse_base_match}\s*;/m =~ inline_function_match.post_match
|
||||
# Only remove the inline part from the function declaration, leaving the function declaration won't do any harm
|
||||
inspected_source += inline_function_match.pre_match
|
||||
source = inline_function_match.post_match
|
||||
next
|
||||
end
|
||||
|
||||
# 3. If we get here, we found an inline function declaration AND inline function body.
|
||||
# Remove the function body to transform it into a 'normal' function declaration.
|
||||
if /\A#{@function_declaration_parse_base_match}\s*\{/m =~ inline_function_match.post_match
|
||||
total_pairs_to_remove = count_number_of_pairs_of_braces_in_function(inline_function_match.post_match)
|
||||
|
||||
break if total_pairs_to_remove == 0 # Bad source?
|
||||
|
||||
inline_function_stripped = inline_function_match.post_match
|
||||
|
||||
total_pairs_to_remove.times do
|
||||
inline_function_stripped.sub!(/\s*#{square_bracket_pair_regex_format}/, ';') # Remove inline implementation (+ some whitespace because it's prettier)
|
||||
end
|
||||
inspected_source += inline_function_match.pre_match
|
||||
source = inline_function_stripped
|
||||
next
|
||||
end
|
||||
|
||||
# 4. If we get here, it means the regex match, but it is not related to the function (ex. static variable in header)
|
||||
# Leave this code as it is.
|
||||
inspected_source += inline_function_match.pre_match + inline_function_match[0]
|
||||
source = inline_function_match.post_match
|
||||
end
|
||||
end
|
||||
|
||||
source
|
||||
end
|
||||
|
||||
def import_source(source, parse_project, cpp = false)
|
||||
# let's clean up the encoding in case they've done anything weird with the characters we might find
|
||||
source = source.force_encoding('ISO-8859-1').encode('utf-8', :replace => nil)
|
||||
|
||||
# void must be void for cmock _ExpectAndReturn calls to process properly, not some weird typedef which equates to void
|
||||
# to a certain extent, this action assumes we're chewing on pre-processed header files, otherwise we'll most likely just get stuff from @treat_as_void
|
||||
@@ -62,13 +225,18 @@ class CMockHeaderParser
|
||||
@local_as_void += void_types.flatten.uniq.compact
|
||||
end
|
||||
|
||||
# If user wants to mock inline functions,
|
||||
# remove the (user specific) inline keywords before removing anything else to avoid missing an inline function
|
||||
if @treat_inlines == :include
|
||||
@inline_function_patterns.each do |user_format_string|
|
||||
source.gsub!(/#{user_format_string}/, '') # remove user defined inline function patterns
|
||||
end
|
||||
end
|
||||
|
||||
# smush multiline macros into single line (checking for continuation character at end of line '\')
|
||||
source.gsub!(/\s*\\\s*/m, ' ')
|
||||
|
||||
#remove comments (block and line, in three steps to ensure correct precedence)
|
||||
source.gsub!(/(?<!\*)\/\/(?:.+\/\*|\*(?:$|[^\/])).*$/, '') # remove line comments that comment out the start of blocks
|
||||
source.gsub!(/\/\*.*?\*\//m, '') # remove block comments
|
||||
source.gsub!(/\/\/.*$/, '') # remove line comments (all that remain)
|
||||
remove_comments_from_source(source)
|
||||
|
||||
# remove assembler pragma sections
|
||||
source.gsub!(/^\s*#\s*pragma\s+asm\s+.*?#\s*pragma\s+endasm/m, '')
|
||||
@@ -84,66 +252,123 @@ class CMockHeaderParser
|
||||
# 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|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
|
||||
# remove problem keywords
|
||||
source.gsub!(/(\W)(?:register|auto|restrict)(\W)/, '\1\2')
|
||||
source.gsub!(/(\W)(?:static)(\W)/, '\1\2') unless cpp
|
||||
|
||||
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
|
||||
source.gsub!(/\)(\w)/, ') \1') # add space between parenthese and alphanumeric
|
||||
source.gsub!(/(^|\W+)(?:#{@c_strippables.join('|')})(?=$|\W+)/,'\1') unless @c_strippables.empty? # remove known attributes slated to be stripped
|
||||
source.gsub!(/(^|\W+)(?:#{@c_strippables.join('|')})(?=$|\W+)/, '\1') unless @c_strippables.empty? # remove known attributes slated to be stripped
|
||||
|
||||
#scan standalone function pointers and remove them, because they can just be ignored
|
||||
source.gsub!(/\w+\s*\(\s*\*\s*\w+\s*\)\s*\([^)]*\)\s*;/,';')
|
||||
# scan standalone function pointers and remove them, because they can just be ignored
|
||||
source.gsub!(/\w+\s*\(\s*\*\s*\w+\s*\)\s*\([^)]*\)\s*;/, ';')
|
||||
|
||||
#scan for functions which return function pointers, because they are a pain
|
||||
source.gsub!(/([\w\s\*]+)\(*\(\s*\*([\w\s\*]+)\s*\(([\w\s\*,]*)\)\)\s*\(([\w\s\*,]*)\)\)*/) do |m|
|
||||
functype = "cmock_#{@module_name}_func_ptr#{@typedefs.size + 1}"
|
||||
@typedefs << "typedef #{$1.strip}(*#{functype})(#{$4});"
|
||||
"#{functype} #{$2.strip}(#{$3});"
|
||||
end
|
||||
|
||||
# remove nested pairs of braces because no function declarations will be inside of them (leave outer pair for function definition detection)
|
||||
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, '{ }')
|
||||
# scan for functions which return function pointers, because they are a pain
|
||||
source.gsub!(/([\w\s\*]+)\(*\(\s*\*([\w\s\*]+)\s*\(([\w\s\*,]*)\)\)\s*\(([\w\s\*,]*)\)\)*/) do |_m|
|
||||
functype = "cmock_#{parse_project[:module_name]}_func_ptr#{parse_project[:typedefs].size + 1}"
|
||||
unless cpp # only collect once
|
||||
parse_project[:typedefs] << "typedef #{Regexp.last_match(1).strip}(*#{functype})(#{Regexp.last_match(4)});"
|
||||
"#{functype} #{Regexp.last_match(2).strip}(#{Regexp.last_match(3)});"
|
||||
end
|
||||
end
|
||||
|
||||
# remove function definitions by stripping off the arguments right now
|
||||
source.gsub!(/\([^\)]*\)\s*\{[^\}]*\}/m, ";")
|
||||
source = remove_nested_pairs_of_braces(source) unless cpp
|
||||
|
||||
#drop extra white space to make the rest go faster
|
||||
if @treat_inlines == :include
|
||||
# Functions having "{ }" at this point are/were inline functions,
|
||||
# User wants them in so 'disguise' them as normal functions with the ";"
|
||||
source.gsub!('{ }', ';')
|
||||
end
|
||||
|
||||
# remove function definitions by stripping off the arguments right now
|
||||
source.gsub!(/\([^\)]*\)\s*\{[^\}]*\}/m, ';')
|
||||
|
||||
# drop extra white space to make the rest go faster
|
||||
source.gsub!(/^\s+/, '') # remove extra white space from beginning of line
|
||||
source.gsub!(/\s+$/, '') # remove extra white space from end of line
|
||||
source.gsub!(/\s*\(\s*/, '(') # remove extra white space from before left parens
|
||||
source.gsub!(/\s*\)\s*/, ')') # remove extra white space from before right parens
|
||||
source.gsub!(/\s+/, ' ') # remove remaining extra white space
|
||||
|
||||
#split lines on semicolons and remove things that are obviously not what we are looking for
|
||||
src_lines = source.split(/\s*;\s*/).uniq
|
||||
src_lines.delete_if {|line| line.strip.length == 0} # remove blank lines
|
||||
src_lines.delete_if {|line| !(line =~ /[\w\s\*]+\(+\s*\*[\*\s]*[\w\s]+(?:\[[\w\s]*\]\s*)+\)+\s*\((?:[\w\s\*]*,?)*\s*\)/).nil?} #remove function pointer arrays
|
||||
if (@treat_externs == :include)
|
||||
src_lines.delete_if {|line| !(line =~ /(?:^|\s+)(?:inline)\s+/).nil?} # remove inline functions
|
||||
else
|
||||
src_lines.delete_if {|line| !(line =~ /(?:^|\s+)(?:extern|inline)\s+/).nil?} # remove inline and extern functions
|
||||
# split lines on semicolons and remove things that are obviously not what we are looking for
|
||||
src_lines = source.split(/\s*;\s*/)
|
||||
src_lines = src_lines.uniq unless cpp # must retain closing braces for class/namespace
|
||||
src_lines.delete_if { |line| line.strip.empty? } # remove blank lines
|
||||
src_lines.delete_if { |line| !(line =~ /[\w\s\*]+\(+\s*\*[\*\s]*[\w\s]+(?:\[[\w\s]*\]\s*)+\)+\s*\((?:[\w\s\*]*,?)*\s*\)/).nil? } # remove function pointer arrays
|
||||
|
||||
unless @treat_externs == :include
|
||||
src_lines.delete_if { |line| !(line =~ /(?:^|\s+)(?:extern)\s+/).nil? } # remove extern functions
|
||||
end
|
||||
src_lines.delete_if {|line| line.empty? } #drop empty lines
|
||||
|
||||
unless @treat_inlines == :include
|
||||
src_lines.delete_if { |line| !(line =~ /(?:^|\s+)(?:inline)\s+/).nil? } # remove inline functions
|
||||
end
|
||||
|
||||
src_lines.delete_if(&:empty?) # drop empty lines
|
||||
end
|
||||
|
||||
# Rudimentary C++ parser - does not handle all situations - e.g.:
|
||||
# * A namespace function appears after a class with private members (should be parsed)
|
||||
# * Anonymous namespace (shouldn't parse anything - no matter how nested - within it)
|
||||
# * A class nested within another class
|
||||
def parse_cpp_functions(source)
|
||||
funcs = []
|
||||
|
||||
ns = []
|
||||
pub = false
|
||||
source.each do |line|
|
||||
# Search for namespace, class, opening and closing braces
|
||||
line.scan(/(?:(?:\b(?:namespace|class)\s+(?:\S+)\s*)?{)|}/).each do |item|
|
||||
if item == '}'
|
||||
ns.pop
|
||||
else
|
||||
token = item.strip.sub(/\s+/, ' ')
|
||||
ns << token
|
||||
|
||||
pub = false if token.start_with? 'class'
|
||||
pub = true if token.start_with? 'namespace'
|
||||
end
|
||||
end
|
||||
|
||||
pub = true if line =~ /public:/
|
||||
pub = false if line =~ /private:/ || line =~ /protected:/
|
||||
|
||||
# ignore non-public and non-static
|
||||
next unless pub
|
||||
next unless line =~ /\bstatic\b/
|
||||
|
||||
line.sub!(/^.*static/, '')
|
||||
next unless line =~ @declaration_parse_matcher
|
||||
|
||||
tmp = ns.reject { |item| item == '{' }
|
||||
|
||||
# Identify class name, if any
|
||||
cls = nil
|
||||
if tmp[-1].start_with? 'class '
|
||||
cls = tmp.pop.sub(/class (\S+) {/, '\1')
|
||||
end
|
||||
|
||||
# Assemble list of namespaces
|
||||
tmp.each { |item| item.sub!(/(?:namespace|class) (\S+) {/, '\1') }
|
||||
|
||||
funcs << [line.strip.gsub(/\s+/, ' '), tmp, cls]
|
||||
end
|
||||
funcs
|
||||
end
|
||||
|
||||
def parse_functions(source)
|
||||
funcs = []
|
||||
source.each {|line| funcs << line.strip.gsub(/\s+/, ' ') if (line =~ @declaration_parse_matcher)}
|
||||
source.each { |line| funcs << line.strip.gsub(/\s+/, ' ') if line =~ @declaration_parse_matcher }
|
||||
if funcs.empty?
|
||||
case @when_no_prototypes
|
||||
when :error
|
||||
raise "ERROR: No function prototypes found!"
|
||||
when :warn
|
||||
puts "WARNING: No function prototypes found!" unless (@verbosity < 1)
|
||||
when :error
|
||||
raise 'ERROR: No function prototypes found!'
|
||||
when :warn
|
||||
puts 'WARNING: No function prototypes found!' unless @verbosity < 1
|
||||
end
|
||||
end
|
||||
return funcs
|
||||
funcs
|
||||
end
|
||||
|
||||
def parse_type_and_name(arg)
|
||||
@@ -151,8 +376,8 @@ class CMockHeaderParser
|
||||
# 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.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]
|
||||
@@ -177,15 +402,15 @@ class CMockHeaderParser
|
||||
end
|
||||
|
||||
arg_info[:modifier] = attr_array.join(' ')
|
||||
arg_info[:type] = type_array.join(' ').gsub(/\s+\*/,'*') # remove space before asterisks
|
||||
return arg_info
|
||||
arg_info[:type] = type_array.join(' ').gsub(/\s+\*/, '*') # remove space before asterisks
|
||||
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 ...
|
||||
return args if arg =~ /^\s*((\.\.\.)|(void))\s*$/ # we're done if we reach void by itself or ...
|
||||
|
||||
arg_info = parse_type_and_name(arg)
|
||||
arg_info.delete(:modifier) # don't care about this
|
||||
@@ -193,7 +418,7 @@ class CMockHeaderParser
|
||||
|
||||
# in C, array arguments implicitly degrade to pointers
|
||||
# make the translation explicit here to simplify later logic
|
||||
if @treat_as_array[arg_info[:type]] and not arg_info[:ptr?] then
|
||||
if @treat_as_array[arg_info[:type]] && !(arg_info[:ptr?])
|
||||
arg_info[:type] = "#{@treat_as_array[arg_info[:type]]}*"
|
||||
arg_info[:type] = "const #{arg_info[:type]}" if arg_info[:const?]
|
||||
arg_info[:ptr?] = true
|
||||
@@ -203,31 +428,35 @@ class CMockHeaderParser
|
||||
end
|
||||
|
||||
# Try to find array pair in parameters following this pattern : <type> * <name>, <@array_size_type> <@array_size_name>
|
||||
args.each_with_index {|val, index|
|
||||
args.each_with_index do |val, index|
|
||||
next_index = index + 1
|
||||
if (args.length > next_index)
|
||||
if (val[:ptr?] == true and args[next_index][:name].match(@array_size_name) and @array_size_type.include?(args[next_index][:type]))
|
||||
val[:array_data?] = true
|
||||
args[next_index][:array_size?] = true
|
||||
end
|
||||
end
|
||||
}
|
||||
next unless args.length > next_index
|
||||
|
||||
return args
|
||||
if (val[:ptr?] == true) && args[next_index][:name].match(@array_size_name) && @array_size_type.include?(args[next_index][:type])
|
||||
val[:array_data?] = true
|
||||
args[next_index][:array_size?] = true
|
||||
end
|
||||
end
|
||||
|
||||
args
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def divine_const(arg)
|
||||
# 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
|
||||
if arg.include?('*') ? (/(^|\s|\*)const(\s(\w|\s)*)?\*(?!.*\*)/ =~ arg) : (/(^|\s)const(\s|$)/ =~ arg)
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def divine_ptr_and_const(arg)
|
||||
@@ -237,128 +466,158 @@ class CMockHeaderParser
|
||||
divination[:const?] = divine_const(arg)
|
||||
|
||||
# an arg containing "const" after the last * is a constant pointer
|
||||
divination[:const_ptr?] = (/\*(?!.*\*)\s*const(\s|$)/ =~ arg) ? true : false
|
||||
divination[:const_ptr?] = /\*(?!.*\*)\s*const(\s|$)/ =~ arg ? true : false
|
||||
|
||||
return divination
|
||||
divination
|
||||
end
|
||||
|
||||
def clean_args(arg_list)
|
||||
if ((@local_as_void.include?(arg_list.strip)) or (arg_list.empty?))
|
||||
return 'void'
|
||||
def clean_args(arg_list, parse_project)
|
||||
if @local_as_void.include?(arg_list.strip) || arg_list.empty?
|
||||
'void'
|
||||
else
|
||||
c=0
|
||||
arg_list.gsub!(/(\w+)(?:\s*\[\s*\(*[\s\w+-]*\)*\s*\])+/,'*\1') # magically turn brackets into asterisks, also match for parentheses that come from macros
|
||||
arg_list.gsub!(/\s+\*/,'*') # remove space to place asterisks with type (where they belong)
|
||||
arg_list.gsub!(/\*(\w)/,'* \1') # pull asterisks away from arg to place asterisks with type (where they belong)
|
||||
c = 0
|
||||
# magically turn brackets into asterisks, also match for parentheses that come from macros
|
||||
arg_list.gsub!(/(\w+)(?:\s*\[[^\[\]]*\])+/, '*\1')
|
||||
# remove space to place asterisks with type (where they belong)
|
||||
arg_list.gsub!(/\s+\*/, '*')
|
||||
# pull asterisks away from arg to place asterisks with type (where they belong)
|
||||
arg_list.gsub!(/\*(\w)/, '* \1')
|
||||
|
||||
#scan argument list for function pointers and replace them with custom types
|
||||
arg_list.gsub!(/([\w\s\*]+)\(+\s*\*[\*\s]*([\w\s]*)\s*\)+\s*\(((?:[\w\s\*]*,?)*)\s*\)*/) do |m|
|
||||
|
||||
functype = "cmock_#{@module_name}_func_ptr#{@typedefs.size + 1}"
|
||||
funcret = $1.strip
|
||||
funcname = $2.strip
|
||||
funcargs = $3.strip
|
||||
# scan argument list for function pointers and replace them with custom types
|
||||
arg_list.gsub!(/([\w\s\*]+)\(+\s*\*[\*\s]*([\w\s]*)\s*\)+\s*\(((?:[\w\s\*]*,?)*)\s*\)*/) do |_m|
|
||||
functype = "cmock_#{parse_project[:module_name]}_func_ptr#{parse_project[:typedefs].size + 1}"
|
||||
funcret = Regexp.last_match(1).strip
|
||||
funcname = Regexp.last_match(2).strip
|
||||
funcargs = Regexp.last_match(3).strip
|
||||
funconst = ''
|
||||
if (funcname.include? 'const')
|
||||
funcname.gsub!('const','').strip!
|
||||
if funcname.include? 'const'
|
||||
funcname.gsub!('const', '').strip!
|
||||
funconst = 'const '
|
||||
end
|
||||
@typedefs << "typedef #{funcret}(*#{functype})(#{funcargs});"
|
||||
funcname = "cmock_arg#{c+=1}" if (funcname.empty?)
|
||||
parse_project[:typedefs] << "typedef #{funcret}(*#{functype})(#{funcargs});"
|
||||
funcname = "cmock_arg#{c += 1}" if funcname.empty?
|
||||
"#{functype} #{funconst}#{funcname}"
|
||||
end
|
||||
|
||||
#automatically name unnamed arguments (those that only had a type)
|
||||
arg_list.split(/\s*,\s*/).map { |arg|
|
||||
# scan argument list for function pointers with shorthand notation and replace them with custom types
|
||||
arg_list.gsub!(/([\w\s\*]+)+\s+(\w+)\s*\(((?:[\w\s\*]*,?)*)\s*\)*/) do |_m|
|
||||
functype = "cmock_#{parse_project[:module_name]}_func_ptr#{parse_project[:typedefs].size + 1}"
|
||||
funcret = Regexp.last_match(1).strip
|
||||
funcname = Regexp.last_match(2).strip
|
||||
funcargs = Regexp.last_match(3).strip
|
||||
funconst = ''
|
||||
if funcname.include? 'const'
|
||||
funcname.gsub!('const', '').strip!
|
||||
funconst = 'const '
|
||||
end
|
||||
parse_project[:typedefs] << "typedef #{funcret}(*#{functype})(#{funcargs});"
|
||||
funcname = "cmock_arg#{c += 1}" if funcname.empty?
|
||||
"#{functype} #{funconst}#{funcname}"
|
||||
end
|
||||
|
||||
# automatically name unnamed arguments (those that only had a type)
|
||||
arg_list.split(/\s*,\s*/).map do |arg|
|
||||
parts = (arg.split - ['struct', 'union', 'enum', 'const', 'const*'])
|
||||
if ((parts.size < 2) or (parts[-1][-1].chr == '*') or (@standards.include?(parts[-1])))
|
||||
"#{arg} cmock_arg#{c+=1}"
|
||||
if (parts.size < 2) || (parts[-1][-1].chr == '*') || @standards.include?(parts[-1])
|
||||
"#{arg} cmock_arg#{c += 1}"
|
||||
else
|
||||
arg
|
||||
end
|
||||
}.join(', ')
|
||||
end.join(', ')
|
||||
end
|
||||
end
|
||||
|
||||
def parse_declaration(declaration)
|
||||
def parse_declaration(parse_project, declaration, namespace = [], classname = nil)
|
||||
decl = {}
|
||||
decl[:namespace] = namespace
|
||||
decl[:class] = classname
|
||||
|
||||
regex_match = @declaration_parse_matcher.match(declaration)
|
||||
raise "Failed parsing function declaration: '#{declaration}'" if regex_match.nil?
|
||||
|
||||
#grab argument list
|
||||
# grab argument list
|
||||
args = regex_match[2].strip
|
||||
|
||||
#process function attributes, return type, and name
|
||||
# process function attributes, return type, and name
|
||||
parsed = parse_type_and_name(regex_match[1])
|
||||
|
||||
decl[:name] = parsed[:name]
|
||||
# Record original name without scope prefix
|
||||
decl[:unscoped_name] = parsed[:name]
|
||||
|
||||
# Prefix name with namespace scope (if any) and then class
|
||||
decl[:name] = namespace.join('_')
|
||||
unless classname.nil?
|
||||
decl[:name] << '_' unless decl[:name].empty?
|
||||
decl[:name] << classname
|
||||
end
|
||||
# Add original name to complete fully scoped name
|
||||
decl[:name] << '_' unless decl[:name].empty?
|
||||
decl[:name] << decl[:unscoped_name]
|
||||
|
||||
decl[:modifier] = parsed[:modifier]
|
||||
unless parsed[:c_calling_convention].nil?
|
||||
decl[:c_calling_convention] = parsed[:c_calling_convention]
|
||||
end
|
||||
|
||||
rettype = parsed[:type]
|
||||
rettype = 'void' if (@local_as_void.include?(rettype.strip))
|
||||
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'),
|
||||
:ptr? => parsed[:ptr?],
|
||||
:const? => parsed[:const?],
|
||||
:const_ptr? => parsed[:const_ptr?]
|
||||
}
|
||||
:ptr? => parsed[:ptr?] || false,
|
||||
:const? => parsed[:const?] || false,
|
||||
:const_ptr? => parsed[:const_ptr?] || false }
|
||||
|
||||
#remove default argument statements from mock definitions
|
||||
# remove default argument statements from mock definitions
|
||||
args.gsub!(/=\s*[a-zA-Z0-9_\.]+\s*/, ' ')
|
||||
|
||||
#check for var args
|
||||
if (args =~ /\.\.\./)
|
||||
decl[:var_arg] = args.match( /[\w\s]*\.\.\./ ).to_s.strip
|
||||
if (args =~ /\,[\w\s]*\.\.\./)
|
||||
args = args.gsub!(/\,[\w\s]*\.\.\./,'')
|
||||
else
|
||||
args = 'void'
|
||||
end
|
||||
# check for var args
|
||||
if args =~ /\.\.\./
|
||||
decl[:var_arg] = args.match(/[\w\s]*\.\.\./).to_s.strip
|
||||
args = if args =~ /\,[\w\s]*\.\.\./
|
||||
args.gsub!(/\,[\w\s]*\.\.\./, '')
|
||||
else
|
||||
'void'
|
||||
end
|
||||
else
|
||||
decl[:var_arg] = nil
|
||||
end
|
||||
args = clean_args(args)
|
||||
args = clean_args(args, parse_project)
|
||||
decl[:args_string] = args
|
||||
decl[:args] = parse_args(args)
|
||||
decl[:args_call] = decl[:args].map{|a| a[:name]}.join(', ')
|
||||
decl[:contains_ptr?] = decl[:args].inject(false) {|ptr, arg| arg[:ptr?] ? true : ptr }
|
||||
decl[:args_call] = decl[:args].map { |a| a[:name] }.join(', ')
|
||||
decl[:contains_ptr?] = decl[:args].inject(false) { |ptr, arg| arg[:ptr?] ? true : ptr }
|
||||
|
||||
if (decl[:return][:type].nil? or decl[:name].nil? or decl[:args].nil? or
|
||||
decl[:return][:type].empty? or decl[:name].empty?)
|
||||
raise "Failed Parsing Declaration Prototype!\n" +
|
||||
" declaration: '#{declaration}'\n" +
|
||||
" modifier: '#{decl[:modifier]}'\n" +
|
||||
" return: #{prototype_inspect_hash(decl[:return])}\n" +
|
||||
" function: '#{decl[:name]}'\n" +
|
||||
" args: #{prototype_inspect_array_of_hashes(decl[:args])}\n"
|
||||
if decl[:return][:type].nil? || decl[:name].nil? || decl[:args].nil? ||
|
||||
decl[:return][:type].empty? || decl[:name].empty?
|
||||
raise "Failed Parsing Declaration Prototype!\n" \
|
||||
" declaration: '#{declaration}'\n" \
|
||||
" modifier: '#{decl[:modifier]}'\n" \
|
||||
" return: #{prototype_inspect_hash(decl[:return])}\n" \
|
||||
" function: '#{decl[:name]}'\n" \
|
||||
" args: #{prototype_inspect_array_of_hashes(decl[:args])}\n"
|
||||
end
|
||||
|
||||
return decl
|
||||
decl
|
||||
end
|
||||
|
||||
def prototype_inspect_hash(hash)
|
||||
pairs = []
|
||||
hash.each_pair { |name, value| pairs << ":#{name} => #{"'" if (value.class == String)}#{value}#{"'" if (value.class == String)}" }
|
||||
return "{#{pairs.join(', ')}}"
|
||||
hash.each_pair { |name, value| pairs << ":#{name} => #{"'" if value.class == String}#{value}#{"'" if value.class == String}" }
|
||||
"{#{pairs.join(', ')}}"
|
||||
end
|
||||
|
||||
def prototype_inspect_array_of_hashes(array)
|
||||
hashes = []
|
||||
array.each { |hash| hashes << prototype_inspect_hash(hash) }
|
||||
case (array.size)
|
||||
case array.size
|
||||
when 0
|
||||
return "[]"
|
||||
return '[]'
|
||||
when 1
|
||||
return "[#{hashes[0]}]"
|
||||
else
|
||||
return "[\n #{hashes.join("\n ")}\n ]\n"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
+20
-25
@@ -4,10 +4,7 @@
|
||||
# [Released under MIT License. Please refer to license.txt for details]
|
||||
# ==========================================
|
||||
|
||||
require 'thread'
|
||||
|
||||
class CMockPluginManager
|
||||
|
||||
attr_accessor :plugins
|
||||
|
||||
def initialize(config, utils)
|
||||
@@ -15,41 +12,39 @@ class CMockPluginManager
|
||||
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)
|
||||
self.class.plugin_require_mutex.synchronize { load_plugin(plugin_name, object_name, config, utils) }
|
||||
object_name = 'CMockGeneratorPlugin' + camelize(plugin_name)
|
||||
self.class.mutex.synchronize { load_plugin(plugin_name, object_name, config, utils) }
|
||||
end
|
||||
@plugins.sort! {|a,b| a.priority <=> b.priority }
|
||||
@plugins.sort! { |a, b| a.priority <=> b.priority }
|
||||
end
|
||||
|
||||
def run(method, args=nil)
|
||||
def run(method, args = nil)
|
||||
if args.nil?
|
||||
return @plugins.collect{ |plugin| plugin.send(method) if plugin.respond_to?(method) }.flatten.join
|
||||
@plugins.collect { |plugin| plugin.send(method) if plugin.respond_to?(method) }.flatten.join
|
||||
else
|
||||
return @plugins.collect{ |plugin| plugin.send(method, args) if plugin.respond_to?(method) }.flatten.join
|
||||
@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 }
|
||||
lower_case_and_underscored_word.gsub(/\/(.?)/) { '::' + Regexp.last_match(1).upcase }.gsub(/(^|_)(.)/) { Regexp.last_match(2).upcase }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.plugin_require_mutex
|
||||
|
||||
def self.mutex
|
||||
@mutex ||= Mutex.new
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
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}"
|
||||
unless Object.const_defined? object_name
|
||||
file_name = "#{__dir__}/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 StandardError
|
||||
file_name = "#{__dir__}/cmock_generator_plugin_#{plugin_name.downcase}.rb"
|
||||
raise "ERROR: CMock unable to load plugin '#{plugin_name}' '#{object_name}' #{file_name}"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,74 +2,76 @@
|
||||
# CMock Project - Automatic Mock Generation for C
|
||||
# Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
|
||||
# [Released under MIT License. Please refer to license.txt for details]
|
||||
# ==========================================
|
||||
# ==========================================
|
||||
|
||||
class CMockUnityHelperParser
|
||||
|
||||
attr_accessor :c_types
|
||||
|
||||
|
||||
def initialize(config)
|
||||
@config = config
|
||||
@fallback = @config.plugins.include?(:array) ? 'UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY' : 'UNITY_TEST_ASSERT_EQUAL_MEMORY'
|
||||
@c_types = map_C_types.merge(import_source)
|
||||
@c_types = map_c_types.merge(import_source)
|
||||
end
|
||||
|
||||
def get_helper(ctype)
|
||||
lookup = ctype.gsub(/(?:^|(\S?)(\s*)|(\W))const(?:$|(\s*)(\S)|(\W))/,'\1\3\5\6').strip.gsub(/\s+/,'_')
|
||||
return [@c_types[lookup], ''] if (@c_types[lookup])
|
||||
if (lookup =~ /\*$/)
|
||||
lookup = lookup.gsub(/\*$/,'')
|
||||
return [@c_types[lookup], '*'] if (@c_types[lookup])
|
||||
lookup = ctype.gsub(/(?:^|(\S?)(\s*)|(\W))const(?:$|(\s*)(\S)|(\W))/, '\1\3\5\6').strip.gsub(/\s+/, '_')
|
||||
return [@c_types[lookup], ''] if @c_types[lookup]
|
||||
|
||||
if lookup =~ /\*$/
|
||||
lookup = lookup.gsub(/\*$/, '')
|
||||
return [@c_types[lookup], '*'] if @c_types[lookup]
|
||||
else
|
||||
lookup = lookup + '*'
|
||||
return [@c_types[lookup], '&'] if (@c_types[lookup])
|
||||
lookup += '*'
|
||||
return [@c_types[lookup], '&'] if @c_types[lookup]
|
||||
end
|
||||
return ['UNITY_TEST_ASSERT_EQUAL_PTR', ''] if (ctype =~ /cmock_\w+_ptr\d+/)
|
||||
return ['UNITY_TEST_ASSERT_EQUAL_PTR', ''] if ctype =~ /cmock_\w+_ptr\d+/
|
||||
raise("Don't know how to test #{ctype} and memory tests are disabled!") unless @config.memcmp_if_unknown
|
||||
return (lookup =~ /\*$/) ? [@fallback, '&'] : [@fallback, '']
|
||||
|
||||
lookup =~ /\*$/ ? [@fallback, '&'] : [@fallback, '']
|
||||
end
|
||||
|
||||
|
||||
private ###########################
|
||||
|
||||
def map_C_types
|
||||
|
||||
def map_c_types
|
||||
c_types = {}
|
||||
@config.treat_as.each_pair do |ctype, expecttype|
|
||||
c_type = ctype.gsub(/\s+/,'_')
|
||||
if (expecttype =~ /\*/)
|
||||
c_types[c_type] = "UNITY_TEST_ASSERT_EQUAL_#{expecttype.gsub(/\*/,'')}_ARRAY"
|
||||
c_type = ctype.gsub(/\s+/, '_')
|
||||
if expecttype =~ /\*/
|
||||
c_types[c_type] = "UNITY_TEST_ASSERT_EQUAL_#{expecttype.delete('*')}_ARRAY"
|
||||
else
|
||||
c_types[c_type] = "UNITY_TEST_ASSERT_EQUAL_#{expecttype}"
|
||||
c_types[c_type+'*'] ||= "UNITY_TEST_ASSERT_EQUAL_#{expecttype}_ARRAY"
|
||||
c_types[c_type + '*'] ||= "UNITY_TEST_ASSERT_EQUAL_#{expecttype}_ARRAY"
|
||||
end
|
||||
end
|
||||
c_types
|
||||
end
|
||||
|
||||
|
||||
def import_source
|
||||
source = @config.load_unity_helper
|
||||
return {} if source.nil?
|
||||
|
||||
c_types = {}
|
||||
source = source.gsub(/\/\/.*$/, '') #remove line comments
|
||||
source = source.gsub(/\/\*.*?\*\//m, '') #remove block comments
|
||||
|
||||
#scan for comparison helpers
|
||||
match_regex = Regexp.new('^\s*#define\s+(UNITY_TEST_ASSERT_EQUAL_(\w+))\s*\(' + Array.new(4,'\s*\w+\s*').join(',') + '\)')
|
||||
source = source.gsub(/\/\/.*$/, '') # remove line comments
|
||||
source = source.gsub(/\/\*.*?\*\//m, '') # remove block comments
|
||||
|
||||
# scan for comparison helpers
|
||||
match_regex = Regexp.new('^\s*#define\s+(UNITY_TEST_ASSERT_EQUAL_(\w+))\s*\(' + Array.new(4, '\s*\w+\s*').join(',') + '\)')
|
||||
pairs = source.scan(match_regex).flatten.compact
|
||||
(pairs.size/2).times do |i|
|
||||
expect = pairs[i*2]
|
||||
ctype = pairs[(i*2)+1]
|
||||
c_types[ctype] = expect unless expect.include?("_ARRAY")
|
||||
(pairs.size / 2).times do |i|
|
||||
expect = pairs[i * 2]
|
||||
ctype = pairs[(i * 2) + 1]
|
||||
c_types[ctype] = expect unless expect.include?('_ARRAY')
|
||||
end
|
||||
|
||||
#scan for array variants of those helpers
|
||||
match_regex = Regexp.new('^\s*#define\s+(UNITY_TEST_ASSERT_EQUAL_(\w+_ARRAY))\s*\(' + Array.new(5,'\s*\w+\s*').join(',') + '\)')
|
||||
|
||||
# scan for array variants of those helpers
|
||||
match_regex = Regexp.new('^\s*#define\s+(UNITY_TEST_ASSERT_EQUAL_(\w+_ARRAY))\s*\(' + Array.new(5, '\s*\w+\s*').join(',') + '\)')
|
||||
pairs = source.scan(match_regex).flatten.compact
|
||||
(pairs.size/2).times do |i|
|
||||
expect = pairs[i*2]
|
||||
ctype = pairs[(i*2)+1]
|
||||
c_types[ctype.gsub('_ARRAY','*')] = expect
|
||||
(pairs.size / 2).times do |i|
|
||||
expect = pairs[i * 2]
|
||||
ctype = pairs[(i * 2) + 1]
|
||||
c_types[ctype.gsub('_ARRAY', '*')] = expect
|
||||
end
|
||||
|
||||
|
||||
c_types
|
||||
end
|
||||
end
|
||||
|
||||
+9
-64
@@ -1,72 +1,17 @@
|
||||
###################################################################################
|
||||
# #
|
||||
# NAME: meson.build #
|
||||
# #
|
||||
# AUTHOR: Mike Karlesky, Mark VanderVoord, Greg Williams. #
|
||||
# WRITTEN BY: Michael Brockus. #
|
||||
# #
|
||||
# License: MIT #
|
||||
# #
|
||||
###################################################################################
|
||||
|
||||
|
||||
#
|
||||
# build script written by : Michael Brockus.
|
||||
# github repo author: Mike Karlesky, Mark VanderVoord, Greg Williams.
|
||||
#
|
||||
# license: MIT
|
||||
#
|
||||
project('cmock', 'c',
|
||||
license : 'MIT',
|
||||
meson_version : '>=0.52.0',
|
||||
license: 'MIT',
|
||||
meson_version: '>=0.53.0',
|
||||
subproject_dir : 'vendor',
|
||||
default_options: [
|
||||
'buildtype=minsize',
|
||||
'optimization=3',
|
||||
'warning_level=3',
|
||||
'werror=true',
|
||||
]
|
||||
default_options: ['werror=true', 'c_std=c11']
|
||||
)
|
||||
lang = 'c'
|
||||
cc = meson.get_compiler(lang)
|
||||
|
||||
|
||||
##
|
||||
#
|
||||
# Meson: Add compiler flags
|
||||
#
|
||||
##
|
||||
if cc.get_id() == 'clang'
|
||||
add_project_arguments(cc.get_supported_arguments(
|
||||
[
|
||||
'-Wweak-vtables', '-Wexit-time-destructors',
|
||||
'-Wglobal-constructors', '-Wmissing-noreturn'
|
||||
]
|
||||
), language: lang)
|
||||
endif
|
||||
|
||||
if cc.get_argument_syntax() == 'gcc'
|
||||
add_project_arguments(cc.get_supported_arguments(
|
||||
[
|
||||
'-Wformat', '-Waddress', '-Winit-self', '-Wno-multichar',
|
||||
'-Wpointer-arith' , '-Wwrite-strings' ,
|
||||
'-Wno-parentheses' , '-Wno-type-limits' ,
|
||||
'-Wformat-security' , '-Wunreachable-code' ,
|
||||
'-Waggregate-return' , '-Wformat-nonliteral' ,
|
||||
'-Wmissing-prototypes' , '-Wold-style-definition' ,
|
||||
'-Wmissing-declarations', '-Wmissing-include-dirs' ,
|
||||
'-Wno-unused-parameter' , '-Wdeclaration-after-statement'
|
||||
]
|
||||
), language: lang)
|
||||
endif
|
||||
|
||||
if cc.get_id() == 'msvc'
|
||||
add_project_arguments(cc.get_supported_arguments(
|
||||
[
|
||||
'/w44265', '/w44061', '/w44062',
|
||||
'/wd4018', '/wd4146', '/wd4244',
|
||||
'/wd4305',
|
||||
]
|
||||
), language: lang)
|
||||
endif
|
||||
|
||||
|
||||
unity_dep = dependency('unity', fallback: ['unity', 'unity_dep'])
|
||||
|
||||
subdir('src')
|
||||
|
||||
cmock_dep = declare_dependency(link_with: cmock_lib, include_directories: cmock_dir)
|
||||
|
||||
+53
-52
@@ -28,40 +28,39 @@ end
|
||||
|
||||
all_headers_to_mock = []
|
||||
|
||||
suppress_error = !ARGV.nil? && !ARGV.empty? && (ARGV[0].upcase == "--SILENT")
|
||||
|
||||
File.open(TEST_MAKEFILE, "w") do |mkfile|
|
||||
suppress_error = !ARGV.nil? && !ARGV.empty? && (ARGV[0].casecmp('--SILENT') == 0)
|
||||
|
||||
File.open(TEST_MAKEFILE, 'w') do |mkfile|
|
||||
# Define make variables
|
||||
mkfile.puts "CC ?= gcc"
|
||||
mkfile.puts 'CC ?= gcc'
|
||||
mkfile.puts "BUILD_DIR = #{BUILD_DIR}"
|
||||
mkfile.puts "SRC_DIR = #{SRC_DIR}"
|
||||
mkfile.puts "TEST_DIR = #{TEST_DIR}"
|
||||
mkfile.puts "TEST_CFLAGS ?= -DTEST"
|
||||
mkfile.puts 'TEST_CFLAGS ?= -DTEST'
|
||||
mkfile.puts "CMOCK_DIR ?= #{CMOCK_DIR}"
|
||||
mkfile.puts "UNITY_DIR ?= #{UNITY_DIR}"
|
||||
mkfile.puts "TEST_BUILD_DIR ?= ${BUILD_DIR}/test"
|
||||
mkfile.puts "TEST_MAKEFILE = ${TEST_BUILD_DIR}/MakefileTestSupport"
|
||||
mkfile.puts "OBJ ?= ${BUILD_DIR}/obj"
|
||||
mkfile.puts "OBJ_DIR = ${OBJ}"
|
||||
mkfile.puts ""
|
||||
mkfile.puts 'TEST_BUILD_DIR ?= ${BUILD_DIR}/test'
|
||||
mkfile.puts 'TEST_MAKEFILE = ${TEST_BUILD_DIR}/MakefileTestSupport'
|
||||
mkfile.puts 'OBJ ?= ${BUILD_DIR}/obj'
|
||||
mkfile.puts 'OBJ_DIR = ${OBJ}'
|
||||
mkfile.puts ''
|
||||
|
||||
# Build Unity
|
||||
mkfile.puts "#{UNITY_OBJ}: #{UNITY_SRC}/unity.c"
|
||||
mkfile.puts "\t${CC} -o $@ -c $< -I #{UNITY_SRC}"
|
||||
mkfile.puts ""
|
||||
mkfile.puts ''
|
||||
|
||||
# Build CMock
|
||||
mkfile.puts "#{CMOCK_OBJ}: #{CMOCK_SRC}/cmock.c"
|
||||
mkfile.puts "\t${CC} -o $@ -c $< -I #{UNITY_SRC} -I #{CMOCK_SRC}"
|
||||
mkfile.puts ""
|
||||
mkfile.puts ''
|
||||
|
||||
test_sources = Dir["#{TEST_DIR}/**/test_*.c"]
|
||||
test_targets = []
|
||||
generator = UnityTestRunnerGenerator.new
|
||||
|
||||
# headers that begin with prefix or end with suffix are not included
|
||||
all_headers = Dir["#{SRC_DIR}/**/*.h"]
|
||||
all_headers = Dir["#{SRC_DIR}/**/*.h*"]
|
||||
|
||||
def reject_mock_files(file)
|
||||
extn = File.extname file
|
||||
@@ -69,7 +68,8 @@ File.open(TEST_MAKEFILE, "w") do |mkfile|
|
||||
if MOCK_SUFFIX.empty?
|
||||
return filename.start_with? MOCK_PREFIX
|
||||
end
|
||||
return (filename.start_with? MOCK_PREFIX or filename.end_with? MOCK_SUFFIX)
|
||||
|
||||
(filename.start_with?(MOCK_PREFIX) || filename.end_with?(MOCK_SUFFIX))
|
||||
end
|
||||
|
||||
all_headers = all_headers.reject { |f| reject_mock_files(f) }
|
||||
@@ -93,62 +93,64 @@ File.open(TEST_MAKEFILE, "w") do |mkfile|
|
||||
# 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")
|
||||
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 ""
|
||||
unless 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
|
||||
linkonlybase = File.basename(linkonlyfile, '.*')
|
||||
linkonlymodule_src = File.join(SRC_DIR, linkonlyfile.to_s)
|
||||
linkonlymodule_obj = File.join(OBJ_DIR, "#{linkonlybase}.o")
|
||||
linkonly_objs.push(linkonlymodule_obj)
|
||||
# only create the target if we didn't already
|
||||
next if 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
|
||||
|
||||
# Create runners
|
||||
mkfile.puts "#{runner_source}: #{test}"
|
||||
mkfile.puts "\t@UNITY_DIR=${UNITY_DIR} ruby ${CMOCK_DIR}/scripts/create_runner.rb #{test} #{runner_source}"
|
||||
mkfile.puts ""
|
||||
mkfile.puts ''
|
||||
|
||||
# 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} ${INCLUDE_PATH}"
|
||||
mkfile.puts ""
|
||||
mkfile.puts ''
|
||||
|
||||
# Collect mocks to generate
|
||||
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}
|
||||
system_mocks = cfg[:includes][:system].select { |name| name =~ MOCK_MATCHER }
|
||||
raise 'Mocking of system headers is not yet supported!' unless system_mocks.empty?
|
||||
|
||||
module_names_to_mock = local_mocks.map{|name| "#{name.sub(/#{MOCK_PREFIX}/,'')}.h"}
|
||||
local_mocks = cfg[:includes][:local].select { |name| name =~ MOCK_MATCHER }
|
||||
|
||||
module_names_to_mock = local_mocks.map { |name| name.sub(/#{MOCK_PREFIX}/, '').to_s }
|
||||
headers_to_mock = []
|
||||
module_names_to_mock.each do |name|
|
||||
header_to_mock = nil
|
||||
all_headers.each do |header|
|
||||
if (header =~ /[\/\\]?#{name}$/)
|
||||
if header =~ /[\/\\]?#{name}$/
|
||||
header_to_mock = header
|
||||
break
|
||||
end
|
||||
end
|
||||
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')
|
||||
mock_name = MOCK_PREFIX + File.basename(hdr, '.*')
|
||||
File.join(MOCKS_DIR, mock_name + '.o')
|
||||
end
|
||||
all_headers_to_mock.uniq!
|
||||
@@ -156,47 +158,46 @@ 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} ${INCLUDE_PATH}"
|
||||
mkfile.puts ""
|
||||
mkfile.puts ''
|
||||
|
||||
# Build test suite executable
|
||||
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 $@ ${LDFLAGS} #{test_objs}"
|
||||
mkfile.puts ""
|
||||
mkfile.puts ''
|
||||
|
||||
# Run test suite and generate report
|
||||
mkfile.puts "#{test_results}: #{test_bin}"
|
||||
mkfile.puts "\t-#{test_bin} > #{test_results} 2>&1"
|
||||
mkfile.puts ""
|
||||
mkfile.puts ''
|
||||
|
||||
test_targets << test_bin
|
||||
end
|
||||
|
||||
# Generate and build mocks
|
||||
all_headers_to_mock.each do |hdr|
|
||||
mock_name = MOCK_PREFIX + File.basename(hdr, '.h')
|
||||
mock_header = File.join(MOCKS_DIR, mock_name + '.h')
|
||||
mock_name = MOCK_PREFIX + File.basename(hdr, '.*')
|
||||
mock_header = File.join(MOCKS_DIR, mock_name + File.extname(hdr))
|
||||
mock_src = File.join(MOCKS_DIR, mock_name + '.c')
|
||||
mock_obj = File.join(MOCKS_DIR, mock_name + '.o')
|
||||
|
||||
mkfile.puts "#{mock_src}: #{hdr}"
|
||||
mkfile.puts "\t@CMOCK_DIR=${CMOCK_DIR} ruby ${CMOCK_DIR}/scripts/create_mock.rb #{hdr}"
|
||||
mkfile.puts ""
|
||||
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} ${INCLUDE_PATH}"
|
||||
mkfile.puts ""
|
||||
mkfile.puts ''
|
||||
end
|
||||
|
||||
# Create test summary task
|
||||
mkfile.puts "test_summary:"
|
||||
mkfile.puts 'test_summary:'
|
||||
mkfile.puts "\t@UNITY_DIR=${UNITY_DIR} ruby ${CMOCK_DIR}/scripts/test_summary.rb #{suppress_error ? '--silent' : ''}"
|
||||
mkfile.puts ""
|
||||
mkfile.puts ".PHONY: test_summary"
|
||||
mkfile.puts ""
|
||||
mkfile.puts ''
|
||||
mkfile.puts '.PHONY: test_summary'
|
||||
mkfile.puts ''
|
||||
|
||||
# Create target to run all tests
|
||||
mkfile.puts "test: #{test_targets.map{|t| t + '.testresult'}.join(' ')} test_summary"
|
||||
mkfile.puts ""
|
||||
|
||||
mkfile.puts "test: #{test_targets.map { |t| t + '.testresult' }.join(' ')} test_summary"
|
||||
mkfile.puts ''
|
||||
end
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
require "#{ENV['CMOCK_DIR']}/lib/cmock"
|
||||
|
||||
raise "Header file to mock must be specified!" unless ARGV.length >= 1
|
||||
raise 'Header file to mock must be specified!' unless ARGV.length >= 1
|
||||
|
||||
mock_out = ENV.fetch('MOCK_OUT', './build/test/mocks')
|
||||
mock_prefix = ENV.fetch('MOCK_PREFIX', 'mock_')
|
||||
cmock = CMock.new({:plugins => [:ignore, :return_thru_ptr], :mock_prefix => mock_prefix, :mock_path => mock_out})
|
||||
cmock = CMock.new(:plugins => %i[ignore return_thru_ptr], :mock_prefix => mock_prefix, :mock_path => mock_out)
|
||||
cmock.setup_mocks(ARGV[0])
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
if ($0 == __FILE__)
|
||||
if $0 == __FILE__
|
||||
|
||||
#make sure there is at least one parameter left (the input file)
|
||||
# make sure there is at least one parameter left (the input file)
|
||||
if ARGV.length < 2
|
||||
puts ["\nusage: ruby #{__FILE__} input_test_file (output)",
|
||||
"",
|
||||
" input_test_file - this is the C file you want to create a runner for",
|
||||
" output - this is the name of the runner file to generate",
|
||||
" defaults to (input_test_file)_Runner",
|
||||
].join("\n")
|
||||
'',
|
||||
' input_test_file - this is the C file you want to create a runner for',
|
||||
' output - this is the name of the runner file to generate',
|
||||
' defaults to (input_test_file)_Runner'].join("\n")
|
||||
exit 1
|
||||
end
|
||||
|
||||
@@ -15,6 +14,5 @@ if ($0 == __FILE__)
|
||||
|
||||
test = ARGV[0]
|
||||
runner = ARGV[1]
|
||||
generator = UnityTestRunnerGenerator.new.run(test, runner)
|
||||
|
||||
UnityTestRunnerGenerator.new.run(test, runner)
|
||||
end
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
|
||||
suppress_error = !ARGV.nil? && !ARGV.empty? && (ARGV[0].upcase == "--SILENT")
|
||||
suppress_error = !ARGV.nil? && !ARGV.empty? && (ARGV[0].casecmp('--SILENT') == 0)
|
||||
|
||||
begin
|
||||
require "#{ENV['UNITY_DIR']}/auto/unity_test_summary.rb"
|
||||
|
||||
+45
-45
@@ -6,7 +6,7 @@
|
||||
|
||||
#include "cmock.h"
|
||||
|
||||
//public constants to be used by mocks
|
||||
/* public constants to be used by mocks */
|
||||
const char* CMockStringOutOfMemory = "CMock has run out of memory. Please allocate more.";
|
||||
const char* CMockStringCalledMore = "Called more times than expected.";
|
||||
const char* CMockStringCalledLess = "Called fewer times than expected.";
|
||||
@@ -19,7 +19,7 @@ const char* CMockStringPtrIsNULL = "Pointer is NULL.";
|
||||
const char* CMockStringExpNULL = "Expected NULL.";
|
||||
const char* CMockStringMismatch = "Function called with unexpected argument value.";
|
||||
|
||||
//private variables
|
||||
/* private variables */
|
||||
#ifdef CMOCK_MEM_DYNAMIC
|
||||
static unsigned char* CMock_Guts_Buffer = NULL;
|
||||
static CMOCK_MEM_INDEX_TYPE CMock_Guts_BufferSize = CMOCK_MEM_ALIGN_SIZE;
|
||||
@@ -30,37 +30,37 @@ static CMOCK_MEM_INDEX_TYPE CMock_Guts_BufferSize = CMOCK_MEM_SIZE + CMOCK_MEM
|
||||
static CMOCK_MEM_INDEX_TYPE CMock_Guts_FreePtr = CMOCK_MEM_ALIGN_SIZE;
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------
|
||||
// CMock_Guts_MemNew
|
||||
//-------------------------------------------------------
|
||||
/*-------------------------------------------------------
|
||||
* CMock_Guts_MemNew
|
||||
*-------------------------------------------------------*/
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemNew(CMOCK_MEM_INDEX_TYPE size)
|
||||
{
|
||||
CMOCK_MEM_INDEX_TYPE index;
|
||||
|
||||
//verify arguments valid (we must be allocating space for at least 1 byte, and the existing chain must be in memory somewhere)
|
||||
/* verify arguments valid (we must be allocating space for at least 1 byte, and the existing chain must be in memory somewhere) */
|
||||
if (size < 1)
|
||||
return CMOCK_GUTS_NONE;
|
||||
|
||||
//verify we have enough room
|
||||
/* verify we have enough room */
|
||||
size = size + CMOCK_MEM_INDEX_SIZE;
|
||||
if (size & CMOCK_MEM_ALIGN_MASK)
|
||||
size = (size + CMOCK_MEM_ALIGN_MASK) & ~CMOCK_MEM_ALIGN_MASK;
|
||||
if ((CMock_Guts_BufferSize - CMock_Guts_FreePtr) < size)
|
||||
{
|
||||
#ifndef CMOCK_MEM_DYNAMIC
|
||||
return CMOCK_GUTS_NONE; // nothing we can do; our static buffer is out of memory
|
||||
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()
|
||||
/* 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
|
||||
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
|
||||
/* determine where we're putting this new block, and init its pointer to be the end of the line */
|
||||
index = CMock_Guts_FreePtr + CMOCK_MEM_INDEX_SIZE;
|
||||
*(CMOCK_MEM_INDEX_TYPE*)(&CMock_Guts_Buffer[CMock_Guts_FreePtr]) = CMOCK_GUTS_NONE;
|
||||
CMock_Guts_FreePtr += size;
|
||||
@@ -68,9 +68,9 @@ CMOCK_MEM_INDEX_TYPE CMock_Guts_MemNew(CMOCK_MEM_INDEX_TYPE size)
|
||||
return index;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// CMock_Guts_MemChain
|
||||
//-------------------------------------------------------
|
||||
/*-------------------------------------------------------
|
||||
* CMock_Guts_MemChain
|
||||
*-------------------------------------------------------*/
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemChain(CMOCK_MEM_INDEX_TYPE root_index, CMOCK_MEM_INDEX_TYPE obj_index)
|
||||
{
|
||||
CMOCK_MEM_INDEX_TYPE index;
|
||||
@@ -80,12 +80,12 @@ CMOCK_MEM_INDEX_TYPE CMock_Guts_MemChain(CMOCK_MEM_INDEX_TYPE root_index, CMOCK_
|
||||
|
||||
if (root_index == CMOCK_GUTS_NONE)
|
||||
{
|
||||
//if there is no root currently, we return this object as the root of the chain
|
||||
/* if there is no root currently, we return this object as the root of the chain */
|
||||
return obj_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
//reject illegal nodes
|
||||
/* reject illegal nodes */
|
||||
if ((root_index < CMOCK_MEM_ALIGN_SIZE) || (root_index >= CMock_Guts_FreePtr))
|
||||
{
|
||||
return CMOCK_GUTS_NONE;
|
||||
@@ -98,7 +98,7 @@ CMOCK_MEM_INDEX_TYPE CMock_Guts_MemChain(CMOCK_MEM_INDEX_TYPE root_index, CMOCK_
|
||||
root = (void*)(&CMock_Guts_Buffer[root_index]);
|
||||
obj = (void*)(&CMock_Guts_Buffer[obj_index]);
|
||||
|
||||
//find the end of the existing chain and add us
|
||||
/* find the end of the existing chain and add us */
|
||||
next = root;
|
||||
do {
|
||||
index = *(CMOCK_MEM_INDEX_TYPE*)((CMOCK_MEM_PTR_AS_INT)next - CMOCK_MEM_INDEX_SIZE);
|
||||
@@ -112,21 +112,21 @@ CMOCK_MEM_INDEX_TYPE CMock_Guts_MemChain(CMOCK_MEM_INDEX_TYPE root_index, CMOCK_
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// CMock_Guts_MemNext
|
||||
//-------------------------------------------------------
|
||||
/*-------------------------------------------------------
|
||||
* CMock_Guts_MemNext
|
||||
*-------------------------------------------------------*/
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemNext(CMOCK_MEM_INDEX_TYPE previous_item_index)
|
||||
{
|
||||
CMOCK_MEM_INDEX_TYPE index;
|
||||
void* previous_item;
|
||||
|
||||
//There is nothing "next" if the pointer isn't from our buffer
|
||||
/* There is nothing "next" if the pointer isn't from our buffer */
|
||||
if ((previous_item_index < CMOCK_MEM_ALIGN_SIZE) || (previous_item_index >= CMock_Guts_FreePtr))
|
||||
return CMOCK_GUTS_NONE;
|
||||
previous_item = (void*)(&CMock_Guts_Buffer[previous_item_index]);
|
||||
|
||||
//if the pointer is good, then use it to look up the next index
|
||||
//(we know the first element always goes in zero, so NEXT must always be > 1)
|
||||
/* if the pointer is good, then use it to look up the next index
|
||||
* (we know the first element always goes in zero, so NEXT must always be > 1) */
|
||||
index = *(CMOCK_MEM_INDEX_TYPE*)((CMOCK_MEM_PTR_AS_INT)previous_item - CMOCK_MEM_INDEX_SIZE);
|
||||
if ((index > 1) && (index < CMock_Guts_FreePtr))
|
||||
return index;
|
||||
@@ -134,9 +134,9 @@ CMOCK_MEM_INDEX_TYPE CMock_Guts_MemNext(CMOCK_MEM_INDEX_TYPE previous_item_index
|
||||
return CMOCK_GUTS_NONE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// CMock_Guts_MemEndOfChain
|
||||
//-------------------------------------------------------
|
||||
/*-------------------------------------------------------
|
||||
* CMock_Guts_MemEndOfChain
|
||||
*-------------------------------------------------------*/
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemEndOfChain(CMOCK_MEM_INDEX_TYPE root_index)
|
||||
{
|
||||
CMOCK_MEM_INDEX_TYPE index = root_index;
|
||||
@@ -152,9 +152,9 @@ CMOCK_MEM_INDEX_TYPE CMock_Guts_MemEndOfChain(CMOCK_MEM_INDEX_TYPE root_index)
|
||||
return index;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// CMock_GetAddressFor
|
||||
//-------------------------------------------------------
|
||||
/*-------------------------------------------------------
|
||||
* CMock_GetAddressFor
|
||||
*-------------------------------------------------------*/
|
||||
void* CMock_Guts_GetAddressFor(CMOCK_MEM_INDEX_TYPE index)
|
||||
{
|
||||
if ((index >= CMOCK_MEM_ALIGN_SIZE) && (index < CMock_Guts_FreePtr))
|
||||
@@ -167,41 +167,41 @@ void* CMock_Guts_GetAddressFor(CMOCK_MEM_INDEX_TYPE index)
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// CMock_Guts_MemBytesCapacity
|
||||
//-------------------------------------------------------
|
||||
/*-------------------------------------------------------
|
||||
* CMock_Guts_MemBytesCapacity
|
||||
*-------------------------------------------------------*/
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemBytesCapacity(void)
|
||||
{
|
||||
return (sizeof(CMock_Guts_Buffer) - CMOCK_MEM_ALIGN_SIZE);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// CMock_Guts_MemBytesFree
|
||||
//-------------------------------------------------------
|
||||
/*-------------------------------------------------------
|
||||
* CMock_Guts_MemBytesFree
|
||||
*-------------------------------------------------------*/
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemBytesFree(void)
|
||||
{
|
||||
return CMock_Guts_BufferSize - CMock_Guts_FreePtr;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// CMock_Guts_MemBytesUsed
|
||||
//-------------------------------------------------------
|
||||
/*-------------------------------------------------------
|
||||
* CMock_Guts_MemBytesUsed
|
||||
*-------------------------------------------------------*/
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemBytesUsed(void)
|
||||
{
|
||||
return CMock_Guts_FreePtr - CMOCK_MEM_ALIGN_SIZE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// CMock_Guts_MemFreeAll
|
||||
//-------------------------------------------------------
|
||||
/*-------------------------------------------------------
|
||||
* CMock_Guts_MemFreeAll
|
||||
*-------------------------------------------------------*/
|
||||
void CMock_Guts_MemFreeAll(void)
|
||||
{
|
||||
CMock_Guts_FreePtr = CMOCK_MEM_ALIGN_SIZE; //skip the very beginning
|
||||
CMock_Guts_FreePtr = CMOCK_MEM_ALIGN_SIZE; /* skip the very beginning */
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// CMock_Guts_MemFreeFinal
|
||||
//-------------------------------------------------------
|
||||
/*-------------------------------------------------------
|
||||
* CMock_Guts_MemFreeFinal
|
||||
*-------------------------------------------------------*/
|
||||
void CMock_Guts_MemFreeFinal(void)
|
||||
{
|
||||
CMock_Guts_FreePtr = CMOCK_MEM_ALIGN_SIZE;
|
||||
|
||||
+20
-13
@@ -11,30 +11,37 @@
|
||||
|
||||
#define CMOCK_VERSION_MAJOR 2
|
||||
#define CMOCK_VERSION_MINOR 5
|
||||
#define CMOCK_VERSION_BUILD 0
|
||||
#define CMOCK_VERSION_BUILD 3
|
||||
#define CMOCK_VERSION ((CMOCK_VERSION_MAJOR << 16) | (CMOCK_VERSION_MINOR << 8) | CMOCK_VERSION_BUILD)
|
||||
|
||||
//should be big enough to index full range of CMOCK_MEM_MAX
|
||||
/* should be big enough to index full range of CMOCK_MEM_MAX */
|
||||
#ifndef CMOCK_MEM_INDEX_TYPE
|
||||
#define CMOCK_MEM_INDEX_TYPE unsigned int
|
||||
#include <stddef.h>
|
||||
#define CMOCK_MEM_INDEX_TYPE size_t
|
||||
#endif
|
||||
|
||||
#define CMOCK_GUTS_NONE (0)
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Memory API
|
||||
//-------------------------------------------------------
|
||||
#if defined __GNUC__
|
||||
# define CMOCK_FUNCTION_ATTR(a) __attribute__((a))
|
||||
#else
|
||||
# define CMOCK_FUNCTION_ATTR(a) /* ignore */
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------
|
||||
* Memory API
|
||||
*-------------------------------------------------------*/
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemNew(CMOCK_MEM_INDEX_TYPE size);
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemChain(CMOCK_MEM_INDEX_TYPE root_index, CMOCK_MEM_INDEX_TYPE obj_index);
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemNext(CMOCK_MEM_INDEX_TYPE previous_item_index);
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemEndOfChain(CMOCK_MEM_INDEX_TYPE root_index);
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemNext(CMOCK_MEM_INDEX_TYPE previous_item_index) CMOCK_FUNCTION_ATTR(pure);
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemEndOfChain(CMOCK_MEM_INDEX_TYPE root_index) CMOCK_FUNCTION_ATTR(pure);
|
||||
|
||||
void* CMock_Guts_GetAddressFor(CMOCK_MEM_INDEX_TYPE index);
|
||||
void* CMock_Guts_GetAddressFor(CMOCK_MEM_INDEX_TYPE index) CMOCK_FUNCTION_ATTR(pure);
|
||||
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemBytesCapacity(void);
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemBytesFree(void);
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemBytesUsed(void);
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemBytesCapacity(void) CMOCK_FUNCTION_ATTR(const);
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemBytesFree(void) CMOCK_FUNCTION_ATTR(pure);
|
||||
CMOCK_MEM_INDEX_TYPE CMock_Guts_MemBytesUsed(void) CMOCK_FUNCTION_ATTR(pure);
|
||||
void CMock_Guts_MemFreeAll(void);
|
||||
void CMock_Guts_MemFreeFinal(void);
|
||||
|
||||
#endif //CMOCK_FRAMEWORK
|
||||
#endif /* end of CMOCK_FRAMEWORK_H */
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include "unity.h"
|
||||
|
||||
//These are constants that the generated mocks have access to
|
||||
/* These are constants that the generated mocks have access to */
|
||||
extern const char* CMockStringOutOfMemory;
|
||||
extern const char* CMockStringCalledMore;
|
||||
extern const char* CMockStringCalledLess;
|
||||
@@ -22,8 +22,8 @@ extern const char* CMockStringPtrIsNULL;
|
||||
extern const char* CMockStringExpNULL;
|
||||
extern const char* CMockStringMismatch;
|
||||
|
||||
//define CMOCK_MEM_DYNAMIC to grab memory as needed with malloc
|
||||
//when you do that, CMOCK_MEM_SIZE is used for incremental size instead of total
|
||||
/* define CMOCK_MEM_DYNAMIC to grab memory as needed with malloc
|
||||
* when you do that, CMOCK_MEM_SIZE is used for incremental size instead of total */
|
||||
#ifdef CMOCK_MEM_STATIC
|
||||
#undef CMOCK_MEM_DYNAMIC
|
||||
#endif
|
||||
@@ -32,7 +32,7 @@ extern const char* CMockStringMismatch;
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
//this is used internally during pointer arithmetic. make sure this type is the same size as the target's pointer type
|
||||
/* this is used internally during pointer arithmetic. make sure this type is the same size as the target's pointer type */
|
||||
#ifndef CMOCK_MEM_PTR_AS_INT
|
||||
#ifdef UNITY_POINTER_WIDTH
|
||||
#ifdef UNITY_INT_WIDTH
|
||||
@@ -60,7 +60,7 @@ extern const char* CMockStringMismatch;
|
||||
#define CMOCK_MEM_PTR_AS_INT unsigned long
|
||||
#endif
|
||||
|
||||
//0 for no alignment, 1 for 16-bit, 2 for 32-bit, 3 for 64-bit
|
||||
/* 0 for no alignment, 1 for 16-bit, 2 for 32-bit, 3 for 64-bit */
|
||||
#ifndef CMOCK_MEM_ALIGN
|
||||
#ifdef UNITY_LONG_WIDTH
|
||||
#if (UNITY_LONG_WIDTH == 16)
|
||||
@@ -77,15 +77,15 @@ extern const char* CMockStringMismatch;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//amount of memory to allow cmock to use in its internal heap
|
||||
/* amount of memory to allow cmock to use in its internal heap */
|
||||
#ifndef CMOCK_MEM_SIZE
|
||||
#define CMOCK_MEM_SIZE (32768)
|
||||
#endif
|
||||
|
||||
//automatically calculated defs for easier reading
|
||||
/* automatically calculated defs for easier reading */
|
||||
#define CMOCK_MEM_ALIGN_SIZE (CMOCK_MEM_INDEX_TYPE)(1u << CMOCK_MEM_ALIGN)
|
||||
#define CMOCK_MEM_ALIGN_MASK (CMOCK_MEM_INDEX_TYPE)(CMOCK_MEM_ALIGN_SIZE - 1)
|
||||
#define CMOCK_MEM_INDEX_SIZE (CMOCK_MEM_INDEX_TYPE)(CMOCK_MEM_PTR_AS_INT)((sizeof(CMOCK_MEM_INDEX_TYPE) > CMOCK_MEM_ALIGN_SIZE) ? sizeof(CMOCK_MEM_INDEX_TYPE) : CMOCK_MEM_ALIGN_SIZE)
|
||||
|
||||
|
||||
#endif //CMOCK_FRAMEWORK_INTERNALS
|
||||
#endif /* end of CMOCK_FRAMEWORK_INTERNALS_H */
|
||||
|
||||
+7
-12
@@ -1,17 +1,12 @@
|
||||
###################################################################################
|
||||
# #
|
||||
# NAME: meson.build #
|
||||
# #
|
||||
# AUTHOR: Mike Karlesky, Mark VanderVoord, Greg Williams. #
|
||||
# WRITTEN BY: Michael Brockus. #
|
||||
# #
|
||||
# License: MIT #
|
||||
# #
|
||||
###################################################################################
|
||||
|
||||
#
|
||||
# build script written by : Michael Brockus.
|
||||
# github repo author: Mike Karlesky, Mark VanderVoord, Greg Williams.
|
||||
#
|
||||
# license: MIT
|
||||
#
|
||||
cmock_dir = include_directories('.')
|
||||
|
||||
cmock_lib = static_library(meson.project_name(),
|
||||
sources: ['cmock.c'],
|
||||
files('cmock.c'),
|
||||
dependencies: [unity_dep],
|
||||
include_directories: cmock_dir)
|
||||
|
||||
+45
-4
@@ -32,7 +32,7 @@ configure_clean
|
||||
configure_toolchain(DEFAULT_CONFIG_FILE)
|
||||
|
||||
task :default => [:test]
|
||||
task :ci => [:no_color, :default]
|
||||
task :ci => [:no_color, :default, 'test:examples', 'style:check']
|
||||
task :cruise => :ci
|
||||
|
||||
desc "Load configuration"
|
||||
@@ -42,10 +42,13 @@ task :config, :config_file do |t, args|
|
||||
configure_toolchain(args[:config_file])
|
||||
end
|
||||
|
||||
desc "Run all unit, c, and system tests"
|
||||
task :test => [:clobber, :prep_system_tests, 'test:units', 'test:c', 'test:system']
|
||||
# Still support testing everything with just 'test' but switch default to ceedling-like test:all
|
||||
task :test => ['test:all']
|
||||
|
||||
namespace :test do
|
||||
desc "Run all unit, c, and system tests"
|
||||
task :all => [:clobber, :prep_system_tests, 'test:units', 'test:c', 'test:system']
|
||||
|
||||
desc "Run Unit Tests"
|
||||
Rake::TestTask.new('units') do |t|
|
||||
t.pattern = 'unit/*_test.rb'
|
||||
@@ -86,10 +89,15 @@ namespace :test do
|
||||
run_system_test_compilations(compile_tests_to_run)
|
||||
end
|
||||
|
||||
desc "Test cmock examples"
|
||||
task :examples => [:prep_system_tests] do
|
||||
run_examples()
|
||||
end
|
||||
|
||||
#individual system tests
|
||||
FileList['system/test_interactions/*.yml'].each do |test|
|
||||
basename = File.basename(test,'.*')
|
||||
desc "Run system test #{basename}"
|
||||
#desc "Run system test #{basename}"
|
||||
task basename do
|
||||
run_system_test_interactions([test])
|
||||
end
|
||||
@@ -104,3 +112,36 @@ end
|
||||
task :no_color do
|
||||
$colour_output = false
|
||||
end
|
||||
|
||||
################### CODING STYLE VALIDATION
|
||||
namespace :style do
|
||||
desc "Check style"
|
||||
task :check do
|
||||
report "\nVERIFYING RUBY STYLE"
|
||||
report execute("rubocop ../lib ../examples ../config ../scripts --config ../vendor/unity/test/.rubocop.yml", true)
|
||||
report "Styling Ruby:PASS"
|
||||
end
|
||||
|
||||
desc "Fix Style of all C Code"
|
||||
task :c do
|
||||
run_astyle("../src/*.* ../extras/fixture/src/*.*")
|
||||
end
|
||||
|
||||
desc "Attempt to Autocorrect style"
|
||||
task :auto => ['style:clean'] do
|
||||
report execute("rubocop ../lib ../examples ../config ../scripts --auto-correct --config ../vendor/unity/test/.rubocop.yml", true)
|
||||
report "Autocorrected What We Could."
|
||||
end
|
||||
|
||||
desc "Update style todo list"
|
||||
task :todo => ['style:clean'] do
|
||||
report execute("rubocop ../lib ../examples ../config ../scripts --auto-gen-config --config ../vendor/unity/test/.rubocop.yml", true)
|
||||
report "Updated Style TODO List."
|
||||
end
|
||||
|
||||
task :clean do
|
||||
File.delete(".rubocop_todo.yml") if File.exists?(".rubocop_todo.yml")
|
||||
end
|
||||
end
|
||||
|
||||
task :style => ['style:check']
|
||||
@@ -161,6 +161,18 @@ module RakefileHelpers
|
||||
end
|
||||
end
|
||||
|
||||
def run_astyle(style_what)
|
||||
report "Styling C Code..."
|
||||
command = "AStyle " \
|
||||
"--style=allman --indent=spaces=4 --indent-switches --indent-preproc-define --indent-preproc-block " \
|
||||
"--pad-oper --pad-comma --unpad-paren --pad-header " \
|
||||
"--align-pointer=type --align-reference=name " \
|
||||
"--add-brackets --mode=c --suffix=none " \
|
||||
"#{style_what}"
|
||||
execute(command, false)
|
||||
report "Styling C:PASS"
|
||||
end
|
||||
|
||||
def report_summary
|
||||
summary = UnityTestSummary.new
|
||||
summary.root = File.expand_path(File.dirname(__FILE__)) + '/'
|
||||
@@ -374,6 +386,15 @@ module RakefileHelpers
|
||||
end
|
||||
end
|
||||
|
||||
def run_examples()
|
||||
[ "cd #{File.join("..","examples","make_example")} && make clean && make setup && make test",
|
||||
"cd #{File.join("..","examples","temp_sensor")} && rake ci"
|
||||
].each do |cmd|
|
||||
report "Testing '#{cmd}'"
|
||||
execute(cmd, false)
|
||||
end
|
||||
end
|
||||
|
||||
def fail_out(msg)
|
||||
puts msg
|
||||
exit(-1)
|
||||
|
||||
@@ -66,6 +66,7 @@ class SystemTestGenerator
|
||||
|
||||
generate_test_file(yaml_hash, namix, name)
|
||||
generate_source_file(yaml_hash, namix, name)
|
||||
generate_skeleton_file(yaml_hash, namix, name)
|
||||
end
|
||||
|
||||
def generate_types_file(yaml_hash, namix)
|
||||
@@ -136,11 +137,22 @@ class SystemTestGenerator
|
||||
includes << (namix + MOCKABLE_H) if not yaml_hash[:systest][:mockable].nil?
|
||||
includes << header_file
|
||||
|
||||
write_source_file(GENERATED_PATH + name + C_EXTENSION, includes.flatten) do |out|
|
||||
out.puts(source[:code])
|
||||
unless (source[:code].nil?)
|
||||
write_source_file(GENERATED_PATH + name + C_EXTENSION, includes.flatten) do |out|
|
||||
out.puts(source[:code])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def generate_skeleton_file(yaml_hash, namix, name)
|
||||
source = yaml_hash[:systest][:skeleton]
|
||||
return if source.nil?
|
||||
|
||||
require 'cmock.rb'
|
||||
cmock = CMock.new(GENERATED_PATH + namix + 'cmock' + YAML_EXTENSION)
|
||||
cmock.setup_skeletons("#{$cfg['compiler']['source_path']}#{name}.h")
|
||||
end
|
||||
|
||||
def write_header_file(filename, upcase_name, include_list=[])
|
||||
File.open(filename, 'w') do |out|
|
||||
out.puts("#ifndef _#{upcase_name}")
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
:includes: []
|
||||
:mock_path: ./system/generated/
|
||||
:mock_prefix: mock_
|
||||
:treat_inlines: :include
|
||||
:treat_as_void:
|
||||
- OSEK_TASK
|
||||
- VOID_TYPE_CRAZINESS
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
|
||||
static inline int dummy_func_0(void) {
|
||||
return 5;
|
||||
}
|
||||
|
||||
inline static int dummy_func_1(int a) {
|
||||
int a = dummy_func_0();
|
||||
int b = 10;
|
||||
|
||||
return a + b;
|
||||
}
|
||||
|
||||
int inline static dummy_func_2(int a, char b, float c) {
|
||||
c += 3.14;
|
||||
b -= 32;
|
||||
return a + (int)(b) + (int)c;
|
||||
}
|
||||
|
||||
void dummy_normal_func(int a);
|
||||
|
||||
inline void dummy_func_3(void) {
|
||||
//NOP
|
||||
}
|
||||
Executable → Regular
@@ -12,6 +12,7 @@
|
||||
:callback_after_arg_check: true
|
||||
:callback_include_count: false
|
||||
:treat_externs: :include
|
||||
:treat_inlines: :include
|
||||
|
||||
:systest:
|
||||
:types: |
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
:mockable: |
|
||||
void takes_function_type( FUNCTION_T myfunc );
|
||||
void takes_function_ptr( unsigned int (*func_ptr)(int, char) );
|
||||
void takes_function_ptr_shorthand( unsigned int func_ptr(int, char*) );
|
||||
void takes_const_function_ptr( unsigned int (* const)(int, char) );
|
||||
unsigned short (*returns_function_ptr( const char op_code ))( int, long int );
|
||||
|
||||
|
||||
@@ -0,0 +1,325 @@
|
||||
---
|
||||
:cmock:
|
||||
:plugins:
|
||||
- 'ignore_stateless'
|
||||
|
||||
: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: 'successfully exercise simple ExpectAndReturn mock calls'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
bar_Expect(2);
|
||||
foo_ExpectAndReturn(1, 10);
|
||||
foo_ExpectAndReturn(2, 20);
|
||||
foo_ExpectAndReturn(3, 30);
|
||||
TEST_ASSERT_EQUAL(60, function(1, 2, 3));
|
||||
}
|
||||
|
||||
- :pass: TRUE
|
||||
:should: 'ignore foo() calls'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
bar_Expect(4);
|
||||
foo_IgnoreAndReturn(40);
|
||||
TEST_ASSERT_EQUAL(120, function(3, 4, 3));
|
||||
}
|
||||
|
||||
- :pass: TRUE
|
||||
:should: 'ignore the situation where foo() is not called even though we explicitly ignored it'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
foo_IgnoreAndReturn(20);
|
||||
//notice we do not call foo
|
||||
}
|
||||
|
||||
- :pass: TRUE
|
||||
:should: 'ignore foo() calls and always return last item'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
bar_Expect(4);
|
||||
foo_IgnoreAndReturn(20);
|
||||
foo_IgnoreAndReturn(30);
|
||||
TEST_ASSERT_EQUAL(90, function(3, 4, 9));
|
||||
}
|
||||
|
||||
- :pass: TRUE
|
||||
:should: 'ignore bar() and foo() calls'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
bar_Ignore();
|
||||
foo_IgnoreAndReturn(50);
|
||||
TEST_ASSERT_EQUAL(150, function(0, 0, 0));
|
||||
}
|
||||
|
||||
- :pass: TRUE
|
||||
:should: 'multiple cycles of expects still pass when ignores enabled'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
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: 'multiple cycles of expects still fail when ignores enabled'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
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(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 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: 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 only the ignore and return is acknowledged'
|
||||
: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(60, function(4, 5, 6));
|
||||
}
|
||||
|
||||
# StopIgnore
|
||||
|
||||
- :pass: FALSE
|
||||
:should: 'fail when function is called after ignore is stopped'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
bar_Ignore();
|
||||
foo_IgnoreAndReturn(10);
|
||||
function(0, 0, 0);
|
||||
bar_StopIgnore();
|
||||
function(0, 0, 0);
|
||||
}
|
||||
|
||||
- :pass: FALSE
|
||||
:should: 'delete expect after ignore is stopped'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
bar_Ignore();
|
||||
foo_ExpectAndReturn(0, 40);
|
||||
foo_ExpectAndReturn(0, 30);
|
||||
foo_ExpectAndReturn(0, 40);
|
||||
|
||||
foo_IgnoreAndReturn(20);
|
||||
foo_StopIgnore();
|
||||
|
||||
TEST_ASSERT_EQUAL(110, function(0, 0, 0)); // THIS SHOULD FAIL
|
||||
}
|
||||
|
||||
- :pass: TRUE
|
||||
:should: 'delete expected return values after ignore is stopped'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
bar_Ignore();
|
||||
foo_ExpectAndReturn(0, 40);
|
||||
foo_ExpectAndReturn(0, 30);
|
||||
foo_ExpectAndReturn(0, 40);
|
||||
|
||||
foo_IgnoreAndReturn(20);
|
||||
foo_StopIgnore();
|
||||
|
||||
foo_ExpectAndReturn(0, 50);
|
||||
foo_ExpectAndReturn(0, 30);
|
||||
foo_ExpectAndReturn(0, 40);
|
||||
TEST_ASSERT_EQUAL(120, function(0, 0, 0));
|
||||
}
|
||||
|
||||
...
|
||||
@@ -0,0 +1,55 @@
|
||||
---
|
||||
:cmock:
|
||||
:plugins:
|
||||
- # none
|
||||
:skeleton_path: system/generated
|
||||
|
||||
:systest:
|
||||
:types: |
|
||||
#define UINT32 unsigned int
|
||||
|
||||
:mockable: |
|
||||
UINT32 something(int a);
|
||||
|
||||
:skeleton: skeleton.h
|
||||
|
||||
:source:
|
||||
:header: |
|
||||
void function_a(void);
|
||||
int function_b(int a, int b);
|
||||
const char* function_c(void);
|
||||
|
||||
# we are purposefully not including a :code section because it will be generated with skeleton
|
||||
|
||||
:tests:
|
||||
:common: |
|
||||
void setUp(void) {}
|
||||
void tearDown(void) {}
|
||||
|
||||
:units:
|
||||
- :pass: TRUE
|
||||
:should: 'generate an empty shell for functions with no return values'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
function_a();
|
||||
}
|
||||
|
||||
- :pass: TRUE
|
||||
:should: 'return numerical zero for numerical return values'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
TEST_ASSERT_EQUAL_INT(0, function_b(1, 2));
|
||||
}
|
||||
|
||||
- :pass: TRUE
|
||||
:should: 'return null for pointer return values'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
TEST_ASSERT_NULL(function_c());
|
||||
}
|
||||
|
||||
|
||||
...
|
||||
@@ -0,0 +1,76 @@
|
||||
---
|
||||
:cmock:
|
||||
:plugins:
|
||||
- # none
|
||||
:skeleton_path: system/generated
|
||||
|
||||
:systest:
|
||||
:types: |
|
||||
#define UINT32 unsigned int
|
||||
|
||||
:mockable: |
|
||||
UINT32 something(int a);
|
||||
|
||||
:skeleton: skeleton_update.h
|
||||
|
||||
:source:
|
||||
:header: |
|
||||
void function_a(void);
|
||||
int function_b(int a, int b);
|
||||
const char* function_c(void);
|
||||
|
||||
# note that this code section exists and will be updated by the skeleton generator
|
||||
:code: |
|
||||
const char* donuts = "donuts";
|
||||
const char* function_c(void)
|
||||
{
|
||||
return donuts;
|
||||
}
|
||||
|
||||
int function_d(void)
|
||||
{
|
||||
return 77;
|
||||
}
|
||||
|
||||
|
||||
:tests:
|
||||
:common: |
|
||||
void setUp(void) {}
|
||||
void tearDown(void) {}
|
||||
extern int function_d();
|
||||
|
||||
:units:
|
||||
- :pass: TRUE
|
||||
:should: 'generate an empty shell for functions with no return values'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
function_a();
|
||||
}
|
||||
|
||||
- :pass: TRUE
|
||||
:should: 'return numerical zero for numerical return values'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
TEST_ASSERT_EQUAL_INT(0, function_b(1, 2));
|
||||
}
|
||||
|
||||
- :pass: TRUE
|
||||
:should: 'not overwrite functions that already exist'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
TEST_ASSERT_EQUAL_STRING("donuts", function_c());
|
||||
}
|
||||
|
||||
- :pass: TRUE
|
||||
:should: 'leave functions it has never heard of'
|
||||
:code: |
|
||||
test()
|
||||
{
|
||||
TEST_ASSERT_EQUAL_INT(77, function_d());
|
||||
}
|
||||
|
||||
|
||||
...
|
||||
@@ -13,33 +13,39 @@ 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_nil(CMockConfig::CMockDefaultOptions[:includes])
|
||||
assert_equal(CMockConfig::CMOCK_DEFAULT_OPTIONS[:mock_path], config.mock_path)
|
||||
assert_nil(CMockConfig::CMOCK_DEFAULT_OPTIONS[: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)
|
||||
assert_equal(CMockConfig::CMOCK_DEFAULT_OPTIONS[:attributes], config.attributes)
|
||||
assert_equal(CMockConfig::CMOCK_DEFAULT_OPTIONS[:plugins], config.plugins)
|
||||
assert_equal(CMockConfig::CMOCK_DEFAULT_OPTIONS[:treat_externs], config.treat_externs)
|
||||
assert_equal(CMockConfig::CMOCK_DEFAULT_OPTIONS[:treat_inlines], config.treat_inlines)
|
||||
assert_equal(CMockConfig::CMOCK_DEFAULT_OPTIONS[:inline_function_patterns], config.inline_function_patterns)
|
||||
end
|
||||
|
||||
it "replace only options specified in a hash" do
|
||||
test_includes = ['hello']
|
||||
test_attributes = ['blah', 'bleh']
|
||||
config = CMockConfig.new(:includes => test_includes, :attributes => test_attributes)
|
||||
assert_equal(CMockConfig::CMockDefaultOptions[:mock_path], config.mock_path)
|
||||
assert_equal(CMockConfig::CMOCK_DEFAULT_OPTIONS[:mock_path], config.mock_path)
|
||||
assert_equal(test_includes, config.includes)
|
||||
assert_equal(test_attributes, config.attributes)
|
||||
assert_equal(CMockConfig::CMockDefaultOptions[:plugins], config.plugins)
|
||||
assert_equal(CMockConfig::CMockDefaultOptions[:treat_externs], config.treat_externs)
|
||||
assert_equal(CMockConfig::CMOCK_DEFAULT_OPTIONS[:plugins], config.plugins)
|
||||
assert_equal(CMockConfig::CMOCK_DEFAULT_OPTIONS[:treat_externs], config.treat_externs)
|
||||
assert_equal(CMockConfig::CMOCK_DEFAULT_OPTIONS[:treat_inlines], config.treat_inlines)
|
||||
assert_equal(CMockConfig::CMOCK_DEFAULT_OPTIONS[:inline_function_patterns], config.inline_function_patterns)
|
||||
end
|
||||
|
||||
it "replace only options specified in a yaml file" 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_nil(CMockConfig::CMockDefaultOptions[:includes])
|
||||
assert_equal(CMockConfig::CMOCK_DEFAULT_OPTIONS[:mock_path], config.mock_path)
|
||||
assert_nil(CMockConfig::CMOCK_DEFAULT_OPTIONS[:includes])
|
||||
assert_nil(config.includes)
|
||||
assert_equal(test_plugins, config.plugins)
|
||||
assert_equal(:include, config.treat_externs)
|
||||
assert_equal(:include, config.treat_inlines)
|
||||
assert_equal(['MY_INLINE_FUNCTION_DECLARATION_PATTERN'], config.inline_function_patterns)
|
||||
end
|
||||
|
||||
it "populate treat_as map with internal standard_treat_as_map defaults, redefine defaults, and add custom values" do
|
||||
|
||||
@@ -2,4 +2,6 @@
|
||||
:plugins:
|
||||
- 'soda'
|
||||
- 'pizza'
|
||||
:treat_externs: :include
|
||||
:treat_externs: :include
|
||||
:treat_inlines: :include
|
||||
:inline_function_patterns: ['MY_INLINE_FUNCTION_DECLARATION_PATTERN']
|
||||
|
||||
@@ -54,8 +54,11 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
@config.expect :includes_c_post_header, nil
|
||||
@config.expect :subdir, nil
|
||||
@config.expect :fail_on_unexpected_calls, true
|
||||
@config.expect :treat_inlines, :exclude
|
||||
@config.expect :exclude_setjmp_h, false
|
||||
@cmock_generator = CMockGenerator.new(@config, @file_writer, @utils, @plugins)
|
||||
@cmock_generator.module_name = @module_name
|
||||
@cmock_generator.module_ext = '.h'
|
||||
@cmock_generator.mock_name = "Mock#{@module_name}"
|
||||
@cmock_generator.clean_mock_name = "Mock#{@module_name}"
|
||||
|
||||
@@ -72,20 +75,30 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
@config.expect :includes_c_post_header, nil
|
||||
@config.expect :subdir, nil
|
||||
@config.expect :fail_on_unexpected_calls, true
|
||||
@config.expect :treat_inlines, :exclude
|
||||
@config.expect :exclude_setjmp_h, false
|
||||
@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}"
|
||||
@cmock_generator_strict.clean_mock_name = "Mock#{@module_name}"
|
||||
|
||||
@test_project = {
|
||||
:module_name => @module_name,
|
||||
:module_ext => '.h',
|
||||
:mock_name => "Mock#{@module_name}",
|
||||
:clean_name => "Mock#{@module_name}",
|
||||
:folder => nil,
|
||||
:parsed_stuff => {},
|
||||
:skeleton => false
|
||||
}
|
||||
end
|
||||
|
||||
after do
|
||||
end
|
||||
|
||||
it "create the top of a header file with optional include files from config and include file from plugin" do
|
||||
def helper_create_header_top_with_opt_includes_form_config_and_plugin(ext)
|
||||
@config.expect :mock_prefix, "Mock"
|
||||
@config.expect :mock_suffix, ""
|
||||
@config.expect :weak, ""
|
||||
orig_filename = "PoutPoutFish.h"
|
||||
|
||||
orig_filename = "PoutPoutFish#{ext}"
|
||||
define_name = "MOCKPOUTPOUTFISH_H"
|
||||
output = []
|
||||
expected = [
|
||||
@@ -115,32 +128,26 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
@config.expect :orig_header_include_fmt, "#include \"%s\""
|
||||
@plugins.expect :run, "#include \"PluginRequiredHeader.h\"\n", [:include_files]
|
||||
|
||||
@cmock_generator.create_mock_header_header(output, "MockPoutPoutFish.h")
|
||||
# Update the extention for this test
|
||||
test_project = @test_project.clone
|
||||
test_project[:module_ext] = ext
|
||||
|
||||
@cmock_generator.create_mock_header_header(output, "Mock#{orig_filename}", test_project)
|
||||
|
||||
assert_equal(expected, output)
|
||||
end
|
||||
|
||||
it "handle dashes and spaces in the module name" do
|
||||
#no strict handling
|
||||
@config.expect :mock_prefix, "Mock"
|
||||
@config.expect :mock_suffix, ""
|
||||
@config.expect :weak, ""
|
||||
@config.expect :enforce_strict_ordering, nil
|
||||
@config.expect :framework, :unity
|
||||
@config.expect :includes, ["ConfigRequiredHeader1.h","ConfigRequiredHeader2.h"]
|
||||
@config.expect :includes_h_post_orig_header, nil
|
||||
@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"
|
||||
@cmock_generator2.clean_mock_name = "MockPout_Pout_Fish"
|
||||
it "create the top of a header file with optional include files from config and include file from plugin" do
|
||||
['.h','.hh','.hpp'].each do |ext|
|
||||
helper_create_header_top_with_opt_includes_form_config_and_plugin(ext)
|
||||
end
|
||||
end
|
||||
|
||||
it "handle dashes and spaces in the module name" do
|
||||
@config.expect :mock_prefix, "Mock"
|
||||
@config.expect :mock_suffix, ""
|
||||
@config.expect :weak, ""
|
||||
|
||||
orig_filename = "Pout-Pout Fish.h"
|
||||
define_name = "MOCKPOUT_POUT_FISH_H"
|
||||
output = []
|
||||
@@ -171,7 +178,13 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
@config.expect :orig_header_include_fmt, "#include \"%s\""
|
||||
@plugins.expect :run, "#include \"PluginRequiredHeader.h\"\n", [:include_files]
|
||||
|
||||
@cmock_generator2.create_mock_header_header(output, "MockPout-Pout Fish.h")
|
||||
# Create a project with some added challenges
|
||||
test_project = @test_project.clone
|
||||
test_project[:module_name] = "Pout-Pout Fish"
|
||||
test_project[:mock_name] = "MockPout-Pout Fish"
|
||||
test_project[:clean_name] = "MockPout_Pout_Fish"
|
||||
|
||||
@cmock_generator.create_mock_header_header(output, "MockPout-Pout Fish.h", test_project)
|
||||
|
||||
assert_equal(expected, output)
|
||||
end
|
||||
@@ -209,7 +222,7 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
@config.expect :orig_header_include_fmt, "#include \"%s\""
|
||||
@plugins.expect :run, '', [:include_files]
|
||||
|
||||
@cmock_generator.create_mock_header_header(output, "MockPoutPoutFish.h")
|
||||
@cmock_generator.create_mock_header_header(output, "MockPoutPoutFish.h", @test_project)
|
||||
|
||||
assert_equal(expected, output)
|
||||
end
|
||||
@@ -248,7 +261,7 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
@config.expect :orig_header_include_fmt, "#include \"%s\""
|
||||
@plugins.expect :run, "#include \"PluginRequiredHeader.h\"\n", [:include_files]
|
||||
|
||||
@cmock_generator.create_mock_header_header(output, "MockPoutPoutFish.h")
|
||||
@cmock_generator.create_mock_header_header(output, "MockPoutPoutFish.h", @test_project)
|
||||
|
||||
assert_equal(expected, output)
|
||||
end
|
||||
@@ -266,7 +279,8 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
"\n\n"
|
||||
]
|
||||
|
||||
@cmock_generator.create_typedefs(output, typedefs)
|
||||
@test_project[:parsed_stuff][:typedefs] = typedefs
|
||||
@cmock_generator.create_typedefs(output, @test_project)
|
||||
|
||||
assert_equal(expected, output.flatten)
|
||||
end
|
||||
@@ -280,7 +294,7 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
"void #{mock_name}_Verify(void);\n\n"
|
||||
]
|
||||
|
||||
@cmock_generator.create_mock_header_service_call_declarations(output)
|
||||
@cmock_generator.create_mock_header_service_call_declarations(output, @test_project)
|
||||
|
||||
assert_equal(expected, output)
|
||||
end
|
||||
@@ -324,7 +338,8 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
"\n"
|
||||
]
|
||||
|
||||
@cmock_generator.create_source_header_section(output, "MockPoutPoutFish.c", functions)
|
||||
@test_project[:parsed_stuff][:functions] = functions
|
||||
@cmock_generator.create_source_header_section(output, "MockPoutPoutFish.c", @test_project)
|
||||
|
||||
assert_equal(expected, output)
|
||||
end
|
||||
@@ -338,7 +353,8 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
"} Mock;\n\n"
|
||||
].join
|
||||
|
||||
@cmock_generator.create_instance_structure(output, functions)
|
||||
@test_project[:parsed_stuff][:functions] = functions
|
||||
@cmock_generator.create_instance_structure(output, @test_project)
|
||||
|
||||
assert_equal(expected, output.join)
|
||||
end
|
||||
@@ -368,7 +384,8 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
@plugins.expect :run, [" d1"], [:instance_structure, functions[0]]
|
||||
@plugins.expect :run, [" e1"," e2"," e3"], [:instance_structure, functions[1]]
|
||||
|
||||
@cmock_generator.create_instance_structure(output, functions)
|
||||
@test_project[:parsed_stuff][:functions] = functions
|
||||
@cmock_generator.create_instance_structure(output, @test_project)
|
||||
|
||||
assert_equal(expected, output.join)
|
||||
end
|
||||
@@ -400,7 +417,8 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
output = []
|
||||
expected = "void MockPoutPoutFish_Verify(void)\n{\n}\n\n"
|
||||
|
||||
@cmock_generator.create_mock_verify_function(output, functions)
|
||||
@test_project[:parsed_stuff][:functions] = functions
|
||||
@cmock_generator.create_mock_verify_function(output, @test_project)
|
||||
|
||||
assert_equal(expected, output.join)
|
||||
end
|
||||
@@ -425,7 +443,8 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
@plugins.expect :run, [" Uno_Second"," Dos_Second"], [:mock_verify, functions[1]]
|
||||
|
||||
@cmock_generator.ordered = true
|
||||
@cmock_generator.create_mock_verify_function(output, functions)
|
||||
@test_project[:parsed_stuff][:functions] = functions
|
||||
@cmock_generator.create_mock_verify_function(output, @test_project)
|
||||
|
||||
assert_equal(expected, output.flatten)
|
||||
end
|
||||
@@ -437,7 +456,7 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
"}\n\n"
|
||||
]
|
||||
|
||||
@cmock_generator.create_mock_init_function(output)
|
||||
@cmock_generator.create_mock_init_function(output, @test_project)
|
||||
|
||||
assert_equal(expected.join, output.join)
|
||||
end
|
||||
@@ -451,7 +470,8 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
"}\n\n"
|
||||
]
|
||||
|
||||
@cmock_generator.create_mock_destroy_function(output, functions)
|
||||
@test_project[:parsed_stuff][:functions] = functions
|
||||
@cmock_generator.create_mock_destroy_function(output, @test_project)
|
||||
|
||||
assert_equal(expected.join, output.join)
|
||||
end
|
||||
@@ -472,7 +492,8 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
@plugins.expect :run, [], [:mock_destroy, functions[0]]
|
||||
@plugins.expect :run, [" uno"], [:mock_destroy, functions[1]]
|
||||
|
||||
@cmock_generator_strict.create_mock_destroy_function(output, functions)
|
||||
@test_project[:parsed_stuff][:functions] = functions
|
||||
@cmock_generator_strict.create_mock_destroy_function(output, @test_project)
|
||||
|
||||
assert_equal(expected.join, output.join)
|
||||
end
|
||||
@@ -484,6 +505,9 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
:args => ["uint32 sandwiches", "const char* named"],
|
||||
:var_arg => nil,
|
||||
:name => "SupaFunction",
|
||||
:unscoped_name => "SupaFunction",
|
||||
:namespace => [],
|
||||
:class => nil,
|
||||
:attributes => "__inline"
|
||||
}
|
||||
output = []
|
||||
@@ -519,6 +543,9 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
:args => ["uint32 sandwiches"],
|
||||
:var_arg => "corn ...",
|
||||
:name => "SupaFunction",
|
||||
:unscoped_name => "SupaFunction",
|
||||
:namespace => [],
|
||||
:class => nil,
|
||||
:attributes => nil
|
||||
}
|
||||
output = []
|
||||
@@ -545,4 +572,123 @@ describe CMockGenerator, "Verify CMockGenerator Module" do
|
||||
|
||||
assert_equal(expected.join, output.join)
|
||||
end
|
||||
|
||||
it "create mock implementation function in source file for C++ static member" do
|
||||
function = { :modifier => "static",
|
||||
:return => test_return[:int],
|
||||
:args_string => "uint32 sandwiches, const char* named",
|
||||
:args => ["uint32 sandwiches", "const char* named"],
|
||||
:var_arg => nil,
|
||||
:unscoped_name => "SupaFunction",
|
||||
:namespace => ["ns1", "ns2"],
|
||||
:class => "SupaClass",
|
||||
:name => "ns1_ns2_SupaClass_SupaFunction",
|
||||
:attributes => nil
|
||||
}
|
||||
output = []
|
||||
expected = [ "namespace ns1 {\n",
|
||||
"namespace ns2 {\n",
|
||||
"static int SupaClass::SupaFunction(uint32 sandwiches, const char* named)\n",
|
||||
"{\n",
|
||||
" UNITY_LINE_TYPE cmock_line = TEST_LINE_NUM;\n",
|
||||
" CMOCK_ns1_ns2_SupaClass_SupaFunction_CALL_INSTANCE* cmock_call_instance;\n",
|
||||
" UNITY_SET_DETAIL(CMockString_ns1_ns2_SupaClass_SupaFunction);\n",
|
||||
" cmock_call_instance = (CMOCK_ns1_ns2_SupaClass_SupaFunction_CALL_INSTANCE*)CMock_Guts_GetAddressFor(Mock.ns1_ns2_SupaClass_SupaFunction_CallInstance);\n",
|
||||
" Mock.ns1_ns2_SupaClass_SupaFunction_CallInstance = CMock_Guts_MemNext(Mock.ns1_ns2_SupaClass_SupaFunction_CallInstance);\n",
|
||||
" uno",
|
||||
" UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringCalledMore);\n",
|
||||
" cmock_line = cmock_call_instance->LineNumber;\n",
|
||||
" dos",
|
||||
" tres",
|
||||
" UNITY_CLR_DETAILS();\n",
|
||||
" return cmock_call_instance->ReturnVal;\n",
|
||||
"}\n",
|
||||
"}\n",
|
||||
"}\n\n",
|
||||
]
|
||||
@plugins.expect :run, [" uno"], [:mock_implementation_precheck, function]
|
||||
@plugins.expect :run, [" dos"," tres"], [:mock_implementation, function]
|
||||
|
||||
@cmock_generator.create_mock_implementation(output, function)
|
||||
|
||||
assert_equal(expected.join, output.join)
|
||||
end
|
||||
|
||||
it "create mock implementation functions in source file with different options for C++ static member" do
|
||||
function = { :modifier => "static",
|
||||
:c_calling_convention => "__stdcall",
|
||||
:return => test_return[:int],
|
||||
:args_string => "uint32 sandwiches",
|
||||
:args => ["uint32 sandwiches"],
|
||||
:var_arg => "corn ...",
|
||||
:name => "SupaClass_SupaFunction",
|
||||
:unscoped_name => "SupaFunction",
|
||||
:namespace => [],
|
||||
:class => "SupaClass",
|
||||
:attributes => nil
|
||||
}
|
||||
output = []
|
||||
expected = [ "static int __stdcall SupaClass::SupaFunction(uint32 sandwiches, corn ...)\n",
|
||||
"{\n",
|
||||
" UNITY_LINE_TYPE cmock_line = TEST_LINE_NUM;\n",
|
||||
" CMOCK_SupaClass_SupaFunction_CALL_INSTANCE* cmock_call_instance;\n",
|
||||
" UNITY_SET_DETAIL(CMockString_SupaClass_SupaFunction);\n",
|
||||
" cmock_call_instance = (CMOCK_SupaClass_SupaFunction_CALL_INSTANCE*)CMock_Guts_GetAddressFor(Mock.SupaClass_SupaFunction_CallInstance);\n",
|
||||
" Mock.SupaClass_SupaFunction_CallInstance = CMock_Guts_MemNext(Mock.SupaClass_SupaFunction_CallInstance);\n",
|
||||
" uno",
|
||||
" UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringCalledMore);\n",
|
||||
" cmock_line = cmock_call_instance->LineNumber;\n",
|
||||
" dos",
|
||||
" tres",
|
||||
" UNITY_CLR_DETAILS();\n",
|
||||
" return cmock_call_instance->ReturnVal;\n",
|
||||
"}\n\n"
|
||||
]
|
||||
@plugins.expect :run, [" uno"], [:mock_implementation_precheck, function]
|
||||
@plugins.expect :run, [" dos"," tres"], [:mock_implementation, function]
|
||||
|
||||
@cmock_generator.create_mock_implementation(output, function)
|
||||
|
||||
assert_equal(expected.join, output.join)
|
||||
end
|
||||
|
||||
it "creates using statements for C++ static member in namespace" do
|
||||
function = { :modifier => "static",
|
||||
:return => test_return[:int],
|
||||
:args_string => "uint32 sandwiches",
|
||||
:args => ["uint32 sandwiches"],
|
||||
:var_arg => nil,
|
||||
:unscoped_name => "SupaFunction",
|
||||
:namespace => ["ns1"],
|
||||
:class => "SupaClass",
|
||||
:name => "ns1_SupaClass_SupaFunction",
|
||||
:attributes => nil
|
||||
}
|
||||
output = []
|
||||
expected = "using namespace ns1;\n"
|
||||
|
||||
@cmock_generator.create_using_statement(output, function)
|
||||
|
||||
assert_equal(expected, output.join)
|
||||
end
|
||||
|
||||
it "creates using statements for C++ static member in nested namespace" do
|
||||
function = { :modifier => "static",
|
||||
:return => test_return[:int],
|
||||
:args_string => "uint32 sandwiches",
|
||||
:args => ["uint32 sandwiches"],
|
||||
:var_arg => nil,
|
||||
:unscoped_name => "SupaFunction",
|
||||
:namespace => ["ns1", "ns2"],
|
||||
:class => "SupaClass",
|
||||
:name => "ns1_ns2_SupaClass_SupaFunction",
|
||||
:attributes => nil
|
||||
}
|
||||
output = []
|
||||
expected = "using namespace ns1::ns2;\n"
|
||||
|
||||
@cmock_generator.create_using_statement(output, function)
|
||||
|
||||
assert_equal(expected, output.join)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -32,7 +32,7 @@ describe CMockGeneratorPluginCallback, "Verify CMockGeneratorPluginCallback Modu
|
||||
|
||||
it "add to instance structure" do
|
||||
function = {:name => "Oak", :args => [:type => "int*", :name => "blah", :ptr? => true], :return => test_return[:int_ptr]}
|
||||
expected = " int Oak_CallbackBool;\n" +
|
||||
expected = " char Oak_CallbackBool;\n" +
|
||||
" CMOCK_Oak_CALLBACK Oak_CallbackFunctionPointer;\n" +
|
||||
" int Oak_CallbackCalls;\n"
|
||||
returned = @cmock_generator_plugin_callback.instance_structure(function)
|
||||
@@ -191,9 +191,9 @@ describe CMockGeneratorPluginCallback, "Verify CMockGeneratorPluginCallback Modu
|
||||
expected = [" if (!Mock.Apple_CallbackBool &&\n",
|
||||
" Mock.Apple_CallbackFunctionPointer != NULL)\n",
|
||||
" {\n",
|
||||
" int ret = Mock.Apple_CallbackFunctionPointer(Mock.Apple_CallbackCalls++);\n",
|
||||
" int cmock_cb_ret = Mock.Apple_CallbackFunctionPointer(Mock.Apple_CallbackCalls++);\n",
|
||||
" UNITY_CLR_DETAILS();\n",
|
||||
" return ret;\n",
|
||||
" return cmock_cb_ret;\n",
|
||||
" }\n"
|
||||
].join
|
||||
returned = @cmock_generator_plugin_callback.mock_implementation_precheck(function)
|
||||
@@ -246,9 +246,9 @@ describe CMockGeneratorPluginCallback, "Verify CMockGeneratorPluginCallback Modu
|
||||
expected = [" if (!Mock.Apple_CallbackBool &&\n",
|
||||
" Mock.Apple_CallbackFunctionPointer != NULL)\n",
|
||||
" {\n",
|
||||
" int ret = Mock.Apple_CallbackFunctionPointer(steak, flag, Mock.Apple_CallbackCalls++);\n",
|
||||
" int cmock_cb_ret = Mock.Apple_CallbackFunctionPointer(steak, flag, Mock.Apple_CallbackCalls++);\n",
|
||||
" UNITY_CLR_DETAILS();\n",
|
||||
" return ret;\n",
|
||||
" return cmock_cb_ret;\n",
|
||||
" }\n"
|
||||
].join
|
||||
returned = @cmock_generator_plugin_callback.mock_implementation_precheck(function)
|
||||
@@ -264,14 +264,14 @@ describe CMockGeneratorPluginCallback, "Verify CMockGeneratorPluginCallback Modu
|
||||
|
||||
expected = ["void Lemon_AddCallback(CMOCK_Lemon_CALLBACK Callback)\n",
|
||||
"{\n",
|
||||
" Mock.Lemon_IgnoreBool = (int)0;\n",
|
||||
" Mock.Lemon_CallbackBool = (int)1;\n",
|
||||
" Mock.Lemon_IgnoreBool = (char)0;\n",
|
||||
" Mock.Lemon_CallbackBool = (char)1;\n",
|
||||
" Mock.Lemon_CallbackFunctionPointer = Callback;\n",
|
||||
"}\n\n",
|
||||
"void Lemon_Stub(CMOCK_Lemon_CALLBACK Callback)\n",
|
||||
"{\n",
|
||||
" Mock.Lemon_IgnoreBool = (int)0;\n",
|
||||
" Mock.Lemon_CallbackBool = (int)0;\n",
|
||||
" Mock.Lemon_IgnoreBool = (char)0;\n",
|
||||
" Mock.Lemon_CallbackBool = (char)0;\n",
|
||||
" Mock.Lemon_CallbackFunctionPointer = Callback;\n",
|
||||
"}\n\n"
|
||||
].join
|
||||
|
||||
@@ -11,6 +11,9 @@ describe CMockGeneratorPluginCexception, "Verify CMockGeneratorPluginCexception
|
||||
|
||||
before do
|
||||
create_mocks :config, :utils
|
||||
|
||||
@config.expect :exclude_setjmp_h, false
|
||||
|
||||
@cmock_generator_plugin_cexception = CMockGeneratorPluginCexception.new(@config, @utils)
|
||||
end
|
||||
|
||||
@@ -93,4 +96,13 @@ describe CMockGeneratorPluginCexception, "Verify CMockGeneratorPluginCexception
|
||||
assert_equal(expected, returned)
|
||||
end
|
||||
|
||||
it "should throw an exception if we try to use this plugin when setjmp disabled" do
|
||||
|
||||
@config.expect :exclude_setjmp_h, true
|
||||
|
||||
assert_raises RuntimeError do
|
||||
@cmock_generator_plugin_cexception = CMockGeneratorPluginCexception.new(@config, @utils)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -174,9 +174,11 @@ describe CMockGeneratorPluginExpect, "Verify CMockGeneratorPluginExpect Module W
|
||||
|
||||
it "add mock verify lines" do
|
||||
function = {:name => "Banana" }
|
||||
expected = " UNITY_SET_DETAIL(CMockString_Banana);\n" +
|
||||
" UNITY_TEST_ASSERT(CMOCK_GUTS_NONE == call_instance, cmock_line, CMockStringCalledLess);\n" +
|
||||
" UNITY_CLR_DETAILS();\n"
|
||||
expected = " if (CMOCK_GUTS_NONE != call_instance)\n" \
|
||||
" {\n" \
|
||||
" UNITY_SET_DETAIL(CMockString_Banana);\n" \
|
||||
" UNITY_TEST_FAIL(cmock_line, CMockStringCalledLess);\n" \
|
||||
" }\n"
|
||||
returned = @cmock_generator_plugin_expect.mock_verify(function)
|
||||
assert_equal(expected, returned)
|
||||
end
|
||||
|
||||
@@ -57,7 +57,7 @@ describe CMockGeneratorPluginExpectAnyArgs, "Verify CMockGeneratorPluginExpectAn
|
||||
expected = ["void Slime_CMockExpectAnyArgs(UNITY_LINE_TYPE cmock_line)\n",
|
||||
"{\n",
|
||||
"mock_return_1",
|
||||
" cmock_call_instance->ExpectAnyArgsBool = (int)1;\n",
|
||||
" cmock_call_instance->ExpectAnyArgsBool = (char)1;\n",
|
||||
"}\n\n"
|
||||
].join
|
||||
@utils.expect :code_add_base_expectation, "mock_return_1", ["Slime", true]
|
||||
|
||||
@@ -190,11 +190,12 @@ describe CMockGeneratorPluginExpect, "Verify CMockGeneratorPluginExpect Module w
|
||||
|
||||
it "add mock verify lines" do
|
||||
function = {:name => "Banana" }
|
||||
expected = " UNITY_SET_DETAIL(CMockString_Banana);\n" +
|
||||
" UNITY_TEST_ASSERT(CMOCK_GUTS_NONE == call_instance, cmock_line, CMockStringCalledLess);\n" +
|
||||
" UNITY_CLR_DETAILS();\n"
|
||||
expected = " if (CMOCK_GUTS_NONE != call_instance)\n" \
|
||||
" {\n" \
|
||||
" UNITY_SET_DETAIL(CMockString_Banana);\n" \
|
||||
" UNITY_TEST_FAIL(cmock_line, CMockStringCalledLess);\n" \
|
||||
" }\n"
|
||||
returned = @cmock_generator_plugin_expect.mock_verify(function)
|
||||
assert_equal(expected, returned)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -54,9 +54,9 @@ describe CMockGeneratorPluginIgnoreArg, "Verify CMockGeneratorPluginIgnoreArg Mo
|
||||
end
|
||||
|
||||
it "add to tyepdef structure mock needs of functions of style 'void func(int chicken, int* pork)'" do
|
||||
expected = " int IgnoreArg_chicken;\n" +
|
||||
" int IgnoreArg_beef;\n" +
|
||||
" int IgnoreArg_tofu;\n"
|
||||
expected = " char IgnoreArg_chicken;\n" +
|
||||
" char IgnoreArg_beef;\n" +
|
||||
" char IgnoreArg_tofu;\n"
|
||||
returned = @cmock_generator_plugin_ignore_arg.instance_typedefs(@complex_func)
|
||||
assert_equal(expected, returned)
|
||||
end
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
# ==========================================
|
||||
# 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 File.expand_path(File.dirname(__FILE__)) + "/../test_helper"
|
||||
require File.expand_path(File.dirname(__FILE__)) + '/../../lib/cmock_generator_plugin_ignore_stateless'
|
||||
|
||||
describe CMockGeneratorPluginIgnoreStateless, "Verify CMockGeneratorPluginIgnoreStateless Module" do
|
||||
|
||||
before do
|
||||
create_mocks :config, :utils
|
||||
@config = create_stub(:respond_to? => true)
|
||||
@cmock_generator_plugin_ignore_stateless = CMockGeneratorPluginIgnoreStateless.new(@config, @utils)
|
||||
end
|
||||
|
||||
after do
|
||||
end
|
||||
|
||||
it "have set up internal priority" do
|
||||
assert_equal(2, @cmock_generator_plugin_ignore_stateless.priority)
|
||||
end
|
||||
|
||||
it "not have any additional include file requirements" do
|
||||
assert(!@cmock_generator_plugin_ignore_stateless.respond_to?(:include_files))
|
||||
end
|
||||
|
||||
it "add a required variable to the instance structure" do
|
||||
function = {:name => "Grass", :args => [], :return => test_return[:void]}
|
||||
expected = " char Grass_IgnoreBool;\n"
|
||||
returned = @cmock_generator_plugin_ignore_stateless.instance_structure(function)
|
||||
assert_equal(expected, returned)
|
||||
end
|
||||
|
||||
it "handle function declarations for functions without return values" do
|
||||
function = {:name => "Mold", :args_string => "void", :return => test_return[:void]}
|
||||
expected = "#define Mold_Ignore() Mold_CMockIgnore()\nvoid Mold_CMockIgnore(void);\n" +
|
||||
"#define Mold_StopIgnore() Mold_CMockStopIgnore()\nvoid Mold_CMockStopIgnore(void);\n"
|
||||
returned = @cmock_generator_plugin_ignore_stateless.mock_function_declarations(function)
|
||||
assert_equal(expected, returned)
|
||||
end
|
||||
|
||||
it "handle function declarations for functions that returns something" do
|
||||
function = {:name => "Fungus", :args_string => "void", :return => test_return[:string]}
|
||||
expected = "#define Fungus_IgnoreAndReturn(cmock_retval) Fungus_CMockIgnoreAndReturn(cmock_retval)\n"+
|
||||
"void Fungus_CMockIgnoreAndReturn(const char* cmock_to_return);\n" +
|
||||
"#define Fungus_StopIgnore() Fungus_CMockStopIgnore()\n"+
|
||||
"void Fungus_CMockStopIgnore(void);\n"
|
||||
returned = @cmock_generator_plugin_ignore_stateless.mock_function_declarations(function)
|
||||
assert_equal(expected, returned)
|
||||
end
|
||||
|
||||
it "add required code to implementation precheck with void function" do
|
||||
function = {:name => "Mold", :args_string => "void", :return => test_return[:void]}
|
||||
expected = [" if (Mock.Mold_IgnoreBool)\n",
|
||||
" {\n",
|
||||
" UNITY_CLR_DETAILS();\n",
|
||||
" return;\n",
|
||||
" }\n"
|
||||
].join
|
||||
returned = @cmock_generator_plugin_ignore_stateless.mock_implementation_precheck(function)
|
||||
assert_equal(expected, returned)
|
||||
end
|
||||
|
||||
it "add required code to implementation precheck with return functions" do
|
||||
function = {:name => "Fungus", :args_string => "void", :return => test_return[:int]}
|
||||
retval = test_return[:int].merge({ :name => "cmock_call_instance->ReturnVal"})
|
||||
@utils.expect :code_assign_argument_quickly, ' mock_retval_0', ["Mock.Fungus_FinalReturn", retval]
|
||||
expected = [" if (Mock.Fungus_IgnoreBool)\n",
|
||||
" {\n",
|
||||
" UNITY_CLR_DETAILS();\n",
|
||||
" if (cmock_call_instance == NULL)\n",
|
||||
" return Mock.Fungus_FinalReturn;\n",
|
||||
" mock_retval_0",
|
||||
" return cmock_call_instance->ReturnVal;\n",
|
||||
" }\n"
|
||||
].join
|
||||
returned = @cmock_generator_plugin_ignore_stateless.mock_implementation_precheck(function)
|
||||
assert_equal(expected, returned)
|
||||
end
|
||||
|
||||
it "add a new mock interface for ignoring when function had no return value" do
|
||||
function = {:name => "Slime", :args => [], :args_string => "void", :return => test_return[:void]}
|
||||
expected = ["void Slime_CMockIgnore(void)\n",
|
||||
"{\n",
|
||||
" Mock.Slime_IgnoreBool = (char)1;\n",
|
||||
"}\n\n",
|
||||
"void Slime_CMockStopIgnore(void)\n",
|
||||
"{\n",
|
||||
" Mock.Slime_IgnoreBool = (char)0;\n",
|
||||
"}\n\n"
|
||||
].join
|
||||
returned = @cmock_generator_plugin_ignore_stateless.mock_interfaces(function)
|
||||
assert_equal(expected, returned)
|
||||
end
|
||||
|
||||
it "add a new mock interface for ignoring when function has return value" do
|
||||
function = {:name => "Slime", :args => [], :args_string => "void", :return => test_return[:int]}
|
||||
@utils.expect :code_add_base_expectation, "mock_return_1", ["Slime", false]
|
||||
expected = ["void Slime_CMockIgnoreAndReturn(int cmock_to_return)\n",
|
||||
"{\n",
|
||||
" Mock.Slime_CallInstance = CMOCK_GUTS_NONE;\n",
|
||||
" Mock.Slime_FinalReturn = cmock_to_return;\n",
|
||||
" Mock.Slime_IgnoreBool = (char)1;\n",
|
||||
"}\n\n",
|
||||
"void Slime_CMockStopIgnore(void)\n",
|
||||
"{\n",
|
||||
" Mock.Slime_IgnoreBool = (char)0;\n",
|
||||
"}\n\n"
|
||||
].join
|
||||
returned = @cmock_generator_plugin_ignore_stateless.mock_interfaces(function)
|
||||
assert_equal(expected, returned)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -28,14 +28,15 @@ describe CMockGeneratorPluginIgnore, "Verify CMockGeneratorPluginIgnore Module"
|
||||
|
||||
it "add a required variable to the instance structure" do
|
||||
function = {:name => "Grass", :args => [], :return => test_return[:void]}
|
||||
expected = " int Grass_IgnoreBool;\n"
|
||||
expected = " char Grass_IgnoreBool;\n"
|
||||
returned = @cmock_generator_plugin_ignore.instance_structure(function)
|
||||
assert_equal(expected, returned)
|
||||
end
|
||||
|
||||
it "handle function declarations for functions without return values" do
|
||||
function = {:name => "Mold", :args_string => "void", :return => test_return[:void]}
|
||||
expected = "#define Mold_Ignore() Mold_CMockIgnore()\nvoid Mold_CMockIgnore(void);\n"
|
||||
expected = "#define Mold_Ignore() Mold_CMockIgnore()\nvoid Mold_CMockIgnore(void);\n" +
|
||||
"#define Mold_StopIgnore() Mold_CMockStopIgnore()\nvoid Mold_CMockStopIgnore(void);\n"
|
||||
returned = @cmock_generator_plugin_ignore.mock_function_declarations(function)
|
||||
assert_equal(expected, returned)
|
||||
end
|
||||
@@ -43,7 +44,9 @@ describe CMockGeneratorPluginIgnore, "Verify CMockGeneratorPluginIgnore Module"
|
||||
it "handle function declarations for functions that returns something" do
|
||||
function = {:name => "Fungus", :args_string => "void", :return => test_return[:string]}
|
||||
expected = "#define Fungus_IgnoreAndReturn(cmock_retval) Fungus_CMockIgnoreAndReturn(__LINE__, cmock_retval)\n"+
|
||||
"void Fungus_CMockIgnoreAndReturn(UNITY_LINE_TYPE cmock_line, const char* cmock_to_return);\n"
|
||||
"void Fungus_CMockIgnoreAndReturn(UNITY_LINE_TYPE cmock_line, const char* cmock_to_return);\n" +
|
||||
"#define Fungus_StopIgnore() Fungus_CMockStopIgnore()\n"+
|
||||
"void Fungus_CMockStopIgnore(void);\n"
|
||||
returned = @cmock_generator_plugin_ignore.mock_function_declarations(function)
|
||||
assert_equal(expected, returned)
|
||||
end
|
||||
@@ -81,7 +84,12 @@ describe CMockGeneratorPluginIgnore, "Verify CMockGeneratorPluginIgnore Module"
|
||||
function = {:name => "Slime", :args => [], :args_string => "void", :return => test_return[:void]}
|
||||
expected = ["void Slime_CMockIgnore(void)\n",
|
||||
"{\n",
|
||||
" Mock.Slime_IgnoreBool = (int)1;\n",
|
||||
" Mock.Slime_IgnoreBool = (char)1;\n",
|
||||
"}\n\n",
|
||||
|
||||
"void Slime_CMockStopIgnore(void)\n",
|
||||
"{\n",
|
||||
" Mock.Slime_IgnoreBool = (char)0;\n",
|
||||
"}\n\n"
|
||||
].join
|
||||
returned = @cmock_generator_plugin_ignore.mock_interfaces(function)
|
||||
@@ -95,7 +103,13 @@ describe CMockGeneratorPluginIgnore, "Verify CMockGeneratorPluginIgnore Module"
|
||||
"{\n",
|
||||
"mock_return_1",
|
||||
" cmock_call_instance->ReturnVal = cmock_to_return;\n",
|
||||
" Mock.Slime_IgnoreBool = (int)1;\n",
|
||||
" Mock.Slime_IgnoreBool = (char)1;\n",
|
||||
"}\n\n",
|
||||
|
||||
"void Slime_CMockStopIgnore(void)\n{\n",
|
||||
" if(Mock.Slime_IgnoreBool)\n",
|
||||
" Mock.Slime_CallInstance = CMock_Guts_MemNext(Mock.Slime_CallInstance);\n",
|
||||
" Mock.Slime_IgnoreBool = (char)0;\n",
|
||||
"}\n\n"
|
||||
].join
|
||||
returned = @cmock_generator_plugin_ignore.mock_interfaces(function)
|
||||
|
||||
@@ -71,9 +71,9 @@ describe CMockGeneratorPluginReturnThruPtr, "Verify CMockGeneratorPluginReturnTh
|
||||
|
||||
it "add to tyepdef structure mock needs of functions of style 'void func(int chicken, int* pork)'" do
|
||||
complex_func_expect()
|
||||
expected = " int ReturnThruPtr_tofu_Used;\n" +
|
||||
expected = " char ReturnThruPtr_tofu_Used;\n" +
|
||||
" int* ReturnThruPtr_tofu_Val;\n" +
|
||||
" int ReturnThruPtr_tofu_Size;\n"
|
||||
" size_t ReturnThruPtr_tofu_Size;\n"
|
||||
returned = @cmock_generator_plugin_return_thru_ptr.instance_typedefs(@complex_func)
|
||||
assert_equal(expected, returned)
|
||||
end
|
||||
@@ -91,10 +91,10 @@ describe CMockGeneratorPluginReturnThruPtr, "Verify CMockGeneratorPluginReturnTh
|
||||
"#define Pine_ReturnThruPtr_tofu(tofu)" +
|
||||
" Pine_CMockReturnMemThruPtr_tofu(__LINE__, tofu, sizeof(int))\n" +
|
||||
"#define Pine_ReturnArrayThruPtr_tofu(tofu, cmock_len)" +
|
||||
" Pine_CMockReturnMemThruPtr_tofu(__LINE__, tofu, (int)(cmock_len * (int)sizeof(*tofu)))\n" +
|
||||
" Pine_CMockReturnMemThruPtr_tofu(__LINE__, tofu, cmock_len * sizeof(*tofu))\n" +
|
||||
"#define Pine_ReturnMemThruPtr_tofu(tofu, cmock_size)" +
|
||||
" Pine_CMockReturnMemThruPtr_tofu(__LINE__, tofu, cmock_size)\n" +
|
||||
"void Pine_CMockReturnMemThruPtr_tofu(UNITY_LINE_TYPE cmock_line, int* tofu, int cmock_size);\n"
|
||||
"void Pine_CMockReturnMemThruPtr_tofu(UNITY_LINE_TYPE cmock_line, int* tofu, size_t cmock_size);\n"
|
||||
|
||||
returned = @cmock_generator_plugin_return_thru_ptr.mock_function_declarations(@complex_func)
|
||||
assert_equal(expected, returned)
|
||||
@@ -104,7 +104,7 @@ describe CMockGeneratorPluginReturnThruPtr, "Verify CMockGeneratorPluginReturnTh
|
||||
complex_func_expect();
|
||||
|
||||
expected =
|
||||
"void Pine_CMockReturnMemThruPtr_tofu(UNITY_LINE_TYPE cmock_line, int* tofu, int cmock_size)\n" +
|
||||
"void Pine_CMockReturnMemThruPtr_tofu(UNITY_LINE_TYPE cmock_line, int* tofu, size_t cmock_size)\n" +
|
||||
"{\n" +
|
||||
" CMOCK_Pine_CALL_INSTANCE* cmock_call_instance = " +
|
||||
"(CMOCK_Pine_CALL_INSTANCE*)CMock_Guts_GetAddressFor(CMock_Guts_MemEndOfChain(Mock.Pine_CallInstance));\n" +
|
||||
|
||||
@@ -20,17 +20,19 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do
|
||||
@config.expect :plugins, []
|
||||
@config.expect :plugins, []
|
||||
@config.expect :plugins, []
|
||||
@config.expect :plugins, []
|
||||
@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
|
||||
@config.expect :enforce_strict_ordering, true
|
||||
@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 :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 :plugins, [:array, :cexception, :return_thru_ptr, :ignore_arg, :ignore, :ignore_stateless]
|
||||
@config.expect :plugins, [:array, :cexception, :return_thru_ptr, :ignore_arg, :ignore, :ignore_stateless]
|
||||
@config.expect :plugins, [:array, :cexception, :return_thru_ptr, :ignore_arg, :ignore, :ignore_stateless]
|
||||
@config.expect :plugins, [:array, :cexception, :return_thru_ptr, :ignore_arg, :ignore, :ignore_stateless]
|
||||
@config.expect :plugins, [:array, :cexception, :return_thru_ptr, :ignore_arg, :ignore, :ignore_stateless]
|
||||
@config.expect :plugins, [:array, :cexception, :return_thru_ptr, :ignore_arg, :ignore, :ignore_stateless]
|
||||
@config.expect :plugins, [:array, :cexception, :return_thru_ptr, :ignore_arg, :ignore, :ignore_stateless]
|
||||
@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
|
||||
@@ -73,7 +75,7 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do
|
||||
" UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringOutOfMemory);\n" +
|
||||
" memset(cmock_call_instance, 0, sizeof(*cmock_call_instance));\n" +
|
||||
" Mock.Apple_CallInstance = CMock_Guts_MemChain(Mock.Apple_CallInstance, cmock_guts_index);\n" +
|
||||
" Mock.Apple_IgnoreBool = (int)0;\n" +
|
||||
" Mock.Apple_IgnoreBool = (char)0;\n" +
|
||||
" cmock_call_instance->LineNumber = cmock_line;\n" +
|
||||
" cmock_call_instance->CallOrder = ++GlobalExpectCount;\n" +
|
||||
" cmock_call_instance->ExceptionToThrow = CEXCEPTION_NONE;\n"
|
||||
@@ -88,7 +90,7 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do
|
||||
" UNITY_TEST_ASSERT_NOT_NULL(cmock_call_instance, cmock_line, CMockStringOutOfMemory);\n" +
|
||||
" memset(cmock_call_instance, 0, sizeof(*cmock_call_instance));\n" +
|
||||
" Mock.Apple_CallInstance = CMock_Guts_MemChain(Mock.Apple_CallInstance, cmock_guts_index);\n" +
|
||||
" Mock.Apple_IgnoreBool = (int)0;\n" +
|
||||
" Mock.Apple_IgnoreBool = (char)0;\n" +
|
||||
" cmock_call_instance->LineNumber = cmock_line;\n" +
|
||||
" cmock_call_instance->ExceptionToThrow = CEXCEPTION_NONE;\n"
|
||||
output = @cmock_generator_utils_complex.code_add_base_expectation("Apple", false)
|
||||
@@ -301,9 +303,7 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do
|
||||
expected = " if (!cmock_call_instance->IgnoreArg_MyInt)\n" +
|
||||
" {\n" +
|
||||
" UNITY_SET_DETAILS(CMockString_Pear,CMockString_MyInt);\n" +
|
||||
" if (cmock_call_instance->Expected_MyInt != MyInt) {\n" +
|
||||
" UNITY_TEST_ASSERT_EQUAL_INT(cmock_call_instance->Expected_MyInt, MyInt, cmock_line, CMockStringMismatch);\n" +
|
||||
" }\n" +
|
||||
" }\n"
|
||||
@unity_helper.expect :nil?, false
|
||||
@unity_helper.expect :get_helper, ['UNITY_TEST_ASSERT_EQUAL_INT',''], ['int']
|
||||
@@ -316,14 +316,12 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do
|
||||
expected = " if (!cmock_call_instance->IgnoreArg_MyIntPtr)\n" +
|
||||
" {\n" +
|
||||
" UNITY_SET_DETAILS(CMockString_Pear,CMockString_MyIntPtr);\n" +
|
||||
" if (cmock_call_instance->Expected_MyIntPtr != MyIntPtr) {\n" +
|
||||
" if (cmock_call_instance->Expected_MyIntPtr == NULL)\n" +
|
||||
" { UNITY_TEST_ASSERT_NULL(MyIntPtr, cmock_line, CMockStringExpNULL); }\n" +
|
||||
" else if (cmock_call_instance->Expected_MyIntPtr_Depth == 0)\n" +
|
||||
" { UNITY_TEST_ASSERT_EQUAL_PTR(cmock_call_instance->Expected_MyIntPtr, MyIntPtr, cmock_line, CMockStringMismatch); }\n" +
|
||||
" else\n" +
|
||||
" { UNITY_TEST_ASSERT_EQUAL_INT_ARRAY(cmock_call_instance->Expected_MyIntPtr, MyIntPtr, cmock_call_instance->Expected_MyIntPtr_Depth, cmock_line, CMockStringMismatch); }\n" +
|
||||
" }\n" +
|
||||
" }\n"
|
||||
@unity_helper.expect :nil?, false
|
||||
@unity_helper.expect :get_helper, ['UNITY_TEST_ASSERT_EQUAL_INT_ARRAY',''], ['int*']
|
||||
@@ -336,9 +334,7 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do
|
||||
expected = " if (!cmock_call_instance->IgnoreArg_MyStr)\n" +
|
||||
" {\n" +
|
||||
" UNITY_SET_DETAILS(CMockString_Pear,CMockString_MyStr);\n" +
|
||||
" if (cmock_call_instance->Expected_MyStr != MyStr) {\n" +
|
||||
" UNITY_TEST_ASSERT_EQUAL_STRING(cmock_call_instance->Expected_MyStr, MyStr, cmock_line, CMockStringMismatch);\n" +
|
||||
" }\n" +
|
||||
" }\n"
|
||||
@unity_helper.expect :nil?, false
|
||||
@unity_helper.expect :get_helper, ['UNITY_TEST_ASSERT_EQUAL_STRING',''], ['const char*']
|
||||
@@ -351,12 +347,10 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do
|
||||
expected = " if (!cmock_call_instance->IgnoreArg_MyMyType)\n" +
|
||||
" {\n" +
|
||||
" UNITY_SET_DETAILS(CMockString_Pear,CMockString_MyMyType);\n" +
|
||||
" if (cmock_call_instance->Expected_MyMyType != MyMyType) {\n" +
|
||||
" if (cmock_call_instance->Expected_MyMyType == NULL)\n" +
|
||||
" { UNITY_TEST_ASSERT_NULL(MyMyType, cmock_line, CMockStringExpNULL); }\n" +
|
||||
" else\n" +
|
||||
" { UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((void*)(cmock_call_instance->Expected_MyMyType), (void*)(MyMyType), sizeof(MY_TYPE), 1, cmock_line, CMockStringMismatch); }\n" +
|
||||
" }\n" +
|
||||
" }\n"
|
||||
@unity_helper.expect :nil?, false
|
||||
@unity_helper.expect :get_helper, ['UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY', ''], ['MY_TYPE']
|
||||
@@ -369,9 +363,7 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do
|
||||
expected = " if (!cmock_call_instance->IgnoreArg_MyMyType)\n" +
|
||||
" {\n" +
|
||||
" UNITY_SET_DETAILS(CMockString_Pear,CMockString_MyMyType);\n" +
|
||||
" if (cmock_call_instance->Expected_MyMyType != MyMyType) {\n" +
|
||||
" UNITY_TEST_ASSERT_EQUAL_MY_TYPE(cmock_call_instance->Expected_MyMyType, MyMyType, cmock_line, CMockStringMismatch);\n" +
|
||||
" }\n" +
|
||||
" }\n"
|
||||
@unity_helper.expect :nil?, false
|
||||
@unity_helper.expect :get_helper, ['UNITY_TEST_ASSERT_EQUAL_MY_TYPE', ''], ['MY_TYPE']
|
||||
@@ -384,14 +376,12 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do
|
||||
expected = " if (!cmock_call_instance->IgnoreArg_MyMyTypePtr)\n" +
|
||||
" {\n" +
|
||||
" UNITY_SET_DETAILS(CMockString_Pear,CMockString_MyMyTypePtr);\n" +
|
||||
" if (cmock_call_instance->Expected_MyMyTypePtr != MyMyTypePtr) {\n" +
|
||||
" if (cmock_call_instance->Expected_MyMyTypePtr == NULL)\n" +
|
||||
" { UNITY_TEST_ASSERT_NULL(MyMyTypePtr, cmock_line, CMockStringExpNULL); }\n" +
|
||||
" else if (cmock_call_instance->Expected_MyMyTypePtr_Depth == 0)\n" +
|
||||
" { UNITY_TEST_ASSERT_EQUAL_PTR(cmock_call_instance->Expected_MyMyTypePtr, MyMyTypePtr, cmock_line, CMockStringMismatch); }\n" +
|
||||
" else\n" +
|
||||
" { UNITY_TEST_ASSERT_EQUAL_MY_TYPE_ARRAY(cmock_call_instance->Expected_MyMyTypePtr, MyMyTypePtr, cmock_call_instance->Expected_MyMyTypePtr_Depth, cmock_line, CMockStringMismatch); }\n" +
|
||||
" }\n" +
|
||||
" }\n"
|
||||
@unity_helper.expect :nil?, false
|
||||
@unity_helper.expect :get_helper, ['UNITY_TEST_ASSERT_EQUAL_MY_TYPE_ARRAY', ''], ['MY_TYPE*']
|
||||
@@ -404,9 +394,7 @@ describe CMockGeneratorUtils, "Verify CMockGeneratorUtils Module" do
|
||||
expected = " if (!cmock_call_instance->IgnoreArg_MyMyType)\n" +
|
||||
" {\n" +
|
||||
" UNITY_SET_DETAILS(CMockString_Pear,CMockString_MyMyType);\n" +
|
||||
" if (&cmock_call_instance->Expected_MyMyType != &MyMyType) {\n" +
|
||||
" UNITY_TEST_ASSERT_EQUAL_MY_TYPE_ARRAY(&cmock_call_instance->Expected_MyMyType, &MyMyType, 1, cmock_line, CMockStringMismatch);\n" +
|
||||
" }\n" +
|
||||
" }\n"
|
||||
@unity_helper.expect :nil?, false
|
||||
@unity_helper.expect :get_helper, ['UNITY_TEST_ASSERT_EQUAL_MY_TYPE_ARRAY', '&'], ['MY_TYPE']
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,8 @@ describe CMockPluginManager, "Verify CMockPluginManager Module" do
|
||||
:respond_to => true,
|
||||
:when_ptr => :compare_data,
|
||||
:enforce_strict_ordering => false,
|
||||
:ignore => :args_and_calls
|
||||
:ignore => :args_and_calls,
|
||||
:exclude_setjmp_h => false
|
||||
)
|
||||
|
||||
def @config.plugins
|
||||
|
||||
Vendored
+1
-1
Submodule vendor/c_exception updated: e78c5aacc7...71b47be7c9
Vendored
+1
-1
Submodule vendor/unity updated: c3d7662a1e...cf949f45ca
Reference in New Issue
Block a user