kerneltest/e32test/pipe/t_pipe.cpp
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:29:07 +0100
changeset 30 8aab599e3476
parent 0 a41df078684a
child 43 c1f20ce4abcf
permissions -rw-r--r--
Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h) Have multiple extension sections in the bld.inf, one for each version of the compiler. The RVCT version building the tools will build the runtime libraries for its version, but make sure we extract all the other versions from zip archives. Also add the archive for RVCT4.

// Copyright (c) 2002-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\pipe\t_pipe.cpp
// Overview:
// Test pipe mechanism
// API Information:
// RPipe
// Details:
// - Create various leagal and illegal pipe and verify that pipe
// functionality works as stated in requirements.
// - Create Named and UnNamed Pipes and verify.
// - Test Pipes communication in multiprocess , multithreaded , single process
// single threaded environment.
// Platforms/Drives/Compatibility:
// All.
// Assumptions/Requirement/Pre-requisites:
// Refer Pipes design and requirement document.
// 1. SGL.GT0314.202 PREQ1460 Design Doc
// 2. SGL.GT0314.203 PREQ1460 Pipe Functional Specification
// Refer Pipe test specification document.
// 1. SGL.GT0314.601 Pipes_Test_Specifications
// Failures and causes:
// Base Port information:
// MMP File:
// t_pipe.mmp
// 
//

/**
 @STMTestCaseID			KBASE-T_PIPE-0217
 @SYMPREQ				PREQ1460
 @SYMREQ					REQ6141
 @SYMCR					CR0923
 @SYMTestCaseDesc		Pipe functional tests
 @SYMTestPriority		High
 @SYMTestActions			Tests the functionality of the pipe. Success and failure tests are performed.
 @SYMTestExpectedResults	Test should pass
*/

#define __E32TEST_EXTENSION__
#include <e32test.h>
#include <e32svr.h>
#include <e32des8.h>
#include <e32des8_private.h>
#include <e32cmn.h>
#include <e32cmn_private.h>
#include <e32math.h>
#include <hal.h>

#include "RPipe.h"

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


//if the test is to run under the debugger, uncomment the following line



const TInt KHeapSize=0x2000;



// Test Data
_LIT8(KTestData,"Pipe Data To Be Passed");
_LIT8(KTestData1,"P");
_LIT8(KTestData2,"Pipe Data To Be Passed");
_LIT8(KTestData3,"ipe Data To Be Passed");


// Test Pipe Names
_LIT(KPipe1Name,"TestPipe1");
_LIT(KPipe3Name,"TestPipe3");

//Global semaphore name
_LIT(KSemaphoreName,"Semaphore1");

// Pipename of max pipe length 80 Charecters.
_LIT(KMaxPipeName,"abcdefghijklmnopqrstabcdefghijklmnopqrstabcdefghijklmnopqrstabcdefghijklmnopqrst");
// PipeName of max pipe length plus one ,81 charecters
_LIT(KMaxPipeNamePlusOne,"abcdefghijklmnopqrstabcdefghijklmnopqrstabcdefghijklmnopqrstabcdefghijklmnopqrst1");

// Thread Name Constants
_LIT(KThread2Name, "thread2");
_LIT(KThread3Name, "thread3");
_LIT(KThread4Name, "thread4");
_LIT(KThread5Name, "thread5");
_LIT(KReaderThread, "ReaderThread");
_LIT(KWriterThread, "WriterThread");
_LIT(KThread8Name, "thread8");
_LIT(KThread9Name, "thread9");
_LIT(KThread11Name, "thread11");

// Test Process Name Constants
_LIT(KProcessName, "t_pipe2.exe");


// Following class is used to pass thread handle information to different threads.
class TData
	{
public:
	TData(RPipe* aReadEnd, RPipe *aWriteEnd); 
	TData(RPipe* aReadEnd, RPipe *aWriteEnd, const TDesC8* aPipeData, TInt aIterations=1);
	RPipe* iReadEnd;
	RPipe* iWriteEnd;
	const TDesC8* iPipeData;
	TInt iIterations;
	};

TData::TData(RPipe* aReadEnd , RPipe *aWriteEnd)
	:iReadEnd(aReadEnd),iWriteEnd(aWriteEnd), iPipeData(NULL), iIterations(NULL)
	{}

TData::TData(RPipe* aReadEnd , RPipe *aWriteEnd, const TDesC8* aPipeData, TInt aIterations)
	:iReadEnd(aReadEnd),iWriteEnd(aWriteEnd), iPipeData(aPipeData), iIterations(aIterations)
	{}

/**
A utility class for running functions in other threads/processes
*/
class TTestRemote
	{
public:
	virtual TInt WaitForExitL()=0;
	virtual ~TTestRemote()
		{}

	virtual void Rendezvous(TRequestStatus& aStatus) =0;

protected:
	TTestRemote()
		{}

	static TInt RunFunctor(TAny* aFunctor)
		{
		TFunctor& functor = *(TFunctor*)aFunctor;
		functor();
		return KErrNone;
		}

	TRequestStatus iLogonStatus;
	static TInt iCount;
	};
TInt TTestRemote::iCount=0;

class TTestThread : public TTestRemote
	{
public:
	TTestThread(const TDesC& aName, TThreadFunction aFn, TAny* aData, TBool aAutoResume=ETrue)
		{
		Init(aName, aFn, aData, aAutoResume);
		}

	/**
	Run aFunctor in another thread
	*/
	TTestThread(const TDesC& aName, TFunctor& aFunctor, TBool aAutoResume=ETrue)
		{
		Init(aName, RunFunctor, &aFunctor, aAutoResume);
		}

	~TTestThread()
		{
		//RTest::CloseHandleAndWaitForDestruction(iThread);
		iThread.Close();
		}

	void Resume()
		{
		iThread.Resume();
		}

	/**
	If thread exited normally, return its return code
	Otherwise, leave with exit reason
	*/
	virtual TInt WaitForExitL()
		{
		User::WaitForRequest(iLogonStatus);
		const TInt exitType = iThread.ExitType();
		const TInt exitReason = iThread.ExitReason();

		__ASSERT_ALWAYS(exitType != EExitPending, User::Panic(_L("TTestThread"),0));

		if(exitType != EExitKill)
			User::Leave(exitReason);

		return exitReason;
		}

	virtual void Rendezvous(TRequestStatus& aStatus)
		{
		iThread.Rendezvous(aStatus);
		}

private:
	void Init(const TDesC& aName, TThreadFunction aFn, TAny* aData, TBool aAutoResume)
		{
		TKName name(aName);
		name.AppendFormat(_L("-%d"), iCount++);	
		TInt r=iThread.Create(name, aFn, KDefaultStackSize, KHeapSize, KHeapSize, aData);
		User::LeaveIfError(r);
		
		iThread.Logon(iLogonStatus);
		__ASSERT_ALWAYS(iLogonStatus == KRequestPending, User::Panic(_L("TTestThread"),0));

		if(aAutoResume)
			iThread.Resume();
		}



	RThread iThread;
	};


/**
Non blocking reads, verifying data as expected
*/
TInt TestThread2(TAny* aData)
	{
	RTest test(_L("t_pipe_t2"));

	test.Start(_L("Thread 2"));
	test.Printf(_L("THREAD 2 called by TestMultiThreadNamedPipes And TestMultiThreadUnNamedPipes\n"));
	
	TBuf8<50>		cPipeReadData;
	TInt 			ret,readsize;
	


	TData& data = *(TData *)aData; 					// aData will have pipe handles and size.


	test.Next(_L("PIPE TEST:Thread 2-1 Read 1 byte of data from the pipe : Test for success\n"));
	readsize = 1;
		
	ret = data.iReadEnd->Read(cPipeReadData ,readsize);
	test_Equal(readsize, ret);


	test.Next(_L("PIPE TEST:Thread 2-2 Validate 1 byte received is correct\n"));
	ret = cPipeReadData.Compare(KTestData1);
	test_KErrNone(ret);


	test.Next(_L("PIPE TEST:Thread 2-3 Read remaining data from the pipe\n"));
	readsize = 21;
	ret = data.iReadEnd->Read(cPipeReadData , readsize);
	test_Equal(readsize, ret);

	test.Next(_L("PIPE TEST:Thread 2-4 Validate received data\n"));
	ret = cPipeReadData.Compare(KTestData3);
	test_KErrNone(ret);
	
	test.End();
	test.Close();
	return KErrNone;


}
/****************************************************************************
	This function is used as thread to test Unnamed pipes.
	TestMultiThreadUnNamedPipes() will use this function.
	TestMultiThreadNamedPipes() will use this function.
	@aData 			: Used to pass the pipe and handle its size information.

	Return Value	: TInt

******************************************************************************/
TInt TestThread3(TAny* aData) {

	
	TInt 				ret, aWriteSize;

	TBufC8<50> 			cTestData3(KTestData2); 	// Test Data

	
	
	TData& data = *(TData *)aData; 					// aData will have pipe handles and size.
	RTest test(_L("t_pipe_t3"));

	test.Start(_L("Thread 3"));
	
	test.Printf(_L(" THREAD 3 called by TestMultiThreadNamedPipes And TestMultiThreadUnNamedPipes\n"));
		
	test.Next(_L("PIPE TEST:Thread 3-1 Call Write blocking and write data\n"));
	
	// Call Writeblocking function. Write one byte of data.
		
	aWriteSize = cTestData3.Length();
	ret = data.iWriteEnd->WriteBlocking(cTestData3,aWriteSize);
	test_Equal(aWriteSize, ret);
	
	// Call Writeblocking function. Write aSize bye data.

	// Write data so that pipe get filled.
	test.Next(_L("PIPE TEST:Thread 3-2 Write data till pipe is filled up \n"));
	ret = data.iWriteEnd->WriteBlocking(cTestData3,aWriteSize);
	test_Equal(aWriteSize, ret);
	
	test.End();
	test.Close();
	return KErrNone;
}
/****************************************************************************
	This function is used as thread to test Unnamed pipes.
	TestMultiThreadUnNamedPipes() will use this function.

	@aData 			: Used to pass the pipe and handle its size information.

	Return Value	: TInt

******************************************************************************/
//TRequestStatus			stat1;
TInt TestThread4(TAny* aData) {

	TData& data = *(TData *)aData; 					// aData will have pipe handles and size.
	TRequestStatus			stat1;
	TBuf8<150>				cPipeReadData;
	TInt					ret;
	RTest test(_L("t_pipe_t4"));
	test.Start(_L("Thread 4"));
	
	RSemaphore				sem;					//	Handle to the global semaphore
	ret = sem.OpenGlobal(KSemaphoreName);					// Access to the global semaphore identified by its name.
	test(ret == KErrNone);


	
	test.Printf(_L("Thread 4:Created by TestNotifyMechanismPipes.\n"));
	test.Next(_L("PIPE TEST:Thread 4-1 Register Notify Data available request.\n"));
	data.iReadEnd->NotifyDataAvailable(stat1);
	test_Equal(KRequestPending, stat1.Int());
	sem.Signal(); //signal to say that we have issued notification request
		
	test.Next(_L("PIPE TEST:Thread 4-2 Wait till notified for data. Check for Available.\n"));
	User::WaitForRequest(stat1);
	test ( stat1.Int() == KErrNone);
		
	test.Next(_L("PIPE TEST:Thread 4-3 Read One byte of data from the pipe.\n"));
	sem.Wait();	//wait for signal that 1 byte should be read
	ret = data.iReadEnd->Read(cPipeReadData,1);
	test (ret == 1);
	
	test.Next(_L("PIPE TEST:Thread 4-4 Verify data is correct ?.\n"));
	test (KErrNone == cPipeReadData.Compare(KTestData1));

	test.Next(_L("PIPE TEST:Thread 4-5 Read remaining data from the pipe.\n"));
	ret = data.iReadEnd->Read(cPipeReadData,21);
	test (ret == 21);
	
	
	test.Next(_L("PIPE TEST:Thread 4-6 Verify data is correct ?.\n"));
	test (KErrNone == cPipeReadData.Compare(KTestData3));
	
	sem.Signal();	//signalling to the main thread to continue its operation
	sem.Close();	//closing the handle to the semaphore
	test.End();
	test.Close();

	return KErrNone;

}

/****************************************************************************
	This function is used as thread to test Unnamed pipes.
	TestWaitMechanismPipes() will use this function.

	@aData 			: Used to pass the pipe and handle its size information.

	Return Value	: TInt

******************************************************************************/

TInt TestThread5(TAny* aData) {

	TData& data = *(TData *)aData; 							// aData will have pipe handles and size.
	TRequestStatus			stat1;
	TInt					ret;

	RTest test(_L("t_pipe_t5"));
	
	test.Start(_L("Thread 5"));
	test.Printf(_L("PIPE TEST:Thread 5:Created by TestWaitMechanismPipes.\n"));
	
	test.Next(_L("PIPE TEST:Thread 5-1:Register one more request to wait till open to read. It shall not allow\n"));
	data.iWriteEnd->Wait(KPipe3Name, stat1);
	test (stat1.Int() == KErrInUse);
	data.iWriteEnd->WaitForReader(KPipe3Name, stat1);
	test (stat1.Int() == KErrInUse);


	test.Next(_L("PIPE TEST:Thread 5-2:Open Pipe handle to Read.\n"));
	ret = data.iReadEnd->Open(KPipe3Name,RPipe::EOpenToRead);
	test(ret == KErrNone);
	
	test.End();
	test.Close();
	return KErrNone;
}

/**
The reader thread will wait till there is data in the pipe
and then continuously read till it has read the total length
of the pipe.
*/
TInt ReaderThread(TAny* aData) {
// Read data from Pipe
	RTest test(KReaderThread);
	test.Title();
	test.Start(_L("Reader Thread"));

	TData& data = *(TData *)aData;
	TBuf8<10> pipeReadData;
	
	const TInt sizeToRead = data.iReadEnd->MaxSize(); //attempt to read everything from pipe
	TRequestStatus status(KErrGeneral);
	
	//do read in loop in case thread is notified before pipe is full
	TInt totalDataRead=0;
	do
		{
		data.iReadEnd->NotifyDataAvailable(status);
		test.Printf(_L("notify data request status is %d\n"), status.Int());
		if(status==KRequestPending)
			User::WaitForRequest(status);
		test(status==KErrNone);
		test.Printf(_L("ready to read data\n"), status.Int());

		const TInt sizeRead = data.iReadEnd->Read(pipeReadData, sizeToRead);
		test.Printf(_L("Read %d bytes from pipe\n"), sizeRead);
		test(sizeRead>0);
		totalDataRead+=sizeRead;
		} 
	while(totalDataRead<sizeToRead);

	test(totalDataRead==sizeToRead);
	test.End();
	test.Close();

	return KErrNone;
}

