1#include "test_timers.h" 2 3#include "lwip/def.h" 4#include "lwip/timeouts.h" 5#include "arch/sys_arch.h" 6 7/* Setups/teardown functions */ 8 9static struct sys_timeo* old_list_head; 10 11static void 12timers_setup(void) 13{ 14 struct sys_timeo** list_head = sys_timeouts_get_next_timeout(); 15 old_list_head = *list_head; 16 *list_head = NULL; 17} 18 19static void 20timers_teardown(void) 21{ 22 struct sys_timeo** list_head = sys_timeouts_get_next_timeout(); 23 *list_head = old_list_head; 24 lwip_sys_now = 0; 25} 26 27static int fired[3]; 28static void 29dummy_handler(void* arg) 30{ 31 int index = LWIP_PTR_NUMERIC_CAST(int, arg); 32 fired[index] = 1; 33} 34 35#define HANDLER_EXECUTION_TIME 5 36static int cyclic_fired; 37static void 38dummy_cyclic_handler(void) 39{ 40 cyclic_fired = 1; 41 lwip_sys_now += HANDLER_EXECUTION_TIME; 42} 43 44struct lwip_cyclic_timer test_cyclic = {10, dummy_cyclic_handler}; 45 46static void 47do_test_cyclic_timers(u32_t offset) 48{ 49 struct sys_timeo** list_head = sys_timeouts_get_next_timeout(); 50 51 /* verify normal timer expiration */ 52 lwip_sys_now = offset + 0; 53 sys_timeout(test_cyclic.interval_ms, lwip_cyclic_timer, &test_cyclic); 54 55 cyclic_fired = 0; 56 sys_check_timeouts(); 57 fail_unless(cyclic_fired == 0); 58 59 lwip_sys_now = offset + test_cyclic.interval_ms; 60 sys_check_timeouts(); 61 fail_unless(cyclic_fired == 1); 62 63 fail_unless((*list_head)->time == (u32_t)(lwip_sys_now + test_cyclic.interval_ms - HANDLER_EXECUTION_TIME)); 64 65 sys_untimeout(lwip_cyclic_timer, &test_cyclic); 66 67 68 /* verify "overload" - next cyclic timer execution is already overdue twice */ 69 lwip_sys_now = offset + 0; 70 sys_timeout(test_cyclic.interval_ms, lwip_cyclic_timer, &test_cyclic); 71 72 cyclic_fired = 0; 73 sys_check_timeouts(); 74 fail_unless(cyclic_fired == 0); 75 76 lwip_sys_now = offset + 2*test_cyclic.interval_ms; 77 sys_check_timeouts(); 78 fail_unless(cyclic_fired == 1); 79 80 fail_unless((*list_head)->time == (u32_t)(lwip_sys_now + test_cyclic.interval_ms)); 81} 82 83START_TEST(test_cyclic_timers) 84{ 85 LWIP_UNUSED_ARG(_i); 86 87 /* check without u32_t wraparound */ 88 do_test_cyclic_timers(0); 89 90 /* check with u32_t wraparound */ 91 do_test_cyclic_timers(0xfffffff0); 92} 93END_TEST 94 95/* reproduce bug #52748: the bug in timeouts.c */ 96START_TEST(test_bug52748) 97{ 98 LWIP_UNUSED_ARG(_i); 99 100 memset(&fired, 0, sizeof(fired)); 101 102 lwip_sys_now = 50; 103 sys_timeout(20, dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 0)); 104 sys_timeout( 5, dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 2)); 105 106 lwip_sys_now = 55; 107 sys_check_timeouts(); 108 fail_unless(fired[0] == 0); 109 fail_unless(fired[1] == 0); 110 fail_unless(fired[2] == 1); 111 112 lwip_sys_now = 60; 113 sys_timeout(10, dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 1)); 114 sys_check_timeouts(); 115 fail_unless(fired[0] == 0); 116 fail_unless(fired[1] == 0); 117 fail_unless(fired[2] == 1); 118 119 lwip_sys_now = 70; 120 sys_check_timeouts(); 121 fail_unless(fired[0] == 1); 122 fail_unless(fired[1] == 1); 123 fail_unless(fired[2] == 1); 124} 125END_TEST 126 127static void 128do_test_timers(u32_t offset) 129{ 130 struct sys_timeo** list_head = sys_timeouts_get_next_timeout(); 131 132 lwip_sys_now = offset + 0; 133 134 sys_timeout(10, dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 0)); 135 fail_unless(sys_timeouts_sleeptime() == 10); 136 sys_timeout(20, dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 1)); 137 fail_unless(sys_timeouts_sleeptime() == 10); 138 sys_timeout( 5, dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 2)); 139 fail_unless(sys_timeouts_sleeptime() == 5); 140 141 /* linked list correctly sorted? */ 142 fail_unless((*list_head)->time == (u32_t)(lwip_sys_now + 5)); 143 fail_unless((*list_head)->next->time == (u32_t)(lwip_sys_now + 10)); 144 fail_unless((*list_head)->next->next->time == (u32_t)(lwip_sys_now + 20)); 145 146 /* check timers expire in correct order */ 147 memset(&fired, 0, sizeof(fired)); 148 149 lwip_sys_now += 4; 150 sys_check_timeouts(); 151 fail_unless(fired[2] == 0); 152 153 lwip_sys_now += 1; 154 sys_check_timeouts(); 155 fail_unless(fired[2] == 1); 156 157 lwip_sys_now += 4; 158 sys_check_timeouts(); 159 fail_unless(fired[0] == 0); 160 161 lwip_sys_now += 1; 162 sys_check_timeouts(); 163 fail_unless(fired[0] == 1); 164 165 lwip_sys_now += 9; 166 sys_check_timeouts(); 167 fail_unless(fired[1] == 0); 168 169 lwip_sys_now += 1; 170 sys_check_timeouts(); 171 fail_unless(fired[1] == 1); 172 173 sys_untimeout(dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 0)); 174 sys_untimeout(dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 1)); 175 sys_untimeout(dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 2)); 176} 177 178START_TEST(test_timers) 179{ 180 LWIP_UNUSED_ARG(_i); 181 182 /* check without u32_t wraparound */ 183 do_test_timers(0); 184 185 /* check with u32_t wraparound */ 186 do_test_timers(0xfffffff0); 187} 188END_TEST 189 190START_TEST(test_long_timer) 191{ 192 LWIP_UNUSED_ARG(_i); 193 194 memset(&fired, 0, sizeof(fired)); 195 lwip_sys_now = 0; 196 197 sys_timeout(LWIP_UINT32_MAX / 4, dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 0)); 198 fail_unless(sys_timeouts_sleeptime() == LWIP_UINT32_MAX / 4); 199 200 sys_check_timeouts(); 201 fail_unless(fired[0] == 0); 202 203 lwip_sys_now += LWIP_UINT32_MAX / 8; 204 205 sys_check_timeouts(); 206 fail_unless(fired[0] == 0); 207 208 lwip_sys_now += LWIP_UINT32_MAX / 8; 209 210 sys_check_timeouts(); 211 fail_unless(fired[0] == 0); 212 213 lwip_sys_now += 1; 214 215 sys_check_timeouts(); 216 fail_unless(fired[0] == 1); 217 218 sys_untimeout(dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 0)); 219} 220END_TEST 221 222/** Create the suite including all tests for this module */ 223Suite * 224timers_suite(void) 225{ 226 testfunc tests[] = { 227 TESTFUNC(test_bug52748), 228 TESTFUNC(test_cyclic_timers), 229 TESTFUNC(test_timers), 230 TESTFUNC(test_long_timer), 231 }; 232 return create_suite("TIMERS", tests, LWIP_ARRAYSIZE(tests), timers_setup, timers_teardown); 233} 234