mirror of
https://github.com/meekrosoft/fff
synced 2026-01-23 08:25:59 +01:00
Squashed commit of the following:
commit e5a5749971eb9274679699020a54c91d4053ed79 Author: James Fraser <wulfgar.pro@gmail.com> Date: Sun Feb 3 19:57:31 2019 +1100 PR #47: Minor review fixes to tests files. commit e9f11b9ec8de8f8d1f0de7b6959c575e15894526 Author: James Fraser <wulfgar.pro@gmail.com> Date: Sun Feb 3 19:57:04 2019 +1100 PR #47: Minor review fixes. commit0a7fbeceecAuthor: Pauli Salmenrinne <pauli.salmenrinne@pexraytech.com> Date: Tue Jan 22 15:11:10 2019 +0200 Add example for the weak linking commit647737304dAuthor: susundberg <susundberg@gmail.com> Date: Wed Mar 21 13:14:05 2018 +0200 Add "FFF_FUNCTION_ATTRIBUTES" definition that can be used to declare attributes for functions. More specifically, allow __weak__ attribute.
This commit is contained in:
26
README.md
26
README.md
@@ -21,6 +21,7 @@
|
|||||||
- [How do I fake a function that returns a value by reference?](#how-do-i-fake-a-function-that-returns-a-value-by-reference)
|
- [How do I fake a function that returns a value by reference?](#how-do-i-fake-a-function-that-returns-a-value-by-reference)
|
||||||
- [How do I fake a function with a function pointer parameter?](#how-do-i-fake-a-function-with-a-function-pointer-parameter)
|
- [How do I fake a function with a function pointer parameter?](#how-do-i-fake-a-function-with-a-function-pointer-parameter)
|
||||||
- [How do I reuse a fake across multiple test-suites?](#how-do-i-reuse-a-fake-across-multiple-test-suites)
|
- [How do I reuse a fake across multiple test-suites?](#how-do-i-reuse-a-fake-across-multiple-test-suites)
|
||||||
|
- [Specifying GCC Function Attributes](#specifying-gcc-function-attributes)
|
||||||
- [Find out more...](#find-out-more)
|
- [Find out more...](#find-out-more)
|
||||||
- [Benefits](#benefits)
|
- [Benefits](#benefits)
|
||||||
- [Under the hood](#under-the-hood)
|
- [Under the hood](#under-the-hood)
|
||||||
@@ -603,6 +604,26 @@ DEFINE_FAKE_VALUE_FUNC_VARARG(int, value_function_vargs, const char *, int, ...)
|
|||||||
DEFINE_FAKE_VOID_FUNC_VARARG(void_function_vargs, const char *, int, ...);
|
DEFINE_FAKE_VOID_FUNC_VARARG(void_function_vargs, const char *, int, ...);
|
||||||
|
|
||||||
```
|
```
|
||||||
|
## 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...
|
## Find out more...
|
||||||
|
|
||||||
@@ -621,8 +642,9 @@ So whats the point?
|
|||||||
|
|
||||||
## Under the Hood
|
## Under the Hood
|
||||||
* The fff.h header file is generated by a ruby script
|
* The fff.h header file is generated by a ruby script
|
||||||
* There are tests under src/test
|
* There are tests under _./test_
|
||||||
* There is an example for testing an embedded UI and a hardware driver under src/examples
|
* 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
|
## Cheat Sheet
|
||||||
|
|||||||
@@ -14,3 +14,7 @@ build/fff_test_glob_c
|
|||||||
build/fff_test_glob_cpp --gtest_output=xml:build/test_global_results.xml
|
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 --gtest_output=xml:build/driver_testing.xml
|
||||||
build/driver_testing_fff --gtest_output=xml:build/driver_testing_fff.xml
|
build/driver_testing_fff --gtest_output=xml:build/driver_testing_fff.xml
|
||||||
|
build/weak_linking/test_display
|
||||||
|
build/weak_linking/test_sensor
|
||||||
|
build/weak_linking/test_main
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
all:
|
all:
|
||||||
cd embedded_ui; $(MAKE) all
|
cd embedded_ui; $(MAKE) all
|
||||||
cd driver_testing; $(MAKE) all
|
cd driver_testing; $(MAKE) all
|
||||||
|
cd weak_linking; $(MAKE) all
|
||||||
clean:
|
clean:
|
||||||
cd embedded_ui; $(MAKE) clean
|
cd embedded_ui; $(MAKE) clean
|
||||||
cd driver_testing; $(MAKE) clean
|
cd driver_testing; $(MAKE) clean
|
||||||
|
cd weak_linking; $(MAKE) clean
|
||||||
|
|
||||||
|
|||||||
39
examples/weak_linking/Makefile
Normal file
39
examples/weak_linking/Makefile
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
BUILD_DIR = ../../build
|
||||||
|
INCLUDE_DIRS = -I "../../" -I "./src/"
|
||||||
|
|
||||||
|
BUILD_DIR_FAKE = $(BUILD_DIR)/weak_linking
|
||||||
|
CC = gcc
|
||||||
|
WEAK_FLAGS=-Wall -DFFF_GCC_FUNCTION_ATTRIBUTES="__attribute__((weak))"
|
||||||
|
|
||||||
|
$(BUILD_DIR_FAKE)/%.o: test/%.c
|
||||||
|
@echo "Compiling "$@
|
||||||
|
$(CC) $(WEAK_FLAGS) $(INCLUDE_DIRS) -g -O0 -c $< -o $@
|
||||||
|
|
||||||
|
FAKE_OBJECTS = $(BUILD_DIR_FAKE)/display.fake.o $(BUILD_DIR_FAKE)/sensor.fake.o $(BUILD_DIR_FAKE)/sensor.fake.o $(BUILD_DIR_FAKE)/error.fake.o $(BUILD_DIR_FAKE)/bus.fake.o $(BUILD_DIR_FAKE)/test_common.o
|
||||||
|
|
||||||
|
TEST_BINARIES = $(BUILD_DIR_FAKE)/test_main $(BUILD_DIR_FAKE)/test_display $(BUILD_DIR_FAKE)/test_sensor
|
||||||
|
mkdir:
|
||||||
|
mkdir -p $(BUILD_DIR_FAKE)/
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(BUILD_DIR_FAKE)/
|
||||||
|
|
||||||
|
$(BUILD_DIR_FAKE)/libfakes.a: $(FAKE_OBJECTS)
|
||||||
|
ar r $@ $^
|
||||||
|
|
||||||
|
# First case where we need __weak__ linking:
|
||||||
|
# - If we have the build objects (for some reason) in order where the fake object comes first.
|
||||||
|
$(BUILD_DIR_FAKE)/test_display: ./test/display.test.c $(BUILD_DIR_FAKE)/libfakes.a ./src/display.c
|
||||||
|
$(CC) $(WEAK_FLAGS) $(INCLUDE_DIRS) -o $@ $^
|
||||||
|
|
||||||
|
# Second case where we need weak linking:
|
||||||
|
# - If we use an object from the fake object -> gcc linker will include it.
|
||||||
|
$(BUILD_DIR_FAKE)/test_sensor: ./test/sensor.test.c ./src/sensor.c $(BUILD_DIR_FAKE)/libfakes.a
|
||||||
|
$(CC) $(WEAK_FLAGS) $(INCLUDE_DIRS) -o $@ $^
|
||||||
|
|
||||||
|
# Third case where we need weak linking:
|
||||||
|
# - We want to fake one function but not all.
|
||||||
|
$(BUILD_DIR_FAKE)/test_main: ./test/main.test.c ./src/main.c $(BUILD_DIR_FAKE)/libfakes.a
|
||||||
|
$(CC) $(WEAK_FLAGS) $(INCLUDE_DIRS) -o $@ $^
|
||||||
|
|
||||||
|
all: mkdir $(TEST_BINARIES)
|
||||||
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;
|
||||||
|
}
|
||||||
6
examples/weak_linking/src/bus.h
Normal file
6
examples/weak_linking/src/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 );
|
||||||
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!");
|
||||||
|
}
|
||||||
|
}
|
||||||
5
examples/weak_linking/src/display.h
Normal file
5
examples/weak_linking/src/display.h
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "error.h"
|
||||||
|
|
||||||
|
bool display_init();
|
||||||
|
void display_update( const char* info );
|
||||||
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;
|
||||||
|
}
|
||||||
7
examples/weak_linking/src/error.h
Normal file
7
examples/weak_linking/src/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 );
|
||||||
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;
|
||||||
|
}
|
||||||
6
examples/weak_linking/src/sensor.h
Normal file
6
examples/weak_linking/src/sensor.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "error.h"
|
||||||
|
|
||||||
|
bool sensor_init();
|
||||||
|
float sensor_read();
|
||||||
4
examples/weak_linking/test/bus.fake.c
Normal file
4
examples/weak_linking/test/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 );
|
||||||
10
examples/weak_linking/test/bus.fake.h
Normal file
10
examples/weak_linking/test/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
|
||||||
4
examples/weak_linking/test/display.fake.c
Normal file
4
examples/weak_linking/test/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* );
|
||||||
10
examples/weak_linking/test/display.fake.h
Normal file
10
examples/weak_linking/test/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
|
||||||
24
examples/weak_linking/test/display.test.c
Normal file
24
examples/weak_linking/test/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/error.fake.c
Normal file
4
examples/weak_linking/test/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* );
|
||||||
10
examples/weak_linking/test/error.fake.h
Normal file
10
examples/weak_linking/test/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
|
||||||
26
examples/weak_linking/test/main.test.c
Normal file
26
examples/weak_linking/test/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/sensor.fake.c
Normal file
11
examples/weak_linking/test/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;
|
||||||
|
}
|
||||||
13
examples/weak_linking/test/sensor.fake.h
Normal file
13
examples/weak_linking/test/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
|
||||||
23
examples/weak_linking/test/sensor.test.c
Normal file
23
examples/weak_linking/test/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/test_common.c
Normal file
33
examples/weak_linking/test/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;
|
||||||
|
}
|
||||||
13
examples/weak_linking/test/test_common.h
Normal file
13
examples/weak_linking/test/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];
|
||||||
10
fakegen.rb
10
fakegen.rb
@@ -26,6 +26,12 @@ def output_constants
|
|||||||
putd "#define FFF_CALL_HISTORY_LEN (#{$MAX_CALL_HISTORY}u)"
|
putd "#define FFF_CALL_HISTORY_LEN (#{$MAX_CALL_HISTORY}u)"
|
||||||
}
|
}
|
||||||
putd "#endif"
|
putd "#endif"
|
||||||
|
putd "#ifndef FFF_GCC_FUNCTION_ATTRIBUTES"
|
||||||
|
indent {
|
||||||
|
putd "#define FFF_GCC_FUNCTION_ATTRIBUTES"
|
||||||
|
}
|
||||||
|
putd "#endif"
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -384,8 +390,8 @@ def function_signature(arg_count, has_varargs, has_calling_conventions, is_value
|
|||||||
return_type = is_value_function ? "RETURN_TYPE" : "void"
|
return_type = is_value_function ? "RETURN_TYPE" : "void"
|
||||||
varargs = has_varargs ? ", ..." : ""
|
varargs = has_varargs ? ", ..." : ""
|
||||||
calling_conventions = has_calling_conventions ?
|
calling_conventions = has_calling_conventions ?
|
||||||
"#{return_type} CALLING_CONVENTION FUNCNAME(#{arg_val_list(arg_count)}#{varargs})" :
|
"#{return_type} FFF_GCC_FUNCTION_ATTRIBUTES CALLING_CONVENTION FUNCNAME(#{arg_val_list(arg_count)}#{varargs})" :
|
||||||
"#{return_type} FUNCNAME(#{arg_val_list(arg_count)}#{varargs})"
|
"#{return_type} FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(#{arg_val_list(arg_count)}#{varargs})"
|
||||||
end
|
end
|
||||||
|
|
||||||
def output_function_body(arg_count, has_varargs, is_value_function)
|
def output_function_body(arg_count, has_varargs, is_value_function)
|
||||||
|
|||||||
Reference in New Issue
Block a user