_LIT8(KTestDataNum1 , "12345");
_LIT8(KTestDataNum , "1234567890");



/**
Write into pipe to completely fill it.
*/
TInt WriterThread(TAny* aData)
	{
// Write data to pipe
	RPipe* writeEnd = static_cast<TData*>(aData)->iWriteEnd;
	RTest test(_L("WriterThread"));
	test.Start(_L("WriterThread"));
	writeEnd->Flush(); //make sure pipe is empty
	const TInt sizeToWrite = writeEnd->MaxSize();
	test.Printf(_L("Writing %d bytes in to pipe\n"), sizeToWrite);
	TInt length=writeEnd->WriteBlocking(KTestDataNum1,sizeToWrite);
	test(length==sizeToWrite);
	test.End();
	test.Close();
	return KErrNone;
	}

/**
The FlusherThread waits till the supplied pipe
is full before flushing it. 
*/
TInt FlusherThread(TAny* aData)
	{
	TData& data = *(TData *)aData; 							// aData will have pipe handles and size.
	
	//wait for pipe to fill, then flush
	TRequestStatus status;
	const TInt maxSize=data.iReadEnd->MaxSize();
	do
		{	
		data.iReadEnd->NotifyDataAvailable(status);
		if(status==KRequestPending)
			User::WaitForRequest(status);
		if(status!=KErrNone)
			return status.Int();
		} while(data.iReadEnd->Size()<maxSize);
	data.iReadEnd->Flush();
	return KErrNone;
	}

/****************************************************************************
	This function is used as thread to test Unnamed pipes.
	TestWaitMechanismPipes() will use this function.

	@aData 			: Used to pass the pipe and handle its size information.

	Return Value	: TInt

******************************************************************************/
TInt	CloseFlag;

TInt TestThread9(TAny* aData) {

	TData& data = *(TData *)aData; 							// aData will have pipe handles and size.
	
	if (CloseFlag == 1)
	data.iReadEnd->Close();
	if (CloseFlag == 0)
	data.iWriteEnd->Close();
	
			
	return 0;
	}

/**
The test will create 2 threads running this function. They will
race to placing the blocking read request. The first
will succeed and wait, the second will write to pipe
*/
TInt ReadBlockThenWrite(TAny* aData) {

	TData& data = *(TData *)aData; 							// aData will have pipe handles and size.
	TBuf8<10>		cReadData;
	RTest test(_L("Concurrent blocking read"));
	test.Start(_L("Call blocking read on pipe\n"));

	TInt ret = data.iReadEnd->ReadBlocking(cReadData,5);
	if(ret == KErrNone)
		{
		test_KErrNone(cReadData.Compare(KTestDataNum1));
		}

	if(ret == KErrInUse)
		{
		test.Next(_L("Other thread beat us - write to pipe so it may proceed"));
		TInt write = data.iWriteEnd->Write(KTestDataNum,5);
		test_Equal(5, write);
		}
	
	test.End();
	test.Close();
				
	return ret;
}

/**
The test will create 2 threads running this function. They will
race to placing the blocking write request. The first
will succeed and wait, the second will read from pipe
*/
TInt WriteBlockThenRead(TAny* aData) {

	TData& data = *(TData *)aData; 							// aData will have pipe handles and size.
	TBuf8<10>		cReadData;
	RTest test(_L("Concurrent blocking write"));
	test.Start(_L("test writing blocked pipe\n"));

	TInt ret = data.iWriteEnd->WriteBlocking(KTestDataNum,10);
	if(ret == KErrInUse)
		{
		test.Next(_L("The other thread beat us - read from pipe so it may proceed"));
		TInt read = data.iReadEnd->Read(cReadData,5);
		test_Equal(5, read);
		test_KErrNone(cReadData.Compare(KTestDataNum1));
		}

	test.End();
	test.Close();
				
	return ret;
}

/****************************************************************************
	This function is used as thread to test Unnamed pipes.
	TestWaitMechanismPipes() will use this function.

	@aData 			: Used to pass the pipe and handle its size information.

	Return Value	: TInt

******************************************************************************/

TInt TestThread11(TAny* aData) {

	TData& data = *(TData *)aData; 							// aData will have pipe handles and size.
	TRequestStatus			stat1;
	TBufC<50>				cPipeName(KPipe3Name);			// Descriptor to hold data for Writing.
	TInt					ret;
	RTest test(_L("t_pipe_t11"));

	test.Start(_L("PIPE TEST:Thread 11:Created by TestWaitMechanismPipes.\n"));

	test.Next(_L("PIPE TEST:Thread 11-1:Register one more request to wait till open to read. It shall not allow\n"));
	data.iReadEnd->WaitForWriter(cPipeName, stat1);
	test_Equal(KErrInUse, stat1.Int());


	test.Next(_L("PIPE TEST:Thread 11-2:Open Pipe handle to write.\n"));
	ret = data.iWriteEnd->Open(cPipeName,RPipe::EOpenToWrite);
	test_KErrNone(ret);
	
	test.End();
	test.Close();
	return KErrNone;
}

/****************************************************************************
	This is a function to test Named/UnNamed pipes Performace.
	Check the functionality of following library functions
		-
		-



******************************************************************************/
/**
	- test that WriteBlocking unblocks
		- when data is read
		- whed date is flushed
	- test that notify data available request is completed as data is read
	- test that ReadBlocking unblocks
	- test that data available notification works

*/
void TestBlockingAndNotify() {
		
		TRequestStatus	stat1;
		RPipe		aReader,aWriter;
		TInt		aSize,ret;
		TBufC8<10>	cPipeTestDataNum(KTestDataNum);

		TBuf8<10>	cReadData;
		
		
		aSize = 5;
		ret = RPipe::Create(	aSize,
								aReader,
								aWriter,
								EOwnerProcess, //
								EOwnerProcess //
							 ); 
		test_KErrNone(ret);

		TData data(	&aReader, &aWriter);

		{
		TTestThread readerThread(KReaderThread, ReaderThread, &data);

		test.Start(_L("Test that WriteBlock unblocks as data is read from pipe\n"));
		ret = aWriter.WriteBlocking(cPipeTestDataNum,10);
		test(ret == 10);
		test(aWriter.Size()==5);
		aWriter.Flush();
		test(aWriter.Size()==0);

		ret = readerThread.WaitForExitL();
		test_KErrNone(ret);
		}

		{
		TTestThread flusherThread(KThread8Name,	FlusherThread, &data);
		test.Next(_L("Test that WriteBlock unblocks as data is flushed from read end of pipe\n"));
		
		ret = aWriter.WriteBlocking(cPipeTestDataNum,10);
		test (ret == 10);
		ret = flusherThread.WaitForExitL();
		test_KErrNone(ret);
		}
		
		test.Next(_L("Test that NotifyDataAvailable request is completed as data is read from pipe\n"));
		
		aWriter.NotifySpaceAvailable(aSize,stat1);
		test(stat1==KRequestPending);
		
		{
		TTestThread readerThread2(KReaderThread, ReaderThread, &data);
		
		User::WaitForRequest(stat1);
		test(stat1==KErrNone);
	
		ret = readerThread2.WaitForExitL();
		test_KErrNone(ret);
		}

		aReader.Flush();

		test.Next(_L("PIPE TEST: Test that ReadBlocking unblocks\n"));
		{
		TTestThread writeThread(KWriterThread, WriterThread, &data);

		ret = aReader.ReadBlocking(cReadData,5);		
		test(ret == 5);

		ret = writeThread.WaitForExitL();
		test_KErrNone(ret);
		}
		
		test.Next(_L("PIPE TEST: Test NotifyDataAvailable\n"));
		aReader.Flush();
		aReader.NotifyDataAvailable(stat1);
		test(stat1==KRequestPending);

		{	
		TTestThread writeThread2(KWriterThread,WriterThread, &data);

		User::WaitForRequest(stat1);		
		test(stat1==KErrNone);

		aReader.Flush();

		ret = writeThread2.WaitForExitL();
		test_KErrNone(ret);
		}	
		test.Next(_L("PIPE TEST: Test reading from pipe closed by the writer\n"));

		CloseFlag = 0; // 0 Close Write Handle	
		//CloseFlag = 1; // 1 Close Read Handle							
		test.Next(_L("PIPE TEST: TestBlockingAndNotify 10.6\n"));
		TTestThread closeThread(KThread9Name, TestThread9, &data);

		ret = closeThread.WaitForExitL();
		test_KErrNone(ret);

		ret = aReader.ReadBlocking(cReadData,5);
		test_Equal(KErrNotReady, ret);
				
		aWriter.Close();
		aReader.Close();
		aSize = 5;
		ret = RPipe::Create(	aSize,
								aReader,
								aWriter,
								EOwnerProcess, //
								EOwnerProcess //
							 ); 
		test_KErrNone(ret);

		TData data1(&aReader,&aWriter);
				
		
		//CloseFlag = 0; // 0 Close Write Handle	
		CloseFlag = 1; // 1 Close Read Handle							
		test.Printf(_L("PIPE TEST: TestBlockingAndNotify 10.7\n"));
		TTestThread closeThread2(KThread9Name, TestThread9, &data1);
		ret = aWriter.WriteBlocking(cPipeTestDataNum,10);
		test_Equal(KErrNotReady, ret);

		ret = closeThread2.WaitForExitL();
		test_KErrNone(ret);
		
		aWriter.Close();
		aReader.Close();

		test.End();
}


/****************************************************************************
	TestPipesPermissionCheck	:
			This function is used to test Permission and Access related
			Errors of Pipes API.
			APIs tested are Define , Create , Destroy , Read and Write.
			

******************************************************************************/
// Different pipes for different capability , VID values.
_LIT(KPipeName2, "PipeWithNoCap");
_LIT(KPipeName3, "PipeWithNoCapVID");
_LIT(KPipeName4, "PipeWithRWCap");
_LIT(KPipeName5, "PipeWithComDDCap");
_LIT(KPipeName6, "PipeWithRWComDDCap");
_LIT(KPipeName7, "PipeWithRWComDDCapVID");
_LIT(KPipeName8, "PipeWithRWRUCap");

// Different processes with different capability , VID  values.
_LIT(KProcessNoCap, "t_pipe3.exe");
_LIT(KProcessRCap, "t_pipe5.exe");

// My VID and SID
_LIT_VENDOR_ID(MyVID,0x70000001);

void TestPipesPermissionCheck() {

		RProcess			proc;
		TInt 				ret;
			
		// Define TSecurity objects with different capabilities and VID .
		TSecurityPolicy 	NoCapVID(MyVID,ECapability_None,ECapability_None,ECapability_None);
		TSecurityPolicy 	RWCap(ECapabilityReadDeviceData,ECapabilityWriteDeviceData);
		TSecurityPolicy 	ComDDCap(ECapabilityCommDD);
		TSecurityPolicy 	RWComDDCap(ECapabilityReadDeviceData,ECapabilityCommDD,ECapabilityWriteDeviceData);
		TSecurityPolicy 	RWComDDCapVID(MyVID,ECapabilityCommDD,ECapabilityReadDeviceData,ECapabilityWriteDeviceData);
		TSecurityPolicy 	RWRUCap(ECapabilityReadUserData,ECapabilityReadDeviceData,ECapabilityWriteDeviceData);

		// Define Named pipes with No Cap , combination of Cap and VID 
		
		TInt 	aSize = 10;
		ret = RPipe::Define(KPipeName2, aSize);
		test (ret == KErrNone);
		ret = RPipe::Define(KPipeName3, aSize,NoCapVID);
		test (ret == KErrNone);
		ret = RPipe::Define(KPipeName4, aSize,RWCap);
		test (ret == KErrNone);
		ret = RPipe::Define(KPipeName5, aSize,ComDDCap);
		test (ret == KErrNone);
		ret = RPipe::Define(KPipeName6, aSize,RWComDDCap);
		test (ret == KErrNone);
		ret = RPipe::Define(KPipeName7, aSize,RWComDDCapVID);
		test (ret == KErrNone);
		ret = RPipe::Define(KPipeName8, aSize,RWRUCap);
		test (ret == KErrNone);
		
		//Lets see who can use pipes. Check for Permissions and Access
		test.Next(_L("PIPE TEST:8.1	Create Process with No Cap t_pipe3.exe\n"));
		ret = proc.Create	(
								KProcessNoCap,			// Launch t_pipe3.exe process
					 			KNullDesC				// No arguments passed to t_pipe3.exe
					 		);

		if (ret != KErrNone) 
		{
			test.Printf(_L(" ***** t_pipe3.exe could not start ****"));
		}
		test_KErrNone(ret);
		test.Printf(_L("Process Created successfully"));
		
		TRequestStatus procLogon;
		proc.Logon(procLogon);
		test(procLogon==KRequestPending);
		proc.Resume();
		User::WaitForRequest(procLogon);
		proc.Close();
		
		// Lets see what happens with Read Capability.
		test.Next(_L("PIPE TEST:8.2	Create Process with Read-Write-CommDD Cap t_pipe5.exe\n"));
		ret = RPipe::Define(KPipeName2, aSize);
		test_KErrNone(ret);
		ret = RPipe::Define(KPipeName3, aSize,NoCapVID);
		test_KErrNone(ret);
	
		ret = proc.Create	(
								KProcessRCap,			// Launch t_pipe3.exe process
					 			KNullDesC				// No arguments passed to t_pipe3.exe
					 		);

		if (ret != KErrNone) 
		{
			test.Printf(_L(" ***** t_pipe5.exe could not start ****"));
		}
		test_KErrNone(ret);
		test.Printf(_L("Process Created successfully"));
		proc.Logon(procLogon);
		test(procLogon==KRequestPending);
		proc.Resume();
		User::WaitForRequest(procLogon);
		proc.Close();
		
		//the t_pipe5.exe process should destroy most of these
		//but we call destroy again to verify this
		ret = RPipe::Destroy (KPipeName2);
		test_Equal(KErrNotFound, ret);
		ret = RPipe::Destroy (KPipeName3);
		test_KErrNone(ret); //KPipeName3 is not destroyed by the other process.
		ret = RPipe::Destroy (KPipeName4);
		test_Equal(KErrNotFound, ret);
		ret = RPipe::Destroy (KPipeName5);
		test_Equal(KErrNotFound, ret);
		ret = RPipe::Destroy (KPipeName6);
		test_Equal(KErrNotFound, ret);
		ret = RPipe::Destroy (KPipeName7);
		test_KErrNone(ret); //t_pipe5.exe does not have permission to delete
		ret = RPipe::Destroy (KPipeName8);
		test_KErrNone(ret); //t_pipe5.exe does not have permission to delete
				
				

		return;

}

