kerneltest/e32test/secure/t_sthread.cpp
changeset 0 a41df078684a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/secure/t_sthread.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,974 @@
+// Copyright (c) 2001-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\secure\t_sthread.cpp
+// Overview:
+// Test the platform security aspects of the RThread class
+// API Information:
+// RThread
+// Details:
+// - Test renaming the current thread and renaming a thread from 
+// another thread. Verify results are as expected.
+// - Test resuming a thread from a different process and from the
+// process that created the thread. Verify results are as expected.
+// - Verify that other processes can not suspend a thread and that the
+// creating process can.
+// - Perform a variety of tests on killing, terminating and panicking
+// a thread. Verify results are as expected.
+// - Test setting thread priority in a variety of ways, verify results
+// are as expected. Includes ensuring real-time priorities are
+// unavailable to processes without capability ProtServ.
+// - Test RequestComplete and RequestSignal on a thread in a variety 
+// of ways, verify results are as expected.
+// - Test SetProcessPriority on a thread in a variety of ways, verify 
+// results are as expected.
+// - Test the Heap, ExceptionHandler, SetExceptionHandler, 
+// ModifyExceptionMask, RaiseException, IsExceptionHandled, 
+// SetProtected and SetSystem methods. Verify results as expected.
+// Platforms/Drives/Compatibility:
+// All.
+// Assumptions/Requirement/Pre-requisites:
+// Failures and causes:
+// Base Port information:
+// 
+//
+
+#include <e32test.h>
+
+LOCAL_D RTest test(_L("T_STHREAD"));
+
+_LIT(KSyncMutex,"T_STHREAD-sync-mutex");
+RMutex SyncMutex;
+
+void Wait()
+	{
+	RMutex syncMutex;
+	if(syncMutex.OpenGlobal(KSyncMutex)!=KErrNone)
+		User::Invariant();
+	syncMutex.Wait();
+	syncMutex.Signal();
+	syncMutex.Close();
+	}
+
+enum TTestProcessFunctions
+	{
+	ETestProcessResume,
+	ETestProcessSuspend,
+	ETestProcessKill,
+	ETestProcessTerminate,
+	ETestProcessPanic,
+	ETestProcessRequestComplete,
+	ETestProcessRequestSignal,
+	ETestProcessPriorityControlOff,
+	ETestProcessPriorityControlOn,
+	ETestProcessSetPriority,
+	ETestProcessSetPrioritiesWithoutProtServ,
+	ETestProcessSetPrioritiesWithProtServ
+	};
+
+#include "testprocess.h"
+
+_LIT(KTestPanicCategory,"TEST PANIC");
+_LIT(KTestThreadName,"TestName");
+
+
+class RTestThread : public RThread
+	{
+public:
+	void Create(TThreadFunction aFunction,TAny* aArg=0);
+	};
+
+volatile TInt TestThreadCount = 0;
+
+TInt TestThreadNull(TAny*)
+	{
+	++TestThreadCount;
+	Wait();
+	return KErrNone;
+	}
+
+void RTestThread::Create(TThreadFunction aFunction,TAny* aArg)
+	{
+	TInt r=RThread::Create(_L("TestThread"),aFunction,KDefaultStackSize,KDefaultStackSize,KDefaultStackSize,aArg);
+	test(r==KErrNone);
+	}
+
+
+// these priorities are available to any process
+void TestSetNormalApplicationPriorities(RThread& aThread)
+	{
+	TThreadPriority priority = aThread.Priority(); // save priority to restore before return
+	aThread.SetPriority(EPriorityAbsoluteVeryLow);
+	test(aThread.Priority()==EPriorityAbsoluteVeryLow);
+	aThread.SetPriority(EPriorityAbsoluteLowNormal);
+	test(aThread.Priority()==EPriorityAbsoluteLowNormal);
+	aThread.SetPriority(EPriorityAbsoluteLow);
+	test(aThread.Priority()==EPriorityAbsoluteLow);
+	aThread.SetPriority(EPriorityAbsoluteBackgroundNormal);
+	test(aThread.Priority()==EPriorityAbsoluteBackgroundNormal);
+	aThread.SetPriority(EPriorityAbsoluteBackground);
+	test(aThread.Priority()==EPriorityAbsoluteBackground);
+	aThread.SetPriority(EPriorityAbsoluteForegroundNormal);
+	test(aThread.Priority()==EPriorityAbsoluteForegroundNormal);
+	aThread.SetPriority(EPriorityAbsoluteForeground);
+	test(aThread.Priority()==EPriorityAbsoluteForeground);
+	aThread.SetPriority(EPriorityAbsoluteHighNormal);
+	test(aThread.Priority()==EPriorityAbsoluteHighNormal);
+	aThread.SetPriority(EPriorityAbsoluteHigh);
+	test(aThread.Priority()==EPriorityAbsoluteHigh);
+	aThread.SetPriority(priority);
+	}
+
+TInt TestThreadSetPriority(TAny* aArg)
+	{
+	RThread thisThread;
+	thisThread.SetPriority((TThreadPriority)(reinterpret_cast<TInt>(aArg)));
+	return KErrNone;
+	}
+
+void TestSetPriorityPanic(TThreadPriority aPriority)
+	{
+	RTestThread thread;
+	TRequestStatus status;
+	thread.Create(TestThreadSetPriority, reinterpret_cast<TAny*>(aPriority));
+	thread.Logon(status);
+	thread.Resume();
+	User::WaitForRequest(status);
+	test(thread.ExitType()==EExitPanic);
+	test(thread.ExitCategory()==_L("KERN-EXEC"));
+	test(thread.ExitReason()==46);
+	CLOSE_AND_WAIT(thread);
+	}
+
+void TestSetPrioritySuccess(TThreadPriority aPriority)
+	{
+	RTestThread thread;
+	TRequestStatus status;
+	thread.Create(TestThreadSetPriority, reinterpret_cast<TAny*>(aPriority));
+	thread.Logon(status);
+	thread.Resume();
+	User::WaitForRequest(status);
+	test(thread.Priority()==aPriority);
+	test(thread.ExitCategory()==_L("Kill"));
+	test(thread.ExitReason()==0);
+	CLOSE_AND_WAIT(thread);
+	}
+
+TInt DoTestProcess(TInt aTestNum,TInt aArg1,TInt aArg2)
+	{
+	RThread thread;
+	TInt r;
+
+	switch(aTestNum)
+		{
+
+	case ETestProcessResume:
+		{
+		r = thread.Open(aArg1);
+		if(r==KErrNone)
+			thread.Resume(); // Should panic us
+		return r;
+		}
+
+	case ETestProcessSuspend:
+		{
+		r = thread.Open(aArg1);
+		if(r==KErrNone)
+			thread.Suspend(); // Should panic us
+		return r;
+		}
+
+	case ETestProcessKill:
+		{
+		r = thread.Open(aArg1);
+		if(r==KErrNone)
+			thread.Kill(999); // Should panic us
+		return r;
+		}
+
+	case ETestProcessTerminate:
+		{
+		r = thread.Open(aArg1);
+		if(r==KErrNone)
+			thread.Terminate(999); // Should panic us
+		return r;
+		}
+
+	case ETestProcessPanic:
+		{
+		r = thread.Open(aArg1);
+		if(r==KErrNone)
+			thread.Panic(KTestPanicCategory,999); // Should panic us
+		return r;
+		}
+
+	case ETestProcessSetPriority:
+		{
+		r = thread.Open(aArg1);
+		if(r==KErrNone)
+			thread.SetPriority((TThreadPriority)aArg2);
+		return r;
+		}
+
+	case ETestProcessRequestComplete:
+		{
+		r = thread.Open(aArg1);
+		if(r==KErrNone)
+			{
+			// use a local request status because Thread::RequestComplete is
+			// implemented to write to it in our context
+			TRequestStatus myStatus;
+			TRequestStatus* status = &myStatus;
+			thread.RequestComplete(status,KErrNone);
+			}
+		return r;
+		}
+
+	case ETestProcessRequestSignal:
+		{
+		r = thread.Open(aArg1);
+		if(r==KErrNone)
+			thread.RequestSignal();
+		return r;
+		}
+
+	case ETestProcessPriorityControlOn:
+		User::SetPriorityControl(ETrue);
+		// fall through...
+	case ETestProcessPriorityControlOff:
+		RProcess::Rendezvous(RThread().Id());
+		Wait();
+		return KErrNone;
+
+	case ETestProcessSetPrioritiesWithoutProtServ:
+		{
+		RThread thread;
+		TestSetNormalApplicationPriorities(thread);
+		TestSetPriorityPanic(EPriorityAbsoluteRealTime1);
+		TestSetPriorityPanic(EPriorityAbsoluteRealTime2);
+		TestSetPriorityPanic(EPriorityAbsoluteRealTime3);
+		TestSetPriorityPanic(EPriorityAbsoluteRealTime4);
+		TestSetPriorityPanic(EPriorityAbsoluteRealTime5);
+		TestSetPriorityPanic(EPriorityAbsoluteRealTime6);
+		TestSetPriorityPanic(EPriorityAbsoluteRealTime7);
+		TestSetPriorityPanic(EPriorityAbsoluteRealTime8);	
+		return KErrNone;
+		}
+		
+	case ETestProcessSetPrioritiesWithProtServ:
+		{
+		RThread thread;
+		TestSetNormalApplicationPriorities(thread);
+		TestSetPrioritySuccess(EPriorityAbsoluteRealTime1);
+		TestSetPrioritySuccess(EPriorityAbsoluteRealTime2);
+		TestSetPrioritySuccess(EPriorityAbsoluteRealTime3);
+		TestSetPrioritySuccess(EPriorityAbsoluteRealTime4);
+		TestSetPrioritySuccess(EPriorityAbsoluteRealTime5);
+		TestSetPrioritySuccess(EPriorityAbsoluteRealTime6);
+		TestSetPrioritySuccess(EPriorityAbsoluteRealTime7);
+		TestSetPrioritySuccess(EPriorityAbsoluteRealTime8);	
+		return KErrNone;
+		}
+
+	default:
+		User::Panic(_L("T_STHREAD"),1);
+		}
+
+	return KErrNone;
+	}
+
+
+
+void TestThreadForPlatformSecurityTrap(TThreadFunction aFunction)
+	{
+	TBool jit = User::JustInTime();
+	TRequestStatus logonStatus;
+	RTestThread thread;
+	thread.Create(aFunction,(TAny*)(TUint)RThread().Id());
+	thread.Logon(logonStatus);
+	User::SetJustInTime(EFalse);
+	thread.Resume();
+	User::WaitForRequest(logonStatus);
+	User::SetJustInTime(jit);
+	test(thread.ExitType()==EExitPanic);
+	test(logonStatus==EPlatformSecurityTrap);
+	CLOSE_AND_WAIT(thread);
+	}
+
+
+void TestProcessForPlatformSecurityTrap(TTestProcessFunctions aFunction)
+	{
+	TRequestStatus logonStatus2;
+	RTestProcess process;
+	process.Create(~0u,aFunction,RThread().Id(),EPriorityAbsoluteLow);
+	process.Logon(logonStatus2);
+	process.Resume();
+	User::WaitForRequest(logonStatus2);
+	test(process.ExitType()==EExitPanic); // Process should have got a Platform Security panic
+	test(logonStatus2==EPlatformSecurityTrap);
+	CLOSE_AND_WAIT(process);
+	}
+
+
+void TestRename()
+	{
+	TName name;
+
+	test.Start(_L("Renaming the current thread"));
+	name = RThread().Name();
+	name.SetLength(KTestThreadName().Length());
+	test(name.CompareF(KTestThreadName)!=0);
+	User::RenameThread(KTestThreadName);
+	name = RThread().Name();
+	name.SetLength(KTestThreadName().Length());
+	test(name.CompareF(KTestThreadName)==0);
+
+
+	test.End();
+	}
+
+
+
+void TestResume()
+	{
+	RTestProcess process;
+	RTestThread thread;
+	TRequestStatus logonStatus;
+	TInt testCount = TestThreadCount;
+
+	test.Start(_L("Try to get another process to resume one we've created"));
+	thread.Create(TestThreadNull);
+	process.Create(~0u,ETestProcessResume,thread.Id());
+	process.Logon(logonStatus);
+	process.Resume();
+	User::WaitForRequest(logonStatus);
+	test(process.ExitType()==EExitPanic); // Process should have got a Platform Security panic
+	test(logonStatus==EPlatformSecurityTrap);
+	User::After(1000000); // Give time for thread to run (if it had been resumed)...
+	test(TestThreadCount==testCount); // it shouldn't have, so count will be unchanged.
+
+	test.Next(_L("Test resuming a thread we've created"));
+	thread.Logon(logonStatus);
+	test(logonStatus==KRequestPending);
+	thread.Resume();
+	User::WaitForRequest(logonStatus);
+	test(logonStatus==KErrNone);
+	test(TestThreadCount==testCount+1); // Thread should have run and incremented the count
+	CLOSE_AND_WAIT(thread);
+	CLOSE_AND_WAIT(process);
+
+	test.End();
+	}
+
+
+
+TInt TestThreadCounting(TAny*)
+	{
+	RThread().SetPriority(EPriorityAbsoluteVeryLow);
+	for(;;)
+		++TestThreadCount;
+	}
+
+TBool IsTestThreadRunning()
+	{
+	 // Thread should have been busy incrementing the count if it is running
+	TInt testCount = TestThreadCount;
+	User::After(100000);
+	if(testCount!=TestThreadCount)
+		return ETrue;
+	User::After(1000000);
+	return testCount!=TestThreadCount;
+	}
+
+void TestSuspend()
+	{
+	RTestProcess process;
+	RTestThread thread;
+	TRequestStatus logonStatus;
+
+	test.Start(_L("Creating a never ending thread..."));
+	thread.Create(TestThreadCounting);
+	thread.Resume();
+	test(IsTestThreadRunning());  // Thread should still be running
+
+	test.Next(_L("Checking other process can't supspend it"));
+	process.Create(~0u,ETestProcessSuspend,thread.Id());
+	process.Logon(logonStatus);
+	process.Resume();
+	User::WaitForRequest(logonStatus);
+	test(process.ExitType()==EExitPanic); // Process should have got a Platform Security panic
+	test(logonStatus==EPlatformSecurityTrap);
+	test(IsTestThreadRunning());  // Thread should still be running
+
+	test.Next(_L("Test suspending a thread in same process"));
+	thread.Logon(logonStatus);
+	thread.Suspend();
+	test(!IsTestThreadRunning()); // Thread should have stopped...
+	test(logonStatus==KRequestPending); // but not have died
+	thread.LogonCancel(logonStatus);
+	User::WaitForRequest(logonStatus);
+	
+	test.Next(_L("Kill thread"));
+	thread.Kill(0);
+	CLOSE_AND_WAIT(thread);
+	CLOSE_AND_WAIT(process);
+
+	test.End();
+	}
+
+
+
+TInt TestThreadKillSelf(TAny* )
+	{
+	RThread().Kill(999);
+	return KErrGeneral;
+	}
+
+TInt TestThreadTerminateSelf(TAny*)
+	{
+	RThread().Terminate(999);
+	return KErrGeneral;
+	}
+
+TInt TestThreadPanicSelf(TAny*)
+	{
+	RThread().Panic(KTestPanicCategory,999);
+	return KErrGeneral;
+	}
+
+void TestKill()
+	{
+	RTestProcess process;
+	RTestThread thread;
+	TRequestStatus logonStatus;
+	TRequestStatus logonStatus2;
+	TBool jit = User::JustInTime();
+
+	// Test RProcess::Kill()
+
+	test.Start(_L("Test killing an un-resumed thread created by us"));
+	thread.Create(TestThreadNull);
+	thread.Logon(logonStatus);
+	thread.Kill(999);
+	User::WaitForRequest(logonStatus);
+	test(thread.ExitType()==EExitKill);
+	test(logonStatus==999);
+	CLOSE_AND_WAIT(thread);
+
+	test.Next(_L("Test killing a resumed thread created by us"));
+	thread.Create(TestThreadNull);
+	thread.Logon(logonStatus);
+	SyncMutex.Wait();
+	thread.Resume();
+	thread.Kill(999);
+	SyncMutex.Signal();
+	User::WaitForRequest(logonStatus);
+	test(thread.ExitType()==EExitKill);
+	test(logonStatus==999);
+	CLOSE_AND_WAIT(thread);
+
+	test.Next(_L("Try killing un-resumed thread not created by self"));
+	thread.Create(TestThreadNull);
+	process.Create(~0u,ETestProcessKill,thread.Id());
+	thread.Logon(logonStatus2);
+	process.Logon(logonStatus);
+	process.Resume();
+	User::WaitForRequest(logonStatus);
+	test(process.ExitType()==EExitPanic); // Process should have got a Platform Security panic
+	test(logonStatus==EPlatformSecurityTrap);
+	test(logonStatus2==KRequestPending); // the thread should still be alive
+	thread.Resume();
+	User::WaitForRequest(logonStatus2);
+	test(logonStatus2==KErrNone);
+	CLOSE_AND_WAIT(thread);
+	CLOSE_AND_WAIT(process);
+
+	test.Next(_L("Try killing resumed thread not created by self"));
+	thread.Create(TestThreadNull);
+	process.Create(~0u,ETestProcessKill,thread.Id());
+	thread.Logon(logonStatus2);
+	process.Logon(logonStatus);
+	SyncMutex.Wait();
+	thread.Resume();
+	process.Resume();
+	User::WaitForRequest(logonStatus);
+	test(process.ExitType()==EExitPanic); // Process should have got a Platform Security panic
+	test(logonStatus==EPlatformSecurityTrap);
+	test(logonStatus2==KRequestPending); // the thread should still be alive
+	SyncMutex.Signal();
+	User::WaitForRequest(logonStatus2);
+	test(logonStatus2==KErrNone);
+	CLOSE_AND_WAIT(thread);
+	CLOSE_AND_WAIT(process);
+
+	test.Next(_L("Test a thread killing itself"));
+	thread.Create(TestThreadKillSelf);
+	thread.Logon(logonStatus);
+	thread.Resume();
+	User::WaitForRequest(logonStatus);
+	test(thread.ExitType()==EExitKill);
+	test(logonStatus==999);
+	CLOSE_AND_WAIT(thread);
+
+	// Test RProcess::Teminate()
+
+	test.Next(_L("Test terminating an un-resumed thread created by us"));
+	thread.Create(TestThreadNull);
+	thread.Logon(logonStatus);
+	thread.Terminate(999);
+	User::WaitForRequest(logonStatus);
+	test(thread.ExitType()==EExitTerminate);
+	test(logonStatus==999);
+	CLOSE_AND_WAIT(thread);
+
+	test.Next(_L("Test terminating a resumed thread created by us"));
+	thread.Create(TestThreadNull);
+	thread.Logon(logonStatus);
+	SyncMutex.Wait();
+	thread.Resume();
+	thread.Terminate(999);
+	SyncMutex.Signal();
+	User::WaitForRequest(logonStatus);
+	test(thread.ExitType()==EExitTerminate);
+	test(logonStatus==999);
+	CLOSE_AND_WAIT(thread);
+
+	test.Next(_L("Try terminating un-resumed thread not created by self"));
+	thread.Create(TestThreadNull);
+	process.Create(~0u,ETestProcessTerminate,thread.Id());
+	thread.Logon(logonStatus2);
+	process.Logon(logonStatus);
+	process.Resume();
+	User::WaitForRequest(logonStatus);
+	test(process.ExitType()==EExitPanic); // Process should have got a Platform Security panic
+	test(logonStatus==EPlatformSecurityTrap);
+	test(logonStatus2==KRequestPending); // the thread should still be alive
+	thread.Resume();
+	User::WaitForRequest(logonStatus2);
+	test(logonStatus2==KErrNone);
+	CLOSE_AND_WAIT(thread);
+	CLOSE_AND_WAIT(process);
+
+	test.Next(_L("Try terminating resumed thread not created by self"));
+	thread.Create(TestThreadNull);
+	process.Create(~0u,ETestProcessTerminate,thread.Id());
+	thread.Logon(logonStatus2);
+	process.Logon(logonStatus);
+	SyncMutex.Wait();
+	thread.Resume();
+	process.Resume();
+	User::WaitForRequest(logonStatus);
+	test(process.ExitType()==EExitPanic); // Process should have got a Platform Security panic
+	test(logonStatus==EPlatformSecurityTrap);
+	test(logonStatus2==KRequestPending); // the thread should still be alive
+	SyncMutex.Signal();
+	User::WaitForRequest(logonStatus2);
+	test(logonStatus2==KErrNone);
+	CLOSE_AND_WAIT(thread);
+	CLOSE_AND_WAIT(process);
+
+	test.Next(_L("Test a thread terminating itself"));
+	thread.Create(TestThreadTerminateSelf);
+	thread.Logon(logonStatus);
+	thread.Resume();
+	User::WaitForRequest(logonStatus);
+	test(thread.ExitType()==EExitTerminate);
+	test(logonStatus==999);
+	CLOSE_AND_WAIT(thread);
+
+	// Test RProcess::Panic()
+
+	test.Next(_L("Test panicking an un-resumed thread created by us"));
+	thread.Create(TestThreadNull);
+	thread.Logon(logonStatus);
+	User::SetJustInTime(EFalse);
+	thread.Panic(KTestPanicCategory,999);
+	User::WaitForRequest(logonStatus);
+	User::SetJustInTime(jit);
+	test(thread.ExitType()==EExitPanic);
+	test(logonStatus==999);
+	CLOSE_AND_WAIT(thread);
+
+	test.Next(_L("Test panicking a resumed thread created by us"));
+	thread.Create(TestThreadNull);
+	thread.Logon(logonStatus);
+	SyncMutex.Wait();
+	thread.Resume();
+	User::SetJustInTime(EFalse);
+	thread.Panic(KTestPanicCategory,999);
+	SyncMutex.Signal();
+	User::WaitForRequest(logonStatus);
+	User::SetJustInTime(jit);
+	test(thread.ExitType()==EExitPanic);
+	test(logonStatus==999);
+	CLOSE_AND_WAIT(thread);
+
+	test.Next(_L("Try panicking un-resumed thread not created by self"));
+	thread.Create(TestThreadNull);
+	process.Create(~0u,ETestProcessPanic,thread.Id());
+	thread.Logon(logonStatus2);
+	process.Logon(logonStatus);
+	process.Resume();
+	User::WaitForRequest(logonStatus);
+	test(process.ExitType()==EExitPanic); // Process should have got a Platform Security panic
+	test(logonStatus==EPlatformSecurityTrap);
+	test(logonStatus2==KRequestPending); // the thread should still be alive
+	thread.Resume();
+	User::WaitForRequest(logonStatus2);
+	test(logonStatus2==KErrNone);
+	CLOSE_AND_WAIT(thread);
+	CLOSE_AND_WAIT(process);
+
+	test.Next(_L("Try panicking resumed thread not created by self"));
+	thread.Create(TestThreadNull);
+	process.Create(~0u,ETestProcessPanic,thread.Id());
+	thread.Logon(logonStatus2);
+	process.Logon(logonStatus);
+	SyncMutex.Wait();
+	thread.Resume();
+	process.Resume();
+	User::WaitForRequest(logonStatus);
+	test(process.ExitType()==EExitPanic); // Process should have got a Platform Security panic
+	test(logonStatus==EPlatformSecurityTrap);
+	test(logonStatus2==KRequestPending); // the thread should still be alive
+	SyncMutex.Signal();
+	User::WaitForRequest(logonStatus2);
+	test(logonStatus2==KErrNone);
+	CLOSE_AND_WAIT(thread);
+	CLOSE_AND_WAIT(process);
+
+	test.Next(_L("Test a thread panicking itself"));
+	thread.Create(TestThreadPanicSelf);
+	thread.Logon(logonStatus);
+	User::SetJustInTime(EFalse);
+	thread.Resume();
+	User::WaitForRequest(logonStatus);
+	User::SetJustInTime(jit);
+	test(thread.ExitType()==EExitPanic);
+	test(logonStatus==999);
+	CLOSE_AND_WAIT(thread);
+
+	// 
+
+	test.End();
+	}
+
+
+//---------------------------------------------
+//! @SYMTestCaseID KBASE-T_STHREAD-0120
+//! @SYMTestCaseDesc Set thread priority
+//! @SYMTestType UT
+//! @SYMREQ historical, enhanced under PREQ955
+//! @SYMTestActions Test setting all thread priority values to threads in this process,
+//!     and in another process, resumed and not.
+//! @SYMTestExpectedResults Confirm can set and get "normal application" thread priorities
+//!     for threads in this process, whether resumed or not. Confirm thread is panicked
+//!     if attempts to set priority of thread in another process. Confirm can set and get
+//!     "real-time" thread priorities if this process has ProtServ capability, and that
+//!     calling thread is panicked if not.
+//! @SYMTestPriority Critical
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void TestSetPriority()
+	{
+	RTestThread thread;
+	RTestProcess process;
+	TRequestStatus logonStatus;
+	TRequestStatus logonStatus2;
+
+	test.Start(_L("Test changing our own threads priority"));
+	TestSetNormalApplicationPriorities(thread);
+
+	test.Next(_L("Test changing priority of un-resumed thread in our process"));
+	thread.Create(TestThreadNull);
+	thread.Logon(logonStatus);
+	TestSetNormalApplicationPriorities(thread);
+
+	test.Next(_L("Test changing priority of resumed thread in our process"));
+	SyncMutex.Wait();
+	thread.Resume();
+	TestSetNormalApplicationPriorities(thread);
+	SyncMutex.Signal();
+	User::WaitForRequest(logonStatus);
+	test(logonStatus==KErrNone);
+	CLOSE_AND_WAIT(thread);
+
+	test.Next(_L("Try changing priority of an un-resumed thread in other process"));
+	thread.Create(TestThreadNull);
+	thread.Logon(logonStatus);
+	thread.SetPriority(EPriorityAbsoluteHigh);
+	process.Create(~0u,ETestProcessSetPriority,thread.Id(),EPriorityAbsoluteLow);
+	process.Logon(logonStatus2);
+	process.Resume();
+	User::WaitForRequest(logonStatus2);
+	test(process.ExitType()==EExitPanic); // Process should have got a Platform Security panic
+	test(logonStatus2==EPlatformSecurityTrap);
+	test(thread.Priority()==EPriorityAbsoluteHigh); // Priority should be unaltered
+
+	test.Next(_L("Try changing priority of a resumed thread in other process"));
+	process.Create(~0u,ETestProcessSetPriority,thread.Id(),EPriorityAbsoluteLow);
+	process.Logon(logonStatus2);
+	SyncMutex.Wait();
+	thread.Resume();
+	process.Resume();
+	User::WaitForRequest(logonStatus2);
+	test(process.ExitType()==EExitPanic); // Process should have got a Platform Security panic
+	test(logonStatus2==EPlatformSecurityTrap);
+	test(thread.Priority()==EPriorityAbsoluteHigh); // Priority should be unaltered
+	SyncMutex.Signal();
+	User::WaitForRequest(logonStatus);
+	test(logonStatus==KErrNone);
+	CLOSE_AND_WAIT(thread);
+
+	test.Next(_L("Test setting thread priorities without ECapabilityProtServ"));
+	process.Create(~(1u<<ECapabilityProtServ), ETestProcessSetPrioritiesWithoutProtServ);
+	process.Run();
+	
+	test.Next(_L("Test setting thread priorities with ECapabilityProtServ"));
+	process.Create(1<<ECapabilityProtServ, ETestProcessSetPrioritiesWithProtServ);
+	process.Run();
+
+	test.End();
+	}
+
+
+TRequestStatus TestRequest;
+
+TInt TestThreadRequestComplete(TAny* aArg)
+	{
+	RThread thread;
+	TInt r = thread.Open((TInt)aArg);
+	if(r==KErrNone)
+		{
+		TRequestStatus* status = &TestRequest;
+		thread.RequestComplete(status,KErrNone);
+		}
+	return r;
+	}
+
+void TestRequestComplete()
+	{
+	RTestThread thread;
+	RTestProcess process;
+	TRequestStatus logonStatus;
+
+	test.Start(_L("Test RequestComplete on thread in current process"));
+	TestRequest = KRequestPending;
+	thread.Create(TestThreadRequestComplete,(TAny*)(TUint)RThread().Id());
+	thread.Logon(logonStatus);
+	thread.Resume();
+	User::WaitForRequest(TestRequest);
+	test(TestRequest==KErrNone);
+	User::WaitForRequest(logonStatus);
+	test(logonStatus==KErrNone);
+	CLOSE_AND_WAIT(thread);
+
+	test.Next(_L("Test RequestComplete on with NULL request pointer"));
+	test(RThread().RequestCount()==0); // No signals
+	TRequestStatus* nullReq = 0;
+	RThread().RequestComplete(nullReq,0);
+	test(RThread().RequestCount()==0); // No signals
+
+	test.Next(_L("Test RequestComplete on thread in different process"));
+	TestRequest = KRequestPending;
+	process.Create(~0u,ETestProcessRequestComplete,RThread().Id(),(TInt)&TestRequest);
+	process.Logon(logonStatus);
+	process.Resume();
+	User::WaitForRequest(logonStatus);
+	test(process.ExitType()==EExitPanic); // Process should have got a Platform Security panic
+	test(logonStatus==EPlatformSecurityTrap);
+	test(TestRequest==KRequestPending);
+	CLOSE_AND_WAIT(process);
+
+	test.End();
+	}
+
+
+
+TInt TestThreadRequestSignal(TAny* aArg)
+	{
+	RThread thread;
+	TInt r = thread.Open((TInt)aArg);
+	if(r==KErrNone)
+		thread.RequestSignal();
+	return r;
+	}
+
+void TestRequestSignal()
+	{
+	RTestThread thread;
+	RTestProcess process;
+	TRequestStatus logonStatus;
+	TInt count;
+
+	test.Start(_L("Test RequestSignal on thread in current process"));
+	thread.Create(TestThreadRequestSignal,(TAny*)(TUint)RThread().Id());
+	thread.Logon(logonStatus);
+	count = RThread().RequestCount();
+	test(count==0); // No signals yet
+	thread.Resume();
+	User::WaitForRequest(logonStatus);
+	test(logonStatus==KErrNone);
+	count = RThread().RequestCount();
+	test(count==1); // We should have been signalled
+	User::WaitForAnyRequest();	// eat signal
+	CLOSE_AND_WAIT(thread);
+
+	test.Next(_L("Test RequestSignal on thread in different process"));
+	process.Create(~0u,ETestProcessRequestSignal,RThread().Id(),0);
+	process.Logon(logonStatus);
+	process.Resume();
+	User::WaitForRequest(logonStatus);
+	test(process.ExitType()==EExitPanic); // Process should have got a Platform Security panic
+	test(logonStatus==EPlatformSecurityTrap);
+	count = RThread().RequestCount();
+	test(count==0); // We shouldn't have been signalled
+	CLOSE_AND_WAIT(process);
+
+	test.End();
+	}
+
+
+
+void TestSetProcessPriority()
+	{
+	RTestThread thread;
+	RTestProcess process;
+	TProcessPriority priority;
+	TRequestStatus rendezvousStatus;
+	TRequestStatus logonStatus;
+	TInt r;
+
+	test.Start(_L("Test changing our own process priority"));
+	priority = process.Priority();
+	thread.SetProcessPriority(EPriorityLow);
+	test(process.Priority()==EPriorityLow);
+	thread.SetProcessPriority(EPriorityBackground);
+	test(process.Priority()==EPriorityBackground);
+	thread.SetProcessPriority(EPriorityForeground);
+	test(process.Priority()==EPriorityForeground);
+	thread.SetProcessPriority(priority);
+
+	test.Next(_L("Try changing other process's priority (no priority-control enabled)"));
+	process.Create(~0u,ETestProcessPriorityControlOff);
+	process.Rendezvous(rendezvousStatus);
+	process.Logon(logonStatus);
+	SyncMutex.Wait();
+	process.Resume();
+	User::WaitForRequest(rendezvousStatus); // Process has started
+	r = thread.Open(rendezvousStatus.Int()); // Process returned Id of main thread as status value
+	test(r==KErrNone);
+	priority = process.Priority();
+	thread.SetProcessPriority(EPriorityLow);
+	test(process.Priority()==priority); // priority shouldn't have changed
+	thread.SetProcessPriority(EPriorityBackground);
+	test(process.Priority()==priority); // priority shouldn't have changed
+	thread.SetProcessPriority(EPriorityForeground);
+	test(process.Priority()==priority); // priority shouldn't have changed
+	test(logonStatus==KRequestPending); // wait for process to end
+	SyncMutex.Signal();
+	User::WaitForRequest(logonStatus);
+	CLOSE_AND_WAIT(thread);
+	CLOSE_AND_WAIT(process);
+
+	test.Next(_L("Try changing other process's priority (priority-control enabled)"));
+	process.Create(~0u,ETestProcessPriorityControlOn);
+	process.Rendezvous(rendezvousStatus);
+	process.Logon(logonStatus);
+	SyncMutex.Wait();
+	process.Resume();
+	User::WaitForRequest(rendezvousStatus); // Process has started
+	r = thread.Open(rendezvousStatus.Int()); // Process returned Id of main thread as status value
+	test(r==KErrNone);
+	priority = process.Priority();
+	thread.SetProcessPriority(EPriorityForeground);
+	test(process.Priority()==EPriorityForeground);
+	thread.SetProcessPriority(EPriorityBackground);
+	test(process.Priority()==EPriorityBackground);
+	thread.SetProcessPriority(EPriorityForeground);
+	test(process.Priority()==EPriorityForeground);
+	thread.SetProcessPriority(EPriorityLow);
+	test(process.Priority()==EPriorityForeground); // should still be foreground priority
+	thread.SetProcessPriority(priority);
+	test(logonStatus==KRequestPending); // wait for process to end
+	SyncMutex.Signal();
+	User::WaitForRequest(logonStatus);
+	CLOSE_AND_WAIT(thread);
+	CLOSE_AND_WAIT(process);
+
+	test.End();
+	}
+
+
+
+GLDEF_C TInt E32Main()
+    {
+	TBuf16<512> cmd;
+	User::CommandLine(cmd);
+	if(cmd.Length() && TChar(cmd[0]).IsDigit())
+		{
+		TInt function = -1;
+		TInt arg1 = -1;
+		TInt arg2 = -1;
+		TLex lex(cmd);
+
+		lex.Val(function);
+		lex.SkipSpace();
+		lex.Val(arg1);
+		lex.SkipSpace();
+		lex.Val(arg2);
+		return DoTestProcess(function,arg1,arg2);
+		}
+
+	test.Title();
+
+	if((!PlatSec::ConfigSetting(PlatSec::EPlatSecProcessIsolation))||(!PlatSec::ConfigSetting(PlatSec::EPlatSecEnforcement)))
+		{
+		test.Start(_L("TESTS NOT RUN - PlatSecProcessIsolation is not enforced"));
+		test.End();
+		return 0;
+		}
+
+	test(SyncMutex.CreateGlobal(KSyncMutex)==KErrNone);
+	
+	test.Start(_L("Test Rename"));
+	TestRename();
+
+	test.Next(_L("Test Resume"));
+	TestResume();
+
+	test.Next(_L("Test Suspend"));
+	TestSuspend();
+
+	test.Next(_L("Test Kill, Panic and Teminate"));
+	TestKill();
+
+	test.Next(_L("Test SetPriority"));
+	TestSetPriority();
+
+	test.Next(_L("Test RequestComplete"));
+	TestRequestComplete();
+
+	test.Next(_L("Test RequestSignal"));
+	TestRequestSignal();
+
+	test.Next(_L("Test SetProcessPriority"));
+	TestSetProcessPriority();
+
+
+	SyncMutex.Close();
+	test.End();
+
+	return(0);
+    }
+