From 06b7f66f20ac62177d1d89693ef10aea5b4b4b6d Mon Sep 17 00:00:00 2001 From: Barry Kane Date: Sun, 14 Apr 2024 23:17:29 +0100 Subject: [PATCH] Added testing harness and test for lists * Makefile.am (SilverMUDClient_SOURCES): Added testing into configuration. * source/tests/lists-test.c: Initial list test. * source/tests/tests.h (SILVERMUD_TESTS): Simple test harness. --- Makefile.am | 7 ++ source/tests/lists-test.c | 172 ++++++++++++++++++++++++++++++++++++++ source/tests/tests.h | 43 ++++++++++ 3 files changed, 222 insertions(+) create mode 100644 source/tests/lists-test.c create mode 100644 source/tests/tests.h diff --git a/Makefile.am b/Makefile.am index f239522..d93e064 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,3 +18,10 @@ SilverMUDClient_SOURCES = \ source/client/client-drawing.c \ source/client/receiving-thread.c \ source/client/main.c + +check_PROGRAMS = lists_test +lists_test_SOURCES = \ + source/tests/lists-test.c \ + source/server/lists.c + +TESTS = $(check_PROGRAMS) diff --git a/source/tests/lists-test.c b/source/tests/lists-test.c new file mode 100644 index 0000000..81a5daf --- /dev/null +++ b/source/tests/lists-test.c @@ -0,0 +1,172 @@ +// ========================================= +// | SilverMUD Tests - lists-test.c | +// | Copyright (C) 2023, Barra Ó Catháin | +// | See end of file for copyright notice. | +// ========================================= +#include +#include +#include +#include "tests.h" +#include "../server/lists.h" + +SETUP_TESTS; + +bool compareChar (void * a, void * b) +{ + return *(char *)a == *(char *)b; +} + +void printListHeader(struct List * list) +{ + printf("Items in list: %zu\nType: %d\nHead: %p\nTail: %p\n\n", + list->itemCount, list->type, list->head, list->tail); +} + +void printNode(struct Node * node) +{ + printf("%p\nNext: %p\nPrevious: %p\nData: %c\n\n", + node, node->next, node->previous, *(char *)(node->data)); +} + +int main (int argc, char ** argv) +{ + char testDataA = 'A', testDataB = 'B', testDataC = 'C'; + + // Test 1: + struct List * testList = createList(PLAYER); + TEST("Creating list", + (testList->head == NULL && + testList->tail == NULL && + testList->itemCount == 0)); + + // Test 2: + appendToList(PLAYER, testList, &testDataA); + TEST("Adding a single item to the list", + (testList->itemCount == 1 && + testList->head != NULL && + testList->tail != NULL && + testList->tail == testList->head && + *(char *)(testList->head->data) == 'A')); + + // Test 3: + deleteNodeFromList(0, testList); + TEST("Deleting a single item from the list", + (testList->head == NULL && + testList->tail == NULL && + testList->itemCount == 0)); + + // Test 4: + appendToList(PLAYER, testList, &testDataA); + appendToList(PLAYER, testList, &testDataB); + TEST("Adding two items to the list", + (testList->itemCount == 2 && + testList->head != NULL && + testList->tail != NULL && + *(char *)testList->head->data == 'A' && + *(char *)testList->tail->data == 'B' && + testList->tail != testList->head && + testList->head->next == testList->tail && + testList->tail->previous == testList->head)); + + // Test 5: + deleteNodeFromList(1, testList); + TEST("Deleting tail from the list", + (testList->itemCount == 1 && + testList->head != NULL && + testList->tail != NULL && + testList->tail == testList->head && + *(char *)(testList->head->data) == 'A')); + + // Test 6: + appendToList(PLAYER, testList, &testDataB); + deleteNodeFromList(0, testList); + TEST("Deleting head from the list", + (testList->itemCount == 1 && + testList->head != NULL && + testList->tail != NULL && + testList->tail == testList->head && + *(char *)(testList->head->data) == 'B')); + + // Test 7: + deleteNodeFromList(0, testList); + appendToList(PLAYER, testList, &testDataA); + appendToList(PLAYER, testList, &testDataB); + appendToList(PLAYER, testList, &testDataC); + TEST("Adding three items to the list", + (testList->itemCount == 3 && + testList->head != NULL && + testList->tail != NULL && + *(char *)testList->head->data == 'A' && + *(char *)testList->tail->data == 'C' && + *(char *)testList->head->next->data == 'B' && + *(char *)testList->tail->previous->data == 'B' && + testList->tail != testList->head && + testList->tail->previous == testList->head->next)); + + // Test 8: + deleteNodeFromList(1, testList); + TEST("Deleting an item in middle of the list", + (testList->itemCount == 2 && + testList->head != NULL && + testList->tail != NULL && + *(char *)testList->head->data == 'A' && + *(char *)testList->tail->data == 'C' && + testList->tail != testList->head && + testList->head->next == testList->tail && + testList->tail->previous == testList->head)); + + // Test 9: + deleteNodeFromList(1, testList); + appendToList(PLAYER, testList, &testDataB); + appendToList(PLAYER, testList, &testDataC); + TEST("Checking for data in the list using comparison function", + (isInList(compareChar, &testDataB, testList) == true)); + + // Test 10: + TEST("Checking for data NOT in the list using comparison function", + (isInList(compareChar, &(char){'D'}, testList) == true)); + + // Test 11: + TEST("Checking for data in the list using pointer", + (isPointerInList(&testDataB, testList) == true)); + + // Test 12: + TEST("Checking for data NOT in the list using pointer", + (isPointerInList(&(char){'D'}, testList) == false)); + + // Test 13: + TEST("Checking index of data in the list", + (indexOfFromList(compareChar, &testDataB, testList) == 1)); + + // Test 14: + TEST("Checking index of data NOT in the list", + (indexOfFromList(compareChar, &(char){'D'}, testList) == -1)); + + // Test 15: + appendToList(PLAYER, testList, &testDataA); + TEST("Checking first of data in the list", + (getFirstFromList(compareChar, &testDataA, testList) == testList->head)); + + // Test 16: + TEST("Checking first of data NOT in the list", + (getFirstFromList(compareChar, &(char){'D'}, testList) == NULL)); + + FINISH_TESTING; +} + +// ================================================== +// | End of lists-test.c, copyright notice follows. | +// ================================================== + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. + +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . diff --git a/source/tests/tests.h b/source/tests/tests.h new file mode 100644 index 0000000..7376dc5 --- /dev/null +++ b/source/tests/tests.h @@ -0,0 +1,43 @@ +// ========================================= +// | SilverMUD Tests - tests.h | +// | Copyright (C) 2023, Barra Ó Catháin | +// | See end of file for copyright notice. | +// ========================================= +#ifndef SILVERMUD_TESTS +#define SILVERMUD_TESTS + +#define SETUP_TESTS \ + size_t TEST_SUCCESSES = 0, TEST_FAILURES = 0, TEST_COUNT; + +#define TEST(STRING, CONDITION) \ + printf("Test %zu: ", ++TEST_COUNT); \ + printf(STRING); \ + if (CONDITION) { printf("... SUCCESS!\n"); TEST_SUCCESSES++; } \ + else { printf("... FAILED.\n"); TEST_FAILURES++; } + +#define FINISH_TESTING \ + printf("=====\n\nSuccesses: %zu | Failures: %zu\n", TEST_SUCCESSES, TEST_FAILURES); \ + if (TEST_FAILURES == 0) \ + { \ + printf("All good! We're done here.\n"); \ + exit(EXIT_SUCCESS); \ + } \ + exit(EXIT_FAILURE); + +#endif +// ============================================= +// | End of tests.h, copyright notice follows. | +// ============================================= + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. + +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see .