// Copyright (c) 1996-2010 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\bench\t_proc1.cpp
// One half of the process relative type test stuff
// Overview:
// Tests the RProcess class, including tests on the heap, process naming, 
// process resumption, process creation and shared chunks. 
// API Information:
// RProcess
// Details:
// - Open a nonexistent process by a process Id and checks for the failure 
// of finding this process.
// - Open a process with invalid name and verify failure results are as expected.
// - Test the closing of processes by calling Kill, Terminate, and Panic methods.
// Verify results are as expected.
// - Create a process and verify the full path name of the loaded executable on 
// which this process is based.
// - Open a process by name, rename the process in a variety of ways and verify 
// the results are as expected.
// - Open a process, assign high, low, and bad priorities, verify the results
// are as expected.
// - Open a process, kill it and verify the results are as expected.
// - Open a process by name based on the file name, verify the results are as 
// expected.
// - Retrieve the process Id and open a handle on it. Create a duplicate process.
// Verify the results are as expected.
// - Find a process using TFindProcess() and open a handle on it. Verify the
// results are as expected.
// - Check chunk sharing between threads and verify results are as expected.
// - Perform a "speed" test where a new thread is created and the thread increments
// a count until stopped. Calculate and display counts per second. Verify results
// are as expected.
// - Verify the ExitReason, ExitType and ExitCatagory when the thread dies.
// - Verify that stopping the process completes existing pending requests with 
// KErrServerTerminated.
// - Verify that the heap was not corrupted by the tests.
// Platforms/Drives/Compatibility:
// All.
// Assumptions/Requirement/Pre-requisites:
// Failures and causes:
// Base Port information:
// 
//

#include <e32test.h>
#include "../mmu/mmudetect.h"
#include "t_proc.h"

LOCAL_D RTest test(_L("T_PROC1"));

const TBufC<67> tooLong=_L("This should return KErrBadName and not crash.......0123456789ABCDEF");
const TBufC<66> notQuiteTooLong=_L("This should return KErrNone and be completely OK..0123456789ABCDEF");
const TBufC<26> bond=_L("Bond, James Bond[00000000]");
const TBufC<16> jamesBond=_L("Bond, James Bond");

RProcess proc;
RProcess proc2;
RProcess proc3;
RProcess proc4;

TName command;
TRequestStatus stat,notStat;

const TInt KKillReason=2563453;
const TInt KTerminateReason=8034255;
const TInt KPanicReason=39365235;

LOCAL_D RSemaphore client;
LOCAL_D TInt speedCount;

class RDisplay : public RSessionBase
	{
public:
	TInt Open();
	TInt Display(const TDesC& aMessage);
	TInt Read();
	TInt Write();
	TInt Stop();
	TInt Test();
	TVersion Version();
	};

TInt RDisplay::Open()
//
// Open the server.
//
	{

	return(CreateSession(_L("Display"),Version(),1));
	}

TInt RDisplay::Display(const TDesC& aMessage)
//
// Display a message.
//
	{

	TBuf<0x10> b(aMessage);
	return(SendReceive(CMyServer::EDisplay,TIpcArgs(&b)));
	}

TInt RDisplay::Read()
//
// Get session to test CSession2::ReadL.
//
	{

	TBuf<0x10> b(_L("Testing read"));
	return(SendReceive(CMyServer::ERead,TIpcArgs(&b)));
	}

TInt RDisplay::Write()
//
// Get session to test CSession2::WriteL.
//
	{

	TBuf<0x10> b;
    TBufC<0x10> c; // Bad descriptor - read only
	TInt r=SendReceive(CMyServer::EWrite,TIpcArgs(&b,&c));
	if (r==KErrNone && b!=_L("It worked!"))
		r=KErrGeneral;
	return r;
	}

TInt RDisplay::Test()
//
// Send a message and wait for completion.
//
	{

	TInt i[4];
	return(SendReceive(CMyServer::ETest,TIpcArgs(&i[0])));
	}

TInt RDisplay::Stop()
//
// Stop the server.
//
	{

	TInt i[4];
	return(SendReceive(CMyServer::EStop,TIpcArgs(&i[0])));
	}

