blob: 0cc4157665c150eaa046cd950f1920093d931be4 [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 "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