lowlevellibsandfws/pluginfw/Framework/DiscovererTest/t_discoverer.cpp
changeset 0 e4d67989cc36
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lowlevellibsandfws/pluginfw/Framework/DiscovererTest/t_discoverer.cpp	Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,2485 @@
+// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "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:
+// This file contains test classes and their implementations
+// to test production class CDiscoverer. Where necessary stubs
+// are implemented to help in writing test harness using RTest.
+// 
+//
+
+#include "Discoverer.h"
+#include "EComErrorCodes.h"
+#include "ImplementationInformation.h"
+#include "DiscovererObserver.h"
+#include "../EcomTestUtils/EcomTestUtils.h"
+#include "EComUidCodes.h"
+#include "RegistryData.h"
+#include "DriveInfo.h"
+
+#include <ecom/ecompanics.h>
+#include <e32test.h>
+#include <bautils.h>
+#include <s32file.h>
+#include <barsread2.h>
+#include <e32uid.h>
+#include <startup.hrh>
+#include "baspi.h"
+#include <sacls.h>
+
+
+//New RSC based plugins
+_LIT(KNewResourceFileName,		 		"C:\\resource\\plugins\\EComExample5.rsc");
+_LIT(KNewExampleDllFileName,	 		"C:\\sys\\bin\\EComExample5.dll");
+_LIT(KNewResourceFileNameOnZ,   		"z:\\RAMOnly\\EComExample5.rsc");
+_LIT(KNewExampleDllFileNameOnZ, 		"z:\\RAMOnly\\EComExample5.dll");
+_LIT(KNewExampleDllFileNameOnly,		"EComExample5.dll");
+_LIT(KNewResourceSearchPath,			"\\resource\\plugins\\*");
+//PlugIn3 RSC based plugins
+_LIT(KPlugIn3ResourceFileName,		 		"C:\\resource\\plugins\\EComExample12.rsc");
+_LIT(KPlugIn3ExampleDllFileName,	 		"C:\\sys\\bin\\EComExample12.dll");
+_LIT(KPlugIn3ResourceFileNameOnZ,   		"z:\\RAMOnly\\EComExample12.rsc");
+_LIT(KPlugIn3ExampleDllFileNameOnZ, 		"z:\\RAMOnly\\EComExample12.dll");
+_LIT(KPlugIn3ExampleDllFileNameOnly,		"EComExample12.dll");
+
+//Old DLL based plugins
+
+// spi test file
+_LIT(KEComSpiTestFilePathAndName, "Z:\\Test\\Data\\EcomTest.spi");
+_LIT(KEComSpiTestFilePlugIn3PathAndName, "Z:\\Test\\Data\\EcomTestType3.spi");
+// file name detremined from example spi file
+_LIT(KEComSpiTestFileDllPathAndName, "Z:\\sys\\bin\\EComExample5.dll");
+_LIT(KEComSpiTestFilePlugIn3DllPathAndName, "Z:\\sys\\bin\\EComExample12.dll");
+
+// spi file
+_LIT(KEComSPIFilePathAndName, "Z:\\private\\10009D8F\\Ecom.spi");
+
+const TInt KOneSecond = 1000000;
+
+LOCAL_D RFs	TheFs;
+
+LOCAL_D RTest test(_L("t_discoverer.exe"));
+
+LOCAL_D CTrapCleanup* 	  TheTrapCleanup 	 = NULL;
+
+LOCAL_D CActiveScheduler* TheActiveScheduler = NULL;
+
+// Used for supressing warning in OOM tests
+#define __UNUSED_VAR(var) var = var
+
+// Used for OOM test
+#define TEST_OOM_ERR if(err == KErrNoMemory) User::Leave(err)
+
+/**
+Stub classes are provided to act as replacement members for the class
+under test. This ensures the test class is constructed correctly and its
+behaviour is also correct within the context of the test. It allows the
+class to be tested in isolation. Other tests are available that test the
+interoperability of the class
+*/
+class CObserverStub : public CBase, public MDiscovererObserver
+{
+public:
+	enum OSState
+		{
+		OSS_Undefined,
+		OSS_NoPlugins,
+		OSS_CriticalPlugins,
+		OSS_DiscoverNonCriticalPlugins,
+		OSS_AllPlugins
+		};
+	static CObserverStub* NewL();
+	virtual ~CObserverStub();
+
+	// Inherited from MDiscovererObserver
+	virtual void DiscoveriesBegin();
+	virtual void RegisterDiscoveryL(const TDriveName& aDrive,CPluginBase*& aDirEntry,TBool aDatFileExists);
+	virtual void DiscoveriesComplete(TBool aSuccessful, TPluginProcessingTypeIdentifier aProcessingType);
+	virtual void DriveRemovedL(TDriveUnit aDrive);
+	virtual void DriveReinstatedL(TDriveUnit aDrive);
+	virtual void DriveIsSpiBasedL(const TDriveUnit& /*aDrive*/){}
+	virtual TBool NotifiedWithErrorCode(TInt aError);
+	virtual TBool IsAnyDllRegisteredWithDriveL(const TDriveUnit aDrive) const;
+	virtual void SetDiscoveryFlagL(const TDriveUnit &aDrive);
+	virtual void LanguageChangedL(TBool& aLanguageChanged);
+
+
+	// Result verifing methods
+	TBool IsDriveMounted(const TDriveUnit aDrive);
+	TBool IsEntryProcessed(CPluginBase*& aDirEntry);
+	//TBool IsSpiEntryProcessed(const TEntry& aEntry);
+	TBool IsDiscoveriesCompleteSuccessfully();
+	void SetDiscoverer(CDiscoverer* aDiscoverer);
+	OSState GetState();
+
+private:
+	CObserverStub();
+
+private:
+	/** Base class ecom entry */
+	CPluginBase* iEntryBase;
+
+	/** Information of the dll which contains interface implementations */
+	//TEComEntryDetails		iEntry;
+
+	/** Information of the spi file which contains interface implementations */
+	//TEComSpiResourceEntryDetails		iSpiEntry;
+
+	/** iDriveUnit is drive mounted */
+	TDriveUnit	iDriveUnit;
+
+	/** Flag to indicate whether iDriveUnit is mounted or not */
+	TBool		iDriveMounted;
+
+	/** Flag to indicate whether iEntry is processed or not */
+	TBool		iEntryProcessed;
+
+	/** Flag to indicate whether iSpiEntry is processed or not */
+	TBool		iSpiEntryProcessed;
+
+	/** Flag to indicate whether Discovery process is Complete or not */
+	TBool		iDiscoveriesComplete;
+
+	/** The current start-up state of this object */
+	OSState     iState;
+
+	/** A reference to the CDiscoverer object that this class is observing*/
+	CDiscoverer* iDiscoverer;
+};  // End of CObserverStub declaration
+
+
+/**
+The TDiscoverer_StateAccessor class allows to access the private and protected
+members of production code class CDiscoverer, as its a friend class.
+*/
+class TDiscoverer_StateAccessor
+	{
+public:
+
+	// Auxiliary functions that provide access to
+	// CDiscoverer private/protected members
+	void ScanDirectoryL(CDiscoverer& aDiscoverer, TDriveUnit aDriveUnit);
+	void ScanDirectoryCancel(CDiscoverer& aDiscoverer);
+	void CompleteNotificationProcessing(CDiscoverer& aDiscoverer);
+	void ValidateEntryL(CDiscoverer& aDiscoverer,
+						const TEntry& aEntry,
+						const TDriveName& aDriveName,
+						CPluginBase*& aEntryToFill,
+						TBool aIsRO);
+	void ValidateEntryL(CDiscoverer& aDiscoverer,
+						RResourceArchive& aRscArchive,
+						CPluginBase*& aEntryToFill);
+	void ProcessEntryL(CDiscoverer& aDiscoverer,const TDriveName& aDrive, CPluginBase*& aEntry, TBool aDatFileExists);
+	void DriveMountedL(CDiscoverer& aDiscoverer, const TDriveUnit aDrive);
+	void DriveUnmountedL(CDiscoverer& aDiscoverer, const TDriveUnit aDrive);
+	void SwiChangeNotificationL(CDiscoverer& aDiscoverer, TInt aSwiOperation);
+	void IdleScanningTimerRunErrorL(CDiscoverer& aDiscoverer, TInt aError);
+	void DirChangeNotifierRunErrorL(CDiscoverer& aDiscoverer, TInt aError);
+	void SwiChangeNotifierRunError(CDiscoverer& aDiscoverer, TInt aError);
+
+	// Verification functions to check the state of CDiscoverer object against tests
+	TBool IsDriveMounted(CDiscoverer& aDiscoverer, const TDriveUnit aDrive);
+	TBool IsDiscovererActive(CDiscoverer& aDiscoverer);
+	TBool IsDirectoryScanCancelled(CDiscoverer& aDiscoverer);
+	TBool IsScanDirectoryComplete(CDiscoverer& aDiscoverer);
+	TBool IsScanDirectoryPending(CDiscoverer& aDiscoverer, TDriveUnit aDrive);
+	TUint PendingDriveListCount(CDiscoverer& aDiscoverer);
+	CDiscoverer::TDiscovererState State(CDiscoverer& aDiscoverer);
+	CObserverStub::OSState GetDiscovererObserverState(CDiscoverer& aDiscoverer);
+	void ScanDriveL(CDiscoverer& aDiscoverer, TDriveUnit aDrive,  TBool aIsRO);
+	void LanguageChangedL(CDiscoverer& aDiscoverer);
+	};
+
+/**
+Scans plugin directories
+
+@param		aDiscoverer The CDiscoverer class object under test
+@return		void
+*/
+void TDiscoverer_StateAccessor::ScanDirectoryL(CDiscoverer& aDiscoverer, TDriveUnit aDriveUnit)
+	{
+	aDiscoverer.RediscoveryScanDirectoryL(aDriveUnit);
+	}
+
+/**
+Stops scanning of the plugin directories
+
+@param		aDiscoverer The CDiscoverer class object under test
+*/
+void TDiscoverer_StateAccessor::ScanDirectoryCancel(CDiscoverer& aDiscoverer)
+	{
+	aDiscoverer.ScanDirectoryCancel();
+	}
+
+/**
+Signals that the directory change has been fully processed.
+
+@param		aDiscoverer The CDiscoverer class object under test
+*/
+void TDiscoverer_StateAccessor::CompleteNotificationProcessing(CDiscoverer& aDiscoverer)
+	{
+	aDiscoverer.CompleteNotificationProcessing();
+	}
+
+/**
+Verifies that the discovered entry is valid.
+Used to test the Interface Implementation Collection entry
+
+@param		aDiscoverer The CDiscoverer class object under test
+@param		aEntry The plugin name
+@param		aDriveName The drive containing the entry
+@param		aEntryToFill On return points to complete
+			plugin file name(with path) i.e. aPath + aEntry
+*/
+void TDiscoverer_StateAccessor::ValidateEntryL(CDiscoverer& aDiscoverer,
+											   const TEntry& aEntry,
+											   const TDriveName& aDriveName,
+											   CPluginBase*& aEntryToFill,
+											   TBool aIsRO)
+	{
+	aDiscoverer.ValidateEntryL(aEntry, aDriveName, aEntryToFill, aIsRO);
+	}
+
+/**
+Verifies that the discovered entry is valid.
+Used to test the Interface Implementation Collection entry
+
+@param		aDiscoverer The CDiscoverer class object under test
+@param		aRscArchive reference to the resource archive
+@param		aEntryToFill On return points to complete
+			plugin file name(with path) i.e. aPath + aEntry
+*/
+void TDiscoverer_StateAccessor::ValidateEntryL(CDiscoverer& aDiscoverer,
+											RResourceArchive& aRscArchive,
+											CPluginBase*& aEntryToFill)
+	{
+	aDiscoverer.ValidateEntryL(aRscArchive,aEntryToFill);
+	}
+/**
+Registers an Interface Implementation Collection
+
+@param		aDiscoverer The CDiscoverer class object under test
+@param		aEntry This is the plugin name that needs to be registered
+*/
+void TDiscoverer_StateAccessor::ProcessEntryL(CDiscoverer& aDiscoverer,const TDriveName& aDrive,
+										  CPluginBase*& aEntry, TBool aDatFileExists)
+	{
+	aDiscoverer.ProcessEntryL(aDrive,aEntry,aDatFileExists);
+	}
+
+/**
+Notifies the discoverer of an SWI operation change
+
+@param		aDiscoverer The CDiscoverer class object under test
+@param		aSwiOperation This new SWI state
+*/
+void TDiscoverer_StateAccessor::SwiChangeNotificationL(CDiscoverer& aDiscoverer, TInt aSwiOperation)
+	{
+	aDiscoverer.SwiChangeNotificationL(aSwiOperation);
+	}
+
+/**
+Signals that a drive is available
+
+@param		aDiscoverer The CDiscoverer class object under test
+@param		aDrive Drive that needs to be mounted
+*/
+void TDiscoverer_StateAccessor::DriveMountedL(CDiscoverer& aDiscoverer,
+											  const TDriveUnit aDrive)
+	{
+	aDiscoverer.DriveMountedL(aDrive);
+	}
+
+/**
+Signals that a drive is unavailable
+
+@param		aDiscoverer The CDiscoverer class object under test
+@param		aDrive Drive that needs to be unmounted/removed
+*/
+void TDiscoverer_StateAccessor::DriveUnmountedL(CDiscoverer& aDiscoverer,
+												const TDriveUnit aDrive)
+	{
+	aDiscoverer.DriveUnmountedL(aDrive);
+	}
+
+/**
+Checks whether CDiscoverer object has successfully completed with
+the scanning of the plugin directories on all drives
+
+@param		aDiscoverer The CDiscoverer class object under test
+@return		true if notification has been processed on all drives.
+			false if there is notification processing pending on any drive
+*/
+TBool TDiscoverer_StateAccessor::IsScanDirectoryComplete(CDiscoverer& aDiscoverer)
+	{
+	// check state of discoverer to see if all pending drives have been scanned.
+	return(aDiscoverer.State() == CDiscoverer::EDisc_AllPluginsDisc);
+	}
+
+/**
+Checks whether a notification has been signaled but not processed on specified drive.
+
+Error Condition	: Leaves with KErrNotFound if the drive is not registered.
+@param		aDiscoverer The CDiscoverer class object under test
+@param		aDrive The drive to check
+@return		true if notification has been processed on the specified drive.
+			false if notification processing is pending
+*/
+TBool TDiscoverer_StateAccessor::IsScanDirectoryPending(CDiscoverer& aDiscoverer, TDriveUnit aDrive)
+	{
+	if(aDiscoverer.iScanningTimer->iPendingDriveList.Find(aDrive)!=KErrNotFound)
+		{
+		return ETrue;
+		}
+	else
+		{
+		return EFalse;
+		}
+	}
+
+/**
+Checks the current count of drives in the list waiting for processing.
+
+@param		aDiscoverer The CDiscoverer class object under test
+@return		TUint
+*/
+TUint TDiscoverer_StateAccessor::PendingDriveListCount(CDiscoverer& aDiscoverer)
+	{
+	return(aDiscoverer.iScanningTimer->iPendingDriveList.Count());
+	}
+
+/**
+Checks that CDiscoverer object is not scanning the plugin directories.
+
+@param		aDiscoverer The CDiscoverer class object under test
+@return		true if plugin dirctory scanning is stopped.
+*/
+TBool TDiscoverer_StateAccessor::IsDirectoryScanCancelled(CDiscoverer& aDiscoverer)
+	{
+	if(!aDiscoverer.iDirScanner)
+		{
+		return ETrue;
+		}
+	return EFalse;
+	}
+
+/**
+Checks that CDiscoverer object is currently activated for the plugin dir scanning
+
+@param		aDiscoverer The CDiscoverer class object under test
+@return		true if Discoverer object is tracking changes in the plugin directories in each drive.
+*/
+TBool TDiscoverer_StateAccessor::IsDiscovererActive(CDiscoverer& aDiscoverer)
+	{
+	//Return ETrue if both iScanningTimer & directory notifier(s) are active
+	TBool isActive = ETrue;
+
+	  for(TInt index = 0; index <aDiscoverer.iRscDirNotifierList.Count(); index++)
+	  	{
+	  	if(!(aDiscoverer.iRscDirNotifierList[index]&& aDiscoverer.iRscDirNotifierList[index]->IsActive()))
+			{
+			// iRscDirNotifierList should be active, as each active object on list is constantly
+			// looking for changes in the plugin directories in each drive.
+			isActive = EFalse;
+			break;
+			}
+		}
+	return isActive;
+	}
+
+/**
+Verifies whether given drive is registered
+
+@param		aDiscoverer The CDiscoverer class object under test
+@param		aDrive Drive that needs to be verified for registration
+@return		return true if given drive is installed
+*/
+TBool TDiscoverer_StateAccessor::IsDriveMounted(CDiscoverer& aDiscoverer,
+												const TDriveUnit aDrive)
+	{
+	TBool isMounted = ETrue;
+	if(aDiscoverer.iDrivesDiscovered.Find(aDrive) == KErrNotFound)
+		{
+		isMounted = EFalse;
+		}
+	return isMounted;
+	}
+
+/**
+Scans plugin directories
+
+@param		aDiscoverer The CDiscoverer class object under test
+@param 		aDrive	The drive which is scanned
+@param		aIsRO	Whether the drive is ready-only
+@return		true if plugin directorie in each drive get scaned successfully
+*/
+void TDiscoverer_StateAccessor::ScanDriveL(CDiscoverer& aDiscoverer, TDriveUnit aDrive,  TBool aIsRO)
+	{
+	return aDiscoverer.iDirScanner->ScanDriveL(aDrive, aIsRO);
+	}
+void TDiscoverer_StateAccessor::LanguageChangedL(CDiscoverer& aDiscoverer)
+	{
+	aDiscoverer.LanguageChangeNotificationL();
+	}
+/**
+Retrieve the object's current state.
+
+@param		aDiscoverer The CDiscoverer class object under test
+@return 	TDiscovererState the current state of the CDiscoverer
+class object under test
+*/
+CDiscoverer::TDiscovererState TDiscoverer_StateAccessor::State(CDiscoverer& aDiscoverer)
+	{
+	return aDiscoverer.State();
+	}
+
+CObserverStub::OSState TDiscoverer_StateAccessor::GetDiscovererObserverState(CDiscoverer& aDiscoverer)
+	{
+	CObserverStub* discovererObserver =
+		static_cast<CObserverStub*>(&aDiscoverer.iDiscovererObserver);
+	return discovererObserver->GetState();
+	}
+
+/**
+Call the CIdleScanningTimer RunError funtion
+
+@param		aDiscoverer The CDiscoverer class object under test
+@param 		aError The error code to pass to the RunError function
+*/
+void TDiscoverer_StateAccessor::IdleScanningTimerRunErrorL(CDiscoverer& aDiscoverer, TInt aError)
+	{
+	aDiscoverer.iScanningTimer->RunError(aError);
+	}
+
+/**
+Call the CDirChangeNotifier RunError funtion
+
+@param		aDiscoverer The CDiscoverer class object under test
+@param 		aError The error code to pass to the RunError function
+*/
+void TDiscoverer_StateAccessor::DirChangeNotifierRunErrorL(CDiscoverer& aDiscoverer, TInt aError)
+	{
+	aDiscoverer.iRscDirNotifierList[0]->RunError(aError);
+	}
+
+/**
+Call the CSwiChangeNotifier RunError funtion
+
+@param		aDiscoverer The CDiscoverer class object under test
+@param 		aError The error code to pass to the RunError function
+*/
+void TDiscoverer_StateAccessor::SwiChangeNotifierRunError(CDiscoverer& aDiscoverer, TInt aError)
+	{
+	aDiscoverer.iSwiChangeNotifier->RunError(aError);
+	}
+
+/**
+Creates an instance of CObserverStub class.
+
+@return		The new'ed object.
+*/
+CObserverStub* CObserverStub::NewL()
+	{
+	return new(ELeave) CObserverStub();
+	}
+
+/**
+Destructor
+
+@post		This object is properly destroyed.
+*/
+CObserverStub::~CObserverStub()
+	{
+	// do nothing;
+	}
+
+/**
+Default constructor.
+
+@post		The object is properly constructed.
+*/
+CObserverStub::CObserverStub()
+				:CBase(),
+				iDriveUnit(EDriveC),
+				iDriveMounted(EFalse),
+				iEntryProcessed(EFalse),
+				iSpiEntryProcessed(EFalse),
+				iDiscoveriesComplete(EFalse),
+				iState(OSS_NoPlugins)
+	{
+	// do nothing;
+	}
+
+/**
+MDiscovererObserver callback method, to signal that a discovery
+session is starting.
+*/
+void CObserverStub::DiscoveriesBegin()
+	{
+	iDiscoveriesComplete = EFalse;
+	}
+
+void CObserverStub::SetDiscoveryFlagL(const TDriveUnit & /*aDrive*/)
+	{
+	iDiscoveriesComplete = ETrue;
+	}
+/**
+MDiscovererObserver callback method to register an Ecom Spi file.
+
+@param		aEntry The Ecom file  that needs to be registered
+*/
+void CObserverStub::RegisterDiscoveryL(const TDriveName& /* aDriveName */,CPluginBase*& aEntry,TBool /* aDatFileExists*/)
+	{
+	iEntryBase = aEntry;
+	iSpiEntryProcessed = ETrue;
+	}
+
+/**
+MDiscovererObserver callback method, to signal that a discovery
+session is complete.
+
+@param		aSuccessful Indicates discoveries process completed successfully or not
+@param		aProcessingType indicates the type of processing for plugins
+			for ensuring that plugins are not processed multiple times
+			during start-up phase
+*/
+void CObserverStub::DiscoveriesComplete(TBool aSuccessful, TPluginProcessingTypeIdentifier aProcessingType)
+	{
+	iDiscoveriesComplete = aSuccessful;
+
+	switch(iState)
+		{
+		case OSS_NoPlugins:
+			if(aProcessingType == EPluginProcessingTypeCriticalOnly &&
+			   iDiscoverer->State() == CDiscoverer::EDisc_CriticalPluginsDisc)
+				{
+				iState = OSS_CriticalPlugins;
+				}
+			else if(aProcessingType == EPluginProcessingTypeAll &&
+				    iDiscoverer->State() == CDiscoverer::EDisc_AllPluginsDisc)
+				{
+				iState = OSS_AllPlugins;
+				}
+			break;
+		case OSS_CriticalPlugins:
+			if(aProcessingType == EPluginProcessingTypeNonCriticalOnly &&
+			   iDiscoverer->State() == CDiscoverer::EDisc_AllPluginsDisc)
+				{
+				iState = OSS_AllPlugins;
+				}
+			break;
+		}
+	}
+
+/**
+Verifies whether given plugin entry is registered
+
+@param		aDirEntry The Ecom plugin that to be checked for registration.
+@return		true if given plugin is registered
+*/
+TBool CObserverStub::IsEntryProcessed(CPluginBase*& aDirEntry)
+	{
+	if(iEntryProcessed && (iEntryBase->iDllThirdUid == aDirEntry->iDllThirdUid))
+		{
+		return ETrue;
+		}
+
+	return EFalse;
+	}
+
+/**
+MDiscovererObserver callback method, to signal that a Drive
+is removed/dismounted.
+
+@param		aDrive The drive that is removed.
+*/
+void CObserverStub::DriveRemovedL(TDriveUnit aDrive)
+	{
+	iDriveMounted = EFalse;
+	iDriveUnit = aDrive;
+	}
+
+/**
+MDiscovererObserver callback method, to signal that a Drive
+is reinstalled.
+
+@param		aDrive The drive that is available now.
+*/
+void CObserverStub::DriveReinstatedL(TDriveUnit aDrive)
+	{
+	iDriveMounted = ETrue;
+	iDriveUnit = aDrive;
+	}
+
+/**
+MDiscovererObserver callback method, to signal that
+during a discovery session an error has occured.
+
+@param		aError The notification error code.
+@return		true if aError is one of the acceptable error codes
+*/
+TBool CObserverStub::NotifiedWithErrorCode(TInt aError)
+	{
+	// Test the safe error codes
+	return (aError == KErrNotReady ||		// Drive removed
+			aError == KErrPathNotFound);	// Directory deleted
+	}
+
+/**
+MDiscovererObserver callback method,to retrieve the drive unit's DAT
+file infor.
+
+@param 		aDrive the identifier of the drive to retrieve DAT file infor from.
+@return		ETrue if DAT file exists on the drive unit, otherwise EFlase.
+
+*/
+TBool CObserverStub::IsAnyDllRegisteredWithDriveL(const TDriveUnit /*aDrive*/) const
+	{
+	// To pass the build always returns EFalse to mean no Dll is discovered in the drive,
+	// it is not used in this test.
+	return EFalse;
+	}
+
+/**
+Verification method that checks whether given drive is available
+
+@param		aDrive The drive that to be checked.
+@return		true if given drive is registered
+*/
+TBool CObserverStub::IsDriveMounted(const TDriveUnit aDrive)
+	{
+	TBool mounted = EFalse;
+	if(iDriveMounted && (aDrive == iDriveUnit))
+		{
+		mounted = ETrue;
+		}
+	return mounted;
+	}
+
+/**
+Verification method that checks whether discovery process is completed successfully
+
+@return		true if discovery process is completed successfully
+*/
+TBool CObserverStub::IsDiscoveriesCompleteSuccessfully()
+	{
+	return iDiscoveriesComplete;
+	}
+
+/**
+Returns the current start-up state of this object
+
+@return	    The current start-up state of this object
+*/
+CObserverStub::OSState CObserverStub::GetState()
+	{
+	return iState;
+	}
+
+void CObserverStub::SetDiscoverer(CDiscoverer* aDiscoverer)
+	{
+	iDiscoverer = aDiscoverer;
+	}
+
+void CObserverStub::LanguageChangedL(TBool& aLanguageChanged)
+	{
+	aLanguageChanged = EFalse;
+	}
+class CDiscovererTestShutdown : public CTimer
+	{
+public:
+	inline CDiscovererTestShutdown();
+	inline void ConstructL();
+	inline void StartAfter(TTimeIntervalMicroSeconds32 aTimeInterval);
+
+private:
+	void RunL();
+	};
+
+inline CDiscovererTestShutdown::CDiscovererTestShutdown()
+:CTimer(EPriorityHigh)// Priority set higher than CIdleScanningTimer
+	{
+	CActiveScheduler::Add(this);
+	}
+
+inline void CDiscovererTestShutdown::ConstructL()
+	{
+	CTimer::ConstructL();
+	}
+
+inline void CDiscovererTestShutdown::StartAfter(TTimeIntervalMicroSeconds32 aTimeInterval)
+	{
+	After(aTimeInterval);
+	}
+void CDiscovererTestShutdown::RunL()
+	{
+	CActiveScheduler::Stop();
+	}
+
+/**
+Test class for object CDiscoverer.
+This class provides the parameters and behaviour that
+allows this class to behave normally under a test
+scenario.
+*/
+class CDiscovererTest : public CBase
+	{
+public:
+	static CDiscovererTest* NewL();
+	virtual ~CDiscovererTest();
+
+	void ResumeSuspendTestL();
+	void DriveMountUnmountTestL();
+	void ProcessEntryTestL();
+	void ProcessSpiEntryTestL();
+	void ValidateSpiEntryTestL();
+	void ValidateSpiPluginsTestL();
+	void ValidateEntryTestL();
+	void ProcessEntryPlugIn3TestL();
+	void ProcessSpiEntryPlugIn3TestL();
+	void ValidateSpiEntryPlugIn3TestL();
+	void ValidateEntryPlugIn3TestL();
+	void ScanDirectoryIncrementTestL();
+	void ScanDirectoryTestL();
+	void ScanDirectoryCancelTestL();
+	void StagedDiscoveryStateTransitionTestL();
+	void AllAtOnceDiscoveryStateTransitionTestL();
+	void MultipleNotificationProcessingTestL();
+	void SWINotificationProcessingTestL();
+	void IdleScanningTimerRunErrorL();
+	void DirChangeNotifierRunErrorL();
+	void SwiChangeNotifierRunError();
+	void LanguageChangedNotificationTestL();
+
+private:
+	CDiscovererTest();
+	void ConstructL();
+
+public:
+	/** The instance of the class under test */
+	CDiscoverer* iDiscoverer;
+
+	/** The instance of the state accessor interface */
+	TDiscoverer_StateAccessor* iStateAccessor;
+
+	/** The instance of the observer stub of the CDiscoverer */
+	CObserverStub* iDiscovererObserver;
+
+	/** Unique Id of the ECOM dll */
+	TUid		iDllUid;
+
+	/** The drive on which interface implementations can be found */
+	TDriveUnit	iDriveUnit;
+
+	/** Information on a dll which contains interface implementations */
+	TEntry		iDllEntry;
+
+	/** A shutdown timer to manipulate the Active Scheduler of testing server */
+	CDiscovererTestShutdown	iShutdown;
+
+	CEComCachedDriveInfo* iCachedDriveInfo;
+	};
+
+/**
+Standardised safe construction which
+leaves nothing on the cleanup stack.
+
+@post			CDiscovererTest is fully constructed and initialised
+@return			The new'ed object.
+*/
+CDiscovererTest* CDiscovererTest::NewL()
+	{
+	CDiscovererTest* self = new (ELeave) CDiscovererTest();
+	CleanupStack::PushL( self );
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+/**
+Default constructor.
+
+@post	The object is properly constructed.
+*/
+CDiscovererTest::CDiscovererTest()
+				:CBase(),
+				 iDriveUnit(EDriveC)
+	{
+	TUid uid1 = {0};
+	TUid uid2 = {0};
+
+	iDllUid.iUid	= 0x10009DB6; // Dll Uid for EComRomOnlyExampleOnC.dll
+	iDllEntry.iType = TUidType(uid1, uid2, iDllUid);
+	}
+
+/**
+Destructor.
+
+@post		This object is properly destroyed.
+*/
+CDiscovererTest::~CDiscovererTest()
+	{
+	delete iDiscoverer;
+	delete iStateAccessor;
+	delete iDiscovererObserver;
+	delete iCachedDriveInfo;
+	}
+
+/**
+Standardized 2nd(Initialization) phase of two phase construction.
+Creates supporting class objects for the execution of test.
+
+@post			CDiscovererTest is fully constructed.
+*/
+void CDiscovererTest::ConstructL()
+	{
+	iStateAccessor		= new(ELeave) TDiscoverer_StateAccessor;
+	iDiscovererObserver	= CObserverStub::NewL();
+	iDiscoverer			= CDiscoverer::NewL(*iDiscovererObserver, TheFs);
+	iDiscovererObserver->SetDiscoverer(iDiscoverer);
+	iShutdown.ConstructL();
+	iCachedDriveInfo = CEComCachedDriveInfo::NewL(TheFs);
+	}
+
+/**
+The test executes by first suspending the discoverer then by
+resuming it.
+
+@SYMTestCaseID          SYSLIB-ECOM-CT-0716
+@SYMTestCaseDesc	    Tests for resuming and suspending Discoverer
+@SYMTestPriority 	    High
+@SYMTestActions  	    Suspend if Discoverer is active and then resume. Check for the error conditions(OOM)
+@SYMTestExpectedResults The test must not fail.
+@SYMREQ                 REQ0000
+*/
+void CDiscovererTest::ResumeSuspendTestL()
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-0716 "));
+	// Perform an initial discovery and start the notifiers.
+	iDiscoverer->ProcessSSAEventL(EStartupStateNonCritical);
+
+	TBool isDiscActive = iStateAccessor->IsDiscovererActive(*iDiscoverer);
+	// Notifiers should be active.
+	test(isDiscActive);
+
+	TInt err = iDiscoverer->Suspend();
+	TEST_OOM_ERR;
+	test(err == KErrNone);
+
+	// Notifiers should still be active.
+	isDiscActive = iStateAccessor->IsDiscovererActive(*iDiscoverer);
+	test(isDiscActive);
+
+	// Test that there are no drives pending a scan before we copy the plugin.
+	test(!iStateAccessor->IsScanDirectoryPending(*iDiscoverer, EDriveC));
+
+	// Raise a plugin change notification on C: drive. This simulates a plugin being copied.
+	iDiscoverer->ProcessDNEventL(CDiscoverer::EPluginsModified, EDriveC);
+	iDiscoverer->ProcessDNEventL(CDiscoverer::EPluginsRediscover, EDriveC);
+
+	// Test that the drive we copied the plugin to still has a scan pending.
+	test(iStateAccessor->IsScanDirectoryPending(*iDiscoverer, EDriveC));
+
+	isDiscActive = iStateAccessor->IsDiscovererActive(*iDiscoverer);
+	// Notifiers should still be active.
+	test(isDiscActive);
+
+	// Start Active Scheduler and shut it down in 3 secs, it will launch RunL of timer to process
+	// all pending notification.
+	iShutdown.StartAfter(KOneSecond * 3);
+	CActiveScheduler::Start();
+
+	// Check that notifications have not been processed.
+	test(!iStateAccessor->IsScanDirectoryComplete(*iDiscoverer));
+
+	err = iDiscoverer->Resume();
+	TEST_OOM_ERR;
+	test(err == KErrNone);
+
+	isDiscActive = iStateAccessor->IsDiscovererActive(*iDiscoverer);
+	// Notifiers should still be active.
+	test(isDiscActive);
+
+	// Start Active Scheduler and shut it down in 3 secs, it will launch RunL of timer to process
+	// all pending notification.
+	iShutdown.StartAfter(KOneSecond * 3);
+	CActiveScheduler::Start();
+
+	// Check if notifications have been processed on all drives.
+	test(iStateAccessor->IsScanDirectoryComplete(*iDiscoverer));
+	}
+
+/**
+The test executes by first making the test drive unmounted and
+then testing for Mount and Unmount.
+
+@SYMTestCaseID          SYSLIB-ECOM-CT-0717
+@SYMTestCaseDesc	    Tests for drive mount and unmount
+@SYMTestPriority 	    High
+@SYMTestActions  	    First remove the drive if its already there, then test for Mount then for unmount
+@SYMTestExpectedResults The test must not fail.
+@SYMREQ                 REQ0000
+*/
+void CDiscovererTest::DriveMountUnmountTestL()
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-0717 "));
+	TInt err;
+	TDriveUnit drive(EDriveC);
+	//First remove the drive if its already there, then test for Mount then for unmount
+	if(iStateAccessor->IsDriveMounted(*iDiscoverer, drive))
+		{
+		TRAP(err, iStateAccessor->DriveUnmountedL(*iDiscoverer, drive));
+		TEST_OOM_ERR;
+		test(err == KErrNone);
+		}
+
+	// Drive should not be present
+	test(!iStateAccessor->IsDriveMounted(*iDiscoverer, drive));
+
+	// Test Mount
+	TRAP(err, iStateAccessor->DriveMountedL(*iDiscoverer, drive));
+	TEST_OOM_ERR;
+	test(err == KErrNone);
+
+	// CDiscoverer->DriveMountedL/DriveUnmountedL updates both itself and
+	// DiscovererObserver class for Mount/Unmount of drives. So testing for both
+	test(iStateAccessor->IsDriveMounted(*iDiscoverer, drive));
+	test(iDiscovererObserver->IsDriveMounted(drive));
+
+	// Test Unmount
+	TRAP(err, iStateAccessor->DriveUnmountedL(*iDiscoverer, drive));
+	TEST_OOM_ERR;
+	test(err == KErrNone );
+
+	// CDiscoverer->DriveMountedL/DriveUnmountedL updates both itself and
+	// DiscovererObserver class for Mount/Unmount of drives. So testing for both
+	test(!iStateAccessor->IsDriveMounted(*iDiscoverer, drive));
+	test(!iDiscovererObserver->IsDriveMounted(drive));
+	}
+
+
+/**
+@SYMTestCaseID          SYSLIB-ECOM-UT-3559
+@SYMTestCaseDesc	    Tests for process entry of PLUGIN3 type.
+@SYMTestPriority 	    High
+@SYMTestActions  	    Call CDiscoverer::ProcessEntryL().
+@SYMTestExpectedResults The entry is registered successfully and no leave occurred.
+@SYMEC	                EC43
+*/
+void CDiscovererTest::ProcessEntryPlugIn3TestL()
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-UT-3559 "));
+	CPluginBase* entryBase = NULL;
+	TInt err = KErrNone;
+
+	//This part refers to testing of the entry containing the RSC
+	_LIT(KExampleRscFileNameOnly,"EComExample12.rsc");
+	TDriveName driveName1(iDriveUnit.Name());
+	TParse path1;
+	path1.Set(KNewResourceSearchPath(),NULL,&driveName1);
+	//Creating a entry that represents the Rsc disovered during scanning of \\resource\\plugins
+	TEntry rscEntry;
+	rscEntry.iName = KExampleRscFileNameOnly;
+	rscEntry.iType = TUidType(KNullUid,KUidInterfaceImplementationCollectionInfo,KNullUid);
+	entryBase = CSecurePlugin::NewL(TheFs,rscEntry,driveName1, EFalse);
+	CleanupStack::PushL(entryBase);
+
+	// ProcessEntryL() updates entryToFill with information on a rsc specified by the other params.
+	TRAP(err, iStateAccessor->ProcessEntryL(*iDiscoverer,driveName1,entryBase,ETrue));
+	TEST_OOM_ERR;
+	test(err == KErrNone);
+	CleanupStack::PopAndDestroy(entryBase);
+	}
+
+/**
+@SYMTestCaseID			SYSLIB-ECOM-UT-3560
+@SYMTestCaseDesc 		Check that the ProcessEntryL for spi data works correctly when using PLUGIN3 entries in the spi file.
+@SYMTestPriority 		High
+@SYMTestActions  		Call CDiscoverer::ProcessEntryL().
+@SYMTestExpectedResults ecomtesttype3.spi is processed successfully and no leave occurred.
+@SYMEC					EC43
+*/
+void CDiscovererTest::ProcessSpiEntryPlugIn3TestL()
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-UT-3560 "));
+	TEntry spiEntry;
+	test(TheFs.Entry(KEComSpiTestFilePlugIn3PathAndName, spiEntry) == KErrNone);
+	TParse spiPath;
+	spiPath.Set(KEComSpiTestFilePlugIn3PathAndName, NULL, NULL);
+
+	RResourceArchive resourceArchive;
+	resourceArchive.OpenL(TheFs, KEComSpiTestFilePlugIn3PathAndName);
+	CleanupClosePushL(resourceArchive);
+
+	// check SPI file type
+	TUid type = resourceArchive.Type();
+	test(type == KEcomSpiFileTypeUid);
+
+	// there is only 1 resource file
+	while(!resourceArchive.End())
+		{
+		CPluginBase* entry = CSpiPlugin::NewL(resourceArchive);
+		CleanupStack::PushL(entry);
+
+		TRAPD(err, iStateAccessor->ProcessEntryL(*iDiscoverer,spiPath.Drive(), entry,ETrue));
+		TEST_OOM_ERR;
+		test(err == KErrNone);
+
+		CleanupStack::PopAndDestroy(entry);
+		entry = NULL;
+		}
+	CleanupStack::PopAndDestroy(&resourceArchive);
+	}
+/**
+@SYMTestCaseID          SYSLIB-ECOM-UT-3561
+@SYMTestCaseDesc	    Tests for the reference of the entry containing the DLL of PLUGIN3 type.
+@SYMTestPriority 	    High
+@SYMTestActions  	    Call CDiscoverer::ValidateEntryL(). Check the entry returned.
+@SYMTestExpectedResults The entry is validated successfully and no leave occurred.
+@SYMEC	                EC43
+*/
+void CDiscovererTest::ValidateEntryPlugIn3TestL()
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-UT-3561 "));
+	TInt err = KErrNone;
+
+	//This part refers to testing of the entry containing the RSC
+	_LIT(KExampleRscFileNameOnly,"EComExample12.rsc");
+	TDriveName driveName1(iDriveUnit.Name());
+	CPluginBase *entryToFill1 = NULL;
+	//Creating an entry that represents the Rsc disovered during scanning of \\resource\\plugins
+	TEntry rscEntry;
+	rscEntry.iName = KExampleRscFileNameOnly;
+	rscEntry.iType = TUidType(KNullUid,KUidInterfaceImplementationCollectionInfo,KNullUid);
+
+	TUid dllUid1 = {KDynamicLibraryUidValue};
+	TUid example12Uid = {0x10009E3E};
+	TUidType dllUidType = TUidType(dllUid1,KUidInterfaceImplementationCollection,example12Uid);
+
+	//Now call ValidateEntryL() with this entry containg the rsc
+	TRAP(err,iStateAccessor->ValidateEntryL(*iDiscoverer,rscEntry,driveName1,entryToFill1, EFalse));
+	TEST_OOM_ERR;
+	test(err == KErrNone);
+	test(entryToFill1->iDllThirdUid == dllUidType[2]);
+	TParse dllParse;
+	dllParse.Set(KPlugIn3ExampleDllFileName,NULL,NULL);
+	test(entryToFill1->iDllName->CompareF(dllParse.NameAndExt()) == 0);
+
+	delete entryToFill1;
+	}
+
+/**
+@SYMTestCaseID			SYSLIB-ECOM-UT-3562
+@SYMTestCaseDesc 		Check that the ValidateEntryL for spi data works correctly when using PLUGIN3 entries in the spi file.
+@SYMTestPriority 		High
+@SYMTestActions  		Call CDiscoverer::ValidateEntryL(). Check the entry returned.
+@SYMTestExpectedResults ecomtesttype3.spi file is validated successfully and no leave occurred.
+@SYMEC					EC43
+*/
+void CDiscovererTest::ValidateSpiEntryPlugIn3TestL()
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-UT-3562 "));
+	TEntry spiEntry;
+	test(TheFs.Entry(KEComSpiTestFilePlugIn3PathAndName, spiEntry) == KErrNone);
+	TParse spiPath;
+	spiPath.Set(KEComSpiTestFilePlugIn3PathAndName, NULL, NULL);
+
+	TEntry TestEntry;
+	TUid uid1 = {0x10000079};
+	TUid uid2 = {0x10009D93};
+	TUid uid3 = {0x10009E3E}; // Uid for EComExample12.dll
+	TestEntry.iType = TUidType(uid1, uid2, uid3);
+	TestEntry.iName = KPlugIn3ExampleDllFileNameOnly;
+
+	RResourceArchive resourceArchive;
+	resourceArchive.OpenL(TheFs, KEComSpiTestFilePlugIn3PathAndName);
+	CleanupClosePushL(resourceArchive);
+
+	// check SPI file type
+	TUid type = resourceArchive.Type();
+	test(type == KEcomSpiFileTypeUid);
+
+	// there is only 1 resource file
+	while(!resourceArchive.End())
+		{
+		CPluginBase* entryToFill = NULL;
+		TRAPD(err, iStateAccessor->ValidateEntryL(*iDiscoverer,resourceArchive,entryToFill));
+		CleanupStack::PushL(entryToFill);
+
+		TEST_OOM_ERR;
+		test(err == KErrNone);
+		test(entryToFill->iDllThirdUid == TestEntry.iType[2]);
+
+		TFileName name1(KEComSpiTestFilePlugIn3DllPathAndName);
+		TFileName name2(*(entryToFill->iDllName));
+		name1.LowerCase();
+		name2.LowerCase();
+		TParse dllparse;
+		dllparse.Set(name1,NULL,NULL);
+		test(dllparse.NameAndExt()== name2);
+
+		CleanupStack::PopAndDestroy(entryToFill); // resourceFile, resourceName, entryToFill
+		entryToFill = NULL;
+		}
+	CleanupStack::PopAndDestroy(&resourceArchive);
+	}
+
+/**
+The test executes by Registering an Interface Implementation Collection
+and later verifing it
+
+@SYMTestCaseID          SYSLIB-ECOM-CT-0718
+@SYMTestCaseDesc	    Tests for process entry.
+@SYMTestPriority 	    High
+@SYMTestActions  	    Register an interface implementation collection and later verifies it.
+                        Check for OOM error.
+@SYMTestExpectedResults The test must not fail.
+@SYMREQ                 REQ0000
+*/
+void CDiscovererTest::ProcessEntryTestL()
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-0718 "));
+	CPluginBase* entryBase=NULL;
+	TInt err=KErrNone;
+
+	//This part refers to testing of the entry containing the RSC
+	_LIT(KExampleRscFileNameOnly,"EComExample5.rsc");
+	TDriveName driveName1(iDriveUnit.Name());
+	TParse path1;
+	path1.Set(KNewResourceSearchPath(),NULL,&driveName1);
+	//Creating a entry that represents the Rsc disovered during scanning of \\resource\\plugins
+	TEntry rscEntry;
+	rscEntry.iName=KExampleRscFileNameOnly;
+	rscEntry.iType=TUidType(KNullUid,KUidInterfaceImplementationCollectionInfo,KNullUid);
+	TUid dllUid1 = {KDynamicLibraryUidValue};
+	TUid example5Uid={0x101F847B};
+	TUidType dllUidType=TUidType(dllUid1,KUidInterfaceImplementationCollection,example5Uid);
+	entryBase=CSecurePlugin::NewL(TheFs,rscEntry,driveName1, EFalse);
+	CleanupStack::PushL(entryBase);
+
+	// ProcessEntryL() updates entryToFill with information on a rsc specified by the other params.
+	TRAP(err, iStateAccessor->ProcessEntryL(*iDiscoverer,driveName1,entryBase,ETrue));
+	TEST_OOM_ERR;
+	test(err == KErrNone);
+	CleanupStack::PopAndDestroy(entryBase);
+	entryBase=NULL;
+
+	}
+
+/**
+@SYMTestCaseID		SYSLIB-ECOM-CT-0091
+@SYMTestCaseDesc 	Check that the ProcessEntryL for spi data works correctly.
+@SYMTestPriority 	High
+@SYMTestActions  	Ensure ecomtest.spi can be processed successfully
+					and no leave occurred.
+@SYMTestExpectedResults The test must not fail.
+@SYMREQ REQ3655
+*/
+void CDiscovererTest::ProcessSpiEntryTestL()
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-0091 "));
+	TEntry spiEntry;
+	test(TheFs.Entry(KEComSpiTestFilePathAndName, spiEntry) == KErrNone);
+	TParse spiPath;
+	spiPath.Set(KEComSpiTestFilePathAndName, NULL, NULL);
+
+	RResourceArchive resourceArchive;
+	resourceArchive.OpenL(TheFs, KEComSpiTestFilePathAndName);
+	CleanupClosePushL(resourceArchive);
+
+	// check SPI file type
+	TUid type = resourceArchive.Type();
+	test(type == KEcomSpiFileTypeUid);
+
+	// there is only 1 resource file
+	while(!resourceArchive.End())
+		{
+		CPluginBase* entry = CSpiPlugin::NewL(resourceArchive);
+		CleanupStack::PushL(entry);
+
+		TRAPD(err, iStateAccessor->ProcessEntryL(*iDiscoverer,spiPath.Drive(), entry,ETrue));
+		TEST_OOM_ERR;
+		test(err == KErrNone);
+
+		CleanupStack::PopAndDestroy(entry);
+		entry = NULL;
+		}
+	CleanupStack::PopAndDestroy(&resourceArchive);
+	}
+/**
+The test executes by checking whether discovered plugin entry is valid
+
+@SYMTestCaseID          SYSLIB-ECOM-CT-0719
+@SYMTestCaseDesc	    Tests for plugin that resides on C drive
+@SYMTestPriority 	    High
+@SYMTestActions  	    Tests for the reference of the entry containing in the DLL
+                        Check for OOM error.
+@SYMTestExpectedResults The test must not fail.
+@SYMREQ                 REQ0000
+*/
+void CDiscovererTest::ValidateEntryTestL()
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-0719 "));
+	TInt err=KErrNone;
+
+	//This part refers to testing of the entry containing the RSC
+	_LIT(KExampleRscFileNameOnly,"EComExample5.rsc");
+	TDriveName driveName1(iDriveUnit.Name());
+	TParse path1;
+	CPluginBase *entryToFill1 = NULL;
+	path1.Set(KNewResourceSearchPath(),NULL,&driveName1);
+	//Creating a entry that represents the Rsc disovered during scanning of \\resource\\plugins
+	TEntry rscEntry;
+	rscEntry.iName=KExampleRscFileNameOnly;
+	rscEntry.iType=TUidType(KNullUid,KUidInterfaceImplementationCollectionInfo,KNullUid);
+
+	TUid dllUid1 = {KDynamicLibraryUidValue};
+	TUid example5Uid={0x101F847B};
+	TUidType dllUidType=TUidType(dllUid1,KUidInterfaceImplementationCollection,example5Uid);
+
+	//Now call ValidateEntryL() with this entry containg the rsc
+	TRAP(err,iStateAccessor->ValidateEntryL(*iDiscoverer,rscEntry,driveName1,entryToFill1, EFalse));
+	TEST_OOM_ERR;
+	test(err==KErrNone);
+	test(entryToFill1->iDllThirdUid==dllUidType[2]);
+	TParse dllParse;
+	dllParse.Set(KNewExampleDllFileName,NULL,NULL);
+	test(entryToFill1->iDllName->CompareF(dllParse.NameAndExt())==0);
+
+	delete entryToFill1;
+	}
+
+/**
+@SYMTestCaseID		SYSLIB-ECOM-CT-0092
+@SYMTestCaseDesc 	Check that the ValidateEntryL for spi data works correctly.
+@SYMTestPriority 	High
+@SYMTestActions  	Ensure ecomtest.spi can be validated successfully
+					and no leave occurred.
+@SYMTestExpectedResults The test must not fail.
+@SYMREQ REQ3655
+*/
+void CDiscovererTest::ValidateSpiEntryTestL()
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-0092 "));
+	TEntry spiEntry;
+	test(TheFs.Entry(KEComSpiTestFilePathAndName, spiEntry) == KErrNone);
+	TParse spiPath;
+	spiPath.Set(KEComSpiTestFilePathAndName, NULL, NULL);
+
+	TEntry TestEntry;
+	TUid uid1 = {0x10000079};
+	TUid uid2 = {0x10009D8D};
+	TUid	 uid3 = {0x101F847B}; // Uid for EComExample5.dll
+	TestEntry.iType = TUidType(uid1, uid2, uid3);
+	TestEntry.iName = KNewExampleDllFileNameOnly;
+
+	RResourceArchive resourceArchive;
+	resourceArchive.OpenL(TheFs, KEComSpiTestFilePathAndName);
+	CleanupClosePushL(resourceArchive);
+
+	// check SPI file type
+	TUid type = resourceArchive.Type();
+	test(type == KEcomSpiFileTypeUid);
+
+	// there is only 1 resource file
+	while(!resourceArchive.End())
+		{
+		CPluginBase* entryToFill = NULL;
+		TRAPD(err, iStateAccessor->ValidateEntryL(*iDiscoverer,resourceArchive,entryToFill));
+		CleanupStack::PushL(entryToFill);
+
+		TEST_OOM_ERR;
+		test(err == KErrNone);
+		test(entryToFill->iDllThirdUid == TestEntry.iType[2]);
+
+		TFileName name1(KEComSpiTestFileDllPathAndName);
+		TFileName name2(*(entryToFill->iDllName));
+		name1.LowerCase();
+		name2.LowerCase();
+		TParse dllparse;
+		dllparse.Set(name1,NULL,NULL);
+		test(dllparse.NameAndExt()== name2);
+
+		CleanupStack::PopAndDestroy(entryToFill); // resourceFile, resourceName, entryToFill
+		entryToFill = NULL;
+		}
+	CleanupStack::PopAndDestroy(&resourceArchive);
+	}
+
+/**
+@SYMTestCaseID		SYSLIB-ECOM-CT-0093
+@SYMTestCaseDesc 	Check that there is DLL for each resource in SPI file
+@SYMTestPriority 	High
+@SYMTestActions  	Ensure ecom.spi contents i.e, rsc, actually exist on drive
+@SYMTestExpectedResults The test must not fail.
+@SYMREQ REQ3655
+*/
+void CDiscovererTest::ValidateSpiPluginsTestL()
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-0093 "));
+	__UHEAP_MARK;
+
+	TEntry spiEntry;
+	TBool err = TheFs.Entry(KEComSPIFilePathAndName, spiEntry);
+	// It is possible for ecom.spi file not to exist. If it does not then no testing can be done.
+	if(err != KErrNone)
+		return;
+
+	TParse spiPath;
+	spiPath.Set(KEComSPIFilePathAndName, NULL, NULL);
+
+	//To read the SPI file
+	RResourceArchive resourceArchive;
+	resourceArchive.OpenL(TheFs, KEComSPIFilePathAndName);
+	CleanupClosePushL(resourceArchive);
+	CRegistryData::CDriveData* driveData = NULL;
+	//Check spi file type
+	TUid spiType = resourceArchive.Type();
+	test(spiType == KEcomSpiFileTypeUid);
+
+	while(!resourceArchive.End())
+		{
+		CPluginBase* entryToFill = NULL;
+		TRAPD(err, iStateAccessor->ValidateEntryL(*iDiscoverer,resourceArchive,entryToFill));
+		CleanupStack::PushL(entryToFill);
+
+		TEST_OOM_ERR;
+		test(err == KErrNone);
+
+		CRegistryData::CDllData * dllData=CRegistryData::CDllData::NewLC(*(entryToFill->iDllName),entryToFill->iDllModifiedTime,entryToFill->iDllSecondUid, entryToFill->iDllThirdUid,driveData);
+
+		TBool successful=dllData->ProcessSecurityCheckL();
+		if(!successful)
+		{
+			_LIT(KMessage,"ERROR: Plugin SID Mismatch ERROR for %S.");
+			RDebug::Print(KMessage, entryToFill->iDllName);
+		}
+		test(successful);
+
+		CleanupStack::PopAndDestroy(dllData);
+		CleanupStack::PopAndDestroy(entryToFill);
+		entryToFill=NULL;
+		}
+
+		CleanupStack::PopAndDestroy(&resourceArchive);
+	__UHEAP_MARKEND;
+	}
+
+
+/**
+Scans plugin directories and verifies successfull completion
+
+@SYMTestCaseID          SYSLIB-ECOM-CT-0720
+@SYMTestCaseDesc	    Tests for scanning plugin directories and verifies successfull completion
+@SYMTestPriority 	    High
+@SYMTestActions  	    Scans registered plugin directories from A to Z drive
+@SYMTestExpectedResults The test must not fail.
+@SYMREQ                 REQ0000
+*/
+void CDiscovererTest::ScanDirectoryIncrementTestL()
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-0720 "));
+	TInt err;
+	// Scans registered plugin directories from A to Z drive
+	TEComCachedDriveInfoIterator iter(*iCachedDriveInfo);
+	for(iter.Last(); iter.InRange(); iter.Prev())
+		{
+		TRAP(err, iStateAccessor->ScanDirectoryL(*iDiscoverer,iter.DriveNumber()));
+		TEST_OOM_ERR;
+		test(err == KErrNone);
+		}
+	// After successful completion of ScanDirectoryL, DiscovererObserver is updated
+	// with DiscoveriesComplete successful
+	// DiscovererObserver is a stub class used in place of CRegistrar. Flags are used for the
+	// successfull execution of API
+	test(iDiscovererObserver->IsDiscoveriesCompleteSuccessfully());
+	}
+
+/**
+Stops scaning of plugin directories
+
+@SYMTestCaseID          SYSLIB-ECOM-CT-0722
+@SYMTestCaseDesc	    Tests for stopping of scanning plugin directories
+@SYMTestPriority 	    High
+@SYMTestActions  	    Stops scaning of plugin directories. Check for OOM error.
+@SYMTestExpectedResults The test must not fail.
+@SYMREQ                 REQ0000
+*/
+void CDiscovererTest::ScanDirectoryCancelTestL()
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-0722 "));
+	TRAPD(err, iStateAccessor->ScanDirectoryCancel(*iDiscoverer));
+	TEST_OOM_ERR;
+	test(err == KErrNone);
+	test(iStateAccessor->IsDirectoryScanCancelled(*iDiscoverer));
+	}
+
+/**
+Scaning of plugin directories in Z: drive and C:drive, check these two drives is in drive list
+
+@SYMTestCaseID          SYSLIB-ECOM-UT-1859
+@SYMTestCaseDesc	    Tests for scanning plugin directories in specific drives.
+@SYMTestPriority 	    High
+@SYMTestActions  	    scaning of plugin directories. Check for OOM error.
+@SYMTestExpectedResults The test must not fail.
+@SYMDEF                 DEF088454
+*/
+
+void CDiscovererTest::ScanDirectoryTestL()
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-UT-1859 "));
+	EComPerformance::ResetEComPerfTimeRecords();
+
+	// Do scan on specific drive
+	TRAPD(err, iStateAccessor->ScanDriveL(*iDiscoverer, EDriveZ, ETrue));
+	TEST_OOM_ERR;
+	test(err == KErrNone);
+
+	TRAP(err, iStateAccessor->ScanDriveL(*iDiscoverer, EDriveC, EFalse));
+	TEST_OOM_ERR;
+	test(err == KErrNone);
+
+	// Test record information correct
+	test(EComPerformance::iEComPerfTimeRecordCount == 4);
+	test(EComPerformance::iEComPerfTimeRecords[0].iType == ECDiscovererRediscoveryScanDirectoryL);
+	test(EComPerformance::iEComPerfTimeRecords[0].iInfo == EDriveZ);
+	test(EComPerformance::iEComPerfTimeRecords[1].iType == ECDiscovererRediscoveryScanDirectoryL);
+	test(EComPerformance::iEComPerfTimeRecords[1].iInfo == EDriveZ);
+
+	test(EComPerformance::iEComPerfTimeRecords[2].iType == ECDiscovererRediscoveryScanDirectoryL);
+	test(EComPerformance::iEComPerfTimeRecords[2].iInfo == EDriveC);
+	test(EComPerformance::iEComPerfTimeRecords[3].iType == ECDiscovererRediscoveryScanDirectoryL);
+	test(EComPerformance::iEComPerfTimeRecords[3].iInfo == EDriveC);
+	}
+
+/**
+@SYMTestCaseID		SYSLIB-ECOM-CT-0185
+@SYMTestCaseDesc 	Check that SSA related states transition as expected when discovery is staged
+@SYMTestPriority 	High
+@SYMTestActions  	Use CDiscoverer::ProcessSSAEventL to start discovery in stages i.e. rom only
+then non rom only. Check that the
+CDiscoverer state is transitioning correctly at every step.
+@SYMTestExpectedResults The test must not fail.
+@SYMREQ REQ3655
+*/
+void CDiscovererTest::StagedDiscoveryStateTransitionTestL()
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-0185 "));
+	//After construction check that:
+	//- current state is EDisc_NoPluginsDisc
+	//- registry is empty. i.e. no plugins discovered
+	test(iStateAccessor->State(*iDiscoverer) == CDiscoverer::EDisc_NoPluginsDisc);
+
+	//Call ProcessSSAEvent with state set to various states that will
+	//not cause a transition. Check that:
+	//- current state has not changed
+	iDiscoverer->ProcessSSAEventL(EStartupStateUndefined);
+	test(iStateAccessor->State(*iDiscoverer) == CDiscoverer::EDisc_NoPluginsDisc);
+
+	//Call ProcessSSAEventL with EStartupStateCriticalStatic state.
+	//Check that
+	//- current state is EDisc_CriticalPluginsDisc
+	//- discoverer observer has processed RO plugins
+	iDiscoverer->ProcessSSAEventL(EStartupStateCriticalStatic);
+	test(iStateAccessor->GetDiscovererObserverState(*iDiscoverer) == CObserverStub::OSS_CriticalPlugins);
+	test(iStateAccessor->State(*iDiscoverer) == CDiscoverer::EDisc_CriticalPluginsDisc);
+
+	//Call ProcessSSAEvent with state set to various states that will
+	//not cause a transition. Check that:
+	//- current state has not changed
+	iDiscoverer->ProcessSSAEventL(EStartupStateUndefined);
+	test(iStateAccessor->State(*iDiscoverer) == CDiscoverer::EDisc_CriticalPluginsDisc);
+	iDiscoverer->ProcessSSAEventL(EStartupStateCriticalStatic);
+	test(iStateAccessor->State(*iDiscoverer) == CDiscoverer::EDisc_CriticalPluginsDisc);
+
+	//Call ProcessSSAEventL with EStartupStateNonCritical state. Check that
+	//- current state is EDisc_AllPluginsDisc
+	//- discoverer observer has processed non-RO plugins
+	iDiscoverer->ProcessSSAEventL(EStartupStateNonCritical);
+	test(iStateAccessor->GetDiscovererObserverState(*iDiscoverer) == CObserverStub::OSS_AllPlugins);
+	test(iStateAccessor->State(*iDiscoverer) == CDiscoverer::EDisc_AllPluginsDisc);
+
+	//Call ProcessSSAEvent with state set to various states that will
+	//not cause a transition. Check that:
+	//- current state has not changed
+	iDiscoverer->ProcessSSAEventL(EStartupStateUndefined);
+	test(iStateAccessor->State(*iDiscoverer) == CDiscoverer::EDisc_AllPluginsDisc);
+	iDiscoverer->ProcessSSAEventL(EStartupStateCriticalStatic);
+	test(iStateAccessor->State(*iDiscoverer) == CDiscoverer::EDisc_AllPluginsDisc);
+	iDiscoverer->ProcessSSAEventL(EStartupStateCriticalDynamic);
+	test(iStateAccessor->State(*iDiscoverer) == CDiscoverer::EDisc_AllPluginsDisc);
+	iDiscoverer->ProcessSSAEventL(EStartupStateNonCritical);
+	test(iStateAccessor->State(*iDiscoverer) == CDiscoverer::EDisc_AllPluginsDisc);
+
+	//Call ProcessDNEventL to indicate that current set of plugins is dirty.
+	//Check that:
+	//- current state is EDisc_PluginsDirty
+	iDiscoverer->ProcessDNEventL(CDiscoverer::EPluginsModified, EDriveC);
+	test(iStateAccessor->State(*iDiscoverer) == CDiscoverer::EDisc_PluginsDirty);
+
+	//Call ProcessDNEventL to indicate that a rediscovery should take place.
+	//Check that:
+	//- current state is EDisc_AllPluginsDisc
+	iDiscoverer->ProcessDNEventL(CDiscoverer::EPluginsRediscover, EDriveC);
+	iStateAccessor->CompleteNotificationProcessing(*iDiscoverer);
+	test(iStateAccessor->State(*iDiscoverer) == CDiscoverer::EDisc_AllPluginsDisc);
+	}
+
+/**
+@SYMTestCaseID		SYSLIB-ECOM-CT-0186
+@SYMTestCaseDesc 	Check that SSA related states transition as expected when discovery is all at once
+@SYMTestPriority 	High
+@SYMTestActions  	Use CDiscoverer::ProcessSSAEventL to start discovery all at once. Check that the
+CDiscoverer state is transitioning correctly at every step.
+@SYMTestExpectedResults The test must not fail.
+@SYMREQ REQ3655
+*/
+void CDiscovererTest::AllAtOnceDiscoveryStateTransitionTestL()
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-0186 "));
+	//After construction check that:
+	//- current state is EDisc_NoPluginsDisc
+	//- registry is empty. i.e. no plugins discovered
+	test(iStateAccessor->State(*iDiscoverer) == CDiscoverer::EDisc_NoPluginsDisc);
+
+	//Call ProcessSSAEvent with state set to various states that will
+	//not cause a transition. Check that:
+	//- current state has not changed
+	iDiscoverer->ProcessSSAEventL(EStartupStateUndefined);
+	test(iStateAccessor->State(*iDiscoverer) == CDiscoverer::EDisc_NoPluginsDisc);
+
+	//Call ProcessSSAEventL with EStartupStateNonCritical state. Check that
+	//- current state is EDisc_AllPluginsDisc
+	//- discoverer observer has processed non-RO plugins
+	iDiscoverer->ProcessSSAEventL(EStartupStateNonCritical);
+	test(iStateAccessor->GetDiscovererObserverState(*iDiscoverer) == CObserverStub::OSS_AllPlugins);
+	test(iStateAccessor->State(*iDiscoverer) == CDiscoverer::EDisc_AllPluginsDisc);
+
+	//Call ProcessSSAEvent with state set to various states that will
+	//not cause a transition. Check that:
+	//- current state has not changed
+	iDiscoverer->ProcessSSAEventL(EStartupStateUndefined);
+	test(iStateAccessor->State(*iDiscoverer) == CDiscoverer::EDisc_AllPluginsDisc);
+	iDiscoverer->ProcessSSAEventL(EStartupStateCriticalStatic);
+	test(iStateAccessor->State(*iDiscoverer) == CDiscoverer::EDisc_AllPluginsDisc);
+	iDiscoverer->ProcessSSAEventL(EStartupStateCriticalDynamic);
+	test(iStateAccessor->State(*iDiscoverer) == CDiscoverer::EDisc_AllPluginsDisc);
+	iDiscoverer->ProcessSSAEventL(EStartupStateNonCritical);
+	test(iStateAccessor->State(*iDiscoverer) == CDiscoverer::EDisc_AllPluginsDisc);
+
+	//Call ProcessDNEventL to indicate that current set of plugins is dirty.
+	//Check that:
+	//- current state is EDisc_PluginsDirty
+	iDiscoverer->ProcessDNEventL(CDiscoverer::EPluginsModified, EDriveC);
+	test(iStateAccessor->State(*iDiscoverer) == CDiscoverer::EDisc_PluginsDirty);
+
+	//Call ProcessDNEventL to indicate that a rediscovery should take place.
+	//Check that:
+	//- current state is EDisc_AllPluginsDisc
+	iDiscoverer->ProcessDNEventL(CDiscoverer::EPluginsRediscover, EDriveC);
+	iStateAccessor->CompleteNotificationProcessing(*iDiscoverer);
+	test(iStateAccessor->State(*iDiscoverer) == CDiscoverer::EDisc_AllPluginsDisc);
+	}
+
+/**
+@SYMTestCaseID          SYSLIB-ECOM-UT-1796
+@SYMTestCaseDesc	    Tests multiple notification processing for
+						"INC087110: ECOM rescanning code could miss a drive?" and
+						"DEF088454: [PCB] ECOM CDiscoverer::CIdleScanningTimer::RunL() Performs Unnecessary Tasks"
+@SYMTestPriority 	    High
+@SYMTestActions  	    Create multiple notification request on both single drive and multiple drives.
+						Check if the notifications are ONLY processed on corresponding drive(s) by timer.
+						Check the notifications are processed properly by timer.
+						Check the state of discoverer was set correctly on completion.
+@SYMTestExpectedResults The test must not fail.
+@SYMDEF                 INC087110, DEF088454
+*/
+void CDiscovererTest::MultipleNotificationProcessingTestL()
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-UT-1796 "));
+	TBool pending = EFalse;
+
+	// Multiple notification on single drive:
+	iDiscoverer->ProcessSSAEventL(EStartupStateNonCritical);
+	// Raise multiple notification on C: drive
+	for(TInt num = 0; num < 10; ++num)
+		{
+		iDiscoverer->ProcessDNEventL(CDiscoverer::EPluginsModified, EDriveC);
+		iDiscoverer->ProcessDNEventL(CDiscoverer::EPluginsRediscover, EDriveC);
+		}
+
+	// Check only one pending drive in the list.
+	test(iStateAccessor->PendingDriveListCount(*iDiscoverer) == 1);
+	// Check the pending drive is C: drive
+	pending = iStateAccessor->IsScanDirectoryPending(*iDiscoverer, EDriveC);
+	test(pending);
+
+	// Start Active Scheduler and shut it down in 3 secs, it will launch RunL of timer to process
+	// all pending notification.
+	iShutdown.StartAfter(KOneSecond * 3);
+	CActiveScheduler::Start();
+
+	// Check if notifications have been processed on all drives.
+	test(iStateAccessor->IsScanDirectoryComplete(*iDiscoverer));
+
+	// Multiple notification on multiple drives:
+	iDiscoverer->ProcessSSAEventL(EStartupStateNonCritical);
+	// Raise multiple notification on C: drive
+	for(TInt num = 0; num < 10; ++num)
+		{
+		iDiscoverer->ProcessDNEventL(CDiscoverer::EPluginsModified, EDriveC);
+		iDiscoverer->ProcessDNEventL(CDiscoverer::EPluginsRediscover, EDriveC);
+		}
+#if defined(__WINSCW__) // X: drive on emulator
+	// Raise multiple notification on X: drive
+	for(TInt num = 0; num < 10; ++num)
+		{
+		iDiscoverer->ProcessDNEventL(CDiscoverer::EPluginsModified, EDriveX);
+		iDiscoverer->ProcessDNEventL(CDiscoverer::EPluginsRediscover, EDriveX);
+		}
+
+#else // E: drive on HW
+	// Raise multiple notification on E: drive
+	for(TInt num = 0; num < 10; ++num)
+		{
+		iDiscoverer->ProcessDNEventL(CDiscoverer::EPluginsModified, EDriveE);
+		iDiscoverer->ProcessDNEventL(CDiscoverer::EPluginsRediscover, EDriveE);
+		}
+#endif	// __WINSCW__
+
+	// Check only one pending drive in the list.
+	test(iStateAccessor->PendingDriveListCount(*iDiscoverer) == 2);
+
+	// Check the pending drive are C: and X: on emulator, or C: and E: on hardware.
+	pending = iStateAccessor->IsScanDirectoryPending(*iDiscoverer, EDriveC);
+	test(pending);
+#if defined(__WINSCW__) // X: drive on emulator
+	pending = iStateAccessor->IsScanDirectoryPending(*iDiscoverer, EDriveX);
+	test(pending);
+#else // E: drive on HW
+	pending = iStateAccessor->IsScanDirectoryPending(*iDiscoverer, EDriveE);
+	test(pending);
+#endif	// __WINSCW__
+
+	// Start Active Scheduler and shut it down in 3 secs, it will launch RunL of timer to process
+	// all pending notification.
+	iShutdown.StartAfter(KOneSecond * 3);
+	CActiveScheduler::Start();
+
+	// Check if notifications have been processed on all drives.
+	test(iStateAccessor->IsScanDirectoryComplete(*iDiscoverer));
+	}
+
+/**
+@SYMTestCaseID          SYSLIB-ECOM-UT-3519
+@SYMTestCaseDesc	    Tests notification processing during SWI for
+						PDEF110201: Undesireable interaction between ECOM and SWI
+@SYMTestActions  	    Create notification request on  drives.
+						Check the notifications are not processed by timer if SWI in progress.
+						Check that timer processes pending notifications after SWI completes
+@SYMTestExpectedResults The test must not fail.
+@SYMDEF                 PDEF110201
+*/
+void CDiscovererTest::SWINotificationProcessingTestL()
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-UT-3519 "));
+
+	//Begin SWI
+	iStateAccessor->SwiChangeNotificationL(*iDiscoverer,ESASwisInstall);
+
+	iDiscoverer->ProcessSSAEventL(EStartupStateNonCritical);
+
+	// Raise a notification on C: drive
+	iDiscoverer->ProcessDNEventL(CDiscoverer::EPluginsModified, EDriveC);
+	iDiscoverer->ProcessDNEventL(CDiscoverer::EPluginsRediscover, EDriveC);
+
+	// Start Active Scheduler and shut it down in 3 secs, it will launch RunL of timer to process
+	// all pending notification.
+	iShutdown.StartAfter(KOneSecond * 3);
+	CActiveScheduler::Start();
+
+	// Check that notifications have NOT been processed as SWI is in progress
+	test(!iStateAccessor->IsScanDirectoryComplete(*iDiscoverer));
+
+	//complete SWI
+	iStateAccessor->SwiChangeNotificationL(*iDiscoverer,ESASwisUninstall);
+
+
+#if defined(__WINSCW__) // X: drive on emulator
+	// Raise  notification on X: drive
+	iDiscoverer->ProcessDNEventL(CDiscoverer::EPluginsModified, EDriveX);
+	iDiscoverer->ProcessDNEventL(CDiscoverer::EPluginsRediscover, EDriveX);
+#else // E: drive on HW
+	// Raise notification on E: drive
+	iDiscoverer->ProcessDNEventL(CDiscoverer::EPluginsModified, EDriveE);
+	iDiscoverer->ProcessDNEventL(CDiscoverer::EPluginsRediscover, EDriveE);
+#endif	// __WINSCW__
+
+	// Start Active Scheduler and shut it down in 3 secs, it will launch RunL of timer to process
+	// all pending notification.
+	iShutdown.StartAfter(KOneSecond * 3);
+	CActiveScheduler::Start();
+
+	// Check that notifications have NOT been processed as SWI is not finished
+	test(!iStateAccessor->IsScanDirectoryComplete(*iDiscoverer));
+
+	//finalise SWI
+	iStateAccessor->SwiChangeNotificationL(*iDiscoverer,ESASwisNone);
+
+	// Start Active Scheduler and shut it down in 3 secs, it will launch RunL of timer to process
+	// all pending notification.
+	iShutdown.StartAfter(KOneSecond * 3);
+	CActiveScheduler::Start();
+
+	// Check that notifications have been processed on all drives
+	test(iStateAccessor->IsScanDirectoryComplete(*iDiscoverer));
+
+	//Begin SWI
+	iStateAccessor->SwiChangeNotificationL(*iDiscoverer,ESASwisInstall);
+
+	iDiscoverer->ProcessSSAEventL(EStartupStateNonCritical);
+
+	// Raise a notification
+	iDiscoverer->ProcessDNEventL(CDiscoverer::EPluginsModified,EDriveC);
+	iDiscoverer->ProcessDNEventL(CDiscoverer::EPluginsRediscover,EDriveC);
+
+	// Start Active Scheduler and shut it down in 3 secs, it will launch RunL of timer to process
+	// all pending notification.
+	iShutdown.StartAfter(KOneSecond * 3);
+	CActiveScheduler::Start();
+
+	// Check that notifications have NOT been processed as SWI is in progress
+	test(!iStateAccessor->IsScanDirectoryComplete(*iDiscoverer));
+
+	//Simulate an error in reading the P&S Variable - This should reset the
+	//SWI state to ESASwisNone in the same way as completing SWI
+	iStateAccessor->SwiChangeNotifierRunError(*iDiscoverer,KErrNotFound);
+
+	// Start Active Scheduler and shut it down in 3 secs, it will launch RunL of timer to process
+	// all pending notification.
+	iShutdown.StartAfter(KOneSecond * 3);
+	CActiveScheduler::Start();
+
+	// Check that notifications have been processed on all drives
+	test(iStateAccessor->IsScanDirectoryComplete(*iDiscoverer));
+	}
+
+/**
+Call the TDiscoverer_StateAccessor::IdleScanningTimerRunErrorL funtion
+passing in a reference to the CDiscoverer object and the error code
+to be passed to the CIdleScanningTimer::RunError function
+*/
+void CDiscovererTest::IdleScanningTimerRunErrorL()
+	{
+	iStateAccessor->IdleScanningTimerRunErrorL(*iDiscoverer, EEComPanic_CDiscoverer_CIdleScanningTimer_RunError);
+	}
+
+/**
+Call the TDiscoverer_StateAccessor::IdleScanningTimerRunErrorL funtion
+passing in a reference to the CDiscoverer object and the error code
+to be passed to the CDirChangeNotifier::RunError function
+*/
+void CDiscovererTest::DirChangeNotifierRunErrorL()
+	{
+	iStateAccessor->DirChangeNotifierRunErrorL(*iDiscoverer, EEComPanic_CDiscoverer_CDirChangeNotifier_RunError);
+	}
+
+/**
+Call the TDiscoverer_StateAccessor::IdleScanningTimerRunErrorL funtion
+passing in a reference to the CDiscoverer object and the error code
+to be passed to the CSwiChangeNotifier::RunError function
+*/
+void CDiscovererTest::SwiChangeNotifierRunError()
+	{
+	iStateAccessor->SwiChangeNotifierRunError(*iDiscoverer, KErrNoMemory);
+	}
+/**
+@SYMTestCaseID          SYSLIB-ECOM-UT-3172
+@SYMTestCaseDesc	    Tests language switch notification processing for
+						"CR0902: Enable Dynamic Language Switching in APPARC, ECOM and EIKSTD"
+@SYMTestPriority 	    High
+@SYMTestActions  	    Call ProcessSSAEventL with EStartupStateNonCritical state.
+						Call DriveMountedL to build up drives in system.
+						Call LanguageChangedL to raise multiple notification on all drives in system.
+						Check if the notifications are processed on all drive(s) by timer.
+						Check the notifications are processed properly by timer.
+						Check the state of discoverer was set correctly on completion.
+@SYMTestExpectedResults The test must not fail.
+@SYMDEF                 CR0902
+*/
+void CDiscovererTest::LanguageChangedNotificationTestL()
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-UT-3172 "));
+	TBool pending = EFalse;
+
+	//Call ProcessSSAEventL with EStartupStateNonCritical state
+	iDiscoverer->ProcessSSAEventL(EStartupStateNonCritical);
+
+	if(iStateAccessor->IsDriveMounted(*iDiscoverer, EDriveK))
+		{
+		TRAPD(err, iStateAccessor->DriveUnmountedL(*iDiscoverer, EDriveK));
+		TEST_OOM_ERR;
+		test(err == KErrNone);
+		}
+
+	// Mount drives on system
+	TRAPD(err, iStateAccessor->DriveMountedL(*iDiscoverer, EDriveZ));
+	TEST_OOM_ERR;
+	test(err == KErrNone);
+
+	TRAP(err, iStateAccessor->DriveMountedL(*iDiscoverer, EDriveC));
+	TEST_OOM_ERR;
+	test(err == KErrNone);
+
+#if defined(__WINSCW__) // X: drive on emulator
+	TRAP(err, iStateAccessor->DriveMountedL(*iDiscoverer, EDriveX));
+	TEST_OOM_ERR;
+	test(err == KErrNone);
+#else // E: drive on HW
+	TRAP(err, iStateAccessor->DriveMountedL(*iDiscoverer, EDriveE));
+	TEST_OOM_ERR;
+	test(err == KErrNone);
+#endif
+
+	// Multiple notification on all drives:
+	iStateAccessor->LanguageChangedL(*iDiscoverer);
+
+	// Check three pending drive in the list.
+	test(iStateAccessor->PendingDriveListCount(*iDiscoverer) == 3);
+	// Check the pending drive is Z: drive
+	pending = iStateAccessor->IsScanDirectoryPending(*iDiscoverer, EDriveZ);
+	test(pending);
+
+	// Check the pending drive is C: drive
+	pending = iStateAccessor->IsScanDirectoryPending(*iDiscoverer, EDriveC);
+	test(pending);
+
+#if defined(__WINSCW__) // X: drive on emulator
+	pending = iStateAccessor->IsScanDirectoryPending(*iDiscoverer, EDriveX);
+	test(pending);
+#else // E: drive on HW
+	pending = iStateAccessor->IsScanDirectoryPending(*iDiscoverer, EDriveE);
+	test(pending);
+#endif	// __WINSCW__
+
+	// Start Active Scheduler and shut it down in 3 secs, it will launch RunL of timer to process
+	// all pending notification.
+	iShutdown.StartAfter(KOneSecond * 3);
+	CActiveScheduler::Start();
+
+	// Check if notifications have been processed on all drives.
+	test(iStateAccessor->IsScanDirectoryComplete(*iDiscoverer));
+
+	}
+
+/**
+@SYMTestCaseID          SYSLIB-ECOM-CT-0723
+@SYMTestCaseDesc	    Tests the creation and deletion of CDiscoverer
+@SYMTestPriority 	    High
+@SYMTestActions  	    Create and delete CDiscoverer object,checks for open handles
+@SYMTestExpectedResults The test must not fail.
+@SYMREQ                 REQ0000
+*/
+LOCAL_C void CreateDeleteTestL()
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-0723 CreateDeleteTestL "));
+	//
+	// Tests the Creating and deletion of CDiscoverer
+	// ------------------------------------------------------------------
+	//
+	// Set up for heap leak checking
+	__UHEAP_MARK;
+
+	//Check Thread handles leak
+	TInt startProcessHandleCount = 0;
+	TInt startThreadHandleCount = 0;
+	TInt endProcessHandleCount = 0;
+	TInt endThreadHandleCount = 0;
+
+	RThread rThread;
+	rThread.HandleCount(startProcessHandleCount, startThreadHandleCount);
+
+	//START CREATE DELETE TEST//
+
+	CDiscovererTest* discTest = CDiscovererTest::NewL();
+
+	test(discTest != NULL);
+
+	delete discTest;
+
+	//END CREATE DELETE TEST//
+
+	// Check for open handles
+	rThread.HandleCount(endProcessHandleCount, endThreadHandleCount);
+	test(startThreadHandleCount == endThreadHandleCount);
+
+	//Test ends
+	__UHEAP_MARKEND;
+	}
+
+/**
+@SYMTestCaseID          SYSLIB-ECOM-CT-0724
+@SYMTestCaseDesc	    OOM test for create and delete of CDiscoverer.
+@SYMTestPriority 	    High
+@SYMTestActions  	    Create and delete CDiscoverer object,checks for any memory leak.
+@SYMTestExpectedResults The test must not fail.
+@SYMREQ                 REQ0000
+*/
+LOCAL_C void OOMCreateDeleteTest()
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-0724 OOM CreateDeleteTest "));
+	TInt err;
+	TInt failAt = 1;
+	__UNUSED_VAR(failAt);
+
+	CDiscovererTest* discTest = NULL;
+
+	do
+		{
+		__UHEAP_MARK;
+  		// find out the number of open handles
+		TInt startProcessHandleCount;
+		TInt startThreadHandleCount;
+		RThread().HandleCount(startProcessHandleCount, startThreadHandleCount);
+
+		__UHEAP_SETFAIL(RHeap::EDeterministic, failAt++);
+
+		TRAP(err, discTest = CDiscovererTest::NewL());
+
+		__UHEAP_SETFAIL(RHeap::ENone, 0);
+
+		delete discTest;
+		discTest = NULL;
+
+		// check that no handles have leaked
+		TInt endProcessHandleCount;
+		TInt endThreadHandleCount;
+		RThread().HandleCount(endProcessHandleCount, endThreadHandleCount);
+
+		test(startProcessHandleCount == endProcessHandleCount);
+		test(startThreadHandleCount  == endThreadHandleCount);
+
+		__UHEAP_MARKEND;
+		}
+	while(err == KErrNoMemory);
+
+	test.Printf(_L("- Succeeded at heap failure rate of %i\n"), failAt);
+	test(err == KErrNone);
+	}
+
+// Type definition for pointer to member function.
+// Used in calling the CDiscovererTest member function for testing.
+typedef void (CDiscovererTest::*ClassFuncPtrL) (void);
+
+/**
+@SYMTestCaseID          SYSLIB-ECOM-CT-0725
+@SYMTestCaseDesc	    Function to call all test functions
+@SYMTestPriority 	    High
+@SYMTestActions  	    Calls up test function of CDiscovererTest.
+@SYMTestExpectedResults The test must not fail.
+@SYMREQ                 REQ0000
+*/
+/**
+Wrapper function to call all test functions
+
+@param		testFunc pointer to test function
+@param		aTestDesc test function name
+*/
+LOCAL_C void DoBasicTestL(ClassFuncPtrL testFuncL, const TDesC& aTestDesc)
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-0725 "));
+	test.Next(aTestDesc);
+
+	__UHEAP_MARK;
+  	// find out the number of open handles
+	TInt startProcessHandleCount;
+	TInt startThreadHandleCount;
+	RThread().HandleCount(startProcessHandleCount, startThreadHandleCount);
+
+	CDiscovererTest* discTest = CDiscovererTest::NewL();
+	CleanupStack::PushL(discTest);
+
+	(discTest->*testFuncL)();
+
+	CleanupStack::PopAndDestroy(discTest);
+
+	// check that no handles have leaked
+	TInt endProcessHandleCount;
+	TInt endThreadHandleCount;
+	RThread().HandleCount(endProcessHandleCount, endThreadHandleCount);
+
+	test(startProcessHandleCount == endProcessHandleCount);
+	test(startThreadHandleCount  == endThreadHandleCount);
+
+	__UHEAP_MARKEND;
+	}
+
+/**
+Utility function to continually invoke a test function and cause memory allocation failures
+
+@param		testFuncL pointer to OOM test function
+@param	 	tryCount specifies what value to start memory allocation failures at
+@param		increment how much to increase the point at which memory allocation will fail on each test attempt
+@param		stopCount the value of memory allocation failure to stop testing at
+*/
+TInt RunTestUnderOOMCondition(ClassFuncPtrL testFuncL, TInt tryCount, TInt increment, TInt stopCount)
+{
+	TInt err = KErrNone;
+
+	do
+		{
+
+		__UHEAP_MARK;
+  		// find out the number of open handles
+		TInt startProcessHandleCount;
+		TInt startThreadHandleCount;
+		RThread().HandleCount(startProcessHandleCount, startThreadHandleCount);
+
+		CDiscovererTest* discTest = CDiscovererTest::NewL();
+		CleanupStack::PushL(discTest);
+
+
+		__UHEAP_SETFAIL(RHeap::EDeterministic, tryCount);
+		TRAP(err, (discTest->*testFuncL)());
+		__UHEAP_SETFAIL(RHeap::ENone, 0);
+
+
+		CleanupStack::PopAndDestroy(discTest);
+		discTest = NULL;
+
+		// check that no handles have leaked
+		TInt endProcessHandleCount;
+		TInt endThreadHandleCount;
+		RThread().HandleCount(endProcessHandleCount, endThreadHandleCount);
+
+		test(startProcessHandleCount == endProcessHandleCount);
+		test(startThreadHandleCount  == endThreadHandleCount);
+
+		__UHEAP_MARKEND;
+
+	 	tryCount = tryCount + increment;
+		} while((err == KErrNoMemory) && (tryCount != stopCount));
+
+		tryCount = tryCount - increment;
+
+
+		if (err == KErrNoMemory)
+		{
+			// test has not yet been able to pass due to memory allocation failures.
+			return -1;
+		}
+
+		test(err == KErrNone);
+
+	 	// If enough memory has finally been allocated for the test to pass then return
+		// the memory allocation counter value.
+		test.Printf(_L("- server succeeded at heap failure rate of %i\n"), tryCount);
+		return tryCount;
+}
+
+/**
+Wrapper function to call all OOM test functions
+
+@param		testFuncL pointer to OOM test function
+@param		aTestDesc test function name
+*/
+LOCAL_C void DoOOMTestL(ClassFuncPtrL testFuncL, const TDesC& aTestDesc)
+	{
+	test.Next(aTestDesc);
+
+	TInt startCount = 1;
+	TInt increment = 1;
+	TInt successRate = -1;
+	TInt stopCount = 256;
+
+ 	successRate = RunTestUnderOOMCondition(testFuncL, startCount, increment, stopCount);
+
+ 	// (INC115057)
+ 	// When method CDiscoverer::CDirScanner::DoScanDriveL is encountered in a test hundreds
+ 	// of plug-in files will be scanned. It takes in the order of 3-4000 memory allocation failure
+ 	// loops (in techview context) before the scan is finished and the test can complete successfully.
+ 	// This will take over an hour. Instead determine the approximate failure point by
+ 	// testing with large increments between failures. Once a failure rate interval is found test
+ 	// for OOM conditions running up to it.
+ 	// This in effect means that we are checking OOM at the start and end of tests but skipping
+ 	// the scanning of each and every plugin in the middle of the test.
+ 	// (Note that CDiscoverer::CDirScanner::DoScanDriveL may return without leaving when it
+ 	// can't allocate TFileName. In this case it seems to this function that the test is
+ 	// successful. Therefore even if the successRate above indicates a pass the test is still
+ 	// re-run below with larger memory allocation failure valued to make sure that the test does
+ 	// in fact run to completion.
+
+ 		startCount = 256;
+ 		increment = 256;
+ 		stopCount = -1;
+ 		successRate = RunTestUnderOOMCondition(testFuncL, startCount, increment, stopCount);
+ 		test(successRate > 0);
+
+ 		if (successRate > 256)
+ 		{
+ 			startCount = successRate - 256;
+ 			increment = 1;
+ 			stopCount = -1;
+ 			successRate = RunTestUnderOOMCondition(testFuncL, startCount, increment, stopCount);
+ 		}
+
+ 	test(successRate > 0);
+	}
+
+/**
+Creates and installs active scheduler for this thread and calls
+CDiscovererTest::IdleScanningTimerRunErrorL
+
+@param		aDiscTest The CDiscovererTest object used to carry out the test
+*/
+LOCAL_C	void DoIdleScanningTimerRunErrorTestL(CDiscovererTest* aDiscTest)
+	{
+
+	// create and install the active scheduler we need
+	CActiveScheduler* scheduler=new(ELeave) CActiveScheduler;
+	CleanupStack::PushL(scheduler);
+
+	CActiveScheduler::Install(scheduler);
+
+	aDiscTest->IdleScanningTimerRunErrorL();
+
+	// Cleanup CDiscovererTest, TheFs and scheduler
+	CleanupStack::PopAndDestroy(scheduler);
+
+	}
+/**
+Thread entry point for the test thread.  Creates a CTrapCleanup and
+calls  DoIdleScanningTimerRunErrorTestL to carry out the test
+
+@param		aDiscTest The CDiscovererTest object used to carry out the test
+*/
+LOCAL_C TInt IdleScanningTimerRunErrorThreadEntry(TAny* aDiscTest)
+	{
+
+	CTrapCleanup* tc = CTrapCleanup::New();
+
+	CDiscovererTest *discTest = static_cast<CDiscovererTest*>(aDiscTest);
+
+	TRAPD(err,DoIdleScanningTimerRunErrorTestL(discTest));
+
+	delete tc;
+
+	return err;
+
+	}
+
+
+/**
+@SYMTestCaseID		SYSLIB-ECOM-CT-3165
+@SYMTestCaseDesc 	Check that the CIdleScanningTimer::RunError() works correctly.
+@SYMTestPriority 	High
+@SYMTestActions  	Create a new thread which will call RunError.  Wait for the
+					thread to exit and check the thread exit type and reason
+					to verify behaviour
+@SYMTestExpectedResults The test must not fail.
+@SYMDEF DEF094675
+*/
+LOCAL_C void IdleScanningTimer_RunErrorTest()
+	{
+	__UHEAP_MARK;
+
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-3165 CIdleScanningTimer RunError test "));
+
+	_LIT(KStartThreadName,"CIdleScanningTimer RunError Thread");
+
+	//Disable JIT so that the Panic doesn't bring up a dialog
+	//and stop the test
+	TBool jitEnabled = User::JustInTime();
+	User::SetJustInTime(EFalse);
+
+	//Create a CDiscovererTest object to pass into the test thread
+	CDiscovererTest* discTest = CDiscovererTest::NewL();
+	CleanupStack::PushL(discTest);
+
+	//Create a new thread to run the test
+	RThread testThread;
+	testThread.Create(KStartThreadName, IdleScanningTimerRunErrorThreadEntry,
+					KDefaultStackSize,KMinHeapSize,KMinHeapSize,discTest);
+	TRequestStatus status;
+	testThread.Logon(status);
+
+
+	testThread.Resume();
+
+	//Wait for the thread to exit
+	User::WaitForRequest(status);
+
+	//Obtain exit type and reason for test thread
+	TExitType exitType = testThread.ExitType();
+	TInt exitReason = testThread.ExitReason();
+
+	//close the thread handle
+	testThread.Close();
+
+	CleanupStack::PopAndDestroy(discTest);
+
+	//Set JIT back to original state
+	User::SetJustInTime(jitEnabled);
+
+	//Verify the exit reason and exit code
+	test(exitType == EExitPanic);
+	test(exitReason == EEComPanic_CDiscoverer_CIdleScanningTimer_RunError);
+
+	__UHEAP_MARKEND;
+	}
+
+/**
+Creates and installs active scheduler for this thread and calls
+CDiscovererTest::DirChangeNotifierRunErrorL
+
+@param		aDiscTest The CDiscovererTest object used to carry out the test
+*/
+LOCAL_C void DoDirChangeNotifierRunErrorTestL(CDiscovererTest* aDiscTest)
+	{
+
+	// create and install the active scheduler we need
+	CActiveScheduler* scheduler=new(ELeave) CActiveScheduler;
+	CleanupStack::PushL(scheduler);
+
+	CActiveScheduler::Install(scheduler);
+
+	//call the RunErrorL method which should panic
+	aDiscTest->DirChangeNotifierRunErrorL();
+
+	// Cleanup CDiscovererTest, TheFs and scheduler
+	CleanupStack::PopAndDestroy(scheduler);
+
+	}
+
+/**
+Thread entry point for the test thread.  Creates a CTrapCleanup and
+calls  DoDirChangeNotifierRunErrorTestL to carry out the test
+
+@param		aDiscTest The CDiscovererTest object used to carry out the test
+*/
+LOCAL_C TInt DirChangeNotifierRunErrorThreadEntry(TAny* aDiscTest)
+	{
+
+	CTrapCleanup* tc = CTrapCleanup::New();
+
+	CDiscovererTest *discTest = static_cast<CDiscovererTest*>(aDiscTest);
+
+	TRAPD(err,DoDirChangeNotifierRunErrorTestL(discTest));
+
+	delete tc;
+
+	return err;
+
+	}
+
+/**
+@SYMTestCaseID		SYSLIB-ECOM-CT-3166
+@SYMTestCaseDesc 	Check that the CDirChangeNotifier::RunError() works correctly.
+@SYMTestPriority 	High
+@SYMTestActions  	Create a new thread which will call RunError.  Wait for the
+					thread to exit and check the thread exit type and reason
+					to verify behaviour
+@SYMTestExpectedResults The test must not fail.
+@SYMDEF DEF094675
+*/
+LOCAL_C void DirChangeNotifier_RunErrorTest()
+	{
+	__UHEAP_MARK;
+
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-3166 CDirChangeNotifier RunError test "));
+
+	_LIT(KStartThreadName,"CDirChangeNotifier RunError Thread");
+
+	//Disable JIT so that the Panic doesn't bring up a dialog
+	//and stop the test
+	TBool jitEnabled = User::JustInTime();
+	User::SetJustInTime(EFalse);
+
+	//Create a CDiscovererTest object to pass into the test thread
+	CDiscovererTest* discTest = CDiscovererTest::NewL();
+	CleanupStack::PushL(discTest);
+
+	//Create a new thread to run the test
+	RThread testThread;
+	testThread.Create(KStartThreadName, DirChangeNotifierRunErrorThreadEntry,
+					KDefaultStackSize,KMinHeapSize,KMinHeapSize,discTest);
+	TRequestStatus status;
+	testThread.Logon(status);
+	testThread.Resume();
+
+	//Wait for the thread to exit
+	User::WaitForRequest(status);
+
+	//Obtain exit type and reason for test thread
+	TExitType exitType = testThread.ExitType();
+	TInt exitReason = testThread.ExitReason();
+
+	//close the thread handle
+	testThread.Close();
+
+	CleanupStack::PopAndDestroy(discTest);
+
+	//Set JIT back to original state
+	User::SetJustInTime(jitEnabled);
+
+	//Verify the exit reason and exit code
+	test(exitType == EExitPanic);
+	test(exitReason == EEComPanic_CDiscoverer_CDirChangeNotifier_RunError);
+
+	__UHEAP_MARKEND;
+	}
+
+TInt DoTestsL()
+	{
+	__UHEAP_MARK;
+
+	// Basic tests
+	CreateDeleteTestL();
+	DoBasicTestL(&CDiscovererTest::ResumeSuspendTestL, _L("ResumeSuspendTestL"));
+	DoBasicTestL(&CDiscovererTest::DriveMountUnmountTestL, _L("DriveMountUnmountTestL"));
+	DoBasicTestL(&CDiscovererTest::ProcessEntryTestL, _L("ProcessEntryTestL"));
+	DoBasicTestL(&CDiscovererTest::ValidateEntryTestL, _L("ValidateEntryTestL"));
+	DoBasicTestL(&CDiscovererTest::ProcessSpiEntryTestL, _L("ProcessSpiEntryTestL"));
+	DoBasicTestL(&CDiscovererTest::ValidateSpiEntryTestL, _L("ValidateSpiEntryTestL"));
+	DoBasicTestL(&CDiscovererTest::ProcessEntryPlugIn3TestL, _L("ProcessEntryPlugIn3TestL"));
+	DoBasicTestL(&CDiscovererTest::ValidateEntryPlugIn3TestL, _L("ValidateEntryPlugIn3TestL"));
+	DoBasicTestL(&CDiscovererTest::ProcessSpiEntryPlugIn3TestL, _L("ProcessSpiEntryPlugIn3TestL"));
+	DoBasicTestL(&CDiscovererTest::ValidateSpiEntryPlugIn3TestL, _L("ValidateSpiEntryPlugIn3TestL"));
+	DoBasicTestL(&CDiscovererTest::ValidateSpiPluginsTestL, _L("ValidateSpiPluginsTestL"));
+	DoBasicTestL(&CDiscovererTest::ScanDirectoryIncrementTestL, _L("ScanDirectoryIncrementTestL"));
+	DoBasicTestL(&CDiscovererTest::StagedDiscoveryStateTransitionTestL, _L("StagedDiscoveryStateTransitionTestL"));
+	DoBasicTestL(&CDiscovererTest::AllAtOnceDiscoveryStateTransitionTestL, _L("AllAtOnceDiscoveryStateTransitionTestL"));
+	DoBasicTestL(&CDiscovererTest::ScanDirectoryTestL, _L("ScanDirectoryTestL"));
+	DoBasicTestL(&CDiscovererTest::MultipleNotificationProcessingTestL, _L("MultipleNotificationProcessingTestL"));
+	DoBasicTestL(&CDiscovererTest::LanguageChangedNotificationTestL, _L("MLanguageChangedNotificationTestL"));
+	DoBasicTestL(&CDiscovererTest::SWINotificationProcessingTestL, _L("SWINotificationProcessingTestL"));
+
+	//RunError tests
+	IdleScanningTimer_RunErrorTest();
+	DirChangeNotifier_RunErrorTest();
+
+	// OOM tests
+	OOMCreateDeleteTest();
+	// This test is not performed because the error from the final memory allocation failures are not
+	// propagated back to the calling function and cannot be dealt with. Therefore
+	// this test does not complete. However the normal test is performed above.
+	//DoOOMTestL(&CDiscovererTest::ResumeSuspendTestL, _L("OOM ResumeSuspendTestL"));
+	DoOOMTestL(&CDiscovererTest::DriveMountUnmountTestL, _L("OOM DriveMountUnmountTestL"));
+	DoOOMTestL(&CDiscovererTest::ProcessEntryTestL, _L("OOM ProcessEntryTestL"));
+	DoOOMTestL(&CDiscovererTest::ProcessSpiEntryTestL, _L("OOM ProcessSpiEntryTestL"));
+	DoOOMTestL(&CDiscovererTest::ValidateSpiEntryTestL, _L("OOM ValidateSpiEntryTestL"));
+	DoOOMTestL(&CDiscovererTest::ValidateEntryTestL, _L("OOM ValidateEntryTestL"));
+	DoOOMTestL(&CDiscovererTest::ProcessEntryPlugIn3TestL, _L("OOM ProcessEntryPlugIn3TestL"));
+	DoOOMTestL(&CDiscovererTest::ProcessSpiEntryPlugIn3TestL, _L("OOM ProcessSpiEntryPlugIn3TestL"));
+	DoOOMTestL(&CDiscovererTest::ValidateSpiEntryPlugIn3TestL, _L("OOM ValidateSpiEntryPlugIn3TestL"));
+	DoOOMTestL(&CDiscovererTest::ValidateEntryPlugIn3TestL, _L("OOM ValidateEntryPlugIn3TestL"));
+	DoOOMTestL(&CDiscovererTest::ScanDirectoryIncrementTestL, _L("OOM ScanDirectoryIncrementTestL"));
+	DoOOMTestL(&CDiscovererTest::StagedDiscoveryStateTransitionTestL, _L("StagedDiscoveryStateTransitionTestL"));
+	DoOOMTestL(&CDiscovererTest::AllAtOnceDiscoveryStateTransitionTestL, _L("AllAtOnceDiscoveryStateTransitionTestL"));
+	DoOOMTestL(&CDiscovererTest::ScanDirectoryTestL, _L("OOM ScanDirectoryTestL"));
+	// This test is not performed because the error from the final memory allocation failures are not
+	// propagated back to the calling function and cannot be dealt with. Therefore
+	// this test does not complete. However the normal test is performed above.
+	//DoOOMTestL(&CDiscovererTest::MultipleNotificationProcessingTestL, _L("MultipleNotificationProcessingTestL"));
+	// This test is not performed because the error from the final memory allocation failures are not
+	// propagated back to the calling function and cannot be dealt with. Therefore
+	// this test does not complete. However the normal test is performed above.
+	//DoOOMTestL(&CDiscovererTest::SWINotificationProcessingTestL, _L("OOM SWINotificationProcessingTestL"));
+
+	__UHEAP_MARKEND;
+	return KErrNone;
+	}
+
+// Copy the Plugins to specific folder for testing purpose
+LOCAL_C void CopyPlugins()
+	{
+	TInt err=KErrNone;
+	TRAP(err, EComTestUtils::FileManCopyFileL(KNewResourceFileNameOnZ, KNewResourceFileName));
+	test(err==KErrNone);
+	TRAP(err, EComTestUtils::FileManCopyFileL(KNewExampleDllFileNameOnZ, KNewExampleDllFileName));
+	test(err==KErrNone);
+	TRAP(err, EComTestUtils::FileManCopyFileL(KPlugIn3ResourceFileNameOnZ, KPlugIn3ResourceFileName));
+	test(err==KErrNone);
+	TRAP(err, EComTestUtils::FileManCopyFileL(KPlugIn3ExampleDllFileNameOnZ, KPlugIn3ExampleDllFileName));
+	test(err==KErrNone);
+	}
+
+// Deleting plugin from the RAM for cleanup purpose
+inline LOCAL_C void DeleteTestPlugin()
+	{
+	TInt err=KErrNone;
+	TRAP(err, EComTestUtils::FileManDeleteFileL(KNewResourceFileName));
+	TRAP(err, EComTestUtils::FileManDeleteFileL(KNewExampleDllFileName));
+	TRAP(err, EComTestUtils::FileManDeleteFileL(KPlugIn3ResourceFileName));
+	TRAP(err, EComTestUtils::FileManDeleteFileL(KPlugIn3ExampleDllFileName));
+	}
+
+//
+//Initialise the Active Scheduler
+//
+LOCAL_C void SetupL()
+	{
+	// Construct and install the Active Scheduler. The Active Schedular is needed
+	// by components used by this test as they are ActiveObjects.
+	TheActiveScheduler = new(ELeave)CActiveScheduler;
+	CActiveScheduler::Install(TheActiveScheduler);
+	}
+
+GLDEF_C TInt E32Main()
+	{
+	__UHEAP_MARK;
+
+	test.Printf(_L("\n"));
+	test.Title();
+	test.Start(_L("Discoverer Tests."));
+
+	TheTrapCleanup = CTrapCleanup::New();
+
+	TRAPD(err, SetupL());
+	test(err == KErrNone);
+
+	// Connect the file server instance
+	User::LeaveIfError(TheFs.Connect());
+
+	CopyPlugins();
+
+	// The reason for the folowing delay is:
+	// ECOM server could be already started. It means that when we copy some
+	// ECOM plugins from Z: to C: drive - ECOM server should look for and
+	// find the new ECOM plugins. The ECOM server uses for that an active object,
+	// which scans plugin directories. So the discovering service is asynchronous.
+	// We have to wait some time until it finishes.
+	// Otherwise ListImplementationsL could fail to find requested implementations.
+	User::After(KOneSecond * 3);
+
+
+	// Call the main tests
+	TRAP(err, DoTestsL());
+	test(err == KErrNone);
+
+	// Cleanup files. If the cleanup fails that is no problem,
+	// as any subsequent tests will replace them. The only downside
+	// would be the disk not being tidied
+	DeleteTestPlugin();
+
+	TheFs.Close();
+
+	delete TheActiveScheduler;
+	delete TheTrapCleanup;
+
+	test.End();
+	test.Close();
+
+	__UHEAP_MARKEND;
+	return (KErrNone);
+	}
+