--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/pipe/t_pipe.cpp Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,3451 @@
+// 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;
+ }
+
+