diff -r 000000000000 -r 96e5fb8b040d kerneltest/e32test/pipe/t_pipe4.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/pipe/t_pipe4.cpp Thu Dec 17 09:24:54 2009 +0200 @@ -0,0 +1,746 @@ +// 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_pipe4.cpp +// This is very similar to User::WaitForRequest() but allows the User +// to specify multiple TRequestStatus objects to wait on. The function +// will return when the first TRequestStatus object completes. +// / Header Files//////// +// +// + +/** + @STMTestCaseID KBASE-T_PIPE4-0218 + @SYMPREQ PREQ1460 + @SYMREQ REQ6142 + @SYMCR CR0923 + @SYMTestCaseDesc User::WaitForNRequests functional test + @SYMTestPriority High + @SYMTestActions Tests the operation of the API User::WaitForNRequests(). + @SYMTestExpectedResults Test should pass +*/ + +#define __E32TEST_EXTENSION__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rpipe.h" + +//// Test Objects for All threads//// + +LOCAL_D RTest test(_L("t_pipe4")); +LOCAL_D RTest test2(_L("t_pipe_t2")); +LOCAL_D RTest test3(_L("t_pipe_t3")); +LOCAL_D RTest test4(_L("t_pipe_t4")); +LOCAL_D RTest test5(_L("t_pipe_t5")); + +//// Thread Name Constants ////// +_LIT(KThread2Name, "WaitThread"); +_LIT(KThread3Name, "NotifyDataThread"); +_LIT(KThread4Name, "NotifySpaceThread"); +_LIT(KThread5Name, "CancelNotifyThread"); + +_LIT(KPipe1Name,"TestPipeP"); +_LIT(KPipe2Name,"TestPipeQ"); +_LIT(KPipe3Name,"TestPipeR"); +_LIT(KPipe4Name,"TestPipeS"); +_LIT(KPipe5Name,"TestPipeT"); + + +_LIT8(KTestDataNum,"1234567890"); + + + +const TInt KHeapSize=0x2000; + + +// Following class is used to pass thread handle information to different threads. +class TData + { +public: + TData(RPipe* aPipe, RPipe *bPipe, TInt aSize); + RPipe* rPipe; // Pipe Read handle + RPipe* wPipe; // Pipe Write handle + TInt iSize; + + + }; + +TData::TData(RPipe * aPipe , RPipe *bPipe, TInt aSize) { + rPipe = aPipe; + wPipe = bPipe; + iSize = aSize; + +} + +//////////////////////////////////////////////////// +//// WaitThread : Function opens the Read handle +//// for the pipe passed to it. +//// +//// CPipeName --> Pipe Name +//// aData --> Read Write Handle +//// +//////////////////////////////////////////////////// +TBufC<100> cPipeName; + +TInt WaitThread(TAny* aData) { + + test2.Start(_L("PIPE TEST:WaitThread Entry")); + TInt ret; + + TData& data = *(TData *)aData; // aData will have pipe handles and size. + + ret = data.rPipe->Open(cPipeName,RPipe::EOpenToRead); + test2 (ret == KErrNone); + + test2.Printf(_L("PIPE TEST:WaitThread Exit\n")); + test2.End(); + test2.Close(); + return KErrNone; +} + +//////////////////////////////////////////////////// +//// NotifyDataThread : +//// Function writes data into the pipe. +//// +//// aData --> Read Write Handle +//// +//////////////////////////////////////////////////// + +TInt NotifyDataThread(TAny* aData) { + + TBufC8<50> cTestData(KTestDataNum); // Test Data + TInt ret; + + test3.Start(_L("PIPE TEST:NotifyDataThread Entry")); + + TData& data = *(TData *)aData; // aData will have pipe handles and size. + + User::After(10000); + + ret = data.wPipe->Write(cTestData,cTestData.Length()); + test3(ret == cTestData.Length()); + + test3.Printf(_L("PIPE TEST:NotifyDataThread Exit\n")); + test3.End(); + test3.Close(); + return KErrNone; +} + +//////////////////////////////////////////////////// +//// NotifySpaceThread : +//// Function flush the pipe and makes +//// it free. +//// +//// aData --> Read Write Handle +//// +//////////////////////////////////////////////////// + +TInt NotifySpaceThread(TAny* aData) { + + + test4.Start(_L("PIPE TEST:NotifySpaceThread Entry")); + + TData& data = *(TData *)aData; // aData will have pipe handles and size. + +// User::After(10000000); + + data.rPipe->Flush(); + + test4.Printf(_L("PIPE TEST:NotifySpaceThread Exit\n")); + test4.End(); + test4.Close(); + return KErrNone; +} + + +//////////////////////////////////////////////////// +//// CancelNotifyThread : +//// Function cancels Space available request +//// or Cancels Data available request. +//// +//// CancelFlag --> 1 CancelSpaceAvailable +//// 0 for CancelDataAvailable +//// +//// aData --> Read Write Handle +//// +//////////////////////////////////////////////////// + +TInt CancelFlag; // 1 CancelSpaceAvailable ; 0 for CancelDataAvailable +TInt CancelNotifyThread(TAny* aData) { + + test5.Start(_L("PIPE TEST:CancelNotifyThread Entry")); + + TData& data = *(TData *)aData; // aData will have pipe handles and size. + + if ( CancelFlag == 1) + data.wPipe->CancelSpaceAvailable(); + else if ( CancelFlag == 0) + data.rPipe->CancelDataAvailable(); + else + test5.Printf(_L("PIPE TEST: *** Illegal Cancel\n")); + + test5.Printf(_L("PIPE TEST:CancelNotifyThread Exit\n")); + test5.End(); + test5.Close(); + return KErrNone; +} + +//////////////////////////////////////////////////// +//// Main Thread +//// +//// +//////////////////////////////////////////////////// +/* + + +1. Create 5 (UN)Pipes. +2. Register NotifyData AVailable on 5 pipes. +3. Create Thread 1 +4. Wait for n request. +5. In thread 1 write data into any one pipe. Exit +6. Main should show 1 stat variable updated. + +7. Again call Wait for n request. +8. It shall come out as one stat is Available. + +9. Close all the pipes. Repeat same for NotifySpace available. + +10. Define 5 N-Pipes +11. Open write end and call wait till read end open. +12. Create thread 2 +12. Wait for n request +13. In thread 2 , open read end of one of the pipe. +14. Main should show 1 stat variable updated. + +15. Again call Wait for n request. +16. It shall come out as one stat is Available. + +17. Close all the pipes. Destroy pipes. + +18. Create 3 N pipe and 2 UN pipes. +19. Register 2 NDA , 2 NSA , 2 Read end wait. +20. Create thread 3 make any request successful. + + +*/ + +LOCAL_C void test_MainThread() +{ + + RPipe aReader1,aWriter1; // Used to pass to thread. + RPipe aReader2,aWriter2; // Used to pass to thread. + RPipe aReader3,aWriter3; // Used to pass to thread. + RPipe aReader4,aWriter4; // Used to pass to thread. + RPipe aReader5,aWriter5; // Used to pass to thread. + + TInt ret,aSize; + RThread thread2; + RThread thread3; + RThread thread4; + RThread thread5; + + TRequestStatus stat1; + TRequestStatus stat2; + TRequestStatus stat3; + TRequestStatus stat4; + TRequestStatus stat5; + + TRequestStatus s; + + TRequestStatus *ReqArray[] = + { + &stat1,&stat2,&stat3,&stat4,&stat5 + }; + const TBufC<100> cPipeName1(KPipe1Name); + TBufC8<50> cTestData(KTestDataNum); // Test Data + + + + test.Printf(_L("PIPE TEST:Main Thread Entry\n")); + +//Test 1: + + aSize = 10; + // Create 5 Pipes. + ret = RPipe::Create( aSize, aReader1,aWriter1,EOwnerProcess, EOwnerProcess); + test_KErrNone(ret); + ret = RPipe::Create( aSize, aReader2,aWriter2,EOwnerProcess, EOwnerProcess); + test_KErrNone(ret); + ret = RPipe::Create( aSize, aReader3,aWriter3,EOwnerProcess, EOwnerProcess); + test_KErrNone(ret); + ret = RPipe::Create( aSize, aReader4,aWriter4,EOwnerProcess, EOwnerProcess); + test_KErrNone(ret); + ret = RPipe::Create( aSize, aReader5,aWriter5,EOwnerProcess, EOwnerProcess); + test_KErrNone(ret); + // Register Notification for Data Available for all 5 pipes. + aReader1.NotifyDataAvailable(stat1); + aReader2.NotifyDataAvailable(stat2); + aReader3.NotifyDataAvailable(stat3); + aReader4.NotifyDataAvailable(stat4); + aReader5.NotifyDataAvailable(stat5); + + + // Pass handles for Pipe# 3 + TData data1(&aReader3,&aWriter3,aSize); + + // Create thread for Writing data into pipe. + // This will make status variable of respective pipe as AVAILABLE + ret = thread3.Create( + KThread3Name, // Thread name + NotifyDataThread, // Function to be called + KDefaultStackSize, + KHeapSize, + KHeapSize, + (TAny *)&data1 // Data object containing Pipe information. + ); + test_KErrNone(ret); + thread3.Logon(s); + test_Equal(KRequestPending, s.Int()); + + // Start the Thread + thread3.Resume(); + + // Wait till any of the request status is Avaialble + User::WaitForNRequest(ReqArray,5); + + // As WaitForNRequest returned. This proves test pass. + test.Printf(_L("PIPE TEST:Test 1: Pass\n")); + + // Cancel all pending requests for other tests. + aReader1.CancelDataAvailable(); + aReader2.CancelDataAvailable(); + aReader3.CancelDataAvailable(); + aReader4.CancelDataAvailable(); + aReader5.CancelDataAvailable(); + + // Close thread. + User::WaitForRequest(s); + CLOSE_AND_WAIT(thread3); + + +//Test 2: + + // Pipes created in Test 1. + // Write data into all the pipes and Fill it. + aWriter1.Write(cTestData,cTestData.Length()); + aWriter2.Write(cTestData,cTestData.Length()); + aWriter3.Write(cTestData,cTestData.Length()); + aWriter4.Write(cTestData,cTestData.Length()); + aWriter5.Write(cTestData,cTestData.Length()); + + // Register notification for Space availability for all pipes. + + aWriter1.NotifySpaceAvailable(aSize,stat1); + aWriter2.NotifySpaceAvailable(aSize,stat2); + aWriter3.NotifySpaceAvailable(aSize,stat3); + aWriter4.NotifySpaceAvailable(aSize,stat4); + aWriter5.NotifySpaceAvailable(aSize,stat5); + + + // Create data object for Pipe# 5. + TData data2(&aReader5,&aWriter5,aSize); + + // Create thread which will make space available in Pipe. + // + ret = thread4.Create( + KThread4Name, // Thread name + NotifySpaceThread, // Function to be called + KDefaultStackSize, + KHeapSize, + KHeapSize, + (TAny *)&data2 // Data object containing Pipe information. + ); + test_KErrNone(ret); + thread4.Logon(s); + test_Equal(KRequestPending, s.Int()); + + // Start the thread. + thread4.Resume(); + + // Wait till any of the status variable status change to Avaialble + User::WaitForNRequest(ReqArray,5); + + test.Printf(_L("PIPE TEST:Test 2: Pass\n")); + + // Cancel all pending requests. + aWriter1.CancelSpaceAvailable(); + aWriter2.CancelSpaceAvailable(); + aWriter3.CancelSpaceAvailable(); + aWriter4.CancelSpaceAvailable(); + aWriter5.CancelSpaceAvailable(); + + // Close the thread. + User::WaitForRequest(s); + CLOSE_AND_WAIT(thread4); + +//Test 3: + // Flush all the Pipes. + // This is needed for NotifyDataAvailable request. + aReader1.Flush(); + aReader2.Flush(); + aReader3.Flush(); + aReader4.Flush(); + aReader5.Flush(); + + // Register NotifyDataAvailable request for all the pipes. + + CancelFlag = 0; // 0 = CanceldataAvailable() + aReader1.NotifyDataAvailable(stat1); + aReader2.NotifyDataAvailable(stat2); + aReader3.NotifyDataAvailable(stat3); + aReader4.NotifyDataAvailable(stat4); + aReader5.NotifyDataAvailable(stat5); + + TData data3(&aReader2,&aWriter2,aSize); + + ret = thread5.Create( + KThread5Name, // Thread name + CancelNotifyThread, // Function to be called + KDefaultStackSize, + KHeapSize, + KHeapSize, + (TAny *)&data3 // Data object containing Pipe information. + ); + test_KErrNone(ret); + thread5.Logon(s); + test_Equal(KRequestPending, s.Int()); + thread5.Resume(); + + User::WaitForNRequest(ReqArray,5); + + test.Printf(_L("PIPE TEST:Test 3: Pass\n")); + aReader1.CancelDataAvailable(); + aReader2.CancelDataAvailable(); + aReader3.CancelDataAvailable(); + aReader4.CancelDataAvailable(); + aReader5.CancelDataAvailable(); + User::WaitForRequest(s); + CLOSE_AND_WAIT(thread5); + + +//Test 4: + aReader1.Close(); + aWriter1.Close(); + aReader2.Close(); + aWriter2.Close(); + aReader3.Close(); + aWriter3.Close(); + aReader4.Close(); + aWriter4.Close(); + aReader5.Close(); + aWriter5.Close(); + + ret = RPipe::Define(KPipe1Name,aSize); + test_KErrNone(ret); + ret = RPipe::Define(KPipe2Name,aSize); + test_KErrNone(ret); + ret = RPipe::Define(KPipe3Name,aSize); + test_KErrNone(ret); + ret = RPipe::Define(KPipe4Name,aSize); + test_KErrNone(ret); + ret = RPipe::Define(KPipe5Name,aSize); + test_KErrNone(ret); + + aWriter1.Open(KPipe1Name,RPipe::EOpenToWrite); + aWriter2.Open(KPipe2Name,RPipe::EOpenToWrite); + aWriter3.Open(KPipe3Name,RPipe::EOpenToWrite); + aWriter4.Open(KPipe4Name,RPipe::EOpenToWrite); + aWriter5.Open(KPipe5Name,RPipe::EOpenToWrite); + + aWriter1.Wait(KPipe1Name,stat1); + aWriter2.Wait(KPipe2Name,stat2); + aWriter3.Wait(KPipe3Name,stat3); + aWriter4.Wait(KPipe4Name,stat4); + aWriter5.Wait(KPipe5Name,stat5); + + const TBufC<100> cPipeName2(KPipe2Name); + + TData data4(&aReader2,&aWriter2,aSize); + cPipeName = cPipeName2; + + ret = thread2.Create( + KThread2Name, // Thread name + WaitThread, // Function to be called + KDefaultStackSize, + KHeapSize, + KHeapSize, + (TAny *)&data4 // Data object containing Pipe information. + ); + test_KErrNone(ret); + thread2.Logon(s); + test_Equal(KRequestPending, s.Int()); + thread2.Resume(); + User::WaitForNRequest(ReqArray,5); + test.Printf(_L("PIPE TEST:Test 4: Pass\n")); + aWriter1.CancelWait(); + aWriter2.CancelWait(); + aWriter3.CancelWait(); + aWriter4.CancelWait(); + aWriter5.CancelWait(); + + aReader1.Close(); aWriter1.Close(); + aReader2.Close(); aWriter2.Close(); + aReader3.Close(); aWriter3.Close(); + aReader4.Close(); aWriter4.Close(); + aReader5.Close(); aWriter5.Close(); + + User::WaitForRequest(s); + CLOSE_AND_WAIT(thread2); + +//Test 5: + + ret =aWriter1.Open(KPipe1Name,RPipe::EOpenToWrite); + test_KErrNone(ret); + aReader1.Close(); + //ret =aWriter1.Wait(KPipe1Name,stat1); + aWriter1.Wait(KPipe1Name,stat1); + + ret =aWriter2.Open(KPipe2Name,RPipe::EOpenToWrite); + test_KErrNone(ret); + ret =aReader2.Open(KPipe2Name,RPipe::EOpenToRead); + test_KErrNone(ret); + ret =aWriter2.Write(cTestData,cTestData.Length()); + //ret =aWriter2.NotifySpaceAvailable(aSize,stat2); + aWriter2.NotifySpaceAvailable(aSize,stat2); + + ret = RPipe::Create( aSize, aReader3,aWriter3,EOwnerProcess, EOwnerProcess); + test_KErrNone(ret); + aReader3.Flush(); + //ret =aReader3.NotifyDataAvailable(stat3); + aReader3.NotifyDataAvailable(stat3); + + ret = RPipe::Create( aSize, aReader4,aWriter4,EOwnerProcess, EOwnerProcess); + test_KErrNone(ret); + ret =aWriter4.Write(cTestData,cTestData.Length()); + //ret =aWriter4.NotifySpaceAvailable(aSize,stat4); + aWriter4.NotifySpaceAvailable(aSize,stat4); + + ret = RPipe::Create( aSize, aReader5,aWriter5,EOwnerProcess, EOwnerProcess); + test_KErrNone(ret); + aReader5.Flush(); + //ret =aReader5.NotifyDataAvailable(stat5); + aReader5.NotifyDataAvailable(stat5); + + TData data5(&aReader3,&aWriter3,aSize); + cPipeName = cPipeName2; + + RThread thread6; + + ret = thread6.Create( + KThread3Name, // Thread name + NotifyDataThread, // Function to be called + KDefaultStackSize, + KHeapSize, + KHeapSize, + (TAny *)&data5 // Data object containing Pipe information. + ); + test_KErrNone(ret); + thread6.Logon(s); + test_Equal(KRequestPending, s.Int()); + thread6.Resume(); + User::WaitForNRequest(ReqArray,5); + test.Printf(_L("PIPE TEST:Test 5: Pass\n")); + + User::WaitForRequest(s); + CLOSE_AND_WAIT(thread6); +//Test 6: + + TData data6(&aReader2,&aWriter2,aSize); + cPipeName = cPipeName2; + + RThread thread7; + + ret = thread7.Create( + KThread3Name, // Thread name + NotifySpaceThread, // Function to be called + KDefaultStackSize, + KHeapSize, + KHeapSize, + (TAny *)&data6 // Data object containing Pipe information. + ); + test_KErrNone(ret); + thread7.Logon(s); + test_Equal(KRequestPending, s.Int()); + thread7.Resume(); + + User::WaitForNRequest(ReqArray,5); + test.Printf(_L("PIPE TEST:Test 6: Pass\n")); + + + User::WaitForRequest(s); + CLOSE_AND_WAIT(thread7); + +//Test 7: + TData data7(&aReader1,&aWriter1,aSize); + cPipeName = cPipeName1; + + RThread thread8; + + ret = thread8.Create( + KThread2Name, // Thread name + WaitThread, // Function to be called + KDefaultStackSize, + KHeapSize, + KHeapSize, + (TAny *)&data7 // Data object containing Pipe information. + ); + test_KErrNone(ret); + thread8.Logon(s); + test_Equal(KRequestPending, s.Int()); + thread8.Resume(); + + User::WaitForNRequest(ReqArray,5); + test.Printf(_L("PIPE TEST:Test 7: Pass\n")); + + + User::WaitForRequest(s); +// CLOSE_AND_WAIT(thread8); DOESN'T WORK SINCE PIPE DRIVER KEEPS THE THREAD OPEN + thread8.Close(); + +//Test 8: + TData data8(&aReader4,&aWriter4,aSize); + + RThread thread9; + + CancelFlag = 1; // 1 = CancelSpaceAvailable() + + ret = thread9.Create( + KThread4Name, // Thread name + CancelNotifyThread, // Function to be called + KDefaultStackSize, + KHeapSize, + KHeapSize, + (TAny *)&data8 // Data object containing Pipe information. + ); + test_KErrNone(ret); + thread9.Logon(s); + test_Equal(KRequestPending, s.Int()); + thread9.Resume(); + + User::WaitForNRequest(ReqArray,5); + test.Printf(_L("PIPE TEST:Test 8: Pass\n")); + + User::WaitForRequest(s); + CLOSE_AND_WAIT(thread9); + +//Test 9: + TData data9(&aReader5,&aWriter5,aSize); + + RThread thread10; + + CancelFlag = 0; // 0 = CancelDataAvailable() + + ret = thread10.Create( + KThread5Name, // Thread name + CancelNotifyThread, // Function to be called + KDefaultStackSize, + KHeapSize, + KHeapSize, + (TAny *)&data9 // Data object containing Pipe information. + ); + test_KErrNone(ret); + thread10.Logon(s); + test_Equal(KRequestPending, s.Int()); + thread10.Resume(); + + + User::WaitForNRequest(ReqArray,5); + test.Printf(_L("PIPE TEST:Test 9: Pass\n")); + + User::WaitForRequest(s); + CLOSE_AND_WAIT(thread10); + + + aReader1.Close(); aWriter1.Close(); + aReader2.Close(); aWriter2.Close(); + aReader3.Close(); aWriter3.Close(); + aReader4.Close(); aWriter4.Close(); + aReader5.Close(); aWriter5.Close(); + ret = RPipe::Destroy(KPipe1Name); + test_KErrNone(ret); + ret = RPipe::Destroy(KPipe2Name); + test_KErrNone(ret); + ret = RPipe::Destroy(KPipe3Name); + test_KErrNone(ret); + ret = RPipe::Destroy(KPipe4Name); + test_KErrNone(ret); + ret = RPipe::Destroy(KPipe5Name); + test_KErrNone(ret); + + + test.Printf(_L("PIPE TEST:Main Thread Exit\n")); + return; + + + +} + +//////////////////////////////////////////////////// +//// RunTests: +//// +//// +//////////////////////////////////////////////////// +LOCAL_C void RunTests(void) +{ + + test.Start(_L("PIPE TEST: Testing WaitForNRequest")); + + test_MainThread(); + + test.Printf(_L("PIPE TEST: Ending test.\n")); + + test.End(); + test.Close(); + return; +} + + +//////////////////////////////////////////////////// +//// E32Main : Main entry point to test. +//// +//// +//////////////////////////////////////////////////// + + +GLDEF_C TInt E32Main() + +{ + TInt ret = 0; + + ret = RPipe::Init(); + + if (ret != KErrNone && ret != KErrAlreadyExists) + { + test.Printf(_L(" t_pipe4.exe PIPE TEST: Error loading driver %d\n"),ret); + test.Printf(_L(" Exiting t_pipe4.exe\n")); + + return KErrNone; + + } + RunTests(); + + TName pddName1(RPipe::Name()); + + ret= User::FreeLogicalDevice(pddName1); + + return KErrNone; + +}