Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h)
Have multiple extension sections in the bld.inf, one for each version
of the compiler. The RVCT version building the tools will build the
runtime libraries for its version, but make sure we extract all the other
versions from zip archives. Also add the archive for RVCT4.
// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// e32test\pipe\t_pipe.cpp
// Overview:
// Test pipe mechanism
// API Information:
// RPipe
// Details:
// - Create various leagal and illegal pipe and verify that pipe
// functionality works as stated in requirements.
// - Create Named and UnNamed Pipes and verify.
// - Test Pipes communication in multiprocess , multithreaded , single process
// single threaded environment.
// Platforms/Drives/Compatibility:
// All.
// Assumptions/Requirement/Pre-requisites:
// Refer Pipes design and requirement document.
// 1. SGL.GT0314.202 PREQ1460 Design Doc
// 2. SGL.GT0314.203 PREQ1460 Pipe Functional Specification
// Refer Pipe test specification document.
// 1. SGL.GT0314.601 Pipes_Test_Specifications
// Failures and causes:
// Base Port information:
// MMP File:
// t_pipe.mmp
//
//
/**
@STMTestCaseID KBASE-T_PIPE-0217
@SYMPREQ PREQ1460
@SYMREQ REQ6141
@SYMCR CR0923
@SYMTestCaseDesc Pipe functional tests
@SYMTestPriority High
@SYMTestActions Tests the functionality of the pipe. Success and failure tests are performed.
@SYMTestExpectedResults Test should pass
*/
#define __E32TEST_EXTENSION__
#include <e32test.h>
#include <e32svr.h>
#include <e32des8.h>
#include <e32des8_private.h>
#include <e32cmn.h>
#include <e32cmn_private.h>
#include <e32math.h>
#include <hal.h>
#include "RPipe.h"
LOCAL_D RTest test(_L("t_pipe"));
//if the test is to run under the debugger, uncomment the following line
const TInt KHeapSize=0x2000;
// Test Data
_LIT8(KTestData,"Pipe Data To Be Passed");
_LIT8(KTestData1,"P");
_LIT8(KTestData2,"Pipe Data To Be Passed");
_LIT8(KTestData3,"ipe Data To Be Passed");
// Test Pipe Names
_LIT(KPipe1Name,"TestPipe1");
_LIT(KPipe3Name,"TestPipe3");
//Global semaphore name
_LIT(KSemaphoreName,"Semaphore1");
// Pipename of max pipe length 80 Charecters.
_LIT(KMaxPipeName,"abcdefghijklmnopqrstabcdefghijklmnopqrstabcdefghijklmnopqrstabcdefghijklmnopqrst");
// PipeName of max pipe length plus one ,81 charecters
_LIT(KMaxPipeNamePlusOne,"abcdefghijklmnopqrstabcdefghijklmnopqrstabcdefghijklmnopqrstabcdefghijklmnopqrst1");
// Thread Name Constants
_LIT(KThread2Name, "thread2");
_LIT(KThread3Name, "thread3");
_LIT(KThread4Name, "thread4");
_LIT(KThread5Name, "thread5");
_LIT(KReaderThread, "ReaderThread");
_LIT(KWriterThread, "WriterThread");
_LIT(KThread8Name, "thread8");
_LIT(KThread9Name, "thread9");
_LIT(KThread11Name, "thread11");
// Test Process Name Constants
_LIT(KProcessName, "t_pipe2.exe");
// Following class is used to pass thread handle information to different threads.
class TData
{
public:
TData(RPipe* aReadEnd, RPipe *aWriteEnd);
TData(RPipe* aReadEnd, RPipe *aWriteEnd, const TDesC8* aPipeData, TInt aIterations=1);
RPipe* iReadEnd;
RPipe* iWriteEnd;
const TDesC8* iPipeData;
TInt iIterations;
};
TData::TData(RPipe* aReadEnd , RPipe *aWriteEnd)
:iReadEnd(aReadEnd),iWriteEnd(aWriteEnd), iPipeData(NULL), iIterations(NULL)
{}
TData::TData(RPipe* aReadEnd , RPipe *aWriteEnd, const TDesC8* aPipeData, TInt aIterations)
:iReadEnd(aReadEnd),iWriteEnd(aWriteEnd), iPipeData(aPipeData), iIterations(aIterations)
{}
/**
A utility class for running functions in other threads/processes
*/
class TTestRemote
{
public:
virtual TInt WaitForExitL()=0;
virtual ~TTestRemote()
{}
virtual void Rendezvous(TRequestStatus& aStatus) =0;
protected:
TTestRemote()
{}
static TInt RunFunctor(TAny* aFunctor)
{
TFunctor& functor = *(TFunctor*)aFunctor;
functor();
return KErrNone;
}
TRequestStatus iLogonStatus;
static TInt iCount;
};
TInt TTestRemote::iCount=0;
class TTestThread : public TTestRemote
{
public:
TTestThread(const TDesC& aName, TThreadFunction aFn, TAny* aData, TBool aAutoResume=ETrue)
{
Init(aName, aFn, aData, aAutoResume);
}
/**
Run aFunctor in another thread
*/
TTestThread(const TDesC& aName, TFunctor& aFunctor, TBool aAutoResume=ETrue)
{
Init(aName, RunFunctor, &aFunctor, aAutoResume);
}
~TTestThread()
{
//RTest::CloseHandleAndWaitForDestruction(iThread);
iThread.Close();
}
void Resume()
{
iThread.Resume();
}
/**
If thread exited normally, return its return code
Otherwise, leave with exit reason
*/
virtual TInt WaitForExitL()
{
User::WaitForRequest(iLogonStatus);
const TInt exitType = iThread.ExitType();
const TInt exitReason = iThread.ExitReason();
__ASSERT_ALWAYS(exitType != EExitPending, User::Panic(_L("TTestThread"),0));
if(exitType != EExitKill)
User::Leave(exitReason);
return exitReason;
}
virtual void Rendezvous(TRequestStatus& aStatus)
{
iThread.Rendezvous(aStatus);
}
private:
void Init(const TDesC& aName, TThreadFunction aFn, TAny* aData, TBool aAutoResume)
{
TKName name(aName);
name.AppendFormat(_L("-%d"), iCount++);
TInt r=iThread.Create(name, aFn, KDefaultStackSize, KHeapSize, KHeapSize, aData);
User::LeaveIfError(r);
iThread.Logon(iLogonStatus);
__ASSERT_ALWAYS(iLogonStatus == KRequestPending, User::Panic(_L("TTestThread"),0));
if(aAutoResume)
iThread.Resume();
}
RThread iThread;
};
/**
Non blocking reads, verifying data as expected
*/
TInt TestThread2(TAny* aData)
{
RTest test(_L("t_pipe_t2"));
test.Start(_L("Thread 2"));
test.Printf(_L("THREAD 2 called by TestMultiThreadNamedPipes And TestMultiThreadUnNamedPipes\n"));
TBuf8<50> cPipeReadData;
TInt ret,readsize;
TData& data = *(TData *)aData; // aData will have pipe handles and size.
test.Next(_L("PIPE TEST:Thread 2-1 Read 1 byte of data from the pipe : Test for success\n"));
readsize = 1;
ret = data.iReadEnd->Read(cPipeReadData ,readsize);
test_Equal(readsize, ret);
test.Next(_L("PIPE TEST:Thread 2-2 Validate 1 byte received is correct\n"));
ret = cPipeReadData.Compare(KTestData1);
test_KErrNone(ret);
test.Next(_L("PIPE TEST:Thread 2-3 Read remaining data from the pipe\n"));
readsize = 21;
ret = data.iReadEnd->Read(cPipeReadData , readsize);
test_Equal(readsize, ret);
test.Next(_L("PIPE TEST:Thread 2-4 Validate received data\n"));
ret = cPipeReadData.Compare(KTestData3);
test_KErrNone(ret);
test.End();
test.Close();
return KErrNone;
}
/****************************************************************************
This function is used as thread to test Unnamed pipes.
TestMultiThreadUnNamedPipes() will use this function.
TestMultiThreadNamedPipes() will use this function.
@aData : Used to pass the pipe and handle its size information.
Return Value : TInt
******************************************************************************/
TInt TestThread3(TAny* aData) {
TInt ret, aWriteSize;
TBufC8<50> cTestData3(KTestData2); // Test Data
TData& data = *(TData *)aData; // aData will have pipe handles and size.
RTest test(_L("t_pipe_t3"));
test.Start(_L("Thread 3"));
test.Printf(_L(" THREAD 3 called by TestMultiThreadNamedPipes And TestMultiThreadUnNamedPipes\n"));
test.Next(_L("PIPE TEST:Thread 3-1 Call Write blocking and write data\n"));
// Call Writeblocking function. Write one byte of data.
aWriteSize = cTestData3.Length();
ret = data.iWriteEnd->WriteBlocking(cTestData3,aWriteSize);
test_Equal(aWriteSize, ret);
// Call Writeblocking function. Write aSize bye data.
// Write data so that pipe get filled.
test.Next(_L("PIPE TEST:Thread 3-2 Write data till pipe is filled up \n"));
ret = data.iWriteEnd->WriteBlocking(cTestData3,aWriteSize);
test_Equal(aWriteSize, ret);
test.End();
test.Close();
return KErrNone;
}
/****************************************************************************
This function is used as thread to test Unnamed pipes.
TestMultiThreadUnNamedPipes() will use this function.
@aData : Used to pass the pipe and handle its size information.
Return Value : TInt
******************************************************************************/
//TRequestStatus stat1;
TInt TestThread4(TAny* aData) {
TData& data = *(TData *)aData; // aData will have pipe handles and size.
TRequestStatus stat1;
TBuf8<150> cPipeReadData;
TInt ret;
RTest test(_L("t_pipe_t4"));
test.Start(_L("Thread 4"));
RSemaphore sem; // Handle to the global semaphore
ret = sem.OpenGlobal(KSemaphoreName); // Access to the global semaphore identified by its name.
test(ret == KErrNone);
test.Printf(_L("Thread 4:Created by TestNotifyMechanismPipes.\n"));
test.Next(_L("PIPE TEST:Thread 4-1 Register Notify Data available request.\n"));
data.iReadEnd->NotifyDataAvailable(stat1);
test_Equal(KRequestPending, stat1.Int());
sem.Signal(); //signal to say that we have issued notification request
test.Next(_L("PIPE TEST:Thread 4-2 Wait till notified for data. Check for Available.\n"));
User::WaitForRequest(stat1);
test ( stat1.Int() == KErrNone);
test.Next(_L("PIPE TEST:Thread 4-3 Read One byte of data from the pipe.\n"));
sem.Wait(); //wait for signal that 1 byte should be read
ret = data.iReadEnd->Read(cPipeReadData,1);
test (ret == 1);
test.Next(_L("PIPE TEST:Thread 4-4 Verify data is correct ?.\n"));
test (KErrNone == cPipeReadData.Compare(KTestData1));
test.Next(_L("PIPE TEST:Thread 4-5 Read remaining data from the pipe.\n"));
ret = data.iReadEnd->Read(cPipeReadData,21);
test (ret == 21);
test.Next(_L("PIPE TEST:Thread 4-6 Verify data is correct ?.\n"));
test (KErrNone == cPipeReadData.Compare(KTestData3));
sem.Signal(); //signalling to the main thread to continue its operation
sem.Close(); //closing the handle to the semaphore
test.End();
test.Close();
return KErrNone;
}
/****************************************************************************
This function is used as thread to test Unnamed pipes.
TestWaitMechanismPipes() will use this function.
@aData : Used to pass the pipe and handle its size information.
Return Value : TInt
******************************************************************************/
TInt TestThread5(TAny* aData) {
TData& data = *(TData *)aData; // aData will have pipe handles and size.
TRequestStatus stat1;
TInt ret;
RTest test(_L("t_pipe_t5"));
test.Start(_L("Thread 5"));
test.Printf(_L("PIPE TEST:Thread 5:Created by TestWaitMechanismPipes.\n"));
test.Next(_L("PIPE TEST:Thread 5-1:Register one more request to wait till open to read. It shall not allow\n"));
data.iWriteEnd->Wait(KPipe3Name, stat1);
test (stat1.Int() == KErrInUse);
data.iWriteEnd->WaitForReader(KPipe3Name, stat1);
test (stat1.Int() == KErrInUse);
test.Next(_L("PIPE TEST:Thread 5-2:Open Pipe handle to Read.\n"));
ret = data.iReadEnd->Open(KPipe3Name,RPipe::EOpenToRead);
test(ret == KErrNone);
test.End();
test.Close();
return KErrNone;
}
/**
The reader thread will wait till there is data in the pipe
and then continuously read till it has read the total length
of the pipe.
*/
TInt ReaderThread(TAny* aData) {
// Read data from Pipe
RTest test(KReaderThread);
test.Title();
test.Start(_L("Reader Thread"));
TData& data = *(TData *)aData;
TBuf8<10> pipeReadData;
const TInt sizeToRead = data.iReadEnd->MaxSize(); //attempt to read everything from pipe
TRequestStatus status(KErrGeneral);
//do read in loop in case thread is notified before pipe is full
TInt totalDataRead=0;
do
{
data.iReadEnd->NotifyDataAvailable(status);
test.Printf(_L("notify data request status is %d\n"), status.Int());
if(status==KRequestPending)
User::WaitForRequest(status);
test(status==KErrNone);
test.Printf(_L("ready to read data\n"), status.Int());
const TInt sizeRead = data.iReadEnd->Read(pipeReadData, sizeToRead);
test.Printf(_L("Read %d bytes from pipe\n"), sizeRead);
test(sizeRead>0);
totalDataRead+=sizeRead;
}
while(totalDataRead<sizeToRead);
test(totalDataRead==sizeToRead);
test.End();
test.Close();
return KErrNone;
}
_LIT8(KTestDataNum1 , "12345");
_LIT8(KTestDataNum , "1234567890");
/**
Write into pipe to completely fill it.
*/
TInt WriterThread(TAny* aData)
{
// Write data to pipe
RPipe* writeEnd = static_cast<TData*>(aData)->iWriteEnd;
RTest test(_L("WriterThread"));
test.Start(_L("WriterThread"));
writeEnd->Flush(); //make sure pipe is empty
const TInt sizeToWrite = writeEnd->MaxSize();
test.Printf(_L("Writing %d bytes in to pipe\n"), sizeToWrite);
TInt length=writeEnd->WriteBlocking(KTestDataNum1,sizeToWrite);
test(length==sizeToWrite);
test.End();
test.Close();
return KErrNone;
}
/**
The FlusherThread waits till the supplied pipe
is full before flushing it.
*/
TInt FlusherThread(TAny* aData)
{
TData& data = *(TData *)aData; // aData will have pipe handles and size.
//wait for pipe to fill, then flush
TRequestStatus status;
const TInt maxSize=data.iReadEnd->MaxSize();
do
{
data.iReadEnd->NotifyDataAvailable(status);
if(status==KRequestPending)
User::WaitForRequest(status);
if(status!=KErrNone)
return status.Int();
} while(data.iReadEnd->Size()<maxSize);
data.iReadEnd->Flush();
return KErrNone;
}
/****************************************************************************
This function is used as thread to test Unnamed pipes.
TestWaitMechanismPipes() will use this function.
@aData : Used to pass the pipe and handle its size information.
Return Value : TInt
******************************************************************************/
TInt CloseFlag;
TInt TestThread9(TAny* aData) {
TData& data = *(TData *)aData; // aData will have pipe handles and size.
if (CloseFlag == 1)
data.iReadEnd->Close();
if (CloseFlag == 0)
data.iWriteEnd->Close();
return 0;
}
/**
The test will create 2 threads running this function. They will
race to placing the blocking read request. The first
will succeed and wait, the second will write to pipe
*/
TInt ReadBlockThenWrite(TAny* aData) {
TData& data = *(TData *)aData; // aData will have pipe handles and size.
TBuf8<10> cReadData;
RTest test(_L("Concurrent blocking read"));
test.Start(_L("Call blocking read on pipe\n"));
TInt ret = data.iReadEnd->ReadBlocking(cReadData,5);
if(ret == KErrNone)
{
test_KErrNone(cReadData.Compare(KTestDataNum1));
}
if(ret == KErrInUse)
{
test.Next(_L("Other thread beat us - write to pipe so it may proceed"));
TInt write = data.iWriteEnd->Write(KTestDataNum,5);
test_Equal(5, write);
}
test.End();
test.Close();
return ret;
}
/**
The test will create 2 threads running this function. They will
race to placing the blocking write request. The first
will succeed and wait, the second will read from pipe
*/
TInt WriteBlockThenRead(TAny* aData) {
TData& data = *(TData *)aData; // aData will have pipe handles and size.
TBuf8<10> cReadData;
RTest test(_L("Concurrent blocking write"));
test.Start(_L("test writing blocked pipe\n"));
TInt ret = data.iWriteEnd->WriteBlocking(KTestDataNum,10);
if(ret == KErrInUse)
{
test.Next(_L("The other thread beat us - read from pipe so it may proceed"));
TInt read = data.iReadEnd->Read(cReadData,5);
test_Equal(5, read);
test_KErrNone(cReadData.Compare(KTestDataNum1));
}
test.End();
test.Close();
return ret;
}
/****************************************************************************
This function is used as thread to test Unnamed pipes.
TestWaitMechanismPipes() will use this function.
@aData : Used to pass the pipe and handle its size information.
Return Value : TInt
******************************************************************************/
TInt TestThread11(TAny* aData) {
TData& data = *(TData *)aData; // aData will have pipe handles and size.
TRequestStatus stat1;
TBufC<50> cPipeName(KPipe3Name); // Descriptor to hold data for Writing.
TInt ret;
RTest test(_L("t_pipe_t11"));
test.Start(_L("PIPE TEST:Thread 11:Created by TestWaitMechanismPipes.\n"));
test.Next(_L("PIPE TEST:Thread 11-1:Register one more request to wait till open to read. It shall not allow\n"));
data.iReadEnd->WaitForWriter(cPipeName, stat1);
test_Equal(KErrInUse, stat1.Int());
test.Next(_L("PIPE TEST:Thread 11-2:Open Pipe handle to write.\n"));
ret = data.iWriteEnd->Open(cPipeName,RPipe::EOpenToWrite);
test_KErrNone(ret);
test.End();
test.Close();
return KErrNone;
}
/****************************************************************************
This is a function to test Named/UnNamed pipes Performace.
Check the functionality of following library functions
-
-
******************************************************************************/
/**
- test that WriteBlocking unblocks
- when data is read
- whed date is flushed
- test that notify data available request is completed as data is read
- test that ReadBlocking unblocks
- test that data available notification works
*/
void TestBlockingAndNotify() {
TRequestStatus stat1;
RPipe aReader,aWriter;
TInt aSize,ret;
TBufC8<10> cPipeTestDataNum(KTestDataNum);
TBuf8<10> cReadData;
aSize = 5;
ret = RPipe::Create( aSize,
aReader,
aWriter,
EOwnerProcess, //
EOwnerProcess //
);
test_KErrNone(ret);
TData data( &aReader, &aWriter);
{
TTestThread readerThread(KReaderThread, ReaderThread, &data);
test.Start(_L("Test that WriteBlock unblocks as data is read from pipe\n"));
ret = aWriter.WriteBlocking(cPipeTestDataNum,10);
test(ret == 10);
test(aWriter.Size()==5);
aWriter.Flush();
test(aWriter.Size()==0);
ret = readerThread.WaitForExitL();
test_KErrNone(ret);
}
{
TTestThread flusherThread(KThread8Name, FlusherThread, &data);
test.Next(_L("Test that WriteBlock unblocks as data is flushed from read end of pipe\n"));
ret = aWriter.WriteBlocking(cPipeTestDataNum,10);
test (ret == 10);
ret = flusherThread.WaitForExitL();
test_KErrNone(ret);
}
test.Next(_L("Test that NotifyDataAvailable request is completed as data is read from pipe\n"));
aWriter.NotifySpaceAvailable(aSize,stat1);
test(stat1==KRequestPending);
{
TTestThread readerThread2(KReaderThread, ReaderThread, &data);
User::WaitForRequest(stat1);
test(stat1==KErrNone);
ret = readerThread2.WaitForExitL();
test_KErrNone(ret);
}
aReader.Flush();
test.Next(_L("PIPE TEST: Test that ReadBlocking unblocks\n"));
{
TTestThread writeThread(KWriterThread, WriterThread, &data);
ret = aReader.ReadBlocking(cReadData,5);
test(ret == 5);
ret = writeThread.WaitForExitL();
test_KErrNone(ret);
}
test.Next(_L("PIPE TEST: Test NotifyDataAvailable\n"));
aReader.Flush();
aReader.NotifyDataAvailable(stat1);
test(stat1==KRequestPending);
{
TTestThread writeThread2(KWriterThread,WriterThread, &data);
User::WaitForRequest(stat1);
test(stat1==KErrNone);
aReader.Flush();
ret = writeThread2.WaitForExitL();
test_KErrNone(ret);
}
test.Next(_L("PIPE TEST: Test reading from pipe closed by the writer\n"));
CloseFlag = 0; // 0 Close Write Handle
//CloseFlag = 1; // 1 Close Read Handle
test.Next(_L("PIPE TEST: TestBlockingAndNotify 10.6\n"));
TTestThread closeThread(KThread9Name, TestThread9, &data);
ret = closeThread.WaitForExitL();
test_KErrNone(ret);
ret = aReader.ReadBlocking(cReadData,5);
test_Equal(KErrNotReady, ret);
aWriter.Close();
aReader.Close();
aSize = 5;
ret = RPipe::Create( aSize,
aReader,
aWriter,
EOwnerProcess, //
EOwnerProcess //
);
test_KErrNone(ret);
TData data1(&aReader,&aWriter);
//CloseFlag = 0; // 0 Close Write Handle
CloseFlag = 1; // 1 Close Read Handle
test.Printf(_L("PIPE TEST: TestBlockingAndNotify 10.7\n"));
TTestThread closeThread2(KThread9Name, TestThread9, &data1);
ret = aWriter.WriteBlocking(cPipeTestDataNum,10);
test_Equal(KErrNotReady, ret);
ret = closeThread2.WaitForExitL();
test_KErrNone(ret);
aWriter.Close();
aReader.Close();
test.End();
}
/****************************************************************************
TestPipesPermissionCheck :
This function is used to test Permission and Access related
Errors of Pipes API.
APIs tested are Define , Create , Destroy , Read and Write.
******************************************************************************/
// Different pipes for different capability , VID values.
_LIT(KPipeName2, "PipeWithNoCap");
_LIT(KPipeName3, "PipeWithNoCapVID");
_LIT(KPipeName4, "PipeWithRWCap");
_LIT(KPipeName5, "PipeWithComDDCap");
_LIT(KPipeName6, "PipeWithRWComDDCap");
_LIT(KPipeName7, "PipeWithRWComDDCapVID");
_LIT(KPipeName8, "PipeWithRWRUCap");
// Different processes with different capability , VID values.
_LIT(KProcessNoCap, "t_pipe3.exe");
_LIT(KProcessRCap, "t_pipe5.exe");
// My VID and SID
_LIT_VENDOR_ID(MyVID,0x70000001);
void TestPipesPermissionCheck() {
RProcess proc;
TInt ret;
// Define TSecurity objects with different capabilities and VID .
TSecurityPolicy NoCapVID(MyVID,ECapability_None,ECapability_None,ECapability_None);
TSecurityPolicy RWCap(ECapabilityReadDeviceData,ECapabilityWriteDeviceData);
TSecurityPolicy ComDDCap(ECapabilityCommDD);
TSecurityPolicy RWComDDCap(ECapabilityReadDeviceData,ECapabilityCommDD,ECapabilityWriteDeviceData);
TSecurityPolicy RWComDDCapVID(MyVID,ECapabilityCommDD,ECapabilityReadDeviceData,ECapabilityWriteDeviceData);
TSecurityPolicy RWRUCap(ECapabilityReadUserData,ECapabilityReadDeviceData,ECapabilityWriteDeviceData);
// Define Named pipes with No Cap , combination of Cap and VID
TInt aSize = 10;
ret = RPipe::Define(KPipeName2, aSize);
test (ret == KErrNone);
ret = RPipe::Define(KPipeName3, aSize,NoCapVID);
test (ret == KErrNone);
ret = RPipe::Define(KPipeName4, aSize,RWCap);
test (ret == KErrNone);
ret = RPipe::Define(KPipeName5, aSize,ComDDCap);
test (ret == KErrNone);
ret = RPipe::Define(KPipeName6, aSize,RWComDDCap);
test (ret == KErrNone);
ret = RPipe::Define(KPipeName7, aSize,RWComDDCapVID);
test (ret == KErrNone);
ret = RPipe::Define(KPipeName8, aSize,RWRUCap);
test (ret == KErrNone);
//Lets see who can use pipes. Check for Permissions and Access
test.Next(_L("PIPE TEST:8.1 Create Process with No Cap t_pipe3.exe\n"));
ret = proc.Create (
KProcessNoCap, // Launch t_pipe3.exe process
KNullDesC // No arguments passed to t_pipe3.exe
);
if (ret != KErrNone)
{
test.Printf(_L(" ***** t_pipe3.exe could not start ****"));
}
test_KErrNone(ret);
test.Printf(_L("Process Created successfully"));
TRequestStatus procLogon;
proc.Logon(procLogon);
test(procLogon==KRequestPending);
proc.Resume();
User::WaitForRequest(procLogon);
proc.Close();
// Lets see what happens with Read Capability.
test.Next(_L("PIPE TEST:8.2 Create Process with Read-Write-CommDD Cap t_pipe5.exe\n"));
ret = RPipe::Define(KPipeName2, aSize);
test_KErrNone(ret);
ret = RPipe::Define(KPipeName3, aSize,NoCapVID);
test_KErrNone(ret);
ret = proc.Create (
KProcessRCap, // Launch t_pipe3.exe process
KNullDesC // No arguments passed to t_pipe3.exe
);
if (ret != KErrNone)
{
test.Printf(_L(" ***** t_pipe5.exe could not start ****"));
}
test_KErrNone(ret);
test.Printf(_L("Process Created successfully"));
proc.Logon(procLogon);
test(procLogon==KRequestPending);
proc.Resume();
User::WaitForRequest(procLogon);
proc.Close();
//the t_pipe5.exe process should destroy most of these
//but we call destroy again to verify this
ret = RPipe::Destroy (KPipeName2);
test_Equal(KErrNotFound, ret);
ret = RPipe::Destroy (KPipeName3);
test_KErrNone(ret); //KPipeName3 is not destroyed by the other process.
ret = RPipe::Destroy (KPipeName4);
test_Equal(KErrNotFound, ret);
ret = RPipe::Destroy (KPipeName5);
test_Equal(KErrNotFound, ret);
ret = RPipe::Destroy (KPipeName6);
test_Equal(KErrNotFound, ret);
ret = RPipe::Destroy (KPipeName7);
test_KErrNone(ret); //t_pipe5.exe does not have permission to delete
ret = RPipe::Destroy (KPipeName8);
test_KErrNone(ret); //t_pipe5.exe does not have permission to delete
return;
}
/****************************************************************************
TestMiscPipes :
This is a function to test Named/UnNamed pipes for all Misc test cases.
******************************************************************************/
void TestMiscPipes() {
_LIT(KInvalidPipeName,"PipeNotExist");
TInt ret,aSize;
RPipe aReader,aWriter;
TBufC<50> cPipeName(KInvalidPipeName); // Descriptor to hold data for Writing.
TBufC8<50> cPipeTestData2(KTestData2);
// Try to create unnamed pipe with Negative size
test.Next(_L("PIPE TEST:9.1 Create Pipe of Negative Size.\n"));
aSize = -1;
ret = RPipe::Create( aSize,
aReader,
aWriter,
EOwnerProcess, //
EOwnerProcess //
);
test( ret == KErrArgument);
// Try to create unnamed pipe with zero size
test.Next(_L("PIPE TEST:9.2 Create Pipe with of Zero size.\n"));
aSize = 0;
ret = RPipe::Create( aSize,
aReader,
aWriter,
EOwnerProcess, //
EOwnerProcess //
);
test( ret == KErrArgument);
// Try to define named pipe with Negative size
test.Next(_L("PIPE TEST:9.3 Define Pipe of Negative size.\n"));
aSize = -1;
ret = RPipe::Define(cPipeName, aSize);
test( ret == KErrArgument);
// Try to define named pipe with Zero size
test.Next(_L("PIPE TEST:9.4 Define Pipe of Zero size.\n"));
aSize = 0;
ret = RPipe::Define(cPipeName, aSize);
test( ret == KErrArgument);
// Try to destroy pipe which does not exists
test.Next(_L("PIPE TEST:9.5 Try to destroy named pipe which do not exist.\n"));
ret = RPipe::Destroy (cPipeName);
test (ret == KErrNotFound);
// Try to read from pipe with invalid length data to be read
RPipe aReaderUN,aWriterUN;
TBuf8<150> cPipeReadData;
aSize = 10;
ret = RPipe::Create( aSize,
aReaderUN,
aWriterUN,
EOwnerProcess, //
EOwnerProcess //
);
test (ret == KErrNone );
test.Next(_L("PIPE TEST:9.6 Try calling ReadBlocking using write handle and WriteBlocking using Read handle.\n"));
ret = aWriterUN.ReadBlocking(cPipeReadData, aSize);
test (ret == KErrAccessDenied);
ret = aReaderUN.WriteBlocking(cPipeTestData2,aSize);
test (ret == KErrAccessDenied);
test.Next(_L("PIPE TEST:9.7 Read negative size data from un-named pipe.\n"));
aSize = -1;
ret = aReaderUN.Read(cPipeReadData, aSize);
test( ret == KErrArgument);
ret = aWriterUN.Write(cPipeTestData2,aSize);
test( ret == KErrArgument);
test.Next(_L("PIPE TEST:9.8 Read/Write zero size data from/to un-named pipe\n"));
aSize = 0;
ret = aReaderUN.Read(cPipeReadData, aSize);
test( ret == KErrNone);
ret = aWriterUN.Write(cPipeTestData2,aSize);
test( ret == KErrNone);
test.Next(_L("PIPE TEST:9.9 Call ReadBlocking and WriteBlocking to Read and Write negative size data.\n"));
// Try to readblocking from pipe with invalid length data to be read
aSize = -1;
ret = aReaderUN.ReadBlocking(cPipeReadData, aSize);
test( ret == KErrArgument);
ret = aWriterUN.WriteBlocking(cPipeTestData2,aSize);
test( ret == KErrArgument);
test.Next(_L("PIPE TEST:9.10 ReadBlocking/WriteBlocking to read/write zero size data.\n"));
aSize = 0;
ret = aReaderUN.ReadBlocking(cPipeReadData, aSize);
test( ret == KErrArgument);
ret = aWriterUN.WriteBlocking(cPipeTestData2,aSize);
test( ret == KErrArgument);
test.Next(_L("PIPE TEST:9.11 Try calling ReadBlocking and WriteBlocking using un opened RPipe handles.\n"));
RPipe aReaderT,aWriterT;
ret = aReaderT.ReadBlocking(cPipeReadData, aSize);
test (ret == KErrBadHandle);
ret = aWriterT.WriteBlocking(cPipeTestData2,aSize);
test (ret == KErrBadHandle);
aReaderUN.Close();
aWriterUN.Close();
return;
}
/****************************************************************************
This is a function to test notify mechanism of pipes.
Check the functionality of following library functions
- Notify...()
******************************************************************************/
void TestWaitMechanismPipes() {
RPipe aReader,aWriter; // Used to pass to thread.
RPipe aWriter2;
TInt ret;
TBufC<50> cPipeName(KPipe3Name); // Descriptor to hold data for Writing.
TInt aSize;
TRequestStatus stat1;
aSize = 22 * 10; // Sizeof(KTestData) * 10
ret = RPipe::Define( cPipeName,aSize);
ret = aWriter.Open(cPipeName,RPipe::EOpenToWrite);
test (ret == KErrNone);
test.Next(_L("PIPE TEST:7.1 Try calling Wait function on BadPipe name.\n"));
_LIT(KBadPipeName , "***R$@#$@#%#$%#^.12-.");
aWriter.Wait(KBadPipeName,stat1);
test(stat1.Int() == KErrBadName);
aWriter.WaitForReader(KBadPipeName,stat1);
test(stat1.Int() == KErrBadName);
_LIT(KBadPipeName2 , "");
aWriter.Wait(KBadPipeName2,stat1);
test(stat1.Int() == KErrBadName);
aWriter.WaitForReader(KBadPipeName2,stat1);
test(stat1.Int() == KErrBadName);
test.Next(_L("PIPE TEST:7.2 Try calling Wait function on non existing Pipe\n"));
_LIT(KInvalidPipe , "NotExistingPipe");
aWriter.Wait(KInvalidPipe,stat1);
test(stat1.Int() == KErrNotFound);
aWriter.WaitForReader(KInvalidPipe,stat1);
test(stat1.Int() == KErrNotFound);
test.Next(_L("PIPE TEST:7.3 Try calling Wait function on Pipe name length more than maxlength.\n"));
aWriter.Wait(KMaxPipeNamePlusOne,stat1);
test(stat1.Int() == KErrBadName);
aWriter.WaitForReader(KMaxPipeNamePlusOne,stat1);
test(stat1.Int() == KErrBadName);
test.Next(_L("PIPE TEST:7.4 Try calling Wait function from unopened handle.\n"));
aWriter2.Wait(cPipeName, stat1);
test (stat1.Int() == KErrInUse);
aWriter2.WaitForReader(cPipeName, stat1);
test (stat1.Int() == KErrInUse);
test.Next(_L("PIPE TEST:7.5 Register a valid Wait Request .\n"));
aWriter.Wait(cPipeName, stat1);
TData data( &aReader, &aWriter);
// Create Thread 5
// Pass TData object with Write and Read handle both
TTestThread thread5(KThread5Name, TestThread5, &data);
User::WaitForRequest(stat1);
ret = thread5.WaitForExitL();
test_KErrNone(ret);
test.Next(_L("PIPE TEST:7.6 After Wait finish check the value of status register.\n"));
test_KErrNone(stat1.Int());
aWriter.Close();
aReader.Close();
ret = aWriter.Open(cPipeName,RPipe::EOpenToWrite);
test_KErrNone(ret);
ret = aReader.Open(cPipeName,RPipe::EOpenToRead);
test_KErrNone(ret);
test.Next(_L("PIPE TEST:7.7 After Read handle is open , register request to Wait\n"));
aWriter.Wait(cPipeName, stat1);
test (stat1.Int() == KErrNone);
test.Next(_L("PIPE TEST:7.8 Check for CancelWait.\n"));
aWriter.Close();
aReader.Close();
ret = aWriter.Open(cPipeName,RPipe::EOpenToWrite);
TRequestStatus stat2;
aWriter.Wait(cPipeName, stat1);
aWriter.Wait(cPipeName, stat2);
test(stat2.Int() == KErrInUse);
aWriter.CancelWait();
test(stat1.Int() == KErrCancel);
test(stat2.Int() == KErrInUse);
aWriter.Wait(cPipeName, stat1);
ret = aReader.Open(cPipeName,RPipe::EOpenToRead);
test(stat1.Int() == KErrNone);
test.Next(_L("PIPE TEST:7.9 Check Wait and CancelWait from reader end\n"));
aWriter.Close();
aReader.Close();
ret = aReader.Open(cPipeName,RPipe::EOpenToRead);
aReader.Wait(cPipeName, stat1);
test (stat1.Int() == KErrAccessDenied);
aReader.CancelWait();
aWriter.Close();
aReader.Close();
RPipe::Destroy(cPipeName);
/*****************Newly added tests for CR 1114 - WaitForReader *********/
ret = RPipe::Define( cPipeName,aSize);
ret = aWriter.Open(cPipeName,RPipe::EOpenToWrite);
test (ret == KErrNone);
test.Next(_L("PIPE TEST:7.10 Register a valid Wait Request .\n"));
aWriter.WaitForReader(cPipeName, stat1);
test(stat1==KRequestPending);
// Create Thread 5
// Pass TData object with Write and Read handle both
{
TTestThread thread5_1(KThread5Name, TestThread5, &data);
User::WaitForRequest(stat1);
ret = thread5_1.WaitForExitL();
test_KErrNone(ret);
}
test.Next(_L("PIPE TEST:7.11 After Wait finish check the value of status register.\n"));
aWriter.Close();
aReader.Close();
ret = aWriter.Open(cPipeName,RPipe::EOpenToWrite);
ret = aReader.Open(cPipeName,RPipe::EOpenToRead);
aReader.WaitForReader(cPipeName, stat1);
test (stat1.Int() == KErrAccessDenied);
test.Next(_L("PIPE TEST:7.12 After Read handle is open , register request to Wait\n"));
aWriter.WaitForReader(cPipeName, stat1);
test (stat1.Int() == KErrNone);
test.Next(_L("PIPE TEST:7.13 Check for CancelWait.\n"));
aWriter.Close();
aReader.Close();
ret = aWriter.Open(cPipeName,RPipe::EOpenToWrite);
aWriter.WaitForReader(cPipeName, stat1);
aWriter.WaitForReader(cPipeName, stat2);
test(stat2.Int() == KErrInUse);
aWriter.CancelWait();
test(stat1.Int() == KErrCancel);
test(stat2.Int() == KErrInUse);
aWriter.WaitForReader(cPipeName, stat1);
ret = aReader.Open(cPipeName,RPipe::EOpenToRead);
test(stat1.Int() == KErrNone);
// Release all the resources.
aWriter.Close();
aReader.Close();
// Create Thread 5
// Pass TData object with Write and Read handle both
test.Next(_L("PIPE TEST:7.14 Register a valid Wait Request .\n"));
aWriter.WaitForReader(cPipeName, stat1);
{
TTestThread thread5_2(KThread5Name, TestThread5, &data);
User::WaitForRequest(stat1);
ret = thread5_2.WaitForExitL();
test_KErrNone(ret);
}
test.Next(_L("PIPE TEST:7.15 After Wait finish close the handles.\n"));
test (stat1.Int() == KErrNone);
aWriter.Close();
aReader.Close();
// Release all the resources.
ret = RPipe::Destroy(cPipeName);
test_KErrNone(ret);
/*****************Newly added tests for CR 1114 - WaitForWriter *********/
ret = RPipe::Define( cPipeName,aSize);
test_KErrNone(ret);
ret = aReader.Open(cPipeName,RPipe::EOpenToRead);
test (ret == KErrNone);
// Create Thread 11
// Pass TData object with Write and Read handle both
test.Next(_L("PIPE TEST:7.16 Register a valid Wait Request .\n"));
aReader.WaitForWriter(cPipeName, stat1);
test(stat1==KRequestPending);
{
TTestThread thread11(KThread11Name, TestThread11, &data);
User::WaitForRequest(stat1);
ret = thread11.WaitForExitL();
test_KErrNone(ret);
}
test.Next(_L("PIPE TEST:7.17 After Wait finish check the value of status register.\n"));
aWriter.Close();
aReader.Close();
ret = aWriter.Open(cPipeName,RPipe::EOpenToWrite);
test_KErrNone(ret);
ret = aReader.Open(cPipeName,RPipe::EOpenToRead);
test_KErrNone(ret);
aWriter.WaitForWriter(cPipeName, stat1);
test (stat1.Int() == KErrAccessDenied);
test.Next(_L("PIPE TEST:7.18 After Write handle is open , register request to Wait\n"));
aReader.WaitForWriter(cPipeName, stat1);
test (stat1.Int() == KErrNone);
test.Next(_L("PIPE TEST:7.19 Check for CancelWait.\n"));
aWriter.Close();
aReader.Close();
ret = aReader.Open(cPipeName,RPipe::EOpenToRead);
aReader.WaitForWriter(cPipeName, stat1);
aReader.WaitForWriter(cPipeName, stat2);
test(stat2.Int() == KErrInUse);
aReader.CancelWait();
test(stat1.Int() == KErrCancel);
test(stat2.Int() == KErrInUse);
aReader.WaitForWriter(cPipeName, stat1);
ret = aWriter.Open(cPipeName,RPipe::EOpenToWrite);
test(stat1.Int() == KErrNone);
// Release all the resources.
aWriter.Close();
aReader.Close();
// Create Thread 11
// Pass TData object with Write and Read handle both
test.Next(_L("PIPE TEST:7.20 Register a valid Wait Request .\n"));
aReader.WaitForWriter(cPipeName, stat1);
{
TTestThread thread11_2(KThread11Name, TestThread11, &data);
User::WaitForRequest(stat1);
test.Next(_L("PIPE TEST:7.21 After Wait finish , close the hadles.\n"));
test (stat1.Int() == KErrNone);
ret = thread11_2.WaitForExitL();
test_KErrNone(ret);
// Release all the resources.
aWriter.Close();
aReader.Close();
}
ret = RPipe::Destroy(cPipeName);
test_KErrNone(ret);
/**********************************************************/
// Define the pipe.
ret = RPipe::Define( cPipeName,aSize);
test(ret == KErrNone);
// Wait for Writer.
aReader.WaitForWriter(cPipeName, stat1);
// Try to open read end again. It should not open because WaitForWriter
// will has already opened the Read End of the pipe.
ret = aReader.Open(cPipeName ,RPipe::EOpenToRead );
test(ret = KErrInUse );
// Status of the wait request is pending because writer is not opened yet.
test (stat1.Int() == KRequestPending);
// Wait on Reader.
aWriter.WaitForReader(cPipeName , stat2);
// Reader was already opened so status is KErrNone.
test ( stat2.Int() == KErrNone);
// Try to open Write end. It should not allow because WaitForReader has
// already opened the write end of the pipe.
ret = aWriter.Open(cPipeName ,RPipe::EOpenToWrite);
test (ret == KErrInUse);
// Check the status of the WaitForWriter request. It should be KErrNone now.
test (stat1.Int() == KErrNone);
// Let's check for pipe attributes.
ret = aReader.MaxSize();
test (ret = aSize);
ret = aWriter.MaxSize();
test (ret = aSize);
ret = aReader.Size();
test (ret = aSize);
ret = aWriter.Size();
test (ret = aSize);
// Close the Reade handle.
aReader.Close();
// Put request to wait for Reader.
aWriter.WaitForReader(cPipeName , stat2);
// It should be pending.
test ( stat2.Int() == KRequestPending);
// Open the reader end of the pipe. It should allow , KErrNone
ret = aReader.Open(cPipeName ,RPipe::EOpenToRead );
test ( stat2.Int() == KErrNone);
test (ret == KErrNone);
aReader.Close();
aWriter.Close();
ret=RPipe::Destroy(cPipeName);
test_KErrNone(ret);
return;
}
/****************************************************************************
This is a function to test notify mechanism of pipes.
Check the functionality of following library functions
- Notify...()
******************************************************************************/
void TestNotifyMechanismPipes() {
// Test NotifyDataAvailable , NotifySpaceAvailable
RSemaphore globalSem; // Handle to a global semaphore. Semaphore is used to maintain synchronisation between thread4 and the main thread
TInt ret; // Return Value variable.
RPipe aReader,aWriter; // Used to pass to thread.
RPipe aReader2,aWriter2; // Used to pass to thread.
TInt aSize; // Used to pass to thread.
const TBufC<50> cPipeName(KPipe1Name); // Descriptor to hold data for Writing.
TRequestStatus stat1;
TBuf8<50> cPipeTestData1(KTestData2);
const TBufC<50> cSemaphoreName(KSemaphoreName); // Descriptor conataining the name of the global semaphore.
ret = globalSem.CreateGlobal(cSemaphoreName,0); //create and open a global semaphore with initial count as 0.
test (ret == KErrNone);
aSize = 22; // Size of KTestData * 10
ret = RPipe::Create( aSize,
aReader,
aWriter,
EOwnerProcess, //
EOwnerProcess //
);
TData data( &aReader, &aWriter);
// Create Thread 4
// Pass TData object with Write and Read handle both
test.Next(_L("PIPE TEST:6.1 Call CancelDataAvailable/CancelSpaceAvailable using unopened RPipe handles.\n"));
ret = aReader2.CancelDataAvailable();
test ( ret == KErrBadHandle);
ret = aWriter2.CancelSpaceAvailable();
test (ret == KErrBadHandle);
test.Next(_L("PIPE TEST:6.2 Call NotifySpaceAvailable with Negative size \n"));
// Call Notfifyspace
TInt tempsize = -1;
aWriter.NotifySpaceAvailable(tempsize, stat1);
test ( stat1.Int() == KErrArgument);
test.Next(_L("PIPE TEST:6.2a Call NotifySpaceAvailable for space larger than pipe.\n"));
aWriter.NotifySpaceAvailable(aSize+1, stat1);
test_Equal( KErrArgument, stat1.Int());
// Start the thread
{
TTestThread thread4(KThread4Name, TestThread4, &data);
// Thread 4
// Call Notifydata available
// Loop for Available
// Read the data and validate
test.Next(_L("PIPE TEST:6.3 Write data into the pipe , verify return value.\n"));
// Write one byte data into the pipe.
globalSem.Wait(); //wait before writing to ensure that other thread can register Data Available request while pipe is empty.
ret = aWriter.Write(cPipeTestData1,cPipeTestData1.Length());
test (ret == cPipeTestData1.Length());
test.Next(_L("PIPE TEST:6.4 Call NotifySpaceAvailable with valid parameters \n"));
tempsize = 1;
aWriter.NotifySpaceAvailable(tempsize, stat1);
test(stat1==KRequestPending);
globalSem.Signal(); //signal that thread 4 may go ahead and read 1 byte
test.Next(_L("PIPE TEST:6.5 Wait till request says AVAILABLE. Available ?\n"));
User::WaitForRequest(stat1);
test ( stat1.Int() == KErrNone || stat1.Int() == KErrCompletion);
// Thread 4
// Notify data available
// Loop for available
// Flush the buffer
// Register two request for Notifydata available
// Register two request for Notifyspace available
// Call Notifydata available using Read handle
// Call Notifydata available using write handle
// return
// Check for Error conditions
// Flush buffer
globalSem.Wait(); // this is waiting for a signal from thread4
test.Next(_L("PIPE TEST:6.6 Register Notification for space availability. Allows ?\n"));
ret = aWriter.Write(cPipeTestData1,cPipeTestData1.Length());
ret = aWriter.Write(cPipeTestData1,cPipeTestData1.Length());
// Register two request for Notifyspace available
aWriter.NotifySpaceAvailable(tempsize, stat1);
test_Equal(KRequestPending, stat1.Int() );
test.Next(_L("PIPE TEST:6.7 Register One more Notification for space availability. Allows ?\n"));
TRequestStatus tempstat1;
aWriter.NotifySpaceAvailable(tempsize, tempstat1);
test ( tempstat1.Int() == KErrInUse);
test.Next(_L("PIPE TEST:6.7a Cancellation of non-outstanding requests must not disrupt oustanding requests\n"));
aWriter.CancelWait();
aWriter.NotifySpaceAvailable(tempsize, tempstat1);
test_Equal( KErrInUse, tempstat1.Int());
test.Next(_L("PIPE TEST:6.8 Cancel all the pending Notifications.\n"));
ret = aWriter.CancelSpaceAvailable();
test ( ret == KErrNone);
test_Equal(KErrCancel, stat1.Int() );
test.Next(_L("PIPE TEST:6.9 Try to cancel some more notifications. It should not allow\n"));
ret = aWriter.CancelSpaceAvailable();
test ( ret == KErrNone);
test.Next(_L("PIPE TEST:6.10 Register Notification for Data availability. Allows ?\n"));
// Register two request for Notifydata available
aWriter.Flush();
aReader.NotifyDataAvailable(stat1);
test.Next(_L("PIPE TEST:6.11 Register One More Notification for Data availability. Allows ?\n"));
aReader.NotifyDataAvailable(tempstat1);
test ( ( tempstat1.Int() == KErrInUse) || (tempstat1.Int() == KErrCompletion));
test.Next(_L("PIPE TEST:6.12 Cancel all the pending Notifications for Data.\n"));
ret = aReader.CancelDataAvailable();
test ( ( ret == KErrNone) || (ret == KErrNotFound));
test (stat1.Int() == KErrCancel);
test.Next(_L("PIPE TEST:6.13 Try to cancel some more notifications. It should not allow\n"));
ret = aReader.CancelDataAvailable();
test ( ret == KErrNone);
test.Next(_L("PIPE TEST:6.14 Try to register Data available notification using Write handle. Should not allow.\n"));
aWriter.NotifyDataAvailable(stat1);
test ( stat1.Int() == KErrAccessDenied);
test.Next(_L("PIPE TEST:6.15 Try to register Space available notification using Read handle. Should not allow.\n"));
aReader.NotifySpaceAvailable(tempsize, stat1);
test ( stat1.Int() == KErrAccessDenied);
test.Next(_L("PIPE TEST:6.16 Try to Cancel Data available notification using Write handle. Should not allow.\n"));
ret = aWriter.CancelDataAvailable();
test ( ret == KErrAccessDenied);
test.Next(_L("PIPE TEST:6.17 Try to Cancel Space available notification using Write handle. Should not allow.\n"));
ret = aReader.CancelSpaceAvailable();
test ( ret == KErrAccessDenied);
// Stop the thread and Close the Thread
ret = thread4.WaitForExitL();
}
test_KErrNone(ret);
// Close all the pipe handles.
aReader.Close();
aWriter.Close();
test.Printf(_L(" TEST NOTIFICATION MECHNISM FOR NAMED PIPES\n"));
aSize = 22; // Size of KTestData
test.Next(_L("PIPE TEST:6.18 Create Named pipe and Open Read/Write Handles.\n"));
ret = RPipe::Define( cPipeName,aSize);
test (ret == KErrNone);
ret = aReader.Open(cPipeName,RPipe::EOpenToRead);
test (ret == KErrNone);
ret = aWriter.Open(cPipeName,RPipe::EOpenToWrite);
test (ret == KErrNone);
TData data2( &aReader, &aWriter);
// Create Thread 4
// Pass TData object with Write and Read handle both
TTestThread thread4a(KThread4Name, TestThread4, &data2);
// Thread 4
// Call Notifydata available
// Loop for Available
// Read the data and validate
// Write one byte data into the pipe.
test.Next(_L("PIPE TEST:6.19 Write Data and check for return value.\n"));
globalSem.Wait(); //wait before writing to ensure that other thread can register Data Available request while pipe is empty.
ret = aWriter.Write(cPipeTestData1,cPipeTestData1.Length());
test (ret == cPipeTestData1.Length());
test.Next(_L("PIPE TEST:6.20 Register Notification for Space Available.\n"));
// Call Notfifyspace
tempsize = 1;
aWriter.NotifySpaceAvailable(tempsize, stat1);
test(stat1==KRequestPending);
globalSem.Signal(); //signal that thread 4 may go ahead and read byte
test.Next(_L("PIPE TEST:6.21 Wait till notified for Space Availanle.\n"));
User::WaitForRequest(stat1);
test ( stat1.Int() == KErrNone);
// Thread 4
// Read one byte of data
// Thread 4
// Notify data available
// Loop for available
// Flush the buffer
// Register two request for Notifydata available
// Register two request for Notifyspace available
// Call Notifydata available using Read handle
// Call Notifydata available using write handle
// return
globalSem.Wait(); //waiting for a signal from thread4.
test.Next(_L("PIPE TEST:6.22 Notify for Space available.\n"));
// Register two request for Notifydata available
ret = aWriter.Write(cPipeTestData1,cPipeTestData1.Length());
aWriter.NotifySpaceAvailable(tempsize, stat1);
test.Next(_L("PIPE TEST:6.23 Notify one more notifier for Space available.\n"));
// Register two request for Notifyspace available
TRequestStatus notifyStatus;
aWriter.NotifySpaceAvailable(tempsize, notifyStatus);
test ( notifyStatus.Int() == KErrInUse);
aWriter.Flush();
aWriter.NotifySpaceAvailable(tempsize, stat1);
test ( stat1.Int() == KErrNone);
test.Next(_L("PIPE TEST:6.24 Cancel Notify for Space available.\n"));
ret = aWriter.CancelSpaceAvailable();
test (( ret == KErrNotFound) ||( ret == KErrNone));
test.Next(_L("PIPE TEST:6.25 Cancel one more Notify for Space available.\n"));
ret = aWriter.CancelSpaceAvailable();
test ( ret == KErrNone);
test.Next(_L("PIPE TEST:6.26 Register Notify for Data available.\n"));
// Register two request for Notifydata available
aWriter.Flush();
TRequestStatus stat5,stat6;
aReader.NotifyDataAvailable(stat5);
test.Next(_L("PIPE TEST:6.27 Register One more Notify for Data available.\n"));
// Register two request for Notifyspace available
aReader.NotifyDataAvailable(notifyStatus);
test ( notifyStatus.Int() == KErrInUse);
test.Next(_L("PIPE TEST:6.28 Cancel Notify for Data available.\n"));
ret = aReader.CancelDataAvailable();
test ( ret == KErrNone);
test (stat5.Int() == KErrCancel);
test.Next(_L("PIPE TEST:6.29 Cancel One more Notify for Data available.\n"));
ret = aReader.CancelDataAvailable();
test ( ret == KErrNone);
test.Next(_L("PIPE TEST:6.30 Register Notify for Data available using Write handle\n"));
aWriter.NotifyDataAvailable(stat6);
test ( stat6.Int() == KErrAccessDenied);
test.Next(_L("PIPE TEST:6.31 Register Notify for Space available using Read handle\n"));
aReader.NotifySpaceAvailable(tempsize, stat6);
test ( stat6.Int() == KErrAccessDenied);
test.Next(_L("PIPE TEST:6.32 Cancel Notify for Data available using Write handle\n"));
ret = aWriter.CancelDataAvailable();
test ( ret == KErrAccessDenied);
test.Next(_L("PIPE TEST:6.33 Cancel Notify for Space available using Read handle\n"));
ret = aReader.CancelSpaceAvailable();
test ( ret == KErrAccessDenied);
//close the handle to the global semaphore
globalSem.Close();
// Stop the thread and Close the Thread
ret = thread4a.WaitForExitL();
test_KErrNone(ret);
aReader.Close();
aWriter.Close();
RPipe::Destroy(cPipeName);
return;
} // End TestNotifyMechanismPipes()
/****************************************************************************
This is a function to test Named pipes in Mutli process environment.
Check the functionality of following library functions
- Define ()
-
******************************************************************************/
_LIT8(KTestDataIP, "ABCDEFGHIJ");
void TestMultiProcessNamedPipes() {
_LIT(KPipeName5, "InterProcessPipe1");
TInt ret; // Return value variable
RProcess proc; // Process Handle
RPipe aWriter;
RPipe aWriterUN,aReaderUN;
const TBufC<150> cPipeName1(KPipeName5);
TBufC8<150> cPipeWriteData1(KTestDataIP);
TInt aSize;
TRequestStatus stat1;
TBuf8<150> cPipeReadData1;
aSize = 10;
// Define Pipe with valid size.
test.Next(_L("PIPE TEST:5.1 Define Pipe and Create UnNAmed pipe and pass handle to other process.\n"));
ret = RPipe::Define(cPipeName1, aSize);
test_KErrNone(ret);
ret = proc.Create(
KProcessName, // Launch t_pipe2.exe process
KNullDesC // No arguments passed to t_pipe2.exe
);
if (ret != KErrNone) {
// Check for process successfully launched
test.Printf(_L("Error : Could not start the process t_pipe2.exe \n"));
}
test_KErrNone(ret);
TRequestStatus procLogon;
proc.Logon(procLogon);
test(procLogon==KRequestPending);
aSize = 512;
ret = RPipe::Create( aSize,
aReaderUN,
aWriterUN,
EOwnerProcess,//TOwnerType aTypeW
EOwnerProcess //TOwnerType aTypeW
);
test_KErrNone(ret);
ret = aWriterUN.Write(KTestData,22);
test (ret == 22);
ret = aReaderUN.Read(cPipeReadData1,10);
test ( ret == 10);
aWriterUN.Close();
ret = aReaderUN.Read(cPipeReadData1,6);
test (ret == 6);
aReaderUN.NotifyDataAvailable(stat1);
ret = stat1.Int();
test (ret == KErrNone);
ret = aReaderUN.ReadBlocking(cPipeReadData1,6);
test (ret == 6);
ret = aReaderUN.Read(cPipeReadData1,1);
test ( ret == KErrNotReady);
ret = aReaderUN.ReadBlocking(cPipeReadData1,1);
test ( ret == KErrNotReady);
aReaderUN.Close();
ret = RPipe::Create( aSize,
aReaderUN,
aWriterUN,
EOwnerProcess,//TOwnerType aTypeW
EOwnerProcess //TOwnerType aTypeW
);
test_KErrNone(ret);
proc.SetParameter(3,aReaderUN);
aReaderUN.Close();
ret = aWriterUN.Write(KTestData,22);
test (ret == 22 );
proc.Resume();
aSize = 10;
test.Next(_L("PIPE TEST:5.2 Open Write handle to Pipe. Wait till Read handle Opened\n"));
ret = aWriter.Open(cPipeName1, RPipe::EOpenToWrite);
test_KErrNone(ret);
aWriter.Wait(cPipeName1,stat1);
User::WaitForRequest(stat1);
test (stat1.Int() == KErrNone);
test.Next(_L("PIPE TEST:5.3 Write data to Pipe.\n"));
ret = aWriter.Write(cPipeWriteData1,cPipeWriteData1.Length());
test ( ret == cPipeWriteData1.Length());
test.Next(_L("PIPE TEST:5.4 Wait till Space Available in Pipe.\n"));
aWriter.NotifySpaceAvailable(aSize,stat1);
User::WaitForRequest(stat1);
test.Next(_L("PIPE TEST:5.5 Write the data using WriteBlocking call\n"));
test_Equal(0, aWriter.Size());
ret = aWriter.WriteBlocking(cPipeWriteData1,cPipeWriteData1.Length());
test ( ret ==cPipeWriteData1.Length() );
User::WaitForRequest(procLogon);
aWriter.Close();
ret=RPipe::Destroy(cPipeName1);
test_KErrNone(ret);
proc.Close();
aWriterUN.Close();
aReaderUN.Close();
return;
} // End TestMultiProcessNamedPipes ()
/****************************************************************************
This is a function to test Named pipes in Multi threaded environment.
Check the functionality of following library functions
- Define ()
- Read()
- Write()
- ReadBlocking()
- WriteBlocking()
******************************************************************************/
//
// Test defining and opening both ends of pipe
// Attempt to readblock from pipe closed at far end (should fail)
// Attemp writeblock to pipe closed at far end
//
// Do some normal reading and writing between threads
// do some blocking read/write between threads
void TestMultiThreadNamedPipes() {
TInt ret; // Return Value variable.
RPipe aReader,aWriter; // Used to pass to thread.
TInt aSize; // Used to pass to thread.
const TBufC<50> cPipeName(KPipe1Name); // Descriptor to hold data for Writing.
TInt aReadSize;
TBuf8<150> cPipeReadData;
TBufC8<50> cTestData(KTestData); // Test Data
///////////////////////////////////////////////////////////
// PART : 1 ///
// Test Read and Write Functionality ///
///////////////////////////////////////////////////////////
test.Next(_L("PIPE TEST:4.1 Define Pipe , Open Read and Write Handle.\n"));
aSize = 22;
ret = RPipe::Define( cPipeName,aSize);
test (ret == KErrNone);
ret = aReader.Open(cPipeName,RPipe::EOpenToRead);
test (ret == KErrNone);
ret = aWriter.Open(cPipeName,RPipe::EOpenToWrite);
test (ret == KErrNone);
aWriter.Close();
test.Next(_L("PIPE TEST:4.2 ReadBlocking: Check for KErrNotReady.\n"));
aReadSize = 1;
ret = aReader.ReadBlocking(cPipeReadData,aReadSize);
test (ret == KErrNotReady);
ret = aWriter.Open(cPipeName,RPipe::EOpenToWrite);
test (ret == KErrNone);
aReader.Close();
test.Next(_L("PIPE TEST:4.3 WriteBlocking: Check for KErrNotReady.\n"));
ret = aWriter.WriteBlocking(cTestData,cTestData.Length());
test (ret == KErrNotReady);
ret = aReader.Open(cPipeName,RPipe::EOpenToRead);
test (ret == KErrNone);
TData data( &aReader, &aWriter);
// Write data to Pipe using valid handle
test.Next(_L("PIPE TEST:4.4 Write into the pipe and verify return value.\n"));
ret = aWriter.Write(cTestData,cTestData.Length());
test (ret == cTestData.Length() );
// Keep writing the data into pipe till it overflows
test.Next(_L("PIPE TEST:4.5 Write into the pipe till it overflows.\n"));
ret = aWriter.Write(cTestData,cTestData.Length());
test (( ret == KErrOverflow)) ;
// Start the thread.
TTestThread thread2(KThread2Name, TestThread2, &data);
// Read 1 byte data from pipe
// Validate data
// Read aByte size data
// Validate data
// Thread 2
// Read aByte size data
// User:: After (10000)
// Keep reading data till zero return
// return
// Stop the thread and Close the Thread
ret = thread2.WaitForExitL();
test_KErrNone(ret);
aReader.Close();
aWriter.Close();
ret = RPipe::Destroy(cPipeName);
test_KErrNone(ret);
///////////////////////////////////////////////////////////
// PART : 2 ///
// Test ReadBlocking and WriteBlocking Functionality ///
///////////////////////////////////////////////////////////
// Test Read and Write blocking call
test.Next(_L("PIPE TEST:4.6 Create UnNamed Pipe with valid size.\n"));
aSize = 22;
ret = RPipe::Define( cPipeName,aSize);
test (ret == KErrNone);
ret = aReader.Open(cPipeName,RPipe::EOpenToRead);
test (ret == KErrNone);
ret = aWriter.Open(cPipeName,RPipe::EOpenToWrite);
test (ret == KErrNone);
// Create TData object to pass Pipe handles.
TData data2( &aReader, &aWriter);
// Create Thread ( Note : Thread is in pending state now)
// Flush the data if any in pipe to make sure its empty.
aWriter.Flush();
// Start the thread
TTestThread thread3(KThread3Name, TestThread3, &data2);
// Thread 3
// Write one byte of data
// Write one one byte of data using WriteBlocking call
// Write aByte size data using Writblocking call
// Call Readblocking function.Read one byte of data.
test.Next(_L("PIPE TEST:4.7 Flush the buffer and Call ReadBlocking one byte into the pipe.\n"));
aReadSize = 1;
ret = aReader.ReadBlocking(cPipeReadData,aReadSize);
test_Equal(aReadSize, ret);
test.Next(_L("PIPE TEST:4.8 Verify the data received.\n"));
test ( KErrNone == cPipeReadData.Compare(KTestData1));
test.Next(_L("PIPE TEST:4.9 Call ReadBlocking and read complete data from Pipe. As big as Pipe Size\n"));
// Call Readblocking function.Read aSize bytes of data.
aReadSize = aSize-aReadSize; //read rest of data
ret = aReader.ReadBlocking(cPipeReadData,aReadSize);
test_Equal(aReadSize, ret);
test ( KErrNone == cPipeReadData.Compare(KTestData3));
// Thread 3
// Wait for some time
// Call Readblocking and read 1 byte of data
// Call Readblocking and Read abyte size data
// Call flush buffer
// return
test.Next(_L("PIPE TEST:4.10 Call ReadBlocking and read complete data from Pipe. As big as Pipe Size\n"));
// Call Readblocking function.Read aSize bytes of data.
aReadSize = aSize;
ret = aReader.ReadBlocking(cPipeReadData,aReadSize);
test_Equal(aReadSize, ret);
test ( KErrNone == cPipeReadData.Compare(KTestData2));
// Stop the thread and Close the Thread
ret = thread3.WaitForExitL();
test_KErrNone(ret);
aReader.Close();
aWriter.Close();
ret=RPipe::Destroy(cPipeName);
test_KErrNone(ret);
return ;
} // End TestMultiThreadNamedPipes ()
/****************************************************************************
This is a function to test UnNamed pipes in Multi threaded environment.
Check the functionality of following library functions
- Create()
- Read()
- Write()
- ReadBlocking()
- WriteBlocking()
******************************************************************************/
void TestMultiThreadUnNamedPipes() {
TInt ret; // Return Value variable.
RPipe aReader,aWriter; // Used to pass to thread.
TInt aSize; // Used to pass to thread.
TBuf8<250> cPipeReadData;
TInt aReadSize;
TBufC8<50> cTestData(KTestData); // Test Data
///////////////////////////////////////////////////////////
// PART : 1 ///
// Test Read and Write Functionality ///
///////////////////////////////////////////////////////////
test.Next(_L("PIPE TEST: 3.1 Create Pipe : Check for no erros on Pipe Creation \n"));
ret = 100;
aSize = 22; // Size of KTestData * 10
ret = RPipe::Create( aSize,
aReader,
aWriter,
EOwnerProcess ,//TOwnerType aTypeW
EOwnerProcess //TOwnerType aTypeW
);
test (ret == KErrNone);
// Create TData object to pass Pipe handles.
TData data1( &aReader, &aWriter);
// Create Thread ( Note : Thread is in pending state now)
// Create test data stream.
test.Next(_L("PIPE TEST: 3.2 Write Function test : Write data into the pipe \n"));
ret = aWriter.Write(cTestData,cTestData.Length()); // Write ""Pipe Data To Be Passed"
test (ret == cTestData.Length());
// Keep writing the data into pipe till it overflows
test.Next(_L("PIPE TEST: 3.3 Write Data till the Pipe returns KErrOverFlow\n"));
ret = aWriter.Write(cTestData,cTestData.Length());
test ( ret == KErrOverflow);
TTestThread thread2(KThread2Name, TestThread2, &data1);
// Thread2
// Read 1 byte data from pipe
// Validate data
// Read aByte size data
// Validate data
// Thread 2
// Read aByte size data
// User:: After (10000)
// Keep reading data till zero return
// return
// Stop the thread , Close it.
ret = thread2.WaitForExitL();
test_KErrNone(ret);
aReader.Close();
aWriter.Close();
///////////////////////////////////////////////////////////
// PART : 2 ///
// Test ReadBlocking and WriteBlocking Functionality ///
///////////////////////////////////////////////////////////
aSize = 22; // Size of KTestData
ret = RPipe::Create( aSize,
aReader,
aWriter,
EOwnerProcess , //TOwnerType aTypeW
EOwnerProcess //TOwnerType aTypeW
);
test_KErrNone(ret);
// Create TData object to pass Pipe handles.
TData data2(&aReader, &aWriter);
// Flush the data if any in pipe to make sure its empty.
aWriter.Flush();
// Start the thread
TTestThread thread3(KThread3Name, TestThread3, &data2);
// Thread 3
// Write one byte of data
// Write one one byte of data using WriteBlocking call
// Write aByte size data using Writblocking call
// Call Readblocking function.Read one byte of data.
aReadSize = 1;
test.Next(_L("PIPE TEST: 3.4 : Call readblocking and read one byte of data \n"));
ret = aReader.ReadBlocking(cPipeReadData,aReadSize);
// Call goes to Thread 3
test_Equal(aReadSize, ret);
test.Next(_L("PIPE TEST: 3.5 : Validate the data \n"));
test_Equal(0, cPipeReadData.Compare(KTestData1));
// Call Readblocking function.Read aSize bytes of data.
test.Next(_L("PIPE TEST: 3.6 : Read remaining data \n"));
aReadSize = 21;
ret = aReader.ReadBlocking(cPipeReadData,aReadSize);
test_Equal(aReadSize, ret);
test_Equal(0, cPipeReadData.Compare(KTestData3));
test.Next(_L("PIPE TEST: 3.7 : Read complete pipe size data \n"));
aReadSize = 22;
ret = aReader.ReadBlocking(cPipeReadData,aReadSize);
test_Equal(aReadSize, ret);
test_Equal(0, cPipeReadData.Compare(KTestData2));
// Wait for thread to end and Close
ret = thread3.WaitForExitL();
test_KErrNone(ret);
aReader.Close();
aWriter.Close();
return ;
}// End TestMultiThreadUnNamedPipes()
/****************************************************************************
This is a function to test Named pipes in Single threaded environment.
Check the functionality of following library functions
- Define ()
-
******************************************************************************/
void TestSingleThreadNamedPipes()
{
const TBufC<50> cPipeName(KPipe1Name); // Descriptor to hold data for Writing.
TInt aSize, ret;
RPipe testPipe1;
RPipe testPipe2;
RPipe testPipe3;
RPipe testPipe4;
RPipe testPipe5;
const TBufC<100> cPipeNameMax(KMaxPipeName);
const TBufC<100> cPipeNameMaxPlusOne(KMaxPipeNamePlusOne);
_LIT(KBadName , "***?SFSDFWE?*_-");
_LIT(KBadName2 , "");
test.Next(_L("PIPE TEST: 2.1 Define Function test : Check for No Error\n"));
aSize = 10;
ret = RPipe::Define(cPipeName , aSize);
test (ret == KErrNone);
ret = RPipe::Destroy (cPipeName);
test (ret == KErrNone);
test.Next(_L("PIPE TEST: 2.2 Define Function test : Check for Max length \n"));
aSize = 10;
ret = RPipe::Define(cPipeNameMax , aSize);
test (ret == KErrNone);
ret = RPipe::Destroy (cPipeNameMax);
test (ret == KErrNone);
test.Next(_L("PIPE TEST: 2.3 Define Function test : Check for Max length \n"));
aSize = 10;
ret = RPipe::Define(cPipeNameMaxPlusOne , aSize);
test (ret == KErrBadName);
ret = RPipe::Destroy (cPipeNameMaxPlusOne);
test (ret == KErrBadName);
test.Next(_L("PIPE TEST: 2.4 Open Function test : Test Open \n"));
aSize = 10;
ret = RPipe::Define(cPipeName , aSize);
test_KErrNone(ret);
ret = testPipe1.Open(KBadName,RPipe::EOpenToRead);
test (ret == KErrBadName);
ret = testPipe1.Open(KBadName2,RPipe::EOpenToRead);
test (ret == KErrBadName);
ret = testPipe1.Open(cPipeName,RPipe::EOpenToRead);
test (ret == KErrNone);
ret = testPipe1.Open(cPipeName,RPipe::EOpenToWrite);
test (ret == KErrInUse);
test.Next(_L("PIPE TEST: 2.5 Destroy Function test : Destroy opened pipe error \n"));
ret = RPipe::Destroy (cPipeName);
test (ret == KErrInUse);
test.Next(_L("PIPE TEST: 2.6 Open Function test : Reopen pipe for reading\n"));
ret = testPipe2.Open(cPipeName,RPipe::EOpenToRead);
test (ret == KErrInUse);
test.Next(_L("PIPE TEST: 2.7 Open Function test : Bad name test \n"));
ret = testPipe2.Open(cPipeNameMaxPlusOne,RPipe::EOpenToRead);
test (ret == KErrBadName);
test.Next(_L("PIPE TEST: 2.8 Open Function test : Write mode test\n"));
ret = testPipe3.Open(cPipeName,RPipe::EOpenToWrite);
test (ret == KErrNone);
ret = testPipe3.Open(cPipeName,RPipe::EOpenToRead);
test (ret == KErrInUse);
test.Next(_L("PIPE TEST: 2.9 Open Function test : Bad name test \n"));
ret = testPipe4.Open(cPipeNameMaxPlusOne,RPipe::EOpenToWrite);
test (ret == KErrBadName);
test.Next(_L("PIPE TEST: 2.10 Open Function test : Reopen for writing \n"));
ret = testPipe4.Open(cPipeName,RPipe::EOpenToWrite);
test (ret == KErrInUse);
// Do we have pipes created ? Close and Destroy them ....!!
testPipe1.Close();
testPipe2.Close();
testPipe3.Close();
testPipe4.Close();
ret = RPipe::Destroy (cPipeName);
test_KErrNone(ret);
test.Next(_L("PIPE TEST: 2.11a Open Function test : Write But Fail on no Readers mode before pipe defined\n"));
ret = testPipe1.Open(cPipeName,RPipe::EOpenToWriteNamedPipeButFailOnNoReaders);
test_Equal(KErrNotFound,ret);
test.Next(_L("PIPE TEST: 2.11 Open Function test : Write But Fail on no Readers mode Error test\n"));
ret = RPipe::Define(cPipeName , aSize);
test (ret == KErrNone);
ret = testPipe1.Open(cPipeName,RPipe::EOpenToWriteNamedPipeButFailOnNoReaders);
test (ret == KErrNotReady);
test.Next(_L("PIPE TEST: 2.12 Open Function test : Write But Fail on no Readers mode Success test\n"));
ret = testPipe1.Open(cPipeName,RPipe::EOpenToRead);
test_KErrNone(ret);
ret = testPipe2.Open(cPipeName,RPipe::EOpenToWriteNamedPipeButFailOnNoReaders);
test ( ret == KErrNone);
// Do we have pipes created ? Close and Destroy them ....!!
testPipe1.Close();
testPipe2.Close();
testPipe3.Close();
testPipe4.Close();
ret = RPipe::Destroy (cPipeName);
test_KErrNone(ret);
test.Next(_L(" 2.13 Define Function test : Check Incorrect Size\n"));
aSize = -1;
ret = RPipe::Define(cPipeName , aSize);
test (ret == KErrArgument);
test.Next(_L("PIPE TEST: 2.14 Define Function test : Check Incorrect Size\n"));
aSize = 0x1fffffff;
ret = RPipe::Define(cPipeName , aSize);
test (ret == KErrNoMemory);
test.Next(_L("PIPE TEST: 2.15 Size Function test : Size\n"));
aSize = 10;
ret = RPipe::Define(cPipeName , aSize);
ret = testPipe5.MaxSize();
test (ret == KErrBadHandle);
test.Next(_L("PIPE TEST: 2.16 Size Function test : Size\n"));
aSize = 10;
ret = RPipe::Define(cPipeName , aSize);
testPipe5.Open(cPipeName, RPipe::EOpenToRead);
testPipe4.Open(cPipeName, RPipe::EOpenToWrite);
ret = testPipe5.MaxSize();
test (ret == aSize);
ret = testPipe4.MaxSize();
test (ret == aSize);
/* Close all the pipes and Destroy*/
testPipe1.Close();
testPipe2.Close();
testPipe3.Close();
testPipe4.Close();
testPipe5.Close();
ret = RPipe::Destroy (cPipeName);
test_KErrNone(ret);
_LIT(KRedefinePipe , "REDEFINEPIPE");
test.Next(_L("PIPE TEST: 2.17 Check for Redefining same pipe name \n"));
ret = RPipe::Define(KRedefinePipe , aSize);
test_KErrNone(ret);
ret = RPipe::Define(KRedefinePipe , aSize);
test (ret == KErrAlreadyExists);
ret = RPipe::Destroy (KRedefinePipe);
test_KErrNone(ret);
test.Next(_L("PIPE TEST: 2.18 Open Function test : Bad Pipe name\n"));
aSize = 10;
RPipe testPipe6;
ret = testPipe6.Open(cPipeName, RPipe::EOpenToRead);
test (ret == KErrNotFound);
const TBufC<50> cPipeNameNull;
test.Next(_L("PIPE TEST: 2.19 Define Function test : Null Pipe name and Bad Pipe name\n"));
aSize = 10;
ret = RPipe::Define(cPipeNameNull , aSize);
test (ret == KErrBadName);
ret = RPipe::Define(KBadName , aSize);
test (ret == KErrBadName);
ret = RPipe::Destroy(KBadName);
test (ret == KErrBadName);
ret = RPipe::Define(KBadName2 , aSize);
test (ret == KErrBadName);
ret = RPipe::Destroy(KBadName2);
test (ret == KErrBadName);
test.Next(_L("PIPE TEST: 2.20 Destroy a pipe while Write end is open\n"));
ret = RPipe::Define(cPipeName , aSize);
testPipe1.Close();
ret = testPipe1.Open(cPipeName,RPipe::EOpenToRead);
test (ret == KErrNone);
testPipe2.Close();
ret = testPipe2.Open(cPipeName,RPipe::EOpenToWrite);
test (ret == KErrNone);
testPipe1.Close();
ret = RPipe::Destroy (cPipeName);
test (ret == KErrInUse);
testPipe2.Close();
ret = RPipe::Destroy (cPipeName);
test (ret == KErrNone);
testPipe1.Close();
testPipe2.Close();
testPipe3.Close();
testPipe4.Close();
testPipe5.Close();
_LIT(KPipe1Name,"TestPipeA");
_LIT(KPipe2Name,"TestPipeB");
_LIT(KPipe3Name,"TestPipeC");
_LIT(KPipe4Name,"TestPipeD");
test.Next(_L("PIPE TEST: 2.21 Define Four pipes and Destroy in different sequence ( Code Coverage test)\n"));
ret = RPipe::Define(KPipe1Name , aSize);
test (ret == KErrNone);
ret = RPipe::Define(KPipe2Name , aSize);
test (ret == KErrNone);
ret = RPipe::Define(KPipe3Name , aSize);
test (ret == KErrNone);
ret = RPipe::Define(KPipe4Name , aSize);
test (ret == KErrNone);
ret = RPipe::Destroy (KPipe2Name);
test (ret == KErrNone);
ret = RPipe::Destroy (KPipe4Name);
test (ret == KErrNone);
ret = RPipe::Destroy (KPipe1Name);
test (ret == KErrNone);
ret = RPipe::Destroy (KPipe3Name);
test (ret == KErrNone);
return;
} // End TestSingleThreadNamedPipes()
/****************************************************************************
This is a function to test UnNamed pipes in Single threaded environment.
Check the functionality of following library functions
- Create ()
-
******************************************************************************/
_LIT8(KTxtDataToSend,"*Test data to send**");
void TestSingleThreadUnNamedPipes() {
TInt ret = 1; // Return value test variable.
TInt aSize;
TBufC8<40> wData(KTxtDataToSend); // Descriptor to hold data for Writing.
RPipe aReader,aWriter;
RPipe aReader2,aWriter2;
// Following tests will verify all the APIs in single thread
// for all the possible return values.
// This is to verify different paths of API
// not for detail functional verification.
// Create the Pipe and Check for No Errors when Valid parameters are passed.
test.Next(_L("PIPE TEST:1.1 Create Function test : Check for No Error\n"));
aSize = 10;
ret = RPipe::Create( aSize,
aReader,
aWriter,
EOwnerProcess,//TOwnerType aTypeW
EOwnerProcess //TOwnerType aTypeW
);
test (ret == KErrNone);
ret = RPipe::Create( aSize,
aReader,
aWriter,
EOwnerProcess,//TOwnerType aTypeW
EOwnerProcess //TOwnerType aTypeW
);
test (ret == KErrInUse);
aWriter.Close();
aReader.Close();
// How big pipe we can create ?
test.Next(_L("PIPE TEST:1.2 Create Function test : Check for No Memory\n"));
aSize = 0x1BCDEFFF;
ret = RPipe::Create( aSize,
aReader2,
aWriter2,
EOwnerProcess,//TOwnerType aTypeW
EOwnerProcess //TOwnerType aTypeW
);
test (ret == KErrNoMemory);
aReader2.Close();
aWriter2.Close();
test.Next(_L("PIPE TEST:1.3 Create Function test : Check for Reopening pipe\n"));
aSize = 10;
ret = RPipe::Create( aSize,
aReader,
aWriter,
EOwnerProcess,//TOwnerType aTypeW
EOwnerProcess//TOwnerType aTypeW
);
test_KErrNone(ret);
ret = RPipe::Create( aSize,
aReader,
aWriter,
EOwnerProcess,//TOwnerType aTypeW
EOwnerProcess//TOwnerType aTypeW
);
test (ret == KErrInUse);
aReader.Close();
aWriter.Close();
test.Next(_L("PIPE TEST:1.4 Read/Write Function test : Check for Writing to pipe\n"));
aSize = 100;
ret = RPipe::Create( aSize,
aReader,
aWriter,
EOwnerProcess,//TOwnerType aTypeW
EOwnerProcess//TOwnerType aTypeW
);
test_KErrNone(ret);
ret=aWriter.Write(wData , wData.Size());
test (ret == wData.Size() );
ret=aWriter.Write(wData , -1);
test (ret == KErrArgument );
test.Next(_L("PIPE TEST:1.5 Read/Write Function test : Check for Reading from pipe\n"));
TBuf8<100> rData ;// Descriptor for reading data from Pipe.
ret=aReader.Read(rData,wData.Size()); // Length of the data to be read from Pipe
test (ret == wData.Size());// Length of the data read from the Pipe
test.Next(_L("PIPE TEST:1.6 Read/Write Function test : Validate data received\n"));
test (KErrNone == rData.Compare(wData));
test.Next(_L("PIPE TEST:1.7 Read/Write Function test : Check for Reading from pipe\n"));
ret=aReader.Read(rData,1);
test (ret == 0);
{
RPipe aReaderT, aWriterT;
aSize = 20;
ret = RPipe::Create( aSize,
aReaderT,
aWriterT,
EOwnerProcess,//TOwnerType aTypeW
EOwnerProcess//TOwnerType aTypeW
);
test_KErrNone(ret);
ret=aWriterT.Write(wData ,15);
test_Equal(15, ret);
ret = aReaderT.Read(rData,10);
test_Equal(10, ret);
ret=aWriterT.Write(wData ,10);
test_Equal(10, ret);
ret = aReaderT.Read(rData,20);
test (ret ==15);
ret = aReaderT.Read(rData,5);
test_Equal(0, ret);
ret = aReaderT.Read(rData,25);
test_Equal(0, ret);
aReaderT.Close();
aWriterT.Close();
}
test.Next(_L("PIPE TEST:1.8 Read/Write Function test : Check for Wrong RPipe Handle\n"));
ret=aWriter.Read(rData,15 );// Length of the data to be read from Pipe
test (ret == KErrAccessDenied );
test.Next(_L("PIPE TEST:1.9 Read/Write Function test : Check for Wrong RPipe Handle\n"));
ret=aReader.Write(rData,rData.Size());
test (ret == KErrAccessDenied );
test.Next(_L("PIPE TEST:1.10 Read/Write Function test : Check for write overflow\n"));
ret=aWriter.Write(wData,wData.Size());
ret=aWriter.Write(wData,wData.Size());
ret=aWriter.Write(wData,wData.Size());
ret=aWriter.Write(wData,wData.Size());
ret=aWriter.Write(wData,wData.Size());
ret=aWriter.Write(wData,wData.Size());
test (ret == KErrOverflow );
test.Next(_L("PIPE TEST:1.11 MaxSize Function test : MaxSize Check \n"));
aSize = 10;
// Just to be on safer side , close pipes if any.
aReader.Close();
aWriter.Close();
ret = RPipe::Create( aSize,
aReader,
aWriter,
EOwnerProcess,//TOwnerType aTypeW
EOwnerProcess//TOwnerType aTypeW
);
test (ret == KErrNone); // This error condition is not defined yet.
ret =aReader.MaxSize();
test (ret == aSize);
test.Next(_L("PIPE TEST:1.12 Size Function test : Size Check \n"));
rData.Zero();
ret = aReader.Size();
test_Equal(0, ret);
_LIT8(KSizeTestData1,"123456789");
ret = aWriter.Write(KSizeTestData1,9);
test_Equal(9, ret);
ret = aReader.Size();
test_Equal(9, ret);
ret = aReader.Read(rData,1);
test_Equal(1, ret);
ret = rData.Compare(_L8("1"));
test_KErrNone(ret);
ret = aReader.Size();
test_Equal(8, ret);
_LIT8(KSizeTestData2,"ab");
ret = aWriter.Write(KSizeTestData2,2);
test_Equal(2, ret);
ret = aReader.Size();
test_Equal(10, ret);
ret = aWriter.Write(KSizeTestData2,1);
test_Equal(KErrOverflow, ret);
ret = aReader.Size();
test_Equal(10, ret);
ret = aReader.Read(rData,9);
test_Equal(9, ret);
ret = rData.Compare(_L8("23456789a"));
test_KErrNone(ret);
ret = aReader.Size();
test_Equal(1, ret);
ret = aReader.Read(rData,1);
test_Equal(1, ret);
ret = rData.Compare(_L8("b"));
test_KErrNone(ret);
ret = aReader.Size();
test_Equal(0, ret);
ret = aWriter.Size();
test_Equal(0, ret);
RPipe WrongPipeHandle;
ret = WrongPipeHandle.Size();
test ( ret == KErrBadHandle);
test.Next(_L("PIPE TEST:1.13 Size Function test : Size Function call with Wrong handle \n"));
ret = WrongPipeHandle.MaxSize();
test (ret == KErrBadHandle);
aReader.Close();
aWriter.Close();
aReader2.Close();
aWriter2.Close();
test.Next(_L("PIPE TEST:1.14 Read Function : KErrNotReady \n"));
aSize = 10;
ret = RPipe::Create( aSize,
aReader,
aWriter,
EOwnerProcess,//TOwnerType aTypeW
EOwnerProcess//TOwnerType aTypeW
);
test (ret == KErrNone); // This error condition is not defined yet.
aWriter.Close();
ret = aReader.Read(rData,aSize);
test (ret == KErrNotReady);
ret = aReader.Read(rData,110);
test (ret == KErrArgument);
test.Next(_L("PIPE TEST:1.15 Check Handle Type function \n"));
aReader.Close();
aWriter.Close();
aSize = 10;
ret = RPipe::Create( aSize,
aReader,
aWriter,
EOwnerProcess,//TOwnerType aTypeW
EOwnerProcess//TOwnerType aTypeW
);
test_KErrNone(ret);
ret = aReader.HandleType();
test (ret == RPipe::EReadChannel);
ret = aWriter.HandleType();
test (ret == RPipe::EWriteChannel);
aReader.Close();
ret = aReader.HandleType();
test (ret == KErrBadHandle);
test.Next(_L("PIPE TEST:1.16 Write Function : KErrNotReady \n"));
aSize = 1;
ret = aWriter.Write(wData,aSize);
test (ret == KErrNotReady);
test.Next(_L("PIPE TEST:1.17 Write Function : Write data more than size of Descriptor \n"));
ret = aWriter.Write(wData,110);
test (ret == KErrArgument);
test.Next(_L("PIPE TEST:1.18 Write Function : KErrCompletion \n"));
aWriter.Close();
ret = RPipe::Create( aSize,
aReader,
aWriter,
EOwnerProcess,//TOwnerType aTypeW
EOwnerProcess//TOwnerType aTypeW
);
test_KErrNone(ret);
ret = aWriter.Write(wData,wData.Size());
test (ret == KErrOverflow);
test.Next(_L("PIPE TEST:1.19 Create Function : KErrInUse \n"));
aReader.Close();
ret = RPipe::Create( aSize,
aReader,
aWriter,
EOwnerProcess,//TOwnerType aTypeW
EOwnerProcess//TOwnerType aTypeW
);
test (ret == KErrInUse);
aWriter.Close();
ret = RPipe::Create( aSize,
aReader,
aWriter,
EOwnerProcess,//TOwnerType aTypeW
EOwnerProcess//TOwnerType aTypeW
);
test (ret == KErrNone);
aWriter.Close();
ret = RPipe::Create( aSize,
aReader,
aWriter,
EOwnerProcess,//TOwnerType aTypeW
EOwnerProcess//TOwnerType aTypeW
);
test (ret == KErrInUse);
test.Next(_L("PIPE TEST:1.20 Read / Write using un opened handles \n"));
RPipe aReaderT,aWriterT;
ret = aWriterT.Write(wData,wData.Size());
test (ret == KErrBadHandle);
ret = aReaderT.Read(rData,aSize);
test (ret == KErrBadHandle);
// Close all the pipes and return the resources.
aReader.Close();
aWriter.Close();
aReader2.Close();
aWriter2.Close();
return;
} // End TestSingleThreadUnNamedPipes()
/****************************************************************************
This is a function to test UnNamed pipes and named pipes in Single
threaded environment.
This test ensures that the memory is actually being released when:
RPipe::Close() is called for unnamed pipes and
RPipe::Destroy() is called for named pipes.
******************************************************************************/
void TestCreateClosePipe()
{
//unnamed pipes
RPipe readHandle, writeHandle;
const TInt K3MB = 1024*1024*3;
// The loop is run ten times to ensure that if memory allocated while pipe
// creation is not deallocated by close,then creation of pipe will fail with
// KErrNoMemory in the sixth iteration. Default heap size is assumed.
TInt i;
test.Next(_L("PIPE TEST:11.1 Create Function test in a loop : Check for No Error\n"));
for(i=1; i<10; i++)
{
TInt r = RPipe::Create(K3MB, readHandle, writeHandle,EOwnerProcess, EOwnerProcess);
test(KErrNone == r);
readHandle.Close();
writeHandle.Close();
}
//named pipes
_LIT(KPipeName, "testPipe");
// The loop is run ten times to ensure that if memory allocated while pipe
// creation is not deallocated by destroy,then creation of pipe will fail with
// KErrNoMemory in the sixth iteration. Default heap size is assumed.
test.Next(_L("PIPE TEST:11.2 Define Function test in a loop : Check for No Error\n"));
for(i=1; i<10; i++)
{
TInt r = RPipe::Define(KPipeName,K3MB);
test(KErrNone == r);
r = RPipe::Destroy(KPipeName);
test(KErrNone == r);
}
}// End TestCreateClosePipe()
struct TStressArgs
{
TStressArgs(TInt aIter, TInt aSize)
:iIter(aIter), iSize(aSize)
{}
const TInt iIter;
const TInt iSize;
};
struct TDefDesArgs: public TStressArgs
{
TDefDesArgs(TInt aIter, TInt aSize, const TDesC& aName)
:TStressArgs(aIter,aSize), iName(aName)
{}
const TDesC& iName;
};
/**
Repeatedly define and destroy named pipe
*/
TInt DefineDestroy(TAny* aArgs)
{
const TDefDesArgs args = *static_cast<TDefDesArgs*>(aArgs);
for(TInt i=0; i<args.iIter; i++)
{
TInt r = RPipe::Define(args.iName, args.iSize);
if(r!=KErrNone && r!=KErrAlreadyExists)
{
return r;
}
r = RPipe::Destroy(args.iName);
if(r!=KErrNone && r!=KErrInUse && r!=KErrNotFound)
{
return r;
}
}
return KErrNone;
}
/**
The parent thread will try to repeatedly open and close a named pipe
which is being repeatedly created and destroyed by the child thread.
This attempts to catch race conditions.
*/
void TestRapidDefineDestroy()
{
const TInt iterations=1000;
TDefDesArgs args(iterations, 16, KPipe1Name);
RPipe pipe;
TTestThread thread(_L("DefineDestroy"), DefineDestroy, &args);
TInt r=KErrNone;
for(TInt i=0; i<args.iIter; i++)
{
r = pipe.Open(args.iName, RPipe::EOpenToWrite);
if(r!=KErrNone && r !=KErrNotFound)
{
test_KErrNone(r);
}
pipe.Close();
}
r = thread.WaitForExitL();
test_KErrNone(r);
}
/**
Write the descriptor specified in to the pipe repeating
as many times as specified by TData::iIterations
*/
TInt WriteThread(TAny* aData)
{
TData& data = *static_cast<TData*>(aData);
const TInt iter = data.iIterations;
TInt write=0;
for(TInt i=0; i<iter; i++)
{
write = data.iWriteEnd->WriteBlocking(*data.iPipeData, data.iPipeData->Size());
if(write <KErrNone)
{
return write;
}
}
return write*iter;
}
/**
Fill descriptor with random bytes
*/
void FillRandom(TDes8& aDes)
{
aDes.Zero();
while(aDes.Size()+4<=aDes.MaxSize())
{
TUint8 rand[4];
*(TUint32*)rand = Math::Random();
aDes.Append(rand, 4);
}
}
/**
@param aTotalBytes Bytes transfered in period
@param aTicks number of ticks elapsed in period
@return The rate of the transfer on kilobytes per second
*/
TReal KiloBytesPerSecond(TInt aTotalBytes, TInt aTicks)
{
TInt period=0; //period of nanotick in microseconds
TInt r = HAL::Get(HAL::ENanoTickPeriod, period);
User::LeaveIfError(r);
//we use the definition that a kilobytes is 1000 bytes
TReal result = (aTotalBytes/(aTicks*period/1000));
return result;
}
/**
Create a source data buffer of aTotal bytes and fill with random data.
Create a pipe and thread (WriteThread) to write the source buffer
into the pipe.
Read from the pipe into destination buffer
and optionally verify that buffers match
@param aTotal Size of data buffer
@param aPipeData Size of pipe to create
@param aIter number of times to repeat transfer
@param aVerify Confirm that destination buffer matches source buffer
@param aPollRead read pipe by polling instead of using blocking read
@return Total number of ticks elapsed
*/
TInt TestLoopBack(TInt aTotal, TInt aPipeSize, TInt aIter, TBool aVerify=ETrue, TBool aPollRead=EFalse)
{
const TInt bufferSize = aTotal;
RBuf8 sourceBuffer;
sourceBuffer.CreateL(bufferSize);
FillRandom(sourceBuffer);
test_Equal(bufferSize,sourceBuffer.Size());
const TInt pipeSize=aPipeSize;
RPipe readEnd, writeEnd;
TInt r = RPipe::Create(pipeSize, readEnd, writeEnd ,EOwnerProcess, EOwnerProcess);
test_KErrNone(r);
const TInt maxIter=aIter;
TData data(NULL, &writeEnd, &sourceBuffer, maxIter);
RBuf8 destBuffer;
destBuffer.CreateL(bufferSize);
RBuf8 tempBuffer;
tempBuffer.CreateL(bufferSize);
TTestThread writer(_L("LoopBack"), WriteThread, &data);
const TUint32 startTicks=User::NTickCount();
for(TInt iter=0; iter<maxIter; iter++)
{
TInt remainingData = bufferSize;
do
{
const TInt toRead = Min(pipeSize,remainingData);
if(aPollRead)
{
//an inefficient way to read a pipe!
r = readEnd.Read(tempBuffer, toRead);
test_NotNegative(r);
}
else
{
r = readEnd.ReadBlocking(tempBuffer, toRead );
test_Equal(toRead, r);
}
destBuffer+=tempBuffer;
tempBuffer.Zero();
remainingData-=r;
}
while(remainingData);
if(aVerify)
{
r = sourceBuffer.Compare(destBuffer);
test_KErrNone(r);
}
destBuffer.Zero();
}
const TUint32 endTicks = User::NTickCount();
r = writer.WaitForExitL();
test_Equal(bufferSize*maxIter, r);
const TUint32 ticksElapsed= endTicks - startTicks;
sourceBuffer.Close();
tempBuffer.Close();
destBuffer.Close();
readEnd.Close();
writeEnd.Close();
return ticksElapsed;
}
/**
Simple test to confirm that data is reproduced after being fed through a pipe
*/
void TestTransferIntegrity()
{
TestLoopBack(128*1024, 128, 1, ETrue);
TestLoopBack(1024, 1, 1, ETrue);
//read by constantly polling
TestLoopBack(128*1024, 1024, 1, ETrue, ETrue);
}
/**
Enable Writeblocking and Readblocking notifications
without actual reads and writes
*/
class RTestPipe: public RPipe
{
public:
void RequestWriteBlocking(TInt aNumByte, TRequestStatus& aStatus)
{
DoRequest(EWriteBlocking, aStatus, &aNumByte);
}
void RequestReadBlocking(TRequestStatus& aStatus)
{
DoRequest(EReadBlocking, aStatus);
}
};
/**
A test which will request some type of notification
*/
struct CNotificationTest : public TFunctor
{
CNotificationTest(RTestPipe& aPipe)
:iPipe(aPipe)
{
TInt r = iParent.Open(iParent.Id());
test_KErrNone(r);
}
virtual ~CNotificationTest()
{
}
void operator()()
{
RunTest();
//set up rendezvous with parent
iParent.Rendezvous(iRendezvousStatus);
//announce we have run test
RThread::Rendezvous(KErrNone);
//wait untill parent has reached rendezvous
User::WaitForRequest(iRendezvousStatus);
}
virtual CNotificationTest* Clone()=0;
/**
If necessary, gets pipe into correct state for the start of test
*/
virtual void PreparePipe() =0;
virtual void RunTest() =0;
/**
Cancel the notification
*/
virtual void Cancel() =0;
virtual TInt GetReturn()
{
return iStatus.Int();
}
RTestPipe& iPipe;
TRequestStatus iStatus;
TRequestStatus iRendezvousStatus;
RThread iParent;
};
/**
Will request free space notification
*/
struct CSpaceNotificationTest : public CNotificationTest
{
typedef void (RTestPipe::*TSpaceNotification) (TInt, TRequestStatus&);
/**
@param aPipe Pipe handle to use
@param TSpaceNotification A pointer for the method to test
@param aNumBytes Amount of space to request
*/
CSpaceNotificationTest(RTestPipe& aPipe, TSpaceNotification aFunc, TInt aNumBytes)
:CNotificationTest(aPipe), iFn(aFunc), iNumBytes(aNumBytes)
{}
CNotificationTest* Clone()
{
return new CSpaceNotificationTest(*this);
}
void RunTest()
{
(iPipe.*iFn)(iNumBytes, iStatus);
}
//Make sure space notification won't complete immediately
void PreparePipe()
{
TInt freeSpace = iPipe.MaxSize() - iPipe.Size();
if(freeSpace >= iNumBytes)
{
TInt r = iPipe.Write(KTestData, freeSpace);
test_Equal(freeSpace, r);
}
}
void Cancel()
{
iPipe.CancelSpaceAvailable();
};
TSpaceNotification iFn;
TInt iNumBytes;
};
struct CDataNotificationTest : public CNotificationTest
{
typedef void (RTestPipe::*TDataNotification) (TRequestStatus&);
CDataNotificationTest(RTestPipe& aPipe, TDataNotification aFunc)
:CNotificationTest(aPipe), iFn(aFunc)
{}
CNotificationTest* Clone()
{
return new CDataNotificationTest(*this);
}
void RunTest()
{
(iPipe.*iFn)(iStatus);
}
//make sure we start with an empty pipe
void PreparePipe()
{
iPipe.Flush();
}
void Cancel()
{
iPipe.CancelDataAvailable();
};
TDataNotification iFn;
};
void ProcessNotificationTests(RPointerArray<CNotificationTest>& aArray)
{
const TInt count = aArray.Count();
for(TInt i=0; i < count; i++)
{
for(TInt j=0; j < count; j++)
{
//need copies as objects contain request states
CNotificationTest* testA = aArray[i]->Clone();
test_NotNull(testA);
CNotificationTest* testB = aArray[j]->Clone();
test_NotNull(testB);
testA->PreparePipe(); testB->PreparePipe();
TTestThread a(_L("CNotificationTestA"), *testA, EFalse);
TTestThread b(_L("CNotificationTestB"), *testB, EFalse);
TRequestStatus rendezvousA, rendezvousB;
a.Rendezvous(rendezvousA);
b.Rendezvous(rendezvousB);
a.Resume(); b.Resume();
//wait till after threads have made notification request.
User::WaitForRequest(rendezvousA);
User::WaitForRequest(rendezvousB);
TInt retA = testA->GetReturn(); TInt retB = testB->GetReturn();
//announce that we have read status requests, allowing
//child threads to terminate
RThread::Rendezvous(KErrNone);
a.WaitForExitL();
b.WaitForExitL();
TBool oneRequestSupported = ((retA == KRequestPending) && (retB == KErrInUse))
|| ((retB == KRequestPending) && (retA == KErrInUse));
TBool bothSupported = (retA == KRequestPending) && (retB == KRequestPending);
if(!(oneRequestSupported || bothSupported))
{
test.Printf(_L("Failure: i=%d, j=%d"), i, j);
test(EFalse);
}
testA->Cancel(); testB->Cancel();
delete testA;
delete testB;
}
}
}
/**
Test abillity of pipe channels to handle multiple notification requests
simultaneously.
*/
void TestNotifications()
{
RTestPipe readEnd, writeEnd;
TInt pipeSize = 5;
TInt r = RPipe::Create(pipeSize, readEnd, writeEnd, EOwnerProcess, EOwnerProcess);
test_KErrNone(r);
test.Next(_L("Test write end requests"));
CSpaceNotificationTest writeBlocking(writeEnd, &RTestPipe::RequestWriteBlocking, pipeSize);
CSpaceNotificationTest spaceAvailable(writeEnd, &RTestPipe::NotifySpaceAvailable, pipeSize);
RPointerArray<CNotificationTest> writeEndTests;
writeEndTests.AppendL(&writeBlocking);
writeEndTests.AppendL(&spaceAvailable);
for(TInt i=0; i<10; i++)
{
ProcessNotificationTests(writeEndTests);
}
writeEndTests.Close();
test.Next(_L("Test read end requests"));
CDataNotificationTest readBlocking(readEnd, &RTestPipe::RequestReadBlocking);
CDataNotificationTest dataAvailable(readEnd, &RTestPipe::NotifyDataAvailable);
RPointerArray<CNotificationTest> readEndTests;
readEndTests.AppendL(&readBlocking);
readEndTests.AppendL(&dataAvailable);
for(TInt j=0; j<10; j++)
{
ProcessNotificationTests(readEndTests);
}
readEndTests.Close();
readEnd.Close();
writeEnd.Close();
}
LOCAL_C void RunTests(void)
{
// Test UnNamed Pipes in Single Thread
test.Next(_L("PIPE TEST: 1.Un Named pipes in Single Thread\n"));
TestSingleThreadUnNamedPipes();
// Test Named Pipes in Single Thread
test.Next(_L("PIPE TEST: 2.Named pipes in Single Thread\n"));
TestSingleThreadNamedPipes();
// Test UnNamed Pipes in MultiThread
test.Next(_L("PIPE TEST: 3.Un Named pipes in Multi Thread\n"));
TestMultiThreadUnNamedPipes();
// Test Named Pipes in MultiThread
test.Next(_L("PIPE TEST: 4.Named pipes in Multi Thread\n"));
TestMultiThreadNamedPipes();
// Test Named Pipes in Multi Process
test.Next(_L("PIPE TEST: 5.Named pipes in Multi Process\n"));
TestMultiProcessNamedPipes();
// Test Notify mechanism
test.Next(_L("PIPE TEST: 6.Pipes Notify mechanism test\n"));
TestNotifyMechanismPipes();
// Test Wait Mechanism
test.Next(_L("PIPE TEST: 7.Pipes Wait mechanism test\n"));
TestWaitMechanismPipes();
// Test Pipes performance
test.Next(_L("PIPE TEST: 8.Pipes Permission test\n"));
TestPipesPermissionCheck ();
// Misc Pipe tests
test.Next(_L("PIPE TEST: 9.Misc Pipe tests\n"));
TestMiscPipes();
// Blocking and Notify method tests.
test.Next(_L("PIPE TEST: 10.Blocking and Notification calls test\n"));
TestBlockingAndNotify();
//Creation and closure of a large number of Pipes
test.Next(_L("PIPE TEST: 11. Creation and subsequent closure of a large number of pipes\n"));
TestCreateClosePipe();
test.Next(_L("Test concurrent notification requests"));
TestNotifications();
test.Next(_L("Repeatedly open a named pipe whilst it's being created and destroyed"));
TestRapidDefineDestroy();
test.Next(_L("Check integrity of data after transfer\n"));
TestTransferIntegrity();
test.Next(_L("PIPE TEST: Ending test.\n"));
return;
}
TInt ParseCommandLine()
{
TBuf<20> cmdLine;
//TInt r= cmdLine.Create(User::CommandLineLength());
//test_KErrNone(r);
User::CommandLine(cmdLine);
TLex lex(cmdLine);
TPtrC token=lex.NextToken();
if(token.Length()>0)
{
TInt os=token.Match(_L("-n*"));
if(os==0)
{
if(token.Length()>2)
lex.SkipAndMark(2-lex.TokenLength()); //set mark backwards to after the "-n"
token.Set(lex.NextToken());
if(token.Length()==0)
return KErrArgument;
TLex valLex(token);
TInt value;
TInt r=valLex.Val(value);
if(r<0)
return r;
else
return value;
}
else
{
return KErrArgument;
}
}
else
{
const TInt KDefaultRuns=1;
return KDefaultRuns;
}
}
GLDEF_C TInt E32Main()
// Main entry point for the test.
{
__UHEAP_MARK;
TInt ret = 0;
test.Start(_L("PIPE TEST: Testing"));
ret = RPipe::Init();
if ( ret != KErrNone && ret != KErrAlreadyExists)
{
test.Printf(_L("Fail to load RPIPE driver %d\n"),ret);
return KErrNone;
}
TName pddName(RPipe::Name());
ret = RPipe::Define (KPipe1Name,10);
test_KErrNone(ret);
User::FreeLogicalDevice(pddName);
ret = RPipe::Define (KPipe1Name,10);
test_Equal(KErrNotFound, ret);
ret = RPipe::Init();
if ( ret != KErrNone && ret != KErrAlreadyExists)
{
test.Printf(_L("Fail to load RPIPE driver %d\n"),ret);
return KErrNone;
}
TInt runs=ParseCommandLine();
if(runs>=0)
{
TBool forever=(runs==0);
for(TInt i=0; forever||(i<runs); ++i)
{
if(i!=0)
test.Next(_L("Next iteration"));
test.Start(_L("Starting Run")); //sub nest each test iteration
__UHEAP_MARK;
TRAP(ret, RunTests());
test_KErrNone(ret);
__UHEAP_MARKEND;
test.End();
}
}
else
{
test.Printf(_L("Usage: t_pipe -n N\n N is number of runs to do. If N=0 run forever"));
}
TName pddName2(RPipe::Name());
ret= User::FreeLogicalDevice(pddName2);
test_KErrNone(ret);
test.End();
test.Close();
__UHEAP_MARKEND;
return KErrNone;
}