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\active\t_cactw.cpp
// Overview:
// Test the CActiveSchedulerWait class.
// API Information:
// CActiveSchedulerWait
// Details:
// - Verify the thread is panicked when one of the following programming errors occurs:
// - the scheduler is started twice.
// - the scheduler is stopped without starting scheduler.
// - the scheduler is started and then stopped twice.
// - the CanStopNow method of scheduler is called without starting scheduler.
// - Run different combinations of wait, start, async stop, async stop with a callback,
// canstopnow and nested calls to start and async stop operations and verify they run
// correctly
// - Check the heap is not corrupted by all the tests.
// Platforms/Drives/Compatibility:
// All.
// Assumptions/Requirement/Pre-requisites:
// Failures and causes:
// Base Port information:
//
//
#include <e32test.h>
#include <e32panic.h>
const TInt KPanicThreadRet = 222;
const TInt KHeapSize = 0x1000;
const TInt KMaxActions = 32;
const TInt KNumWaits = 2;
enum TDirective {ENormal,EStartTwice,EStopUnstarted,EStopTwice,ECanStopNotStarted};
enum TActionType {EStartWait, EStopWait, EStopWaitCallBack, EIsWaitStarted, ECanStopWait, EStart, EStop};
struct TAction
{
TActionType iType;
TInt iId;
};
class TSchedulerTester
{
public:
void Test1();
void Test2();
private:
void SubTest2(TAction* aActions, TInt aCount, const TDesC& aResult);
};
class CActionRunner : public CActive
{
public:
CActionRunner();
~CActionRunner();
void SetActions(TAction* aActions, TInt aCount);
void Start();
const TDesC& Trace() const;
private:
void DoCancel();
void RunL();
static TInt CallBack(TAny* aThis);
private:
TInt iStep;
TInt iNumActions;
TAction iActions[KMaxActions];
CActiveSchedulerWait iWait[KNumWaits];
TBuf<256> iTrace;
};
LOCAL_D RTest test(_L("T_CACTW"));
LOCAL_D RSemaphore threadSemaphore;
CActionRunner::CActionRunner() : CActive(EPriorityStandard)
{
CActiveScheduler::Add(this);
}
CActionRunner::~CActionRunner()
{
Cancel();
}
void CActionRunner::SetActions(TAction* aActions, TInt aCount)
{
iNumActions = aCount;
for (TInt ii=0; ii<aCount && ii<KMaxActions; ii++)
iActions[ii] = aActions[ii];
}
void CActionRunner::Start()
{
TRequestStatus* s = &iStatus;
SetActive();
User::RequestComplete(s, KErrNone);
}
void CActionRunner::DoCancel()
{
}
void CActionRunner::RunL()
{
Start();
if (iStep < iNumActions)
{
TAction& action = iActions[iStep];
CActiveSchedulerWait& wait = iWait[action.iId];
iTrace.AppendFormat(_L("%d%dS"), action.iId, action.iType);
iStep++;
switch (action.iType)
{
case EStartWait:
wait.Start();
break;
case EStopWait:
wait.AsyncStop();
break;
case EStopWaitCallBack:
wait.AsyncStop(TCallBack(CallBack, this));
break;
case EIsWaitStarted:
iTrace.AppendFormat(_L("%d"), wait.IsStarted()!=0);
break;
case ECanStopWait:
iTrace.AppendFormat(_L("%d"), wait.CanStopNow()!=0);
break;
case EStart:
CActiveScheduler::Start();
break;
case EStop:
CActiveScheduler::Stop();
break;
default:
break;
}
iTrace.AppendFormat(_L("%d%dE"), action.iId, action.iType);
}
}
const TDesC& CActionRunner::Trace() const
{
return iTrace;
}
TInt CActionRunner::CallBack(TAny* aThis)
{
CActionRunner* self = (CActionRunner*) aThis;
self->iTrace.Append(_L("C"));
return 0;
}
LOCAL_D TInt panicThread(TAny* aDirective)
//
// Test thread which panics
//
{
// cause panics in various ways depending upon aDirective
CActiveScheduler* pManager=new CActiveScheduler;
CActiveScheduler::Install(pManager);
CActionRunner* r = new(ELeave)CActionRunner;
switch((TInt)aDirective)
{
case ENormal:
{
TAction actions[] = {{EStop, 0}};
r->SetActions(actions, sizeof(actions)/sizeof(*actions));
break;
}
case EStartTwice:
{
TAction actions[] = {{EStartWait, 0}, {EStartWait, 0}, {EStop, 0}};
r->SetActions(actions, sizeof(actions)/sizeof(*actions));
break;
}
case EStopUnstarted:
{
TAction actions[] = {{EStopWait, 0}, {EStop, 0}};
r->SetActions(actions, sizeof(actions)/sizeof(*actions));
break;
}
case EStopTwice:
{
TAction actions[] = {{EStartWait, 0}, {EStopWait, 0}, {EStopWait, 0}, {EStop, 0}};
r->SetActions(actions, sizeof(actions)/sizeof(*actions));
break;
}
case ECanStopNotStarted:
{
TAction actions[] = {{ECanStopWait, 0}, {EStop, 0}};
r->SetActions(actions, sizeof(actions)/sizeof(*actions));
break;
}
default:
break;
}
r->Start();
CActiveScheduler::Start();
delete r;
delete pManager;
return(KPanicThreadRet);
}
void TSchedulerTester::Test1()
//
// Test 1
//
{
//
// Test the panics
//
RThread thread;
TRequestStatus stat;
//
test.Start(_L("First test normal thread termination"));
TInt r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ENormal);
test(r==KErrNone);
thread.Logon(stat);
thread.Resume();
User::WaitForRequest(stat);
test(thread.ExitCategory().Compare(_L("Kill"))==0);
test(thread.ExitReason()==KPanicThreadRet);
test(thread.ExitType()==EExitKill);
CLOSE_AND_WAIT(thread);
//
test.Next(_L("Two starts panics"));
r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EStartTwice);
test(r==KErrNone);
thread.Logon(stat);
thread.Resume();
User::WaitForRequest(stat);
test(thread.ExitReason()==EActiveSchedulerWaitAlreadyStarted);
test(thread.ExitType()==EExitPanic);
CLOSE_AND_WAIT(thread);
//
test.Next(_L("Stop without start panics"));
r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EStopUnstarted);
test(r==KErrNone);
thread.Logon(stat);
thread.Resume();
User::WaitForRequest(stat);
test(thread.ExitReason()==EActiveSchedulerWaitNotStarted);
test(thread.ExitType()==EExitPanic);
CLOSE_AND_WAIT(thread);
//
test.Next(_L("Start then two stops panics"));
r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EStopTwice);
test(r==KErrNone);
thread.Logon(stat);
thread.Resume();
User::WaitForRequest(stat);
test(thread.ExitReason()==EActiveSchedulerWaitNotStarted);
test(thread.ExitType()==EExitPanic);
CLOSE_AND_WAIT(thread);
//
test.Next(_L("Can stop now, without start panics"));
r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ECanStopNotStarted);
test(r==KErrNone);
thread.Logon(stat);
thread.Resume();
User::WaitForRequest(stat);
test(thread.ExitReason()==EActiveSchedulerWaitNotStarted);
test(thread.ExitType()==EExitPanic);
CLOSE_AND_WAIT(thread);
test.End();
}
void TSchedulerTester::Test2()
//
// Test 2
//
{
//
// Test sequencing
test.Start(_L("Scheduler wait sequencing"));
{
test.Next(_L("First a simple stop"));
TAction a[] = {{EStop, 0}};
SubTest2(a, sizeof(a)/sizeof(*a), _L("06S06E"));
}
{
test.Next(_L("Simple wait stop"));
TAction a[] = { {EIsWaitStarted, 0}, {EStartWait, 0}, {EIsWaitStarted, 0},
{ECanStopWait, 0}, {EStopWait, 0}, {EIsWaitStarted, 0},
{EStop, 0}};
SubTest2(a, sizeof(a)/sizeof(*a), _L("03S003E00S03S103E04S104E01S01E00E03S003E06S06E"));
}
{
test.Next(_L("Properly nested wait"));
TAction a[] = { {EStartWait, 0}, {EStartWait, 1},
{EStopWait, 1}, {EStopWait, 0}, {EStop, 0}};
SubTest2(a, sizeof(a)/sizeof(*a), _L("00S10S11S11E10E01S01E00E06S06E"));
}
{
test.Next(_L("Properly nested scheduler"));
TAction a[] = { {EStart, 0}, {EStart, 1},
{EStop, 1}, {EStop, 0}, {EStop, 0}};
SubTest2(a, sizeof(a)/sizeof(*a), _L("05S15S16S16E15E06S06E05E06S06E"));
}
{
test.Next(_L("Badly nested wait"));
TAction a[] = { {EStartWait, 0}, {EStartWait, 1},
{EStopWait, 0}, {EStopWait, 1}, {EStop, 0}};
SubTest2(a, sizeof(a)/sizeof(*a), _L("00S10S01S01E11S11E10E00E06S06E"));
}
{
test.Next(_L("Badly nested scheduler"));
TAction a[] = { {EStart, 0}, {EStart, 1},
{EStop, 0}, {EStop, 1}, {EStop, 0}};
SubTest2(a, sizeof(a)/sizeof(*a), _L("05S15S06S06E15E16S16E05E06S06E"));
}
{
test.Next(_L("Bad mixed nesting 1"));
TAction a[] = { {EStartWait, 0}, {EStart, 1},
{EStopWait, 0}, {EStop, 1}, {EStop, 0}};
SubTest2(a, sizeof(a)/sizeof(*a), _L("00S15S01S01E16S16E15E00E06S06E"));
}
{
test.Next(_L("Bad mixed nesting 2"));
TAction a[] = { {EStart, 0}, {EStartWait, 1},
{EStop, 0}, {EStopWait, 1}, {EStop, 0}};
SubTest2(a, sizeof(a)/sizeof(*a), _L("05S10S06S06E11S11E10E05E06S06E"));
}
{
test.Next(_L("Properly nested wait callback 1"));
TAction a[] = { {EStartWait, 0}, {EStartWait, 1},
{EStopWaitCallBack, 1}, {EStopWait, 0}, {EStop, 0}};
SubTest2(a, sizeof(a)/sizeof(*a), _L("00S10S12S12EC10E01S01E00E06S06E"));
}
{
test.Next(_L("Properly nested wait callback 2"));
TAction a[] = { {EStartWait, 0}, {EStartWait, 1},
{EStopWait, 1}, {EStopWaitCallBack, 0}, {EStop, 0}};
SubTest2(a, sizeof(a)/sizeof(*a), _L("00S10S11S11E10E02S02EC00E06S06E"));
}
{
test.Next(_L("Badly nested wait callback 1"));
TAction a[] = { {EStartWait, 0}, {EStartWait, 1},
{EStopWaitCallBack, 0}, {EStopWait, 1}, {EStop, 0}};
SubTest2(a, sizeof(a)/sizeof(*a), _L("00S10S02S02E11S11E10EC00E06S06E"));
}
{
test.Next(_L("Badly nested wait callback 2"));
TAction a[] = { {EStartWait, 0}, {EStartWait, 1},
{EStopWait, 0}, {EStopWaitCallBack, 1}, {EStop, 0}};
SubTest2(a, sizeof(a)/sizeof(*a), _L("00S10S01S01E12S12EC10E00E06S06E"));
}
{
test.Next(_L("Properly nested wait can stop now"));
TAction a[] = { {EStartWait, 0}, {EStartWait, 1}, {ECanStopWait, 0}, {ECanStopWait, 1},
{EStopWait, 1}, {ECanStopWait, 0}, {EStopWait, 0}, {EStop, 0}};
SubTest2(a, sizeof(a)/sizeof(*a), _L("00S10S04S004E14S114E11S11E10E04S104E01S01E00E06S06E"));
}
{
test.Next(_L("Badly nested wait can stop now"));
TAction a[] = { {EStartWait, 0}, {EStartWait, 1}, {ECanStopWait, 0}, {ECanStopWait, 1},
{EStopWait, 0}, {ECanStopWait, 1}, {EStopWait, 1}, {EStop, 0}};
SubTest2(a, sizeof(a)/sizeof(*a), _L("00S10S04S004E14S114E01S01E14S114E11S11E10E00E06S06E"));
}
{
test.Next(_L("Properly nested wait is started"));
TAction a[] = { {EStartWait, 0}, {EStartWait, 1}, {EIsWaitStarted, 0}, {EIsWaitStarted, 1},
{EStopWait, 1}, {EIsWaitStarted, 0}, {EIsWaitStarted, 1}, {EStopWait, 0}, {EStop, 0}};
SubTest2(a, sizeof(a)/sizeof(*a), _L("00S10S03S103E13S113E11S11E10E03S103E13S013E01S01E00E06S06E"));
}
{
test.Next(_L("Badly nested wait is started"));
TAction a[] = { {EStartWait, 0}, {EStartWait, 1}, {EIsWaitStarted, 0}, {EIsWaitStarted, 1},
{EStopWait, 0}, {EIsWaitStarted, 0}, {EIsWaitStarted, 1}, {EStopWait, 1}, {EStop, 0}};
SubTest2(a, sizeof(a)/sizeof(*a), _L("00S10S03S103E13S113E01S01E03S003E13S113E11S11E10E00E06S06E"));
}
{
test.Next(_L("Interleaved badly nested wait with callback"));
TAction a[] = { {EStartWait, 0}, {EStartWait, 1}, {EStopWaitCallBack, 0},
{EStartWait, 0}, {EStopWaitCallBack, 1}, {EStopWaitCallBack, 0},
{EStop, 0}};
SubTest2(a, sizeof(a)/sizeof(*a), _L("00S10S02S02E00S12S12E02S02EC00EC10EC00E06S06E"));
}
test.End();
}
void TSchedulerTester::SubTest2(TAction* aActions, TInt aCount, const TDesC& aResult)
{
CActiveScheduler* pManager=new CActiveScheduler;
CActiveScheduler::Install(pManager);
CActionRunner* r = new(ELeave)CActionRunner;
r->SetActions(aActions, aCount);
r->Start();
CActiveScheduler::Start();
test(r->Trace() == aResult);
delete r;
delete pManager;
}
GLDEF_C TInt E32Main()
{
// don't want just in time debugging as we trap panics
TBool justInTime=User::JustInTime();
User::SetJustInTime(EFalse);
test.Title();
__UHEAP_MARK;
//
test.Start(_L("Test1"));
TSchedulerTester sched;
sched.Test1();
//
test.Next(_L("Test2"));
sched.Test2();
//
test.End();
__UHEAP_MARKEND;
User::SetJustInTime(justInTime);
return(KErrNone);
}