blob: 8666ba755589824617ae82d4ba1c8737e4529d0c [file] [log] [blame]
/*
* 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 "common/array.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/num_utils.hpp"
#include "common/timer.hpp"
#include "instance/instance.hpp"
namespace ot {
enum
{
kCallCountIndexAlarmStop = 0,
kCallCountIndexAlarmStart,
kCallCountIndexTimerHandler,
kCallCountIndexMax
};
uint32_t sNow;
uint32_t sPlatT0;
uint32_t sPlatDt;
bool sTimerOn;
uint32_t sCallCount[kCallCountIndexMax];
extern "C" {
void otPlatAlarmMilliStop(otInstance *)
{
sTimerOn = false;
sCallCount[kCallCountIndexAlarmStop]++;
}
void otPlatAlarmMilliStartAt(otInstance *, uint32_t aT0, uint32_t aDt)
{
sTimerOn = true;
sCallCount[kCallCountIndexAlarmStart]++;
sPlatT0 = aT0;
sPlatDt = aDt;
}
uint32_t otPlatAlarmMilliGetNow(void) { return sNow; }
#if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
void otPlatAlarmMicroStop(otInstance *)
{
sTimerOn = false;
sCallCount[kCallCountIndexAlarmStop]++;
}
void otPlatAlarmMicroStartAt(otInstance *, uint32_t aT0, uint32_t aDt)
{
sTimerOn = true;
sCallCount[kCallCountIndexAlarmStart]++;
sPlatT0 = aT0;
sPlatDt = aDt;
}
uint32_t otPlatAlarmMicroGetNow(void) { return sNow; }
#endif
} // extern "C"
void InitCounters(void) { memset(sCallCount, 0, sizeof(sCallCount)); }
/**
* `TestTimer` sub-classes `TimerMilli` and provides a handler and a counter to keep track of number of times timer
* gets fired.
*/
template <typename TimerType> class TestTimer : public TimerType
{
public:
explicit TestTimer(Instance &aInstance)
: TimerType(aInstance, TestTimer::HandleTimerFired)
, mFiredCounter(0)
{
}
static void HandleTimerFired(Timer &aTimer) { static_cast<TestTimer &>(aTimer).HandleTimerFired(); }
void HandleTimerFired(void)
{
sCallCount[kCallCountIndexTimerHandler]++;
mFiredCounter++;
}
uint32_t GetFiredCounter(void) { return mFiredCounter; }
void ResetFiredCounter(void) { mFiredCounter = 0; }
static void RemoveAll(Instance &aInstance) { TimerType::RemoveAll(aInstance); }
private:
uint32_t mFiredCounter; //< Number of times timer has been fired so far
};
template <typename TimerType> void AlarmFired(otInstance *aInstance);
template <> void AlarmFired<TimerMilli>(otInstance *aInstance) { otPlatAlarmMilliFired(aInstance); }
#if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
template <> void AlarmFired<TimerMicro>(otInstance *aInstance) { otPlatAlarmMicroFired(aInstance); }
#endif
/**
* Test the TimerScheduler's behavior of one timer started and fired.
*/
template <typename TimerType> int TestOneTimer(void)
{
const uint32_t kTimeT0 = 1000;
const uint32_t kTimerInterval = 10;
Instance *instance = testInitInstance();
TestTimer<TimerType> timer(*instance);
// Test one Timer basic operation.
TestTimer<TimerType>::RemoveAll(*instance);
InitCounters();
printf("TestOneTimer() ");
sNow = kTimeT0;
timer.Start(kTimerInterval);
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "Start CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "Handler CallCount Failed.");
VerifyOrQuit(sPlatT0 == 1000 && sPlatDt == 10, "Start params Failed.");
VerifyOrQuit(timer.IsRunning(), "Timer running Failed.");
VerifyOrQuit(sTimerOn, "Platform Timer State Failed.");
sNow += kTimerInterval;
AlarmFired<TimerType>(instance);
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "Start CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 1, "Stop CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 1, "Handler CallCount Failed.");
VerifyOrQuit(timer.IsRunning() == false, "Timer running Failed.");
VerifyOrQuit(sTimerOn == false, "Platform Timer State Failed.");
// Test one Timer that spans the 32-bit wrap.
InitCounters();
sNow = 0 - (kTimerInterval - 2);
timer.Start(kTimerInterval);
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "Start CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "Handler CallCount Failed.");
VerifyOrQuit(sPlatT0 == 0 - (kTimerInterval - 2) && sPlatDt == 10, "Start params Failed.");
VerifyOrQuit(timer.IsRunning(), "Timer running Failed.");
VerifyOrQuit(sTimerOn, "Platform Timer State Failed.");
sNow += kTimerInterval;
AlarmFired<TimerType>(instance);
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "Start CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 1, "Stop CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 1, "Handler CallCount Failed.");
VerifyOrQuit(timer.IsRunning() == false, "Timer running Failed.");
VerifyOrQuit(sTimerOn == false, "Platform Timer State Failed.");
// Test one Timer that is late by several msec
InitCounters();
sNow = kTimeT0;
timer.Start(kTimerInterval);
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "Start CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "Handler CallCount Failed.");
VerifyOrQuit(sPlatT0 == 1000 && sPlatDt == 10, "Start params Failed.");
VerifyOrQuit(timer.IsRunning(), "Timer running Failed.");
VerifyOrQuit(sTimerOn, "Platform Timer State Failed.");
sNow += kTimerInterval + 5;
AlarmFired<TimerType>(instance);
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "Start CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 1, "Stop CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 1, "Handler CallCount Failed.");
VerifyOrQuit(timer.IsRunning() == false, "Timer running Failed.");
VerifyOrQuit(sTimerOn == false, "Platform Timer State Failed.");
// Test one Timer that is early by several msec
InitCounters();
sNow = kTimeT0;
timer.Start(kTimerInterval);
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "Start CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "Handler CallCount Failed.");
VerifyOrQuit(sPlatT0 == 1000 && sPlatDt == 10, "Start params Failed.");
VerifyOrQuit(timer.IsRunning(), "Timer running Failed.");
VerifyOrQuit(sTimerOn, "Platform Timer State Failed.");
sNow += kTimerInterval - 2;
AlarmFired<TimerType>(instance);
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 2, "Start CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "Handler CallCount Failed.");
VerifyOrQuit(timer.IsRunning() == true, "Timer running Failed.");
VerifyOrQuit(sTimerOn == true, "Platform Timer State Failed.");
sNow += kTimerInterval;
AlarmFired<TimerType>(instance);
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 2, "Start CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 1, "Stop CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 1, "Handler CallCount Failed.");
VerifyOrQuit(timer.IsRunning() == false, "Timer running Failed.");
VerifyOrQuit(sTimerOn == false, "Platform Timer State Failed.");
printf(" --> PASSED\n");
testFreeInstance(instance);
return 0;
}
/**
* Test the TimerScheduler's behavior of two timers started and fired.
*/
template <typename TimerType> int TestTwoTimers(void)
{
const uint32_t kTimeT0 = 1000;
const uint32_t kTimerInterval = 10;
Instance *instance = testInitInstance();
TestTimer<TimerType> timer1(*instance);
TestTimer<TimerType> timer2(*instance);
TestTimer<TimerType>::RemoveAll(*instance);
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, "Start CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "Handler CallCount Failed.");
VerifyOrQuit(sPlatT0 == kTimeT0 && sPlatDt == kTimerInterval, "Start params Failed.");
VerifyOrQuit(timer1.IsRunning(), "Timer running Failed.");
VerifyOrQuit(timer2.IsRunning() == false, "Timer running Failed.");
VerifyOrQuit(sTimerOn, "Platform Timer State Failed.");
sNow += kTimerInterval;
timer2.Start(kTimerInterval);
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "Start CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "Handler CallCount Failed.");
VerifyOrQuit(sPlatT0 == kTimeT0 && sPlatDt == kTimerInterval, "Start params Failed.");
VerifyOrQuit(timer1.IsRunning() == true, "Timer running Failed.");
VerifyOrQuit(timer2.IsRunning() == true, "Timer running Failed.");
VerifyOrQuit(sTimerOn, "Platform Timer State Failed.");
AlarmFired<TimerType>(instance);
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 2, "Start CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 1, "Handler CallCount Failed.");
VerifyOrQuit(timer1.GetFiredCounter() == 1, "Fire Counter failed.");
VerifyOrQuit(sPlatT0 == sNow && sPlatDt == kTimerInterval, "Start params Failed.");
VerifyOrQuit(timer1.IsRunning() == false, "Timer running Failed.");
VerifyOrQuit(timer2.IsRunning() == true, "Timer running Failed.");
VerifyOrQuit(sTimerOn == true, "Platform Timer State Failed.");
sNow += kTimerInterval;
AlarmFired<TimerType>(instance);
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 2, "Start CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 1, "Stop CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 2, "Handler CallCount Failed.");
VerifyOrQuit(timer2.GetFiredCounter() == 1, "Fire Counter failed.");
VerifyOrQuit(timer1.IsRunning() == false, "Timer running Failed.");
VerifyOrQuit(timer2.IsRunning() == false, "Timer running Failed.");
VerifyOrQuit(sTimerOn == false, "Platform Timer State Failed.");
// Test when second timer starts at the fire time of first timer (before AlarmFired<TimerType>()) 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, "Start CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "Handler CallCount Failed.");
VerifyOrQuit(sPlatT0 == kTimeT0 && sPlatDt == kTimerInterval, "Start params Failed.");
VerifyOrQuit(timer1.IsRunning(), "Timer running Failed.");
VerifyOrQuit(timer2.IsRunning() == false, "Timer running Failed.");
VerifyOrQuit(sTimerOn, "Platform Timer State Failed.");
sNow += kTimerInterval;
timer2.StartAt(TimeMilli(kTimeT0), kTimerInterval - 2); // Timer 2 is even before timer 1
VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "Handler CallCount Failed.");
VerifyOrQuit(timer1.IsRunning() == true, "Timer running Failed.");
VerifyOrQuit(timer2.IsRunning() == true, "Timer running Failed.");
VerifyOrQuit(sTimerOn, "Platform Timer State Failed.");
AlarmFired<TimerType>(instance);
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 1, "Handler CallCount Failed.");
VerifyOrQuit(timer2.GetFiredCounter() == 1, "Fire Counter failed.");
VerifyOrQuit(sPlatT0 == sNow && sPlatDt == 0, "Start params Failed.");
VerifyOrQuit(timer1.IsRunning() == true, "Timer running Failed.");
VerifyOrQuit(timer2.IsRunning() == false, "Timer running Failed.");
VerifyOrQuit(sTimerOn == true, "Platform Timer State Failed.");
AlarmFired<TimerType>(instance);
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 1, "Stop CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 2, "Handler CallCount Failed.");
VerifyOrQuit(timer1.GetFiredCounter() == 1, "Fire Counter failed.");
VerifyOrQuit(timer1.IsRunning() == false, "Timer running Failed.");
VerifyOrQuit(timer2.IsRunning() == false, "Timer running Failed.");
VerifyOrQuit(sTimerOn == false, "Platform Timer State Failed.");
// Timer 1 fire callback is late by some ticks/ms, and second timer is scheduled (before call to
// AlarmFired) 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, "Start CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "Handler CallCount Failed.");
VerifyOrQuit(sPlatT0 == kTimeT0 && sPlatDt == kTimerInterval, "Start params Failed.");
VerifyOrQuit(timer1.IsRunning(), "Timer running Failed.");
VerifyOrQuit(timer2.IsRunning() == false, "Timer running Failed.");
VerifyOrQuit(sTimerOn, "Platform Timer State Failed.");
sNow += kTimerInterval + 5;
timer2.Start(Timer::kMaxDelay);
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "Start CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "Handler CallCount Failed.");
VerifyOrQuit(timer1.IsRunning() == true, "Timer running Failed.");
VerifyOrQuit(timer2.IsRunning() == true, "Timer running Failed.");
VerifyOrQuit(sTimerOn, "Platform Timer State Failed.");
AlarmFired<TimerType>(instance);
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 2, "Start CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 1, "Handler CallCount Failed.");
VerifyOrQuit(timer1.GetFiredCounter() == 1, "Fire Counter failed.");
VerifyOrQuit(sPlatT0 == sNow, "Start params Failed.");
VerifyOrQuit(sPlatDt == Timer::kMaxDelay, "Start params Failed.");
VerifyOrQuit(timer1.IsRunning() == false, "Timer running Failed.");
VerifyOrQuit(timer2.IsRunning() == true, "Timer running Failed.");
VerifyOrQuit(sTimerOn == true, "Platform Timer State Failed.");
sNow += Timer::kMaxDelay;
AlarmFired<TimerType>(instance);
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 2, "Start CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 1, "Stop CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 2, "Handler CallCount Failed.");
VerifyOrQuit(timer2.GetFiredCounter() == 1, "Fire Counter failed.");
VerifyOrQuit(timer1.IsRunning() == false, "Timer running Failed.");
VerifyOrQuit(timer2.IsRunning() == false, "Timer running Failed.");
VerifyOrQuit(sTimerOn == false, "Platform Timer State Failed.");
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).
*/
template <typename TimerType> 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, (Timer::kMaxDelay - kTimeT0[2]), 100000, 1000000, 10, Timer::kMaxDelay, 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 kMaxDuration
// 6 kMaxDuration + 1005
const uint32_t kTriggerTimes[kNumTriggers] = {
1014, 1020, 1100, 1207, 101004, Timer::kMaxDelay, Timer::kMaxDelay + 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};
Instance *instance = testInitInstance();
TestTimer<TimerType> timer0(*instance);
TestTimer<TimerType> timer1(*instance);
TestTimer<TimerType> timer2(*instance);
TestTimer<TimerType> timer3(*instance);
TestTimer<TimerType> timer4(*instance);
TestTimer<TimerType> timer5(*instance);
TestTimer<TimerType> timer6(*instance);
TestTimer<TimerType> timer7(*instance);
TestTimer<TimerType> timer8(*instance);
TestTimer<TimerType> timer9(*instance);
TestTimer<TimerType> *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.
TestTimer<TimerType>::RemoveAll(*instance);
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 otPlatAlarmMilliStartAt 2 times.
// one for timer[0] and one for timer[5] which will supersede timer[0].
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 2, "TestTenTimer: Start CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "TestTenTimer: Stop CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "TestTenTimer: Handler CallCount Failed.");
VerifyOrQuit(sPlatT0 == kTimeT0[5] + aTimeShift, "TestTenTimer: Start params Failed.");
VerifyOrQuit(sPlatDt == kTimerInterval[5], "TestTenTimer: Start params Failed.");
VerifyOrQuit(sTimerOn, "TestTenTimer: Platform Timer State Failed.");
for (i = 0; i < kNumTimers; i++)
{
VerifyOrQuit(timers[i]->IsRunning(), "TestTenTimer: Timer running Failed.");
}
// 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 AlarmFired<TimerType>() can result in 0 or 1 calls to a timer handler.
// For some combinations of sNow and Timers queued, it is necessary to call AlarmFired<TimerType>()
// 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 otPlatAlarmMilliStartAt(). If
// that value is 0, then AlarmFired should be fired immediately. This loop calls
// AlarmFired<TimerType>() the requisite number of times based on the aDt argument.
AlarmFired<TimerType>(instance);
} while (sPlatDt == 0);
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == kTimerStartCountAfterTrigger[trigger],
"TestTenTimer: Start CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == kTimerStopCountAfterTrigger[trigger],
"TestTenTimer: Stop CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == kTimerHandlerCountAfterTrigger[trigger],
"TestTenTimer: Handler CallCount Failed.");
VerifyOrQuit(sTimerOn == kSchedulerStateAfterTrigger[trigger], "TestTenTimer: Platform Timer State Failed.");
for (i = 0; i < kNumTimers; i++)
{
VerifyOrQuit(timers[i]->IsRunning() == kTimerStateAfterTrigger[trigger][i],
"TestTenTimer: Timer running Failed.");
}
}
for (i = 0; i < kNumTimers; i++)
{
VerifyOrQuit(timers[i]->GetFiredCounter() == 1, "TestTenTimer: Timer fired counter Failed.");
}
printf("--> PASSED\n");
testFreeInstance(instance);
}
template <typename TimerType> int TestTenTimers(void)
{
// Time shift to change the start/fire time of ten timers.
const uint32_t kTimeShift[] = {
0, 100000U, 0U - 1U, 0U - 1100U, Timer::kMaxDelay, Timer::kMaxDelay + 1020U,
};
size_t i;
for (i = 0; i < GetArrayLength(kTimeShift); i++)
{
TenTimers<TimerType>(kTimeShift[i]);
}
return 0;
}
/**
* Test the `Timer::Time` class.
*/
int TestTimerTime(void)
{
const uint32_t kMaxTime = 0xffffffff;
const uint32_t kStartTimes[] = {0, 100, kMaxTime / 2, kMaxTime - 100, kMaxTime};
const uint32_t kDurations[] = {1, 100, Timer::kMaxDelay - 1, Timer::kMaxDelay};
Time t1;
Time t2;
for (uint32_t startTime : kStartTimes)
{
for (uint32_t duration : kDurations)
{
printf("TestTimerTime() start=%-10x duration=%-10x ", startTime, duration);
t1.SetValue(startTime);
VerifyOrQuit(t1.GetValue() == startTime, "Time::SetValue() failed.");
t2 = t1;
VerifyOrQuit(t1.GetValue() == startTime, "Time assignment failed.");
VerifyOrQuit(t1 == t2, "Time == failed.");
VerifyOrQuit(!(t1 != t2), "Time != failed.");
VerifyOrQuit(!(t1 < t2), "Time < failed.");
VerifyOrQuit((t1 <= t2), "Time <= failed.");
VerifyOrQuit(!(t1 > t2), "Time > failed.");
VerifyOrQuit((t1 >= t2), "Time >= failed.");
VerifyOrQuit(t2 - t1 == 0, "Time difference failed");
t2 = t1 + duration;
VerifyOrQuit(!(t1 == t2), "Time == failed.");
VerifyOrQuit((t1 != t2), "Time != failed.");
VerifyOrQuit((t1 < t2), "Time < failed.");
VerifyOrQuit((t1 <= t2), "Time <= failed.");
VerifyOrQuit(!(t1 > t2), "Time > failed.");
VerifyOrQuit(!(t1 >= t2), "Time >= failed.");
VerifyOrQuit(t2 - t1 == duration, "Time difference failed");
t2 = t1;
t2 += duration;
VerifyOrQuit(!(t1 == t2), "Time == failed.");
VerifyOrQuit((t1 != t2), "Time != failed.");
VerifyOrQuit((t1 < t2), "Time < failed.");
VerifyOrQuit((t1 <= t2), "Time <= failed.");
VerifyOrQuit(!(t1 > t2), "Time > failed.");
VerifyOrQuit(!(t1 >= t2), "Time >= failed.");
VerifyOrQuit(t2 - t1 == duration, "Time difference failed");
t2 = t1 - duration;
VerifyOrQuit(!(t1 == t2), "Time == failed.");
VerifyOrQuit((t1 != t2), "Time != failed.");
VerifyOrQuit(!(t1 < t2), "Time < failed.");
VerifyOrQuit(!(t1 <= t2), "Time <= failed.");
VerifyOrQuit((t1 > t2), "Time > failed.");
VerifyOrQuit((t1 >= t2), "Time >= failed.");
VerifyOrQuit(t1 - t2 == duration, "Time difference failed");
t2 = t1;
t2 -= duration;
VerifyOrQuit(!(t1 == t2), "Time == failed.");
VerifyOrQuit((t1 != t2), "Time != failed.");
VerifyOrQuit(!(t1 < t2), "Time < failed.");
VerifyOrQuit(!(t1 <= t2), "Time <= failed.");
VerifyOrQuit((t1 > t2), "Time > failed.");
VerifyOrQuit((t1 >= t2), "Time >= failed.");
VerifyOrQuit(t1 - t2 == duration, "Time difference failed");
t2 = t1.GetDistantFuture();
VerifyOrQuit((t1 < t2) && !(t1 > t2), "GetDistanceFuture() failed");
t2 += 1;
VerifyOrQuit(!(t1 < t2) || (t1 > t2), "GetDistanceFuture() failed");
t2 = t1.GetDistantPast();
VerifyOrQuit((t1 > t2) && !(t1 < t2), "GetDistantPast() failed");
t2 -= 1;
VerifyOrQuit(!(t1 > t2) || (t1 < t2), "GetDistantPast() failed");
VerifyOrQuit(Min(t1, t1.GetDistantFuture()) == t1);
VerifyOrQuit(Min(t1.GetDistantFuture(), t1) == t1);
VerifyOrQuit(Max(t1, t1.GetDistantPast()) == t1);
VerifyOrQuit(Max(t1.GetDistantPast(), t1) == t1);
printf("--> PASSED\n");
}
}
return 0;
}
template <typename TimerType> void RunTimerTests(void)
{
TestOneTimer<TimerType>();
TestTwoTimers<TimerType>();
TestTenTimers<TimerType>();
}
} // namespace ot
int main(void)
{
ot::RunTimerTests<ot::TimerMilli>();
#if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
ot::RunTimerTests<ot::TimerMicro>();
#endif
ot::TestTimerTime();
printf("All tests passed\n");
return 0;
}