#include #include #include #include #include #include #include "game.h" #include "game_aux.h" #include "game_ext.h" #define SIZE_LIMIT_GAME 10 // put usable square at the start of the list and S_BLANK at the first element #define LIST_OF_SQUARE \ { S_BLANK, S_LIGHTBULB, S_MARK, S_BLACK0, S_BLACK1, S_BLACK2, S_BLACK3, S_BLACK4, S_BLACKU, F_LIGHTED, F_ERROR } #define USABLE_SQUARE 2 /* ********** DUMMY ********** */ bool test_dummy(void) { return EXIT_SUCCESS; } /* ******* game_new_ext_empty ******* */ /** * @brief test creating every game between size 0 to SIZE_LIMIT_GAME * * @return EXIT_SUCCESS if every game has been created well */ bool test_game_new_empty_ext(void) { for (uint height = 1; height <= SIZE_LIMIT_GAME; height++) { for (uint width = 1; width <= SIZE_LIMIT_GAME; width++) { for (int wrap = 0; wrap < 2; wrap++) { game g = game_new_empty_ext(height, width, wrap); assert(g); game_delete(g); g = NULL; } } } return EXIT_SUCCESS; } /* ******* game_new_ext ******* */ /** * @brief test creating every game between size 0 to SIZE_LIMIT_GAME + fill it with every square of list * * @return EXIT_SUCCESS if every game has been created well and well filled */ bool test_game_new_ext(void) { square list[] = LIST_OF_SQUARE; for (uint height = 1; height <= SIZE_LIMIT_GAME; height++) { for (uint width = 1; width <= SIZE_LIMIT_GAME; width++) { square tab[height * width]; for (uint index_list = 0; index_list < sizeof(list) / sizeof(list[0]); index_list++) { for (uint index_tab = 0; index_tab < height * width; index_tab++) { tab[index_tab] = list[index_list]; } for (int wrap = 0; wrap < 2; wrap++) { printf("%d\n", index_list); game g = game_new_ext(height, width, tab, wrap); assert(g); for (uint i = 0; i < game_nb_rows(g); i++) { for (uint j = 0; j < game_nb_cols(g); j++) { printf("list :%d, get square :%d\n", list[index_list], game_get_square(g, i, j)); assert(list[index_list] == game_get_square(g, i, j)); } } game_delete(g); g = NULL; } } } } return EXIT_SUCCESS; } /* ******* game_is_over ******* */ /** * @brief test if game_is_over return true with default_solution, false with one flag F_ERROR, false with one S_BLANK and false with game_default * * @return EXIT_SUCCESS if there is no errors */ bool test_game_is_over(void) { game g = game_default_solution(); game_update_flags(g); assert(game_is_over(g)); game_set_square(g, 0, 0, (S_LIGHTBULB | F_LIGHTED | F_ERROR)); assert(!game_is_over(g)); game_update_flags(g); game_set_square(g, 0, 1, S_BLANK); assert(!game_is_over(g)); game_delete(g); g = game_default(); game_update_flags(g); assert(!game_is_over(g)); game_delete(g); return EXIT_SUCCESS; } /* ******* game_restart ******* */ /** * @brief test if game_restart remove every S_LIGHTBULB, S_MARK, and F_LIGHTED but nothing else and if the history has been reset * * @return EXIT_SUCCESS if there is no error */ bool test_game_restart(void) { game game_def = game_default(); game game_def_solution = game_default_solution(); game_set_square(game_def, 1, 5, S_BLACK4); game_set_square(game_def_solution, 1, 5, S_BLACK4); game_set_square(game_def, 3, 2, S_BLACK3); game_set_square(game_def_solution, 3, 2, S_BLACK3); game_play_move(game_def, 0, 1, S_LIGHTBULB); game_play_move(game_def_solution, 0, 1, S_LIGHTBULB); game_play_move(game_def, 2, 0, S_MARK); game_play_move(game_def_solution, 2, 0, S_MARK); game_play_move(game_def, 1, 1, S_LIGHTBULB); game_play_move(game_def_solution, 1, 1, S_LIGHTBULB); game_play_move(game_def, 1, 1, S_MARK); game_play_move(game_def_solution, 1, 1, S_MARK); game_undo(game_def); game_undo(game_def_solution); assert(!game_equal(game_def, game_def_solution)); game_restart(game_def_solution); game_restart(game_def); assert(game_equal(game_def, game_def_solution)); game_redo(game_def); assert(game_equal(game_def, game_def_solution)); game_undo(game_def); assert(game_equal(game_def, game_def_solution)); game_delete(game_def); game_delete(game_def_solution); return EXIT_SUCCESS; } /* ********* game_new ********* */ /** * @brief test if created game with game_new are well filled by the tab * * @return EXIT_SUCCESS if there is no error */ bool test_game_new(void) { square tab[DEFAULT_SIZE * DEFAULT_SIZE]; square list[] = LIST_OF_SQUARE; for (uint index_list = 0; index_list < sizeof(list) / sizeof(list[0]); index_list++) { for (uint index_tab = 0; index_tab < DEFAULT_SIZE * DEFAULT_SIZE; index_tab++) { tab[index_tab] = list[index_list]; } printf("%d\n", index_list); game g = game_new(tab); for (uint i = 0; i < DEFAULT_SIZE; i++) { for (uint j = 0; j < DEFAULT_SIZE; j++) { printf("list :%d, get square :%d\n", list[index_list], game_get_square(g, i, j)); assert(list[index_list] == game_get_square(g, i, j)); } } assert(g); game_delete(g); g = NULL; } return EXIT_SUCCESS; } /* ******** game_print ******** */ /** * @brief test if there is no major problems by printing every square of list * * @return EXIT_SUCCESS if there is no error */ bool test_game_print(void) { for (int height = 1; height <= SIZE_LIMIT_GAME; height++) { for (int width = 1; width <= SIZE_LIMIT_GAME; width++) { square tab[width * height]; square list[] = LIST_OF_SQUARE; game g; for (uint index_list = 0; index_list < sizeof(list) / sizeof(list[0]); index_list++) { for (uint index_tab = 0; index_tab < width * height; index_tab++) { tab[index_tab] = list[index_list]; } printf("%d\n", list[index_list]); g = game_new_ext(height, width, tab, false); assert(g); game_print(g); game_delete(g); } } } return EXIT_SUCCESS; } /* ******* game_get_square ******* */ /** * @brief test if get_square return the same as tab, used to create the game * * @return EXIT_SUCCESS if there is no error */ bool test_game_get_square(void) { for (int height = 1; height <= SIZE_LIMIT_GAME; height++) { for (int width = 1; width <= SIZE_LIMIT_GAME; width++) { square tab[width * height]; square list[] = LIST_OF_SQUARE; for (uint index_list = 0; index_list < sizeof(list) / sizeof(list[0]); index_list++) { for (uint index_tab = 0; index_tab < height * width; index_tab++) { tab[index_tab] = list[index_list]; game g = game_new_ext(height, width, tab, false); printf("[%d, %d] %d %d\n", index_tab / game_nb_cols(g), index_tab % game_nb_cols(g), game_get_square(g, index_tab / game_nb_cols(g), index_tab % game_nb_cols(g)), tab[index_tab]); assert(game_get_square(g, index_tab / game_nb_cols(g), index_tab % game_nb_cols(g)) == tab[index_tab]); game_delete(g); } } } } return EXIT_SUCCESS; } /* ******* game_default ******* */ /** * @brief test if the game_default is the same as tab (tab is game_default) * * @return EXIT_SUCCESS if there is no error */ bool test_game_default(void) { game game_def = game_default(); assert(game_def); // clang-format off square tab[49] = { /*X0 X1 X2 X3 X4 X5 X6*/ /*Y 0*/ S_BLANK, S_BLANK, S_BLACK1, S_BLANK, S_BLANK, S_BLANK, S_BLANK, /*Y 1*/ S_BLANK, S_BLANK, S_BLACK2, S_BLANK, S_BLANK, S_BLANK, S_BLANK, /*Y 2*/ S_BLANK, S_BLANK, S_BLANK, S_BLANK, S_BLANK, S_BLACKU, S_BLACK2, /*Y 3*/ S_BLANK, S_BLANK, S_BLANK, S_BLANK, S_BLANK, S_BLANK, S_BLANK, /*Y 4*/ S_BLACK1, S_BLACKU, S_BLANK, S_BLANK, S_BLANK, S_BLANK, S_BLANK, /*Y 5*/ S_BLANK, S_BLANK, S_BLANK, S_BLANK, S_BLACK2, S_BLANK, S_BLANK, /*Y 6*/ S_BLANK, S_BLANK, S_BLANK, S_BLANK, S_BLACKU, S_BLANK, S_BLANK }; // clang-format on game game_test = game_new(tab); assert(game_equal(game_def, game_test)); game_delete(game_def); game_delete(game_test); return EXIT_SUCCESS; } /* *** game_default_solution *** */ /** * @brief test if game_default_solution is the same as game_default with moves needed to win * * @return EXIT_SUCCESS if there is no error */ bool test_game_default_solution(void) { game game_def_solution = game_default_solution(); game game_def = game_default(); assert(game_def_solution); // solution game_set_square(game_def, 0, 0, S_LIGHTBULB); game_set_square(game_def, 1, 1, S_LIGHTBULB); game_set_square(game_def, 0, 3, S_LIGHTBULB); game_set_square(game_def, 1, 6, S_LIGHTBULB); game_set_square(game_def, 2, 2, S_LIGHTBULB); game_set_square(game_def, 3, 6, S_LIGHTBULB); game_set_square(game_def, 4, 4, S_LIGHTBULB); game_set_square(game_def, 5, 0, S_LIGHTBULB); game_set_square(game_def, 5, 5, S_LIGHTBULB); game_set_square(game_def, 6, 1, S_LIGHTBULB); game_update_flags(game_def); assert(game_equal(game_def_solution, game_def)); game_delete(game_def_solution); game_delete(game_def); return EXIT_SUCCESS; } /* **** game_update_flags **** */ /** * @brief count the number of F_ERROR on the entire game g * * @param g the game to analyze * @return uint the number of F_ERROR on the game g */ uint counterF_ERROR(game g) { uint cpt = 0; for (uint i = 0; i < game_nb_rows(g); i++) { for (uint j = 0; j < game_nb_cols(g); j++) { if (game_has_error(g, i, j)) cpt++; } } return cpt; } /* Tests without the wrapping option test on a 2x2 game without *wrapping* test on a 3x3 game without *wrapping* test on a 5x3 game without *wrapping* test flags *error* on specifics cases On the 2x2, 3x3 and 5x3 tests, we play these move to win and we test if the grid is correct 01 012 012 -- --- --- 0 |2*| 0 |.w0| 0 |*..| 1 |*.| 1 |*1w| 1 |w*1| -- 2 |..*| 2 |*2.| (2x2) --- 3 |..*| (3x3) 4 |.*.| --- (5x3) Tests of the wrapping option test on a 2x2 game with option *wrapping* (cas limite) test on a 3x3 game with option *wrapping* test on a 5x3 game with option *wrapping* test of the flags *error* in the specifics cases of the option *wrapping* On the 2x2, 3x3 and 5x3 tests, we play these move to win and we test if the grid is correct 01 012 012 -- --- --- 0 |4*| 0 |*w2| 0 |...| 1 |*.| 1 |.ww| 1 |w*1| -- 2 |..*| 2 |*2.| (2x2) --- 3 |..*| (3x3) 4 |...| --- (5x3) */ bool test_game_update_flags(void) { square test2x2w[4] = {S_BLACK4, S_BLANK, S_BLANK, S_BLANK}; square test3x3w[9] = {S_BLANK, S_BLACKU, S_BLACK2, S_BLANK, S_BLACKU, S_BLACKU, S_BLANK, S_BLANK, S_BLANK}; square test2x2[4] = {S_BLACK2, S_BLANK, S_BLANK, S_BLANK}; square test3x3[9] = {S_BLANK, S_BLACKU, S_BLACK0, S_BLANK, S_BLACK1, S_BLACKU, S_BLANK, S_BLANK, S_BLANK}; square test5x3[15] = {S_BLANK, S_BLANK, S_BLANK, S_BLACKU, S_BLANK, S_BLACK1, S_BLANK, S_BLACK2, S_BLANK, S_BLANK, S_BLANK, S_BLANK, S_BLANK, S_BLANK, S_BLANK}; // with wrapping game g2x2w = game_new_ext(2, 2, test2x2w, true); game_play_move(g2x2w, 0, 1, S_LIGHTBULB); game_play_move(g2x2w, 1, 0, S_LIGHTBULB); assert(game_is_over(g2x2w)); game g3x3w = game_new_ext(3, 3, test3x3w, true); game_play_move(g3x3w, 0, 0, S_LIGHTBULB); game_play_move(g3x3w, 2, 2, S_LIGHTBULB); assert(game_is_over(g3x3w)); game_delete(g3x3w); game g5x3w = game_new_ext(5, 3, test5x3, true); game_play_move(g5x3w, 1, 1, S_LIGHTBULB); game_play_move(g5x3w, 2, 0, S_LIGHTBULB); game_play_move(g5x3w, 3, 2, S_LIGHTBULB); assert(game_is_over(g5x3w)); game_restart(g2x2w); game_restart(g5x3w); game_play_move(g2x2w, 0, 1, S_MARK); assert(!game_is_over(g2x2w)); assert(game_has_error(g2x2w, 0, 0)); assert(counterF_ERROR(g2x2w) == 1); game_delete(g2x2w); game_play_move(g5x3w, 0, 2, S_LIGHTBULB); game_play_move(g5x3w, 2, 2, S_LIGHTBULB); game_play_move(g5x3w, 1, 1, S_LIGHTBULB); game_play_move(g5x3w, 2, 0, S_LIGHTBULB); assert(!game_is_over(g5x3w)); assert(game_has_error(g5x3w, 0, 2)); assert(game_has_error(g5x3w, 1, 2)); assert(game_has_error(g5x3w, 2, 2)); assert(game_has_error(g5x3w, 2, 0)); assert(game_has_error(g5x3w, 2, 1)); assert(counterF_ERROR(g5x3w) == 5); game_delete(g5x3w); // without wrapping game g2x2 = game_new_ext(2, 2, test2x2, false); game_play_move(g2x2, 0, 1, S_LIGHTBULB); game_play_move(g2x2, 1, 0, S_LIGHTBULB); assert(game_is_over(g2x2)); game g3x3 = game_new_ext(3, 3, test3x3, false); game_play_move(g3x3, 1, 0, S_LIGHTBULB); game_play_move(g3x3, 2, 2, S_LIGHTBULB); assert(game_is_over(g3x3)); game_delete(g3x3); game g5x3 = game_new_ext(5, 3, test5x3, false); game_play_move(g5x3, 0, 0, S_LIGHTBULB); game_play_move(g5x3, 1, 1, S_LIGHTBULB); game_play_move(g5x3, 2, 0, S_LIGHTBULB); game_play_move(g5x3, 3, 2, S_LIGHTBULB); game_play_move(g5x3, 4, 1, S_LIGHTBULB); assert(game_is_over(g5x3)); game_restart(g2x2); game_restart(g5x3); game_play_move(g2x2, 1, 0, S_MARK); assert(!game_is_over(g2x2)); assert(game_has_error(g2x2, 0, 0)); assert(counterF_ERROR(g2x2) == 1); game_delete(g2x2); game_play_move(g5x3, 0, 2, S_LIGHTBULB); game_play_move(g5x3, 1, 1, S_LIGHTBULB); game_play_move(g5x3, 2, 0, S_LIGHTBULB); game_play_move(g5x3, 2, 2, S_LIGHTBULB); game_play_move(g5x3, 3, 2, S_LIGHTBULB); game_play_move(g5x3, 4, 1, S_LIGHTBULB); assert(!game_is_over(g5x3)); assert(game_has_error(g5x3, 1, 2)); assert(game_has_error(g5x3, 2, 1)); assert(game_has_error(g5x3, 2, 2)); assert(game_has_error(g5x3, 3, 2)); assert(counterF_ERROR(g5x3) == 4); game_delete(g5x3); return EXIT_SUCCESS; } /* ****** game_play_move ****** */ /** * @brief test if play move set square + update the flags + update history * * @return EXIT_SUCCESS if there is no error */ bool test_game_play_move(void) { game game_play = game_new_empty(); game game_set = game_new_empty(); square list[] = LIST_OF_SQUARE; for (uint index_list = 0; index_list <= USABLE_SQUARE; index_list++) { game_play_move(game_play, 0, 0, list[index_list]); game_set_square(game_set, 0, 0, list[index_list]); game_update_flags(game_set); assert(game_equal(game_play, game_set)); } // undo / redo game_undo(game_play); game_set_square(game_set, 0, 0, list[USABLE_SQUARE - 1]); // take the before last usable element of list game_update_flags(game_set); assert(game_equal(game_play, game_set)); // delete game_delete(game_play); game_delete(game_set); return EXIT_SUCCESS; } /* ***** game_check_move ***** */ /** * @brief test if we can place usable square (here : S_BLANK, S_LIGHTBULB, S_MARK) and nothing else + if we can place something over the limits * * @return EXIT_SUCCESS if there is no error */ bool test_game_check_move(void) { game g = game_new_empty(); // put usable square at the start of the list square list[] = LIST_OF_SQUARE; // test limits for (uint i = 0; i < SIZE_LIMIT_GAME + 10; i++) { for (uint j = 0; j < SIZE_LIMIT_GAME + 10; j++) { for (uint index_list = 0; index_list < sizeof(list) / sizeof(list[0]); index_list++) { if (i >= game_nb_rows(g) || j >= game_nb_cols(g) || index_list > USABLE_SQUARE) assert(!game_check_move(g, i, j, list[index_list])); else assert(game_check_move(g, i, j, list[index_list])); } } } // test if we can place something on a wall for (uint i = 0; i < S_BLACKU - S_BLACK0; i++) { game_set_square(g, 0, 0, S_BLACK + i); for (uint index_list = 0; index_list <= USABLE_SQUARE; index_list++) { assert(!game_check_move(g, 0, 0, list[index_list])); } } game_delete(g); return EXIT_SUCCESS; } /* ********** USAGE ********** */ int usage(int argc, char* argv[]) { fprintf(stderr, "Usage: %s [<...>]\n", argv[0]); exit(EXIT_FAILURE); } /* ********** MAIN ********** */ int main(int argc, char* argv[]) { if (argc == 1) { usage(argc, argv); } fprintf(stderr, "=> Start test \"%s\"\n", argv[1]); bool ok = true; if (strcmp("dummy", argv[1]) == 0) ok = test_dummy(); else if (strcmp("game_print", argv[1]) == 0) ok = test_game_print(); else if (strcmp("game_default", argv[1]) == 0) ok = test_game_default(); else if (strcmp("game_default_solution", argv[1]) == 0) ok = test_game_default_solution(); else if (strcmp("game_new", argv[1]) == 0) ok = test_game_new(); else if (strcmp("game_restart", argv[1]) == 0) ok = test_game_restart(); else if (strcmp("game_get_square", argv[1]) == 0) ok = test_game_get_square(); else if (strcmp("game_is_over", argv[1]) == 0) ok = test_game_is_over(); else if (strcmp("game_update_flags", argv[1]) == 0) ok = test_game_update_flags(); else if (strcmp("game_play_move", argv[1]) == 0) ok = test_game_play_move(); else if (strcmp("game_check_move", argv[1]) == 0) ok = test_game_check_move(); else if (strcmp("game_new_empty_ext", argv[1]) == 0) ok = test_game_new_empty_ext(); else if (strcmp("game_new_ext", argv[1]) == 0) ok = test_game_new_ext(); else { fprintf(stderr, "Error: test \"%s\" not found!\n", argv[1]); exit(EXIT_FAILURE); } // print test result if (!ok) { fprintf(stderr, "Test \"%s\" finished: SUCCESS\n", argv[1]); return EXIT_SUCCESS; } else { fprintf(stderr, "Test \"%s\" finished: FAILURE\n", argv[1]); return EXIT_FAILURE; } }