// 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