/* ---------------------------------------------------------------------------- * -- _____ ______ _____ - * -- |_ _| | ____|/ ____| - * -- | | _ __ | |__ | (___ Institute of Embedded Systems - * -- | | | '_ \| __| \___ \ Zuercher Hochschule Winterthur - * -- _| |_| | | | |____ ____) | (University of Applied Sciences) - * -- |_____|_| |_|______|_____/ 8401 Winterthur, Switzerland - * ---------------------------------------------------------------------------- */ /** * @file * @brief Test suite for the given package. */ #include #include #include #include #include #include #include "test_utils.h" #include "model.h" #ifndef TARGET // must be given by the make file --> see test target #error missing TARGET define #endif /// @brief alias for EXIT_SUCCESS #define OK EXIT_SUCCESS /// @brief alias for EXIT_FAILURE #define FAIL EXIT_FAILURE /// @brief The name of the STDOUT text file. #define OUTFILE "stdout.txt" /// @brief The name of the STDERR text file. #define ERRFILE "stderr.txt" #define TRACE_INDENT "\n " ///< allow for better stdout formatting in case of error // setup & cleanup static int setup(void) { remove_file_if_exists(OUTFILE); remove_file_if_exists(ERRFILE); return 0; // success } static int teardown(void) { // Do nothing. // Especially: do not remove result files - they are removed in int setup(void) *before* running a test. return 0; // success } // test utils static void init_model(model_t *instance, int act) { if (act) printf(TRACE_INDENT "init_model:... "); model_init(instance); for(size_t row = 0; row < MODEL_SIZE; row++) { for(size_t col = 0; col < MODEL_SIZE; col++) { if (act) printf("%zd/%zd ", row, col); CU_ASSERT_EQUAL_FATAL(instance->board[row][col], model_state_none); } } if (act) printf(TRACE_INDENT); } static void print_board(model_state_t board[MODEL_SIZE][MODEL_SIZE]) { for(size_t row = 0; row < MODEL_SIZE; row++) { printf("{ "); for(size_t col = 0; col < MODEL_SIZE; col++) { printf("%d ", board[row][col]); } printf("} "); } } // tests static void test_model_init(void) { // check void model_init(model_t *instance); // arrange model_t model; // act & assert init_model(&model, 1); } static void test_model_get_state(void) { // check: model_state_t model_get_state(model_t *instance, model_pos_t pos); { // arrange model_t model; init_model(&model, 0); // act & assert printf(TRACE_INDENT "initial state:... "); print_board(model.board); for(size_t row = 0; row < MODEL_SIZE; row++) { for(size_t col = 0; col < MODEL_SIZE; col++) { printf("%zd/%zd ", row, col); CU_ASSERT_EQUAL_FATAL(model_get_state(&model, model_pos(row, col)), model_state_none); } } } { // arrange static const model_state_t board[MODEL_SIZE][MODEL_SIZE] = { { model_state_none, model_state_a, model_state_b }, { model_state_a, model_state_b, model_state_none }, { model_state_b, model_state_none, model_state_a }, }; model_t model; init_model(&model, 0); memcpy(model.board, board, sizeof(board)); // act & assert printf(TRACE_INDENT "modified state:... "); print_board(model.board); for(size_t row = 0; row < MODEL_SIZE; row++) { for(size_t col = 0; col < MODEL_SIZE; col++) { printf("%zd/%zd ", row, col); CU_ASSERT_EQUAL_FATAL(model_get_state(&model, model_pos(row, col)), board[row][col]); } } } printf(TRACE_INDENT); } static void test_model_get_winner(void) { // check: model_state_t model_get_winner(model_t *instance); { // arrange model_t model; init_model(&model, 0); // act & assert printf(TRACE_INDENT "initial no winner:... "); print_board(model.board); CU_ASSERT_EQUAL_FATAL(model_get_winner(&model), model_state_none); } { // arrange static const model_state_t board[MODEL_SIZE][MODEL_SIZE] = { { model_state_none, model_state_a, model_state_b }, { model_state_a, model_state_b, model_state_none }, { model_state_b, model_state_none, model_state_a }, }; model_t model; init_model(&model, 0); memcpy(model.board, board, sizeof(board)); // act & assert printf(TRACE_INDENT "winner:... "); print_board(model.board); CU_ASSERT_EQUAL_FATAL(model_get_winner(&model), model_state_b); } printf(TRACE_INDENT); } static void test_model_can_move(void) { // check: int model_can_move(model_t *instance); { // arrange model_t model; init_model(&model, 0); // act & assert printf(TRACE_INDENT "initial can move:... "); print_board(model.board); CU_ASSERT_EQUAL_FATAL(model_can_move(&model), 1); } { // arrange static const model_state_t board[MODEL_SIZE][MODEL_SIZE] = { { model_state_none, model_state_a, model_state_a }, { model_state_a, model_state_b, model_state_none }, { model_state_b, model_state_none, model_state_b }, }; model_t model; init_model(&model, 0); memcpy(model.board, board, sizeof(board)); // act & assert printf(TRACE_INDENT "can move while not yet done nor win:... "); print_board(model.board); CU_ASSERT_EQUAL_FATAL(model_can_move(&model), 1); } { // arrange static const model_state_t board[MODEL_SIZE][MODEL_SIZE] = { { model_state_none, model_state_a, model_state_b }, { model_state_a, model_state_b, model_state_none }, { model_state_b, model_state_none, model_state_a }, }; model_t model; init_model(&model, 0); memcpy(model.board, board, sizeof(board)); // act & assert printf(TRACE_INDENT "cannot move after win:... "); print_board(model.board); CU_ASSERT_EQUAL_FATAL(model_can_move(&model), 0); } { // arrange static const model_state_t board[MODEL_SIZE][MODEL_SIZE] = { { model_state_b, model_state_a, model_state_a }, { model_state_a, model_state_b, model_state_b }, { model_state_b, model_state_a, model_state_a }, }; model_t model; init_model(&model, 0); memcpy(model.board, board, sizeof(board)); // act & assert printf(TRACE_INDENT "cannot move when all done:... "); print_board(model.board); CU_ASSERT_EQUAL_FATAL(model_can_move(&model), 0); } printf(TRACE_INDENT); } static void test_model_move(void) { // check: int model_move(model_t *instance, model_pos_t pos, model_state_t state); { // arrange model_t model; init_model(&model, 0); // act & assert printf(TRACE_INDENT "initial move:... "); print_board(model.board); model_pos_t pos_a = model_pos(0, 0); printf("%zd/%zd ", pos_a.row, pos_a.col); CU_ASSERT_EQUAL_FATAL(model_move(&model, pos_a, model_state_a), 1); CU_ASSERT_EQUAL_FATAL(model_move(&model, pos_a, model_state_a), 0); CU_ASSERT_EQUAL_FATAL(model_move(&model, pos_a, model_state_b), 0); model_pos_t pos_b = model_pos(2, 2); printf("%zd/%zd ", pos_b.row, pos_b.col); CU_ASSERT_EQUAL_FATAL(model_move(&model, pos_b, model_state_b), 1); CU_ASSERT_EQUAL_FATAL(model_move(&model, pos_b, model_state_b), 0); CU_ASSERT_EQUAL_FATAL(model_move(&model, pos_b, model_state_a), 0); } { // arrange static const model_state_t board[MODEL_SIZE][MODEL_SIZE] = { { model_state_none, model_state_a, model_state_a }, { model_state_a, model_state_b, model_state_none }, { model_state_b, model_state_none, model_state_b }, }; model_t model; init_model(&model, 0); memcpy(model.board, board, sizeof(board)); // act & assert printf(TRACE_INDENT "can move while not yet done nor win:... "); print_board(model.board); model_pos_t pos = model_pos(2, 1); CU_ASSERT_EQUAL_FATAL(model_move(&model, pos, model_state_a), 1); CU_ASSERT_EQUAL_FATAL(model_move(&model, pos, model_state_a), 0); CU_ASSERT_EQUAL_FATAL(model_move(&model, pos, model_state_b), 0); } { // arrange static const model_state_t board[MODEL_SIZE][MODEL_SIZE] = { { model_state_none, model_state_a, model_state_b }, { model_state_a, model_state_b, model_state_none }, { model_state_b, model_state_none, model_state_a }, }; model_t model; init_model(&model, 0); memcpy(model.board, board, sizeof(board)); // act & assert printf(TRACE_INDENT "cannot move after win:... "); print_board(model.board); model_pos_t pos = model_pos(2, 1); CU_ASSERT_EQUAL_FATAL(model_move(&model, pos, model_state_a), 0); CU_ASSERT_EQUAL_FATAL(model_move(&model, pos, model_state_b), 0); } { // arrange static const model_state_t board[MODEL_SIZE][MODEL_SIZE] = { { model_state_b, model_state_a, model_state_a }, { model_state_a, model_state_b, model_state_b }, { model_state_b, model_state_a, model_state_a }, }; model_t model; init_model(&model, 0); memcpy(model.board, board, sizeof(board)); // act & assert printf(TRACE_INDENT "cannot move when all done:... "); print_board(model.board); for(size_t row = 0; row < MODEL_SIZE; row++) { for(size_t col = 0; col < MODEL_SIZE; col++) { model_pos_t pos = model_pos(row, col); printf("%zd/%zd ", row, col); CU_ASSERT_EQUAL_FATAL(model_move(&model, pos, model_state_a), 0); CU_ASSERT_EQUAL_FATAL(model_move(&model, pos, model_state_b), 0); } } CU_ASSERT_EQUAL_FATAL(model_can_move(&model), 0); } printf(TRACE_INDENT); } static void test_model_get_win_line(void) { // check: model_line_t model_get_win_line(model_t *instance); { // arrange model_t model; init_model(&model, 0); // act & assert printf(TRACE_INDENT "initial no winner:... "); print_board(model.board); model_line_t no_win = model_get_win_line(&model); CU_ASSERT_EQUAL_FATAL(no_win.dir, model_dir_none); } { // arrange static const model_state_t board[MODEL_SIZE][MODEL_SIZE] = { { model_state_none, model_state_a, model_state_a }, { model_state_a, model_state_b, model_state_none }, { model_state_b, model_state_none, model_state_b }, }; model_t model; init_model(&model, 0); memcpy(model.board, board, sizeof(board)); // act & assert printf(TRACE_INDENT "no winner while not yet done nor win:... "); print_board(model.board); model_line_t no_win = model_get_win_line(&model); CU_ASSERT_EQUAL_FATAL(no_win.dir, model_dir_none); } { // arrange static const model_state_t board[MODEL_SIZE][MODEL_SIZE] = { { model_state_b, model_state_a, model_state_a }, { model_state_a, model_state_b, model_state_b }, { model_state_b, model_state_a, model_state_a }, }; model_t model; init_model(&model, 0); memcpy(model.board, board, sizeof(board)); // act & assert printf(TRACE_INDENT "no winner when all done:... "); print_board(model.board); model_line_t no_win = model_get_win_line(&model); CU_ASSERT_EQUAL_FATAL(no_win.dir, model_dir_none); } { for(size_t row = 0; row < MODEL_SIZE; row++) { // arrange model_t model; init_model(&model, 0); for(size_t col = 0; col < MODEL_SIZE; col++) { CU_ASSERT_EQUAL_FATAL(model_move(&model, model_pos(row, col), model_state_a), 1); } // act & assert printf(TRACE_INDENT "row winner:... "); print_board(model.board); model_line_t win = model_get_win_line(&model); CU_ASSERT_EQUAL_FATAL(win.dir, model_dir_h); CU_ASSERT_EQUAL_FATAL(win.start.row, row); CU_ASSERT_EQUAL_FATAL(win.start.col, 0); } } { for(size_t col = 0; col < MODEL_SIZE; col++) { // arrange model_t model; init_model(&model, 0); for(size_t row = 0; row < MODEL_SIZE; row++) { CU_ASSERT_EQUAL_FATAL(model_move(&model, model_pos(row, col), model_state_a), 1); } // act & assert printf(TRACE_INDENT "column winner:... "); print_board(model.board); model_line_t win = model_get_win_line(&model); CU_ASSERT_EQUAL_FATAL(win.dir, model_dir_v); CU_ASSERT_EQUAL_FATAL(win.start.row, 0); CU_ASSERT_EQUAL_FATAL(win.start.col, col); } } { printf(TRACE_INDENT "diagonal left-right winner:... "); // arrange model_t model; init_model(&model, 0); for(size_t i = 0; i < MODEL_SIZE; i++) { CU_ASSERT_EQUAL_FATAL(model_move(&model, model_pos(i, i), model_state_a), 1); } // act & assert print_board(model.board); model_line_t win = model_get_win_line(&model); CU_ASSERT_EQUAL_FATAL(win.dir, model_dir_d); CU_ASSERT_EQUAL_FATAL(win.start.row, 0); CU_ASSERT_EQUAL_FATAL(win.start.col, 0); } { printf(TRACE_INDENT "diagonal right-left winner:... "); // arrange model_t model; init_model(&model, 0); for(size_t i = 0; i < MODEL_SIZE; i++) { CU_ASSERT_EQUAL_FATAL(model_move(&model, model_pos(MODEL_SIZE - 1 - i, i), model_state_a), 1); } // act & assert print_board(model.board); model_line_t win = model_get_win_line(&model); CU_ASSERT_EQUAL_FATAL(win.dir, model_dir_d); CU_ASSERT_EQUAL_FATAL(win.start.row, 0); CU_ASSERT_EQUAL_FATAL(win.start.col, MODEL_SIZE - 1); } printf(TRACE_INDENT); } /** * @brief Registers and runs the tests. * @returns success (0) or one of the CU_ErrorCode (>0) */ int main(void) { // setup, run, teardown TestMainBasic("lab test", setup, teardown , test_model_init , test_model_get_state , test_model_get_winner , test_model_can_move , test_model_move , test_model_get_win_line ); }