| /* |
| * Copyright (c) 2016, The OpenThread Authors. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. Neither the name of the copyright holder nor the |
| * names of its contributors may be used to endorse or promote products |
| * derived from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| * POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "test_platform.h" |
| |
| #include "openthread-instance.h" |
| #include "common/debug.hpp" |
| #include "common/timer.hpp" |
| |
| enum |
| { |
| kCallCountIndexAlarmStop = 0, |
| kCallCountIndexAlarmStart, |
| kCallCountIndexTimerHandler, |
| |
| kCallCountIndexMax |
| }; |
| |
| uint32_t sNow; |
| uint32_t sPlatT0; |
| uint32_t sPlatDt; |
| bool sTimerOn; |
| uint32_t sCallCount[kCallCountIndexMax]; |
| |
| void testTimerAlarmStop(otInstance *) |
| { |
| sTimerOn = false; |
| sCallCount[kCallCountIndexAlarmStop]++; |
| } |
| |
| void testTimerAlarmStartAt(otInstance *, uint32_t aT0, uint32_t aDt) |
| { |
| sTimerOn = true; |
| sCallCount[kCallCountIndexAlarmStart]++; |
| sPlatT0 = aT0; |
| sPlatDt = aDt; |
| } |
| |
| uint32_t testTimerAlarmGetNow(void) |
| { |
| return sNow; |
| } |
| |
| void InitTestTimer(void) |
| { |
| g_testPlatAlarmStop = testTimerAlarmStop; |
| g_testPlatAlarmStartAt = testTimerAlarmStartAt; |
| g_testPlatAlarmGetNow = testTimerAlarmGetNow; |
| } |
| |
| void InitCounters(void) |
| { |
| memset(sCallCount, 0, sizeof(sCallCount)); |
| } |
| |
| /** |
| * `TestTimer` sub-classes `ot::Timer` and provides a handler and a counter to keep track of number of times timer gets |
| * fired. |
| */ |
| class TestTimer: public ot::Timer |
| { |
| public: |
| TestTimer(otInstance *aInstance): |
| ot::Timer(aInstance->mIp6.mTimerScheduler, TestTimer::HandleTimerFired, NULL), |
| mFiredCounter(0) |
| { } |
| |
| static void HandleTimerFired(ot::Timer &aTimer) { |
| static_cast<TestTimer &>(aTimer).HandleTimerFired(); |
| } |
| |
| void HandleTimerFired(void) { |
| sCallCount[kCallCountIndexTimerHandler]++; |
| mFiredCounter++; |
| } |
| |
| uint32_t GetFiredCounter(void) { return mFiredCounter; } |
| |
| void ResetFiredCounter(void) { mFiredCounter = 0; } |
| |
| private: |
| uint32_t mFiredCounter; //< Number of times timer has been fired so far |
| }; |
| |
| /** |
| * Test the TimerScheduler's behavior of one timer started and fired. |
| */ |
| int TestOneTimer(void) |
| { |
| const uint32_t kTimeT0 = 1000; |
| const uint32_t kTimerInterval = 10; |
| otInstance *instance = testInitInstance(); |
| TestTimer timer(instance); |
| |
| // Test one Timer basic operation. |
| |
| InitTestTimer(); |
| InitCounters(); |
| |
| printf("TestOneTimer() "); |
| |
| sNow = kTimeT0; |
| timer.Start(kTimerInterval); |
| |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "TestOneTimer: Start CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "TestOneTimer: Stop CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "TestOneTimer: Handler CallCount Failed.\n"); |
| VerifyOrQuit(sPlatT0 == 1000 && sPlatDt == 10, "TestOneTimer: Start params Failed.\n"); |
| VerifyOrQuit(timer.IsRunning(), "TestOneTimer: Timer running Failed.\n"); |
| VerifyOrQuit(sTimerOn, "TestOneTimer: Platform Timer State Failed.\n"); |
| |
| sNow += kTimerInterval; |
| |
| otPlatAlarmFired(instance); |
| |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "TestOneTimer: Start CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 1, "TestOneTimer: Stop CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 1, "TestOneTimer: Handler CallCount Failed.\n"); |
| VerifyOrQuit(timer.IsRunning() == false, "TestOneTimer: Timer running Failed.\n"); |
| VerifyOrQuit(sTimerOn == false, "TestOneTimer: Platform Timer State Failed.\n"); |
| |
| // Test one Timer that spans the 32-bit wrap. |
| |
| InitCounters(); |
| |
| sNow = 0 - (kTimerInterval - 2); |
| timer.Start(kTimerInterval); |
| |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "TestOneTimer: Start CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "TestOneTimer: Stop CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "TestOneTimer: Handler CallCount Failed.\n"); |
| VerifyOrQuit(sPlatT0 == 0 - (kTimerInterval - 2) && sPlatDt == 10, "TestOneTimer: Start params Failed.\n"); |
| VerifyOrQuit(timer.IsRunning(), "TestOneTimer: Timer running Failed.\n"); |
| VerifyOrQuit(sTimerOn, "TestOneTimer: Platform Timer State Failed.\n"); |
| |
| sNow += kTimerInterval; |
| |
| otPlatAlarmFired(instance); |
| |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "TestOneTimer: Start CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 1, "TestOneTimer: Stop CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 1, "TestOneTimer: Handler CallCount Failed.\n"); |
| VerifyOrQuit(timer.IsRunning() == false, "TestOneTimer: Timer running Failed.\n"); |
| VerifyOrQuit(sTimerOn == false, "TestOneTimer: Platform Timer State Failed.\n"); |
| |
| // Test one Timer that is late by several msec |
| |
| InitCounters(); |
| |
| sNow = kTimeT0; |
| timer.Start(kTimerInterval); |
| |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "TestOneTimer: Start CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "TestOneTimer: Stop CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "TestOneTimer: Handler CallCount Failed.\n"); |
| VerifyOrQuit(sPlatT0 == 1000 && sPlatDt == 10, "TestOneTimer: Start params Failed.\n"); |
| VerifyOrQuit(timer.IsRunning(), "TestOneTimer: Timer running Failed.\n"); |
| VerifyOrQuit(sTimerOn, "TestOneTimer: Platform Timer State Failed.\n"); |
| |
| sNow += kTimerInterval + 5; |
| |
| otPlatAlarmFired(instance); |
| |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "TestOneTimer: Start CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 1, "TestOneTimer: Stop CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 1, "TestOneTimer: Handler CallCount Failed.\n"); |
| VerifyOrQuit(timer.IsRunning() == false, "TestOneTimer: Timer running Failed.\n"); |
| VerifyOrQuit(sTimerOn == false, "TestOneTimer: Platform Timer State Failed.\n"); |
| |
| // Test one Timer that is early by several msec |
| |
| InitCounters(); |
| |
| sNow = kTimeT0; |
| timer.Start(kTimerInterval); |
| |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "TestOneTimer: Start CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "TestOneTimer: Stop CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "TestOneTimer: Handler CallCount Failed.\n"); |
| VerifyOrQuit(sPlatT0 == 1000 && sPlatDt == 10, "TestOneTimer: Start params Failed.\n"); |
| VerifyOrQuit(timer.IsRunning(), "TestOneTimer: Timer running Failed.\n"); |
| VerifyOrQuit(sTimerOn, "TestOneTimer: Platform Timer State Failed.\n"); |
| |
| sNow += kTimerInterval - 2; |
| |
| otPlatAlarmFired(instance); |
| |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 2, "TestOneTimer: Start CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "TestOneTimer: Stop CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "TestOneTimer: Handler CallCount Failed.\n"); |
| VerifyOrQuit(timer.IsRunning() == true, "TestOneTimer: Timer running Failed.\n"); |
| VerifyOrQuit(sTimerOn == true, "TestOneTimer: Platform Timer State Failed.\n"); |
| |
| sNow += kTimerInterval; |
| |
| otPlatAlarmFired(instance); |
| |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 2, "TestOneTimer: Start CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 1, "TestOneTimer: Stop CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 1, "TestOneTimer: Handler CallCount Failed.\n"); |
| VerifyOrQuit(timer.IsRunning() == false, "TestOneTimer: Timer running Failed.\n"); |
| VerifyOrQuit(sTimerOn == false, "TestOneTimer: Platform Timer State Failed.\n"); |
| |
| printf(" --> PASSED\n"); |
| |
| testFreeInstance(instance); |
| |
| return 0; |
| } |
| |
| /** |
| * Test the TimerScheduler's behavior of two timers started and fired. |
| */ |
| int TestTwoTimers(void) |
| { |
| const uint32_t kTimeT0 = 1000; |
| const uint32_t kTimerInterval = 10; |
| otInstance *instance = testInitInstance(); |
| TestTimer timer1(instance); |
| TestTimer timer2(instance); |
| |
| InitTestTimer(); |
| printf("TestTwoTimers() "); |
| |
| // Test when second timer stars at the fire time of first timer (before alarm callback). |
| |
| InitCounters(); |
| |
| sNow = kTimeT0; |
| timer1.Start(kTimerInterval); |
| |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "TestTwoTimers: Start CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "TestTwoTimers: Stop CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "TestTwoTimers: Handler CallCount Failed.\n"); |
| VerifyOrQuit(sPlatT0 == kTimeT0 && sPlatDt == kTimerInterval, "TestTwoTimers: Start params Failed.\n"); |
| VerifyOrQuit(timer1.IsRunning(), "TestTwoTimers: Timer running Failed.\n"); |
| VerifyOrQuit(timer2.IsRunning() == false, "TestTwoTimers: Timer running Failed.\n"); |
| VerifyOrQuit(sTimerOn, "TestTwoTimers: Platform Timer State Failed.\n"); |
| |
| sNow += kTimerInterval; |
| |
| timer2.Start(kTimerInterval); |
| |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "TestTwoTimers: Start CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "TestTwoTimers: Stop CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "TestTwoTimers: Handler CallCount Failed.\n"); |
| VerifyOrQuit(sPlatT0 == kTimeT0 && sPlatDt == kTimerInterval, "TestTwoTimers: Start params Failed.\n"); |
| VerifyOrQuit(timer1.IsRunning() == true, "TestTwoTimers: Timer running Failed.\n"); |
| VerifyOrQuit(timer2.IsRunning() == true, "TestTwoTimers: Timer running Failed.\n"); |
| VerifyOrQuit(sTimerOn, "TestTwoTimers: Platform Timer State Failed.\n"); |
| |
| otPlatAlarmFired(instance); |
| |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 2, "TestTwoTimers: Start CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "TestTwoTimers: Stop CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 1, "TestTwoTimers: Handler CallCount Failed.\n"); |
| VerifyOrQuit(timer1.GetFiredCounter() == 1, "TestTwoTimers: Fire Counter failed.\n"); |
| VerifyOrQuit(sPlatT0 == sNow && sPlatDt == kTimerInterval, "TestTwoTimers: Start params Failed.\n"); |
| VerifyOrQuit(timer1.IsRunning() == false, "TestTwoTimers: Timer running Failed.\n"); |
| VerifyOrQuit(timer2.IsRunning() == true, "TestTwoTimers: Timer running Failed.\n"); |
| VerifyOrQuit(sTimerOn == true, "TestTwoTimers: Platform Timer State Failed.\n"); |
| |
| sNow += kTimerInterval; |
| otPlatAlarmFired(instance); |
| |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 2, "TestTwoTimers: Start CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 1, "TestTwoTimers: Stop CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 2, "TestTwoTimers: Handler CallCount Failed.\n"); |
| VerifyOrQuit(timer2.GetFiredCounter() == 1, "TestTwoTimers: Fire Counter failed.\n"); |
| VerifyOrQuit(timer1.IsRunning() == false, "TestTwoTimers: Timer running Failed.\n"); |
| VerifyOrQuit(timer2.IsRunning() == false, "TestTwoTimers: Timer running Failed.\n"); |
| VerifyOrQuit(sTimerOn == false, "TestTwoTimers: Platform Timer State Failed.\n"); |
| |
| // Test when second timer starts at the fire time of first timer (before otPlatAlarmFired()) and its fire time |
| // is before the first timer. Ensure that the second timer handler is invoked before the first one. |
| |
| InitCounters(); |
| timer1.ResetFiredCounter(); |
| timer2.ResetFiredCounter(); |
| |
| sNow = kTimeT0; |
| timer1.Start(kTimerInterval); |
| |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "TestTwoTimers: Start CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "TestTwoTimers: Stop CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "TestTwoTimers: Handler CallCount Failed.\n"); |
| VerifyOrQuit(sPlatT0 == kTimeT0 && sPlatDt == kTimerInterval, "TestTwoTimers: Start params Failed.\n"); |
| VerifyOrQuit(timer1.IsRunning(), "TestTwoTimers: Timer running Failed.\n"); |
| VerifyOrQuit(timer2.IsRunning() == false, "TestTwoTimers: Timer running Failed.\n"); |
| VerifyOrQuit(sTimerOn, "TestTwoTimers: Platform Timer State Failed.\n"); |
| |
| sNow += kTimerInterval; |
| |
| timer2.StartAt(kTimeT0, kTimerInterval - 2); // Timer 2 is even before timer 1 |
| |
| VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "TestTwoTimers: Handler CallCount Failed.\n"); |
| VerifyOrQuit(timer1.IsRunning() == true, "TestTwoTimers: Timer running Failed.\n"); |
| VerifyOrQuit(timer2.IsRunning() == true, "TestTwoTimers: Timer running Failed.\n"); |
| VerifyOrQuit(sTimerOn, "TestTwoTimers: Platform Timer State Failed.\n"); |
| |
| otPlatAlarmFired(instance); |
| |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "TestTwoTimers: Stop CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 1, "TestTwoTimers: Handler CallCount Failed.\n"); |
| VerifyOrQuit(timer2.GetFiredCounter() == 1, "TestTwoTimers: Fire Counter failed.\n"); |
| VerifyOrQuit(sPlatT0 == sNow && sPlatDt == 0, "TestTwoTimers: Start params Failed.\n"); |
| VerifyOrQuit(timer1.IsRunning() == true, "TestTwoTimers: Timer running Failed.\n"); |
| VerifyOrQuit(timer2.IsRunning() == false, "TestTwoTimers: Timer running Failed.\n"); |
| VerifyOrQuit(sTimerOn == true, "TestTwoTimers: Platform Timer State Failed.\n"); |
| |
| otPlatAlarmFired(instance); |
| |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 1, "TestTwoTimers: Stop CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 2, "TestTwoTimers: Handler CallCount Failed.\n"); |
| VerifyOrQuit(timer1.GetFiredCounter() == 1, "TestTwoTimers: Fire Counter failed.\n"); |
| VerifyOrQuit(timer1.IsRunning() == false, "TestTwoTimers: Timer running Failed.\n"); |
| VerifyOrQuit(timer2.IsRunning() == false, "TestTwoTimers: Timer running Failed.\n"); |
| VerifyOrQuit(sTimerOn == false, "TestTwoTimers: Platform Timer State Failed.\n"); |
| |
| // Timer 1 fire callback is late by some ticks/ms, and second timer is scheduled (before call to otPlatAlarmFired) |
| // with a maximum interval. This is to test (corner-case) scenario where the fire time of two timers spanning over |
| // the maximum interval. |
| |
| InitCounters(); |
| timer1.ResetFiredCounter(); |
| timer2.ResetFiredCounter(); |
| |
| sNow = kTimeT0; |
| timer1.Start(kTimerInterval); |
| |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "TestTwoTimers: Start CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "TestTwoTimers: Stop CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "TestTwoTimers: Handler CallCount Failed.\n"); |
| VerifyOrQuit(sPlatT0 == kTimeT0 && sPlatDt == kTimerInterval, "TestTwoTimers: Start params Failed.\n"); |
| VerifyOrQuit(timer1.IsRunning(), "TestTwoTimers: Timer running Failed.\n"); |
| VerifyOrQuit(timer2.IsRunning() == false, "TestTwoTimers: Timer running Failed.\n"); |
| VerifyOrQuit(sTimerOn, "TestTwoTimers: Platform Timer State Failed.\n"); |
| |
| sNow += kTimerInterval + 5; |
| |
| timer2.Start(ot::Timer::kMaxDt); |
| |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "TestTwoTimers: Start CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "TestTwoTimers: Stop CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "TestTwoTimers: Handler CallCount Failed.\n"); |
| VerifyOrQuit(timer1.IsRunning() == true, "TestTwoTimers: Timer running Failed.\n"); |
| VerifyOrQuit(timer2.IsRunning() == true, "TestTwoTimers: Timer running Failed.\n"); |
| VerifyOrQuit(sTimerOn, "TestTwoTimers: Platform Timer State Failed.\n"); |
| |
| otPlatAlarmFired(instance); |
| |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 2, "TestTwoTimers: Start CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "TestTwoTimers: Stop CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 1, "TestTwoTimers: Handler CallCount Failed.\n"); |
| VerifyOrQuit(timer1.GetFiredCounter() == 1, "TestTwoTimers: Fire Counter failed.\n"); |
| VerifyOrQuit(sPlatT0 == sNow, "TestTwoTimers: Start params Failed.\n"); |
| VerifyOrQuit(sPlatDt == ot::Timer::kMaxDt, "TestTwoTimers: Start params Failed.\n"); |
| VerifyOrQuit(timer1.IsRunning() == false, "TestTwoTimers: Timer running Failed.\n"); |
| VerifyOrQuit(timer2.IsRunning() == true, "TestTwoTimers: Timer running Failed.\n"); |
| VerifyOrQuit(sTimerOn == true, "TestTwoTimers: Platform Timer State Failed.\n"); |
| |
| sNow += ot::Timer::kMaxDt; |
| otPlatAlarmFired(instance); |
| |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 2, "TestTwoTimers: Start CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 1, "TestTwoTimers: Stop CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 2, "TestTwoTimers: Handler CallCount Failed.\n"); |
| VerifyOrQuit(timer2.GetFiredCounter() == 1, "TestTwoTimers: Fire Counter failed.\n"); |
| VerifyOrQuit(timer1.IsRunning() == false, "TestTwoTimers: Timer running Failed.\n"); |
| VerifyOrQuit(timer2.IsRunning() == false, "TestTwoTimers: Timer running Failed.\n"); |
| VerifyOrQuit(sTimerOn == false, "TestTwoTimers: Platform Timer State Failed.\n"); |
| |
| printf(" --> PASSED\n"); |
| |
| testFreeInstance(instance); |
| |
| return 0; |
| } |
| |
| /** |
| * Test the TimerScheduler's behavior of ten timers started and fired. |
| * |
| * `aTimeShift` is added to the t0 and trigger times for all timers. It can be used to check the ten timer behavior |
| * at different start time (e.g., around a 32-bit wrap). |
| */ |
| static void TenTimers(uint32_t aTimeShift) |
| { |
| const uint32_t kNumTimers = 10; |
| const uint32_t kNumTriggers = 7; |
| const uint32_t kTimeT0[kNumTimers] = |
| { |
| 1000, |
| 1000, |
| 1001, |
| 1002, |
| 1003, |
| 1004, |
| 1005, |
| 1006, |
| 1007, |
| 1008 |
| }; |
| const uint32_t kTimerInterval[kNumTimers] = |
| { |
| 20, |
| 100, |
| (ot::Timer::kMaxDt - kTimeT0[2]), |
| 100000, |
| 1000000, |
| 10, |
| ot::Timer::kMaxDt, |
| 200, |
| 200, |
| 200 |
| }; |
| // Expected timer fire order |
| // timer # Trigger time |
| // 5 1014 |
| // 0 1020 |
| // 1 1100 |
| // 7 1206 |
| // 8 1207 |
| // 9 1208 |
| // 3 101002 |
| // 4 1001003 |
| // 2 kMaxDt |
| // 6 kMaxDt + 1005 |
| const uint32_t kTriggerTimes[kNumTriggers] = |
| { |
| 1014, |
| 1020, |
| 1100, |
| 1207, |
| 101004, |
| ot::Timer::kMaxDt, |
| ot::Timer::kMaxDt + kTimeT0[6] |
| }; |
| // Expected timers fired by each kTriggerTimes[] value |
| // Trigger # Timers Fired |
| // 0 5 |
| // 1 0 |
| // 2 1 |
| // 3 7, 8 |
| // 4 9, 3 |
| // 5 4, 2 |
| // 6 6 |
| const bool kTimerStateAfterTrigger [kNumTriggers][kNumTimers] = |
| { |
| { true, true, true, true, true, false, true, true, true, true}, // 5 |
| { false, true, true, true, true, false, true, true, true, true}, // 0 |
| { false, false, true, true, true, false, true, true, true, true}, // 1 |
| { false, false, true, true, true, false, true, false, false, true}, // 7, 8 |
| { false, false, true, false, true, false, true, false, false, false}, // 9, 3 |
| { false, false, false, false, false, false, true, false, false, false}, // 4, 2 |
| { false, false, false, false, false, false, false, false, false, false} // 6 |
| }; |
| |
| const bool kSchedulerStateAfterTrigger[kNumTriggers] = |
| { |
| true, |
| true, |
| true, |
| true, |
| true, |
| true, |
| false |
| }; |
| |
| const uint32_t kTimerHandlerCountAfterTrigger[kNumTriggers] = |
| { |
| 1, |
| 2, |
| 3, |
| 5, |
| 7, |
| 9, |
| 10 |
| }; |
| |
| const uint32_t kTimerStopCountAfterTrigger[kNumTriggers] = |
| { |
| 0, |
| 0, |
| 0, |
| 0, |
| 0, |
| 0, |
| 1 |
| }; |
| |
| const uint32_t kTimerStartCountAfterTrigger[kNumTriggers] = |
| { |
| 3, |
| 4, |
| 5, |
| 7, |
| 9, |
| 11, |
| 11 |
| }; |
| |
| otInstance *instance = testInitInstance(); |
| |
| TestTimer timer0(instance); |
| TestTimer timer1(instance); |
| TestTimer timer2(instance); |
| TestTimer timer3(instance); |
| TestTimer timer4(instance); |
| TestTimer timer5(instance); |
| TestTimer timer6(instance); |
| TestTimer timer7(instance); |
| TestTimer timer8(instance); |
| TestTimer timer9(instance); |
| TestTimer *timers[kNumTimers] = |
| { |
| &timer0, |
| &timer1, |
| &timer2, |
| &timer3, |
| &timer4, |
| &timer5, |
| &timer6, |
| &timer7, |
| &timer8, |
| &timer9 |
| }; |
| size_t i; |
| |
| printf("TestTenTimer() with aTimeShift=%-10u ", aTimeShift); |
| |
| // Start the Ten timers. |
| |
| InitTestTimer(); |
| InitCounters(); |
| |
| for (i = 0; i < kNumTimers ; i++) |
| { |
| sNow = kTimeT0[i] + aTimeShift; |
| timers[i]->Start(kTimerInterval[i]); |
| } |
| |
| // given the order in which timers are started, the TimerScheduler should call otPlatAlarmStartAt 2 times. |
| // one for timer[0] and one for timer[5] which will supercede timer[0]. |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 2, "TestTenTimer: Start CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "TestTenTimer: Stop CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "TestTenTimer: Handler CallCount Failed.\n"); |
| VerifyOrQuit(sPlatT0 == kTimeT0[5] + aTimeShift, "TestTenTimer: Start params Failed.\n"); |
| VerifyOrQuit(sPlatDt == kTimerInterval[5], "TestTenTimer: Start params Failed.\n"); |
| VerifyOrQuit(sTimerOn, "TestTenTimer: Platform Timer State Failed.\n"); |
| |
| for (i = 0 ; i < kNumTimers ; i++) |
| { |
| VerifyOrQuit(timers[i]->IsRunning(), "TestTenTimer: Timer running Failed.\n"); |
| } |
| |
| // Issue the triggers and test the State after each trigger. |
| |
| for (size_t trigger = 0 ; trigger < kNumTriggers ; trigger++) |
| { |
| sNow = kTriggerTimes[trigger] + aTimeShift; |
| |
| do |
| { |
| // By design, each call to otPlatAlarmFired() can result in 0 or 1 calls to a timer handler. |
| // For some combinations of sNow and Timers queued, it is necessary to call otPlatAlarmFired() |
| // multiple times in order to handle all the expired timers. It can be determined that another |
| // timer is ready to be triggered by examining the aDt arg passed into otPlatAlarmStartAt(). If |
| // that value is 0, then otPlatAlarmFired should be fired immediately. This loop calls otPlatAlarmFired() |
| // the requisite number of times based on the aDt argument. |
| otPlatAlarmFired(instance); |
| } |
| while (sPlatDt == 0); |
| |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == kTimerStartCountAfterTrigger[trigger], |
| "TestTenTimer: Start CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == kTimerStopCountAfterTrigger[trigger], |
| "TestTenTimer: Stop CallCount Failed.\n"); |
| VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == kTimerHandlerCountAfterTrigger[trigger], |
| "TestTenTimer: Handler CallCount Failed.\n"); |
| VerifyOrQuit(sTimerOn == kSchedulerStateAfterTrigger[trigger], |
| "TestTenTimer: Platform Timer State Failed.\n"); |
| |
| for (i = 0 ; i < kNumTimers ; i++) |
| { |
| VerifyOrQuit( |
| timers[i]->IsRunning() == kTimerStateAfterTrigger[trigger][i], |
| "TestTenTimer: Timer running Failed.\n" |
| ); |
| } |
| } |
| |
| for (i = 0 ; i < kNumTimers ; i++) |
| { |
| VerifyOrQuit(timers[i]->GetFiredCounter() == 1, "TestTenTimer: Timer fired counter Failed.\n"); |
| } |
| |
| printf("--> PASSED\n"); |
| |
| testFreeInstance(instance); |
| } |
| |
| int TestTenTimers(void) |
| { |
| // Time shift to change the start/fire time of ten timers. |
| const uint32_t kTimeShift[] = |
| { |
| 0, |
| 100000U, |
| 0U - 1U, |
| 0U - 1100U, |
| ot::Timer::kMaxDt, |
| ot::Timer::kMaxDt + 1020U, |
| }; |
| |
| size_t i; |
| |
| for (i = 0; i < sizeof(kTimeShift) / sizeof(kTimeShift[0]); i++) |
| { |
| TenTimers(kTimeShift[i]); |
| } |
| |
| return 0; |
| } |
| |
| void RunTimerTests(void) |
| { |
| TestOneTimer(); |
| TestTwoTimers(); |
| TestTenTimers(); |
| } |
| |
| #ifdef ENABLE_TEST_MAIN |
| int main(void) |
| { |
| RunTimerTests(); |
| printf("All tests passed\n"); |
| return 0; |
| } |
| #endif |