summaryrefslogtreecommitdiff
path: root/test/unit/core/test_timers.c
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2024-10-16 08:10:14 -0600
committerTom Rini <trini@konsulko.com>2024-10-16 08:10:14 -0600
commitf3f86fd1fe0fb288356bff78f8a6fa2edf89e3fc (patch)
treef0a99ea87d92f63895a6d053e3185838ebecf2d0 /test/unit/core/test_timers.c
Squashed 'lib/lwip/lwip/' content from commit 0a0452b2c39b
git-subtree-dir: lib/lwip/lwip git-subtree-split: 0a0452b2c39bdd91e252aef045c115f88f6ca773
Diffstat (limited to 'test/unit/core/test_timers.c')
-rw-r--r--test/unit/core/test_timers.c233
1 files changed, 233 insertions, 0 deletions
diff --git a/test/unit/core/test_timers.c b/test/unit/core/test_timers.c
new file mode 100644
index 00000000000..820b718924f
--- /dev/null
+++ b/test/unit/core/test_timers.c
@@ -0,0 +1,233 @@
+#include "test_timers.h"
+
+#include "lwip/def.h"
+#include "lwip/timeouts.h"
+#include "arch/sys_arch.h"
+
+/* Setups/teardown functions */
+
+static struct sys_timeo* old_list_head;
+
+static void
+timers_setup(void)
+{
+ struct sys_timeo** list_head = sys_timeouts_get_next_timeout();
+ old_list_head = *list_head;
+ *list_head = NULL;
+}
+
+static void
+timers_teardown(void)
+{
+ struct sys_timeo** list_head = sys_timeouts_get_next_timeout();
+ *list_head = old_list_head;
+ lwip_sys_now = 0;
+}
+
+static int fired[3];
+static void
+dummy_handler(void* arg)
+{
+ int index = LWIP_PTR_NUMERIC_CAST(int, arg);
+ fired[index] = 1;
+}
+
+#define HANDLER_EXECUTION_TIME 5
+static int cyclic_fired;
+static void
+dummy_cyclic_handler(void)
+{
+ cyclic_fired = 1;
+ lwip_sys_now += HANDLER_EXECUTION_TIME;
+}
+
+struct lwip_cyclic_timer test_cyclic = {10, dummy_cyclic_handler};
+
+static void
+do_test_cyclic_timers(u32_t offset)
+{
+ struct sys_timeo** list_head = sys_timeouts_get_next_timeout();
+
+ /* verify normal timer expiration */
+ lwip_sys_now = offset + 0;
+ sys_timeout(test_cyclic.interval_ms, lwip_cyclic_timer, &test_cyclic);
+
+ cyclic_fired = 0;
+ sys_check_timeouts();
+ fail_unless(cyclic_fired == 0);
+
+ lwip_sys_now = offset + test_cyclic.interval_ms;
+ sys_check_timeouts();
+ fail_unless(cyclic_fired == 1);
+
+ fail_unless((*list_head)->time == (u32_t)(lwip_sys_now + test_cyclic.interval_ms - HANDLER_EXECUTION_TIME));
+
+ sys_untimeout(lwip_cyclic_timer, &test_cyclic);
+
+
+ /* verify "overload" - next cyclic timer execution is already overdue twice */
+ lwip_sys_now = offset + 0;
+ sys_timeout(test_cyclic.interval_ms, lwip_cyclic_timer, &test_cyclic);
+
+ cyclic_fired = 0;
+ sys_check_timeouts();
+ fail_unless(cyclic_fired == 0);
+
+ lwip_sys_now = offset + 2*test_cyclic.interval_ms;
+ sys_check_timeouts();
+ fail_unless(cyclic_fired == 1);
+
+ fail_unless((*list_head)->time == (u32_t)(lwip_sys_now + test_cyclic.interval_ms));
+}
+
+START_TEST(test_cyclic_timers)
+{
+ LWIP_UNUSED_ARG(_i);
+
+ /* check without u32_t wraparound */
+ do_test_cyclic_timers(0);
+
+ /* check with u32_t wraparound */
+ do_test_cyclic_timers(0xfffffff0);
+}
+END_TEST
+
+/* reproduce bug #52748: the bug in timeouts.c */
+START_TEST(test_bug52748)
+{
+ LWIP_UNUSED_ARG(_i);
+
+ memset(&fired, 0, sizeof(fired));
+
+ lwip_sys_now = 50;
+ sys_timeout(20, dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 0));
+ sys_timeout( 5, dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 2));
+
+ lwip_sys_now = 55;
+ sys_check_timeouts();
+ fail_unless(fired[0] == 0);
+ fail_unless(fired[1] == 0);
+ fail_unless(fired[2] == 1);
+
+ lwip_sys_now = 60;
+ sys_timeout(10, dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 1));
+ sys_check_timeouts();
+ fail_unless(fired[0] == 0);
+ fail_unless(fired[1] == 0);
+ fail_unless(fired[2] == 1);
+
+ lwip_sys_now = 70;
+ sys_check_timeouts();
+ fail_unless(fired[0] == 1);
+ fail_unless(fired[1] == 1);
+ fail_unless(fired[2] == 1);
+}
+END_TEST
+
+static void
+do_test_timers(u32_t offset)
+{
+ struct sys_timeo** list_head = sys_timeouts_get_next_timeout();
+
+ lwip_sys_now = offset + 0;
+
+ sys_timeout(10, dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 0));
+ fail_unless(sys_timeouts_sleeptime() == 10);
+ sys_timeout(20, dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 1));
+ fail_unless(sys_timeouts_sleeptime() == 10);
+ sys_timeout( 5, dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 2));
+ fail_unless(sys_timeouts_sleeptime() == 5);
+
+ /* linked list correctly sorted? */
+ fail_unless((*list_head)->time == (u32_t)(lwip_sys_now + 5));
+ fail_unless((*list_head)->next->time == (u32_t)(lwip_sys_now + 10));
+ fail_unless((*list_head)->next->next->time == (u32_t)(lwip_sys_now + 20));
+
+ /* check timers expire in correct order */
+ memset(&fired, 0, sizeof(fired));
+
+ lwip_sys_now += 4;
+ sys_check_timeouts();
+ fail_unless(fired[2] == 0);
+
+ lwip_sys_now += 1;
+ sys_check_timeouts();
+ fail_unless(fired[2] == 1);
+
+ lwip_sys_now += 4;
+ sys_check_timeouts();
+ fail_unless(fired[0] == 0);
+
+ lwip_sys_now += 1;
+ sys_check_timeouts();
+ fail_unless(fired[0] == 1);
+
+ lwip_sys_now += 9;
+ sys_check_timeouts();
+ fail_unless(fired[1] == 0);
+
+ lwip_sys_now += 1;
+ sys_check_timeouts();
+ fail_unless(fired[1] == 1);
+
+ sys_untimeout(dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 0));
+ sys_untimeout(dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 1));
+ sys_untimeout(dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 2));
+}
+
+START_TEST(test_timers)
+{
+ LWIP_UNUSED_ARG(_i);
+
+ /* check without u32_t wraparound */
+ do_test_timers(0);
+
+ /* check with u32_t wraparound */
+ do_test_timers(0xfffffff0);
+}
+END_TEST
+
+START_TEST(test_long_timer)
+{
+ LWIP_UNUSED_ARG(_i);
+
+ memset(&fired, 0, sizeof(fired));
+ lwip_sys_now = 0;
+
+ sys_timeout(LWIP_UINT32_MAX / 4, dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 0));
+ fail_unless(sys_timeouts_sleeptime() == LWIP_UINT32_MAX / 4);
+
+ sys_check_timeouts();
+ fail_unless(fired[0] == 0);
+
+ lwip_sys_now += LWIP_UINT32_MAX / 8;
+
+ sys_check_timeouts();
+ fail_unless(fired[0] == 0);
+
+ lwip_sys_now += LWIP_UINT32_MAX / 8;
+
+ sys_check_timeouts();
+ fail_unless(fired[0] == 0);
+
+ lwip_sys_now += 1;
+
+ sys_check_timeouts();
+ fail_unless(fired[0] == 1);
+
+ sys_untimeout(dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 0));
+}
+END_TEST
+
+/** Create the suite including all tests for this module */
+Suite *
+timers_suite(void)
+{
+ testfunc tests[] = {
+ TESTFUNC(test_bug52748),
+ TESTFUNC(test_cyclic_timers),
+ TESTFUNC(test_timers),
+ TESTFUNC(test_long_timer),
+ };
+ return create_suite("TIMERS", tests, LWIP_ARRAYSIZE(tests), timers_setup, timers_teardown);
+}