diff -r 000000000000 -r 96e5fb8b040d kerneltest/f32test/server/t_notify.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/f32test/server/t_notify.cpp Thu Dec 17 09:24:54 2009 +0200 @@ -0,0 +1,4364 @@ +// 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_notify.cpp +// +// + +#include +#include +#include +#include +#include "t_server.h" + +const TInt KHeapSize=0x200; + +// wait for a bit since NotifyChange handled asynchronously and SetDriveName synchronously +const TInt KNotifyChangeAfter=100000; +const TInt KMediaRemountForceMediaChange = 0x00000001; + +RTest test(_L("T_NOTIFY")); +RSemaphore gSleepThread; +TInt gSocketNumber=0; +TInt SocketToDrive[KMaxPBusSockets]; + +//#define __INCLUDE_MANUAL_TESTS__ + +void do_check_no_pending_requests(TInt aLine) + { + RTimer timer; + TRequestStatus timerStat; + timer.CreateLocal(); + timer.After(timerStat, 125000); + User::WaitForAnyRequest(); + if(timerStat==KRequestPending) + { + RDebug::Printf("do_check_no_pending_requests failed at line %d",aLine); + test(0); + } + timer.Close(); + } +#define CHECK_NO_PENDING_REQUESTS do_check_no_pending_requests(__LINE__); + + +TBool CheckDriveRead(TInt aDrive) + //Determines if can connect to local drive number and read + { + TBusLocalDrive TBLD; + TBool TBLDChangedFlag; + + TInt r = TBLD.Connect(aDrive, TBLDChangedFlag); + test.Printf(_L("Connect returned %d\n"), r); + if (r == KErrNone) + { + const TInt KSectSize = 512; + TBuf8 sect; + r = TBLD.Read(0, KSectSize, sect); + test.Printf(_L("Read returned %d\n"), r); + TBLD.Disconnect(); + if(r!=KErrNone) + return EFalse; + else + return ETrue; + } + else + return EFalse; + } + +void GenerateMediaChange() + { + TPckgBuf pckg; + pckg()=0; + + RFs fs; + TInt r = fs.Connect(); + if (r == KErrNone) + { + r = fs.RemountDrive(CurrentDrive(), &pckg, (TUint)KMediaRemountForceMediaChange); + if(r == KErrNotReady) + { + r = KErrNone; + } + fs.Close(); + } + + if (r!=KErrNone) + { + RProcess me; + me.Panic(_L("GenMedChg"),r); + } + } + +enum TTestCode {ETest1,ETest2,ETest3,ETest4,ETest5,ETest6,ETest7,ETest8,ETest9,ETest10,ETest11,ETest12}; +const TUint KGenericEntryChange=0x02; + +static TInt ThreadEntryPoint(TAny* aTestCode) +// +// Thread entry point +// + { + RFs fs; + TInt r=fs.Connect(); + test(r==KErrNone); + r=fs.SetSessionPath(gSessionPath); + test(r==KErrNone); + TTestCode testCode=*(TTestCode*)&aTestCode; + RFile f; + switch (testCode) + { + + case ETest1: + r=f.Replace(fs,_L("\\F32-TST\\NOTIFY\\NewFile.txt"),EFileStream); + test(r==KErrNone); + f.Close(); + break; + + case ETest2: + r=f.Replace(fs,_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.doc"),EFileStream); + test(r==KErrNone); + f.Close(); + break; + + case ETest3: + r=fs.MkDir(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\SCARECROW\\")); + test((r==KErrNone)||(r==KErrAlreadyExists)); + break; + + case ETest4: + { + TRequestStatus s; + fs.NotifyChange(ENotifyAll,s); + test(s==KRequestPending); + gSleepThread.Signal(); + User::After(100000000); + } + break; + + case ETest5: + { + RFile file; + TInt r=file.Open(fs,_L("\\F32-TST\\NOTIFY\\kangaroo.txt"),EFileRead|EFileWrite); + test(r==KErrNone); + r=file.SetSize(sizeof(TCheckedUid)); + test(r==KErrNone); + r=file.Write(sizeof(TCheckedUid),_L8("012345678912")); + test(r==KErrNone); + TBuf8<64> dum; + r=file.Read(0,dum); + test(r==KErrNone); + file.Close(); + + r=file.Open(fs,_L("\\F32-TST\\NOTIFY\\koala.txt"),EFileRead|EFileWrite); + test(r==KErrNone); + r=file.SetSize(50); + test(r==KErrNone); + r=file.Write(sizeof(TCheckedUid),_L8("ABCDEFGHIJKLMNOPQRSTUVWXYZ")); + test(r==KErrNone); + r=file.Read(0,dum); + test(r==KErrNone); + file.Close(); + + r=file.Open(fs,_L("\\F32-TST\\NOTIFY\\dingo.txt"),EFileRead|EFileWrite); + test(r==KErrNone); + r=file.SetSize(50); + test(r==KErrNone); + r=file.Write(sizeof(TCheckedUid),_L8("01234567890123456789")); + test(r==KErrNone); + r=file.Read(0,dum); + test(r==KErrNone); + file.Close(); + gSleepThread.Signal(); + } + break; + + case ETest6: + { + GenerateMediaChange(); + User::After(300000); // Wait for a bit + gSleepThread.Signal(); + } + break; + + case ETest7: + { + RFile file; + TInt r=file.Open(fs,_L("\\F32-TST\\NOTIFY\\NewFILE.TXT"),EFileRead|EFileWrite); + test(r==KErrNone); + r=file.Write(_L8("asdfasdfasdf")); + test(r==KErrNone); + file.Close(); + gSleepThread.Signal(); + } + break; + + case ETest8: + { + r=f.Open(fs,_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\WickedWitch.msg"),EFileRead|EFileWrite); + test(r==KErrNone); + f.SetSize(500); + f.Close(); + break; + } + + case ETest9: + { + TRequestStatus s; + TFileName path=_L("\\F32-TST\\NOTIFY\\"); + fs.NotifyChange(ENotifyAll,s,path); + test(s==KRequestPending); + gSleepThread.Signal(); + User::After(100000000); + } + break; + case ETest10: + { + TFileName path=_L("\\F32-TST\\NOTIFY\\BehindTheCurtain\\"); + r=fs.MkDir(path); + test(r==KErrNone); + break; + } + case ETest11: + { + TFileName path=_L("\\F32-TST\\NOTIFY\\BehindTheCurtain\\PayNoAttention.man"); + RFile file; + r=file.Replace(fs,path,EFileStream); + test(r==KErrNone); + file.Close(); + break; + } + case ETest12: + { + RFile writer; + TInt r=writer.Open(fs,_L("\\F32-TST\\NOTIFY\\NewFile.txt"),EFileWrite|EFileShareAny); + test(r==KErrNone); + TInt i; + for(i=0; i<10; i++) + { + r=writer.Write(_L8("ABCDEFGHIJKLMNOPQRSTUVWXYZ")); + test(r==KErrNone); + User::After(1000000); + } + writer.Close(); + break; + } + default: + break; + } + return KErrNone; + } + +#if defined (__EPOC32__)//we have no removable media on Emulator yet +static void WaitForMediaChange() +// +// Wait for media driver to register drive is present +// + { + + TEntry entry; + FOREVER + { + User::After(10000); + TInt r=TheFs.Entry(_L("xxxxxxxx"),entry); + if (r!=KErrNotReady) + break; + } + } +#endif + +static void Test1() +// +// Test notification of an entry change +// + { + + test.Next(_L("Test notification of an entry change")); + TRequestStatus reqStat(KRequestPending); + TRequestStatus thrdStat(KRequestPending); + TInt r; + TheFs.NotifyChange(ENotifyEntry,reqStat); + RThread thread; + r=thread.Create(_L("MyThread"),ThreadEntryPoint,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ETest1); + test(r==KErrNone); + thread.Logon(thrdStat); + thread.Resume(); + User::WaitForRequest(thrdStat); + test(thrdStat==KErrNone); + thread.Close(); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + + RFile file; + r=file.Open(TheFs,_L("\\F32-TST\\NOTIFY\\NewFile.txt"),EFileRead|EFileWrite|EFileShareExclusive); + test(r==KErrNone); + file.Write(_L8("Somewhere over the rainbow..."),reqStat); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + TBuf8<256> buf; + file.Read(0, buf,reqStat); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + file.Close(); + + r=file.Open(TheFs,_L("\\F32-TST\\NOTIFY\\NewFile.txt"),EFileRead|EFileReadAsyncAll|EFileShareExclusive); + test(r==KErrArgument); + + r=file.Open(TheFs,_L("\\F32-TST\\NOTIFY\\NewFile.txt"),EFileRead|EFileReadAsyncAll|EFileShareReadersOnly); + test(r==KErrArgument); + + r=file.Open(TheFs,_L("\\F32-TST\\NOTIFY\\NewFile.txt"),EFileRead|EFileReadAsyncAll|EFileShareAny); + test(r==KErrNone); + file.Read(0, buf, 100, reqStat); + test(reqStat==KRequestPending); + file.Close(); + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + + r=file.Open(TheFs,_L("\\F32-TST\\NOTIFY\\NewFile.txt"),EFileRead|EFileReadAsyncAll|EFileShareAny); + test(r==KErrNone); + file.Read(0, buf, 100, reqStat); + test(reqStat==KRequestPending); + file.ReadCancel(reqStat); + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + file.Close(); + + r=file.Open(TheFs,_L("\\F32-TST\\NOTIFY\\NewFile.txt"),EFileRead|EFileReadAsyncAll|EFileWrite|EFileShareAny); + test(r==KErrNone); + file.Read(0, buf, 100, reqStat); + test(reqStat==KRequestPending); + file.SetSize(100); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + test(buf.Length() == 100); + file.Close(); + + test.Next(_L("Repeat Test notification of an entry change")); + TheFs.NotifyChange(ENotifyEntry,reqStat); + thread.Create(_L("MyThread2"),ThreadEntryPoint,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ETest1); + thread.Logon(thrdStat); + thread.Resume(); + User::WaitForRequest(thrdStat); + test(thrdStat==KErrNone); + thread.Close(); + User::WaitForRequest(reqStat); + if (reqStat!=KErrNone) + { + test.Printf(_L("ReqStat=%d\n"),reqStat.Int()); + //test.Getch(); + } + test(reqStat==KErrNone); + + test.Next(_L("Test Notify cancel")); + TheFs.NotifyChange(ENotifyEntry,reqStat); + TheFs.NotifyChangeCancel(); + User::WaitForRequest(reqStat); + + test.Next(_L("Test notification still works")); + TheFs.NotifyChange(ENotifyEntry,reqStat); + thread.Create(_L("MyThread3"),ThreadEntryPoint,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ETest1); + thread.Logon(thrdStat); + thread.Resume(); + User::WaitForRequest(thrdStat); + test(thrdStat==KErrNone); + thread.Close(); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + } + +static void Test2() +// +// Test notify for multiple clients +// + { + + test.Next(_L("Test notification of multiple clients")); + + TRequestStatus reqStat1(KRequestPending); + RFs fs1; + TInt r=fs1.Connect(); + test(r==KErrNone); + fs1.NotifyChange(ENotifyEntry,reqStat1); + + TRequestStatus reqStat2(KRequestPending); + RFs fs2; + r=fs2.Connect(); + test(r==KErrNone); + fs2.NotifyChange(ENotifyEntry,reqStat2); + + test(reqStat1==KRequestPending); + test(reqStat2==KRequestPending); + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\NEWFILE.TXT")); + test(r==KErrNone); + User::WaitForRequest(reqStat1); + User::WaitForRequest(reqStat2); + test(reqStat1==KErrNone); + test(reqStat2==KErrNone); + } + +static void Test3() +// +// Test notify cancel +// + { + + test.Next(_L("Cancel notification")); + RFs fs1; + TInt r=fs1.Connect(); + test(r==KErrNone); + + TRequestStatus status1; + TRequestStatus status2; + TRequestStatus status3; + TRequestStatus status4; + TRequestStatus status5; + + fs1.NotifyChange(ENotifyAll,status1); + fs1.NotifyChange(ENotifyAll,status2); + fs1.NotifyChange(ENotifyAll,status3); + fs1.NotifyChange(ENotifyAll,status4); + fs1.NotifyChange(ENotifyAll,status5); + test(status1==KRequestPending); + test(status2==KRequestPending); + test(status3==KRequestPending); + test(status4==KRequestPending); + test(status5==KRequestPending); + + test.Next(_L("RFs::NotifyCancel()")); +// Test that one call to RFs::NotifyCancel() cancels all outstanding requests + fs1.NotifyChangeCancel(); + User::WaitForRequest(status1); + test(status1==KErrCancel); + User::WaitForRequest(status2); + test(status2==KErrCancel); + User::WaitForRequest(status3); + test(status3==KErrCancel); + User::WaitForRequest(status4); + test(status4==KErrCancel); + User::WaitForRequest(status5); + test(status5==KErrCancel); +// Call the cancel function again to check no further action + fs1.NotifyChangeCancel(); + +// Test overloaded function to cancel a single request + test.Next(_L("Cancel notification request using function overload")); + fs1.NotifyChange(ENotifyAll,status1); + fs1.NotifyChange(ENotifyAll,status2); + fs1.NotifyChange(ENotifyAll,status3); + fs1.NotifyChange(ENotifyAll,status4); + fs1.NotifyChange(ENotifyAll,status5); + test(status1==KRequestPending); + test(status2==KRequestPending); + test(status3==KRequestPending); + test(status4==KRequestPending); + test(status5==KRequestPending); + +// Cancel the outstanding request with status5 + test.Next(_L("RFs::NotifyCancel()")); + fs1.NotifyChangeCancel(status5); + User::WaitForRequest(status5); + test(status1==KRequestPending); + test(status2==KRequestPending); + test(status3==KRequestPending); + test(status4==KRequestPending); + test(status5==KErrCancel); + + fs1.NotifyChangeCancel(status2); + User::WaitForRequest(status2); + + test(status1==KRequestPending); + test(status2==KErrCancel); + test(status3==KRequestPending); + test(status4==KRequestPending); + + fs1.NotifyChangeCancel(status4); + User::WaitForRequest(status4); + test(status1==KRequestPending); + test(status3==KRequestPending); + test(status4==KErrCancel); + + fs1.NotifyChangeCancel(status4); // Test no side effects on trying to cancel a request + test(status4==KErrCancel); // that has already been cancelled + + fs1.NotifyChangeCancel(status1); + User::WaitForRequest(status1); + test(status1==KErrCancel); + test(status3==KRequestPending); + fs1.NotifyChangeCancel(status1); // Test no side effects on trying to cancel a request + test(status1==KErrCancel); // that has already been cancelled + + fs1.NotifyChangeCancel(status3); + User::WaitForRequest(status3); + test(status3==KErrCancel); + + fs1.Close(); + } + +static void Test4() +// +// Test notify client death +// + { + + test.Next(_L("Kill client")); + TInt r=gSleepThread.CreateLocal(0); + test(r==KErrNone); + RThread clientThread; + r=clientThread.Create(_L("ClientThread"),ThreadEntryPoint,0x4000,KHeapSize,KHeapSize,(TAny*)ETest4); + if (r!=KErrNone) + { + test.Printf(_L(" ERROR: Failed to create clientthread %d\n"),r); + test(0); + //test.Getch(); + return; + } + clientThread.Resume(); + gSleepThread.Wait(); + + TBool jit = User::JustInTime(); + User::SetJustInTime(EFalse); + clientThread.Panic(_L("Test client thread panic"),KErrGeneral); + User::SetJustInTime(jit); + + clientThread.Close(); + + r=TheFs.MkDir(_L("\\F32-TST\\NOTIFY\\")); + test(r==KErrNone || r==KErrAlreadyExists); + MakeFile(_L("\\F32-TST\\NOTIFY\\NewFile.Txt")); + User::After(1000); + } + +static void Test5() +// +// Test reads and writes do not cause notification +// + { + + test.Next(_L("Test reads and writes do not cause notification")); + + + RFile file; + TInt r=file.Replace(TheFs,_L("\\F32-TST\\NOTIFY\\kangaroo.txt"),EFileRead|EFileWrite); + test(r==KErrNone); + file.Close(); + r=file.Replace(TheFs,_L("\\F32-TST\\NOTIFY\\koala.txt"),EFileRead|EFileWrite); + test(r==KErrNone); + file.Close(); + r=file.Replace(TheFs,_L("\\F32-TST\\NOTIFY\\dingo.txt"),EFileRead|EFileWrite); + test(r==KErrNone); + file.Close(); + + TRequestStatus reqStat=0; + TheFs.NotifyChange(ENotifyEntry,reqStat); + test(reqStat==KRequestPending); + + r=gSleepThread.CreateLocal(0); + test(r==KErrNone); + RThread clientThread; + r=clientThread.Create(_L("Test5Thread"),ThreadEntryPoint,0x4000,KHeapSize,KHeapSize,(TAny*)ETest5); + test(r==KErrNone); + clientThread.Resume(); + gSleepThread.Wait(); + test(reqStat==KRequestPending); + + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\kangaroo.txt")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\koala.txt")); + test(r==KErrNone); + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\dingo.txt")); + test(r==KErrNone); + + + + gSleepThread.Close(); + clientThread.Close(); + } + +#if defined (__EPOC32__)//we have no removable media on Emulator yet .. ??? we do now +static void Test6() +// +// Test media change notification +// + { + TDriveInfo driveInfo; + TInt r=TheFs.Drive(driveInfo,CurrentDrive()); + test(r==KErrNone); + // only test on removable media + if (driveInfo.iDriveAtt&KDriveAttRemovable) + { + TBuf<64> b; + b.Format(_L("Test Media change notification (socket:%d)"),gSocketNumber); + test.Next(b); + TRequestStatus reqStat=0; + TInt r; + TheFs.NotifyChange(ENotifyEntry,reqStat); + test(reqStat==KRequestPending); + r=gSleepThread.CreateLocal(0); + test(r==KErrNone); + RThread clientThread; + r=clientThread.Create(_L("Test6Thread"),ThreadEntryPoint,0x4000,KHeapSize,KHeapSize,(TAny*)ETest6); + test(r==KErrNone); + clientThread.Resume(); + gSleepThread.Wait(); + TInt reqInt=reqStat.Int(); + test(reqInt==KErrNone); + User::WaitForRequest(reqStat); + WaitForMediaChange(); + gSleepThread.Close(); + clientThread.Close(); + } + + //-- it seems that after generating media change the meia driver isn't ready for some time + User::After(2000000); + r=TheFs.Drive(driveInfo,CurrentDrive()); + test(r==KErrNone); + + + } +#endif + +static void Test7() +// +// Test Write to uid region does not trigger notification +// + { + + test.Next(_L("Test Write to uid region does not trigger notification")); + TRequestStatus reqStat=0; + MakeFile(_L("NewFile.TXT")); + TInt r; + TheFs.NotifyChange(ENotifyEntry,reqStat); + test(reqStat==KRequestPending); + + r=gSleepThread.CreateLocal(0); + test(r==KErrNone); + RThread clientThread; + r=clientThread.Create(_L("Test7Thread"),ThreadEntryPoint,0x4000,KHeapSize,KHeapSize,(TAny*)ETest7); + test(r==KErrNone); + clientThread.Resume(); + gSleepThread.Wait(); + test(reqStat==KRequestPending); + + r=TheFs.Delete(_L("Newfile.txt")); + test(r==KErrNone); + + User::WaitForRequest(reqStat); + + gSleepThread.Close(); + clientThread.Close(); + } + +#if defined (__EPOC32__)//we have no removable media on Emulator yet +static void MediaChangeExtendedNotification() +// +// Test media change notification +// Always notified of media change - regardless of requested TNotifyType +// + { + TDriveInfo driveInfo; + TInt r=TheFs.Drive(driveInfo,CurrentDrive()); + test(r==KErrNone); + // only test on removable media + if (driveInfo.iDriveAtt&KDriveAttRemovable) + { + test.Next(_L("Test Media change extended notification")); + TRequestStatus reqStat=0; + TFileName path = _L("\\F32-tst\\NOTIFY\\"); + TInt r; + TheFs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); + r=gSleepThread.CreateLocal(0); + test(r==KErrNone); + RThread clientThread; + gSocketNumber=0; + r=clientThread.Create(_L("Test6Thread1"),ThreadEntryPoint,0x4000,KHeapSize,KHeapSize,(TAny*)ETest6); //only generates a media change on removable media + test(r==KErrNone); + clientThread.Resume(); + gSleepThread.Wait(); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + WaitForMediaChange(); + gSleepThread.Close(); + clientThread.Close(); + + //-- it seems that after generating media change the meia driver isn't ready for some time + User::After(2000000); + r=TheFs.Drive(driveInfo,CurrentDrive()); + test(r==KErrNone); + + + TheFs.NotifyChange(ENotifyDisk,reqStat,path); + test(reqStat==KRequestPending); + r=gSleepThread.CreateLocal(0); + test(r==KErrNone); + r=clientThread.Create(_L("Test6Thread2"),ThreadEntryPoint,0x4000,KHeapSize,KHeapSize,(TAny*)ETest6); + test(r==KErrNone); + clientThread.Resume(); + gSleepThread.Wait(); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + WaitForMediaChange(); + gSleepThread.Close(); + clientThread.Close(); + + //-- it seems that after generating media change the meia driver isn't ready for some time + User::After(2000000); + r=TheFs.Drive(driveInfo,CurrentDrive()); + test(r==KErrNone); + + TheFs.NotifyChange(ENotifyWrite,reqStat,path); + test(reqStat==KRequestPending); + r=gSleepThread.CreateLocal(0); + test(r==KErrNone); + r=clientThread.Create(_L("Test6Thread3"),ThreadEntryPoint,0x4000,KHeapSize,KHeapSize,(TAny*)ETest6); + test(r==KErrNone); + clientThread.Resume(); + gSleepThread.Wait(); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + WaitForMediaChange(); + gSleepThread.Close(); + clientThread.Close(); + + //-- it seems that after generating media change the meia driver isn't ready for some time + User::After(2000000); + r=TheFs.Drive(driveInfo,CurrentDrive()); + test(r==KErrNone); + + } + } +#endif + +static void TestRequestAhead() +// +// Test extended notification works when path initially does not exist +// + { + test.Next(_L("Test Request Ahead")); +// First a simple example + + TInt r=TheFs.RmDir(_L("\\F32-TST\\NOTIFY\\BehindTheCurtain\\")); + test((r==KErrNotFound)||(r==KErrPathNotFound)||(r==KErrNone)); + + TFileName path=_L("\\F32-TST\\NOTIFY\\BehindTheCurtain\\"); + TRequestStatus reqStat(KRequestPending); + TheFs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); + + r=TheFs.MkDir(_L("\\F32-TST\\NOTIFY\\BehindTheCurtain\\")); + test(r==KErrNone); + + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + + path=_L("\\F32-TST\\NOTIFY\\BehindTheCurtain\\PayNoAttention.man"); + TheFs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); + + RFile file; + r=file.Replace(TheFs,path,EFileStream); + test(r==KErrNone); + file.Close(); + + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + + r=TheFs.Delete(path); + test(r==KErrNone); + + TheFs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); +// Now cancel the outstanding request + TheFs.NotifyChangeCancel(reqStat); + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + +// Repeat with a ENotifyFile request + TheFs.NotifyChange(ENotifyFile,reqStat,path); + test(reqStat==KRequestPending); + + r=file.Replace(TheFs,path,EFileStream); + test(r==KErrNone); + file.Close(); + + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + + r=TheFs.Delete(path); + test(r==KErrNone); + + TheFs.NotifyChange(ENotifyFile,reqStat,path); + test(reqStat==KRequestPending); +// Now cancel the outstanding request + TheFs.NotifyChangeCancel(reqStat); + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + +// Repeat with an ENotifyAttributes request + TheFs.NotifyChange(ENotifyAttributes,reqStat,path); + test(reqStat==KRequestPending); + + r=file.Replace(TheFs,path,EFileStream); + test(r==KErrNone); + file.Close(); + + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); // Monitoring attributes but informed anyway + + r=TheFs.Delete(path); + test(r==KErrNone); + + TheFs.NotifyChange(ENotifyAttributes,reqStat,path); + test(reqStat==KRequestPending); +// Now cancel the outstanding request + TheFs.NotifyChangeCancel(reqStat); + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + +// Repeat with an ENotifyWrite request + TheFs.NotifyChange(ENotifyWrite,reqStat,path); + test(reqStat==KRequestPending); + + r=file.Replace(TheFs,path,EFileStream); + test(r==KErrNone); + file.Close(); + + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); // Monitoring file writing but informed anyway + + r=TheFs.Delete(path); + test(r==KErrNone); + + TheFs.NotifyChange(ENotifyWrite,reqStat,path); + test(reqStat==KRequestPending); +// Now cancel the outstanding request + TheFs.NotifyChangeCancel(reqStat); + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + +// Repeat with an ENotifyDisk request + TheFs.NotifyChange(ENotifyDisk,reqStat,path); + test(reqStat==KRequestPending); + + r=file.Replace(TheFs,path,EFileStream); + test(r==KErrNone); + file.Close(); + + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); // Monitoring disk activity but informed anyway + + r=TheFs.Delete(path); + test(r==KErrNone); + + TheFs.NotifyChange(ENotifyAttributes,reqStat,path); + test(reqStat==KRequestPending); +// Now cancel the outstanding request + TheFs.NotifyChangeCancel(reqStat); + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + +// Now do much the same with directory monitoring + path=_L("\\F32-TST\\NOTIFY\\BehindTheCurtain\\"); + TheFs.RmDir(path); + + TheFs.NotifyChange(ENotifyDir,reqStat,path); + test(reqStat==KRequestPending); + + TheFs.MkDir(path); + test(r==KErrNone); + + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + + TheFs.RmDir(path); + test(r==KErrNone); + + TheFs.NotifyChange(ENotifyDir,reqStat,path); + test(r==KErrNone); + test(reqStat==KRequestPending); + +// Now cancel the outstanding request + TheFs.NotifyChangeCancel(reqStat); + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + + TheFs.NotifyChange(ENotifyDir,reqStat,path); + test(r==KErrNone); + test(reqStat==KRequestPending); + +// Get a separate thread to create the directory + RThread thread; + thread.Create(_L("RequestAheadyThready"),ThreadEntryPoint,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ETest10); + TRequestStatus thrdStat(KRequestPending); + thread.Logon(thrdStat); + thread.Resume(); + thread.Close(); + + User::WaitForRequest(thrdStat); + test(thrdStat==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + + TheFs.RmDir(path); + test(r==KErrNone); + +// Check that notification is not received for a non-existent file if only the previously +// non existent directory that contains it is created + path=_L("\\F32-TST\\NOTIFY\\BehindTheCurtain\\PayNoAttention.man"); + TheFs.NotifyChange(ENotifyEntry,reqStat,path); + test(r==KErrNone); + test(reqStat==KRequestPending); + + thread.Create(_L("RequestAheadThread"),ThreadEntryPoint,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ETest10); + thread.Logon(thrdStat); + thread.Resume(); + thread.Close(); + + User::WaitForRequest(thrdStat); + test(thrdStat==KErrNone); + test(reqStat==KRequestPending); + +// Now get a thread to create the file + thread.Create(_L("RequestAhead"),ThreadEntryPoint,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ETest11); + thread.Logon(thrdStat); + thread.Resume(); + User::WaitForRequest(thrdStat); + test(thrdStat==KErrNone); + thread.Close(); + + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + + TheFs.Delete(path); + test(r==KErrNone); + + TheFs.NotifyChange(ENotifyEntry,reqStat,path); + test(r==KErrNone); + test(reqStat==KRequestPending); + +// Now cancel the outstanding request + TheFs.NotifyChangeCancel(reqStat); + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + + path=_L("\\F32-TST\\NOTIFY\\BehindTheCurtain\\"); + TheFs.RmDir(path); + test(r==KErrNone); + } + + +static void Test8() +// +// Test extended notification of an entry change +// + { +// Test notification of an entry change in directory F32-TST + test.Next(_L("Test notification of an entry change")); + TRequestStatus reqStat(KRequestPending); + TRequestStatus thrdStat(KRequestPending); + TFileName path=(_L("\\F32-TST\\")); + + TheFs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); + RThread thread; + TInt r=thread.Create(_L("MyThread"),ThreadEntryPoint,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ETest1); + test(r==KErrNone); + thread.Logon(thrdStat); + thread.Resume(); + User::WaitForRequest(thrdStat); + test(thrdStat==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + thread.Close(); + +// Repeat the test + test.Next(_L("Repeat Test notification of an entry change")); + TheFs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); + r=thread.Create(_L("MyThread2"),ThreadEntryPoint,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ETest1); + test(r==KErrNone); + thread.Logon(thrdStat); + thread.Resume(); + User::WaitForRequest(thrdStat); + test(thrdStat==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + thread.Close(); + +// Test it can be cancelled + test.Next(_L("Test Notify cancel")); + TheFs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); + TheFs.NotifyChangeCancel(); + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + +// Test it can be notified again + test.Next(_L("Test notification still works")); + TheFs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); + r=thread.Create(_L("MyThread3"),ThreadEntryPoint,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ETest1); + test(r==KErrNone); + thread.Logon(thrdStat); + thread.Resume(); + User::WaitForRequest(thrdStat); + test(thrdStat==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + thread.Close(); + +// Test notification doesn't occur when a change occurs above the directory monitored +// (Notification of rename events occurring above the directory which affect the path +// will occur - this is tested for in Test18()) + test.Next(_L("Test changing above monitored directory")); + r=TheFs.MkDir(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\")); + test((r==KErrNone)||(r==KErrAlreadyExists)); + path=_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\"); + TheFs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); + r=thread.Create(_L("MyThread4"),ThreadEntryPoint,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ETest1); + test(r==KErrNone); + thread.Logon(thrdStat); + thread.Resume(); + User::WaitForRequest(thrdStat); + test(thrdStat==KErrNone); + User::After(500000); + thread.Close(); + test(reqStat==KRequestPending); + TheFs.NotifyChangeCancel(); + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + +// Test notification occurs when a change is made to the subdirectory monitored + test.Next(_L("Create a file in monitored subdirectory")); + TheFs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); + r=thread.Create(_L("MyThread5"),ThreadEntryPoint,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ETest2); + test(r==KErrNone); + thread.Logon(thrdStat); + thread.Resume(); + User::WaitForRequest(thrdStat); + test(thrdStat==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + thread.Close(); + + test.Next(_L("Create a directory in monitored subdirectory")); + TheFs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); + r=thread.Create(_L("MyThread6"),ThreadEntryPoint,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ETest3); + test(r==KErrNone); + thread.Logon(thrdStat); + thread.Resume(); + User::WaitForRequest(thrdStat); + test(thrdStat==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + thread.Close(); + + TheFs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.MkDir(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\SCARECROW\\TINMAN\\")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + + + r=TheFs.RmDir(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\SCARECROW\\TINMAN\\")); + test(r==KErrNone); + r=TheFs.RmDir(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\SCARECROW\\")); + test(r==KErrNone); + +// Test again that notification doesn't occur above the subdirectory being monitored + test.Next(_L("Test changing above monitored directory")); + r=TheFs.MkDir(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\")); + test((r==KErrNone)||(r==KErrAlreadyExists)); + path=_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\"); + + TheFs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); + r=thread.Create(_L("MyThread7"),ThreadEntryPoint,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ETest1); + test(r==KErrNone); + thread.Logon(thrdStat); + thread.Resume(); + User::WaitForRequest(thrdStat); + test(thrdStat==KErrNone); + User::After(500000); + thread.Close(); + test(reqStat==KRequestPending); + TheFs.NotifyChangeCancel(); + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + +// Test notification occurs when a change is made to the subdirectory monitored + test.Next(_L("Delete a file in monitored subdirectory")); + TheFs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.doc")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + + RFile file; + r=file.Replace(TheFs,_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\WickedWitch.msg"),EFileStream); + test(r==KErrNone); + file.Close(); + +// Test notification on a specific file + test.Next(_L("Monitor changes to a specific file")); + path+=_L("WickedWitch.msg"); + TheFs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=thread.Create(_L("MyThread8"),ThreadEntryPoint,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ETest8); + test(r==KErrNone); + thread.Logon(thrdStat); + thread.Resume(); + User::WaitForRequest(thrdStat); + test(thrdStat==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + thread.Close(); + +// Test notification does not occur if a change is made above the file + TheFs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); + thread.Create(_L("MyThread9"),ThreadEntryPoint,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ETest2); + thread.Logon(thrdStat); + thread.Resume(); + User::WaitForRequest(thrdStat); + test(thrdStat==KErrNone); + User::After(500000); + thread.Close(); + test(reqStat==KRequestPending); + TheFs.NotifyChangeCancel(); + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + +// Test notification occurs when a change is made to the file + test.Next(_L("Delete monitored file")); + TheFs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\WickedWitch.Msg")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// Test notification request is now submitted on the non existent path successfully + TheFs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); + TheFs.NotifyChangeCancel(reqStat); + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + + path=_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.Doc"); + TheFs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.Doc")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + + path=_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\"); + TheFs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.RmDir(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// Submit a request for a path which does not yet exist + path=_L("\\F32-TST\\NOTIFY\\GOOD_WITCH\\"); + TheFs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); +// Now create the directory we are waiting on + r=TheFs.MkDir(path); + test(r==KErrNone); +// Make sure the notification has now been received + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// Submit a request for a file which does not yet exist + path=_L("\\F32-TST\\NOTIFY\\GOOD_WITCH\\Red-Shoes.red"); + TheFs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); +// Now create the file we are waiting on + r=file.Replace(TheFs,path,EFileStream); + test(r==KErrNone); + file.Close(); +// Make sure the notification has now been received + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); +// Submit another notification request and delete the file + TheFs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.Delete(path); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + path=_L("\\F32-TST\\NOTIFY\\GOOD_WITCH\\"); + TheFs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.RmDir(path); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + // test passing in an empty string + TheFs.NotifyChange(ENotifyEntry,reqStat,_L("")); + User::WaitForRequest(reqStat); + test(reqStat==KErrArgument); + } + +static void Test9() +// +// Test notify for multiple clients +// + { + + test.Next(_L("Test notification of multiple clients")); + +// Create five sessions monitoring various levels of a directory tree + + TInt r=TheFs.MkDir(_L("\\F32-TST\\NOTIFY\\ANIMAL\\")); + test((r==KErrNone)||(r==KErrAlreadyExists)); + RFile file; + r=file.Replace(TheFs,_L("\\F32-TST\\NOTIFY\\ANIMAL\\cat.txt"),EFileStream); + test(r==KErrNone); + file.Close(); + r=file.Replace(TheFs,_L("\\F32-TST\\NOTIFY\\ANIMAL\\dog.txt"),EFileStream); + test(r==KErrNone); + file.Close(); + + TFileName path1=_L("\\F32-TST\\"); + TFileName path2=_L("\\F32-TST\\NOTIFY\\"); + TFileName path3=_L("\\F32-TST\\NOTIFY\\ANIMAL\\"); + TFileName path4=_L("\\F32-TST\\NOTIFY\\ANIMAL\\cat.txt"); + TFileName path5=_L("\\F32-TST\\NOTIFY\\ANIMAL\\dog.txt"); + TFileName path6=_L("?:\\F32-TST\\"); + + TRequestStatus reqStat1(KRequestPending); + RFs fs1; + r=fs1.Connect(); + test(r==KErrNone); + r=fs1.SetSessionPath(gSessionPath); + test(r==KErrNone); + fs1.NotifyChange(ENotifyEntry,reqStat1,path1); + + TRequestStatus reqStat2(KRequestPending); + RFs fs2; + r=fs2.Connect(); + test(r==KErrNone); + r=fs2.SetSessionPath(gSessionPath); + test(r==KErrNone); + fs2.NotifyChange(ENotifyEntry,reqStat2,path2); + + TRequestStatus reqStat3(KRequestPending); + RFs fs3; + r=fs3.Connect(); + test(r==KErrNone); + r=fs3.SetSessionPath(gSessionPath); + test(r==KErrNone); + fs3.NotifyChange(ENotifyEntry,reqStat3,path3); + + TRequestStatus reqStat4(KRequestPending); + RFs fs4; + r=fs4.Connect(); + test(r==KErrNone); + r=fs4.SetSessionPath(gSessionPath); + test(r==KErrNone); + fs4.NotifyChange(ENotifyEntry,reqStat4,path4); + + TRequestStatus reqStat5(KRequestPending); + RFs fs5; + r=fs5.Connect(); + test(r==KErrNone); + r=fs5.SetSessionPath(gSessionPath); + test(r==KErrNone); + fs5.NotifyChange(ENotifyEntry,reqStat5,path5); + + TRequestStatus reqStat6(KRequestPending); + RFs fs6; + r=fs6.Connect(); + test(r==KErrNone); + r=fs6.SetSessionPath(gSessionPath); + test(r==KErrNone); + fs6.NotifyChange(ENotifyEntry,reqStat6,path6); + + test(reqStat1==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + test(reqStat5==KRequestPending); + test(reqStat6==KRequestPending); + +// Make a change a the top level and check that only the session monitoring +// that level is notified + test.Next(_L("Test only client monitoring top level is notified")); + r=file.Replace(TheFs,_L("\\F32-TST\\NewFile.txt"),EFileStream); + test(r==KErrNone); + file.Close(); + User::WaitForRequest(reqStat1); + test(reqStat1==KErrNone); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + test(reqStat5==KRequestPending); + User::WaitForRequest(reqStat6); + test(reqStat6==KErrNone); + + r=TheFs.Delete(_L("\\F32-TST\\NewFile.txt")); + test(r==KErrNone); + +// Renew the notify request at the top level and make a change one step lower + fs1.NotifyChange(ENotifyEntry,reqStat1,path1); + fs6.NotifyChange(ENotifyEntry,reqStat6,path6); + test(reqStat1==KRequestPending); + test(reqStat6==KRequestPending); + + test.Next(_L("Test clients monitoring levels 1 and 2 are notified")); + r=file.Replace(TheFs,_L("\\F32-TST\\NOTIFY\\NewFile.txt"),EFileStream); + test(r==KErrNone); + file.Close(); + + User::WaitForRequest(reqStat1); + User::WaitForRequest(reqStat2); + test(reqStat1==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + test(reqStat5==KRequestPending); + User::WaitForRequest(reqStat6); + test(reqStat6==KErrNone); + + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\NewFile.txt")); + test(r==KErrNone); + +// Renew the notify request at the top and second levels and make a change +// one step lower still + fs1.NotifyChange(ENotifyEntry,reqStat1,path1); + fs2.NotifyChange(ENotifyEntry,reqStat2,path2); + fs6.NotifyChange(ENotifyEntry,reqStat6,path6); + test(reqStat1==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat6==KRequestPending); + + test.Next(_L("Test clients monitoring levels 1,2 and 3 are notified")); + r=file.Replace(TheFs,_L("\\F32-TST\\NOTIFY\\ANIMAL\\NewFile.txt"),EFileStream); + test(r==KErrNone); + file.Close(); + + User::WaitForRequest(reqStat1); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat3); + test(reqStat1==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KErrNone); + test(reqStat4==KRequestPending); + test(reqStat5==KRequestPending); + User::WaitForRequest(reqStat6); + test(reqStat6==KErrNone); + + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\ANIMAL\\NewFile.txt")); + test(r==KErrNone); + +// Renew the notify request at the top, second and third levels and make a change +// one step lower still + fs1.NotifyChange(ENotifyEntry,reqStat1,path1); + fs2.NotifyChange(ENotifyEntry,reqStat2,path2); + fs3.NotifyChange(ENotifyEntry,reqStat3,path3); + fs6.NotifyChange(ENotifyEntry,reqStat6,path6); + test(reqStat1==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat6==KRequestPending); + + test.Next(_L("Test clients monitoring levels 1 - 4 are notified")); + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\ANIMAL\\cat.txt")); + test(r==KErrNone); + User::WaitForRequest(reqStat1); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat3); + User::WaitForRequest(reqStat4); + test(reqStat1==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KErrNone); + test(reqStat4==KErrNone); + test(reqStat5==KRequestPending); + User::WaitForRequest(reqStat6); + test(reqStat6==KErrNone); + +// Renew the notify request at the top, second and third levels and on the file deleted above +// which will be successful, but will not complete (for obvious reasons) + +// Make a change one step lower still + fs1.NotifyChange(ENotifyEntry,reqStat1,path1); + fs2.NotifyChange(ENotifyEntry,reqStat2,path2); + fs3.NotifyChange(ENotifyEntry,reqStat3,path3); + fs6.NotifyChange(ENotifyEntry,reqStat6,path6); + fs4.NotifyChange(ENotifyEntry,reqStat4,path4); + test(reqStat1==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + test(reqStat6==KRequestPending); + + test.Next(_L("Test clients monitoring levels 1 - 3 and 5 are notified")); + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\ANIMAL\\dog.txt")); + test(r==KErrNone); + User::WaitForRequest(reqStat1); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat3); +// Don't wait for reqStat4 + User::WaitForRequest(reqStat5); + User::WaitForRequest(reqStat6); + test(reqStat1==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KErrNone); + test(reqStat4==KRequestPending); // File does not exist + test(reqStat5==KErrNone); + test(reqStat6==KErrNone); + + fs4.NotifyChangeCancel(reqStat4); + User::WaitForRequest(reqStat4); + test(reqStat4==KErrCancel); +// Renew the notify request at the top, second and third levels and attempt to renew +// the request on the files deleted above (which will fail). + + test.Next(_L("Test clients monitoring levels 1 - 3 are notified")); + fs1.NotifyChange(ENotifyEntry,reqStat1,path1); + fs2.NotifyChange(ENotifyEntry,reqStat2,path2); + fs3.NotifyChange(ENotifyEntry,reqStat3,path3); + fs4.NotifyChange(ENotifyEntry,reqStat4,path4); + fs6.NotifyChange(ENotifyEntry,reqStat6,path6); + fs5.NotifyChange(ENotifyEntry,reqStat5,path5); + test(reqStat1==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + test(reqStat5==KRequestPending); + test(reqStat6==KRequestPending); + + r=TheFs.RmDir(_L("\\F32-TST\\NOTIFY\\ANIMAL\\")); + test(r==KErrNone); + User::WaitForRequest(reqStat1); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat3); + test(reqStat1==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KErrNone); + test(reqStat4==KRequestPending); + test(reqStat5==KRequestPending); + User::WaitForRequest(reqStat6); + test(reqStat6==KErrNone); + +// Renew the notify request at the top and second levels on the third level +// which was removed - it'll succeed but won't complete. + + test.Next(_L("Test clients monitoring levels 1 and 2 are notified")); + test.Next(_L("Test clients' attempts to monitor levels 3-5 fail")); + fs1.NotifyChange(ENotifyEntry,reqStat1,path1); + fs2.NotifyChange(ENotifyEntry,reqStat2,path2); + fs3.NotifyChange(ENotifyEntry,reqStat3,path3); + fs6.NotifyChange(ENotifyEntry,reqStat6,path6); + + test(reqStat1==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + test(reqStat5==KRequestPending); + test(reqStat6==KRequestPending); + + fs1.NotifyChangeCancel(); + fs2.NotifyChangeCancel(); + + fs1.Close(); + fs2.Close(); +// Close the other sessions with requests outstanding to test that there's no evilness + fs3.Close(); + fs4.Close(); + fs5.Close(); + fs6.Close(); + + User::WaitForRequest(reqStat1); + User::WaitForRequest(reqStat2); + // Closing file server sessions doesn't seem to complete notifications, is this a bug? +// User::WaitForRequest(reqStat3); +// User::WaitForRequest(reqStat4); +// User::WaitForRequest(reqStat5); +// User::WaitForRequest(reqStat6); + } + +static void Test10() +// +// Test notify cancel +// + { + + test.Next(_L("Cancel notification request using simple function")); + TFileName path=_L("\\F32-TST\\NOTIFY\\"); + RFs fs1; + TInt r=fs1.Connect(); + test(r==KErrNone); + r=fs1.SetSessionPath(gSessionPath); + test(r==KErrNone); + + TRequestStatus status1; + TRequestStatus status2; + TRequestStatus status3; + TRequestStatus status4; + TRequestStatus status5; + + fs1.NotifyChange(ENotifyAll,status1,path); + fs1.NotifyChange(ENotifyAll,status2,path); + fs1.NotifyChange(ENotifyAll,status3,path); + fs1.NotifyChange(ENotifyAll,status4,path); + fs1.NotifyChange(ENotifyAll,status5,path); + test(status1==KRequestPending); + test(status2==KRequestPending); + test(status3==KRequestPending); + test(status4==KRequestPending); + test(status5==KRequestPending); + + test.Next(_L("RFs::NotifyCancel()")); +// Test that one call to RFs::NotifyCancel() cancels all outstanding requests + fs1.NotifyChangeCancel(); + User::WaitForRequest(status1); + test(status1==KErrCancel); + User::WaitForRequest(status2); + test(status2==KErrCancel); + User::WaitForRequest(status3); + test(status3==KErrCancel); + User::WaitForRequest(status4); + test(status4==KErrCancel); + User::WaitForRequest(status5); + test(status5==KErrCancel); +// Call the cancel function again to check no further action + fs1.NotifyChangeCancel(); + +// Test overloaded function to cancel a single request + test.Next(_L("Cancel notification request using function overload")); + fs1.NotifyChange(ENotifyAll,status1,path); + fs1.NotifyChange(ENotifyAll,status2,path); + fs1.NotifyChange(ENotifyAll,status3,path); + fs1.NotifyChange(ENotifyAll,status4,path); + fs1.NotifyChange(ENotifyAll,status5,path); + test(status1==KRequestPending); + test(status2==KRequestPending); + test(status3==KRequestPending); + test(status4==KRequestPending); + test(status5==KRequestPending); + +// Cancel the outstanding request with status5 + test.Next(_L("RFs::NotifyCancel()")); + fs1.NotifyChangeCancel(status5); + User::WaitForRequest(status5); + test(status1==KRequestPending); + test(status2==KRequestPending); + test(status3==KRequestPending); + test(status4==KRequestPending); + test(status5==KErrCancel); + + r=TheFs.MkDir(_L("\\F32-TST\\TROPICANA\\")); + test(r==KErrNone); + test(status1==KRequestPending); + test(status2==KRequestPending); + test(status3==KRequestPending); + test(status4==KRequestPending); + + fs1.NotifyChangeCancel(status2); + User::WaitForRequest(status2); + + test(status1==KRequestPending); + test(status2==KErrCancel); + test(status3==KRequestPending); + test(status4==KRequestPending); + + r=TheFs.RmDir(_L("\\F32-TST\\TROPICANA\\")); + test(r==KErrNone); + test(status1==KRequestPending); + test(status3==KRequestPending); + test(status4==KRequestPending); + + fs1.NotifyChangeCancel(status4); + User::WaitForRequest(status4); + test(status1==KRequestPending); + test(status3==KRequestPending); + test(status4==KErrCancel); + + fs1.NotifyChangeCancel(status4); // Test no side effects on trying to cancel a request + test(status4==KErrCancel); // that has already been cancelled + + fs1.NotifyChangeCancel(status1); + User::WaitForRequest(status1); + test(status1==KErrCancel); + test(status3==KRequestPending); + fs1.NotifyChangeCancel(status1); // Test no side effects on trying to cancel a request + test(status1==KErrCancel); // that has already been cancelled + + fs1.NotifyChangeCancel(status3); + User::WaitForRequest(status3); + test(status3==KErrCancel); + + fs1.Close(); + } + +static void Test11() +// +// Test notify client death +// + { + + test.Next(_L("Kill client while it is monitoring changes to a directory")); +// Call CreateLocal to create RSemaphore gSleepThread which is local to this process + TInt r=gSleepThread.CreateLocal(0); + test(r==KErrNone); + + RThread clientThread; + r=clientThread.Create(_L("ClientThread"),ThreadEntryPoint,0x4000,KHeapSize,KHeapSize,(TAny*)ETest9); + test(r==KErrNone); + clientThread.Resume(); + gSleepThread.Wait(); // Wait for gSleepThread to be signalled + // Client thread is waiting for notification of changes + // to directory \\F32-TST\\NOTIFY + + TBool jit = User::JustInTime(); + User::SetJustInTime(EFalse); + clientThread.Panic(_L("Test client thread panic"),KErrGeneral); // Panic client + User::SetJustInTime(jit); + + clientThread.Close(); + +// Make a change and check there's no disaster + r=TheFs.MkDir(_L("\\F32-TST\\NOTIFY\\")); + test(r==KErrNone || r==KErrAlreadyExists); + MakeFile(_L("\\F32-TST\\NOTIFY\\NewFile.Txt")); + User::After(1000); + } + + +static void Test12() +// +// Test reads and writes do not cause notification under ENotifyEntry +// Test reads and writes do cause notification under ENotifyAll +// + { + + test.Next(_L("Test reads and writes do not cause notification under ENotifyEntry")); + + RFile file; + TInt r=file.Replace(TheFs,_L("\\F32-TST\\NOTIFY\\kangaroo.txt"),EFileRead|EFileWrite); + test(r==KErrNone); + file.Close(); + r=file.Replace(TheFs,_L("\\F32-TST\\NOTIFY\\koala.txt"),EFileRead|EFileWrite); + test(r==KErrNone); + file.Close(); + r=file.Replace(TheFs,_L("\\F32-TST\\NOTIFY\\dingo.txt"),EFileRead|EFileWrite); + test(r==KErrNone); + file.Close(); + + TFileName path=_L("\\F32-TST\\NOTIFY\\"); + TRequestStatus reqStat1(KRequestPending); + RFs fs1; + r=fs1.Connect(); + test(r==KErrNone); + r=fs1.SetSessionPath(gSessionPath); + test(r==KErrNone); + fs1.NotifyChange(ENotifyEntry,reqStat1,path); + + TRequestStatus reqStat2(KRequestPending); + RFs fs2; + r=fs2.Connect(); + test(r==KErrNone); + r=fs2.SetSessionPath(gSessionPath); + test(r==KErrNone); + fs2.NotifyChange(ENotifyEntry,reqStat2,path); + + TRequestStatus reqStat3(KRequestPending); + RFs fs3; + r=fs3.Connect(); + test(r==KErrNone); + r=fs3.SetSessionPath(gSessionPath); + test(r==KErrNone); + fs3.NotifyChange(ENotifyEntry,reqStat3,path); + + test(reqStat1==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + + r=gSleepThread.CreateLocal(0); + test(r==KErrNone); + RThread thread1; + r=thread1.Create(_L("TestThread1"),ThreadEntryPoint,0x4000,KHeapSize,KHeapSize,(TAny*)ETest5); + test(r==KErrNone); + thread1.Resume(); + gSleepThread.Wait(); + + test(reqStat1==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\kangaroo.txt")); + test(r==KErrNone); + User::WaitForRequest(reqStat1); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat3); + test(reqStat1==KErrNone); // All three notifications occur because they + test(reqStat2==KErrNone); // are all monitoring the top level directory + test(reqStat3==KErrNone); // Later, we'll test monitoring individual files... + + gSleepThread.Close(); + thread1.Close(); + + test.Next(_L("Test reads and writes do cause notification under ENotifyAll")); + r=file.Replace(TheFs,_L("\\F32-TST\\NOTIFY\\kangaroo.txt"),EFileRead|EFileWrite); + test(r==KErrNone); + file.Close(); + + fs1.NotifyChange(ENotifyAll,reqStat1,path); + fs2.NotifyChange(ENotifyAll,reqStat2,path); + fs3.NotifyChange(ENotifyAll,reqStat3,path); + + test(reqStat1==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + + r=gSleepThread.CreateLocal(0); + test(r==KErrNone); + RThread thread2; + r=thread2.Create(_L("TestThread2"),ThreadEntryPoint,0x4000,KHeapSize,KHeapSize,(TAny*)ETest5); + test(r==KErrNone); + thread2.Resume(); + gSleepThread.Wait(); + + User::WaitForRequest(reqStat1); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat3); + test(reqStat1==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KErrNone); + + gSleepThread.Close(); + thread2.Close(); + + test.Next(_L("Monitor reads and writes on specific files with either TNotifyType")); + TFileName path1=path; + TFileName path2=path; + TFileName path3=path; + path1+=_L("kangaroo.txt"); + path2+=_L("koala.txt"); + path3+=_L("dingo.txt"); + + fs1.NotifyChange(ENotifyAll,reqStat1,path1); + fs2.NotifyChange(ENotifyEntry,reqStat2,path2); + fs3.NotifyChange(ENotifyAll,reqStat3,path3); + + test(reqStat1==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + + r=gSleepThread.CreateLocal(0); + test(r==KErrNone); + RThread thread3; + r=thread3.Create(_L("TestThread3"),ThreadEntryPoint,0x4000,KHeapSize,KHeapSize,(TAny*)ETest5); + test(r==KErrNone); + thread3.Resume(); + gSleepThread.Wait(); + + User::WaitForRequest(reqStat1); + test(reqStat1==KErrNone); + test(reqStat2==KRequestPending); // Monitoring with ENotifyEntry + User::WaitForRequest(reqStat3); + test(reqStat3==KErrNone); + + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\koala.txt")); + test(r==KErrNone); + User::WaitForRequest(reqStat2); + test(reqStat2==KErrNone); + + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\kangaroo.txt")); + test(r==KErrNone); + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\dingo.txt")); + test(r==KErrNone); + + gSleepThread.Close(); + thread3.Close(); + fs1.Close(); + fs2.Close(); + fs3.Close(); + } + + +static void Test13() +// +// Test file notification +// + { + RFs fs; // Session to be notified of any changes + TInt r=fs.Connect(); + test(r==KErrNone); + r=fs.SetSessionPath(gSessionPath); + test(r==KErrNone); + + + r=TheFs.MkDir(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\")); + test(r==KErrNone||r==KErrAlreadyExists); + + RFile file; + r=file.Replace(TheFs,_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\WickedWitch.msg"),EFileStream); + test(r==KErrNone||KErrAlreadyExists); + file.Close(); + +// Test notification on a specific file + test.Next(_L("Monitor changes to a specific file")); + TFileName path=_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\WickedWitch.msg"); + TRequestStatus reqStat(KRequestPending); + TRequestStatus thrdStat(KRequestPending); + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + RThread thread; + r=thread.Create(_L("MyThread7"),ThreadEntryPoint,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ETest8); + test(r==KErrNone); + thread.Logon(thrdStat); + thread.Resume(); + User::WaitForRequest(thrdStat); + test(thrdStat==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + thread.Close(); +// Test notification does not occur if a change is made above the file + fs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); + r=thread.Create(_L("MyThread8"),ThreadEntryPoint,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ETest1); + test(r==KErrNone); + thread.Logon(thrdStat); + thread.Resume(); + User::WaitForRequest(thrdStat); + test(thrdStat==KErrNone); + User::After(500000); + thread.Close(); + test(reqStat==KRequestPending); + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\NEWFILE.TXT")); + test(r==KErrNone); + +// Test notification does not occur if a change is made to another file + r=file.Replace(TheFs,_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Lion.log"),EFileStream); + test(r==KErrNone); + test(reqStat==KRequestPending); + file.Close(); + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Lion.log")); + test(r==KErrNone); + test(reqStat==KRequestPending); + + +// Test notification occurs when a change is made to the file + test.Next(_L("Delete monitored file")); + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\WickedWitch.Msg")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + + fs.Close(); + } + +static void Test14() + + { +// +// Test notification request succeeds with all RFile and RFs operations which result in +// notifications +// + RFs fs; + TInt r=fs.Connect(); // Session to be notified of any changes + test(r==KErrNone); + r=fs.SetSessionPath(gSessionPath); + test(r==KErrNone); + +// RFile::Write() to a file within the monitored directory + test.Next(_L("RFile::Write()")); + TFileName path=_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.Doc"); + TRequestStatus reqStat(KRequestPending); + + RFile file; + + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=file.Replace(TheFs,_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.doc"),EFileRead|EFileWrite); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=file.Write(0,_L8("Pay no attention to the man behind the curtain")); + test(r==KErrNone); + file.Close(); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// RFile::Read() a file within the monitored directory - no notification for reads + path=_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\"); + TBuf8<100> temp; + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=file.Open(TheFs,_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.doc"),EFileRead|EFileWrite); + test(r==KErrNone); + test(reqStat==KRequestPending); + r=file.Read(0,temp,100); + test(reqStat==KRequestPending); + +// RFile::SetAtt() of a file within the monitored directory + test.Next(_L("RFile::SetAtt()")); + r=file.SetAtt(KEntryAttSystem,KEntryAttNormal); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + +// RFile::SetSize() of a file within the monitored directory + test.Next(_L("RFile::SetSize()")); + r=file.SetSize(256); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + file.Close(); + +// RFile::Temp() to create a temp file within the monitored directory + test.Next(_L("RFile::Temp()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + TFileName fileName; + r=file.Temp(TheFs,path,fileName,EFileWrite); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + file.Close(); + +// RFile::SetModified() to change modification time of a file within monitored dir + test.Next(_L("RFile::SetModified()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + TTime now; + now.HomeTime(); + r=file.Open(TheFs,_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.doc"),EFileRead|EFileWrite); + test(r==KErrNone); + test(reqStat==KRequestPending); + file.SetModified(now); + file.Close(); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// RFs::SetEntry() to change a directory entry within the monitored directory + test.Next(_L("RFs::SetEntry()")); + TEntry entry; + fs.NotifyChange(ENotifyAll,reqStat,path); + r=TheFs.Entry(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.doc"),entry); + test(reqStat==KRequestPending); + now.HomeTime(); + r=TheFs.SetEntry(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.doc"),now,KEntryAttHidden,KEntryAttNormal); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// RFile::Set() to change file's modification time and attributes + test.Next(_L("RFile::Set()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + r=file.Open(TheFs,_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.doc"),EFileRead|EFileWrite); + test(r==KErrNone); + test(reqStat==KRequestPending); + now.HomeTime(); + r=file.Set(now,KEntryAttNormal,KEntryAttHidden); + file.Close(); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// RFs::SetDriveName() + test.Next(_L("RFs::SetDriveName()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + User::After(KNotifyChangeAfter); + r=TheFs.SetDriveName(KDefaultDrive,_L("DRIVETEST")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + fs.NotifyChange(ENotifyEntry,reqStat,path); + User::After(KNotifyChangeAfter); + r=TheFs.SetDriveName(KDefaultDrive,_L("TEST")); + test(r==KErrNone); + test(reqStat==KRequestPending); + fs.NotifyChangeCancel(reqStat); + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + fs.NotifyChange(ENotifyDisk,reqStat,path); + User::After(KNotifyChangeAfter); + r=TheFs.SetDriveName(KDefaultDrive,_L("DRIVE")); + test(r==KErrNone); + test(reqStat==KRequestPending); + fs.NotifyChangeCancel(reqStat); + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + + +// RFs::MkDir() + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + test.Next(_L("RFs::MkDir()")); + r=TheFs.MkDir(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\EMERALD_CITY\\")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// RFs::RmDir() + test.Next(_L("RFs::RmDir()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.RmDir(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\EMERALD_CITY\\")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// RFile::Create() + test.Next(_L("RFile::Create()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=file.Create(TheFs,_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Good_Witch.bat"),EFileRead|EFileWrite); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + file.Close(); + +// RFs::Delete() + test.Next(_L("RFs::Delete()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Good_Witch.bat")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// RFile::Replace() + test.Next(_L("RFile::Replace()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=file.Replace(TheFs,_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Good_Witch.bat"),EFileRead|EFileWrite); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + file.Close(); + +// RFs::Delete() + test.Next(_L("RFs::Delete()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Good_Witch.bat")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// RFs::SetVolumeLabel() - should only be notification when monitoring relevant TNotifyTypes + test.Next(_L("RFs::SetVolumeLabel")); + fs.NotifyChange(ENotifyAll,reqStat,path); + + TInt driveNum=CurrentDrive(); + TVolumeInfo volInfo; + TFileName currentVolName; + + r=TheFs.Volume(volInfo,driveNum); + test(r==KErrNone); + test(reqStat==KRequestPending); + currentVolName=volInfo.iName; + + r=TheFs.SetVolumeLabel(_L("VOL"),driveNum); + if (r==KErrNone) + { + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + r=TheFs.Volume(volInfo,driveNum); + test(r==KErrNone); + test(volInfo.iName==_L("VOL")); + // Test notification occurs under ENotifyDisk + fs.NotifyChange(ENotifyDisk,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.SetVolumeLabel(_L("ABCDEFGHIJK"),driveNum); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + r=TheFs.Volume(volInfo,driveNum); + test(r==KErrNone); + + test(volInfo.iName==_L("ABCDEFGHIJK")); + + // Test notification does not occur under ENotifyAttributes + fs.NotifyChange(ENotifyAttributes,reqStat,path); + r=TheFs.SetVolumeLabel(_L("TROPICANA"),driveNum); + test(r==KErrNone); + test(reqStat==KRequestPending); + r=TheFs.Volume(volInfo,driveNum); + test(r==KErrNone); + + test(volInfo.iName==_L("TROPICANA")); + + fs.NotifyChangeCancel(reqStat); + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + // Test notification occurs under ENotifyEntry + fs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.SetVolumeLabel(currentVolName,driveNum); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + r=TheFs.Volume(volInfo,driveNum); + test(r==KErrNone); + test(volInfo.iName==currentVolName); + } + + else // RFs::SetVolumeLabel() doesn't work on subst drives + { + fs.NotifyChangeCancel(); + User::WaitForRequest(reqStat); + test.Printf(_L("Cannot set volume label on a substed drive\n")); + } + + +// RFs::Rename() + + test.Next(_L("RFs::Rename()")); + fs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.Rename(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.doc"),_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Toto.doc")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + + r=TheFs.Rename(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Toto.doc"),_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.doc")); + test(r==KErrNone); + +#if defined(__WINS__) + if(gSessionPath[0]=='Y'||gSessionPath[0]=='X') +#endif + { + test.Next(_L("RFs::Rename() with max path length")); + TFileName longName=_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\"); + while(longName.Length()<(KMaxFileName-2)) + longName+=_L("a"); + r=TheFs.Rename(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.doc"),longName); + test(r==KErrNone); + fs.NotifyChange(ENotifyEntry,reqStat,longName); + test(reqStat==KRequestPending); + r=TheFs.Rename(longName,_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.doc")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + } + + fs.Close(); + } + + +static void Test15() + + { +// +// Repeat Test15 operations in a subtree of that monitored, and ensure notification +// occurs for a variety of RFile and RFs operations +// + RFs fs; // Session to be notified when a change occurs + TInt r=fs.Connect(); + test(r==KErrNone); + r=fs.SetSessionPath(gSessionPath); + test(r==KErrNone); + +// RFile::Write() to a file in the subtree + test.Next(_L("RFile::Write()")); + TFileName path=_L("\\F32-TST\\NOTIFY\\"); + TRequestStatus reqStat(KRequestPending); + fs.NotifyChange(ENotifyAll,reqStat,path); + + RFile file; + r=file.Open(TheFs,_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.doc"),EFileRead|EFileWrite); + test(r==KErrNone); + test(reqStat==KRequestPending); + r=file.Write(0,_L8("Pay no attention to the man behind the curtain")); + file.Close(); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// RFile::Read() a file within the monitored directory - no notification for reads + fs.NotifyChange(ENotifyAll,reqStat,path); + TBuf8<100> temp; + r=file.Open(TheFs,_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.doc"),EFileRead|EFileWrite); + test(r==KErrNone); + test(reqStat==KRequestPending); + r=file.Read(0,temp,100); + test(reqStat==KRequestPending); + +// RFile::SetAtt() of a file within the monitored directory + test.Next(_L("RFile::SetAtt()")); + r=file.SetAtt(KEntryAttNormal,KEntryAttHidden); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// RFile::SetSize() of a file within the monitored directory + test.Next(_L("RFile::SetSize()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=file.SetSize(256); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + file.Close(); + +// RFile::Temp() to create a temp file in the subtree + test.Next(_L("RFile::Temp()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + TFileName fileName; + r=file.Temp(TheFs,_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\"),fileName,EFileWrite); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + file.Close(); + +// RFile::SetModified() to change modification time of a file within monitored dir + test.Next(_L("RFile::SetModified()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + TTime now; + now.HomeTime(); + r=file.Open(TheFs,_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.doc"),EFileRead|EFileWrite); + test(r==KErrNone); + test(reqStat==KRequestPending); + file.SetModified(now); + file.Close(); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// RFs::Entry() to change a directory entry within the monitored directory + test.Next(_L("RFs::Entry()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + TEntry entry; + r=TheFs.Entry(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.doc"),entry); + test(reqStat==KRequestPending); + now.HomeTime(); + r=TheFs.SetEntry(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.doc"),now,KEntryAttHidden,KEntryAttNormal); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// RFile::Set() to change file's modification time and attributes + test.Next(_L("RFile::Set()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + r=file.Open(TheFs,_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.doc"),EFileRead|EFileWrite); + test(r==KErrNone); + test(reqStat==KRequestPending); + now.HomeTime(); + r=file.Set(now,KEntryAttNormal,KEntryAttHidden); + file.Close(); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// RFs::SetDriveName() + test.Next(_L("RFs::SetDriveName()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + User::After(KNotifyChangeAfter); + r=TheFs.SetDriveName(KDefaultDrive,_L("DRIVETEST")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + fs.NotifyChange(ENotifyEntry,reqStat,path); + r=TheFs.SetDriveName(KDefaultDrive,_L("TEST")); + test(r==KErrNone); + test(reqStat==KRequestPending); + User::After(KNotifyChangeAfter); + fs.NotifyChangeCancel(reqStat); + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + fs.NotifyChange(ENotifyDisk,reqStat,path); + User::After(KNotifyChangeAfter); + r=TheFs.SetDriveName(KDefaultDrive,_L("DRIVE")); + test(r==KErrNone); + test(reqStat==KRequestPending); + fs.NotifyChangeCancel(reqStat); + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + +// RFs::MkDir() + test.Next(_L("RFs::MkDir()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.MkDir(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\EMERALD_CITY\\")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// RFs::RmDir() + test.Next(_L("RFs::RmDir()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.RmDir(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\EMERALD_CITY\\")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// RFile::Create() + test.Next(_L("RFile::Create()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=file.Create(TheFs,_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Good_Witch.bat"),EFileRead|EFileWrite); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + file.Close(); + +// RFs::Delete() + test.Next(_L("RFs::Delete()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Good_Witch.bat")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// RFile::Replace() + test.Next(_L("RFile::Replace()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=file.Replace(TheFs,_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Good_Witch.bat"),EFileRead|EFileWrite); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + file.Close(); + +// RFs::Delete() + test.Next(_L("RFs::Delete()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Good_Witch.bat")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// RFs::SetVolumeLabel() - should be notification under relevant TNotifyType monitoring +// The operation is non-path specific so all outstanding interested requests are notified + test.Next(_L("RFs::SetVolumeLabel()")); + + fs.NotifyChange(ENotifyAll,reqStat,path); + + TInt driveNum=CurrentDrive(); + TVolumeInfo volInfo; + TFileName currentVolName; + r=TheFs.Volume(volInfo,driveNum); + test(r==KErrNone); + test(reqStat==KRequestPending); + currentVolName=volInfo.iName; + + r=TheFs.SetVolumeLabel(_L("VOL"),driveNum); + if (r==KErrNone) + { + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + r=TheFs.Volume(volInfo,driveNum); + test(r==KErrNone); + test(volInfo.iName==_L("VOL")); + // Test notification occurs under ENotifyDisk + fs.NotifyChange(ENotifyDisk,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.SetVolumeLabel(_L("ABCDEFGHIJK"),driveNum); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + r=TheFs.Volume(volInfo,driveNum); + test(r==KErrNone); + + test(volInfo.iName==_L("ABCDEFGHIJK")); + + // Test notification does not occur under ENotifyAttributes + fs.NotifyChange(ENotifyAttributes,reqStat,path); + r=TheFs.SetVolumeLabel(_L("TROPICANA"),driveNum); + test(r==KErrNone); + test(reqStat==KRequestPending); + r=TheFs.Volume(volInfo,driveNum); + test(r==KErrNone); + + test(volInfo.iName==_L("TROPICANA")); + + fs.NotifyChangeCancel(reqStat); + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + // Test notification occurs under ENotifyEntry + fs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.SetVolumeLabel(currentVolName,driveNum); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + r=TheFs.Volume(volInfo,driveNum); + test(r==KErrNone); + test(volInfo.iName==currentVolName); + } + + else // RFs::SetVolumeLabel() doesn't work on subst drives + { + fs.NotifyChangeCancel(); + User::WaitForRequest(reqStat); + test.Printf(_L("Cannot set volume label on a substed drive\n")); + } + + + +// Test that notification is made when change is made to monitored directory + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.MkDir(_L("\\F32-TST\\NOTIFY\\EMERALD_CITY\\")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.RmDir(_L("\\F32-TST\\NOTIFY\\EMERALD_CITY\\")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + fs.Close(); + } + + +static void Test16() + + { +// +// Repeat Test15 operations in a subtree of that monitored, and ensure notification +// does occur for a variety of file operations when subtree watching is on +// + RFs fs; + TInt r=fs.Connect(); // Session to be notified when a change occurs + test(r==KErrNone); + r=fs.SetSessionPath(gSessionPath); + test(r==KErrNone); + +// RFile::Write() to a file in the subtree + TFileName path=_L("\\F32-TST\\NOTIFY\\"); + TRequestStatus reqStat(KRequestPending); + fs.NotifyChange(ENotifyAll,reqStat,path); + + RFile file; + r=file.Open(TheFs,_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.doc"),EFileRead|EFileWrite); + test(r==KErrNone); + test(reqStat==KRequestPending); + r=file.Write(0,_L8("Pay no attention to the man behind the curtain")); + file.Close(); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// RFile::Read() a file within the monitored directory - no notification for reads + fs.NotifyChange(ENotifyAll,reqStat,path); + TBuf8<100> temp; + r=file.Open(TheFs,_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.doc"),EFileRead|EFileWrite); + test(r==KErrNone); + test(reqStat==KRequestPending); + r=file.Read(0,temp,100); + test(reqStat==KRequestPending); + +// RFile::SetAtt() of a file within the monitored directory + r=file.SetAtt(KEntryAttNormal,KEntryAttHidden); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// RFile::SetSize() of a file within the monitored directory + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=file.SetSize(256); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + file.Close(); + + +// RFile::SetModified() to change modification time of a file within monitored dir + fs.NotifyChange(ENotifyAll,reqStat,path); + TTime now; + now.HomeTime(); + r=file.Open(TheFs,_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.doc"),EFileRead|EFileWrite); + test(r==KErrNone); + test(reqStat==KRequestPending); + file.SetModified(now); + file.Close(); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// RFs::Entry() to change a directory entry within the monitored directory + fs.NotifyChange(ENotifyAll,reqStat,path); + TEntry entry; + r=TheFs.Entry(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.doc"),entry); + test(reqStat==KRequestPending); + now.HomeTime(); + r=TheFs.SetEntry(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.doc"),now,KEntryAttHidden,KEntryAttNormal); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// RFile::Set() to change file's modification time and attributes + fs.NotifyChange(ENotifyAll,reqStat,path); + r=file.Open(TheFs,_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.doc"),EFileRead|EFileWrite); + test(r==KErrNone); + test(reqStat==KRequestPending); + now.HomeTime(); + r=file.Set(now,KEntryAttNormal,KEntryAttHidden); + file.Close(); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// RFs::SetDriveName() - should be no notification ever with extended notification + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + User::After(KNotifyChangeAfter); + r=TheFs.SetDriveName(KDefaultDrive,_L("DRIVETEST")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + fs.NotifyChange(ENotifyEntry,reqStat,path); + User::After(KNotifyChangeAfter); + r=TheFs.SetDriveName(KDefaultDrive,_L("TEST")); + test(r==KErrNone); + test(reqStat==KRequestPending); + fs.NotifyChangeCancel(reqStat); + User::WaitForRequest(reqStat); + fs.NotifyChange(ENotifyDisk,reqStat,path); + User::After(KNotifyChangeAfter); + r=TheFs.SetDriveName(KDefaultDrive,_L("DRIVE")); + test(r==KErrNone); + test(reqStat==KRequestPending); + fs.NotifyChangeCancel(reqStat); + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + + +// RFs::MkDir() + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.MkDir(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\EMERALD_CITY\\")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// RFs::RmDir() + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.RmDir(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\EMERALD_CITY\\")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// RFile::Create() + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=file.Create(TheFs,_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Good_Witch.bat"),EFileRead|EFileWrite); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + file.Close(); + +// RFs::Delete() + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Good_Witch.bat")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// RFile::Replace() + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=file.Replace(TheFs,_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Good_Witch.bat"),EFileRead|EFileWrite); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + file.Close(); + +// RFs::Delete() + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Good_Witch.bat")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// RFs::SetVolumeLabel() +// Not path specific, so all outstanding requests of correct TNotifyType are notified + fs.NotifyChange(ENotifyAll,reqStat,path); + TInt driveNum=CurrentDrive(); + TVolumeInfo volInfo; + TFileName currentVolName; + r=TheFs.Volume(volInfo,driveNum); + test(r==KErrNone); + test(reqStat==KRequestPending); + currentVolName=volInfo.iName; + + r=TheFs.SetVolumeLabel(_L("VOL"),driveNum); + if (r==KErrNone) + { + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + r=TheFs.Volume(volInfo,driveNum); + test(r==KErrNone); + test(volInfo.iName==_L("VOL")); + // Test notification occurs under ENotifyDisk + fs.NotifyChange(ENotifyDisk,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.SetVolumeLabel(_L("ABCDEFGHIJK"),driveNum); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + r=TheFs.Volume(volInfo,driveNum); + test(r==KErrNone); + + test(volInfo.iName==_L("ABCDEFGHIJK")); + + // Test notification does not occur under ENotifyAttributes + fs.NotifyChange(ENotifyAttributes,reqStat,path); + r=TheFs.SetVolumeLabel(_L("TROPICANA"),driveNum); + test(r==KErrNone); + test(reqStat==KRequestPending); + r=TheFs.Volume(volInfo,driveNum); + test(r==KErrNone); + + test(volInfo.iName==_L("TROPICANA")); + + fs.NotifyChangeCancel(reqStat); + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + // Test notification occurs under ENotifyEntry + fs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.SetVolumeLabel(currentVolName,driveNum); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + r=TheFs.Volume(volInfo,driveNum); + test(r==KErrNone); + test(volInfo.iName==currentVolName); + } + + else // RFs::SetVolumeLabel() doesn't work on subst drives + { + fs.NotifyChangeCancel(); + User::WaitForRequest(reqStat); + test.Printf(_L("Cannot set volume label on a substed drive\n")); + } + +// RFs::Rename() + fs.NotifyChange(ENotifyEntry,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.Rename(_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Dorothy.doc"),_L("\\F32-TST\\NOTIFY\\MUNCHKINS\\Toto.doc")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + +// Test that notification is made when change is made to monitored directory + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.MkDir(_L("\\F32-TST\\NOTIFY\\EMERALD_CITY\\")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + r=TheFs.RmDir(_L("\\F32-TST\\NOTIFY\\EMERALD_CITY\\")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + fs.Close(); + } + + +static void Test17() +// +// Test multiple requests from a single session +// + { + + test.Next(_L("Test reads and writes do not cause notification under ENotifyEntry")); + + RFile file; + TInt r=file.Replace(TheFs,_L("\\F32-TST\\NOTIFY\\kangaroo.txt"),EFileRead|EFileWrite); + test(r==KErrNone); + file.Close(); + r=file.Replace(TheFs,_L("\\F32-TST\\NOTIFY\\koala.txt"),EFileRead|EFileWrite); + test(r==KErrNone); + file.Close(); + r=file.Replace(TheFs,_L("\\F32-TST\\NOTIFY\\dingo.txt"),EFileRead|EFileWrite); + test(r==KErrNone); + file.Close(); + + RFs fs; + r=fs.Connect(); + test(r==KErrNone); + r=fs.SetSessionPath(gSessionPath); + test(r==KErrNone); + + TRequestStatus reqStat1(KRequestPending); + TFileName path1=_L("\\F32-TST\\NOTIFY\\"); + fs.NotifyChange(ENotifyEntry,reqStat1,path1); + + TRequestStatus status1(KRequestPending); + TRequestStatus status2(KRequestPending); + TRequestStatus status3(KRequestPending); + TRequestStatus status4(KRequestPending); + TRequestStatus status5(KRequestPending); + TRequestStatus status6(KRequestPending); + + TRequestStatus statusExtended1(KRequestPending); + TRequestStatus statusExtended2(KRequestPending); + TRequestStatus statusExtended3(KRequestPending); + TRequestStatus statusExtended4(KRequestPending); + TRequestStatus statusExtended5(KRequestPending); + TRequestStatus statusExtended6(KRequestPending); + +// Request multiple notifications using standard change notification request + fs.NotifyChange(ENotifyEntry,status1); + fs.NotifyChange(ENotifyEntry,status2); + fs.NotifyChange(ENotifyEntry,status3); + fs.NotifyChange(ENotifyEntry,status4); + fs.NotifyChange(ENotifyEntry,status5); + fs.NotifyChange(ENotifyEntry,status6); + +// Request multiple notifications using extended change notification request + fs.NotifyChange(ENotifyEntry,statusExtended1,path1); + fs.NotifyChange(ENotifyEntry,statusExtended2,path1); + fs.NotifyChange(ENotifyEntry,statusExtended3,path1); + fs.NotifyChange(ENotifyEntry,statusExtended4,path1); + fs.NotifyChange(ENotifyEntry,statusExtended5,path1); + fs.NotifyChange(ENotifyEntry,statusExtended6,path1); + + TRequestStatus reqStat2(KRequestPending); + TFileName path2=_L("\\F32-TST\\NOTIFY\\kangaroo.txt"); + fs.NotifyChange(ENotifyEntry,reqStat2,path2); + + TRequestStatus reqStat3(KRequestPending); + TFileName path3=_L("\\F32-TST\\NOTIFY\\koala.txt"); + fs.NotifyChange(ENotifyEntry,reqStat3,path3); + + TRequestStatus reqStat4(KRequestPending); + TFileName path4=_L("\\F32-TST\\NOTIFY\\dingo.txt"); + fs.NotifyChange(ENotifyEntry,reqStat4,path4); + + + r=gSleepThread.CreateLocal(0); + test(r==KErrNone); + RThread thread1; + r=thread1.Create(_L("TestThread1"),ThreadEntryPoint,0x4000,KHeapSize,KHeapSize,(TAny*)ETest5); + test(r==KErrNone); + thread1.Resume(); + gSleepThread.Wait(); + + test(status1==KRequestPending); + test(status2==KRequestPending); + test(status3==KRequestPending); + test(status4==KRequestPending); + test(status5==KRequestPending); + test(status6==KRequestPending); + + test(statusExtended1==KRequestPending); + test(statusExtended2==KRequestPending); + test(statusExtended3==KRequestPending); + test(statusExtended4==KRequestPending); + test(statusExtended5==KRequestPending); + test(statusExtended6==KRequestPending); + + test(reqStat1==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\kangaroo.txt")); + test(r==KErrNone); + User::WaitForRequest(reqStat1); + test(reqStat1==KErrNone); + User::WaitForRequest(status1); + test(status1==KErrNone); + User::WaitForRequest(status2); + test(status2==KErrNone); + User::WaitForRequest(status3); + test(status3==KErrNone); + User::WaitForRequest(status4); + test(status4==KErrNone); + User::WaitForRequest(status5); + test(status5==KErrNone); + User::WaitForRequest(status6); + test(status6==KErrNone); + + User::WaitForRequest(statusExtended1); + test(statusExtended1==KErrNone); + User::WaitForRequest(statusExtended2); + test(statusExtended2==KErrNone); + User::WaitForRequest(statusExtended3); + test(statusExtended3==KErrNone); + User::WaitForRequest(statusExtended4); + test(statusExtended4==KErrNone); + User::WaitForRequest(statusExtended5); + test(statusExtended5==KErrNone); + User::WaitForRequest(statusExtended6); + test(statusExtended6==KErrNone); + + User::WaitForRequest(reqStat2); + test(reqStat2==KErrNone); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + fs.NotifyChangeCancel(); // Cancels both remaining notification requests + + User::WaitForRequest(reqStat3); + User::WaitForRequest(reqStat4); + + gSleepThread.Close(); + thread1.Close(); + + test.Next(_L("Test reads and writes do cause notification under ENotifyAll")); + r=file.Replace(TheFs,_L("\\F32-TST\\NOTIFY\\kangaroo.txt"),EFileRead|EFileWrite); + test(r==KErrNone); + file.Close(); + + fs.NotifyChange(ENotifyAll,reqStat1,path1); + fs.NotifyChange(ENotifyEntry,reqStat2,path2); + fs.NotifyChange(ENotifyAll,reqStat3,path3); + fs.NotifyChange(ENotifyEntry,reqStat4,path4); + test(reqStat1==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + + r=gSleepThread.CreateLocal(0); + test(r==KErrNone); + RThread thread2; + r=thread2.Create(_L("TestThread2"),ThreadEntryPoint,0x4000,KHeapSize,KHeapSize,(TAny*)ETest5); + test(r==KErrNone); + thread2.Resume(); + gSleepThread.Wait(); + + User::WaitForRequest(reqStat1); + test(reqStat1==KErrNone); + test(reqStat2==KRequestPending); + User::WaitForRequest(reqStat3); + test(reqStat3==KErrNone); + test(reqStat4==KRequestPending); + + gSleepThread.Close(); + thread2.Close(); + + fs.NotifyChange(ENotifyAll,reqStat1,path1); + fs.NotifyChange(ENotifyAll,reqStat3,path3); + + test(reqStat1==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + + r=gSleepThread.CreateLocal(0); + test(r==KErrNone); + RThread thread3; + r=thread3.Create(_L("TestThread3"),ThreadEntryPoint,0x4000,KHeapSize,KHeapSize,(TAny*)ETest5); + test(r==KErrNone); + thread3.Resume(); + gSleepThread.Wait(); + + User::WaitForRequest(reqStat1); + test(reqStat1==KErrNone); + test(reqStat2==KRequestPending); // Monitoring with ENotifyEntry + User::WaitForRequest(reqStat3); + test(reqStat3==KErrNone); + test(reqStat4==KRequestPending); // Monitoring with ENotifyEntry + + RFs fs2; + r=fs2.Connect(); + test(r==KErrNone); + r=fs2.SetSessionPath(gSessionPath); + test(r==KErrNone); + + TRequestStatus reqStat(KRequestPending); + fs2.NotifyChange(ENotifyEntry,reqStat); + test(reqStat==KRequestPending); + + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\kangaroo.txt")); + test(r==KErrNone); + User::WaitForRequest(reqStat2); + test(reqStat2==KErrNone); + test(reqStat4==KRequestPending); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + + fs2.NotifyChange(ENotifyAll,reqStat); + test(reqStat==KRequestPending); + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\koala.txt")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + test(reqStat4==KRequestPending); + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\dingo.txt")); + test(r==KErrNone); + User::WaitForRequest(reqStat4); + test(reqStat4==KErrNone); + + gSleepThread.Close(); + thread3.Close(); + fs.Close(); + } + +static void Test18() + + { +// +// Test notification request succeeds or fails as appropriate to the notification type +// with all file operations which result in notifications +// enum TNotifyType {ENotifyEntry=0x00,ENotifyAll=0x01,ENotifyFile=0x04,ENotifyDir=0x08, +// ENotifyAttributes=0x10,ENotifyWrite=0x20,ENotifyDisk=0x40}; +// + RFs fs; + TInt r=fs.Connect(); // Session to be notified of any changes + test(r==KErrNone); + r=fs.SetSessionPath(gSessionPath); + test(r==KErrNone); + +// RFile::Write() to a file within the monitored directory + test.Next(_L("RFile::Write()")); + TFileName path=_L("\\F32-TST\\NOTIFY\\NewFile.txt"); + TRequestStatus reqStat(KRequestPending); + TRequestStatus reqStat2(KRequestPending); + TRequestStatus reqStat3(KRequestPending); + TRequestStatus reqStat4(KRequestPending); + TRequestStatus reqStat5(KRequestPending); + TRequestStatus reqStat6(KRequestPending); + TRequestStatus reqStat7(KRequestPending); + + + RFile file; + r=file.Replace(TheFs,_L("\\F32-TST\\NOTIFY\\NewFile.txt"),EFileRead|EFileWrite); + test(r==KErrNone); + + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyFile,reqStat2,path); + fs.NotifyChange(ENotifyWrite,reqStat3,path); + fs.NotifyChange(ENotifyDir,reqStat4,path); + fs.NotifyChange(ENotifyEntry,reqStat5,path); + fs.NotifyChange(ENotifyAttributes,reqStat6,path); + fs.NotifyChange(ENotifyDisk,reqStat7,path); + + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + User::WaitForRequest(reqStat4); + test(reqStat4==KErrArgument); // Cannot monitor a file with ENotifyDir + test(reqStat5==KRequestPending); + test(reqStat6==KRequestPending); + fs.NotifyChange(ENotifyEntry,reqStat4,path); + test(reqStat4==KRequestPending); + + r=file.Write(0,_L8("Pay no attention to the man behind the curtain")); + file.Close(); + + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + test(reqStat2==KRequestPending); // Monitoring with ENotifyFile + User::WaitForRequest(reqStat3); + test(reqStat3==KErrNone); + test(reqStat4==KRequestPending); // Monitoring with ENotifyEntry + test(reqStat5==KRequestPending); + test(reqStat6==KRequestPending); + test(reqStat7==KRequestPending); + fs.NotifyChangeCancel(); // Cancels all outstanding notification requests + + User::WaitForRequest(reqStat2); + test(reqStat2==KErrCancel); + User::WaitForRequest(reqStat4); + test(reqStat4==KErrCancel); + User::WaitForRequest(reqStat5); + test(reqStat5==KErrCancel); + User::WaitForRequest(reqStat6); + test(reqStat6==KErrCancel); + User::WaitForRequest(reqStat7); + test(reqStat7==KErrCancel); + + r=file.Open(TheFs,_L("\\F32-TST\\NOTIFY\\NewFile.txt"),EFileRead|EFileWrite); + test(r==KErrNone); + +// RFile::SetAtt() of a file within the monitored directory + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyFile,reqStat2,path); + fs.NotifyChange(ENotifyEntry,reqStat3,path); + fs.NotifyChange(ENotifyAttributes,reqStat4,path); + fs.NotifyChange(ENotifyDir,reqStat5,path); + fs.NotifyChange(ENotifyWrite,reqStat6,path); + fs.NotifyChange(ENotifyDisk,reqStat7,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + User::WaitForRequest(reqStat5); + test(reqStat5==KErrArgument); + test(reqStat6==KRequestPending); + test(reqStat7==KRequestPending); + + test.Next(_L("RFile::SetAtt()")); + r=file.SetAtt(KEntryAttSystem,KEntryAttNormal); + test(r==KErrNone); + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat4); + test(reqStat==KErrNone); + test(reqStat2==KRequestPending); // Monitoring with ENotifyFile + test(reqStat3==KRequestPending); // Monitoring with ENotifyEntry + test(reqStat4==KErrNone); // Monitoring a file - can't use ENotifyDir + test(reqStat6==KRequestPending); + test(reqStat7==KRequestPending); + + fs.NotifyChange(ENotifyWrite,reqStat,path); + test(reqStat==KRequestPending); + fs.NotifyChange(ENotifyDir,reqStat4,path); + User::WaitForRequest(reqStat4); + test(reqStat4==KErrArgument); + r=file.SetAtt(KEntryAttNormal,KEntryAttSystem); + test(r==KErrNone); + test(reqStat==KRequestPending); // Monitoring with ENotifyWrite + fs.NotifyChangeCancel(); // Cancel outstanding notification request + + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + User::WaitForRequest(reqStat2); + test(reqStat2==KErrCancel); + User::WaitForRequest(reqStat3); + test(reqStat3==KErrCancel); + User::WaitForRequest(reqStat6); + test(reqStat6==KErrCancel); + User::WaitForRequest(reqStat7); + test(reqStat7==KErrCancel); + + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyFile,reqStat2,path); + fs.NotifyChange(ENotifyEntry,reqStat3,path); + fs.NotifyChange(ENotifyAttributes,reqStat4,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + +// RFile::SetSize() of a file within the monitored directory + test.Next(_L("RFile::SetSize()")); + r=file.SetSize(256); + test(r==KErrNone); + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat4); + test(reqStat==KErrNone); + test(reqStat2==KRequestPending); // Monitoring with ENotifyFile + test(reqStat3==KRequestPending); // Monitoring with ENotifyEntry + test(reqStat4==KErrNone); + + fs.NotifyChange(ENotifyWrite,reqStat,path); + test(reqStat==KRequestPending); + fs.NotifyChange(ENotifyDir,reqStat4,path); + User::WaitForRequest(reqStat4); + test(reqStat4==KErrArgument); + r=file.SetSize(200); + test(r==KErrNone); + User::After(1000000); + test(reqStat==KRequestPending); // Monitoring with ENotifyWrite + + file.Close(); + fs.NotifyChangeCancel(); // Cancels all outstanding notification requests + + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + User::WaitForRequest(reqStat2); + test(reqStat2==KErrCancel); + User::WaitForRequest(reqStat3); + test(reqStat3==KErrCancel); + +// RFile::Temp() to create a temp file within the monitored directory + test.Next(_L("RFile::Temp()")); + path=_L("\\F32-TST\\NOTIFY\\"); + + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyDir,reqStat2,path); + fs.NotifyChange(ENotifyEntry,reqStat3,path); + fs.NotifyChange(ENotifyAttributes,reqStat4,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + + TFileName fileName; + r=file.Temp(TheFs,path,fileName,EFileWrite); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); // Monitoring ENotifyEntry + test(reqStat4==KRequestPending); // Monitoring ENotifyAttributes + file.Close(); + fs.NotifyChangeCancel(); + + User::WaitForRequest(reqStat2); + test(reqStat2==KErrCancel); + User::WaitForRequest(reqStat3); + test(reqStat3==KErrCancel); + User::WaitForRequest(reqStat4); + test(reqStat4==KErrCancel); + + fs.NotifyChange(ENotifyFile,reqStat,path); + fs.NotifyChange(ENotifyDisk,reqStat2,path); + fs.NotifyChange(ENotifyWrite,reqStat3,path); + r=file.Temp(TheFs,path,fileName,EFileWrite); + test(r==KErrNone); + test(reqStat==KRequestPending); // Monitoring ENotifyFile + test(reqStat2==KRequestPending); // Monitoring ENotifyDisk + test(reqStat3==KRequestPending); // Monitoring ENotifyWrite + file.Close(); + + fs.NotifyChangeCancel(); // Cancels all outstanding notification requests + + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + User::WaitForRequest(reqStat2); + test(reqStat2==KErrCancel); + User::WaitForRequest(reqStat3); + test(reqStat3==KErrCancel); + +// RFile::SetModified() to change modification time of a file within monitored dir + test.Next(_L("RFile::SetModified()")); + path=_L("\\F32-TST\\NOTIFY\\NewFile.txt"); + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyEntry,reqStat2,path); + fs.NotifyChange(ENotifyAttributes,reqStat3,path); + fs.NotifyChange(ENotifyFile,reqStat4,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + + TTime now; + now.HomeTime(); + r=file.Open(TheFs,_L("\\F32-TST\\NOTIFY\\NewFile.txt"),EFileRead|EFileWrite); + test(r==KErrNone); + test(reqStat==KRequestPending); + file.SetModified(now); + file.Close(); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + test(reqStat2==KRequestPending); + User::WaitForRequest(reqStat3); + test(reqStat3==KErrNone); + test(reqStat4==KRequestPending); + fs.NotifyChangeCancel(); + + User::WaitForRequest(reqStat2); + test(reqStat2==KErrCancel); + User::WaitForRequest(reqStat4); + test(reqStat4==KErrCancel); + +// RFs::SetEntry() to change a directory entry within the monitored directory + test.Next(_L("RFs::SetEntry()")); + TEntry entry; + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyEntry,reqStat2,path); + fs.NotifyChange(ENotifyAttributes,reqStat3,path); + fs.NotifyChange(ENotifyDisk,reqStat4,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + + r=TheFs.Entry(_L("\\F32-TST\\NOTIFY\\NewFile.txt"),entry); + test(reqStat==KRequestPending); + now.HomeTime(); + r=TheFs.SetEntry(_L("\\F32-TST\\NOTIFY\\NewFile.txt"),now,KEntryAttHidden,KEntryAttNormal); + test(r==KErrNone); + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat3); + test(reqStat==KErrNone); + test(reqStat2==KRequestPending); + test(reqStat3==KErrNone); + test(reqStat4==KRequestPending); + fs.NotifyChangeCancel(); + + User::WaitForRequest(reqStat2); + test(reqStat2==KErrCancel); + User::WaitForRequest(reqStat4); + test(reqStat4==KErrCancel); + +// RFile::Set() to change file's modification time and attributes + test.Next(_L("RFile::Set()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyEntry,reqStat2,path); + fs.NotifyChange(ENotifyAttributes,reqStat3,path); + fs.NotifyChange(ENotifyWrite,reqStat4,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + + r=file.Open(TheFs,_L("\\F32-TST\\NOTIFY\\NewFile.txt"),EFileRead|EFileWrite); + test(r==KErrNone); + test(reqStat==KRequestPending); + now.HomeTime(); + r=file.Set(now,KEntryAttNormal,KEntryAttHidden); + file.Close(); + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat3); + test(reqStat==KErrNone); + test(reqStat2==KRequestPending); + test(reqStat3==KErrNone); + test(reqStat4==KRequestPending); + fs.NotifyChangeCancel(); + + User::WaitForRequest(reqStat2); + test(reqStat2==KErrCancel); + User::WaitForRequest(reqStat4); + test(reqStat4==KErrCancel); + +// RFs::SetDriveName() + + test.Next(_L("RFs::SetDriveName()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyEntry,reqStat2,path); + fs.NotifyChange(ENotifyDisk,reqStat3,path); + fs.NotifyChange(ENotifyAttributes,reqStat4,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + User::After(KNotifyChangeAfter); + + r=TheFs.SetDriveName(KDefaultDrive,_L("DRIVETEST")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + test(reqStat==KErrNone); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + fs.NotifyChangeCancel(); + + User::WaitForRequest(reqStat2); + test(reqStat2==KErrCancel); + User::WaitForRequest(reqStat3); + test(reqStat3==KErrCancel); + User::WaitForRequest(reqStat4); + test(reqStat4==KErrCancel); + +// RFs::MkDir() + test.Next(_L("RFs::MkDir()")); + path=_L("\\F32-TST\\NOTIFY\\"); + + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyEntry,reqStat2,path); + fs.NotifyChange(ENotifyDir,reqStat3,path); + fs.NotifyChange(ENotifyFile,reqStat4,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + + r=TheFs.MkDir(_L("\\F32-TST\\NOTIFY\\EMERALD_CITY\\")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat3); + test(reqStat==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KErrNone); + test(reqStat4==KRequestPending); + +// RFs::RmDir() + test.Next(_L("RFs::RmDir()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyDir,reqStat2,path); + fs.NotifyChange(ENotifyWrite,reqStat3,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + + r=TheFs.RmDir(_L("\\F32-TST\\NOTIFY\\EMERALD_CITY\\")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat2); + test(reqStat==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + fs.NotifyChangeCancel(); + + User::WaitForRequest(reqStat3); + test(reqStat3==KErrCancel); + User::WaitForRequest(reqStat4); + test(reqStat4==KErrCancel); + +// RFile::Create() + test.Next(_L("RFile::Create()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyEntry,reqStat2,path); + fs.NotifyChange(ENotifyDir,reqStat3,path); + fs.NotifyChange(ENotifyFile,reqStat4,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + + r=file.Create(TheFs,_L("\\F32-TST\\NOTIFY\\Good_Witch.bat"),EFileRead|EFileWrite); + test(r==KErrNone); + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat4); + test(reqStat==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KRequestPending); // Monitoring ENotifyDir + test(reqStat4==KErrNone); + file.Close(); + fs.NotifyChangeCancel(reqStat3); + User::WaitForRequest(reqStat3); + + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyEntry,reqStat2,path); + fs.NotifyChange(ENotifyDisk,reqStat3,path); + fs.NotifyChange(ENotifyWrite,reqStat4,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + + r=file.Create(TheFs,_L("\\F32-TST\\NOTIFY\\Bad_Witch.bat"),EFileRead|EFileWrite); + test(r==KErrNone); + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat2); + test(reqStat==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + file.Close(); + fs.NotifyChangeCancel(); + + User::WaitForRequest(reqStat3); + test(reqStat3==KErrCancel); + User::WaitForRequest(reqStat4); + test(reqStat4==KErrCancel); + +// RFs::Delete() + test.Next(_L("RFs::Delete()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyEntry,reqStat2,path); + fs.NotifyChange(ENotifyDir,reqStat3,path); + fs.NotifyChange(ENotifyFile,reqStat4,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\Good_Witch.bat")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat4); + test(reqStat==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KRequestPending); // Monitoring ENotifyDir + test(reqStat4==KErrNone); + fs.NotifyChangeCancel(reqStat3); + User::WaitForRequest(reqStat3); + test(reqStat3==KErrCancel); + + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyEntry,reqStat2,path); + fs.NotifyChange(ENotifyAttributes,reqStat3,path); + fs.NotifyChange(ENotifyAll,reqStat4,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\Bad_Witch.bat")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat4); + test(reqStat==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KRequestPending); + test(reqStat4==KErrNone); + fs.NotifyChangeCancel(reqStat3); + User::WaitForRequest(reqStat3); + test(reqStat3==KErrCancel); + +// RFile::Replace() + test.Next(_L("RFile::Replace()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyEntry,reqStat2,path); + fs.NotifyChange(ENotifyFile,reqStat3,path); + fs.NotifyChange(ENotifyDir,reqStat4,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + + r=file.Replace(TheFs,_L("\\F32-TST\\NOTIFY\\Good_Witch.bat"),EFileRead|EFileWrite); + test(r==KErrNone); + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat3); + test(reqStat==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KErrNone); + test(reqStat4==KRequestPending); + file.Close(); + fs.NotifyChangeCancel(); + + test(reqStat==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KErrNone); + User::WaitForRequest(reqStat4); + test(reqStat4==KErrCancel); + +// RFs::Delete() + test.Next(_L("RFs::Delete()")); + path=_L("\\F32-TST\\NOTIFY\\Good_Witch.bat"); + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyEntry,reqStat2,path); + fs.NotifyChange(ENotifyFile,reqStat3,path); + fs.NotifyChange(ENotifyDir,reqStat4,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + User::WaitForRequest(reqStat4); + test(reqStat4==KErrArgument); + + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\Good_Witch.bat")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat3); + test(reqStat==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KErrNone); + test(reqStat4==KErrArgument); + +// RFs::SetVolumeLabel() + test.Next(_L("RFs::SetVolumeLabel()")); + path=_L("\\F32-TST\\NOTIFY\\"); + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyEntry,reqStat2,path); + fs.NotifyChange(ENotifyFile,reqStat3,path); + fs.NotifyChange(ENotifyDir,reqStat4,path); + fs.NotifyChange(ENotifyWrite,reqStat5,path); + fs.NotifyChange(ENotifyAttributes,reqStat6,path); + fs.NotifyChange(ENotifyDisk,reqStat7,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + test(reqStat5==KRequestPending); + test(reqStat6==KRequestPending); + test(reqStat7==KRequestPending); + + TInt driveNum=CurrentDrive(); + TVolumeInfo volInfo; + TFileName currentVolName; + r=TheFs.Volume(volInfo,driveNum); + test(r==KErrNone); + test(reqStat==KRequestPending); + currentVolName=volInfo.iName; + + r=TheFs.SetVolumeLabel(_L("VOL"),driveNum); + if (r==KErrNone) + { + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat7); + + test(reqStat==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + test(reqStat5==KRequestPending); + test(reqStat6==KRequestPending); + test(reqStat7==KErrNone); + + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyEntry,reqStat2,path); + fs.NotifyChange(ENotifyDisk,reqStat7,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat7==KRequestPending); + + r=TheFs.SetVolumeLabel(currentVolName,driveNum); + test(r==KErrNone); + + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat7); + + test(reqStat==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + test(reqStat5==KRequestPending); + test(reqStat6==KRequestPending); + test(reqStat7==KErrNone); + + r=TheFs.Volume(volInfo,driveNum); + test(r==KErrNone); + test(volInfo.iName==currentVolName); + + fs.NotifyChangeCancel(); + + User::WaitForRequest(reqStat3); + test(reqStat3==KErrCancel); + User::WaitForRequest(reqStat4); + test(reqStat4==KErrCancel); + User::WaitForRequest(reqStat5); + test(reqStat5==KErrCancel); + User::WaitForRequest(reqStat6); + test(reqStat6==KErrCancel); + } + + else // RFs::SetVolumeLabel() doesn't work on subst drives + { + fs.NotifyChangeCancel(); + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat3); + User::WaitForRequest(reqStat4); + User::WaitForRequest(reqStat5); + User::WaitForRequest(reqStat6); + User::WaitForRequest(reqStat7); + test.Printf(_L("Cannot set volume label on a substed drive!\n")); + } + + +// RFile::Rename() + test.Next(_L("RFile::Rename()")); + path=_L("\\F32-TST\\NOTIFY\\"); + + file.Open(TheFs,_L("\\F32-TST\\NOTIFY\\NewFile.txt"),EFileShareExclusive|EFileWrite); + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyEntry,reqStat2,path); + fs.NotifyChange(ENotifyFile,reqStat3,path); + fs.NotifyChange(ENotifyDir,reqStat4,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + + r=file.Rename(_L("\\F32-TST\\NOTIFY\\OldFile.abc")); + test(r==KErrNone||r==KErrAlreadyExists); + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat3); + test(reqStat==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KErrNone); + test(reqStat4==KRequestPending); // Monitoring ENotifyDir + file.Close(); + fs.NotifyChangeCancel(); + User::WaitForRequest(reqStat4); + test(reqStat4==KErrCancel); + + path=_L("\\F32-TST\\NOTIFY\\OldFile.abc"); + + r=file.Open(TheFs,_L("\\F32-TST\\NOTIFY\\OldFile.abc"),EFileShareExclusive|EFileWrite); + test(r==KErrNone); + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyEntry,reqStat2,path); + fs.NotifyChange(ENotifyFile,reqStat3,path); + fs.NotifyChange(ENotifyDir,reqStat4,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + User::WaitForRequest(reqStat4); + test(reqStat4==KErrArgument); + + r=file.Rename(_L("\\F32-TST\\NOTIFY\\NewFile.xyz")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat3); + test(reqStat==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KErrNone); + test(reqStat4==KErrArgument); + file.Close(); + +// RFs::Rename() + test.Next(_L("RFs::Rename()")); + path=_L("\\F32-TST\\NOTIFY\\"); + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyEntry,reqStat2,path); + fs.NotifyChange(ENotifyFile,reqStat3,path); + fs.NotifyChange(ENotifyDir,reqStat4,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + + r=TheFs.Rename(_L("\\F32-TST\\NOTIFY\\NewFile.xyz"),_L("\\F32-TST\\NOTIFY\\NewerFile.cat")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat3); + test(reqStat==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KErrNone); + test(reqStat4==KRequestPending); // Changed a file not a directory entry + fs.NotifyChangeCancel(); + + test(reqStat==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KErrNone); + User::WaitForRequest(reqStat4); + test(reqStat4==KErrCancel); + + path=_L("\\F32-TST\\NOTIFY\\NewerFile.cat"); + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyEntry,reqStat2,path); + fs.NotifyChange(ENotifyFile,reqStat3,path); + fs.NotifyChange(ENotifyDir,reqStat4,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + User::WaitForRequest(reqStat4); + test(reqStat4==KErrArgument); + + r=TheFs.Rename(_L("\\F32-TST\\NOTIFY\\NewerFile.cat"),_L("\\F32-TST\\NOTIFY\\Original.dog")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat3); + test(reqStat==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KErrNone); + + path=_L("\\F32-TST\\NOTIFY\\"); + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyEntry,reqStat2,path); + fs.NotifyChange(ENotifyFile,reqStat3,path); + fs.NotifyChange(ENotifyDir,reqStat4,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + + r=TheFs.Rename(_L("\\F32-TST\\NOTIFY\\"),_L("\\F32-TST\\NOTIFY_TEMP\\")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat3); + User::WaitForRequest(reqStat4); + test(reqStat==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KErrNone); // Changed a directory entry but notified anyway despite + test(reqStat4==KErrNone); // requesting file notification only because the path we + // were monitoring has changed + + path=_L("\\F32-TST\\NOTIFY_TEMP\\Original.dog"); + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyEntry,reqStat2,path); + fs.NotifyChange(ENotifyFile,reqStat3,path); + fs.NotifyChange(ENotifyDir,reqStat4,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + User::WaitForRequest(reqStat4); + test(reqStat4==KErrArgument); + + r=TheFs.Rename(_L("\\F32-TST\\NOTIFY_TEMP\\"),_L("\\F32-TST\\NOTIFY\\")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat3); + test(reqStat==KErrNone); // Modified a directory above the level at which we + test(reqStat2==KErrNone); // are monitoring for changes - we must be notified + test(reqStat3==KErrNone); // anyway because the path has changed + + fs.NotifyChange(ENotifyAll,reqStat,path); + test(reqStat==KRequestPending); + fs.NotifyChange(ENotifyEntry,reqStat2,path); + test(reqStat2==KRequestPending); + fs.NotifyChange(ENotifyFile,reqStat3,path); + test(reqStat3==KRequestPending); + + fs.NotifyChangeCancel(reqStat); + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + fs.NotifyChangeCancel(reqStat2); + User::WaitForRequest(reqStat2); + test(reqStat2==KErrCancel); + fs.NotifyChangeCancel(reqStat3); + User::WaitForRequest(reqStat3); + test(reqStat3==KErrCancel); + + path=_L("\\F32-TST\\NOTIFY\\Original.dog"); + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyEntry,reqStat2,path); + fs.NotifyChange(ENotifyFile,reqStat3,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\Original.dog")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat3); + test(reqStat==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KErrNone); + + path=_L("\\F32-TST\\NOTIFY\\"); + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyEntry,reqStat2,path); + fs.NotifyChange(ENotifyDir,reqStat3,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + + r=TheFs.Rename(_L("\\F32-TST\\"),_L("\\F32-TEST\\")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat3); + test(reqStat==KErrNone); // Modified a directory above the level at which we + test(reqStat2==KErrNone); // are monitoring for changes but we receive notification + test(reqStat3==KErrNone); // because the notification path has been changed + + fs.NotifyChange(ENotifyAll,reqStat,path); + // Notification request is submitted, despite the subject's disappearance + test(reqStat==KRequestPending); + fs.NotifyChange(ENotifyEntry,reqStat2,path); + // Notification request is submitted, despite the subject's disappearance + test(reqStat2==KRequestPending); + fs.NotifyChange(ENotifyFile,reqStat3,path); + // Notification request is submitted, despite the subject's disappearance + test(reqStat3==KRequestPending); + + fs.NotifyChangeCancel(reqStat); + User::WaitForRequest(reqStat); + test(reqStat==KErrCancel); + fs.NotifyChangeCancel(reqStat2); + User::WaitForRequest(reqStat2); + test(reqStat2==KErrCancel); + fs.NotifyChangeCancel(reqStat3); + User::WaitForRequest(reqStat3); + test(reqStat3==KErrCancel); + + path=_L("\\F32-TEST\\NOTIFY\\"); + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyEntry,reqStat2,path); + fs.NotifyChange(ENotifyDir,reqStat3,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + + r=TheFs.Rename(_L("\\F32-TEST\\NOTIFY\\"),_L("\\F32-TEST\\NOTIFY_CHANGED\\")); + test(r==KErrNone); + + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat3); + + test(reqStat==KErrNone); // Rename the directory we were monitoring + test(reqStat2==KErrNone); + test(reqStat3==KErrNone); + +// Tidy up the test directory before continuing (while testing notifications of renaming to the monitored directory) + + path=_L("\\F32-TST\\NOTIFY_CHANGED\\"); + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyEntry,reqStat2,path); + fs.NotifyChange(ENotifyDir,reqStat3,path); + fs.NotifyChange(ENotifyFile,reqStat4,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + + r=TheFs.Rename(_L("\\F32-TEST\\"),_L("\\F32-TST\\")); + test(r==KErrNone); + + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat3); + + test(reqStat==KErrNone); // Renaming to (under) the directory we were monitoring + test(reqStat2==KErrNone); + test(reqStat3==KErrNone); + test(reqStat4==KRequestPending); + + fs.NotifyChangeCancel(reqStat4); + User::WaitForRequest(reqStat4); + test(reqStat4==KErrCancel); + + path=_L("\\F32-TST\\NOTIFY\\"); + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange(ENotifyEntry,reqStat2,path); + fs.NotifyChange(ENotifyDir,reqStat3,path); + fs.NotifyChange(ENotifyFile,reqStat4,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + + r=TheFs.Rename(_L("\\F32-TST\\NOTIFY_CHANGED\\"),_L("\\F32-TST\\NOTIFY\\")); + test(r==KErrNone); + + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat3); + + test(reqStat==KErrNone); // Renaming to the directory we were monitoring + test(reqStat2==KErrNone); + test(reqStat3==KErrNone); + test(reqStat4==KRequestPending); + + fs.NotifyChangeCancel(reqStat4); + User::WaitForRequest(reqStat4); + test(reqStat4==KErrCancel); + +// Test combinations of notify types + test.Next(_L("Test combinations of notify types")); + + path=_L("\\F32-TST\\NOTIFY\\"); + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange((TNotifyType)(KGenericEntryChange|ENotifyAttributes),reqStat2,path); + fs.NotifyChange((TNotifyType)(ENotifyDir|ENotifyFile),reqStat3,path); + fs.NotifyChange((TNotifyType)(ENotifyDisk|ENotifyAttributes),reqStat4,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + + r=file.Create(TheFs,_L("\\F32-TST\\NOTIFY\\Munchkin.msg"),EFileRead|EFileWrite); + test(r==KErrNone); + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat3); + test(reqStat==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KErrNone); + test(reqStat4==KRequestPending); // Monitoring ENotifyAttributes|ENotifyDisk + file.Close(); + fs.NotifyChangeCancel(reqStat4); + User::WaitForRequest(reqStat4); + test(reqStat4==KErrCancel); + +// RFile::SetModified() + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange((TNotifyType)(KGenericEntryChange|ENotifyAttributes),reqStat2,path); + fs.NotifyChange((TNotifyType)(ENotifyDir|ENotifyFile),reqStat3,path); + fs.NotifyChange((TNotifyType)(ENotifyDisk|ENotifyAttributes),reqStat4,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + + TTime nowTime; + nowTime.HomeTime(); + r=file.Open(TheFs,_L("\\F32-TST\\NOTIFY\\Munchkin.msg"),EFileRead|EFileWrite); + test(r==KErrNone); + test(reqStat==KRequestPending); + file.SetModified(now); + file.Close(); + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat4); + test(reqStat==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KRequestPending); + test(reqStat4==KErrNone); + fs.NotifyChangeCancel(); + User::WaitForRequest(reqStat3); + test(reqStat3==KErrCancel); + +// RFile::Write() + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange((TNotifyType)(KGenericEntryChange|ENotifyAttributes),reqStat2,path); + fs.NotifyChange((TNotifyType)(ENotifyFile|ENotifyWrite),reqStat3,path); + fs.NotifyChange((TNotifyType)(ENotifyDir|ENotifyWrite),reqStat4,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + + r=file.Open(TheFs,_L("\\F32-TST\\NOTIFY\\Munchkin.msg"),EFileRead|EFileWrite); + test(r==KErrNone); + r=file.Write(0,_L8("Pay no attention to the man behind the curtain")); + file.Close(); + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat3); + User::WaitForRequest(reqStat4); + test(reqStat==KErrNone); + test(reqStat2==KRequestPending); + test(reqStat3==KErrNone); + test(reqStat4==KErrNone); + fs.NotifyChangeCancel(reqStat2); // Cancels all outstanding notification requests + User::WaitForRequest(reqStat2); + test(reqStat2==KErrCancel); + +// RFs::Delete() + test.Next(_L("RFs::Delete()")); + fs.NotifyChange(ENotifyAll,reqStat,path); + fs.NotifyChange((TNotifyType)(KGenericEntryChange|ENotifyAttributes),reqStat2,path); + fs.NotifyChange((TNotifyType)(ENotifyFile|ENotifyWrite),reqStat3,path); + fs.NotifyChange((TNotifyType)(ENotifyDir|ENotifyWrite),reqStat4,path); + + test(reqStat==KRequestPending); + test(reqStat2==KRequestPending); + test(reqStat3==KRequestPending); + test(reqStat4==KRequestPending); + + r=TheFs.Delete(_L("\\F32-TST\\NOTIFY\\Munchkin.msg")); + test(r==KErrNone); + User::WaitForRequest(reqStat); + User::WaitForRequest(reqStat2); + User::WaitForRequest(reqStat3); + test(reqStat==KErrNone); + test(reqStat2==KErrNone); + test(reqStat3==KErrNone); + test(reqStat4==KRequestPending); + fs.NotifyChangeCancel(reqStat4); + User::WaitForRequest(reqStat4); + test(reqStat4==KErrCancel); + + fs.Close(); + } + +#if defined __EPOC32__ && defined __INCLUDE_MANUAL_TESTS__ +// Manual media change test +// assumes the media is intially present and then prompts +// the user to remove the media +static void Test99() + { + TBuf<64> b; + b.Format(_L("Test Manual Media change notification (socket:%d)"),gSocketNumber); + test.Next(b); + TRequestStatus reqStat=0; + + RFs fs; + TInt r=fs.Connect(); + test(r==KErrNone); + + TDriveInfo driveInfo; + TInt driveNum = EDriveC + SocketToDrive[gSocketNumber]; + + // verify TDriveInfo.iType == EMediaHardDisk + r = fs.Drive(driveInfo, driveNum); + test (r == KErrNone); + test.Printf(_L("iType = %d\n"), driveInfo.iType); + test(driveInfo.iType == EMediaHardDisk); + + + // ask the user to eject the media + TheFs.NotifyChange(ENotifyEntry,reqStat); + test(reqStat==KRequestPending); + test.Printf(_L("Please eject media on drive %C...\n"), 'A' + driveNum); + User::WaitForRequest(reqStat); + test.Printf(_L("Done.\n")); + TInt reqInt=reqStat.Int(); + test(reqInt==KErrNone); + User::WaitForRequest(reqStat); + + // verify TDriveInfo.iType == EMediaNotPresent + r = fs.Drive(driveInfo, driveNum); + test (r == KErrNone); + test.Printf(_L("iType = %d\n"), driveInfo.iType); + test(driveInfo.iType == EMediaNotPresent); + + + // ask the user to re-insert the media + TheFs.NotifyChange(ENotifyEntry,reqStat); + test(reqStat==KRequestPending); + test.Printf(_L("Please re-insert media...\n")); + User::WaitForRequest(reqStat); + test.Printf(_L("Done.\n")); + reqInt = reqStat.Int(); + test(reqInt==KErrNone); + User::WaitForRequest(reqStat); + + // verify TDriveInfo.iType == EMediaHardDisk + r = fs.Drive(driveInfo, driveNum); + test (r == KErrNone); + test.Printf(_L("iType = %d\n"), driveInfo.iType); + test(driveInfo.iType == EMediaHardDisk); + + fs.Close(); + } +#endif // __INCLUDE_MANUAL_TESTS__ + + +//--------------------------------------------- +//! @SYMTestCaseID PBASE-T_NOTIFY-0042 +//! @SYMTestType UT +//! @SYMREQ REQ5664 +//! @SYMTestCaseDesc Test asynchronous RFile API's +//! @SYMTestActions Test normal asynchronous read, share modes, read cancellation, race conditions +//! (with RFile::SetSize() and RFile::Write()), multiple asynchronous readers. +//! @SYMTestExpectedResults Expected behaviour reached. +//! @SYMTestPriority High +//! @SYMTestStatus Implemented +//--------------------------------------------- +static void TestAsyncReader() +// +// Test asynchronous read notifications +// + { + TRequestStatus readStat1(KRequestPending); + TRequestStatus readStat2(KRequestPending); + TRequestStatus thrdStat(KRequestPending); + + MakeFile(_L("\\F32-TST\\NOTIFY\\NewFile.Txt")); + + test.Next(_L("Test original behaviour of asynchronous read API")); + RFile reader; + TInt r=reader.Open(TheFs,_L("\\F32-TST\\NOTIFY\\NewFile.txt"),EFileRead|EFileShareAny); + test(r==KErrNone); + TBuf8<596> readBuf; + reader.Read(0, readBuf, 100, readStat1); + User::WaitForRequest(readStat1); + test(readStat1==KErrNone); + test(readBuf.Length()==0); + reader.Close(); + + test.Next(_L("Test asynchronous read fails in EFileShareExclusive mode")); + r=reader.Open(TheFs,_L("\\F32-TST\\NOTIFY\\NewFile.txt"),EFileRead|EFileReadAsyncAll|EFileShareExclusive); + test(r==KErrArgument); + + test.Next(_L("Test asynchronous read fails in EFileShareReadersOnly mode")); + r=reader.Open(TheFs,_L("\\F32-TST\\NOTIFY\\NewFile.txt"),EFileRead|EFileReadAsyncAll|EFileShareReadersOnly); + test(r==KErrArgument); + + test.Next(_L("Test asynchronous read is cancelled when file is closed")); + r=reader.Open(TheFs,_L("\\F32-TST\\NOTIFY\\NewFile.txt"),EFileRead|EFileReadAsyncAll|EFileShareAny); + test(r==KErrNone); + reader.Read(0, readBuf, 100, readStat1); + test(readStat1==KRequestPending); + reader.Close(); + User::WaitForRequest(readStat1); + test(readStat1==KErrCancel); + + test.Next(_L("Test asynchronous read can be cancelled")); + r=reader.Open(TheFs,_L("\\F32-TST\\NOTIFY\\NewFile.txt"),EFileRead|EFileReadAsyncAll|EFileShareAny); + test(r==KErrNone); + reader.Read(0, readBuf, 100, readStat1); + test(readStat1==KRequestPending); + reader.ReadCancel(readStat1); + User::WaitForRequest(readStat1); + test(readStat1==KErrCancel); + reader.Close(); + + // DEF105438: File server thread safety issues + // Up the priority of this thread so that we can cancel the request before the drive thread + // runs (to test whether cancelling still works...) + test.Next(_L("Test asynchronous read is cancelled when running at high priority")); + r=reader.Open(TheFs,_L("\\F32-TST\\NOTIFY\\NewFile.txt"),EFileRead|EFileReadAsyncAll|EFileShareAny); + test(r==KErrNone); + RThread thisThread; + thisThread.SetPriority(EPriorityRealTime); + reader.Read(0, readBuf, 100, readStat1); + test(readStat1==KRequestPending); + reader.ReadCancel(readStat1); + test.Printf(_L("readStat1 %d"), readStat1.Int()); + User::WaitForRequest(readStat1); + test(readStat1==KErrCancel); + reader.Close(); + thisThread.SetPriority(EPriorityNormal); + + test.Next(_L("Test asynchronous read is notified due to RFile::SetSize()")); + r=reader.Open(TheFs,_L("\\F32-TST\\NOTIFY\\NewFile.txt"),EFileRead|EFileReadAsyncAll|EFileWrite|EFileShareAny); + test(r==KErrNone); + reader.Read(0, readBuf, 100, readStat1); + test(readStat1==KRequestPending); + r = reader.SetSize(100); + test(r==KErrNone); + User::WaitForRequest(readStat1); + test(readStat1==KErrNone); + test(readBuf.Length() == 100); + r=reader.SetSize(0); + test(r==KErrNone); + reader.Close(); + + test.Next(_L("Test asynchronous read is notified due to RFile::Write()")); + r=reader.Open(TheFs,_L("\\F32-TST\\NOTIFY\\NewFile.txt"),EFileRead|EFileReadAsyncAll|EFileWrite|EFileShareAny); + test(r==KErrNone); + reader.Read(0, readBuf, 26, readStat1); + test(readStat1==KRequestPending); + RFile writer; + r=writer.Open(TheFs,_L("\\F32-TST\\NOTIFY\\NewFile.txt"),EFileWrite|EFileShareAny); + writer.Write(_L8("ABCDEFGHIJKLMNOPQRSTUVWXYZ")); + User::WaitForRequest(readStat1); + test(readStat1==KErrNone); + test(readBuf.Length() == 26); + reader.Close(); + writer.Close(); + + test.Next(_L("Test multiple asynchronous readers notified from separate thread")); + r=reader.Open(TheFs,_L("\\F32-TST\\NOTIFY\\NewFile.txt"),EFileRead|EFileReadAsyncAll|EFileWrite|EFileShareAny); + test(r==KErrNone); + r=reader.SetSize(0); + test(r==KErrNone); + const TInt KReadLen = 26; + test.Printf(_L(">Read%d[%d]\n"), 0, KReadLen); + reader.Read(0, readBuf, KReadLen, readStat1); + TBuf8<596> readBuf2; + test.Printf(_L(">Read%d[%d]\n"), 1, KReadLen); + reader.Read(KReadLen, readBuf2, KReadLen, readStat2); + test(readStat1==KRequestPending); + test(readStat2==KRequestPending); + + RThread thread; + r=thread.Create(_L("MyThread"),ThreadEntryPoint,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ETest12); + test(r==KErrNone); + thread.Logon(thrdStat); + thread.Resume(); + thread.Close(); + + RTimer timer; + TRequestStatus timerStat(KRequestPending); + timer.CreateLocal(); + timer.After(timerStat, 30000000); // 30 seconds timeout (the following async test should take 10 seconds) + test(timerStat==KRequestPending); + + #define ODDPASS (pass&0x01) + #define REQSTAT (ODDPASS ? readStat2 : readStat1) + #define PENDSTAT (ODDPASS ? readStat1 : readStat2) + #define COMPLEN (ODDPASS ? KReadLen : (pass+1)*KReadLen) + #define READLEN (ODDPASS ? KReadLen : (pass+3)*KReadLen) + #define READPOS (ODDPASS ? (pass+2)*KReadLen : 0) + #define READBUF (ODDPASS ? readBuf2 : readBuf) + + TInt pass = 0; + FOREVER + { + User::WaitForRequest(REQSTAT, timerStat); + test(REQSTAT==KErrNone); + test(timerStat==KRequestPending); + test(READBUF.Length() == COMPLEN); + test(READBUF.Right(KReadLen) == _L8("ABCDEFGHIJKLMNOPQRSTUVWXYZ")); + test.Printf(_L(">Read%d[%d]\n"), pass&0x01, READLEN); + reader.Read(READPOS, READBUF, READLEN, REQSTAT); + test(REQSTAT==KRequestPending); + if(++pass==10) + break; + } + + test.Next(_L("Close reader and test multiple outstanding requests are cancelled")); + timer.Close(); + User::WaitForRequest(timerStat); + reader.Close(); + User::WaitForRequest(readStat1); + test(readStat1==KErrCancel); + User::WaitForRequest(readStat2); + test(readStat2==KErrCancel); + + User::WaitForRequest(thrdStat); + test(thrdStat==KErrNone); + } + + +//----------------------------------------------------------------------- + +/** + Testing that TheFs.NotifyChange() works for the root directory of the drive +*/ +void TestRootDirNotifyChange() +{ + test.Next(_L("Testing RFs::NotifyChange() on drive's root directory.")); + + TInt nRes; + TRequestStatus reqStatNotify1(KRequestPending); + + _LIT(KTestPath, "\\"); //-- root dir, actually + + //-- set up notifier + TheFs.NotifyChange(ENotifyAll, reqStatNotify1, KTestPath); + test(reqStatNotify1.Int() == KRequestPending); + + //-- create a file in the root dir + RFile file; + TFileName fileName(KTestPath); + + fileName.Append(_L("TestFile.tst")); + + nRes=file.Replace(TheFs, fileName, EFileWrite|EFileRead); + test(nRes == KErrNone || nRes ==KErrAlreadyExists); + file.Close(); + + //-- check that the notifier worked + User::WaitForRequest(reqStatNotify1); + test(reqStatNotify1.Int() == KErrNone); + +} + + + +//----------------------------------------------------------------------- + +// +// Do all tests +// +GLDEF_C void CallTestsL() + { + + CreateTestDirectory(_L("\\F32-TST\\NOTIFY\\")); + +// Test RFs::NotifyChange() + CHECK_NO_PENDING_REQUESTS; + Test1(); + CHECK_NO_PENDING_REQUESTS; + Test2(); + CHECK_NO_PENDING_REQUESTS; + Test3(); + CHECK_NO_PENDING_REQUESTS; + Test4(); + CHECK_NO_PENDING_REQUESTS; + Test5(); + CHECK_NO_PENDING_REQUESTS; + +#if defined (__EPOC32__)//we have no removable media on Emulator yet .. ??? we do now +#if defined __INCLUDE_MANUAL_TESTS__ + + // Media change notification on every socket supported + TInt i; + for (i=0; i0) + { + if (mask & (1<=0; gSocketNumber--) + { + if (SocketToDrive[gSocketNumber] != -1) + { + test.Printf(_L("Testing socket %u, drive %u...\n"), + gSocketNumber, SocketToDrive[gSocketNumber]); + Test99(); + } + } +#endif + Test6(); +#endif + CHECK_NO_PENDING_REQUESTS; + Test7(); + CHECK_NO_PENDING_REQUESTS; + + +#if defined (__EPOC32__)//we have no removable media on Emulator yet + +// Test RFs::NotifyChange() extended notification + TInt uid; + test(HAL::Get(HAL::EMachineUid,uid)==KErrNone); + if(uid!=HAL::EMachineUid_Cogent && uid!=HAL::EMachineUid_IQ80310 && + uid != HAL::EMachineUid_Integrator && uid!=HAL::EMachineUid_X86PC) + MediaChangeExtendedNotification(); + +#endif + + CHECK_NO_PENDING_REQUESTS; + TestRequestAhead(); + CHECK_NO_PENDING_REQUESTS; + Test8(); + CHECK_NO_PENDING_REQUESTS; + Test9(); + CHECK_NO_PENDING_REQUESTS; + Test10(); + CHECK_NO_PENDING_REQUESTS; + Test11(); + CHECK_NO_PENDING_REQUESTS; + Test12(); + CHECK_NO_PENDING_REQUESTS; + Test13(); + CHECK_NO_PENDING_REQUESTS; + Test14(); + CHECK_NO_PENDING_REQUESTS; + Test15(); + CHECK_NO_PENDING_REQUESTS; + Test16(); + CHECK_NO_PENDING_REQUESTS; + Test17(); + CHECK_NO_PENDING_REQUESTS; + Test18(); + CHECK_NO_PENDING_REQUESTS; + TestAsyncReader(); + CHECK_NO_PENDING_REQUESTS; + DeleteTestDirectory(); + CHECK_NO_PENDING_REQUESTS; + TestRootDirNotifyChange(); + CHECK_NO_PENDING_REQUESTS; + }