1 /*
2 * Copyright (c) 2016, The OpenThread Authors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "test_platform.h"
30
31 #include "common/code_utils.hpp"
32 #include "common/debug.hpp"
33 #include "common/instance.hpp"
34 #include "common/timer.hpp"
35
36 enum
37 {
38 kCallCountIndexAlarmStop = 0,
39 kCallCountIndexAlarmStart,
40 kCallCountIndexTimerHandler,
41
42 kCallCountIndexMax
43 };
44
45 uint32_t sNow;
46 uint32_t sPlatT0;
47 uint32_t sPlatDt;
48 bool sTimerOn;
49 uint32_t sCallCount[kCallCountIndexMax];
50
testTimerAlarmStop(otInstance *)51 void testTimerAlarmStop(otInstance *)
52 {
53 sTimerOn = false;
54 sCallCount[kCallCountIndexAlarmStop]++;
55 }
56
testTimerAlarmStartAt(otInstance *,uint32_t aT0,uint32_t aDt)57 void testTimerAlarmStartAt(otInstance *, uint32_t aT0, uint32_t aDt)
58 {
59 sTimerOn = true;
60 sCallCount[kCallCountIndexAlarmStart]++;
61 sPlatT0 = aT0;
62 sPlatDt = aDt;
63 }
64
testTimerAlarmGetNow(void)65 uint32_t testTimerAlarmGetNow(void)
66 {
67 return sNow;
68 }
69
InitTestTimer(void)70 void InitTestTimer(void)
71 {
72 g_testPlatAlarmStop = testTimerAlarmStop;
73 g_testPlatAlarmStartAt = testTimerAlarmStartAt;
74 g_testPlatAlarmGetNow = testTimerAlarmGetNow;
75 }
76
InitCounters(void)77 void InitCounters(void)
78 {
79 memset(sCallCount, 0, sizeof(sCallCount));
80 }
81
82 /**
83 * `TestTimer` sub-classes `ot::TimerMilli` and provides a handler and a counter to keep track of number of times timer
84 * gets fired.
85 */
86 template <typename TimerType> class TestTimer : public TimerType
87 {
88 public:
TestTimer(ot::Instance & aInstance)89 explicit TestTimer(ot::Instance &aInstance)
90 : TimerType(aInstance, TestTimer::HandleTimerFired)
91 , mFiredCounter(0)
92 {
93 }
94
HandleTimerFired(ot::Timer & aTimer)95 static void HandleTimerFired(ot::Timer &aTimer) { static_cast<TestTimer &>(aTimer).HandleTimerFired(); }
96
HandleTimerFired(void)97 void HandleTimerFired(void)
98 {
99 sCallCount[kCallCountIndexTimerHandler]++;
100 mFiredCounter++;
101 }
102
GetFiredCounter(void)103 uint32_t GetFiredCounter(void) { return mFiredCounter; }
104
ResetFiredCounter(void)105 void ResetFiredCounter(void) { mFiredCounter = 0; }
106
RemoveAll(ot::Instance & aInstance)107 static void RemoveAll(ot::Instance &aInstance) { TimerType::RemoveAll(aInstance); }
108
109 private:
110 uint32_t mFiredCounter; //< Number of times timer has been fired so far
111 };
112
113 template <typename TimerType> void AlarmFired(otInstance *aInstance);
114
AlarmFired(otInstance * aInstance)115 template <> void AlarmFired<ot::TimerMilli>(otInstance *aInstance)
116 {
117 otPlatAlarmMilliFired(aInstance);
118 }
119
120 #if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
AlarmFired(otInstance * aInstance)121 template <> void AlarmFired<ot::TimerMicro>(otInstance *aInstance)
122 {
123 otPlatAlarmMicroFired(aInstance);
124 }
125 #endif
126
127 /**
128 * Test the TimerScheduler's behavior of one timer started and fired.
129 */
TestOneTimer(void)130 template <typename TimerType> int TestOneTimer(void)
131 {
132 const uint32_t kTimeT0 = 1000;
133 const uint32_t kTimerInterval = 10;
134 ot::Instance * instance = testInitInstance();
135 TestTimer<TimerType> timer(*instance);
136
137 // Test one Timer basic operation.
138
139 TestTimer<TimerType>::RemoveAll(*instance);
140 InitTestTimer();
141 InitCounters();
142
143 printf("TestOneTimer() ");
144
145 sNow = kTimeT0;
146 timer.Start(kTimerInterval);
147
148 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "Start CallCount Failed.");
149 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
150 VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "Handler CallCount Failed.");
151 VerifyOrQuit(sPlatT0 == 1000 && sPlatDt == 10, "Start params Failed.");
152 VerifyOrQuit(timer.IsRunning(), "Timer running Failed.");
153 VerifyOrQuit(sTimerOn, "Platform Timer State Failed.");
154
155 sNow += kTimerInterval;
156
157 AlarmFired<TimerType>(instance);
158
159 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "Start CallCount Failed.");
160 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 1, "Stop CallCount Failed.");
161 VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 1, "Handler CallCount Failed.");
162 VerifyOrQuit(timer.IsRunning() == false, "Timer running Failed.");
163 VerifyOrQuit(sTimerOn == false, "Platform Timer State Failed.");
164
165 // Test one Timer that spans the 32-bit wrap.
166
167 InitCounters();
168
169 sNow = 0 - (kTimerInterval - 2);
170 timer.Start(kTimerInterval);
171
172 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "Start CallCount Failed.");
173 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
174 VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "Handler CallCount Failed.");
175 VerifyOrQuit(sPlatT0 == 0 - (kTimerInterval - 2) && sPlatDt == 10, "Start params Failed.");
176 VerifyOrQuit(timer.IsRunning(), "Timer running Failed.");
177 VerifyOrQuit(sTimerOn, "Platform Timer State Failed.");
178
179 sNow += kTimerInterval;
180
181 AlarmFired<TimerType>(instance);
182
183 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "Start CallCount Failed.");
184 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 1, "Stop CallCount Failed.");
185 VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 1, "Handler CallCount Failed.");
186 VerifyOrQuit(timer.IsRunning() == false, "Timer running Failed.");
187 VerifyOrQuit(sTimerOn == false, "Platform Timer State Failed.");
188
189 // Test one Timer that is late by several msec
190
191 InitCounters();
192
193 sNow = kTimeT0;
194 timer.Start(kTimerInterval);
195
196 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "Start CallCount Failed.");
197 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
198 VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "Handler CallCount Failed.");
199 VerifyOrQuit(sPlatT0 == 1000 && sPlatDt == 10, "Start params Failed.");
200 VerifyOrQuit(timer.IsRunning(), "Timer running Failed.");
201 VerifyOrQuit(sTimerOn, "Platform Timer State Failed.");
202
203 sNow += kTimerInterval + 5;
204
205 AlarmFired<TimerType>(instance);
206
207 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "Start CallCount Failed.");
208 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 1, "Stop CallCount Failed.");
209 VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 1, "Handler CallCount Failed.");
210 VerifyOrQuit(timer.IsRunning() == false, "Timer running Failed.");
211 VerifyOrQuit(sTimerOn == false, "Platform Timer State Failed.");
212
213 // Test one Timer that is early by several msec
214
215 InitCounters();
216
217 sNow = kTimeT0;
218 timer.Start(kTimerInterval);
219
220 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "Start CallCount Failed.");
221 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
222 VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "Handler CallCount Failed.");
223 VerifyOrQuit(sPlatT0 == 1000 && sPlatDt == 10, "Start params Failed.");
224 VerifyOrQuit(timer.IsRunning(), "Timer running Failed.");
225 VerifyOrQuit(sTimerOn, "Platform Timer State Failed.");
226
227 sNow += kTimerInterval - 2;
228
229 AlarmFired<TimerType>(instance);
230
231 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 2, "Start CallCount Failed.");
232 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
233 VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "Handler CallCount Failed.");
234 VerifyOrQuit(timer.IsRunning() == true, "Timer running Failed.");
235 VerifyOrQuit(sTimerOn == true, "Platform Timer State Failed.");
236
237 sNow += kTimerInterval;
238
239 AlarmFired<TimerType>(instance);
240
241 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 2, "Start CallCount Failed.");
242 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 1, "Stop CallCount Failed.");
243 VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 1, "Handler CallCount Failed.");
244 VerifyOrQuit(timer.IsRunning() == false, "Timer running Failed.");
245 VerifyOrQuit(sTimerOn == false, "Platform Timer State Failed.");
246
247 printf(" --> PASSED\n");
248
249 testFreeInstance(instance);
250
251 return 0;
252 }
253
254 /**
255 * Test the TimerScheduler's behavior of two timers started and fired.
256 */
TestTwoTimers(void)257 template <typename TimerType> int TestTwoTimers(void)
258 {
259 const uint32_t kTimeT0 = 1000;
260 const uint32_t kTimerInterval = 10;
261 ot::Instance * instance = testInitInstance();
262 TestTimer<TimerType> timer1(*instance);
263 TestTimer<TimerType> timer2(*instance);
264
265 TestTimer<TimerType>::RemoveAll(*instance);
266 InitTestTimer();
267 printf("TestTwoTimers() ");
268
269 // Test when second timer stars at the fire time of first timer (before alarm callback).
270
271 InitCounters();
272
273 sNow = kTimeT0;
274 timer1.Start(kTimerInterval);
275
276 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "Start CallCount Failed.");
277 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
278 VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "Handler CallCount Failed.");
279 VerifyOrQuit(sPlatT0 == kTimeT0 && sPlatDt == kTimerInterval, "Start params Failed.");
280 VerifyOrQuit(timer1.IsRunning(), "Timer running Failed.");
281 VerifyOrQuit(timer2.IsRunning() == false, "Timer running Failed.");
282 VerifyOrQuit(sTimerOn, "Platform Timer State Failed.");
283
284 sNow += kTimerInterval;
285
286 timer2.Start(kTimerInterval);
287
288 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "Start CallCount Failed.");
289 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
290 VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "Handler CallCount Failed.");
291 VerifyOrQuit(sPlatT0 == kTimeT0 && sPlatDt == kTimerInterval, "Start params Failed.");
292 VerifyOrQuit(timer1.IsRunning() == true, "Timer running Failed.");
293 VerifyOrQuit(timer2.IsRunning() == true, "Timer running Failed.");
294 VerifyOrQuit(sTimerOn, "Platform Timer State Failed.");
295
296 AlarmFired<TimerType>(instance);
297
298 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 2, "Start CallCount Failed.");
299 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
300 VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 1, "Handler CallCount Failed.");
301 VerifyOrQuit(timer1.GetFiredCounter() == 1, "Fire Counter failed.");
302 VerifyOrQuit(sPlatT0 == sNow && sPlatDt == kTimerInterval, "Start params Failed.");
303 VerifyOrQuit(timer1.IsRunning() == false, "Timer running Failed.");
304 VerifyOrQuit(timer2.IsRunning() == true, "Timer running Failed.");
305 VerifyOrQuit(sTimerOn == true, "Platform Timer State Failed.");
306
307 sNow += kTimerInterval;
308 AlarmFired<TimerType>(instance);
309
310 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 2, "Start CallCount Failed.");
311 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 1, "Stop CallCount Failed.");
312 VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 2, "Handler CallCount Failed.");
313 VerifyOrQuit(timer2.GetFiredCounter() == 1, "Fire Counter failed.");
314 VerifyOrQuit(timer1.IsRunning() == false, "Timer running Failed.");
315 VerifyOrQuit(timer2.IsRunning() == false, "Timer running Failed.");
316 VerifyOrQuit(sTimerOn == false, "Platform Timer State Failed.");
317
318 // Test when second timer starts at the fire time of first timer (before AlarmFired<TimerType>()) and its fire time
319 // is before the first timer. Ensure that the second timer handler is invoked before the first one.
320
321 InitCounters();
322 timer1.ResetFiredCounter();
323 timer2.ResetFiredCounter();
324
325 sNow = kTimeT0;
326 timer1.Start(kTimerInterval);
327
328 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "Start CallCount Failed.");
329 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
330 VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "Handler CallCount Failed.");
331 VerifyOrQuit(sPlatT0 == kTimeT0 && sPlatDt == kTimerInterval, "Start params Failed.");
332 VerifyOrQuit(timer1.IsRunning(), "Timer running Failed.");
333 VerifyOrQuit(timer2.IsRunning() == false, "Timer running Failed.");
334 VerifyOrQuit(sTimerOn, "Platform Timer State Failed.");
335
336 sNow += kTimerInterval;
337
338 timer2.StartAt(ot::TimeMilli(kTimeT0), kTimerInterval - 2); // Timer 2 is even before timer 1
339
340 VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "Handler CallCount Failed.");
341 VerifyOrQuit(timer1.IsRunning() == true, "Timer running Failed.");
342 VerifyOrQuit(timer2.IsRunning() == true, "Timer running Failed.");
343 VerifyOrQuit(sTimerOn, "Platform Timer State Failed.");
344
345 AlarmFired<TimerType>(instance);
346
347 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
348 VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 1, "Handler CallCount Failed.");
349 VerifyOrQuit(timer2.GetFiredCounter() == 1, "Fire Counter failed.");
350 VerifyOrQuit(sPlatT0 == sNow && sPlatDt == 0, "Start params Failed.");
351 VerifyOrQuit(timer1.IsRunning() == true, "Timer running Failed.");
352 VerifyOrQuit(timer2.IsRunning() == false, "Timer running Failed.");
353 VerifyOrQuit(sTimerOn == true, "Platform Timer State Failed.");
354
355 AlarmFired<TimerType>(instance);
356
357 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 1, "Stop CallCount Failed.");
358 VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 2, "Handler CallCount Failed.");
359 VerifyOrQuit(timer1.GetFiredCounter() == 1, "Fire Counter failed.");
360 VerifyOrQuit(timer1.IsRunning() == false, "Timer running Failed.");
361 VerifyOrQuit(timer2.IsRunning() == false, "Timer running Failed.");
362 VerifyOrQuit(sTimerOn == false, "Platform Timer State Failed.");
363
364 // Timer 1 fire callback is late by some ticks/ms, and second timer is scheduled (before call to
365 // AlarmFired) with a maximum interval. This is to test (corner-case) scenario where the fire time of two
366 // timers spanning over the maximum interval.
367
368 InitCounters();
369 timer1.ResetFiredCounter();
370 timer2.ResetFiredCounter();
371
372 sNow = kTimeT0;
373 timer1.Start(kTimerInterval);
374
375 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "Start CallCount Failed.");
376 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
377 VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "Handler CallCount Failed.");
378 VerifyOrQuit(sPlatT0 == kTimeT0 && sPlatDt == kTimerInterval, "Start params Failed.");
379 VerifyOrQuit(timer1.IsRunning(), "Timer running Failed.");
380 VerifyOrQuit(timer2.IsRunning() == false, "Timer running Failed.");
381 VerifyOrQuit(sTimerOn, "Platform Timer State Failed.");
382
383 sNow += kTimerInterval + 5;
384
385 timer2.Start(ot::Timer::kMaxDelay);
386
387 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "Start CallCount Failed.");
388 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
389 VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "Handler CallCount Failed.");
390 VerifyOrQuit(timer1.IsRunning() == true, "Timer running Failed.");
391 VerifyOrQuit(timer2.IsRunning() == true, "Timer running Failed.");
392 VerifyOrQuit(sTimerOn, "Platform Timer State Failed.");
393
394 AlarmFired<TimerType>(instance);
395
396 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 2, "Start CallCount Failed.");
397 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
398 VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 1, "Handler CallCount Failed.");
399 VerifyOrQuit(timer1.GetFiredCounter() == 1, "Fire Counter failed.");
400 VerifyOrQuit(sPlatT0 == sNow, "Start params Failed.");
401 VerifyOrQuit(sPlatDt == ot::Timer::kMaxDelay, "Start params Failed.");
402 VerifyOrQuit(timer1.IsRunning() == false, "Timer running Failed.");
403 VerifyOrQuit(timer2.IsRunning() == true, "Timer running Failed.");
404 VerifyOrQuit(sTimerOn == true, "Platform Timer State Failed.");
405
406 sNow += ot::Timer::kMaxDelay;
407 AlarmFired<TimerType>(instance);
408
409 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 2, "Start CallCount Failed.");
410 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 1, "Stop CallCount Failed.");
411 VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 2, "Handler CallCount Failed.");
412 VerifyOrQuit(timer2.GetFiredCounter() == 1, "Fire Counter failed.");
413 VerifyOrQuit(timer1.IsRunning() == false, "Timer running Failed.");
414 VerifyOrQuit(timer2.IsRunning() == false, "Timer running Failed.");
415 VerifyOrQuit(sTimerOn == false, "Platform Timer State Failed.");
416
417 printf(" --> PASSED\n");
418
419 testFreeInstance(instance);
420
421 return 0;
422 }
423
424 /**
425 * Test the TimerScheduler's behavior of ten timers started and fired.
426 *
427 * `aTimeShift` is added to the t0 and trigger times for all timers. It can be used to check the ten timer behavior
428 * at different start time (e.g., around a 32-bit wrap).
429 */
TenTimers(uint32_t aTimeShift)430 template <typename TimerType> static void TenTimers(uint32_t aTimeShift)
431 {
432 const uint32_t kNumTimers = 10;
433 const uint32_t kNumTriggers = 7;
434 const uint32_t kTimeT0[kNumTimers] = {1000, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008};
435 const uint32_t kTimerInterval[kNumTimers] = {
436 20, 100, (ot::Timer::kMaxDelay - kTimeT0[2]), 100000, 1000000, 10, ot::Timer::kMaxDelay, 200, 200, 200};
437 // Expected timer fire order
438 // timer # Trigger time
439 // 5 1014
440 // 0 1020
441 // 1 1100
442 // 7 1206
443 // 8 1207
444 // 9 1208
445 // 3 101002
446 // 4 1001003
447 // 2 kMaxDuration
448 // 6 kMaxDuration + 1005
449 const uint32_t kTriggerTimes[kNumTriggers] = {
450 1014, 1020, 1100, 1207, 101004, ot::Timer::kMaxDelay, ot::Timer::kMaxDelay + kTimeT0[6]};
451 // Expected timers fired by each kTriggerTimes[] value
452 // Trigger # Timers Fired
453 // 0 5
454 // 1 0
455 // 2 1
456 // 3 7, 8
457 // 4 9, 3
458 // 5 4, 2
459 // 6 6
460 const bool kTimerStateAfterTrigger[kNumTriggers][kNumTimers] = {
461 {true, true, true, true, true, false, true, true, true, true}, // 5
462 {false, true, true, true, true, false, true, true, true, true}, // 0
463 {false, false, true, true, true, false, true, true, true, true}, // 1
464 {false, false, true, true, true, false, true, false, false, true}, // 7, 8
465 {false, false, true, false, true, false, true, false, false, false}, // 9, 3
466 {false, false, false, false, false, false, true, false, false, false}, // 4, 2
467 {false, false, false, false, false, false, false, false, false, false} // 6
468 };
469
470 const bool kSchedulerStateAfterTrigger[kNumTriggers] = {true, true, true, true, true, true, false};
471
472 const uint32_t kTimerHandlerCountAfterTrigger[kNumTriggers] = {1, 2, 3, 5, 7, 9, 10};
473
474 const uint32_t kTimerStopCountAfterTrigger[kNumTriggers] = {0, 0, 0, 0, 0, 0, 1};
475
476 const uint32_t kTimerStartCountAfterTrigger[kNumTriggers] = {3, 4, 5, 7, 9, 11, 11};
477
478 ot::Instance *instance = testInitInstance();
479
480 TestTimer<TimerType> timer0(*instance);
481 TestTimer<TimerType> timer1(*instance);
482 TestTimer<TimerType> timer2(*instance);
483 TestTimer<TimerType> timer3(*instance);
484 TestTimer<TimerType> timer4(*instance);
485 TestTimer<TimerType> timer5(*instance);
486 TestTimer<TimerType> timer6(*instance);
487 TestTimer<TimerType> timer7(*instance);
488 TestTimer<TimerType> timer8(*instance);
489 TestTimer<TimerType> timer9(*instance);
490 TestTimer<TimerType> *timers[kNumTimers] = {&timer0, &timer1, &timer2, &timer3, &timer4,
491 &timer5, &timer6, &timer7, &timer8, &timer9};
492 size_t i;
493
494 printf("TestTenTimer() with aTimeShift=%-10u ", aTimeShift);
495
496 // Start the Ten timers.
497
498 TestTimer<TimerType>::RemoveAll(*instance);
499 InitTestTimer();
500 InitCounters();
501
502 for (i = 0; i < kNumTimers; i++)
503 {
504 sNow = kTimeT0[i] + aTimeShift;
505 timers[i]->Start(kTimerInterval[i]);
506 }
507
508 // given the order in which timers are started, the TimerScheduler should call otPlatAlarmMilliStartAt 2 times.
509 // one for timer[0] and one for timer[5] which will supercede timer[0].
510 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 2, "TestTenTimer: Start CallCount Failed.");
511 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "TestTenTimer: Stop CallCount Failed.");
512 VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "TestTenTimer: Handler CallCount Failed.");
513 VerifyOrQuit(sPlatT0 == kTimeT0[5] + aTimeShift, "TestTenTimer: Start params Failed.");
514 VerifyOrQuit(sPlatDt == kTimerInterval[5], "TestTenTimer: Start params Failed.");
515 VerifyOrQuit(sTimerOn, "TestTenTimer: Platform Timer State Failed.");
516
517 for (i = 0; i < kNumTimers; i++)
518 {
519 VerifyOrQuit(timers[i]->IsRunning(), "TestTenTimer: Timer running Failed.");
520 }
521
522 // Issue the triggers and test the State after each trigger.
523
524 for (size_t trigger = 0; trigger < kNumTriggers; trigger++)
525 {
526 sNow = kTriggerTimes[trigger] + aTimeShift;
527
528 do
529 {
530 // By design, each call to AlarmFired<TimerType>() can result in 0 or 1 calls to a timer handler.
531 // For some combinations of sNow and Timers queued, it is necessary to call AlarmFired<TimerType>()
532 // multiple times in order to handle all the expired timers. It can be determined that another
533 // timer is ready to be triggered by examining the aDt arg passed into otPlatAlarmMilliStartAt(). If
534 // that value is 0, then AlarmFired should be fired immediately. This loop calls
535 // AlarmFired<TimerType>() the requisite number of times based on the aDt argument.
536 AlarmFired<TimerType>(instance);
537 } while (sPlatDt == 0);
538
539 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == kTimerStartCountAfterTrigger[trigger],
540 "TestTenTimer: Start CallCount Failed.");
541 VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == kTimerStopCountAfterTrigger[trigger],
542 "TestTenTimer: Stop CallCount Failed.");
543 VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == kTimerHandlerCountAfterTrigger[trigger],
544 "TestTenTimer: Handler CallCount Failed.");
545 VerifyOrQuit(sTimerOn == kSchedulerStateAfterTrigger[trigger], "TestTenTimer: Platform Timer State Failed.");
546
547 for (i = 0; i < kNumTimers; i++)
548 {
549 VerifyOrQuit(timers[i]->IsRunning() == kTimerStateAfterTrigger[trigger][i],
550 "TestTenTimer: Timer running Failed.");
551 }
552 }
553
554 for (i = 0; i < kNumTimers; i++)
555 {
556 VerifyOrQuit(timers[i]->GetFiredCounter() == 1, "TestTenTimer: Timer fired counter Failed.");
557 }
558
559 printf("--> PASSED\n");
560
561 testFreeInstance(instance);
562 }
563
TestTenTimers(void)564 template <typename TimerType> int TestTenTimers(void)
565 {
566 // Time shift to change the start/fire time of ten timers.
567 const uint32_t kTimeShift[] = {
568 0, 100000U, 0U - 1U, 0U - 1100U, ot::Timer::kMaxDelay, ot::Timer::kMaxDelay + 1020U,
569 };
570
571 size_t i;
572
573 for (i = 0; i < OT_ARRAY_LENGTH(kTimeShift); i++)
574 {
575 TenTimers<TimerType>(kTimeShift[i]);
576 }
577
578 return 0;
579 }
580
581 /**
582 * Test the `Timer::Time` class.
583 */
TestTimerTime(void)584 int TestTimerTime(void)
585 {
586 const uint32_t kMaxTime = 0xffffffff;
587 const uint32_t kStartTimes[] = {0, 100, kMaxTime / 2, kMaxTime - 100, kMaxTime};
588 const uint32_t kDurations[] = {1, 100, ot::Timer::kMaxDelay - 1, ot::Timer::kMaxDelay};
589
590 ot::Time t1;
591 ot::Time t2;
592
593 for (uint32_t startTime : kStartTimes)
594 {
595 for (uint32_t duration : kDurations)
596 {
597 printf("TestTimerTime() start=%-10x duration=%-10x ", startTime, duration);
598
599 t1.SetValue(startTime);
600 VerifyOrQuit(t1.GetValue() == startTime, "Time::SetValue() failed.");
601
602 t2 = t1;
603 VerifyOrQuit(t1.GetValue() == startTime, "Time assignment failed.");
604
605 VerifyOrQuit(t1 == t2, "Time == failed.");
606 VerifyOrQuit(!(t1 != t2), "Time != failed.");
607 VerifyOrQuit(!(t1 < t2), "Time < failed.");
608 VerifyOrQuit((t1 <= t2), "Time <= failed.");
609 VerifyOrQuit(!(t1 > t2), "Time > failed.");
610 VerifyOrQuit((t1 >= t2), "Time >= failed.");
611 VerifyOrQuit(t2 - t1 == 0, "Time difference failed");
612
613 t2 = t1 + duration;
614 VerifyOrQuit(!(t1 == t2), "Time == failed.");
615 VerifyOrQuit((t1 != t2), "Time != failed.");
616 VerifyOrQuit((t1 < t2), "Time < failed.");
617 VerifyOrQuit((t1 <= t2), "Time <= failed.");
618 VerifyOrQuit(!(t1 > t2), "Time > failed.");
619 VerifyOrQuit(!(t1 >= t2), "Time >= failed.");
620 VerifyOrQuit(t2 - t1 == duration, "Time difference failed");
621
622 t2 = t1;
623 t2 += duration;
624 VerifyOrQuit(!(t1 == t2), "Time == failed.");
625 VerifyOrQuit((t1 != t2), "Time != failed.");
626 VerifyOrQuit((t1 < t2), "Time < failed.");
627 VerifyOrQuit((t1 <= t2), "Time <= failed.");
628 VerifyOrQuit(!(t1 > t2), "Time > failed.");
629 VerifyOrQuit(!(t1 >= t2), "Time >= failed.");
630 VerifyOrQuit(t2 - t1 == duration, "Time difference failed");
631
632 t2 = t1 - duration;
633 VerifyOrQuit(!(t1 == t2), "Time == failed.");
634 VerifyOrQuit((t1 != t2), "Time != failed.");
635 VerifyOrQuit(!(t1 < t2), "Time < failed.");
636 VerifyOrQuit(!(t1 <= t2), "Time <= failed.");
637 VerifyOrQuit((t1 > t2), "Time > failed.");
638 VerifyOrQuit((t1 >= t2), "Time >= failed.");
639 VerifyOrQuit(t1 - t2 == duration, "Time difference failed");
640
641 t2 = t1;
642 t2 -= duration;
643 VerifyOrQuit(!(t1 == t2), "Time == failed.");
644 VerifyOrQuit((t1 != t2), "Time != failed.");
645 VerifyOrQuit(!(t1 < t2), "Time < failed.");
646 VerifyOrQuit(!(t1 <= t2), "Time <= failed.");
647 VerifyOrQuit((t1 > t2), "Time > failed.");
648 VerifyOrQuit((t1 >= t2), "Time >= failed.");
649 VerifyOrQuit(t1 - t2 == duration, "Time difference failed");
650
651 t2 = t1.GetDistantFuture();
652 VerifyOrQuit((t1 < t2), "GetDistanceFuture() failed");
653 t2 += 1;
654 VerifyOrQuit(!(t1 < t2), "GetDistanceFuture() failed");
655
656 t2 = t1.GetDistantPast();
657 VerifyOrQuit((t1 > t2), "GetDistantPast() failed");
658 t2 -= 1;
659 VerifyOrQuit(!(t1 > t2), "GetDistantPast() failed");
660
661 printf("--> PASSED\n");
662 }
663 }
664
665 return 0;
666 }
667
RunTimerTests(void)668 template <typename TimerType> void RunTimerTests(void)
669 {
670 TestOneTimer<TimerType>();
671 TestTwoTimers<TimerType>();
672 TestTenTimers<TimerType>();
673 }
674
main(void)675 int main(void)
676 {
677 RunTimerTests<ot::TimerMilli>();
678 #if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
679 RunTimerTests<ot::TimerMicro>();
680 #endif
681 TestTimerTime();
682 printf("All tests passed\n");
683 return 0;
684 }
685