#include // Für printf #include // Für malloc, free #include "stack.h" // Für die Stack-Funktionen und -Strukturen // Globale Zähler für die Testergebnisse int test_count = 0; int test_failed = 0; // Hilfsfunktion für Assertionen void assert_equals_int(int expected, int actual, const char *test_name) { test_count++; if (expected == actual) { printf(" [PASS] %s\n", test_name); } else { printf(" [FAIL] %s - Erwartet: %d, Tatsächlich: %d\n", test_name, expected, actual); test_failed++; } } void assert_equals_ptr(void *expected, void *actual, const char *test_name) { test_count++; if (expected == actual) { printf(" [PASS] %s\n", test_name); } else { printf(" [FAIL] %s - Erwartet: %p, Tatsächlich: %p\n", test_name, expected, actual); test_failed++; } } // Hilfsfunktion zum Freigeben der Daten im Stack, bevor der Stack selbst geleert wird void free_stack_data(StackNode *stack) { StackNode *current = stack; while (current != NULL) { if (current->data != NULL) { free(current->data); // Freigabe der Integer-Daten current->data = NULL; // Optional: Pointer auf NULL setzen } current = current->next; } } // --- Testfälle --- void test_push_single_element() { printf("--- Test: push_single_element ---\n"); StackNode *stack = NULL; int *data1 = (int *)malloc(sizeof(int)); *data1 = 10; stack = push(stack, data1); assert_equals_ptr(data1, stack->data, "Top should be 10"); assert_equals_ptr(NULL, stack->next, "Next element should be NULL"); // Aufräumen free_stack_data(stack); // Daten freigeben clearStack(stack); // StackNodes freigeben } void test_push_multiple_elements() { printf("--- Test: push_multiple_elements ---\n"); StackNode *stack = NULL; int *data1 = (int *)malloc(sizeof(int)); *data1 = 10; int *data2 = (int *)malloc(sizeof(int)); *data2 = 20; int *data3 = (int *)malloc(sizeof(int)); *data3 = 30; stack = push(stack, data1); // Stack: [10] stack = push(stack, data2); // Stack: [20, 10] stack = push(stack, data3); // Stack: [30, 20, 10] assert_equals_int(30, *(int*)stack->data, "Top should be 30"); assert_equals_int(20, *(int*)stack->next->data, "Second element should be 20"); assert_equals_int(10, *(int*)stack->next->next->data, "Third element should be 10"); assert_equals_ptr(NULL, stack->next->next->next, "Fourth element should be NULL"); // Aufräumen free_stack_data(stack); clearStack(stack); } void test_pop_from_empty_stack() { printf("--- Test: pop_from_empty_stack ---\n"); StackNode *stack = NULL; StackNode *result = pop(stack); assert_equals_ptr(NULL, result, "Pop from empty stack should return NULL"); assert_equals_ptr(NULL, stack, "Stack should remain NULL"); // stack pointer passed by value, so it's still NULL } void test_pop_single_element() { printf("--- Test: pop_single_element ---\n"); StackNode *stack = NULL; int *data1 = (int *)malloc(sizeof(int)); *data1 = 10; stack = push(stack, data1); // Stack: [10] assert_equals_int(10, *(int*)stack->data, "Top should be 10 before pop"); // Daten freigeben, bevor der Knoten freigegeben wird free(top(stack)); // Freigabe von data1 stack = pop(stack); // Stack: [] assert_equals_ptr(NULL, stack, "Stack should be empty after popping last element"); assert_equals_ptr(NULL, stack->data, "Top should be NULL after popping last element"); } void test_pop_multiple_elements() { printf("--- Test: pop_multiple_elements ---\n"); StackNode *stack = NULL; int *data1 = (int *)malloc(sizeof(int)); *data1 = 10; int *data2 = (int *)malloc(sizeof(int)); *data2 = 20; int *data3 = (int *)malloc(sizeof(int)); *data3 = 30; stack = push(stack, data1); stack = push(stack, data2); stack = push(stack, data3); // Stack: [30, 20, 10] // Pop 1 (30) free(top(stack)); // Freigabe von data3 stack = pop(stack); // Stack: [20, 10] assert_equals_int(20, *(int*)top(stack), "Top should be 20 after first pop"); // Pop 2 (20) free(top(stack)); // Freigabe von data2 stack = pop(stack); // Stack: [10] assert_equals_int(10, *(int*)top(stack), "Top should be 10 after second pop"); // Pop 3 (10) free(top(stack)); // Freigabe von data1 stack = pop(stack); // Stack: [] assert_equals_ptr(NULL, stack, "Stack should be empty after third pop"); assert_equals_ptr(NULL, top(stack), "Top should be NULL after third pop"); } void test_top_function() { printf("--- Test: top_function ---\n"); StackNode *stack = NULL; int *data1 = (int *)malloc(sizeof(int)); *data1 = 100; int *data2 = (int *)malloc(sizeof(int)); *data2 = 200; assert_equals_ptr(NULL, top(stack), "Top of empty stack should be NULL"); stack = push(stack, data1); assert_equals_int(100, *(int*)top(stack), "Top should be 100"); stack = push(stack, data2); assert_equals_int(200, *(int*)top(stack), "Top should be 200"); // Aufräumen free_stack_data(stack); clearStack(stack); } void test_clear_stack_function() { printf("--- Test: clear_stack_function ---\n"); StackNode *stack = NULL; int *data1 = (int *)malloc(sizeof(int)); *data1 = 1; int *data2 = (int *)malloc(sizeof(int)); *data2 = 2; int *data3 = (int *)malloc(sizeof(int)); *data3 = 3; stack = push(stack, data1); stack = push(stack, data2); stack = push(stack, data3); // Stack: [3, 2, 1] // Zuerst die Daten freigeben free_stack_data(stack); // Dann die StackNodes freigeben clearStack(stack); // WICHTIG: Der lokale 'stack'-Zeiger muss manuell auf NULL gesetzt werden, // da clearStack ihn nicht ändern kann (pass-by-value). stack = NULL; assert_equals_ptr(NULL, stack, "Stack should be NULL after clearStack"); assert_equals_ptr(NULL, top(stack), "Top of cleared stack should be NULL"); } int main() { printf("Starte Stack Unit-Tests...\n"); test_push_single_element(); test_push_multiple_elements(); test_pop_from_empty_stack(); test_pop_single_element(); test_pop_multiple_elements(); test_top_function(); test_clear_stack_function(); printf("\n--- Testergebnisse ---\n"); printf("Gesamtzahl der Tests: %d\n", test_count); printf("Fehlgeschlagene Tests: %d\n", test_failed); if (test_failed == 0) { printf("Alle Tests erfolgreich bestanden! 🎉\n"); return EXIT_SUCCESS; } else { printf("Einige Tests sind fehlgeschlagen. 😟\n"); return EXIT_FAILURE; } }