2025-12-15 21:04:35 +01:00

142 lines
4.3 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "numbers.h"
/*
* Unit-Tests für createNumbers und getDuplicate:
* - createNumbers liefert ein gültiges Array
* - alle Zahlen liegen im Bereich [1, 2*len]
* - genau eine Zahl kommt doppelt vor
* - getDuplicate findet genau diese doppelte Zahl
* - Fehlerfälle (NULL-Pointer, zu kleine Länge)
*/
/*
* Prüft ein Zahlenarray auf Korrektheit:
* - Array darf nicht NULL sein
* - Wertebereich muss stimmen
* - genau eine Zahl darf doppelt vorkommen
*/
static void check_numbers_array(unsigned int *numbers, unsigned int len)
{
unsigned int maxValue = 2 * len; // Maximal erlaubter Zahlenwert
unsigned int *counts; // Array zum Zählen der Vorkommen
unsigned int i;
unsigned int duplicatesCount = 0; // Zähler für doppelte Werte
assert(numbers != NULL); // Sicherstellen, dass das Array existiert
// Speicher für Zähler-Array reservieren und mit 0 initialisieren
counts = (unsigned int *)calloc(maxValue + 1, sizeof(unsigned int));
assert(counts != NULL); // Prüfen, ob Speicher erfolgreich reserviert wurde
// Schleife über alle Elemente des numbers-Arrays
// Zählt die Werte und prüft gleichzeitig den gültigen Wertebereich
for (i = 0; i < len; ++i)
{
unsigned int v = numbers[i]; // Aktueller Wert
assert(v >= 1 && v <= maxValue); // Wertebereich prüfen
counts[v]++; // Anzahl dieses Wertes erhöhen
}
// Schleife über alle möglichen Werte
// Prüft, dass genau ein Wert doppelt vorkommt
for (i = 1; i <= maxValue; ++i)
{
if (counts[i] == 2)
duplicatesCount++; // Ein doppelter Wert gefunden
else
assert(counts[i] == 0 || counts[i] == 1); // Alle anderen max. einmal
}
assert(duplicatesCount == 1); // Es darf genau ein Duplikat geben
free(counts); // Speicher freigeben
}
/*
* Testet createNumbers und getDuplicate für eine gegebene Länge
*/
static void test_createNumbers_and_getDuplicate(unsigned int len)
{
printf("test_createNumbers_and_getDuplicate(len=%u)...\n", len);
// Zahlenarray erzeugen
unsigned int *numbers = createNumbers(len);
assert(numbers != NULL); // Rückgabewert prüfen
// Struktur und Inhalt des Arrays überprüfen
check_numbers_array(numbers, len);
// Erneutes Zählen, um das erwartete Duplikat zu ermitteln
unsigned int maxValue = 2 * len;
unsigned int *counts = (unsigned int *)calloc(maxValue + 1, sizeof(unsigned int));
assert(counts != NULL);
// Schleife zum Zählen aller Werte
for (unsigned int i = 0; i < len; ++i)
{
unsigned int v = numbers[i];
counts[v]++;
}
// Schleife zur Bestimmung des doppelten Wertes
unsigned int expectedDuplicate = 0;
for (unsigned int v = 1; v <= maxValue; ++v)
{
if (counts[v] == 2)
{
expectedDuplicate = v; // Doppelten Wert merken
break;
}
}
assert(expectedDuplicate != 0); // Es muss ein Duplikat existieren
// getDuplicate-Funktion testen
unsigned int found = getDuplicate(numbers, len);
assert(found == expectedDuplicate); // Ergebnis vergleichen
free(counts); // Speicher freigeben
free(numbers);
printf("...OK\n");
}
/*
* Testet Fehlerfälle für getDuplicate
*/
static void test_getDuplicate_error_cases(void)
{
printf("test_getDuplicate_error_cases...\n");
// Test mit NULL-Pointer
unsigned int dup = getDuplicate(NULL, 10);
assert(dup == 0);
// Test mit zu kleiner Länge (< 2)
unsigned int dummy[1] = {42};
dup = getDuplicate(dummy, 1);
assert(dup == 0);
printf("...OK\n");
}
/*
* Hauptfunktion: startet alle Unit-Tests
*/
int main(void)
{
printf("Running numbers unit tests...\n\n");
// Typische Testfälle mit unterschiedlichen Array-Längen
test_createNumbers_and_getDuplicate(5);
test_createNumbers_and_getDuplicate(10);
test_createNumbers_and_getDuplicate(20);
// Test der Fehlerfälle
test_getDuplicate_error_cases();
printf("\nAll numbers tests passed.\n");
return 0;
}