#include "../../../__mocks__/SDL_keyboard.mock.h" #include "../../../__mocks__/SDL_joystick.mock.h" #include "../../../__mocks__/minIni.mock.h" #include "../__mocks__/IZ_config.mock.h" #include "IZ_keyboard.h" #include "IZ_joystick.h" short int GenerateAxisValueWithinThreshold(short int threshold) { return rand() % threshold; } short int GenerateAxisValueOutsideThreshold(short int threshold) { return threshold + (rand() % (RAND_MAX - threshold - 1)) + 1; } spec("input") { describe("joystick") { describe("HandleJoystickEvents") { static SDL_Event e; static IZ_JoystickState state; static IZ_Action action; describe("on axis motion events") { before_each() { e.type = SDL_JOYAXISMOTION; state.config.axis_threshold = 8000; } describe("on primary horizontal direction") { before_each() { e.jaxis.axis = IZ_JOYAXIS_DIRECTION_HORIZONTAL1; } it("handles positive motion") { e.jaxis.value = GenerateAxisValueOutsideThreshold(state.config.axis_threshold); action = 0; printf("(axis value: %d) ", e.jaxis.value); IZ_HandleJoystickEvents(e, &state, &action); check( action == (0x1 << IZ_ACTION_INDEX_RIGHT), "Action not set." ); } it("handles negative motion") { e.jaxis.value = -GenerateAxisValueOutsideThreshold(state.config.axis_threshold); action = 0; printf("(axis value: %d) ", e.jaxis.value); IZ_HandleJoystickEvents(e, &state, &action); check( action == (0x1 << IZ_ACTION_INDEX_LEFT), "Action not set." ); } it("handles neutral motion") { e.jaxis.value = GenerateAxisValueWithinThreshold(state.config.axis_threshold); action = 0; printf("(axis value: %d) ", e.jaxis.value); IZ_HandleJoystickEvents(e, &state, &action); check( action == 0, "Action not set." ); } } describe("on secondary horizontal direction") { before_each() { e.jaxis.axis = IZ_JOYAXIS_DIRECTION_HORIZONTAL2; } it("handles positive motion") { e.jaxis.value = GenerateAxisValueOutsideThreshold(state.config.axis_threshold); action = 0; printf("(axis value: %d) ", e.jaxis.value); IZ_HandleJoystickEvents(e, &state, &action); check( action == (0x1 << IZ_ACTION_INDEX_RIGHT), "Action not set." ); } it("handles negative motion") { e.jaxis.value = -GenerateAxisValueOutsideThreshold(state.config.axis_threshold); action = 0; printf("(axis value: %d) ", e.jaxis.value); IZ_HandleJoystickEvents(e, &state, &action); check( action == (0x1 << IZ_ACTION_INDEX_LEFT), "Action not set." ); } it("handles neutral motion") { e.jaxis.value = GenerateAxisValueWithinThreshold(state.config.axis_threshold);; action = 0; printf("(axis value: %d) ", e.jaxis.value); IZ_HandleJoystickEvents(e, &state, &action); check( action == 0, "Action not set." ); } } describe("on primary vertical direction") { before_each() { e.jaxis.axis = IZ_JOYAXIS_DIRECTION_VERTICAL1; } it("handles positive motion") { e.jaxis.value = GenerateAxisValueOutsideThreshold(state.config.axis_threshold); action = 0; printf("(axis value: %d) ", e.jaxis.value); IZ_HandleJoystickEvents(e, &state, &action); check( action == (0x1 << IZ_ACTION_INDEX_DOWN), "Action not set." ); } it("handles negative motion") { e.jaxis.value = -GenerateAxisValueOutsideThreshold(state.config.axis_threshold); action = 0; printf("(axis value: %d) ", e.jaxis.value); IZ_HandleJoystickEvents(e, &state, &action); check( action == (0x1 << IZ_ACTION_INDEX_UP), "Action not set." ); } it("handles neutral motion") { e.jaxis.value = GenerateAxisValueWithinThreshold(state.config.axis_threshold);; action = 0; printf("(axis value: %d) ", e.jaxis.value); IZ_HandleJoystickEvents(e, &state, &action); check( action == 0, "Action not set." ); } } describe("on secondary vertical direction") { before_each() { e.jaxis.axis = IZ_JOYAXIS_DIRECTION_VERTICAL2; } it("handles positive motion") { e.jaxis.value = GenerateAxisValueOutsideThreshold(state.config.axis_threshold); action = 0; printf("(axis value: %d) ", e.jaxis.value); IZ_HandleJoystickEvents(e, &state, &action); check( action == (0x1 << IZ_ACTION_INDEX_DOWN), "Action not set." ); } it("handles negative motion") { e.jaxis.value = -GenerateAxisValueOutsideThreshold(state.config.axis_threshold); action = 0; printf("(axis value: %d) ", e.jaxis.value); IZ_HandleJoystickEvents(e, &state, &action); check( action == (0x1 << IZ_ACTION_INDEX_UP), "Action not set." ); } it("handles neutral motion") { e.jaxis.value = GenerateAxisValueWithinThreshold(state.config.axis_threshold);; action = 0; printf("(axis value: %d) ", e.jaxis.value); IZ_HandleJoystickEvents(e, &state, &action); check( action == 0, "Action not set." ); } } } describe("on hat motion events") { before_each() { e.type = SDL_JOYHATMOTION; } for (uint8_t i = 0; i < 4; i += 1) { it("handles motion for %s action", ACTION_NAMES[i]) { e.jhat.value = (0x1u << i); action = 0; IZ_HandleJoystickEvents(e, &state, &action); check( action == (0x1u << i), "Action not set." ); } it("handles motion for %s deactivation", ACTION_NAMES[i]) { e.jhat.value = 0; action = ~0; IZ_HandleJoystickEvents(e, &state, &action); check( !(action & (0x1 << i)), "Action not unset." ); } } } describe("on button events") { for (uint8_t i = 4; i < CONTROLS; i += 1) { it("handles %s action activation", ACTION_NAMES[i]) { e.type = SDL_JOYBUTTONDOWN; e.jbutton.button = IZ_DEFAULT_JOYSTICK_CONTROLS[0][i]; state.config.control_mapping[i] = IZ_DEFAULT_JOYSTICK_CONTROLS[0][i]; action = 0; IZ_HandleJoystickEvents(e, &state, &action); check( action == (0x1u << i), "Action not set." ); } it("handles %s action deactivation", ACTION_NAMES[i]) { e.type = SDL_JOYBUTTONUP; e.jbutton.button = IZ_DEFAULT_JOYSTICK_CONTROLS[0][i]; state.config.control_mapping[i] = IZ_DEFAULT_JOYSTICK_CONTROLS[0][i]; action = ~0; IZ_HandleJoystickEvents(e, &state, &action); check( !(action & (0x1 << i)), "Action not unset." ); } } } } describe("LoadJoystickConfig") { static IZ_JoystickConfig config; after_each() { mock_reset(IZ_GetConfigPath); } after_each() { mock_reset(ini_getl); } it("calls load method") { mock_set_expected_calls(ini_getl, CONTROLS - 4 + 1); IZ_LoadJoystickConfig(&config, 0); 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("SaveJoystickConfig") { static IZ_JoystickConfig config; after_each() { mock_reset(IZ_GetConfigPath); } after_each() { mock_reset(ini_putl); } before_each() { for (uint8_t i = 0; i < CONTROLS; i += 1) { config.control_mapping[i] = IZ_DEFAULT_JOYSTICK_CONTROLS[0][i]; } } it("calls save method") { mock_set_expected_calls(ini_putl, CONTROLS - 4 + 1); IZ_SaveJoystickConfig(&config, 0); 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) ); } } } describe("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) ); } } } }