Update contrib.
1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32test\misc\t_svrstress.cpp
15 // This is a stress test for client server session connect and disconnect
19 #include <e32base_private.h>
20 #define __E32TEST_EXTENSION__
24 #include <e32atomics.h>
27 #include <e32def_private.h>
29 RTest test(_L("T_SVRSTRESS"));
31 RSemaphore SyncSemaphore;
35 TInt UseGlobalMessagePool;
37 const TInt BigDesLength = 256 * 1024;
40 #define TRACE(t) RDebug::RawPrint(_L8(t))
46 // utility functions...
51 User::WaitForAnyRequest();
52 RThread().RequestSignal(); // put request semaphore count back
56 TInt WaitForRequest(TRequestStatus& aStatus,TTimeIntervalMicroSeconds32 aTimeout=2*1000000)
59 test_Equal(KErrNone,timer.CreateLocal());
61 TRequestStatus timeoutStatus;
62 timer.After(timeoutStatus,aTimeout);
64 User::WaitForRequest(aStatus,timeoutStatus);
67 if(aStatus.Int()==KRequestPending)
75 User::WaitForRequest(timeoutStatus);
78 CLOSE_AND_WAIT(timer);
88 _LIT(KMyServerName,"StressSvr");
90 class CMyServer : public CServer2
93 CMyServer(TInt aPriority);
94 static CMyServer* New(TInt aPriority);
95 virtual CSession2* NewSessionL(const TVersion&, const RMessage2&) const;
99 class CMySession : public CSession2
102 virtual void ServiceL(const RMessage2& aMessage);
106 CMyServer* CMyServer::New(TInt aPriority)
108 return new CMyServer(aPriority);
112 CMyServer::CMyServer(TInt aPriority)
113 : CServer2(aPriority, ESharableSessions)
117 CSession2* CMyServer::NewSessionL(const TVersion&, const RMessage2&) const
120 return new(ELeave) CMySession;
126 TInt MyServerThread(TAny*)
128 CActiveScheduler* pR=new CActiveScheduler;
131 CActiveScheduler::Install(pR);
132 RestartServer = ETrue;
137 CMyServer* pS=CMyServer::New(0);
140 TInt r = pS->Start(KMyServerName);
145 RThread::Rendezvous(KErrNone);
147 CActiveScheduler::Start();
162 class RMyServer : public RSessionBase
171 ECompleteWhileCopying
176 inline TInt Send(TFunction aFunction) const
177 { return SendReceive(aFunction); }
179 inline TInt Send(TFunction aFunction, const TIpcArgs& aArgs) const
180 { return SendReceive(aFunction, aArgs); }
182 inline void Send(TFunction aFunction, TRequestStatus& aStatus) const
183 { SendReceive(aFunction, aStatus); }
185 inline void Send(TFunction aFunction, const TIpcArgs& aArgs, TRequestStatus& aStatus) const
186 { SendReceive(aFunction, aArgs, aStatus); }
190 TInt RMyServer::Connect()
193 TInt r = temp.CreateSession(KMyServerName, TVersion(), UseGlobalMessagePool ? -1 : NumMessageSlots);
197 // turn handle into process owned...
198 RMyServer temp2(temp);
199 r = temp2.Duplicate(RThread());
212 TInt CopierThread(TAny* aPtr)
214 RMessage2& msg = *(RMessage2*)aPtr;
215 HBufC* bigdes = HBufC::NewMax(BigDesLength);
218 TPtr ptr = bigdes->Des();
219 RThread().Rendezvous(KErrNone);
220 RDebug::Print(_L("START\n"));
221 TInt r = msg.Read(2, ptr);
222 RDebug::Print(_L("DONE\n"));
227 void CMySession::ServiceL(const RMessage2& aMessage)
231 aMessage.Client(client);
234 TRequestStatus logon, rendez;
236 s = (TRequestStatus*)aMessage.Ptr0();
238 switch(aMessage.Function())
240 case RMyServer::EStop:
242 CActiveScheduler::Stop();
245 case RMyServer::ESync:
247 client.RequestComplete(s,KErrNone); // let client know we've received the message
248 SyncSemaphore.Wait(); // wait for signal from client
249 s = (TRequestStatus*)aMessage.Ptr1(); // use second status for later end signal
250 aMessage.Complete(KErrNone); // complete the message
253 case RMyServer::EPing:
255 aMessage.Complete(KErrNone);
258 case RMyServer::EShutdown:
260 RestartServer = EFalse;
261 CActiveScheduler::Stop();
264 case RMyServer::ECompleteWhileCopying:
265 s2 = (TRequestStatus*)aMessage.Ptr1();
266 r = copier.Create(_L("Copier"),CopierThread,KDefaultStackSize,&User::Allocator(),(TAny*)&aMessage);
270 copier.Rendezvous(rendez);
271 copier.SetPriority(EPriorityLess);
273 User::WaitForRequest(rendez);
274 User::AfterHighRes(5000); // 5ms delay to let copy actually start
275 RDebug::Print(_L("COMPLETING\n"));
276 aMessage.Complete(KErrNone);
277 User::WaitForRequest(logon);
280 client.RequestComplete(s,r);
286 aMessage.Complete(KErrNotSupported);
290 // let client know we've completed the message...
292 client.RequestComplete(s,KErrNone);
306 RStressThread(TThreadFunction aThreadFunction, const char* aName, TInt aDelay=-1);
311 // for use by thread...
312 static RStressThread& Begin(TAny* aInfo);
315 TThreadFunction iThreadFunction;
318 TRequestStatus iLogon;
324 static TInt iInstanceCounter;
328 TInt RStressThread::iInstanceCounter = 0;
331 RStressThread::RStressThread(TThreadFunction aThreadFunction, const char* aName, TInt aDelay)
332 : iThreadFunction(aThreadFunction), iName(aName), iLogon(KErrNone), iDelay(aDelay)
334 iThread.SetHandle(0);
338 RStressThread::~RStressThread()
344 void RStressThread::Start()
349 TBuf<KMaxKernelName> name;
350 name.Copy(TPtrC8((const TUint8*)iName));
351 name.Append((TText)'-');
352 name.AppendNum(iInstanceCounter++);
353 test_Equal(KErrNone,iThread.Create(name,iThreadFunction,KDefaultStackSize,&User::Allocator(),this));
355 iThread.Logon(iLogon);
356 test_Equal(KRequestPending,iLogon.Int());
358 TRequestStatus rendezvous;
359 iThread.Rendezvous(rendezvous);
363 User::WaitForRequest(rendezvous);
364 test_Equal(KErrNone,rendezvous.Int());
368 void RStressThread::Stop()
370 if(!iThread.Handle())
371 return; // thread not running
374 RDebug::Printf("RStressThread::Stop %s (count=%d)",iName,iCount);
375 if(WaitForRequest(iLogon,10*1000000)!=KErrNone)
377 CLOSE_AND_WAIT(iThread);
381 void RStressThread::Restart()
385 if(iLogon==KRequestPending)
386 return; // thread still running
388 User::WaitForRequest(iLogon);
389 CLOSE_AND_WAIT(iThread);
396 TBool RStressThread::Loop()
399 User::AfterHighRes(iDelay);
405 RStressThread& RStressThread::Begin(TAny* aInfo)
407 RStressThread& t = *(RStressThread*)aInfo;
409 RThread().SetPriority(EPriorityMore); // so this preempts threads after delay
410 RThread::Rendezvous(KErrNone);
420 RThread ServerThread;
425 RMyServer newSession;
427 test_Equal(KErrNone,newSession.Connect());
429 RMyServer oldSession(Session);
430 Session = newSession;
433 if(oldSession.Handle())
434 CLOSE_AND_WAIT(oldSession);
438 TInt SessionCloserThread(TAny* aInfo)
440 RStressThread& t = RStressThread::Begin(aInfo);
450 TInt ServerStopperThread(TAny* aInfo)
452 RStressThread& t = RStressThread::Begin(aInfo);
456 TRequestStatus rendezvous;
457 ServerThread.Rendezvous(rendezvous);
459 TRequestStatus s1 = KRequestPending;
461 Session.Send(RMyServer::EStop,TIpcArgs(&s1),s2);
462 User::WaitForRequest(s1,s2);
463 if(s2!=KRequestPending)
465 test_Equal(KErrServerTerminated,s2.Int());
466 User::WaitForRequest(s1);
469 User::WaitForRequest(rendezvous);
477 TInt SessionPingerThread(TAny* aInfo)
479 RStressThread& t = RStressThread::Begin(aInfo);
483 TRequestStatus s1 = KRequestPending;
485 Session.Send(RMyServer::EPing,TIpcArgs(&s1),s2);
486 User::WaitForRequest(s1,s2);
487 if(s2.Int()==KErrNone)
489 // message completed OK, wait for servers extra signal
490 User::WaitForRequest(s1);
492 else if(s2.Int()==KErrServerTerminated)
494 // server died before message processed, there shouldn't be an extra signal
495 test_Equal(KRequestPending,s1.Int());
499 // assume message was completed by server, but we didn't get signalled because session was closed
500 test_Equal(KRequestPending,s2.Int());
501 test_Equal(KErrNone,s1.Int());
511 RThread().SetPriority(EPriorityMuchMore); // so this main thread is higher priority than workers
513 test_Equal(KErrNone,SyncSemaphore.CreateLocal(0,EOwnerProcess));
515 // calculate async cleanup timeout value...
516 TInt factor = UserSvr::HalFunction(EHalGroupVariant, EVariantHalTimeoutExpansion, 0, 0);
521 WaitABit = 200000 * (TUint32)factor;
527 // start test server...
528 test_Equal(KErrNone,ServerThread.Create(_L("Server"),MyServerThread,KDefaultStackSize,1<<12,1<<20,0));
529 TRequestStatus rendezvous;
530 ServerThread.Rendezvous(rendezvous);
531 ServerThread.Resume();
532 User::WaitForRequest(rendezvous);
533 test_Equal(KErrNone,rendezvous.Int());
534 test_Equal(EExitPending,ServerThread.ExitType());
540 TRequestStatus logon;
542 TRequestStatus s1 = KRequestPending;
544 ServerThread.Logon(logon);
545 Session.Send(RMyServer::EShutdown,TIpcArgs(&s1),s2);
546 User::WaitForRequest(s1,s2);
547 if(s2!=KRequestPending)
549 test_Equal(KErrServerTerminated,s2.Int());
550 User::WaitForRequest(s1);
552 CLOSE_AND_WAIT(Session);
553 User::WaitForRequest(logon);
554 test_KErrNone(logon.Int());
555 test_Equal(EExitKill, ServerThread.ExitType());
556 CLOSE_AND_WAIT(ServerThread);
560 void TestMessageCompleteOnClosedSession()
564 test.Start(_L("Start server"));
567 test.Next(_L("Connect"));
568 test_Equal(KErrNone,Session.Connect());
570 test.Next(_L("Send message"));
571 TRequestStatus s1 = KRequestPending;
572 TRequestStatus s2 = KRequestPending;
574 Session.Send(RMyServer::ESync,TIpcArgs(&s1,&s2),s3);
575 test_Equal(KRequestPending,s3.Int());
577 test.Next(_L("Wait for s1"));
578 test_Equal(KErrNone,WaitForRequest(s1));
579 test_Equal(KErrNone,s1.Int());
580 test_Equal(KRequestPending,s2.Int());
581 test_Equal(KRequestPending,s3.Int());
583 test.Next(_L("Close session"));
585 test_Equal(KRequestPending,s2.Int());
586 test_Equal(KRequestPending,s3.Int());
588 test.Next(_L("Trigger message completion"));
589 SyncSemaphore.Signal();
591 test.Next(_L("Wait for s2"));
592 test_Equal(KErrNone,WaitForRequest(s2));
593 test_Equal(KErrNone,s2.Int());
594 test_Equal(KRequestPending,s3.Int());
596 test.Next(_L("Stop server"));
601 User::After(WaitABit); // allow asynchronous cleanup to happen
607 void TestMessageCompleteWhileCopying()
611 test.Start(_L("Start server"));
614 test.Next(_L("Connect"));
615 test_Equal(KErrNone,Session.Connect());
617 test.Next(_L("Create large descriptor"));
618 HBufC* bigdes = HBufC::NewMax(BigDesLength);
619 test_NotNull(bigdes);
620 TPtr ptr = bigdes->Des();
622 test.Next(_L("Send message"));
623 TRequestStatus s1 = KRequestPending;
624 TRequestStatus s2 = KRequestPending;
626 Session.Send(RMyServer::ECompleteWhileCopying,TIpcArgs(&s1,&s2,&ptr),s3);
628 test.Next(_L("Wait for s3"));
629 test_Equal(KErrNone,WaitForRequest(s3,10*1000000));
630 test_Equal(KErrNone,s3.Int());
632 test.Next(_L("Wait for s2"));
633 test_Equal(KErrNone,WaitForRequest(s2,10*1000000));
634 test_Equal(KErrNone,s2.Int());
636 test.Next(_L("Wait for s1"));
637 test_Equal(KErrNone,WaitForRequest(s1,10*1000000));
638 test_Equal(KErrNone,s1.Int());
640 test.Next(_L("Close session"));
643 test.Next(_L("Stop server"));
648 User::After(WaitABit); // allow asynchronous cleanup to happen
654 void RunStressThreads(RStressThread& aThread1, RStressThread& aThread2, TInt aTimeout=1000000)
666 test_Equal(KErrNone,timer.CreateLocal());
667 TRequestStatus timeoutStatus;
668 timer.After(timeoutStatus,aTimeout);
675 while(timeoutStatus==KRequestPending);
676 User::WaitForRequest(timeoutStatus);
677 CLOSE_AND_WAIT(timer);
682 CLOSE_AND_WAIT(Session);
685 User::After(WaitABit); // allow asynchronous cleanup to happen
690 GLDEF_C TInt E32Main()
696 test.Start(_L("Initialise"));
699 for(UseGlobalMessagePool=0; UseGlobalMessagePool<2; ++UseGlobalMessagePool)
701 if(UseGlobalMessagePool)
702 test.Next(_L("Tests using global message pool"));
704 test.Next(_L("Tests using local message pool"));
708 test.Start(_L("Check completing messages on dead session"));
709 TestMessageCompleteOnClosedSession();
713 test.Next(_L("Check completing message while IPC copying"));
714 TestMessageCompleteWhileCopying();
717 test.Next(_L("Stress closing session whilst in use"));
718 RStressThread closer(SessionCloserThread,"SessionCloser",0);
719 RStressThread pinger1(SessionPingerThread,"Pinger");
720 RunStressThreads(closer, pinger1);
724 test.Next(_L("Stress stopping server whilst in use"));
725 RStressThread stopper(ServerStopperThread,"ServerStopper",0);
726 RStressThread pinger2(SessionPingerThread,"Pinger");
727 RunStressThreads(stopper, pinger2);