os/kernelhwsrv/kerneltest/e32test/active/t_messge.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32test\active\t_messge.cpp
    15 // Overview:
    16 // Test the RMessage2 and RMessagePtr2 classes. 
    17 // API Information:
    18 // RMessage2, RMessagePtr2, RSessionBase, CSession2, CServer2
    19 // Details:
    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
    26 // same integers.
    27 // - Send pointers as message arguments from client and test that the server receives the
    28 // same pointers. 
    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:
    43 // All.
    44 // Assumptions/Requirement/Pre-requisites:
    45 // Failures and causes:
    46 // Base Port information:
    47 // 
    48 //
    49 
    50 #include <e32std.h>
    51 #include <e32std_private.h>
    52 #include <e32test.h>
    53 #include <e32ver.h>
    54 #include <e32panic.h>
    55 
    56 const TInt KHeapMinSize=0x1000;
    57 const TInt KHeapMaxSize=0x1000;
    58 
    59 _LIT(KServerName,"CTestServer");
    60 
    61 class CTestServer : public CServer2
    62 	{
    63 public:
    64 	IMPORT_C CTestServer(TInt aPriority);
    65 	enum TPanicType{
    66 		EInt0Error=1, EInt1Error, EInt2Error, EInt3Error,
    67 		EPtr0Error, EPtr1Error, EPtr2Error, EPtr3Error,
    68 		ECreateNameError, ENewSessionError,
    69 		EClientError
    70 		};
    71 	static void Panic(TPanicType aReason);
    72 protected:
    73 	//override the pure virtual functions:
    74 	IMPORT_C virtual CSession2* NewSessionL(const TVersion& aVersion,const RMessage2& aMessage) const;
    75 	};
    76 
    77 
    78 class CTestSession : public CSession2
    79 	{
    80 public:
    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);
    84 private:
    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);
    93 	//	
    94 	TInt count1;//initially ==0
    95 	RMessage2 messages[5];//Used in TestComplete()
    96 //
    97 	TInt count2;//initially ==0
    98 	RMessagePtr2 messagePtrs[5];//User in TestPtrComplete()
    99 	};
   100 
   101 
   102 class CMyActiveScheduler : public CActiveScheduler
   103 	{
   104 public:
   105 	virtual void Error(TInt anError) const; //override pure virtual error function
   106 	};
   107 
   108 
   109 class RSession : public RSessionBase
   110 	{
   111 public:
   112 	TInt PublicSendReceive(TInt aFunction, const TIpcArgs &aPtr)
   113 		{
   114 		return (SendReceive(aFunction, aPtr));
   115 		}
   116 	void PublicSendReceive(TInt aFunction, const TIpcArgs &aPtr, TRequestStatus& aStatus)
   117 		{
   118 		SendReceive(aFunction, aPtr, aStatus);
   119 		}
   120 	TInt PublicCreateSession(const TDesC& aServer,TInt aMessageSlots)
   121 		{
   122 		return (CreateSession(aServer,User::Version(),aMessageSlots));
   123 		}
   124 	};
   125 
   126 // CTestServer functions
   127 
   128 CTestServer::CTestServer(TInt aPriority) 
   129 //
   130 // Constructor - sets name
   131 //
   132 	: CServer2(aPriority)
   133 	{}
   134 
   135 CSession2* CTestServer::NewSessionL(const TVersion& aVersion,const RMessage2& /*aMessage*/) const
   136 //
   137 // Virtual fn - checks version supported and creates a CTestSession
   138 //
   139 	{
   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);
   147 	}
   148 
   149 RThread clientThread, serverThread;
   150 
   151 void CTestServer::Panic(TPanicType aReason)	  //static function
   152 	{
   153 	clientThread.Kill(KErrNone);
   154 	User::Panic(_L("CTestServer"),aReason);
   155 	}
   156 
   157 RSession session, otherSession;
   158 RSemaphore sem;
   159 
   160 const TInt KTestInt[] = {-3866,30566,0,200};
   161 
   162 void CTestSession::TestInt(const RMessage2& aMessage)
   163 //
   164 // Tests to see that the correct Int0/1/2/3 have been received
   165 //
   166 	{
   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);
   175 	}
   176 
   177 const TAny* KTestPtr[]={&clientThread, &serverThread, &session, &sem};
   178 
   179 void CTestSession::TestPtr(const RMessage2& aMessage)
   180 //
   181 // Tests to see that the correct Ptr0/1/2/3 have been received
   182 //
   183 	{
   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);
   192 	}
   193 
   194 void CTestSession::TestClient(const RMessage2& aMessage)
   195 //
   196 // Tests Client()
   197 //
   198 	{
   199 
   200 	TFullName n=RProcess().Name();
   201 	n+=_L("::Client Thread");
   202 	RThread t;
   203 	TInt r=aMessage.Client(t);
   204 	if (r!=KErrNone)
   205 		User::Invariant();
   206 	if (t.FullName().CompareF(n)!=0)
   207 		{
   208 		clientThread.Kill(0);
   209 		CTestServer::Panic(CTestServer::EClientError);
   210 		}
   211 	t.Close();
   212 	}
   213 
   214 void CTestSession::TestComplete(const RMessage2& aMessage)
   215 //
   216 // Stores messages up then Completes in reverse order 
   217 //
   218 	{
   219 	messages[count1] = aMessage;
   220 	if (++count1==5)
   221 		for(count1=4; count1>=0; count1--)
   222 			messages[count1].Complete(5-count1);  //Complete with different 'error messages'
   223 	}
   224 
   225 void CTestSession::TestPtrComplete(const RMessage2& aMessage)
   226 //
   227 // Stores messages up as RMessagePtrs then Completes in reverse order
   228 // Also tests RMessage2::MessagePtr()
   229 //
   230 	{
   231 
   232 	messagePtrs[count2] = aMessage;
   233 	__ASSERT_ALWAYS(!messagePtrs[count2].IsNull(), User::Invariant());
   234 	if (++count2==5)
   235 		for(count2=4; count2>=0; count2--)
   236 			{
   237 			messagePtrs[count2].Complete(10-count2*2);
   238 			__ASSERT_ALWAYS(messagePtrs[count2].IsNull(), User::Invariant());
   239 			}
   240 	}
   241 
   242 
   243 
   244 TInt CTestSession::TestMessageConstruction(const RMessage2& aMessage)
   245 	{
   246 	RMessage2 m2((RMessagePtr2&)aMessage);
   247 	if(m2!=aMessage)
   248 		return KErrGeneral;
   249 	return KErrNone;
   250 	}
   251 
   252 TInt CTestSession::TestRMessagePtr2LeavingInterface(const RMessage2& aMessage)
   253 	{
   254 	RThread thread1, thread2;
   255 	TProcessPriority priority = EPriorityForeground;
   256 	
   257 	//Check that both Client and ClientL methods return the same thread and error code.
   258 	if (aMessage.Client(thread1)) 
   259 		return KErrGeneral;
   260 
   261 	TRAPD(r1, aMessage.ClientL(thread2))
   262 	if (KErrNone != r1)	
   263 		{
   264 		thread1.Close();
   265 		return r1;
   266 		}
   267 	if (thread1.Id() != thread2.Id()) 
   268 		{
   269 		thread1.Close();
   270 		thread2.Close();
   271 		return KErrBadHandle;
   272 		}
   273 
   274 	//Check that both SetPriority & SetPriorityL methods return the same error code 
   275 	r1 = aMessage.SetProcessPriority(priority);
   276 	TRAPD(r2, aMessage.SetProcessPriorityL(priority))
   277 
   278 	thread1.Close();
   279 	thread2.Close();
   280 	if (r1 != r2)
   281 		return KErrGeneral;
   282 
   283 	return KErrNone;
   284 	}
   285 
   286 void CTestSession::ServiceL(const RMessage2& aMessage)
   287 //
   288 // Virtual message-handler
   289 //
   290 	{
   291 	TInt r=KErrNone;
   292 	switch (aMessage.Function())
   293 		{
   294 		case EStop:
   295 			CActiveScheduler::Stop();
   296 			break;		
   297 		case ETestInt:
   298 			TestInt(aMessage);
   299 			break;
   300 		case ETestPtr:
   301 			TestPtr(aMessage);
   302 			break;
   303 		case ETestClient:
   304 			TestClient(aMessage);
   305 			break;
   306 		case ETestComplete:
   307 			TestComplete(aMessage);
   308 			return;
   309 		case ETestPtrComplete:
   310 			TestPtrComplete(aMessage);
   311 			return;
   312 		case ETestCompletePanic:
   313 			aMessage.Complete(KErrNone);
   314 			break;
   315 		case ETestOtherSession:
   316 			break;
   317 		case ETestCompleteAfter:
   318 			User::After(7000000);
   319 			break;
   320 		case ETestMessageConstruction:
   321 			r=TestMessageConstruction(aMessage);
   322 			break;
   323 		case ETestRMessagePtr2LeavingInterface:
   324 			r=TestRMessagePtr2LeavingInterface(aMessage);
   325 			break;
   326 		default:
   327 			r=KErrNotSupported;
   328 
   329 		}						  
   330  	aMessage.Complete(r);
   331 	
   332 	}
   333 
   334 // CTestSession funtions
   335 
   336 void CMyActiveScheduler::Error(TInt anError) const
   337 //
   338 // Virtual error handler
   339 //
   340 	{
   341 	User::Panic(_L("CMyActiveScheduer::Error"), anError);
   342 	}
   343 
   344 #include <e32svr.h>
   345 
   346 TInt ClientThread(TAny*)
   347 //
   348 // Passed as the first client thread - signals the server to do several tests
   349 //
   350 	{
   351 	RTest test(_L("T_MESSGE...client"));
   352 	
   353 	test.Title(); 
   354 	test.Start(_L("Wait for server to start"));
   355 	sem.Wait();
   356 	
   357 	test.Next(_L("Create Session"));
   358 	TInt r=session.PublicCreateSession(_L("CTestServer"),5);
   359 	if (r!=KErrNone)
   360 		User::Panic(_L("CreateSessn failure"),r);
   361 
   362 	test.Next(_L("Signal to test Int0/1/2/3()"));
   363 	r=session.PublicSendReceive(CTestSession::ETestInt,TIpcArgs(-3866,30566,0,200) );
   364 	test(r==KErrNone);
   365 
   366 	test.Next(_L("Signal to test Ptr0/1/2/3()"));
   367 	
   368 	r=session.PublicSendReceive(CTestSession::ETestPtr, TIpcArgs(&clientThread, &serverThread, &session, &sem));
   369 	test(r==KErrNone);
   370 
   371 	test.Next(_L("Signal to test Client()"));
   372 	r=session.PublicSendReceive(CTestSession::ETestClient, TIpcArgs());
   373 	test(r==KErrNone);
   374 
   375 	test.Next(_L("Test RMessage2::Complete()"));
   376 	TRequestStatus stat[7];
   377 	for (r=0;r<4;r++)
   378 		{
   379 		session.PublicSendReceive(CTestSession::ETestComplete, TIpcArgs(), stat[r]);
   380 		test(stat[r]==KRequestPending);
   381 		}
   382 	session.PublicSendReceive(CTestSession::ETestComplete, TIpcArgs(), stat[4]);
   383 	User::WaitForRequest(stat[0]);
   384 	for (r=0;r<5;r++)
   385 		test(stat[r]==5-r);	 //Test the 'error messages' set by Complete()
   386 	test.Next(_L("Test RMessagePtr2::Complete()"));
   387 	for (r=0;r<4;r++)
   388 		{
   389 		session.PublicSendReceive(CTestSession::ETestPtrComplete, TIpcArgs(), stat[r]);
   390 		test(stat[r]==KRequestPending);
   391 		}
   392 	session.PublicSendReceive(CTestSession::ETestPtrComplete, TIpcArgs(), stat[4]);
   393 	User::WaitForRequest(stat[0]);
   394 	for (r=0;r<5;r++)
   395 		test(stat[r]==10-r*2);
   396 
   397 	test.Next(_L("Test RMessage contruction from Ptr"));
   398 	if(UserSvr::IpcV1Available())
   399 		{
   400 		r=session.PublicSendReceive(CTestSession::ETestMessageConstruction, TIpcArgs(111,222,333,444));
   401 		test(r==KErrNone);
   402 		}
   403 	else
   404 		{
   405 		test.Printf(_L("NOT TESTED - IPC V1 is not supported by system"));
   406 		}
   407 
   408 	test.Next(_L("Test RMessagePtr leaving interface"));
   409 	r=session.PublicSendReceive(CTestSession::ETestRMessagePtr2LeavingInterface, TIpcArgs());
   410 	test(r==KErrNone);
   411 
   412 	test.Next(_L("Try another session"));
   413 	r=otherSession.PublicCreateSession(_L("CTestServer"),5);
   414 	test(r==KErrNone);
   415 
   416 	r=otherSession.PublicSendReceive(CTestSession::ETestOtherSession, TIpcArgs());
   417 	test(r==KErrNone);
   418 	
   419 	test.Next(_L("Saturate server"));
   420 	for(r=0;r<7;r++)
   421 		{
   422 		test.Printf(_L("Send %d\r"),r);
   423 		session.PublicSendReceive(CTestSession::ETestCompleteAfter,TIpcArgs(),stat[r]);			
   424 		if (r<5)
   425 			test(stat[r]==KRequestPending);
   426 		else
   427 			test(stat[r]==KErrServerBusy);
   428 		}
   429  	test.Printf(_L("\n"));
   430 	for(r=0;r<5;r++)
   431 		{
   432 		test.Printf(_L("Wait %d\r"),r);
   433 		User::WaitForRequest(stat[r]);
   434 		test(stat[r]==KErrNone);
   435 		}
   436  	test.Printf(_L("\n"));
   437 
   438 	test.Next(_L("Signal to stop ActiveScheduler"));
   439 	session.PublicSendReceive(CTestSession::EStop, TIpcArgs());	
   440 	session.Close();
   441 	otherSession.PublicSendReceive(CTestSession::EStop, TIpcArgs());
   442 	otherSession.Close();
   443 	test.Close();
   444 	
   445 	return (KErrNone);
   446 	}
   447 
   448 TInt ServerThread(TAny*)
   449 //
   450 // Passed as the server thread in 2 tests - sets up and runs CTestServer
   451 //
   452 	{
   453 	RTest test(_L("T_MESSGE...server"));
   454 	
   455 	test.Title();
   456 	test.Start(_L("Create and install ActiveScheduler"));
   457 	CMyActiveScheduler* pScheduler = new CMyActiveScheduler;
   458 	if (pScheduler==NULL)
   459 		{
   460 		clientThread.Kill(0);
   461 		User::Panic(_L("CreateSched failure"),KErrNoMemory);
   462 		}
   463 
   464 	CActiveScheduler::Install(pScheduler);
   465 
   466 	test.Next(_L("Creating and starting Server"));
   467 	CTestServer* pServer = new CTestServer(0);
   468 	if (pServer==NULL)
   469 		{
   470 		clientThread.Kill(0);
   471 		User::Panic(_L("CreateServr failure"),KErrNoMemory);
   472 		}
   473 
   474 	TInt r=pServer->Start(KServerName);//Starting a CServer2 also Adds it to the ActiveScheduler
   475 	if (r!=KErrNone)
   476 		{
   477 		clientThread.Kill(0);
   478 		User::Panic(_L("StartServr failure"),r);
   479 		}
   480 
   481 
   482 	test.Next(_L("Start ActiveScheduler and signal to client"));
   483 	test.Printf(_L("        There might be something going on beneath this window"));
   484 	sem.Signal();
   485 	CActiveScheduler::Start();
   486 	test.Next(_L("Destroy ActiveScheduler"));
   487 	delete pScheduler;
   488 	delete pServer;
   489 
   490 	test.Close();
   491 		
   492 	return (KErrNone);
   493 	}
   494 
   495 const TInt KTestPanic = 14849;
   496 
   497 TInt PanicTestThread (TAny*)
   498 //
   499 // Passed as a thread entry - just calls RMessage2::Panic()
   500 //
   501 	{
   502 	RMessage2 message;
   503 	message.Panic(_L("Testing Panic"),KTestPanic);
   504 	return(KErrNone);
   505 	}
   506 
   507 RTest test(_L("Main T_MESSGE test"));
   508 
   509 TInt CompletePanicClientThread (TAny*)
   510 //
   511 // Passed as the second client thread entry - signals to server to call Complete() twice
   512 //
   513 	{
   514 	sem.Wait();
   515 	
   516 	TInt r=session.PublicCreateSession(_L("CTestServer"),1);
   517 	test(r==KErrNone);
   518 
   519 	r=session.PublicSendReceive(CTestSession::ETestCompletePanic, TIpcArgs());
   520 	test(r==KErrNone);
   521 
   522 	session.PublicSendReceive(CTestSession::EStop, TIpcArgs());//panic should occur before this is serviced 
   523 	return(KErrNone);
   524 	}
   525 
   526 void SimpleRMessage()
   527 //
   528 // Simple RMessage2 Tests - constructors and assignment
   529 //
   530 	{
   531 	
   532 	test.Start(_L("Default constructor"));
   533 	RMessage2 message1;
   534 
   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());
   542 
   543 	test.Next(_L("Assignment operator"));
   544 	RMessage2 message3;
   545 	Mem::Fill(&message3,sizeof(message3),0xb9);	// first fill message 3 with rubbish
   546 	message3=message1;
   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());
   552 
   553 	test.End();
   554 	}
   555 
   556 void SimpleRMessagePtr()
   557 //
   558 // Simple RMessagePtr2 tests - constructors and assignment
   559 //
   560 	{
   561 	test.Start(_L("Default constructor"));
   562 	RMessagePtr2 messagePtr1;
   563 	test(messagePtr1.IsNull());
   564 
   565 	test.Next(_L("Copy constructor"));
   566 	RMessagePtr2 messagePtr2(messagePtr1);
   567 	test(messagePtr2.IsNull());
   568 
   569 	test.Next(_L("Constructor from pointer to RMessage2"));
   570 	RMessage2 message;
   571     messagePtr1= message;
   572 
   573 	test.Next(_L("Assignment operator"));
   574 	messagePtr1=messagePtr2;
   575 
   576 	test.End();
   577 	}
   578 
   579 
   580 GLDEF_C TInt E32Main()
   581 	{
   582 	test.Title();
   583 	
   584 	test.Start(_L("Simple RMessage2 tests"));
   585 	SimpleRMessage();
   586 
   587 	test.Next(_L("Simple RMessagePtr2 tests"));
   588 	SimpleRMessagePtr();
   589 
   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);
   594 	
   595 	test.Next(_L("Logon to the threads"));
   596 	TRequestStatus clientStat,serverStat;	
   597 	clientThread.Logon(clientStat);
   598 	serverThread.Logon(serverStat);
   599 
   600 	test.Next(_L("Start the threads"));
   601 	sem.CreateLocal(0);
   602 	clientThread.Resume();
   603 	serverThread.Resume();
   604 	
   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())
   611 		{
   612 		case EExitKill:
   613 			test.Printf(_L("  Client thread killed\n")); 
   614 			break;
   615 		case EExitTerminate:
   616 			test.Printf(_L("!!Client thread terminated:"));
   617 			test.Panic(clientThread.ExitCategory(), clientThread.ExitReason());
   618 		case EExitPanic:
   619 			test.Panic(_L("!!Client thread panicked:"));
   620 			test.Panic(clientThread.ExitCategory(), clientThread.ExitReason());
   621 		default:
   622 			test.Panic(_L("!!Client thread did something bizarre"), clientThread.ExitReason());
   623 		}
   624 	switch (serverThread.ExitType())
   625 		{
   626 		case EExitKill:
   627 			test.Printf(_L("  Server thread killed\n")); 
   628 			break;
   629 		case EExitTerminate:
   630 			test.Printf(_L("!!Server thread terminated:"));
   631 			test.Panic(serverThread.ExitCategory(), serverThread.ExitReason());
   632 		case EExitPanic:
   633 			test.Printf(_L("!!Server thread panicked:"));
   634 			test.Panic(serverThread.ExitCategory(), serverThread.ExitReason());
   635 			//
   636 			// To catch a panic put a breakpoint in User::Panic() (in UCDT\UC_UNC.CPP).
   637 			//
   638 		default:
   639 			test.Panic(_L("!!Server thread did something bizarre"), serverThread.ExitReason());
   640 		}
   641 
   642 	test.Next(_L("Close the threads"));
   643 	CLOSE_AND_WAIT(serverThread);
   644 	CLOSE_AND_WAIT(clientThread);
   645 	test.End();
   646 
   647 	TBool justInTime=User::JustInTime();
   648 	
   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);
   653 	
   654 	test.Next(_L("Logon to the threads"));
   655 	clientThread.Logon(clientStat);
   656 	serverThread.Logon(serverStat);
   657 
   658 	test.Next(_L("Start the threads"));
   659 	sem.CreateLocal(0);
   660 	User::SetJustInTime(EFalse); 
   661 	clientThread.Resume();
   662 	serverThread.Resume();
   663 	
   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);
   672 		
   673 	test(serverThread.ExitType()==EExitPanic);
   674 	test(serverThread.ExitCategory().Compare(_L("USER"))==0);
   675 	test(serverThread.ExitReason()==ETMesCompletion);
   676 
   677 	test.Next(_L("Close the threads"));
   678 	CLOSE_AND_WAIT(serverThread);
   679 	CLOSE_AND_WAIT(clientThread);
   680 	test.End();	  
   681   	
   682 	test.End();
   683   
   684 	return (KErrNone);
   685 	}
   686 
   687