#include #include #include #include #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(); }