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);