info2Praktikum-DobleSpiel/Test_bintree.c
2025-12-12 14:33:45 +01:00

423 lines
11 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#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;
}
}