diff -r 000000000000 -r a41df078684a kerneltest/f32test/fileshare/t_handshare.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/f32test/fileshare/t_handshare.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,886 @@ +// 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_handshare.cpp +// +// + +#include +#include +#include "t_server.h" +#include "handshare.h" + +GLDEF_D RTest test(_L("T_HANDSHARE")); + +LOCAL_D TInt drivenum; + + + +// test of (deprecated) RFile::Adopt() +// +// Request an open file (read only) +// +GLDEF_C void RequestFileDeprecatedAdopt() + { + test.Next(_L("RFile::Adopt()")); + + TInt r; + RFileHandleSharer handsvr; + do + { + r=handsvr.Connect(); + } + while(r==KErrNotFound); + test(r==KErrNone); + r=handsvr.SetTestDrive(drivenum); + test(r==KErrNone); + TInt ssh; + RFs fs1; + TInt fsh = handsvr.GetFileHandle(ssh, EFileRead); + + r = fs1.SetReturnedHandle(fsh); + test(r==KErrNone); + + RFile file; + r=file.Adopt(fs1,ssh); + test(r==KErrNone); + + TBuf8<100> rbuf; + r=file.Read(0,rbuf); + test(r==KErrNone); + + r=rbuf.CompareF(KTestData1()); + test(r==KErrNone); + + r=file.Write(KTestData()); + test(r==KErrAccessDenied); + + r=file.ChangeMode(EFileWrite); + test(r==KErrArgument); + + r=file.Rename(_L("\\newname.txt")); + test(r==KErrPermissionDenied || r==KErrAccessDenied); + + file.Close(); + + fsh = handsvr.GetFileHandle(ssh, EFileRead); + r = fs1.SetReturnedHandle(fsh); + test(r==KErrNone); + + // Adopt a bad sub-session handle + + r=file.Adopt(fs1, KNullHandle); + test(r==KErrBadHandle); + + r=file.Adopt(fs1, -1); + test(r==KErrBadHandle); + + + handsvr.Close(); + file.Close(); + RDebug::Print(_L("End Of Tests")); + fs1.Close(); + } + + + +// Cloning tests +GLDEF_C void Duplicate() + { + test.Next(_L("RFile::Duplicate()")); + + RFs fs; + TInt r=fs.Connect(); + test(r==KErrNone); + + // Check the number of open file handles + TInt resCount = fs.ResourceCount(); + test(resCount == 0); + + // create a file & fill it with data + RFile file1; + r=file1.Replace(fs,KCliFileName,EFileWrite); + test(r==KErrNone); + r=file1.Write(KTestData()); + test(r==KErrNone); + file1.Close(); + + // open the file for read + r = file1.Open(fs,KCliFileName,EFileRead); + test(r==KErrNone); + TBuf8<100> rbuf; + r = file1.Read(0,rbuf); + test(r==KErrNone); + r=rbuf.CompareF(KTestData); + test(r==KErrNone); + + + // clone the file + RFile file2; + r = file2.Duplicate(file1); + test(r==0); + + // make sure file positions are the same + TInt pos1 = 0; + r = file1.Seek(ESeekCurrent, pos1); + test(r==KErrNone); + TInt pos2 = 0; + r = file2.Seek(ESeekCurrent, pos2); + test(r==KErrNone); + test(pos1 == pos2); + + // change the position on the duplcated file handle & + // verify that the original file handle's position is unchanged + TInt oldPos1 = pos1; + + const TInt newPos2 = 5; + pos2 = newPos2; + r = file2.Seek(ESeekStart, pos2); + test(r==KErrNone); + + pos1 = 0; + r = file1.Seek(ESeekCurrent, pos1); + test(r==KErrNone); + test(pos1 == oldPos1); + + pos2 = 0; + r = file2.Seek(ESeekCurrent, pos2); + test(r==KErrNone); + test(pos2 == newPos2); + test(pos1 != pos2); + + // close the parent file and check we can still use the duplicated one. + file1.Close(); + + // Check the number of open file handles - should be 1 (the duplicated one) + resCount = fs.ResourceCount(); + test(resCount == 1); + + fs.Close(); + + rbuf.FillZ(); + + // reset to pos 0 + pos2 = 0; + r = file2.Seek(ESeekStart, pos2); + test(r==KErrNone); + + r=file2.Read(0,rbuf); + test(r==KErrNone); + r=rbuf.CompareF(KTestData); + test(r==KErrNone); + file2.Close(); + + // start again - this time we're going to close the duplicated file first + // and check we can still use the parent file + + r = fs.Connect(); + test(r==KErrNone); + + // Make a note of the number of open resources + fs.ResourceCountMarkStart(); + + // open the file for read + r = file1.Open(fs,KCliFileName,EFileRead); + test(r==KErrNone); + + + // clone the file & check we can read it + r = file2.Duplicate(file1, EOwnerThread); + test(r==0); + rbuf.FillZ(); + r = file2.Read(0,rbuf); + test(r==KErrNone); + r=rbuf.CompareF(KTestData); + test(r==KErrNone); + + + // close the duplicated file and check we can still use the parent one. + file2.Close(); + + rbuf.FillZ(); + + // check we can read the parent file + r=file1.Read(0,rbuf); + test(r==KErrNone); + r=rbuf.CompareF(KTestData); + test(r==KErrNone); + + // close the parent + file1.Close(); + + // Check the number of open file handles + fs.ResourceCountMarkEnd(); + resCount = fs.ResourceCount(); + test(resCount == 0); + + fs.Close(); + } + + +// Request an open file (write mode) from the server +// using RFile::AdoptFromServer() +GLDEF_C void RequestFileWrite() + { + TInt r; + RFileHandleSharer handsvr; + do + { + r=handsvr.Connect(); + } + while(r==KErrNotFound); + test(r==KErrNone); + + r=handsvr.SetTestDrive(drivenum); + test(r==KErrNone); + + TInt ssh; + TInt fsh = handsvr.GetFileHandle2(ssh, EFileWrite); + test (fsh >= 0); + + // Closing the handle to the server ensures the server has closed it's + // RFs and RFile handles - this provides a means of testing whether we + // can still adopt the RFile even if the server has closed it's one. + + handsvr.Sync(); // make sure server has finished doing what it's doing + handsvr.Close(); + + // adopt the file handle from FHServer + test.Next(_L("RFile::AdoptFromServer()")); + + RFile file; + r=file.AdoptFromServer(fsh, ssh); + test(r==KErrNone); + + TBuf8<100> rbuf; + r=file.Read(0,rbuf); + test(r==KErrNone); + + // server should write KTestData1 ("Server Write Server Write") to file + r=rbuf.CompareF(KTestData1); + test(r==KErrNone); + + // reset to pos 0 + TInt pos = 0; + r = file.Seek(ESeekStart, pos); + test(r==KErrNone); + + // overwrite with KTestData ("Client Write Client Write") to file + r=file.Write(KTestData()); + test(r==KErrNone); + rbuf.FillZ(); + r=file.Read(0,rbuf); + test(r==KErrNone); + r=rbuf.CompareF(KTestData); + test(r==KErrNone); + +// !!! Disable platform security tests until we get the new APIs +// r=file.Rename(_L("\\newname.txt")); +// test(r==KErrPermissionDenied); + + test.Next(_L("RFile::Name()")); + + // retrieve the file name from the server + TFileName name; + r = file.Name(name); + test(r==KErrNone); + r = name.Compare(KSvrFileName()); + test(r==0); + + + test.Next(_L("RFile::Duplicate()")); + RFile file2; + r = file2.Duplicate(file); + test(r==0); + + + TInt pos1 = 0; + r = file.Seek(ESeekCurrent, pos1); + test(r==KErrNone); + TInt pos2 = 0; + r = file2.Seek(ESeekCurrent, pos2); + test(r==KErrNone); + test(pos1 == pos2); + + // close the parent file and check we can still use the duplicated one. + file.Close(); + + rbuf.FillZ(); + + // reset to pos 0 + pos2 = 0; + r = file2.Seek(ESeekStart, pos2); + test(r==KErrNone); + + r=file2.Read(0,rbuf); + test(r==KErrNone); + r=rbuf.CompareF(KTestData); + test(r==KErrNone); + file2.Close(); + } + + +// Request a test file & test what we can do with it +// i.e CFileMan::Copy, RFile::Rename() and RFs:Delete() +// +void RequestFileTest() + { + TInt r; + + RFs fs; + r=fs.Connect(); + test(r==KErrNone); + r=fs.ShareProtected(); + test(r==KErrNone); + + + // define a filename in our private path + TPath newPath; + fs.PrivatePath(newPath); + TFileName newFileName; + newFileName = newPath; + newFileName.Append(_L("newname.txt")); + + r=fs.CreatePrivatePath(drivenum); + test(r==KErrNone); + r=fs.SetSessionToPrivate(drivenum); + + RFileHandleSharer handsvr; + do + { + r=handsvr.Connect(); + } + while(r==KErrNotFound); + test(r==KErrNone); + + r=handsvr.SetTestDrive(drivenum); + test(r==KErrNone); + + // Next verify that we can copy a file retrieved from the server + // using CFileMan::Copy() + + test.Next(_L("CFileMan::Copy()")); + + TInt ssh; + TInt fsh = handsvr.GetFileHandle2(ssh, EFileRead); + test (fsh >= 0); + + RFile file; + r=file.AdoptFromServer(fsh, ssh); + test(r==KErrNone); + + + CFileMan* fileMan = NULL; + TRAP(r, fileMan = CFileMan::NewL(fs)); + test(r == KErrNone && fileMan != NULL); + + // copy to file, overwrite + r = fileMan->Copy(file, newFileName, CFileMan::EOverWrite); + test(r == KErrNone); + + // copy to file, don't overwrite + r = fileMan->Copy(file, newFileName, 0); + test(r == KErrAlreadyExists); + + // copy to file, overwrite + r = fileMan->Copy(file, newFileName, CFileMan::EOverWrite); + test(r == KErrNone); + + // copy to path + r = fileMan->Copy(file, newPath, CFileMan::EOverWrite); + test(r == KErrNone); + + // copy to file, overwrite, asynchnonous + TRequestStatus status(KRequestPending); + r = fileMan->Copy(file, newFileName, CFileMan::EOverWrite, status); + test(r == KErrNone); + User::WaitForRequest(status); + test(status == KErrNone); + + + // Negative tests... + TPath newLongPath; + TInt len; + + // copy to very long but valid path (no filename) which will overflow + // when the filename is appended to it + newLongPath = newPath; + for (len=newLongPath.Length(); len< KMaxPath -4; len = newLongPath.Length()) + newLongPath.Append(_L("x\\")); + r = fileMan->Copy(file, newLongPath, CFileMan::EOverWrite); + test(r == KErrBadName); + + // copy to very long but valid path (no filename) which will overflow + // when drive letter is pre-pended to it + newLongPath = newPath; + for (len=newLongPath.Length(); len< KMaxPath -2; len = newLongPath.Length()) + newLongPath.Append(_L("x\\")); + r = fileMan->Copy(file, newLongPath, CFileMan::EOverWrite); + test(r == KErrBadName); + + // copy to very long but valid path and filename which will overflow + // when drive letter is pre-pended to it + newLongPath.Append(_L("y")); + r = fileMan->Copy(file, newLongPath, CFileMan::EOverWrite); + test(r == KErrBadName); + + // copy to badly formed path + newLongPath = newPath; + newLongPath.Append(_L("\\y")); + r = fileMan->Copy(file, newLongPath, CFileMan::EOverWrite); + test(r == KErrBadName); + + // copy to correctly formed path which doesn't exist + newLongPath = newPath; + newLongPath.Append(_L("x\\y\\z")); + r = fileMan->Copy(file, newLongPath, CFileMan::EOverWrite); + test(r == KErrPathNotFound); + + delete fileMan; fileMan = NULL; + + file.Close(); + + + // First verify that we CANNOT rename a file retrieved from the server + // that has not been opened in EFileShareExclusive mode + + test.Next(_L("negative test of RFile::Rename()")); + + fsh = handsvr.GetFileHandle2(ssh, TFileMode(EFileShareAny | EFileWrite)); + test (fsh >= 0); + + // adopt the file handle from FHServer + r=file.AdoptFromServer(fsh, ssh); + test(r==KErrNone); + + r=file.Rename(_L("newname.txt")); + test(r==KErrPermissionDenied || r==KErrAccessDenied); + + // delete the file before we try to rename anything to it + r = fs.Delete(newFileName); + test(r == KErrNone || r == KErrNotFound); + + r=file.Rename(newFileName); + test(r==KErrPermissionDenied || r==KErrAccessDenied); + + file.Close(); + + + // Next verify that we CAN rename a file retrieved from the server + // that HAS been opened in EFileShareExclusive mode + + test.Next(_L("RFile::Rename()")); + + fsh = handsvr.GetFileHandle2(ssh, EFileWrite); + test (fsh >= 0); + + r=file.AdoptFromServer(fsh, ssh); + test(r==KErrNone); + + // delete the file before we try to rename anything to it + r = fs.Delete(newFileName); + test(r == KErrNone || r == KErrNotFound); + + r=file.Rename(newFileName); + test(r==KErrNone); + + file.Close(); + + // Next verify that we can delete the file (which should now + // have been moved to our private directory) + test.Next(_L("RFs::Delete()")); + r = fs.Delete(newFileName); + test(r == KErrNone); + + handsvr.Close(); + + fs.Close(); + } + +// +// Pass an open file to the server +// The server will use RFile::AdoptFromClient() +// +GLDEF_C void PassFile() + { + RFs fs; + TInt r=fs.Connect(); + test(r==KErrNone); + + // Check the number of open file handles + TInt resCount = fs.ResourceCount(); + test(resCount == 0); + + r=fs.ShareProtected(); + test(r==KErrNone); + + r=fs.CreatePrivatePath(drivenum); + test(r==KErrNone); + r=fs.SetSessionToPrivate(drivenum); + + + RFile file1; + r=file1.Replace(fs,KCliFileName,EFileWrite); + test(r==KErrNone); + r=file1.Write(KTestData()); + test(r==KErrNone); + file1.Close(); + + RFileHandleSharer handsvr; + do + { + r=handsvr.Connect(); + } + while(r==KErrNotFound); + test(r==KErrNone); + + r=handsvr.SetTestDrive(drivenum); + test(r==KErrNone); + + r=fs.SetSessionToPrivate(drivenum); + test(r==KErrNone); + + r=file1.Open(fs,KCliFileName,EFileRead); + test(r==KErrNone); + + // pass the file handle to FHServer + test.Next(_L("RFile::TransferToServer()")); + + TIpcArgs ipcArgs; + file1.TransferToServer(ipcArgs, 0, 1); + + r = handsvr.PassFileHandle(ipcArgs); + + + // verify that the original file handle's position is unchanged + TInt pos = 0; + r = file1.Seek(ESeekCurrent, pos); + test(r==KErrNone); + test(pos == 0); + + // make sure we can still use it + TBuf8<100> rbuf; + r=file1.Read(0,rbuf); + test(r==KErrNone); + + // Close the file + file1.Close(); + + handsvr.Close(); + + r=fs.MkDir(_L("C:\\mdir")); + test(r==KErrNone || r==KErrAlreadyExists); + + // Check the number of open file handles + resCount = fs.ResourceCount(); + test(resCount == 0); + + fs.Close(); + } + + +// +// Pass an invalid file handle to the server +// The server will use RFile::AdoptFromClient() +// +GLDEF_C void PassInvalidFile() + { + + RFs fs; + TInt r=fs.Connect(); + test(r==KErrNone); + + // Check the number of open file handles + TInt resCount = fs.ResourceCount(); + test(resCount == 0); + + r=fs.ShareProtected(); + test(r==KErrNone); + + r=fs.CreatePrivatePath(drivenum); + test(r==KErrNone); + r=fs.SetSessionToPrivate(drivenum); + + + RFile file1; + r=file1.Replace(fs,KCliFileName,EFileWrite); + test(r==KErrNone); + r=file1.Write(KTestData()); + test(r==KErrNone); + file1.Close(); + + RFileHandleSharer handsvr; + do + { + r=handsvr.Connect(); + } + while(r==KErrNotFound); + test(r==KErrNone); + + r=handsvr.SetTestDrive(drivenum); + test(r==KErrNone); + + r=fs.SetSessionToPrivate(drivenum); + test(r==KErrNone); + + r=file1.Open(fs,KCliFileName,EFileRead); + test(r==KErrNone); + + // check the resoure count - there should be 1 open file handle + resCount = fs.ResourceCount(); + test(resCount == 1); + + // pass an invalid file handle to FHServer + // by overwriting the IPC slots + test.Next(_L("PassInvalidFileHandle - RFile::TransferToServer()")); + + TIpcArgs ipcArgs; + + // Pass a bad RFs handle + file1.TransferToServer(ipcArgs, 0, 1); + + // check the resoure count - there should be 2 open file handles + resCount = fs.ResourceCount(); + test(resCount == 2); + + ipcArgs.Set(0, 0); // invalidate the RFs handle + r = handsvr.PassInvalidFileHandle(ipcArgs); + test (r == KErrBadHandle); + + // Pass a bad RFile handle + file1.TransferToServer(ipcArgs, 0, 1); + + // check the resoure count - there should be 3 open file handles + resCount = fs.ResourceCount(); + test(resCount == 3); + + ipcArgs.Set(1, 0); // invalidate the RFile handle + r = handsvr.PassInvalidFileHandle(ipcArgs); + test (r == KErrBadHandle); + + // Pass bad RFs and RFile handles + file1.TransferToServer(ipcArgs, 0, 1); + + // check the resoure count - there should be 4 open file handles + resCount = fs.ResourceCount(); + test(resCount == 4); + + + ipcArgs.Set(0, 0); // invalidate the RFs handle + ipcArgs.Set(1, 0); // invalidate the RFile handle + r = handsvr.PassInvalidFileHandle(ipcArgs); + test (r == KErrBadHandle); + + // Close the file + handsvr.Close(); + file1.Close(); + + // Check the number of open file handles + resCount = fs.ResourceCount(); + test(resCount == 3); + + fs.Close(); + } + + +// Pass RFs/RFile handles to the server using +// process parameter slots (RProcess::SetParameter()), +// resume the process and wait for it to read the file... +// The server will use RFile::AdoptFromCreator() +GLDEF_C void PassFile(RProcess& aProcess) + { + + RFs fs; + TInt r=fs.Connect(); + test(r==KErrNone); + + // Check the number of open file handles + TInt resCount = fs.ResourceCount(); + test(resCount == 0); + + r=fs.ShareProtected(); + test(r==KErrNone); + + r=fs.CreatePrivatePath(drivenum); + test(r==KErrNone); + r=fs.SetSessionToPrivate(drivenum); + + + RFile file1; + r=file1.Replace(fs,KCliFileName,EFileWrite); + test(r==KErrNone); + r=file1.Write(KTestData()); + test(r==KErrNone); + file1.Close(); + + r=file1.Open(fs, KCliFileName, EFileWrite); + + test(r==KErrNone); + + // NB slot 0 is reserved for the command line + + test.Next(_L("RFile::TransferToProcess()")); + + r = file1.TransferToProcess(aProcess, 1, 2); + + r = aProcess.SetParameter(3, drivenum); + test(r==KErrNone); + + r=fs.SetSessionToPrivate(drivenum); + test(r==KErrNone); + + // make sure we can still read from the file + TBuf8<100> rbuf; + r=file1.Read(0,rbuf); + test(r==KErrNone); + r=rbuf.CompareF(KTestData()); + test(r==KErrNone); + file1.Close(); + + r=fs.MkDir(_L("C:\\mdir")); + test(r==KErrNone || r==KErrAlreadyExists); + + // Check the number of open file handles - + // should be 1 (the one duplicated for the other process) + resCount = fs.ResourceCount(); + test(resCount == 1); + + fs.Close(); + + // Start the server thread + aProcess.Resume(); + + + + // connect to the server + RFileHandleSharer handsvr; + do + { + r=handsvr.Connect(); + } + while(r==KErrNotFound); + test(r==KErrNone); + + + r=handsvr.SetTestDrive(drivenum); + test(r==KErrNone); + + // wait for server to read the file + r = handsvr.PassFileHandleProcess(); + test (r == KErrNone); + + handsvr.Close(); + } + + + +GLDEF_C void CallTestsL(void) + { + RFs::CharToDrive(gDriveToTest,drivenum); + + // make sure the session path exists + RFs fs; + TInt r = fs.Connect(); + test(r==KErrNone); + + TFileName sessionp; + fs.SessionPath(sessionp); + r = fs.MkDirAll(sessionp); + test(r==KErrNone || r==KErrAlreadyExists); + fs.Close(); + + // Remember the number of open handles. Just for a sanity check .... + TInt start_thc, start_phc; + RThread().HandleCount(start_phc, start_thc); + test.Printf(_L("Handles: start_phc %d, start_thc %d\n"), start_phc, start_thc); + + //create test server + RProcess p; + r = p.Create(_L("FHServer.exe"), KNullDesC); + test(r==KErrNone); + + // RFile::Duplicate() tests + Duplicate(); + + // Pass RFs/RFile handles to the server using RFile::TransferToProcess() + // process parameter slots (RProcess::SetParameter()), + // resume the server process and wait for it to read the file... + PassFile(p); + + // Transfer the file handle to FHServer using RFile::TransferToServer(). + // Get FHServer to transfer it to FHServer2 + PassFile(); + + + // Get an open writeable file from FHServer2 via FHServer + // using RFile::AdoptFromServer() + RequestFileWrite(); + + // Deprecated RFile::Adopt() test + RequestFileDeprecatedAdopt(); + + // negative test + // Pass an invalid file handle to the server + PassInvalidFile(); + + + // Get an open file handle from FHServer2 via FHServer + // and test whether we can copy/rename/delete it etc + // be able to rename it. + RequestFileTest(); + + // stop the servers + RFileHandleSharer handsvr; + r=handsvr.Connect(); + test(r==KErrNone); + r = handsvr.Exit(); + test(r == KErrNone); + handsvr.Close(); + + // delete the test file + RFs cleanupfs; + r=cleanupfs.Connect(); + test(r==KErrNone); + r=cleanupfs.SetSessionToPrivate(drivenum); + test(r==KErrNone); + r=cleanupfs.Delete(KCliFileName); + test(r==KErrNone || r==KErrNotFound); + cleanupfs.Close(); + + + // wait for server process to end + TRequestStatus status; + p.Logon(status); + User::WaitForRequest(status); + test (status == KErrNone); + + // cleanup + p.Close(); + + // Sanity check for open handles + TInt end_thc, end_phc; + RThread().HandleCount(end_phc, end_thc); + test.Printf(_L("Handles: end_phc %d, end_thc %d\n"), end_phc, end_thc); + + test(start_thc == end_thc); + test(start_phc == end_phc); + + // and also for pending requests ... + test(RThread().RequestCount() == 0); + + + RDebug::Print(_L("End Of Tests")); + } + + +