Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h)
Have multiple extension sections in the bld.inf, one for each version
of the compiler. The RVCT version building the tools will build the
runtime libraries for its version, but make sure we extract all the other
versions from zip archives. Also add the archive for RVCT4.
// 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