Update contrib.
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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32test\system\t_trap.cpp
16 // Test TRAP, Leave and Assert
18 // TRAP, User::Leave, __ASSERT_DEBUG_NO_LEAVE, __ASSERT_ALWAYS_NO_LEAVE
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:
28 // Assumptions/Requirement/Pre-requisites:
29 // Failures and causes:
30 // Base Port information:
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;
43 //#define __TEST_BREAKPOINT_IN_TRAP__
45 LOCAL_D RTest test(_L("T_TRAP"));
48 LOCAL_C TInt UnLeaveFunction(void)
54 LOCAL_C TInt LeaveFunction(void)
57 User::Leave(KLeaveVal);
61 LOCAL_C TInt RecursiveUnLeave(TInt level)
65 return(KRecursiveUnLeaveVal);
67 return(RecursiveUnLeave(--level));
70 LOCAL_C TInt RecursiveSingleLeave(TInt level)
74 User::Leave(KRecursiveSingleLeaveVal);
76 RecursiveSingleLeave(--level);
80 LOCAL_C TInt RecursiveMultiLeave1(TInt level)
84 TRAP(ret,{if (level==0) User::Leave(level); else ret=RecursiveMultiLeave1(level-1); test(EFalse);})
90 LOCAL_C TInt RecursiveMultiLeave2(TInt level)
96 TRAP(ret,ret=RecursiveMultiLeave2(level-1))
102 LOCAL_C TInt doTrap(TInt aVal)
104 // Nest trap function.
111 TRAP(j,j=doTrap(aVal-1))
117 #ifdef __TEST_BREAKPOINT_IN_TRAP__
124 LOCAL_C void doLeave(TInt aLevel,TInt aVal)
126 // Nest trap with leave function.
131 doLeave(aLevel-1,aVal);
136 LOCAL_C void testTrap()
138 // Test trap functions O.K.
142 test.Start(_L("Trap level 1"));
147 #ifdef __TEST_BREAKPOINT_IN_TRAP__
149 TRAP(i,TRAP(i,bkpt()));
152 test.Next(_L("Trap level n"));
153 for (i=1;i<KMaxDepth;i++)
154 test(doTrap(i)==(i+1));
159 LOCAL_C void testLeave()
161 // Test leave functions O.K.
165 test.Start(_L("Leave level 1"));
168 TRAP(i,User::Leave(2))
171 test.Next(_L("Leave level 2"));
173 TRAP(i,TRAP(i,User::Leave(3)))
176 #ifdef __TEST_BREAKPOINT_IN_TRAP__
177 TRAP(i,TRAP(i,User::Leave(33)); bkpt())
181 test.Next(_L("Leave from nested calls"));
182 for (i=1;i<KMaxDepth;i++)
192 LOCAL_C void testMH(void)
196 TRAP(ret,ret=UnLeaveFunction())
197 test(ret==KUnLeaveVal);
198 TRAP(ret,LeaveFunction())
199 test(ret==KLeaveVal);
201 for(;i<=KMaxDepth;i++)
203 TRAP(ret,ret=RecursiveUnLeave(i))
204 test(ret==KRecursiveUnLeaveVal);
206 for(i=0;i<=KMaxDepth;i++)
208 TRAP(ret,ret=RecursiveSingleLeave(i))
209 test(ret==KRecursiveSingleLeaveVal);
211 for(i=0;i<=KMaxDepth;i++)
213 TRAP(ret,ret=RecursiveMultiLeave1(i))
216 for(i=0;i<=KMaxDepth;i++)
218 TRAP(ret,ret=RecursiveMultiLeave2(i))
223 TInt LeaveNoTrapThread(TAny*)
225 User::Leave(KErrGeneral);
229 void TestLeaveNoTrap()
232 TInt r=thread.Create(_L("Leave without Trap thread"),LeaveNoTrapThread,0x1000,&User::Allocator(),NULL);
236 test(stat==KRequestPending);
237 TBool justInTime=User::JustInTime();
238 User::SetJustInTime(EFalse);
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);
250 EAssertTest_Debug = 1,
251 EAssertTest_Leave = 2,
255 TInt AssertThread(TAny* a)
258 TInt r = f | EAssertTest_Ret;
259 if (f & EAssertTest_Leave)
261 if (f & EAssertTest_Debug)
263 __ASSERT_DEBUG_NO_LEAVE(User::Leave(r));
267 __ASSERT_ALWAYS_NO_LEAVE(User::Leave(r));
272 if (f & EAssertTest_Debug)
274 __ASSERT_DEBUG_NO_LEAVE(RThread().Terminate(r));
278 __ASSERT_ALWAYS_NO_LEAVE(RThread().Terminate(r));
284 TInt _AssertThread(TAny* a)
287 TRAP_IGNORE(s=AssertThread(a));
291 void TestAssert(TInt aTest)
293 test.Printf(_L("Assert %d\n"), aTest);
295 TInt r = t.Create(_L("assert"), &_AssertThread, 0x1000, NULL, (TAny*)aTest);
299 test(s==KRequestPending);
300 TBool jit = User::JustInTime();
301 User::SetJustInTime(EFalse);
303 User::WaitForRequest(s);
304 User::SetJustInTime(jit);
305 TInt exitType = t.ExitType();
306 TInt exitReason = t.ExitReason();
307 const TDesC& exitCat = t.ExitCategory();
309 test.Printf(_L("Exit %d,%d,%S\n"), exitType, exitReason, &exitCat);
310 if (aTest & EAssertTest_Leave)
312 if (aTest & EAssertTest_Debug)
315 test(exitType == EExitPanic);
316 test(exitReason == EUnexpectedLeave);
318 test(exitType == EExitKill);
319 test(exitReason == KErrNone);
324 test(exitType == EExitPanic);
325 test(exitReason == EUnexpectedLeave);
330 test(exitType == EExitTerminate);
331 test(exitReason == (aTest | EAssertTest_Ret));
335 /*============== server for testing exceptions in TRAP implementation ====================*/
338 #include <e32base_private.h>
340 #include "../mmu/mmudetect.h"
342 const TInt KHeapSize=0x2000;
344 _LIT(KServerName,"Display");
346 class CMySession : public CSession2
350 virtual void ServiceL(const RMessage2& aMessage);
353 class CMyServer : public CServer2
358 CMyServer(TInt aPriority);
359 static CMyServer* New(TInt aPriority);
360 virtual CSession2* NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const;//Overloading
363 class RDisplay : public RSessionBase
367 void Read(TRequestStatus& aStatus);
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;
380 CMySession::CMySession()
383 CMyServer* CMyServer::New(TInt aPriority)
385 // Create a new CMyServer.
388 return new CMyServer(aPriority);
391 CMyServer::CMyServer(TInt aPriority)
395 : CServer2(aPriority)
398 CSession2* CMyServer::NewSessionL(const TVersion& /*aVersion*/, const RMessage2&) const
400 // Create a new client for this server.
403 return(new(ELeave) CMySession());
406 void CMySession::ServiceL(const RMessage2& aMessage)
408 // Handle messages for this server.
412 switch (aMessage.Function())
414 case CMyServer::ERead:
415 testSvr.Printf(_L("read message received\n"));
423 case CMyServer::EStop:
424 testSvr.Printf(_L("stop message received\n"));
425 CActiveScheduler::Stop();
430 aMessage.Complete(r);
433 TInt RDisplay::Open()
438 return(CreateSession(KServerName,TVersion(),1));
441 void RDisplay::Read(TRequestStatus& aStatus)
443 // Get session to test CSession2::ReadL.
446 TBuf<0x10>* bad = (TBuf<0x10> *)(0x30000000);
447 SendReceive(CMyServer::ERead, TIpcArgs(bad), aStatus);
450 TInt RDisplay::Stop()
455 return SendReceive(CMyServer::EStop, TIpcArgs());
458 LOCAL_C TInt serverThreadEntryPoint(TAny*)
460 // The entry point for the server thread.
464 testSvr.Start(_L("Create CActiveScheduler"));
465 CActiveScheduler* pR=new CActiveScheduler;
467 CActiveScheduler::Install(pR);
469 testSvr.Next(_L("Create CMyServer"));
470 CMyServer* pS=CMyServer::New(0);
473 testSvr.Next(_L("Start CMyServer"));
474 TInt r=pS->Start(KServerName);
475 testSvr(r==KErrNone);
477 testSvr.Next(_L("Signal to client that we have started"));
480 testSvr.Next(_L("Start CActiveScheduler"));
481 CActiveScheduler::Start();
483 testSvr.Next(_L("Exit server"));
491 test.Next(_L("Creating client semaphore"));
492 TInt r=client.CreateLocal(0);
495 test.Next(_L("Creating server semaphore"));
496 r=server.CreateLocal(0);
499 test.Next(_L("Creating server thread"));
501 r=server.Create(_L("Server"),serverThreadEntryPoint,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
503 server.SetPriority(EPriorityMore);
505 test.Next(_L("Resume server thread"));
509 test.Next(_L("Wait for server to start"));
512 test.Next(_L("Connect to server"));
519 test.Next(_L("Stop server"));
520 TInt r=display.Stop();
523 test.Next(_L("Close connection"));
526 test.Next(_L("Close all"));
531 /*============== end of server for testing exceptions in TRAP implementation ====================*/
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;
541 TInt TrapNoLeave = 0;
542 TInt TrapLeave = 123;
545 // This is mostly for the benefit of WINS, where Win32 exceptions
546 // have a nasty habit of interacting badly with C++ exceptions
549 void TestExcInInstrumentation()
551 TRequestStatus status;
552 display.Read(status);
553 test(status.Int() == KRequestPending);
559 test(message->Read(0,buf) == KErrBadDescriptor);
563 User::WaitForRequest(status);
564 test(status.Int() == KErrNone);
567 void TestTrapInstrumentation()
571 test.Start(_L("TRAPD No Leave"));
572 TRAPD(r,User::LeaveIfError(0));
574 test(TrapLeave==123);
576 test(TrapNoLeave==1);
578 test.Next(_L("TRAP No Leave"));
579 TRAP(r,User::LeaveIfError(0));
581 test(TrapLeave==123);
583 test(TrapNoLeave==2);
585 test.Next(_L("TRAP_IGNORE No Leave"));
586 TRAP_IGNORE(User::LeaveIfError(0));
588 test(TrapLeave==123);
589 test(TrapNoLeave==3);
591 test.Next(_L("TRAPD Leave"));
592 TRAPD(r2,User::LeaveIfError(-999));
594 test(TrapLeave==-999);
596 test(TrapNoLeave==3);
598 test.Next(_L("TRAP Leave"));
599 TRAP(r2,User::LeaveIfError(-666));
601 test(TrapLeave==-666);
603 test(TrapNoLeave==3);
605 test.Next(_L("TRAP_IGNORE Leave"));
606 TRAP_IGNORE(User::LeaveIfError(-333));
608 test(TrapLeave==-333);
609 test(TrapNoLeave==3);
611 test.Next(_L("Leave"));
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)
626 volatile TInt* volatile Q;
627 const TInt A[] = {17,19,23,29,31,37,41,43,47,53};
629 void ExceptionHandler(TExcType)
632 for (; *sp!=0xfacefeed; --sp) {}
633 *sp = (TUint32)(Q++);
636 __NAKED__ TInt GetNext()
639 _asm mov eax, 0facefeedh
644 void testExceptionsInTrap()
648 User::SetExceptionHandler(&ExceptionHandler, 0xffffffff);
649 Q = (volatile TInt* volatile)A;
656 TRAP(i,TRAP(i,r=GetNext()));
659 TRAP(i, TRAP(i,User::Leave(271));r=GetNext(); );
662 TRAP(i, TRAP(i, TRAP(i,User::Leave(487));r=GetNext(); ); );
666 TRAP(i, TRAP(i, TRAP(i, TRAP(i,User::Leave(999));r=GetNext(); ); s=GetNext(); ); );
670 TInt j=-1, k=-1, l=-1;
674 TRAP(i,User::Leave(9991)); \
690 GLDEF_C TInt E32Main()
694 test.Start(_L("Trap"));
697 test.Next(_L("Leave"));
700 test.Next(_L("Assorted"));
703 test.Next(_L("Leave without Trap"));
706 test.Next(_L("Assertions"));
708 TestAssert(EAssertTest_Debug);
709 TestAssert(EAssertTest_Leave);
710 TestAssert(EAssertTest_Leave | EAssertTest_Debug);
712 #ifdef __LEAVE_EQUALS_THROW__
713 test.Next(_L("Trap instrumentation"));
714 TestTrapInstrumentation();
718 testExceptionsInTrap();