/****************************************************************************

	TestMiscPipes :
	This is a function to test Named/UnNamed pipes for all Misc test cases.
	

******************************************************************************/

void TestMiscPipes() {

_LIT(KInvalidPipeName,"PipeNotExist");
		TInt			ret,aSize;
		RPipe			aReader,aWriter;
		TBufC<50>		cPipeName(KInvalidPipeName);			// Descriptor to hold data for Writing.
		TBufC8<50>		cPipeTestData2(KTestData2);
		
		
		// Try to create unnamed pipe with Negative size
		test.Next(_L("PIPE TEST:9.1 Create Pipe of Negative Size.\n"));
		aSize = -1;
		ret = RPipe::Create(	aSize,
								aReader,
								aWriter,
								EOwnerProcess, //
								EOwnerProcess //
							 ); 
		test( ret == KErrArgument);
		
		
		// Try to create unnamed pipe with zero size
		test.Next(_L("PIPE TEST:9.2 Create Pipe with of Zero size.\n"));
		aSize = 0;
		ret = RPipe::Create(	aSize,
								aReader,
								aWriter,
								EOwnerProcess, //
								EOwnerProcess //
							 );
		test( ret == KErrArgument);
		

		// Try to define named pipe with Negative size
		test.Next(_L("PIPE TEST:9.3 Define Pipe of Negative size.\n"));
		aSize = -1;
		ret = RPipe::Define(cPipeName, aSize); 
		test( ret == KErrArgument);
		
		

		// Try to define named pipe with Zero size
		test.Next(_L("PIPE TEST:9.4 Define Pipe of Zero size.\n"));
		aSize = 0;
		ret = RPipe::Define(cPipeName, aSize);
		test( ret == KErrArgument);
		

		// Try to destroy pipe which does not exists
		test.Next(_L("PIPE TEST:9.5 Try to destroy named pipe which do not exist.\n"));
		ret = RPipe::Destroy (cPipeName);
		test (ret == KErrNotFound);

		
		// Try to read from pipe with invalid length data to be read
		RPipe			aReaderUN,aWriterUN;
		TBuf8<150>		cPipeReadData;
		aSize = 10;
		ret = RPipe::Create(	aSize,
								aReaderUN,
								aWriterUN,
								EOwnerProcess, //
								EOwnerProcess //
							 );
		test (ret == KErrNone );

		
		test.Next(_L("PIPE TEST:9.6 Try calling ReadBlocking using write handle and WriteBlocking using Read handle.\n"));
		ret = aWriterUN.ReadBlocking(cPipeReadData, aSize);
		test (ret == KErrAccessDenied);
		ret = aReaderUN.WriteBlocking(cPipeTestData2,aSize);
		test (ret == KErrAccessDenied);
		
		
		
		
		test.Next(_L("PIPE TEST:9.7 Read negative size data from un-named pipe.\n"));
		aSize = -1;
		ret = aReaderUN.Read(cPipeReadData, aSize);
		test( ret == KErrArgument);
		ret = aWriterUN.Write(cPipeTestData2,aSize);
		test( ret == KErrArgument);
		

		
		test.Next(_L("PIPE TEST:9.8 Read/Write zero size data from/to un-named pipe\n"));
		aSize = 0;
		ret = aReaderUN.Read(cPipeReadData, aSize);
		test( ret == KErrNone);

		ret = aWriterUN.Write(cPipeTestData2,aSize);
		test( ret == KErrNone);
		

		test.Next(_L("PIPE TEST:9.9 Call ReadBlocking and WriteBlocking to Read and Write negative size data.\n"));
		// Try to readblocking from pipe with invalid length data to be read
		aSize = -1;
		ret = aReaderUN.ReadBlocking(cPipeReadData, aSize);
		test( ret == KErrArgument);
		ret = aWriterUN.WriteBlocking(cPipeTestData2,aSize);
		test( ret == KErrArgument);

		test.Next(_L("PIPE TEST:9.10 ReadBlocking/WriteBlocking to read/write zero size data.\n"));
		aSize = 0;
		ret = aReaderUN.ReadBlocking(cPipeReadData, aSize);
		test( ret == KErrArgument);
		ret = aWriterUN.WriteBlocking(cPipeTestData2,aSize);
		test( ret == KErrArgument);
		
		
		test.Next(_L("PIPE TEST:9.11 Try calling ReadBlocking and WriteBlocking using un opened RPipe handles.\n"));		
		RPipe		aReaderT,aWriterT;
		ret = aReaderT.ReadBlocking(cPipeReadData, aSize);
		test (ret == KErrBadHandle);
		ret = aWriterT.WriteBlocking(cPipeTestData2,aSize);
		test (ret == KErrBadHandle);
		aReaderUN.Close();
		aWriterUN.Close();
		

		return;
}

/****************************************************************************
	This is a function to test notify mechanism of pipes.
	Check the functionality of following library functions
		- Notify...()


******************************************************************************/
void TestWaitMechanismPipes() {

		RPipe			aReader,aWriter;			// Used to pass to thread.
		RPipe			aWriter2;
		TInt			ret;
		TBufC<50>		cPipeName(KPipe3Name);		// Descriptor to hold data for Writing.
		TInt			aSize;
		TRequestStatus	stat1;

		aSize = 22 * 10; // Sizeof(KTestData) * 10

		ret = RPipe::Define( cPipeName,aSize);
		ret = aWriter.Open(cPipeName,RPipe::EOpenToWrite);
		test (ret == KErrNone);


		
		test.Next(_L("PIPE TEST:7.1 Try calling Wait function on BadPipe name.\n"));
		
		_LIT(KBadPipeName , "***R$@#$@#%#$%#^.12-.");
		aWriter.Wait(KBadPipeName,stat1);
		test(stat1.Int() == KErrBadName);
		aWriter.WaitForReader(KBadPipeName,stat1);
		test(stat1.Int() == KErrBadName);
		
			
		_LIT(KBadPipeName2 , "");
		aWriter.Wait(KBadPipeName2,stat1);
		test(stat1.Int() == KErrBadName);
		aWriter.WaitForReader(KBadPipeName2,stat1);
		test(stat1.Int() == KErrBadName);
		
		
		
		test.Next(_L("PIPE TEST:7.2 Try calling Wait function on non existing Pipe\n"));
		_LIT(KInvalidPipe , "NotExistingPipe");
		aWriter.Wait(KInvalidPipe,stat1);
		test(stat1.Int() == KErrNotFound);
		aWriter.WaitForReader(KInvalidPipe,stat1);
		test(stat1.Int() == KErrNotFound);
		
		
		test.Next(_L("PIPE TEST:7.3 Try calling Wait function on Pipe name length more than maxlength.\n"));
		aWriter.Wait(KMaxPipeNamePlusOne,stat1);
		test(stat1.Int() == KErrBadName);
		aWriter.WaitForReader(KMaxPipeNamePlusOne,stat1);
		test(stat1.Int() == KErrBadName);
			
	
		test.Next(_L("PIPE TEST:7.4 Try calling Wait function from unopened handle.\n"));
		aWriter2.Wait(cPipeName, stat1);
		test (stat1.Int() == KErrInUse);
		aWriter2.WaitForReader(cPipeName, stat1);
		test (stat1.Int() == KErrInUse);
				
		
		test.Next(_L("PIPE TEST:7.5 Register a valid Wait Request .\n"));
		aWriter.Wait(cPipeName, stat1);

		TData data(	&aReader, &aWriter);

		// Create Thread 5
		// Pass TData object with Write and Read handle both
		TTestThread thread5(KThread5Name, TestThread5, &data);
		User::WaitForRequest(stat1);

		ret = thread5.WaitForExitL();
		test_KErrNone(ret);
		
		test.Next(_L("PIPE TEST:7.6 After Wait finish check the value of status register.\n"));
		test_KErrNone(stat1.Int());
		aWriter.Close();
		aReader.Close();
		ret = aWriter.Open(cPipeName,RPipe::EOpenToWrite);
		test_KErrNone(ret);
		ret = aReader.Open(cPipeName,RPipe::EOpenToRead);
		test_KErrNone(ret);
		
		test.Next(_L("PIPE TEST:7.7 After Read handle is open , register request to Wait\n"));
		
		aWriter.Wait(cPipeName, stat1);
		test (stat1.Int() == KErrNone);
	
		test.Next(_L("PIPE TEST:7.8 Check for CancelWait.\n"));
		aWriter.Close();
		aReader.Close();
		ret = aWriter.Open(cPipeName,RPipe::EOpenToWrite);
		TRequestStatus stat2;
		aWriter.Wait(cPipeName, stat1);
		aWriter.Wait(cPipeName, stat2);
		test(stat2.Int() == KErrInUse);
		aWriter.CancelWait();
		test(stat1.Int() == KErrCancel);
		test(stat2.Int() == KErrInUse);
		aWriter.Wait(cPipeName, stat1);
		ret = aReader.Open(cPipeName,RPipe::EOpenToRead);
		test(stat1.Int() == KErrNone);
		
		test.Next(_L("PIPE TEST:7.9 Check Wait and CancelWait from reader end\n"));
		aWriter.Close();
		aReader.Close();
		ret = aReader.Open(cPipeName,RPipe::EOpenToRead);
		aReader.Wait(cPipeName, stat1);
		test (stat1.Int() ==  KErrAccessDenied);
		aReader.CancelWait();

	
		aWriter.Close();
		aReader.Close();
		RPipe::Destroy(cPipeName);
		
		/*****************Newly added tests for CR 1114 - WaitForReader *********/
		
		ret = RPipe::Define( cPipeName,aSize);
		ret = aWriter.Open(cPipeName,RPipe::EOpenToWrite);
		test (ret == KErrNone);


		test.Next(_L("PIPE TEST:7.10 Register a valid Wait Request .\n"));
		aWriter.WaitForReader(cPipeName, stat1);
		test(stat1==KRequestPending);
						
		// Create Thread 5
		// Pass TData object with Write and Read handle both
		{
		TTestThread thread5_1(KThread5Name, TestThread5, &data);
		User::WaitForRequest(stat1);

		ret = thread5_1.WaitForExitL();
		test_KErrNone(ret);
		}
		
		test.Next(_L("PIPE TEST:7.11 After Wait finish check the value of status register.\n"));
		aWriter.Close();
		aReader.Close();
		ret = aWriter.Open(cPipeName,RPipe::EOpenToWrite);
		ret = aReader.Open(cPipeName,RPipe::EOpenToRead);
		
		aReader.WaitForReader(cPipeName, stat1);
		test (stat1.Int() ==  KErrAccessDenied);
		
		test.Next(_L("PIPE TEST:7.12 After Read handle is open , register request to Wait\n"));
				
		aWriter.WaitForReader(cPipeName, stat1);
		test (stat1.Int() == KErrNone);
		
		test.Next(_L("PIPE TEST:7.13 Check for CancelWait.\n"));
		aWriter.Close();
		aReader.Close();
		ret = aWriter.Open(cPipeName,RPipe::EOpenToWrite);
		
		aWriter.WaitForReader(cPipeName, stat1);
		aWriter.WaitForReader(cPipeName, stat2);
		test(stat2.Int() == KErrInUse);
		aWriter.CancelWait();
		test(stat1.Int() == KErrCancel);
		test(stat2.Int() == KErrInUse);
		aWriter.WaitForReader(cPipeName, stat1);
		ret = aReader.Open(cPipeName,RPipe::EOpenToRead);
		test(stat1.Int() == KErrNone);
				
		// Release all the resources.
		aWriter.Close();
		aReader.Close();
		
		// Create Thread 5
		// Pass TData object with Write and Read handle both
		
		test.Next(_L("PIPE TEST:7.14 Register a valid Wait Request .\n"));
		aWriter.WaitForReader(cPipeName, stat1);
						
		{
		TTestThread thread5_2(KThread5Name, TestThread5, &data);
		User::WaitForRequest(stat1);
		
		ret = thread5_2.WaitForExitL();
		test_KErrNone(ret);
		}
		test.Next(_L("PIPE TEST:7.15 After Wait finish close the handles.\n"));
		test (stat1.Int() == KErrNone);
		aWriter.Close();
		aReader.Close();
		// Release all the resources.
		ret = RPipe::Destroy(cPipeName);
		test_KErrNone(ret);
		
		/*****************Newly added tests for CR 1114 - WaitForWriter *********/
		
		ret = RPipe::Define( cPipeName,aSize);
		test_KErrNone(ret);	
		ret = aReader.Open(cPipeName,RPipe::EOpenToRead);
		test (ret == KErrNone);


		// Create Thread 11
		// Pass TData object with Write and Read handle both
		
		test.Next(_L("PIPE TEST:7.16 Register a valid Wait Request .\n"));
		aReader.WaitForWriter(cPipeName, stat1);
		test(stat1==KRequestPending);
			
		{	
		TTestThread thread11(KThread11Name, TestThread11, &data);
		User::WaitForRequest(stat1);

		ret = thread11.WaitForExitL();
		test_KErrNone(ret);
		}

		test.Next(_L("PIPE TEST:7.17 After Wait finish check the value of status register.\n"));
		aWriter.Close();
		aReader.Close();
		ret = aWriter.Open(cPipeName,RPipe::EOpenToWrite);
		test_KErrNone(ret);	
		ret = aReader.Open(cPipeName,RPipe::EOpenToRead);
		test_KErrNone(ret);	
		
		aWriter.WaitForWriter(cPipeName, stat1);
		test (stat1.Int() ==  KErrAccessDenied);
		
		test.Next(_L("PIPE TEST:7.18 After Write handle is open , register request to Wait\n"));
		
		aReader.WaitForWriter(cPipeName, stat1);
		test (stat1.Int() == KErrNone);
		
		test.Next(_L("PIPE TEST:7.19 Check for CancelWait.\n"));
		aWriter.Close();
		aReader.Close();
		ret = aReader.Open(cPipeName,RPipe::EOpenToRead);
	
		aReader.WaitForWriter(cPipeName, stat1);
		aReader.WaitForWriter(cPipeName, stat2);
		test(stat2.Int() == KErrInUse);
		aReader.CancelWait();
		test(stat1.Int() == KErrCancel);
		test(stat2.Int() == KErrInUse);
		aReader.WaitForWriter(cPipeName, stat1);
		ret = aWriter.Open(cPipeName,RPipe::EOpenToWrite);
		test(stat1.Int() == KErrNone);
		
		// Release all the resources.
		aWriter.Close();
		aReader.Close();
		
		// Create Thread 11
		// Pass TData object with Write and Read handle both

		test.Next(_L("PIPE TEST:7.20 Register a valid Wait Request .\n"));
		aReader.WaitForWriter(cPipeName, stat1);
				
		{
		TTestThread thread11_2(KThread11Name, TestThread11, &data);
		User::WaitForRequest(stat1);
		
		test.Next(_L("PIPE TEST:7.21 After Wait finish , close the hadles.\n"));
		test (stat1.Int() == KErrNone);
		ret = thread11_2.WaitForExitL();
		test_KErrNone(ret);

		// Release all the resources.
		aWriter.Close();
		aReader.Close();
		}

		ret = RPipe::Destroy(cPipeName);
		test_KErrNone(ret);
		
		/**********************************************************/
		
		// Define the pipe.
		ret = RPipe::Define( cPipeName,aSize);
		test(ret == KErrNone);
		
		// Wait for Writer.
		aReader.WaitForWriter(cPipeName, stat1);
		// Try to open read end again. It should not open because WaitForWriter
		// will has already opened the Read End of the pipe.
		ret = aReader.Open(cPipeName ,RPipe::EOpenToRead );
		test(ret = KErrInUse );
		// Status of the wait request is pending because writer is not opened yet.
		test (stat1.Int() == KRequestPending);
		
		// Wait on Reader.
		aWriter.WaitForReader(cPipeName , stat2);
		// Reader was already opened so status is KErrNone.
		test ( stat2.Int() == KErrNone);
		
		// Try to open Write end. It should not allow because WaitForReader has 
		// already opened the write end of the pipe.
		ret = aWriter.Open(cPipeName ,RPipe::EOpenToWrite);
		test (ret == KErrInUse);
		
		// Check the status of the WaitForWriter  request. It should be KErrNone now.
		test (stat1.Int() == KErrNone);
		
		// Let's check for pipe attributes.
		ret = aReader.MaxSize();
		test (ret = aSize);
		ret = aWriter.MaxSize();
		test (ret = aSize);
		ret = aReader.Size();
		test (ret = aSize);
		ret = aWriter.Size();
		test (ret = aSize);
		
		// Close the Reade handle.
		aReader.Close();
		
		// Put request to wait for Reader.
		aWriter.WaitForReader(cPipeName , stat2);
		// It should be pending.
		test ( stat2.Int() == KRequestPending);
		// Open the reader end of the pipe. It should allow , KErrNone
		ret = aReader.Open(cPipeName ,RPipe::EOpenToRead );
		test ( stat2.Int() == KErrNone);
		test (ret == KErrNone);
		
		aReader.Close();
		aWriter.Close();
		ret=RPipe::Destroy(cPipeName);
		test_KErrNone(ret);
									
		return;


}

