From 461562b59b1bb6954e7af70d8df4c28532866a85 Mon Sep 17 00:00:00 2001 From: z004x46y Date: Mon, 15 Dec 2025 19:42:56 +0100 Subject: [PATCH] Unity-Tests numbers --- test_numbers.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 test_numbers.c diff --git a/test_numbers.c b/test_numbers.c new file mode 100644 index 0000000..a748fe6 --- /dev/null +++ b/test_numbers.c @@ -0,0 +1,162 @@ + +// test_numbers_unity.c +#include "unity.h" +#include "numbers.h" + +#include +#include + +/* ===================== Test-Fixture ===================== */ +void setUp(void) { /* nothing */ } +void tearDown(void){ /* nothing */ } + +/* ===================== Helpers ===================== */ + +// Zählt Vorkommen eines Werts im Array +static unsigned count_occurrences(const unsigned int *arr, unsigned int len, unsigned int value) +{ + unsigned cnt = 0; + for (unsigned i = 0; i < len; ++i) + if (arr[i] == value) ++cnt; + return cnt; +} + +/* Prüft Eigenschaften von createNumbers: + - Wertebereich: [1..2*len] + - Genau EIN Wert doppelt (keiner > 2x) + Liefert den doppelten Wert per Out-Param zurück. +*/ +static void assert_numbers_properties(const unsigned int *arr, unsigned int len, unsigned int *dup_out) +{ + TEST_ASSERT_NOT_NULL(arr); + TEST_ASSERT_TRUE(len >= 2); + + const unsigned int maxVal = 2 * len; + + // Häufigkeitstabelle von 0..maxVal (0 bleibt ungenutzt) + unsigned int *counts = (unsigned int*)calloc(maxVal + 1, sizeof(unsigned int)); + TEST_ASSERT_NOT_NULL_MESSAGE(counts, "calloc(counts) failed"); + + for (unsigned int i = 0; i < len; ++i) + { + unsigned int v = arr[i]; + TEST_ASSERT_TRUE_MESSAGE(v >= 1 && v <= maxVal, "value out of [1..2*len]"); + counts[v]++; + } + + int dupCount = 0; + unsigned int dupVal = 0; + for (unsigned int v = 1; v <= maxVal; ++v) + { + if (counts[v] == 2) { dupCount++; dupVal = v; } + TEST_ASSERT_LESS_OR_EQUAL_UINT_MESSAGE(2u, counts[v], "a value occurs more than twice"); + } + + free(counts); + + TEST_ASSERT_EQUAL_INT_MESSAGE(1, dupCount, "not exactly one duplicated value"); + if (dup_out) *dup_out = dupVal; +} + +/* ===================== Einzeltests ===================== */ + +// createNumbers: len < 2 -> NULL +static void test_createNumbers_len_too_small(void) +{ + TEST_ASSERT_NULL(createNumbers(0)); + TEST_ASSERT_NULL(createNumbers(1)); +} + +// createNumbers: Eigenschaften bei repräsentativer Länge +static void test_createNumbers_properties_len20(void) +{ + const unsigned int len = 20; + unsigned int *arr = createNumbers(len); + TEST_ASSERT_NOT_NULL(arr); + + unsigned int dupVal = 0; + assert_numbers_properties(arr, len, &dupVal); + + // Der gefundene doppelte Wert muss auch wirklich genau 2x im Array stehen + TEST_ASSERT_EQUAL_UINT(2u, count_occurrences(arr, len, dupVal)); + + free(arr); +} + +// getDuplicate: Minimalfall [x, x] -> x +static void test_getDuplicate_minimal_pair(void) +{ + unsigned int a[2] = { 5, 5 }; + TEST_ASSERT_EQUAL_UINT(5u, getDuplicate(a, 2)); +} + +// getDuplicate: Bekannte, unsortierte Arrays +static void test_getDuplicate_known_arrays(void) +{ + unsigned int a1[] = {1,2,3,4,5,3}; // dup = 3 + unsigned int a2[] = {7,1,3,4,7}; // dup = 7 + unsigned int a3[] = {9,8,9,1,2,3,4}; // dup = 9 + + TEST_ASSERT_EQUAL_UINT(3u, getDuplicate(a1, (unsigned) (sizeof a1/sizeof a1[0]))); + TEST_ASSERT_EQUAL_UINT(7u, getDuplicate(a2, (unsigned) (sizeof a2/sizeof a2[0]))); + TEST_ASSERT_EQUAL_UINT(9u, getDuplicate(a3, (unsigned) (sizeof a3/sizeof a3[0]))); +} + +// getDuplicate: Ungültige Eingaben -> 0 +static void test_getDuplicate_invalid_inputs(void) +{ + TEST_ASSERT_EQUAL_UINT(0u, getDuplicate(NULL, 10)); + unsigned int x = 42; + TEST_ASSERT_EQUAL_UINT(0u, getDuplicate(&x, 1)); +} + +// Integration: createNumbers + getDuplicate (mehrere Läufe) +static void test_integration_create_then_getDuplicate_multi_runs(void) +{ + const unsigned int len = 30; + for (int run = 0; run < 3; ++run) + { + unsigned int *arr = createNumbers(len); + TEST_ASSERT_NOT_NULL(arr); + + // Eigenschaften prüfen + unsigned int dupVal = 0; + assert_numbers_properties(arr, len, &dupVal); + + // getDuplicate muss genau diesen Wert liefern + TEST_ASSERT_EQUAL_UINT(dupVal, getDuplicate(arr, len)); + + free(arr); + } +} + +// getDuplicate verändert das Original-Array NICHT +static void test_getDuplicate_does_not_modify_input(void) +{ + unsigned int arr[] = { 10, 2, 10, 7, 8, 9, 1 }; + unsigned int original[sizeof arr/sizeof arr[0]]; + memcpy(original, arr, sizeof arr); + + unsigned int dup = getDuplicate(arr, (unsigned) (sizeof arr/sizeof arr[0])); + TEST_ASSERT_EQUAL_UINT(10u, dup); + + // Speicherinhalt identisch? + TEST_ASSERT_EQUAL_MEMORY(original, arr, sizeof arr); +} + +/* ===================== Runner ===================== */ + +int main(void) +{ + UNITY_BEGIN(); + + RUN_TEST(test_createNumbers_len_too_small); + RUN_TEST(test_createNumbers_properties_len20); + RUN_TEST(test_getDuplicate_minimal_pair); + RUN_TEST(test_getDuplicate_known_arrays); + RUN_TEST(test_getDuplicate_invalid_inputs); + RUN_TEST(test_integration_create_then_getDuplicate_multi_runs); + RUN_TEST(test_getDuplicate_does_not_modify_input); + + return UNITY_END(); +}