kerneltest/f32test/server/t_notifier.cpp
changeset 43 96e5fb8b040d
--- /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
+