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