/****************************************************************************
	This is a function to test notify mechanism of pipes.
	Check the functionality of following library functions
		- Notify...()


******************************************************************************/
void TestNotifyMechanismPipes() {
		// Test NotifyDataAvailable , NotifySpaceAvailable
		RSemaphore 					globalSem;						// Handle to a global semaphore. Semaphore is used to maintain synchronisation between thread4 and the main thread 
		TInt						ret;							// Return Value variable.
		RPipe						aReader,aWriter;				// Used to pass to thread.
		RPipe						aReader2,aWriter2;				// Used to pass to thread.
		
		TInt						aSize;							// Used to pass to thread.
		const TBufC<50>				cPipeName(KPipe1Name);			// Descriptor to hold data for Writing.

		TRequestStatus				stat1;
		TBuf8<50>					cPipeTestData1(KTestData2);
		
		const TBufC<50>             cSemaphoreName(KSemaphoreName); // Descriptor conataining the name of the global semaphore.

		
		ret = globalSem.CreateGlobal(cSemaphoreName,0);		//create and open a global semaphore with initial count as 0.
		test (ret == KErrNone);
		
		aSize = 22; 											// Size of KTestData * 10

		ret = RPipe::Create(	aSize,
								aReader,
								aWriter,
								EOwnerProcess, //
								EOwnerProcess //
							 );

		TData data(	&aReader, &aWriter);

		// Create Thread 4
		// Pass TData object with Write and Read handle both
		test.Next(_L("PIPE TEST:6.1 Call CancelDataAvailable/CancelSpaceAvailable using unopened RPipe handles.\n"));
		ret = aReader2.CancelDataAvailable();
		test ( ret == KErrBadHandle);
		ret = aWriter2.CancelSpaceAvailable();
		test (ret == KErrBadHandle);
		
		test.Next(_L("PIPE TEST:6.2 Call NotifySpaceAvailable with Negative size \n"));
		// Call Notfifyspace
		TInt	tempsize = -1;
		aWriter.NotifySpaceAvailable(tempsize, stat1);
		test ( stat1.Int() == KErrArgument);

		test.Next(_L("PIPE TEST:6.2a Call NotifySpaceAvailable for space larger than pipe.\n"));
		aWriter.NotifySpaceAvailable(aSize+1, stat1);
		test_Equal( KErrArgument, stat1.Int());
		
		
		// Start the thread
		{
		TTestThread thread4(KThread4Name, TestThread4, &data);

																	//	Thread 4
																	// 	Call Notifydata available
																	//	Loop for Available
																	//	Read the data and validate

		test.Next(_L("PIPE TEST:6.3 Write data into the pipe , verify return value.\n"));
		// Write one byte data into the pipe.
		globalSem.Wait(); //wait before writing to ensure that other thread can register Data Available request while pipe is empty. 
		ret = aWriter.Write(cPipeTestData1,cPipeTestData1.Length());
		test (ret == cPipeTestData1.Length());
		
						
		test.Next(_L("PIPE TEST:6.4 Call NotifySpaceAvailable with valid parameters \n"));
		tempsize = 1;
		aWriter.NotifySpaceAvailable(tempsize, stat1);
		test(stat1==KRequestPending);
		globalSem.Signal();	//signal that thread 4 may go ahead and read 1 byte
		
		
		test.Next(_L("PIPE TEST:6.5 Wait till request says AVAILABLE. Available ?\n"));
		User::WaitForRequest(stat1);
		test ( stat1.Int() == KErrNone || stat1.Int() == KErrCompletion);
		
					// Thread 4
					// Notify data available
					// Loop for available
					// Flush the buffer
					// Register two request for Notifydata available
					// Register two request for Notifyspace available
					// Call Notifydata available using Read handle
					// Call Notifydata available using write handle
					// return


		// Check for Error conditions

		// Flush buffer
		globalSem.Wait(); // this is waiting for a signal from thread4
		test.Next(_L("PIPE TEST:6.6 Register Notification for space availability. Allows ?\n"));
		ret = aWriter.Write(cPipeTestData1,cPipeTestData1.Length());
		ret = aWriter.Write(cPipeTestData1,cPipeTestData1.Length());
		// Register two request for Notifyspace available
		
		aWriter.NotifySpaceAvailable(tempsize, stat1);
		test_Equal(KRequestPending, stat1.Int() );
		test.Next(_L("PIPE TEST:6.7 Register One more Notification for space availability. Allows ?\n"));
		TRequestStatus tempstat1;
		aWriter.NotifySpaceAvailable(tempsize, tempstat1);
		test ( tempstat1.Int() == KErrInUse);
	
		test.Next(_L("PIPE TEST:6.7a Cancellation of non-outstanding requests must not disrupt oustanding requests\n"));
		aWriter.CancelWait();
		aWriter.NotifySpaceAvailable(tempsize, tempstat1);
		test_Equal( KErrInUse, tempstat1.Int());

		test.Next(_L("PIPE TEST:6.8 Cancel all the pending Notifications.\n"));
		ret = aWriter.CancelSpaceAvailable();
		test ( ret == KErrNone);
		test_Equal(KErrCancel, stat1.Int() );
		
		test.Next(_L("PIPE TEST:6.9 Try to cancel some more notifications. It should not allow\n"));
		ret = aWriter.CancelSpaceAvailable();
		test ( ret == KErrNone);
		
		test.Next(_L("PIPE TEST:6.10 Register Notification for Data availability. Allows ?\n"));
		// Register two request for Notifydata available
		aWriter.Flush();
		aReader.NotifyDataAvailable(stat1);
			
		test.Next(_L("PIPE TEST:6.11 Register One More Notification for Data availability. Allows ?\n"));
				
		aReader.NotifyDataAvailable(tempstat1);
		test ( ( tempstat1.Int() == KErrInUse) || (tempstat1.Int() == KErrCompletion));
		
		test.Next(_L("PIPE TEST:6.12 Cancel all the pending Notifications for Data.\n"));
		ret = aReader.CancelDataAvailable();
		test ( ( ret == KErrNone) || (ret == KErrNotFound));
		test (stat1.Int() == KErrCancel);
		
		test.Next(_L("PIPE TEST:6.13 Try to cancel some more notifications. It should not allow\n"));
		ret = aReader.CancelDataAvailable();
		test ( ret == KErrNone);

		test.Next(_L("PIPE TEST:6.14 Try to register Data available notification using Write handle. Should not allow.\n"));
		aWriter.NotifyDataAvailable(stat1);
		test ( stat1.Int() == KErrAccessDenied);
		
		test.Next(_L("PIPE TEST:6.15 Try to register Space available notification using Read handle. Should not allow.\n"));
		aReader.NotifySpaceAvailable(tempsize, stat1);
		test ( stat1.Int() == KErrAccessDenied);
		
		test.Next(_L("PIPE TEST:6.16 Try to Cancel Data available notification using Write handle. Should not allow.\n"));
		ret = aWriter.CancelDataAvailable();
		test ( ret == KErrAccessDenied);
		
		test.Next(_L("PIPE TEST:6.17 Try to Cancel Space available notification using Write handle. Should not allow.\n"));
		ret = aReader.CancelSpaceAvailable();
		test ( ret == KErrAccessDenied);

		// Stop the thread and Close the Thread
		ret = thread4.WaitForExitL();
		}
		test_KErrNone(ret);
		// Close all the pipe handles.
		aReader.Close();
		aWriter.Close();
	
	
		
		test.Printf(_L(" TEST NOTIFICATION MECHNISM FOR NAMED PIPES\n"));
		
		aSize = 22; // Size of KTestData
		
		test.Next(_L("PIPE TEST:6.18 Create Named pipe and Open Read/Write Handles.\n"));
		ret = RPipe::Define( cPipeName,aSize);
		test (ret == KErrNone);
		ret = aReader.Open(cPipeName,RPipe::EOpenToRead);
		test (ret == KErrNone);
		ret = aWriter.Open(cPipeName,RPipe::EOpenToWrite);
		test (ret == KErrNone);
		
		
	
		TData data2(	&aReader, &aWriter);

		// Create Thread 4
		// Pass TData object with Write and Read handle both
		TTestThread thread4a(KThread4Name, TestThread4, &data2);

														//	Thread 4
														// 	Call Notifydata available
														//	Loop for Available
														//	Read the data and validate
		
		// Write one byte data into the pipe.
		test.Next(_L("PIPE TEST:6.19 Write Data and check for return value.\n"));
		globalSem.Wait(); //wait before writing to ensure that other thread can register Data Available request while pipe is empty. 
		ret = aWriter.Write(cPipeTestData1,cPipeTestData1.Length());
		test (ret == cPipeTestData1.Length());

		test.Next(_L("PIPE TEST:6.20 Register Notification for Space Available.\n"));
		// Call Notfifyspace
		tempsize = 1;
		aWriter.NotifySpaceAvailable(tempsize, stat1);
		test(stat1==KRequestPending);
		globalSem.Signal();	//signal that thread 4 may go ahead and read byte
		
		test.Next(_L("PIPE TEST:6.21 Wait till notified for Space Availanle.\n"));
		User::WaitForRequest(stat1);
		test ( stat1.Int() == KErrNone);

														// Thread 4
														// Read one byte of data
														// Thread 4
														// Notify data available
														// Loop for available
														// Flush the buffer
														// Register two request for Notifydata available
														// Register two request for Notifyspace available
														// Call Notifydata available using Read handle
														// Call Notifydata available using write handle
														// return
														
		globalSem.Wait();	//waiting for a signal from thread4.
		test.Next(_L("PIPE TEST:6.22 Notify for Space available.\n"));
		// Register two request for Notifydata available
		ret = aWriter.Write(cPipeTestData1,cPipeTestData1.Length());
		aWriter.NotifySpaceAvailable(tempsize, stat1);
		
		test.Next(_L("PIPE TEST:6.23 Notify one more notifier for Space available.\n"));
		// Register two request for Notifyspace available
		TRequestStatus notifyStatus;
		aWriter.NotifySpaceAvailable(tempsize, notifyStatus);
		test ( notifyStatus.Int() == KErrInUse);
		
		aWriter.Flush();
		aWriter.NotifySpaceAvailable(tempsize, stat1);
		test ( stat1.Int() == KErrNone);
		
		test.Next(_L("PIPE TEST:6.24 Cancel Notify for Space available.\n"));
		ret = aWriter.CancelSpaceAvailable();
		test (( ret == KErrNotFound) ||( ret == KErrNone));
		test.Next(_L("PIPE TEST:6.25 Cancel one more Notify for Space available.\n"));
		ret = aWriter.CancelSpaceAvailable();
		test ( ret == KErrNone);
		
		test.Next(_L("PIPE TEST:6.26 Register Notify for Data available.\n"));
		// Register two request for Notifydata available
		
		aWriter.Flush();
		TRequestStatus stat5,stat6;
		aReader.NotifyDataAvailable(stat5);
			
		test.Next(_L("PIPE TEST:6.27 Register One more Notify for Data available.\n"));
		// Register two request for Notifyspace available
		aReader.NotifyDataAvailable(notifyStatus);
		test ( notifyStatus.Int() == KErrInUse);
		test.Next(_L("PIPE TEST:6.28 Cancel Notify for Data available.\n"));
		ret = aReader.CancelDataAvailable();
		test ( ret == KErrNone);
		test (stat5.Int() == KErrCancel);
		
		test.Next(_L("PIPE TEST:6.29 Cancel One more Notify for Data available.\n"));
		ret = aReader.CancelDataAvailable();
		test ( ret == KErrNone);

		test.Next(_L("PIPE TEST:6.30 Register Notify for Data available using Write handle\n"));
		aWriter.NotifyDataAvailable(stat6);
		test ( stat6.Int() == KErrAccessDenied);
		
		test.Next(_L("PIPE TEST:6.31 Register Notify for Space available using Read handle\n"));
		aReader.NotifySpaceAvailable(tempsize, stat6);
		test ( stat6.Int() == KErrAccessDenied);
		
		test.Next(_L("PIPE TEST:6.32 Cancel Notify for Data available using Write handle\n"));
		ret = aWriter.CancelDataAvailable();
		test ( ret == KErrAccessDenied);
		
		test.Next(_L("PIPE TEST:6.33 Cancel Notify for Space available using Read handle\n"));
		ret = aReader.CancelSpaceAvailable();
		test ( ret == KErrAccessDenied);

	//close the handle to the global semaphore
	
	globalSem.Close();
	// Stop the thread and Close the Thread
		ret = thread4a.WaitForExitL();
		test_KErrNone(ret);
	aReader.Close();
	aWriter.Close();
	RPipe::Destroy(cPipeName);
	

	return;



} // End TestNotifyMechanismPipes()

