Doble-Spiel/test_numbers.c
2025-12-15 12:42:02 +01:00

161 lines
5.5 KiB
C

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include "unity.h"
#include "numbers.h"
// Externe Deklaration der Vergleichsfunktion aus numbers.c (für den Test)
extern int compareNumbers(const void *arg1, const void *arg2);
// =========================================================================
// HILFSFUNKTIONEN
// =========================================================================
/**
* Zählt in einem Array, wie oft jedes Element vorkommt und stellt sicher,
* dass genau ein Element zweimal (Duplikat) und der Rest einmal vorkommt.
* Dies ist die vollständige Validierung, die der Test 'test_createNumbersGeneratesCorrectDuplicate' nutzt.
* @param numbers Das zu prüfende Array.
* @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)
{
if (len < 3) return 0;
int duplicateCount = 0;
int uniqueCount = 0;
for (unsigned int i = 0; i < len; i++)
{
int occurrences = 0;
// Zähle, wie oft numbers[i] im gesamten Array vorkommt
for (unsigned int j = 0; j < len; j++)
{
if (numbers[i] == numbers[j])
{
occurrences++;
}
}
if (occurrences == 2)
{
duplicateCount++;
}
else if (occurrences == 1)
{
uniqueCount++;
}
else
{
// Eine Zahl kommt 0, 3 oder mehr Male vor -> Fehler
return 0;
}
}
// Wenn genau ein Duplikat vorhanden ist, dann:
// duplicateCount muss 2 sein (da 2 Instanzen der doppelten Zahl gezählt werden)
// uniqueCount muss len - 2 sein (alle anderen Zahlen sind eindeutig)
if (duplicateCount == 2 && uniqueCount == (int)len - 2) {
return 1; // Korrekte Duplikat-Struktur gefunden
}
// Ansonsten ist die Struktur fehlerhaft.
return 0;
}
// =========================================================================
// TESTFALL GRUPPE 1: createNumbers (KERNFUNKTION)
// =========================================================================
// Prüft die wichtigste Anforderung: Zufallsgenerierung, Duplikatprüfung (via BST) und korrekte Array-Struktur
void test_createNumbersCoreFunctionality(void)
{
const unsigned int len = 10; // Definiert Array-Größe (10) für den Test
unsigned int *numbers = createNumbers(len); // Ruft createNumbers-Fkt auf
TEST_ASSERT_NOT_NULL(numbers); // prüft ob Speicher allokiert worden ist
// 1. Prüfe, ob genau ein Duplikat und sonst unikate vorhanden ist (mit Hilffunktion)
TEST_ASSERT_TRUE(validateArrayHasSingleDuplicate(numbers, len));
// 2. Prüfe, ob die Duplikat-Findung funktioniert (Test der Integration von getDuplicate)
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
// 3. Prüfe, ob die Zahlen im erwarteten Bereich [1, 2 * len] liegen
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++) // 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] <= max_val);
}
// Speicher freigeben
free(numbers);
}
// =========================================================================
// TESTFALL GRUPPE 2: getDuplicate (KERNFUNKTION)
// =========================================================================
// Prüft die Duplikaterkennung über qsort auf einem unsortierten Array.
void test_getDuplicateFindsDuplicatedNumber(void)
{
unsigned int testArray[] = {10, 5, 20, 30, 5}; //Definiert ein unsortiertes Array mit dem Duplikat 5
TEST_ASSERT_EQUAL_UINT(5, getDuplicate(testArray, 5)); //Ruft getDuplicate auf, die intern qsort aufruft; Der Test erwartet die Zahl 5 und vergleicht
}
// =========================================================================
// TESTFALL GRUPPE 3: compareNumbers (HILFSFUNKTION FÜR qsort)
// =========================================================================
// Prüft die korrekte Funktionalität der Vergleichsfunktion für alle 3 Fälle.
void test_compareNumbersCheckAllCases(void)
{
unsigned int a = 10, b = 5, c = 10;
//Aufrufen der compareNumbers-fkt
// Fall 1: a > b (muss positiv sein)
TEST_ASSERT_TRUE(compareNumbers(&a, &b) > 0); // (10 > 5) -> return 1 > 0 -> positiver Wert -> True
// Fall 2: b < a (muss negativ sein)
TEST_ASSERT_TRUE(compareNumbers(&b, &a) < 0); // (5 < 10) -> return -1 < 0 -> negativer Wert -> True
// Fall 3: a = c (muss null sein)
TEST_ASSERT_EQUAL_INT(0, compareNumbers(&a, &c)); // (10 = 10) -> return 0 == 0 -> True
}
// =========================================================================
// MAIN
// =========================================================================
void setUp(void) {
// Wird vor jedem Test aufgerufen
}
void tearDown(void) {
// Wird nach jedem Test aufgerufen
}
int main(void)
{
UNITY_BEGIN();
printf("\n============================\nNumbers Module Tests\n============================\n");
// Die essentiellen Tests
RUN_TEST(test_createNumbersCoreFunctionality);
RUN_TEST(test_getDuplicateFindsDuplicatedNumber);
RUN_TEST(test_compareNumbersCheckAllCases);
return UNITY_END();
}