|         |      1 // Copyright (c) 1994-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\system\t_trap.cpp | 
|         |     15 // Overview: | 
|         |     16 // Test TRAP, Leave and Assert | 
|         |     17 // API Information: | 
|         |     18 // TRAP, User::Leave, __ASSERT_DEBUG_NO_LEAVE, __ASSERT_ALWAYS_NO_LEAVE | 
|         |     19 // Details: | 
|         |     20 // - Test TRAP macro works as expected. | 
|         |     21 // - Test User::Leave works as expected including leave from | 
|         |     22 // within nested calls. | 
|         |     23 // - Verify that a leave without a TRAP causes the thread to panic. | 
|         |     24 // - Create a thread that asserts and verify the exit type and other | 
|         |     25 // results are as expected. | 
|         |     26 // Platforms/Drives/Compatibility: | 
|         |     27 // All. | 
|         |     28 // Assumptions/Requirement/Pre-requisites: | 
|         |     29 // Failures and causes: | 
|         |     30 // Base Port information: | 
|         |     31 //  | 
|         |     32 // | 
|         |     33  | 
|         |     34 #include <e32test.h> | 
|         |     35 #include <e32panic.h> | 
|         |     36  | 
|         |     37 const TInt KLeaveVal=1111; | 
|         |     38 const TInt KUnLeaveVal=2222; | 
|         |     39 const TInt KRecursiveUnLeaveVal=3333; | 
|         |     40 const TInt KRecursiveSingleLeaveVal=4444; | 
|         |     41 const TInt KMaxDepth=20; | 
|         |     42  | 
|         |     43 //#define __TEST_BREAKPOINT_IN_TRAP__ | 
|         |     44  | 
|         |     45 LOCAL_D RTest test(_L("T_TRAP")); | 
|         |     46  | 
|         |     47  | 
|         |     48 LOCAL_C TInt UnLeaveFunction(void) | 
|         |     49 	{ | 
|         |     50  | 
|         |     51 	return(KUnLeaveVal); | 
|         |     52 	} | 
|         |     53  | 
|         |     54 LOCAL_C TInt LeaveFunction(void) | 
|         |     55 	{ | 
|         |     56  | 
|         |     57 	User::Leave(KLeaveVal); | 
|         |     58 	return(0); | 
|         |     59 	} | 
|         |     60  | 
|         |     61 LOCAL_C TInt RecursiveUnLeave(TInt level) | 
|         |     62 	{ | 
|         |     63  | 
|         |     64 	if (level==0) | 
|         |     65 		return(KRecursiveUnLeaveVal); | 
|         |     66 	else | 
|         |     67 		return(RecursiveUnLeave(--level)); | 
|         |     68 	} | 
|         |     69  | 
|         |     70 LOCAL_C TInt RecursiveSingleLeave(TInt level) | 
|         |     71 	{ | 
|         |     72  | 
|         |     73 	if (level==0) | 
|         |     74 		User::Leave(KRecursiveSingleLeaveVal); | 
|         |     75 	else | 
|         |     76 		RecursiveSingleLeave(--level); | 
|         |     77 	return(0); | 
|         |     78 	} | 
|         |     79  | 
|         |     80 LOCAL_C TInt RecursiveMultiLeave1(TInt level) | 
|         |     81 	{ | 
|         |     82  | 
|         |     83 	TInt ret=0; | 
|         |     84 	TRAP(ret,{if (level==0)	User::Leave(level);	else ret=RecursiveMultiLeave1(level-1);	test(EFalse);}) | 
|         |     85 	test(ret==level); | 
|         |     86 	User::Leave(level+1); | 
|         |     87 	return(0); | 
|         |     88 	} | 
|         |     89  | 
|         |     90 LOCAL_C TInt RecursiveMultiLeave2(TInt level) | 
|         |     91 	{ | 
|         |     92  | 
|         |     93 	if (level==0) | 
|         |     94 		return(1); | 
|         |     95 	TInt ret=0; | 
|         |     96 	TRAP(ret,ret=RecursiveMultiLeave2(level-1)) | 
|         |     97 	test(ret==level); | 
|         |     98 	User::Leave(level+1); | 
|         |     99 	return(0); | 
|         |    100 	} | 
|         |    101 	 | 
|         |    102 LOCAL_C TInt doTrap(TInt aVal) | 
|         |    103 // | 
|         |    104 // Nest trap function. | 
|         |    105 // | 
|         |    106 	{ | 
|         |    107  | 
|         |    108 	if (aVal) | 
|         |    109 		{ | 
|         |    110 		TInt j=(-1); | 
|         |    111 		TRAP(j,j=doTrap(aVal-1)) | 
|         |    112 		test(j==aVal); | 
|         |    113 		} | 
|         |    114 	return(aVal+1); | 
|         |    115 	} | 
|         |    116  | 
|         |    117 #ifdef __TEST_BREAKPOINT_IN_TRAP__ | 
|         |    118 void bkpt() | 
|         |    119 	{ | 
|         |    120 	__BREAKPOINT(); | 
|         |    121 	} | 
|         |    122 #endif | 
|         |    123  | 
|         |    124 LOCAL_C void doLeave(TInt aLevel,TInt aVal) | 
|         |    125 // | 
|         |    126 // Nest trap with leave function. | 
|         |    127 // | 
|         |    128 	{ | 
|         |    129  | 
|         |    130 	if (aLevel) | 
|         |    131 		doLeave(aLevel-1,aVal); | 
|         |    132 	else | 
|         |    133 		User::Leave(aVal); | 
|         |    134 	} | 
|         |    135  | 
|         |    136 LOCAL_C void testTrap() | 
|         |    137 // | 
|         |    138 // Test trap functions O.K. | 
|         |    139 // | 
|         |    140 	{ | 
|         |    141  | 
|         |    142 	test.Start(_L("Trap level 1")); | 
|         |    143 // | 
|         |    144 	TInt i=2; | 
|         |    145 	TRAP(i,i=1); | 
|         |    146 	test(i==1); | 
|         |    147 #ifdef __TEST_BREAKPOINT_IN_TRAP__ | 
|         |    148 	TRAP(i,bkpt()); | 
|         |    149 	TRAP(i,TRAP(i,bkpt())); | 
|         |    150 #endif | 
|         |    151 // | 
|         |    152 	test.Next(_L("Trap level n")); | 
|         |    153 	for (i=1;i<KMaxDepth;i++) | 
|         |    154 		test(doTrap(i)==(i+1)); | 
|         |    155 // | 
|         |    156 	test.End(); | 
|         |    157 	} | 
|         |    158  | 
|         |    159 LOCAL_C void testLeave() | 
|         |    160 // | 
|         |    161 // Test leave functions O.K. | 
|         |    162 // | 
|         |    163 	{ | 
|         |    164  | 
|         |    165 	test.Start(_L("Leave level 1")); | 
|         |    166 // | 
|         |    167 	TInt i=0; | 
|         |    168 	TRAP(i,User::Leave(2)) | 
|         |    169 	test(i==2); | 
|         |    170 // | 
|         |    171 	test.Next(_L("Leave level 2")); | 
|         |    172 	i=0; | 
|         |    173 	TRAP(i,TRAP(i,User::Leave(3))) | 
|         |    174 	test(i==3); | 
|         |    175 // | 
|         |    176 #ifdef __TEST_BREAKPOINT_IN_TRAP__ | 
|         |    177 	TRAP(i,TRAP(i,User::Leave(33)); bkpt()) | 
|         |    178 	test(i==33); | 
|         |    179 #endif | 
|         |    180 // | 
|         |    181 	test.Next(_L("Leave from nested calls")); | 
|         |    182 	for (i=1;i<KMaxDepth;i++) | 
|         |    183 		{ | 
|         |    184 		TInt j=(-1); | 
|         |    185 		TRAP(j,doLeave(i,i)) | 
|         |    186 		test(j==i); | 
|         |    187 		} | 
|         |    188 // | 
|         |    189 	test.End(); | 
|         |    190 	} | 
|         |    191  | 
|         |    192 LOCAL_C void testMH(void) | 
|         |    193 	{ | 
|         |    194  | 
|         |    195 	TInt ret=0; | 
|         |    196 	TRAP(ret,ret=UnLeaveFunction()) | 
|         |    197 	test(ret==KUnLeaveVal); | 
|         |    198 	TRAP(ret,LeaveFunction()) | 
|         |    199 	test(ret==KLeaveVal); | 
|         |    200 	TInt i=0; | 
|         |    201 	for(;i<=KMaxDepth;i++) | 
|         |    202 		{ | 
|         |    203 		TRAP(ret,ret=RecursiveUnLeave(i)) | 
|         |    204 		test(ret==KRecursiveUnLeaveVal); | 
|         |    205 		} | 
|         |    206 	for(i=0;i<=KMaxDepth;i++) | 
|         |    207 		{ | 
|         |    208 		TRAP(ret,ret=RecursiveSingleLeave(i)) | 
|         |    209 		test(ret==KRecursiveSingleLeaveVal); | 
|         |    210 		} | 
|         |    211 	for(i=0;i<=KMaxDepth;i++) | 
|         |    212 		{ | 
|         |    213 		TRAP(ret,ret=RecursiveMultiLeave1(i)) | 
|         |    214 		test(ret==i+1); | 
|         |    215 		} | 
|         |    216 	for(i=0;i<=KMaxDepth;i++) | 
|         |    217 		{ | 
|         |    218 		TRAP(ret,ret=RecursiveMultiLeave2(i)) | 
|         |    219 		test(ret==i+1); | 
|         |    220 		} | 
|         |    221 	} | 
|         |    222  | 
|         |    223 TInt LeaveNoTrapThread(TAny*) | 
|         |    224 	{ | 
|         |    225 	User::Leave(KErrGeneral); | 
|         |    226 	return KErrNone; | 
|         |    227 	} | 
|         |    228  | 
|         |    229 void TestLeaveNoTrap() | 
|         |    230 	{ | 
|         |    231 	RThread thread; | 
|         |    232 	TInt r=thread.Create(_L("Leave without Trap thread"),LeaveNoTrapThread,0x1000,&User::Allocator(),NULL); | 
|         |    233 	test(r==KErrNone); | 
|         |    234 	TRequestStatus stat; | 
|         |    235 	thread.Logon(stat); | 
|         |    236 	test(stat==KRequestPending); | 
|         |    237 	TBool justInTime=User::JustInTime(); | 
|         |    238 	User::SetJustInTime(EFalse); | 
|         |    239 	thread.Resume(); | 
|         |    240 	User::WaitForRequest(stat); | 
|         |    241 	User::SetJustInTime(justInTime); | 
|         |    242 	test(thread.ExitType()==EExitPanic); | 
|         |    243 	test(thread.ExitReason()==EUserLeaveWithoutTrap); | 
|         |    244 	test(thread.ExitCategory()==_L("USER")); | 
|         |    245 	CLOSE_AND_WAIT(thread); | 
|         |    246 	} | 
|         |    247  | 
|         |    248 enum TAssertTest | 
|         |    249 	{ | 
|         |    250 	EAssertTest_Debug = 1, | 
|         |    251 	EAssertTest_Leave = 2, | 
|         |    252 	EAssertTest_Ret = 4, | 
|         |    253 	}; | 
|         |    254  | 
|         |    255 TInt AssertThread(TAny* a) | 
|         |    256 	{ | 
|         |    257 	TInt f = (TInt)a; | 
|         |    258 	TInt r = f | EAssertTest_Ret; | 
|         |    259 	if (f & EAssertTest_Leave) | 
|         |    260 		{ | 
|         |    261 		if (f & EAssertTest_Debug) | 
|         |    262 			{ | 
|         |    263 			__ASSERT_DEBUG_NO_LEAVE(User::Leave(r)); | 
|         |    264 			} | 
|         |    265 		else | 
|         |    266 			{ | 
|         |    267 			__ASSERT_ALWAYS_NO_LEAVE(User::Leave(r)); | 
|         |    268 			} | 
|         |    269 		} | 
|         |    270 	else | 
|         |    271 		{ | 
|         |    272 		if (f & EAssertTest_Debug) | 
|         |    273 			{ | 
|         |    274 			__ASSERT_DEBUG_NO_LEAVE(RThread().Terminate(r)); | 
|         |    275 			} | 
|         |    276 		else | 
|         |    277 			{ | 
|         |    278 			__ASSERT_ALWAYS_NO_LEAVE(RThread().Terminate(r)); | 
|         |    279 			} | 
|         |    280 		} | 
|         |    281 	return r; | 
|         |    282 	} | 
|         |    283  | 
|         |    284 TInt _AssertThread(TAny* a) | 
|         |    285 	{ | 
|         |    286 	TInt s=0; | 
|         |    287 	TRAP_IGNORE(s=AssertThread(a)); | 
|         |    288 	return s; | 
|         |    289 	} | 
|         |    290  | 
|         |    291 void TestAssert(TInt aTest) | 
|         |    292 	{ | 
|         |    293 	test.Printf(_L("Assert %d\n"), aTest); | 
|         |    294 	RThread t; | 
|         |    295 	TInt r = t.Create(_L("assert"), &_AssertThread, 0x1000, NULL, (TAny*)aTest); | 
|         |    296 	test(r==KErrNone); | 
|         |    297 	TRequestStatus s; | 
|         |    298 	t.Logon(s); | 
|         |    299 	test(s==KRequestPending); | 
|         |    300 	TBool jit = User::JustInTime(); | 
|         |    301 	User::SetJustInTime(EFalse); | 
|         |    302 	t.Resume(); | 
|         |    303 	User::WaitForRequest(s); | 
|         |    304 	User::SetJustInTime(jit); | 
|         |    305 	TInt exitType = t.ExitType(); | 
|         |    306 	TInt exitReason = t.ExitReason(); | 
|         |    307 	const TDesC& exitCat = t.ExitCategory(); | 
|         |    308 	CLOSE_AND_WAIT(t); | 
|         |    309 	test.Printf(_L("Exit %d,%d,%S\n"), exitType, exitReason, &exitCat); | 
|         |    310 	if (aTest & EAssertTest_Leave) | 
|         |    311 		{ | 
|         |    312 		if (aTest & EAssertTest_Debug) | 
|         |    313 			{ | 
|         |    314 #ifdef _DEBUG | 
|         |    315 			test(exitType == EExitPanic); | 
|         |    316 			test(exitReason == EUnexpectedLeave); | 
|         |    317 #else | 
|         |    318 			test(exitType == EExitKill); | 
|         |    319 			test(exitReason == KErrNone); | 
|         |    320 #endif | 
|         |    321 			} | 
|         |    322 		else | 
|         |    323 			{ | 
|         |    324 			test(exitType == EExitPanic); | 
|         |    325 			test(exitReason == EUnexpectedLeave); | 
|         |    326 			} | 
|         |    327 		} | 
|         |    328 	else | 
|         |    329 		{ | 
|         |    330 		test(exitType == EExitTerminate); | 
|         |    331 		test(exitReason == (aTest | EAssertTest_Ret)); | 
|         |    332 		} | 
|         |    333 	} | 
|         |    334  | 
|         |    335 /*============== server for testing exceptions in TRAP implementation ====================*/ | 
|         |    336  | 
|         |    337 #include <e32base.h> | 
|         |    338 #include <e32base_private.h> | 
|         |    339  | 
|         |    340 #include "../mmu/mmudetect.h" | 
|         |    341  | 
|         |    342 const TInt KHeapSize=0x2000; | 
|         |    343  | 
|         |    344 _LIT(KServerName,"Display"); | 
|         |    345  | 
|         |    346 class CMySession : public CSession2 | 
|         |    347 	{ | 
|         |    348 public: | 
|         |    349 	CMySession(); | 
|         |    350 	virtual void ServiceL(const RMessage2& aMessage); | 
|         |    351 	}; | 
|         |    352  | 
|         |    353 class CMyServer : public CServer2 | 
|         |    354 	{ | 
|         |    355 public: | 
|         |    356 	enum {ERead,EStop}; | 
|         |    357 public: | 
|         |    358 	CMyServer(TInt aPriority); | 
|         |    359 	static CMyServer* New(TInt aPriority); | 
|         |    360 	virtual CSession2* NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const;//Overloading | 
|         |    361 	}; | 
|         |    362  | 
|         |    363 class RDisplay : public RSessionBase | 
|         |    364 	{ | 
|         |    365 public: | 
|         |    366 	TInt Open(); | 
|         |    367 	void Read(TRequestStatus& aStatus); | 
|         |    368 	TInt Stop(); | 
|         |    369 	}; | 
|         |    370  | 
|         |    371 LOCAL_D RTest testSvr(_L("T_TRAP Server")); | 
|         |    372 LOCAL_D RSemaphore client; | 
|         |    373 LOCAL_D RSemaphore server; | 
|         |    374 LOCAL_D RDisplay display; | 
|         |    375 LOCAL_D const RMessage2* message; | 
|         |    376  | 
|         |    377 // Constructor | 
|         |    378 // | 
|         |    379 //  | 
|         |    380 CMySession::CMySession() | 
|         |    381 	{} | 
|         |    382  | 
|         |    383 CMyServer* CMyServer::New(TInt aPriority) | 
|         |    384 // | 
|         |    385 // Create a new CMyServer. | 
|         |    386 // | 
|         |    387 	{ | 
|         |    388 	return new CMyServer(aPriority); | 
|         |    389 	} | 
|         |    390  | 
|         |    391 CMyServer::CMyServer(TInt aPriority) | 
|         |    392 // | 
|         |    393 // Constructor. | 
|         |    394 // | 
|         |    395 	: CServer2(aPriority) | 
|         |    396 	{} | 
|         |    397  | 
|         |    398 CSession2* CMyServer::NewSessionL(const TVersion& /*aVersion*/, const RMessage2&) const | 
|         |    399 // | 
|         |    400 // Create a new client for this server. | 
|         |    401 // | 
|         |    402 	{ | 
|         |    403 	return(new(ELeave) CMySession()); | 
|         |    404 	} | 
|         |    405  | 
|         |    406 void CMySession::ServiceL(const RMessage2& aMessage) | 
|         |    407 // | 
|         |    408 // Handle messages for this server. | 
|         |    409 // | 
|         |    410 	{ | 
|         |    411 	TInt r=KErrNone; | 
|         |    412 	switch (aMessage.Function()) | 
|         |    413 		{ | 
|         |    414 	case CMyServer::ERead: | 
|         |    415 		testSvr.Printf(_L("read message received\n")); | 
|         |    416 		if (HaveVirtMem()) | 
|         |    417 			{ | 
|         |    418 			message = &aMessage; | 
|         |    419 			} | 
|         |    420 		client.Signal(); | 
|         |    421 		server.Wait(); | 
|         |    422 		break; | 
|         |    423 	case CMyServer::EStop: | 
|         |    424 		testSvr.Printf(_L("stop message received\n")); | 
|         |    425 		CActiveScheduler::Stop(); | 
|         |    426 		break; | 
|         |    427 	default: | 
|         |    428 		r=KErrNotSupported; | 
|         |    429 		} | 
|         |    430 	aMessage.Complete(r); | 
|         |    431 	} | 
|         |    432  | 
|         |    433 TInt RDisplay::Open() | 
|         |    434 // | 
|         |    435 // Open the server. | 
|         |    436 // | 
|         |    437 	{ | 
|         |    438 	return(CreateSession(KServerName,TVersion(),1)); | 
|         |    439 	} | 
|         |    440  | 
|         |    441 void RDisplay::Read(TRequestStatus& aStatus) | 
|         |    442 // | 
|         |    443 // Get session to test CSession2::ReadL. | 
|         |    444 // | 
|         |    445 	{ | 
|         |    446 	TBuf<0x10>* bad = (TBuf<0x10> *)(0x30000000); | 
|         |    447 	SendReceive(CMyServer::ERead, TIpcArgs(bad), aStatus); | 
|         |    448 	} | 
|         |    449  | 
|         |    450 TInt RDisplay::Stop() | 
|         |    451 // | 
|         |    452 // Stop the server. | 
|         |    453 // | 
|         |    454 	{ | 
|         |    455 	return SendReceive(CMyServer::EStop, TIpcArgs()); | 
|         |    456 	} | 
|         |    457  | 
|         |    458 LOCAL_C TInt serverThreadEntryPoint(TAny*) | 
|         |    459 // | 
|         |    460 // The entry point for the server thread. | 
|         |    461 // | 
|         |    462 	{ | 
|         |    463 	testSvr.Title(); | 
|         |    464 	testSvr.Start(_L("Create CActiveScheduler")); | 
|         |    465 	CActiveScheduler* pR=new CActiveScheduler; | 
|         |    466 	testSvr(pR!=NULL); | 
|         |    467 	CActiveScheduler::Install(pR); | 
|         |    468 // | 
|         |    469 	testSvr.Next(_L("Create CMyServer")); | 
|         |    470 	CMyServer* pS=CMyServer::New(0); | 
|         |    471 	testSvr(pS!=NULL); | 
|         |    472 // | 
|         |    473 	testSvr.Next(_L("Start CMyServer")); | 
|         |    474 	TInt r=pS->Start(KServerName); | 
|         |    475 	testSvr(r==KErrNone); | 
|         |    476 // | 
|         |    477 	testSvr.Next(_L("Signal to client that we have started")); | 
|         |    478 	client.Signal(); | 
|         |    479 // | 
|         |    480 	testSvr.Next(_L("Start CActiveScheduler")); | 
|         |    481 	CActiveScheduler::Start(); | 
|         |    482 // | 
|         |    483 	testSvr.Next(_L("Exit server")); | 
|         |    484 	delete pS; | 
|         |    485 	testSvr.Close(); | 
|         |    486 	return(KErrNone); | 
|         |    487 	} | 
|         |    488  | 
|         |    489 void CreateServer() | 
|         |    490 	{ | 
|         |    491 	test.Next(_L("Creating client semaphore")); | 
|         |    492 	TInt r=client.CreateLocal(0); | 
|         |    493 	test(r==KErrNone); | 
|         |    494 // | 
|         |    495 	test.Next(_L("Creating server semaphore")); | 
|         |    496 	r=server.CreateLocal(0); | 
|         |    497 	test(r==KErrNone); | 
|         |    498 // | 
|         |    499 	test.Next(_L("Creating server thread")); | 
|         |    500 	RThread server; | 
|         |    501 	r=server.Create(_L("Server"),serverThreadEntryPoint,KDefaultStackSize,KHeapSize,KHeapSize,NULL); | 
|         |    502 	test(r==KErrNone); | 
|         |    503 	server.SetPriority(EPriorityMore); | 
|         |    504 // | 
|         |    505 	test.Next(_L("Resume server thread")); | 
|         |    506 	server.Resume(); | 
|         |    507 	test(ETrue); | 
|         |    508 // | 
|         |    509 	test.Next(_L("Wait for server to start")); | 
|         |    510 	client.Wait(); | 
|         |    511 // | 
|         |    512 	test.Next(_L("Connect to server")); | 
|         |    513 	r=display.Open(); | 
|         |    514 	test(r==KErrNone); | 
|         |    515 	} | 
|         |    516  | 
|         |    517 void StopServer() | 
|         |    518 	{ | 
|         |    519 	test.Next(_L("Stop server")); | 
|         |    520 	TInt r=display.Stop(); | 
|         |    521 	test(r==KErrNone); | 
|         |    522 // | 
|         |    523 	test.Next(_L("Close connection")); | 
|         |    524 	display.Close(); | 
|         |    525 // | 
|         |    526 	test.Next(_L("Close all")); | 
|         |    527 	server.Close(); | 
|         |    528 	client.Close(); | 
|         |    529     } | 
|         |    530  | 
|         |    531 /*============== end of server for testing exceptions in TRAP implementation ====================*/ | 
|         |    532  | 
|         |    533 #undef TRAP_INSTRUMENTATION_START | 
|         |    534 #undef TRAP_INSTRUMENTATION_NOLEAVE | 
|         |    535 #undef TRAP_INSTRUMENTATION_LEAVE | 
|         |    536 #define TRAP_INSTRUMENTATION_START			++TrapStart; | 
|         |    537 #define TRAP_INSTRUMENTATION_NOLEAVE		++TrapNoLeave; TestExcInInstrumentation(); | 
|         |    538 #define TRAP_INSTRUMENTATION_LEAVE(aReason) TrapLeave=aReason; | 
|         |    539  | 
|         |    540 TInt TrapStart = 0; | 
|         |    541 TInt TrapNoLeave = 0; | 
|         |    542 TInt TrapLeave = 123; | 
|         |    543  | 
|         |    544 // | 
|         |    545 // This is mostly for the benefit of WINS, where Win32 exceptions | 
|         |    546 // have a nasty habit of interacting badly with C++ exceptions | 
|         |    547 // | 
|         |    548  | 
|         |    549 void TestExcInInstrumentation() | 
|         |    550 	{ | 
|         |    551 	TRequestStatus status; | 
|         |    552 	display.Read(status); | 
|         |    553 	test(status.Int() == KRequestPending); | 
|         |    554  | 
|         |    555 	client.Wait(); | 
|         |    556  | 
|         |    557 	TBuf<0x100> buf; | 
|         |    558 	if (message) | 
|         |    559 		test(message->Read(0,buf) == KErrBadDescriptor); | 
|         |    560  | 
|         |    561 	server.Signal(); | 
|         |    562  | 
|         |    563 	User::WaitForRequest(status); | 
|         |    564 	test(status.Int() == KErrNone); | 
|         |    565 	} | 
|         |    566  | 
|         |    567 void TestTrapInstrumentation() | 
|         |    568 	{ | 
|         |    569 	CreateServer(); | 
|         |    570  | 
|         |    571 	test.Start(_L("TRAPD No Leave")); | 
|         |    572 	TRAPD(r,User::LeaveIfError(0)); | 
|         |    573 	test(TrapStart==1); | 
|         |    574 	test(TrapLeave==123); | 
|         |    575 	test(r==0); | 
|         |    576 	test(TrapNoLeave==1); | 
|         |    577  | 
|         |    578 	test.Next(_L("TRAP No Leave")); | 
|         |    579 	TRAP(r,User::LeaveIfError(0)); | 
|         |    580 	test(TrapStart==2); | 
|         |    581 	test(TrapLeave==123); | 
|         |    582 	test(r==0); | 
|         |    583 	test(TrapNoLeave==2); | 
|         |    584  | 
|         |    585 	test.Next(_L("TRAP_IGNORE No Leave")); | 
|         |    586 	TRAP_IGNORE(User::LeaveIfError(0)); | 
|         |    587 	test(TrapStart==3); | 
|         |    588 	test(TrapLeave==123); | 
|         |    589 	test(TrapNoLeave==3); | 
|         |    590  | 
|         |    591 	test.Next(_L("TRAPD Leave")); | 
|         |    592 	TRAPD(r2,User::LeaveIfError(-999)); | 
|         |    593 	test(TrapStart==4); | 
|         |    594 	test(TrapLeave==-999); | 
|         |    595 	test(r2==TrapLeave); | 
|         |    596 	test(TrapNoLeave==3); | 
|         |    597  | 
|         |    598 	test.Next(_L("TRAP Leave")); | 
|         |    599 	TRAP(r2,User::LeaveIfError(-666)); | 
|         |    600 	test(TrapStart==5); | 
|         |    601 	test(TrapLeave==-666); | 
|         |    602 	test(r2==TrapLeave); | 
|         |    603 	test(TrapNoLeave==3); | 
|         |    604  | 
|         |    605 	test.Next(_L("TRAP_IGNORE Leave")); | 
|         |    606 	TRAP_IGNORE(User::LeaveIfError(-333)); | 
|         |    607 	test(TrapStart==6); | 
|         |    608 	test(TrapLeave==-333); | 
|         |    609 	test(TrapNoLeave==3); | 
|         |    610  | 
|         |    611 	test.Next(_L("Leave")); | 
|         |    612 	test.End(); | 
|         |    613  | 
|         |    614 	StopServer(); | 
|         |    615 	} | 
|         |    616  | 
|         |    617 #undef TRAP_INSTRUMENTATION_START | 
|         |    618 #undef TRAP_INSTRUMENTATION_NOLEAVE | 
|         |    619 #undef TRAP_INSTRUMENTATION_LEAVE | 
|         |    620 #define TRAP_INSTRUMENTATION_START | 
|         |    621 #define TRAP_INSTRUMENTATION_NOLEAVE | 
|         |    622 #define TRAP_INSTRUMENTATION_LEAVE(aReason) | 
|         |    623  | 
|         |    624 #ifdef __WINS__ | 
|         |    625 TUint32* Stack; | 
|         |    626 volatile TInt* volatile Q; | 
|         |    627 const TInt A[] = {17,19,23,29,31,37,41,43,47,53}; | 
|         |    628  | 
|         |    629 void ExceptionHandler(TExcType) | 
|         |    630 	{ | 
|         |    631 	TUint32* sp = Stack; | 
|         |    632 	for (; *sp!=0xfacefeed; --sp) {} | 
|         |    633 	*sp = (TUint32)(Q++); | 
|         |    634 	} | 
|         |    635  | 
|         |    636 __NAKED__ TInt GetNext() | 
|         |    637 	{ | 
|         |    638 	_asm mov Stack, esp | 
|         |    639 	_asm mov eax, 0facefeedh | 
|         |    640 	_asm mov eax, [eax] | 
|         |    641 	_asm ret | 
|         |    642 	} | 
|         |    643  | 
|         |    644 void testExceptionsInTrap() | 
|         |    645 	{ | 
|         |    646 	TInt ix = 0; | 
|         |    647 	TInt r; | 
|         |    648 	User::SetExceptionHandler(&ExceptionHandler, 0xffffffff); | 
|         |    649 	Q = (volatile TInt* volatile)A; | 
|         |    650 	r = GetNext(); | 
|         |    651 	test(r==A[ix++]); | 
|         |    652 	TInt i; | 
|         |    653 	TRAP(i,r=GetNext()); | 
|         |    654 	test(i==0); | 
|         |    655 	test(r==A[ix++]); | 
|         |    656 	TRAP(i,TRAP(i,r=GetNext())); | 
|         |    657 	test(i==0); | 
|         |    658 	test(r==A[ix++]); | 
|         |    659 	TRAP(i, TRAP(i,User::Leave(271));r=GetNext(); ); | 
|         |    660 	test(i==271); | 
|         |    661 	test(r==A[ix++]); | 
|         |    662 	TRAP(i, TRAP(i, TRAP(i,User::Leave(487));r=GetNext(); ); ); | 
|         |    663 	test(i==487); | 
|         |    664 	test(r==A[ix++]); | 
|         |    665 	TInt s=-1; | 
|         |    666 	TRAP(i, TRAP(i, TRAP(i, TRAP(i,User::Leave(999));r=GetNext(); ); s=GetNext(); ); ); | 
|         |    667 	test(i==999); | 
|         |    668 	test(r==A[ix++]); | 
|         |    669 	test(s==A[ix++]); | 
|         |    670 	TInt j=-1, k=-1, l=-1; | 
|         |    671 	TRAP(l,										\ | 
|         |    672 		TRAP(k,									\ | 
|         |    673 			TRAP(j,								\ | 
|         |    674 				TRAP(i,User::Leave(9991));		\ | 
|         |    675 				r=GetNext();					\ | 
|         |    676 				);								\ | 
|         |    677 			User::Leave(9992);					\ | 
|         |    678 			);									\ | 
|         |    679 		s=GetNext();							\ | 
|         |    680 		); | 
|         |    681 	test(i==9991); | 
|         |    682 	test(j==0); | 
|         |    683 	test(k==9992); | 
|         |    684 	test(l==0); | 
|         |    685 	test(r==A[ix++]); | 
|         |    686 	test(s==A[ix++]); | 
|         |    687 	} | 
|         |    688 #endif | 
|         |    689  | 
|         |    690 GLDEF_C TInt E32Main() | 
|         |    691     { | 
|         |    692 	test.Title(); | 
|         |    693 // | 
|         |    694 	test.Start(_L("Trap")); | 
|         |    695 	testTrap(); | 
|         |    696 // | 
|         |    697 	test.Next(_L("Leave")); | 
|         |    698 	testLeave(); | 
|         |    699 // | 
|         |    700 	test.Next(_L("Assorted")); | 
|         |    701 	testMH(); | 
|         |    702 // | 
|         |    703 	test.Next(_L("Leave without Trap")); | 
|         |    704 	TestLeaveNoTrap(); | 
|         |    705 // | 
|         |    706 	test.Next(_L("Assertions")); | 
|         |    707 	TestAssert(0); | 
|         |    708 	TestAssert(EAssertTest_Debug); | 
|         |    709 	TestAssert(EAssertTest_Leave); | 
|         |    710 	TestAssert(EAssertTest_Leave | EAssertTest_Debug); | 
|         |    711  | 
|         |    712 #ifdef __LEAVE_EQUALS_THROW__ | 
|         |    713 	test.Next(_L("Trap instrumentation")); | 
|         |    714 	TestTrapInstrumentation(); | 
|         |    715 #endif | 
|         |    716  | 
|         |    717 #ifdef __WINS__ | 
|         |    718 	testExceptionsInTrap(); | 
|         |    719 #endif | 
|         |    720  | 
|         |    721 	test.End(); | 
|         |    722 	return(0); | 
|         |    723     } |