generated from freudenreichan/info2Praktikum-DobleSpiel
comments unit tests
This commit is contained in:
parent
bb8bd2ace8
commit
e0537dda8f
6
makefile
6
makefile
@ -60,12 +60,12 @@ highscore.o: highscore.c
|
|||||||
#unitTests:
|
#unitTests:
|
||||||
# echo "needs to be implemented"
|
# echo "needs to be implemented"
|
||||||
|
|
||||||
numbersTests: numbers.o bintree.o test_numbers.c $(unityfolder)/unity.c
|
|
||||||
$(CC) $(CFLAGS) -I$(unityfolder) -o runNumbersTests test_numbers.c numbers.o bintree.o $(unityfolder)/unity.c
|
|
||||||
|
|
||||||
stackTests: stack.o test_stack.c $(unityfolder)/unity.c
|
stackTests: stack.o test_stack.c $(unityfolder)/unity.c
|
||||||
$(CC) $(CFLAGS) -I$(unityfolder) -o runStackTests test_stack.c stack.o $(unityfolder)/unity.c
|
$(CC) $(CFLAGS) -I$(unityfolder) -o runStackTests test_stack.c stack.o $(unityfolder)/unity.c
|
||||||
|
|
||||||
|
numbersTests: numbers.o bintree.o stack.o test_numbers.c $(unityfolder)/unity.c
|
||||||
|
$(CC) $(CFLAGS) -I$(unityfolder) -o runNumbersTests test_numbers.c numbers.o bintree.o stack.o $(unityfolder)/unity.c
|
||||||
|
|
||||||
# --------------------------
|
# --------------------------
|
||||||
# Clean
|
# Clean
|
||||||
# --------------------------
|
# --------------------------
|
||||||
|
|||||||
4
stack.c
4
stack.c
@ -19,11 +19,9 @@ StackNode *push(StackNode *stack, void *data)
|
|||||||
newNode->next = stack; // Der bisherige Stack ist jetzt der Nächste (LIFO)
|
newNode->next = stack; // Der bisherige Stack ist jetzt der Nächste (LIFO)
|
||||||
|
|
||||||
return newNode; // Der neue Knoten ist jetzt die Spitze des Stacks
|
return newNode; // Der neue Knoten ist jetzt die Spitze des Stacks
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deletes the top element of the stack (latest added element) and releases its memory. (Pointer to data has to be
|
// Deletes the top element of the stack (latest added element) and releases its memory. (Pointer to data has to be freed by caller.)
|
||||||
// freed by caller.)
|
|
||||||
StackNode *pop(StackNode *stack)
|
StackNode *pop(StackNode *stack)
|
||||||
{
|
{
|
||||||
// Check, ob der Stack leer ist
|
// Check, ob der Stack leer ist
|
||||||
|
|||||||
@ -20,6 +20,8 @@ extern int compareNumbers(const void *arg1, const void *arg2);
|
|||||||
* @param numbers Das zu prüfende Array.
|
* @param numbers Das zu prüfende Array.
|
||||||
* @param len Die Länge des Arrays.
|
* @param len Die Länge des Arrays.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//Das Array enthält exakt (len-2) Unikate und 1 Duplikat
|
||||||
static int validateArrayHasSingleDuplicate(const unsigned int *numbers, unsigned int len)
|
static int validateArrayHasSingleDuplicate(const unsigned int *numbers, unsigned int len)
|
||||||
{
|
{
|
||||||
if (len < 3) return 0;
|
if (len < 3) return 0;
|
||||||
@ -70,26 +72,26 @@ static int validateArrayHasSingleDuplicate(const unsigned int *numbers, unsigned
|
|||||||
// TESTFALL GRUPPE 1: createNumbers (KERNFUNKTION)
|
// TESTFALL GRUPPE 1: createNumbers (KERNFUNKTION)
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|
||||||
// Prüft die wichtigste Anforderung: Korrekte Allokation, Länge, Duplikat-Struktur und Wertebereich.
|
// Prüft die wichtigste Anforderung: Zufallsgenerierung, Duplikatprüfung (via BST) und korrekte Array-Struktur
|
||||||
void test_createNumbersCoreFunctionality(void)
|
void test_createNumbersCoreFunctionality(void)
|
||||||
{
|
{
|
||||||
const unsigned int len = 10;
|
const unsigned int len = 10; // Definiert Array-Größe (10) für den Test
|
||||||
unsigned int *numbers = createNumbers(len);
|
unsigned int *numbers = createNumbers(len); // Ruft createNumbers-Fkt auf
|
||||||
|
|
||||||
TEST_ASSERT_NOT_NULL(numbers); // Muss Speicher allokieren
|
TEST_ASSERT_NOT_NULL(numbers); // prüft ob Speicher allokiert worden ist
|
||||||
|
|
||||||
// 1. Prüfe, ob genau ein Duplikat vorhanden ist (mit Helper-Funktion)
|
// 1. Prüfe, ob genau ein Duplikat und sonst unikate vorhanden ist (mit Hilffunktion)
|
||||||
TEST_ASSERT_TRUE(validateArrayHasSingleDuplicate(numbers, len));
|
TEST_ASSERT_TRUE(validateArrayHasSingleDuplicate(numbers, len));
|
||||||
|
|
||||||
// 2. Prüfe, ob die Duplikat-Findung funktioniert (Test der Integration von getDuplicate)
|
// 2. Prüfe, ob die Duplikat-Findung funktioniert (Test der Integration von getDuplicate)
|
||||||
unsigned int duplicate = getDuplicate(numbers, len);
|
unsigned int duplicate = getDuplicate(numbers, len); // getDuplicate-Fkt sucht das Duplikat aus dem gerade erzeugtem array mit qsort
|
||||||
TEST_ASSERT_TRUE(duplicate != 0); // Muss eine doppelte Zahl finden
|
TEST_ASSERT_TRUE(duplicate != 0); // Muss eine doppelte Zahl finden
|
||||||
|
|
||||||
// 3. Prüfe, ob die Zahlen im erwarteten Bereich [1, 2 * len] liegen
|
// 3. Prüfe, ob die Zahlen im erwarteten Bereich [1, 2 * len] liegen
|
||||||
const unsigned int max_val = 2 * len;
|
const unsigned int max_val = 2 * len; //maximale größe der zahlen ist 2*len = hier 20
|
||||||
for (unsigned int i = 0; i < len; i++)
|
for (unsigned int i = 0; i < len; i++) // Geht dasss array (len=10) durch und prüft ob die zahlen zwischen 1 und 20 liegen
|
||||||
{
|
{
|
||||||
TEST_ASSERT_TRUE(numbers[i] >= 1);
|
TEST_ASSERT_TRUE(numbers[i] >= 1); //
|
||||||
TEST_ASSERT_TRUE(numbers[i] <= max_val);
|
TEST_ASSERT_TRUE(numbers[i] <= max_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,9 +107,9 @@ void test_createNumbersCoreFunctionality(void)
|
|||||||
// Prüft die Duplikaterkennung über qsort auf einem unsortierten Array.
|
// Prüft die Duplikaterkennung über qsort auf einem unsortierten Array.
|
||||||
void test_getDuplicateFindsDuplicatedNumber(void)
|
void test_getDuplicateFindsDuplicatedNumber(void)
|
||||||
{
|
{
|
||||||
// Testfall: Duplikat in der Mitte eines unsortierten Arrays
|
|
||||||
unsigned int testArray[] = {10, 5, 20, 30, 5};
|
unsigned int testArray[] = {10, 5, 20, 30, 5}; //Definiert ein unsortiertes Array mit dem Duplikat 5
|
||||||
TEST_ASSERT_EQUAL_UINT(5, getDuplicate(testArray, 5));
|
TEST_ASSERT_EQUAL_UINT(5, getDuplicate(testArray, 5)); //Ruft getDuplicate auf, die intern qsort aufruft; Der Test erwartet die Zahl 5 und vergleicht
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -120,14 +122,15 @@ void test_compareNumbersCheckAllCases(void)
|
|||||||
{
|
{
|
||||||
unsigned int a = 10, b = 5, c = 10;
|
unsigned int a = 10, b = 5, c = 10;
|
||||||
|
|
||||||
|
//Aufrufen der compareNumbers-fkt
|
||||||
// Fall 1: a > b (muss positiv sein)
|
// Fall 1: a > b (muss positiv sein)
|
||||||
TEST_ASSERT_TRUE(compareNumbers(&a, &b) > 0);
|
TEST_ASSERT_TRUE(compareNumbers(&a, &b) > 0); // (10 > 5) -> return 1 > 0 -> positiver Wert -> True
|
||||||
|
|
||||||
// Fall 2: b < a (muss negativ sein)
|
// Fall 2: b < a (muss negativ sein)
|
||||||
TEST_ASSERT_TRUE(compareNumbers(&b, &a) < 0);
|
TEST_ASSERT_TRUE(compareNumbers(&b, &a) < 0); // (5 < 10) -> return -1 < 0 -> negativer Wert -> True
|
||||||
|
|
||||||
// Fall 3: a = c (muss null sein)
|
// Fall 3: a = c (muss null sein)
|
||||||
TEST_ASSERT_EQUAL_INT(0, compareNumbers(&a, &c));
|
TEST_ASSERT_EQUAL_INT(0, compareNumbers(&a, &c)); // (10 = 10) -> return 0 == 0 -> True
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
72
test_stack.c
72
test_stack.c
@ -42,81 +42,79 @@ static void clearStackWithData(StackNode *stack)
|
|||||||
// DIE WICHTIGSTEN TESTFÄLLE (REDUZIERT)
|
// DIE WICHTIGSTEN TESTFÄLLE (REDUZIERT)
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|
||||||
// Testet Push und Top (LIFO-Prinzip, 1 Element)
|
// Testet ob das oberste Element (top) korrekt das zuletzt hinzugefügte Element (push) ist
|
||||||
void test_pushAndTop(void)
|
void test_pushAndTop(void)
|
||||||
{
|
{
|
||||||
StackNode *stack = NULL;
|
StackNode *stack = NULL; // Initialisiert den Stack als leeren Pointer.
|
||||||
int *data = createIntPointer(42);
|
int *data = createIntPointer(42); // Erzeugt Integer-Wert (42) auf dem Heap
|
||||||
|
|
||||||
// 1. Push
|
// 1. Push
|
||||||
stack = push(stack, data);
|
stack = push(stack, data); //Ruft push-Funktion auf; neuer Knoten oben auf den stack
|
||||||
TEST_ASSERT_NOT_NULL(stack);
|
TEST_ASSERT_NOT_NULL(stack); // Prüfung -> Stack-Pointer darf nach dem Pushen nicht NULL sein (siehe unity.h)
|
||||||
|
|
||||||
// 2. Top (LIFO - Last In)
|
// 2. Top
|
||||||
int *top_data = (int *)top(stack);
|
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);
|
TEST_ASSERT_EQUAL_INT(42, *top_data);// Prüft, ob der Wert an der Spitze tatsächlich 42 ist
|
||||||
|
|
||||||
// Aufräumen: Da die Daten hier nur einmalig gepusht wurden,
|
//clean-up
|
||||||
// können wir den Knoten poppen und die Daten separat freigeben (wie es pop() erfordert).
|
stack = pop(stack); // pop-Funktion: Entfernt den obersten Knoten und gibt seinen Speicher frei.
|
||||||
stack = pop(stack);
|
free(data); // Gibt den Datenpointer (42) frei
|
||||||
free(data);
|
TEST_ASSERT_NULL(stack); // Prüft ob stack jetzt wieder NULL ist
|
||||||
TEST_ASSERT_NULL(stack);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Testet die LIFO-Reihenfolge mit mehreren Elementen und die Pop-Funktion.
|
// Testet die korrekte LIFO-Reihenfolge mit mehreren Elementen und die Pop-Funktion.
|
||||||
void test_popMultipleElements(void)
|
void test_popMultipleElements(void)
|
||||||
{
|
{
|
||||||
StackNode *stack = NULL;
|
StackNode *stack = NULL;
|
||||||
|
|
||||||
|
// Erzeugt drei separate Integer-Werte (1, 2, 3) auf dem Heap
|
||||||
int *data1 = createIntPointer(1);
|
int *data1 = createIntPointer(1);
|
||||||
int *data2 = createIntPointer(2);
|
int *data2 = createIntPointer(2);
|
||||||
int *data3 = createIntPointer(3);
|
int *data3 = createIntPointer(3);
|
||||||
|
|
||||||
// Stack: [3 (oben), 2, 1 (unten)]
|
// stack befüllen mit push-Funktion
|
||||||
stack = push(NULL, data1);
|
stack = push(NULL, data1); // Stack: [1] (1 ist unten)
|
||||||
stack = push(stack, data2);
|
stack = push(stack, data2); // Stack: [2, 1]
|
||||||
stack = push(stack, data3);
|
stack = push(stack, data3); // Stack: [3, 2, 1] (3 ist oben, LIFO).
|
||||||
|
|
||||||
// 1. Pop: Prüfe 3
|
// 1. Pop: Prüfe ob 3 oben liegt
|
||||||
TEST_ASSERT_EQUAL_INT(3, *(int *)top(stack));
|
TEST_ASSERT_EQUAL_INT(3, *(int *)top(stack)); // vergleicht 3 mit top-fkt ausgabe (siehe unity.h)
|
||||||
free(data3);
|
free(data3); //Gibt den Heap-Speicher frei
|
||||||
stack = pop(stack);
|
stack = pop(stack); //Entfernt den Knoten 3; Stack ist jetzt [2, 1]
|
||||||
|
|
||||||
// 2. Pop: Prüfe 2
|
// 2. Pop: Prüfe 2
|
||||||
TEST_ASSERT_EQUAL_INT(2, *(int *)top(stack));
|
TEST_ASSERT_EQUAL_INT(2, *(int *)top(stack)); //vergleicht 2 mit top-fkt ausgabe (siehe unity.h)
|
||||||
free(data2);
|
free(data2);
|
||||||
stack = pop(stack);
|
stack = pop(stack); //Entfernt den Knoten 2; Stack ist jetzt [1]
|
||||||
|
|
||||||
// 3. Pop: Prüfe 1
|
// 3. Pop: Prüfe 1
|
||||||
TEST_ASSERT_EQUAL_INT(1, *(int *)top(stack));
|
TEST_ASSERT_EQUAL_INT(1, *(int *)top(stack)); //vergleicht 1 mit top-fkt ausgabe (siehe unity.h)
|
||||||
free(data1);
|
free(data1);
|
||||||
stack = pop(stack);
|
stack = pop(stack); //Entfernt den Knoten 2; Stack ist jetzt NULL
|
||||||
|
|
||||||
TEST_ASSERT_NULL(stack);
|
TEST_ASSERT_NULL(stack); //Prüft ob Stack NULL ist
|
||||||
}
|
}
|
||||||
|
|
||||||
// Testet den Grenzfall: Pop auf einem leeren Stack.
|
// Testet den Grenzfall: Pop auf einem leeren Stack -> soll NULL zurückgeben
|
||||||
void test_popOnEmptyStack(void)
|
void test_popOnEmptyStack(void)
|
||||||
{
|
{
|
||||||
StackNode *stack = NULL;
|
StackNode *stack = NULL; //Initialisiert leeren Stack
|
||||||
// Pop sollte NULL zurückgeben, wenn der Stack leer ist.
|
|
||||||
TEST_ASSERT_NULL(pop(stack));
|
TEST_ASSERT_NULL(pop(stack));// Pop sollte NULL zurückgeben, wenn der Stack leer ist
|
||||||
}
|
}
|
||||||
|
|
||||||
// Testet die Speicherfreigabe (die wichtigste Anforderung der Aufgabenstellung).
|
// Testet die Speicherfreigabe
|
||||||
void test_clearStackFunctionality(void)
|
void test_clearStackFunctionality(void)
|
||||||
{
|
{
|
||||||
StackNode *stack = NULL;
|
StackNode *stack = NULL;
|
||||||
|
|
||||||
// Allokiere Daten und pushe sie auf den Stack
|
// Allokiere Daten und pushe sie auf den Stack
|
||||||
stack = push(stack, createIntPointer(10));
|
stack = push(stack, createIntPointer(10)); //Knoten mit zugehörigem Pointer mit Hilfsfkt
|
||||||
stack = push(stack, createIntPointer(20));
|
stack = push(stack, createIntPointer(20));
|
||||||
stack = push(stack, createIntPointer(30));
|
stack = push(stack, createIntPointer(30));
|
||||||
|
|
||||||
// Die Helferfunktion clearStackWithData ruft free() auf allen Knoten und Daten auf.
|
clearStackWithData(stack); // gibt iterativ alle Daten und Knoten frei
|
||||||
// Wir prüfen implizit, ob die clearStack Logik fehlerfrei durchläuft.
|
|
||||||
clearStackWithData(stack);
|
|
||||||
stack = NULL;
|
stack = NULL;
|
||||||
|
|
||||||
// Wenn der Test ohne Speicherzugriffsverletzung durchläuft, war clearStack erfolgreich.
|
// Wenn der Test ohne Speicherzugriffsverletzung durchläuft, war clearStack erfolgreich.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user