#include #include #include #include "state_presenter.h" static void set_board(board_t *board) { memset(board, 0, sizeof(*board)); board->cells[0] = CELL_SHIP; board->cells[1] = CELL_MISS; board->cells[2] = CELL_HIT; board->cells[99] = CELL_SHIP; } static const char *board_start(const char *json, uint8_t board) { const char *first = strstr(json, "\"boards\":[\""); assert(first != NULL); first += strlen("\"boards\":[\""); return board == 0U ? first : first + kBoardCellCount + 3U; } static void assert_hidden(const char *json, uint8_t board) { const char *cells = board_start(json, board); for (uint8_t index = 0; index < kBoardCellCount; ++index) assert(cells[index] != '1'); } static void test_role_views_and_golden_schema(void) { game_state_t state = {0}; state.game_id = 42U; state.version = 9U; state.phase = PHASE_IN_PROGRESS; state.mode = MODE_HUMAN; state.current_player = 1U; set_board(&state.boards[0]); set_board(&state.boards[1]); char output[kStateMessageCapacity] = {0}; size_t written = 0; assert(state_presenter_write(&state, ROLE_PLAYER_1, output, sizeof(output), &written)); assert(written == strlen(output)); assert(strstr(output, "{\"type\":\"state\",\"version\":9,\"gameId\":42,\"phase\":\"in_progress\",\"mode\":\"human\",\"viewer\":\"player1\",\"turn\":\"player2\",\"boards\":[\"") == output); assert(board_start(output, 0)[0] == '1' && board_start(output, 0)[1] == '2' && board_start(output, 0)[2] == '3'); assert_hidden(output, 1); assert(state_presenter_write(&state, ROLE_PLAYER_2, output, sizeof(output), &written)); assert_hidden(output, 0); assert(board_start(output, 1)[0] == '1'); assert(state_presenter_write(&state, ROLE_SPECTATOR, output, sizeof(output), &written)); assert_hidden(output, 0); assert_hidden(output, 1); assert(board_start(output, 0)[1] == '2' && board_start(output, 1)[2] == '3'); } static void test_finished_and_failure_are_safe(void) { game_state_t state = {0}; state.game_id = UINT32_MAX; state.version = UINT32_MAX; state.phase = PHASE_FINISHED; state.mode = MODE_BOT; state.current_player = 0U; set_board(&state.boards[0]); set_board(&state.boards[1]); char output[kStateMessageCapacity] = {0}; size_t written = 0; assert(state_presenter_write(&state, ROLE_SPECTATOR, output, sizeof(output), &written)); assert(written < sizeof(output)); assert(board_start(output, 0)[0] == '1' && board_start(output, 1)[99] == '1'); game_lifecycle_t lifecycle = {0}; lifecycle.game.state = state; lifecycle.game.state.phase = PHASE_REMATCH_WAIT; lifecycle.game.state.mode = MODE_HUMAN; lifecycle.cumulative[0].wins = UINT16_MAX; lifecycle.cumulative[1].wins = UINT16_MAX; assert(state_presenter_write_lifecycle(&lifecycle, ROLE_SPECTATOR, output, sizeof(output), &written)); assert(written == 371U); char unchanged[16]; memset(unchanged, 'X', sizeof(unchanged)); size_t failure_written = 99U; assert(!state_presenter_write(&state, ROLE_PLAYER_1, unchanged, sizeof(unchanged), &failure_written)); assert(failure_written == 0U); for (size_t index = 0; index < sizeof(unchanged); ++index) assert(unchanged[index] == 'X'); } int main(void) { test_role_views_and_golden_schema(); test_finished_and_failure_are_safe(); puts("state presenter tests passed"); return 0; }