// 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;
}