sl@0: // Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // f32test\bench\t_notify_perf.h sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: // File operation made in test path to trigger notifications sl@0: enum TNotifyPerfTestOperations sl@0: { sl@0: // File Operations sl@0: EOpEnd, // indicates that a series of operations ended sl@0: EOpCreate, sl@0: EOpReplace, sl@0: EOpChgAttr, sl@0: EOpRename, sl@0: EOpWrite, sl@0: EOpResize, sl@0: EOpDelete, sl@0: EOpManyChanges, // Large number changes to a single file sl@0: EOpManyFiles, // Small changes to large number of files sl@0: sl@0: // Directory Operations sl@0: EOpCreateDir, sl@0: EOpRenameDir, sl@0: EOpDeleteDir, sl@0: sl@0: // Mixed Operations sl@0: EOpMixed // A series of mixed operations involving both Files and Dirs sl@0: }; sl@0: sl@0: enum TTestOptions sl@0: { sl@0: ////////////////////////////////////////////////////// sl@0: // Lowest 4 bit reserved for notification treads ID // sl@0: ////////////////////////////////////////////////////// sl@0: sl@0: // Test with a lot of filters for enhanced notification - 1st bit sl@0: // set - on; unset - off sl@0: EBigFilter = 0x0010, sl@0: sl@0: // Whether perform full directory scan and save the file changes to a list - 2nd bit sl@0: // set - perform; unset - not perform sl@0: EReportChg = 0x0020, sl@0: sl@0: // Whether use big buffer for enhanced notification- 3rd bit sl@0: // Set - big buffer(no overflow); unset - small(could have overflow) sl@0: EBigBuffer = 0x0040, sl@0: sl@0: // For multi clients test. Enhanced Notification Only! sl@0: // Mode 1: set a variety of different notifications, same on each clients - 4th bit sl@0: EMultiNoti1 = 0x0080, sl@0: sl@0: // For multi clients test. Enhanced Notification Only! sl@0: // Mode 2: set a variety of different notifications, in which some are different on each clients, sl@0: // and some are same on each clients, only support upto 4 clients - 5th bit sl@0: EMultiNoti2 = 0x0100, sl@0: sl@0: ENotPerfTestReserved6 = 0x0200, sl@0: ENotPerfTestReserved7 = 0x0400, sl@0: ENotPerfTestReserved8 = 0x0800, sl@0: sl@0: // Notification type - 13th - 16th bits sl@0: ENoNotify = 0x1000, // Test without notification sl@0: EEnhanced = 0x2000, // Using enhanced notification APIs sl@0: EOriginal = 0x4000, // Using original notification APIs sl@0: EPlugin = 0x8000, // Using Nokia plug-in for notification sl@0: }; sl@0: sl@0: // Note for Plugin Test sl@0: // the plugin test can only be run manually because the plugin is not available in KHS code base sl@0: // to run the test: sl@0: // 1. enable the MACRO above in the mmp sl@0: // 2. get a S60 environment sl@0: // 3. copy the MdsFileServerPlugin.ptx from the release(\Winscw or \Armv5 depend on what kind of test you want to run) sl@0: // directory of S60 to the equivalent folder of release directory of your epoc32 sl@0: // 4. when build a rom, include the MdsFileServerPlugin.ptx file in the rom sl@0: // 5. then you can run sl@0: enum TMdsFSPOperation sl@0: { sl@0: EMdsFSPOpEnable, sl@0: EMdsFSPOpDisable, sl@0: EMdsFSPOpRegisterNotification, sl@0: EMdsFSPOpAddNotificationPath, sl@0: EMdsFSPOpRemoveNotificationPath, sl@0: EMdsFSPOpAddIgnorePath, sl@0: EMdsFSPOpRemoveIgnorePath, sl@0: EMdsFSPOpNotificationCancel, sl@0: }; sl@0: sl@0: class TMdsFSPStatus sl@0: { sl@0: public: sl@0: TInt iFileEventType; sl@0: TInt iDriveNumber; sl@0: TFileName iFileName; sl@0: TFileName iNewFileName; sl@0: TUid iProcessId; sl@0: }; sl@0: sl@0: enum TMdsFileEventType sl@0: { sl@0: EMdsFileCreated, sl@0: EMdsFileRenamed, sl@0: EMdsFileModified, sl@0: EMdsFileReplaced, sl@0: EMdsFileDeleted, sl@0: EMdsDriveFormatted, sl@0: EMdsFileUnknown, sl@0: EMdsDirRenamed sl@0: }; sl@0: sl@0: typedef TPckgBuf TMdsFSPStatusPckg; sl@0: sl@0: const TInt KMdsFSPluginPosition = 0x200071CD; sl@0: _LIT(KPluginName, "MdsFileServerPlugin"); sl@0: sl@0: // the list of operations to be conducted during a test case sl@0: const TUint KDefaultOpList[] = {EOpCreate, EOpReplace, EOpChgAttr, EOpRename, EOpWrite, EOpResize, EOpDelete, EOpEnd}; sl@0: const TUint KDefaultOpListDir[] = {EOpCreateDir, EOpRenameDir, EOpDeleteDir, EOpEnd}; sl@0: sl@0: const TUint KManyChangesOpList[] = {EOpManyChanges, EOpManyChanges, EOpManyChanges, EOpManyChanges, EOpManyChanges, EOpEnd}; sl@0: const TUint KManyFilesOpList[] = {EOpManyFiles, EOpManyFiles, EOpManyFiles, EOpManyFiles, EOpManyFiles, EOpEnd}; sl@0: const TUint KMixedOpTestList[] = {EOpMixed, EOpMixed, EOpMixed, EOpMixed, EOpMixed, EOpEnd}; sl@0: sl@0: const TUint16 KNotifyOptionMask = 0xF000; sl@0: const TUint16 KNotifyTreadIdMask = 0x000F; sl@0: sl@0: // default time scale for timer sl@0: const TUint KDefaultTimeScale = 1000; // 1ms sl@0: const TInt KMaxHeapSize = 0x1000000; sl@0: sl@0: // used by SafeCheck sl@0: const TInt KNoThreadId = -1; sl@0: sl@0: // a Controllor of whether measure time and write loggs; sl@0: extern TBool gPerfMeasure; sl@0: sl@0: extern TFileName gTestPath; sl@0: extern TFileName gLogFilePath; sl@0: sl@0: // Threads handles sl@0: extern RArray gNotiThreads; sl@0: extern RThread gFileThread; sl@0: sl@0: extern TBuf<50> gLogPostFix; sl@0: sl@0: //------------------------------------------------------------- sl@0: sl@0: class CTimerLogger; sl@0: sl@0: // a wrapper for test settings sl@0: class TTestSetting sl@0: { sl@0: sl@0: public: sl@0: TTestSetting(); sl@0: TTestSetting(TInt aNumFiles, TInt aNumCli, TUint16 aOpt, const TUint* aOpList); sl@0: inline void Reset(); sl@0: sl@0: public: sl@0: TInt iNumFiles; sl@0: TInt iNumCli; sl@0: TUint16 iOption; sl@0: const TUint* iOperationList; sl@0: sl@0: }; sl@0: sl@0: // a wrapper of parameters for the main thread to pass into notification thread or file operation thread sl@0: struct TThreadParam sl@0: { sl@0: TTestSetting iSetting; sl@0: RSemaphore* iSmphFT; // Semophore used by File Thread for waiting for signals from Notification Threads sl@0: RSemaphore* iSmphNT; // Semophore used by Notification Threads for waiting for signals from File Thread sl@0: CTimerLogger* iLogger; // Logger used by Notification Threads; sl@0: RPointerArray* iLoggerArray; // a pointer to an array of pointers to CTimmerLoggger sl@0: }; sl@0: sl@0: // This is the controller of the plugin, it's a simplified copy of the plugin engine used in S60 internally sl@0: class CMdsPluginControl : public RPlugin sl@0: { sl@0: public: sl@0: inline void RegisterNotification( TMdsFSPStatusPckg& aMdsFSPStatus, TRequestStatus& aStat); sl@0: inline void AddNotificationPath( const TDesC& aPath ); sl@0: inline void RemoveNotificationPath( const TDesC& aPath ); sl@0: inline TInt Enable(); sl@0: inline TInt Disable(); sl@0: inline void NotificationCancel(); sl@0: }; sl@0: sl@0: // timer class, also responsible for writing logs sl@0: class CTimerLogger : public CBase sl@0: { sl@0: sl@0: public: sl@0: static CTimerLogger* NewL(const TFileName& aLogFile); sl@0: ~CTimerLogger(); sl@0: inline TInt MeasureStart(); sl@0: inline TInt MeasureEnd(); sl@0: inline TBool Timing(); sl@0: TInt Log(const TDesC& aDes, TBool aIsLine = ETrue); sl@0: TInt LogAndPrint(const TDesC& aDes, TBool aIsLine = ETrue); sl@0: TInt LogSettingDescription(const TInt aNumFile, const TInt aNumCli, const TUint16 aOption, TBool aNumOpVaries = EFalse); sl@0: TInt LogTestStepTime(TUint aOp, TInt aNum); sl@0: sl@0: private: sl@0: CTimerLogger(); sl@0: void ConstructL(const TFileName& aLogFile); sl@0: sl@0: private: sl@0: TBool iTiming; sl@0: TUint32 iTickNumber; sl@0: TUint iTimeScale; sl@0: TInt iTickPeriod; sl@0: TFileName iLogFile; sl@0: RFs iFs; sl@0: }; sl@0: sl@0: // the conductor of test cases sl@0: class CTestExecutor : public CBase sl@0: { sl@0: sl@0: public: sl@0: CTestExecutor(TTestSetting& aSetting); sl@0: ~CTestExecutor(); sl@0: sl@0: inline void SetTestSetting(TTestSetting& aSetting); sl@0: inline void LogDescription(); sl@0: sl@0: void RunTestCaseL(); sl@0: static void KillAllTestThreads(); sl@0: sl@0: private: sl@0: TTestSetting iTestSetting; sl@0: sl@0: }; sl@0: sl@0: // This class performs file operations sl@0: class CFileOperator : public CBase sl@0: { sl@0: sl@0: public: sl@0: CFileOperator(const TTestSetting& aSetting, RPointerArray& aLoggerArray, RSemaphore* aSmphFT, RSemaphore* aSmphNT); sl@0: ~CFileOperator(); sl@0: void DoChangesL(); sl@0: sl@0: private: sl@0: void DoCreateL(); sl@0: void DoReplaceL(); sl@0: void DoChangeAttL(); sl@0: void DoRenameL(); sl@0: void DoWriteL(); sl@0: void DoResizeL(); sl@0: void DoDeleteL(); sl@0: void DoCreateDirL(); sl@0: void DoRenameDirL(); sl@0: void DoDeleteDirL(); sl@0: void DoMixedOperationsL(); sl@0: sl@0: void DoManyChangesOnSingleFileL(); sl@0: void DoSmallChangesOnManyFilesL(); sl@0: sl@0: void MesureStartsAll(); sl@0: void WaitForSignalsAll(); sl@0: sl@0: void TestStepPrepare(TUint aOp); sl@0: void TestStepFinish(TUint aOp); sl@0: sl@0: private: sl@0: // test case will use the number iFirstFile and iNumFiles to generate test file names. sl@0: // For example: sl@0: // if iFirstFile = 0 and iNumFiles = 100, the test files will be 0000.tst, 0001.tst ... 0099.tst sl@0: // if iFirstFile = 21 and iNumFiles = 200, the test files will be 0021.tst, 0022.tst ... 0220.tst sl@0: // sl@0: // When doing rename or replace test, the new names for test will be the biggest existing file sl@0: // number + 1 to the number + iNumFiles. sl@0: // As a result, in the case of if iFirstFile = 0 and iNumFiles = 100: sl@0: // The exsting files should be 0000.tst ... 0099.tst sl@0: // Rename or Replace test will use the new names 0100.tst ... 0199.tst to replace or rename the sl@0: // existing files. sl@0: TInt iFirstFile; sl@0: sl@0: // Number of files for operating. sl@0: // Note: in "Large number changes to a single file" case, this indicates the number of changes made on the single file. sl@0: TInt iNumFiles; sl@0: TInt iNumCli; sl@0: TUint16 iOption; sl@0: const TUint* iCurrentOp; sl@0: sl@0: RPointerArray iLoggers; sl@0: RSemaphore* iSmphS; // Use for signaling Notification threads sl@0: RSemaphore* iSmphW; // Use for waiting signal from Notification threads sl@0: sl@0: RFs iFs; sl@0: }; sl@0: sl@0: // an operator to monitor notification watcher and test stopper sl@0: class CNotifyOperator : public CBase sl@0: { sl@0: sl@0: public: sl@0: CNotifyOperator(const TTestSetting& aSetting, RSemaphore* aSmphFT, RSemaphore* aSmphNT, CTimerLogger* aLogger); sl@0: ~CNotifyOperator(); sl@0: sl@0: void StartOperationL(); sl@0: sl@0: private: sl@0: void LogNotificationNumbers(TInt aNumNoti, TInt aNumIter, TInt aNumOverflow); sl@0: void LogTestResult(TInt aCounter, TInt aMeanCounter, TInt aOFCounter); sl@0: void TestChangeReport(TInt aNumChanges); sl@0: sl@0: private: sl@0: TInt iNumFiles; sl@0: TUint16 iOption; sl@0: const TUint* iCurrentOp; sl@0: sl@0: CTimerLogger* iLogger; sl@0: RSemaphore* iSmphS; // Use for signaling file operation thread sl@0: RSemaphore* iSmphW; // Use for waiting signal from file operation thread sl@0: }; sl@0: sl@0: // this class is responsible for handling notifications sl@0: class CNotifyWatcher : public CActive sl@0: { sl@0: friend class CNotifyOperator; sl@0: sl@0: public: sl@0: static CNotifyWatcher* NewL(TInt aNumFiles, TUint16 aOption, TUint aCurrentOp, CTimerLogger* aLogger); sl@0: ~CNotifyWatcher(); sl@0: sl@0: void DoCancel(); sl@0: void RunL(); sl@0: sl@0: void RequestNotification(); sl@0: sl@0: void Reset(TUint aOp); sl@0: sl@0: private: sl@0: CNotifyWatcher(TInt aNumFiles, TUint16 aOption, TUint aCurrentOp, CTimerLogger* aLogger); sl@0: void ConstructL(); sl@0: sl@0: void FullDirectoryScanL(RArray& aArray); sl@0: void MakeChangeRecordL(RArray& aArray); sl@0: TBool CompareEntry(const TEntry& aEntry1, const TEntry& aEntry2); sl@0: sl@0: void AddLotsOfFilters(); sl@0: sl@0: void RequestNotificationEnhanced(); sl@0: void RequestNotificationOriginal(); sl@0: sl@0: void HandleNotification(TBool aLastTime); sl@0: sl@0: void HandleNotificationEnhanced(TBool aLastTime); sl@0: void HandleNotificationOriginal(TBool aLastTime); sl@0: sl@0: void ResetMdsFSPStatus(); sl@0: void RequestNotificationPlugin(); sl@0: void HandleNotificationPlugin(TBool aLastTime); sl@0: sl@0: private: sl@0: TInt iCounter; sl@0: TInt iMeanCounter; sl@0: TInt iOverflowCounter; sl@0: sl@0: TUint iCurrentOp; sl@0: TInt iNumFiles; sl@0: TUint16 iOption; sl@0: sl@0: RArray iEntries; sl@0: RArray iRecords; // this is the output we produce sl@0: sl@0: CTimerLogger* iLogger; sl@0: sl@0: CFsNotify* iNotify; sl@0: sl@0: TMdsFSPStatusPckg iPluginStatusPkg; sl@0: CMdsPluginControl iPlugin; sl@0: sl@0: RFs iFs; sl@0: }; sl@0: sl@0: // An AO aims for stopping the Active Scheduler when test finish sl@0: class CTestStopper : public CActive sl@0: { sl@0: sl@0: public: sl@0: CTestStopper(); sl@0: ~CTestStopper(); sl@0: sl@0: void DoCancel(); sl@0: void RunL(); sl@0: sl@0: void StartWaitingForFile(); sl@0: sl@0: private: sl@0: TFileName iTestEndFile; sl@0: RFs iFs; sl@0: }; sl@0: sl@0: #include "t_notify_perf.inl"