Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h)
Have multiple extension sections in the bld.inf, one for each version
of the compiler. The RVCT version building the tools will build the
runtime libraries for its version, but make sure we extract all the other
versions from zip archives. Also add the archive for RVCT4.
// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// e32test\prime\t_timer.cpp
// Overview:
// Time and Timer tests.
// API Information:
// RTimer, TTime
// Details:
// - Test relative timers using the RTimer::After() method. Verify
// results are as expected.
// - Set the date and time using TTime::HomeTime() and verify results
// are as expected.
// - Test absolute timers using RTimer::At() method. Verify results
// are as expected.
// - Test the timer is ok if its thread terminates.
// - Test synchronising time via the RTimer::Lock() method. Verify
// results are as expected.
// - Test locked timers abort when the system time changes.
// - Test User::ResetInactivityTime() results are as expected.
// Platforms/Drives/Compatibility:
// All.
// Assumptions/Requirement/Pre-requisites:
// Failures and causes:
// Base Port information:
//
//
// the following was used to help debug emulator implemenation of user mode callbacks
//#define REQUEST_STATUS_POLL_SOAK_TEST
#define __E32TEST_EXTENSION__
#include <e32test.h>
#include <e32hal.h>
#include <e32panic.h>
#include <hal.h>
#include <e32power.h>
#include <e32math.h>
LOCAL_D RTest test(_L("T_TIMER"));
TInt MachineUid;
TInt AfterNegative(TAny*)
{
RTimer t;
TInt r=t.CreateLocal();
test(r==KErrNone);
TRequestStatus s;
t.After(s,-1);
return KErrNone;
}
TInt AfterTwice(TAny*)
{
RTimer t;
TInt r=t.CreateLocal();
test(r==KErrNone);
TRequestStatus s;
t.After(s,1000000);
test(s==KRequestPending);
t.After(s,1000000);
return KErrNone;
}
void PrintTime()
{
TTime now;
now.HomeTime();
TDateTime dt(now.DateTime());
test.Printf(_L("Time: %02d:%02d:%02d:%06d\n"),dt.Hour(),dt.Minute(),dt.Second(),dt.MicroSecond());
}
TBool RequestIsComplete(TRequestStatus& s)
{
return s != KRequestPending;
}
LOCAL_C void testRel()
//
// Test relative timers.
//
{
test.Start(_L("After 0"));
RTimer t;
TInt r=t.CreateLocal();
test(r==KErrNone);
TRequestStatus s;
t.After(s,0);
test(s==KRequestPending || s==KErrNone);
User::WaitForRequest(s);
test(s==KErrNone);
test.Next(_L("After 1 tenth"));
t.After(s,100000);
#ifdef __WINS__
// On WINS we can't guarantee thread scheduling so timer may already have
// completed before we get to test the status. Therefore, allow KErrNone.
test(s==KRequestPending || s==KErrNone);
if(s==KErrNone)
test.Printf(_L("NOTE: completed 'early'"));
#else
test(s==KRequestPending);
#endif
User::WaitForRequest(s);
test(s==KErrNone);
test.Next(_L("After -1 millionth"));
RThread thread;
r=thread.Create(_L("After -1"),AfterNegative,KDefaultStackSize,NULL,&thread);
test(r==KErrNone);
thread.Logon(s);
test(s==KRequestPending);
TBool justInTime=User::JustInTime();
User::SetJustInTime(EFalse);
thread.Resume();
User::WaitForRequest(s);
test(s==ERTimerAfterTimeNegative);
test(thread.ExitCategory()==_L("USER"));
test(thread.ExitReason()==ERTimerAfterTimeNegative);
test(thread.ExitType()==EExitPanic);
CLOSE_AND_WAIT(thread);
User::SetJustInTime(justInTime);
test.Next(_L("After 1 second"));
t.After(s,1000000);
test(s==KRequestPending);
User::WaitForRequest(s);
test(s==KErrNone);
test.Next(_L("After 1 second polling"));
t.After(s,1000000);
test(s==KRequestPending);
// Have to be careful the compiler doesn't optimise this away
while(!RequestIsComplete(s))
; // poll
test(s==KErrNone);
User::WaitForRequest(s);
test.Next(_L("Cancel"));
t.After(s,1000000);
test(s==KRequestPending);
t.Cancel();
User::WaitForRequest(s);
test(s==KErrCancel);
t.Close();
test.Next(_L("Request twice"));
r=thread.Create(_L("After twice"),AfterTwice,KDefaultStackSize,NULL,&thread);
test(r==KErrNone);
thread.Logon(s);
test(s==KRequestPending);
User::SetJustInTime(EFalse);
thread.Resume();
User::WaitForRequest(s);
test(s==ETimerAlreadyPending);
test(thread.ExitCategory()==_L("KERN-EXEC"));
test(thread.ExitReason()==ETimerAlreadyPending);
test(thread.ExitType()==EExitPanic);
CLOSE_AND_WAIT(thread);
User::SetJustInTime(justInTime);
test.End();
}
#ifdef REQUEST_STATUS_POLL_SOAK_TEST
static volatile TBool PollTestRunning;
LOCAL_C TInt PollThread(TAny* aArg)
{
const TInt KMaxTimers = 1000;
TInt threadIndex = (TInt)aArg;
TInt64 seed = 5511498647534504549 + RThread().Id();
RTimer timers[KMaxTimers];
TRequestStatus statuses[KMaxTimers];
TInt i;
for (i = 0 ; i < KMaxTimers ; ++i)
{
test_KErrNone(timers[i].CreateLocal());
statuses[i] = 1;
}
TInt totalComplete = 0;
TInt totalWaiting = 0;
while(PollTestRunning)
{
for (i = 0 ; i < KMaxTimers ; ++i)
{
switch(statuses[i].Int())
{
case KRequestPending:
// do nothing
++totalWaiting;
break;
case KErrNone:
User::WaitForRequest(statuses[i]);
++totalComplete;
// fall through
case 1:
{
TInt after = ((TUint)Math::Rand(seed) >> 28) + 1;
timers[i].HighRes(statuses[i], after);
}
break;
default:
return statuses[i].Int();
}
}
}
for (i = 0 ; i < KMaxTimers ; ++i)
{
User::WaitForRequest(statuses[i]);
if (statuses[i].Int() != KErrNone)
return statuses[i].Int();
timers[i].Close();
}
RDebug::Printf("%d: %d %d\n", threadIndex, totalComplete, totalWaiting);
return KErrNone;
}
LOCAL_C void testPoll()
{
const TInt KMaxThreads = 10;
const TInt KSecondsToTest = 60;
RThread threads[KMaxThreads];
TRequestStatus statuses[KMaxThreads];
test.Start(_L("Test polling"));
PollTestRunning = ETrue;
TInt i;
for (i = 0 ; i < KMaxThreads ; ++i)
{
test_KErrNone(threads[i].Create(KNullDesC, PollThread, 0x1000, NULL, (TAny*)i));
threads[i].Logon(statuses[i]);
threads[i].Resume();
}
User::After(KSecondsToTest * 1000 * 1000);
PollTestRunning = EFalse;
for (i = 0 ; i < KMaxThreads ; ++i)
{
User::WaitForRequest(statuses[i]);
test_KErrNone(statuses[i].Int());
test_Equal(EExitKill, threads[i].ExitType());
threads[i].Close();
}
test.End();
}
#endif
LOCAL_C void testHomeTime()
//
// Test HomeTime.
//
{
TTime t1, t2;
t1.HomeTime();
for (TInt x=0;x<100;x++)
{
do
{
t2.HomeTime();
}
while (t2==t1);
#if defined(_DEBUG)
TDateTime dt=t2.DateTime();
test.Printf(_L("%d:%d\r\n"),dt.Second(),dt.MicroSecond());
#endif
test(t2>t1);
t1=t2;
}
#if defined(_DEBUG)
test.Printf(_L("\r\n"));
#endif
}
TInt AtTwice(TAny*)
{
RTimer t;
TInt r=t.CreateLocal();
test(r==KErrNone);
TRequestStatus s;
TTime time;
time.UniversalTime();
t.AtUTC(s,time+TTimeIntervalSeconds(1));
test(s==KRequestPending);
t.AtUTC(s,time+TTimeIntervalSeconds(2));
return KErrNone;
}
TInt AtAfter(TAny*)
{
RTimer t;
TInt r=t.CreateLocal();
test(r==KErrNone);
TRequestStatus s;
TTime time;
time.UniversalTime();
t.AtUTC(s,time+TTimeIntervalSeconds(1));
test(s==KRequestPending);
t.After(s,1000000);
return KErrNone;
}
TInt AfterAt(TAny*)
{
RTimer t;
TInt r=t.CreateLocal();
test(r==KErrNone);
TRequestStatus s;
TTime time;
time.UniversalTime();
t.After(s,1000000);
test(s==KRequestPending);
t.AtUTC(s,time+TTimeIntervalSeconds(2));
return KErrNone;
}
LOCAL_C void testAbs()
//
// Test absolute timers.
//
{
test.Start(_L("Now -1"));
RTimer t;
TInt r=t.CreateLocal();
test(r==KErrNone);
TRequestStatus s;
TTime time;
time.UniversalTime();
t.AtUTC(s,time+TTimeIntervalSeconds(-2));
test(s==KErrUnderflow); // =KRequestPending
User::WaitForRequest(s);
test(s==KErrUnderflow);
TTime time2;
test.Next(_L("Synchronise to clock"));
time.UniversalTime();
TDateTime dateTime=time.DateTime();
dateTime.SetMicroSecond(0);
time=dateTime;
time+=TTimeIntervalSeconds(2);
t.AtUTC(s,time);
User::WaitForRequest(s);
test.Next(_L("Now +1"));
time += TTimeIntervalSeconds(1);
t.AtUTC(s,time);
test(s==KRequestPending);
User::WaitForRequest(s);
time2.UniversalTime();
test(s==KErrNone);
TTimeIntervalMicroSeconds delay=time2.MicroSecondsFrom(time);
// Test we are in the same second as the requested time...
test(delay>=TTimeIntervalMicroSeconds(0));
test(delay<TTimeIntervalMicroSeconds(1000000));
test.Next(_L("Now +3"));
time += TTimeIntervalSeconds(3);
t.AtUTC(s,time);
test(s==KRequestPending);
User::WaitForRequest(s);
time2.UniversalTime();
test(s==KErrNone);
delay=time2.MicroSecondsFrom(time);
// Test we are in the same second as the requested time...
test(delay>=TTimeIntervalMicroSeconds(0));
test(delay<TTimeIntervalMicroSeconds(1000000));
test.Next(_L("UTC vs local"));
TTimeIntervalSeconds savedOffset = User::UTCOffset();
User::SetUTCOffset(3600);
time.HomeTime();
time += TTimeIntervalSeconds(1);
t.At(s,time);
test(s==KRequestPending);
User::WaitForRequest(s);
time2.HomeTime();
test(s==KErrNone);
delay=time2.MicroSecondsFrom(time);
// Test we are in the same second as the requested time...
test(delay>=TTimeIntervalMicroSeconds(0));
test(delay<TTimeIntervalMicroSeconds(1000000));
time.UniversalTime();
time += TTimeIntervalSeconds(1);
t.AtUTC(s,time);
test(s==KRequestPending);
User::WaitForRequest(s);
time2.UniversalTime();
test(s==KErrNone);
delay=time2.MicroSecondsFrom(time);
// Test we are in the same second as the requested time...
test(delay>=TTimeIntervalMicroSeconds(0));
test(delay<TTimeIntervalMicroSeconds(1000000));
User::SetUTCOffset(savedOffset);
test.Next(_L("Cancel"));
time.UniversalTime();
t.AtUTC(s,time+TTimeIntervalSeconds(10));
test(s==KRequestPending);
t.Cancel();
User::WaitForRequest(s);
test(s==KErrCancel);
t.Close();
test.Next(_L("Request twice"));
RThread thread;
r=thread.Create(_L("At twice"),AtTwice,KDefaultStackSize,NULL,&thread);
test(r==KErrNone);
thread.Logon(s);
test(s==KRequestPending);
TBool justInTime=User::JustInTime();
User::SetJustInTime(EFalse);
thread.Resume();
User::WaitForRequest(s);
User::SetJustInTime(justInTime);
test(s==ETimerAlreadyPending);
test(thread.ExitCategory()==_L("KERN-EXEC"));
test(thread.ExitReason()==ETimerAlreadyPending);
test(thread.ExitType()==EExitPanic);
CLOSE_AND_WAIT(thread);
r=thread.Create(_L("At After"),AtAfter,KDefaultStackSize,NULL,&thread);
test(r==KErrNone);
thread.Logon(s);
test(s==KRequestPending);
User::SetJustInTime(EFalse);
thread.Resume();
User::WaitForRequest(s);
User::SetJustInTime(justInTime);
test(s==ETimerAlreadyPending);
test(thread.ExitCategory()==_L("KERN-EXEC"));
test(thread.ExitReason()==ETimerAlreadyPending);
test(thread.ExitType()==EExitPanic);
CLOSE_AND_WAIT(thread);
r=thread.Create(_L("After At"),AfterAt,KDefaultStackSize,NULL,&thread);
test(r==KErrNone);
thread.Logon(s);
test(s==KRequestPending);
User::SetJustInTime(EFalse);
thread.Resume();
User::WaitForRequest(s);
User::SetJustInTime(justInTime);
test(s==ETimerAlreadyPending);
test(thread.ExitCategory()==_L("KERN-EXEC"));
test(thread.ExitReason()==ETimerAlreadyPending);
test(thread.ExitType()==EExitPanic);
CLOSE_AND_WAIT(thread);
test.End();
}
TInt LockTwice(TAny*)
{
RTimer t;
test(t.CreateLocal()==KErrNone);
TRequestStatus stat;
t.Lock(stat, ETwelveOClock);
User::WaitForRequest(stat);
test(stat==KErrGeneral);
t.Lock(stat, ETwelveOClock);
t.Lock(stat, ETwelveOClock);
return KErrNone;
}
LOCAL_C void testLock()
//
// Test locked timers
//
{
test.Start(_L("Test synchronise to ETwelveOClock"));
RTimer t;
TTime time,time2;
test(t.CreateLocal()==KErrNone);
TRequestStatus stat;
t.Lock(stat, ETwelveOClock);
User::WaitForRequest(stat);
test(stat==KErrGeneral);
time.UniversalTime();
t.Lock(stat, ETwelveOClock);
User::WaitForRequest(stat);
test(stat==KErrNone);
time2.UniversalTime();
test(time<time2);
User::After(500000);
test.Next(_L("Test sync to EOneOClock for 4 seconds"));
t.Lock(stat, EOneOClock);
User::WaitForRequest(stat);
test(stat==KErrGeneral);
time.UniversalTime();
TInt i;
for (i=0; i<5; i++)
{
t.Lock(stat, EOneOClock);
User::WaitForRequest(stat);
test(stat==KErrNone);
test.Printf(_L("."));
}
time2.UniversalTime();
TTimeIntervalSeconds ti;
test(time2.SecondsFrom(time, ti)==KErrNone);
test(ti>=TTimeIntervalSeconds(4));
test.Printf(_L("\n"));
test.Next(_L("Test sync to every half second, from EFourOClock for 5 seconds"));
t.Lock(stat, ETwelveOClock);
User::WaitForRequest(stat);
for (i=0; i<5; i++)
{
t.Lock(stat, EFourOClock);
User::WaitForRequest(stat);
test(stat==KErrNone);
test.Printf(_L("."));
t.Lock(stat, ETenOClock);
User::WaitForRequest(stat);
test(stat==KErrNone);
test.Printf(_L(","));
}
test.Printf(_L("\n"));
test.Next(_L("Test KErrGeneral after delay"));
User::After(1000000);
t.Lock(stat,EThreeOClock);
User::WaitForRequest(stat);
test(stat==KErrGeneral);
test.Next(_L("Test cancel, and re-request immediately"));
User::After(1000000);
t.Lock(stat, ETwelveOClock);
User::WaitForRequest(stat);
test(stat==KErrGeneral);
t.Lock(stat, EElevenOClock);
t.Cancel();
User::WaitForRequest(stat);
test(stat==KErrCancel);
t.Lock(stat, EElevenOClock);
User::WaitForRequest(stat);
test(stat==KErrNone);
test.Next(_L("Test complete a request at 1, then cancel a request for 11, and re-request at 3 gives KErrGeneral"));
User::After(1000000);
t.Lock(stat, ETwelveOClock);
User::WaitForRequest(stat);
test(stat==KErrGeneral);
t.Lock(stat,EOneOClock);
User::WaitForRequest(stat);
test(stat==KErrNone);
t.Lock(stat,EElevenOClock);
User::After(400000); // ensure EThreeOClock is in the past
t.Cancel();
User::WaitForRequest(stat);
test(stat==KErrCancel);
t.Lock(stat,EThreeOClock);
User::WaitForRequest(stat);
// EThreeOClock should be more than one second away from the previous timer expiration
test(stat==KErrGeneral);
test.Next(_L("Lock twice"));
RThread thread;
TInt r=thread.Create(_L("Lock twice"),LockTwice,KDefaultStackSize,NULL,&thread);
test(r==KErrNone);
thread.Logon(stat);
test(stat==KRequestPending);
TBool justInTime=User::JustInTime();
User::SetJustInTime(EFalse);
thread.Resume();
User::WaitForRequest(stat);
User::SetJustInTime(justInTime);
test(stat==ETimerAlreadyPending);
test(thread.ExitCategory()==_L("KERN-EXEC"));
test(thread.ExitReason()==ETimerAlreadyPending);
test(thread.ExitType()==EExitPanic);
CLOSE_AND_WAIT(thread);
#if !(defined(__EPOC32__) && defined(__X86__))
TInt muid = 0;
HAL::Get(HAL::EMachineUid, muid);
if(muid!=HAL::EMachineUid_Lubbock && muid!=HAL::EMachineUid_NE1_TB && muid!=HAL::EMachineUid_STE8500)
{
test.Next(_L("Test sequential locks fail over on/off"));
RTimer tat;
TRequestStatus sat;
r=tat.CreateLocal();
TTime now;
now.UniversalTime();
tat.AtUTC(sat, now+TTimeIntervalSeconds(10)); // turn on in 10 seconds
test(sat==KRequestPending);
t.Lock(stat, ETwelveOClock);
User::WaitForRequest(stat);
test(stat==KErrGeneral);
t.Lock(stat, EElevenOClock);
User::WaitForRequest(stat);
PrintTime();
// Go to standby
r = Power::EnableWakeupEvents(EPwStandby);
test (r == KErrNone);
r = Power::PowerDown();
test (r == KErrNone);
test(stat==KErrNone);
PrintTime();
t.Lock(stat, EElevenOClock);
User::WaitForRequest(stat);
test(stat==KErrGeneral);
tat.Close();
}
#endif
t.Close();
test.End();
}
void testChange()
//
// Bug HA-255
// Test locked timers abort when the system time changes
//
{
RTimer rr;
TRequestStatus stat;
rr.CreateLocal();
rr.Lock(stat, ETwelveOClock);
User::WaitForRequest(stat);
test(stat==KErrGeneral);
RTimer rrr;
rrr.CreateLocal();
rrr.After(stat, 1000000);
User::WaitForRequest(stat);
RTimer r;
TRequestStatus sstat;
TTime t;
r.CreateLocal();
r.Lock(stat,ETwelveOClock);
rr.Lock(sstat,EOneOClock);
User::WaitForRequest(stat);
test(stat==KErrGeneral);
User::WaitForRequest(sstat);
test(sstat==KErrGeneral);
r.Lock(stat,ETwelveOClock);
rr.Lock(sstat,EOneOClock);
User::WaitForRequest(stat);
test(stat==KErrNone);
User::WaitForRequest(sstat);
test(sstat==KErrNone);
t.UniversalTime();
r.Lock(stat,ETwelveOClock);
rr.Lock(sstat,EOneOClock);
TInt ret=User::SetUTCTime(t-TTimeIntervalSeconds(100));
test(ret==KErrNone);
t.UniversalTime();
ret=User::SetUTCTime(t+TTimeIntervalSeconds(100));
test(ret==KErrNone);
User::WaitForRequest(stat);
test(stat==KErrAbort);
User::WaitForRequest(sstat);
test(sstat==KErrAbort);
// Check that changing the *secure* time *doesn't* abort a locked timer
r.Lock(stat, ETwelveOClock);
User::WaitForRequest(stat); // stat will be KErrGeneral after abort above, but time will be TwelveOClock anyway
t.UniversalTimeSecure();
r.Lock(stat, EEightOClock);
ret = User::SetUTCTimeSecure(t+TTimeIntervalSeconds(100));
User::WaitForRequest(stat); // this timer should complete at EightOClock with status KErrNone, *not* KErrAbort
r.Lock(sstat, ETwelveOClock);
User::WaitForRequest(sstat); // this should complete one whole second after we read the secure time above
User::SetUTCTimeSecure(t+TTimeIntervalSeconds(1));
test(stat == KErrNone);
test(sstat == KErrNone);
if (ret != KErrNone)
RDebug::Printf("WARNING: Secure clock change test skipped because secure time could not be changed!");
r.Close();
rr.Close();
rrr.Close();
}
void testInactivity()
{
test.Start(_L("Test User::ResetInactivityTime()"));
RTimer t,t2;
TRequestStatus stat,stat2;
t.CreateLocal();
t2.CreateLocal();
User::ResetInactivityTime();
t.Inactivity(stat, 4);
t2.Inactivity(stat2, 2);
TTime now;
now.UniversalTime();
TInt r=User::SetUTCTime(now+TTimeIntervalDays(1));
test(r==KErrNone);
test(stat==KRequestPending);
test(stat2==KRequestPending);
r=User::SetUTCTime(now-TTimeIntervalDays(1));
test(r==KErrNone);
test(stat==KRequestPending);
test(stat2==KRequestPending);
r=User::SetUTCTime(now);
test(r==KErrNone);
test(stat==KRequestPending);
test(stat2==KRequestPending);
User::After(1000000);
User::ResetInactivityTime();
test(stat==KRequestPending);
test(stat2==KRequestPending);
User::After(3000000);
User::ResetInactivityTime();
test(stat==KRequestPending);
test(stat2!=KRequestPending);
User::After(2000000);
User::ResetInactivityTime();
test(stat==KRequestPending);
User::After(2000000);
User::ResetInactivityTime();
test(stat==KRequestPending);
User::After(5000000);
test(stat!=KRequestPending);
test.End();
}
GLDEF_C TInt E32Main()
//
// Test timers.
//
{
test.Title();
TInt r=HAL::Get(HAL::EMachineUid,MachineUid);
test(r==KErrNone);
test.Start(_L("Testing relative timers"));
testRel();
#ifdef REQUEST_STATUS_POLL_SOAK_TEST
test.Next(_L("Testing polling"));
testPoll();
#endif
test.Next(_L("Testing HomeTime()"));
testHomeTime();
test.Next(_L("Testing absolute timers"));
testAbs();
test.Next(_L("Testing locked timers"));
testLock();
test.Next(_L("Testing changing time"));
testChange();
test.Next(_L("Testing inactivity timers"));
testInactivity();
test.End();
return(KErrNone);
}