diff -r 000000000000 -r a41df078684a kerneltest/e32test/prime/t_timer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/prime/t_timer.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,792 @@ +// 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 +#include +#include +#include +#include +#include + +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(0)); + test(delay=TTimeIntervalMicroSeconds(0)); + test(delay=TTimeIntervalMicroSeconds(0)); + test(delay=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) + { + test.Next(_L("Test sequential locks fail over on/off")); + RTimer tat; + TRequestStatus sat; + r=tat.CreateLocal(); + TTime now; + now.UniversalTime(); + tat.At(sat, now+TTimeIntervalSeconds(10)); // turn on in 10 seconds + 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); + } +