diff -r 000000000000 -r a41df078684a kerneltest/e32test/misc/t_destruct_slave.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/misc/t_destruct_slave.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,289 @@ +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// e32test\misc\t_destruct_slave.cpp +// +// + +#define __E32TEST_EXTENSION__ + +#include +#include +#include +#include +#include + +#include "t_destruct.h" + +_LIT(KDynamicDll, "t_destruct_dll2"); + +class TTestObject + { +public: + TTestType iTestType; +public: + TTestObject(); + ~TTestObject(); + }; + +RTest test(_L("t_desruct_slave")); +TThreadId MainThreadId; +TTestObject GlobalObjectWithDestructor; + +void Panic(TInt aReason) + { + User::Panic(_L("t_destruct_slave"), aReason); + } + +TInt ExitThread(TAny*) + { + return KErrNone; + } + +TInt PanicThread(TAny*) + { + Panic(KErrNone); + return KErrNone; + } + +TInt LoopThread(TAny*) + { + // Open handle on dynamic DLL in this thread + RLibrary library; + test_KErrNone(library.Load(KDynamicDll)); + for (;;) + ; + } + +TInt ChildThread(TAny* aArg) + { + TInt testType = (TInt)aArg; + RThread mainThread; + TInt r = mainThread.Open(MainThreadId); + if (r != KErrNone) + return r; + // Open handle on dynamic DLL in this thread + RLibrary library; + test_KErrNone(library.Load(KDynamicDll)); + RThread().Rendezvous(KErrNone); + TRequestStatus status; + mainThread.Logon(status); + User::WaitForRequest(status); + if (mainThread.ExitType() != EExitKill) + return KErrGeneral; + if (mainThread.ExitReason() != KErrNone) + return mainThread.ExitReason(); + mainThread.Close(); + if (testType != ETestRecursive) + { + RMsgQueue messageQueue; + r = messageQueue.OpenGlobal(KMessageQueueName); + if (r != KErrNone) + return r; + r = messageQueue.Send(EMessagePreDestruct); + if (r != KErrNone) + return r; + } + return testType; + } + +TInt PermanentThread(TAny* aArg) + { + TInt testType = (TInt)aArg; + // Open handle on dynamic DLL in this thread + RLibrary library; + TInt r = library.Load(KDynamicDll); + if (r != KErrNone) + return r; + RMsgQueue messageQueue; + r = messageQueue.OpenGlobal(KMessageQueueName); + if (r != KErrNone) + return r; + r = messageQueue.Send(EMessagePreDestruct); + if (r != KErrNone) + return r; + messageQueue.Close(); + User::SetCritical(User::EProcessPermanent); + User::Exit(testType); + return KErrGeneral; + } + +TTestObject::TTestObject() + { + RDebug::Printf("t_destruct_slave constructor called\n"); + RMsgQueue messageQueue; + TInt r = messageQueue.OpenGlobal(KMessageQueueName); + if (r != KErrNone) + Panic(r); + messageQueue.Send(EMessageConstruct); + if (r != KErrNone) + Panic(r); + } + +TTestObject::~TTestObject() + { + RDebug::Printf("t_destruct_slave destructor called\n"); + if (iTestType == ETestRecursive) + { + // Start child thread passing this thread's id + MainThreadId = RThread().Id(); + RThread childThread; + test_KErrNone(childThread.Create(_L("ChildThread"), ChildThread, 4096, NULL, (TAny*)iTestType)); + TRequestStatus status; + childThread.Rendezvous(status); + childThread.Resume(); + + // Wait for child to open handle on this thread + User::WaitForRequest(status); + test_KErrNone(status.Int()); + childThread.Close(); + + // Set this thread non-critical + User::SetCritical(User::ENotCritical); + } + else if (iTestType == ETestDestructorExits) + { + User::Exit(iTestType); + } + + RMsgQueue messageQueue; + TInt r = messageQueue.OpenGlobal(KMessageQueueName); + if (r != KErrNone) + Panic(r); + messageQueue.Send(EMessageDestruct); + if (r != KErrNone) + Panic(r); + } + +TInt E32Main() + { + StaticMain(); + + RBuf cmd; + test_KErrNone(cmd.Create(User::CommandLineLength())); + User::CommandLine(cmd); + + TLex lex(cmd); + TTestType type; + test_KErrNone(lex.Val((TInt&)type)); + GlobalObjectWithDestructor.iTestType = type; + + RMsgQueue messageQueue; + test_KErrNone(messageQueue.OpenGlobal(KMessageQueueName)); + + // Dynamically load DLL with global data + RLibrary library; + test_KErrNone(library.Load(KDynamicDll)); + + switch(type) + { + case ETestMainThreadReturn: + test_KErrNone(messageQueue.Send(EMessagePreDestruct)); + return type; + + case ETestMainThreadExit: + test_KErrNone(messageQueue.Send(EMessagePreDestruct)); + User::Exit(type); + break; + + case ETestChildThreadReturn: + { + // Start child thread passing this thread's id + MainThreadId = RThread().Id(); + RThread childThread; + test_KErrNone(childThread.Create(_L("ChildThread"), ChildThread, 4096, NULL, (TAny*)type)); + TRequestStatus status; + childThread.Rendezvous(status); + childThread.Resume(); + + User::After(1); + + // Wait for child to open handle on this thread + User::WaitForRequest(status); + test_KErrNone(status.Int()); + childThread.Close(); + + // Set this thread non-critical and exit + User::SetCritical(User::ENotCritical); + } + break; + + case ETestOtherThreadExit: + { + RThread childThread; + test_KErrNone(childThread.Create(_L("ChildThread"), ExitThread, 4096, NULL, (TAny*)type)); + childThread.Resume(); + TRequestStatus status; + childThread.Logon(status); + User::WaitForRequest(status); + test_KErrNone(status.Int()); + childThread.Close(); + test_KErrNone(messageQueue.Send(EMessagePreDestruct)); + } + return type; + + case ETestOtherThreadPanic: + { + RThread childThread; + test_KErrNone(childThread.Create(_L("ChildThread"), PanicThread, 4096, NULL, (TAny*)type)); + childThread.Resume(); + TRequestStatus status; + childThread.Logon(status); + User::WaitForRequest(status); + test_KErrNone(status.Int()); + childThread.Close(); + test_KErrNone(messageQueue.Send(EMessagePreDestruct)); + } + return type; + + case ETestOtherThreadRunning: + { + RThread childThread; + test_KErrNone(childThread.Create(_L("ChildThread"), LoopThread, 4096, NULL, (TAny*)type)); + childThread.Resume(); + childThread.Close(); + test_KErrNone(messageQueue.Send(EMessagePreDestruct)); + } + return type; + + case ETestPermanentThreadExit: + { + RThread childThread; + test_KErrNone(childThread.Create(_L("ChildThread"), PermanentThread, 4096, NULL, (TAny*)type)); + childThread.Resume(); + TRequestStatus status; + childThread.Logon(status); + User::WaitForRequest(status); + test_KErrNone(status.Int()); + childThread.Close(); + } + break; + + case ETestRecursive: + test_KErrNone(messageQueue.Send(EMessagePreDestruct)); + break; + + case ETestDestructorExits: + test_KErrNone(messageQueue.Send(EMessagePreDestruct)); + break; + + case ETestLastThreadPanic: + test_KErrNone(messageQueue.Send(EMessagePreDestruct)); + Panic(type); + break; + + default: + test(EFalse); + } + return KErrNone; + }