diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..72989b2 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = tab +indent_style = tab +insert_final_newline = true +max_line_length = 120 +tab_width = 2 diff --git a/CMakeLists.txt b/CMakeLists.txt index 18fd467..12056c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,54 +6,81 @@ project(izanagi C) set(CMAKE_C_STANDARD 11) include_directories( - "${PROJECT_SOURCE_DIR}/dependencies/SDL2/include" - "${PROJECT_SOURCE_DIR}/dependencies/minIni/dev" - "${PROJECT_SOURCE_DIR}/dependencies/bdd-for-c" - "${PROJECT_SOURCE_DIR}/dependencies/portmidi/pm_common" + "${PROJECT_SOURCE_DIR}/dependencies/SDL2/include" + "${PROJECT_SOURCE_DIR}/dependencies/minIni/dev" + "${PROJECT_SOURCE_DIR}/dependencies/bdd-for-c" + "${PROJECT_SOURCE_DIR}/dependencies/portmidi/pm_common" ) if (WIN32) - if (CMAKE_SIZEOF_VOID_P EQUAL 8) - set(PROJECT_ARCH x64) - else () - set(PROJECT_ARCH x86) - endif () + if (CMAKE_SIZEOF_VOID_P EQUAL 8) + set(PROJECT_ARCH x64) + else () + set(PROJECT_ARCH x86) + endif () endif () link_directories( - "${PROJECT_SOURCE_DIR}/dependencies/SDL2/lib/${PROJECT_ARCH}" - "${PROJECT_SOURCE_DIR}/dependencies/portmidi/Release" + "${PROJECT_SOURCE_DIR}/dependencies/SDL2/lib/${PROJECT_ARCH}" + "${PROJECT_SOURCE_DIR}/dependencies/portmidi/Release" ) add_executable( - game - dependencies/minIni/dev/minIni.h - dependencies/minIni/dev/minIni.c - src/packages/game/output/IZ_video.h - src/packages/game/output/IZ_video.c - src/packages/game/IZ_common.h - src/packages/game/IZ_action.h - src/packages/game/IZ_app.h - src/packages/game/IZ_app.c - src/packages/game/main.c - src/packages/game/input/IZ_joystick.c src/packages/game/input/IZ_joystick.h src/packages/game/input/IZ_keyboard.c src/packages/game/input/IZ_keyboard.h src/packages/game/IZ_config.c src/packages/game/IZ_config.h) + game + dependencies/minIni/dev/minIni.h + dependencies/minIni/dev/minIni.c + src/packages/game/output/IZ_video.h + src/packages/game/output/IZ_video.c + src/packages/game/IZ_common.h + src/packages/game/IZ_action.h + src/packages/game/IZ_app.h + src/packages/game/IZ_app.c + src/packages/game/main.c + src/packages/game/input/IZ_joystick.c + src/packages/game/input/IZ_joystick.h + src/packages/game/input/IZ_keyboard.c + src/packages/game/input/IZ_keyboard.h + src/packages/game/IZ_config.c + src/packages/game/IZ_config.h +) target_link_libraries( - game - SDL2main - SDL2 + game + SDL2main + SDL2 ) add_executable( - game-test - dependencies/bdd-for-c/bdd-for-c.h - src/packages/game/output/IZ_video.h - src/packages/game/output/IZ_video.c - src/packages/game/output/IZ_config.test.c - src/packages/test/IZ_mock.h) + game-test-output + dependencies/bdd-for-c/bdd-for-c.h + src/packages/test/IZ_mock.h src/packages/test/IZ_test.h + __mocks__/minIni.mock.h + + src/packages/game/IZ_config.h + + src/packages/game/output/IZ_video.h + src/packages/game/output/IZ_video.c + src/packages/game/output/IZ_video.test.c + __mocks__/SDL_keyboard.mock.h src/packages/game/__mocks__/IZ_config.mock.h) + +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 + __mocks__/minIni.mock.h + + src/packages/game/IZ_config.h + + src/packages/game/input/IZ_keyboard.h + src/packages/game/input/IZ_keyboard.c + src/packages/game/input/IZ_keyboard.test.c + +# src/packages/game/input/IZ_joystick.h +# src/packages/game/input/IZ_joystick.c + __mocks__/SDL_keyboard.mock.h src/packages/game/__mocks__/IZ_config.mock.h) if (WIN32) - add_custom_command(TARGET game POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different # which executes "cmake - E copy_if_different..." - "${PROJECT_SOURCE_DIR}/dependencies/SDL2/lib/${PROJECT_ARCH}/SDL2.dll" # <--this is in-file - $) # <--this is out-file path + add_custom_command(TARGET game POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different # which executes "cmake - E copy_if_different..." + "${PROJECT_SOURCE_DIR}/dependencies/SDL2/lib/${PROJECT_ARCH}/SDL2.dll" # <--this is in-file + $) # <--this is out-file path endif () diff --git a/__mocks__/SDL_keyboard.mock.h b/__mocks__/SDL_keyboard.mock.h new file mode 100644 index 0000000..71ebcb3 --- /dev/null +++ b/__mocks__/SDL_keyboard.mock.h @@ -0,0 +1,14 @@ +#ifndef SDL_KEYBOARD_MOCK_H +#define SDL_KEYBOARD_MOCK_H + +#include "../src/packages/test/IZ_test.h" + +mock(SDL_GetKeyName) const char* SDL_GetKeyName(int key) { + mock_return(SDL_GetKeyName) ""; +} + +mock(SDL_GetKeyFromName) int SDL_GetKeyFromName(const char *name) { + mock_return(SDL_GetKeyFromName) 0; +} + +#endif diff --git a/__mocks__/minIni.mock.h b/__mocks__/minIni.mock.h new file mode 100644 index 0000000..9191a7d --- /dev/null +++ b/__mocks__/minIni.mock.h @@ -0,0 +1,29 @@ +#ifndef MININI_MOCK_H +#define MININI_MOCK_H + +#include "../src/packages/test/IZ_test.h" + +mock(ini_getl) long ini_getl(const TCHAR *Section, const TCHAR *Key, long DefValue, const TCHAR *Filename) { + mock_return(ini_getl) DefValue; +} + +mock(ini_putl) int ini_putl(const TCHAR *Section, const TCHAR *Key, long Value, const TCHAR *Filename) { + mock_return(ini_putl) 1; +} + +mock(ini_gets) int ini_gets( + const TCHAR *Section, + const TCHAR *Key, + const TCHAR *DefValue, + TCHAR *Buffer, + int BufferSize, + const TCHAR *Filename +) { + mock_return(ini_gets) 0; +} + +mock(ini_puts) int ini_puts(const TCHAR *Section, const TCHAR *Key, const TCHAR *Value, const TCHAR *Filename) { + mock_return(ini_puts) 1; +} + +#endif diff --git a/src/packages/game/IZ_config.c b/src/packages/game/IZ_config.c index f1dda1f..e9cf71a 100644 --- a/src/packages/game/IZ_config.c +++ b/src/packages/game/IZ_config.c @@ -1,8 +1,8 @@ #include "IZ_config.h" -void IZ_GetConfigPath(char* config_path) { +void IZ_GetConfigPath(char* config_path, size_t string_size) { //const char* config_path_dir = SDL_GetPrefPath("Modal Studios", APP_NAME); const char* config_path_dir = SDL_GetBasePath(); - memcpy_s(config_path, 128, config_path_dir, 128); - strcat_s(config_path, 128, "config.ini"); + memcpy_s(config_path, string_size, config_path_dir, 128); + strcat_s(config_path, string_size, "config.ini"); } diff --git a/src/packages/game/IZ_config.h b/src/packages/game/IZ_config.h index 10fb5b6..f9fcefe 100644 --- a/src/packages/game/IZ_config.h +++ b/src/packages/game/IZ_config.h @@ -4,6 +4,6 @@ #include #include -void IZ_GetConfigPath(char* config_path); +void IZ_GetConfigPath(char*, size_t); #endif diff --git a/src/packages/game/__mocks__/IZ_config.mock.h b/src/packages/game/__mocks__/IZ_config.mock.h new file mode 100644 index 0000000..af0a879 --- /dev/null +++ b/src/packages/game/__mocks__/IZ_config.mock.h @@ -0,0 +1,12 @@ +#ifndef IZ_CONFIG_MOCK_H +#define IZ_CONFIG_MOCK_H + +#include "../../test/IZ_test.h" + +mock(IZ_GetConfigPath) void IZ_GetConfigPath(char* config_path, size_t string_size) { + const char dummy_path[] = "test-config.ini"; + memcpy_s(config_path, string_size, dummy_path, 128); + mock_return(IZ_GetConfigPath); +} + +#endif diff --git a/src/packages/game/input/IZ_joystick.c b/src/packages/game/input/IZ_joystick.c index 25584f6..5c252b2 100644 --- a/src/packages/game/input/IZ_joystick.c +++ b/src/packages/game/input/IZ_joystick.c @@ -74,7 +74,7 @@ void IZ_HandleJoystickEvents(SDL_Event e, IZ_JoystickState* state, IZ_Action* ac void IZ_LoadJoystickConfig(IZ_JoystickConfig* config, uint8_t p) { char config_path[128]; - IZ_GetConfigPath(config_path); + IZ_GetConfigPath(config_path, 128); char joystick_control_mapping_section_name[] = "Joystick.0.ControlMapping"; joystick_control_mapping_section_name[9] = (char) (48 + p); @@ -89,7 +89,7 @@ void IZ_LoadJoystickConfig(IZ_JoystickConfig* config, uint8_t p) { void IZ_SaveJoystickConfig(IZ_JoystickConfig* config, uint8_t p) { char config_path[128]; - IZ_GetConfigPath(config_path); + IZ_GetConfigPath(config_path, 128); char joystick_control_mapping_section_name[] = "Joystick.0.ControlMapping"; joystick_control_mapping_section_name[9] = (char) (48 + p); diff --git a/src/packages/game/input/IZ_keyboard.c b/src/packages/game/input/IZ_keyboard.c index dd2a983..1d54edd 100644 --- a/src/packages/game/input/IZ_keyboard.c +++ b/src/packages/game/input/IZ_keyboard.c @@ -15,11 +15,10 @@ void IZ_HandleKeyboardEvents(SDL_Event e, IZ_KeyboardState* state, IZ_Action* ac void IZ_SaveKeyboardConfig(IZ_KeyboardConfig* config, uint8_t p) { char config_path[128]; - IZ_GetConfigPath(config_path); + IZ_GetConfigPath(config_path, 128); char keyboard_section_name[] = "Keyboard.0.ControlMapping"; keyboard_section_name[9] = (char) (48 + p); - for (uint8_t i = 0; i < CONTROLS; i += 1) { ini_puts(keyboard_section_name, ACTION_NAMES[i], SDL_GetKeyName(config->control_mapping[i]), config_path); } @@ -27,7 +26,7 @@ void IZ_SaveKeyboardConfig(IZ_KeyboardConfig* config, uint8_t p) { void IZ_LoadKeyboardConfig(IZ_KeyboardConfig* config, uint8_t p) { char config_path[128]; - IZ_GetConfigPath(config_path); + IZ_GetConfigPath(config_path, 128); char buffer[128]; char keyboard_section_name[] = "Keyboard.0.ControlMapping"; diff --git a/src/packages/game/input/IZ_keyboard.test.c b/src/packages/game/input/IZ_keyboard.test.c new file mode 100644 index 0000000..1c24c6b --- /dev/null +++ b/src/packages/game/input/IZ_keyboard.test.c @@ -0,0 +1,101 @@ +#include "../../../__mocks__/SDL_keyboard.mock.h" +#include "../../../__mocks__/minIni.mock.h" +#include "../__mocks__/IZ_config.mock.h" +#include "IZ_keyboard.h" + +spec("input/keyboard") { + describe("HandleKeyboardEvents") { + static SDL_Event e; + static IZ_KeyboardState state; + static IZ_Action action; + + for (uint8_t i = 0; i < CONTROLS; i += 1) { + it("handles %s action activation", ACTION_NAMES[i]) { + e.type = SDL_KEYDOWN; + e.key.keysym.sym = IZ_DEFAULT_KEYBOARD_CONTROLS[0][i]; + state.config.control_mapping[i] = IZ_DEFAULT_KEYBOARD_CONTROLS[0][i]; + action = 0; + + IZ_HandleKeyboardEvents(e, &state, &action); + check( + action == (0x1 << i), + "Action not set." + ); + } + + it("handles %s action deactivation", ACTION_NAMES[i]) { + e.type = SDL_KEYUP; + e.key.keysym.sym = IZ_DEFAULT_KEYBOARD_CONTROLS[0][i]; + state.config.control_mapping[i] = IZ_DEFAULT_KEYBOARD_CONTROLS[0][i]; + action = ~0; + + IZ_HandleKeyboardEvents(e, &state, &action); + check( + !(action & (0x1 << i)), + "Action not unset." + ); + } + } + } + + describe("LoadKeyboardConfig") { + static IZ_KeyboardConfig config; + + after_each() { + mock_reset(IZ_GetConfigPath); + } + + after_each() { + mock_reset(ini_gets); + } + + it("calls load method") { + mock_set_expected_calls(ini_gets, CONTROLS); + + IZ_LoadKeyboardConfig(&config, 0); + + check( + mock_is_called(IZ_GetConfigPath), + "SDL_GetBasePath() not called." + ); + + check( + mock_get_expected_calls(ini_gets) == mock_get_actual_calls(ini_gets), + "Call count mismatch for ini_gets() (expected %u, received %u).", + mock_get_expected_calls(ini_gets), + mock_get_actual_calls(ini_gets) + ); + } + } + + describe("SaveKeyboardConfig") { + static IZ_KeyboardConfig config; + + after_each() { + mock_reset(IZ_GetConfigPath); + } + + after_each() { + mock_reset(ini_puts); + } + + before_each() { + for (uint8_t i = 0; i < CONTROLS; i += 1) { + config.control_mapping[i] = IZ_DEFAULT_KEYBOARD_CONTROLS[0][i]; + } + } + + it("calls save method") { + mock_set_expected_calls(ini_puts, CONTROLS); + + IZ_SaveKeyboardConfig(&config, 0); + + check( + mock_get_expected_calls(ini_puts) == mock_get_actual_calls(ini_puts), + "Call count mismatch for ini_puts() (expected %u, received %u).", + mock_get_expected_calls(ini_puts), + mock_get_actual_calls(ini_puts) + ); + } + } +} diff --git a/src/packages/game/output/IZ_config.test.c b/src/packages/game/output/IZ_config.test.c deleted file mode 100644 index 590b5d7..0000000 --- a/src/packages/game/output/IZ_config.test.c +++ /dev/null @@ -1,126 +0,0 @@ -#include -#include "../../test/IZ_mock.h" -#include "IZ_video.h" - -mock(SDL_GetBasePath) char* SDL_GetBasePath() { - mock_return(SDL_GetBasePath) ""; -} - -mock(SDL_GetKeyName) const char* SDL_GetKeyName (SDL_KeyCode code) { - mock_return(SDL_GetKeyName) ""; -} - -mock(SDL_GetKeyFromName) SDL_KeyCode SDL_GetKeyFromName(const char* name) { - mock_return(SDL_GetKeyFromName) 0; -} - -mock(ini_gets) int ini_gets( - const TCHAR *Section, - const TCHAR *Key, - const TCHAR *DefValue, - char *Buffer, - int BufferSize, - const TCHAR *Filename -) { - mock_return(ini_gets) 0; -} - -mock(ini_getl) long ini_getl( - const TCHAR *Section, - const TCHAR *Key, - long DefValue, - const TCHAR *Filename -) { - mock_return(ini_getl) DefValue; -} - -spec("config") { - describe("LoadConfig") { - static IZ_Config config; - - after_each() { - mock_reset(ini_getl); - } - - after_each() { - mock_reset(ini_gets); - } - - after_each() { - mock_reset(SDL_GetKeyFromName); - } - - after_each() { - mock_reset(SDL_GetKeyName); - } - - after_each() { - mock_reset(SDL_GetBasePath); - } - - it("should load default config values") { - IZ_LoadVideoConfig(&config); - - check( - mock_calls(SDL_GetBasePath) > 0, - "SDL_GetBasePath() not called." - ); - - static const mock_call_count_t expected_calls_ini_getl = - 3 // video params - + 1 // input params - + (12 * PLAYERS); // joystick controls - check( - mock_calls(ini_getl) == expected_calls_ini_getl, - "Call count mismatch for ini_getl() (expected %u, received %u).", - expected_calls_ini_getl, - mock_calls(ini_getl) - ); - - check( - config.video.width == 640, - "Default value for Video.Width is not loaded." - ); - check( - config.video.height == 480, - "Default value for Video.Height is not loaded." - ); - check( - config.video.max_fps == 30, - "Default value for Video.MaxFps is not loaded." - ); - - check( - config.input.axis_threshold == 8000, - "Default value for Input.GamepadAxisThreshold is not loaded." - ); - - static const mock_call_count_t expected_calls_ini_gets = - (16 * PLAYERS); // keyboard controls - check( - mock_calls(ini_gets) == expected_calls_ini_gets, - "Call count mismatch for ini_gets() (expected %u, received %u).", - expected_calls_ini_gets, - mock_calls(ini_gets) - ); - - static const mock_call_count_t expected_calls_SDL_GetKeyFromName = - (16 * PLAYERS); // keyboard controls - check( - mock_calls(SDL_GetKeyFromName) == expected_calls_SDL_GetKeyFromName, - "Call count mismatch for SDL_GetKeyFromName() (expected %u, received %u).", - expected_calls_SDL_GetKeyFromName, - mock_calls(SDL_GetKeyFromName) - ); - - static const mock_call_count_t expected_calls_SDL_GetKeyName = - (16 * PLAYERS); // keyboard controls - check( - mock_calls(SDL_GetKeyName) == expected_calls_SDL_GetKeyName, - "Call count mismatch for SDL_GetKeyName() (expected %u, received %u).", - expected_calls_SDL_GetKeyName, - mock_calls(SDL_GetKeyName) - ); - } - } -} diff --git a/src/packages/game/output/IZ_video.c b/src/packages/game/output/IZ_video.c index cc50c71..6a54230 100644 --- a/src/packages/game/output/IZ_video.c +++ b/src/packages/game/output/IZ_video.c @@ -1,17 +1,25 @@ #include "IZ_video.h" -void IZ_SaveVideoConfig(IZ_VideoConfig* config) { +IZ_ProcedureResult IZ_SaveVideoConfig(IZ_VideoConfig* config) { char config_path[128]; - IZ_GetConfigPath(config_path); + IZ_GetConfigPath(config_path, 128); - ini_putl("Video", "Width", config->width, config_path); - ini_putl("Video", "Height", config->height, config_path); - ini_putl("Video", "MaxFps", config->max_fps, config_path); + if (!ini_putl("Video", "Width", config->width, config_path)) { + return 1; + } + if (!ini_putl("Video", "Height", config->height, config_path)) { + return 1; + } + if (!ini_putl("Video", "MaxFps", config->max_fps, config_path)) { + return 1; + } + + return 0; } void IZ_LoadVideoConfig(IZ_VideoConfig* config) { char config_path[128]; - IZ_GetConfigPath(config_path); + IZ_GetConfigPath(config_path, 128); config->width = ini_getl("Video", "Width", 640l, config_path); config->height = ini_getl("Video", "Height", 480l, config_path); diff --git a/src/packages/game/output/IZ_video.h b/src/packages/game/output/IZ_video.h index 8b8833b..b2fb3fb 100644 --- a/src/packages/game/output/IZ_video.h +++ b/src/packages/game/output/IZ_video.h @@ -3,6 +3,7 @@ #include #include +#include "../IZ_common.h" #include "../IZ_config.h" typedef struct { @@ -11,7 +12,7 @@ typedef struct { uint8_t max_fps; } IZ_VideoConfig; -void IZ_SaveVideoConfig(IZ_VideoConfig* config); +IZ_ProcedureResult IZ_SaveVideoConfig(IZ_VideoConfig* config); void IZ_LoadVideoConfig(IZ_VideoConfig* config); diff --git a/src/packages/game/output/IZ_video.test.c b/src/packages/game/output/IZ_video.test.c new file mode 100644 index 0000000..e67196c --- /dev/null +++ b/src/packages/game/output/IZ_video.test.c @@ -0,0 +1,66 @@ +#include "../../../__mocks__/minIni.mock.h" +#include "../__mocks__/IZ_config.mock.h" +#include "IZ_video.h" + +spec("output/video") { + describe("LoadVideoConfig") { + static IZ_VideoConfig config; + + after_each() { + mock_reset(IZ_GetConfigPath); + } + + after_each() { + mock_reset(ini_getl); + } + + it("calls load method") { + mock_set_expected_calls(ini_getl, 3); + + IZ_LoadVideoConfig(&config); + + check( + mock_is_called(IZ_GetConfigPath), + "SDL_GetBasePath() not called." + ); + + check( + mock_get_expected_calls(ini_getl) == mock_get_actual_calls(ini_getl), + "Call count mismatch for ini_getl() (expected %u, received %u).", + mock_get_expected_calls(ini_getl), + mock_get_actual_calls(ini_getl) + ); + } + } + + describe("SaveVideoConfig") { + static IZ_VideoConfig config; + + after_each() { + mock_reset(IZ_GetConfigPath); + } + + after_each() { + mock_reset(ini_putl); + } + + before_each() { + config.width = 1337; + config.height = 420; + config.max_fps = 69; + } + + it("calls save method") { + mock_set_expected_calls(ini_putl, 3); + + IZ_SaveVideoConfig(&config); + + check( + mock_get_expected_calls(ini_putl) == mock_get_actual_calls(ini_putl), + "Call count mismatch for ini_putl() (expected %u, received %u).", + mock_get_expected_calls(ini_putl), + mock_get_actual_calls(ini_putl) + ); + } + } +} diff --git a/src/packages/test/IZ_mock.h b/src/packages/test/IZ_mock.h index 1ea5731..c8a7bd4 100644 --- a/src/packages/test/IZ_mock.h +++ b/src/packages/test/IZ_mock.h @@ -1,14 +1,20 @@ #ifndef IZ_MOCK_H #define IZ_MOCK_H -#define mock_call_count_t uint8_t +#define mock_call_count_t unsigned char -#define mock(X) static mock_call_count_t calls_##X = 0; +#define mock(X) static mock_call_count_t actual_##X = 0; -#define mock_return(X) calls_##X += 1; return +#define mock_return(X) actual_##X += 1; return -#define mock_reset(X) calls_##X = 0 +#define mock_reset(X) actual_##X = 0 -#define mock_calls(X) ((mock_call_count_t) (calls_##X)) +#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 diff --git a/src/packages/test/IZ_test.h b/src/packages/test/IZ_test.h new file mode 100644 index 0000000..9e938ee --- /dev/null +++ b/src/packages/test/IZ_test.h @@ -0,0 +1,8 @@ +#ifndef IZ_TEST_H +#define IZ_TEST_H + +#include + +#include "IZ_mock.h" + +#endif