diff -r 000000000000 -r a41df078684a kerneltest/f32test/server/t_open.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/f32test/server/t_open.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,725 @@ +// Copyright (c) 1996-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: +// f32test\server\t_open.cpp +// +// + +#include +#include +#include "t_server.h" + +GLDEF_D RTest test(_L("T_OPEN")); + +LOCAL_D TFileName gBatchFile; +LOCAL_D TBool gRunByBatch=EFalse; + +TFileName filename1=_L("Z:\\TEST\\T_FSRV.CPP"); +TFileName filename2=_L("Z:\\TEST\\T_FILE.CPP"); +TFileName dirname1=_L("Z:\\TEST\\*.XDE"); + + +LOCAL_C void Test0() +// +// Scan for open files - no sessions +// + { + + test.Next(_L("Scan for open files with no sessions open")); + CFileList* list; + TOpenFileScan fileScan(TheFs); + fileScan.NextL(list); + if (list==NULL) + return; + TInt count=list->Count(); + if (count==1) + { + gRunByBatch=ETrue; + gBatchFile=(*list)[0].iName; + delete list; + fileScan.NextL(list); + if (list==NULL) + return; + count=list->Count(); + } + while (count--) + { + TEntry entry=(*list)[count]; + test.Printf(_L("%d) EntryName = %S\n"),count,&entry.iName); + } + test.Printf(_L("Test will fail unless files are closed.\n")); + test(0); + //test.Printf(_L("Press any key ...\n")); + //test.Getch(); + } + +LOCAL_C void Test1() +// +// Test OpenFileScan +// + { + + test.Next(_L("Scan for open files - one session only")); + + RFile file1,file2,file3; + + TInt r=file1.Open(TheFs,filename1,EFileRead|EFileShareReadersOnly); + test(r==KErrNone); + + r=file2.Open(TheFs,filename2,EFileRead); + test(r==KErrNone); + + r=file3.Open(TheFs,filename1,EFileRead|EFileShareReadersOnly); + test(r==KErrNone); + + CFileList* list=NULL; + TOpenFileScan fileScan(TheFs); + TRAP(r,fileScan.NextL(list)); + test(r==KErrNone); + + if (gRunByBatch) + { + test(list!=NULL); + test(list->Count()==1); + TEntry entry=(*list)[0]; + test(entry.iName.FindF(_L(".BAT"))>=0); + delete list; + fileScan.NextL(list); + } + + + test(list!=NULL); + TInt count=list->Count(); + test(count==3); + TEntry entry=(*list)[0]; + + test(entry.iName.FindF(_L("T_FSRV.CPP"))>=0); + entry=(*list)[1]; + test(entry.iName.FindF(_L("T_FILE.CPP"))>=0); + entry=(*list)[2]; + test(entry.iName.FindF(_L("T_FSRV.CPP"))>=0); + TThreadId threadId=fileScan.ThreadId(); + RThread current; + TThreadId currentId=current.Id(); + test(threadId==currentId); + delete list; + + fileScan.NextL(list); + test(list==NULL); + + file1.Close(); + file2.Close(); + file3.Close(); + } + +LOCAL_C void Test2() +// +// Test openfilescan - empty, full, empty. +// + { + + + test.Next(_L("Scan for open files - empty sessions")); + + RFs fs1,fs2,fs3,fs4; + TInt r=fs1.Connect(); + test(r==KErrNone); + r=fs2.Connect(); + test(r==KErrNone); + r=fs3.Connect(); + test(r==KErrNone); + r=fs4.Connect(); + test(r==KErrNone); + + RFile file1,file2,file3; + + r=file1.Open(fs2,filename1,EFileRead|EFileShareReadersOnly); + test(r==KErrNone); + + r=file2.Open(fs2,filename2,EFileRead); + test(r==KErrNone); + + r=file3.Open(fs2,filename1,EFileRead|EFileShareReadersOnly); + test(r==KErrNone); + + CFileList* list; + TOpenFileScan fileScan(TheFs); + fileScan.NextL(list); + + if (gRunByBatch) + { + test(list!=NULL); + test(list->Count()==1); + TEntry entry=(*list)[0]; + test(entry.iName.FindF(_L(".BAT"))>=0); + delete list; + fileScan.NextL(list); + } + + test(list!=NULL); + TInt count=list->Count(); + test(count==3); + TEntry entry=(*list)[0]; + test(entry.iName.FindF(_L("T_FSRV.CPP"))>=0); + entry=(*list)[1]; + test(entry.iName.FindF(_L("T_FILE.CPP"))>=0); + entry=(*list)[2]; + test(entry.iName.FindF(_L("T_FSRV.CPP"))>=0); + TThreadId threadId=fileScan.ThreadId(); + RThread current; + TThreadId currentId=current.Id(); + test(threadId==currentId); + delete list; + + fileScan.NextL(list); + test(list==NULL); + + file1.Close(); + file2.Close(); + file3.Close(); + fs1.Close(); + fs2.Close(); + fs3.Close(); + fs4.Close(); + } + +LOCAL_C void Test3() +// +// Test openfilescan - empty, full, empty full +// + { + + test.Next(_L("Scan for open files - multiple sessions")); + + RFs fs1,fs2,fs3,fs4; + TInt r=fs1.Connect(); + test(r==KErrNone); + r=fs2.Connect(); + test(r==KErrNone); + r=fs3.Connect(); + test(r==KErrNone); + r=fs4.Connect(); + test(r==KErrNone); + + RFile file1,file2,file3; + + r=file1.Open(fs2,filename1,EFileRead|EFileShareReadersOnly); + test(r==KErrNone); + + r=file2.Open(fs2,filename2,EFileRead|EFileShareReadersOnly); + test(r==KErrNone); + + r=file3.Open(fs2,filename1,EFileRead|EFileShareReadersOnly); + test(r==KErrNone); + + r=file1.Open(fs4,filename1,EFileRead|EFileShareReadersOnly); + test(r==KErrNone); + + r=file2.Open(fs4,filename2,EFileRead|EFileShareReadersOnly); + test(r==KErrNone); + + r=file3.Open(fs4,filename1,EFileRead|EFileShareReadersOnly); + test(r==KErrNone); + + CFileList* list; + TOpenFileScan fileScan(TheFs); + fileScan.NextL(list); + + if (gRunByBatch) + { + test(list!=NULL); + test(list->Count()==1); + TEntry entry=(*list)[0]; + test(entry.iName.FindF(_L(".BAT"))>=0); + delete list; + fileScan.NextL(list); + } + + test(list!=NULL); + TInt count=list->Count(); + test(count==3); + TEntry entry=(*list)[0]; + test(entry.iName.FindF(_L("T_FSRV.CPP"))>=0); + entry=(*list)[1]; + test(entry.iName.FindF(_L("T_FILE.CPP"))>=0); + entry=(*list)[2]; + test(entry.iName.FindF(_L("T_FSRV.CPP"))>=0); + TThreadId threadId=fileScan.ThreadId(); + RThread current; + TThreadId currentId=current.Id(); + test(threadId==currentId); + delete list; + + fileScan.NextL(list); + test(list!=NULL); + count=list->Count(); + test(count==3); + entry=(*list)[0]; + test(entry.iName.FindF(_L("T_FSRV.CPP"))>=0); + entry=(*list)[1]; + test(entry.iName.FindF(_L("T_FILE.CPP"))>=0); + entry=(*list)[2]; + test(entry.iName.FindF(_L("T_FSRV.CPP"))>=0); + threadId=fileScan.ThreadId(); + currentId=current.Id(); + test(threadId==currentId); + delete list; + + fileScan.NextL(list); + test(list==NULL); + + file1.Close(); + file2.Close(); + file3.Close(); + fs1.Close(); + fs2.Close(); + fs3.Close(); + fs4.Close(); + } + +LOCAL_C void Test4() +// +// Test openfilescan - rdirs, empty, full, empty rdirs. +// + { + test.Next(_L("Scan for open files - check RDir sessions are ignored")); + + RFs fs1,fs2,fs3,fs4; + TInt r=fs1.Connect(); + test(r==KErrNone); + r=fs2.Connect(); + test(r==KErrNone); + r=fs3.Connect(); + test(r==KErrNone); + r=fs4.Connect(); + test(r==KErrNone); + + RDir dir1,dir2,dir3,dir4; + r=dir1.Open(TheFs,dirname1,KEntryAttMaskSupported); + test(r==KErrNone); + r=dir2.Open(TheFs,dirname1,KEntryAttMaskSupported); + test(r==KErrNone); + r=dir3.Open(TheFs,dirname1,KEntryAttMaskSupported); + test(r==KErrNone); + r=dir4.Open(TheFs,dirname1,KEntryAttMaskSupported); + test(r==KErrNone); + + RFile file1,file2,file3; + r=file1.Open(fs2,filename1,EFileRead|EFileShareReadersOnly); + test(r==KErrNone); + r=file2.Open(fs2,filename2,EFileRead); + test(r==KErrNone); + r=file3.Open(fs2,filename1,EFileRead|EFileShareReadersOnly); + test(r==KErrNone); + + RDir dir5,dir6,dir7,dir8; + r=dir5.Open(fs4,dirname1,KEntryAttMaskSupported); + test(r==KErrNone); + r=dir6.Open(fs4,dirname1,KEntryAttMaskSupported); + test(r==KErrNone); + r=dir7.Open(fs4,dirname1,KEntryAttMaskSupported); + test(r==KErrNone); + r=dir8.Open(fs4,dirname1,KEntryAttMaskSupported); + test(r==KErrNone); + + CFileList* list; + TOpenFileScan fileScan(TheFs); + fileScan.NextL(list); + + if (gRunByBatch) + { + test(list!=NULL); + test(list->Count()==1); + TEntry entry=(*list)[0]; + test(entry.iName.FindF(_L(".BAT"))>=0); + delete list; + fileScan.NextL(list); + } + + test(list!=NULL); + TInt count=list->Count(); + test(count==3); + TEntry entry=(*list)[0]; + test(entry.iName.FindF(_L("T_FSRV.CPP"))>=0); + entry=(*list)[1]; + test(entry.iName.FindF(_L("T_FILE.CPP"))>=0); + entry=(*list)[2]; + test(entry.iName.FindF(_L("T_FSRV.CPP"))>=0); + TThreadId threadId=fileScan.ThreadId(); + RThread current; + TThreadId currentId=current.Id(); + test(threadId==currentId); + delete list; + + fileScan.NextL(list); + test(list==NULL); + + file1.Close(); + file2.Close(); + file3.Close(); + dir1.Close(); dir2.Close(); + dir3.Close(); dir4.Close(); + dir5.Close(); dir6.Close(); + dir7.Close(); dir8.Close(); + fs1.Close(); fs2.Close(); + fs3.Close(); fs4.Close(); + } + +LOCAL_C void Test5() +// +// Test OpenFileScan +// + { + + test.Next(_L("Scan for open files - mixed RDirs and RFiles")); + + RFile file1,file2,file3; + TInt r=file1.Open(TheFs,filename1,EFileRead|EFileShareReadersOnly); + test(r==KErrNone); + r=file2.Open(TheFs,filename2,EFileRead); + test(r==KErrNone); + r=file3.Open(TheFs,filename1,EFileRead|EFileShareReadersOnly); + test(r==KErrNone); + + RDir dir1,dir2,dir3,dir4; + r=dir1.Open(TheFs,dirname1,KEntryAttMaskSupported); + test(r==KErrNone); + r=dir2.Open(TheFs,dirname1,KEntryAttMaskSupported); + test(r==KErrNone); + r=dir3.Open(TheFs,dirname1,KEntryAttMaskSupported); + test(r==KErrNone); + r=dir4.Open(TheFs,dirname1,KEntryAttMaskSupported); + test(r==KErrNone); + + CFileList* list; + TOpenFileScan fileScan(TheFs); + fileScan.NextL(list); + + if (gRunByBatch) + { + test(list!=NULL); + test(list->Count()==1); + TEntry entry=(*list)[0]; + test(entry.iName.FindF(_L(".BAT"))>=0); + delete list; + fileScan.NextL(list); + } + + test(list!=NULL); + TInt count=list->Count(); + test(count==3); + TEntry entry=(*list)[0]; + test(entry.iName.FindF(_L("T_FSRV.CPP"))>=0); + entry=(*list)[1]; + test(entry.iName.FindF(_L("T_FILE.CPP"))>=0); + entry=(*list)[2]; + test(entry.iName.FindF(_L("T_FSRV.CPP"))>=0); + TThreadId threadId=fileScan.ThreadId(); + RThread current; + TThreadId currentId=current.Id(); + test(threadId==currentId); + delete list; + + fileScan.NextL(list); + test(list==NULL); + + file1.Close(); + file2.Close(); + file3.Close(); + dir1.Close(); + dir2.Close(); + dir3.Close(); + dir4.Close(); + } + + +NONSHARABLE_STRUCT(TThreadData) +// +// Encapsulates the data required by the worker thread. +// + { + // Thread identifier for debug output + TInt iNumber; + + // ID of the thread that started the worker thread, and the + // worker thread itself + TThreadId iMain; + TThreadId iWorker; + + // Request status object of the parent thread, used for signalling + TRequestStatus* iStatus; + + // Name of the file the parent thread requires this thread to open + TFileName iFilename; + + // Number of files opened by the thread; + TInt iNumFiles; + }; + + +LOCAL_C TInt WorkerThread(TAny* aParameter) +// +// This function is designed to run as a separate thread in order to verify the +// fix for DEF062875. +// +// When the thread is started it opens the file specified in the startup +// parameter, signals the main thread and then suspends. Once the main thread +// has completed its checking the worker thread is resumed and allowed to run +// to completion. +// +// @param aParameter Thread specific data supplied by the main thread when the +// worker thread is started. The data may be accessed by +// casting this pointer to a TThreadData* +// + { + // Can't use our global "test" object here + RTest myTest(_L("Worker thread")); + + + // Extract the parameters that this thread will need to use + TThreadData* threadData = (TThreadData*)aParameter; + + + RThread current; + TThreadId currentId = current.Id(); + + + myTest.Printf(_L("WORK%d: Worker thread %d started\n"), threadData->iNumber, threadData->iNumber); + myTest.Printf(_L("WORK%d: File: %S\n"), threadData->iNumber, &threadData->iFilename); + myTest.Printf(_L("WORK%d: Thread: %d\n"), threadData->iNumber, (TUint)currentId); + myTest.Printf(_L("WORK%d: Parent: %d\n"), threadData->iNumber, (TUint)threadData->iMain); + + + // Open the file specified by the parameter passed to us from the main + // thread + RFs myFs; + myFs.Connect(); + RFile file; + User::LeaveIfError(file.Open(myFs, threadData->iFilename, EFileRead | EFileShareReadersOnly)); + + // Signal the parent thread to continue then wait + myTest.Printf(_L("WORK%d: Signalling parent thread\n"), threadData->iNumber); + RThread parent; + User::LeaveIfError(parent.Open(threadData->iMain)); + parent.RequestComplete(threadData->iStatus, KErrNone); + + + myTest.Printf(_L("WORK%d: Waiting for parent thread to restart us\n"), threadData->iNumber); + current.Suspend(); + + + // Tidy up + myTest.Printf(_L("WORK%d: Closing file\n"), threadData->iNumber); + file.Close(); + + + return KErrNone; + } + + +LOCAL_C void TestDEF062875() +// +// Verify that TOpenFileScan::ThreadId() returns the ID of the thread that +// opened the file. +// +// The object of the exercise here is to create several worker threads, each +// one will open a file, signal the main thread and then suspend. Once all +// the worker threads have suspended the main thread then uses +// TOpenFileScan::NextL() to verify that the thread IDs correspond to the +// worker threads that opened each file and not that of the main thread. +// +// The worker threads are then restarted and allowed to terminate naturally by +// running to completion +// + { + test.Start(_L("Test TOpenFileScan::ThreadId()")); + + const TInt KHeapSize = 32768; + + RThread thread1; + RThread thread2; + + TRequestStatus status1; + TRequestStatus status2; + + TThreadId id = RThread().Id(); + + TThreadData threadData[3]; + + threadData[0].iNumber = 0; + threadData[0].iMain = id; + threadData[0].iWorker = id; + threadData[0].iStatus = 0; + threadData[0].iFilename = filename1; + threadData[0].iNumFiles = 2; + + threadData[1].iNumber = 1; + threadData[1].iMain = id; + threadData[1].iStatus = &status1; + threadData[1].iFilename = filename1; + threadData[1].iNumFiles = 1; + + threadData[2].iNumber = 2; + threadData[2].iMain = id; + threadData[2].iStatus = &status2; + threadData[2].iFilename = filename2; + threadData[2].iNumFiles = 1; + + TInt numThreads = sizeof(threadData)/sizeof(threadData[0]); + + + // Open the files in the MAIN thread. + RFile file1; + User::LeaveIfError(file1.Open(TheFs, filename1, EFileRead | EFileShareReadersOnly)); + + RFile file2; + User::LeaveIfError(file2.Open(TheFs, filename2, EFileRead | EFileShareReadersOnly)); + + + // Create the first worker thread + test.Printf(_L("MAIN: Creating worker threads\n")); + thread1.Create(_L("WorkerThread1"), WorkerThread, KDefaultStackSize, KHeapSize, KHeapSize, &threadData[1]); + threadData[1].iWorker = thread1.Id(); + + // Start it and wait for it to suspend + thread1.Logon(status1); + thread1.Resume(); + test.Printf(_L("MAIN: Waiting for worker thread 1\n")); + User::WaitForRequest(status1); + + + // Create the second worker thread + thread2.Create(_L("WorkerThread2"), WorkerThread, KDefaultStackSize, KHeapSize, KHeapSize, &threadData[2]); + threadData[2].iWorker = thread2.Id(); + + + // Start it and wait for it to suspend + thread2.Logon(status2); + thread2.Resume(); + test.Printf(_L("MAIN: Waiting for worker thread 2\n")); + User::WaitForRequest(status2); + + + // Obtain a list of open files. At this point we should have a single open + // file, as opened by our worker thread. The thread ID reported by + // TOpenFileScan should be that of our worker thread rather than the main + // thread. + test.Printf(_L("MAIN: Verifying thread ID of open file(s)\n")); + CFileList* list; + TOpenFileScan fileScan(TheFs); + + + TInt count = 0; + FOREVER + { + fileScan.NextL(list); + + + // The NULL list indicates we've run out of sessions. + if(!list) + { + break; + } + + + TThreadId threadId=fileScan.ThreadId(); + TThreadData* data = 0; + for (count = 0; count < numThreads; count++) + { + if (threadId == threadData[count].iWorker) + { + data = &threadData[count]; + break; + } + } + + + if (data) + { + test.Next(_L("Check number of open files...")); + test.Printf(_L("MAIN: Number of open files: %d (expecting %d)\n"), list->Count(), data->iNumFiles); + test(list->Count() == threadData[count].iNumFiles); + + + test.Next(_L("Check TThreadIds...")); + test.Printf(_L("MAIN: Main thread ID : %d\n"), (TUint)data->iMain); + test.Printf(_L("MAIN: Worker thread ID: %d\n"), (TUint)data->iWorker); + test.Printf(_L("MAIN: File thread ID : %d\n"), (TUint)threadId); + + + TInt loop = 0; + for (loop = 0; loop < list->Count(); loop++) + { + const TEntry& theEntry = (*list)[loop]; + test.Printf(_L(" ")); + test.Printf(theEntry.iName); + test.Printf(_L("\n")); + } + } + else + { + test.Printf(_L("Ignored thread %d\n"), (TUint)threadId); + } + + + delete list; + list = 0; + + + test.Printf(_L("\n")); + } + + + // Signal the two worker threads to tidy up and run to normal termination + test.Printf(_L("MAIN: Signalling worker thread 1\n")); + thread1.Logon(status1); + thread1.Resume(); + User::WaitForRequest(status1); + + test.Printf(_L("MAIN: Signalling worker thread 2\n")); + thread2.Logon(status2); + thread2.Resume(); + User::WaitForRequest(status2); + + + // Tidy up and finish + test.Printf(_L("MAIN: Closing worker thread 1\n")); + thread1.Close(); + + test.Printf(_L("MAIN: Closing worker thread 2\n")); + thread2.Close(); + + file1.Close(); + file2.Close(); + + test.End(); + } + + +GLDEF_C void CallTestsL() +// +// Call tests that may leave +// + { + filename1[0] = gExeFileName[0]; + filename2[0] = gExeFileName[0]; + dirname1[0] = gExeFileName[0]; + Test0(); + Test1(); + Test2(); + Test3(); + Test4(); + Test5(); + + TestDEF062875(); + }