/****************************************************************************
	This is a function to test Named pipes in Mutli process environment.
	Check the functionality of following library functions
		- Define ()
		-


******************************************************************************/


_LIT8(KTestDataIP, "ABCDEFGHIJ");

void TestMultiProcessNamedPipes() {

_LIT(KPipeName5, "InterProcessPipe1");
	TInt 						ret;								// Return value variable
	RProcess					proc;								// Process Handle
	RPipe 						aWriter;
	RPipe						aWriterUN,aReaderUN;
	const	TBufC<150>			cPipeName1(KPipeName5);

	TBufC8<150>					cPipeWriteData1(KTestDataIP);
	TInt						aSize;
	TRequestStatus				stat1;
	TBuf8<150>					cPipeReadData1;

	aSize = 10;

	// Define Pipe with valid size.

	test.Next(_L("PIPE TEST:5.1 Define Pipe and Create UnNAmed pipe and pass handle to other process.\n"));
	ret = RPipe::Define(cPipeName1, aSize);
	test_KErrNone(ret);	
	ret = proc.Create(
						KProcessName,								// Launch t_pipe2.exe process
					 	KNullDesC									// No arguments passed to t_pipe2.exe
					 );

	if (ret != KErrNone) {
		// Check for process successfully launched
		test.Printf(_L("Error : Could not start the process t_pipe2.exe \n"));
	}
	test_KErrNone(ret);	
	TRequestStatus procLogon;
	proc.Logon(procLogon);
	test(procLogon==KRequestPending);

	aSize = 512;
	ret = RPipe::Create(	aSize,
							aReaderUN,
							aWriterUN,
							EOwnerProcess,//TOwnerType aTypeW
							EOwnerProcess //TOwnerType aTypeW
						);
	test_KErrNone(ret);	
						
	ret = aWriterUN.Write(KTestData,22);
	test (ret == 22);
	ret = aReaderUN.Read(cPipeReadData1,10);
	test ( ret == 10);
	aWriterUN.Close();
	ret = aReaderUN.Read(cPipeReadData1,6);
	test (ret == 6);
	aReaderUN.NotifyDataAvailable(stat1);
	ret = stat1.Int();
	test (ret == KErrNone);
	ret = aReaderUN.ReadBlocking(cPipeReadData1,6);
	test (ret == 6);
	ret = aReaderUN.Read(cPipeReadData1,1);
	test ( ret == KErrNotReady);
	ret = aReaderUN.ReadBlocking(cPipeReadData1,1);
	test ( ret == KErrNotReady);
	aReaderUN.Close();
		
	ret = RPipe::Create(	aSize,
							aReaderUN,
							aWriterUN,
							EOwnerProcess,//TOwnerType aTypeW
							EOwnerProcess //TOwnerType aTypeW
						);
	test_KErrNone(ret);	
	proc.SetParameter(3,aReaderUN);
	aReaderUN.Close();
	ret = aWriterUN.Write(KTestData,22);
	test (ret == 22 );
	
	proc.Resume();

	aSize = 10;
	test.Next(_L("PIPE TEST:5.2 Open Write handle to Pipe. Wait till Read handle Opened\n"));
	ret = aWriter.Open(cPipeName1, RPipe::EOpenToWrite);
	test_KErrNone(ret);	
	aWriter.Wait(cPipeName1,stat1);
	User::WaitForRequest(stat1);
	test (stat1.Int() == KErrNone);
	
	test.Next(_L("PIPE TEST:5.3 Write data to Pipe.\n"));
	ret = aWriter.Write(cPipeWriteData1,cPipeWriteData1.Length());
	test ( ret == cPipeWriteData1.Length());

	test.Next(_L("PIPE TEST:5.4 Wait till Space Available in Pipe.\n"));
	aWriter.NotifySpaceAvailable(aSize,stat1);
	User::WaitForRequest(stat1);
	
	test.Next(_L("PIPE TEST:5.5 Write the data using WriteBlocking call\n"));
	test_Equal(0, aWriter.Size());
	ret = aWriter.WriteBlocking(cPipeWriteData1,cPipeWriteData1.Length());
	test ( ret ==cPipeWriteData1.Length() );

	User::WaitForRequest(procLogon);
	
	aWriter.Close();
	ret=RPipe::Destroy(cPipeName1);
	test_KErrNone(ret);
	
	proc.Close();
	aWriterUN.Close();
	aReaderUN.Close();
	return;
	
} // End TestMultiProcessNamedPipes ()
/****************************************************************************
	This is a function to test Named pipes in Multi threaded environment.
	Check the functionality of following library functions
		- Define ()
		- Read()
		- Write()
		- ReadBlocking()
		- WriteBlocking()


******************************************************************************/
//
// Test defining and opening both ends of pipe
// Attempt to readblock from pipe closed at far end (should fail)
// Attemp writeblock to pipe closed at far end
//
// Do some normal reading and writing between threads
// do some blocking read/write between threads
void TestMultiThreadNamedPipes() {

	TInt					ret;							// Return Value variable.
	RPipe					aReader,aWriter;				// Used to pass to thread.
	TInt					aSize;							// Used to pass to thread.
	const TBufC<50>			cPipeName(KPipe1Name);			// Descriptor to hold data for Writing.
	TInt					aReadSize;
	TBuf8<150>				cPipeReadData;
	TBufC8<50> 				cTestData(KTestData); 			// Test Data




///////////////////////////////////////////////////////////
//  PART : 1											///
//	Test Read and Write Functionality					///
///////////////////////////////////////////////////////////

	test.Next(_L("PIPE TEST:4.1 Define Pipe , Open Read and Write Handle.\n"));
	aSize = 22;
	ret = RPipe::Define( cPipeName,aSize);
	test (ret == KErrNone);
	
	ret = aReader.Open(cPipeName,RPipe::EOpenToRead);
	test (ret == KErrNone);
	
	ret = aWriter.Open(cPipeName,RPipe::EOpenToWrite);
	test (ret == KErrNone);
	
	aWriter.Close();
	
	test.Next(_L("PIPE TEST:4.2 ReadBlocking: Check for KErrNotReady.\n"));
	aReadSize = 1;
	ret = aReader.ReadBlocking(cPipeReadData,aReadSize);
	test (ret == KErrNotReady);
	
	ret = aWriter.Open(cPipeName,RPipe::EOpenToWrite);
	test (ret == KErrNone);
	
	
	aReader.Close();
	test.Next(_L("PIPE TEST:4.3 WriteBlocking: Check for KErrNotReady.\n"));
	ret = aWriter.WriteBlocking(cTestData,cTestData.Length());
	test (ret == KErrNotReady);
		
	ret = aReader.Open(cPipeName,RPipe::EOpenToRead);
	test (ret == KErrNone);
	

	TData data(	&aReader, &aWriter);




	// Write data to Pipe using valid handle
	test.Next(_L("PIPE TEST:4.4 Write into the pipe and verify return value.\n"));
	ret = aWriter.Write(cTestData,cTestData.Length());
	test (ret == cTestData.Length() );

	
	// Keep writing the data into pipe till it overflows
	
	test.Next(_L("PIPE TEST:4.5 Write into the pipe till it overflows.\n"));
	ret = aWriter.Write(cTestData,cTestData.Length());
	test (( ret == KErrOverflow)) ;
	
	// Start the thread.
	TTestThread thread2(KThread2Name, TestThread2, &data);
	// Read 1 byte data from pipe
	// Validate data
	// Read aByte size data
	// Validate data
	// Thread 2
	// Read aByte size data
	// User:: After (10000)
	// Keep reading data till zero return
	// return

	// Stop the thread and Close the Thread
	ret = thread2.WaitForExitL();
	test_KErrNone(ret);

	aReader.Close();
	aWriter.Close();
	ret = RPipe::Destroy(cPipeName);
	test_KErrNone(ret);


///////////////////////////////////////////////////////////
//  PART : 2											///
//	Test ReadBlocking and WriteBlocking Functionality	///
///////////////////////////////////////////////////////////

	// Test Read and Write blocking call

	test.Next(_L("PIPE TEST:4.6 Create UnNamed Pipe with valid size.\n"));
	
	aSize = 22;
	ret = RPipe::Define( cPipeName,aSize);
	test (ret == KErrNone);
	
	ret = aReader.Open(cPipeName,RPipe::EOpenToRead);
	test (ret == KErrNone);
	
	ret = aWriter.Open(cPipeName,RPipe::EOpenToWrite);
	test (ret == KErrNone);
	
	// Create TData object to pass Pipe handles.
	TData data2(	&aReader, &aWriter);

	
	// Create Thread ( Note : Thread is in pending state now)
	// Flush the data if any in pipe to make sure its empty.
	aWriter.Flush();
	
	// Start the thread
	TTestThread thread3(KThread3Name, TestThread3, &data2);
											// Thread 3
											// Write one byte of data
											// Write one one byte of data using WriteBlocking call
											// Write aByte size data using Writblocking call

	
	// Call Readblocking function.Read one byte of data.
	test.Next(_L("PIPE TEST:4.7 Flush the buffer and Call ReadBlocking one byte into the pipe.\n"));
		aReadSize = 1;
		ret = aReader.ReadBlocking(cPipeReadData,aReadSize);
		test_Equal(aReadSize, ret);
	
	test.Next(_L("PIPE TEST:4.8 Verify the data received.\n"));
		test ( KErrNone == cPipeReadData.Compare(KTestData1));
		
	
	test.Next(_L("PIPE TEST:4.9 Call ReadBlocking and read complete data from Pipe. As big as Pipe Size\n"));
	// Call Readblocking function.Read aSize bytes of data.
		aReadSize = aSize-aReadSize; //read rest of data
		ret = aReader.ReadBlocking(cPipeReadData,aReadSize);
		test_Equal(aReadSize, ret);
		test ( KErrNone == cPipeReadData.Compare(KTestData3));
		
											// Thread 3
											// Wait for some time
											// Call Readblocking and read 1 byte of data
											// Call Readblocking and Read abyte size data
											// Call flush buffer
											// return
	test.Next(_L("PIPE TEST:4.10 Call ReadBlocking and read complete data from Pipe. As big as Pipe Size\n"));
	// Call Readblocking function.Read aSize bytes of data.
		aReadSize = aSize;
		ret = aReader.ReadBlocking(cPipeReadData,aReadSize);
		test_Equal(aReadSize, ret);
		test ( KErrNone == cPipeReadData.Compare(KTestData2));
		
	// Stop the thread and Close the Thread
	ret = thread3.WaitForExitL();
	test_KErrNone(ret);

	aReader.Close();
	aWriter.Close();
	ret=RPipe::Destroy(cPipeName);
	test_KErrNone(ret);
	return ;

} // End TestMultiThreadNamedPipes ()


/****************************************************************************
	This is a function to test UnNamed pipes in Multi threaded environment.
	Check the functionality of following library functions
		- Create()
		- Read()
		- Write()
		- ReadBlocking()
		- WriteBlocking()


******************************************************************************/
void TestMultiThreadUnNamedPipes() {

	TInt					ret;							// Return Value variable.
	RPipe					aReader,aWriter;				// Used to pass to thread.
	TInt					aSize;							// Used to pass to thread.
	TBuf8<250>				cPipeReadData;
	TInt					aReadSize;
	TBufC8<50> 				cTestData(KTestData); 			// Test Data


///////////////////////////////////////////////////////////
//  PART : 1											///
//	Test Read and Write Functionality					///
///////////////////////////////////////////////////////////
	
	test.Next(_L("PIPE TEST: 3.1 Create Pipe : Check for no erros on Pipe Creation \n"));
	ret = 100;
	aSize = 22; 										// Size of KTestData * 10

	ret = RPipe::Create(		aSize,
								aReader,
								aWriter,
								EOwnerProcess ,//TOwnerType aTypeW
								EOwnerProcess //TOwnerType aTypeW
							 );

	test (ret == KErrNone);

	// Create TData object to pass Pipe handles.
	TData data1(	&aReader, &aWriter);

	// Create Thread ( Note : Thread is in pending state now)

	// Create test data stream.
	test.Next(_L("PIPE TEST: 3.2 Write Function test : Write data into the pipe \n"));
	ret = aWriter.Write(cTestData,cTestData.Length()); 		// Write ""Pipe Data To Be Passed"
	test (ret == cTestData.Length());

	// Keep writing the data into pipe till it overflows
	test.Next(_L("PIPE TEST: 3.3 Write Data till the Pipe returns KErrOverFlow\n"));
	ret = aWriter.Write(cTestData,cTestData.Length());
	test ( ret == KErrOverflow);
	
	TTestThread thread2(KThread2Name, TestThread2, &data1);
	// Thread2
	// Read 1 byte data from pipe
	// Validate data
	// Read aByte size data
	// Validate data
	// Thread 2
	// Read aByte size data
	// User:: After (10000)
	// Keep reading data till zero return
	// return
	
	// Stop the thread , Close it.
	
	ret = thread2.WaitForExitL();
	test_KErrNone(ret);

	aReader.Close();
	aWriter.Close();


///////////////////////////////////////////////////////////
//  PART : 2											///
//	Test ReadBlocking and WriteBlocking Functionality	///
///////////////////////////////////////////////////////////


	aSize = 22; 									// Size of KTestData

	ret = RPipe::Create(		aSize,
								aReader,
								aWriter,
								EOwnerProcess ,			//TOwnerType aTypeW
								EOwnerProcess 			//TOwnerType aTypeW
					   );
	test_KErrNone(ret);	

	// Create TData object to pass Pipe handles.

	TData data2(&aReader, &aWriter);

	// Flush the data if any in pipe to make sure its empty.
	 aWriter.Flush();
	 
	// Start the thread
	TTestThread thread3(KThread3Name, TestThread3, &data2);
						// Thread 3
						// Write one byte of data
						// Write one one byte of data using WriteBlocking call
						// Write aByte size data using Writblocking call


	// Call Readblocking function.Read one byte of data.
	
	aReadSize = 1;
	test.Next(_L("PIPE TEST: 3.4 : Call readblocking and read one byte of data \n"));
	ret = aReader.ReadBlocking(cPipeReadData,aReadSize);
	// Call goes to Thread 3
	test_Equal(aReadSize, ret);
	
	test.Next(_L("PIPE TEST: 3.5 : Validate the data \n"));
	test_Equal(0, cPipeReadData.Compare(KTestData1));
	

	// Call Readblocking function.Read aSize bytes of data.
	test.Next(_L("PIPE TEST: 3.6 : Read remaining data \n"));
	aReadSize = 21;
	ret = aReader.ReadBlocking(cPipeReadData,aReadSize);
	test_Equal(aReadSize, ret);
	test_Equal(0, cPipeReadData.Compare(KTestData3));
	
	
	test.Next(_L("PIPE TEST: 3.7 : Read complete pipe size data \n"));
	aReadSize = 22;
	ret = aReader.ReadBlocking(cPipeReadData,aReadSize);
	test_Equal(aReadSize, ret);
	test_Equal(0, cPipeReadData.Compare(KTestData2));
	
	// Wait for thread to end and Close
	ret = thread3.WaitForExitL();
	test_KErrNone(ret);

	aReader.Close();
	aWriter.Close();

	return ;


}// End TestMultiThreadUnNamedPipes()

