sl@0: // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32test\bench\t_svr5.cpp sl@0: // Overview: sl@0: // Test client server shareable sessions and benchmark their performance. sl@0: // API information: sl@0: // CSession2, CServer2, RSessionBase, RMessage2, DServer, DSession sl@0: // Details: sl@0: // - Start the test server sl@0: // - Open a connection with the server specifying 0 message slots should be sl@0: // available for the session and verify the server returns KErrServerBusy sl@0: // when it tries to pass a message to it. sl@0: // - Open a connection using a fixed pool of messages and test that the server sl@0: // handles the messages correctly. sl@0: // - Open a connection using the kernel's global pool of messages and test the sl@0: // servers handles the messages correctly. sl@0: // - Open a shareable session with the server and verify that: sl@0: // - all arguments are passed to the server and back correctly sl@0: // - server can read and write to/from the client and return the appropriate sl@0: // errors when bad descriptors are passed in. sl@0: // - another thread can share the session to send messages to the server. sl@0: // - a message sent by one thread can be saved and completed later in sl@0: // response to a message sent by a different thread. sl@0: // - another thread can close the session. sl@0: // - a different thread can attach to a session by handle. sl@0: // - Establish a global shareable session to the server and test it fails, as sl@0: // the server doesn't support global shareable sessions. sl@0: // - Open an unshareable session with the server and verify that: sl@0: // - all arguments are passed to the server and back correctly. sl@0: // - server can reads and write to/from the client and return the sl@0: // appropriate errors when bad descriptors are passed in. sl@0: // - the session handle is local (thread owned) sl@0: // - Open an automatically shared session using ShareAuto and test it can be sl@0: // shared by threads in the same process. sl@0: // - Send dummy messages that the server completes immediately and display how sl@0: // many are completed per second. sl@0: // - Verify that stopping the server completes existing pending requests with sl@0: // KErrServerTerminated. sl@0: // - Verify that the kernel does not crash by completing a message with an invalid sl@0: // handle and verify the client is panicked with EBadMessageHandle. sl@0: // Platforms/Drives/Compatibility: sl@0: // All. sl@0: // Assumptions/Requirement/Pre-requisites: sl@0: // Failures and causes: sl@0: // Base Port information: sl@0: // This test does not help to validate an EKA2 port. sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include sl@0: #define __E32TEST_EXTENSION__ sl@0: #include sl@0: #include sl@0: sl@0: #include "../mmu/mmudetect.h" sl@0: sl@0: const TInt KHeapSize=0x2000; sl@0: const TInt KMajorVersionNumber=1; sl@0: const TInt KMinorVersionNumber=0; sl@0: const TInt KBuildVersionNumber=1; sl@0: sl@0: _LIT(KServerName,"Display"); sl@0: sl@0: TInt SessionCreateLResult=0; sl@0: TInt SessionCostructCount=0; sl@0: TInt SessionDestructCount=0; sl@0: sl@0: class CMySession : public CSession2 sl@0: { sl@0: public: sl@0: CMySession(); sl@0: ~CMySession(); sl@0: void DisplayName(const RMessage2& aM); sl@0: virtual void ServiceL(const RMessage2& aMessage); sl@0: virtual void CreateL(); sl@0: TInt Hold(const RMessage2& aM); sl@0: TInt Release(const RMessage2& aM); sl@0: public: sl@0: RPointerArray iAsyncMsgArray; // 'pointers' are actually message handles sl@0: TInt iCompleteIndex; sl@0: }; sl@0: sl@0: TInt AsyncMsgOrder(const TInt& aL, const TInt& aR) sl@0: { sl@0: TInt lh = (TInt)&aL; sl@0: TInt rh = (TInt)&aR; sl@0: RMessage2 l(*(const RMessagePtr2*)&lh); sl@0: RMessage2 r(*(const RMessagePtr2*)&rh); sl@0: return l.Int0() - r.Int0(); sl@0: } sl@0: sl@0: TInt GetClientName(const RMessagePtr2& aM, TFullName& aN) sl@0: { sl@0: RThread t; sl@0: TInt r = aM.Client(t); sl@0: if (r==KErrNone) sl@0: { sl@0: aN = t.FullName(); sl@0: t.Close(); sl@0: } sl@0: return r; sl@0: } sl@0: sl@0: class CMyServer : public CServer2 sl@0: { sl@0: public: sl@0: enum {EDisplay,ERead,EWrite,ETest,EStop,EHold,ERelease,EGetCompleteIndex}; sl@0: public: sl@0: CMyServer(TInt aPriority); sl@0: static CMyServer* New(TInt aPriority); sl@0: virtual CSession2* NewSessionL(const TVersion& aVersion,const RMessage2& aMessage) const; sl@0: }; sl@0: sl@0: class CMyActiveScheduler : public CActiveScheduler sl@0: { sl@0: public: sl@0: virtual void Error(TInt anError) const; //Overloading pure virtual function sl@0: }; sl@0: sl@0: class RDisplay : public RSessionBase sl@0: { sl@0: public: sl@0: TInt Open(); sl@0: TInt OpenNoAsync(); sl@0: TInt OpenDynamic(); sl@0: TInt OpenUS(); sl@0: TInt OpenS(); sl@0: TInt OpenGS(); sl@0: TInt Display(const TDesC& aMessage); sl@0: TInt Read(); sl@0: TInt Write(); sl@0: TInt Stop(); sl@0: TInt Test(); sl@0: TInt Echo(TInt aWhat, TInt a0, TInt a1, TInt a2, TInt a3); sl@0: TVersion Version(); sl@0: TInt Hold(TInt aOrder=0, TInt aArg=0); sl@0: void Hold(TRequestStatus& aStatus, TInt aOrder=0, TInt aArg=0); sl@0: TInt Release(TInt aCount=KMaxTInt); sl@0: TInt CompleteIndex(); sl@0: }; sl@0: sl@0: LOCAL_D RTest test(_L("T_SVR")); sl@0: LOCAL_D RTest testSvr(_L("T_SVR Server")); sl@0: LOCAL_D RTest testSpeedy(_L("T_SVR Speedy")); sl@0: LOCAL_D RSemaphore client; sl@0: LOCAL_D TInt speedCount; sl@0: sl@0: CMySession::CMySession() sl@0: // sl@0: // Constructor sl@0: // sl@0: { sl@0: ++SessionCostructCount; sl@0: } sl@0: sl@0: CMySession::~CMySession() sl@0: { sl@0: iAsyncMsgArray.Close(); sl@0: ++SessionDestructCount; sl@0: } sl@0: sl@0: void CMySession::CreateL() sl@0: { sl@0: User::LeaveIfError(SessionCreateLResult); sl@0: } sl@0: sl@0: void CMySession::DisplayName(const RMessage2& aM) sl@0: // sl@0: // Display the client's name. sl@0: // sl@0: { sl@0: sl@0: TFullName fn; sl@0: TInt r = GetClientName(aM, fn); sl@0: testSvr(r==KErrNone); sl@0: TBuf<256> text; sl@0: r=aM.Read(0,text); sl@0: testSvr(r==KErrNone); sl@0: testSvr.Printf(_L("Session %08x %S\n%S\n"), this, &fn, &text); sl@0: } sl@0: sl@0: CMyServer* CMyServer::New(TInt aPriority) sl@0: // sl@0: // Create a new CMyServer. sl@0: // sl@0: { sl@0: sl@0: return new CMyServer(aPriority); sl@0: } sl@0: sl@0: CMyServer::CMyServer(TInt aPriority) sl@0: // sl@0: // Constructor. sl@0: // sl@0: : CServer2(aPriority, ESharableSessions) sl@0: {} sl@0: sl@0: CSession2* CMyServer::NewSessionL(const TVersion& aVersion, const RMessage2&) const sl@0: // sl@0: // Create a new client for this server. sl@0: // sl@0: { sl@0: sl@0: TVersion v(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber); sl@0: if (!User::QueryVersionSupported(v,aVersion)) sl@0: User::Leave(KErrNotSupported); sl@0: return new(ELeave) CMySession; sl@0: } sl@0: sl@0: void CMySession::ServiceL(const RMessage2& aMessage) sl@0: // sl@0: // Handle messages for this server. sl@0: // sl@0: { sl@0: sl@0: TInt f = aMessage.Function(); sl@0: if (f & 0x40000000) sl@0: { sl@0: TInt what = f & 0x3fffffff; sl@0: TInt a0 = aMessage.Int0(); sl@0: TInt a1 = aMessage.Int1(); sl@0: TInt a2 = aMessage.Int2(); sl@0: TInt a3 = aMessage.Int3(); sl@0: switch (what) sl@0: { sl@0: case 0: sl@0: aMessage.Complete(a0); sl@0: return; sl@0: case 1: sl@0: aMessage.Complete(a1); sl@0: return; sl@0: case 2: sl@0: aMessage.Complete(a2); sl@0: return; sl@0: case 3: sl@0: aMessage.Complete(a3); sl@0: return; sl@0: case 4: sl@0: aMessage.Complete(a0+a1+a2+a3); sl@0: return; sl@0: case 5: sl@0: aMessage.Complete(a0*a0+a1*a1+a2*a2+a3*a3); sl@0: return; sl@0: default: sl@0: break; sl@0: } sl@0: } sl@0: sl@0: TInt r=KErrNone; sl@0: TBuf<0x100> b; sl@0: switch (f) sl@0: { sl@0: case CMyServer::EDisplay: sl@0: DisplayName(aMessage); sl@0: break; sl@0: case CMyServer::ERead: sl@0: testSvr.Printf(_L("read message received\n")); sl@0: r=aMessage.Read(0,b); sl@0: if (r==KErrNone && b!=_L("Testing read")) sl@0: r=KErrGeneral; sl@0: if (r==KErrNone) sl@0: { sl@0: r=aMessage.Read(0,b,-1); sl@0: if (r==KErrNone) sl@0: r=KErrGeneral; sl@0: if (r==KErrArgument) sl@0: r=KErrNone; sl@0: } sl@0: if (r==KErrNone && HaveVirtMem()) sl@0: { sl@0: r=aMessage.Read(1,b); sl@0: if (r==KErrNone) sl@0: r=KErrGeneral; sl@0: if (r==KErrBadDescriptor) sl@0: r=KErrNone; sl@0: } sl@0: break; sl@0: case CMyServer::EWrite: sl@0: testSvr.Printf(_L("write message received\n")); sl@0: r=aMessage.Write(0,_L("It worked!")); sl@0: RDebug::Print(_L("Write returns %d"),r); sl@0: if (r==KErrNone) sl@0: { sl@0: r=aMessage.Write(0,b,-1); sl@0: if (r==KErrNone) sl@0: r=KErrGeneral; sl@0: if (r==KErrArgument) sl@0: r=KErrNone; sl@0: } sl@0: if (r==KErrNone) sl@0: { sl@0: r=aMessage.Write(1,b); sl@0: if (r==KErrNone) sl@0: r=KErrGeneral; sl@0: if (r==KErrBadDescriptor) sl@0: r=KErrNone; sl@0: } sl@0: if (r==KErrNone && HaveVirtMem()) sl@0: { sl@0: r=aMessage.Write(2,b); sl@0: if (r==KErrNone) sl@0: r=KErrGeneral; sl@0: if (r==KErrBadDescriptor) sl@0: r=KErrNone; sl@0: } sl@0: break; sl@0: case CMyServer::ETest: sl@0: break; sl@0: case CMyServer::EStop: sl@0: testSvr.Printf(_L("stop message received\n")); sl@0: CActiveScheduler::Stop(); sl@0: break; sl@0: case CMyServer::EHold: sl@0: { sl@0: r = Hold(aMessage); sl@0: if (r==KErrNone) sl@0: return; sl@0: break; sl@0: } sl@0: case CMyServer::ERelease: sl@0: { sl@0: r = Release(aMessage); sl@0: break; sl@0: } sl@0: case CMyServer::EGetCompleteIndex: sl@0: { sl@0: r = iCompleteIndex; sl@0: break; sl@0: } sl@0: default: sl@0: r=KErrNotSupported; sl@0: } sl@0: aMessage.Complete(r); sl@0: } sl@0: sl@0: TInt CMySession::Hold(const RMessage2& a) sl@0: { sl@0: TInt ord = a.Int0(); sl@0: TInt arg = a.Int1(); sl@0: TFullName fn; sl@0: TInt r = GetClientName(a, fn); sl@0: testSvr(r==KErrNone); sl@0: testSvr.Printf(_L("Hold message from %S ord %08x arg %08x\n"), &fn, ord, arg); sl@0: r = iAsyncMsgArray.InsertInOrder((const TInt*)a.Handle(), &AsyncMsgOrder); sl@0: return r; sl@0: } sl@0: sl@0: TInt CMySession::Release(const RMessage2& a) sl@0: { sl@0: TInt req_count = a.Int0(); sl@0: TInt avail = iAsyncMsgArray.Count(); sl@0: TInt count = Min(req_count, avail); sl@0: TFullName fn; sl@0: TInt r = GetClientName(a, fn); sl@0: testSvr(r==KErrNone); sl@0: testSvr.Printf(_L("Release message from %S req_count=%d count=%d\n"), &fn, req_count, count); sl@0: while (count--) sl@0: { sl@0: TInt mp = (TInt)iAsyncMsgArray[0]; sl@0: iAsyncMsgArray.Remove(0); sl@0: RMessage2 m(*(const RMessagePtr2*)&mp); sl@0: TInt arg = m.Int1(); sl@0: TInt code = arg ? arg ^ iCompleteIndex : 0; sl@0: r = GetClientName(m, fn); sl@0: testSvr(r==KErrNone); sl@0: testSvr.Printf(_L("Releasing %S arg=%08x index=%08x code=%08x\n"), &fn, arg, iCompleteIndex, code); sl@0: ++iCompleteIndex; sl@0: m.Complete(code); sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: void CMyActiveScheduler::Error(TInt anError) const sl@0: // sl@0: // Called if any Run() method leaves. sl@0: // sl@0: { sl@0: sl@0: testSvr.Panic(anError,_L("CMyActiveScheduler::Error")); sl@0: } sl@0: sl@0: TInt RDisplay::Open() sl@0: { sl@0: TInt r=CreateSession(KServerName,Version(),8); // use fixed pool of 8 slots sl@0: if (r==KErrNone) sl@0: r=ShareAuto(); sl@0: return r; sl@0: } sl@0: sl@0: TInt RDisplay::OpenUS() sl@0: { sl@0: return CreateSession(KServerName,Version(),8,EIpcSession_Unsharable); // use fixed pool of 8 slots sl@0: } sl@0: sl@0: TInt RDisplay::OpenS() sl@0: { sl@0: return CreateSession(KServerName,Version(),8,EIpcSession_Sharable); // use fixed pool of 8 slots sl@0: } sl@0: sl@0: TInt RDisplay::OpenGS() sl@0: { sl@0: return CreateSession(KServerName,Version(),8,EIpcSession_GlobalSharable); // use fixed pool of 8 slots sl@0: } sl@0: sl@0: TInt RDisplay::OpenNoAsync() sl@0: { sl@0: sl@0: TInt r=CreateSession(KServerName,Version(),0); // no asynchronous messages allowed sl@0: if (r==KErrNone) sl@0: r=ShareAuto(); sl@0: return r; sl@0: } sl@0: sl@0: TInt RDisplay::OpenDynamic() sl@0: { sl@0: TInt r=CreateSession(KServerName,Version(),-1); // use global dynamic message pool sl@0: if (r==KErrNone) sl@0: r=ShareAuto(); sl@0: return r; sl@0: } sl@0: sl@0: TInt RDisplay::Display(const TDesC& aMessage) sl@0: // sl@0: // Display a message. sl@0: // sl@0: { sl@0: sl@0: TBuf<0x100> b(aMessage); sl@0: return SendReceive(CMyServer::EDisplay, TIpcArgs(&b)); sl@0: } sl@0: sl@0: TInt RDisplay::Read() sl@0: // sl@0: // Get session to test CSession2::ReadL. sl@0: // sl@0: { sl@0: sl@0: TBuf<0x10> b(_L("Testing read")); sl@0: TBuf<0x10>* bad = (TBuf<0x10> *)(0x30000000); sl@0: sl@0: return SendReceive(CMyServer::ERead, TIpcArgs(&b, bad)); sl@0: } sl@0: sl@0: TInt RDisplay::Write() sl@0: // sl@0: // Get session to test CSession2::WriteL. sl@0: // sl@0: { sl@0: sl@0: TBuf<0x10> b; sl@0: TBufC<0x10> c; // Bad descriptor - read only sl@0: TBuf<0x10>* bad = (TBuf<0x10> *)(0x30000000); sl@0: TInt r=SendReceive(CMyServer::EWrite, TIpcArgs(&b, &c, bad)); sl@0: if (r==KErrNone && b!=_L("It worked!")) sl@0: r=KErrGeneral; sl@0: return r; sl@0: } sl@0: sl@0: TInt RDisplay::Test() sl@0: // sl@0: // Send a message and wait for completion. sl@0: // sl@0: { sl@0: sl@0: return SendReceive(CMyServer::ETest, TIpcArgs()); sl@0: } sl@0: sl@0: TInt RDisplay::Stop() sl@0: // sl@0: // Stop the server. sl@0: // sl@0: { sl@0: sl@0: return SendReceive(CMyServer::EStop, TIpcArgs()); sl@0: } sl@0: sl@0: TVersion RDisplay::Version() sl@0: // sl@0: // Return the current version. sl@0: // sl@0: { sl@0: sl@0: TVersion v(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber); sl@0: return v; sl@0: } sl@0: sl@0: TInt RDisplay::Echo(TInt aWhat, TInt a0, TInt a1, TInt a2, TInt a3) sl@0: { sl@0: return SendReceive(0x40000000|aWhat, TIpcArgs(a0,a1,a2,a3)); sl@0: } sl@0: sl@0: TInt RDisplay::Hold(TInt aOrder, TInt aArg) sl@0: { sl@0: sl@0: return Send(CMyServer::EHold, TIpcArgs(aOrder, aArg)); sl@0: } sl@0: sl@0: void RDisplay::Hold(TRequestStatus& aStatus, TInt aOrder, TInt aArg) sl@0: { sl@0: sl@0: SendReceive(CMyServer::EHold, TIpcArgs(aOrder, aArg), aStatus); sl@0: } sl@0: sl@0: TInt RDisplay::Release(TInt aCount) sl@0: { sl@0: sl@0: return SendReceive(CMyServer::ERelease, TIpcArgs(aCount)); sl@0: } sl@0: sl@0: TInt RDisplay::CompleteIndex() sl@0: { sl@0: return SendReceive(CMyServer::EGetCompleteIndex, TIpcArgs()); sl@0: } sl@0: sl@0: TInt serverThreadEntryPoint(TAny*) sl@0: // sl@0: // The entry point for the producer thread. sl@0: // sl@0: { sl@0: sl@0: testSvr.Title(); sl@0: testSvr.Start(_L("Create CActiveScheduler")); sl@0: CMyActiveScheduler* pR=new CMyActiveScheduler; sl@0: testSvr(pR!=NULL); sl@0: CActiveScheduler::Install(pR); sl@0: // sl@0: testSvr.Next(_L("Create CMyServer")); sl@0: CMyServer* pS=CMyServer::New(0); sl@0: testSvr(pS!=NULL); sl@0: // sl@0: testSvr.Next(_L("Start CMyServer")); sl@0: TInt r=pS->Start(KServerName); sl@0: testSvr(r==KErrNone); sl@0: // sl@0: testSvr.Next(_L("Signal to client that we have started")); sl@0: client.Signal(); sl@0: // sl@0: testSvr.Next(_L("Start CActiveScheduler")); sl@0: CActiveScheduler::Start(); sl@0: // sl@0: testSvr.Next(_L("Exit server")); sl@0: delete pS; sl@0: testSvr.Close(); sl@0: return(KErrNone); sl@0: } sl@0: sl@0: TInt speedyThreadEntryPoint(TAny* aDisplay) sl@0: // sl@0: // The entry point for the speed test thread. sl@0: // sl@0: { sl@0: sl@0: RDisplay& t=*(RDisplay*)aDisplay; sl@0: TInt r=t.Test(); sl@0: testSpeedy(r==KErrNone); sl@0: speedCount=0; sl@0: client.Signal(); sl@0: while ((r=t.Test())==KErrNone) sl@0: speedCount++; sl@0: testSpeedy(r==KErrServerTerminated); sl@0: return(KErrNone); sl@0: } sl@0: sl@0: TInt RunPanicThread(RThread& aThread) sl@0: { sl@0: TRequestStatus s; sl@0: aThread.Logon(s); sl@0: TBool jit = User::JustInTime(); sl@0: User::SetJustInTime(EFalse); sl@0: aThread.Resume(); sl@0: User::WaitForRequest(s); sl@0: User::SetJustInTime(jit); sl@0: return s.Int(); sl@0: } sl@0: sl@0: TInt RogueThread1(TAny*) sl@0: { sl@0: // try to kill the kernel sl@0: RMutex mutex; sl@0: TPtrC* p=(TPtrC*)0x30000000; sl@0: mutex.CreateGlobal(*p,EOwnerProcess); // this should panic the thread sl@0: return KErrNone; sl@0: } sl@0: sl@0: class RMessageT : public RMessage2 sl@0: { sl@0: public: sl@0: RMessageT(TLinAddr anAddr) { iFunction=0; iHandle=(TInt)anAddr; } sl@0: }; sl@0: sl@0: TInt RogueThread2(TAny*) sl@0: { sl@0: // try to kill the kernel sl@0: RMessageT m(0x30000000); sl@0: m.Complete(KErrNone); // this should panic the thread sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt RogueThread3(TAny*) sl@0: { sl@0: // try to kill the kernel sl@0: RMessageT m(0x80000000); sl@0: m.Complete(KErrNone); // this should panic the thread sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt RogueThread4(TAny*) sl@0: { sl@0: // try to kill the kernel sl@0: RMessageT m(0x800fff00); // this should be off the end of the kernel heap sl@0: m.Complete(KErrNone); // this should panic the thread sl@0: return KErrNone; sl@0: } sl@0: sl@0: void DisplayThreadExitInfo(const RThread& aThread) sl@0: { sl@0: TFullName fn=aThread.FullName(); sl@0: TExitType exitType=aThread.ExitType(); sl@0: TInt exitReason=aThread.ExitReason(); sl@0: TBuf<32> exitCat=aThread.ExitCategory(); sl@0: test.Printf(_L("Thread %S exited %d,%d,%S\n"),&fn,exitType,exitReason,&exitCat); sl@0: } sl@0: sl@0: void RogueThreadTest() sl@0: { sl@0: RThread thread; sl@0: TInt r; sl@0: if (HaveVirtMem()) sl@0: { sl@0: test.Next(_L("Rogue thread test 1")); sl@0: r=thread.Create(_L("Rogue1"),RogueThread1,KDefaultStackSize,KHeapSize,KHeapSize,NULL); sl@0: test_KErrNone(r); sl@0: RunPanicThread(thread); // wait for rogue thread to die sl@0: DisplayThreadExitInfo(thread); sl@0: test(thread.ExitType()==EExitPanic); sl@0: test(thread.ExitReason()==ECausedException); sl@0: thread.Close(); sl@0: } sl@0: sl@0: test.Next(_L("Rogue thread test 2")); sl@0: r=thread.Create(_L("Rogue2"),RogueThread2,KDefaultStackSize,KHeapSize,KHeapSize,NULL); sl@0: test_KErrNone(r); sl@0: RunPanicThread(thread); // wait for rogue thread to die sl@0: DisplayThreadExitInfo(thread); sl@0: test(thread.ExitType()==EExitPanic); sl@0: test(thread.ExitReason()==EBadMessageHandle); sl@0: thread.Close(); sl@0: sl@0: test.Next(_L("Rogue thread test 3")); sl@0: r=thread.Create(_L("Rogue3"),RogueThread3,KDefaultStackSize,KHeapSize,KHeapSize,NULL); sl@0: test_KErrNone(r); sl@0: RunPanicThread(thread); // wait for rogue thread to die sl@0: DisplayThreadExitInfo(thread); sl@0: test(thread.ExitType()==EExitPanic); sl@0: test(thread.ExitReason()==EBadMessageHandle); sl@0: thread.Close(); sl@0: sl@0: test.Next(_L("Rogue thread test 4")); sl@0: r=thread.Create(_L("Rogue4"),RogueThread4,KDefaultStackSize,KHeapSize,KHeapSize,NULL); sl@0: test_KErrNone(r); sl@0: RunPanicThread(thread); // wait for rogue thread to die sl@0: DisplayThreadExitInfo(thread); sl@0: test(thread.ExitType()==EExitPanic); sl@0: test(thread.ExitReason()==EBadMessageHandle); sl@0: thread.Close(); sl@0: } sl@0: sl@0: TInt SecondClient(TAny* aSession) sl@0: { sl@0: RDisplay d; sl@0: d.SetHandle(TInt(aSession)); sl@0: TInt r=d.Display(_L("Second client")); sl@0: if (r!=KErrNone) sl@0: return r; sl@0: r = d.Echo(0,19,31,83,487); sl@0: if (r!=19) sl@0: return -999990; sl@0: r = d.Echo(1,19,31,83,487); sl@0: if (r!=31) sl@0: return -999991; sl@0: r = d.Echo(2,19,31,83,487); sl@0: if (r!=83) sl@0: return -999992; sl@0: r = d.Echo(3,19,31,83,487); sl@0: if (r!=487) sl@0: return -999993; sl@0: r = d.Echo(4,19,31,83,487); sl@0: if (r!=620) sl@0: return -999994; sl@0: r = d.Echo(5,19,31,83,487); sl@0: if (r!=245380) sl@0: return -999995; sl@0: r=d.Read(); sl@0: if (r!=KErrNone) sl@0: return r; sl@0: r=d.Write(); sl@0: if (r!=KErrNone) sl@0: return r; sl@0: d.Release(); sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt ThirdClient(TAny* aSession) sl@0: { sl@0: RDisplay d; sl@0: d.SetHandle(TInt(aSession)); sl@0: TInt r=d.Display(_L("Third client")); sl@0: if (r!=KErrNone) sl@0: return r; sl@0: r=d.Hold(); sl@0: if (r!=KErrNone) sl@0: return r; sl@0: r=d.Read(); sl@0: if (r!=KErrNone) sl@0: return r; sl@0: r=d.Write(); sl@0: if (r!=KErrNone) sl@0: return r; sl@0: return KErrNone; sl@0: } sl@0: sl@0: void TestSecondClient(RSessionBase& aSession) sl@0: { sl@0: RThread t; sl@0: TInt r=t.Create(_L("SecondClient"),SecondClient,0x1000,NULL,(TAny*)aSession.Handle()); sl@0: test_KErrNone(r); sl@0: TRequestStatus s; sl@0: t.Logon(s); sl@0: t.Resume(); sl@0: User::WaitForRequest(s); sl@0: test_KErrNone(s.Int()); sl@0: t.Close(); sl@0: } sl@0: sl@0: void TestThirdClient(RSessionBase& aSession) sl@0: { sl@0: RThread t; sl@0: TInt r=t.Create(_L("ThirdClient"),ThirdClient,0x1000,NULL,(TAny*)aSession.Handle()); sl@0: test_KErrNone(r); sl@0: TRequestStatus s; sl@0: t.Logon(s); sl@0: t.Resume(); sl@0: User::WaitForRequest(s); sl@0: test_KErrNone(s.Int()); sl@0: t.Close(); sl@0: } sl@0: sl@0: TInt FourthClient(TAny* aSession) sl@0: { sl@0: RDisplay d; sl@0: d.SetHandle(TInt(aSession)); sl@0: TInt r=d.Display(_L("Fourth client")); sl@0: if (r!=KErrNone) sl@0: return r; sl@0: d.Close(); sl@0: return KErrNone; sl@0: } sl@0: sl@0: void TestSessionClose() sl@0: { sl@0: RDisplay d; sl@0: TInt r=d.Open(); sl@0: test_KErrNone(r); sl@0: TRequestStatus msgStat; sl@0: d.Hold(msgStat); sl@0: test(msgStat==KRequestPending); sl@0: RThread t; sl@0: r=t.Create(_L("FourthClient"),FourthClient,0x1000,NULL,(TAny*)d.Handle()); sl@0: test_KErrNone(r); sl@0: TRequestStatus s; sl@0: t.Logon(s); sl@0: t.Resume(); sl@0: User::WaitForRequest(s); sl@0: test_KErrNone(s.Int()); sl@0: t.Close(); sl@0: User::After(1000000); sl@0: test(msgStat==KRequestPending); sl@0: } sl@0: sl@0: TInt FifthClient(TAny* aDisplay) sl@0: { sl@0: RDisplay& d=*(RDisplay*)aDisplay; sl@0: TInt r=d.Open(); sl@0: if (r!=KErrNone) sl@0: return r; sl@0: r=d.Display(_L("Fifth client")); sl@0: if (r!=KErrNone) sl@0: return r; sl@0: return KErrNone; sl@0: } sl@0: sl@0: void TestZeroShares() sl@0: { sl@0: RDisplay d; sl@0: d.SetHandle(0); sl@0: RThread t; sl@0: TInt r=t.Create(_L("FifthClient"),FifthClient,0x1000,NULL,&d); sl@0: test_KErrNone(r); sl@0: TRequestStatus s; sl@0: t.Logon(s); sl@0: t.Resume(); sl@0: User::WaitForRequest(s); sl@0: test_KErrNone(s.Int()); sl@0: test(d.Handle()!=0); sl@0: t.Close(); sl@0: r=d.Display(_L("Access after last share closed")); sl@0: test_KErrNone(r); sl@0: d.Close(); sl@0: } sl@0: sl@0: TInt AttachClient1(TAny* aSession) sl@0: { sl@0: RDisplay d; sl@0: d.SetHandle(TInt(aSession)); sl@0: __KHEAP_MARK; sl@0: TInt r=d.Display(_L("Attach client 1")); sl@0: __KHEAP_MARKEND; // shouldn't need to allocate memory sl@0: return r; sl@0: } sl@0: sl@0: TInt AttachClient2(TAny* aSession) sl@0: { sl@0: RDisplay d; sl@0: d.SetHandle(TInt(aSession)); sl@0: TInt r=d.Display(_L("Attach client 2")); sl@0: if (r!=KErrNone) sl@0: return r; sl@0: __KHEAP_MARK; sl@0: r=d.Display(_L("Attach client 2")); sl@0: __KHEAP_MARKEND; // check no memory was allocated by message send sl@0: return r; sl@0: } sl@0: sl@0: void TestAttach(RSessionBase& aSession) sl@0: { sl@0: test.Next(_L("Test Attach")); sl@0: RThread t; sl@0: TInt r=t.Create(_L("AttachClient1"),AttachClient1,0x1000,NULL,(TAny*)aSession.Handle()); sl@0: test_KErrNone(r); sl@0: r=RunPanicThread(t); // wait for thread to die sl@0: test_KErrNone(r); sl@0: test(t.ExitType()==EExitKill); sl@0: test_KErrNone(t.ExitReason()); sl@0: t.Close(); sl@0: sl@0: r=t.Create(_L("AttachClient2"),AttachClient2,0x1000,NULL,(TAny*)aSession.Handle()); sl@0: test_KErrNone(r); sl@0: TRequestStatus s; sl@0: t.Logon(s); sl@0: t.Resume(); sl@0: User::WaitForRequest(s); sl@0: test_KErrNone(s.Int()); sl@0: test(t.ExitType()==EExitKill); sl@0: test_KErrNone(t.ExitReason()); sl@0: t.Close(); sl@0: } sl@0: sl@0: TInt SixthClient(TAny* aDisplay) sl@0: { sl@0: RDisplay& d=*(RDisplay*)aDisplay; sl@0: TInt r=d.Display(_L("Sixth client")); sl@0: if (r!=KErrNone) sl@0: return r; sl@0: TRequestStatus s; sl@0: User::WaitForRequest(s); sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt SeventhClient(TAny* aDisplay) sl@0: { sl@0: RDisplay& d=*(RDisplay*)aDisplay; sl@0: TInt r=d.Display(_L("Seventh client")); sl@0: if (r!=KErrNone) sl@0: return r; sl@0: TRequestStatus s; sl@0: User::WaitForRequest(s); sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt EighthClient(TAny* aDisplay) sl@0: { sl@0: RDisplay& d=*(RDisplay*)aDisplay; sl@0: TInt r=d.Display(_L("Eighth client")); sl@0: if (r!=KErrNone) sl@0: return r; sl@0: TRequestStatus s; sl@0: User::WaitForRequest(s); sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt NinthClient(TAny* aDisplay) sl@0: { sl@0: RDisplay& d=*(RDisplay*)aDisplay; sl@0: TInt r=d.Display(_L("Ninth client")); sl@0: if (r!=KErrNone) sl@0: return r; sl@0: TRequestStatus s; sl@0: User::WaitForRequest(s); sl@0: return KErrNone; sl@0: } sl@0: sl@0: void TestAsync(RDisplay& aD) sl@0: { sl@0: TInt ci = aD.CompleteIndex(); sl@0: TRequestStatus s[128]; sl@0: TInt i; sl@0: TInt r; sl@0: for (i=0; i<128; ++i) sl@0: { sl@0: TInt ord = i ^ 0x55; sl@0: TInt arg = i + 1; sl@0: aD.Hold(s[i], ord, arg); sl@0: if (s[i]==KErrServerBusy) sl@0: { sl@0: User::WaitForRequest(s[i]); sl@0: break; sl@0: } sl@0: test(s[i]==KRequestPending); sl@0: } sl@0: r = aD.Release(); sl@0: test_KErrNone(r); sl@0: TInt j; sl@0: for (j=0; j<128; ++j) sl@0: { sl@0: if ( (j^0x55) >= i ) sl@0: continue; sl@0: TInt code = s[j^0x55].Int(); sl@0: TInt expected = ci ^ ((j^0x55)+1); sl@0: if (code != expected) sl@0: { sl@0: test.Printf(_L("j=%02x i=%02x expected=%08x got=%08x\n"),j,j^0x55,expected,code); sl@0: test(0); sl@0: } sl@0: User::WaitForRequest(s[j^0x55]); sl@0: ++ci; sl@0: } sl@0: } sl@0: sl@0: void TestSession(RDisplay& aSess) sl@0: { sl@0: // sl@0: TInt r; sl@0: test.Next(_L("Test all args passed")); sl@0: test(aSess.Echo(0,3,5,7,11)==3); sl@0: test(aSess.Echo(1,3,5,7,11)==5); sl@0: test(aSess.Echo(2,3,5,7,11)==7); sl@0: test(aSess.Echo(3,3,5,7,11)==11); sl@0: test(aSess.Echo(4,3,5,7,11)==26); sl@0: test(aSess.Echo(5,3,5,7,11)==204); sl@0: // sl@0: test.Next(_L("Send to server")); sl@0: r=aSess.Display(_L("First message")); sl@0: test_KErrNone(r); sl@0: // sl@0: test.Next(_L("Read")); sl@0: r=aSess.Read(); sl@0: test_KErrNone(r); sl@0: // sl@0: test.Next(_L("Write")); sl@0: r=aSess.Write(); sl@0: test_KErrNone(r); sl@0: // sl@0: TestThirdClient(aSess); sl@0: User::After(1000000); sl@0: TestSecondClient(aSess); sl@0: User::After(1000000); sl@0: TestSessionClose(); sl@0: User::After(1000000); sl@0: TestZeroShares(); sl@0: User::After(1000000); sl@0: TestAttach(aSess); sl@0: User::After(1000000); sl@0: } sl@0: sl@0: void TestUnsharableSession(RDisplay& aSess) sl@0: { sl@0: // sl@0: TInt r; sl@0: test.Next(_L("Test all args passed")); sl@0: test(aSess.Echo(0,3,5,7,11)==3); sl@0: test(aSess.Echo(1,3,5,7,11)==5); sl@0: test(aSess.Echo(2,3,5,7,11)==7); sl@0: test(aSess.Echo(3,3,5,7,11)==11); sl@0: test(aSess.Echo(4,3,5,7,11)==26); sl@0: test(aSess.Echo(5,3,5,7,11)==204); sl@0: // sl@0: test.Next(_L("Send to server")); sl@0: r=aSess.Display(_L("First message")); sl@0: test_KErrNone(r); sl@0: // sl@0: test.Next(_L("Read")); sl@0: r=aSess.Read(); sl@0: test_KErrNone(r); sl@0: // sl@0: test.Next(_L("Write")); sl@0: r=aSess.Write(); sl@0: test_KErrNone(r); sl@0: // sl@0: TInt h = aSess.Handle(); sl@0: test.Printf(_L("HANDLE %08x\n"), h); sl@0: test((h & KHandleFlagLocal)!=0); sl@0: } sl@0: sl@0: void TestSessionCreateLLeaving() sl@0: { sl@0: SessionCreateLResult=KErrGeneral; sl@0: sl@0: TInt c=SessionCostructCount; sl@0: TInt d=SessionDestructCount; sl@0: sl@0: RDisplay t; sl@0: TInt r = t.Open(); sl@0: test(r==SessionCreateLResult); sl@0: sl@0: test(SessionCostructCount==c+1); sl@0: test(SessionDestructCount==d+1); sl@0: sl@0: SessionCreateLResult=KErrNone; sl@0: } sl@0: sl@0: GLDEF_C TInt E32Main() sl@0: // sl@0: // Test timers. sl@0: // sl@0: { sl@0: sl@0: test.Title(); sl@0: test.Start(_L("Creating client semaphore")); sl@0: TInt r=client.CreateLocal(0); sl@0: test_KErrNone(r); sl@0: // sl@0: test.Next(_L("Creating server thread")); sl@0: RThread server; sl@0: r=server.Create(_L("Server"),serverThreadEntryPoint,KDefaultStackSize,KHeapSize,KHeapSize,NULL); sl@0: test_KErrNone(r); sl@0: server.SetPriority(EPriorityMore); sl@0: // sl@0: test.Next(_L("Resume server thread")); sl@0: server.Resume(); sl@0: test(ETrue); sl@0: // sl@0: test.Next(_L("Wait for server to start")); sl@0: client.Wait(); sl@0: // sl@0: test.Next(_L("Connect to server")); sl@0: RDisplay t; sl@0: r = t.OpenNoAsync(); sl@0: test_KErrNone(r); sl@0: test.Next(_L("Send to server")); sl@0: r=t.Display(_L("AsyncMsg")); sl@0: test_KErrNone(r); sl@0: TRequestStatus s0; sl@0: t.Hold(s0); sl@0: test(s0==KErrServerBusy); sl@0: t.Close(); sl@0: // sl@0: test.Next(_L("Test Session::CreateL leaving")); sl@0: TestSessionCreateLLeaving(); sl@0: // sl@0: test.Next(_L("Async fixed pool")); sl@0: r = t.Open(); sl@0: test_KErrNone(r); sl@0: TestAsync(t); sl@0: TestAsync(t); sl@0: t.Close(); sl@0: test.Next(_L("Async global pool")); sl@0: r = t.OpenDynamic(); sl@0: test_KErrNone(r); sl@0: TestAsync(t); sl@0: TestAsync(t); sl@0: t.Close(); sl@0: // sl@0: r=t.Open(); sl@0: test_KErrNone(r); sl@0: // sl@0: TestSession(t); sl@0: // sl@0: RDisplay tt; sl@0: r = tt.OpenS(); sl@0: test.Printf(_L("OpenS -> %d\n"),r); sl@0: test_KErrNone(r); sl@0: TestSession(tt); sl@0: tt.Close(); sl@0: // sl@0: r = tt.OpenGS(); sl@0: test.Printf(_L("OpenGS -> %d\n"),r); sl@0: test(r==KErrPermissionDenied); sl@0: tt.Close(); sl@0: // sl@0: r = tt.OpenUS(); sl@0: test.Printf(_L("OpenUS -> %d\n"),r); sl@0: test_KErrNone(r); sl@0: TestUnsharableSession(tt); sl@0: tt.Close(); sl@0: // sl@0: test.Next(_L("Starting speedy client")); sl@0: RThread speedy; sl@0: TRequestStatus speedyStat; sl@0: r=speedy.Create(_L("Speedy"),speedyThreadEntryPoint,KDefaultStackSize,KHeapSize,KHeapSize,&t); sl@0: test_KErrNone(r); sl@0: speedy.Logon(speedyStat); sl@0: RThread t1; sl@0: RThread t2; sl@0: RThread t3; sl@0: RThread t4; sl@0: TRequestStatus s1; sl@0: TRequestStatus s2; sl@0: TRequestStatus s3; sl@0: TRequestStatus s4; sl@0: r=t1.Create(_L("SixthClient"),SixthClient,0x1000,NULL,&t); sl@0: test_KErrNone(r); sl@0: t1.Logon(s1); sl@0: r=t2.Create(_L("SeventhClient"),SeventhClient,0x1000,NULL,&t); sl@0: test_KErrNone(r); sl@0: t2.Logon(s2); sl@0: r=t3.Create(_L("EighthClient"),EighthClient,0x1000,NULL,&t); sl@0: test_KErrNone(r); sl@0: t3.Logon(s3); sl@0: r=t4.Create(_L("NinthClient"),NinthClient,0x1000,NULL,&t); sl@0: test_KErrNone(r); sl@0: t4.Logon(s4); sl@0: t1.Resume(); sl@0: t2.Resume(); sl@0: t3.Resume(); sl@0: t4.Resume(); sl@0: User::After(1000000); sl@0: // sl@0: test.Next(_L("Wait for speedy to start")); sl@0: speedy.SetPriority(EPriorityNormal); sl@0: RThread().SetPriority(EPriorityMuchMore); sl@0: speedy.Resume(); sl@0: client.Wait(); sl@0: // sl@0: test.Printf(_L("Starting speed test...\n")); sl@0: User::After(300000); sl@0: TInt b=speedCount; sl@0: User::After(3000000); sl@0: TInt n=speedCount; sl@0: test.Printf(_L("Count = %d in 1 second\n"),(n-b)/3); sl@0: // sl@0: test.Next(_L("Stop server")); sl@0: r=t.Stop(); sl@0: test_KErrNone(r); sl@0: User::After(0); // Allow the speed client to die sl@0: // sl@0: test.Next(_L("Close extra threads")); sl@0: t1.Kill(0); sl@0: User::WaitForRequest(s1); sl@0: test(t1.ExitType()==EExitKill && s1==KErrNone); sl@0: t2.Kill(0); sl@0: User::WaitForRequest(s2); sl@0: test(t2.ExitType()==EExitKill && s2==KErrNone); sl@0: t3.Kill(0); sl@0: User::WaitForRequest(s3); sl@0: test(t3.ExitType()==EExitKill && s3==KErrNone); sl@0: t4.Kill(0); sl@0: User::WaitForRequest(s4); sl@0: test(t4.ExitType()==EExitKill && s4==KErrNone); sl@0: User::WaitForRequest(speedyStat); sl@0: test(speedy.ExitType()==EExitKill && speedyStat==KErrNone); sl@0: // sl@0: test.Next(_L("Close all")); sl@0: t1.Close(); sl@0: t2.Close(); sl@0: t3.Close(); sl@0: t4.Close(); sl@0: speedy.Close(); sl@0: server.Close(); sl@0: client.Close(); sl@0: // sl@0: test.Next(_L("Close connection")); sl@0: t.Close(); sl@0: // sl@0: RogueThreadTest(); sl@0: // sl@0: test.End(); sl@0: return(0); sl@0: } sl@0: