#include #include #include #include #include "bintree.h" #define GREEN "\033[0;32m" #define RED "\033[0;31m" #define RESET "\033[0m" #define BLUE "\033[0;34m" int testsPassed = 0; int testsFailed = 0; void printTestResult(const char *testName, int passed) { if (passed) { printf(GREEN "[PASS]" RESET " %s\n", testName); testsPassed++; } else { printf(RED "[FAIL]" RESET " %s\n", testName); testsFailed++; } } // Vergleichsfunktion für Integers int compareInt(const void *arg1, const void *arg2) { int val1 = *(const int *)arg1; int val2 = *(const int *)arg2; if (val1 < val2) return -1; if (val1 > val2) return 1; return 0; } // Vergleichsfunktion für Strings int compareString(const void *arg1, const void *arg2) { return strcmp(*(const char **)arg1, *(const char **)arg2); } // Test 1: addToTree mit einem Element void test_add_single_element() { printf(BLUE "\n--- Test 1: addToTree mit einem Element ---" RESET "\n"); TreeNode *root = NULL; int value = 42; root = addToTree(root, &value, sizeof(int), compareInt, NULL); printTestResult("Baum wurde erstellt", root != NULL); printTestResult("Root-Daten sind korrekt", root != NULL && *(int *)root->data == 42); printTestResult("Root hat keine Kinder", root != NULL && root->left == NULL && root->right == NULL); clearTree(root); } // Test 2: addToTree mit mehreren Elementen void test_add_multiple_elements() { printf(BLUE "\n--- Test 2: addToTree mit mehreren Elementen ---" RESET "\n"); TreeNode *root = NULL; int values[] = {50, 30, 70, 20, 40, 60, 80}; for (int i = 0; i < 7; i++) { root = addToTree(root, &values[i], sizeof(int), compareInt, NULL); } printTestResult("Baum mit 7 Elementen erstellt", root != NULL); printTestResult("Root ist 50", *(int *)root->data == 50); printTestResult("Linkes Kind ist 30", root->left != NULL && *(int *)root->left->data == 30); printTestResult("Rechtes Kind ist 70", root->right != NULL && *(int *)root->right->data == 70); clearTree(root); } // Test 3: addToTree mit Duplikat-Erkennung void test_duplicate_detection() { printf(BLUE "\n--- Test 3: Duplikat-Erkennung ---" RESET "\n"); TreeNode *root = NULL; int value1 = 42; int value2 = 17; int value3 = 42; // Duplikat! int isDuplicate = 0; root = addToTree(root, &value1, sizeof(int), compareInt, &isDuplicate); printTestResult("Erstes Element: kein Duplikat", isDuplicate == 0); isDuplicate = 0; root = addToTree(root, &value2, sizeof(int), compareInt, &isDuplicate); printTestResult("Zweites Element: kein Duplikat", isDuplicate == 0); isDuplicate = 0; root = addToTree(root, &value3, sizeof(int), compareInt, &isDuplicate); printTestResult("Drittes Element: Duplikat erkannt", isDuplicate == 1); clearTree(root); } // Test 4: addToTree mit Duplikaten erlaubt void test_allow_duplicates() { printf(BLUE "\n--- Test 4: Duplikate erlauben (isDuplicate = NULL) ---" RESET "\n"); TreeNode *root = NULL; int values[] = {50, 30, 50, 30}; // Mit Duplikaten for (int i = 0; i < 4; i++) { root = addToTree(root, &values[i], sizeof(int), compareInt, NULL); } unsigned int size = treeSize(root); printTestResult("Alle 4 Elemente wurden eingefuegt (inkl. Duplikate)", size == 4); clearTree(root); } // Test 5: treeSize void test_tree_size() { printf(BLUE "\n--- Test 5: treeSize ---" RESET "\n"); TreeNode *root = NULL; printTestResult("Leerer Baum hat Groesse 0", treeSize(root) == 0); int values[] = {50, 30, 70, 20, 40}; for (int i = 0; i < 5; i++) { root = addToTree(root, &values[i], sizeof(int), compareInt, NULL); } printTestResult("Baum mit 5 Elementen hat Groesse 5", treeSize(root) == 5); // Füge mehr hinzu int value6 = 60; int value7 = 80; root = addToTree(root, &value6, sizeof(int), compareInt, NULL); root = addToTree(root, &value7, sizeof(int), compareInt, NULL); printTestResult("Nach Hinzufuegen von 2 Elementen: Groesse 7", treeSize(root) == 7); clearTree(root); } // Test 6: nextTreeData In-Order Traversierung void test_next_tree_data() { printf(BLUE "\n--- Test 6: nextTreeData (In-Order Traversierung) ---" RESET "\n"); TreeNode *root = NULL; int values[] = {50, 30, 70, 20, 40, 60, 80}; for (int i = 0; i < 7; i++) { root = addToTree(root, &values[i], sizeof(int), compareInt, NULL); } // Erwartete Reihenfolge: 20, 30, 40, 50, 60, 70, 80 (sortiert!) int expected[] = {20, 30, 40, 50, 60, 70, 80}; int index = 0; int allCorrect = 1; int *data = (int *)nextTreeData(root); while (data != NULL) { if (index >= 7 || *data != expected[index]) { allCorrect = 0; printf(" Fehler bei Index %d: Erwartet %d, bekommen %d\n", index, expected[index], *data); } index++; data = (int *)nextTreeData(NULL); } printTestResult("In-Order Traversierung gibt sortierte Reihenfolge", allCorrect && index == 7); clearTree(root); } // Test 7: nextTreeData mit einzelnem Element void test_next_tree_data_single() { printf(BLUE "\n--- Test 7: nextTreeData mit einem Element ---" RESET "\n"); TreeNode *root = NULL; int value = 42; root = addToTree(root, &value, sizeof(int), compareInt, NULL); int *data = (int *)nextTreeData(root); int correct = (data != NULL && *data == 42); data = (int *)nextTreeData(NULL); correct = correct && (data == NULL); printTestResult("nextTreeData mit einem Element funktioniert", correct); clearTree(root); } // Test 8: nextTreeData mit leerem Baum void test_next_tree_data_empty() { printf(BLUE "\n--- Test 8: nextTreeData mit leerem Baum ---" RESET "\n"); TreeNode *root = NULL; int *data = (int *)nextTreeData(root); printTestResult("nextTreeData mit leerem Baum gibt NULL zurueck", data == NULL); } // Test 9: Mehrfache Traversierungen void test_multiple_traversals() { printf(BLUE "\n--- Test 9: Mehrfache Traversierungen ---" RESET "\n"); TreeNode *root = NULL; int values[] = {50, 30, 70}; for (int i = 0; i < 3; i++) { root = addToTree(root, &values[i], sizeof(int), compareInt, NULL); } // Erste Traversierung int count1 = 0; int *data = (int *)nextTreeData(root); while (data != NULL) { count1++; data = (int *)nextTreeData(NULL); } // Zweite Traversierung (neu starten) int count2 = 0; data = (int *)nextTreeData(root); while (data != NULL) { count2++; data = (int *)nextTreeData(NULL); } printTestResult("Mehrfache Traversierungen moeglich", count1 == 3 && count2 == 3); clearTree(root); } // Test 10: clearTree void test_clear_tree() { printf(BLUE "\n--- Test 10: clearTree ---" RESET "\n"); TreeNode *root = NULL; int values[] = {50, 30, 70, 20, 40, 60, 80}; for (int i = 0; i < 7; i++) { root = addToTree(root, &values[i], sizeof(int), compareInt, NULL); } clearTree(root); root = NULL; printTestResult("clearTree ausgefuehrt (valgrind prueft Speicher)", 1); // Neuer Baum nach Clear int newValue = 100; root = addToTree(root, &newValue, sizeof(int), compareInt, NULL); printTestResult("Nach clearTree kann neuer Baum aufgebaut werden", root != NULL && *(int *)root->data == 100); clearTree(root); } // Test 11: Strings im Baum void test_string_tree() { printf(BLUE "\n--- Test 11: Baum mit Strings ---" RESET "\n"); TreeNode *root = NULL; char *words[] = {"dog", "cat", "elephant", "ant", "bear"}; for (int i = 0; i < 5; i++) { root = addToTree(root, &words[i], sizeof(char *), compareString, NULL); } printTestResult("String-Baum erstellt", root != NULL); // Traversierung sollte alphabetisch sortiert sein char *expected[] = {"ant", "bear", "cat", "dog", "elephant"}; int index = 0; int allCorrect = 1; char **data = (char **)nextTreeData(root); while (data != NULL) { if (index >= 5 || strcmp(*data, expected[index]) != 0) { allCorrect = 0; printf(" Fehler bei Index %d: Erwartet '%s', bekommen '%s'\n", index, expected[index], *data); } index++; data = (char **)nextTreeData(NULL); } printTestResult("String-Baum gibt alphabetisch sortierte Reihenfolge", allCorrect && index == 5); clearTree(root); } // Test 12: Stress-Test mit vielen Elementen void test_large_tree() { printf(BLUE "\n--- Test 12: Stress-Test (1000 Elemente) ---" RESET "\n"); TreeNode *root = NULL; // 1000 zufällige Zahlen einfügen for (int i = 0; i < 1000; i++) { int value = i; root = addToTree(root, &value, sizeof(int), compareInt, NULL); } printTestResult("1000 Elemente eingefuegt", treeSize(root) == 1000); // Traversierung zählen int count = 0; int *data = (int *)nextTreeData(root); while (data != NULL) { count++; data = (int *)nextTreeData(NULL); } printTestResult("Traversierung ueber alle 1000 Elemente", count == 1000); clearTree(root); } // Test 13: Einseitiger Baum (nur rechts) void test_unbalanced_tree() { printf(BLUE "\n--- Test 13: Einseitiger Baum ---" RESET "\n"); TreeNode *root = NULL; // Aufsteigende Reihenfolge -> nur rechte Kinder for (int i = 1; i <= 5; i++) { root = addToTree(root, &i, sizeof(int), compareInt, NULL); } printTestResult("Einseitiger Baum erstellt", treeSize(root) == 5); // Traversierung sollte trotzdem funktionieren int count = 0; int *data = (int *)nextTreeData(root); while (data != NULL) { count++; data = (int *)nextTreeData(NULL); } printTestResult("Traversierung ueber einseitigen Baum funktioniert", count == 5); clearTree(root); } int main() { printf("\n"); printf("+----------------------------------------------+\n"); printf("| BINARY TREE UNIT TESTS |\n"); printf("+----------------------------------------------+\n"); test_add_single_element(); test_add_multiple_elements(); test_duplicate_detection(); test_allow_duplicates(); test_tree_size(); test_next_tree_data(); test_next_tree_data_single(); test_next_tree_data_empty(); test_multiple_traversals(); test_clear_tree(); test_string_tree(); test_large_tree(); test_unbalanced_tree(); printf("\n"); printf("+----------------------------------------------+\n"); printf("| TEST ZUSAMMENFASSUNG |\n"); printf("+----------------------------------------------+\n"); printf(GREEN "Tests bestanden: %d" RESET "\n", testsPassed); printf(RED "Tests fehlgeschlagen: %d" RESET "\n", testsFailed); printf("Gesamt: %d\n", testsPassed + testsFailed); if (testsFailed == 0) { printf(GREEN "\n==> Alle Tests erfolgreich!\n" RESET); return EXIT_SUCCESS; } else { printf(RED "\n==> Einige Tests sind fehlgeschlagen!\n" RESET); return EXIT_FAILURE; } }