/****************************************************************************
	This is a function to test Named pipes in Single threaded environment.
	Check the functionality of following library functions
		- Define ()
		-


******************************************************************************/

void TestSingleThreadNamedPipes()

{


	const TBufC<50> 		cPipeName(KPipe1Name); 		// Descriptor to hold data for Writing.
	TInt 					aSize, ret;
	RPipe 					testPipe1;
	RPipe 					testPipe2;
	RPipe					testPipe3;
	RPipe					testPipe4;
	RPipe					testPipe5;
	const TBufC<100> 		cPipeNameMax(KMaxPipeName);
	const TBufC<100> 		cPipeNameMaxPlusOne(KMaxPipeNamePlusOne);

	_LIT(KBadName , "***?SFSDFWE?*_-");
	_LIT(KBadName2 , "");

	test.Next(_L("PIPE TEST: 2.1 Define Function test : Check for No Error\n"));
		aSize = 10;

		ret = RPipe::Define(cPipeName , aSize);
		test (ret == KErrNone);
	
		ret = RPipe::Destroy (cPipeName);
		test (ret == KErrNone);

	

	test.Next(_L("PIPE TEST: 2.2 Define Function test : Check for Max length \n"));
	
		aSize = 10;

		ret = RPipe::Define(cPipeNameMax , aSize);
		test (ret == KErrNone);
	
		ret = RPipe::Destroy (cPipeNameMax);
		test (ret == KErrNone);

	test.Next(_L("PIPE TEST: 2.3 Define Function test : Check for Max length \n"));
		
		aSize = 10;
		ret = RPipe::Define(cPipeNameMaxPlusOne , aSize);
		test (ret == KErrBadName);
		ret = RPipe::Destroy (cPipeNameMaxPlusOne);
		test (ret == KErrBadName);

	test.Next(_L("PIPE TEST: 2.4 Open Function test : Test Open  \n"));
		aSize = 10;
		ret = RPipe::Define(cPipeName , aSize);
		test_KErrNone(ret);

		ret = testPipe1.Open(KBadName,RPipe::EOpenToRead);
		test (ret == KErrBadName);
		
		ret = testPipe1.Open(KBadName2,RPipe::EOpenToRead);
		test (ret == KErrBadName);
		
		ret = testPipe1.Open(cPipeName,RPipe::EOpenToRead);
		test (ret == KErrNone);
		
		ret = testPipe1.Open(cPipeName,RPipe::EOpenToWrite);
		test (ret == KErrInUse);
		
		
		
	test.Next(_L("PIPE TEST: 2.5 Destroy Function test : Destroy opened pipe error  \n"));
		ret = RPipe::Destroy (cPipeName);
		test (ret == KErrInUse);

	test.Next(_L("PIPE TEST: 2.6 Open Function test : Reopen pipe for reading\n"));
		ret = testPipe2.Open(cPipeName,RPipe::EOpenToRead);
		test (ret == KErrInUse);

	test.Next(_L("PIPE TEST: 2.7 Open Function test : Bad name test  \n"));
		ret = testPipe2.Open(cPipeNameMaxPlusOne,RPipe::EOpenToRead);
		test (ret == KErrBadName);
			

	test.Next(_L("PIPE TEST: 2.8 Open Function test : Write mode test\n"));

		ret = testPipe3.Open(cPipeName,RPipe::EOpenToWrite);
		test (ret == KErrNone);
		
		ret = testPipe3.Open(cPipeName,RPipe::EOpenToRead);
		test (ret == KErrInUse);

	test.Next(_L("PIPE TEST: 2.9 Open Function test : Bad name test  \n"));
	
		ret = testPipe4.Open(cPipeNameMaxPlusOne,RPipe::EOpenToWrite);
		test (ret == KErrBadName);
	

	test.Next(_L("PIPE TEST: 2.10 Open Function test : Reopen for writing  \n"));
		ret = testPipe4.Open(cPipeName,RPipe::EOpenToWrite);
		test (ret == KErrInUse);
		

	// Do we have pipes created ? Close and Destroy them ....!!

	testPipe1.Close();
	testPipe2.Close();
	testPipe3.Close();
	testPipe4.Close();
	ret = RPipe::Destroy (cPipeName);
	test_KErrNone(ret);



	test.Next(_L("PIPE TEST: 2.11a Open Function test : Write But Fail on no Readers mode before pipe defined\n"));
	ret = testPipe1.Open(cPipeName,RPipe::EOpenToWriteNamedPipeButFailOnNoReaders);
	test_Equal(KErrNotFound,ret); 

	test.Next(_L("PIPE TEST: 2.11 Open Function test : Write But Fail on no Readers mode Error test\n"));
		ret = RPipe::Define(cPipeName , aSize);
		test (ret == KErrNone);

		ret = testPipe1.Open(cPipeName,RPipe::EOpenToWriteNamedPipeButFailOnNoReaders);
		test (ret == KErrNotReady); 
		

	test.Next(_L("PIPE TEST: 2.12 Open Function test : Write But Fail on no Readers mode Success test\n"));
		ret = testPipe1.Open(cPipeName,RPipe::EOpenToRead);
		test_KErrNone(ret);
		ret = testPipe2.Open(cPipeName,RPipe::EOpenToWriteNamedPipeButFailOnNoReaders);
		test ( ret == KErrNone);
		

	// Do we have pipes created ? Close and Destroy them ....!!

	testPipe1.Close();
	testPipe2.Close();
	testPipe3.Close();
	testPipe4.Close();
	ret = RPipe::Destroy (cPipeName);
	test_KErrNone(ret);


	
	test.Next(_L("	2.13 Define Function test : Check Incorrect Size\n"));
		aSize = -1;
		ret = RPipe::Define(cPipeName , aSize);
		test (ret == KErrArgument); 
	
	
	test.Next(_L("PIPE TEST: 2.14 Define Function test : Check Incorrect Size\n"));
		aSize = 0x1fffffff;
		ret = RPipe::Define(cPipeName , aSize);
		test (ret == KErrNoMemory); 
	

	test.Next(_L("PIPE TEST: 2.15 Size Function test : Size\n"));
		aSize = 10;
		ret = RPipe::Define(cPipeName , aSize);
		
		ret = testPipe5.MaxSize();
		test (ret == KErrBadHandle);


	test.Next(_L("PIPE TEST: 2.16 Size Function test : Size\n"));
		aSize = 10;
		ret = RPipe::Define(cPipeName , aSize);
		testPipe5.Open(cPipeName, RPipe::EOpenToRead);
		testPipe4.Open(cPipeName, RPipe::EOpenToWrite);
		ret = testPipe5.MaxSize();
		test (ret == aSize);
		ret = testPipe4.MaxSize();
		test (ret == aSize);
		

	/* Close all the pipes and Destroy*/
	testPipe1.Close();
	testPipe2.Close();
	testPipe3.Close();
	testPipe4.Close();
	testPipe5.Close();
	ret = RPipe::Destroy (cPipeName);
	test_KErrNone(ret);

	_LIT(KRedefinePipe , "REDEFINEPIPE");

	test.Next(_L("PIPE TEST: 2.17 Check for Redefining same pipe name \n"));
		ret = RPipe::Define(KRedefinePipe , aSize);
		test_KErrNone(ret);
		ret = RPipe::Define(KRedefinePipe , aSize);
		test (ret == KErrAlreadyExists);
	ret = RPipe::Destroy (KRedefinePipe);
	test_KErrNone(ret);
		
	test.Next(_L("PIPE TEST: 2.18 Open Function test : Bad Pipe name\n"));
		aSize = 10;
		RPipe testPipe6;
		ret = testPipe6.Open(cPipeName, RPipe::EOpenToRead);
		test (ret == KErrNotFound);
		

	const TBufC<50> cPipeNameNull;
	test.Next(_L("PIPE TEST: 2.19 Define Function test : Null Pipe name and Bad Pipe name\n"));
		aSize = 10;
		ret = RPipe::Define(cPipeNameNull , aSize);
		test (ret == KErrBadName);


	ret = RPipe::Define(KBadName , aSize);
		test (ret == KErrBadName);
	ret = RPipe::Destroy(KBadName);
		test (ret == KErrBadName);
		

	ret = RPipe::Define(KBadName2 , aSize);
		test (ret == KErrBadName);
	ret = RPipe::Destroy(KBadName2);
		test (ret == KErrBadName);
		
		
	test.Next(_L("PIPE TEST: 2.20 Destroy a pipe while Write end is open\n"));
	ret = RPipe::Define(cPipeName , aSize);

	testPipe1.Close();
	ret = testPipe1.Open(cPipeName,RPipe::EOpenToRead);
	test (ret == KErrNone);
	testPipe2.Close();
	ret = testPipe2.Open(cPipeName,RPipe::EOpenToWrite);
	test (ret == KErrNone);
	testPipe1.Close();
	ret = RPipe::Destroy (cPipeName);
	test (ret == KErrInUse);
	
	testPipe2.Close();
	ret = RPipe::Destroy (cPipeName);
	test (ret == KErrNone);
	
	testPipe1.Close();
	testPipe2.Close();
	testPipe3.Close();
	testPipe4.Close();
	testPipe5.Close();
	
	
	_LIT(KPipe1Name,"TestPipeA");
	_LIT(KPipe2Name,"TestPipeB");
	_LIT(KPipe3Name,"TestPipeC");
	_LIT(KPipe4Name,"TestPipeD");
	
	test.Next(_L("PIPE TEST: 2.21 Define Four pipes and Destroy in different sequence ( Code Coverage test)\n"));
	ret = RPipe::Define(KPipe1Name , aSize);
	test (ret == KErrNone);
	ret = RPipe::Define(KPipe2Name , aSize);
	test (ret == KErrNone);
	ret = RPipe::Define(KPipe3Name , aSize);
	test (ret == KErrNone);
	ret = RPipe::Define(KPipe4Name , aSize);
	test (ret == KErrNone);
	ret = RPipe::Destroy (KPipe2Name);
	test (ret == KErrNone);
	ret = RPipe::Destroy (KPipe4Name);
	test (ret == KErrNone);
	ret = RPipe::Destroy (KPipe1Name);
	test (ret == KErrNone);
	ret = RPipe::Destroy (KPipe3Name);
	test (ret == KErrNone);
	
	return;

} // End TestSingleThreadNamedPipes()

/****************************************************************************
	This is a function to test UnNamed pipes in Single threaded environment.
	Check the functionality of following library functions
		- Create ()
		-


******************************************************************************/

_LIT8(KTxtDataToSend,"*Test data to send**");

