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