--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/f32test/server/t_open.cpp Thu Dec 17 09:24:54 2009 +0200
@@ -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 <f32file.h>
+#include <e32test.h>
+#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();
+ }