void TestSingleThreadUnNamedPipes() {

	TInt 				ret = 1; 				// Return value test variable.
	TInt 				aSize;
	TBufC8<40>			wData(KTxtDataToSend); 	// Descriptor to hold data for Writing.
	RPipe				aReader,aWriter;
	RPipe				aReader2,aWriter2;


	// Following tests will verify all the APIs in single thread
	// for all the possible return values. 
	// This is to verify different paths of API
	// not for detail functional verification.
	// Create the Pipe and Check for No Errors when Valid parameters are passed.
	
	test.Next(_L("PIPE TEST:1.1 Create Function test : Check for No Error\n"));
		aSize = 10;

		ret = RPipe::Create(	aSize,
								aReader,
								aWriter,
								EOwnerProcess,//TOwnerType aTypeW
								EOwnerProcess //TOwnerType aTypeW
							 );

		test (ret == KErrNone);
		
		ret = RPipe::Create(	aSize,
								aReader,
								aWriter,
								EOwnerProcess,//TOwnerType aTypeW
								EOwnerProcess //TOwnerType aTypeW
							 );

		test (ret == KErrInUse);
				
		aWriter.Close();
		aReader.Close();
	

	// How big pipe we can create ?

	test.Next(_L("PIPE TEST:1.2 Create Function test : Check for No Memory\n"));
	
		aSize = 0x1BCDEFFF;

		ret = RPipe::Create(	aSize,
								aReader2,
								aWriter2,
								EOwnerProcess,//TOwnerType aTypeW
								EOwnerProcess //TOwnerType aTypeW
							 );

		test (ret == KErrNoMemory);

		aReader2.Close();
		aWriter2.Close();

	
	test.Next(_L("PIPE TEST:1.3 Create Function test : Check for Reopening pipe\n"));
		aSize = 10;

		ret = RPipe::Create(	aSize,
								aReader,
								aWriter,
								EOwnerProcess,//TOwnerType aTypeW
								EOwnerProcess//TOwnerType aTypeW
							 );
		test_KErrNone(ret);	

		
		ret = RPipe::Create(	aSize,
								aReader,
								aWriter,
								EOwnerProcess,//TOwnerType aTypeW
								EOwnerProcess//TOwnerType aTypeW
							 );

		test (ret == KErrInUse);
		
		aReader.Close();
		aWriter.Close();
		


	test.Next(_L("PIPE TEST:1.4 Read/Write Function test : Check for Writing to pipe\n"));

		aSize = 100;
		ret = RPipe::Create(	aSize,
								aReader,
								aWriter,
								EOwnerProcess,//TOwnerType aTypeW
								EOwnerProcess//TOwnerType aTypeW
							 );
		test_KErrNone(ret);	

		ret=aWriter.Write(wData , wData.Size());
		test (ret == wData.Size() ); 
		
		ret=aWriter.Write(wData , -1);
		test (ret == KErrArgument ); 
		
		
	test.Next(_L("PIPE TEST:1.5 Read/Write Function test : Check for Reading from pipe\n"));


		TBuf8<100> rData ;// Descriptor for reading data from Pipe.
		
		ret=aReader.Read(rData,wData.Size()); // Length of the data to be read from Pipe
		test (ret == wData.Size());// Length of the data read from the Pipe


	test.Next(_L("PIPE TEST:1.6 Read/Write Function test : Validate data received\n"));

		test (KErrNone == rData.Compare(wData));


	test.Next(_L("PIPE TEST:1.7 Read/Write Function test : Check for Reading from pipe\n"));

		ret=aReader.Read(rData,1);
		test (ret == 0);
		{
			
		
		RPipe		aReaderT, aWriterT;
		aSize = 20;
		ret = RPipe::Create(	aSize,
								aReaderT,
								aWriterT,
								EOwnerProcess,//TOwnerType aTypeW
								EOwnerProcess//TOwnerType aTypeW
							 );
		test_KErrNone(ret);	
							 
		ret=aWriterT.Write(wData ,15);
		test_Equal(15, ret);
		ret = aReaderT.Read(rData,10);
		test_Equal(10, ret);
		ret=aWriterT.Write(wData ,10);
		test_Equal(10, ret);
		ret = aReaderT.Read(rData,20);
		test (ret ==15);
		ret = aReaderT.Read(rData,5);
		test_Equal(0, ret);
		ret = aReaderT.Read(rData,25);
		test_Equal(0, ret);

		aReaderT.Close();
		aWriterT.Close();
				
		}
		
	
	test.Next(_L("PIPE TEST:1.8 Read/Write Function test : Check for Wrong RPipe Handle\n"));


		ret=aWriter.Read(rData,15 );// Length of the data to be read from Pipe
		test (ret == KErrAccessDenied );

	test.Next(_L("PIPE TEST:1.9 Read/Write Function test : Check for Wrong RPipe Handle\n"));

		ret=aReader.Write(rData,rData.Size());
		test (ret == KErrAccessDenied );
		

	test.Next(_L("PIPE TEST:1.10 Read/Write Function test : Check for write overflow\n"));

		ret=aWriter.Write(wData,wData.Size());
		ret=aWriter.Write(wData,wData.Size());
		ret=aWriter.Write(wData,wData.Size());
		ret=aWriter.Write(wData,wData.Size());
		ret=aWriter.Write(wData,wData.Size());
		ret=aWriter.Write(wData,wData.Size());
		test (ret == KErrOverflow );
		
		

	test.Next(_L("PIPE TEST:1.11 MaxSize Function test : MaxSize Check \n"));
		aSize = 10;
		// Just to be on safer side , close pipes if any.
		aReader.Close();
		aWriter.Close();

		ret = RPipe::Create(	aSize,
								aReader,
								aWriter,
								EOwnerProcess,//TOwnerType aTypeW
								EOwnerProcess//TOwnerType aTypeW
							 );
		test (ret == KErrNone); // This error condition is not defined yet.
		ret =aReader.MaxSize();
		test (ret == aSize);
		

	test.Next(_L("PIPE TEST:1.12 Size Function test : Size Check \n"));
		rData.Zero();	
		
		ret = aReader.Size();
		test_Equal(0, ret);
			
		_LIT8(KSizeTestData1,"123456789");

		ret = aWriter.Write(KSizeTestData1,9);
		test_Equal(9, ret);
		ret = aReader.Size();
		test_Equal(9, ret);

		ret = aReader.Read(rData,1);
		test_Equal(1, ret);
		ret = rData.Compare(_L8("1"));
		test_KErrNone(ret);
		ret = aReader.Size();
		test_Equal(8, ret);
		
		_LIT8(KSizeTestData2,"ab");
		ret = aWriter.Write(KSizeTestData2,2);
		test_Equal(2, ret);
		ret = aReader.Size();
		test_Equal(10, ret);
		
		ret = aWriter.Write(KSizeTestData2,1);
		test_Equal(KErrOverflow, ret);
		ret = aReader.Size();
		test_Equal(10, ret);
		
		ret = aReader.Read(rData,9);
		test_Equal(9, ret);
		ret = rData.Compare(_L8("23456789a"));
		test_KErrNone(ret);
		ret = aReader.Size();
		test_Equal(1, ret);
		
		ret = aReader.Read(rData,1);
		test_Equal(1, ret);
		ret = rData.Compare(_L8("b"));
		test_KErrNone(ret);
		ret = aReader.Size();
		test_Equal(0, ret);
		
		ret = aWriter.Size();
		test_Equal(0, ret);
		RPipe WrongPipeHandle;
		
		ret = WrongPipeHandle.Size();
		test ( ret == KErrBadHandle);

	test.Next(_L("PIPE TEST:1.13 Size Function test : Size Function call with Wrong handle \n"));

	

		ret = WrongPipeHandle.MaxSize();
		test (ret == KErrBadHandle);
	
	aReader.Close();
	aWriter.Close();
	aReader2.Close();
	aWriter2.Close();
		
	test.Next(_L("PIPE TEST:1.14 Read Function : KErrNotReady \n"));
		aSize = 10;
		ret = RPipe::Create(	aSize,
								aReader,
								aWriter,
								EOwnerProcess,//TOwnerType aTypeW
								EOwnerProcess//TOwnerType aTypeW
							 );
		test (ret == KErrNone); // This error condition is not defined yet.
		aWriter.Close();
		ret = aReader.Read(rData,aSize);
		test (ret == KErrNotReady);
		ret = aReader.Read(rData,110);
		test (ret == KErrArgument);
			
		
	test.Next(_L("PIPE TEST:1.15 Check Handle Type function \n"));	
		aReader.Close();
		aWriter.Close();
		aSize = 10;
		ret = RPipe::Create(	aSize,
								aReader,
								aWriter,
								EOwnerProcess,//TOwnerType aTypeW
								EOwnerProcess//TOwnerType aTypeW
							 );
		test_KErrNone(ret);	
							 
		ret = aReader.HandleType();
		test (ret == RPipe::EReadChannel);
		
		ret = aWriter.HandleType();
		test (ret == RPipe::EWriteChannel);
		
		
		aReader.Close();
		ret = aReader.HandleType();
		test (ret == KErrBadHandle);
		
	test.Next(_L("PIPE TEST:1.16 Write Function : KErrNotReady \n"));	
		aSize = 1;
		ret = aWriter.Write(wData,aSize);
		test (ret == KErrNotReady);
	
	test.Next(_L("PIPE TEST:1.17 Write Function : Write data more than size of Descriptor \n"));			
		ret = aWriter.Write(wData,110);
		test (ret == KErrArgument);
		
		
	test.Next(_L("PIPE TEST:1.18 Write Function : KErrCompletion \n"));
		aWriter.Close();
		ret = RPipe::Create(	aSize,
								aReader,
								aWriter,
								EOwnerProcess,//TOwnerType aTypeW
								EOwnerProcess//TOwnerType aTypeW
							 );
		test_KErrNone(ret);	
		ret = aWriter.Write(wData,wData.Size());
		test (ret == KErrOverflow);
	
	test.Next(_L("PIPE TEST:1.19 Create Function : KErrInUse \n"));
		aReader.Close();
		ret = RPipe::Create(	aSize,
								aReader,
								aWriter,
								EOwnerProcess,//TOwnerType aTypeW
								EOwnerProcess//TOwnerType aTypeW
							 );
		test (ret == KErrInUse);
		
		aWriter.Close();
		ret = RPipe::Create(	aSize,
								aReader,
								aWriter,
								EOwnerProcess,//TOwnerType aTypeW
								EOwnerProcess//TOwnerType aTypeW
							 );
		test (ret == KErrNone);
		aWriter.Close();
		ret = RPipe::Create(	aSize,
								aReader,
								aWriter,
								EOwnerProcess,//TOwnerType aTypeW
								EOwnerProcess//TOwnerType aTypeW
							 );
		test (ret == KErrInUse);
		
	
		
	test.Next(_L("PIPE TEST:1.20 Read / Write using un opened handles \n"));	
		RPipe		aReaderT,aWriterT;
		
		ret = aWriterT.Write(wData,wData.Size());
		test (ret == KErrBadHandle);
		ret = aReaderT.Read(rData,aSize);
		test (ret == KErrBadHandle);
		
			
		

	// Close all the pipes and return the resources.
		aReader.Close();
		aWriter.Close();
		aReader2.Close();
		aWriter2.Close();
	return;

} // End TestSingleThreadUnNamedPipes()

/****************************************************************************
	This is a function to test UnNamed pipes and named pipes in Single 
	threaded environment.
	This test ensures that the memory is actually being released when:
	RPipe::Close() is called for unnamed pipes and
	RPipe::Destroy() is called for named pipes.
******************************************************************************/
void TestCreateClosePipe()
	{
	
	//unnamed pipes
	RPipe readHandle, writeHandle;
	const TInt K3MB = 1024*1024*3;
	// The loop is run ten times to ensure that if memory allocated while pipe
	// creation is not deallocated by close,then creation of pipe will fail with
	// KErrNoMemory in the sixth iteration. Default heap size is assumed.
	TInt i;
	test.Next(_L("PIPE TEST:11.1 Create Function test in a loop : Check for No Error\n"));
	for(i=1; i<10; i++) 
    	{
        TInt r = RPipe::Create(K3MB, readHandle, writeHandle,EOwnerProcess, EOwnerProcess);
        test(KErrNone == r);
        readHandle.Close(); 
        writeHandle.Close();
        }
     
    //named pipes
    _LIT(KPipeName, "testPipe");
    // The loop is run ten times to ensure that if memory allocated while pipe
	// creation is not deallocated by destroy,then creation of pipe will fail with
	// KErrNoMemory in the sixth iteration. Default heap size is assumed.
	test.Next(_L("PIPE TEST:11.2 Define Function test in a loop : Check for No Error\n"));
    for(i=1; i<10; i++) 
   	 	{
    	TInt r = RPipe::Define(KPipeName,K3MB);
    	test(KErrNone == r);
    	r = RPipe::Destroy(KPipeName);
    	test(KErrNone == r);
    	}
    
    }// End TestCreateClosePipe()


struct TStressArgs
	{
	TStressArgs(TInt aIter, TInt aSize)
		:iIter(aIter), iSize(aSize)
		{}

	const TInt iIter;
	const TInt iSize;
	};

struct TDefDesArgs: public TStressArgs
	{
	TDefDesArgs(TInt aIter, TInt aSize, const TDesC& aName)
		:TStressArgs(aIter,aSize), iName(aName)
		{}
	const TDesC& iName;
	};

/**
Repeatedly define and destroy named pipe
*/
TInt DefineDestroy(TAny* aArgs)
	{
	const TDefDesArgs args = *static_cast<TDefDesArgs*>(aArgs);
	
	for(TInt i=0; i<args.iIter; i++)
		{
		TInt r = RPipe::Define(args.iName, args.iSize);
		if(r!=KErrNone && r!=KErrAlreadyExists)
			{
			return r;
			}
		r = RPipe::Destroy(args.iName);
		if(r!=KErrNone && r!=KErrInUse && r!=KErrNotFound)
			{
			return r;
			}
		}
	return KErrNone;
	}


/**
The parent thread will try to repeatedly open and close a named pipe
which is being repeatedly created and destroyed by the child thread.
This attempts to catch race conditions.
*/
void TestRapidDefineDestroy()
	{
	const TInt iterations=1000;
	TDefDesArgs args(iterations, 16, KPipe1Name);

	RPipe pipe;

	TTestThread thread(_L("DefineDestroy"), DefineDestroy, &args);
	
	TInt r=KErrNone;

	for(TInt i=0; i<args.iIter; i++)
		{
		r = pipe.Open(args.iName, RPipe::EOpenToWrite);
		if(r!=KErrNone && r !=KErrNotFound)
			{
			test_KErrNone(r);
			}

		pipe.Close();
		}
	r = thread.WaitForExitL();
	test_KErrNone(r);
	}


/**
Write the descriptor specified in to the pipe repeating
as many times as specified by TData::iIterations
*/
TInt WriteThread(TAny* aData)
	{
	TData& data = *static_cast<TData*>(aData);
	
	const TInt iter = data.iIterations;

	TInt write=0;
	for(TInt i=0; i<iter; i++)
		{
		write = data.iWriteEnd->WriteBlocking(*data.iPipeData, data.iPipeData->Size());
		if(write <KErrNone)
			{
			return write;
			}
		}

	return write*iter;
	}

/**
Fill descriptor with random bytes
*/
void FillRandom(TDes8& aDes)
	{
	aDes.Zero();

	while(aDes.Size()+4<=aDes.MaxSize())
		{
		TUint8 rand[4];
		*(TUint32*)rand = Math::Random();

		aDes.Append(rand, 4);
		} 
	}

/**
@param aTotalBytes Bytes transfered in period
@param aTicks number of ticks elapsed in period
@return The rate of the transfer on kilobytes per second
*/
TReal KiloBytesPerSecond(TInt aTotalBytes, TInt aTicks)
	{
	TInt period=0; //period of nanotick in microseconds
	TInt r = HAL::Get(HAL::ENanoTickPeriod, period);
	User::LeaveIfError(r);

	//we use the definition that a kilobytes is 1000 bytes
	TReal result = (aTotalBytes/(aTicks*period/1000));
	return result;
	}


