kerneltest/e32test/misc/t_destruct_slave.cpp
changeset 0 a41df078684a
child 300 1d28c8722707
--- /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 <e32std.h>
+#include <e32std_private.h>
+#include <e32test.h>
+#include <e32debug.h>
+#include <e32msgqueue.h>
+
+#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<TMessage> 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<TMessage> 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<TMessage> 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<TMessage> 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<TMessage> 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;
+	}