#include #include #include #include "unity.h" #include "stack.h" // ========================================================================= // HILFSFUNKTIONEN FÜR DIE TESTS // ========================================================================= /** * Erstellt eine Kopie eines Integer-Wertes auf dem Heap. * Dies ist notwendig, da der Stack void* Pointer speichert. */ static int *createIntPointer(int value) { int *ptr = (int *)malloc(sizeof(int)); TEST_ASSERT_NOT_NULL(ptr); // Stelle sicher, dass malloc erfolgreich war *ptr = value; return ptr; } /** * Räumt den Stack und die darauf gespeicherten Datenpointer auf (spezifisch für Integer-Tests). * Im Gegensatz zu clearStack() befreit diese Funktion auch die Daten, da sie im Test hier allokiert wurden. */ static void clearStackWithData(StackNode *stack) { while (stack != NULL) { StackNode *next = stack->next; if (stack->data != NULL) { free(stack->data); // Gib die Daten (Integer-Pointer) frei } free(stack); // Gib den Knoten selbst frei stack = next; } } // ========================================================================= // DIE WICHTIGSTEN TESTFÄLLE (REDUZIERT) // ========================================================================= // Testet ob das oberste Element (top) korrekt das zuletzt hinzugefügte Element (push) ist void test_pushAndTop(void) { StackNode *stack = NULL; // Initialisiert den Stack als leeren Pointer. int *data = createIntPointer(42); // Erzeugt Integer-Wert (42) auf dem Heap // 1. Push stack = push(stack, data); //Ruft push-Funktion auf; neuer Knoten oben auf den stack TEST_ASSERT_NOT_NULL(stack); // Prüfung -> Stack-Pointer darf nach dem Pushen nicht NULL sein (siehe unity.h) // 2. Top int *top_data = (int *)top(stack); // Ruft top-Funktion auf; Holt void* Pointer von oben und castet ihn zurück zu int* TEST_ASSERT_EQUAL_INT(42, *top_data);// Prüft, ob der Wert an der Spitze tatsächlich 42 ist //clean-up stack = pop(stack); // pop-Funktion: Entfernt den obersten Knoten und gibt seinen Speicher frei. free(data); // Gibt den Datenpointer (42) frei TEST_ASSERT_NULL(stack); // Prüft ob stack jetzt wieder NULL ist } // Testet die korrekte LIFO-Reihenfolge mit mehreren Elementen und die Pop-Funktion. void test_popMultipleElements(void) { StackNode *stack = NULL; // Erzeugt drei separate Integer-Werte (1, 2, 3) auf dem Heap int *data1 = createIntPointer(1); int *data2 = createIntPointer(2); int *data3 = createIntPointer(3); // stack befüllen mit push-Funktion stack = push(NULL, data1); // Stack: [1] (1 ist unten) stack = push(stack, data2); // Stack: [2, 1] stack = push(stack, data3); // Stack: [3, 2, 1] (3 ist oben, LIFO). // 1. Pop: Prüfe ob 3 oben liegt TEST_ASSERT_EQUAL_INT(3, *(int *)top(stack)); // vergleicht 3 mit top-fkt ausgabe (siehe unity.h) free(data3); //Gibt den Heap-Speicher frei stack = pop(stack); //Entfernt den Knoten 3; Stack ist jetzt [2, 1] // 2. Pop: Prüfe 2 TEST_ASSERT_EQUAL_INT(2, *(int *)top(stack)); //vergleicht 2 mit top-fkt ausgabe (siehe unity.h) free(data2); stack = pop(stack); //Entfernt den Knoten 2; Stack ist jetzt [1] // 3. Pop: Prüfe 1 TEST_ASSERT_EQUAL_INT(1, *(int *)top(stack)); //vergleicht 1 mit top-fkt ausgabe (siehe unity.h) free(data1); stack = pop(stack); //Entfernt den Knoten 2; Stack ist jetzt NULL TEST_ASSERT_NULL(stack); //Prüft ob Stack NULL ist } // Testet den Grenzfall: Pop auf einem leeren Stack -> soll NULL zurückgeben void test_popOnEmptyStack(void) { StackNode *stack = NULL; //Initialisiert leeren Stack TEST_ASSERT_NULL(pop(stack));// Pop sollte NULL zurückgeben, wenn der Stack leer ist } // Testet die Speicherfreigabe void test_clearStackFunctionality(void) { StackNode *stack = NULL; // Allokiere Daten und pushe sie auf den Stack stack = push(stack, createIntPointer(10)); //Knoten mit zugehörigem Pointer mit Hilfsfkt stack = push(stack, createIntPointer(20)); stack = push(stack, createIntPointer(30)); clearStackWithData(stack); // gibt iterativ alle Daten und Knoten frei stack = NULL; // Wenn der Test ohne Speicherzugriffsverletzung durchläuft, war clearStack erfolgreich. } // ========================================================================= // MAIN SETUP / RUNNER // ========================================================================= void setUp(void) { // Wird vor jedem Test aufgerufen } void tearDown(void) { // Wird nach jedem Test aufgerufen } int main(void) { UNITY_BEGIN(); printf("\n============================\nStack Module Tests\n============================\n"); // Die essentiellen Tests RUN_TEST(test_pushAndTop); RUN_TEST(test_popMultipleElements); RUN_TEST(test_popOnEmptyStack); RUN_TEST(test_clearStackFunctionality); return UNITY_END(); }