@@ -59,6 +59,7 @@ include_directories( | |||
"${PROJECT_SOURCE_DIR}/dependencies/SDL2_ttf/include" | |||
"${PROJECT_SOURCE_DIR}/dependencies/minIni/dev" | |||
"${PROJECT_SOURCE_DIR}/dependencies/bdd-for-c" | |||
"${PROJECT_SOURCE_DIR}/dependencies/bdd-for-c-mocks" | |||
"${PROJECT_SOURCE_DIR}/dependencies/portmidi/pm_common" | |||
"${PROJECT_SOURCE_DIR}/dependencies/spine-runtimes/spine-c/spine-c/include" | |||
"${PROJECT_SOURCE_DIR}/dependencies/getopt-for-windows" | |||
@@ -191,8 +192,7 @@ endif() | |||
add_executable( | |||
game-test-geometry | |||
dependencies/bdd-for-c/bdd-for-c.h | |||
src/packages/test/IZ_mock.h | |||
src/packages/test/IZ_test.h | |||
dependencies/bdd-for-c-mocks/bdd-for-c-mocks.h | |||
src/packages/game/geometry/IZ_rect.h | |||
src/packages/game/geometry/IZ_rect.c | |||
@@ -204,8 +204,7 @@ add_executable( | |||
add_executable( | |||
game-test-input | |||
dependencies/bdd-for-c/bdd-for-c.h | |||
src/packages/test/IZ_mock.h | |||
src/packages/test/IZ_test.h | |||
dependencies/bdd-for-c-mocks/bdd-for-c-mocks.h | |||
__mocks__/dependencies/minIni/minIni.mock.h | |||
__mocks__/dependencies/SDL2/SDL_keyboard.mock.h | |||
@@ -234,11 +233,12 @@ add_executable( | |||
add_executable( | |||
game-test-output | |||
dependencies/bdd-for-c/bdd-for-c.h | |||
src/packages/test/IZ_mock.h | |||
src/packages/test/IZ_test.h | |||
dependencies/bdd-for-c-mocks/bdd-for-c-mocks.h | |||
__mocks__/dependencies/minIni/minIni.mock.h | |||
__mocks__/dependencies/SDL2/SDL_stdinc.mock.h | |||
__mocks__/dependencies/SDL2/SDL_render.mock.h | |||
src/packages/config/IZ_config.h | |||
src/packages/game/output/video/IZ_video.h | |||
src/packages/game/output/video/IZ_video.c | |||
@@ -248,21 +248,25 @@ add_executable( | |||
add_executable( | |||
game-test-memory | |||
dependencies/bdd-for-c/bdd-for-c.h | |||
src/packages/test/IZ_mock.h | |||
src/packages/test/IZ_test.h | |||
dependencies/bdd-for-c-mocks/bdd-for-c-mocks.h | |||
src/packages/timer/IZ_timer.h | |||
src/packages/timer/IZ_timer.c | |||
src/packages/stdinc/IZ_stdlib.h | |||
__mocks__/src/packages/stdinc/IZ_stdlib.mock.h | |||
src/packages/stdinc/IZ_string.h | |||
__mocks__/src/packages/stdinc/IZ_string.mock.h | |||
src/packages/log/IZ_log.h | |||
__mocks__/src/packages/log/IZ_log.mock.h | |||
src/packages/game/data/IZ_list.c | |||
src/packages/game/data/IZ_list.h | |||
src/packages/game/memory/IZ_pool.h | |||
src/packages/game/memory/IZ_pool.c | |||
src/packages/game/memory/memory.test.c | |||
src/packages/game/data/IZ_list.c | |||
src/packages/game/data/IZ_list.h | |||
) | |||
target_link_libraries( | |||
@@ -274,13 +278,22 @@ target_link_libraries( | |||
add_executable( | |||
game-test-data | |||
dependencies/bdd-for-c/bdd-for-c.h | |||
src/packages/test/IZ_mock.h | |||
src/packages/test/IZ_test.h | |||
dependencies/bdd-for-c-mocks/bdd-for-c-mocks.h | |||
src/packages/stdinc/IZ_stdlib.h | |||
__mocks__/src/packages/stdinc/IZ_stdlib.mock.h | |||
src/packages/game/data/IZ_list.h | |||
src/packages/game/data/IZ_list.c | |||
src/packages/game/data/data.test.c | |||
) | |||
target_link_libraries( | |||
game-test-data | |||
SDL2main | |||
SDL2 | |||
) | |||
add_executable( | |||
server | |||
dependencies/sqlite/sqlite3.h | |||
@@ -1,8 +1,8 @@ | |||
#ifndef SDL_JOYSTICK_MOCK_H | |||
#define SDL_JOYSTICK_MOCK_H | |||
#include <bdd-for-c-mocks.h> | |||
#include "../../../src/packages/common/IZ_common.h" | |||
#include "../../../src/packages/test/IZ_test.h" | |||
typedef struct _SDL_Joystick {} SDL_Joystick; | |||
@@ -1,8 +1,8 @@ | |||
#ifndef SDL_KEYBOARD_MOCK_H | |||
#define SDL_KEYBOARD_MOCK_H | |||
#include <bdd-for-c-mocks.h> | |||
#include "../../../src/packages/common/IZ_common.h" | |||
#include "../../../src/packages/test/IZ_test.h" | |||
mock(SDL_GetKeyName) const char* SDL_GetKeyName(i32 key) { | |||
mock_return(SDL_GetKeyName) ""; | |||
@@ -1,8 +1,8 @@ | |||
#ifndef SDL_RENDER_MOCK_H | |||
#define SDL_RENDER_MOCK_H | |||
#include <bdd-for-c-mocks.h> | |||
#include "../../../src/packages/common/IZ_common.h" | |||
#include "../../../src/packages/test/IZ_test.h" | |||
typedef struct SDL_Renderer SDL_Renderer; | |||
@@ -2,8 +2,8 @@ | |||
#define SDL_STDINC_MOCK_H | |||
#include <string.h> | |||
#include <bdd-for-c-mocks.h> | |||
#include "../../../src/packages/common/IZ_common.h" | |||
#include "../../../src/packages/test/IZ_test.h" | |||
mock(SDL_memcpy) void* SDL_memcpy(void* dst, const void* src, size_t len) { | |||
mock_return(SDL_memcpy) memcpy(dst, src, len); | |||
@@ -1,8 +1,8 @@ | |||
#ifndef MININI_MOCK_H | |||
#define MININI_MOCK_H | |||
#include <bdd-for-c-mocks.h> | |||
#include "../../../src/packages/common/IZ_common.h" | |||
#include "../../../src/packages/test/IZ_test.h" | |||
mock(ini_getl) long ini_getl(const char *Section, const char *Key, long DefValue, const char *Filename) { | |||
mock_return(ini_getl) DefValue; | |||
@@ -1,7 +1,7 @@ | |||
#ifndef IZ_LOG_MOCK_H | |||
#define IZ_LOG_MOCK_H | |||
#include "../../../src/packages/test/IZ_mock.h" | |||
#include <bdd-for-c-mocks.h> | |||
#include "../../../src/packages/log/IZ_log.h" | |||
mock_modes(IZ_LogInfo) { | |||
@@ -1,8 +1,8 @@ | |||
#ifndef IZ_STDLIB_MOCK_C | |||
#define IZ_STDLIB_MOCK_C | |||
#include <bdd-for-c-mocks.h> | |||
#include <SDL_stdinc.h> | |||
#include "../../../../src/packages/test/IZ_mock.h" | |||
mock(IZ_malloc) void* IZ_malloc(size_t size) { | |||
mock_return(IZ_malloc) SDL_malloc(size); | |||
@@ -1,7 +1,7 @@ | |||
#ifndef IZ_STRING_MOCK_C | |||
#define IZ_STRING_MOCK_C | |||
#include "../../../../src/packages/test/IZ_mock.h" | |||
#include <bdd-for-c-mocks.h> | |||
mock(IZ_memset) void* IZ_memset(void* dst, int c, size_t len) { | |||
mock_return(IZ_memset) 0; | |||
@@ -9,3 +9,4 @@ https://github.com/Chunde/getopt-for-windows | |||
https://libwebsockets.org/repo/libwebsockets | |||
https://github.com/openssl/openssl | |||
https://www.sqlite.org/download.html (use SQLite amalgamated source code, unpack into `sqlite` directory) | |||
https://code.modal.sh/TheoryOfNekomata/bdd-for-c-mocks |
@@ -1,6 +1,6 @@ | |||
#include "../../test/IZ_test.h" | |||
#include <bdd-for-c.h> | |||
#include "../../common/IZ_common.h" | |||
#include "../../../../__mocks__/dependencies/SDL2/SDL_stdinc.mock.h" | |||
#include "../../../../__mocks__/src/packages/stdinc/IZ_stdlib.mock.h" | |||
#include "IZ_list.h" | |||
bool NodeExists(IZ_ListNode** node, u64 _index, IZ_List* list) { | |||
@@ -46,15 +46,15 @@ spec("data") { | |||
} | |||
after_each() { | |||
mock_reset(SDL_free); | |||
mock_reset(IZ_free); | |||
} | |||
it("removes all nodes from the list") { | |||
mock_set_expected_calls(SDL_free, 3); | |||
mock_set_expected_calls(IZ_free, 3); | |||
IZ_ListTeardown(&list); | |||
check( | |||
mock_get_expected_calls(SDL_free) == mock_get_actual_calls(SDL_free), | |||
mock_get_expected_calls(IZ_free) == mock_get_actual_calls(IZ_free), | |||
"Deallocator function call count mismatch." | |||
); | |||
} | |||
@@ -80,7 +80,7 @@ spec("data") { | |||
} | |||
after_each() { | |||
mock_reset(SDL_malloc); | |||
mock_reset(IZ_malloc); | |||
} | |||
after_each() { | |||
@@ -97,7 +97,7 @@ spec("data") { | |||
check(*((u64*) list.root->value) == 69420u, "Node not properly appended."); | |||
check( | |||
mock_is_called(SDL_malloc), | |||
mock_is_called(IZ_malloc), | |||
"Allocator function not called." | |||
); | |||
check(list.length == 1, "Length mismatch."); | |||
@@ -110,7 +110,7 @@ spec("data") { | |||
check(*((u64*) list2.root->next->value) == 42069u, "Node not properly appended."); | |||
check( | |||
mock_is_called(SDL_malloc), | |||
mock_is_called(IZ_malloc), | |||
"Allocator function not called." | |||
); | |||
check(list2.length == 2, "Length mismatch."); | |||
@@ -160,14 +160,14 @@ spec("data") { | |||
} | |||
after_each() { | |||
mock_reset(SDL_free); | |||
mock_reset(IZ_free); | |||
} | |||
it("removes first node satisfying the filter condition") { | |||
IZ_ListDeleteFirstNode(&list, NodeExists); | |||
check( | |||
mock_is_called(SDL_free), | |||
mock_is_called(IZ_free), | |||
"Deallocator function not called." | |||
); | |||
@@ -1,4 +1,4 @@ | |||
#include "../../test/IZ_test.h" | |||
#include <bdd-for-c.h> | |||
#include "IZ_vector2d.h" | |||
#include "IZ_rect.h" | |||
@@ -1,28 +0,0 @@ | |||
#ifndef IZ_MOCK_H | |||
#define IZ_MOCK_H | |||
#define mock_call_count_t unsigned char | |||
#define mock(X) static mock_call_count_t actual_##X = 0; | |||
#define mock_mode_t unsigned char | |||
#define mock_modes(X) static mock_mode_t current_mock_mode_##X = 0; enum mock_modes_##X | |||
#define mock_mode(X, Y) current_mock_mode_##X = Y | |||
#define mock_mode_if(X, Y) if (current_mock_mode_##X == Y) | |||
#define mock_return(X) actual_##X += 1; return | |||
#define mock_reset(X) actual_##X = 0 | |||
#define mock_get_actual_calls(X) (mock_call_count_t) actual_##X | |||
#define mock_set_expected_calls(X, Y) static const mock_call_count_t expected_##X = Y | |||
#define mock_get_expected_calls(X) (mock_call_count_t) expected_##X | |||
#define mock_is_called(X) mock_get_actual_calls(X) > 0 | |||
#endif |
@@ -1,8 +0,0 @@ | |||
#ifndef IZ_TEST_H | |||
#define IZ_TEST_H | |||
#include <bdd-for-c.h> | |||
#include "IZ_mock.h" | |||
#endif |
@@ -1,126 +0,0 @@ | |||
# bdd-for-c-mocks | |||
## Usage | |||
Suppose you have a library `lib` and an application `app` that uses `lib`. You want to test `app` and you want to mock | |||
`lib`'s functions. You can do this by creating a mock header file for `lib` and including it in `app`'s test file. | |||
### `lib.h` | |||
This is a reference header file for `lib`. The implementation should be abstracted from us, and we want to be able to | |||
mock its behavior. | |||
```c | |||
#ifndef LIB_H | |||
#define LIB_H | |||
int add(int a, int b); | |||
void alert(); | |||
#endif | |||
``` | |||
### `lib.mock.h` | |||
We define mocked behavior for `lib`. `bdd-for-c-mocks` offers a capability to force mock behavior through modes. Note | |||
that all mode behaviors should be implemented already. | |||
```c | |||
#ifndef LIB_MOCK_H | |||
#define LIB_MOCK_H | |||
#include <bdd-for-c-mocks.h> | |||
mock_modes(add) { | |||
ADD_RETURNS_SUM = 0, | |||
ADD_RETURNS_CONSTANT_VALUE, | |||
}; | |||
mock(add) int add(int a, int b) { | |||
mock_mode_if(add, ADD_RETURNS_SUM) { | |||
// suppose we want to test normal behavior | |||
mock_return(add) a + b; | |||
} else mock_mode_if(add, ADD_RETURNS_CONSTANT_VALUE) { | |||
// maybe an edge case? | |||
mock_return(add) 5; | |||
} | |||
} | |||
mock(alert) void alert() { | |||
mock_return(alert); | |||
} | |||
#endif | |||
``` | |||
### `app.h` | |||
```c | |||
#ifndef APP_H | |||
#define APP_H | |||
void math(); | |||
#endif | |||
``` | |||
### `app.c` | |||
This is a reference implementation of `app`. We want to test the invocations done inside the `math()` function. | |||
```c | |||
#include "lib.h" | |||
#include "app.h" | |||
void math() { | |||
int result_a = add(1, 2); | |||
int result_b = add(3, 4); | |||
if (result_a == result_b) { | |||
// this is the edge case! | |||
// alert() should be called if the add values are the same | |||
alert(); | |||
} | |||
} | |||
``` | |||
### `app.test.c` | |||
This is the test file for `app`. It includes `lib.mock.h` instead of `lib.c`. `lib.h` should still be linked because we | |||
are sharing the original function declarations. | |||
```c | |||
#include <bdd-for-c.h> | |||
#include "app.h" | |||
spec("app") { | |||
describe("math") { | |||
after_each() { | |||
mock_reset(add); | |||
} | |||
after_each() { | |||
mock_reset(alert); | |||
} | |||
it("calls add") { | |||
mock_mode(add, ADD_RETURNS_SUM); | |||
mock_set_excepted_calls(math, 2); | |||
math(); | |||
check( | |||
mock_get_expected_calls(math) == mock_get_actual_calls(math), | |||
"add was not called." | |||
); | |||
} | |||
it("calls alert when calls from add return the same values") { | |||
mock_mode(add, ADD_RETURNS_CONSTANT_VALUE); | |||
math(); | |||
check(mock_is_called(alert), "alert was not called."); | |||
} | |||
} | |||
} | |||
``` |