forked from 3rd-party/fff
Compare commits
47 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
488442255c | ||
|
|
d4fed915a3 | ||
|
|
25d4c616be | ||
|
|
21f1693002 | ||
|
|
78555cb85c | ||
|
|
2eb067e5a1 | ||
|
|
ff70585de8 | ||
|
|
c325073b44 | ||
|
|
bdb739732b | ||
|
|
c9bebd9d14 | ||
|
|
7e09f07e5b | ||
|
|
b9f11dcd8a | ||
|
|
ab47e7fc5b | ||
|
|
f9c08aec81 | ||
|
|
cf2c4780ef | ||
|
|
995f26b939 | ||
|
|
0b9e9f5064 | ||
|
|
2c5ecf5495 | ||
|
|
f38b06e939 | ||
|
|
96827e3a39 | ||
|
|
fe54d15393 | ||
|
|
b76c7c7168 | ||
|
|
35b26878a7 | ||
|
|
eabb622ea0 | ||
|
|
4e031416d6 | ||
|
|
5b930a1382 | ||
|
|
8e0e312556 | ||
|
|
955db6c60c | ||
|
|
0376823b0c | ||
|
|
5fb4dc64e8 | ||
|
|
6011dfde79 | ||
|
|
d0328c9e4a | ||
|
|
840a619e19 | ||
|
|
11b70375a6 | ||
|
|
54c35b6a1b | ||
|
|
3553583f57 | ||
|
|
dc667cbf82 | ||
|
|
15cb0ecbac | ||
|
|
e0ca6b9e72 | ||
|
|
1cac9afc41 | ||
|
|
45c4d31690 | ||
|
|
1c981604a1 | ||
|
|
d0a214c584 | ||
|
|
a31a9ee38c | ||
|
|
cd727d4195 | ||
|
|
86c5e44614 | ||
|
|
b8f9e65387 |
28
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
28
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Compiler, toolset, platform (please complete the following information):**
|
||||
- OS: [e.g. Ubuntu 16.04 LTS]
|
||||
- Compiler: [e.g. gcc (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
17
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
17
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
8
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
8
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
Thank you for your contribution.
|
||||
|
||||
Before submitting this PR, please make sure:
|
||||
|
||||
- [ ] Your code builds clean without any errors or warnings
|
||||
- [ ] You are not breaking consistency
|
||||
- [ ] You have added unit tests
|
||||
- [ ] All tests and other checks pass
|
||||
25
.github/workflows/verify_pr.yaml
vendored
Normal file
25
.github/workflows/verify_pr.yaml
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
name: Check PR
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
push:
|
||||
|
||||
|
||||
jobs:
|
||||
check-pr:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: seanmiddleditch/gha-setup-ninja@master
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir build
|
||||
cmake -GNinja -B build
|
||||
cmake --build build
|
||||
ctest --test-dir build --output-on-failure
|
||||
|
||||
36
.gitignore
vendored
36
.gitignore
vendored
@@ -2,3 +2,39 @@ build/
|
||||
*~
|
||||
*.sublime-project
|
||||
*.sublime-workspace
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
|
||||
# IntelliJ IDE project directory
|
||||
.idea/
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
34
CMakeLists.txt
Normal file
34
CMakeLists.txt
Normal file
@@ -0,0 +1,34 @@
|
||||
# Copyright 2022 Google LLC
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.20.0)
|
||||
project(fff)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
# Add the gtest library which will be used below
|
||||
add_subdirectory(gtest)
|
||||
|
||||
# Enable ctest
|
||||
enable_testing()
|
||||
|
||||
# Generate fff.h if fakegen.rb changed
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${CMAKE_CURRENT_LIST_DIR}/fff.h
|
||||
COMMAND
|
||||
ruby ${CMAKE_CURRENT_LIST_DIR}/fakegen.rb >> ${CMAKE_CURRENT_LIST_DIR}/fff.h
|
||||
DEPENDS
|
||||
${CMAKE_CURRENT_LIST_DIR}/fakegen.rb
|
||||
${CMAKE_CURRENT_LIST_DIR}/LICENSE
|
||||
)
|
||||
add_custom_target(fff_h DEPENDS ${CMAKE_CURRENT_LIST_DIR}/fff.h)
|
||||
|
||||
# Add an interface library for fff.h
|
||||
add_library(fff INTERFACE)
|
||||
add_dependencies(fff fff_h)
|
||||
target_include_directories(fff INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# Add tests and samples
|
||||
add_subdirectory(test)
|
||||
add_subdirectory(examples)
|
||||
10
Makefile
10
Makefile
@@ -1,10 +0,0 @@
|
||||
all:
|
||||
mkdir -p build
|
||||
cd gtest; $(MAKE) all
|
||||
cd test; $(MAKE) all
|
||||
cd examples; $(MAKE) all
|
||||
|
||||
clean:
|
||||
cd gtest; $(MAKE) clean
|
||||
cd test; $(MAKE) clean
|
||||
cd examples; $(MAKE) clean
|
||||
155
README.md
155
README.md
@@ -2,13 +2,45 @@
|
||||
-----------------------------
|
||||
|
||||
[](https://travis-ci.org/meekrosoft/fff)
|
||||
[](https://ci.appveyor.com/project/wulfgarpro/fff/branch/master)
|
||||
[](https://gitter.im/wulfgarpro/fff?utm_source=share-link&utm_medium=link&utm_campaign=share-link)
|
||||
|
||||
- [A Fake Function Framework for C](#a-fake-function-framework-for-c)
|
||||
- [Hello Fake World!](#hello-fake-world)
|
||||
- [Capturing Arguments](#capturing-arguments)
|
||||
- [Return Values](#return-values)
|
||||
- [Resetting a Fake](#resetting-a-fake)
|
||||
- [Call History](#call-history)
|
||||
- [Default Argument History](#default-argument-history)
|
||||
- [User Defined Argument History](#user-defined-argument-history)
|
||||
- [Function Return Value Sequences](#function-return-value-sequences)
|
||||
- [Custom Return Value Delegate](#custom-return-value-delegate)
|
||||
- [Return Value History](#return-value-history)
|
||||
- [Variadic Functions](#variadic-functions)
|
||||
- [Common Questions](#common-questions)
|
||||
- [Specifying GCC Function Attributes](#specifying-gcc-function-attributes)
|
||||
- [Find Out More](#find-out-more)
|
||||
- [Benefits](#benefits)
|
||||
- [Under the Hood](#under-the-hood)
|
||||
- [Cheat Sheet](#cheat-sheet)
|
||||
|
||||
## A Fake Function Framework for C
|
||||
fff is a micro-framework for creating fake C functions for tests. Because life
|
||||
is too short to spend time hand-writing fake functions for testing.
|
||||
|
||||
## Running all tests
|
||||
|
||||
## Hello fake world!
|
||||
### Linux / MacOS
|
||||
To run all the tests and sample apps, simply call `$ buildandtest`. This script
|
||||
will call down into CMake with the following:
|
||||
|
||||
```shell
|
||||
cmake -GNinja -B build
|
||||
cmake --build build
|
||||
ctest --test-dir build --output-on-failure
|
||||
```
|
||||
|
||||
## Hello Fake World!
|
||||
|
||||
Say you are testing an embedded user interface and you have a function that
|
||||
you want to create a fake for:
|
||||
@@ -62,11 +94,7 @@ typedef struct DISPLAY_init_Fake {
|
||||
DISPLAY_init_Fake DISPLAY_init_fake;
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Capturing arguments
|
||||
## Capturing Arguments
|
||||
|
||||
Ok, enough with the toy examples. What about faking functions with arguments?
|
||||
|
||||
@@ -104,9 +132,7 @@ type (a char pointer in this example).
|
||||
A variable is created for every argument in the form
|
||||
`"function_name"fake.argN_val`
|
||||
|
||||
|
||||
|
||||
## Return values
|
||||
## Return Values
|
||||
|
||||
When you want to define a fake function that returns a value, you should use the
|
||||
`FAKE_VALUE_FUNC` macro. For instance:
|
||||
@@ -153,10 +179,7 @@ you would use a syntax like this:
|
||||
```c
|
||||
FAKE_VALUE_FUNC(double, pow, double, double);
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Resetting a fake
|
||||
## Resetting a Fake
|
||||
|
||||
Good tests are isolated tests, so it is important to reset the fakes for each
|
||||
unit test. All the fakes have a reset function to reset their arguments and
|
||||
@@ -196,9 +219,9 @@ void setup()
|
||||
}
|
||||
```
|
||||
|
||||
## Call history
|
||||
## Call History
|
||||
Say you want to test that a function calls functionA, then functionB, then
|
||||
functionA again, how would you do that? Well `fff` maintains a call
|
||||
functionA again, how would you do that? Well fff maintains a call
|
||||
history so that it is easy to assert these expectations.
|
||||
|
||||
Here's how it works:
|
||||
@@ -260,7 +283,7 @@ The other is to check if the call count is greater than the history size:
|
||||
ASSERT(voidfunc2_fake.arg_history_len < voidfunc2_fake.call_count);
|
||||
```
|
||||
|
||||
The argument histories for a fake function are reset when the RESET_FAKE
|
||||
The argument histories for a fake function are reset when the `RESET_FAKE`
|
||||
function is called
|
||||
|
||||
## User Defined Argument History
|
||||
@@ -277,7 +300,6 @@ override the default by defining it before include the `fff.h` like this:
|
||||
#include "../fff.h"
|
||||
```
|
||||
|
||||
|
||||
## Function Return Value Sequences
|
||||
|
||||
Often in testing we would like to test the behaviour of sequence of function call
|
||||
@@ -308,7 +330,7 @@ value in the sequence indefinitely.
|
||||
## Custom Return Value Delegate
|
||||
|
||||
You can specify your own function to provide the return value for the fake. This
|
||||
is done by setting the custom_fake member of the fake. Here's an example:
|
||||
is done by setting the `custom_fake` member of the fake. Here's an example:
|
||||
|
||||
```c
|
||||
#define MEANING_OF_LIFE 42
|
||||
@@ -324,13 +346,13 @@ TEST_F(FFFTestSuite, when_value_custom_fake_called_THEN_it_returns_custom_return
|
||||
}
|
||||
```
|
||||
|
||||
## Custom Return Value Delegate Sequences
|
||||
### Custom Return Value Delegate Sequences
|
||||
|
||||
Say you have a function with an out parameter, and you want it to have a different behaviour
|
||||
on the first three calls, for example: set the value 'x' to the out parameter on the first call,
|
||||
the value 'y' to the out parameter on the second call, and the value 'z' to the out parameter
|
||||
on the third call. You can specify a sequence of custom functions to a non-variadic function
|
||||
using the SET_CUSTOM_FAKE_SEQ macro. Here's an example:
|
||||
using the `SET_CUSTOM_FAKE_SEQ` macro. Here's an example:
|
||||
|
||||
```c
|
||||
void voidfunc1outparam_custom_fake1(char *a)
|
||||
@@ -366,14 +388,15 @@ TEST_F(FFFTestSuite, custom_fake_sequence_not_exausthed)
|
||||
}
|
||||
```
|
||||
|
||||
The fake will call your custom functions in the order specified by the SET_CUSTOM_FAKE_SEQ
|
||||
The fake will call your custom functions in the order specified by the `SET_CUSTOM_FAKE_SEQ`
|
||||
macro. When the last custom fake is reached the fake will keep calling the last custom
|
||||
fake in the sequence. This macro works much like the SET_RETURN_SEQ macro.
|
||||
fake in the sequence. This macro works much like the `SET_RETURN_SEQ` macro.
|
||||
|
||||
## Return Value History
|
||||
|
||||
## Return value history
|
||||
Say you have two functions f1 and f2. f2 must be called to release some resource
|
||||
allocated by f1, but only in the cases where f1 returns zero. f1 could be
|
||||
pthread_mutex_trylock and f2 could be pthread_mutex_unlock. <tt>fff</tt> will
|
||||
pthread_mutex_trylock and f2 could be pthread_mutex_unlock. fff will
|
||||
save the history of returned values so this can be easily checked, even when
|
||||
you use a sequence of custom fakes. Here's a simple example:
|
||||
|
||||
@@ -389,18 +412,18 @@ you use a sequence of custom fakes. Here's a simple example:
|
||||
ASSERT_EQ(myReturnVals[2], longfunc0_fake.return_val_history[2]);
|
||||
}
|
||||
|
||||
You access the returned values in the <tt>return_val_history</tt> field.
|
||||
You access the returned values in the `return_val_history` field.
|
||||
|
||||
## Variadic Functions
|
||||
|
||||
You can fake variadic functions using the macros <tt>FAKE_VALUE_FUNC_VARARG</tt>
|
||||
and <tt>FAKE_VOID_FUNC_VARARG</tt>. For instance:
|
||||
You can fake variadic functions using the macros `FAKE_VALUE_FUNC_VARARG`
|
||||
and `FAKE_VOID_FUNC_VARARG`. For instance:
|
||||
|
||||
FAKE_VALUE_FUNC_VARARG(int, fprintf, FILE *, const char*, ...);
|
||||
|
||||
In order to access the variadic parameters from a custom fake function, declare a
|
||||
<tt>va_list</tt> parameter. For instance, a custom fake for <tt>fprintf()</tt>
|
||||
could call the real <tt>fprintf()</tt> like this:
|
||||
`va_list` parameter. For instance, a custom fake for `fprintf()`
|
||||
could call the real `fprintf()` like this:
|
||||
|
||||
int fprintf_custom(FILE *stream, const char *format, va_list ap) {
|
||||
if (fprintf0_fake.return_val < 0) // should we fail?
|
||||
@@ -408,8 +431,31 @@ could call the real <tt>fprintf()</tt> like this:
|
||||
return vfprintf(stream, format, ap);
|
||||
}
|
||||
|
||||
## How do I fake a function that returns a value by reference?
|
||||
The basic mechanism that FFF provides you in this case is the custom_fake field described in the *Custom Return Value Delegate* example above.
|
||||
Just like [return value delegates](#custom-return-value-delegate-sequences), you can also specify sequences for variadic functions using `SET_CUSTOM_FAKE_SEQ`.
|
||||
See the test files for examples.
|
||||
|
||||
## Common Questions
|
||||
|
||||
### How do I specify calling conventions for my fake functions?
|
||||
|
||||
fff has a limited capability for enabling specification of Microsoft's Visual C/C++ calling conventions, but this support must be enabled when generating fff's header file `fff.h`.
|
||||
|
||||
```bash
|
||||
ruby fakegen.rb --with-calling-conventions > fff.h
|
||||
```
|
||||
|
||||
By enabling this support, all of fff's fake function scaffolding will necessitate the specification of a calling convention, e.g. `__cdecl` for each VALUE or VOID fake.
|
||||
|
||||
Here are some basic examples: take note that the placement of the calling convention being specified is different depending on whether the fake is a VOID or VALUE function.
|
||||
|
||||
```c
|
||||
FAKE_VOID_FUNC(__cdecl, voidfunc1, int);
|
||||
FAKE_VALUE_FUNC(long, __cdecl, longfunc0);
|
||||
```
|
||||
|
||||
### How do I fake a function that returns a value by reference?
|
||||
|
||||
The basic mechanism that fff provides you in this case is the custom_fake field described in the *Custom Return Value Delegate* example above.
|
||||
|
||||
You need to create a custom function (e.g. getTime_custom_fake) to produce the output optionally by use of a helper variable (e.g. getTime_custom_now) to retrieve that output from. Then some creativity to tie it all together. The most important part (IMHO) is to keep your test case readable and maintainable.
|
||||
|
||||
@@ -447,8 +493,9 @@ TEST_F(FFFTestSuite, when_value_custom_fake_called_THEN_it_returns_custom_output
|
||||
}
|
||||
```
|
||||
|
||||
## How do I fake a function with a function pointer parameter?
|
||||
Using FFF to stub functions that have function pointer parameter can cause problems when trying to stub them. Presented here is an example how to deal with this situation.
|
||||
### How do I fake a function with a function pointer parameter?
|
||||
|
||||
Using fff to stub functions that have function pointer parameter can cause problems when trying to stub them. Presented here is an example how to deal with this situation.
|
||||
|
||||
If you need to stub a function that has a function pointer parameter, e.g. something like:
|
||||
|
||||
@@ -458,7 +505,7 @@ typedef int timer_handle;
|
||||
extern int timer_start(timer_handle handle, long delay, void (*cb_function) (int arg), int arg);
|
||||
```
|
||||
|
||||
Then creating a fake like below will horribly fail when trying to compile because the FFF macro will internally expand into an illegal variable ```int (*)(int) arg2_val```.
|
||||
Then creating a fake like below will horribly fail when trying to compile because the fff macro will internally expand into an illegal variable ```int (*)(int) arg2_val```.
|
||||
|
||||
```c
|
||||
/* The fake, attempt one */
|
||||
@@ -473,7 +520,7 @@ FAKE_VALUE_FUNC(int,
|
||||
The solution to this problem is to create a bridging type that needs only to be visible in the unit tester. The fake will use that intermediate type. This way the compiler will not complain because the types match.
|
||||
|
||||
```c
|
||||
/* Additional type needed to be able to use callback in FFF */
|
||||
/* Additional type needed to be able to use callback in fff */
|
||||
typedef void (*timer_cb) (int argument);
|
||||
|
||||
/* The fake, attempt two */
|
||||
@@ -530,8 +577,10 @@ TEST_F(FFFTestSuite, test_fake_with_function_pointer)
|
||||
ASSERT_EQ(cb_timeout_called, 1);
|
||||
}
|
||||
```
|
||||
## How do I reuse a fake across multiple test-suites?
|
||||
FFF functions like FAKE_VALUE_FUNC will perform both the declaration AND the definition of the fake function and the corresponding data structs. This cannot be placed in a header, since it will lead to multiple definitions of the fake functions.
|
||||
|
||||
### How do I reuse a fake across multiple test-suites?
|
||||
|
||||
fff functions like `FAKE_VALUE_FUNC` will perform both the declaration AND the definition of the fake function and the corresponding data structs. This cannot be placed in a header, since it will lead to multiple definitions of the fake functions.
|
||||
|
||||
The solution is to separate declaration and definition of the fakes, and place the declaration into a public header file, and the definition into a private source file.
|
||||
|
||||
@@ -557,7 +606,28 @@ DEFINE_FAKE_VOID_FUNC_VARARG(void_function_vargs, const char *, int, ...);
|
||||
|
||||
```
|
||||
|
||||
## Find out more...
|
||||
## Specifying GCC Function Attributes
|
||||
|
||||
You can specify GCC function attributes for your fakes using the `FFF_GCC_FUNCTION_ATTRIBUTES` directive.
|
||||
|
||||
### Weak Functions
|
||||
|
||||
One usful attribute is the _weak_ attribute that marks a function such that it can be overridden by a non-weak variant at link time. Using weak functions in combination with fff can help simplify your testing approach.
|
||||
|
||||
For example:
|
||||
* Define a library of fake functions, e.g. libfake.a.
|
||||
* Link a binary (you might have many) that defines a subset of real variants of the fake functions to the aforementioned fake library.
|
||||
* This has the benefit of allowing a binary to selectively use a subset of the required fake functions while testing the real variants without the need for many different make targets.
|
||||
|
||||
You can mark all fakes with the weak attribute like so:
|
||||
```
|
||||
#define FFF_GCC_FUNCTION_ATTRIBUTES __attribute__((weak))
|
||||
#include "fff.h"
|
||||
```
|
||||
|
||||
See the example project that demonstrates the above approach: _./examples/weak_linking_.
|
||||
|
||||
## Find Out More
|
||||
|
||||
Look under the examples directory for full length examples in both C and C++.
|
||||
There is also a test suite for the framework under the test directory.
|
||||
@@ -572,10 +642,11 @@ So whats the point?
|
||||
* To work in both C and C++ test environments
|
||||
|
||||
|
||||
## Under the hood:
|
||||
## Under the Hood
|
||||
* The fff.h header file is generated by a ruby script
|
||||
* There are tests under src/test
|
||||
* There is an example for testing an embedded UI and a hardware driver under src/examples
|
||||
* There are tests under _./test_
|
||||
* There is an example for testing an embedded UI and a hardware driver under _./examples_
|
||||
* There is an example of weak_linking under _./examples_
|
||||
|
||||
|
||||
## Cheat Sheet
|
||||
@@ -583,4 +654,6 @@ So whats the point?
|
||||
|-------|-------------|---------|
|
||||
| FAKE_VOID_FUNC(fn [,arg_types*]); | Define a fake function named fn returning void with n arguments | FAKE_VOID_FUNC(DISPLAY_output_message, const char*); |
|
||||
| FAKE_VALUE_FUNC(return_type, fn [,arg_types*]); | Define a fake function returning a value with type return_type taking n arguments | FAKE_VALUE_FUNC(int, DISPLAY_get_line_insert_index); |
|
||||
| FAKE_VOID_FUNC_VARARG(fn [,arg_types*], ...); | Define a fake variadic function returning void with type return_type taking n arguments and n variadic arguments | FAKE_VOID_FUNC_VARARG(fn, const char*, ...) |
|
||||
| FAKE_VALUE_FUNC_VARARG(return_type, fn [,arg_types*], ...); | Define a fake variadic function returning a value with type return_type taking n arguments and n variadic arguments | FAKE_VALUE_FUNC_VARARG(int, fprintf, FILE*, const char*, ...) |
|
||||
| RESET_FAKE(fn); | Reset the state of fake function called fn | RESET_FAKE(DISPLAY_init); |
|
||||
|
||||
25
buildandtest
25
buildandtest
@@ -1,16 +1,15 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
cat LICENSE > fff.h
|
||||
echo >> fff.h
|
||||
ruby fakegen.rb >> fff.h
|
||||
make clean
|
||||
make all
|
||||
build/fff_test_c
|
||||
build/fff_test_cpp --gtest_output=xml:build/test_results.xml
|
||||
build/ui_test_ansic
|
||||
build/ui_test_cpp --gtest_output=xml:build/example_results.xml
|
||||
build/fff_test_glob_c
|
||||
build/fff_test_glob_cpp --gtest_output=xml:build/test_global_results.xml
|
||||
build/driver_testing --gtest_output=xml:build/driver_testing.xml
|
||||
build/driver_testing_fff --gtest_output=xml:build/driver_testing_fff.xml
|
||||
# Clear the environment
|
||||
rm -fr build fff.h
|
||||
mkdir build
|
||||
|
||||
# Configure the build
|
||||
cmake -GNinja -B build || exit -1
|
||||
|
||||
# Build all targets
|
||||
cmake --build build || exit -1
|
||||
|
||||
# Run all tests
|
||||
ctest --test-dir build --output-on-failure
|
||||
|
||||
6
examples/CMakeLists.txt
Normal file
6
examples/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
# Copyright 2022 Google LLC
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
add_subdirectory(driver_testing)
|
||||
add_subdirectory(embedded_ui)
|
||||
add_subdirectory(weak_linking)
|
||||
@@ -1,7 +0,0 @@
|
||||
all:
|
||||
cd embedded_ui; $(MAKE) all
|
||||
cd driver_testing; $(MAKE) all
|
||||
|
||||
clean:
|
||||
cd embedded_ui; $(MAKE) clean
|
||||
cd driver_testing; $(MAKE) clean
|
||||
31
examples/driver_testing/CMakeLists.txt
Normal file
31
examples/driver_testing/CMakeLists.txt
Normal file
@@ -0,0 +1,31 @@
|
||||
# Copyright 2022 Google LLC
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# Create the driver test binary
|
||||
add_executable(driver_test
|
||||
src/driver.c
|
||||
src/driver.test.cpp
|
||||
)
|
||||
target_include_directories(driver_test PRIVATE include)
|
||||
target_link_libraries(driver_test PRIVATE gtest fff)
|
||||
target_compile_definitions(driver_test PUBLIC TEST_USER_OWN_TR1_TUPLE=1 TESTING)
|
||||
|
||||
# Create the driver fff test binary
|
||||
add_executable(driver_fff_test
|
||||
src/driver.c
|
||||
src/driver.test.fff.cpp
|
||||
)
|
||||
target_include_directories(driver_fff_test PRIVATE include)
|
||||
target_link_libraries(driver_fff_test PRIVATE gtest fff)
|
||||
target_compile_definitions(driver_fff_test PUBLIC TEST_USER_OWN_TR1_TUPLE=1 TESTING)
|
||||
|
||||
# Add tests to ctest
|
||||
add_test(
|
||||
NAME driver_test
|
||||
COMMAND $<TARGET_FILE:driver_test>
|
||||
)
|
||||
|
||||
add_test(
|
||||
NAME driver_fff_test
|
||||
COMMAND $<TARGET_FILE:driver_fff_test>
|
||||
)
|
||||
@@ -1,64 +0,0 @@
|
||||
$(VERBOSE).SILENT:
|
||||
|
||||
BUILD_DIR = ../../build
|
||||
TEMPLATE_PROGNAME = $(BUILD_DIR)/template
|
||||
CPP_PROGNAME_NOFFF = $(BUILD_DIR)/driver_testing
|
||||
CPP_PROGNAME_FFF = $(BUILD_DIR)/driver_testing_fff
|
||||
CC = gcc
|
||||
CC += -c
|
||||
CPP = g++
|
||||
CPP += -c
|
||||
LD = g++
|
||||
|
||||
GTEST_OBJS = $(BUILD_DIR)/gtest-all.o $(BUILD_DIR)/gtest-main.o
|
||||
C_OBJFILES = $(BUILD_DIR)/driver.o
|
||||
TEMPLATE_OBJFILES = $(BUILD_DIR)/test_suite_template.o
|
||||
FFF_OBJFILES = $(BUILD_DIR)/driver.test.fff.o $(GTEST_OBJS)
|
||||
NOFFF_OBJFILES = $(BUILD_DIR)/driver.test.o $(GTEST_OBJS)
|
||||
CPP_LIBS = -lpthread
|
||||
|
||||
|
||||
all: $(CPP_PROGNAME_NOFFF) $(CPP_PROGNAME_FFF) $(TEMPLATE_PROGNAME)
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
clean:
|
||||
@echo "Cleaning object files"
|
||||
@echo " rm -f $(BUILD_DIR)/*.o"
|
||||
rm -f $(BUILD_DIR)/*.o
|
||||
@echo "Cleaning backups"
|
||||
@echo " rm -f *~"
|
||||
rm -f *~
|
||||
@echo "Removing programs"
|
||||
@echo " rm -f $(CPP_PROGNAME_NOFFF) $(CPP_PROGNAME_FFF) $(TEMPLATE_PROGNAME)"
|
||||
rm -f $(CPP_PROGNAME_NOFFF) $(CPP_PROGNAME_FFF) $(TEMPLATE_PROGNAME)
|
||||
|
||||
|
||||
$(BUILD_DIR)/%.o: %.c
|
||||
@echo "Compiling "$@
|
||||
@echo " CC "$<
|
||||
$(CC) -o $@ $< -DTESTING
|
||||
|
||||
$(BUILD_DIR)/%.o: %.cpp
|
||||
@echo "Compiling "$@
|
||||
@echo " CPP "$<
|
||||
$(CPP) -DGTEST_USE_OWN_TR1_TUPLE=1 -I../.. -o $@ $< -DTESTING
|
||||
|
||||
$(TEMPLATE_PROGNAME): $(TEMPLATE_OBJFILES)
|
||||
@echo "Linking "$@
|
||||
@echo " LD -o "ctemplate" "$(TEMPLATE_OBJFILES)
|
||||
$(LD) -o $(TEMPLATE_PROGNAME) $(TEMPLATE_OBJFILES)
|
||||
|
||||
$(CPP_PROGNAME_FFF): $(FFF_OBJFILES) $(C_OBJFILES)
|
||||
@echo "Linking "$@
|
||||
@echo " LD -o "$(CPP_PROGNAME_FFF)" "$(FFF_OBJFILES)
|
||||
$(LD) -o $(CPP_PROGNAME_FFF) $(FFF_OBJFILES) $(C_OBJFILES) $(CPP_LIBS)
|
||||
|
||||
$(CPP_PROGNAME_NOFFF): $(NOFFF_OBJFILES) $(C_OBJFILES)
|
||||
@echo "Linking "$@
|
||||
@echo " LD -o "$(CPP_PROGNAME_NOFFF)" "$(NOFFF_OBJFILES)
|
||||
$(LD) -o $(CPP_PROGNAME_NOFFF) $(NOFFF_OBJFILES) $(C_OBJFILES) $(CPP_LIBS)
|
||||
|
||||
nothing:
|
||||
@echo "Nothing to do; quitting :("
|
||||
@echo "HINT: Try make all"
|
||||
@@ -3,7 +3,7 @@ extern "C"
|
||||
#include "driver.h"
|
||||
#include "registers.h"
|
||||
}
|
||||
#include "../../fff.h"
|
||||
#include "../../../fff.h"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
extern "C"{
|
||||
#include "driver.h"
|
||||
#include "registers.h"
|
||||
#include "hardware_abstraction.h"
|
||||
}
|
||||
#include "../../fff.h"
|
||||
#include "fff.h"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
DEFINE_FFF_GLOBALS;
|
||||
23
examples/embedded_ui/CMakeLists.txt
Normal file
23
examples/embedded_ui/CMakeLists.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
# Copyright 2022 Google LLC
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# Create the ui_test_ansic test binary
|
||||
add_executable(ui_test_ansic src/UI_test_ansic.c src/UI.c)
|
||||
target_include_directories(ui_test_ansic PRIVATE include)
|
||||
target_link_libraries(ui_test_ansic PRIVATE fff)
|
||||
|
||||
# Create the ui_test_cpp test binary
|
||||
add_executable(ui_test_cpp src/UI_test_cpp.cpp src/UI.c)
|
||||
target_include_directories(ui_test_cpp PRIVATE include)
|
||||
target_link_libraries(ui_test_cpp PRIVATE gtest fff)
|
||||
|
||||
# Add tests to ctest
|
||||
add_test(
|
||||
NAME ui_test_ansic
|
||||
COMMAND $<TARGET_FILE:ui_test_ansic>
|
||||
)
|
||||
|
||||
add_test(
|
||||
NAME ui_test_cpp
|
||||
COMMAND $<TARGET_FILE:ui_test_cpp>
|
||||
)
|
||||
@@ -1,67 +0,0 @@
|
||||
$(VERBOSE).SILENT:
|
||||
|
||||
BUILD_DIR = ../../build
|
||||
TEMPLATE_PROGNAME = $(BUILD_DIR)/template
|
||||
C_PROGNAME = $(BUILD_DIR)/ui_test_ansic
|
||||
CPP_PROGNAME = $(BUILD_DIR)/ui_test_cpp
|
||||
CC = gcc
|
||||
CC += -c
|
||||
CPP = g++
|
||||
CPP += -c
|
||||
LD = g++
|
||||
|
||||
GTEST_OBJS = $(BUILD_DIR)/gtest-all.o $(BUILD_DIR)/gtest-main.o
|
||||
C_OBJFILES = $(BUILD_DIR)/UI_test_ansic.o $(BUILD_DIR)/UI.o
|
||||
TEMPLATE_OBJFILES = $(BUILD_DIR)/test_suite_template.o
|
||||
CPP_OBJFILES = $(BUILD_DIR)/UI_test_cpp.o $(BUILD_DIR)/UI.o $(GTEST_OBJS)
|
||||
CPP_LIBS = -lpthread
|
||||
|
||||
|
||||
all: $(C_PROGNAME) $(CPP_PROGNAME) $(TEMPLATE_PROGNAME)
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
clean:
|
||||
@echo "Cleaning object files"
|
||||
@echo " rm -f $(BUILD_DIR)/*.o"
|
||||
rm -f $(BUILD_DIR)/*.o
|
||||
@echo "Cleaning backups"
|
||||
@echo " rm -f *~"
|
||||
rm -f *~
|
||||
@echo "Removing programs"
|
||||
@echo " rm -f "$(C_PROGNAME)
|
||||
rm -f $(C_PROGNAME)
|
||||
@echo " rm -f "$(CPP_PROGNAME) $(TEMPLATE_PROGNAME)
|
||||
rm -f $(CPP_PROGNAME) $(TEMPLATE_PROGNAME)
|
||||
|
||||
|
||||
$(BUILD_DIR)/%.o: %.c
|
||||
@echo "Compiling "$@
|
||||
@echo " CC "$<
|
||||
$(CC) -o $@ $<
|
||||
|
||||
$(BUILD_DIR)/%.o: %.cpp
|
||||
@echo "Compiling "$@
|
||||
@echo " CPP "$<
|
||||
$(CPP) -DGTEST_USE_OWN_TR1_TUPLE=1 -I../.. -o $@ $<
|
||||
|
||||
$(TEMPLATE_PROGNAME): $(TEMPLATE_OBJFILES)
|
||||
@echo "Linking "$@
|
||||
@echo " LD -o "ctemplate" "$(TEMPLATE_OBJFILES)
|
||||
$(LD) -o $(TEMPLATE_PROGNAME) $(TEMPLATE_OBJFILES)
|
||||
|
||||
$(C_PROGNAME): $(C_OBJFILES)
|
||||
@echo "Linking "$@
|
||||
@echo " LD -o "$(C_PROGNAME)" "$(C_OBJFILES)
|
||||
$(LD) -o $(C_PROGNAME) $(C_OBJFILES)
|
||||
|
||||
$(CPP_PROGNAME): $(CPP_OBJFILES) $(C_OBJFILES)
|
||||
@echo "Linking "$@
|
||||
@echo " LD -o "$(CPP_PROGNAME)" "$(CPP_OBJFILES)
|
||||
$(LD) -o $(CPP_PROGNAME) $(CPP_OBJFILES) $(CPP_LIBS)
|
||||
|
||||
|
||||
|
||||
nothing:
|
||||
@echo "Nothing to do; quitting :("
|
||||
@echo "HINT: Try make all"
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "UI.h"
|
||||
#include "../../fff.h"
|
||||
#include "fff.h"
|
||||
#include "SYSTEM.h"
|
||||
#include "DISPLAY.h"
|
||||
|
||||
@@ -6,7 +6,7 @@ extern "C"{
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
|
||||
#include "../../fff.h"
|
||||
#include "fff.h"
|
||||
DEFINE_FFF_GLOBALS;
|
||||
|
||||
/* SYSTEM.h */
|
||||
@@ -1,34 +0,0 @@
|
||||
#include "../../test/c_test_framework.h"
|
||||
|
||||
/* Initialializers called for every test */
|
||||
void setup()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* Tests go here */
|
||||
TEST_F(GreeterTests, hello_world)
|
||||
{
|
||||
assert(1 == 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
setbuf(stderr, NULL);
|
||||
fprintf(stdout, "-------------\n");
|
||||
fprintf(stdout, "Running Tests\n");
|
||||
fprintf(stdout, "-------------\n\n");
|
||||
fflush(0);
|
||||
|
||||
/* Run tests */
|
||||
RUN_TEST(GreeterTests, hello_world);
|
||||
|
||||
|
||||
printf("\n-------------\n");
|
||||
printf("Complete\n");
|
||||
printf("-------------\n\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
54
examples/weak_linking/CMakeLists.txt
Normal file
54
examples/weak_linking/CMakeLists.txt
Normal file
@@ -0,0 +1,54 @@
|
||||
# Copyright 2022 Google LLC
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# Skip these tests for Windows
|
||||
if(WIN32)
|
||||
message(STATUS "Weak linking requires __attribute__((weak)) which isn't supported on MS VS, skipping tests")
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Set the global FFF_GCC_FUNCTION_ATTRIBUTES for config.h
|
||||
set(FFF_GCC_FUNCTION_ATTRIBUTES "__attribute__((weak))")
|
||||
configure_file(config/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
|
||||
# Create a libfakes static library that will be used in the executables below.
|
||||
# This library will depend on the above generated config.h which will add the
|
||||
# FFF 'weak' function attributes.
|
||||
add_library(libfakes STATIC
|
||||
test/src/bus.fake.c
|
||||
test/src/display.fake.c
|
||||
test/src/error.fake.c
|
||||
test/src/sensor.fake.c
|
||||
test/src/test_common.c
|
||||
)
|
||||
target_precompile_headers(libfakes PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
target_include_directories(libfakes PUBLIC include test/include)
|
||||
target_link_libraries(libfakes PUBLIC fff)
|
||||
|
||||
# Create the main test binary
|
||||
add_executable(test_main src/main.c test/src/main.test.c)
|
||||
target_link_libraries(test_main PRIVATE libfakes)
|
||||
|
||||
# Create the sensor test binary
|
||||
add_executable(test_sensor src/sensor.c test/src/sensor.test.c)
|
||||
target_link_libraries(test_sensor PRIVATE libfakes)
|
||||
|
||||
# Create the display test binary
|
||||
add_executable(test_display src/display.c test/src/display.test.c ${LIBFAKES_SRCS})
|
||||
target_link_libraries(test_display PRIVATE libfakes)
|
||||
|
||||
# Add tests to ctest
|
||||
add_test(
|
||||
NAME test_main
|
||||
COMMAND $<TARGET_FILE:test_main>
|
||||
)
|
||||
|
||||
add_test(
|
||||
NAME test_sensor
|
||||
COMMAND $<TARGET_FILE:test_sensor>
|
||||
)
|
||||
|
||||
add_test(
|
||||
NAME test_display
|
||||
COMMAND $<TARGET_FILE:test_display>
|
||||
)
|
||||
5
examples/weak_linking/config/config.h.in
Normal file
5
examples/weak_linking/config/config.h.in
Normal file
@@ -0,0 +1,5 @@
|
||||
/* Copyright 2022 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#cmakedefine FFF_GCC_FUNCTION_ATTRIBUTES @FFF_GCC_FUNCTION_ATTRIBUTES@
|
||||
6
examples/weak_linking/include/bus.h
Normal file
6
examples/weak_linking/include/bus.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "error.h"
|
||||
|
||||
bool bus_read_write( uint8_t dev, uint8_t registry, uint8_t* buffer, int len, bool assume_echo );
|
||||
bool bus_write( uint8_t dev, uint8_t registry, const uint8_t* buffer, int len, bool assume_echo );
|
||||
5
examples/weak_linking/include/display.h
Normal file
5
examples/weak_linking/include/display.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
#include "error.h"
|
||||
|
||||
bool display_init();
|
||||
void display_update( const char* info );
|
||||
7
examples/weak_linking/include/error.h
Normal file
7
examples/weak_linking/include/error.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
void runtime_error( const char* msg );
|
||||
char* runtime_error_nice_print( const char* msg );
|
||||
6
examples/weak_linking/include/sensor.h
Normal file
6
examples/weak_linking/include/sensor.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "error.h"
|
||||
|
||||
bool sensor_init();
|
||||
float sensor_read();
|
||||
30
examples/weak_linking/src/bus.c
Normal file
30
examples/weak_linking/src/bus.c
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
uint16_t* BUS_REGISTER_BASE = (uint16_t*)0xDEADBEEF;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t action;
|
||||
uint16_t reg;
|
||||
uint8_t input;
|
||||
uint8_t output
|
||||
} BusDevice;
|
||||
|
||||
BusDevice* BUS = (BusDevice*)BUS_REGISTER_BASE;
|
||||
|
||||
bool bus_read_write( uint8_t dev, uint8_t registry, uint8_t* buffer, int len, bool assume_echo )
|
||||
{
|
||||
// Something that we dont want to run, since the emulation would be hard.
|
||||
BUS->action = 0x01;
|
||||
BUS->reg = registry;
|
||||
for ( int loop =0 ; loop < len; loop ++ )
|
||||
{
|
||||
char output = buffer[loop];
|
||||
BUS->output = output;
|
||||
buffer[loop] = BUS->input;
|
||||
|
||||
if ( ( assume_echo ) && ( buffer[loop] != output ) )
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
29
examples/weak_linking/src/display.c
Normal file
29
examples/weak_linking/src/display.c
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "display.h"
|
||||
#include "bus.h"
|
||||
|
||||
#define DISPLAY_ADDRESS 0xAF
|
||||
#define DISPLAY_REG_INIT 0x10
|
||||
#define DISPLAY_REG_UPDATE 0x20
|
||||
|
||||
bool display_init()
|
||||
{
|
||||
char init_config[] = { 0xDE, 0xFE, 0x00 };
|
||||
bus_read_write( DISPLAY_ADDRESS, DISPLAY_REG_INIT, (uint8_t*)init_config, 3, false );
|
||||
|
||||
if (init_config[2] != 0x10)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void display_update( const char* info )
|
||||
{
|
||||
int len = strlen( info );
|
||||
|
||||
if ( bus_write( DISPLAY_ADDRESS, DISPLAY_REG_UPDATE, (const uint8_t*)info, len, true ) != true )
|
||||
{
|
||||
runtime_error("display update failed!");
|
||||
}
|
||||
}
|
||||
10
examples/weak_linking/src/error.c
Normal file
10
examples/weak_linking/src/error.c
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <assert.h>
|
||||
#include "error.h"
|
||||
|
||||
char* runtime_error_nice_print( const char* msg )
|
||||
{
|
||||
char* buffer = malloc(512);
|
||||
snprintf(buffer, 512, "Got error: %s", msg );
|
||||
buffer[511] = 0;
|
||||
return buffer;
|
||||
}
|
||||
27
examples/weak_linking/src/main.c
Normal file
27
examples/weak_linking/src/main.c
Normal file
@@ -0,0 +1,27 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "display.h"
|
||||
#include "sensor.h"
|
||||
|
||||
void give_error( const char* msg )
|
||||
{
|
||||
char* buffer = runtime_error_nice_print( msg );
|
||||
runtime_error( buffer );
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
int update_main( void )
|
||||
{
|
||||
if ( !sensor_init() )
|
||||
runtime_error("sensor init failed");
|
||||
|
||||
if ( !display_init() )
|
||||
runtime_error("display init failed");
|
||||
|
||||
char buffer[32];
|
||||
float reading = sensor_read();
|
||||
snprintf( buffer, 32, "Sensor: %0.1f", reading );
|
||||
display_update( buffer );
|
||||
return 0;
|
||||
}
|
||||
29
examples/weak_linking/src/sensor.c
Normal file
29
examples/weak_linking/src/sensor.c
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "sensor.h"
|
||||
#include "bus.h"
|
||||
|
||||
#define SENSOR_ADDRESS 0xAA
|
||||
#define SENSOR_REG_READ 0xF0
|
||||
|
||||
float LOCAL_buffer[4];
|
||||
|
||||
bool sensor_init()
|
||||
{
|
||||
memset( LOCAL_buffer, 0x00, sizeof(LOCAL_buffer));
|
||||
return true;
|
||||
}
|
||||
|
||||
float sensor_read()
|
||||
{
|
||||
char data[4] = { 0xFF, 0xFF, 0x00, 0x00 };
|
||||
bus_read_write( SENSOR_ADDRESS, SENSOR_REG_READ, (uint8_t*)&data, 4, false );
|
||||
|
||||
if (data[0] != 0x10)
|
||||
{
|
||||
runtime_error("sensor read failed");
|
||||
}
|
||||
|
||||
float ret_value = data[1] + data[2] / 256.0;
|
||||
return ret_value;
|
||||
}
|
||||
10
examples/weak_linking/test/include/bus.fake.h
Normal file
10
examples/weak_linking/test/include/bus.fake.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef _AUTOFAKE_BUS_H
|
||||
#define _AUTOFAKE_BUS_H
|
||||
|
||||
#include "fff.h"
|
||||
#include "bus.h"
|
||||
|
||||
DECLARE_FAKE_VALUE_FUNC( bool, bus_read_write, uint8_t, uint8_t, uint8_t*, int, bool );
|
||||
DECLARE_FAKE_VALUE_FUNC( bool, bus_write, uint8_t, uint8_t, const uint8_t*, int, bool );
|
||||
|
||||
#endif // _AUTOFAKE_BUS_H
|
||||
10
examples/weak_linking/test/include/display.fake.h
Normal file
10
examples/weak_linking/test/include/display.fake.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef _AUTOFAKE_DISPLAY_H
|
||||
#define _AUTOFAKE_DISPLAY_H
|
||||
|
||||
#include "fff.h"
|
||||
#include "display.h"
|
||||
|
||||
DECLARE_FAKE_VALUE_FUNC( bool, display_init );
|
||||
DECLARE_FAKE_VOID_FUNC( display_update, const char* );
|
||||
|
||||
#endif // _AUTOFAKE_DISPLAY_H
|
||||
10
examples/weak_linking/test/include/error.fake.h
Normal file
10
examples/weak_linking/test/include/error.fake.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef _AUTOFAKE_ERROR_H
|
||||
#define _AUTOFAKE_ERROR_H
|
||||
|
||||
#include "fff.h"
|
||||
#include "error.h"
|
||||
|
||||
DECLARE_FAKE_VOID_FUNC( runtime_error, const char* );
|
||||
DECLARE_FAKE_VALUE_FUNC( char*, runtime_error_nice_print, const char* );
|
||||
|
||||
#endif // _AUTOFAKE_ERROR_H
|
||||
13
examples/weak_linking/test/include/sensor.fake.h
Normal file
13
examples/weak_linking/test/include/sensor.fake.h
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
#ifndef _AUTOMOCK_SENSOR_H
|
||||
#define _AUTOMOCK_SENSOR_H
|
||||
|
||||
#include "fff.h"
|
||||
#include "sensor.h"
|
||||
|
||||
DECLARE_FAKE_VALUE_FUNC( bool, sensor_init );
|
||||
DECLARE_FAKE_VALUE_FUNC( float, sensor_read );
|
||||
|
||||
void TEST_sensor_generate_data( char* buffer, float value );
|
||||
|
||||
#endif // _AUTOMOCK_SENSOR_H
|
||||
13
examples/weak_linking/test/include/test_common.h
Normal file
13
examples/weak_linking/test/include/test_common.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "fff.h"
|
||||
#include "bus.fake.h"
|
||||
#include "error.fake.h"
|
||||
|
||||
|
||||
void init_tests();
|
||||
|
||||
extern char GLOBAL_TEST_bus_read_ret[32];
|
||||
4
examples/weak_linking/test/src/bus.fake.c
Normal file
4
examples/weak_linking/test/src/bus.fake.c
Normal file
@@ -0,0 +1,4 @@
|
||||
#include "bus.fake.h"
|
||||
|
||||
DEFINE_FAKE_VALUE_FUNC( bool, bus_read_write, uint8_t, uint8_t, uint8_t*, int, bool );
|
||||
DEFINE_FAKE_VALUE_FUNC( bool, bus_write, uint8_t, uint8_t, const uint8_t*, int, bool );
|
||||
4
examples/weak_linking/test/src/display.fake.c
Normal file
4
examples/weak_linking/test/src/display.fake.c
Normal file
@@ -0,0 +1,4 @@
|
||||
#include "display.fake.h"
|
||||
|
||||
DEFINE_FAKE_VALUE_FUNC( bool, display_init );
|
||||
DEFINE_FAKE_VOID_FUNC( display_update, const char* );
|
||||
24
examples/weak_linking/test/src/display.test.c
Normal file
24
examples/weak_linking/test/src/display.test.c
Normal file
@@ -0,0 +1,24 @@
|
||||
#include "test_common.h"
|
||||
#include "display.h"
|
||||
|
||||
DEFINE_FFF_GLOBALS;
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
init_tests(); // Resets common and hook errors to asserts.
|
||||
|
||||
GLOBAL_TEST_bus_read_ret[2] = 0x10;
|
||||
assert( display_init() == true );
|
||||
assert( bus_read_write_fake.call_count == 1);
|
||||
|
||||
display_update( "TEST INFO" );
|
||||
assert( bus_read_write_fake.call_count == 1 );
|
||||
assert( bus_write_fake.call_count == 1 );
|
||||
|
||||
GLOBAL_TEST_bus_read_ret[2] = 0x00;
|
||||
assert( display_init() == false );
|
||||
|
||||
printf("Test " __FILE__ " ok\n");
|
||||
return 0;
|
||||
}
|
||||
4
examples/weak_linking/test/src/error.fake.c
Normal file
4
examples/weak_linking/test/src/error.fake.c
Normal file
@@ -0,0 +1,4 @@
|
||||
#include "error.fake.h"
|
||||
|
||||
DEFINE_FAKE_VOID_FUNC( runtime_error, const char* );
|
||||
DEFINE_FAKE_VALUE_FUNC( char*, runtime_error_nice_print, const char* );
|
||||
26
examples/weak_linking/test/src/main.test.c
Normal file
26
examples/weak_linking/test/src/main.test.c
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
#include "display.fake.h"
|
||||
#include "sensor.fake.h"
|
||||
#include "test_common.h"
|
||||
|
||||
DEFINE_FFF_GLOBALS;
|
||||
|
||||
|
||||
int update_main( void );
|
||||
|
||||
int main(void)
|
||||
{
|
||||
init_tests(); // Resets common and hook errors to asserts.
|
||||
|
||||
sensor_init_fake.return_val = true;
|
||||
display_init_fake.return_val = true;
|
||||
|
||||
update_main();
|
||||
|
||||
assert( sensor_init_fake.call_count == 1 );
|
||||
assert( display_init_fake.call_count == 1 );
|
||||
assert( display_update_fake.call_count == 1 );
|
||||
|
||||
printf("Test " __FILE__ " ok\n");
|
||||
return 0;
|
||||
}
|
||||
11
examples/weak_linking/test/src/sensor.fake.c
Normal file
11
examples/weak_linking/test/src/sensor.fake.c
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "sensor.fake.h"
|
||||
|
||||
DEFINE_FAKE_VALUE_FUNC( bool, sensor_init );
|
||||
DEFINE_FAKE_VALUE_FUNC( float, sensor_read );
|
||||
|
||||
void TEST_sensor_generate_data( char* buffer, float value )
|
||||
{
|
||||
buffer[0] = 0x10;
|
||||
buffer[1] = (int)(value);
|
||||
buffer[2] = (value - buffer[1])*255;
|
||||
}
|
||||
23
examples/weak_linking/test/src/sensor.test.c
Normal file
23
examples/weak_linking/test/src/sensor.test.c
Normal file
@@ -0,0 +1,23 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "test_common.h"
|
||||
|
||||
#include "sensor.h"
|
||||
#include "sensor.fake.h"
|
||||
|
||||
DEFINE_FFF_GLOBALS;
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
init_tests();
|
||||
|
||||
assert( sensor_init() == true );
|
||||
|
||||
TEST_sensor_generate_data( GLOBAL_TEST_bus_read_ret, 1.5f );
|
||||
float value = sensor_read();
|
||||
float value_error = value - 1.5f;
|
||||
assert( value_error < 0.1f && value_error > -0.1f );
|
||||
printf("Test " __FILE__ " ok\n");
|
||||
return 0;
|
||||
}
|
||||
33
examples/weak_linking/test/src/test_common.c
Normal file
33
examples/weak_linking/test/src/test_common.c
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "test_common.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
char GLOBAL_TEST_bus_read_ret[32];
|
||||
|
||||
|
||||
void spoof_runtime_error( const char* info )
|
||||
{
|
||||
fprintf(stderr, "Runtime error: %s\n", info );
|
||||
assert(0);
|
||||
}
|
||||
|
||||
bool spoof_bus_read_write( uint8_t dev, uint8_t registry, uint8_t* buffer, int len, bool assume_echo )
|
||||
{
|
||||
memcpy( buffer, GLOBAL_TEST_bus_read_ret, len );
|
||||
fprintf(stderr, "bus spoof %d %d\n", (int)dev, (int)registry );
|
||||
return true;
|
||||
}
|
||||
|
||||
void init_tests()
|
||||
{
|
||||
memset( GLOBAL_TEST_bus_read_ret, 0x00, sizeof(GLOBAL_TEST_bus_read_ret));
|
||||
FFF_RESET_HISTORY();
|
||||
|
||||
RESET_FAKE(bus_read_write);
|
||||
RESET_FAKE(bus_write);
|
||||
RESET_FAKE(runtime_error);
|
||||
|
||||
runtime_error_fake.custom_fake = spoof_runtime_error;
|
||||
bus_read_write_fake.custom_fake = spoof_bus_read_write;
|
||||
bus_write_fake.return_val = true;
|
||||
}
|
||||
274
fakegen.rb
274
fakegen.rb
@@ -8,6 +8,10 @@ $MAX_ARGS = 20
|
||||
$DEFAULT_ARG_HISTORY = 50
|
||||
$MAX_CALL_HISTORY = 50
|
||||
|
||||
def license
|
||||
File.foreach("#{__dir__}/LICENSE") { |line| putd line }
|
||||
end
|
||||
|
||||
def include_dependencies
|
||||
putd "#include <stdarg.h>"
|
||||
putd "#include <string.h> /* For memset and memcpy */"
|
||||
@@ -26,6 +30,12 @@ def output_constants
|
||||
putd "#define FFF_CALL_HISTORY_LEN (#{$MAX_CALL_HISTORY}u)"
|
||||
}
|
||||
putd "#endif"
|
||||
putd "#ifndef FFF_GCC_FUNCTION_ATTRIBUTES"
|
||||
indent {
|
||||
putd "#define FFF_GCC_FUNCTION_ATTRIBUTES"
|
||||
}
|
||||
putd "#endif"
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -159,9 +169,9 @@ def define_value_function_variables_helper
|
||||
puts
|
||||
putd_backslash "#define DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE)"
|
||||
indent {
|
||||
putd_backslash "RETURN_TYPE return_val;"
|
||||
putd_backslash "int return_val_seq_len;"
|
||||
putd_backslash "int return_val_seq_idx;"
|
||||
putd_backslash "RETURN_TYPE return_val;"
|
||||
putd_backslash "int return_val_seq_len;"
|
||||
putd_backslash "int return_val_seq_idx;"
|
||||
putd_backslash "RETURN_TYPE * return_val_seq;"
|
||||
}
|
||||
end
|
||||
@@ -208,8 +218,8 @@ def define_extern_c_helper
|
||||
puts
|
||||
putd "#ifdef __cplusplus"
|
||||
indent {
|
||||
putd "#define FFF_EXTERN_C extern \"C\"{"
|
||||
putd "#define FFF_END_EXTERN_C } "
|
||||
putd "#define FFF_EXTERN_C extern \"C\"{"
|
||||
putd "#define FFF_END_EXTERN_C } "
|
||||
}
|
||||
putd "#else /* ansi c */"
|
||||
indent {
|
||||
@@ -254,12 +264,12 @@ def popd
|
||||
end
|
||||
|
||||
def indent
|
||||
pushd
|
||||
pushd
|
||||
yield
|
||||
popd
|
||||
end
|
||||
|
||||
def output_macro(arg_count, has_varargs, is_value_function)
|
||||
def output_macro(arg_count, has_varargs, has_calling_conventions, is_value_function)
|
||||
|
||||
vararg_name = has_varargs ? "_VARARG" : ""
|
||||
fake_macro_name = is_value_function ? "FAKE_VALUE_FUNC#{arg_count}#{vararg_name}" : "FAKE_VOID_FUNC#{arg_count}#{vararg_name}"
|
||||
@@ -269,53 +279,50 @@ def output_macro(arg_count, has_varargs, is_value_function)
|
||||
return_type = is_value_function ? "RETURN_TYPE" : ""
|
||||
|
||||
puts
|
||||
output_macro_header(declare_macro_name, saved_arg_count, has_varargs, return_type)
|
||||
output_macro_header(declare_macro_name, saved_arg_count, has_varargs, has_calling_conventions, return_type)
|
||||
indent {
|
||||
extern_c { # define argument capture variables
|
||||
output_variables(saved_arg_count, has_varargs, is_value_function)
|
||||
}
|
||||
output_variables(saved_arg_count, has_varargs, has_calling_conventions, is_value_function)
|
||||
}
|
||||
|
||||
|
||||
puts
|
||||
output_macro_header(define_macro_name, saved_arg_count, has_varargs, return_type)
|
||||
output_macro_header(define_macro_name, saved_arg_count, has_varargs, has_calling_conventions, return_type)
|
||||
indent {
|
||||
extern_c {
|
||||
putd_backslash "FUNCNAME##_Fake FUNCNAME##_fake;"
|
||||
putd_backslash function_signature(saved_arg_count, has_varargs, is_value_function) + "{"
|
||||
indent {
|
||||
output_function_body(saved_arg_count, has_varargs, is_value_function)
|
||||
}
|
||||
putd_backslash "}"
|
||||
putd_backslash "DEFINE_RESET_FUNCTION(FUNCNAME)"
|
||||
putd_backslash "FUNCNAME##_Fake FUNCNAME##_fake;"
|
||||
putd_backslash function_signature(saved_arg_count, has_varargs, has_calling_conventions, is_value_function) + "{"
|
||||
indent {
|
||||
output_function_body(saved_arg_count, has_varargs, is_value_function)
|
||||
}
|
||||
putd_backslash "}"
|
||||
putd_backslash "DEFINE_RESET_FUNCTION(FUNCNAME)"
|
||||
}
|
||||
|
||||
|
||||
puts
|
||||
|
||||
output_macro_header(fake_macro_name, saved_arg_count, has_varargs, return_type)
|
||||
|
||||
output_macro_header(fake_macro_name, saved_arg_count, has_varargs, has_calling_conventions, return_type)
|
||||
indent {
|
||||
putd macro_signature_for(declare_macro_name, saved_arg_count, has_varargs, return_type)
|
||||
putd macro_signature_for(define_macro_name, saved_arg_count, has_varargs, return_type)
|
||||
putd macro_signature_for(declare_macro_name, saved_arg_count, has_varargs, has_calling_conventions, return_type)
|
||||
putd macro_signature_for(define_macro_name, saved_arg_count, has_varargs, has_calling_conventions, return_type)
|
||||
puts
|
||||
}
|
||||
end
|
||||
|
||||
def output_macro_header(macro_name, arg_count, has_varargs, return_type)
|
||||
output_macro_name(macro_name, arg_count, has_varargs, return_type)
|
||||
def output_macro_header(macro_name, arg_count, has_varargs, has_calling_conventions, return_type)
|
||||
output_macro_name(macro_name, arg_count, has_varargs, has_calling_conventions, return_type)
|
||||
end
|
||||
|
||||
# #define #macro_name(RETURN_TYPE, FUNCNAME, ARG0,...)
|
||||
def output_macro_name(macro_name, arg_count, has_varargs, return_type)
|
||||
putd "#define " + macro_signature_for(macro_name, arg_count, has_varargs, return_type)
|
||||
def output_macro_name(macro_name, arg_count, has_varargs, has_calling_conventions, return_type)
|
||||
putd "#define " + macro_signature_for(macro_name, arg_count, has_varargs, has_calling_conventions, return_type)
|
||||
end
|
||||
|
||||
# #macro_name(RETURN_TYPE, FUNCNAME, ARG0,...) \
|
||||
def macro_signature_for(macro_name, arg_count, has_varargs, return_type)
|
||||
def macro_signature_for(macro_name, arg_count, has_varargs, has_calling_conventions, return_type)
|
||||
parameter_list = "#{macro_name}("
|
||||
if return_type != ""
|
||||
parameter_list += return_type
|
||||
parameter_list += ", "
|
||||
end
|
||||
parameter_list += "CALLING_CONVENTION, " if (has_calling_conventions)
|
||||
parameter_list += "FUNCNAME"
|
||||
|
||||
arg_count.times { |i| parameter_list += ", ARG#{i}_TYPE" }
|
||||
@@ -327,21 +334,21 @@ def macro_signature_for(macro_name, arg_count, has_varargs, return_type)
|
||||
parameter_list
|
||||
end
|
||||
|
||||
def output_variables(arg_count, has_varargs, is_value_function)
|
||||
def output_variables(arg_count, has_varargs, has_calling_conventions, is_value_function)
|
||||
in_struct{
|
||||
arg_count.times { |argN|
|
||||
arg_count.times { |argN|
|
||||
putd_backslash "DECLARE_ARG(ARG#{argN}_TYPE, #{argN}, FUNCNAME)"
|
||||
}
|
||||
putd_backslash "DECLARE_ALL_FUNC_COMMON"
|
||||
putd_backslash "DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE)" unless not is_value_function
|
||||
putd_backslash "DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE)" unless not is_value_function
|
||||
putd_backslash "DECLARE_CUSTOM_FAKE_SEQ_VARIABLES"
|
||||
output_custom_function_signature(arg_count, has_varargs, is_value_function)
|
||||
output_custom_function_array(arg_count, has_varargs, is_value_function)
|
||||
output_custom_function_signature(arg_count, has_varargs, has_calling_conventions, is_value_function)
|
||||
output_custom_function_array(arg_count, has_varargs, has_calling_conventions, is_value_function)
|
||||
}
|
||||
putd_backslash "extern FUNCNAME##_Fake FUNCNAME##_fake;"
|
||||
putd_backslash "void FUNCNAME##_reset(void);"
|
||||
putd_backslash function_signature(arg_count, has_varargs, is_value_function) + ";"
|
||||
putd_backslash function_signature(arg_count, has_varargs, has_calling_conventions, is_value_function) + ";"
|
||||
end
|
||||
|
||||
#example: ARG0_TYPE arg0, ARG1_TYPE arg1
|
||||
@@ -360,26 +367,35 @@ def arg_list(args_count)
|
||||
end
|
||||
|
||||
# RETURN_TYPE (*custom_fake)(ARG0_TYPE arg0);\
|
||||
# OR
|
||||
# RETURN_TYPE (CALLING_CONVENTION *custom_fake)(ARG0_TYPE arg0);\
|
||||
#
|
||||
# void (*custom_fake)(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2);\
|
||||
def output_custom_function_signature(arg_count, has_varargs, is_value_function)
|
||||
def output_custom_function_signature(arg_count, has_varargs, has_calling_conventions, is_value_function)
|
||||
return_type = is_value_function ? "RETURN_TYPE" : "void"
|
||||
ap_list = has_varargs ? ", va_list ap" : ""
|
||||
signature = "(*custom_fake)(#{arg_val_list(arg_count)}#{ap_list});"
|
||||
signature = has_calling_conventions ? "(CALLING_CONVENTION *custom_fake)" : "(*custom_fake)"
|
||||
signature += "(#{arg_val_list(arg_count)}#{ap_list});"
|
||||
putd_backslash return_type + signature
|
||||
end
|
||||
|
||||
def output_custom_function_array(arg_count, has_varargs, is_value_function)
|
||||
def output_custom_function_array(arg_count, has_varargs, has_calling_conventions, is_value_function)
|
||||
return_type = is_value_function ? "RETURN_TYPE" : "void"
|
||||
ap_list = has_varargs ? ", va_list ap" : ""
|
||||
custom_array = "(**custom_fake_seq)(#{arg_val_list(arg_count)}#{ap_list});"
|
||||
custom_array = has_calling_conventions ? "(CALLING_CONVENTION **custom_fake_seq)" : "(**custom_fake_seq)"
|
||||
custom_array += "(#{arg_val_list(arg_count)}#{ap_list});"
|
||||
putd_backslash return_type + custom_array
|
||||
end
|
||||
|
||||
# example: RETURN_TYPE FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1)
|
||||
def function_signature(arg_count, has_varargs, is_value_function)
|
||||
# OR
|
||||
# RETURN_TYPE CALLING_CONVENTION FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1)
|
||||
def function_signature(arg_count, has_varargs, has_calling_conventions, is_value_function)
|
||||
return_type = is_value_function ? "RETURN_TYPE" : "void"
|
||||
varargs = has_varargs ? ", ..." : ""
|
||||
"#{return_type} FUNCNAME(#{arg_val_list(arg_count)}#{varargs})"
|
||||
calling_conventions = has_calling_conventions ?
|
||||
"#{return_type} FFF_GCC_FUNCTION_ATTRIBUTES CALLING_CONVENTION FUNCNAME(#{arg_val_list(arg_count)}#{varargs})" :
|
||||
"#{return_type} FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(#{arg_val_list(arg_count)}#{varargs})"
|
||||
end
|
||||
|
||||
def output_function_body(arg_count, has_varargs, is_value_function)
|
||||
@@ -398,6 +414,35 @@ def output_function_body(arg_count, has_varargs, is_value_function)
|
||||
putd_backslash "REGISTER_CALL(FUNCNAME);"
|
||||
|
||||
if has_varargs
|
||||
return_type = is_value_function ? "return " : ""
|
||||
putd_backslash "if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */"
|
||||
indent {
|
||||
putd_backslash "if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){"
|
||||
indent {
|
||||
putd_backslash "va_list ap;"
|
||||
putd_backslash "va_start(ap, arg#{arg_count-1});"
|
||||
putd_backslash "RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](#{arg_list(arg_count)}, ap);" unless not is_value_function
|
||||
putd_backslash "SAVE_RET_HISTORY(FUNCNAME, ret);" unless not is_value_function
|
||||
putd_backslash "va_end(ap);" unless not is_value_function
|
||||
putd_backslash "return ret;" unless not is_value_function
|
||||
putd_backslash "#{return_type}FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](#{arg_list(arg_count)}, ap);" unless is_value_function
|
||||
putd_backslash "va_end(ap);" unless is_value_function
|
||||
}
|
||||
putd_backslash "}"
|
||||
putd_backslash "else{"
|
||||
indent {
|
||||
putd_backslash "va_list ap;"
|
||||
putd_backslash "va_start(ap, arg#{arg_count-1});"
|
||||
putd_backslash "RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](#{arg_list(arg_count)}, ap);" unless not is_value_function
|
||||
putd_backslash "SAVE_RET_HISTORY(FUNCNAME, ret);" unless not is_value_function
|
||||
putd_backslash "va_end(ap);" unless not is_value_function
|
||||
putd_backslash "return ret;" unless not is_value_function
|
||||
putd_backslash "#{return_type}FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](#{arg_list(arg_count)}, ap);"
|
||||
putd_backslash "va_end(ap);" unless is_value_function
|
||||
}
|
||||
putd_backslash "}"
|
||||
}
|
||||
putd_backslash "}"
|
||||
putd_backslash "if(FUNCNAME##_fake.custom_fake){"
|
||||
indent {
|
||||
putd_backslash "RETURN_TYPE ret;" if is_value_function
|
||||
@@ -438,7 +483,14 @@ def output_function_body(arg_count, has_varargs, is_value_function)
|
||||
putd_backslash "}"
|
||||
}
|
||||
putd_backslash "}"
|
||||
putd_backslash "if (FUNCNAME##_fake.custom_fake) #{return_type}FUNCNAME##_fake.custom_fake(#{arg_list(arg_count)});"
|
||||
putd_backslash "if (FUNCNAME##_fake.custom_fake){ "
|
||||
indent {
|
||||
putd_backslash "RETURN_TYPE ret = FUNCNAME##_fake.custom_fake(#{arg_list(arg_count)});" unless not is_value_function
|
||||
putd_backslash "SAVE_RET_HISTORY(FUNCNAME, ret);" unless not is_value_function
|
||||
putd_backslash "return ret;" unless not is_value_function
|
||||
putd_backslash "#{return_type}FUNCNAME##_fake.custom_fake(#{arg_list(arg_count)});"
|
||||
}
|
||||
putd_backslash "}"
|
||||
end
|
||||
|
||||
putd_backslash "RETURN_FAKE_RESULT(FUNCNAME)" if is_value_function
|
||||
@@ -453,9 +505,9 @@ def define_fff_globals
|
||||
}
|
||||
putd "} fff_globals_t;"
|
||||
puts
|
||||
putd_backslash "FFF_EXTERN_C"
|
||||
putd "FFF_EXTERN_C"
|
||||
putd "extern fff_globals_t fff;"
|
||||
putd_backslash "FFF_END_EXTERN_C"
|
||||
putd "FFF_END_EXTERN_C"
|
||||
puts
|
||||
putd_backslash "#define DEFINE_FFF_GLOBALS"
|
||||
indent {
|
||||
@@ -466,25 +518,21 @@ def define_fff_globals
|
||||
putd "FFF_END_EXTERN_C"
|
||||
}
|
||||
puts
|
||||
putd "#define FFF_RESET_HISTORY() fff.call_history_idx = 0;"
|
||||
putd_backslash "#define FFF_RESET_HISTORY()"
|
||||
indent {
|
||||
putd_backslash "fff.call_history_idx = 0;"
|
||||
putd "memset(fff.call_history, 0, sizeof(fff.call_history));"
|
||||
}
|
||||
puts
|
||||
putd_backslash "#define REGISTER_CALL(function)"
|
||||
indent {
|
||||
putd_backslash "if(fff.call_history_idx < FFF_CALL_HISTORY_LEN)"
|
||||
indent {
|
||||
putd "fff.call_history[fff.call_history_idx++] = (fff_function_t)function;"
|
||||
putd "fff.call_history[fff.call_history_idx++] = (fff_function_t)function;"
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def extern_c
|
||||
putd_backslash "FFF_EXTERN_C"
|
||||
indent {
|
||||
yield
|
||||
}
|
||||
putd_backslash "FFF_END_EXTERN_C"
|
||||
end
|
||||
|
||||
def in_struct
|
||||
putd_backslash "typedef struct FUNCNAME##_Fake {"
|
||||
indent {
|
||||
@@ -505,18 +553,22 @@ def include_guard
|
||||
end
|
||||
|
||||
def msvc_expand_macro_fix
|
||||
putd "/* MSVC expand macro fix */"
|
||||
putd "#define EXPAND(x) x"
|
||||
putd "/* MSVC expand macro fix */"
|
||||
putd "#define EXPAND(x) x"
|
||||
end
|
||||
|
||||
def generate_arg_sequence(args, prefix, do_reverse, joinstr)
|
||||
fmap = (0..args).flat_map {|i| [prefix + i.to_s]}
|
||||
if do_reverse then fmap.reverse.join(joinstr) else fmap.join(", ") end
|
||||
fmap = (0..args).flat_map {|i| [prefix + i.to_s]}
|
||||
if do_reverse then fmap.reverse.join(joinstr) else fmap.join(", ") end
|
||||
end
|
||||
|
||||
def counting_macro_instance(type, vararg = :non_vararg, prefix = "")
|
||||
def counting_macro_instance(type, has_calling_conventions, vararg = :non_vararg, prefix = "")
|
||||
appendix = (vararg == :vararg) ? "_VARARG" : ""
|
||||
minus_count = (type == :VOID) ? 1 : 2
|
||||
if has_calling_conventions
|
||||
minus_count = (type == :VOID) ? 2 : 3
|
||||
else
|
||||
minus_count = (type == :VOID) ? 1 : 2
|
||||
end
|
||||
|
||||
<<-MACRO_COUNTING_INSTANCE
|
||||
#define #{prefix}FAKE_#{type.to_s}_FUNC#{appendix}(...) \
|
||||
@@ -531,78 +583,96 @@ def counting_macro_instance(type, vararg = :non_vararg, prefix = "")
|
||||
MACRO_COUNTING_INSTANCE
|
||||
end
|
||||
|
||||
def output_macro_counting_shortcuts
|
||||
def output_macro_counting_shortcuts(has_calling_conventions)
|
||||
has_calling_conventions ?
|
||||
(arg_depth = ["3", "2"]; calling_conv = "callingConv, ") :
|
||||
(arg_depth = ["2", "1"]; calling_conv = "")
|
||||
|
||||
msvc_expand_macro_fix
|
||||
putd <<-MACRO_COUNTING
|
||||
|
||||
#define PP_NARG_MINUS2(...) \
|
||||
EXPAND(PP_NARG_MINUS2_(__VA_ARGS__, PP_RSEQ_N_MINUS2()))
|
||||
#define PP_NARG_MINUS#{arg_depth[0]}(...) \
|
||||
EXPAND(PP_NARG_MINUS#{arg_depth[0]}_(__VA_ARGS__, PP_RSEQ_N_MINUS#{arg_depth[0]}()))
|
||||
|
||||
#define PP_NARG_MINUS2_(...) \
|
||||
EXPAND(PP_ARG_MINUS2_N(__VA_ARGS__))
|
||||
#define PP_NARG_MINUS#{arg_depth[0]}_(...) \
|
||||
EXPAND(PP_ARG_MINUS#{arg_depth[0]}_N(__VA_ARGS__))
|
||||
|
||||
#define PP_ARG_MINUS2_N(returnVal, #{generate_arg_sequence($MAX_ARGS, '_', false, ", ")}, N, ...) N
|
||||
#define PP_ARG_MINUS#{arg_depth[0]}_N(returnVal, #{calling_conv} #{generate_arg_sequence($MAX_ARGS, '_', false, ", ")}, N, ...) N
|
||||
|
||||
#define PP_RSEQ_N_MINUS2() \
|
||||
#{generate_arg_sequence($MAX_ARGS, '', true, ',')}
|
||||
#define PP_RSEQ_N_MINUS#{arg_depth[0]}() \
|
||||
#{generate_arg_sequence($MAX_ARGS, '', true, ',')}
|
||||
|
||||
#define PP_NARG_MINUS#{arg_depth[1]}(...) \
|
||||
EXPAND(PP_NARG_MINUS#{arg_depth[1]}_(__VA_ARGS__, PP_RSEQ_N_MINUS#{arg_depth[1]}()))
|
||||
|
||||
#define PP_NARG_MINUS1(...) \
|
||||
EXPAND(PP_NARG_MINUS1_(__VA_ARGS__, PP_RSEQ_N_MINUS1()))
|
||||
#define PP_NARG_MINUS#{arg_depth[1]}_(...) \
|
||||
EXPAND(PP_ARG_MINUS#{arg_depth[1]}_N(__VA_ARGS__))
|
||||
|
||||
#define PP_NARG_MINUS1_(...) \
|
||||
EXPAND(PP_ARG_MINUS1_N(__VA_ARGS__))
|
||||
#define PP_ARG_MINUS#{arg_depth[1]}_N(#{calling_conv} #{generate_arg_sequence($MAX_ARGS, '_', false, ", ")}, N, ...) N
|
||||
|
||||
#define PP_ARG_MINUS1_N(#{generate_arg_sequence($MAX_ARGS, '_', false, ", ")}, N, ...) N
|
||||
|
||||
#define PP_RSEQ_N_MINUS1() \
|
||||
#{generate_arg_sequence($MAX_ARGS, '', true, ',')}
|
||||
#define PP_RSEQ_N_MINUS#{arg_depth[1]}() \
|
||||
#{generate_arg_sequence($MAX_ARGS, '', true, ',')}
|
||||
|
||||
|
||||
|
||||
/* DECLARE AND DEFINE FAKE FUNCTIONS - PLACE IN TEST FILES */
|
||||
|
||||
#{counting_macro_instance(:VALUE)}
|
||||
#{counting_macro_instance(:VOID)}
|
||||
#{counting_macro_instance(:VALUE, :vararg)}
|
||||
#{counting_macro_instance(:VOID, :vararg)}
|
||||
#{counting_macro_instance(:VALUE, has_calling_conventions)}
|
||||
#{counting_macro_instance(:VOID, has_calling_conventions)}
|
||||
#{counting_macro_instance(:VALUE, has_calling_conventions, :vararg)}
|
||||
#{counting_macro_instance(:VOID, has_calling_conventions, :vararg)}
|
||||
|
||||
/* DECLARE FAKE FUNCTIONS - PLACE IN HEADER FILES */
|
||||
|
||||
#{counting_macro_instance(:VALUE, :non_vararg, "DECLARE_")}
|
||||
#{counting_macro_instance(:VOID, :non_vararg, "DECLARE_")}
|
||||
#{counting_macro_instance(:VALUE, :vararg, "DECLARE_")}
|
||||
#{counting_macro_instance(:VOID, :vararg, "DECLARE_")}
|
||||
#{counting_macro_instance(:VALUE, has_calling_conventions, :non_vararg, "DECLARE_")}
|
||||
#{counting_macro_instance(:VOID, has_calling_conventions, :non_vararg, "DECLARE_")}
|
||||
#{counting_macro_instance(:VALUE, has_calling_conventions, :vararg, "DECLARE_")}
|
||||
#{counting_macro_instance(:VOID, has_calling_conventions, :vararg, "DECLARE_")}
|
||||
|
||||
/* DEFINE FAKE FUNCTIONS - PLACE IN SOURCE FILES */
|
||||
|
||||
#{counting_macro_instance(:VALUE, :non_vararg, "DEFINE_")}
|
||||
#{counting_macro_instance(:VOID, :non_vararg, "DEFINE_")}
|
||||
#{counting_macro_instance(:VALUE, :vararg, "DEFINE_")}
|
||||
#{counting_macro_instance(:VOID, :vararg, "DEFINE_")}
|
||||
#{counting_macro_instance(:VALUE, has_calling_conventions, :non_vararg, "DEFINE_")}
|
||||
#{counting_macro_instance(:VOID, has_calling_conventions, :non_vararg, "DEFINE_")}
|
||||
#{counting_macro_instance(:VALUE, has_calling_conventions, :vararg, "DEFINE_")}
|
||||
#{counting_macro_instance(:VOID, has_calling_conventions, :vararg, "DEFINE_")}
|
||||
|
||||
MACRO_COUNTING
|
||||
end
|
||||
|
||||
def output_c_and_cpp
|
||||
|
||||
def output_c_and_cpp(has_calling_conventions)
|
||||
license
|
||||
include_guard {
|
||||
include_dependencies
|
||||
output_constants
|
||||
output_internal_helper_macros
|
||||
yield
|
||||
output_macro_counting_shortcuts
|
||||
output_macro_counting_shortcuts(has_calling_conventions)
|
||||
}
|
||||
end
|
||||
|
||||
# lets generate!!
|
||||
output_c_and_cpp{
|
||||
define_fff_globals
|
||||
# Create fake generators for 0..MAX_ARGS
|
||||
num_fake_generators = $MAX_ARGS + 1
|
||||
num_fake_generators.times {|arg_count| output_macro(arg_count, false, false)}
|
||||
num_fake_generators.times {|arg_count| output_macro(arg_count, false, true)}
|
||||
# generate the varargs variants
|
||||
(2..$MAX_ARGS).each {|arg_count| output_macro(arg_count, true, false)}
|
||||
(2..$MAX_ARGS).each {|arg_count| output_macro(arg_count, true, true)}
|
||||
def help
|
||||
# Check if we should generate _with_ support for specifying calling conventions
|
||||
if (ARGV[0] == "--help" or ARGV[0] == "-h")
|
||||
puts "Usage: fakegen.rb [options]
|
||||
-h, --help Show this help message
|
||||
-wcc, --with-calling-conventions Support specifying calling conventions"
|
||||
exit
|
||||
end
|
||||
yield
|
||||
end
|
||||
|
||||
help {
|
||||
# Determine if we should generate with support for calling conventions
|
||||
has_calling_conventions = true if (ARGV[0] == "--with-calling-conventions" or ARGV[0] == "-wcc")
|
||||
# lets generate!!
|
||||
output_c_and_cpp(has_calling_conventions) {
|
||||
define_fff_globals
|
||||
# Create fake generators for 0..MAX_ARGS
|
||||
num_fake_generators = $MAX_ARGS + 1
|
||||
num_fake_generators.times {|arg_count| output_macro(arg_count, false, has_calling_conventions, false)}
|
||||
num_fake_generators.times {|arg_count| output_macro(arg_count, false, has_calling_conventions, true)}
|
||||
# generate the varargs variants
|
||||
(2..$MAX_ARGS).each {|arg_count| output_macro(arg_count, true, has_calling_conventions, false)}
|
||||
(2..$MAX_ARGS).each {|arg_count| output_macro(arg_count, true, has_calling_conventions, true)}
|
||||
}
|
||||
}
|
||||
|
||||
12
gtest/CMakeLists.txt
Normal file
12
gtest/CMakeLists.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
# Copyright 2022 Google LLC
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.20.0)
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
set(CMAKE_EXE_LINKER_FLAGS " -static")
|
||||
|
||||
# Create the gtest library
|
||||
add_library(gtest src/gtest-all.cc src/gtest-main.cc)
|
||||
target_include_directories(gtest PUBLIC include include/gtest)
|
||||
target_link_libraries(gtest PRIVATE Threads::Threads -static-libstdc++)
|
||||
@@ -1,22 +0,0 @@
|
||||
|
||||
BUILD_DIR = ../build
|
||||
LIBS := -lpthread
|
||||
CPP_OBJS=$(BUILD_DIR)/gtest-all.o $(BUILD_DIR)/gtest-main.o
|
||||
|
||||
SOURCES=gtest-all.cc gtest-main.cc
|
||||
|
||||
|
||||
# Each subdirectory must supply rules for building sources it contributes
|
||||
$(BUILD_DIR)/%.o: %.cc
|
||||
@echo 'Building file: $<'
|
||||
@echo 'Invoking: GCC C++ Compiler'
|
||||
g++ -I../ -O0 -g3 -Wall -DGTEST_USE_OWN_TR1_TUPLE=1 -c -o "$@" "$<"
|
||||
@echo 'Finished building: $<'
|
||||
@echo ' '
|
||||
|
||||
all: $(CPP_OBJS)
|
||||
|
||||
clean:
|
||||
-$(RM) $(CPP_OBJS)
|
||||
-@echo ' '
|
||||
|
||||
@@ -1554,11 +1554,29 @@ inline bool operator!=(const GTEST_10_TUPLE_(T)& t,
|
||||
// <tr1/functional>. Hence the following #define is a hack to prevent
|
||||
// <tr1/functional> from being included.
|
||||
# define _TR1_FUNCTIONAL 1
|
||||
# include <tr1/tuple>
|
||||
# include <tuple>
|
||||
namespace std {
|
||||
namespace tr1 {
|
||||
using ::std::get;
|
||||
using ::std::make_tuple;
|
||||
using ::std::tuple;
|
||||
using ::std::tuple_element;
|
||||
using ::std::tuple_size;
|
||||
}
|
||||
}
|
||||
# undef _TR1_FUNCTIONAL // Allows the user to #include
|
||||
// <tr1/functional> if he chooses to.
|
||||
# else
|
||||
# include <tr1/tuple> // NOLINT
|
||||
# include <tuple> // NOLINT
|
||||
namespace std {
|
||||
namespace tr1 {
|
||||
using ::std::get;
|
||||
using ::std::make_tuple;
|
||||
using ::std::tuple;
|
||||
using ::std::tuple_element;
|
||||
using ::std::tuple_size;
|
||||
}
|
||||
}
|
||||
# endif // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
|
||||
|
||||
# else
|
||||
56
test/CMakeLists.txt
Normal file
56
test/CMakeLists.txt
Normal file
@@ -0,0 +1,56 @@
|
||||
# Copyright 2022 Google LLC
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# Create a list of common files needed for tests
|
||||
set(
|
||||
COMMON_FILE_LIST
|
||||
c_test_framework.h
|
||||
test_cases.include
|
||||
)
|
||||
|
||||
# Create the C test executable
|
||||
add_executable(c_test fff_test_c.c ${COMMON_FILE_LIST})
|
||||
target_link_libraries(c_test PRIVATE fff)
|
||||
|
||||
# Create the C++ test executable
|
||||
add_executable(cpp_test fff_test_cpp.cpp ${COMMON_FILE_LIST})
|
||||
target_link_libraries(cpp_test PRIVATE gtest fff)
|
||||
|
||||
# Create the C global test executable
|
||||
add_executable(c_global_test
|
||||
fff_test_global_c.c
|
||||
global_fakes.c
|
||||
global_fakes.h
|
||||
${COMMON_FILE_LIST}
|
||||
)
|
||||
target_link_libraries(c_global_test PRIVATE fff)
|
||||
|
||||
# Create the C++ global test executable
|
||||
add_executable(cpp_global_test
|
||||
fff_test_global_cpp.cpp
|
||||
global_fakes.c
|
||||
global_fakes.h
|
||||
${COMMON_FILE_LIST}
|
||||
)
|
||||
target_link_libraries(cpp_global_test PRIVATE gtest fff)
|
||||
|
||||
# Add the tests for ctest
|
||||
add_test(
|
||||
NAME c_test
|
||||
COMMAND $<TARGET_FILE:c_test>
|
||||
)
|
||||
|
||||
add_test(
|
||||
NAME cpp_test
|
||||
COMMAND $<TARGET_FILE:cpp_test>
|
||||
)
|
||||
|
||||
add_test(
|
||||
NAME c_global_test
|
||||
COMMAND $<TARGET_FILE:c_global_test>
|
||||
)
|
||||
|
||||
add_test(
|
||||
NAME cpp_global_test
|
||||
COMMAND $<TARGET_FILE:cpp_global_test>
|
||||
)
|
||||
@@ -1,81 +0,0 @@
|
||||
|
||||
BUILD_DIR = ../build
|
||||
|
||||
FFF_TEST_CPP_OBJS += \
|
||||
$(BUILD_DIR)/fff_test_cpp.o \
|
||||
$(BUILD_DIR)/gtest-all.o \
|
||||
$(BUILD_DIR)/gtest-main.o
|
||||
|
||||
FFF_TEST_GLOBAL_CPP_OBJS += \
|
||||
$(BUILD_DIR)/fff_test_global_cpp.o \
|
||||
$(BUILD_DIR)/global_fakes.o \
|
||||
$(BUILD_DIR)/gtest-all.o \
|
||||
$(BUILD_DIR)/gtest-main.o
|
||||
|
||||
FFF_TEST_C_OBJS = $(BUILD_DIR)/fff_test_c.o
|
||||
|
||||
FFF_TEST_GLOBAL_C_OBJS += \
|
||||
$(BUILD_DIR)/global_fakes.o \
|
||||
$(BUILD_DIR)/fff_test_global_c.o
|
||||
|
||||
FFF_TEST_CPP_TARGET = $(BUILD_DIR)/fff_test_cpp
|
||||
FFF_TEST_C_TARGET = $(BUILD_DIR)/fff_test_c
|
||||
FFF_TEST_GLOBAL_C_TARGET = $(BUILD_DIR)/fff_test_glob_c
|
||||
FFF_TEST_GLOBAL_CPP_TARGET = $(BUILD_DIR)/fff_test_glob_cpp
|
||||
|
||||
LIBS := -lpthread
|
||||
# All Target
|
||||
all: $(FFF_TEST_CPP_TARGET) $(FFF_TEST_C_TARGET) $(FFF_TEST_GLOBAL_C_TARGET) $(FFF_TEST_GLOBAL_CPP_TARGET)
|
||||
|
||||
|
||||
# Each subdirectory must supply rules for building sources it contributes
|
||||
$(BUILD_DIR)/%.o: %.cpp
|
||||
@echo 'Building file: $<'
|
||||
@echo 'Invoking: GCC C++ Compiler'
|
||||
g++ -I../ -O0 -g3 -Wall -DGTEST_USE_OWN_TR1_TUPLE=1 -c -o "$@" "$<"
|
||||
@echo 'Finished building: $<'
|
||||
@echo ' '
|
||||
|
||||
$(BUILD_DIR)/%.o: %.c
|
||||
@echo 'Building file: $<'
|
||||
@echo 'Invoking: GCC C Compiler'
|
||||
gcc -I../ -O0 -g3 -Wall -std=c99 -c -o "$@" "$<"
|
||||
@echo 'Finished building: $<'
|
||||
@echo ' '
|
||||
|
||||
|
||||
# Link targets
|
||||
$(FFF_TEST_CPP_TARGET): $(FFF_TEST_CPP_OBJS)
|
||||
@echo 'Building target: $@'
|
||||
@echo 'Invoking: GCC C++ Linker'
|
||||
g++ -o "$(FFF_TEST_CPP_TARGET)" $(FFF_TEST_CPP_OBJS) $(LIBS)
|
||||
@echo 'Finished building target: $@'
|
||||
@echo ' '
|
||||
|
||||
$(FFF_TEST_C_TARGET): $(FFF_TEST_C_OBJS)
|
||||
@echo 'Building target: $@'
|
||||
@echo 'Invoking: GCC C Linker'
|
||||
gcc -o "$(FFF_TEST_C_TARGET)" $(FFF_TEST_C_OBJS) $(LIBS)
|
||||
@echo 'Finished building target: $@'
|
||||
@echo ' '
|
||||
|
||||
$(FFF_TEST_GLOBAL_C_TARGET): $(FFF_TEST_GLOBAL_C_OBJS)
|
||||
@echo 'Building target: $@'
|
||||
@echo 'Invoking: GCC C++ Linker'
|
||||
gcc -o "$(FFF_TEST_GLOBAL_C_TARGET)" $(FFF_TEST_GLOBAL_C_OBJS) $(LIBS) $(WRAP_LDFLAGS)
|
||||
@echo 'Finished building target: $@'
|
||||
@echo ' '
|
||||
|
||||
$(FFF_TEST_GLOBAL_CPP_TARGET): $(FFF_TEST_GLOBAL_CPP_OBJS)
|
||||
@echo 'Building target: $@'
|
||||
@echo 'Invoking: GCC C++ Linker'
|
||||
g++ -o "$(FFF_TEST_GLOBAL_CPP_TARGET)" $(FFF_TEST_GLOBAL_CPP_OBJS) $(LIBS)
|
||||
@echo 'Finished building target: $@'
|
||||
@echo ' '
|
||||
|
||||
# Other Targets
|
||||
clean:
|
||||
-$(RM) $(FFF_TEST_CPP_OBJS) $(FFF_TEST_GLOBAL_C_OBJS) $(FFF_TEST_C_OBJS) \
|
||||
$(FFF_TEST_CPP_TARGET) $(FFF_TEST_C_TARGET) $(FFF_TEST_GLOBAL_CPP_TARGET) $(FFF_TEST_GLOBAL_C_TARGET)
|
||||
-@echo ' '
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#define OVERRIDE_CALL_HIST_LEN 17u
|
||||
#define FFF_CALL_HISTORY_LEN OVERRIDE_CALL_HIST_LEN
|
||||
|
||||
#include "../fff.h"
|
||||
#include "fff.h"
|
||||
#include "c_test_framework.h"
|
||||
|
||||
#include <assert.h>
|
||||
@@ -21,18 +21,31 @@ struct MyStruct {
|
||||
int y;
|
||||
};
|
||||
|
||||
|
||||
#ifndef TEST_WITH_CALLING_CONVENTIONS
|
||||
FAKE_VOID_FUNC(voidfunc1, int);
|
||||
FAKE_VOID_FUNC(voidfunc2, char, char);
|
||||
FAKE_VOID_FUNC(voidfunc1outparam, char *);
|
||||
FAKE_VALUE_FUNC(long, longfunc0);
|
||||
FAKE_VALUE_FUNC(enum MYBOOL, enumfunc0);
|
||||
FAKE_VALUE_FUNC(struct MyStruct, structfunc0);
|
||||
FAKE_VOID_FUNC_VARARG(voidfunc3var, char *, int, ...);
|
||||
FAKE_VALUE_FUNC_VARARG(int, valuefunc3var, char *, int, ...);
|
||||
FAKE_VOID_FUNC_VARARG(voidfunc3var, const char *, int, ...);
|
||||
FAKE_VALUE_FUNC_VARARG(int, valuefunc3var, const char *, int, ...);
|
||||
FAKE_VALUE_FUNC(int, strlcpy3, char* const, const char* const, const size_t);
|
||||
FAKE_VOID_FUNC(voidfunc20, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int);
|
||||
FAKE_VALUE_FUNC(int, valuefunc20, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int);
|
||||
#else
|
||||
FAKE_VOID_FUNC(__cdecl, voidfunc1, int);
|
||||
FAKE_VOID_FUNC(__cdecl, voidfunc2, char, char);
|
||||
FAKE_VOID_FUNC(__cdecl, voidfunc1outparam, char *);
|
||||
FAKE_VALUE_FUNC(long, __cdecl, longfunc0);
|
||||
FAKE_VALUE_FUNC(enum MYBOOL, __cdecl, enumfunc0);
|
||||
FAKE_VALUE_FUNC(struct MyStruct, __cdecl, structfunc0);
|
||||
FAKE_VOID_FUNC_VARARG(__cdecl, voidfunc3var, char *, int, ...);
|
||||
FAKE_VALUE_FUNC_VARARG(int, __cdecl, valuefunc3var, char *, int, ...);
|
||||
FAKE_VALUE_FUNC(int, __cdecl, strlcpy3, char* const, const char* const, const size_t);
|
||||
FAKE_VOID_FUNC(__cdecl, voidfunc20, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int);
|
||||
FAKE_VALUE_FUNC(int, __cdecl, valuefunc20, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int);
|
||||
#endif
|
||||
|
||||
void setup()
|
||||
{
|
||||
@@ -103,6 +116,10 @@ int main()
|
||||
|
||||
RUN_TEST(FFFTestSuite, use_void_vararg_fake_with_different_number_of_arguments);
|
||||
RUN_TEST(FFFTestSuite, use_value_vararg_fake_with_different_number_of_arguments);
|
||||
RUN_TEST(FFFTestSuite, vararg_custom_fake_sequence_not_exhausted);
|
||||
RUN_TEST(FFFTestSuite, vararg_custom_fake_seq_return_values_saved_in_history);
|
||||
RUN_TEST(FFFTestSuite, vararg_custom_fake_sequence_exhausted);
|
||||
RUN_TEST(FFFTestSuite, vararg_custom_fake_sequence_reset);
|
||||
|
||||
RUN_TEST(FFFTestSuite, can_capture_upto_20_arguments_correctly);
|
||||
RUN_TEST(FFFTestSuite, value_func_can_capture_upto_20_arguments_correctly);
|
||||
|
||||
@@ -12,17 +12,30 @@
|
||||
#define OVERRIDE_CALL_HIST_LEN 17u
|
||||
#define FFF_CALL_HISTORY_LEN OVERRIDE_CALL_HIST_LEN
|
||||
|
||||
#include "../fff.h"
|
||||
#include "fff.h"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
DEFINE_FFF_GLOBALS
|
||||
|
||||
#ifndef TEST_WITH_CALLING_CONVENTIONS
|
||||
FAKE_VOID_FUNC(voidfunc1, int);
|
||||
FAKE_VOID_FUNC(voidfunc2, char, char);
|
||||
FAKE_VOID_FUNC(voidfunc1outparam, char *);
|
||||
FAKE_VALUE_FUNC(long, longfunc0);
|
||||
FAKE_VOID_FUNC_VARARG(voidfunc3var, const char *, int, ...);
|
||||
FAKE_VALUE_FUNC_VARARG(int, valuefunc3var, const char *, int, ...);
|
||||
FAKE_VOID_FUNC(voidfunc20, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int);
|
||||
FAKE_VALUE_FUNC(int, valuefunc20, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int);
|
||||
#else
|
||||
FAKE_VOID_FUNC(__cdecl, voidfunc1, int);
|
||||
FAKE_VOID_FUNC(__cdecl, voidfunc2, char, char);
|
||||
FAKE_VOID_FUNC(__cdecl, voidfunc1outparam, char *);
|
||||
FAKE_VALUE_FUNC(long, __cdecl, longfunc0);
|
||||
FAKE_VOID_FUNC_VARARG(__cdecl, voidfunc3var, const char *, int, ...);
|
||||
FAKE_VALUE_FUNC_VARARG(int, __cdecl, valuefunc3var, const char *, int, ...);
|
||||
FAKE_VOID_FUNC(__cdecl, voidfunc20, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int);
|
||||
FAKE_VALUE_FUNC(int, __cdecl, valuefunc20, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int);
|
||||
#endif
|
||||
|
||||
class FFFTestSuite: public testing::Test
|
||||
{
|
||||
@@ -33,12 +46,12 @@ public:
|
||||
RESET_FAKE(voidfunc2);
|
||||
RESET_FAKE(longfunc0);
|
||||
RESET_FAKE(voidfunc1outparam);
|
||||
RESET_FAKE(voidfunc3var);
|
||||
RESET_FAKE(valuefunc3var);
|
||||
FFF_RESET_HISTORY();
|
||||
}
|
||||
};
|
||||
|
||||
#include "test_cases.include"
|
||||
|
||||
TEST_F(FFFTestSuite, default_constants_can_be_overridden)
|
||||
{
|
||||
unsigned sizeCallHistory = (sizeof fff.call_history) / (sizeof fff.call_history[0]);
|
||||
@@ -46,3 +59,43 @@ TEST_F(FFFTestSuite, default_constants_can_be_overridden)
|
||||
ASSERT_EQ(OVERRIDE_ARG_HIST_LEN, voidfunc2_fake.arg_history_len);
|
||||
}
|
||||
|
||||
// Fake declared in C++ context (not extern "C", using namespace)
|
||||
// before the fake is declared
|
||||
namespace cxx
|
||||
{
|
||||
typedef int int_t;
|
||||
void voidfunc1(cxx::int_t);
|
||||
}
|
||||
|
||||
// Now declare the fake. Must be in the same namespace as the
|
||||
// original declaration.
|
||||
namespace cxx
|
||||
{
|
||||
#ifndef TEST_WITH_CALLING_CONVENTIONS
|
||||
FAKE_VOID_FUNC(voidfunc1, cxx::int_t);
|
||||
#else
|
||||
FAKE_VOID_FUNC(_cdecl, voidfunc1, cxx::int_t);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_F(FFFTestSuite, cxx_fake_is_called)
|
||||
{
|
||||
cxx::voidfunc1(66);
|
||||
ASSERT_EQ(cxx::voidfunc1_fake.call_count, 1u);
|
||||
ASSERT_EQ(cxx::voidfunc1_fake.arg0_val, 66);
|
||||
}
|
||||
|
||||
static int cxx_my_custom_fake_called = 0;
|
||||
void cxx_my_custom_fake(cxx::int_t i)
|
||||
{
|
||||
cxx_my_custom_fake_called++;
|
||||
}
|
||||
|
||||
TEST_F(FFFTestSuite, cxx_can_register_custom_fake)
|
||||
{
|
||||
cxx::voidfunc1_fake.custom_fake = cxx_my_custom_fake;
|
||||
cxx::voidfunc1(66);
|
||||
ASSERT_EQ(1, cxx_my_custom_fake_called);
|
||||
}
|
||||
|
||||
#include "test_cases.include"
|
||||
|
||||
@@ -68,6 +68,10 @@ int main()
|
||||
|
||||
RUN_TEST(FFFTestSuite, use_void_vararg_fake_with_different_number_of_arguments);
|
||||
RUN_TEST(FFFTestSuite, use_value_vararg_fake_with_different_number_of_arguments);
|
||||
RUN_TEST(FFFTestSuite, vararg_custom_fake_sequence_not_exhausted);
|
||||
RUN_TEST(FFFTestSuite, vararg_custom_fake_seq_return_values_saved_in_history);
|
||||
RUN_TEST(FFFTestSuite, vararg_custom_fake_sequence_exhausted);
|
||||
RUN_TEST(FFFTestSuite, vararg_custom_fake_sequence_reset);
|
||||
|
||||
RUN_TEST(FFFTestSuite, can_capture_upto_20_arguments_correctly);
|
||||
RUN_TEST(FFFTestSuite, value_func_can_capture_upto_20_arguments_correctly);
|
||||
|
||||
@@ -15,6 +15,8 @@ public:
|
||||
RESET_FAKE(voidfunc2);
|
||||
RESET_FAKE(longfunc0);
|
||||
RESET_FAKE(voidfunc1outparam);
|
||||
RESET_FAKE(voidfunc3var);
|
||||
RESET_FAKE(valuefunc3var);
|
||||
FFF_RESET_HISTORY();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "global_fakes.h"
|
||||
#include <string.h> // for memcpy
|
||||
|
||||
#ifndef TEST_WITH_CALLING_CONVENTIONS
|
||||
DEFINE_FAKE_VOID_FUNC(voidfunc1, int);
|
||||
DEFINE_FAKE_VOID_FUNC(voidfunc2, char, char);
|
||||
DEFINE_FAKE_VOID_FUNC(voidfunc1outparam, char *);
|
||||
@@ -15,3 +16,19 @@ DEFINE_FAKE_VALUE_FUNC(int, strlcpy3, char* const, const char* const, const size
|
||||
#endif /* __cplusplus */
|
||||
DEFINE_FAKE_VOID_FUNC(voidfunc20, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int);
|
||||
DEFINE_FAKE_VALUE_FUNC(int, valuefunc20, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int);
|
||||
#else
|
||||
DEFINE_FAKE_VOID_FUNC(__cdecl, voidfunc1, int);
|
||||
DEFINE_FAKE_VOID_FUNC(__cdecl, voidfunc2, char, char);
|
||||
DEFINE_FAKE_VOID_FUNC(__cdecl, voidfunc1outparam, char *);
|
||||
|
||||
DEFINE_FAKE_VALUE_FUNC(long, __cdecl, longfunc0);
|
||||
DEFINE_FAKE_VALUE_FUNC(enum MYBOOL, __cdecl, enumfunc0);
|
||||
DEFINE_FAKE_VALUE_FUNC(struct MyStruct, __cdecl, structfunc0);
|
||||
DEFINE_FAKE_VOID_FUNC_VARARG(__cdecl, voidfunc3var, const char *, int, ...);
|
||||
DEFINE_FAKE_VALUE_FUNC_VARARG(int, __cdecl, valuefunc3var, const char *, int, ...);
|
||||
#ifndef __cplusplus
|
||||
DEFINE_FAKE_VALUE_FUNC(int, __cdecl, strlcpy3, char* const, const char* const, const size_t);
|
||||
#endif /* __cplusplus */
|
||||
DEFINE_FAKE_VOID_FUNC(__cdecl, voidfunc20, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int);
|
||||
DEFINE_FAKE_VALUE_FUNC(int, __cdecl,valuefunc20, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int);
|
||||
#endif
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
|
||||
#ifndef GLOBAL_FAKES_H_
|
||||
#define GLOBAL_FAKES_H_
|
||||
|
||||
#include "../fff.h"
|
||||
#include "fff.h"
|
||||
#include "string.h"
|
||||
|
||||
|
||||
@@ -16,6 +15,7 @@ enum MYBOOL enumfunc();
|
||||
struct MyStruct structfunc();
|
||||
//// End Imaginary production code header file ///
|
||||
|
||||
#ifndef TEST_WITH_CALLING_CONVENTIONS
|
||||
DECLARE_FAKE_VOID_FUNC(voidfunc1, int);
|
||||
DECLARE_FAKE_VOID_FUNC(voidfunc2, char, char);
|
||||
DECLARE_FAKE_VOID_FUNC(voidfunc1outparam, char *);
|
||||
@@ -26,8 +26,24 @@ DECLARE_FAKE_VOID_FUNC_VARARG(voidfunc3var, const char *, int, ...);
|
||||
DECLARE_FAKE_VALUE_FUNC_VARARG(int, valuefunc3var, const char *, int, ...);
|
||||
DECLARE_FAKE_VOID_FUNC(voidfunc20, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int);
|
||||
DECLARE_FAKE_VALUE_FUNC(int, valuefunc20, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int);
|
||||
#else
|
||||
DECLARE_FAKE_VOID_FUNC(__cdecl, voidfunc1, int);
|
||||
DECLARE_FAKE_VOID_FUNC(__cdecl, voidfunc2, char, char);
|
||||
DECLARE_FAKE_VOID_FUNC(__cdecl, voidfunc1outparam, char *);
|
||||
DECLARE_FAKE_VALUE_FUNC(long, __cdecl, longfunc0);
|
||||
DECLARE_FAKE_VALUE_FUNC(enum MYBOOL, __cdecl, enumfunc0);
|
||||
DECLARE_FAKE_VALUE_FUNC(struct MyStruct, __cdecl, structfunc0);
|
||||
DECLARE_FAKE_VOID_FUNC_VARARG(__cdecl, voidfunc3var, const char *, int, ...);
|
||||
DECLARE_FAKE_VALUE_FUNC_VARARG(int, __cdecl, valuefunc3var, const char *, int, ...);
|
||||
DECLARE_FAKE_VOID_FUNC(__cdecl, voidfunc20, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int);
|
||||
DECLARE_FAKE_VALUE_FUNC(int, __cdecl, valuefunc20, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int);
|
||||
#endif
|
||||
|
||||
#ifndef __cplusplus
|
||||
#ifndef TEST_WITH_CALLING_CONVENTIONS
|
||||
DECLARE_FAKE_VALUE_FUNC(int, strlcpy3, char* const, const char* const, const size_t);
|
||||
#else
|
||||
DECLARE_FAKE_VALUE_FUNC(int, __cdecl, strlcpy3, char* const, const char* const, const size_t);
|
||||
#endif
|
||||
#endif /* __cplusplus */
|
||||
#endif /* GLOBAL_FAKES_H_ */
|
||||
|
||||
@@ -158,11 +158,13 @@ TEST_F(FFFTestSuite, register_call_macro_registers_two_calls)
|
||||
TEST_F(FFFTestSuite, reset_call_history_resets_call_history)
|
||||
{
|
||||
REGISTER_CALL(longfunc0);
|
||||
REGISTER_CALL(voidfunc1);
|
||||
FFF_RESET_HISTORY();
|
||||
REGISTER_CALL(voidfunc2);
|
||||
|
||||
ASSERT_EQ(1u, fff.call_history_idx);
|
||||
ASSERT_EQ(fff.call_history[0], (void *)voidfunc2);
|
||||
ASSERT_EQ(fff.call_history[1], (void *)0);
|
||||
}
|
||||
|
||||
TEST_F(FFFTestSuite, call_history_will_not_write_past_array_bounds)
|
||||
@@ -284,17 +286,18 @@ TEST_F(FFFTestSuite, return_value_saved_in_history)
|
||||
ASSERT_EQ(longfunc0_fake.return_val_history[i], i + 1);
|
||||
}
|
||||
}
|
||||
long custom_longfunc1()
|
||||
|
||||
long custom_longfunc1(void)
|
||||
{
|
||||
return 42;
|
||||
}
|
||||
|
||||
long custom_longfunc2()
|
||||
long custom_longfunc2(void)
|
||||
{
|
||||
return 15;
|
||||
}
|
||||
|
||||
long custom_longfunc3()
|
||||
long custom_longfunc3(void)
|
||||
{
|
||||
return 7;
|
||||
}
|
||||
@@ -304,6 +307,7 @@ TEST_F(FFFTestSuite, custom_fake_seq_return_values_saved_in_history)
|
||||
long (*custom_fakes[])(void) = {custom_longfunc1,
|
||||
custom_longfunc2,
|
||||
custom_longfunc3};
|
||||
|
||||
SET_CUSTOM_FAKE_SEQ(longfunc0, custom_fakes, 3);
|
||||
|
||||
longfunc0();
|
||||
@@ -343,6 +347,13 @@ long my_custom_value_fake(void)
|
||||
{
|
||||
return MEANING_OF_LIFE;
|
||||
}
|
||||
|
||||
long my_custom_value_fake2(void)
|
||||
{
|
||||
static long val = 0;
|
||||
return val++;
|
||||
}
|
||||
|
||||
TEST_F(FFFTestSuite, when_value_custom_fake_called_THEN_it_returns_custom_return_value)
|
||||
{
|
||||
longfunc0_fake.custom_fake = my_custom_value_fake;
|
||||
@@ -350,7 +361,100 @@ TEST_F(FFFTestSuite, when_value_custom_fake_called_THEN_it_returns_custom_return
|
||||
ASSERT_EQ(MEANING_OF_LIFE, retval);
|
||||
}
|
||||
|
||||
#ifndef __cplusplus
|
||||
TEST_F(FFFTestSuite, return_values_from_custom_fake_saved_in_history)
|
||||
{
|
||||
longfunc0_fake.custom_fake = my_custom_value_fake2;
|
||||
longfunc0();
|
||||
longfunc0();
|
||||
longfunc0();
|
||||
|
||||
ASSERT_EQ(0, longfunc0_fake.return_val_history[0]);
|
||||
ASSERT_EQ(1, longfunc0_fake.return_val_history[1]);
|
||||
ASSERT_EQ(2, longfunc0_fake.return_val_history[2]);
|
||||
}
|
||||
|
||||
int valuefunc3var_custom_fake1(const char *str, int a, va_list vl)
|
||||
{
|
||||
int arg;
|
||||
while ((arg = va_arg(vl, int)) != 0)
|
||||
a += arg;
|
||||
return a;
|
||||
}
|
||||
|
||||
int valuefunc3var_custom_fake2(const char *str, int a, va_list vl)
|
||||
{
|
||||
int arg;
|
||||
while ((arg = va_arg(vl, int)) != 0)
|
||||
a -= arg;
|
||||
return a;
|
||||
}
|
||||
|
||||
int valuefunc3var_custom_fake3(const char *str, int a, va_list vl)
|
||||
{
|
||||
int arg;
|
||||
while ((arg = va_arg(vl, int)) != 0)
|
||||
a *= arg;
|
||||
return a;
|
||||
}
|
||||
|
||||
TEST_F(FFFTestSuite, vararg_custom_fake_sequence_not_exhausted)
|
||||
{
|
||||
int (*custom_fakes[])(const char *, int, va_list) = {valuefunc3var_custom_fake1,
|
||||
valuefunc3var_custom_fake2,
|
||||
valuefunc3var_custom_fake3};
|
||||
SET_CUSTOM_FAKE_SEQ(valuefunc3var, custom_fakes, 3);
|
||||
int a = 1;
|
||||
ASSERT_EQ(valuefunc3var("a", a, 2, 3, 4, 0), 10);
|
||||
ASSERT_EQ(valuefunc3var("aa", a, 2, 3, 4, 2, 0), -10);
|
||||
ASSERT_EQ(valuefunc3var("aaa", a, 2, 3, 0), 6);
|
||||
}
|
||||
|
||||
TEST_F(FFFTestSuite, vararg_custom_fake_seq_return_values_saved_in_history)
|
||||
{
|
||||
int (*custom_fakes[])(const char *, int, va_list) = {valuefunc3var_custom_fake1,
|
||||
valuefunc3var_custom_fake2,
|
||||
valuefunc3var_custom_fake3};
|
||||
SET_CUSTOM_FAKE_SEQ(valuefunc3var, custom_fakes, 3);
|
||||
int a = 1;
|
||||
valuefunc3var("a", a, 2, 3, 4, 0);
|
||||
valuefunc3var("aa", a, 2, 3, 4, 2, 0);
|
||||
valuefunc3var("aaa", a, 2, 3, 0);
|
||||
ASSERT_EQ(10, valuefunc3var_fake.return_val_history[0]);
|
||||
ASSERT_EQ(-10, valuefunc3var_fake.return_val_history[1]);
|
||||
ASSERT_EQ(6, valuefunc3var_fake.return_val_history[2]);
|
||||
}
|
||||
|
||||
TEST_F(FFFTestSuite, vararg_custom_fake_sequence_exhausted)
|
||||
{
|
||||
int (*custom_fakes[])(const char *, int, va_list) = {valuefunc3var_custom_fake1,
|
||||
valuefunc3var_custom_fake2,
|
||||
valuefunc3var_custom_fake3};
|
||||
SET_CUSTOM_FAKE_SEQ(valuefunc3var, custom_fakes, 3);
|
||||
int a = 1;
|
||||
ASSERT_EQ(valuefunc3var("a", a, 2, 3, 4, 0), 10);
|
||||
ASSERT_EQ(valuefunc3var("aa", a, 2, 3, 4, 2, 0), -10);
|
||||
ASSERT_EQ(valuefunc3var("aaa", a, 2, 3, 0), 6);
|
||||
ASSERT_EQ(valuefunc3var("aaa", a, 4, 5, 1, 0), 20);
|
||||
ASSERT_EQ(valuefunc3var("aaa", a, 4, 0), 4);
|
||||
}
|
||||
|
||||
TEST_F(FFFTestSuite, vararg_custom_fake_sequence_reset)
|
||||
{
|
||||
int (*custom_fakes[])(const char *, int, va_list) = {valuefunc3var_custom_fake1,
|
||||
valuefunc3var_custom_fake2,
|
||||
valuefunc3var_custom_fake3};
|
||||
SET_CUSTOM_FAKE_SEQ(valuefunc3var, custom_fakes, 3);
|
||||
int a = 1;
|
||||
ASSERT_EQ(valuefunc3var("a", a, 2, 3, 4, 0), 10);
|
||||
ASSERT_EQ(valuefunc3var("aa", a, 2, 3, 4, 2, 0), -10);
|
||||
RESET_FAKE(valuefunc3var);
|
||||
ASSERT_EQ(0, valuefunc3var("b", 7, 4, 5));
|
||||
valuefunc3var_fake.return_val = 1;
|
||||
ASSERT_EQ(1, valuefunc3var("c", 5, 4, 4));
|
||||
valuefunc3var_fake.return_val = 2;
|
||||
ASSERT_EQ(2, valuefunc3var("d", 6, 3, 5));
|
||||
}
|
||||
|
||||
TEST_F(FFFTestSuite, use_void_vararg_fake_with_different_number_of_arguments)
|
||||
{
|
||||
voidfunc3var("0 parameters", 0);
|
||||
@@ -358,7 +462,7 @@ TEST_F(FFFTestSuite, use_void_vararg_fake_with_different_number_of_arguments)
|
||||
voidfunc3var("2 parameters", 2, 10, 20);
|
||||
voidfunc3var("3 parameters", 3, 10, 20, 30);
|
||||
|
||||
ASSERT_EQ(voidfunc3var_fake.call_count, 4);
|
||||
ASSERT_EQ(voidfunc3var_fake.call_count, 4u);
|
||||
char msg[] = "3 parameters";
|
||||
ASSERT_EQ(strcmp(voidfunc3var_fake.arg0_val, msg), 0);
|
||||
ASSERT_EQ(3, voidfunc3var_fake.arg1_val);
|
||||
@@ -371,12 +475,11 @@ TEST_F(FFFTestSuite, use_value_vararg_fake_with_different_number_of_arguments)
|
||||
valuefunc3var("2 parameters", 2, 10, 20);
|
||||
valuefunc3var("3 parameters", 3, 10, 20, 30);
|
||||
|
||||
ASSERT_EQ(valuefunc3var_fake.call_count, 4);
|
||||
ASSERT_EQ(valuefunc3var_fake.call_count, 4u);
|
||||
char msg[] = "3 parameters";
|
||||
ASSERT_EQ(strcmp(valuefunc3var_fake.arg0_val, msg), 0);
|
||||
ASSERT_EQ(3, valuefunc3var_fake.arg1_val);
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
TEST_F(FFFTestSuite, can_capture_upto_20_arguments_correctly)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user