/**
Create a source data buffer of aTotal bytes and fill with random data.
Create a pipe and thread (WriteThread) to write the source buffer
into the pipe.
Read from the pipe into destination buffer
and optionally verify that buffers match

@param aTotal Size of data buffer
@param aPipeData Size of pipe to create
@param aIter number of times to repeat transfer
@param aVerify Confirm that destination buffer matches source buffer
@param aPollRead read pipe by polling instead of using blocking read
@return Total number of ticks elapsed
*/
TInt TestLoopBack(TInt aTotal, TInt aPipeSize, TInt aIter, TBool aVerify=ETrue, TBool aPollRead=EFalse)
	{
	const TInt bufferSize = aTotal;

	RBuf8 sourceBuffer;
	sourceBuffer.CreateL(bufferSize);
	FillRandom(sourceBuffer);
	test_Equal(bufferSize,sourceBuffer.Size());

	const TInt pipeSize=aPipeSize;

	RPipe readEnd, writeEnd;
	TInt r = RPipe::Create(pipeSize, readEnd, writeEnd ,EOwnerProcess, EOwnerProcess);
	test_KErrNone(r);


	const TInt maxIter=aIter;
	TData data(NULL, &writeEnd, &sourceBuffer, maxIter);


	RBuf8 destBuffer;
	destBuffer.CreateL(bufferSize);
	
	RBuf8 tempBuffer;
	tempBuffer.CreateL(bufferSize);

	
	TTestThread writer(_L("LoopBack"), WriteThread, &data);
	const TUint32 startTicks=User::NTickCount();

	for(TInt iter=0; iter<maxIter; iter++)
		{
		TInt remainingData = bufferSize;
		do
			{
				const TInt toRead = Min(pipeSize,remainingData);
				if(aPollRead)
					{
					//an inefficient way to read a pipe!
					r = readEnd.Read(tempBuffer, toRead);
					test_NotNegative(r);
					}
				else
					{
					r = readEnd.ReadBlocking(tempBuffer, toRead );
					test_Equal(toRead, r);
					}
				destBuffer+=tempBuffer;
				tempBuffer.Zero();
				remainingData-=r;
			}
		while(remainingData);

		if(aVerify)
			{
			r = sourceBuffer.Compare(destBuffer);
			test_KErrNone(r);
			}

		destBuffer.Zero();
		}
	const TUint32 endTicks = User::NTickCount();

	r = writer.WaitForExitL();
	test_Equal(bufferSize*maxIter, r);

	const TUint32 ticksElapsed= endTicks - startTicks; 

	sourceBuffer.Close();
	tempBuffer.Close();
	destBuffer.Close();

	readEnd.Close();
	writeEnd.Close();

	return ticksElapsed;
	}

/**
Simple test to confirm that data is reproduced after being fed through a pipe
*/
void TestTransferIntegrity()
	{

	TestLoopBack(128*1024, 128, 1, ETrue);
	TestLoopBack(1024, 1, 1, ETrue);

	//read by constantly polling
	TestLoopBack(128*1024, 1024, 1, ETrue, ETrue);
	}


/**
Enable Writeblocking and Readblocking notifications
without actual reads and writes
*/
class RTestPipe: public RPipe
	{
public:
	void RequestWriteBlocking(TInt aNumByte, TRequestStatus& aStatus)
		{
 		DoRequest(EWriteBlocking, aStatus, &aNumByte);
		}
		
	void RequestReadBlocking(TRequestStatus& aStatus)
		{
		DoRequest(EReadBlocking, aStatus);
		}
	};


/**
A test which will request some type of notification
*/
struct CNotificationTest : public TFunctor
	{
	CNotificationTest(RTestPipe& aPipe)
		:iPipe(aPipe)
		{
		TInt r = iParent.Open(iParent.Id());
		test_KErrNone(r);
		}

	virtual ~CNotificationTest()
		{
		}

	void operator()()
		{
		RunTest();

		//set up rendezvous with parent
		iParent.Rendezvous(iRendezvousStatus);

		//announce we have run test
		RThread::Rendezvous(KErrNone);
		
		//wait untill parent has reached rendezvous
		User::WaitForRequest(iRendezvousStatus);
		}

	virtual CNotificationTest* Clone()=0;

	/**
	If necessary, gets pipe into correct state for the start of test
	*/
	virtual void PreparePipe() =0;
	virtual void RunTest() =0;

	/**
	Cancel the notification
	*/
	virtual void Cancel() =0;

	virtual TInt GetReturn()
		{
		return iStatus.Int();
		}

	RTestPipe& iPipe;
	TRequestStatus iStatus;

	TRequestStatus iRendezvousStatus;
	RThread iParent;
	};



/**
Will request free space notification
*/
struct CSpaceNotificationTest : public CNotificationTest
	{
	typedef void (RTestPipe::*TSpaceNotification) (TInt, TRequestStatus&);

	/**
	@param aPipe Pipe handle to use
	@param TSpaceNotification A pointer for the method to test
	@param aNumBytes Amount of space to request
	*/
	CSpaceNotificationTest(RTestPipe& aPipe, TSpaceNotification aFunc, TInt aNumBytes)
		:CNotificationTest(aPipe), iFn(aFunc), iNumBytes(aNumBytes)
		{}
	
	CNotificationTest* Clone()
		{
		return new CSpaceNotificationTest(*this);
		}

	void RunTest()
		{
		(iPipe.*iFn)(iNumBytes, iStatus);
		}

	//Make sure space notification won't complete immediately
	void PreparePipe()
		{
		TInt freeSpace = iPipe.MaxSize() - iPipe.Size();
		if(freeSpace >= iNumBytes)
			{
			TInt r = iPipe.Write(KTestData, freeSpace);
			test_Equal(freeSpace, r);
			}
		}

	void Cancel()
		{
		iPipe.CancelSpaceAvailable();
		};

	TSpaceNotification iFn; 
	TInt iNumBytes;
	};

struct CDataNotificationTest : public CNotificationTest
	{
	typedef void (RTestPipe::*TDataNotification) (TRequestStatus&);

	CDataNotificationTest(RTestPipe& aPipe, TDataNotification aFunc)
		:CNotificationTest(aPipe), iFn(aFunc)
		{}
	
	CNotificationTest* Clone()
		{
		return new CDataNotificationTest(*this);
		}

	void RunTest()
		{
		(iPipe.*iFn)(iStatus);
		}

	//make sure we start with an empty pipe
	void PreparePipe()
		{
		iPipe.Flush();
		}

	void Cancel()
		{
		iPipe.CancelDataAvailable();
		};

	TDataNotification iFn; 
	};


void ProcessNotificationTests(RPointerArray<CNotificationTest>& aArray)
	{
	const TInt count = aArray.Count();
	for(TInt i=0; i < count; i++)
		{
		for(TInt j=0; j < count; j++)
			{
			//need copies as objects contain request states
			CNotificationTest* testA = aArray[i]->Clone();
			test_NotNull(testA);
			CNotificationTest* testB = aArray[j]->Clone();
			test_NotNull(testB);

			testA->PreparePipe(); testB->PreparePipe();

			TTestThread a(_L("CNotificationTestA"), *testA, EFalse);
			TTestThread b(_L("CNotificationTestB"), *testB, EFalse);

			TRequestStatus rendezvousA, rendezvousB;
			a.Rendezvous(rendezvousA);
			b.Rendezvous(rendezvousB);

			a.Resume();	b.Resume();

			//wait till after threads have made notification request.
			User::WaitForRequest(rendezvousA);
			User::WaitForRequest(rendezvousB);

			TInt retA = testA->GetReturn(); TInt retB = testB->GetReturn();

			//announce that we have read status requests, allowing
			//child threads to terminate
			RThread::Rendezvous(KErrNone);

			a.WaitForExitL();
			b.WaitForExitL();

			TBool oneRequestSupported = ((retA == KRequestPending) && (retB == KErrInUse))
										|| ((retB == KRequestPending) && (retA == KErrInUse));
			TBool bothSupported = (retA == KRequestPending) && (retB == KRequestPending);

			if(!(oneRequestSupported || bothSupported))
				{
				test.Printf(_L("Failure: i=%d, j=%d"), i, j);
				test(EFalse);
				}

			testA->Cancel(); testB->Cancel();
			delete testA;
			delete testB;
			}
		}
	}

/**
Test abillity of pipe channels to handle multiple notification requests
simultaneously.
*/
void TestNotifications()
	{
	RTestPipe readEnd, writeEnd;

	TInt pipeSize = 5;
	TInt r = RPipe::Create(pipeSize, readEnd, writeEnd, EOwnerProcess, EOwnerProcess);
	test_KErrNone(r);

	test.Next(_L("Test write end requests"));
	CSpaceNotificationTest writeBlocking(writeEnd, &RTestPipe::RequestWriteBlocking, pipeSize);
	CSpaceNotificationTest spaceAvailable(writeEnd, &RTestPipe::NotifySpaceAvailable, pipeSize);
	RPointerArray<CNotificationTest> writeEndTests;
	
	writeEndTests.AppendL(&writeBlocking);
	writeEndTests.AppendL(&spaceAvailable);

	for(TInt i=0; i<10; i++)
		{
		ProcessNotificationTests(writeEndTests);
		}
	writeEndTests.Close();

	test.Next(_L("Test read end requests"));
	CDataNotificationTest readBlocking(readEnd, &RTestPipe::RequestReadBlocking);
	CDataNotificationTest dataAvailable(readEnd, &RTestPipe::NotifyDataAvailable);
	RPointerArray<CNotificationTest> readEndTests;

	readEndTests.AppendL(&readBlocking);
	readEndTests.AppendL(&dataAvailable);

	for(TInt j=0; j<10; j++)
		{
		ProcessNotificationTests(readEndTests);
		}

	readEndTests.Close();

	readEnd.Close();
	writeEnd.Close();
	}

LOCAL_C void RunTests(void)
	{
	//  Test UnNamed Pipes in Single Thread
	test.Next(_L("PIPE TEST: 1.Un Named pipes in Single Thread\n"));
	TestSingleThreadUnNamedPipes();

	//	Test Named Pipes in Single Thread
	test.Next(_L("PIPE TEST: 2.Named pipes in Single Thread\n"));
	TestSingleThreadNamedPipes();

	//	Test UnNamed Pipes in MultiThread
	test.Next(_L("PIPE TEST: 3.Un Named pipes in Multi Thread\n"));
	TestMultiThreadUnNamedPipes();

	//	Test Named Pipes in MultiThread
	test.Next(_L("PIPE TEST: 4.Named pipes in Multi Thread\n"));
	TestMultiThreadNamedPipes();

	//	Test Named Pipes in Multi Process
	test.Next(_L("PIPE TEST: 5.Named pipes in Multi Process\n"));
	TestMultiProcessNamedPipes();

	//  Test Notify mechanism
	test.Next(_L("PIPE TEST: 6.Pipes Notify mechanism test\n"));
	TestNotifyMechanismPipes();

	//	Test Wait Mechanism
	test.Next(_L("PIPE TEST: 7.Pipes Wait mechanism test\n"));
	TestWaitMechanismPipes();


	//  Test Pipes performance
	test.Next(_L("PIPE TEST: 8.Pipes Permission test\n"));
	TestPipesPermissionCheck ();

	//	Misc Pipe tests
	test.Next(_L("PIPE TEST: 9.Misc Pipe tests\n"));
	TestMiscPipes();
	
	// Blocking and Notify method tests.
	test.Next(_L("PIPE TEST: 10.Blocking and Notification calls test\n"));
	TestBlockingAndNotify();
	
	//Creation and closure of a large number of Pipes
	test.Next(_L("PIPE TEST: 11. Creation and subsequent closure of a large number of pipes\n"));
	TestCreateClosePipe();

	test.Next(_L("Test concurrent notification requests"));
	TestNotifications();

	test.Next(_L("Repeatedly open a named pipe whilst it's being created and destroyed"));
	TestRapidDefineDestroy();

	test.Next(_L("Check integrity of data after transfer\n"));
	TestTransferIntegrity();

	test.Next(_L("PIPE TEST: Ending test.\n"));
	return;
	}

TInt ParseCommandLine()
	{
	TBuf<20> cmdLine;
	//TInt r= cmdLine.Create(User::CommandLineLength());
	//test_KErrNone(r);
	User::CommandLine(cmdLine);
	TLex lex(cmdLine);

	TPtrC token=lex.NextToken();
	if(token.Length()>0)
		{
		TInt os=token.Match(_L("-n*"));
		if(os==0)
			{
			if(token.Length()>2)
				lex.SkipAndMark(2-lex.TokenLength()); //set mark backwards to after the "-n"
			token.Set(lex.NextToken());
			if(token.Length()==0)
				return KErrArgument;

			TLex valLex(token);
			TInt value;
			TInt r=valLex.Val(value);
			if(r<0)
				return r;
			else
				return value;
			}
		else
			{
			return KErrArgument;
			}
		}
	else
		{	
		const TInt KDefaultRuns=1;
		return KDefaultRuns;
		}
	}

GLDEF_C TInt E32Main()
// Main entry point for the test.
    {
	__UHEAP_MARK;
	TInt		ret = 0;

	test.Start(_L("PIPE TEST: Testing"));
	ret = RPipe::Init();
	if ( ret != KErrNone && ret != KErrAlreadyExists) 
		{
		test.Printf(_L("Fail to load RPIPE driver %d\n"),ret);
		return KErrNone;
		}
	TName pddName(RPipe::Name());
	ret = RPipe::Define (KPipe1Name,10);
	test_KErrNone(ret);
	
	User::FreeLogicalDevice(pddName);
	ret = RPipe::Define (KPipe1Name,10);
	test_Equal(KErrNotFound, ret);
		
	ret = RPipe::Init();
	if ( ret != KErrNone && ret != KErrAlreadyExists) 
		{
		test.Printf(_L("Fail to load RPIPE driver %d\n"),ret);
		return KErrNone;
		}
		

	TInt runs=ParseCommandLine();
	if(runs>=0)
		{
		TBool forever=(runs==0);
		for(TInt i=0; forever||(i<runs); ++i)
			{
			if(i!=0)
				test.Next(_L("Next iteration"));

			test.Start(_L("Starting Run")); //sub nest each test iteration
			__UHEAP_MARK;
			TRAP(ret, RunTests());
			test_KErrNone(ret);
			__UHEAP_MARKEND;
			test.End();
			}
		}
	else
		{
		test.Printf(_L("Usage: t_pipe -n N\n N is number of runs to do. If N=0 run forever"));	
		}
	
	TName pddName2(RPipe::Name());
	ret= User::FreeLogicalDevice(pddName2);
	test_KErrNone(ret);
	test.End();
	test.Close();
	__UHEAP_MARKEND;
	return KErrNone;
 }