--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/f32test/server/t_notifier.cpp Thu Dec 17 09:24:54 2009 +0200
@@ -0,0 +1,4522 @@
+// Copyright (c) 2008-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_notifier.cpp
+//
+//
+
+#include <f32file.h>
+#include <e32test.h>
+#include <e32svr.h>
+#include <hal.h>
+#include "t_server.h"
+#include "t_chlffs.h"
+#include "t_notify_plugin.h"
+
+const TInt KNotificationHeaderSize = (sizeof(TUint16)*2)+(sizeof(TUint));
+const TInt KMinNotificationBufferSize = 2*KNotificationHeaderSize + 2*KMaxFileName;
+
+
+RTest test(_L("T_NOTIFIER"));
+const TInt KMaxHeapSize = 0x800000;
+TInt globalDriveNum;
+
+void DismountPlugin()
+ {
+ TheFs.DismountPlugin(KNotifyPluginName);
+ TheFs.RemovePlugin(KNotifyPluginFileName);
+ }
+
+inline void safe_test(RTest& aTest, TInt aError, TInt aLine, TText* aName)
+ {
+ if(aError!=KErrNone)
+ {
+ test.Printf(_L(": ERROR : %d received on line %d\n"),aError,aLine);
+ DismountPlugin();
+ aTest.operator()(aError==KErrNone,aLine,(TText*)aName);
+ }
+ }
+
+// Used by TestMultipleNotificationsL() to show which line the function is called from
+inline void safe_test(RTest& aTest, TInt aError, TInt aLine, TInt aLineCall)
+ {
+ if(aError != KErrNone)
+ {
+ aTest.Printf(_L(": ERROR : %d received on line %d\n"), aError, aLine);
+ aTest.Printf(_L(": ERROR : Function called from line number: %d\n"), aLineCall);
+ aTest.operator()(aError == KErrNone, aLine);
+ }
+ }
+
+// Prints out the filename
+#define ExpandMe(X) L ## X
+#define Expand(X) ExpandMe(X)
+
+namespace t_notification
+ {
+ enum EOperation
+ {
+ //TFsNotification::ECreate
+ EFileReplace,
+ EFileCreate,
+ EFileCreate_subs, //Create files in subdir, watch subdirs
+ EFileCreate_subs_nowatch, //Create files in subdir, do not monitor subdirs
+ EFileCreate_txt_nowatch, //Create .txt files in subdir, do not monitor subdirs
+ EFileCreate_txt, //Create .txt files
+ EFsMkDir, //Create directory
+ //TFsNotification::EAttribute
+ EFileSetAtt,
+ EFileSetAtt_subs, //Set attributes in subdir
+ EFileSet,
+ EFsSetEntry,
+ //TFsNotification::ERename
+ EFsReplace, //Replace file
+ EFsRename, //Rename file
+ EFsRename_dir, //Rename directory
+ EFileRename,
+ EFileRename_wild, //Rename file using wildcard name
+ //TFsNotification::EDelete
+ EFsDelete, //Delete file
+ EFsRmDir, //Remove directory
+ EFsRmDir_nonEmpty, //Remove non-empty directory, which will return KErrInUse
+ EFsRmDir_wild, //Remove subdirectory using wildcard name
+ //TFsNotification::EFileChange
+ EFileWrite,
+ EFileWrite_samesize, //Write to file without changing its size
+ EFileWrite_async, //Asynchronous write
+ EFileSetSize,
+ //TFsNotification::EVolumeName
+ ESetVolumeLabel,
+ //TFsNotification::EDriveName
+ ESetDriveName,
+ //TFsNotification::EMediaChange
+ EMount,
+ EDismount,
+ EMountScan,
+ EMountDismount,
+ EFormat,
+ EMediaCardRemoval,
+ EMediaCardInsertion,
+ ERawDiskWrite,
+ //Multiple Filters
+ EAllOps1, //Create/Replace and Delete
+ EAllOps2, //Create/Replace, FileChange(Write) and Delete
+ EAllOps3, //Create/Replace, FileChange(SetSize) and Delete
+ EAllOps4, //Create/Replace, Attribute(SetAtt) and Delete
+ EAllOps5, //Create/Replace and Rename
+ EAllOps6, //VolumeName and DriveName
+ ECFileManMove //Create filex in monitored directory, write 4, move to unmonitored, setsize 8, move back, delete
+ };
+ }
+
+// Package filename and semaphore for thread
+struct SThreadPackage
+ {
+ TFileName iFileName;
+ RSemaphore iBarrier;
+ };
+
+struct SThreadPackageDualSemaphore
+ {
+ TFileName iFileName;
+ RSemaphore iBarrier;
+ RSemaphore iBarrier2;
+ };
+
+struct SThreadPackage2
+ {
+ TInt iTestCase;
+ RSemaphore iBarrier;
+ };
+
+// Used by TestMultipleNotificationsL
+struct SThreadPackageMultiple
+ {
+ TFileName iString; //Commonly stores the filename
+ TFileName iFileName; //Commonly stores the path (not inc filename)
+ RSemaphore iBarrier;
+ t_notification::EOperation iOperation;
+ TFsNotification::TFsNotificationType iNotifyType;
+ TInt iIterations; //# of times to 'do' something
+ TInt iMaxNotifications; //# of notifications expected
+ TInt iBufferSize;
+ TInt iLineCall; //Line where the function is called from
+ };
+
+void PrintLine()
+ {
+ test.Printf(_L("======================================================================\n"));
+ }
+
+
+// We should receive an EMediaChange notification even though we did not register for it
+void TestMediaCardNotificationWhenNotRegisteredForIt()
+ {
+ RFs fs;
+ TInt r = fs.Connect();
+ test(r==KErrNone);
+
+ CFsNotify* notify = NULL;
+ TRAP(r,notify= CFsNotify::NewL(fs,KMinNotificationBufferSize));
+
+ TBuf<40> path;
+ path.Append((TChar)gDriveToTest);
+ path.Append(_L(":\\F32-TST\\T_NOTIFIER\\"));
+
+ TBuf<20> filename;
+ filename.Append(_L("media.change1"));
+
+ r = notify->AddNotification((TUint)TFsNotification::ECreate,path,filename);
+ test(r==KErrNone);
+
+ TRequestStatus status;
+ r = notify->RequestNotifications(status);
+ test(r==KErrNone);
+
+ test.Printf(_L("*****************************************************************\n"));
+ test.Printf(_L("Waiting 10 seconds.\n"));
+ test.Printf(_L("This is a MANUAL test, it requires the removal of the media card.\n"));
+ test.Printf(_L("PLEASE REMOVE THE MEDIA CARD. (DriveNumber %d)\n"),globalDriveNum);
+ test.Printf(_L("Or press Ctrl + F5 on the emulator.\n"));
+ test.Printf(_L("*****************************************************************\n"));
+ RTimer timer1;
+ r = timer1.CreateLocal();
+ test(r == KErrNone);
+ TRequestStatus timeout;
+ TTimeIntervalMicroSeconds32 time = 10000000;
+ timer1.After(timeout,time);
+ User::WaitForRequest(timeout,status);
+ test(status.Int() != KRequestPending);
+ timer1.Cancel();
+ timer1.Close();
+
+ const TFsNotification* notification = notify->NextNotification();
+ test(notification != NULL);
+ TFsNotification::TFsNotificationType type = notification->NotificationType();
+ test(type == TFsNotification::EMediaChange);
+ TBuf<2> drive;
+ drive.Append((TChar)gDriveToTest);
+ drive.Append(_L(":"));
+ TPtrC drivePtr;
+ r = notification->Path(drivePtr);
+ test(r==KErrNone);
+ r = drivePtr.Compare(drive);
+ test(r==0);
+
+ test.Printf(_L("*****************************************************************\n"));
+ test.Printf(_L("Waiting 10 seconds.\n"));
+ test.Printf(_L("This is a MANUAL test, it requires the insertion of the media card.\n"));
+ test.Printf(_L("PLEASE INSERT THE MEDIA CARD. (DriveNumber %d)\n"),globalDriveNum);
+ test.Printf(_L("Or press Ctrl + F5 on the emulator.\n"));
+ test.Printf(_L("*****************************************************************\n"));
+
+ notification = notify->NextNotification();
+ if(notification == NULL)
+ {
+ notify->RequestNotifications(status);
+ RTimer timer2;
+ r = timer2.CreateLocal();
+ test(r == KErrNone);
+ TRequestStatus timeout2;
+ timer2.After(timeout2,time);
+ User::WaitForRequest(timeout2,status);
+ test(status.Int() != KRequestPending);
+ notification = notify->NextNotification();
+ timer2.Cancel();
+ timer2.Close();
+ }
+ test(notification != NULL);
+ type = notification->NotificationType();
+ test(type == TFsNotification::EMediaChange);
+
+ delete notify;
+ fs.Close();
+ }
+
+// Creates two sessions, removes the first one
+// and then checks if the second one still works
+TInt TestClientRemovalL()
+ {
+ RFs fs;
+ TInt r = fs.Connect();
+ test(r==KErrNone);
+
+ CFsNotify* notify1 = NULL;
+ CFsNotify* notify2 = NULL;
+ TRAP(r,notify1= CFsNotify::NewL(fs,KMinNotificationBufferSize);
+ notify2= CFsNotify::NewL(fs,KMinNotificationBufferSize);
+ );
+ if(r!=KErrNone)
+ {
+ delete notify1;
+ delete notify2;
+ test(r==KErrNone);
+ }
+
+ TBuf<40> path;
+ path.Append((TChar)gDriveToTest);
+ path.Append(_L(":\\F32-TST\\T_NOTIFIER\\"));
+
+ TBuf<15> filename;
+ filename.Append(_L("create.file"));
+
+ TBuf<40> fullname;
+ fullname.Append(path);
+ fullname.Append(filename);
+
+ r = notify1->AddNotification((TUint)TFsNotification::ECreate,path,filename);
+ test(r==KErrNone);
+ r = notify2->AddNotification((TUint)TFsNotification::ECreate,path,filename);
+ test(r==KErrNone);
+
+ delete notify1; //Delete notify1 and ensure we still get notification on notify2
+
+ TRequestStatus status;
+ r = notify2->RequestNotifications(status);
+ test(r==KErrNone);
+
+ RFile file;
+ file.Replace(fs,fullname,EFileWrite); //Replace produces Create notification
+ file.Close();
+
+ RTimer tim;
+ r = tim.CreateLocal();
+ test(r==KErrNone);
+
+ TRequestStatus timStatus;
+ TTimeIntervalMicroSeconds32 time = 10000000; //10 seconds
+ tim.After(timStatus,time);
+
+ User::WaitForRequest(status,timStatus);
+ test(status!=KRequestPending);
+
+ r = fs.Delete(fullname);
+ test(r==KErrNone);
+
+ delete notify2;
+ tim.Close();
+ fs.Close();
+ return KErrNone;
+ }
+
+/*
+ * This tests that u can set and receive notifications in the root
+ * of a drive.
+ *
+ * (something which was apparently not possible on RFs::NotifyChange)
+ */
+TInt TestRootDriveNotifications()
+ {
+ test.Next(_L("TestRootDriveNotifications"));
+ RFs fs;
+ fs.Connect();
+
+ CFsNotify* notify = NULL;
+
+ TRAPD(r,notify = CFsNotify::NewL(fs,KMinNotificationBufferSize););
+ test(r==KErrNone);
+ test(notify!=NULL);
+
+ TBuf<40> path;
+ path.Append((TChar)gDriveToTest);
+ path.Append(_L(":\\"));
+
+ TBuf<15> filename;
+ filename.Append(_L("*"));
+
+ r = notify->AddNotification((TUint)TFsNotification::ECreate,path,filename);
+ test(r==KErrNone);
+
+ TRequestStatus status;
+ r = notify->RequestNotifications(status);
+ test(r==KErrNone);
+
+ RFile file;
+ TBuf<40> filePath;
+ filePath.Append((TChar)gDriveToTest);
+ filePath.Append(_L(":\\file.root"));
+ r = file.Replace(fs,filePath,EFileRead);
+ test(r==KErrNone);
+ file.Close();
+
+ TRequestStatus s2;
+ RTimer tim;
+ test(tim.CreateLocal()==KErrNone);
+ TTimeIntervalMicroSeconds32 time = 10000000; //10 seconds
+ tim.After(s2,time);
+ User::WaitForRequest(status,s2);
+ test(status!=KRequestPending);
+
+ delete notify;
+ notify = NULL;
+ tim.Close();
+ fs.Close();
+ return KErrNone;
+ }
+
+/*
+ * Creates and deletes loads of CFsNotify objects and makes sure they're all
+ * cleaned up afterwards.
+ */
+TInt TestNewDeleteCFsNotify(TInt aIterations)
+ {
+ RPointerArray<CFsNotify> array;
+ TInt inArray = 0;
+ TInt r = KErrNone;
+ for(TInt i = 0; i < aIterations; i++)
+ {
+ CFsNotify* notify = NULL;
+ TRAP(r,notify = CFsNotify::NewL(TheFs,500));
+ if(r==KErrNone)
+ {
+ test(notify!=NULL);
+ r = array.Append(notify);
+ if(r==KErrNone)
+ {
+ inArray++;
+ }
+ else
+ {
+ delete notify;
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ for(TInt j = inArray-1; j >= 0; j--)
+ {
+ CFsNotify* notify = (CFsNotify*)array[j];
+ array.Remove(j);
+ delete notify;
+ }
+
+ array.Reset();
+ array.Close();
+ return KErrNone;
+ }
+
+
+/*
+ * Creates a file
+ * Used in SimpleTest1L(), TestTwoDoersL() TestTwoWatchersL(), TestCancelNotificationL()
+ */
+TInt SimpleSingleNotificationTFDoer(TAny* aAny)
+ {
+ SThreadPackageDualSemaphore pkgDoer = *(SThreadPackageDualSemaphore*)aAny;
+ RTest simpleTestDoer(_L("SimpleSingleNotificationTFDoer"));
+ simpleTestDoer.Start(_L("SimpleSingleNotificationTFDoer"));
+ TBuf<40> path;
+ path.Append(gDriveToTest);
+ path.Append(_L(":\\F32-TST\\T_NOTIFIER\\"));
+ path.Append(pkgDoer.iFileName);
+
+ //Delete file so we definitely get a create notification
+ RFs fs;
+ TInt r = fs.Connect();
+ safe_test(simpleTestDoer,r,__LINE__,(TText*)Expand("t_notifier.cpp"));
+ r = fs.Delete(path);
+ if(r==KErrNone || r==KErrPathNotFound || r==KErrNotFound)
+ r = KErrNone;
+ safe_test(simpleTestDoer,r,__LINE__,(TText*)Expand("t_notifier.cpp"));
+ r = fs.MkDirAll(path);
+ if(r==KErrNone || r==KErrAlreadyExists)
+ r = KErrNone;
+ safe_test(simpleTestDoer,r,__LINE__,(TText*)Expand("t_notifier.cpp"));
+
+ simpleTestDoer.Printf(_L("SimpleSingleNotificationTFDoer - Create File %S\n"),&path);
+ //Create file
+ RFile file;
+ r = file.Create(fs,path,EFileWrite);
+ safe_test(simpleTestDoer,r,__LINE__,(TText*)Expand("t_notifier.cpp"));
+ file.Close();
+
+ fs.Close();
+ simpleTestDoer.End();
+ simpleTestDoer.Close();
+ return KErrNone;
+ }
+
+/*
+ * Watches 1 file creation
+ * Used in SimpleTest1L()
+ */
+TInt SimpleSingleNotificationTFWatcher(TAny* aAny)
+ {
+ CTrapCleanup* cleanup;
+ cleanup = CTrapCleanup::New();
+ RThread thread;
+ TUint64 threadId = thread.Id().Id();
+
+ SThreadPackage pkgDoer = *(SThreadPackage*)aAny;
+ RSemaphore& simpleBarrierTest = pkgDoer.iBarrier;
+
+ RTest simpleTestWatcher(_L("SimpleSingleNotificationTFWatcher"));
+ simpleTestWatcher.Start(_L("SimpleSingleNotificationTFWatcher"));
+
+ RFs fs;
+ fs.Connect();
+
+ simpleTestWatcher.Printf(_L("SimpleSingleNotificationTFWatcher(%d) - Create CFsNotify\n"),threadId);
+ CFsNotify* notify = NULL;
+ TRAPD(r,notify = CFsNotify::NewL(fs,100); );
+ safe_test(simpleTestWatcher,r,__LINE__,(TText*)Expand("t_notifier.cpp"));
+ TBuf<40> path;
+ path.Append(gDriveToTest);
+ path.Append(_L(":\\F32-TST\\T_NOTIFIER\\")); //len=22
+
+ TBuf<20> filename;
+ filename.Append(pkgDoer.iFileName);
+
+ TBuf<40> fullname;
+ fullname.Append(path);
+ fullname.Append(filename);
+
+ simpleTestWatcher.Printf(_L("SimpleSingleNotificationTFWatcher - Add Notification for %S\n"),&path);
+ r = notify->AddNotification((TUint)TFsNotification::ECreate,path,filename);
+ safe_test(simpleTestWatcher,r,__LINE__,(TText*)Expand("t_notifier.cpp"));
+ TRequestStatus status;
+ simpleTestWatcher.Printf(_L("SimpleSingleNotificationTFWatcher(%d) - Request Notifications\n"),threadId);
+ r = notify->RequestNotifications(status);
+ safe_test(simpleTestWatcher,r,__LINE__,(TText*)Expand("t_notifier.cpp"));
+
+ simpleBarrierTest.Signal();
+
+ simpleTestWatcher.Printf(_L("SimpleSingleNotificationTFWatcher(%d) - Wait for status to return\n"),threadId);
+ User::WaitForRequest(status);
+
+ simpleTestWatcher.Printf(_L("(%d) NextNotification\n"),threadId);
+ const TFsNotification* notification = notify->NextNotification();
+ //Test notification is not null.
+ //We should be getting 1 notification.
+ if(notification == NULL)
+ safe_test(simpleTestWatcher,KErrNotFound,__LINE__,(TText*)Expand("t_notifier.cpp"));
+
+ simpleTestWatcher.Printf(_L("(%d) - Notification Type\n"),threadId);
+ TFsNotification::TFsNotificationType notificationType = ((TFsNotification*)notification)->NotificationType();
+ if(notificationType != TFsNotification::ECreate)
+ safe_test(simpleTestWatcher,KErrGeneral,__LINE__,(TText*)Expand("t_notifier.cpp"));
+ simpleTestWatcher.Printf(_L("(%d) - Notification Path\n"),threadId);
+ TPtrC _pathC;
+ ((TFsNotification*)notification)->Path(_pathC);
+ simpleTestWatcher.Printf(_L("Notification Path = %S\n"),&_pathC);
+ TBuf<40> _path;
+ _path.Copy(_pathC);
+ if(_path.Match(fullname)!=KErrNone)
+ safe_test(simpleTestWatcher,KErrBadName,__LINE__,(TText*)Expand("t_notifier.cpp"));
+
+ /*
+ TInt driveNumber = 0;
+ TInt gDriveNum = -1;
+ notification->DriveNumber(driveNumber);
+ RFs::CharToDrive(_pathC[0],gDriveNum);
+ if(driveNumber != gDriveNum)
+ safe_test(simpleTestWatcher,KErrBadHandle,__LINE__,(TText*)Expand("t_notifier.cpp"));
+
+ TUid uid;
+ TUint32 realUID = 0x76543210;
+ r = notification->UID(uid);
+ safe_test(simpleTestWatcher,r,__LINE__,(TText*)Expand("t_notifier.cpp"));
+ safe_test(simpleTestWatcher,(realUID == uid.iUid)==1,__LINE__,(TText*)Expand("t_notifier.cpp"));
+ */
+ delete notify;
+ fs.Close();
+ simpleTestWatcher.End();
+ simpleTestWatcher.Close();
+ delete cleanup;
+ return KErrNone;
+ }
+
+/*
+ * SimpleTest1L - Runs a simple Create test, gets 1 notification, calls type, path etc and exits
+ * Two threads: 1 watcher, 1 doer
+ */
+TInt SimpleCreateTestL()
+ {
+ test.Next(_L("SimpleTest"));
+ RFs fs;
+ fs.Connect();
+ _LIT(KFileName,"simple.create");
+ SThreadPackage pkgDoer;
+ pkgDoer.iFileName = KFileName;
+
+ SThreadPackage watcherPkg;
+ watcherPkg.iFileName = KFileName;
+ User::LeaveIfError(pkgDoer.iBarrier.CreateLocal(0));
+ User::LeaveIfError(watcherPkg.iBarrier.CreateLocal(0));
+ RThread watcher;
+ RThread doer;
+ watcher.Create(_L("Simple1WatcherThread"),SimpleSingleNotificationTFWatcher,KDefaultStackSize,KMinHeapSize,KMaxHeapSize,&watcherPkg);
+ doer.Create(_L("Simple1DoerThread"),SimpleSingleNotificationTFDoer,KDefaultStackSize,KMinHeapSize,KMaxHeapSize,&pkgDoer);
+ watcher.Resume();
+ watcherPkg.iBarrier.Wait(); //Wait till Watcher has requested notification
+ doer.Resume();
+
+ TRequestStatus status;
+ doer.Logon(status);
+ User::WaitForRequest(status);
+ test.Printf(_L("SimpleCreateTest - Doer Exit Reason = %d\n"),doer.ExitReason());
+ safe_test(test,doer.ExitReason(),__LINE__,(TText*)Expand("t_notifier.cpp"));
+
+ RDebug::Print(_L("Line %d"),__LINE__);
+
+
+ watcher.Logon(status);
+ RTimer timer1;
+ TInt r = timer1.CreateLocal();
+ safe_test(test,r,__LINE__,(TText*)Expand("t_notifier.cpp"));
+ TRequestStatus timeout;
+ TTimeIntervalMicroSeconds32 time = 10000000; //10 seconds
+ timer1.After(timeout,time);
+ User::WaitForRequest(timeout,status);
+ test(status.Int() != KRequestPending);
+ timer1.Cancel();
+ timer1.Close();
+
+
+// User::WaitForRequest(status);
+ test.Printf(_L("SimpleCreateTest - Watcher Exit Reason = %d\n"),watcher.ExitReason());
+ safe_test(test,watcher.ExitReason(),__LINE__,(TText*)Expand("t_notifier.cpp"));
+
+ CLOSE_AND_WAIT(doer);
+ CLOSE_AND_WAIT(watcher);
+
+ pkgDoer.iBarrier.Close();
+ watcherPkg.iBarrier.Close();
+ fs.Close();
+ return KErrNone;
+ }
+
+// Doer thread for TestMultipleNotificationsL
+TInt MultipleNotificationTFDoer(TAny* aAny)
+ {
+ RDebug::Print(_L("MultipleNotificationTFDoer - Start, Line %d"), __LINE__);
+ SThreadPackageMultiple pkgDoer = *(SThreadPackageMultiple*)aAny;
+ RTest multipleTestDoer(_L("MultipleNotificationTFDoer"));
+ multipleTestDoer.Start(_L("Multi-Doer"));
+ multipleTestDoer.Printf(_L("MultipleNotificationTFDoer - Line %d"),__LINE__);
+ TBuf<40> basepath;
+ basepath.Append(gDriveToTest);
+ basepath.Append(_L(":\\F32-TST\\T_NOTIFIER\\"));
+
+ RThread thread;
+ RDebug::Print(_L("MultipleNotificationTFDoer - Line %d"), __LINE__);
+ TUint64 threadID = thread.Id().Id();
+ RDebug::Print(_L("MultipleNotificationTFDoer - Line %d"), __LINE__);
+
+ //Delete file so we definitely get a create notification
+ RFs fs;
+ TInt r = fs.Connect();
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ TEntry entry;
+ TBool wildcard = EFalse;
+ TBuf<40> _path;
+ _path.Append(basepath);
+ _path.Append(pkgDoer.iFileName);
+ _path.Append(pkgDoer.iString);
+ r = fs.Entry(_path, entry);
+ if (pkgDoer.iNotifyType != TFsNotification::EMediaChange &&
+ pkgDoer.iNotifyType != TFsNotification::EDriveName &&
+ pkgDoer.iNotifyType != TFsNotification::EVolumeName &&
+ pkgDoer.iOperation != t_notification::EAllOps6)
+ {
+ if (r == KErrBadName)
+ {
+ wildcard = ETrue;
+ }
+ if(r != KErrNone && r != KErrPathNotFound && r != KErrNotFound && r != KErrBadName)
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ if (r == KErrNone && !entry.IsDir() && pkgDoer.iOperation != t_notification::EFsDelete && !wildcard &&
+ pkgDoer.iOperation != t_notification::EFsRmDir && pkgDoer.iOperation != t_notification::EFsRmDir_nonEmpty)
+ {
+ r = fs.Delete(_path);
+ if(r != KErrNone && r != KErrPathNotFound && r != KErrNotFound)
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ }
+ r = fs.MkDirAll(basepath);
+ if(r != KErrNone && r != KErrAlreadyExists)
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ }
+
+ multipleTestDoer.Printf(_L("MultipleNotificationTFDoer (%d) - Line %d"),threadID,__LINE__);
+
+ switch(pkgDoer.iOperation)
+ {
+ case t_notification::EFileReplace:
+ {
+ RFile file;
+ //Generate Notification
+ multipleTestDoer.Printf(_L("File Replace - (%d)\n"),threadID);
+ r = file.Replace(fs,_path,EFileWrite); //RFile::Replace -> TFsNotification::ECreate
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ file.Close();
+
+ r = fs.Delete(_path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ break;
+ }
+ case t_notification::EFileCreate:
+ case t_notification::EFileCreate_txt_nowatch:
+ case t_notification::EFileCreate_txt:
+ case t_notification::EAllOps1:
+ {
+ multipleTestDoer.Printf(_L("MultipleNotificationTFDoer (%d) - Line %d"),threadID,__LINE__);
+ if(wildcard)
+ {
+ for (TInt i = 0; i < pkgDoer.iIterations; i++)
+ {
+ multipleTestDoer.Printf(_L("MultipleNotificationTFDoer (%d) - Line %d"),threadID,__LINE__);
+ RFile file;
+ TBuf<40> path;
+ path.Append(basepath);
+ path.AppendNum(i);
+ if(pkgDoer.iOperation == t_notification::EFileCreate_txt)
+ {
+ //Create file with different extension (no notification)
+ path.Append(_L(".wrg"));
+ fs.Delete(path);
+ multipleTestDoer.Printf(_L("File Create (wrong extension) - %S (%d)\n"),&path,threadID);
+ r = file.Create(fs, path, EFileWrite);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ //Change path to contain file with correct extension (notification occurs)
+ path.Replace(path.Length()-3,3,_L("txt"));
+ }
+ else if(pkgDoer.iOperation == t_notification::EFileCreate_txt_nowatch)
+ {
+ path.Append(_L(".txt"));
+ }
+ fs.Delete(path);
+
+ multipleTestDoer.Printf(_L("File Create - %S (%d)\n"),&path,threadID);
+ r = file.Create(fs, path, EFileWrite);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ file.Close();
+ r = fs.Delete(path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ }
+ }
+ else
+ {
+ multipleTestDoer.Printf(_L("MultipleNotificationTFDoer (%d) - Line %d"),threadID,__LINE__);
+ for(TInt i = 0; i < pkgDoer.iIterations; i++)
+ {
+ multipleTestDoer.Printf(_L("MultipleNotificationTFDoer (%d) - Line %d"),threadID,__LINE__);
+ RFile file;
+ multipleTestDoer.Printf(_L("File Create - %S (%d)\n"),&_path,threadID);
+ r = file.Create(fs,_path,EFileWrite);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ file.Close();
+ r = fs.Delete(_path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ }
+ }
+ break;
+ }
+ case t_notification::EFileCreate_subs:
+ case t_notification::EFileCreate_subs_nowatch:
+ {
+ if (wildcard)
+ {
+ for (TInt i = 0; i < pkgDoer.iIterations; i++)
+ {
+ RFile file;
+ TBuf<40> path;
+ path.Append(basepath);
+ path.Append(_L("SubDir\\"));
+ r = fs.MkDirAll(path);
+ if(r != KErrNone && r != KErrAlreadyExists)
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ path.AppendNum(i);
+ fs.Delete(path);
+ multipleTestDoer.Printf(_L("File Create - %S (%d)\n"),&path,threadID);
+ r = file.Create(fs, path, EFileWrite);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ file.Close();
+ r = fs.Delete(path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ }
+ }
+ break;
+ }
+ case t_notification::EFileWrite:
+ case t_notification::EAllOps2:
+ {
+ //Works on single file
+ RFile file;
+ TBuf<40> path;
+ path.Append(basepath);
+ path.Append(pkgDoer.iFileName);
+ path.Append(pkgDoer.iString);
+ r = file.Replace(fs,path,EFileWrite);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ for(TInt i = 0; i < pkgDoer.iIterations; i++)
+ {
+ multipleTestDoer.Printf(_L("File Write - %S (%d)\n"),&path,threadID);
+ r = file.Write(4*i,_L8("abcd"));
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ //If cache is enabled, a notification is received only when the cache is flushed
+ //We flush the file to make this a general test
+ multipleTestDoer.Printf(_L("File Flush - (%d)\n"),threadID);
+ r = file.Flush();
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ }
+ file.Close();
+ r = fs.Delete(path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ break;
+ }
+ case t_notification::EFileWrite_samesize:
+ {
+ RFile file;
+ TBuf<40> path;
+ path.Append(basepath);
+ path.Append(pkgDoer.iFileName);
+ path.Append(pkgDoer.iString);
+ r = file.Replace(fs,path,EFileWrite);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ multipleTestDoer.Printf(_L("File Write - %S (%d)\n"),&path,threadID);
+ r = file.Write(0,_L8("abcd"));
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ //If cache is enabled, a notification is received only when the cache is flushed
+ //We flush the file to make this a general test
+ multipleTestDoer.Printf(_L("File Flush - (%d)\n"),threadID);
+ r = file.Flush();
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ for(TInt i = 0; i < pkgDoer.iIterations; i++)
+ {
+ TBuf<2> toWrite;
+ toWrite.AppendNum(i);
+ multipleTestDoer.Printf(_L("File Write - %S (%d)\n"),&path,threadID);
+ r = file.Write(0,(TDesC8&)toWrite);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ multipleTestDoer.Printf(_L("File Flush - (%d)\n"),threadID);
+ r = file.Flush();
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ }
+ file.Close();
+ r = fs.Delete(path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ break;
+ }
+ case t_notification::EFileWrite_async:
+ {
+ RFile file;
+ TBuf<40> path;
+ path.Append(basepath);
+ path.Append(pkgDoer.iFileName);
+ path.Append(pkgDoer.iString);
+ r = file.Replace(fs,path,EFileWrite);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ for(TInt i = 0; i < pkgDoer.iIterations; i++)
+ {
+ TRequestStatus status;
+ file.Write(52*i, _L8("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"), status);
+ User::WaitForRequest(status);
+ multipleTestDoer.Printf(_L("File Write Async - %S (%d)\n"),&path,threadID);
+ TInt fileSize;
+ file.Size(fileSize);
+ multipleTestDoer.Printf(_L("File Write Async - FileSize: %d\n"),fileSize);
+ multipleTestDoer.Printf(_L("File Flush - (%d)\n"),threadID);
+ r = file.Flush();
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ }
+ file.Close();
+ r = fs.Delete(path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ break;
+ }
+ case t_notification::EFileSetSize:
+ case t_notification::EAllOps3:
+ {
+ //Works on single file
+ RFile file;
+ TBuf<40> path;
+ path.Append(basepath);
+ path.Append(pkgDoer.iFileName);
+ path.Append(pkgDoer.iString);
+ r = file.Replace(fs,path,EFileWrite);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ //Increase file size
+ for(TInt i = 0; i < pkgDoer.iIterations; i++)
+ {
+ r = file.SetSize(4*(i+1));
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ multipleTestDoer.Printf(_L("File Set Size - %d (%d)\n"),4*(i+1),threadID);
+ }
+
+ //Decrease file size
+ for(TInt j = pkgDoer.iIterations - 2; j >= 0; j--)
+ {
+ r = file.SetSize(4*(j+1));
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ multipleTestDoer.Printf(_L("File Set Size - %d (%d)\n"),4*(j+1),threadID);
+ }
+
+ file.Close();
+ r = fs.Delete(path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ break;
+ }
+ case t_notification::EFsReplace:
+ {
+ TBuf<45> path;
+ path.Append(basepath);
+ path.Append(pkgDoer.iFileName);
+ path.Append(pkgDoer.iString);
+ path.AppendNum(0);
+
+ RFile tempFile;
+ multipleTestDoer.Printf(_L("RFs Replace (Create temp file) - (%d)\n"),threadID);
+ r = tempFile.Replace(fs,_path,EFileWrite);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ tempFile.Close();
+
+ multipleTestDoer.Printf(_L("RFs Replace - (%d)\n"),threadID);
+ r = fs.Replace(_path,path); //RFs::Replace -> TFsNotification::ERename
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ r = fs.Delete(path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ break;
+ }
+ case t_notification::EFsRename:
+ {
+ TBuf<45> path;
+ path.Append(basepath);
+ path.Append(pkgDoer.iFileName);
+ path.Append(pkgDoer.iString);
+ path.AppendNum(0);
+
+ RFile file;
+ r = file.Replace(fs,_path,EFileWrite);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ file.Close();
+
+ multipleTestDoer.Printf(_L("RFs Rename - (%d)\n"),threadID);
+ r = fs.Rename(_path,path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ r = fs.Delete(path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ break;
+ }
+ case t_notification::EFileRename:
+ case t_notification::EFileRename_wild:
+ case t_notification::EAllOps5:
+ {
+ TBuf<45> path;
+ path.Append(basepath);
+ if (!wildcard)
+ {
+ path.Append(pkgDoer.iFileName);
+ path.Append(pkgDoer.iString);
+ }
+ path.AppendNum(0);
+
+ //Delete new path to ensure it does not exist
+ r = fs.Delete(path);
+ if(r != KErrNone && r != KErrNotFound && r != KErrPathNotFound)
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ if (wildcard)
+ {
+ _path.Delete(_path.Length()-1,1);
+ _path.AppendNum(9);
+ }
+
+ RFile file;
+ r = file.Replace(fs, _path, EFileWrite);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ if (wildcard)
+ {
+ for(TInt i = 1; i <= pkgDoer.iIterations; i++)
+ {
+ path.Delete(path.Length()-1,1);
+ path.AppendNum(i);
+ multipleTestDoer.Printf(_L("File Rename - %S (%d)\n"),&path,threadID);
+ r = file.Rename(path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ }
+ }
+ else
+ {
+ multipleTestDoer.Printf(_L("File Rename - (%d)\n"),threadID);
+ r = file.Rename(path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ }
+
+ file.Close();
+ r = fs.Delete(path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ break;
+ }
+ case t_notification::EFsRename_dir:
+ {
+ r = fs.MkDirAll(_path);
+ if(r != KErrNone && r != KErrAlreadyExists)
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ TBuf<45> newPath;
+ newPath.Copy(_path);
+ newPath.Delete(newPath.Length()-1,1);
+ newPath.AppendNum(0);
+ newPath.Append(KPathDelimiter);
+
+ //Delete new path to ensure it does not exist
+ r = fs.RmDir(newPath);
+ if(r != KErrNone && r != KErrNotFound && r != KErrPathNotFound)
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ multipleTestDoer.Printf(_L("RFs Rename Dir - (%d)\n"),threadID);
+ r = fs.Rename(_path,newPath);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ break;
+ }
+ case t_notification::EFsDelete:
+ {
+ if (wildcard)
+ {
+ for(TInt i = 0; i < pkgDoer.iIterations; i++)
+ {
+ //Create/replace file
+ RFile file;
+ TBuf<40> path;
+ path.Append(basepath);
+ r = fs.MkDirAll(path);
+ if(r != KErrNone && r != KErrAlreadyExists)
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ path.AppendNum(i);
+ path.Append(_L(".txt"));
+ r = file.Replace(fs,path,EFileWrite);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ file.Close();
+
+ //Delete file
+ multipleTestDoer.Printf(_L("RFs Delete - %S (%d)\n"),&path,threadID);
+ r = fs.Delete(path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ //Create file with a different extension which should not produce notifications
+ path.AppendNum(i);
+ r = file.Replace(fs,path,EFileWrite);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ file.Close();
+
+ //Delete that file
+ multipleTestDoer.Printf(_L("RFs Delete - %S (%d)\n"),&path,threadID);
+ r = fs.Delete(path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ }
+ }
+ else
+ {
+ RFile file;
+ r = file.Replace(fs,_path,EFileWrite); //Make sure file exists
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ file.Close();
+
+ multipleTestDoer.Printf(_L("RFs Delete - (%d)\n"),threadID);
+ r = fs.Delete(_path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ }
+ break;
+ }
+ case t_notification::EFileSet:
+ {
+ RFile file;
+ r = file.Replace(fs,_path,EFileWrite);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ multipleTestDoer.Printf(_L("File Set - (%d)\n"),threadID);
+ r = file.Set(TTime(0),KEntryAttHidden,KEntryAttReadOnly);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ file.Close();
+ break;
+ }
+ case t_notification::EFileSetAtt:
+ case t_notification::EAllOps4:
+ {
+ RFile file;
+ r = file.Replace(fs,_path,EFileWrite);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ multipleTestDoer.Printf(_L("File SetAtt - (%d)\n"),threadID);
+ r = file.SetAtt(KEntryAttHidden,KEntryAttReadOnly);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ file.Close();
+ r = fs.Delete(_path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ break;
+ }
+ case t_notification::EFileSetAtt_subs:
+ {
+ if (wildcard)
+ {
+ TBuf<40> path;
+ path.Append(basepath);
+ path.Append(_L("SubDir\\"));
+ r = fs.MkDirAll(path);
+ if(r != KErrNone && r != KErrAlreadyExists)
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ //Create/replace files and set their attributes
+ for(TInt i = 0; i < pkgDoer.iIterations; i++)
+ {
+ RFile file;
+ TBuf<40> dirPath;
+ dirPath.Append(path);
+ dirPath.AppendNum(i);
+ dirPath.Append(_L(".ext"));
+ r = file.Replace(fs, dirPath, EFileWrite);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ multipleTestDoer.Printf(_L("File SetAtt Subs - %d.ext - (%d)\n"),i,threadID);
+ r = file.SetAtt(KEntryAttHidden,KEntryAttReadOnly);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ file.Close();
+ r = fs.Delete(dirPath);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ }
+ }
+ break;
+ }
+ case t_notification::EFsSetEntry:
+ {
+ RFile file;
+ r = file.Replace(fs,_path,EFileWrite);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ file.Close();
+
+ multipleTestDoer.Printf(_L("RFs SetEntry - (%d)\n"),threadID);
+ r = fs.SetEntry(_path,TTime(0),KEntryAttHidden,KEntryAttReadOnly);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ break;
+ }
+ case t_notification::EDismount:
+ {
+ multipleTestDoer.Printf(_L("DismountFileSystem - (%d)\n"),threadID);
+ r = fs.DismountFileSystem(pkgDoer.iFileName,globalDriveNum);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ break;
+ }
+ case t_notification::EMount:
+ {
+ multipleTestDoer.Printf(_L("MountFileSystem - (%d)\n"),threadID);
+ r = fs.MountFileSystem(pkgDoer.iFileName,globalDriveNum);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ break;
+ }
+ case t_notification::EMountScan:
+ {
+ multipleTestDoer.Printf(_L("DismountFileSystem - (%d)\n"),threadID);
+ r = fs.DismountFileSystem(pkgDoer.iFileName,globalDriveNum);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ TBool isMount;
+ multipleTestDoer.Printf(_L("MountFileSystemAndScan - (%d)\n"),threadID);
+ r = fs.MountFileSystemAndScan(pkgDoer.iFileName,globalDriveNum,isMount);
+ if(!isMount)
+ safe_test(multipleTestDoer,KErrGeneral,__LINE__,pkgDoer.iLineCall);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ break;
+ }
+ case t_notification::EMountDismount:
+ {
+ for(TInt i = 0; i < pkgDoer.iIterations; i++)
+ {
+ multipleTestDoer.Printf(_L("DismountFileSystem - (%d)\n"),threadID);
+ r = fs.DismountFileSystem(pkgDoer.iFileName,globalDriveNum);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ multipleTestDoer.Printf(_L("MountFileSystem - (%d)\n"),threadID);
+ r = fs.MountFileSystem(pkgDoer.iFileName,globalDriveNum);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ }
+ break;
+ }
+ case t_notification::EFormat:
+ {
+ RFormat format;
+ TInt count = -1;
+ TBuf<2> driveDes;
+ driveDes.Append(pkgDoer.iFileName);
+ driveDes.Append((TChar)':');
+ format.Open(fs,driveDes,EQuickFormat,count);
+ multipleTestDoer.Printf(_L("Format - (%d)\n"),threadID);
+ while(count != 0)
+ {
+ format.Next(count);
+ }
+ format.Close();
+
+ break;
+ }
+ case t_notification::EMediaCardRemoval:
+ case t_notification::EMediaCardInsertion:
+ {
+ //These are MANUAL tests, they require the removal/insertion of the media card
+ //Instructions are given out in the watcher thread
+ break;
+ }
+ case t_notification::ESetDriveName:
+ {
+ for(TInt i = 0; i < pkgDoer.iIterations; i++)
+ {
+ multipleTestDoer.Printf(_L("SetDriveName - MyDrive\n"));
+ _LIT(KDriveName,"MyDrive");
+ r = fs.SetDriveName(globalDriveNum,KDriveName);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ multipleTestDoer.Printf(_L("SetDriveName - MyDrive2\n"));
+ _LIT(KDriveName2,"MyDrive2");
+ r = fs.SetDriveName(globalDriveNum,KDriveName2);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ }
+ break;
+ }
+ case t_notification::ERawDiskWrite:
+ {
+ RRawDisk rawdisk;
+ TInt drive = 0;
+ TBuf<1> driveDes;
+ driveDes.Append(pkgDoer.iFileName);
+ RFs::CharToDrive(pkgDoer.iFileName[0],drive);
+ r = rawdisk.Open(fs,drive);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ //Read some data
+ TBuf8<10> readData;
+ r = rawdisk.Read(0,readData);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ //Write it back
+ TPtrC8 dataPtr(readData);
+ r = rawdisk.Write((TInt64)0,dataPtr);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ rawdisk.Close();
+ break;
+ }
+ case t_notification::ESetVolumeLabel:
+ {
+ for(TInt i = 0; i < pkgDoer.iIterations; i++)
+ {
+ multipleTestDoer.Printf(_L("SetVolumeLabel - MyVolume\n"));
+ _LIT(KVolumeLabel,"MyVolume");
+ r = fs.SetVolumeLabel(KVolumeLabel,globalDriveNum);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ multipleTestDoer.Printf(_L("SetVolumeLabel - MyVolume2\n"));
+ _LIT(KVolumeLabel2,"MyVolume2");
+ r = fs.SetVolumeLabel(KVolumeLabel2,globalDriveNum);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ }
+ break;
+ }
+ case t_notification::EFsRmDir:
+ {
+ r = fs.MkDirAll(_path); //Make sure directory exists
+ if(r != KErrNone && r != KErrAlreadyExists)
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ multipleTestDoer.Printf(_L("RFs RmDir - Remove directory\n"));
+ r = fs.RmDir(_path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ break;
+ }
+ case t_notification::EFsRmDir_wild:
+ {
+ if (wildcard)
+ {
+ TBuf<40> path;
+ path.Append(basepath);
+ path.Append(_L("SubDir\\"));
+ r = fs.MkDirAll(path);
+ if(r != KErrNone && r != KErrAlreadyExists)
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ multipleTestDoer.Printf(_L("RFs RmDir - Remove directory\n"));
+ r = fs.RmDir(path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ break;
+ }
+ }
+ case t_notification::EFsRmDir_nonEmpty:
+ case t_notification::EFsMkDir:
+ {
+ TBuf<50> path;
+ path.Append(_path);
+ path.Append(pkgDoer.iFileName); //Append another sub-directory
+ multipleTestDoer.Printf(_L("RFs RmDir \n"));
+ r=fs.RmDir(path);
+ if(r != KErrNone && r != KErrPathNotFound && r != KErrNotFound)
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ r=fs.RmDir(_path);
+ if(r != KErrNone && r != KErrPathNotFound && r != KErrNotFound)
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ multipleTestDoer.Printf(_L("RFs MkDir \n"));
+ r=fs.MkDir(path);
+ multipleTestDoer (r==KErrPathNotFound);
+ r=fs.MkDir(_path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ r=fs.MkDir(path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ multipleTestDoer.Printf(_L("RFs RmDir nonEmpty - Full path: %S"),&_path);
+ r = fs.RmDir(_path);
+ if(r != KErrInUse)
+ safe_test(multipleTestDoer,KErrGeneral,__LINE__,pkgDoer.iLineCall);
+
+ r = fs.RmDir(path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ multipleTestDoer.Printf(_L("RFs EFsRmDir_nonEmpty - Full path: %S"),&_path);
+ r = fs.RmDir(_path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ break;
+ }
+ case t_notification::EAllOps6:
+ {
+ //Set drive name to TestDrive
+ multipleTestDoer.Printf(_L("SetDriveName - TestDrive\n"));
+ _LIT(KDriveName,"TestDrive");
+ r = fs.SetDriveName(globalDriveNum,KDriveName);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ //Set volume label to TestVolume
+ multipleTestDoer.Printf(_L("SetVolumeLabel - TestVolume\n"));
+ _LIT(KVolumeLabel,"TestVolume");
+ r = fs.SetVolumeLabel(KVolumeLabel,globalDriveNum);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ break;
+ }
+ case t_notification::ECFileManMove:
+ {
+ CTrapCleanup* cleanup;
+ cleanup = CTrapCleanup::New();
+
+ multipleTestDoer.Printf(_L("Doer - ECFileManMove_part1\n"));
+
+ //Stage 1 - Create File & write some data
+ RFile file;
+ r = file.Replace(fs,_path,EFileWrite);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ r = file.SetSize(4);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ file.Close();
+
+ CFileMan* cfman = NULL;
+ TRAP(r, cfman = CFileMan::NewL(fs);)
+ test(r == KErrNone);
+ test(cfman != NULL);
+ TBuf<40> unmonitored_path;
+ unmonitored_path.Append(gDriveToTest);
+ unmonitored_path.Append(_L(":\\F32-TST\\"));
+ unmonitored_path.Append(pkgDoer.iString);
+
+ //Stage 2 - Move to unmonitored Dir
+ //Rename 1
+ r = cfman->Move(_path,unmonitored_path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ //SetSize (size := 8)
+ RFile file2;
+ r = file2.Open(fs,unmonitored_path,EFileWrite);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ r = file2.SetSize(8);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+ file2.Flush();
+ file2.Close();
+
+ //Stage 3 - Move back to monitored Dir
+ //Rename 2
+ r = cfman->Move(unmonitored_path,_path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ //Stage 4 - Delete
+ //Delete
+ r = cfman->Delete(_path);
+ safe_test(multipleTestDoer,r,__LINE__,pkgDoer.iLineCall);
+
+ delete cleanup;
+ delete cfman;
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ fs.Close();
+ multipleTestDoer.End();
+ multipleTestDoer.Close();
+ return KErrNone;
+ }
+
+/*
+ * Test process Capabilites tries to set up filters on the
+ * the private folder for uid 01234567.
+ * This function returns the results to trying to add filters on the specified path.
+ *
+ * There are three MMP files:
+ * t_notifier_nocaps.mmp, t_notifier_allfiles.mmp, t_notifier_belongs.mmp
+ *
+ * t_notifier_nocaps.mmp -
+ * This process does not have any capabilites, so should not be allowed to set the filter.
+ * t_notifier_allfiles.mmp -
+ * This process has ALLFILES capability, so should
+ * t_notifier_belongs.mmp -
+ * This process is process with UID 01234567 so this should work too.
+ *
+ * See: f32test\server\t_notifier_caps.cpp
+ */
+TInt TestProcessCapabilities(const TDesC& aProcessName)
+ {
+ RProcess process;
+ TUidType uid;
+ TPtrC command((TText*)&gDriveToTest,1);
+ TInt r = process.Create(aProcessName,command,uid);
+ test(r==KErrNone);
+ process.Resume();
+ TRequestStatus s1;
+ TRequestStatus s2;
+ RTimer tim;
+ r = tim.CreateLocal();
+ test(r==KErrNone);
+ TTimeIntervalMicroSeconds32 delay = 5000000; //5 seconds
+ tim.After(s1,delay);
+ process.Logon(s2);
+ User::WaitForRequest(s1,s2);
+ test(s2.Int()!=KRequestPending);
+ r = process.ExitReason();
+ process.Close();
+ return r;
+ }
+
+/*
+ * Creates a file and writes to it twice.
+ * Used in TestTwoNotificationsL().
+ */
+TInt TwoNotificationsTFDoer(TAny* aAny)
+ {
+ RTest testDoer(_L("TestTwoNotificationsThreadFunctionDoer"));
+ testDoer.Start(_L("TestTwoNotificationsThreadFunctionDoer"));
+
+ SThreadPackageMultiple package = *(SThreadPackageMultiple*)aAny;
+ TBuf<40> path;
+ path.Append(gDriveToTest);
+ path.Append(_L(":\\F32-TST\\T_NOTIFIER\\")); //len=22
+ path.Append(package.iFileName);
+
+ //Delete file so we definitely get a create notification
+ RFs fs;
+ TInt r = fs.Connect();
+ testDoer(r==KErrNone);
+ r = fs.Delete(path);
+ testDoer(r==KErrNone || r==KErrPathNotFound || r==KErrNotFound);
+ r = fs.MkDirAll(path);
+ testDoer(r==KErrNone || r==KErrAlreadyExists);
+
+ testDoer.Printf(_L("TestTwoNotificationsThreadFunctionDoer - Create File %S\n"),&path);
+ //Create file
+ RFile file;
+ r = file.Create(fs,path,EFileWrite);
+ testDoer(r == KErrNone);
+
+ testDoer.Printf(_L("TestTwoNotificationsThreadFunctionDoer - Size File 1 %S\n"),&path);
+ TInt fileSize = 0;
+ r = file.Size(fileSize);
+ testDoer(r == KErrNone);
+ testDoer(fileSize==0);
+
+ testDoer.Printf(_L("TestTwoNotificationsThreadFunctionDoer - Write File 1 %S\n"),&path);
+ r = file.Write(_L8("1234"));
+ testDoer(r == KErrNone);
+ testDoer.Printf(_L("TestTwoNotificationsThreadFunctionDoer - Size File 2 %S\n"),&path);
+ r = file.Size(fileSize);
+ testDoer(r == KErrNone);
+ test(fileSize==4);
+
+ testDoer.Printf(_L("TestTwoNotificationsThreadFunctionDoer - Write File 2 %S\n"),&path);
+ r = file.Write(_L8("5678"));
+ testDoer(r == KErrNone);
+ testDoer.Printf(_L("TestTwoNotificationsThreadFunctionDoer - Size File 3 %S\n"),&path);
+ r = file.Size(fileSize);
+ testDoer(r == KErrNone);
+ test(fileSize==8);
+
+ file.Close();
+
+ fs.Close();
+ testDoer.End();
+ testDoer.Close();
+ return KErrNone;
+ }
+
+ /*
+ * The following enum are for the CFileMan test
+ */
+ enum TCFsManEnum
+ {
+ ECFManCreate1 = 0x01,
+ ECFManWrite1 = 0x02,
+ ECFManDelete1 = 0x04,
+ ECFManCreate2 = 0x08,
+ ECFManSetSize1 = 0x10,
+ ECFManWrite2 = 0x20,
+ ECFManAtt1 = 0x40,
+ ECFManDelete2 = 0x80,
+ //Either a create, copy, delete (above - not supported in test)
+ //or rename operation (below)
+ ECFManRename1 = 0x100,
+ ECFManRename2 = 0x200
+ };
+
+/*
+ * Used by MultipleNotificationsTFWatcher() to test the notifications.
+ */
+void HandleMultipleNotifications(RTest& aTest, SThreadPackageMultiple& aPackage, CFsNotify* notify, TDesC& aFullname)
+ {
+ RThread thread;
+ TUint64 threadID = thread.Id().Id();
+ TInt numNotifications = 0;
+ TInt64 fileSize = 0;
+ TBool overflow = EFalse;
+
+ TInt scratch = 0;
+
+ for(TInt i = 0; i < aPackage.iMaxNotifications; ) //Outer-loop to control when we should exit
+ {
+ aTest.Printf(_L("(%d) - NextNotification\n"),threadID);
+ const TFsNotification* notification = notify->NextNotification();
+ while(notification != NULL)
+ {
+ numNotifications++;
+ aTest.Printf(_L("NumNotifications = %d\n"),numNotifications);
+ //Test notification is not null.
+ //We should be getting 1 notification.
+ aTest(notification != NULL);
+
+ aTest.Printf(_L("(%d) - Notification Type\n"),threadID);
+ TFsNotification::TFsNotificationType notificationType = notification->NotificationType();
+ aTest(notificationType & aPackage.iNotifyType ||
+ notificationType & TFsNotification::EOverflow);
+
+ aTest.Printf(_L("Notification Type = %u - (%d)\n"),notificationType,threadID);
+
+ if(notificationType != TFsNotification::EOverflow)
+ {
+ aTest.Printf(_L("(%d) - Notification Path\n"),threadID);
+ TPtrC _pathC;
+ ((TFsNotification*) notification)->Path(_pathC);
+ aTest.Printf(_L("%S - (%d)\n"),&_pathC,threadID);
+
+ if(aPackage.iOperation == t_notification::ECFileManMove
+ && (scratch == (ECFManWrite1 | ECFManCreate1)))
+ {
+ TChar drive = gDriveToTest;
+ TBuf<40> unmodified_path;
+ unmodified_path.Append(drive);
+ unmodified_path.Append(_L(":\\F32-TST\\"));
+ unmodified_path.Append(_L("cf1le.man"));
+ ((TFsNotification*) notification)->NewName(_pathC);
+ TInt matches = _pathC.Match(unmodified_path);
+ safe_test(aTest,matches,__LINE__,aPackage.iLineCall);
+ }
+ else if((scratch == (ECFManWrite1 | ECFManCreate1 | ECFManRename1)))
+ {
+ ((TFsNotification*) notification)->NewName(_pathC);
+ safe_test(aTest,_pathC.Match(aFullname),__LINE__,aPackage.iLineCall);
+ }
+ else
+ {
+ safe_test(aTest,_pathC.Match(aFullname),__LINE__,aPackage.iLineCall);
+ }
+ }
+ else
+ {
+ aTest.Printf(_L("(%d) - OVERFLOW\n"),threadID);
+ //Overflow
+ overflow = ETrue;
+ return;
+ }
+
+ //notificationType will only be of 1 type
+ if(notificationType == TFsNotification::EFileChange)
+ {
+ if(!(((aPackage.iNotifyType & TFsNotification::EFileChange) == TFsNotification::EFileChange) &&
+ (aPackage.iOperation == t_notification::EFileWrite ||
+ aPackage.iOperation == t_notification::EFileWrite_async ||
+ aPackage.iOperation == t_notification::EFileWrite_samesize ||
+ aPackage.iOperation == t_notification::EFileSetSize ||
+ aPackage.iOperation == t_notification::ECFileManMove ||
+ aPackage.iOperation == t_notification::EAllOps2 ||
+ aPackage.iOperation == t_notification::EAllOps3)))
+ safe_test(aTest,KErrGeneral,__LINE__,aPackage.iLineCall);
+
+ if (aPackage.iOperation == t_notification::ECFileManMove)
+ {
+ ((TFsNotification*) notification)->FileSize(fileSize);
+ //File just been created and written to.
+ if(fileSize == 4)
+ {
+ scratch |= ECFManWrite1;
+ }
+ else if(fileSize == 8)
+ {
+ scratch |= ECFManWrite2;
+ }
+ }
+ else if (aPackage.iNotifyType == TFsNotification::EFileChange)
+ {
+ ((TFsNotification*) notification)->FileSize(fileSize);
+ aTest.Printf(_L("Filesize - %d (%d)\n"),fileSize,threadID);
+ //A notification is received every time the size is changed
+ //due to the flushing
+ if (aPackage.iOperation == t_notification::EFileWrite_async)
+ {
+ //We write 52 letters
+ if(fileSize != 52*(i+1))
+ safe_test(aTest,KErrGeneral,__LINE__,aPackage.iLineCall);
+ }
+ else if (aPackage.iOperation == t_notification::EFileWrite_samesize)
+ {
+ //Only 4 letters in file
+ if(fileSize != 4)
+ safe_test(aTest,KErrGeneral,__LINE__,aPackage.iLineCall);
+ }
+ else if (i < aPackage.iIterations)
+ {
+ //We write/increase size by 4 letters/bytes
+ if(fileSize != 4*(i+1))
+ safe_test(aTest,KErrGeneral,__LINE__,aPackage.iLineCall);
+ }
+ else
+ {
+ //We decrease size by 4 bytes
+ if(fileSize != 4*(aPackage.iMaxNotifications-i))
+ safe_test(aTest,KErrGeneral,__LINE__,aPackage.iLineCall);
+ }
+ }
+ }
+ else if(notificationType == TFsNotification::ECreate)
+ {
+ if(!(((aPackage.iNotifyType & TFsNotification::ECreate) == TFsNotification::ECreate) &&
+ (aPackage.iOperation == t_notification::EFileCreate ||
+ aPackage.iOperation == t_notification::EFileReplace ||
+ aPackage.iOperation == t_notification::EFileCreate_subs ||
+ aPackage.iOperation == t_notification::EFileCreate_subs_nowatch ||
+ aPackage.iOperation == t_notification::EFileCreate_txt_nowatch ||
+ aPackage.iOperation == t_notification::EFileCreate_txt ||
+ aPackage.iOperation == t_notification::EFsMkDir ||
+ aPackage.iOperation == t_notification::ECFileManMove ||
+ aPackage.iOperation == t_notification::EAllOps1 ||
+ aPackage.iOperation == t_notification::EAllOps2 ||
+ aPackage.iOperation == t_notification::EAllOps3 ||
+ aPackage.iOperation == t_notification::EAllOps4 ||
+ aPackage.iOperation == t_notification::EAllOps5)))
+ safe_test(aTest,KErrGeneral,__LINE__,aPackage.iLineCall);
+ if (aPackage.iOperation == t_notification::EFileCreate_txt)
+ {
+ //Check filename is of correct extension
+ TPtrC _path;
+ ((TFsNotification*) notification)->Path(_path);
+ TBuf<5> _ext;
+ _ext.Append(_L(".txt"));
+ TBuf<5> ext;
+ ext.Append(_path.Right(4));
+ safe_test(aTest,ext.Match(_ext),__LINE__,aPackage.iLineCall);
+ }
+ else if (aPackage.iOperation == t_notification::ECFileManMove)
+ {
+ if(scratch & ECFManCreate1)
+ {
+ scratch |= ECFManCreate2; //File created second time
+ }
+ else
+ {
+ scratch |= ECFManCreate1; //File created first time
+ }
+ }
+ }
+ else if(notificationType == TFsNotification::EDelete)
+ {
+ if(!(((aPackage.iNotifyType & TFsNotification::EDelete) == TFsNotification::EDelete) &&
+ (aPackage.iOperation == t_notification::EFsDelete ||
+ aPackage.iOperation == t_notification::EFsRmDir ||
+ aPackage.iOperation == t_notification::EFsRmDir_nonEmpty ||
+ aPackage.iOperation == t_notification::EFsRmDir_wild ||
+ aPackage.iOperation == t_notification::ECFileManMove ||
+ aPackage.iOperation == t_notification::EAllOps1 ||
+ aPackage.iOperation == t_notification::EAllOps2 ||
+ aPackage.iOperation == t_notification::EAllOps3 ||
+ aPackage.iOperation == t_notification::EAllOps4)))
+ safe_test(aTest,KErrGeneral,__LINE__,aPackage.iLineCall);
+
+ if(aPackage.iOperation == t_notification::ECFileManMove)
+ {
+ if(scratch & ECFManDelete1)
+ {
+ scratch |= ECFManDelete2;
+ }
+ else
+ {
+ scratch |= ECFManDelete1;
+ }
+ }
+ }
+ else if(notificationType == TFsNotification::ERename)
+ {
+ if(!(((aPackage.iNotifyType & TFsNotification::ERename) == TFsNotification::ERename) &&
+ (aPackage.iOperation == t_notification::EFileRename ||
+ aPackage.iOperation == t_notification::EFileRename_wild ||
+ aPackage.iOperation == t_notification::EFsReplace ||
+ aPackage.iOperation == t_notification::ECFileManMove ||
+ aPackage.iOperation == t_notification::EFsRename ||
+ aPackage.iOperation == t_notification::EFsRename_dir ||
+ aPackage.iOperation == t_notification::EAllOps5)))
+ safe_test(aTest,KErrGeneral,__LINE__,aPackage.iLineCall);
+ TPtrC newnameC;
+ ((TFsNotification*)notification)->NewName(newnameC);
+ aTest.Printf(_L("%S - (%d)\n"),&newnameC,threadID);
+
+ TPtrC _pathC;
+ ((TFsNotification*) notification)->Path(_pathC);
+
+ TBuf<40> _path;
+ _path.Copy(_pathC);
+
+ if (aPackage.iOperation == t_notification::EFsRename_dir)
+ {
+ _path.Delete(_path.Length()-1,1);
+ _path.AppendNum(0);
+ _path.Append(KPathDelimiter);
+ }
+ else if (aPackage.iOperation == t_notification::EFileRename_wild)
+ {
+ _path.Delete(_path.Length()-1,1);
+ _path.AppendNum(numNotifications);
+ }
+ else
+ {
+ _path.AppendNum(0);
+ }
+
+ if(aPackage.iOperation != t_notification::ECFileManMove)
+ {
+ safe_test(aTest,newnameC.Match(_path),__LINE__,aPackage.iLineCall);
+ }
+ else if(scratch & ECFManRename1)
+ {
+ scratch |= ECFManRename2;
+ }
+ else
+ {
+ scratch |= ECFManRename1;
+ }
+
+ }
+ else if(notificationType == TFsNotification::EAttribute)
+ {
+ if(!(((aPackage.iNotifyType & TFsNotification::EAttribute) == TFsNotification::EAttribute) &&
+ (aPackage.iOperation == t_notification::EFsSetEntry ||
+ aPackage.iOperation == t_notification::EFileSet ||
+ aPackage.iOperation == t_notification::EFileSetAtt ||
+ aPackage.iOperation == t_notification::EFileSetAtt_subs ||
+ aPackage.iOperation == t_notification::ECFileManMove ||
+ aPackage.iOperation == t_notification::EAllOps4)))
+ safe_test(aTest,KErrGeneral,__LINE__,aPackage.iLineCall);
+ TUint setAtt = 0;
+ TUint clearAtt = 0;
+ ((TFsNotification*) notification)->Attributes(setAtt, clearAtt);
+
+ if(aPackage.iOperation == t_notification::ECFileManMove)
+ {
+ scratch |= ECFManAtt1;
+ }
+ else
+ {
+ if(setAtt != KEntryAttHidden)
+ safe_test(aTest,KErrGeneral,__LINE__,aPackage.iLineCall);
+ if(clearAtt != KEntryAttReadOnly)
+ safe_test(aTest,KErrGeneral,__LINE__,aPackage.iLineCall);
+ }
+ }
+ else if(notificationType == TFsNotification::EMediaChange)
+ {
+ if(!(((aPackage.iNotifyType & TFsNotification::EMediaChange) == TFsNotification::EMediaChange) &&
+ (aPackage.iOperation == t_notification::EMount ||
+ aPackage.iOperation == t_notification::EMountScan ||
+ aPackage.iOperation == t_notification::EDismount ||
+ aPackage.iOperation == t_notification::EMountDismount ||
+ aPackage.iOperation == t_notification::EMediaCardInsertion ||
+ aPackage.iOperation == t_notification::EMediaCardRemoval ||
+ aPackage.iOperation == t_notification::EFormat ||
+ aPackage.iOperation == t_notification::ECFileManMove ||
+ aPackage.iOperation == t_notification::ERawDiskWrite)))
+ safe_test(aTest,KErrGeneral,__LINE__,aPackage.iLineCall);
+ }
+ else if(notificationType == TFsNotification::EDriveName)
+ {
+ if(!(((aPackage.iNotifyType & TFsNotification::EDriveName) == TFsNotification::EDriveName) &&
+ (aPackage.iOperation == t_notification::ESetDriveName ||
+ aPackage.iOperation == t_notification::EAllOps6)))
+ safe_test(aTest,KErrGeneral,__LINE__,aPackage.iLineCall);
+ }
+ else if(notificationType == TFsNotification::EVolumeName)
+ {
+ if(!(((aPackage.iNotifyType & TFsNotification::EVolumeName) == TFsNotification::EVolumeName) &&
+ (aPackage.iOperation == t_notification::ESetVolumeLabel ||
+ aPackage.iOperation == t_notification::EAllOps6)))
+ safe_test(aTest,KErrGeneral,__LINE__,aPackage.iLineCall);
+
+ TPtrC newnameC;
+ ((TFsNotification*)notification)->NewName(newnameC);
+ aTest.Printf(_L("New volume name: %S - (%d)\n"),&newnameC,threadID);
+ }
+
+ i++;
+ notification = notify->NextNotification();
+ if (notification == NULL)
+ aTest.Printf(_L("Notification is NULL - (%d)\n"),threadID);
+ }
+
+ if(i==1) //First iteration will only ever get 1 notification
+ {
+ if(numNotifications != 1)
+ safe_test(aTest,KErrGeneral,__LINE__,aPackage.iLineCall);
+ }
+
+ if(numNotifications < aPackage.iMaxNotifications && !overflow) //Ensure we get all of the notifications we expected
+ {
+ TRequestStatus status;
+ notify->RequestNotifications(status);
+ User::WaitForRequest(status);
+ }
+ }
+
+ //0x307 = create1 | write1 | delete1 | rename1 | rename2
+ if(aPackage.iOperation == t_notification::ECFileManMove && (scratch != 0x307))
+ {
+ aTest.Printf(_L("CFileManMove test failure - scratch = 0x%x"),scratch);
+ safe_test(aTest,KErrGeneral,__LINE__,aPackage.iLineCall);
+ }
+
+ }
+
+/*
+ * Watches for changes in files/directories.
+ * Used in TestMultipleNotificationsL().
+ */
+TInt MultipleNotificationsTFWatcher(TAny* aAny)
+ {
+ CTrapCleanup* cleanup;
+ cleanup = CTrapCleanup::New();
+
+ RThread thread;
+ TUint64 threadID = thread.Id().Id();
+
+ SThreadPackageMultiple package = *(SThreadPackageMultiple*) aAny;
+ RTest multipleWatcherTest(_L("MultipleNotificationsTFWatcher"));
+ multipleWatcherTest.Start(_L("MultipleNotificationsTFWatcher"));
+
+ RFs fs;
+ fs.Connect();
+
+ multipleWatcherTest.Printf(_L("MultipleNotificationsTFWatcher (%d) - Create CFsNotify\n"),threadID);
+ CFsNotify* notify = NULL;
+ TRAPD(r,notify = CFsNotify::NewL(fs,package.iBufferSize));
+ safe_test(multipleWatcherTest,r,__LINE__,package.iLineCall);
+ TBuf<40> path;
+ TBuf<20> filename;
+ if(package.iNotifyType != TFsNotification::EMediaChange &&
+ package.iNotifyType != TFsNotification::EDriveName &&
+ package.iNotifyType != TFsNotification::EVolumeName &&
+ package.iOperation != t_notification::EAllOps6)
+ {
+ path.Append(gDriveToTest);
+ path.Append(_L(":\\F32-TST\\T_NOTIFIER\\")); //len=22
+ path.Append(package.iFileName);
+ filename.Append(package.iString);
+ }
+ else
+ {
+ path.Append((TChar)globalDriveNum+(TChar)'A');
+ path.Append(_L(":"));
+ }
+ TBuf<40> fullname;
+ fullname.Append(path);
+ fullname.Append(filename);
+
+ if (package.iNotifyType == TFsNotification::EVolumeName ||
+ package.iOperation == t_notification::EAllOps6)
+ {
+ //Ensure volume has no label
+ multipleWatcherTest.Printf(_L("Set volume label to nothing\n"));
+ r = fs.SetVolumeLabel(_L(""),globalDriveNum);
+ safe_test(multipleWatcherTest,r,__LINE__,package.iLineCall);
+ }
+
+ if (package.iNotifyType == TFsNotification::EDriveName ||
+ package.iOperation == t_notification::EAllOps6)
+ {
+ //Ensure drive has no name
+ multipleWatcherTest.Printf(_L("Set drive name to nothing\n"));
+ r = fs.SetDriveName(globalDriveNum,_L(""));
+ safe_test(multipleWatcherTest,r,__LINE__,package.iLineCall);
+ }
+
+ multipleWatcherTest.Printf(_L("MultipleNotificationsTFWatcher - Add Notification for path %S\n"),&path);
+ multipleWatcherTest.Printf(_L("Add Notification for type %u - (%d)\n"),(TUint)package.iNotifyType,threadID);
+ r = notify->AddNotification((TUint)package.iNotifyType,path,filename);
+ safe_test(multipleWatcherTest,r,__LINE__,package.iLineCall);
+
+ TRequestStatus status;
+ multipleWatcherTest.Printf(_L("(%d) - Request Notifications\n"),threadID);
+ r = notify->RequestNotifications(status);
+ safe_test(multipleWatcherTest,r,__LINE__,package.iLineCall);
+
+ if (package.iOperation == t_notification::EMediaCardRemoval)
+ {
+ multipleWatcherTest.Printf(_L("*****************************************************************\n"));
+ multipleWatcherTest.Printf(_L("Waiting 10 seconds.\n"));
+ multipleWatcherTest.Printf(_L("This is a MANUAL test, it requires the removal of the media card.\n"));
+ multipleWatcherTest.Printf(_L("PLEASE REMOVE THE MEDIA CARD. (DriveNumber %d)\n"),globalDriveNum);
+ multipleWatcherTest.Printf(_L("Or press Ctrl + F5 on the emulator.\n"));
+ multipleWatcherTest.Printf(_L("*****************************************************************\n"));
+ }
+ if (package.iOperation == t_notification::EMediaCardInsertion)
+ {
+ multipleWatcherTest.Printf(_L("*******************************************************************\n"));
+ multipleWatcherTest.Printf(_L("Waiting 10 seconds.\n"));
+ multipleWatcherTest.Printf(_L("This is a MANUAL test, it requires the insertion of the media card.\n"));
+ multipleWatcherTest.Printf(_L("PLEASE INSERT THE MEDIA CARD. (DriveNumber %d)\n"),globalDriveNum);
+ multipleWatcherTest.Printf(_L("*******************************************************************\n"));
+ }
+
+ multipleWatcherTest.Printf(_L("(%d) - Signal Test thread to start Doer thread\n"),threadID);
+ package.iBarrier.Signal();
+ User::WaitForRequest(status);
+
+ multipleWatcherTest.Printf(_L("(%d) - MultipleNotificationsTFWatcher Line %d\n"),threadID,__LINE__);
+
+ //Handles the notifications
+ HandleMultipleNotifications(multipleWatcherTest, package, notify, (TDesC&)fullname);
+
+ multipleWatcherTest.Printf(_L("(%d) - MultipleNotificationsTFWatcher Line %d\n"),threadID,__LINE__);
+
+ delete notify;
+ fs.Close();
+ multipleWatcherTest.End();
+ multipleWatcherTest.Close();
+ delete cleanup;
+ return KErrNone;
+ }
+
+/*
+ * TestTwoNotificationsL - Tests File Write, 1 Doer writes to a file twice.
+ * 1 Watcher watches for file write changes. Just so happens that the second one overflows.
+ */
+TInt TestTwoNotificationsL()
+ {
+ test.Next(_L("TestTwoNotifications"));
+
+ RFs fs;
+ fs.Connect();
+ RSemaphore twoNotificationsDoerBar;
+ SThreadPackageMultiple package;
+ _LIT(KFileName,"file0.write");
+ package.iIterations = 10;
+ package.iOperation = t_notification::EFileWrite;
+ package.iNotifyType = TFsNotification::EFileChange;
+ package.iFileName = KFileName;
+ package.iBufferSize = 100; //Should get changed to KMin... in CFsNotify::NewL
+
+ User::LeaveIfError(twoNotificationsDoerBar.CreateLocal(0));
+ User::LeaveIfError(package.iBarrier.CreateLocal(0));
+ RThread watcher;
+ RThread doer;
+
+ TInt r = watcher.Create(_L("TestTwoNotificationsWatcherThread"),MultipleNotificationsTFWatcher,KDefaultStackSize,KMinHeapSize,KMaxHeapSize,&package);
+ test(r==KErrNone);
+ r = doer.Create(_L("TestTwoNotificationsDoerThread"),TwoNotificationsTFDoer,KDefaultStackSize,KMinHeapSize,KMaxHeapSize,&package);
+ test(r==KErrNone);
+ test.Next(_L("TestTwoNotifications - Resume Watcher"));
+ watcher.Resume();
+ test.Next(_L("TestTwoNotifications - Wait for Watcher to be ready"));
+ package.iBarrier.Wait(); //Wait till Watcher has requested notification
+ test.Next(_L("TestTwoNotifications - Resume Doer"));
+ doer.Resume();
+
+ test.Next(_L("TestTwoNotifications - Wait for doer thread death"));
+ TRequestStatus status;
+ doer.Logon(status);
+ User::WaitForRequest(status);
+ test(doer.ExitReason()==KErrNone);
+
+ test.Next(_L("TestTwoNotifications - Wait for watcher thread death"));
+ watcher.Logon(status);
+ User::WaitForRequest(status);
+ test(watcher.ExitReason()==KErrNone);
+
+ CLOSE_AND_WAIT(doer);
+ CLOSE_AND_WAIT(watcher);
+
+ twoNotificationsDoerBar.Close();
+ package.iBarrier.Close();
+ fs.Close();
+
+ return KErrNone;
+ }
+
+
+/*
+ * Watch two threads to receive two notifications.
+ * Used in TestTwoDoersL().
+ */
+TInt TestTwoDoersWatcher(TAny* aAny)
+ {
+ CTrapCleanup* cleanup;
+ cleanup = CTrapCleanup::New();
+
+ RSemaphore& twoThreadsBarrier = *(RSemaphore*)aAny;
+ RTest twoThreadsWatcherTest(_L("TwoThreadsWatcher"));
+ twoThreadsWatcherTest.Start(_L("TwoThreadsWatcher"));
+
+ RFs fs;
+ fs.Connect();
+
+ twoThreadsWatcherTest.Next(_L("Create CFsNotify"));
+ CFsNotify* notify = NULL;
+ TRAPD(r,notify = CFsNotify::NewL(fs,200));
+ twoThreadsWatcherTest(r == KErrNone);
+
+ TBuf<40> path1;
+ TBuf<20> filename1;
+ TBuf<40> path2;
+ TBuf<20> filename2;
+ path1.Append(gDriveToTest);
+ path2.Append(gDriveToTest);
+ path1.Append(_L(":\\F32-TST\\T_NOTIFIER\\"));
+ filename1.Append(_L("file1.create"));
+ path2.Append(_L(":\\F32-TST\\T_NOTIFIER\\"));
+ filename2.Append(_L("file2.create"));
+ TBuf<40> fullname1;
+ fullname1.Append(path1);
+ fullname1.Append(filename1);
+ TBuf<40> fullname2;
+ fullname2.Append(path2);
+ fullname2.Append(filename2);
+
+ twoThreadsWatcherTest.Printf(_L("TwoThreadsWatcher - Add Notification for %S\n"),&path1);
+ r = notify->AddNotification((TUint)TFsNotification::ECreate,path1,filename1);
+ twoThreadsWatcherTest(r == KErrNone);
+
+ twoThreadsWatcherTest.Printf(_L("TwoThreadsWatcher - Add Notification for %S\n"),&path2);
+ r = notify->AddNotification((TUint)TFsNotification::ECreate,path2,filename2);
+ twoThreadsWatcherTest(r == KErrNone);
+
+ TRequestStatus status;
+ twoThreadsWatcherTest.Next(_L("TwoThreadsWatcher - Request Notifications"));
+ r = notify->RequestNotifications(status);
+ twoThreadsWatcherTest(r == KErrNone);
+
+ twoThreadsBarrier.Signal(); //Signal Doer threads to start
+ User::WaitForRequest(status);
+
+ // We should be getting 2 notifications
+ // Test notifications are not null and check notification types and paths
+ // 1st notification:
+ twoThreadsWatcherTest.Next(_L("TwoThreadsWatcher - First Notification"));
+ const TFsNotification* notification = notify->NextNotification();
+ twoThreadsWatcherTest(notification != NULL);
+ twoThreadsWatcherTest.Next(_L("TwoThreadsWatcher - First Notification Type"));
+ TFsNotification::TFsNotificationType notificationType = ((TFsNotification*)notification)->NotificationType();
+ twoThreadsWatcherTest(notificationType == TFsNotification::ECreate);
+ twoThreadsWatcherTest.Next(_L("TwoThreadsWatcher - First Notification Path"));
+ TPtrC _pathC;
+ ((TFsNotification*)notification)->Path(_pathC);
+ twoThreadsWatcherTest.Printf(_L("TwoThreadsWatcher - First Notification Path returned %S\n"),&_pathC);
+ TBuf<40> _path;
+ _path.Copy(_pathC);
+ //We can't guarantee which thread ran first so check that it was either path1 or path2
+ twoThreadsWatcherTest(_path.Match(fullname1) == KErrNone || _path.Match(fullname2) == KErrNone);
+
+ // 2nd notification:
+ twoThreadsWatcherTest.Next(_L("TwoThreadsWatcher - Second Notification"));
+ notification = notify->NextNotification();
+ // Check if next notification exists
+ if (!notification)
+ {
+ notify->RequestNotifications(status);
+ User::WaitForRequest(status);
+ notification = notify->NextNotification();
+ }
+ twoThreadsWatcherTest(notification != NULL);
+ twoThreadsWatcherTest.Next(_L("TwoThreadsWatcher - Second Notification Type"));
+ notificationType = ((TFsNotification*)notification)->NotificationType();
+ twoThreadsWatcherTest(notificationType == TFsNotification::ECreate);
+ twoThreadsWatcherTest.Next(_L("TwoThreadsWatcher - Second Notification Path"));
+ ((TFsNotification*)notification)->Path(_pathC);
+ twoThreadsWatcherTest.Printf(_L("TwoThreadsWatcher - Second Notification Path returned %S\n"),&_pathC);
+ _path.Copy(_pathC);
+ twoThreadsWatcherTest(_path.Match(fullname1) == KErrNone || _path.Match(fullname2) == KErrNone);
+
+ delete notify;
+ fs.Close();
+ twoThreadsWatcherTest.End();
+ twoThreadsWatcherTest.Close();
+ delete cleanup;
+ return KErrNone;
+ }
+
+/*
+ * TestTwoDoersL - Two Doer threads create a file each and there's one Watcher
+ * which expects two notifications (one from each Doer).
+ */
+TInt TestTwoDoersL()
+ {
+ test.Next(_L("TestTwoDoers"));
+
+ RFs fs;
+ fs.Connect();
+
+ _LIT(KFileName1,"file1.create");
+ _LIT(KFileName2,"file2.create");
+ RSemaphore simpleBarrierTest;
+ SThreadPackage pkgDoer1;
+ SThreadPackage pkgDoer2;
+ pkgDoer1.iFileName = KFileName1;
+ pkgDoer2.iFileName = KFileName2;
+
+ User::LeaveIfError(pkgDoer1.iBarrier.CreateLocal(0));
+ User::LeaveIfError(pkgDoer2.iBarrier.CreateLocal(0));
+ User::LeaveIfError(simpleBarrierTest.CreateLocal(0));
+ RThread watcher;
+ RThread doer1;
+ RThread doer2;
+
+ watcher.Create(_L("TestTwoDoers-WatcherThread"),TestTwoDoersWatcher,KDefaultStackSize,KMinHeapSize,KMaxHeapSize,&simpleBarrierTest);
+ doer1.Create(_L("TestTwoDoers-DoerThread1"),SimpleSingleNotificationTFDoer,KDefaultStackSize,KMinHeapSize,KMaxHeapSize,&pkgDoer1);
+ doer2.Create(_L("TestTwoDoers-DoerThread2"),SimpleSingleNotificationTFDoer,KDefaultStackSize,KMinHeapSize,KMaxHeapSize,&pkgDoer2);
+ watcher.Resume();
+ simpleBarrierTest.Wait(); //Wait until Watcher has created CFsNotify
+
+ doer1.Resume();
+ doer2.Resume();
+
+ test.Next(_L("TestTwoDoers - Wait for doer1 thread death"));
+ TRequestStatus status;
+ doer1.Logon(status);
+ User::WaitForRequest(status);
+ test(doer1.ExitReason()==KErrNone);
+
+ test.Next(_L("TestTwoDoers - Wait for doer2 thread death"));
+ doer2.Logon(status);
+ User::WaitForRequest(status);
+ test(doer2.ExitReason()==KErrNone);
+
+ test.Next(_L("TestTwoDoers - Wait for watcher thread death"));
+ watcher.Logon(status);
+ RTimer timer1;
+ TInt r = timer1.CreateLocal();
+ safe_test(test,r,__LINE__,(TText*)Expand("t_notifier.cpp"));
+ TRequestStatus timeout;
+ TTimeIntervalMicroSeconds32 time = 10000000; //10 seconds
+ timer1.After(timeout,time);
+ User::WaitForRequest(timeout,status);
+ test(status.Int() != KRequestPending);
+ timer1.Cancel();
+ timer1.Close();
+ //User::WaitForRequest(status);
+ test(watcher.ExitReason()==KErrNone);
+
+ CLOSE_AND_WAIT(doer1);
+ CLOSE_AND_WAIT(doer2);
+ CLOSE_AND_WAIT(watcher);
+
+ pkgDoer1.iBarrier.Close();
+ pkgDoer2.iBarrier.Close();
+ simpleBarrierTest.Close();
+ fs.Close();
+ return KErrNone;
+ }
+
+/*
+ * TestTwoWatchersL - Uses two watcher threads and one doer thread to test that running
+ * two distinct sub sessions at the same time (both watch the same file).
+ */
+TInt TestTwoWatchersL()
+ {
+ test.Next(_L("TestTwoWatchers"));
+ RFs fs;
+ fs.Connect();
+ _LIT(KFileName,"file.creat3");
+ SThreadPackage pkgDoer;
+ pkgDoer.iFileName = KFileName;
+
+ SThreadPackage watcherPkg;
+ watcherPkg.iFileName = KFileName;
+
+ User::LeaveIfError(pkgDoer.iBarrier.CreateLocal(0));
+ User::LeaveIfError(watcherPkg.iBarrier.CreateLocal(0));
+ RThread watcher;
+ RThread watcher2;
+ RThread doer;
+ watcher.Create(_L("TestTwoWatchersWatcherThread"),SimpleSingleNotificationTFWatcher,KDefaultStackSize,KMinHeapSize,KMaxHeapSize,&watcherPkg);
+ watcher2.Create(_L("TestTwoWatchersWatcher2Thread"),SimpleSingleNotificationTFWatcher,KDefaultStackSize,KMinHeapSize,KMaxHeapSize,&watcherPkg);
+ doer.Create(_L("TestTwoWatchersDoerThread"),SimpleSingleNotificationTFDoer,KDefaultStackSize,KMinHeapSize,KMaxHeapSize,&pkgDoer);
+ watcher.Resume();
+ watcher2.Resume();
+ watcherPkg.iBarrier.Wait(); //Wait till both watchers have requested notification
+ watcherPkg.iBarrier.Wait();
+ doer.Resume();
+
+ test.Printf(_L("Wait for DOER to terminate , Line %d"),__LINE__);
+ TRequestStatus status;
+ doer.Logon(status);
+ User::WaitForRequest(status);
+ test(doer.ExitReason()==KErrNone);
+
+ test.Printf(_L("Wait for WATCHER to terminate , Line %d"),__LINE__);
+ watcher.Logon(status);
+ RTimer timer1;
+ TInt r = timer1.CreateLocal();
+ safe_test(test,r,__LINE__,(TText*)Expand("t_notifier.cpp"));
+ TRequestStatus timeout;
+ TTimeIntervalMicroSeconds32 time = 10000000; //10 seconds
+ timer1.After(timeout,time);
+ User::WaitForRequest(timeout,status);
+ test(status.Int() != KRequestPending);
+ timer1.Cancel();
+ timer1.Close();
+// User::WaitForRequest(status);
+ test(watcher.ExitReason()==KErrNone);
+
+ test.Printf(_L("Wait for WATCHER2 to terminate , Line %d"),__LINE__);
+ watcher2.Logon(status);
+ RTimer timer2;
+ r = timer2.CreateLocal();
+ safe_test(test,r,__LINE__,(TText*)Expand("t_notifier.cpp"));
+ TRequestStatus timeout2;
+ timer2.After(timeout2,time);
+ User::WaitForRequest(timeout2,status);
+ test(status.Int() != KRequestPending);
+ timer2.Cancel();
+ timer2.Close();
+ //User::WaitForRequest(status);
+ test(watcher2.ExitReason()==KErrNone);
+
+ CLOSE_AND_WAIT(doer);
+ CLOSE_AND_WAIT(watcher);
+ CLOSE_AND_WAIT(watcher2);
+
+ pkgDoer.iBarrier.Close();
+ watcherPkg.iBarrier.Close();
+ fs.Close();
+ return KErrNone;
+ }
+
+
+/*
+ * TestTwoWatchersTwoDoersL - Two watcher threads watches two different doer threads.
+ */
+TInt TestTwoWatchersTwoDoersL()
+ {
+ test.Next(_L("TestTwoWatchersTwoDoers"));
+ RFs fs;
+ fs.Connect();
+ _LIT(KFileName1,"f1le.create");
+ _LIT(KFileName2,"f2le.create");
+ SThreadPackage package1;
+ package1.iFileName = KFileName1;
+
+ SThreadPackage package2;
+ package2.iFileName = KFileName2;
+
+ User::LeaveIfError(package1.iBarrier.CreateLocal(0));
+ User::LeaveIfError(package2.iBarrier.CreateLocal(0));
+ RThread watcher;
+ RThread watcher2;
+ RThread doer;
+ RThread doer2;
+ watcher.Create(_L("TestTwoWatchersTwoDoersWatcherThread"),SimpleSingleNotificationTFWatcher,KDefaultStackSize,KMinHeapSize,KMaxHeapSize,&package1);
+ doer.Create(_L("TestTwoWatchersTwoDoersDoerThread"),SimpleSingleNotificationTFDoer,KDefaultStackSize,KMinHeapSize,KMaxHeapSize,&package1);
+
+ watcher2.Create(_L("TestTwoWatchersTwoDoersWatcher2Thread"),SimpleSingleNotificationTFWatcher,KDefaultStackSize,KMinHeapSize,KMaxHeapSize,&package2);
+ doer2.Create(_L("TestTwoWatchersTwoDoersDoer2Thread"),SimpleSingleNotificationTFDoer,KDefaultStackSize,KMinHeapSize,KMaxHeapSize,&package2);
+ watcher.Resume();
+ watcher2.Resume();
+ package1.iBarrier.Wait(); //Wait till both watchers have requested notification
+ package2.iBarrier.Wait();
+ doer.Resume();
+ doer2.Resume();
+
+ test.Printf(_L("Wait for DOER to terminate , Line %d"),__LINE__);
+ TRequestStatus status;
+ doer.Logon(status);
+ User::WaitForRequest(status);
+ test(doer.ExitReason()==KErrNone);
+
+ test.Printf(_L("Wait for DOER2 to terminate , Line %d"),__LINE__);
+ doer2.Logon(status);
+ User::WaitForRequest(status);
+ test(doer2.ExitReason()==KErrNone);
+
+ test.Printf(_L("Wait for WATCHER to terminate , Line %d"),__LINE__);
+ watcher.Logon(status);
+ RTimer timer1;
+ TInt r = timer1.CreateLocal();
+ safe_test(test,r,__LINE__,(TText*)Expand("t_notifier.cpp"));
+ TRequestStatus timeout;
+ TTimeIntervalMicroSeconds32 time = 10000000; //10 seconds
+ timer1.After(timeout,time);
+ User::WaitForRequest(timeout,status);
+ test(status.Int() != KRequestPending);
+ timer1.Cancel();
+ timer1.Close();
+ test(watcher.ExitReason()==KErrNone);
+
+ test.Printf(_L("Wait for WATCHER2 to terminate , Line %d"),__LINE__);
+ watcher2.Logon(status);
+ RTimer timer2;
+ r = timer2.CreateLocal();
+ safe_test(test,r,__LINE__,(TText*)Expand("t_notifier.cpp"));
+ TRequestStatus timeout2;
+ timer2.After(timeout2,time);
+ User::WaitForRequest(timeout2,status);
+ test(status.Int() != KRequestPending);
+ timer2.Cancel();
+ timer2.Close();
+ test(watcher2.ExitReason()==KErrNone);
+
+ CLOSE_AND_WAIT(doer);
+ CLOSE_AND_WAIT(doer2);
+ CLOSE_AND_WAIT(watcher);
+ CLOSE_AND_WAIT(watcher2);
+
+ package1.iBarrier.Close();
+ package2.iBarrier.Close();
+ fs.Close();
+ return KErrNone;
+ }
+
+
+/*
+ * Multi-purpose test
+ *
+ * If aFailureExpected is ETrue, it is expected that the watcher thread is not terminated normally,
+ * due to the notification(s) not being sent.
+ * Since this function is called many times, aLineCall is used to show the line where it is called from.
+ * See SThreadPackageMultiple.
+ */
+TInt TestMultipleNotificationsL(const TDesC& aFilename, const TDesC& aString, TInt aIterations,
+ TInt aMaxNotifications, t_notification::EOperation aOperation,
+ TUint aNotifyType, TInt aBufferSize, TBool aFailureExpected, TInt aLineCall)
+ {
+ test.Next(_L("TestMultipleNotifications"));
+
+ RFs fs;
+ fs.Connect();
+ SThreadPackageMultiple package;
+ package.iIterations = aIterations;
+ package.iMaxNotifications = aMaxNotifications;
+ package.iOperation = aOperation;
+ package.iNotifyType = (TFsNotification::TFsNotificationType)aNotifyType;
+ package.iString = aString;
+ package.iFileName = aFilename;
+ package.iBufferSize = aBufferSize;
+ package.iLineCall = aLineCall;
+
+ User::LeaveIfError(package.iBarrier.CreateLocal(0));
+ RThread watcher;
+ RThread doer;
+ RTimer tim;
+ User::LeaveIfError(tim.CreateLocal());
+
+ TInt r = watcher.Create(_L("TestMultipleNotificationsWatcherThread"),MultipleNotificationsTFWatcher,KDefaultStackSize,KMinHeapSize,KMaxHeapSize,&package);
+ safe_test(test,r,__LINE__,package.iLineCall);
+ r = doer.Create(_L("TestMultipleNotificationsDoerThread"),MultipleNotificationTFDoer,KDefaultStackSize*2,KMinHeapSize,KMaxHeapSize,&package);
+ safe_test(test,r,__LINE__,package.iLineCall);
+ test.Next(_L("TestMultipleNotifications - Resume Watcher"));
+ watcher.Resume();
+ test.Next(_L("TestMultipleNotifications - Wait for Watcher to be ready"));
+ package.iBarrier.Wait(); //Wait till Watcher has requested notification
+ test.Next(_L("TestMultipleNotifications - Resume Doer"));
+ doer.Resume();
+
+ test.Next(_L("TestMultipleNotifications - Wait for doer thread death"));
+ TRequestStatus status;
+ doer.Logon(status);
+ User::WaitForRequest(status);
+ test.Printf(_L("TestMultipleNotifications - Doer Exit Reason %d\n"),doer.ExitReason());
+ safe_test(test,doer.ExitReason(),__LINE__,package.iLineCall);
+
+ TRequestStatus timStatus;
+ TTimeIntervalMicroSeconds32 timeout;
+ if (aFailureExpected && !(package.iOperation == t_notification::EMediaCardInsertion ||
+ package.iOperation == t_notification::EMediaCardRemoval))
+ {
+ timeout = 1500000; //1.5 seconds, we don't want to wait too long if we expect it to fail
+ }
+ else
+ {
+ timeout = 10000000; //10 seconds
+ }
+ tim.After(timStatus,timeout);
+
+ test.Next(_L("TestMultipleNotifications - Wait for watcher thread death or timeout"));
+ watcher.Logon(status);
+ User::WaitForRequest(status,timStatus);
+ if(!(status != KRequestPending || aFailureExpected))
+ safe_test(test,KErrGeneral,__LINE__,package.iLineCall);
+
+ test.Printf(_L("TestMultipleNotifications - Watcher Exit Reason %d\n"),watcher.ExitReason());
+ safe_test(test,watcher.ExitReason(),__LINE__,package.iLineCall);
+
+ CLOSE_AND_WAIT(doer);
+
+ if(status == KRequestPending)
+ {
+ watcher.Kill(KErrTimedOut);
+ test.Printf(_L("TestMultipleNotifications - Watcher timed out\n"));
+ }
+ CLOSE_AND_WAIT(watcher);
+
+ package.iBarrier.Close();
+ fs.Close();
+ tim.Close();
+ test.Printf(_L("----------------------------------------------------------------------\n"));
+ return KErrNone;
+ }
+
+TInt TestMultipleNotificationsL(const TDesC& aFilename, const TDesC& aString, TInt aIterations,
+ TInt aMaxNotifications, t_notification::EOperation aOperation,
+ TFsNotification::TFsNotificationType aNotifyType, TInt aBufferSize,
+ TBool aFailureExpected, TInt aLineCall)
+ {
+ return TestMultipleNotificationsL(aFilename, aString, aIterations, aMaxNotifications, aOperation,
+ (TUint)aNotifyType, aBufferSize, aFailureExpected, aLineCall);
+ }
+
+TInt TestMultipleNotificationsL(const TDesC& aFilename, TInt aIterations, TInt aMaxNotifications,
+ t_notification::EOperation aOperation, TUint aNotifyType, TInt aBufferSize,
+ TBool aFailureExpected, TInt aLineCall)
+ {
+ return TestMultipleNotificationsL(aFilename,_L(""), aIterations, aMaxNotifications, aOperation, aNotifyType,
+ aBufferSize, aFailureExpected, aLineCall);
+ }
+
+
+// Watcher for TestAddRemoveNotificationL()
+TInt TestAddRemoveNotificationWatcher(TAny* aAny)
+ {
+ CTrapCleanup* cleanup;
+ cleanup = CTrapCleanup::New();
+ RThread thread;
+ TUint64 threadId = thread.Id().Id();
+
+ SThreadPackage pkgDoer = *(SThreadPackage*)aAny;
+ RSemaphore& addRemoveBarrier = pkgDoer.iBarrier;
+
+ RTest addRemoveWatcherTest(_L("TestAddRemoveNotificationWatcher"));
+ addRemoveWatcherTest.Start(_L("TestAddRemoveNotificationWatcher"));
+
+ RFs fs;
+ fs.Connect();
+
+ addRemoveWatcherTest.Printf(_L("TestAddRemoveNotificationWatcher(%d) - Create CFsNotify\n"),threadId);
+ CFsNotify* notify = NULL;
+ TRAPD(r,notify = CFsNotify::NewL(fs,100); );
+ addRemoveWatcherTest( r == KErrNone);
+ TBuf<40> path;
+ TBuf<20> filename;
+ path.Append(gDriveToTest);
+ path.Append(_L(":\\F32-TST\\T_NOTIFIER\\")); //len=22
+ filename.Append(pkgDoer.iFileName);
+
+ addRemoveWatcherTest.Printf(_L("TestAddRemoveNotificationWatcher - Add Notification for %S\n"),&path);
+ r = notify->AddNotification((TUint)TFsNotification::ECreate,path,filename);
+ addRemoveWatcherTest(r==KErrNone);
+ addRemoveWatcherTest.Printf(_L("TestAddRemoveNotificationWatcher(%d) - Remove Notifications\n"),threadId);
+ r = notify->RemoveNotifications();
+ addRemoveWatcherTest(r==KErrNone);
+ addRemoveWatcherTest.Printf(_L("TestAddRemoveNotificationWatcher(%d) - Request Notifications\n"),threadId);
+ TRequestStatus status;
+ r = notify->RequestNotifications(status);
+ addRemoveWatcherTest(r==KErrNone);
+ addRemoveWatcherTest.Printf(_L("TestAddRemoveNotificationWatcher status = %d"),status.Int());
+ addRemoveBarrier.Signal();
+
+ addRemoveWatcherTest.Printf(_L("TestAddRemoveNotificationWatcher(%d) - NextNotification\n"),threadId);
+ //We should not be getting any notifications as the notification request has been removed
+ const TFsNotification* notification = notify->NextNotification();
+ addRemoveWatcherTest(notification == NULL);
+
+ delete notify;
+ fs.Close();
+ addRemoveWatcherTest.End();
+ addRemoveWatcherTest.Close();
+ delete cleanup;
+ return KErrNone;
+ }
+
+
+/*
+ * TestAddRemoveNotificationL - Watcher adds and removes notification request.
+ * Any changes by doer thread should not be detected.
+ */
+TInt TestAddRemoveNotificationL()
+ {
+ test.Next(_L("TestAddRemoveNotification"));
+ RFs fs;
+ fs.Connect();
+
+ SThreadPackage package;
+ _LIT(KFileName,"noFile.create");
+ package.iFileName = KFileName;
+
+ User::LeaveIfError(package.iBarrier.CreateLocal(0));
+ RThread watcher;
+ RThread doer;
+
+ watcher.Create(_L("TestAddRemoveNotification-WatcherThread"),TestAddRemoveNotificationWatcher,KDefaultStackSize,KMinHeapSize,KMaxHeapSize,&package);
+ doer.Create(_L("TestAddRemoveNotification-DoerThread"),SimpleSingleNotificationTFDoer,KDefaultStackSize,KMinHeapSize,KMaxHeapSize,&package);
+ watcher.Resume();
+
+ test.Printf(_L("TestAddRemoveNotification - Wait until Watcher has created CFsNotify\n"));
+ package.iBarrier.Wait(); //Wait until Watcher has created CFsNotify
+ doer.Resume();
+
+ test.Next(_L("TestAddRemoveNotification - Wait for doer thread death"));
+ TRequestStatus status;
+ doer.Logon(status);
+ User::WaitForRequest(status);
+ test(doer.ExitReason()==KErrNone);
+
+ test.Next(_L("TestAddRemoveNotification - Wait for watcher thread death"));
+ watcher.Logon(status);
+ RTimer timer1;
+ TInt r = timer1.CreateLocal();
+ safe_test(test,r,__LINE__,(TText*)Expand("t_notifier.cpp"));
+ TRequestStatus timeout;
+ TTimeIntervalMicroSeconds32 time = 10000000; //10 seconds
+ timer1.After(timeout,time);
+ User::WaitForRequest(timeout,status);
+ test(status.Int() != KRequestPending);
+ timer1.Cancel();
+ timer1.Close();
+ test.Printf(_L("Test - Watcher Exit Reason %d\n"),watcher.ExitReason());
+ test(watcher.ExitReason()==KErrNone);
+
+ CLOSE_AND_WAIT(doer);
+ CLOSE_AND_WAIT(watcher);
+
+ package.iBarrier.Close();
+ fs.Close();
+ return KErrNone;
+ }
+
+
+/*
+ * Adds and cancels notification request.
+ * Used in TestCancelNotificationL().
+ */
+TInt TestCancelNotificationWatcher(TAny* aAny)
+ {
+ CTrapCleanup* cleanup;
+ cleanup = CTrapCleanup::New();
+
+ RTest cancelNotificationsWatcherTest(_L("TestCancelNotificationWatcher"));
+ cancelNotificationsWatcherTest.Start(_L("TestCancelNotificationWatcher"));
+
+ RThread thread;
+ TUint64 threadId = thread.Id().Id();
+
+ SThreadPackageDualSemaphore pkgDoer = *(SThreadPackageDualSemaphore*)aAny;
+ RSemaphore& addRemoveBarrier = pkgDoer.iBarrier;
+ RSemaphore& addRemoveBarrier2 = pkgDoer.iBarrier2;
+
+ RFs fs;
+ fs.Connect();
+
+ cancelNotificationsWatcherTest.Printf(_L("TestCancelNotificationWatcher(%d) - Create CFsNotify\n"),threadId);
+ CFsNotify* notify = NULL;
+ TRAPD(r,notify = CFsNotify::NewL(fs,100); );
+ cancelNotificationsWatcherTest(r == KErrNone);
+ TBuf<40> path;
+ TBuf<20> filename;
+ path.Append(gDriveToTest);
+ path.Append(_L(":\\F32-TST\\T_NOTIFIER\\")); //len=22
+ filename.Append(pkgDoer.iFileName);
+
+ cancelNotificationsWatcherTest.Printf(_L("TestCancelNotificationWatcher - Add Notification for %S\n"),&path);
+ r = notify->AddNotification((TUint)TFsNotification::ECreate,path,filename);
+ cancelNotificationsWatcherTest(r==KErrNone);
+ cancelNotificationsWatcherTest.Printf(_L("TestCancelNotificationWatcher(%d) - Request Notifications\n"),threadId);
+ TRequestStatus status;
+ r = notify->RequestNotifications(status);
+ cancelNotificationsWatcherTest(r==KErrNone);
+
+ cancelNotificationsWatcherTest.Printf(_L("TestCancelNotificationWatcher(%d) - Cancel Notifications\n"),threadId);
+ r = notify->CancelNotifications(status);
+ cancelNotificationsWatcherTest(r==KErrNone);
+
+ cancelNotificationsWatcherTest.Printf(_L("TestCancelNotificationWatcher(%d) - Signal W1 - Start doer\n"),threadId);
+ addRemoveBarrier.Signal(); //W1 - Start doer
+
+ cancelNotificationsWatcherTest.Printf(_L("TestCancelNotificationWatcher(%d) - Wait S1 - doer complete\n"),threadId);
+ addRemoveBarrier2.Wait(); //S1 - Wait for doer to have created file
+
+ cancelNotificationsWatcherTest.Printf(_L("TestCancelNotificationWatcher(%d) - NextNotification\n"),threadId);
+ //We should not be getting any notifications as the notification request has been removed
+ const TFsNotification* notification = notify->NextNotification();
+ cancelNotificationsWatcherTest(notification == NULL);
+
+ delete notify;
+ fs.Close();
+ cancelNotificationsWatcherTest.Printf(_L("TestCancelNotificationWatcher(%d) - Complete\n"),threadId);
+ cancelNotificationsWatcherTest.End();
+ cancelNotificationsWatcherTest.Close();
+ delete cleanup;
+ return KErrNone;
+ }
+
+
+/*
+ * TestCancelNotificationL - Watcher adds and cancels notification request.
+ */
+TInt TestCancelNotificationL()
+ {
+ test.Next(_L("TestCancelNotification"));
+ RFs fs;
+ fs.Connect();
+
+ SThreadPackageDualSemaphore package;
+ _LIT(KFileName,"cancel.create");
+ package.iFileName = KFileName;
+
+ User::LeaveIfError(package.iBarrier.CreateLocal(0));
+ User::LeaveIfError(package.iBarrier2.CreateLocal(0));
+ RThread watcher;
+ RThread doer;
+
+ TInt r = watcher.Create(_L("TestCancelNotification-WatcherThread"),TestCancelNotificationWatcher,KDefaultStackSize*2,KMinHeapSize,KMaxHeapSize,&package);
+ test(r == KErrNone);
+ r = doer.Create(_L("TestCancelNotification-DoerThread"),SimpleSingleNotificationTFDoer,KDefaultStackSize*2,KMinHeapSize,KMaxHeapSize,&package);
+ test(r == KErrNone);
+ test.Printf(_L("TestCancelNotificationL - Watcher.Resume()"));
+ watcher.Resume();
+ test.Printf(_L("TestCancelNotificationL - Waiting on package.iBarrier.Wait()"));
+ package.iBarrier.Wait(); //W1 - Wait until Watcher has created CFsNotify
+ test.Printf(_L("TestCancelNotificationL -Doer Resume"));
+ TRequestStatus status;
+ doer.Logon(status);
+ doer.Resume();
+
+ test.Next(_L("TestCancelNotification - Wait for doer thread death"));
+ User::WaitForRequest(status);
+ test(doer.ExitReason()==KErrNone);
+
+ package.iBarrier2.Signal(); //S1
+
+ test.Next(_L("TestCancelNotification - Wait for watcher thread death"));
+ watcher.Logon(status);
+
+ RTimer tim;
+ r = tim.CreateLocal();
+ test(r==KErrNone);
+
+ TRequestStatus timStatus;
+ TTimeIntervalMicroSeconds32 time = 10000000; //10 seconds
+ tim.After(timStatus,time);
+
+ User::WaitForRequest(status,timStatus);
+ test(status!=KRequestPending);
+ test(watcher.ExitReason()==KErrNone);
+
+ CLOSE_AND_WAIT(doer);
+ CLOSE_AND_WAIT(watcher);
+
+ package.iBarrier.Close();
+ package.iBarrier2.Close();
+ fs.Close();
+ tim.Close();
+ return KErrNone;
+ }
+
+/*
+ * Test that if we close the session
+ * before closing the subsession (deleting CFsNotify)
+ * that everything is A-Ok.
+ */
+TInt TestSessionCloseTF(TAny* aTestCase)
+ {
+ CTrapCleanup* cleanup;
+ cleanup = CTrapCleanup::New();
+
+ TRAPD(r,
+ RFs fs;
+ fs.Connect();
+ RDebug::Printf("TestSessionClose\n");
+
+ SThreadPackage2 package = *(SThreadPackage2*)aTestCase;
+ package.iBarrier.Signal();
+
+ switch(package.iTestCase)
+ {
+ case 1:
+ {
+ RDebug::Printf("TestSessionCloseTF - Case 1 - NewL\n");
+ CFsNotify* notify = CFsNotify::NewL(fs,KMinNotificationBufferSize);
+ User::LeaveIfNull(notify);
+
+ RDebug::Printf("TestSessionCloseTF - Case 1 - Fs.Close\n");
+ fs.Close();
+
+ TBuf<45> path;
+ path.Append((TChar)gDriveToTest);
+ path.Append(_L(":\\F32-TST\\T_NOTIFIER\\"));
+
+ TBuf<20> filename;
+ filename.Append(_L("session.close"));
+
+ CleanupStack::PushL(notify);
+
+ RDebug::Printf("TestSessionCloseTF - Case 1 - Add Notification - Panic Expected\n");
+ r = notify->AddNotification((TUint)TFsNotification::ECreate,path,filename);
+ User::LeaveIfError(r);
+
+ RDebug::Printf("TestSessionCloseTF - Case 1 - After Session Close\n");
+ fs.Close();
+ CleanupStack::Pop(notify);
+
+ RDebug::Printf("TestSessionCloseTF - Case 1 - After Delete Notify\n");
+ delete notify;
+ break;
+ }
+ case 2:
+ {
+ RDebug::Printf("TestSessionCloseTF - Case 2 - NewL\n");
+ CFsNotify* notify = CFsNotify::NewL(fs,KMinNotificationBufferSize);
+ User::LeaveIfNull(notify);
+
+ TBuf<45> path;
+ path.Append((TChar)gDriveToTest);
+ path.Append(_L(":\\F32-TST\\T_NOTIFIER\\"));
+ TBuf<20> filename;
+ filename.Append(_L("session.close"));
+
+ RDebug::Printf("TestSessionCloseTF - Case 2 - Add Notification\n");
+ r = notify->AddNotification((TUint)TFsNotification::ECreate,path,filename);
+ test(r==KErrNone);
+
+ RDebug::Printf("TestSessionCloseTF - Case 2 - Fs.Close\n");
+ fs.Close();
+
+ CleanupStack::PushL(notify);
+ TRequestStatus status;
+ RDebug::Printf("TestSessionCloseTF - Case 2 - Request Notification - Panic Expected\n");
+ r = notify->RequestNotifications(status);
+ CleanupStack::Pop(notify);
+
+ RDebug::Printf("TestSessionCloseTF - Case 2 - After Delete Notify\n");
+ delete notify;
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ );
+ delete cleanup;
+ return r;
+ }
+
+/*
+ * Test that if we close the session
+ * before closing the subsession (deleting CFsNotify)
+ * that everything is A-Ok.
+ */
+void TestSessionClose(TInt aTestCase)
+ {
+ RSemaphore sem;
+ User::LeaveIfError(sem.CreateLocal(0));
+
+ SThreadPackage2 package;
+ package.iTestCase = aTestCase;
+ package.iBarrier = sem;
+
+ RThread thread;
+ thread.Create(_L("TestSessionClose"),TestSessionCloseTF,KDefaultStackSize,KMinHeapSize,KMaxHeapSize,&package);
+
+ thread.Resume();
+ sem.Wait();
+
+ TRequestStatus status;
+ thread.Logon(status);
+ User::WaitForRequest(status);
+ test.Printf(_L("Kern-Exec 0 is EXPECTED\n"));
+ TInt err = thread.ExitReason();
+ test(err == KErrNone);
+ TExitType et = thread.ExitType();
+ test(et == EExitPanic);
+ CLOSE_AND_WAIT(thread);
+ sem.Close();
+ }
+
+const TInt KNotificationOverflowIterationLimit = 7;
+
+/*
+ * Does stuff for TestOverflowL
+ * Synchronises such that watchers have seen 1 change.
+ * Then fills their buffers up to KNotificationOverflowIterationLimit.
+ *
+ */
+TInt TestOverflowDoerTF(TAny* aAny)
+ {
+ RFs fs;
+ fs.Connect();
+
+ SThreadPackage& package = *(SThreadPackage*) aAny;
+
+ TBuf<45> path;
+ path.Append((TChar)gDriveToTest);
+ path.Append(_L(":\\F32-TST\\T_NOTIFIER\\"));
+ path.Append(package.iFileName);
+
+ fs.MkDirAll(path);
+
+ RFile file;
+ TInt r = file.Replace(fs,path,EFileWrite);
+ User::LeaveIfError(r);
+
+ //Perform first set size.
+ r = file.SetSize(1);
+ User::LeaveIfError(r);
+
+ //Wait until both watchers have received this change.
+ package.iBarrier.Wait();
+
+ for(TInt i = 0; i< KNotificationOverflowIterationLimit; i++)
+ {
+ file.SetSize(i);
+ }
+
+ file.Close();
+ fs.Close();
+ return KErrNone;
+ }
+
+/*
+ * Thread function used as part of TestOverflowL
+ * Counts the number of notifications and ensures it the correct number before overflow is received#
+ */
+TInt TestOverflowWatcher1TF(TAny* aAny)
+ {
+ CTrapCleanup* cleanup;
+ cleanup = CTrapCleanup::New();
+
+ RTest overflowTest(_L("TestOverflowWatcher1TF"));
+ overflowTest.Start(_L("TestOverflowWatcher1TF"));
+
+ SThreadPackage& package = *(SThreadPackage*) aAny;
+ RFs fs;
+ fs.Connect();
+ TBuf<45> path;
+ TBuf<20> filename;
+ path.Append((TChar)gDriveToTest);
+ path.Append(_L(":\\F32-TST\\T_NOTIFIER\\"));
+ filename.Append(package.iFileName);
+
+ TRequestStatus status;
+ CFsNotify* notify = NULL;
+
+ //This notification's size is 80.
+ //80*7 = 560.
+ // -4 means we should get 6 notifications
+ //Except the first one will still be in the buffer
+ // (as we've not called RequestNotification yet) so we'll only actually get 5.
+ TRAPD(r, notify = CFsNotify::NewL(fs,(80*7)-4));
+ test(r == KErrNone);
+ User::LeaveIfNull(notify);
+ notify->AddNotification(TFsNotification::EFileChange,path,filename);
+ notify->RequestNotifications(status);
+
+ //Signal that we are ready for doer to start (W1)
+ package.iBarrier.Signal();
+
+ //We wait for the 1 notification (doer only does 1 at first)
+ User::WaitForRequest(status);
+
+ overflowTest.Next(_L("Overflow- Get First Notification (Start framework)"));
+ const TFsNotification *notification = notify->NextNotification();
+
+ TFsNotification::TFsNotificationType type = notification->NotificationType();
+ overflowTest.Printf(_L("Overflow - First Notification Type = %d\n"),type);
+
+ //Signal the test thread (W2)
+ package.iBarrier.Signal();
+ //Wait for Signal to continue (W3);
+ package.iBarrier.Wait();
+
+ notify->RequestNotifications(status);
+ User::WaitForRequest(status);
+
+ TInt count = 0;
+ overflowTest.Next(_L("Overflow- Get the rest of the notifications"));
+ notification = notify->NextNotification();
+ while(notification != NULL)
+ {
+
+ type = notification->NotificationType();
+ overflowTest.Printf(_L("Overflow - NotificationType = %d\n"),type);
+ if(type & TFsNotification::EOverflow)
+ {
+ delete notify;
+ fs.Close();
+ overflowTest.Printf(_L("Overflow +- Count = %d\n"),count);
+ overflowTest.End();
+ overflowTest.Close();
+ return count;
+ }
+
+ notification = notify->NextNotification();
+ count++;
+ }
+ overflowTest.Printf(_L("Overflow -- Count = %d\n"),count);
+
+ overflowTest.End();
+ overflowTest.Close();
+ delete notify;
+ delete cleanup;
+ fs.Close();
+ return -1;
+ }
+
+
+/*
+ * Overflow test
+ * As some of the tests above assume sucess if they receive an overflow
+ * we need to ensure that overflow works properly!
+ */
+TInt TestOverflowL()
+ {
+ /*
+ * The scheme used is as follows:
+ * 1 Doer thread which is setting the size of a file, over and over.
+ * 1 watcher thread.
+ *
+ * The doer thread does 1 operation then waits on a signal.
+ * The watcher thread requests notification and receives 1 notification.
+ * It then signals the Doer thread.
+ *
+ * The doer thread continues doing setsize until the number of notifications
+ * should have overflowed.
+ *
+ * The watcher Waits for a signal from doer (that all of the notifications have been sent).
+ * The watcher's last notification should be an overflow
+ */
+ test.Next(_L("TestOverflow"));
+ RFs fs;
+ TInt r = fs.Connect();
+ test(r == KErrNone);
+ _LIT(KFileName,"over.flow");
+ SThreadPackage doerPkg;
+ doerPkg.iFileName = KFileName;
+
+ SThreadPackage watcher1Pkg;
+ watcher1Pkg.iFileName = KFileName;
+
+ User::LeaveIfError(doerPkg.iBarrier.CreateLocal(0));
+ User::LeaveIfError(watcher1Pkg.iBarrier.CreateLocal(0));
+ RThread watcher1;
+ RThread doer;
+ watcher1.Create(_L("TestOverflowWatcher1Thread"),TestOverflowWatcher1TF,KDefaultStackSize,KMinHeapSize,KMaxHeapSize,&watcher1Pkg);
+ doer.Create(_L("TestOverflowDoerThread"),TestOverflowDoerTF,KDefaultStackSize,KMinHeapSize,KMaxHeapSize,&doerPkg);
+ watcher1.Resume();
+
+ //Wait until Request has been requested. (W1)
+ watcher1Pkg.iBarrier.Wait();
+
+ doer.Resume();
+
+ //Wait till watcher has received first notification (W2)
+ watcher1Pkg.iBarrier.Wait();
+
+ //Signal the doer that it is free to continue
+ //doing the rest of the operations
+ doerPkg.iBarrier.Signal();
+
+ test.Next(_L("TestOverflow - Wait for doer thread death"));
+ TRequestStatus status;
+ doer.Logon(status);
+ User::WaitForRequest(status);
+ test(doer.ExitReason()==KErrNone);
+ CLOSE_AND_WAIT(doer);
+
+ //Wait until doer has finished doing notifications
+ //thus the watcher should receive an overflow
+ // (W3)
+ watcher1Pkg.iBarrier.Signal();
+
+ RTimer tim;
+ r = tim.CreateLocal();
+ test(r==KErrNone);
+ TRequestStatus timStatus;
+
+ test.Next(_L("TestOverflow - Wait for watcher1 thread death"));
+ TTimeIntervalMicroSeconds32 interval = 10000000; //10 seconds
+ tim.After(timStatus,interval);
+ watcher1.Logon(status);
+ User::WaitForRequest(status,timStatus);
+ test(status != KRequestPending);
+ /*
+ * The number of notifications returned here should be 5.
+ * This is because :
+ *
+ * The first notification means that the buffer has lost 80 (the size of this
+ * particular notification). Even though the client has read it becase they've not called
+ * RequestNotification the server doesn't know that yet so that's why it's 5 not 6.
+ *
+ * That leaves 556 - 80. Which means only 5 notifications will fit.
+ */
+ TInt count = watcher1.ExitReason();
+ test(count==5);
+
+ CLOSE_AND_WAIT(watcher1);
+ watcher1Pkg.iBarrier.Close();
+ doerPkg.iBarrier.Close();
+ fs.Close();
+ tim.Close();
+ return KErrNone;
+ }
+
+/*
+ * Does stuff for TestPostOverflowL
+ * Synchronises such that watchers have seen 1 change.
+ * Then fills their buffers up to KNotificationOverflowIterationLimit.
+ * Then continues to request changes and akes sure that it gets 3 non-overflow notifications
+ * For DEF140387.
+ */
+TInt TestPostOverflowDoerTF(TAny* aAny)
+ {
+ RFs fs;
+ fs.Connect();
+
+ SThreadPackage& package = *(SThreadPackage*) aAny;
+
+ TBuf<45> path;
+ path.Append((TChar)gDriveToTest);
+ path.Append(_L(":\\F32-TST\\T_NOTIFIER\\"));
+ path.Append(package.iFileName);
+
+ fs.MkDirAll(path);
+
+ RFile file;
+ TInt r = file.Replace(fs,path,EFileWrite);
+ User::LeaveIfError(r);
+
+ //Perform first set size.
+ r = file.SetSize(1);
+ User::LeaveIfError(r);
+
+ //Wait until both watchers have received this change.
+ //D-W-1
+ package.iBarrier.Wait();
+
+ for(TInt i = 0; i< KNotificationOverflowIterationLimit; i++)
+ {
+ file.SetSize(i);
+ }
+
+ file.Close();
+ fs.Close();
+ return KErrNone;
+ }
+
+TInt HandlePostOverflow(SThreadPackage& aPackage, CFsNotify* aNotify)
+ {
+ TRequestStatus status;
+ TInt r = aNotify->RequestNotifications(status);
+ test(r == KErrNone);
+ //Signal that overflow has been found (W4)
+ aPackage.iBarrier.Signal();
+
+ User::WaitForRequest(status);
+
+ const TFsNotification* notification = NULL;
+ TInt count = 1;
+
+ notification = aNotify->NextNotification();
+ test(notification != NULL);
+
+ //3 set sizes will be done (Sx)
+ aPackage.iBarrier.Wait();
+
+ while(count < 3)
+ {
+ TUint type = notification->NotificationType();
+ if(type & TFsNotification::EOverflow)
+ {
+ return KErrOverflow;
+ }
+ notification = aNotify->NextNotification();
+ if(notification == NULL)
+ {
+ r = aNotify->RequestNotifications(status);
+ test(r == KErrNone);
+ User::WaitForRequest(status);
+ notification = aNotify->NextNotification();
+ }
+ test(notification != NULL);
+ count++;
+ }
+ return count;
+ }
+
+
+/*
+ * Thread function used as part of TestOverflowL
+ * Counts the number of notifications and ensures it the correct number before overflow is received#
+ */
+TInt TestPostOverflowWatcher1TF(TAny* aAny)
+ {
+ CTrapCleanup* cleanup;
+ cleanup = CTrapCleanup::New();
+
+ RTest overflowTest(_L("TestOverflowWatcher1TF"));
+ overflowTest.Start(_L("TestOverflowWatcher1TF"));
+
+ SThreadPackage& package = *(SThreadPackage*) aAny;
+ RFs fs;
+ fs.Connect();
+ TBuf<45> path;
+ TBuf<20> filename;
+ path.Append((TChar)gDriveToTest);
+ path.Append(_L(":\\F32-TST\\T_NOTIFIER\\"));
+ filename.Append(package.iFileName);
+
+ TRequestStatus status;
+ CFsNotify* notify = NULL;
+
+ //This notification's size is 80.
+ //80*7 = 560.
+ // -4 means we should get 6 notifications
+ //Except the first one will still be in the buffer
+ // (as we've not called RequestNotification yet) so we'll only actually get 5.
+ TRAPD(r, notify = CFsNotify::NewL(fs,(80*7)-4));
+ test(r == KErrNone);
+ User::LeaveIfNull(notify);
+ notify->AddNotification(TFsNotification::EFileChange,path,filename);
+ notify->RequestNotifications(status);
+
+ //Signal that we are ready for doer to start (W1)
+ package.iBarrier.Signal();
+
+ //We wait for the 1 notification (doer only does 1 at first)
+ User::WaitForRequest(status);
+
+ overflowTest.Next(_L("Overflow- Get First Notification (Start framework)"));
+ const TFsNotification *notification = notify->NextNotification();
+
+ TFsNotification::TFsNotificationType type = notification->NotificationType();
+ overflowTest.Printf(_L("Overflow - First Notification Type = %d\n"),type);
+
+ //Signal the test thread (W2)
+ package.iBarrier.Signal();
+ //Wait for Signal to continue (W3);
+ package.iBarrier.Wait();
+
+ notify->RequestNotifications(status);
+ User::WaitForRequest(status);
+
+ TInt handlePostOverflow = 0;
+ TInt count = 0;
+ overflowTest.Next(_L("Overflow- Get the rest of the notifications"));
+ notification = notify->NextNotification();
+ while(notification != NULL)
+ {
+
+ type = notification->NotificationType();
+ overflowTest.Printf(_L("Overflow - NotificationType = %d\n"),type);
+ if(type & TFsNotification::EOverflow)
+ {
+ overflowTest.Printf(_L("Overflow +- Count = %d\n"),count);
+ if(handlePostOverflow)
+ {
+ count = HandlePostOverflow(package,notify);
+ }
+ delete notify;
+ fs.Close();
+ overflowTest.End();
+ overflowTest.Close();
+ return count;
+ }
+ notification = notify->NextNotification();
+ count++;
+
+ if(count==5)
+ handlePostOverflow = 1;
+ }
+ overflowTest.Printf(_L("Overflow -- Count = %d\n"),count);
+
+ overflowTest.End();
+ overflowTest.Close();
+ delete notify;
+ delete cleanup;
+ fs.Close();
+ return -1;
+ }
+
+
+TInt TestPostOverflowNotifications()
+ {
+ test.Next(_L("TestPostOverflowNotifications"));
+ RFs fs;
+ TInt r = fs.Connect();
+ test(r == KErrNone);
+ _LIT(KFileName,"post.over");
+ SThreadPackage doerPkg;
+ doerPkg.iFileName = KFileName;
+
+ SThreadPackage watcher1Pkg;
+ watcher1Pkg.iFileName = KFileName;
+
+ User::LeaveIfError(doerPkg.iBarrier.CreateLocal(0));
+ User::LeaveIfError(watcher1Pkg.iBarrier.CreateLocal(0));
+ RThread watcher1;
+ RThread doer;
+ watcher1.Create(_L("TestPostOverflowWatcher1Thread"),TestPostOverflowWatcher1TF,KDefaultStackSize,KMinHeapSize,KMaxHeapSize,&watcher1Pkg);
+ doer.Create(_L("TestPostOverflowDoerThread"),TestPostOverflowDoerTF,KDefaultStackSize,KMinHeapSize,KMaxHeapSize,&doerPkg);
+ watcher1.Resume();
+
+ //Wait until Request has been requested. (W1)
+ watcher1Pkg.iBarrier.Wait();
+
+ doer.Resume();
+
+ //Wait till watcher has received first notification (W2)
+ watcher1Pkg.iBarrier.Wait();
+
+ //Signal the doer that it is free to continue
+ //doing the rest of the operations (D-W-1)
+ doerPkg.iBarrier.Signal();
+
+ test.Next(_L("TestOverflow - Wait for doer thread death"));
+ TRequestStatus status;
+ doer.Logon(status);
+ User::WaitForRequest(status);
+ test(doer.ExitReason()==KErrNone);
+ CLOSE_AND_WAIT(doer);
+
+ //Wait until doer has finished doing notifications
+ //thus the watcher should receive an overflow
+ // (W3)
+ watcher1Pkg.iBarrier.Signal();
+
+
+ //wait for the watcher to have processed the first overflow
+ //and to have requested notification.
+ //Then we will perform some actions here
+ // The watcher will wait on the semaphore until we are doing
+ // doing all the operations we want to do
+ // then it should process next notification
+ watcher1Pkg.iBarrier.Wait(); //W4
+
+ TBuf<45> path;
+ path.Append((TChar)gDriveToTest);
+ path.Append(_L(":\\F32-TST\\T_NOTIFIER\\"));
+ path.Append(watcher1Pkg.iFileName);
+ RFile file;
+ r = file.Open(fs,path,EFileWrite);
+ test(r==KErrNone);
+
+ r = file.SetSize(1);
+ test(r==KErrNone);
+ r = file.SetSize(2);
+ test(r==KErrNone);
+ r = file.SetSize(3);
+ test(r==KErrNone);
+ file.Close();
+
+ watcher1Pkg.iBarrier.Signal(); // Signal post operations complete (Sx)
+
+ RTimer tim;
+ r = tim.CreateLocal();
+ test(r==KErrNone);
+ TRequestStatus timStatus;
+
+ test.Next(_L("TestOverflow - Wait for watcher1 thread death"));
+ TTimeIntervalMicroSeconds32 interval = 10000000; //10 seconds
+ tim.After(timStatus,interval);
+ watcher1.Logon(status);
+ User::WaitForRequest(status,timStatus);
+ test(status != KRequestPending);
+ /*
+ * The number of notifications returned here should be 3.
+ * This is because :
+ *
+ * The first notification means that the buffer has lost 80 (the size of this
+ * particular notification). Even though the client has read it becase they've not called
+ * RequestNotification the server doesn't know that yet so that's why it's 5 not 6.
+ *
+ * That leaves 556 - 80. Which means only 5 notifications will fit.
+ *
+ * Then overflow occurs.
+ *
+ * Then count is reset and 3 more operations are performed.
+ */
+ TInt count = watcher1.ExitReason();
+ test(count==3);
+
+ CLOSE_AND_WAIT(watcher1);
+ watcher1Pkg.iBarrier.Close();
+ doerPkg.iBarrier.Close();
+ fs.Close();
+ tim.Close();
+ return KErrNone;
+ }
+
+/*
+ * Call AddNotification with a file without a path nor drive
+ */
+void TestNonDriveFilters()
+ {
+ test.Next(_L("TestNonDriveFilters"));
+ RFs fs;
+ TInt r = fs.Connect();
+ test(r==KErrNone);
+
+ TDriveList drives;
+ r = fs.DriveList(drives);
+ test(r==KErrNone);
+
+ CFsNotify* notify = NULL;
+ TRAP(r,notify= CFsNotify::NewL(fs,KMinNotificationBufferSize));
+
+ TBuf<20> testfile;
+ testfile.Append(_L("test.file"));
+
+ r = notify->AddNotification((TUint)TFsNotification::ECreate,_L(""),testfile);
+ test(r==KErrNone);
+
+ TRequestStatus status;
+ r = notify->RequestNotifications(status);
+ test(r==KErrNone);
+
+ TBuf<40> path;
+ path.Append((TChar)gDriveToTest);
+ path.Append(_L(":\\F32-TST\\T_NOTIFIER\\"));
+
+ TBuf<40> fullname;
+ fullname.Append(path);
+ fullname.Append(testfile);
+
+ RFile file;
+ r = fs.MkDirAll(path);
+ test(r==KErrNone || r==KErrAlreadyExists);
+ r = file.Replace(fs,fullname,EFileWrite);
+ test(r==KErrNone);
+ file.Close();
+
+ fs.Delete(fullname);
+
+ TChar testDrive = (TChar)gDriveToTest;
+ testDrive.UpperCase();
+
+ //Also create the file on another drive;
+ for(TInt i = 0; i < KMaxDrives; i++)
+ {
+ TChar drive = drives[i];
+ if(drive == testDrive)
+ continue;
+
+ if(drive)
+ {
+ TText16 drive16 = (TText16)(i+(TChar)'A');
+ fullname.operator [](0) = drive16;
+ break;
+ }
+ }
+
+ r = fs.MkDirAll(fullname);
+ test(r==KErrNone || r==KErrAlreadyExists);
+ r = file.Replace(fs,fullname,EFileWrite);
+ test(r==KErrNone);
+ file.Close();
+
+ RTimer timer1;
+ r = timer1.CreateLocal();
+ test(r == KErrNone);
+ TRequestStatus timeout;
+ TTimeIntervalMicroSeconds32 time = 10000000; //10 seconds
+ timer1.After(timeout,time);
+ User::WaitForRequest(timeout,status);
+ test(status.Int() != KRequestPending);
+ timer1.Cancel();
+ timer1.Close();
+
+ const TFsNotification* notification = notify->NextNotification();
+ test(notification != NULL);
+ TPtrC _path;
+ r = notification->Path(_path);
+ test(r==KErrNone);
+ TChar driveletter = _path[0];
+ driveletter.UpperCase();
+ test(driveletter == (TChar)gDriveToTest);
+
+ if(notification = notify->NextNotification(), notification==NULL)
+ {
+ TRequestStatus status2;
+ r = notify->RequestNotifications(status2);
+ test(r==KErrNone);
+
+ RTimer timer2;
+ r = timer2.CreateLocal();
+ test(r == KErrNone);
+ TRequestStatus timeout2;
+ TTimeIntervalMicroSeconds32 time2 = 10000000; //10 seconds
+ timer2.After(timeout2,time2);
+ User::WaitForRequest(timeout2,status2);
+ test(status2.Int() != KRequestPending);
+ timer2.Cancel();
+ timer2.Close();
+
+ notification = notify->NextNotification();
+ }
+ test(notification != NULL);
+ r = notification->Path(_path);
+ test(r==KErrNone);
+ driveletter = _path[0];
+ driveletter.UpperCase();
+ test(driveletter == (TChar)'C');
+
+ delete notify;
+ fs.Close();
+ }
+
+// Negative testing for directory without *
+// We receive no notifications for files changed under the directory
+void NegativeTestDirStar()
+ {
+ RFs fs;
+ TInt r = fs.Connect();
+ test(r==KErrNone);
+
+ CFsNotify* notify = NULL;
+ TRAP(r,notify= CFsNotify::NewL(fs,KMinNotificationBufferSize));
+
+ TBuf<40> path;
+ path.Append((TChar)gDriveToTest);
+ path.Append(_L(":\\F32-TST\\T_NOTIFIER\\"));
+ r = fs.MkDirAll(path);
+ test(r == KErrNone || r == KErrAlreadyExists);
+
+ r = notify->AddNotification((TUint)TFsNotification::ECreate,path,_L(""));
+ test(r==KErrNone);
+
+ TRequestStatus status;
+ r = notify->RequestNotifications(status);
+ test(r==KErrNone);
+
+ TBuf<40> filename;
+ filename.Append((TChar)gDriveToTest);
+ filename.Append(_L(":\\F32-TST\\T_NOTIFIER\\dir.star"));
+
+ RFile file;
+ r = file.Replace(fs,filename,EFileWrite);
+ test(r==KErrNone);
+ file.Close();
+
+ RTimer timer1;
+ r = timer1.CreateLocal();
+ test(r == KErrNone);
+ TRequestStatus timeout;
+ TTimeIntervalMicroSeconds32 time = 2000000; //2 seconds
+ timer1.After(timeout,time);
+ User::WaitForRequest(timeout,status);
+ test(status.Int() == KRequestPending);
+ timer1.Cancel();
+ timer1.Close();
+
+ const TFsNotification* notification = notify->NextNotification();
+ test(notification == NULL);
+
+ delete notify;
+ fs.Close();
+ }
+
+/*
+ * Negative Testing
+ */
+void NegativeTests()
+ {
+ test.Next(_L("Negative Tests"));
+ //1
+ test.Printf(_L("NegativeTests() A\n"));
+ RFs fs;
+ CFsNotify* notify = NULL;
+ TInt r = fs.Connect();
+ test(r == KErrNone);
+ TRAP(r,notify = CFsNotify::NewL(fs,0));
+ test(notify != NULL);
+ delete notify;
+ notify = NULL;
+
+ //2
+ test.Printf(_L("NegativeTests() B\n"));
+ TRAP(r,notify = CFsNotify::NewL(fs,-1));
+ test(notify != NULL);
+ delete notify;
+ notify = NULL;
+
+ test.Printf(_L("NegativeTests() C\n"));
+ TRAP(r,notify = CFsNotify::NewL(fs,KMaxTInt));
+ test(r==KErrArgument);
+ test(notify==NULL);
+
+ //3
+ test.Printf(_L("NegativeTests() D\n"));
+ TBuf<40> path;
+ path.Append((TChar)gDriveToTest);
+ path.Append(_L(":\\F32-TST\\T_NOTIFIER\\"));
+ TBuf<20> filename;
+ filename.Append(_L("file.txt"));
+ TRAP(r,notify = CFsNotify::NewL(fs,KMinNotificationBufferSize));
+ test(r==KErrNone);
+ test(notify!=NULL);
+ r = notify->AddNotification(0,path,filename);
+ test(r == KErrArgument);
+
+ test.Printf(_L("NegativeTests() E\n"));
+ r = notify->AddNotification((TUint)0x8000,path,filename); //invalid value
+ test(r == KErrArgument);
+
+ test.Printf(_L("NegativeTests() F\n"));
+ TBuf<40> invalidPath;
+ invalidPath.Append(_L("1:\\*"));
+ r = notify->AddNotification((TUint)TFsNotification::ECreate,invalidPath,filename);
+ test(r == KErrNotFound || r == KErrPathNotFound);
+
+ //4
+ test.Printf(_L("NegativeTests() G\n"));
+ TRequestStatus wrongStatus;
+ wrongStatus = KRequestPending;
+ r = notify->RequestNotifications(wrongStatus);
+ test(r == KErrInUse);
+
+ test.Printf(_L("NegativeTests() H\n"));
+ TRequestStatus status;
+ r = notify->RequestNotifications(status);
+ test(r==KErrNone);
+ r = notify->CancelNotifications(wrongStatus);
+ test(r == KErrInUse);
+
+ delete notify;
+ notify = NULL;
+ fs.Close();
+ }
+
+
+/*
+ * RPlugin devired.
+ * Doesn't actually do anything special.
+ * Can probably be deleted.
+ */
+class MyRPlugin : public RPlugin
+ {
+public:
+ void DoRequest(TInt aReqNo,TRequestStatus& aStatus) const;
+ void DoRequest(TInt aReqNo,TRequestStatus& aStatus,TDes8& a1) const;
+ void DoRequest(TInt aReqNo,TRequestStatus& aStatus,TDes8& a1,TDes8& a2) const;
+ TInt DoControl(TInt aFunction) const;
+ TInt DoControl(TInt aFunction,TDes8& a1) const;
+ TInt DoControl(TInt aFunction,TDes8& a1,TDes8& a2) const;
+ void DoCancel(TUint aReqMask) const;
+ };
+
+void MyRPlugin::DoRequest(TInt aReqNo,TRequestStatus& aStatus) const
+ {
+ RPlugin::DoRequest(aReqNo,aStatus);
+ }
+void MyRPlugin::DoRequest(TInt aReqNo,TRequestStatus& aStatus,TDes8& a1) const
+ {
+ RPlugin::DoRequest(aReqNo,aStatus,a1);
+ }
+void MyRPlugin::DoRequest(TInt aReqNo,TRequestStatus& aStatus,TDes8& a1,TDes8& a2) const
+ {
+ RPlugin::DoRequest(aReqNo,aStatus,a1,a2);
+ }
+TInt MyRPlugin::DoControl(TInt aFunction) const
+ {
+ return RPlugin::DoControl(aFunction);
+ }
+TInt MyRPlugin::DoControl(TInt aFunction,TDes8& a1) const
+ {
+ return RPlugin::DoControl(aFunction,a1);
+ }
+TInt MyRPlugin::DoControl(TInt aFunction,TDes8& a1,TDes8& a2) const
+ {
+ return RPlugin::DoControl(aFunction,a1,a2);
+ }
+void MyRPlugin::DoCancel(TUint aReqMask) const
+ {
+ RPlugin::DoCancel(aReqMask);
+ }
+
+/*
+ * This tests that when file server plugins perform operations that
+ * the framework doesn't notify about them
+ */
+TInt TestNotificationsWithFServPlugins()
+ {
+ TInt r = TheFs.AddPlugin(KNotifyPluginFileName);
+ test(r==KErrNone || r==KErrAlreadyExists);
+ r = TheFs.MountPlugin(KNotifyPluginName,(TUint)gDriveToTest.GetUpperCase() - 65);
+ if (r == KErrNotSupported)
+ {
+ test.Printf(_L("Plugins are not supported on pagable drives.\nSkipping test.\n"));
+ safe_test(test,r,__LINE__,(TText*)Expand("t_notifier.cpp"));
+ }
+
+ MyRPlugin rplugin;
+ TPckgBuf<TChar> drivePckg(gDriveToTest);
+
+ test.Next(_L("Open RPlugin connection for NotifyPlugin"));
+ r = rplugin.Open(TheFs,KNotifyPos);
+ safe_test(test,r,__LINE__,(TText*)Expand("t_notify_plugin.cpp"));
+
+ test.Next(_L("Send drive letter to test down to plugin"));
+ r = rplugin.DoControl(KPluginSetDrive,drivePckg);
+ safe_test(test,r,__LINE__,(TText*)Expand("t_notify_plugin.cpp"));
+ rplugin.Close();
+
+ r = SimpleCreateTestL();
+ safe_test(test,r,__LINE__,(TText*)Expand("t_notifier.cpp"));
+
+ DismountPlugin();
+ return KErrNone;
+ }
+
+/*
+ * This test is testing the use cases
+ * and for negative testing of SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
+ *
+ * Performance tests can be found in test t_notify_perf
+ */
+void CallTestsL()
+ {
+ CTrapCleanup* cleanup;
+ cleanup = CTrapCleanup::New();
+
+ globalDriveNum = gDriveToTest - (TChar)'A';
+
+ PrintLine();
+ test.Start(_L("T_NOTIFIER Test Start"));
+ TInt r = KErrNone;
+
+ //=========================================================================================
+ //! @SYMTestCaseID PBASE-T_NOTIFY-2443
+ //! @SYMTestType CIT
+ //! @SYMREQ PREQ1847
+ //! @SYMTestCaseDesc Simple Tests/User Heap Tests
+ //! @SYMTestStatus Implemented
+ //=========================================================================================
+ //
+ // 1. Create and delete many CFsNotify objects
+ //
+ PrintLine();
+ test.Next(_L("CFsNotify Creation and Delete Tests"));
+ //Creates and Deletes 1 CFsNotify
+ __UHEAP_MARK;
+ r = TestNewDeleteCFsNotify(1);
+ __UHEAP_MARKEND;
+ test(r==KErrNone);
+ //Creates and Deletes 50 CFsNotifys
+ __UHEAP_MARK;
+ r = TestNewDeleteCFsNotify(50);
+ __UHEAP_MARKEND;
+ test(r==KErrNone);
+ test.Printf(_L("------- End of User Heap Tests ---------------------------------------\n"));
+ //
+ // 2. Add notification for creating a file
+ // Create that file
+ //
+ PrintLine();
+ __UHEAP_MARK;
+ r = SimpleCreateTestL();
+ __UHEAP_MARKEND;
+ test(r==KErrNone);
+ test.Printf(_L("------- End of CFsNotify Creation and Delete Tests -------------------\n"));
+ //
+ // 3. Add notification at the root of a drive
+ // Create a file in that drive
+ //
+ PrintLine();
+ TestRootDriveNotifications();
+ test.Printf(_L("------- End of RootDriveNotifications Test ---------------------------\n"));
+ //
+ // 4. Add notification for a filename without a drive
+ // Create that file in the current drive
+ // Create that file in another drive
+ //
+ PrintLine();
+ TestNonDriveFilters();
+ test.Printf(_L("------- End of TestNonDriveFilters Test ------------------------------\n"));
+ //
+ // 5. Add notifications for 2 file creations
+ // Create 2 clients
+ // The clients create a file each
+ //
+ PrintLine();
+ __UHEAP_MARK;
+ r = TestTwoDoersL();
+ __UHEAP_MARKEND;
+ test(r==KErrNone);
+ test.Printf(_L("------- End of TwoDoers Test -----------------------------------------\n"));
+ //
+ // 6. Create 2 file server sessions
+ // Add a notification on each session for the same specific file creation
+ // Create that file
+ //
+ PrintLine();
+ __UHEAP_MARK;
+ r = TestTwoWatchersL();
+ __UHEAP_MARKEND;
+ test(r==KErrNone);
+ test.Printf(_L("------- End of TwoWatchers Test --------------------------------------\n"));
+ //
+ // 7. Create 2 file server sessions and 2 clients
+ // Add a notification on each session for different file creations
+ // Clients create a file each
+ //
+ PrintLine();
+ __UHEAP_MARK;
+ r = TestTwoWatchersTwoDoersL();
+ __UHEAP_MARKEND;
+ test(r==KErrNone);
+ test.Printf(_L("------- End of TwoWatchersTwoDoers Test ------------------------------\n"));
+ //
+ // 8. Add notification for a specific file creation
+ // Cancel the notification request
+ // Create that file
+ //
+ PrintLine();
+ __UHEAP_MARK;
+ r = TestCancelNotificationL();
+ __UHEAP_MARKEND;
+ test(r==KErrNone);
+ test.Printf(_L("------- End of CancelNotification Test -------------------------------\n"));
+ //
+ // 9. Create 2 file server sessions
+ // Add a notification on each session for the same specific file creation
+ // Delete the first notification
+ // Create that file
+ //
+ PrintLine();
+ test.Next(_L("TestClientRemoval"));
+ __UHEAP_MARK;
+ r = TestClientRemovalL();
+ __UHEAP_MARKEND;
+ test(r==KErrNone);
+ test.Printf(_L("------- End of TestClientRemoval Test --------------------------------\n"));
+ //
+ // 10. Create a CFsNotify object
+ // Close the session before closing the subsession
+ // Add notification and request notifications
+ //
+ PrintLine();
+ __UHEAP_MARK;
+ // Close session after creating the object
+ TestSessionClose(1);
+ __UHEAP_MARKEND;
+ __UHEAP_MARK;
+ // Close session after adding the notification
+ TestSessionClose(2);
+ __UHEAP_MARKEND;
+ test.Printf(_L("------- End of TestSessionClose Test ---------------------------------\n"));
+
+
+ //=========================================================================================
+ //! @SYMTestCaseID PBASE-T_NOTIFY-2444
+ //! @SYMTestType UT
+ //! @SYMREQ PREQ1847
+ //! @SYMTestCaseDesc File/Directory Create and Replace – Single File Server Session
+ //! @SYMTestStatus Implemented
+ //!
+ //! TFsNotificationType ECreate
+ //=========================================================================================
+ //
+ // RFile::Create
+ // 1. Add notification for a specific file creation
+ // Create that file
+ //
+ PrintLine();
+ test.Next(_L("EFileCreate Tests"));
+ _LIT(KFilename3,"file.create");
+ r = TestMultipleNotificationsL(_L(""),KFilename3,5,5,t_notification::EFileCreate,TFsNotification::ECreate,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ test.Printf(_L("------- End of EFileCreate Tests -------------------------------------\n"));
+ //
+ // RFs::MkDir
+ // 2. Add notification for a specific directory creation
+ // Create that directory
+ //
+ PrintLine();
+ test.Next(_L("EFsMkDir Test"));
+ _LIT(KDirName1,"dirCreate\\");
+ r = TestMultipleNotificationsL(KDirName1,_L(""),1,1,t_notification::EFsMkDir,TFsNotification::ECreate,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ test.Printf(_L("------- End of EFsMkDir Test -----------------------------------------\n"));
+ //
+ // RFile::Replace
+ // 3. Add notification for a specific file creation
+ // Replace that file
+ //
+ PrintLine();
+ test.Next(_L("EFileReplace Test"));
+ r = TestMultipleNotificationsL(_L(""),KFilename3,1,1,t_notification::EFileReplace,TFsNotification::ECreate,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ test.Printf(_L("------- End of EFileReplace Test -------------------------------------\n"));
+ //
+ // 4. Add notification for a specific file creation
+ // Remove that notification
+ // Create that file
+ //
+ PrintLine();
+ __UHEAP_MARK;
+ r = TestAddRemoveNotificationL();
+ __UHEAP_MARKEND;
+ test(r==KErrNone);
+ test.Printf(_L("------- End of Add and Remove Notification Test ----------------------\n"));
+ //
+ // Wildcard Create Tests
+ // 5. Add notification for file creation using wildcard name
+ // Add notification for file/directory wildcard including subdirectories
+ // Create number of files and directories that match each notification
+ //
+ PrintLine();
+ test.Next(_L("Wildcard Create Tests"));
+ //
+ // Wildcard Name
+ _LIT(KWildcardName1,"*");
+ r = TestMultipleNotificationsL(_L(""),KWildcardName1,1,1,t_notification::EFileCreate,TFsNotification::ECreate,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ r = TestMultipleNotificationsL(KWildcardName1,KWildcardName1,1,1,t_notification::EFileCreate_subs,TFsNotification::ECreate,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ r = TestMultipleNotificationsL(KWildcardName1,KWildcardName1,1,1,t_notification::EFileCreate_subs_nowatch,TFsNotification::ECreate,KMinNotificationBufferSize,(TBool)ETrue,__LINE__);
+ test(r==KErrNone);
+ //
+ // Wildcard including Subdirectories
+ _LIT(KWildcardName2,"*\\");
+ r = TestMultipleNotificationsL(KWildcardName2,KWildcardName1,1,1,t_notification::EFileCreate,TFsNotification::ECreate,KMinNotificationBufferSize,(TBool)ETrue,__LINE__);
+ test(r==KErrNone);
+ r = TestMultipleNotificationsL(KWildcardName2,KWildcardName1,1,1,t_notification::EFileCreate_subs_nowatch,TFsNotification::ECreate,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ _LIT(KDirName2,"SubDir\\");
+ _LIT(KWildcardName3,"?");
+ r = TestMultipleNotificationsL(KDirName2,KWildcardName3,1,1,t_notification::EFileCreate_subs_nowatch,TFsNotification::ECreate,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ //
+ // Wildcard Type
+ _LIT(KWildcardName4,"*.*");
+ r = TestMultipleNotificationsL(_L(""),KWildcardName4,1,1,t_notification::EFileCreate_txt_nowatch,TFsNotification::ECreate,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ r = TestMultipleNotificationsL(_L(""),KWildcardName4,1,1,t_notification::EFileCreate_subs_nowatch,TFsNotification::ECreate,KMinNotificationBufferSize,(TBool)ETrue,__LINE__);
+ test(r==KErrNone);
+ //
+ // 6. Add notification for file creation for a specific type
+ // Create file with that type
+ // Create file with different type
+ //
+ _LIT(KWildcardName5,"*.txt");
+ r = TestMultipleNotificationsL(_L(""),KWildcardName5,1,1,t_notification::EFileCreate_txt,TFsNotification::ECreate,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ test.Printf(_L("------- End of Wildcard Create Tests ---------------------------------\n"));
+
+
+ //=============================================================================
+ //! @SYMTestCaseID PBASE-T_NOTIFY-2445
+ //! @SYMTestType UT
+ //! @SYMREQ PREQ1847
+ //! @SYMTestCaseDesc File Attribute Change – Single File Server Session
+ //! @SYMTestStatus Implemented
+ //
+ // TFsNotificationType EAttribute
+ //=============================================================================
+ //
+ // RFile::SetAtt, RFile::Set and RFs::SetEntry
+ // 1. Add notification for a specific file attribute change
+ // Change the attribute for that file
+ //
+ PrintLine();
+ test.Next(_L("Attribute Tests"));
+ _LIT(KFilename4,"file.setatts");
+ r = TestMultipleNotificationsL(_L(""),KFilename4,1,1,t_notification::EFileSetAtt,TFsNotification::EAttribute,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ r = TestMultipleNotificationsL(_L(""),KFilename4,1,1,t_notification::EFileSet,TFsNotification::EAttribute,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ r = TestMultipleNotificationsL(_L(""),KFilename4,1,1,t_notification::EFsSetEntry,TFsNotification::EAttribute,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ //
+ // Wildcard Attribute Test including subdirectories
+ // 2. Add notification for file attribute change using wildcard name
+ // Create number of files that match the notification
+ // Change attributes of some files
+ //
+ r = TestMultipleNotificationsL(KWildcardName2,_L("*"),3,3,t_notification::EFileSetAtt_subs,TFsNotification::EAttribute,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ test.Printf(_L("------- End of Attribute Tests ---------------------------------------\n"));
+
+
+ //=============================================================================
+ //! @SYMTestCaseID PBASE-T_NOTIFY-2446
+ //! @SYMTestType UT
+ //! @SYMREQ PREQ1847
+ //! @SYMTestCaseDesc File/Directory Rename – Single File Server Session
+ //! @SYMTestStatus Implemented
+ //
+ // TFsNotificationType ERename
+ //=============================================================================
+ //
+ // RFs::Replace, RFs::Rename and RFile::Rename
+ // 1. Add notification for a specific file rename change
+ // Rename that file
+ //
+ PrintLine();
+ test.Next(_L("Rename Tests"));
+ _LIT(KFilename5,"file.rename");
+ r = TestMultipleNotificationsL(_L(""),KFilename5,1,1,t_notification::EFsReplace,TFsNotification::ERename,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ r = TestMultipleNotificationsL(_L(""),KFilename5,1,1,t_notification::EFsRename,TFsNotification::ERename,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ r = TestMultipleNotificationsL(_L(""),KFilename5,1,1,t_notification::EFileRename,TFsNotification::ERename,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ //
+ // 2. Add notification for a specific directory rename
+ // Rename that directory
+ //
+ _LIT(KDirName3,"dirRename\\");
+ r = TestMultipleNotificationsL(KDirName3,_L(""),1,1,t_notification::EFsRename_dir,TFsNotification::ERename,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ //
+ // 3. Add notification for file rename using wildcard name
+ // Create file that match the notification
+ // Repeatedly rename the file
+ //
+ r = TestMultipleNotificationsL(_L(""),KWildcardName1,3,3,t_notification::EFileRename_wild,TFsNotification::ERename,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ test.Printf(_L("------- End of Rename Tests ------------------------------------------\n"));
+
+
+ //=============================================================================
+ //! @SYMTestCaseID PBASE-T_NOTIFY-2447
+ //! @SYMTestType UT
+ //! @SYMREQ PREQ1847
+ //! @SYMTestCaseDesc File/Directory Delete – Single File Server Session
+ //! @SYMTestStatus Implemented
+ //
+ // TFsNotificationType EDelete
+ //=============================================================================
+ //
+ // RFs::Delete
+ // 1. Add notification for a specific file delete
+ // Delete that file
+ //
+ PrintLine();
+ test.Next(_L("EFsDelete Test"));
+ _LIT(KFilename6,"file.delete");
+ r = TestMultipleNotificationsL(_L(""),KFilename6,1,1,t_notification::EFsDelete,TFsNotification::EDelete,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ //
+ // RFs::RmDir
+ // 2. Add notification for a specific directory delete
+ // Delete that directory
+ //
+ PrintLine();
+ test.Next(_L("EFsRmDir Tests"));
+ _LIT(KDirName4,"dirRemove\\");
+ r = TestMultipleNotificationsL(KDirName4,_L(""),1,1,t_notification::EFsRmDir,TFsNotification::EDelete,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ //
+ // This test should not receive any notifications because a non-empty directory cannot be removed
+ // 3. Add notification for specific directory delete
+ // Create files inside that directory
+ // Delete the directory
+ //
+ _LIT(KDirName5,"dirRmNonEmp\\");
+ r = TestMultipleNotificationsL(KDirName5,_L(""),1,1,t_notification::EFsRmDir_nonEmpty,TFsNotification::EDelete,KMinNotificationBufferSize,(TBool)ETrue,__LINE__);
+ test(r==KErrNone);
+ //
+ // Wildcard Name ("*")
+ // 4. Add notification for directory delete using wildcard name
+ // Create directory that match the notification
+ // Delete that directory
+ //
+ r = TestMultipleNotificationsL(KWildcardName1,_L(""),1,1,t_notification::EFsRmDir_wild,TFsNotification::EDelete,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ //
+ // Wildcard Type ("*.txt")
+ // Creates files with different types and should only receive notifications from "*.txt" file deletions
+ // 5. Add notification for file deletes using wildcard type
+ // Create number of files that match the notification
+ // Delete those files
+ //
+ r = TestMultipleNotificationsL(_L(""),KWildcardName4,3,3,t_notification::EFsDelete,TFsNotification::EDelete,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ test.Printf(_L("------- End of Delete Tests ------------------------------------------\n"));
+
+
+ //======================================================================
+ //! @SYMTestCaseID PBASE-T_NOTIFY-2448
+ //! @SYMTestType UT
+ //! @SYMREQ PREQ1847
+ //! @SYMTestCaseDesc File Change – Single File Server Session
+ //! @SYMTestStatus Implemented
+ //
+ // TFsNotificationType EFileChange
+ //======================================================================
+ //
+ // File Write
+ // If caching is enabled, notifications are received only when the file cache is flushed
+ // We flush everytime we do a write to ensure the tests work regardless of cache
+ //
+ // 1. Add notification for a specific file change
+ // Create the file
+ // Write to that file
+ //
+ PrintLine();
+ test.Next(_L("EFileWrite Tests"));
+ _LIT(KFilename7,"file.write");
+ __UHEAP_MARK;
+ r = TestMultipleNotificationsL(_L(""),KFilename7,7,7,t_notification::EFileWrite,TFsNotification::EFileChange,3*KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ __UHEAP_MARKEND;
+ test(r==KErrNone);
+ //
+ // 2. Add notification for a specific file change
+ // Write to the specified file a number of times without changing its size
+ //
+ // Four letters are written to a file, then the first letter in the file is replaced aIterations times
+ // aMaxNotifications = 1 + aIterations
+ //
+ r = TestMultipleNotificationsL(_L(""),KFilename7,3,4,t_notification::EFileWrite_samesize,TFsNotification::EFileChange,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ test.Printf(_L("------- End of EFileWrite Tests --------------------------------------\n"));
+ //
+ // 3. Add notification for a specific file change
+ // Write to that file asynchronously
+ //
+ PrintLine();
+ test.Next(_L("EFileWrite_async Tests"));
+ _LIT(KFilename8,"async.write");
+ __UHEAP_MARK;
+ r = TestMultipleNotificationsL(_L(""),KFilename8,4,4,t_notification::EFileWrite_async,TFsNotification::EFileChange,2*KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ __UHEAP_MARKEND;
+ test(r==KErrNone);
+ test.Printf(_L("------- End of EFileWrite_async Tests --------------------------------\n"));
+ //
+ // File Set Size
+ // 4. Add notification for a specific file change
+ // Both increase and decrease the file sizes a number of times
+ //
+ // The file size is increased aIterations times, and decreased (aIterations - 1) times
+ // aMaxNotifications = 2*aIterations - 1
+ //
+ PrintLine();
+ test.Next(_L("EFileSetSize Tests"));
+ _LIT(KFilename9,"file.setsize");
+ r = TestMultipleNotificationsL(_L(""),KFilename9,5,9,t_notification::EFileSetSize,TFsNotification::EFileChange,3*KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ test.Printf(_L("------- End of EFileSetSize Tests ------------------------------------\n"));
+
+
+ //
+ PrintLine();
+ test.Next(_L("CFileMan Tests"));
+ _LIT(KFilenameCFMan,"cf1le.man");
+ TUint notificationTypes = (TUint)TFsNotification::ECreate|TFsNotification::EFileChange|TFsNotification::EAttribute|TFsNotification::EDelete|TFsNotification::ERename;
+ r = TestMultipleNotificationsL(_L(""),KFilenameCFMan,1,5,t_notification::ECFileManMove,notificationTypes,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ test.Printf(_L("------- End of CFileMan Tests -------------------------------------\n"));
+
+
+ //========================================================================================
+ //! @SYMTestCaseID PBASE-T_NOTIFY-2449
+ //! @SYMTestType UT
+ //! @SYMREQ PREQ1847
+ //! @SYMTestCaseDesc File System Mounted/Dismounted, Media Card Removal/Insertion,
+ // RawDisk Write – Single File Server Session
+ //! @SYMTestStatus Implemented
+ //
+ // TFsNotificationType EMediaChange
+ //========================================================================================
+ //
+ // RFs::DismountFileSystem
+ // 1. Add notification for media change
+ // Dismount the file system
+ //
+ PrintLine();
+ test.Next(_L("Mount Tests"));
+ TFullName filesystemName;
+ r = TheFs.FileSystemName(filesystemName,globalDriveNum);
+ test(r==KErrNone);
+ r = TestMultipleNotificationsL(filesystemName,1,1,t_notification::EDismount,TFsNotification::EMediaChange,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ //
+ // RFs::MountFileSystem
+ // 2. Add notification for media change
+ // Mount the file system
+ //
+ r = TestMultipleNotificationsL(filesystemName,1,1,t_notification::EMount,TFsNotification::EMediaChange,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ //
+ // Repeatedly mount and dismount the file system
+ // 3. Add notification for media change
+ // Repeatedly dismount and mount the file system
+ //
+ // The file system is dismounted and mounted aIterations times
+ // aMaxNotifications = 2*aIterations
+ //
+ r = TestMultipleNotificationsL(filesystemName,5,10,t_notification::EMountDismount,TFsNotification::EMediaChange,3*KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ //
+ // RFs::MountFileSystemAndScan
+ // 4. Add notification for media change
+ // Mount and scan the file system
+ //
+ // The file system is dismounted and mounted aIterations times
+ // aMaxNotifications = 2*aIterations
+ //
+//#ifndef __WINS__
+// r = TestMultipleNotificationsL(filesystemName,1,2,t_notification::EMountScan,TFsNotification::EMediaChange,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+// test(r==KErrNone);
+//#endif
+ test.Printf(_L("------- End of Mount Tests -------------------------------------------\n"));
+ TDriveInfo drvInfo;
+ TInt driveNum;
+ TheFs.CharToDrive(gDriveToTest,driveNum);
+ r = TheFs.Drive(drvInfo,driveNum);
+ test (r == KErrNone);
+ TPtrC driveDes((TText*)&gDriveToTest,1);
+ //
+ // Manual Tests - Will only run on removable drives
+ //
+/* if(drvInfo.iDriveAtt & KDriveAttRemovable)
+ {
+ //
+ // 5. Add notification for media change
+ // Remove media card manually
+ //
+ PrintLine();
+ test.Next(_L("Media Card Removal/Insertion Tests"));
+ r = TestMultipleNotificationsL(driveDes,1,1,t_notification::EMediaCardRemoval,TFsNotification::EMediaChange,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ //
+ // 6. Add notification for media change
+ // Insert media card manually
+ //
+ r = TestMultipleNotificationsL(driveDes,1,1,t_notification::EMediaCardInsertion,TFsNotification::EMediaChange,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ test.Printf(_L("------- End of Media Card Removal/Insertion Tests --------------------\n"));
+ //
+ // We should receive an EMediaChange notification even though we did not register for it
+ // 7. Do not add notification for media change
+ // Remove and insert media card manually
+ //
+ PrintLine();
+ TestMediaCardNotificationWhenNotRegisteredForIt();
+ test.Printf(_L("------- End of TestMediaCardNotificationWhenNotRegisteredForIt -------\n"));
+ }
+*/ //
+ // RRawDisk::Write
+ // 8. Add notification for media change
+ // Write directly to the media
+ //
+#ifdef __WINS__
+ if(gDriveToTest-(TChar)'A' != 2)
+#endif
+ {
+ PrintLine();
+ test.Next(_L("RRawDisk::Write Tests"));
+ r = TestMultipleNotificationsL(driveDes,1,1,t_notification::ERawDiskWrite,TFsNotification::EMediaChange,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ test.Printf(_L("------- End of RRawDisk::Write Test ------------------------------ \n"));
+ }
+
+
+ //===============================================================================
+ //! @SYMTestCaseID PBASE-T_NOTIFY-2450
+ //! @SYMTestType UT
+ //! @SYMREQ PREQ1847
+ //! @SYMTestCaseDesc Drive Name Modification – Single File Server Session
+ //! @SYMTestStatus Implemented
+ //
+ // TFsNotificationType EDriveName
+ //===============================================================================
+ //
+ // RFs::SetDriveName
+ // The drive name is renamed 2*aIterations times
+ // aMaxNotifications = 2*aIterations
+ //
+ // 1. Add notification for a specific drive name change
+ // Change the drive name
+ //
+ PrintLine();
+ test.Next(_L("DriveName Test"));
+ r = TestMultipleNotificationsL(driveDes,1,2,t_notification::ESetDriveName,TFsNotification::EDriveName,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ //
+ // 2. Add notification for a specific drive name change
+ // Repeatedly rename the drive
+ //
+ r = TestMultipleNotificationsL(driveDes,3,6,t_notification::ESetDriveName,TFsNotification::EDriveName,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ test.Printf(_L("------- End of DriveName Test ----------------------------------------\n"));
+
+
+ //================================================================================
+ //! @SYMTestCaseID PBASE-T_NOTIFY-2451
+ //! @SYMTestType UT
+ //! @SYMREQ PREQ1847
+ //! @SYMTestCaseDesc Volume Name Modification – Single File Server Session
+ //! @SYMTestStatus Implemented
+ //
+ // TFsNotificationType EVolumeName
+ //================================================================================
+ //
+ // RFs::SetVolumeLabel - Does not run on WINS
+ // The volume name is renamed 2*aIterations times
+ // aMaxNotifications = 2*aIterations
+ //
+#ifndef __WINS__
+ PrintLine();
+ test.Next(_L("VolumeName Test"));
+ //
+ // 1. Add notification for a specific volume name change
+ // Change the volume name
+ //
+ r = TestMultipleNotificationsL(driveDes,1,2,t_notification::ESetVolumeLabel,TFsNotification::EVolumeName,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ //
+ // 2. Add notification for a specific volume name change
+ // Repeatedly rename the volume
+ //
+ r = TestMultipleNotificationsL(driveDes,3,6,t_notification::ESetVolumeLabel,TFsNotification::EVolumeName,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ test.Printf(_L("------- End of VolumeName Test ---------------------------------------\n"));
+#endif
+
+
+ //=============================================================================
+ //! @SYMTestCaseID PBASE-T_NOTIFY-2452
+ //! @SYMTestType UT
+ //! @SYMREQ PREQ1847
+ //! @SYMTestCaseDesc All Operations Filter – Single File Server Session
+ //! @SYMTestStatus Implemented
+ //
+ // TFsNotificationType EAllOps
+ //=============================================================================
+ PrintLine();
+ test.Next(_L("AllOps Tests"));
+ //
+ // 1. Add notification for all operations
+ // Create a file
+ // Delete the file
+ //
+ // EAllOps1: A file is created and deleted aIterations times
+ // aMaxNotification = 2*aIterations
+ //
+ _LIT(KFilename10,"file.allops");
+ r = TestMultipleNotificationsL(_L(""),KFilename10,4,8,t_notification::EAllOps1,(TUint)TFsNotification::EAllOps,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ //
+ // 2. Add notification for all operations
+ // Create a file
+ // Write to the file
+ // Delete the file
+ //
+ // EAllOps2: A file is created, written to aIterations times and then deleted
+ // aMaxNotification = 2 + aIterations (See File Write Tests)
+ //
+ r = TestMultipleNotificationsL(_L(""),KFilename10,4,6,t_notification::EAllOps2,(TUint)TFsNotification::EAllOps,2*KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ //
+ // 3. Add notification for all operations
+ // Create a file
+ // Change the file size
+ // Delete the file
+ //
+ // EAllOps3: A file is created, its size is increased size aIterations times, decreased (aIterations - 1) times
+ // and then deleted
+ // aMaxNotifications = 1 + 2*aIterations
+ //
+ r = TestMultipleNotificationsL(_L(""),KFilename10,4,9,t_notification::EAllOps3,(TUint)TFsNotification::EAllOps,KMinNotificationBufferSize*2,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ //
+ // 4. Add notification for all operations
+ // Create a file
+ // Change the file attribute
+ // Delete the file
+ //
+ // EAllOps4: A file is created, its attribute is changed and the file is deleted
+ // aMaxNotification = 3
+ //
+ r = TestMultipleNotificationsL(_L(""),KFilename10,1,3,t_notification::EAllOps4,(TUint)TFsNotification::EAllOps,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ //
+ // 5. Add notification for all operations
+ // Create a file
+ // Rename the file
+ //
+ // EAllOps5: A file is created and renamed
+ // aMaxNotification = 2
+ //
+ r = TestMultipleNotificationsL(_L(""),KFilename10,1,2,t_notification::EAllOps5,(TUint)TFsNotification::EAllOps,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ //
+ // 6. Add notification for all operations
+ // Change drive name
+ // Change volume name
+ //
+ // SetVolumeLabel does not run on WINS
+ // EAllOps6: The drive and volume names are changed
+ // aMaxNotification = 2
+ //
+#ifndef __WINS__
+ r = TestMultipleNotificationsL(driveDes,1,2,t_notification::EAllOps6,(TUint)TFsNotification::EAllOps,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+#endif
+ test.Printf(_L("------- End of AllOps Tests ------------------------------------------\n"));
+
+
+ //=============================================================================
+ //! @SYMTestCaseID PBASE-T_NOTIFY-2453
+ //! @SYMTestType UT
+ //! @SYMREQ PREQ1847
+ //! @SYMTestCaseDesc Multiple Filters – Single File Server Session
+ //! @SYMTestStatus Implemented
+ //=============================================================================
+ PrintLine();
+ test.Next(_L("Multiple-Filter Tests"));
+ //
+ // TFsNotification::ECreate | TFsNotification::EDelete
+ // 1. Add notification for create and delete for a specific file
+ // Create that file
+ // Delete the file
+ //
+ // A file is created and deleted aIterations times
+ // aMaxNotification = 2*aIterations
+ //
+ _LIT(KFilename11,"file.mulfil");
+ r = TestMultipleNotificationsL(_L(""),KFilename11,3,6,t_notification::EAllOps1,TFsNotification::ECreate | TFsNotification::EDelete,2*KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ //
+ // TFsNotification::EDelete | TFsNotification::ECreate | TFsNotification::EFileChange
+ // 2. Add notification for create, file change and delete for a specific file
+ // Create a file
+ // Change the file size
+ // Delete the file
+ //
+ // A file is created, its size is increased size aIterations times, decreased (aIterations - 1) times
+ // and then deleted
+ // aMaxNotifications = 1 + 2*aIterations
+ //
+ r = TestMultipleNotificationsL(_L(""),KFilename11,4,9,t_notification::EAllOps3,TFsNotification::EDelete | TFsNotification::ECreate | TFsNotification::EFileChange,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ //
+ // TFsNotification::EAttribute | TFsNotification::EDelete | TFsNotification::ECreate
+ // 3. Add notification for create, attribute change and delete for a specific file
+ // Create a file
+ // Change the file attribute
+ // Delete the file
+ //
+ // A file is created, its attribute is changed and the file is deleted
+ // aMaxNotification = 3
+ //
+ r = TestMultipleNotificationsL(_L(""),KFilename11,1,3,t_notification::EAllOps4,TFsNotification::EAttribute | TFsNotification::EDelete | TFsNotification::ECreate,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ //
+ // TFsNotification::ERename | TFsNotification::ECreate
+ // 4. Add notification for create and rename for a specific file
+ // Create a file
+ // Rename the file
+ //
+ // A file is created and renamed
+ // aMaxNotification = 2
+ //
+ r = TestMultipleNotificationsL(_L(""),KFilename11,1,2,t_notification::EAllOps5,TFsNotification::ERename | TFsNotification::ECreate,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ //
+ // TFsNotification::EVolumeName | TFsNotification::EDriveName
+ // 5. Add notification for drive and volume name change for a specific drive
+ // Change drive name
+ // Change volume name
+ //
+ // SetVolumeLabel does not run on WINS
+ // The drive and volume names are changed
+ // aMaxNotification = 2
+ //
+#ifndef __WINS__
+ r = TestMultipleNotificationsL(driveDes,1,2,t_notification::EAllOps6,TFsNotification::EVolumeName | TFsNotification::EDriveName,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+#endif
+ test.Printf(_L("------- End of Multiple-Filter Tests ---------------------------------\n"));
+
+
+ //==============================================================================
+ //! @SYMTestCaseID PBASE-T_NOTIFY-2454
+ //! @SYMTestType UT
+ //! @SYMREQ PREQ1847
+ //! @SYMTestCaseDesc Overflow Notification – Single File Server Session
+ //! @SYMTestStatus Implemented
+ //==============================================================================
+ //
+ // 1. Add notification with a small buffer size, for a specific file change
+ // Change the file size once
+ // 2. Make continuous file size changes to the file
+ // 3. When overflow notification occurs, delete the notification
+ //
+ PrintLine();
+ r = TestOverflowL();
+ test(r==KErrNone);
+
+ //For DEF140387
+ PrintLine();
+ r= TestPostOverflowNotifications();
+ test(r==KErrNone);
+ test.Printf(_L("------- End of Overflow Test -----------------------------------------\n"));
+
+
+ //============================================================================
+ //! @SYMTestCaseID PBASE-T_NOTIFY-2455
+ //! @SYMTestType CIT
+ //! @SYMREQ PREQ1847
+ //! @SYMTestCaseDesc API Negative Testing – Single File Server Session
+ //! @SYMTestStatus Implemented
+ //============================================================================
+ // 1.
+ // a-CFsNotify class creation with zero buffer size
+ //
+ // 2.
+ // b-CFsNotify class creation with negative buffer size
+ // c-CFsNotify class creation with buffer size that is too large
+ //
+ // 3.
+ // d-Call AddNotification with aNotiififcationType zero
+ // e-Call AddNotification with aNotiififcationType invalid
+ // f-Call AddNotification with many different invalid paths
+ //
+ // 4.
+ // g-Call RequestNotifications with status that is already in use
+ // h-Call CancelNotifications with wrong status
+ //
+ PrintLine();
+ __UHEAP_MARK;
+ NegativeTests();
+ __UHEAP_MARKEND;
+ //
+ // 5.
+ // i-Negative testing for directory without *
+ //
+ test.Printf(_L("NegativeTests() I\n"));
+ NegativeTestDirStar();
+ test.Printf(_L("------- End of Negative Tests ----------------------------------------\n"));
+
+
+ //=============================================================================
+ //! @SYMTestCaseID PBASE-T_NOTIFY-2461
+ //! @SYMTestType CIT
+ //! @SYMREQ PREQ1847
+ //! @SYMTestCaseDesc Plugin Tests
+ //! @SYMTestStatus
+ //=============================================================================
+ PrintLine();
+ r = TestNotificationsWithFServPlugins();
+ test(r==KErrNone);
+ test.Printf(_L("------- End of Plugin Tests ------------------------------------------\n"));
+
+
+ //======================================================================
+ //! @SYMTestCaseID PBASE-T_NOTIFY-2459
+ //! @SYMTestType UT
+ //! @SYMREQ PREQ1847
+ //! @SYMTestCaseDesc Drive Formatting – Single File Server Session
+ //! @SYMTestStatus Implemented
+ //
+ // TFsNotificationType EMediaChange
+ //======================================================================
+ //
+ // RFormat
+ // We do these last so that we can be sure to have deleted anything we've inadvertently not deleted
+ //
+ // 1. Add notification for media change of a specific drive
+ // Format the drive
+ //
+#ifdef __WINS__
+ if(gDriveToTest-(TChar)'A' != 2)
+#endif
+ {
+ PrintLine();
+ test.Next(_L("Format Tests"));
+ r = TestMultipleNotificationsL(driveDes,1,1,t_notification::EFormat,TFsNotification::EMediaChange,KMinNotificationBufferSize,(TBool)EFalse,__LINE__);
+ test(r==KErrNone);
+ test.Printf(_L("------- End of Format Tests ------------------------------------------\n"));
+ }
+
+
+ //======================================================================
+ //! @SYMTestCaseID PBASE-T_NOTIFY-2460
+ //! @SYMTestType UT
+ //! @SYMREQ PREQ1847
+ //! @SYMTestCaseDesc Notifications for Data Caged Areas
+ //! @SYMTestStatus Implemented
+ //======================================================================
+ //
+ // Create a private folder for a specified uid
+ // Add notification filter using the following processes:
+ // 1. A process with no capability
+ // 2. A process with all capabilities
+ // 3. A process with the specified uid
+ //
+ PrintLine();
+ test.Next(_L("Test T_NOTIFIER_NOCAPS.EXE"));
+ r = TestProcessCapabilities(_L("T_NOTIFIER_NOCAPS.EXE"));
+ test(r == KErrPermissionDenied); //Failure on emulator -> Did you forget to do a wintest?
+
+ test.Next(_L("Test T_NOTIFIER_ALLFILES.EXE"));
+ r = TestProcessCapabilities(_L("T_NOTIFIER_ALLFILES.EXE"));
+ test(r == KErrNone);
+
+ test.Next(_L("Test T_NOTIFIER_BELONGS.EXE"));
+ r = TestProcessCapabilities(_L("T_NOTIFIER_BELONGS.EXE"));
+ test(r == KErrNone);
+ test.Printf(_L("------- End of Data-Caging Tests -------------------------------------\n"));
+
+
+ test.End();
+ test.Close();
+ delete cleanup;
+ } //End of CallTestsL
+