First public contribution.
     1 // Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
 
     2 // All rights reserved.
 
     3 // This component and the accompanying materials are made available
 
     4 // under the terms of the License "Eclipse Public License v1.0"
 
     5 // which accompanies this distribution, and is available
 
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
 
     8 // Initial Contributors:
 
     9 // Nokia Corporation - initial contribution.
 
    14 // f32test\bench\t_notify_perf_impl.cpp
 
    18 #include "t_notify_perf.h"
 
    21 extern void FileNameGen(TFileName& aName, TInt aNum, TBool aIsFile = ETrue);
 
    22 extern TInt FileOperationThread(TAny* aSetting);
 
    23 extern TInt NotificationOperationThread(TAny* aSetting);
 
    24 extern TInt KillerThread(TAny*);
 
    25 extern TUint OpNotifyMapping(TUint16& aOption, TInt aOperation);
 
    26 extern TBool CompareEntryName(const TEntry& aEntry1, const TEntry& aEntry2);
 
    27 extern void SafeTestL(TBool aResult, TInt aId, TInt aLine, TText* aFile);
 
    28 extern void SafeTestL(TInt aResult, TInt aExpected, TInt aId, TInt aLine, TText* aFile);
 
    30 const TInt KNotificationHeaderSize = (sizeof(TUint16)*2)+(sizeof(TUint));
 
    31 const TInt KMinNotificationBufferSize = 2*KNotificationHeaderSize + 2*KMaxFileName;
 
    35 TFileName gLogFilePath;
 
    36 RArray<RThread> gNotiThreads;
 
    40 // Prints out the filename
 
    41 #define ExpandMe(X)  L ## X
 
    42 #define Expand(X)    ExpandMe(X)
 
    44 // Safe test, so that sub-threads are not hanging after check fail
 
    45 #define SAFETEST0(a) SafeTestL(a,KNoThreadId,__LINE__,(TText*)Expand("t_notify_perf_impl.cpp"))
 
    46 #define SAFETEST1(a,b) SafeTestL(a,b,__LINE__,(TText*)Expand("t_notify_perf_impl.cpp"))
 
    47 #define SAFETEST2(a,b,c) SafeTestL(a,b,c,__LINE__,(TText*)Expand("t_notify_perf_impl.cpp"))
 
    50 TTestSetting::TTestSetting()
 
    51 : iNumFiles(0), iNumCli(0), iOption(0), iOperationList(NULL)
 
    55 TTestSetting::TTestSetting(TInt aNumFiles, TInt aNumCli, TUint16 aOpt, const TUint* aOpList)
 
    56 : iNumFiles(aNumFiles), iNumCli(aNumCli), iOption(aOpt), iOperationList(aOpList)
 
    60 //===========================================================
 
    62 CTimerLogger* CTimerLogger::NewL(const TFileName& aLogFile)
 
    64 	CTimerLogger* self = new(ELeave) CTimerLogger();
 
    65 	CleanupStack::PushL(self);
 
    66 	self->ConstructL(aLogFile);
 
    67 	CleanupStack::Pop(self);
 
    71 void CTimerLogger::ConstructL(const TFileName& aLogFile)
 
    73 	User::LeaveIfError(HAL::Get(HALData::ENanoTickPeriod, iTickPeriod));
 
    74 	iLogFile.Copy(aLogFile);
 
    77 CTimerLogger::CTimerLogger()
 
    78 :  iTiming(EFalse), iTickNumber(0), iTimeScale(KDefaultTimeScale)
 
    83 CTimerLogger::~CTimerLogger()
 
    89 TInt CTimerLogger::Log(const TDesC& aDes, TBool aIsLine)
 
    94 	TInt err = file.Open(iFs,iLogFile,EFileShareExclusive|EFileWrite);
 
    95 	SAFETEST0(err == KErrNone || err == KErrNotFound || err == KErrPathNotFound);
 
    99 		err = iFs.MkDirAll(iLogFile);
 
   100 		SAFETEST0(err == KErrNone || err == KErrAlreadyExists);
 
   101 		err = file.Create(iFs,iLogFile,EFileShareExclusive|EFileWrite);
 
   102 		SAFETEST0(err == KErrNone);
 
   109 		data.Append(_L8("\r\n"));
 
   113 	err = file.Seek(ESeekEnd, offset);
 
   114 	SAFETEST0(err == KErrNone);
 
   115 	err = file.Write(data);
 
   116 	SAFETEST0(err == KErrNone);
 
   123 // Write Logs and also print the line written in the console
 
   124 TInt CTimerLogger::LogAndPrint(const TDesC& aDes, TBool aIsLine)
 
   129 	    err = Log(aDes, aIsLine);
 
   133 // Write and print the time result
 
   134 TInt CTimerLogger::LogTestStepTime(TUint aOp, TInt aNum)
 
   143 			buf.Append(_L("Create - "));
 
   146 			buf.Append(_L("Replace - "));
 
   149 			buf.Append(_L("Change Attribute - "));
 
   152 			buf.Append(_L("Rename - "));
 
   155 			buf.Append(_L("Write - "));
 
   158 			buf.Append(_L("Resize - "));
 
   161 			buf.Append(_L("Delete - "));
 
   164 			buf.AppendFormat(_L("%d Changes on Single File - "), aNum);
 
   167 			buf.AppendFormat(_L("Small Changes on %d Files - "), aNum);
 
   170 			buf.Append(_L("Create(dir) - "));
 
   173 			buf.Append(_L("Rename(dir) - "));
 
   176 			buf.Append(_L("Delete(dir) - "));
 
   179 			buf.AppendFormat(_L("%d Mixed Operations - "), aNum*18);
 
   184 	TReal time = (static_cast<TReal>(iTickNumber) * iTickPeriod) / iTimeScale;
 
   185 	buf.AppendFormat(_L("time: %d ms"), static_cast<TInt>(time));
 
   186 	return LogAndPrint(buf);
 
   189 // write and print the test case discription
 
   190 TInt CTimerLogger::LogSettingDescription(const TInt aNumFile, const TInt aNumCli, const TUint16 aOption, TBool aNumOpVaries)
 
   192 	LogAndPrint(_L("===================================================="));
 
   195 	buf.Append(_L("Test: "));
 
   198 		buf.AppendFormat(_L("%d files/directories, %d Clients, "), aNumFile, aNumCli);
 
   202 	switch(aOption & KNotifyOptionMask)
 
   205 			buf.Append(_L("No Notification"));
 
   208 			buf.Append(_L("Enhanced"));
 
   211 			buf.Append(_L("Original"));
 
   214 			buf.Append(_L("Nokia Plug-in"));
 
   220 	if (aOption & EBigFilter)
 
   222 		buf.Append(_L(", 100 Filters"));
 
   225 	if (aOption & EReportChg)
 
   227 		buf.Append(_L(", Change Reporting"));
 
   231 		buf.Append(_L(", Not Report Changes"));
 
   234 	if (aOption & EEnhanced)
 
   236 		if (aOption & EBigBuffer)
 
   238 			buf.Append(_L(", Big Buffer"));
 
   242 			buf.Append(_L(", Small Buffer"));
 
   245 		if (aOption & EMultiNoti1)
 
   247 			buf.Append(_L(", Multi Notification Mode 1"));
 
   249 		else if (aOption & EMultiNoti2)
 
   251 			buf.Append(_L(", Multi Notification Mode 2"));
 
   256 	LogAndPrint(_L("----------------------------------------------------"));
 
   261 //===========================================================
 
   263 CTestExecutor::CTestExecutor(TTestSetting& aSetting)
 
   264 : iTestSetting(aSetting)
 
   268 CTestExecutor::~CTestExecutor()
 
   272 void CTestExecutor::KillAllTestThreads()
 
   275     killer.Create(_L("KillerThread"), KillerThread, KDefaultStackSize, KMinHeapSize, KMaxHeapSize, NULL); 
 
   278     TRequestStatus status;
 
   279     killer.Logon(status);
 
   280     User::WaitForRequest(status);
 
   281     TInt err = killer.ExitReason();
 
   282     test(err == KErrNone);
 
   285 // start run a test case
 
   286 void CTestExecutor::RunTestCaseL()
 
   289 	smphF.CreateLocal(0);
 
   291 	smphN.CreateLocal(0);
 
   293 	RArray<RThread> notiThreads; // list of handles of notification threads
 
   294 	RPointerArray<CTimerLogger> loggerList;
 
   297 	TUint16 option = iTestSetting.iOption;
 
   298 	while (count < iTestSetting.iNumCli)
 
   301 		iTestSetting.iOption = (TUint16)(option + count); // Put Thread ID in option
 
   304 		param.iSetting = iTestSetting;
 
   305 		param.iSmphFT = &smphF;
 
   306 		param.iSmphNT = &smphN;
 
   313             logName.Append(gLogFilePath);
 
   314             if (iTestSetting.iNumCli == 1)
 
   315                 logName.Append(_L("SingleClient"));
 
   317                 logName.AppendFormat(_L("MultiClient%02d"), count);
 
   319             logName.Append(gLogPostFix);
 
   322 		CTimerLogger* logger = CTimerLogger::NewL(logName);
 
   323 		CleanupStack::PushL(logger);
 
   325 		param.iLogger = logger;
 
   326 		param.iLoggerArray = NULL;
 
   328 		TUint operation = *iTestSetting.iOperationList;
 
   329 		TBool numFilesVaries = EFalse; 
 
   331 		if (operation == EOpManyFiles || operation == EOpManyChanges || operation == EOpMixed)
 
   333 			numFilesVaries = ETrue;
 
   335 		logger->LogSettingDescription(iTestSetting.iNumFiles, iTestSetting.iNumCli, iTestSetting.iOption, numFilesVaries);
 
   337 		loggerList.AppendL(logger);
 
   340 		threadName.AppendFormat(_L("NotificationThread%02d"), count);
 
   343 		notifyOp.Create(threadName, NotificationOperationThread, KDefaultStackSize, KMinHeapSize, KMaxHeapSize, ¶m);
 
   345 		notiThreads.AppendL(notifyOp);
 
   349 		smphF.Wait();	// Wait for the parameters being properly passed
 
   351 		CleanupStack::Pop(logger);
 
   355 	gNotiThreads = notiThreads;
 
   357 	if (iTestSetting.iNumCli == 0)	// no notification
 
   360 		logName.Append(gLogFilePath);
 
   361 		logName.Append(_L("SingleClient"));
 
   362 		logName.Append(gLogPostFix);
 
   364 		CTimerLogger* logger = CTimerLogger::NewL(logName);
 
   365 		CleanupStack::PushL(logger);
 
   367 		logger->LogSettingDescription(iTestSetting.iNumFiles, iTestSetting.iNumCli, iTestSetting.iOption);
 
   369 		loggerList.AppendL(logger);
 
   370 		CleanupStack::Pop(logger);
 
   373 	TThreadParam paramFileOp;
 
   374 	paramFileOp.iSetting = iTestSetting;
 
   375 	paramFileOp.iSmphFT = &smphF;
 
   376 	paramFileOp.iSmphNT = &smphN;
 
   377 	paramFileOp.iLogger = NULL;
 
   378 	paramFileOp.iLoggerArray = &loggerList;
 
   381 	fileOp.Create(_L("FileOperationThread"), FileOperationThread, KDefaultStackSize, KMinHeapSize, KMaxHeapSize, ¶mFileOp);	
 
   382 	gFileThread = fileOp;
 
   388 	TRequestStatus status;
 
   389 	fileOp.Logon(status);
 
   390 	User::WaitForRequest(status);
 
   391 	err = fileOp.ExitReason();
 
   392 	test(err == KErrNone);
 
   395 	while(count < notiThreads.Count())
 
   397 		notiThreads[count].Logon(status);
 
   398 		User::WaitForRequest(status);
 
   399 		err = notiThreads[count].ExitReason();
 
   400 		test(err == KErrNone);
 
   404 	CLOSE_AND_WAIT(fileOp);
 
   407 	while(count < notiThreads.Count())
 
   409 		RThread thread = notiThreads[count];
 
   410 		CLOSE_AND_WAIT(thread);
 
   414 	for (TInt i = 0; i < loggerList.Count(); i++)
 
   416 		loggerList[i]->LogAndPrint(_L("===================================================="));
 
   421 	loggerList.ResetAndDestroy();
 
   427 //===========================================================
 
   429 CFileOperator::CFileOperator(const TTestSetting& aSetting, RPointerArray<CTimerLogger>& aLoggerArray, RSemaphore* aSmphFT, RSemaphore* aSmphNT)
 
   432 	iNumFiles = aSetting.iNumFiles;
 
   433 	iOption = aSetting.iOption;
 
   434 	iCurrentOp = aSetting.iOperationList;
 
   435 	iNumCli = aSetting.iNumCli;
 
   437 	iLoggers = aLoggerArray; 
 
   444 CFileOperator::~CFileOperator()
 
   449 // starts measuring for all the notification thread
 
   450 // the loggers in iLogger are shared by Notification thread
 
   451 void CFileOperator::MesureStartsAll()
 
   456 		iLoggers[i]->MeasureStart();
 
   461 // Wait for all notification threads to signal
 
   462 void CFileOperator::WaitForSignalsAll()
 
   472 // prepare each test step
 
   473 void CFileOperator::TestStepPrepare(TUint aOp)
 
   475 	RDebug::Print(_L("Preparing for the next test step..."));
 
   480 			User::After(1500000); // Wait for 1.5 sec so that the new files have different modified time
 
   482 			TInt count = iFirstFile + iNumFiles;
 
   483 			while (count < (iFirstFile + (iNumFiles * 2)))
 
   486 				FileNameGen(nextFile, count);
 
   487 				file.Create(iFs, nextFile, EFileRead);
 
   497 			FileNameGen(nextFile, 9999);
 
   498 			file.Create(iFs, nextFile, EFileRead);
 
   505 			iFs.GetDir(gTestPath, KEntryAttMaskSupported, ESortNone, list);
 
   506 			TInt count = list->Count();
 
   511 			for (TInt i = 0; i < iNumFiles - count; i++)
 
   514 				FileNameGen(nextFile, count + i);
 
   515 				file.Create(iFs, nextFile, EFileRead);
 
   521 		// No preparation for other operations
 
   525 	RDebug::Print(_L("Preparation done..."));
 
   528 // Finish each test step, do some clearing or test setting modification
 
   529 void CFileOperator::TestStepFinish(TUint aOp)
 
   531 	RDebug::Print(_L("Finishing the test step..."));
 
   537 			iFirstFile += iNumFiles;
 
   549 			FileNameGen(fileName, 9999);
 
   550 			iFs.Delete(fileName);
 
   563 	    // no clearing for other operations
 
   567 	RDebug::Print(_L("***** Test step finished *****"));
 
   568 	RDebug::Print(_L("\n"));
 
   571 // perform the file operations
 
   572 void CFileOperator::DoChangesL()
 
   574 	while(*iCurrentOp != EOpEnd)
 
   576 		TestStepPrepare(*iCurrentOp);
 
   578 		if (iOption & ENoNotify)
 
   580 			iLoggers[0]->MeasureStart();
 
   584 			iSmphS->Signal(iNumCli);	// Signal notification threads that preparation is done
 
   585 			WaitForSignalsAll();	// Wait for notification threads to finish requesting notifications 
 
   589 		RDebug::Print(_L("Start Timing and File operations..."));	
 
   614 				DoManyChangesOnSingleFileL();
 
   617 				DoSmallChangesOnManyFilesL();
 
   629 				DoMixedOperationsL();
 
   632 				User::Leave(KErrArgument);
 
   634 		RDebug::Print(_L("File Operation Ended..."));
 
   636 		if (iOption & ENoNotify)
 
   638 			RDebug::Print(_L("Timing ended..."));
 
   639 			iLoggers[0]->MeasureEnd();
 
   640 			iLoggers[0]->LogTestStepTime(*iCurrentOp, iNumFiles);
 
   645 			TFileName endFile(gLogFilePath);
 
   646 			endFile.Append(_L("test.end"));
 
   647 			TInt r = file.Replace(iFs, endFile, EFileWrite);
 
   648 			SAFETEST0(r == KErrNone);
 
   651 			WaitForSignalsAll();	// Wait for notification threads to receive all the notifications 
 
   654 		TestStepFinish(*iCurrentOp);
 
   660 void CFileOperator::DoCreateL()
 
   663 	TInt count = iFirstFile;
 
   665 	while (count < iFirstFile + iNumFiles)
 
   668 		FileNameGen(nextFile, count);
 
   670 		TInt r = file.Create(iFs, nextFile, EFileRead);
 
   671 		SAFETEST0(r == KErrNone);
 
   677 void CFileOperator::DoReplaceL()
 
   679 	TInt count = iFirstFile;
 
   681 	while (count < iFirstFile + iNumFiles)
 
   685 		FileNameGen(newFile, count);
 
   686 		FileNameGen(oldFile, count + iNumFiles);
 
   688 		iFs.Replace(oldFile, newFile);
 
   693 void CFileOperator::DoChangeAttL()
 
   695 	TInt count = iFirstFile;
 
   697 	while (count < iFirstFile + iNumFiles)
 
   700 		FileNameGen(nextFile, count);
 
   701 		iFs.SetAtt(nextFile, KEntryAttNormal, KEntryAttArchive);
 
   706 void CFileOperator::DoRenameL()
 
   708 	TInt count = iFirstFile;
 
   710 	while (count < iFirstFile + iNumFiles)
 
   714 		FileNameGen(oldFile, count);
 
   715 		FileNameGen(newFile, count + iNumFiles);
 
   717 		iFs.Rename(oldFile, newFile);
 
   722 void CFileOperator::DoWriteL()
 
   725 	TInt count = iFirstFile;
 
   726 	_LIT8(KData, "Some text for writing test of enhanced notification performance test.");
 
   728 	while (count < iFirstFile + iNumFiles)
 
   731 		FileNameGen(nextFile, count);
 
   732 		file.Open(iFs, nextFile, EFileWrite);
 
   734 		// Flush file to ensure notification is received
 
   741 void CFileOperator::DoResizeL()
 
   744 	TInt count = iFirstFile;
 
   746 	while (count < iFirstFile + iNumFiles)
 
   749 		FileNameGen(nextFile, count);
 
   750 		file.Open(iFs, nextFile, EFileWrite);
 
   753 		file.SetSize(size+10);
 
   759 void CFileOperator::DoDeleteL()
 
   761 	TInt count = iFirstFile;
 
   763 	while (count < iFirstFile + iNumFiles)
 
   766 		FileNameGen(nextFile, count);
 
   767 		iFs.Delete(nextFile);
 
   772 void CFileOperator::DoCreateDirL()
 
   774 	TInt count = iFirstFile;
 
   776 	while (count < iFirstFile + iNumFiles)
 
   779 		FileNameGen(nextFile, count, EFalse);
 
   785 void CFileOperator::DoRenameDirL()
 
   787 	TInt count = iFirstFile;
 
   788 	while (count < iFirstFile + iNumFiles)
 
   792 		FileNameGen(oldFile, count, EFalse);
 
   793 		FileNameGen(newFile, count + iNumFiles, EFalse);
 
   795 		iFs.Rename(oldFile, newFile);
 
   800 void CFileOperator::DoDeleteDirL()
 
   802 	TInt count = iFirstFile;
 
   804 	while (count < iFirstFile + iNumFiles)
 
   807 		FileNameGen(nextFile, count, EFalse);
 
   813 void CFileOperator::DoManyChangesOnSingleFileL()
 
   816 	FileNameGen(fileName, 9999);
 
   821 	for(TInt i = 0; i < iNumFiles; i++)
 
   824 		file.Open(iFs, fileName, EFileWrite);
 
   825 		file.Seek(ESeekEnd, offset);
 
   832 void CFileOperator::DoSmallChangesOnManyFilesL()
 
   837 	for(TInt i = 0; i < iNumFiles; i++)
 
   840 		FileNameGen(nextFile, i);
 
   841 		file.Open(iFs, nextFile, EFileWrite);
 
   848 void CFileOperator::DoMixedOperationsL()
 
   850 	// will perform 18*iNumFiles operations
 
   852 	TInt firstFile = iFirstFile;
 
   853 	TInt lastFile = iFirstFile + (2 * iNumFiles);
 
   854 	TInt firstDir = iFirstFile;
 
   855 	TInt lastDir = iFirstFile + iNumFiles;
 
   857 	_LIT8(KData, "Some text.");
 
   860 	// Create Files - 2*iNumFiles Ops
 
   861 	// we create 2*iNumFiles files here so that we can ensure that at least iNumfiles ops are performed after the replace step
 
   862 	for (i = firstFile; i < lastFile; i++)
 
   865 		FileNameGen(nextFile, i);
 
   866 		file.Create(iFs, nextFile, EFileRead);
 
   870 	// Create Directories - iNumFiles Ops
 
   871 	for (i = firstDir; i < lastDir; i++)
 
   874 		FileNameGen(nextFile, i, EFalse);
 
   878 	// Write - 2*iNumFiles Ops
 
   879 	for (i = firstFile; i < lastFile; i++)
 
   882 		FileNameGen(nextFile, i);
 
   883 		file.Open(iFs, nextFile, EFileWrite);
 
   889 	// Resize - 2*iNumFiles Ops
 
   890 	for (i = firstFile; i < lastFile; i++)
 
   893 		FileNameGen(nextFile, i);
 
   894 		file.Open(iFs, nextFile, EFileWrite);
 
   897 		file.SetSize(size+10);
 
   901 	// Replace Files - iNumFiles Ops
 
   902 	for (i = firstFile; i < firstFile + iNumFiles; i++)
 
   906 		FileNameGen(oldFile, i);
 
   907 		FileNameGen(newFile, i + iNumFiles);
 
   908 		iFs.Replace(oldFile, newFile);
 
   910 	firstFile += iNumFiles;
 
   912 	// Rename Files - iNumFiles Ops
 
   913 	for (i = firstFile; i < lastFile; i++)
 
   917 		FileNameGen(newFile, i - iNumFiles);
 
   918 		FileNameGen(oldFile, i);	
 
   919 		iFs.Rename(oldFile, newFile);
 
   921 	firstFile -= iNumFiles;
 
   922 	lastFile -= iNumFiles;
 
   924 	// Delete Dirs - iNumFiles Ops
 
   925 	for (i = firstDir; i < lastDir; i++)
 
   928 		FileNameGen(nextFile, i, EFalse);
 
   932 	// Delete File - iNumFiles Ops
 
   933 	for (i = firstFile; i < lastFile; i++)
 
   936 		FileNameGen(nextFile, i);
 
   937 		iFs.Delete(nextFile);
 
   940 	// All-in-one - 7*iNumFiles Ops
 
   941 	for (i = firstFile; i < lastFile; i++)
 
   944 		FileNameGen(nextFile, i);
 
   946 		FileNameGen(nextDir, i, EFalse);
 
   950 		file.Create(iFs, nextFile, EFileWrite);
 
   955 		file.SetSize(size+10);
 
   959 		FileNameGen(newName, i + iNumFiles);
 
   960 		iFs.Rename(nextFile, newName);
 
   967 //==========================================================
 
   969 CNotifyOperator::CNotifyOperator(const TTestSetting& aSetting, RSemaphore* aSmphFT, RSemaphore* aSmphNT, CTimerLogger* aLogger)
 
   971 	iNumFiles = aSetting.iNumFiles;
 
   972 	iOption = aSetting.iOption;
 
   973 	iCurrentOp = aSetting.iOperationList;
 
   979 CNotifyOperator::~CNotifyOperator()
 
   983 // start operations in notification thread
 
   984 // this is the main function called in the thread,
 
   985 // it creates notification watcher, requests notification, and check test result
 
   986 void CNotifyOperator::StartOperationL()
 
   988 	CNotifyWatcher* notifyWatcher = CNotifyWatcher::NewL(iNumFiles, iOption, *iCurrentOp, iLogger);
 
   989 	CleanupStack::PushL(notifyWatcher);
 
   990 	CTestStopper* stopper = new(ELeave) CTestStopper();
 
   991 	CleanupStack::PushL(stopper);
 
   993 	CActiveScheduler::Add(notifyWatcher);
 
   994 	CActiveScheduler::Add(stopper);
 
   996 	while (*iCurrentOp != EOpEnd)
 
   998 		iSmphW->Wait();	// wait for file thread finishing preparation for the current file operation.
 
  1000 		notifyWatcher->FullDirectoryScanL(notifyWatcher->iEntries);
 
  1001 		notifyWatcher->RequestNotification();
 
  1002 		stopper->StartWaitingForFile();
 
  1004 		iSmphS->Signal();	// Signal file thread that the notifications are requested, ready to receive
 
  1006 		CActiveScheduler::Start();
 
  1007 		////////////////////////////////
 
  1008 		// receiving notifications... //
 
  1009 		////////////////////////////////
 
  1011 		notifyWatcher->HandleNotification(ETrue); // handle for the last time
 
  1013 		LogTestResult(notifyWatcher->iCounter, notifyWatcher->iMeanCounter, notifyWatcher->iOverflowCounter);
 
  1015 		if(iOption & EReportChg)
 
  1017 			TestChangeReport(notifyWatcher->iRecords.Count());
 
  1022 		    TInt id = iOption & KNotifyTreadIdMask;
 
  1023             if (iOption & EMultiNoti2)
 
  1025                 if ( *iCurrentOp == EOpCreate ||
 
  1026                     (id % 4 == 0 && (*iCurrentOp == EOpRename || *iCurrentOp == EOpReplace)) ||
 
  1027                     (id % 4 == 1 && *iCurrentOp == EOpChgAttr) || 
 
  1028                     (id % 4 == 2 && (*iCurrentOp == EOpResize || *iCurrentOp == EOpWrite)) ||
 
  1029                     (id % 4 == 3 && *iCurrentOp == EOpDelete))
 
  1031                     SAFETEST2(notifyWatcher->iCounter, iNumFiles, id);
 
  1036                 SAFETEST2(notifyWatcher->iCounter, iNumFiles, id);
 
  1040 		iSmphS->Signal();	// Signal file thread that all notifications are received
 
  1044 		notifyWatcher->Reset(*iCurrentOp);
 
  1045 		if ((*iCurrentOp == EOpManyFiles) || (*iCurrentOp == EOpManyChanges))
 
  1049 		else if (*iCurrentOp == EOpMixed)
 
  1055 	CleanupStack::PopAndDestroy(2);
 
  1059 // Write log and print the notification numbers using iLogger
 
  1060 void CNotifyOperator::LogNotificationNumbers(TInt aNumNoti, TInt aNumIter, TInt aNumOverflow)
 
  1064 	if (iOption & EEnhanced)
 
  1066 		if (aNumOverflow > 0)
 
  1068 			buf.AppendFormat(_L("Buffer overflow: %d overflow notifications received."), aNumOverflow, aNumNoti);
 
  1069 			iLogger->LogAndPrint(buf);
 
  1073 		TReal mean = static_cast<TReal>(aNumNoti)/aNumIter;
 
  1074 		buf.AppendFormat(_L("%.2f mean enhanced notifications per iteration."), mean);	
 
  1075 		iLogger->LogAndPrint(buf);
 
  1079 	buf.AppendFormat(_L("%d notifications received overall."), aNumNoti);
 
  1080 	iLogger->LogAndPrint(buf);
 
  1083 // Write log and print the test reault
 
  1084 void CNotifyOperator::LogTestResult(TInt aCounter, TInt aMeanCounter, TInt aOFCounter)
 
  1086     if (iOption & EMultiNoti2)
 
  1088         TInt id = iOption & KNotifyTreadIdMask;
 
  1089         if ( *iCurrentOp == EOpCreate || 
 
  1090             (id % 4 == 0 && (*iCurrentOp == EOpRename || *iCurrentOp == EOpReplace)) || 
 
  1091             (id % 4 == 1 && *iCurrentOp == EOpChgAttr) || 
 
  1092             (id % 4 == 2 && (*iCurrentOp == EOpWrite || *iCurrentOp == EOpResize)) ||
 
  1093             (id % 4 == 3 && *iCurrentOp == EOpDelete))
 
  1095             iLogger->LogTestStepTime(*iCurrentOp, iNumFiles);
 
  1096             LogNotificationNumbers(aCounter, aMeanCounter, aOFCounter);
 
  1099             iLogger->LogAndPrint(_L("File operation not tested - time: 0 ms"));
 
  1101     else if (iOption & EPlugin)
 
  1103         if (*iCurrentOp == EOpChgAttr || *iCurrentOp == EOpWrite || *iCurrentOp == EOpResize)
 
  1104             iLogger->LogAndPrint(_L("File operation not tested - time: 0 ms"));
 
  1107             iLogger->LogTestStepTime(*iCurrentOp, iNumFiles);
 
  1108             LogNotificationNumbers(aCounter, aMeanCounter, aOFCounter);
 
  1113         iLogger->LogTestStepTime(*iCurrentOp, iNumFiles);
 
  1114         LogNotificationNumbers(aCounter, aMeanCounter, aOFCounter);
 
  1118 // When change report enabled, check the number of changes we detected
 
  1119 void CNotifyOperator::TestChangeReport(TInt aNumChanges)
 
  1122     buf.AppendFormat(_L("%d file changes detected.\r\n"), aNumChanges);
 
  1123     iLogger->LogAndPrint(buf);
 
  1125     TInt id = iOption & KNotifyTreadIdMask;
 
  1126     if (iOption & EEnhanced)
 
  1128         if (iOption & EMultiNoti2)
 
  1130             if ( *iCurrentOp == EOpCreate ||
 
  1131                 (id % 4 == 0 && (*iCurrentOp == EOpRename || *iCurrentOp == EOpReplace)) ||
 
  1132                 (id % 4 == 1 && *iCurrentOp == EOpChgAttr) || 
 
  1133                 (id % 4 == 2 && (*iCurrentOp == EOpResize || *iCurrentOp == EOpWrite)) ||
 
  1134                 (id % 4 == 3 && *iCurrentOp == EOpDelete))
 
  1136                 SAFETEST2(aNumChanges, iNumFiles, id);
 
  1139         else if (!(iOption & EBigBuffer))
 
  1141             // not testing this case, because the number of file changes detected 
 
  1142             // could varies depend on when notifications are received
 
  1144         else if (*iCurrentOp == EOpMixed)
 
  1146             SAFETEST2(aNumChanges, (18*iNumFiles), id); // On cached drives, the number of write notification could vary.
 
  1150             SAFETEST2(aNumChanges, iNumFiles, id);
 
  1153     else if (iOption & EOriginal)
 
  1155         if ((*iCurrentOp == EOpManyChanges) || (*iCurrentOp == EOpMixed))
 
  1157             // not testing this case, because the number of file changes detected 
 
  1158             // could varies depend on when notifications are received
 
  1160         else if ((*iCurrentOp == EOpReplace) || (*iCurrentOp == EOpRename) || (*iCurrentOp == EOpRenameDir))
 
  1162             SAFETEST2(aNumChanges, (2*iNumFiles), id);
 
  1166             SAFETEST2(aNumChanges, iNumFiles, id);
 
  1169     else if (iOption & EPlugin)
 
  1171         if (*iCurrentOp == EOpCreate || *iCurrentOp == EOpReplace || *iCurrentOp == EOpRename || 
 
  1172                 *iCurrentOp == EOpDelete || *iCurrentOp == EOpRenameDir)
 
  1174             SAFETEST2(aNumChanges, iNumFiles, id);
 
  1176         else if (*iCurrentOp == EOpMixed)
 
  1178             SAFETEST2(aNumChanges, (8*iNumFiles), id); // only part of operations can be notified
 
  1180         // Other cases are not testable.
 
  1184 //===========================================================
 
  1186 CNotifyWatcher::CNotifyWatcher(TInt aNumFiles, TUint16 aOption, TUint aCurrentOp, CTimerLogger* aLogger) 
 
  1187 : CActive(CActive::EPriorityStandard), iCounter(0), iMeanCounter(0), iOverflowCounter(0), iCurrentOp(aCurrentOp),
 
  1188 iNumFiles(aNumFiles), iOption(aOption), iEntries(aNumFiles), iRecords(aNumFiles), iLogger(aLogger)
 
  1192 CNotifyWatcher::~CNotifyWatcher()
 
  1197     iFs.DismountPlugin(KPluginName);
 
  1198     iFs.RemovePlugin(KPluginName);
 
  1205 CNotifyWatcher* CNotifyWatcher::NewL(TInt aNumFiles, TUint16 aOption, TUint aCurrentOp, CTimerLogger* aLogger)
 
  1207 	CNotifyWatcher* self = new(ELeave) CNotifyWatcher(aNumFiles, aOption, aCurrentOp, aLogger);
 
  1208 	CleanupStack::PushL(self);
 
  1210 	CleanupStack::Pop(self);
 
  1214 void CNotifyWatcher::ConstructL()
 
  1218 	if (iOption & EEnhanced)
 
  1221 		if(iOption & EBigBuffer)
 
  1223 			bufferSize = KMinNotificationBufferSize * iNumFiles;
 
  1224 			if (iCurrentOp == EOpMixed)
 
  1225 				bufferSize = bufferSize * 18;
 
  1228 			bufferSize = KMinNotificationBufferSize;
 
  1230 		iNotify = CFsNotify::NewL(iFs, bufferSize);
 
  1235 	if (iOption& EPlugin)
 
  1237 		TInt r = iFs.AddPlugin(KPluginName);
 
  1238 		test(r == KErrNone || r == KErrAlreadyExists);
 
  1239 		if (r != KErrAlreadyExists)
 
  1241 		    r = iFs.MountPlugin(KPluginName);
 
  1242 		    test(r == KErrNone);
 
  1246 	FullDirectoryScanL(iEntries);
 
  1250 // reset certain members so that we can do next test step
 
  1251 void CNotifyWatcher::Reset(TUint aOp)
 
  1256 	iOverflowCounter = 0;
 
  1258 	if ((aOp == EOpManyFiles) || (aOp == EOpManyChanges))
 
  1262 // perform a full dir scan
 
  1263 void CNotifyWatcher::FullDirectoryScanL(RArray<TEntry>& aArray)
 
  1268 	iFs.GetDir(gTestPath, KEntryAttMaskSupported, ESortByName, list);
 
  1273 	CleanupStack::PushL(list);
 
  1275 	for (TInt i = 0; i < list->Count(); i++)
 
  1277 		TEntry en ((*list)[i]);
 
  1281 	CleanupStack::PopAndDestroy();
 
  1284 // find out what has changed in test path, and save the changes in iRecord
 
  1285 void CNotifyWatcher::MakeChangeRecordL(RArray<TEntry>& aArray)
 
  1287 	TInt num = aArray.Count();
 
  1289 	for (i = 0; i < num; i++)
 
  1291 		TInt index = iEntries.Find(aArray[i], CompareEntryName);
 
  1292 		SAFETEST1((index == KErrNotFound || index >= 0), (iOption & KNotifyTreadIdMask));
 
  1294 		TFileName name(aArray[i].iName);
 
  1296 		if (index == KErrNotFound)
 
  1298 			r = iRecords.Append(name);
 
  1299 			SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
 
  1303 			if (!CompareEntry(iEntries[index], aArray[i]))
 
  1305 				r = iRecords.Append(name);
 
  1306 				SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
 
  1308 			iEntries.Remove(index);
 
  1312 	num = iEntries.Count();
 
  1314 	for (i = 0; i < num; i++)
 
  1316 		TFileName name(iEntries[i].iName);
 
  1317 		r = iRecords.Append(name);
 
  1318 		SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
 
  1322 	num = aArray.Count();
 
  1323 	for (i = 0; i < num; i++)
 
  1325 		TEntry en (aArray[i]);
 
  1326 		iEntries.AppendL(en);
 
  1331 TBool CNotifyWatcher::CompareEntry(const TEntry& aEntry1, const TEntry& aEntry2)
 
  1333 	// we don't compare name, because names are compared by CompareEntryName() already
 
  1334 	// we don't check attributes when creating files, because dir scan sometimes returns file
 
  1335 	// entries before attributes being flushed, and we don't care about it in this test case.
 
  1336 	// we also don't check the modified time for all the test cases expect replacing test, 
 
  1337 	// because dir scan sometimes returns file entries before time being flushed, 
 
  1338 	// and we don't care about it as well.
 
  1339 	// For replacing test, we check modification time, because it's the way we distinguish the old and new files.
 
  1340 	if (iCurrentOp == EOpCreate)
 
  1342 	    if ((aEntry1.iSize == aEntry2.iSize) && (aEntry1.iType == aEntry2.iType))
 
  1345 	else if (iCurrentOp == EOpReplace || iCurrentOp == EOpManyFiles || iCurrentOp == EOpManyChanges || iCurrentOp == EOpMixed)
 
  1347         if ((aEntry1.iAtt == aEntry2.iAtt) && (aEntry1.iModified == aEntry2.iModified) 
 
  1348                 && (aEntry1.iSize == aEntry2.iSize) && (aEntry1.iType == aEntry2.iType))
 
  1353         if ((aEntry1.iAtt == aEntry2.iAtt) && (aEntry1.iSize == aEntry2.iSize) 
 
  1354                 && (aEntry1.iType == aEntry2.iType))
 
  1361 // add 100 filters for enhanced notification test case
 
  1362 void CNotifyWatcher::AddLotsOfFilters()
 
  1364 	for (TInt i = 0; i < 100; i++)
 
  1367 		path.Copy(gTestPath);
 
  1370 		file.AppendFormat(_L("*.%3d"), i);
 
  1371 		TInt r = iNotify->AddNotification((TUint)TFsNotification::EAllOps, gTestPath, file);
 
  1372 		SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
 
  1376 void CNotifyWatcher::RequestNotification()
 
  1378 	switch (iOption & KNotifyOptionMask)
 
  1381 			RequestNotificationEnhanced();
 
  1384 			RequestNotificationOriginal();
 
  1387 			RequestNotificationPlugin();
 
  1395 // request notification using enhanced notification
 
  1396 void CNotifyWatcher::RequestNotificationEnhanced()
 
  1398 	if (iOption & EBigFilter)
 
  1404 	path.Copy(gTestPath);
 
  1406 	TBuf<3> file = _L("*");
 
  1408 	if (iOption & EMultiNoti1)
 
  1410 		TInt r = iNotify->AddNotification(TFsNotification::ECreate, path, file); // Create & replace
 
  1411 		SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
 
  1412 		r = iNotify->AddNotification(TFsNotification::ERename, path, file);	// Change Attribute
 
  1413 		SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
 
  1414 		r = iNotify->AddNotification(TFsNotification::EAttribute, path, file); // Rename
 
  1415 		SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
 
  1416 		r = iNotify->AddNotification(TFsNotification::EFileChange, path, file); // Write & Setsize
 
  1417 		SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
 
  1418 		r = iNotify->AddNotification(TFsNotification::EDelete, path, file); // Delete
 
  1419 		SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
 
  1421 	else if (iOption & EMultiNoti2)
 
  1423 		TInt r = iNotify->AddNotification(TFsNotification::ECreate, path, file); // Create & replace
 
  1424 		TInt id = iOption & KNotifyTreadIdMask;
 
  1429 				r = iNotify->AddNotification(TFsNotification::ERename, path, file);	// Change Attribute
 
  1430 				SAFETEST2(r, KErrNone, id);
 
  1433 				r = iNotify->AddNotification(TFsNotification::EAttribute, path, file); // Rename
 
  1434 				SAFETEST2(r, KErrNone, id);
 
  1437 				r = iNotify->AddNotification(TFsNotification::EFileChange, path, file); // Write & Setsize
 
  1438 				SAFETEST2(r, KErrNone, id);
 
  1441 				r = iNotify->AddNotification(TFsNotification::EDelete, path, file); // Delete
 
  1442 				SAFETEST2(r, KErrNone, id);
 
  1450 		TInt r = iNotify->AddNotification((TUint)TFsNotification::EAllOps, path, file);
 
  1451 		SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
 
  1454 	TInt r = iNotify->RequestNotifications(iStatus);
 
  1455 	SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
 
  1460 // request notification using original notification
 
  1461 void CNotifyWatcher::RequestNotificationOriginal()
 
  1463 	iFs.NotifyChange(ENotifyAll, iStatus, gTestPath);
 
  1467 void CNotifyWatcher::HandleNotification(TBool aLastTime)
 
  1469 	switch (iOption & KNotifyOptionMask)
 
  1472 			HandleNotificationEnhanced(aLastTime);
 
  1475 			HandleNotificationOriginal(aLastTime);
 
  1478 			HandleNotificationPlugin(aLastTime);
 
  1487 		iLogger->MeasureEnd();
 
  1488 		RDebug::Print(_L("Timing ended..."));
 
  1493 // handle enhanced notification
 
  1494 void CNotifyWatcher::HandleNotificationEnhanced(TBool aLastTime)
 
  1496 	TInt num = iCounter;
 
  1499 	TFsNotification::TFsNotificationType type;
 
  1500 	const TFsNotification* notification;
 
  1502 	while((notification = iNotify->NextNotification())!= NULL)
 
  1505 		type = notification->NotificationType();
 
  1506 		if (iOption & EBigBuffer)
 
  1508 			SAFETEST1((type & OpNotifyMapping(iOption, iCurrentOp)), (iOption & KNotifyTreadIdMask));
 
  1512 			SAFETEST1((type & (OpNotifyMapping(iOption, iCurrentOp) | TFsNotification::EOverflow)), (iOption & KNotifyTreadIdMask));
 
  1515       if(iOption & EReportChg)
 
  1517             if (type & TFsNotification::EOverflow)
 
  1520                 RArray<TEntry> newEntries;
 
  1521                 FullDirectoryScanL(newEntries);
 
  1522                 MakeChangeRecordL(newEntries);
 
  1528                 notification->Path(ptr);
 
  1531                 TInt r = iRecords.Append(name);
 
  1532                 SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
 
  1539 		if (num == iCounter) // no new notification so this iteration doesn't count
 
  1546 	iNotify->RequestNotifications(iStatus);
 
  1550 // handle original notification
 
  1551 void CNotifyWatcher::HandleNotificationOriginal(TBool aLastTime)
 
  1555 	if (iOption & EReportChg)
 
  1557 		RArray<TEntry> newEntries;
 
  1558 		FullDirectoryScanL(newEntries);
 
  1559 		MakeChangeRecordL(newEntries);
 
  1565 	    iCounter--; // the last time this function is called is not a notification.
 
  1569 	RequestNotificationOriginal();
 
  1572 // reset the iPluginStatusPkg, so that we can request notification again
 
  1573 void CNotifyWatcher::ResetMdsFSPStatus()
 
  1575     TMdsFSPStatus& status = iPluginStatusPkg();
 
  1577     status.iDriveNumber = 0;
 
  1578     status.iFileEventType = EMdsFileUnknown;
 
  1579     status.iFileName.Zero();
 
  1580     status.iNewFileName.Zero();
 
  1581     status.iProcessId = TUid::Null();
 
  1584 // request notification using nokia MDS plugin
 
  1585 void CNotifyWatcher::RequestNotificationPlugin()
 
  1587     TInt r = iPlugin.Open(iFs, KMdsFSPluginPosition);
 
  1588     SAFETEST2(r, KErrNone, (iOption & KNotifyTreadIdMask));
 
  1589     iPlugin.AddNotificationPath(gTestPath);
 
  1592     ResetMdsFSPStatus();
 
  1593     iPlugin.RegisterNotification(iPluginStatusPkg, iStatus);
 
  1597 // handle notifications from plugin
 
  1598 void CNotifyWatcher::HandleNotificationPlugin(TBool aLastTime)
 
  1603 	if (iOption & EReportChg)
 
  1605 	    TMdsFSPStatus& status = iPluginStatusPkg();
 
  1607 	    name.Copy(status.iFileName);
 
  1608 	    iRecords.Append(name);
 
  1609 	    if (iCurrentOp != EOpMixed)
 
  1611 	        TInt type = status.iFileEventType;
 
  1612 	        SAFETEST1(((TUint)type == OpNotifyMapping(iOption, iCurrentOp)), (iOption & KNotifyTreadIdMask));
 
  1617     ResetMdsFSPStatus();
 
  1618     iPlugin.RegisterNotification(iPluginStatusPkg, iStatus);
 
  1623 void CNotifyWatcher::DoCancel()
 
  1625 	switch (iOption & KNotifyOptionMask)
 
  1628 			iNotify->CancelNotifications(iStatus);
 
  1629 			iNotify->RemoveNotifications();
 
  1630 			// not breaking here as the Enhanced may change to Original if Overflow
 
  1632 			iFs.NotifyChangeCancel(iStatus);
 
  1636 		    iPlugin.NotificationCancel();
 
  1645 void CNotifyWatcher::RunL()
 
  1647 	HandleNotification(EFalse);
 
  1650 //========================================================================
 
  1652 CTestStopper::CTestStopper()
 
  1653 : CActive(EPriorityLow)
 
  1656 	iTestEndFile.Append(gLogFilePath);
 
  1657 	iTestEndFile.Append(_L("test.End"));
 
  1660 CTestStopper::~CTestStopper()
 
  1666 void CTestStopper::DoCancel()
 
  1668 	iFs.NotifyChangeCancel(iStatus);
 
  1671 // stop the scheduler since the test is done
 
  1672 void CTestStopper::RunL()
 
  1674 	CActiveScheduler::Stop();
 
  1675 	iFs.Delete(iTestEndFile);
 
  1679 // start waiting for "test.end" file
 
  1680 void CTestStopper::StartWaitingForFile()
 
  1682 	iFs.NotifyChange(ENotifyAll,iStatus,iTestEndFile);