TVersion RDisplay::Version()
//
// Return the current version.
//
	{

	TVersion v(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
	return(v);
	}

LOCAL_C TInt RunPanicThread(RThread& aThread)
	{
	TRequestStatus s;
	aThread.Logon(s);
	TBool jit = User::JustInTime();
	User::SetJustInTime(EFalse);
	aThread.Resume();
	User::WaitForRequest(s);
	User::SetJustInTime(jit);
	return s.Int();
	}

TInt KillProtectedEntry(TAny*)
	{
	proc.Kill(KErrGeneral);
	return KErrGeneral;
	}

TInt createProc2(RProcess& aProcess)
	{
	TFileName filename(RProcess().FileName());
	TInt pos=filename.LocateReverse(TChar('\\'));
	filename.SetLength(pos+1);
	filename+=_L("T_PROC2.EXE");
	TInt r=aProcess.Create(filename, command);
	if (r==KErrNone)
		{
		TFullName fn(aProcess.FullName());
		test.Printf(_L("Created %S\n"),&fn);
		}
	return r;
	}

void simpleTests1()
	{
	test.Next(_L("Open by name"));
	RProcess me;
	TInt r=proc2.Open(me.Name());
	test(r==KErrNone);
	test.Next(_L("Rename"));
	TName initName(me.Name());
	r=User::RenameProcess(jamesBond);
	test(r==KErrNone);
	test(me.Name().Left(26)==bond);
	test(proc2.Name().Left(26)==bond);
	r=User::RenameProcess(tooLong);
	test(r==KErrBadName);
	test(me.Name().Left(26)==bond);
	test(proc2.Name().Left(26)==bond);
	TName* work=new TName(notQuiteTooLong);
	r=User::RenameProcess(*work);
	test(r==KErrNone);
	work->Append(_L("[00000000]"));
	test(me.Name().Length()==KMaxKernelName);
	test(me.Name().Left(KMaxKernelName-4)==*work);
	test(proc2.Name().Length()==KMaxKernelName);
	test(proc2.Name().Left(KMaxKernelName-4)==*work);
	delete work;
	r=User::RenameProcess(_L("T_PROC1"));
	test(r==KErrNone);
	TFullName fn(_L("T_PROC1["));
	TUidType uidType(me.Type());
	TUint32 uid3 = uidType[2].iUid;
	fn.AppendNumFixedWidth(uid3,EHex,8);
	fn.Append(']');
	test(proc2.Name().Left(17)==fn);
	test(me.Name().Left(17)==fn);
	TInt l = initName.Locate('[');
	r=User::RenameProcess(initName.Left(l));
	test(r==KErrNone);
	test(proc2.Name()==initName);
	proc2.Close();
	}

TInt BadPriority(TAny* proc2)
	{
	((RProcess*)proc2)->SetPriority(EPriorityWindowServer);
	return KErrNone; 
	}

void simpleTests2()
	{
	TInt r=proc2.Open(proc.Name());
	test.Next(_L("Mess with Priority"));
	proc.SetPriority(EPriorityHigh);
	test.Printf(_L("%d %d\n"),proc.Priority(),proc2.Priority());
	test(proc.Priority()==EPriorityHigh);
	test(proc2.Priority()==EPriorityHigh);
	proc2.SetPriority(EPriorityLow);
	test(proc.Priority()==EPriorityLow);
	test(proc2.Priority()==EPriorityLow);

	RThread thread;
	r=thread.Create(_L("Bad Priority"),BadPriority,KDefaultStackSize,NULL,&proc2);
	test(r==KErrNone);
	r=RunPanicThread(thread);
	test(r==EBadPriority);
	test(thread.ExitType()==EExitPanic);
	test(thread.ExitReason()==EBadPriority);
	test(thread.ExitCategory()==_L("KERN-EXEC"));
	CLOSE_AND_WAIT(thread);
	test(proc.Priority()==EPriorityLow);
	test(proc2.Priority()==EPriorityLow);
	proc2.Close();
	}

void procTests1()
	{
	test.Next(_L("Test functions"));
    TFileName fileName(proc.FileName());
    test.Printf(fileName);
#ifndef __WINS__
	if(PlatSec::ConfigSetting(PlatSec::EPlatSecEnforceSysBin))
		test(fileName.Mid(1).CompareF(_L(":\\Sys\\Bin\\T_PROC2.EXE"))==0);
	else
		test(fileName.Mid(1).CompareF(_L(":\\System\\Bin\\T_PROC2.EXE"))==0);
#else
	if(PlatSec::ConfigSetting(PlatSec::EPlatSecEnforceSysBin))
		test(fileName.CompareF(_L("Z:\\Sys\\Bin\\T_PROC2.EXE"))==0);
	else
		test(fileName.CompareF(_L("Z:\\System\\Bin\\T_PROC2.EXE"))==0);
#endif
	test(proc.Name().Left(21).CompareF(_L("T_PROC2.EXE[00000000]"))==0);
	test(proc.Priority()==EPriorityForeground);
	test(proc.ExitType()==EExitPending);
	test(proc.ExitReason()==0);
	test(proc.ExitCategory()==KNullDesC);
	}

void procTests2()
	{
	test.Next(_L("Kill and recreate"));
	RProcess proc2;
	TInt r=proc2.Open(proc.Id());
	test(r==KErrNone);
	test(proc2.Handle()!=0);
	proc.Logon(stat);
	proc.Logon(notStat);
	r=proc.LogonCancel(notStat);
	test(r==KErrNone);
	test(notStat==KErrNone);
	proc.Kill(KKillReason);
	User::WaitForRequest(stat);
	test(stat==KKillReason);
	test(proc.ExitType()==EExitKill);
	test(proc.ExitReason()==KKillReason);
	test(proc.ExitCategory()==_L("Kill"));
	proc.Close();
	test(proc.Handle()==0);
	test(proc2.ExitType()==EExitKill);
	test(proc2.ExitReason()==KKillReason);
	test(proc2.ExitCategory()==_L("Kill"));
	CLOSE_AND_WAIT(proc2);
	test(proc2.Handle()==0);
	}

void procTests3()
	{
	TFileName filename(RProcess().FileName());
	TInt pos=filename.LocateReverse(TChar('\\'));
	filename.SetLength(pos+1);
	filename+=_L("T_PROC2.EXE");
	TInt r=proc.Create(filename, command);
	test(r==KErrNone);
	TFullName fn(proc.FullName());
	test.Printf(_L("Created %S\n"),&fn);
	test(proc.FileName().CompareF(filename)==0);
	test(proc.Name().Left(21).CompareF(_L("T_PROC2.EXE[00000000]"))==0);
	test(proc.Priority()==EPriorityForeground);
	test(proc.ExitType()==EExitPending);
	test(proc.ExitReason()==0);
	test(proc.ExitCategory()==KNullDesC);
	}

void procTests4()
	{
	test.Next(_L("Get and open by Id"));
	TProcessId id=proc.Id();
	TProcessId id2=proc.Id();
	test(id==id2);
	TInt r=proc2.Open(proc.Name());
	test(r==KErrNone);
	id2=proc2.Id();
	test(id==id2);
	r=proc3.Open(id);
	test(r==KErrNone);
	id2=proc3.Id();
	test(id==id2);
	proc3.Close();
	if (HaveVirtMem())
		{
		test.Next(_L("Create duplicate"));
		r=createProc2(proc3);
		test(r==KErrNone);
		id2=proc3.Id();
		test(id!=id2);
		test(*(TUint*)&id<*(TUint*)&id2);
		}
	}

void procTests5()
	{
	test.Next(_L("Try to find processes"));
	TFindProcess* findProc=new TFindProcess(_L("T_PROC2*"));
	test(findProc!=NULL);
	TFullName* result=new TFullName;
	test(result!=NULL);
	TInt r=findProc->Next(*result);
	test(r==KErrNone);
	TFullName temp = proc.FullName();
	test(result->CompareF(temp)==0);
	r=findProc->Next(*result);
	test(r==KErrNone);
	test(result->CompareF(proc3.FullName())==0);
	r=findProc->Next(*result);
	test(r==KErrNotFound);
	findProc->Find(_L("T?PROC2*]*"));
	r=findProc->Next(*result);
	test(r==KErrNone);
	test(result->CompareF(temp)==0);
	r=findProc->Next(*result);
	test(r==KErrNone);
	test(result->CompareF(proc3.FullName())==0);
	delete result;
	test.Next(_L("Open by find handle"));
	r=proc4.Open(*findProc);
	test(r==KErrNone);
	TProcessId id=proc3.Id();
	TProcessId id2=proc4.Id();
	test(id==id2);
	delete findProc;
	}

void procTests6()
	{
	test.Next(_L("Kill duplicate"));
	proc3.Logon(stat);
	test(stat==KRequestPending);
	proc4.Kill(12345);
	User::WaitForRequest(stat);
	test(stat==12345);
	}

void createProcess()
//
// Create T_PROC2 and, on the way, do lots of basic tests
//
	{
	test.Start(_L("Create"));
	TInt r=globSem1.CreateGlobal(_L("GlobSem1"), 0);
	test(r==KErrNone);
	r=globSem2.CreateGlobal(_L("GlobSem2"), 0);
	test(r==KErrNone);

	r=createProc2(proc);
	test(r==KErrNone);

	procTests1();

	simpleTests1();
	simpleTests2();

	procTests2();
	procTests3();
	procTests4();
	if (HaveVirtMem())
		{
		procTests5();
		procTests6();
		}

	proc2.Close();
	proc3.Close();
	if (proc4.Handle())
		CLOSE_AND_WAIT(proc4);

	test.Next(_L("Resume"));
	proc.Logon(stat); // logon to process
	proc.Logon(notStat);
	r=proc.LogonCancel(notStat);
	test(r==KErrNone);
	test(notStat==KErrNone);
	test(proc.ExitType()==EExitPending);
	proc.Resume();
	globSem1.Wait(); // wait for T_PROC2 to get started
	test.End();
	}

void murderProcess()
	{
	test.Start(_L("Kill"));
	RProcess process;
	TInt r=createProc2(process);
	test(r==KErrNone);
	TProcessId id=process.Id();
	TProcessId id2=process.Id();
	test(id==id2);
 	TRequestStatus stat;
	process.Logon(stat);
	test(process.ExitType()==EExitPending);
	process.Kill(KKillReason);
	User::WaitForRequest(stat);
	test(stat==KKillReason);
	test(process.ExitType()==EExitKill);
	test(process.ExitReason()==KKillReason);
	test(process.ExitCategory()==_L("Kill"));
	CLOSE_AND_WAIT(process);

	test.Next(_L("Terminate"));
	r=createProc2(process);
	test(r==KErrNone);
	id2=process.Id();
	test(*(TUint*)&id+2==*(TUint*)&id2);	// use 2 ID's each time, one for process, one for thread
	process.Logon(stat);
	test(process.ExitType()==EExitPending);
	process.Terminate(KTerminateReason);
	User::WaitForRequest(stat);
	test(stat==KTerminateReason);
	test(process.ExitType()==EExitTerminate);
	test(process.ExitReason()==KTerminateReason);
	test(process.ExitCategory()==_L("Terminate"));
	CLOSE_AND_WAIT(process);

	test.Next(_L("Panic"));
	r=createProc2(process);
	test(r==KErrNone);
	id2=process.Id();
	test(*(TUint*)&id+4==*(TUint*)&id2);
 	test(process.ExitType()==EExitPending);
	process.Logon(stat);
	process.SetJustInTime(EFalse);	// prevent the process panic from starting the debugger
	process.Panic(_L("BOO!"),KPanicReason);
	User::WaitForRequest(stat);
	test(stat==KPanicReason);
	test(process.ExitType()==EExitPanic);
	test(process.ExitReason()==KPanicReason);
	test(process.ExitCategory()==_L("BOO!"));
	CLOSE_AND_WAIT(process);
	test.End();
	}

void sharedChunks()
	{
	test.Start(_L("Test chunk sharing between threads"));

	test.Next(_L("Create chunk Marmalade"));
	TInt r=0;
	RChunk chunk;
	TInt size=0x1000;
	TInt maxSize=0x5000;
	r=chunk.CreateGlobal(_L("Marmalade"),size,maxSize);
	test(r==KErrNone);
	test.Next(_L("Write 0-9 to it"));
	TUint8* base=chunk.Base();
	for (TInt8 j=0;j<10;j++)
		*base++=j; // write 0 - 9 to the chunk
  	globSem2.Signal(); // T_PROC2 can check the chunk now
	globSem1.Wait();
	chunk.Close(); // now it's ok to kill the chunk

	test.End();
	}

TInt sharedChunks2(TAny* /*aDummy*/)
	{
    RTest test(_L("Shared Chunks 2"));

	test.Title();	
	test.Start(_L("Test chunk sharing between threads"));

	test.Next(_L("Create chunk Marmalade"));
	TInt r=0;
	RChunk chunk;
	TInt size=0x1000;
	TInt maxSize=0x5000;
	r=chunk.CreateGlobal(_L("Marmalade"),size,maxSize);
	test(r==KErrNone);
	test.Next(_L("Write 0-9 to it"));
	TUint8* base=chunk.Base();
	for (TInt8 j=0;j<10;j++)
		*base++=j; // write 0 - 9 to the chunk
  	globSem2.Signal(); // T_PROC2 can check the chunk now
	globSem1.Wait();
	chunk.Close(); // now it's ok to kill the chunk

	test.End();
    return(KErrNone);
	}

TInt speedyThreadEntryPoint(TAny*)
//
// The entry point for the speed test thread.
//
	{
	RDisplay t;
	TInt r=t.Open();
	test(r==KErrNone);
	speedCount=0;
	client.Signal();
	while ((r=t.Test())==KErrNone)
		speedCount++;
	t.Close();
	return r;
	}

TInt BadName(TAny*)
	{
	proc.Open(_L("*"));
	return KErrNone;
	}

TInt sharedHeap(TAny*)
	{
	RTest test2(_L("sharedHeap"));
	test2.Title();
	test2.Start(_L("Shared heap tests"));

	RAllocator* allocator = &User::Allocator();
	test2.Printf(_L("sharedHeap's heap is at %08x\n"), allocator);
	
	TInt size;
	allocator->AllocSize(size);
	test2.Printf(_L("sharedHeap's heap allocsize is %08x\n"),size);

// Press a key only if running the test in manual mode. We will be
// able to ascertain this when RTest has been enhanced.
//	test.Next(_L("Press a key to continue"));
//	test2.Getch();

	test2.End();
	return(KErrNone);
	}

_LIT(KTestProcessNewName,"T_PROC1_NEW.EXE");

TInt DupRenameProcTest(TInt aCall)
	{
	test.Printf(_L("DupRenameProcTest: call %d\n"),aCall);

	TInt r;

	switch(aCall)
		{
	case 1:
		{
		r = User::RenameProcess(KTestProcessNewName);
		test(r==KErrNone);
		TFullName fn(RProcess().FullName());
		test.Printf(_L("Renamed to %S\n"),&fn);
		TInt li = fn.Locate('[');
		TInt ri = fn.Locate(']');
		test(fn.Left(li)==KTestProcessNewName);
		test(fn.Mid(ri+1)==_L("0001"));
		}

	case 0:
		{
		TFileName filename(RProcess().FileName());
		TInt pos=filename.LocateReverse(TChar('\\'));
		filename.SetLength(pos+1);
		filename+=_L("T_PROC1.EXE");
		RProcess pr;
		TBuf16<10> call;
		call.Num(aCall+1);
		r = pr.Create(filename, call);
		TFullName fn(pr.FullName());
		test.Printf(_L("Created %S\n"),&fn);
		TRequestStatus st;
		pr.Logon(st);
		pr.Resume();
		User::WaitForRequest(st);
		CLOSE_AND_WAIT(pr);
		}
		return KErrNone;

	case 2:
		{
		r = User::RenameProcess(KTestProcessNewName);
		test(r==KErrNone);
		TFullName fn(RProcess().FullName());
		test.Printf(_L("Renamed to %S\n"),&fn);
		TInt li = fn.Locate('[');
		TInt ri = fn.Locate(']');
		test(fn.Left(li)==KTestProcessNewName);
		test(fn.Mid(ri+1)==_L("0002"));
		}
		return KErrNone;

	default:
		return KErrArgument;
		}
	}

_LIT(KTestProcessName,"TestName");

void TestProcessRename()
	{
	// Rename the current process with test name
    TInt r = User::RenameProcess(KTestProcessName);
    test(r==KErrNone);
    TName name1 = RProcess().Name();

    // Check new name is correct
    TName name2 = name1;
    name2.SetLength(KTestProcessName().Length());
    test(name2.CompareF(KTestProcessName)==0);
    
    // Rename the process with same test name
    r = User::RenameProcess(KTestProcessName);
    test(r==KErrNone);
    name2 = RProcess().Name();
    test(name1.Compare(name2)==0);  // name should be unchanged
	}

TInt E32Main()
	{
	COMPLETE_POST_BOOT_SYSTEM_TASKS();
	__KHEAP_MARK;

	TBuf16<512> cmd;
	User::CommandLine(cmd);
	if(cmd.Length() && TChar(cmd[0]).IsDigit())
		{
		TInt r = DupRenameProcTest(TUint(TChar(cmd[0])) - '0');
		test(r==KErrNone);
		return 0;
		}

	test.Title();

	test.Start(_L("Testing process stuff 1"));
	TInt r;
	TRequestStatus s;
	test.Next(_L("Creating semaphore"));
	r=client.CreateLocal(0);
	test(r==KErrNone);

	test.Next(_L("Try to open nonexistant process by ID"));
	r=proc.Open(*(TProcessId*)&KMaxTUint);
	test(r==KErrNotFound);

	test.Next(_L("Try to open process with invalid name"));
	RThread thread;
	r=thread.Create(_L("Bad Name"),BadName,KDefaultStackSize,NULL,NULL);
	test(r==KErrNone);
	TRequestStatus threadStat;
	thread.Logon(threadStat);
	TBool justInTime=User::JustInTime();
	User::SetJustInTime(EFalse);
	thread.Resume();
	User::WaitForRequest(threadStat);
	User::SetJustInTime(justInTime);
	test(threadStat==EBadName);
	test(thread.ExitType()==EExitPanic);
	test(thread.ExitReason()==EBadName);
	test(thread.ExitCategory()==_L("KERN-EXEC"));
	CLOSE_AND_WAIT(thread);

	test.Next(_L("Murder processes in different ways"));
	murderProcess();

	test.Next(_L("Create second process"));
	createProcess();

	test.Next(_L("Shared Chunks from main thread"));
	sharedChunks();

	test.Next(_L("Shared chunks from secondary thread"));
	RThread t;
	r=t.Create(_L("Shared chunks 2"),sharedChunks2,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
    test(r==KErrNone);
	t.Logon(s);
	t.Resume();
	User::WaitForRequest(s);
	test(s==KErrNone);
	CLOSE_AND_WAIT(t);

	test.Next(_L("Starting speedy client"));
	RThread speedy;
	r=speedy.Create(_L("Speedy"),speedyThreadEntryPoint,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
	test(r==KErrNone);

	RThread().SetPriority(EPriorityMuchMore);
    speedy.SetPriority(EPriorityNormal);
	TRequestStatus speedyStatus;
	speedy.Logon(speedyStatus);
	speedy.Resume();

	test.Next(_L("Wait for speedy to start"));
	client.Wait();

	globSem1.Wait(); // wait for proc2 to be nice & quiet
	test.Printf(_L("Starting speed test...\n"));
    User::After(300000);
    TInt b=speedCount;
    User::After(3000000);
    TInt n=speedCount;
    test.Printf(_L("Count = %d in 1 second\n"),(n-b)/3);

	test.Next(_L("Tell second process speed tests are done"));
	globSem2.Signal();

	test.Next(_L("Process Logon"));
	User::WaitForRequest(stat);
	const TDesC& cat=proc.ExitCategory();
	test.Printf(_L("Exit category = %S\n"),&cat);
	test.Printf(_L("Exit reason = %x\n"),proc.ExitReason());
	test.Printf(_L("Exit type = %x\n"),proc.ExitType());

	test(stat==KErrNone);
	test(proc.ExitCategory()==_L("Kill"));
	test(proc.ExitReason()==KErrNone);
	test(proc.ExitType()==EExitKill);
	test(notStat==KErrNone);
	test.Next(_L("Test LogonCancel to dead process is ok"));
	r=proc.LogonCancel(stat);
	test(r==KErrGeneral);
	globSem1.Close();
	globSem2.Close();
	client.Close();

	User::WaitForRequest(speedyStatus);
	test(speedyStatus==KErrServerTerminated);
	test(speedy.ExitReason()==KErrServerTerminated);
	test(speedy.ExitType()==EExitKill);
	CLOSE_AND_WAIT(speedy);
	CLOSE_AND_WAIT(proc);

	User::After(5000000);	// wait for MMC session to disappear

	test.Next(_L("Test rename of the processes with duplicate names"));
	r = DupRenameProcTest(0);
	test(r==KErrNone);

    TestProcessRename();

	test.Next(_L("Check for kernel alloc heaven"));
	__KHEAP_MARKEND; 

	test.End();

	return(KErrNone);
	}


