First public contribution.
1 // Copyright (c) 1995-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\active\t_messge.cpp
16 // Test the RMessage2 and RMessagePtr2 classes.
18 // RMessage2, RMessagePtr2, RSessionBase, CSession2, CServer2
20 // - Verify copy constructor and assignment operator of Rmessage2 is implemented correctly.
21 // - Verify default constructor, copy constructor and assignment operator of RMessagePtr2
22 // is implemented correctly, construct RMessagePtr2 from pointer to RMessage2 and verify
23 // that it is constructed successfully.
24 // - Create client and server threads, open a session with specified number of message slots
25 // - Send integer message arguments from client and test that the server receives the
27 // - Send pointers as message arguments from client and test that the server receives the
29 // - Test Client() method of RMessage2 and verify it opened a handle to the client thread
30 // - Complete several messages using RMessage2::Complete and verify the client gets the
31 // error codes back correctly.
32 // - Complete several messages using RMessagePtr2::Complete and verify the client gets the
33 // error codes back correctly.
34 // - Check RMessage construction from RMessagePtr2 is successful.
35 // - Check creation of other sessions to the same server is successful.
36 // - Check the server return KErrServerBusy when client has more outstanding requests than
37 // available message slots.
38 // - Send stop signal and check that the server has stopped as expected.
39 // - Check the client and server have exited as expected.
40 // - Create client and server threads, open a connection to the server and verify that
41 // - Server is panicked when completing a message twice.
42 // Platforms/Drives/Compatibility:
44 // Assumptions/Requirement/Pre-requisites:
45 // Failures and causes:
46 // Base Port information:
51 #include <e32std_private.h>
56 const TInt KHeapMinSize=0x1000;
57 const TInt KHeapMaxSize=0x1000;
59 _LIT(KServerName,"CTestServer");
61 class CTestServer : public CServer2
64 IMPORT_C CTestServer(TInt aPriority);
66 EInt0Error=1, EInt1Error, EInt2Error, EInt3Error,
67 EPtr0Error, EPtr1Error, EPtr2Error, EPtr3Error,
68 ECreateNameError, ENewSessionError,
71 static void Panic(TPanicType aReason);
73 //override the pure virtual functions:
74 IMPORT_C virtual CSession2* NewSessionL(const TVersion& aVersion,const RMessage2& aMessage) const;
78 class CTestSession : public CSession2
81 enum {EStop,ETestInt,ETestPtr,ETestClient,ETestComplete,ETestPtrComplete,ETestCompletePanic,ETestOtherSession,ETestCompleteAfter,ETestMessageConstruction, ETestRMessagePtr2LeavingInterface};
82 //Override pure virtual
83 IMPORT_C virtual void ServiceL(const RMessage2& aMessage);
85 void TestInt(const RMessage2& aMessage);
86 void TestPtr(const RMessage2& aMessage);
87 void TestClient(const RMessage2& aMessage);
88 void TestComplete(const RMessage2& aMessage);
89 void TestPtrComplete(const RMessage2& aMessage);
90 void TestCompletePanic();
91 TInt TestMessageConstruction(const RMessage2& aMessage);
92 TInt TestRMessagePtr2LeavingInterface(const RMessage2& aMessage);
94 TInt count1;//initially ==0
95 RMessage2 messages[5];//Used in TestComplete()
97 TInt count2;//initially ==0
98 RMessagePtr2 messagePtrs[5];//User in TestPtrComplete()
102 class CMyActiveScheduler : public CActiveScheduler
105 virtual void Error(TInt anError) const; //override pure virtual error function
109 class RSession : public RSessionBase
112 TInt PublicSendReceive(TInt aFunction, const TIpcArgs &aPtr)
114 return (SendReceive(aFunction, aPtr));
116 void PublicSendReceive(TInt aFunction, const TIpcArgs &aPtr, TRequestStatus& aStatus)
118 SendReceive(aFunction, aPtr, aStatus);
120 TInt PublicCreateSession(const TDesC& aServer,TInt aMessageSlots)
122 return (CreateSession(aServer,User::Version(),aMessageSlots));
126 // CTestServer functions
128 CTestServer::CTestServer(TInt aPriority)
130 // Constructor - sets name
132 : CServer2(aPriority)
135 CSession2* CTestServer::NewSessionL(const TVersion& aVersion,const RMessage2& /*aMessage*/) const
137 // Virtual fn - checks version supported and creates a CTestSession
140 TVersion version(KE32MajorVersionNumber,KE32MinorVersionNumber,KE32BuildVersionNumber);
141 if (User::QueryVersionSupported(version,aVersion)==EFalse)
142 User::Leave(KErrNotSupported);
143 CTestSession* newCTestSession = new CTestSession;
144 if (newCTestSession==NULL)
145 Panic(ENewSessionError);
146 return(newCTestSession);
149 RThread clientThread, serverThread;
151 void CTestServer::Panic(TPanicType aReason) //static function
153 clientThread.Kill(KErrNone);
154 User::Panic(_L("CTestServer"),aReason);
157 RSession session, otherSession;
160 const TInt KTestInt[] = {-3866,30566,0,200};
162 void CTestSession::TestInt(const RMessage2& aMessage)
164 // Tests to see that the correct Int0/1/2/3 have been received
167 if (aMessage.Int0()!=KTestInt[0])
168 CTestServer::Panic(CTestServer::EInt0Error);
169 if (aMessage.Int1()!=KTestInt[1])
170 CTestServer::Panic(CTestServer::EInt1Error);
171 if (aMessage.Int2()!=KTestInt[2])
172 CTestServer::Panic(CTestServer::EInt2Error);
173 if (aMessage.Int3()!=KTestInt[3])
174 CTestServer::Panic(CTestServer::EInt3Error);
177 const TAny* KTestPtr[]={&clientThread, &serverThread, &session, &sem};
179 void CTestSession::TestPtr(const RMessage2& aMessage)
181 // Tests to see that the correct Ptr0/1/2/3 have been received
184 if (aMessage.Ptr0()!=KTestPtr[0])
185 CTestServer::Panic(CTestServer::EPtr0Error);
186 if (aMessage.Ptr1()!=KTestPtr[1])
187 CTestServer::Panic(CTestServer::EPtr1Error);
188 if (aMessage.Ptr2()!=KTestPtr[2])
189 CTestServer::Panic(CTestServer::EPtr2Error);
190 if (aMessage.Ptr3()!=KTestPtr[3])
191 CTestServer::Panic(CTestServer::EPtr3Error);
194 void CTestSession::TestClient(const RMessage2& aMessage)
200 TFullName n=RProcess().Name();
201 n+=_L("::Client Thread");
203 TInt r=aMessage.Client(t);
206 if (t.FullName().CompareF(n)!=0)
208 clientThread.Kill(0);
209 CTestServer::Panic(CTestServer::EClientError);
214 void CTestSession::TestComplete(const RMessage2& aMessage)
216 // Stores messages up then Completes in reverse order
219 messages[count1] = aMessage;
221 for(count1=4; count1>=0; count1--)
222 messages[count1].Complete(5-count1); //Complete with different 'error messages'
225 void CTestSession::TestPtrComplete(const RMessage2& aMessage)
227 // Stores messages up as RMessagePtrs then Completes in reverse order
228 // Also tests RMessage2::MessagePtr()
232 messagePtrs[count2] = aMessage;
233 __ASSERT_ALWAYS(!messagePtrs[count2].IsNull(), User::Invariant());
235 for(count2=4; count2>=0; count2--)
237 messagePtrs[count2].Complete(10-count2*2);
238 __ASSERT_ALWAYS(messagePtrs[count2].IsNull(), User::Invariant());
244 TInt CTestSession::TestMessageConstruction(const RMessage2& aMessage)
246 RMessage2 m2((RMessagePtr2&)aMessage);
252 TInt CTestSession::TestRMessagePtr2LeavingInterface(const RMessage2& aMessage)
254 RThread thread1, thread2;
255 TProcessPriority priority = EPriorityForeground;
257 //Check that both Client and ClientL methods return the same thread and error code.
258 if (aMessage.Client(thread1))
261 TRAPD(r1, aMessage.ClientL(thread2))
267 if (thread1.Id() != thread2.Id())
271 return KErrBadHandle;
274 //Check that both SetPriority & SetPriorityL methods return the same error code
275 r1 = aMessage.SetProcessPriority(priority);
276 TRAPD(r2, aMessage.SetProcessPriorityL(priority))
286 void CTestSession::ServiceL(const RMessage2& aMessage)
288 // Virtual message-handler
292 switch (aMessage.Function())
295 CActiveScheduler::Stop();
304 TestClient(aMessage);
307 TestComplete(aMessage);
309 case ETestPtrComplete:
310 TestPtrComplete(aMessage);
312 case ETestCompletePanic:
313 aMessage.Complete(KErrNone);
315 case ETestOtherSession:
317 case ETestCompleteAfter:
318 User::After(7000000);
320 case ETestMessageConstruction:
321 r=TestMessageConstruction(aMessage);
323 case ETestRMessagePtr2LeavingInterface:
324 r=TestRMessagePtr2LeavingInterface(aMessage);
330 aMessage.Complete(r);
334 // CTestSession funtions
336 void CMyActiveScheduler::Error(TInt anError) const
338 // Virtual error handler
341 User::Panic(_L("CMyActiveScheduer::Error"), anError);
346 TInt ClientThread(TAny*)
348 // Passed as the first client thread - signals the server to do several tests
351 RTest test(_L("T_MESSGE...client"));
354 test.Start(_L("Wait for server to start"));
357 test.Next(_L("Create Session"));
358 TInt r=session.PublicCreateSession(_L("CTestServer"),5);
360 User::Panic(_L("CreateSessn failure"),r);
362 test.Next(_L("Signal to test Int0/1/2/3()"));
363 r=session.PublicSendReceive(CTestSession::ETestInt,TIpcArgs(-3866,30566,0,200) );
366 test.Next(_L("Signal to test Ptr0/1/2/3()"));
368 r=session.PublicSendReceive(CTestSession::ETestPtr, TIpcArgs(&clientThread, &serverThread, &session, &sem));
371 test.Next(_L("Signal to test Client()"));
372 r=session.PublicSendReceive(CTestSession::ETestClient, TIpcArgs());
375 test.Next(_L("Test RMessage2::Complete()"));
376 TRequestStatus stat[7];
379 session.PublicSendReceive(CTestSession::ETestComplete, TIpcArgs(), stat[r]);
380 test(stat[r]==KRequestPending);
382 session.PublicSendReceive(CTestSession::ETestComplete, TIpcArgs(), stat[4]);
383 User::WaitForRequest(stat[0]);
385 test(stat[r]==5-r); //Test the 'error messages' set by Complete()
386 test.Next(_L("Test RMessagePtr2::Complete()"));
389 session.PublicSendReceive(CTestSession::ETestPtrComplete, TIpcArgs(), stat[r]);
390 test(stat[r]==KRequestPending);
392 session.PublicSendReceive(CTestSession::ETestPtrComplete, TIpcArgs(), stat[4]);
393 User::WaitForRequest(stat[0]);
395 test(stat[r]==10-r*2);
397 test.Next(_L("Test RMessage contruction from Ptr"));
398 if(UserSvr::IpcV1Available())
400 r=session.PublicSendReceive(CTestSession::ETestMessageConstruction, TIpcArgs(111,222,333,444));
405 test.Printf(_L("NOT TESTED - IPC V1 is not supported by system"));
408 test.Next(_L("Test RMessagePtr leaving interface"));
409 r=session.PublicSendReceive(CTestSession::ETestRMessagePtr2LeavingInterface, TIpcArgs());
412 test.Next(_L("Try another session"));
413 r=otherSession.PublicCreateSession(_L("CTestServer"),5);
416 r=otherSession.PublicSendReceive(CTestSession::ETestOtherSession, TIpcArgs());
419 test.Next(_L("Saturate server"));
422 test.Printf(_L("Send %d\r"),r);
423 session.PublicSendReceive(CTestSession::ETestCompleteAfter,TIpcArgs(),stat[r]);
425 test(stat[r]==KRequestPending);
427 test(stat[r]==KErrServerBusy);
429 test.Printf(_L("\n"));
432 test.Printf(_L("Wait %d\r"),r);
433 User::WaitForRequest(stat[r]);
434 test(stat[r]==KErrNone);
436 test.Printf(_L("\n"));
438 test.Next(_L("Signal to stop ActiveScheduler"));
439 session.PublicSendReceive(CTestSession::EStop, TIpcArgs());
441 otherSession.PublicSendReceive(CTestSession::EStop, TIpcArgs());
442 otherSession.Close();
448 TInt ServerThread(TAny*)
450 // Passed as the server thread in 2 tests - sets up and runs CTestServer
453 RTest test(_L("T_MESSGE...server"));
456 test.Start(_L("Create and install ActiveScheduler"));
457 CMyActiveScheduler* pScheduler = new CMyActiveScheduler;
458 if (pScheduler==NULL)
460 clientThread.Kill(0);
461 User::Panic(_L("CreateSched failure"),KErrNoMemory);
464 CActiveScheduler::Install(pScheduler);
466 test.Next(_L("Creating and starting Server"));
467 CTestServer* pServer = new CTestServer(0);
470 clientThread.Kill(0);
471 User::Panic(_L("CreateServr failure"),KErrNoMemory);
474 TInt r=pServer->Start(KServerName);//Starting a CServer2 also Adds it to the ActiveScheduler
477 clientThread.Kill(0);
478 User::Panic(_L("StartServr failure"),r);
482 test.Next(_L("Start ActiveScheduler and signal to client"));
483 test.Printf(_L(" There might be something going on beneath this window"));
485 CActiveScheduler::Start();
486 test.Next(_L("Destroy ActiveScheduler"));
495 const TInt KTestPanic = 14849;
497 TInt PanicTestThread (TAny*)
499 // Passed as a thread entry - just calls RMessage2::Panic()
503 message.Panic(_L("Testing Panic"),KTestPanic);
507 RTest test(_L("Main T_MESSGE test"));
509 TInt CompletePanicClientThread (TAny*)
511 // Passed as the second client thread entry - signals to server to call Complete() twice
516 TInt r=session.PublicCreateSession(_L("CTestServer"),1);
519 r=session.PublicSendReceive(CTestSession::ETestCompletePanic, TIpcArgs());
522 session.PublicSendReceive(CTestSession::EStop, TIpcArgs());//panic should occur before this is serviced
526 void SimpleRMessage()
528 // Simple RMessage2 Tests - constructors and assignment
532 test.Start(_L("Default constructor"));
535 test.Next(_L("Copy constructor"));
536 RMessage2 message2(message1);
537 test(message1.Function()==message2.Function());
538 test(message1.Int0()==message2.Int0());
539 test(message1.Int1()==message2.Int1());
540 test(message1.Int2()==message2.Int2());
541 test(message1.Int3()==message2.Int3());
543 test.Next(_L("Assignment operator"));
545 Mem::Fill(&message3,sizeof(message3),0xb9); // first fill message 3 with rubbish
547 test(message1.Function()==message3.Function());
548 test(message1.Int0()==message3.Int0());
549 test(message1.Int1()==message3.Int1());
550 test(message1.Int2()==message3.Int2());
551 test(message1.Int3()==message3.Int3());
556 void SimpleRMessagePtr()
558 // Simple RMessagePtr2 tests - constructors and assignment
561 test.Start(_L("Default constructor"));
562 RMessagePtr2 messagePtr1;
563 test(messagePtr1.IsNull());
565 test.Next(_L("Copy constructor"));
566 RMessagePtr2 messagePtr2(messagePtr1);
567 test(messagePtr2.IsNull());
569 test.Next(_L("Constructor from pointer to RMessage2"));
571 messagePtr1= message;
573 test.Next(_L("Assignment operator"));
574 messagePtr1=messagePtr2;
580 GLDEF_C TInt E32Main()
584 test.Start(_L("Simple RMessage2 tests"));
587 test.Next(_L("Simple RMessagePtr2 tests"));
590 test.Next(_L("Sending messages between two threads"));
591 test.Start(_L("Create client and server threads"));
592 clientThread.Create(_L("Client Thread"),ClientThread,KDefaultStackSize,KHeapMinSize,KHeapMaxSize,NULL);
593 serverThread.Create(_L("Server Thread"),ServerThread,KDefaultStackSize,KHeapMinSize,KHeapMaxSize,NULL);
595 test.Next(_L("Logon to the threads"));
596 TRequestStatus clientStat,serverStat;
597 clientThread.Logon(clientStat);
598 serverThread.Logon(serverStat);
600 test.Next(_L("Start the threads"));
602 clientThread.Resume();
603 serverThread.Resume();
605 test.Next(_L("Wait for the threads to stop"));
606 if(clientStat==KRequestPending)
607 User::WaitForRequest(clientStat);
608 if(serverStat==KRequestPending)
609 User::WaitForRequest(serverStat);
610 switch (clientThread.ExitType())
613 test.Printf(_L(" Client thread killed\n"));
616 test.Printf(_L("!!Client thread terminated:"));
617 test.Panic(clientThread.ExitCategory(), clientThread.ExitReason());
619 test.Panic(_L("!!Client thread panicked:"));
620 test.Panic(clientThread.ExitCategory(), clientThread.ExitReason());
622 test.Panic(_L("!!Client thread did something bizarre"), clientThread.ExitReason());
624 switch (serverThread.ExitType())
627 test.Printf(_L(" Server thread killed\n"));
630 test.Printf(_L("!!Server thread terminated:"));
631 test.Panic(serverThread.ExitCategory(), serverThread.ExitReason());
633 test.Printf(_L("!!Server thread panicked:"));
634 test.Panic(serverThread.ExitCategory(), serverThread.ExitReason());
636 // To catch a panic put a breakpoint in User::Panic() (in UCDT\UC_UNC.CPP).
639 test.Panic(_L("!!Server thread did something bizarre"), serverThread.ExitReason());
642 test.Next(_L("Close the threads"));
643 CLOSE_AND_WAIT(serverThread);
644 CLOSE_AND_WAIT(clientThread);
647 TBool justInTime=User::JustInTime();
649 test.Next(_L("Check it Panics if you try to Complete a message twice"));
650 test.Start(_L("Create client and server threads"));
651 clientThread.Create(_L("Client Thread1"),CompletePanicClientThread,KDefaultStackSize,KHeapMinSize,KHeapMaxSize,NULL);
652 serverThread.Create(_L("Server Thread"),ServerThread,KDefaultStackSize,KHeapMinSize,KHeapMaxSize,NULL);
654 test.Next(_L("Logon to the threads"));
655 clientThread.Logon(clientStat);
656 serverThread.Logon(serverStat);
658 test.Next(_L("Start the threads"));
660 User::SetJustInTime(EFalse);
661 clientThread.Resume();
662 serverThread.Resume();
664 test.Next(_L("Wait for the threads to stop"));
665 User::WaitForRequest(clientStat); //
666 User::WaitForRequest(serverStat);
667 User::SetJustInTime(justInTime);
668 test.Next(_L("Check the exit categories"));
669 test(clientThread.ExitType()==EExitKill);
670 test(clientThread.ExitCategory().Compare(_L("Kill"))==0);
671 test(clientThread.ExitReason()==KErrNone);
673 test(serverThread.ExitType()==EExitPanic);
674 test(serverThread.ExitCategory().Compare(_L("USER"))==0);
675 test(serverThread.ExitReason()==ETMesCompletion);
677 test.Next(_L("Close the threads"));
678 CLOSE_AND_WAIT(serverThread);
679 CLOSE_AND_WAIT(clientThread);