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