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) 2002-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\mqueue\t_mqueue.cpp
// Overview:
// Test message queuing
// API Information:
// RMsgQueue, RMsgQueueBase
// Details:
// - Create various illegal and legal private message queues and verify
// results are as expected. Test private message queue functionality in
// both single threaded tests and multi-threaded tests.
// - Create various illegal and legal global named message queues and verify
// results are as expected. Test global named message queue functionality
// in both single threaded tests and multi-threaded tests.
// - Test multi-process queues and template based queues, verify results are
// as expected.
// Platforms/Drives/Compatibility:
// All.
// Assumptions/Requirement/Pre-requisites:
// Failures and causes:
// Base Port information:
//
//
#include <e32test.h>
#include <e32svr.h>
#include <e32msgqueue.h>
#include <f32file.h>
LOCAL_D RTest test(_L("t_mqueue"));
//if the test is to run under the debugger, uncomment the following line
//#define _DEBUGGER_BUILD
const TInt KHeapSize=0x2000;
const TInt KTestValue = 42;
_LIT8(KFillPattern, "1234567890");
_LIT(KGLobalName1, "GlobalMessageQueue1");
LOCAL_C void SingleThreadedTests(RMsgQueueBase& aQueue, TInt aSlots, TInt aSize)
{
test.Printf(_L("Single Threaded Tests"));
TRequestStatus stat;
test.Next(_L("test CancelDataAvailable"));
aQueue.NotifyDataAvailable(stat);
test (stat == KRequestPending);
aQueue.CancelDataAvailable();
User::WaitForRequest(stat);
test (stat == KErrCancel);
TUint8 * pSourceData = (TUint8*)User::Alloc(aSize*2);
test(pSourceData != NULL);
TPtr8 pS(pSourceData, aSize*2, aSize*2);
pS.Repeat(KFillPattern);
TUint8 * pDestinationData = (TUint8*)User::Alloc(aSize*2);
test(pDestinationData != NULL);
TPtr8 pD(pDestinationData, aSize*2, aSize*2);
pD.FillZ();
test.Next(_L("test MessageSize"));
test(aQueue.MessageSize() == aSize);
test.Next(_L("Send a legal message through"));
TInt ret = aQueue.Send(pSourceData, aSize);
test(ret == KErrNone);
test.Next(_L("Receive legal message"));
ret = aQueue.Receive(pDestinationData, aSize);
test(ret == KErrNone);
TPtr8 p(pS);
p.SetLength(aSize);
pD.SetLength(aSize);
test(p == pD);
pD.FillZ();
test.Next(_L("Send a short message through"));
ret = aQueue.Send(pSourceData, aSize/2);
test(ret == KErrNone);
test.Next(_L("Receive legal message"));
ret = aQueue.Receive(pDestinationData, aSize);
test(ret == KErrNone);
p.SetLength(aSize/2);
pD.SetLength(aSize/2);
test(p == pD);
pD.FillZ();
test.Next(_L("Test Receive with no message"));
ret = aQueue.Receive(pDestinationData, aSize);
test(ret == KErrUnderflow);
if (aSlots >= 2)
{
test.Next(_L("Send two legal messages through"));
pS[0] = 0;
ret = aQueue.Send(pSourceData, aSize);
test(ret == KErrNone);
pS[0] = 1;
ret = aQueue.Send(pSourceData, aSize);
test(ret == KErrNone);
test.Next(_L("Receive two legal messages in tx order"));
ret = aQueue.Receive(pDestinationData, aSize);
test(ret == KErrNone);
test(pD[0] == 0);
pD.FillZ();
ret = aQueue.Receive(pDestinationData, aSize);
test(ret == KErrNone);
test(pD[0] == 1);
pD.FillZ();
}
test.Next(_L("Test filling the queue to the max"));
TInt x;
for (x = 0; x < aSlots; x++)
{
pS[0] = (TUint8)x;
ret = aQueue.Send(pSourceData, aSize);
test(ret == KErrNone);
}
test.Next(_L("Test one too many sends"));
ret = aQueue.Send(pSourceData, aSize);
test(ret == KErrOverflow);
test.Next(_L("test cancel SpaceAvailable"));
aQueue.NotifySpaceAvailable(stat);
test (stat == KRequestPending);
aQueue.CancelSpaceAvailable();
User::WaitForRequest(stat);
test (stat == KErrCancel);
test.Next(_L("Test emptying the queue"));
for (x = 0; x < aSlots; x++)
{
ret = aQueue.Receive(pDestinationData, aSize);
test(ret == KErrNone);
test(pD[0] == (TUint8)x );
pD.FillZ();
}
test.Next(_L("test cancel DataAvailable"));
aQueue.NotifyDataAvailable(stat);
test (stat == KRequestPending);
aQueue.CancelDataAvailable();
User::WaitForRequest(stat);
test (stat == KErrCancel);
test.Next(_L("Test one too many receives"));
ret = aQueue.Receive(pDestinationData, aSize);
test(ret == KErrUnderflow);
test.Next(_L("Test wrap around"));
test.Printf(_L("fill queue to max\n"));
for (x = 0; x < aSlots; x++)
{
pS[0] = (TUint8)x;
ret = aQueue.Send(pSourceData, aSize);
test(ret == KErrNone);
}
test.Printf(_L("half empty the queue\n"));
for (x = 0; x < aSlots/2; x++)
{
ret = aQueue.Receive(pDestinationData, aSize);
test(ret == KErrNone);
test(pD[0] == (TUint8)x);
pD.FillZ();
}
test.Printf(_L("fill queue to max\n"));
for (x = 0; x < aSlots/2; x++)
{
pS[0] = (TUint8)x;
ret = aQueue.Send(pSourceData, aSize);
test (ret == KErrNone);
}
ret = aQueue.Send(pSourceData, aSize);
test (ret == KErrOverflow);
test.Printf(_L("empty the queue\n"));
for (x = aSlots/2; x < aSlots; x++)
{
ret = aQueue.Receive(pDestinationData, aSize);
test(ret == KErrNone);
test(pD[0] == (TUint8)x);
}
for (x = 0; x < aSlots/2; x++)
{
ret = aQueue.Receive(pDestinationData, aSize);
test(ret == KErrNone);
test(pD[0] == (TUint8)x);
}
test.Next(_L("Test queue is empty"));
ret = aQueue.Receive(pDestinationData, aSize);
test(ret == KErrUnderflow);
User::Free(pSourceData);
User::Free(pDestinationData);
}
_LIT(KThread2Name, "thread2");
_LIT(KThread3Name, "thread3");
_LIT(KThread4Name, "thread4");
class TData
{
public:
TData(RMsgQueueBase* aQ, TInt aSize, TInt aSlots,TInt aTest=0, TAny* aData=NULL);
RMsgQueueBase* iQueue;
TInt iSize;
TInt iSlots;
TInt iTest;
TAny* iData;
};
TData::TData(RMsgQueueBase* aQ, TInt aSize, TInt aSlots, TInt aTest, TAny* aData) : iQueue(aQ), iSize(aSize),
iSlots(aSlots), iTest(aTest), iData(aData)
{
//empty
};
LOCAL_C TInt illegalSendEntryPoint(TAny* aData)
{
TData& data = *(TData *)aData;
switch (data.iTest)
{
case 0:
data.iQueue->Send(data.iData, data.iSize*2); //should panic, message size incorrect
break;
case 1:
#ifdef _DEBUGGER_BUILD
#pragma message ("BUILT FOR DEBUGGER")
User::Panic(_L("test"),ECausedException);
#else
data.iQueue->Send((TAny*)0xfeed, data.iSize); //should panic
#endif
break;
case 2:
#ifdef _DEBUGGER_BUILD
#pragma message ("BUILT FOR DEBUGGER")
User::Panic(_L("test"),ECausedException);
#else
data.iQueue->Send((TAny*)0xDEDEDEDE, data.iSize); //dodgy address
#endif
break;
}
test(0); //should never get here. This'll make a Kern Exec 0! as tries to use console from different thread
return 0;
}
LOCAL_C TInt illegalReceiveEntryPoint(TAny* aData)
{
TData& data = *(TData *)aData;
TUint8 buf[256];
switch (data.iTest)
{
case 0:
data.iQueue->Receive(buf, data.iSize*2); //should panic, message size incorrect
break;
case 1:
#ifdef _DEBUGGER_BUILD
#pragma message ("BUILT FOR DEBUGGER")
User::Panic(_L("test"),ECausedException);
#else
data.iQueue->Receive((TAny*)0xfeed, data.iSize); //should panic
#endif
break;
case 2:
#ifdef _DEBUGGER_BUILD
#pragma message ("BUILT FOR DEBUGGER")
User::Panic(_L("test"),ECausedException);
#else
data.iQueue->Receive((TAny*)0xDEDEDEDE, data.iSize); //dodgy address
#endif
break;
}
test(0); //should never get here. This'll make a Kern Exec 0!
return 0;
}
LOCAL_C TInt sendBlockingEntryPoint(TAny* aData)
{
TData& data = *(TData *)aData;
TInt d = KTestValue;
data.iQueue->SendBlocking(&d, 4);
return KErrNone;
}
LOCAL_C TInt receiveBlockingEntryPoint(TAny* aData)
{
TData& data = *(TData *)aData;
TUint8 pData[256];
TPtr8 pD(pData, data.iSize, data.iSize);
pD.FillZ();
data.iQueue->ReceiveBlocking(pData, data.iSize);
test (*(TInt*)pData == KTestValue);
return KErrNone;
}
LOCAL_C TInt notifyDataAvailableEntryPoint(TAny* aData)
{
TData& data = *(TData *)aData;
//check size as well
test(data.iQueue->MessageSize() == data.iSize);
TRequestStatus stat;
data.iQueue->NotifyDataAvailable(stat);
User::WaitForRequest(stat);
return KErrNone;
}
LOCAL_C TInt notifySpaceAvailableEntryPoint(TAny* aData)
{
TData& data = *(TData *)aData;
TRequestStatus stat;
data.iQueue->NotifySpaceAvailable(stat);
User::WaitForRequest(stat);
return KErrNone;
}
LOCAL_C void MultiThreadedTests(RMsgQueueBase& aQueue, TInt aSlots, TInt aSize)
{
test.Next(_L("multi threaded tests"));
RThread thread2;
TInt ret = KErrNone;
TAny* ptr = User::Alloc(aSize);
test.Next(_L("test Send with illegal parameters"));
TInt testnum;
TBool jit = User::JustInTime();
User::SetJustInTime(EFalse);
for (testnum = 0; testnum < 3; testnum++) //testnum range is determined by the number of tests in illegalSendEntryPoint
{
TData data(&aQueue, aSize, aSlots, testnum, ptr);
ret = thread2.Create(KThread2Name, illegalSendEntryPoint, KDefaultStackSize, KHeapSize, KHeapSize, &data);
test(KErrNone == ret);
TRequestStatus thread2stat;
thread2.Logon(thread2stat);
thread2.Resume();
User::WaitForRequest(thread2stat);
test (thread2.ExitType() == EExitPanic);
switch (testnum)
{
case 0:
test (thread2.ExitReason() == EMsgQueueInvalidLength);
break;
case 1:
test (thread2.ExitReason() == ECausedException);
break;
case 2:
test (thread2.ExitReason() == ECausedException);
break;
}
CLOSE_AND_WAIT(thread2);
}
User::SetJustInTime(jit);
test.Next(_L("test Receive with illegal parameters"));
jit = User::JustInTime();
User::SetJustInTime(EFalse);
for (testnum = 0; testnum < 3; testnum++) //testnum range is determined by the number of tests in illegalReceiveEntryPoint
{
//put something in the queue
aQueue.Send(&testnum, 4);
TData data(&aQueue, aSize, aSlots, testnum, ptr);
ret = thread2.Create(KThread2Name, illegalReceiveEntryPoint, KDefaultStackSize, KHeapSize, KHeapSize, &data);
test(KErrNone == ret);
TRequestStatus thread2stat;
thread2.Logon(thread2stat);
thread2.Resume();
User::WaitForRequest(thread2stat);
test (thread2.ExitType() == EExitPanic);
switch (testnum)
{
case 0:
test (thread2.ExitReason() == EMsgQueueInvalidLength);
break;
case 1:
test (thread2.ExitReason() == ECausedException);
break;
case 2:
test (thread2.ExitReason() == ECausedException);
break;
}
CLOSE_AND_WAIT(thread2);
}
User::SetJustInTime(jit);
while(KErrNone == aQueue.Receive(ptr, aSize)) //empty the queue
{
//empty,
}
test.Next(_L("multi threaded NotifySpaceAvailable"));
TInt dummydata = KTestValue;
//fill the queue
while (KErrNone == aQueue.Send(&dummydata, sizeof (TInt)))
{
//empty
}
TData data(&aQueue, aSize, aSlots);
ret = thread2.Create(KThread2Name, notifySpaceAvailableEntryPoint, KDefaultStackSize, KHeapSize, KHeapSize, &data);
test(KErrNone == ret);
TRequestStatus thread2stat;
thread2.Logon(thread2stat);
thread2.Resume();
//thread2 should be waiting for space available
test (thread2stat == KRequestPending);
aQueue.ReceiveBlocking(ptr, aSize);
User::WaitForRequest(thread2stat);
test (thread2stat == KErrNone);
test (thread2.ExitType() == EExitKill);
CLOSE_AND_WAIT(thread2);
//thread 2 has exited OK
//empty the queue
while (KErrNone == aQueue.Receive(ptr, aSize))
{
//empty
}
test.Next(_L("multi threaded SendBlocking, ReceiveBlocking"));
ret = thread2.Create(KThread2Name, receiveBlockingEntryPoint, KDefaultStackSize, KHeapSize, KHeapSize, &data);
test(KErrNone == ret);
thread2.Logon(thread2stat);
thread2.Resume();
aQueue.SendBlocking(&dummydata, sizeof (TInt));
User::WaitForRequest(thread2stat);
test (thread2.ExitType() == EExitKill);
CLOSE_AND_WAIT(thread2);
test.Next(_L("multiple ReceiveBlocking"));
ret = thread2.Create(KThread2Name, receiveBlockingEntryPoint, KDefaultStackSize, KHeapSize, KHeapSize, &data);
test(KErrNone == ret);
RThread thread3;
ret = thread3.Create(KThread3Name, receiveBlockingEntryPoint, KDefaultStackSize, KHeapSize, KHeapSize, &data);
test(KErrNone == ret);
RThread thread4;
ret = thread4.Create(KThread4Name, receiveBlockingEntryPoint, KDefaultStackSize, KHeapSize, KHeapSize, &data);
test(KErrNone == ret);
thread2.Logon(thread2stat);
TRequestStatus thread3stat;
thread3.Logon(thread3stat);
TRequestStatus thread4stat;
thread4.Logon(thread4stat);
thread2.Resume();
User::After(500000);
jit = User::JustInTime();
User::SetJustInTime(EFalse);
thread3.Resume();
thread4.Resume();
User::WaitForRequest(thread3stat, thread4stat);
if (thread3stat != KRequestPending)
User::WaitForRequest(thread4stat);
else
User::WaitForRequest(thread3stat);
User::SetJustInTime(jit);
//threads 3 and 4 have exited
test (thread3.ExitType() == EExitPanic);
test (thread3.ExitReason() == EMsgQueueRequestPending);
test (thread4.ExitType() == EExitPanic);
test (thread4.ExitReason() == EMsgQueueRequestPending);
test (thread2stat == KRequestPending);
aQueue.SendBlocking(&dummydata, sizeof (TInt));
User::WaitForRequest(thread2stat);
test (thread2stat == KErrNone);
test (thread2.ExitType() == EExitKill);
CLOSE_AND_WAIT(thread2);
CLOSE_AND_WAIT(thread3);
CLOSE_AND_WAIT(thread4);
//fill the queue
while (KErrNone == aQueue.Send(&dummydata, sizeof (TInt)))
{
//empty
}
test.Next(_L("multiple sendblocking"));
ret = thread2.Create(KThread2Name, sendBlockingEntryPoint, KDefaultStackSize, KHeapSize, KHeapSize, &data);
test(KErrNone == ret);
ret = thread3.Create(KThread3Name, sendBlockingEntryPoint, KDefaultStackSize, KHeapSize, KHeapSize, &data);
test(KErrNone == ret);
ret = thread4.Create(KThread4Name, sendBlockingEntryPoint, KDefaultStackSize, KHeapSize, KHeapSize, &data);
test(KErrNone == ret);
thread2.Logon(thread2stat);
thread3.Logon(thread3stat);
thread4.Logon(thread4stat);
thread2.Resume();
User::After(500000);
jit = User::JustInTime();
User::SetJustInTime(EFalse);
thread3.Resume();
thread4.Resume();
User::WaitForRequest(thread3stat, thread4stat);
if (thread3stat != KRequestPending)
User::WaitForRequest(thread4stat);
else
User::WaitForRequest(thread3stat);
User::SetJustInTime(jit);
//threads 3 and 4 have exited
test (thread3.ExitType() == EExitPanic);
test (thread3.ExitReason() == EMsgQueueRequestPending);
test (thread4.ExitType() == EExitPanic);
test (thread4.ExitReason() == EMsgQueueRequestPending);
test (thread2stat == KRequestPending);
//consume one to allow the blocking write
test(KErrNone == aQueue.Receive(ptr, aSize));
User::WaitForRequest(thread2stat);
test (thread2stat == KErrNone);
test (thread2.ExitType() == EExitKill);
//consume the rest of the queue
while (KErrNone == aQueue.Receive(ptr, aSize))
{
// empty
}
CLOSE_AND_WAIT(thread2);
CLOSE_AND_WAIT(thread3);
CLOSE_AND_WAIT(thread4);
test.Next(_L("multi threaded NotifyDataAvailable"));
ret = thread2.Create(KThread2Name, notifyDataAvailableEntryPoint, KDefaultStackSize, KHeapSize, KHeapSize, &data);
test(KErrNone == ret);
thread2.Logon(thread2stat);
thread2.Resume();
//thread2 should be waiting for data available
test (thread2stat == KRequestPending);
aQueue.SendBlocking(&dummydata, sizeof (TInt));
User::WaitForRequest(thread2stat);
test (thread2stat == KErrNone);
test (thread2.ExitType() == EExitKill);
CLOSE_AND_WAIT(thread2);
//thread 2 has exited OK
//empty the queue
aQueue.ReceiveBlocking(ptr, aSize);
test (*(TInt*)ptr == dummydata);
//create thread 2 again
ret = thread2.Create(KThread2Name, notifyDataAvailableEntryPoint, KDefaultStackSize, KHeapSize, KHeapSize, &data);
test(KErrNone == ret);
thread2.Logon(thread2stat);
thread2.Resume();
//create thread3
ret = thread3.Create(KThread3Name, notifyDataAvailableEntryPoint, KDefaultStackSize, KHeapSize, KHeapSize, &data);
test(KErrNone == ret);
thread3.Logon(thread3stat);
User::SetJustInTime(EFalse);
User::After(10000);
thread3.Resume();
User::WaitForRequest(thread3stat);
User::SetJustInTime(jit);
test (thread3.ExitType() == EExitPanic);
test (thread3.ExitReason() == EMsgQueueRequestPending);
CLOSE_AND_WAIT(thread3);
aQueue.SendBlocking(&dummydata, sizeof (TInt));
User::WaitForRequest(thread2stat);
test (thread2stat == KErrNone);
test (thread2.ExitType() == EExitKill);
CLOSE_AND_WAIT(thread2);
//empty the queue
aQueue.ReceiveBlocking(ptr, aSize);
test (*(TInt*)ptr == dummydata);
User::Free(ptr);
}
class TTemplateTestData
{
public:
TTemplateTestData();
TTemplateTestData(TInt a, TUint b, TUint8 c, TBool d, TInt e);
TInt first;
TUint second;
TUint8 bob;
TBool fred;
TInt chipper;
};
TTemplateTestData::TTemplateTestData() : first(0), second(0), bob(0), fred(0), chipper(0)
{
}
TTemplateTestData::TTemplateTestData(TInt a, TUint b, TUint8 c, TBool d, TInt e) : first(a), second(b), bob(c), fred(d), chipper(e)
{
}
enum TQueueType {ECreateLocal, ECreateGlobal};
LOCAL_C TInt illegalQueueCreation(TAny* aData)
{
TData& data = *(TData *)aData;
switch (data.iTest)
{
case ECreateLocal: //CreateLocal
{
RMsgQueueBase queue;
queue.CreateLocal(data.iSlots, data.iSize);
break;
}
case ECreateGlobal: //create global named
{
RMsgQueueBase queue;
queue.CreateGlobal(KGLobalName1, data.iSlots, data.iSize);
break;
}
}
test(0); //should never get here. This'll make a Kern Exec 0! as tries to use console from different thread
return 0;
}
LOCAL_C void TestIllegalCreation(TInt aSlots, TInt aSize, TQueueType aQueueType, TInt aExpectedReason)
{
RThread thread;
TData data(NULL, aSize, aSlots, aQueueType, NULL);
TRequestStatus threadstat;
TBool jit = User::JustInTime();
User::SetJustInTime(EFalse);
TInt ret = thread.Create(KThread2Name, illegalQueueCreation, KDefaultStackSize, KHeapSize, KHeapSize, &data);
test(KErrNone == ret);
thread.Logon(threadstat);
thread.Resume();
User::WaitForRequest(threadstat);
test (thread.ExitType() == EExitPanic);
test (thread.ExitReason() == aExpectedReason);
CLOSE_AND_WAIT(thread);
User::SetJustInTime(jit);
}
TInt DyingDataAvailableThread( TAny* )
{
RMsgQueue<TInt> theQ;
if( KErrNone != theQ.OpenGlobal(_L("TestNotifiedThreadDied")) )
User::Panic( _L("TESTTH"), 0 );
TRequestStatus stat;
theQ.NotifyDataAvailable( stat );
// now just exit
return KErrNone;
}
TInt DyingSpaceAvailableThread( TAny* )
{
RMsgQueue<TInt> theQ;
if( KErrNone != theQ.OpenGlobal(_L("TestNotifiedThreadDied")) )
User::Panic( _L("TESTTH"), 0 );
TRequestStatus stat;
theQ.NotifySpaceAvailable( stat );
// now just exit
return KErrNone;
}
struct TThreadParams
{
TInt imyQHandle;
TRequestStatus* iRequest;
};
TInt DyingRequestDataNotification(TAny* aThreadParams)
{
CTrapCleanup* trapHandler = CTrapCleanup::New();
if(!trapHandler)
return KErrNoMemory;
TThreadParams* tp = reinterpret_cast<TThreadParams*>(aThreadParams);
RMsgQueue<TInt> msgQue2;
msgQue2.SetHandle(tp->imyQHandle);
msgQue2.NotifyDataAvailable(*tp->iRequest);
delete trapHandler;
return KErrNone;
}
void TestNotifiedThreadDied()
{
RThread th;
TRequestStatus stat;
RMsgQueue<TInt> myQ;
test( KErrNone == myQ.CreateGlobal( _L("TestNotifiedThreadDied"), 1 ) );
//Test when thread waiting on data available dies
test( KErrNone == th.Create( _L("DyingDataAvailableThread"), DyingDataAvailableThread, 1024, 1024, 8192, NULL ) );
th.Logon( stat );
th.Resume();
User::WaitForRequest( stat );
test(stat.Int()==KErrNone);
User::After( 1000000 );
myQ.NotifyDataAvailable( stat );
myQ.CancelDataAvailable();
CLOSE_AND_WAIT(th);
//Test when thread waiting on space available dies
myQ.Send(0);//This will fill in the whole message queue and block any thread waiting on space available.
test( KErrNone == th.Create( _L("DyingSpaceAvailableThread"), DyingSpaceAvailableThread, 1024, 1024, 8192, NULL ) );
th.Logon( stat );
th.Resume();
User::WaitForRequest( stat );
test(stat.Int()==KErrNone);
User::After( 1000000 );
myQ.NotifySpaceAvailable( stat );
myQ.CancelSpaceAvailable();
myQ.Close();
CLOSE_AND_WAIT(th);
// Calling cancel notification should not crash as the thread that requested notification dies
test( KErrNone == myQ.CreateLocal(1, EOwnerProcess));
TThreadParams tp;
tp.imyQHandle = myQ.Handle();
tp.iRequest = &stat;
test( KErrNone == th.Create(_L("DyingRequestDataNotificationThread"), DyingRequestDataNotification, KDefaultStackSize,
KHeapSize, KHeapSize, reinterpret_cast<TAny*>(&tp)));
TRequestStatus status;
th.Logon(status);
th.Resume();
th.Close();
User::WaitForRequest(status);
test(status.Int() == KErrNone);
myQ.CancelDataAvailable();
myQ.Close();
}
LOCAL_C void RunTests(void)
{
TInt ret = KErrNone;
test.Start(_L("Testing"));
RMsgQueueBase mqueue;
// LOCAL message queues
test.Next(_L("Check when thread dies waiting to be notified."));
TestNotifiedThreadDied();
test.Next(_L("Create private message queue with 0 length params"));
TestIllegalCreation(0,0,ECreateLocal, EMsgQueueInvalidLength);
test.Next(_L("Create private message queue with 0 slots"));
TestIllegalCreation(0,4,ECreateLocal, EMsgQueueInvalidSlots);
test.Next(_L("Create private message queue with 0 size message"));
TestIllegalCreation(5, 0, ECreateLocal, EMsgQueueInvalidLength);
test.Next(_L("Create private message queue with none multiple of 4 size message"));
TestIllegalCreation(5, 9, ECreateLocal, EMsgQueueInvalidLength);
test.Next(_L("Create private message queue with illegal max length "));
TestIllegalCreation(8,RMsgQueueBase::KMaxLength+1, ECreateLocal, EMsgQueueInvalidLength);
test.Next(_L("Create private message queue, 43 slots, length 8"));
ret = mqueue.CreateLocal(43,8, EOwnerThread);
test (KErrNone == ret);
mqueue.Close();
test.Next(_L("Create private message queue with max length "));
ret = mqueue.CreateLocal(8, RMsgQueueBase::KMaxLength, EOwnerProcess);
test (KErrNone == ret);
mqueue.Close();
test.Next(_L("test private message queue functionality"));
test.Printf(_L("two slots, small queue"));
ret = mqueue.CreateLocal(2, 4);
test(KErrNone == ret);
SingleThreadedTests(mqueue, 2, 4);
MultiThreadedTests(mqueue, 2, 4);
mqueue.Close();
test.Printf(_L("16 slots, max queue"));
ret = mqueue.CreateLocal(16, RMsgQueueBase::KMaxLength);
test(KErrNone == ret);
SingleThreadedTests(mqueue, 16, RMsgQueueBase::KMaxLength);
MultiThreadedTests(mqueue, 16, RMsgQueueBase::KMaxLength);
mqueue.Close();
test.Printf(_L("big slots, max queue"));
ret = mqueue.CreateLocal(KMaxTInt, RMsgQueueBase::KMaxLength);
test(KErrNoMemory == ret);
/**************************************************************************/
// GLOBAL Named message queues
test.Next(_L("Create global named message queue with 0 length params"));
TestIllegalCreation(0, 0, ECreateGlobal, EMsgQueueInvalidLength);
test.Next(_L("Create global named message queue with 0 slots"));
TestIllegalCreation(0, 4, ECreateGlobal, EMsgQueueInvalidSlots);
test.Next(_L("Create global message queue with 0 size message"));
TestIllegalCreation(5, 0, ECreateGlobal, EMsgQueueInvalidLength);
test.Next(_L("Create global message queue with none multiple of 4 size message"));
TestIllegalCreation(5, 9, ECreateGlobal, EMsgQueueInvalidLength);
test.Next(_L("Create global named message queue with illegal max length "));
TestIllegalCreation(8, RMsgQueueBase::KMaxLength+1, ECreateGlobal, EMsgQueueInvalidLength);
test.Next(_L("Create global named message queue"));
ret = mqueue.CreateGlobal(KGLobalName1, 10,8, EOwnerThread);
test (KErrNone == ret);
mqueue.Close();
test.Next(_L("Create global named message queue with max length "));
ret = mqueue.CreateGlobal(KGLobalName1, 8, RMsgQueueBase::KMaxLength, EOwnerProcess);
test (KErrNone == ret);
mqueue.Close();
test.Next(_L("test global named message queue functionality"));
test.Printf(_L("small queue, two slots"));
ret = mqueue.CreateGlobal(KGLobalName1, 2, 4);
test(KErrNone == ret);
SingleThreadedTests(mqueue, 2, 4);
MultiThreadedTests(mqueue, 2, 4);
mqueue.Close();
test.Printf(_L("max queue, 16 slots"));
ret = mqueue.CreateGlobal(KGLobalName1, 16, RMsgQueueBase::KMaxLength);
test(KErrNone == ret);
SingleThreadedTests(mqueue, 16, RMsgQueueBase::KMaxLength);
MultiThreadedTests(mqueue, 16, RMsgQueueBase::KMaxLength);
mqueue.Close();
test.Printf(_L("32byte queue, 1000 slots"));
ret = mqueue.CreateGlobal(KGLobalName1, 1000, 32);
test(KErrNone == ret);
SingleThreadedTests(mqueue, 1000, 32);
MultiThreadedTests(mqueue, 1000, 32);
mqueue.Close();
test.Printf(_L("12 byte queue, 1 slot"));
ret = mqueue.CreateGlobal(KGLobalName1, 1, 12);
test(KErrNone == ret);
SingleThreadedTests(mqueue, 1, 12);
MultiThreadedTests(mqueue, 1, 12);
mqueue.Close();
test.Printf(_L("max queue, maxint! slots"));
ret = mqueue.CreateGlobal(KGLobalName1, KMaxTInt, RMsgQueueBase::KMaxLength);
test(KErrNoMemory == ret);
_LIT(KNonQueueName,"non-queue name");
test.Printf(_L("open a non-existant queue"));
ret = mqueue.OpenGlobal(KNonQueueName, EOwnerProcess);
test(ret == KErrNotFound);
ret = mqueue.CreateGlobal(KGLobalName1, 16, 4);
test(KErrNone == ret);
SingleThreadedTests(mqueue, 16, 4);
MultiThreadedTests(mqueue, 16, 4);
RMsgQueueBase open;
ret = open.OpenGlobal(KGLobalName1);
test(KErrNone == ret);
SingleThreadedTests(open, 16,4);
MultiThreadedTests(open, 16, 4);
test.Next(_L("Send a legal message through"));
TInt src = 45;
TInt dst = 0;
ret = mqueue.Send(&src, sizeof (TInt));
test(ret == KErrNone);
test.Next(_L("Receive legal message"));
ret = open.Receive(&dst, 4);
test(ret == KErrNone);
test (src == dst);
test.Next(_L("Send a legal message through"));
ret = mqueue.Send(&src, sizeof (TInt));
test(ret == KErrNone);
open.Close();
mqueue.Close();
ret = mqueue.CreateGlobal(KNullDesC, 5, 4);
test(KErrNone == ret);
SingleThreadedTests(mqueue, 5,4);
MultiThreadedTests(mqueue, 5, 4);
ret = open.OpenGlobal(KNullDesC);
test(KErrNotFound == ret);
mqueue.Close();
test.Next(_L("Multi Process Queue Tests"));
_LIT(KQueueA, "A");
_LIT(KQueueB, "B");
_LIT(KProcessName, "T_MQUEUEECHO.EXE");
RMsgQueueBase inQueue;
RMsgQueueBase outQueue;
TInt sizes[6] = {4,8,16,32,100,256};
TInt x;
for (x = 0; x < 6; x++)
{
TUint8* p = (TUint8*)User::Alloc(sizes[x]);
TRequestStatus stat;
test (p != NULL);
ret = inQueue.CreateGlobal(KQueueB, 1, sizes[x]);
test (KErrNone == ret);
ret = outQueue.CreateGlobal(KQueueA, 1, sizes[x]);
test (KErrNone == ret);
//start other process
RProcess proc;
ret = proc.Create(KProcessName, KNullDesC);
test (KErrNone == ret);
//logon to it
proc.Logon(stat);
proc.Resume();
TInt y[64] = {1000};
while (--y[0] >= 0)
{
outQueue.SendBlocking(&y,sizes[x]);
inQueue.ReceiveBlocking(p, sizes[x]);
test (y[0] == *(TInt*)p);
}
User::Free(p);
inQueue.Close();
outQueue.Close();
//wait for the process to terminate
User::WaitForRequest(stat);
test(stat == KErrNone);
CLOSE_AND_WAIT(proc);
}
test.Next(_L("test templated queue"));
RMsgQueue<TTemplateTestData> templateQueue;
TTemplateTestData ch(1,2,3,ETrue,4);
TTemplateTestData ch2;
TTemplateTestData ch3;
test(KErrNone == templateQueue.CreateLocal(12));
test (KErrNone == templateQueue.Send(ch));
test (ch.first != ch2.first);
test (ch.chipper != ch2.chipper);
test (KErrNone == templateQueue.Receive(ch2));
test (ch.first == ch2.first);
test (ch.chipper == ch2.chipper);
templateQueue.SendBlocking(ch);
test (ch.first != ch3.first);
test (ch.chipper != ch3.chipper);
templateQueue.ReceiveBlocking(ch3);
test (ch.first == ch3.first);
test (ch.chipper == ch3.chipper);
templateQueue.Close();
test(KErrNone == templateQueue.CreateGlobal(KNullDesC, 79));
templateQueue.Close();
_LIT(KTestName, "testQueue");
test(KErrNone == templateQueue.CreateGlobal(KTestName, 986));
RMsgQueue<TTemplateTestData> templateQueue2;
test(KErrNone == templateQueue2.OpenGlobal(KTestName));
templateQueue.Close();
templateQueue2.Close();
test.Next(_L("Ending test.\n"));
test.End();
test.Close();
}
GLDEF_C TInt E32Main()
//
//
{
test.Title();
// Turn off evil lazy dll unloading
RLoader l;
test(l.Connect()==KErrNone);
test(l.CancelLazyDllUnload()==KErrNone);
l.Close();
RunTests();
return KErrNone;
}