kerneltest/e32test/domainmgr/t_domain_monitor.cpp
changeset 279 957c583b417b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/domainmgr/t_domain_monitor.cpp	Mon Oct 04 12:03:52 2010 +0100
@@ -0,0 +1,2436 @@
+// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test/domainmgr/t_domain_monitor.cpp
+// Overview:
+// Domain manager transition monitoring feature implementation tests
+//
+// API Information:
+// RDmDomain, RDmDomainManager CDmDomain, CDmDomainManager,CDmDomanKeepAlive
+//
+//  - Domain member deferral and acknowledgments tests
+//  - Domain manager policy interface tests
+//  - Domain member deferral requests Platsec capability checking tests
+//
+// Platforms/Drives/Compatibility:
+// All.
+// Assumptions/Requirement/Pre-requisites:
+// Failures and causes:
+// Base Port information:
+//
+
+#define __E32TEST_EXTENSION__
+
+#include <e32test.h>
+#include <e32ldr_private.h>
+
+#include <domainobserver.h>
+
+#include "domainpolicytest.h"
+
+#include "t_domain.h"
+
+
+RTest test(_L(" T_DOMAIN_MONITOR "));
+
+
+/**
+   Domain member deferral requests PlatSec capability checking tests.
+*/
+_LIT(KSecuritySlavePath1, "t_dmslave_nocaps.exe");
+_LIT(KSecuritySlavePath2, "t_dmslave_wdd.exe");
+_LIT(KSecuritySlavePath3, "t_dmslave_protsrv.exe");
+
+class CDmTestPlatSec : public CActive, public MDmTest
+	{
+public:
+	CDmTestPlatSec(TPtrC aFileName);
+	~CDmTestPlatSec()
+		{
+		Cancel();
+		iManager.Close();
+		}
+	// from CActive
+	void RunL();
+	// from MDmTest
+	void Perform();
+	void Release();
+	TInt TransitionNotification(MDmDomainMember&)
+		{
+		test(0);
+		return KErrNone;
+		}
+	void TransitionRequestComplete()
+		{}
+private:
+	// from CActive
+	virtual void DoCancel()
+		{
+		test(0);
+		}
+private:
+	RDmDomainManager iManager;
+	const TPtrC iFileName;
+	};
+
+
+CDmTestPlatSec::CDmTestPlatSec(TPtrC aFileName)
+	: CActive(CActive::EPriorityStandard), iFileName(aFileName)
+	{}
+
+
+void CDmTestPlatSec::Perform()
+	{
+	test.Next(_L("CDmTestPlatSec"));
+
+	// 1. Set up test hierarchy/domain & join it
+	TInt r = RDmDomainManager::AddDomainHierarchy(KDmHierarchyIdTestV2);
+	test_KErrNone(r);
+	r = iManager.Connect(KDmHierarchyIdTestV2);
+	test_KErrNone(r);
+
+	// 2. Create a child process
+	RProcess proc;
+	r = proc.Create(iFileName, KNullDesC);
+	test_KErrNone(r);
+
+	// Start process & wait until child has set up itself (3. & 4.)
+	TRequestStatus status;
+	proc.Rendezvous(status);
+	proc.Resume();
+	User::WaitForRequest(status);
+	test_KErrNone(status.Int());
+
+	// 5. Transition test domain to some other state (child: 6. & 7.)
+	CActiveScheduler::Add(this);
+	iManager.RequestDomainTransition(KDmIdTestA, EShutdownNonCritical, ETraverseDefault, iStatus);
+	CActive::SetActive();
+	CActiveScheduler::Start();
+
+	// Child processes do: TC 3.1, 3.2, 3.3
+
+	CLOSE_AND_WAIT(proc);
+	}
+
+
+void CDmTestPlatSec::RunL()
+	{
+	RDebug::Printf("CDmTestPlatSec::RunL(): %d", iStatus.Int());
+	CActiveScheduler::Stop();
+	}
+
+
+void CDmTestPlatSec::Release()
+	{
+	delete this;
+	}
+
+
+/**
+   Checks that upon transition acknowledgment, outstanding deferral is
+   completed with KErrCompletion.
+*/
+class CDmDeferralTestCompletion : public CDmDeferralTest, public MDeferringMember
+	{
+public:
+	CDmDeferralTestCompletion(TDmHierarchyId aId, TDmDomainState aState)
+		: CDmDeferralTest(aId, aState)
+		{}
+
+	~CDmDeferralTestCompletion()
+		{
+		delete iKeepAlive;
+		}
+
+	void DoPerform()
+		{
+		test.Next(_L("CDmDeferralTestCompletion\n"));
+
+		iMember = new CDmTestMember(iHierarchyId, KDmIdTestA, 0, this);
+		test_NotNull(iMember);
+
+		iKeepAlive = new CTestKeepAlive(iMember->iDomain);
+		test_NotNull(iKeepAlive);
+
+		iManager.RequestSystemTransition(iState, ETraverseChildrenFirst, CActive::iStatus);
+		}
+
+	void HandleEndOfDeferrals(TInt aError)
+		{
+		test.Printf(_L("End of deferrals\n"));
+
+		// This is the test (TC 1.1.1.2.1):
+
+		test_Equal(KErrCompletion, aError);
+		}
+
+	TInt TransitionNotification(MDmDomainMember& /*aDomainMember*/)
+		{
+		iKeepAlive->BeginDeferrals(this, 1);
+		return KErrNone;
+		}
+
+	void TransitionRequestComplete()
+		{
+		}
+private:
+	CTestKeepAlive* iKeepAlive;
+	};
+
+
+/**
+   Checks that after deferring a given number of times, the deferral
+   after fails with KErrNotSupported.
+*/
+class CDmDeferralTestKErrNotSupported : public CDmDeferralTest, public MDeferringMember
+	{
+public:
+	/**
+	@param aCount Number of deferrals to attempt
+	*/
+	CDmDeferralTestKErrNotSupported(TDmHierarchyId aId, TDmDomainState aState, TInt aCount)
+		: CDmDeferralTest(aId, aState), iCount(aCount)
+		{}
+
+	~CDmDeferralTestKErrNotSupported()
+		{
+		delete iKeepAlive;
+		}
+
+	// from CDmDeferralTest
+	void DoPerform()
+		{
+		test.Next(_L("CDmDeferralTestKErrNotSupported\n"));
+		test.Printf(_L("CDmDeferralTestKErrNotSupported: Hierachy %d, state %d, attempt %d deferrals\n"),
+			iHierarchyId, iState, iCount);
+
+		iMember = new CDmTestMember(iHierarchyId, KDmIdTestA, 0, this);
+		test_NotNull(iMember);
+
+		iKeepAlive = new CTestKeepAlive(iMember->iDomain);
+		test_NotNull(iKeepAlive);
+
+		iManager.RequestSystemTransition(iState, ETraverseChildrenFirst, CActive::iStatus);
+		}
+
+	// from MDeferringMember
+	void HandleEndOfDeferrals(TInt aError)
+		{
+		iMember->Acknowledge();
+
+		test.Printf(_L("CDmDeferralTestKErrNotSupported: End of deferrals %d\n"), aError);
+		// This is the test (TC 1.1.1.3.1, TC 1.1.1.3.2, TC 1.1.1.3.3):
+		test_Equal(KErrNotSupported, aError);
+		}
+
+	// from MDmTest
+	TInt TransitionNotification(MDmDomainMember& /*aDomainMember*/)
+		{
+		iKeepAlive->BeginDeferrals(this, iCount);
+		return KErrAbort; // Don't acknowledge yet
+		}
+
+	void TransitionRequestComplete()
+		{
+		RDebug::Printf("CDmDeferralTestKErrNotSupported::TransitionRequestComplete()");
+		test_KErrNone(iStatus.Int());
+		}
+private:
+	CTestKeepAlive* iKeepAlive;
+	const TInt iCount;
+	};
+
+/**
+   DeferAcknowledgement() with status KErrNone.
+
+   1: Client receives notification, defers once and then acknowledges after the
+   next notification
+   2: Client receives notification, defers twice and then acknowledges after
+   the next notification
+   3: Client receives notification, defers once and then fails to acknowledge
+*/
+class CDmDeferralTestKErrNone : public CDmDeferralTest, public MDeferringMember
+	{
+public:
+	CDmDeferralTestKErrNone(TDmHierarchyId aId, TDmDomainState aState,
+							TInt aDeferrals, TBool aAcknowledge);
+	~CDmDeferralTestKErrNone();
+	// from CDmDeferralTest
+	void DoPerform();
+	// from MDmTest
+	TInt TransitionNotification(MDmDomainMember& aDomainMember);
+	void TransitionRequestComplete();
+	// from MDeferringMember
+	void HandleEndOfDeferrals(TInt aError);
+
+private:
+	CTestKeepAlive* iKeepAlive;
+	const TInt iDeferrals;
+	const TBool iAcknowledge;
+	};
+
+
+CDmDeferralTestKErrNone::CDmDeferralTestKErrNone(TDmHierarchyId aId,
+												 TDmDomainState aState,
+												 TInt aDeferrals,
+												 TBool aAcknowledge)
+	: CDmDeferralTest(aId, aState),
+	  iDeferrals(aDeferrals),
+	  iAcknowledge(aAcknowledge)
+	{}
+
+
+CDmDeferralTestKErrNone::~CDmDeferralTestKErrNone()
+	{
+	delete iKeepAlive;
+	}
+
+
+void CDmDeferralTestKErrNone::DoPerform()
+	{
+	test.Next(_L("CDmDeferralTestKErrNone"));
+
+	iMember = new CDmTestMember(iHierarchyId, KDmIdTestCAA, 0, this);
+	test_NotNull(iMember);
+
+	iKeepAlive = new CTestKeepAlive(iMember->iDomain);
+	test_NotNull(iKeepAlive);
+
+	iManager.RequestSystemTransition(iState, ETraverseDefault, CActive::iStatus);
+	}
+
+
+void CDmDeferralTestKErrNone::HandleEndOfDeferrals(TInt aError)
+	{
+	test.Printf(_L("HandleEndOfDeferrals(): %d\n"), aError);
+
+	// This is the test (TC 1.1.1.1.1, TC 1.1.1.1.2 , TC 1.1.1.1.3):
+
+	test_Equal(KErrNone, aError);
+
+	if (iAcknowledge)
+		{
+		RDebug::Printf(" Calling AcknowledgeLastState()");
+		iMember->iDomain.AcknowledgeLastState();
+		}
+	}
+
+
+TInt CDmDeferralTestKErrNone::TransitionNotification(MDmDomainMember&)
+	{
+	iKeepAlive->BeginDeferrals(this, iDeferrals);
+	// don't acknowledge yet
+	return KErrAbort;
+	}
+
+
+void CDmDeferralTestKErrNone::TransitionRequestComplete()
+	{
+	}
+
+
+/**
+   Test mix of deferral and non-deferral clients (1.3)
+  
+   1: Three clients receive notification.
+   2: One makes three deferrals and then acknowledges after the next notification
+   3: The other two non-deferral clients acknowledge without making a deferral      
+*/
+class CDmDeferralMixed : public CDmDeferralTest, public MDeferringMember
+	{
+public:
+	CDmDeferralMixed(TDmHierarchyId aId, TDmDomainState aState, TInt aDeferrals, TBool aAcknowledge, TBool aDelayAck);
+	~CDmDeferralMixed();
+	// from CDmDeferralTest
+	void DoPerform();
+	// from MDmTest
+	TInt TransitionNotification(MDmDomainMember& aDomainMember);
+	void TransitionRequestComplete();
+	// from MDeferringMember
+	void HandleEndOfDeferrals(TInt aError);
+
+private:
+	CTestKeepAlive* iKeepAlive;	
+	CDmTestMember* iMixedDeferralTestMember[2];
+	const TInt iDeferrals;
+	const TBool iAcknowledge;
+	TBool iDoneDeferral;	
+	const TBool iDelayAck;
+	TBool iNonMemberAck[2];
+	MDmDomainMember* iFirstMemberToCompleteAddr;
+	};
+
+CDmDeferralMixed::CDmDeferralMixed(TDmHierarchyId aId, 
+								   TDmDomainState aState,
+								   TInt aDeferrals,
+								   TBool aAcknowledge,
+								   TBool aDelayAck)	
+    :CDmDeferralTest(aId, aState),
+ 	 iDeferrals(aDeferrals),
+	 iAcknowledge(aAcknowledge),
+	 iDelayAck(aDelayAck)
+	{
+	iDoneDeferral=EFalse; 	
+	iFirstMemberToCompleteAddr = NULL;
+	iNonMemberAck[0]=EFalse;
+	iNonMemberAck[1]=EFalse;
+	}
+
+CDmDeferralMixed::~CDmDeferralMixed()
+	{
+	delete iKeepAlive;	
+	delete iMixedDeferralTestMember[0];
+	delete iMixedDeferralTestMember[1];	   
+	}
+
+void CDmDeferralMixed::DoPerform()
+	{
+	test.Next(_L("CDmDeferralMixed"));	
+	
+	// Attach three test members to the same domain (KDmIdTestCAA). One of the test
+	// member is a deferring member while the other two are non deferring members.
+	iMember = new CDmTestMember(iHierarchyId, KDmIdTestCAA, 0, this);
+	test_NotNull(iMember);
+
+	iMixedDeferralTestMember[0] = new CDmTestMember(iHierarchyId, KDmIdTestCAA, 0, this);
+	test_NotNull(iMixedDeferralTestMember[0]);
+
+	iMixedDeferralTestMember[1] = new CDmTestMember(iHierarchyId, KDmIdTestCAA, 0, this); 
+	test_NotNull(iMixedDeferralTestMember[1]);
+
+	iManager.RequestSystemTransition(iState, ETraverseDefault, CActive::iStatus);
+	}
+
+void CDmDeferralMixed::HandleEndOfDeferrals(TInt aError)
+	{
+	test.Printf(_L("HandleEndOfDeferrals(): %d\n"), aError);
+	test_Equal(KErrNone, aError);
+	if (iAcknowledge)
+		{
+		RDebug::Printf(" Calling AcknowledgeLastState()");
+		//iFirstMemberToCompleteAddr is the first member to complete and is deferred 
+		static_cast<CDmTestMember*>(iFirstMemberToCompleteAddr)->iDomain.AcknowledgeLastState();		
+		iDoneDeferral = ETrue;
+		}
+	}
+
+TInt CDmDeferralMixed::TransitionNotification(MDmDomainMember& aDomainMember)
+	{
+	RDebug::Printf("CDmDeferralMixed::TransitionNotification()");
+
+	// if first member to complete, take note of this member and defer.
+	if (iFirstMemberToCompleteAddr ==  NULL)
+		{
+		iFirstMemberToCompleteAddr =  &aDomainMember; // Get address of first member to complete		
+		iKeepAlive = new CTestKeepAlive(static_cast<CDmTestMember*>(iFirstMemberToCompleteAddr)->iDomain);
+		test_NotNull(iKeepAlive);		
+		}
+
+	if  ( (!iDoneDeferral) && (&aDomainMember == iFirstMemberToCompleteAddr) ) // Defer 
+		{
+		//TC 1.3.1 Define a client to defer 3 times and then acknowledge and include 2 non deferring clients 	
+		test.Printf(_L("CDmDeferralMixed Attempting %d deferrals\n"), iDeferrals);
+		iKeepAlive->BeginDeferrals(this, iDeferrals);		
+		return KErrAbort;// don't acknowledge yet
+		}
+	else if (iNonMemberAck[0]== EFalse) 
+		{//One of the two non deferring clients which acknowledges without any delay
+		iNonMemberAck[0]= ETrue;
+		test.Printf(_L("CDmDeferralMixed acknowledging iMixedDeferralTestMember - 1 \n"));	
+		return KErrNone;  // Non deferral memeber acknowledges on time
+		}
+	else if (iNonMemberAck[1]== EFalse ) 
+		{//One of the two non deferring clients which acknowledges with and without a delay based on the state of iDelayAck
+		iNonMemberAck[1]= ETrue;
+		if(!iDelayAck)
+			{
+			test.Printf(_L("CDmDeferralMixed acknowledging iMixedDeferralTestMember - 2 \n"));
+			return KErrNone; // Non deferral member acknowledges on time
+			}
+		else
+			{
+			test.Printf(_L("CDmDeferralMixed delaying acknowledgement for iMixedDeferralTestMember - 2  \n"));
+			//TC 1.3.2 - 1 fails to acknowledge in time
+			return KErrAbort; // Delay acknowlegdement
+			}			
+		}
+	test(EFalse);
+	//default
+	return KErrNone;
+	}					
+
+void CDmDeferralMixed::TransitionRequestComplete()
+	{
+	RDebug::Printf("CDmDeferralMixed::TransitionRequestComplete()");
+	}
+
+/////////////////////////////////////////////// CDmKeepAlive Test cases ///////////////////////////////////////////////
+
+//-------------------------------------------------
+// Domain member deferral and acknowledgments tests
+//-------------------------------------------------
+
+class MDomainMemberTests;
+class CDomainMemberKeepAlive;
+const TUint KMembersMax = 32;
+
+// Policy related service functions user by the CDmDomainKeepAlive tests
+SDmStateSpecV1 Get0DeferralState()
+	{
+	TUint i = 0;
+	for (i=0; i<StateSpecificationSize; i++)
+		{
+		if(StateSpecification[i].iDeferralLimit != 0)
+			continue;
+		return StateSpecification[i];
+		}
+
+	// We could not find any state that has a 0 deferral specified in the policy
+	test(0);
+	return StateSpecification[i]; // get rid of compiler warnings
+	}
+
+// Get the first minimal deferral state from the policy greater than 0
+SDmStateSpecV1 GetMinDeferralState() 
+	{
+	SDmStateSpecV1 maxState, minState;
+	maxState = StateSpecification[0];
+	minState = StateSpecification[0];
+
+	for (TUint i=0; i<StateSpecificationSize; i++)
+		{
+		if(StateSpecification[i].iDeferralLimit != 0)
+			{
+			if(StateSpecification[i].iDeferralLimit > maxState.iDeferralLimit)
+				maxState = StateSpecification[i];
+			if(StateSpecification[i].iDeferralLimit < minState.iDeferralLimit)
+				{
+				minState = StateSpecification[i];
+				}
+			else if(minState.iDeferralLimit == 0)
+				minState = StateSpecification[i];
+			}
+		continue;
+		}
+
+	test.Printf(_L("minState's TimeoutMs = %d , count = %d\n"), minState.iTimeoutMs, minState.iDeferralLimit );
+
+	// Test whether there exists atleast one minimal deferral state that is greater than 0 deferrals and less than max deferrals
+	test(minState.iDeferralLimit > 0 && minState.iDeferralLimit < maxState.iDeferralLimit);
+	return minState;
+	}
+
+// Get the max deferral state from the policy. This is a simple function that always gets the first max deferral from the list
+// The parameter aContinueOnError is used to get a state eith maximum deferral that has the policy error as
+// ETransitionFailureContinue or ETransitionFailureStop
+SDmStateSpecV1 GetMaxDeferralState(TBool aContinueOnError = EFalse) 
+	{
+	SDmStateSpecV1 aState;
+	aState = StateSpecification[0];
+
+	TUint i;
+	for (i=0; i<StateSpecificationSize; i++)
+		{
+		const SDmStateSpecV1& spec = StateSpecification[i];
+
+		if((spec.iDeferralLimit > aState.iDeferralLimit) &&
+			(spec.iFailurePolicy == aContinueOnError ? ETransitionFailureContinue : ETransitionFailureStop))
+			{
+			aState = StateSpecification[i];
+			}
+		}
+
+	// Check that a suitable state was found
+	test(aState.iFailurePolicy == aContinueOnError ? ETransitionFailureContinue : ETransitionFailureStop);
+
+	test.Printf(_L("Max deferrral state's TimeoutMs = %d , count = %d, failure policy %d\n"), aState.iTimeoutMs, aState.iDeferralLimit, aState.iFailurePolicy);
+	return aState;
+	}
+
+// CDmDomainKeepAliveTest test
+//-------------------------------------------------
+// Domain member deferral and acknowledgments tests
+//-------------------------------------------------
+class CDmDomainKeepAliveTest : public CActive, public MDmTest
+	{
+public: 
+	// from CActive
+	void RunL();
+ 
+	// from MDmTest
+	void Perform();
+	void Release();
+	TInt TransitionNotification(MDmDomainMember& aDomainMember);
+	void TransitionRequestComplete() {};
+
+	// for the individual tests to handle
+	void HandleTransitionL(CDomainMemberKeepAlive* aDmMember);
+	TInt HandleDeferralError(TInt aError);
+
+	CDmDomainKeepAliveTest() : CActive(CActive::EPriorityStandard) {}
+	void SetExpectedValues(TInt aTestNotificationsExpected, TInt aTransitionsExpected);
+	void ValidateTestResults();
+	void RequestSystemTransition(TDmDomainState aTestState, TDmTraverseDirection aDirection);
+	void DoAsynMemberAck();
+	void CancelTransition();
+protected:
+	// from CActive
+	virtual void DoCancel();
+
+private:
+	void Init(MDomainMemberTests* aTest);
+	void UnInit();
+
+private:
+	CDomainMemberKeepAlive*	iTestMembers[KMembersMax]; 
+	RDmDomainManager		iTestDomainManager;
+	
+	MDomainMemberTests*			iCurrentTest;
+
+public:
+	static TUint		gTestMemberCount;
+	static TUint		gLeafMemberCount;
+	TInt				iTestNotifications;
+	TInt				iTestNotificationsExpected;
+
+	TInt				iTransitionsCompleted;
+	TInt				iTransitionsExpected;
+	};
+
+// CDomainMemberKeepAlive
+class CDomainMemberKeepAlive : public CDmDomainKeepAlive, public MDmDomainMember
+	{
+public:
+	static CDomainMemberKeepAlive* NewL(TDmHierarchyId aHierarchy, TDmDomainId aId, TUint32 aOrdinal, MDomainMemberTests*);
+	~CDomainMemberKeepAlive();
+
+	// from CDmDomainKeepAlive
+	TInt HandleDeferralError(TInt aError);
+	void HandleTransitionL();
+
+	// from MDmDomainMember
+	inline TDmHierarchyId HierarchyId() {return iHierarchy;};
+	inline TDmDomainId	DomainId() {return iId;};
+	inline TDmDomainState State() {return iState;};
+	inline TInt Status() {return iStatus.Int();};
+	inline TUint32 Ordinal() {return iOrdinal;};
+	inline TInt Notifications() {return iNotifications;};
+	static TInt TimerCallback(TAny* obj);
+	void DoAsynHandleTransition(const TTimeIntervalMicroSeconds32 aInterval);
+private:
+	CDomainMemberKeepAlive(TDmHierarchyId aHierarchy, TDmDomainId aId, TUint32 aOrdinal, MDomainMemberTests*);
+
+public:
+	// used only for test cases TC 1.1.2.2.2, TC 1.1.2.3.1 and TC 1.1.2.3.2 where DoAsynMemberAck is used
+	TBool				iShouldAck; 
+	
+private:
+	TDmHierarchyId		iHierarchy;
+	TDmDomainId			iId;
+	TDmDomainState		iState;
+	TUint32				iOrdinal;
+	MDomainMemberTests*	iTest;
+	TUint				iNotifications;
+
+	CPeriodic*			iTimer;
+	};
+
+class MDomainMemberTests
+	{
+public:
+	virtual void Perform() = 0;
+	virtual void Release() = 0;
+	virtual void HandleTransitionL(CDomainMemberKeepAlive* aDmMember) = 0;
+	virtual TInt HandleDeferralError(TInt aError) = 0;
+	virtual void DoAsynHandleTransition(CDomainMemberKeepAlive*) {};
+	virtual void DoAsynMemberAck(CDomainMemberKeepAlive*) {};
+public:
+	TDmDomainState		iTestState;
+	};
+
+CDomainMemberKeepAlive* CDomainMemberKeepAlive::NewL(TDmHierarchyId aHierarchy, TDmDomainId aId, TUint32 aOrdinal, MDomainMemberTests* aTest)
+	{
+	CDomainMemberKeepAlive* self=new (ELeave) CDomainMemberKeepAlive(aHierarchy, aId, aOrdinal, aTest);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+
+	self->RequestTransitionNotification();
+
+	CleanupStack::Pop();
+	return self;
+	}
+
+CDomainMemberKeepAlive::~CDomainMemberKeepAlive()
+	{
+	delete iTimer;
+	Cancel();
+	}
+
+CDomainMemberKeepAlive::CDomainMemberKeepAlive(TDmHierarchyId aHierarchy, TDmDomainId aId, TUint32 aOrdinal, MDomainMemberTests* aTest):
+	CDmDomainKeepAlive(aHierarchy, aId), iShouldAck(EFalse),
+	iHierarchy(aHierarchy), iId(aId), iOrdinal(aOrdinal), iTest(aTest)
+	{
+	}
+
+TInt CDomainMemberKeepAlive::HandleDeferralError(TInt aError)
+	{
+	TInt r = KErrNone;
+
+	TBuf16<4> buf;
+	GetDomainDesc(Ordinal(), buf);
+	test.Printf(_L("HandleDeferralError domain = %S, error = %d\n"), &buf, aError);
+
+	r = iTest->HandleDeferralError(aError);
+	return r;
+	}
+
+void CDomainMemberKeepAlive::HandleTransitionL()
+	{
+	iShouldAck = ETrue;
+	iNotifications++;
+	iTest->HandleTransitionL(this);
+	}
+
+TInt CDomainMemberKeepAlive::TimerCallback(TAny* obj)
+	{
+    CDomainMemberKeepAlive* member = static_cast<CDomainMemberKeepAlive*>(obj);
+
+	TBuf16<4> buf;
+	GetDomainDesc(member->Ordinal(), buf);
+
+	test.Printf(_L("Member asynchronous transition handler, domain = %S\n"), &buf);
+
+	member->iTest->DoAsynHandleTransition(member);
+	member->iTimer->Cancel();
+	return KErrNone;
+	}
+
+void CDomainMemberKeepAlive::DoAsynHandleTransition(const TTimeIntervalMicroSeconds32 aInterval)
+	{
+	iTimer = CPeriodic::NewL(CActive::EPriorityHigh);
+
+	TCallBack callback(TimerCallback, this);
+	iTimer->Start(aInterval, aInterval, callback);
+	}
+
+////////////////////////////////////////////////////////////////////////////////////
+//                      TC 1.1.2.1.1 (with deferral count 0)                      //
+////////////////////////////////////////////////////////////////////////////////////
+class TestTransitionWithDeferral0 : public MDomainMemberTests // TC 1.1.2.1.1 (with deferral count 0)
+	{
+public:
+	TestTransitionWithDeferral0(CDmDomainKeepAliveTest& aTester) : iTester(aTester) {}
+	// from MDmKeepAliveTest
+	void Perform();
+	void Release();
+	void HandleTransitionL(CDomainMemberKeepAlive* aDmMember);
+	TInt HandleDeferralError(TInt aError);
+
+private:
+	CDmDomainKeepAliveTest& iTester;
+	};
+
+void TestTransitionWithDeferral0::Perform()
+	{
+	test.Printf(_L("****************TestTransitionWithDeferral0****************\n"));
+	test.Next(_L("Test state transition that has 0 deferral"));
+	test.Printf(_L("Acknowleding immediately......\n"));
+
+	iTester.SetExpectedValues(iTester.gTestMemberCount, 1);
+
+	SDmStateSpecV1 aStateSpec = Get0DeferralState();
+
+	iTestState =  aStateSpec.iState;
+
+	// request a system transition
+	iTester.RequestSystemTransition(iTestState, ETraverseChildrenFirst);
+	test.Printf(_L("Requested system transition\n"));
+
+	// wait for test transitions to complete
+	CActiveScheduler::Start();
+	test.Printf(_L("....transition completed\n"));
+
+	iTester.ValidateTestResults();
+	}
+
+void TestTransitionWithDeferral0::Release()
+	{
+	delete this;
+	}
+
+void TestTransitionWithDeferral0::HandleTransitionL(CDomainMemberKeepAlive* aDmMember)
+	{
+	TInt ackError = iTester.TransitionNotification(*aDmMember);
+	aDmMember->GetState();
+
+	aDmMember->AcknowledgeLastState(ackError);
+	}
+
+TInt TestTransitionWithDeferral0::HandleDeferralError(TInt aError)
+	{
+	// Since this test case expects 0 deferral, the KErrNotSupported will happen which is expected
+	test(aError == KErrNotSupported);
+	return KErrNone;
+	}
+
+////////////////////////////////////////////////////////////////////////////////////
+//         TC 1.1.2.1.1 (with max deferral count - ack after n deferrals          //
+////////////////////////////////////////////////////////////////////////////////////
+class TestAckWithinDeferral : public MDomainMemberTests
+	{
+public:
+	TestAckWithinDeferral(CDmDomainKeepAliveTest& aTester) : iTester(aTester) {}
+	// from MDmKeepAliveTest
+	void Perform();
+	void Release();
+	void HandleTransitionL(CDomainMemberKeepAlive* aDmMember);
+	TInt HandleDeferralError(TInt aError);
+	void DoAsynHandleTransition(CDomainMemberKeepAlive* aDmMember);
+private:
+	CDmDomainKeepAliveTest& iTester;
+	TUint iTransitionTime;
+	};
+
+void TestAckWithinDeferral::Perform()
+	{
+	test.Printf(_L("****************TestAckWithinDeferral****************\n"));
+	test.Next(_L("Test state transition that has deferral > 0"));
+	test.Printf(_L("Acknowleding immediately......\n"));
+
+	iTester.SetExpectedValues(iTester.gTestMemberCount, 1);
+
+	SDmStateSpecV1 aStateSpec = GetMaxDeferralState();
+
+	iTestState =  aStateSpec.iState;
+	iTransitionTime = aStateSpec.iTimeoutMs * aStateSpec.iDeferralLimit / 2;
+
+	// request a system transition
+	iTester.RequestSystemTransition(iTestState, ETraverseChildrenFirst);
+	test.Printf(_L("Requested system transition\n"));
+
+	// wait for test transitions to complete
+	CActiveScheduler::Start();
+	test.Printf(_L(".......transition completed\n"));
+
+	iTester.ValidateTestResults();
+	}
+
+void TestAckWithinDeferral::Release()
+	{
+	delete this;
+	}
+
+void TestAckWithinDeferral::HandleTransitionL(CDomainMemberKeepAlive* aDmMember)
+	{
+	iTester.TransitionNotification(*aDmMember);
+
+	aDmMember->GetState();
+
+	const TTimeIntervalMicroSeconds32 KInterval = iTransitionTime * 1000; // policy defines in millisec - convert it to microsec
+
+	aDmMember->DoAsynHandleTransition(KInterval);
+	}
+
+TInt TestAckWithinDeferral::HandleDeferralError(TInt aError)
+	{
+	// Since this test case expects acknowledging within the deferral, the KErrCompletion will happen which is expected
+	test_Equal(KErrCompletion, aError);
+	return KErrNone;
+	}
+
+/* By now atleast 3 deferrals should have got finished */
+void TestAckWithinDeferral::DoAsynHandleTransition(CDomainMemberKeepAlive* aDmMember)
+	{
+	aDmMember->AcknowledgeLastState(KErrNone);
+	}
+
+////////////////////////////////////////////////////////////////////////////////////
+//                 TC 1.1.2.2.1 (But still ongoing with other domain)             //
+////////////////////////////////////////////////////////////////////////////////////
+class TestAckAfterDomainDeferralExpiry : public MDomainMemberTests
+	{
+public:
+	TestAckAfterDomainDeferralExpiry(CDmDomainKeepAliveTest& aTester) : iTester(aTester) {}
+	// from MDmKeepAliveTest
+	void Perform();
+	void Release();
+	void HandleTransitionL(CDomainMemberKeepAlive* aDmMember);
+	TInt HandleDeferralError(TInt aError);
+	void DoAsynHandleTransition(CDomainMemberKeepAlive* aDmMember);
+private:
+	CDmDomainKeepAliveTest& iTester;
+	TUint iTransitionTime;
+	};
+
+void TestAckAfterDomainDeferralExpiry::Perform()
+	{
+	test.Printf(_L("****************TestAckAfterDomainDeferralExpiry****************\n"));
+	test.Next(_L("Test client that does not acknowledge within the allowed number of deferrals "));
+	test.Printf(_L("but which then acknowledges while transition still ongoing (in other domain)\n"));
+
+	iTester.SetExpectedValues(iTester.gTestMemberCount, 1);
+
+	SDmStateSpecV1 aStateSpec = GetMaxDeferralState(ETrue);
+
+	iTestState =  aStateSpec.iState;
+	iTransitionTime = aStateSpec.iTimeoutMs * aStateSpec.iDeferralLimit * 2;
+
+	// request a system transition
+	iTester.RequestSystemTransition(iTestState, ETraverseChildrenFirst);
+	test.Printf(_L("Requested system transition\n"));
+
+	// wait for test transitions to complete
+	CActiveScheduler::Start();
+	test.Printf(_L(".......transition completed\n"));
+
+	iTester.ValidateTestResults();
+	}
+
+void TestAckAfterDomainDeferralExpiry::Release()
+	{
+	delete this;
+	}
+
+void TestAckAfterDomainDeferralExpiry::HandleTransitionL(CDomainMemberKeepAlive* aDmMember)
+	{
+	iTester.TransitionNotification(*aDmMember);
+
+	aDmMember->GetState();
+
+	const TTimeIntervalMicroSeconds32 KInterval = iTransitionTime * 1000; // policy defines in millisec - convert it to microsec
+
+	aDmMember->DoAsynHandleTransition(KInterval);
+	}
+
+TInt TestAckAfterDomainDeferralExpiry::HandleDeferralError(TInt aError)
+	{
+	// We expect the KErrNotSupported happens after expiring the deferral counts
+	test(aError == KErrNotSupported);
+	return KErrNone;
+	}
+
+/* By the time this function is called the server would have transitioned this member
+   under the domain and would have moved on to the next domain */
+void TestAckAfterDomainDeferralExpiry::DoAsynHandleTransition(CDomainMemberKeepAlive* aDmMember)
+	{
+	aDmMember->AcknowledgeLastState(KErrNone);
+	}
+
+////////////////////////////////////////////////////////////////////////////////////
+//                                   TC 1.1.2.2.2                                 //
+////////////////////////////////////////////////////////////////////////////////////
+class TestAckAfterTransitionCompletes : public MDomainMemberTests
+	{
+public:
+	TestAckAfterTransitionCompletes(CDmDomainKeepAliveTest& aTester) : iTester(aTester) {}
+	// from MDmKeepAliveTest
+	void Perform();
+	void Release();
+	void HandleTransitionL(CDomainMemberKeepAlive* aDmMember);
+	TInt HandleDeferralError(TInt aError);
+	void DoAsynMemberAck(CDomainMemberKeepAlive* aDmMember);
+private:
+	CDmDomainKeepAliveTest& iTester;
+	TInt iExpectedErrorCode;
+	};
+
+void TestAckAfterTransitionCompletes::Perform()
+	{
+	test.Printf(_L("****************TestAckAfterTransitionCompletes****************\n"));
+
+	test.Next(_L("Test client that does not acknowledge within the allowed number of deferrals "));
+	test.Printf(_L("but which then acknowledges while transition has completed\n"));
+
+	iTester.SetExpectedValues(iTester.gTestMemberCount, 1);
+
+	SDmStateSpecV1 aStateSpec = GetMaxDeferralState(ETrue);
+
+	iTestState =  aStateSpec.iState;
+
+	// request a system transition
+	iTester.RequestSystemTransition(iTestState, ETraverseChildrenFirst);
+	test.Printf(_L("Requested system transition\n"));
+
+	// wait for test transitions to complete
+	CActiveScheduler::Start();
+	test.Printf(_L(".......transition completed\n"));
+
+	iTester.ValidateTestResults();
+
+	iTester.DoAsynMemberAck();
+	}
+
+void TestAckAfterTransitionCompletes::Release()
+	{
+	delete this;
+	}
+
+void TestAckAfterTransitionCompletes::HandleTransitionL(CDomainMemberKeepAlive* aDmMember)
+	{
+	iTester.TransitionNotification(*aDmMember);
+	aDmMember->GetState();
+	}
+
+void TestAckAfterTransitionCompletes::DoAsynMemberAck(CDomainMemberKeepAlive* aDmMember)
+	{
+	aDmMember->AcknowledgeLastState(KErrNone);
+	}
+
+TInt TestAckAfterTransitionCompletes::HandleDeferralError(TInt aError)
+	{
+	test(aError == KErrNotSupported);
+	return KErrNone;
+	}
+
+////////////////////////////////////////////////////////////////////////////////////
+//					TC 1.1.2.2.3	and    TC 1.1.2.2.4						      //
+////////////////////////////////////////////////////////////////////////////////////
+class TestAckPrevTransAfterNewTransStart : public MDomainMemberTests
+	{
+public:
+	TestAckPrevTransAfterNewTransStart(CDmDomainKeepAliveTest& aTester, TBool aAckPrevTran) :
+				iShouldAck(EFalse), iAckPrevTran(aAckPrevTran), iTester(aTester) {}
+	// from MDmKeepAliveTest
+	void Perform();
+	void Release();
+	void HandleTransitionL(CDomainMemberKeepAlive* aDmMember);
+	TInt HandleDeferralError(TInt aError);
+
+private:
+	TBool iShouldAck;
+	TBool iAckPrevTran;
+	CDmDomainKeepAliveTest& iTester;
+	};
+
+void TestAckPrevTransAfterNewTransStart::Perform()
+	{
+	if(iAckPrevTran)
+		{
+		test.Printf(_L("**************** TestAckPrevTransAfterNewTransStart (Ack Previous Transition after new transition started) ****************\n"));
+		test.Next(_L("Test client that does not acknowledge within the allowed number of deferrals "));
+		test.Printf(_L("but which then acknowledges while next new transition has started\n"));
+		}
+	else
+		{
+		test.Printf(_L("**************** TestAckPrevTransAfterNewTransStart (Never Ack Previous Transition) ****************\n"));
+		test.Next(_L("Test client that does not acknowledge within the allowed number of deferrals "));
+		test.Printf(_L("but which never acknowledges and continues handling next transition\n"));
+		}
+
+	iTester.SetExpectedValues(iTester.gTestMemberCount, 1);
+
+	SDmStateSpecV1 aStateSpec = GetMaxDeferralState(ETrue);
+
+	iTestState =  aStateSpec.iState;
+
+	// request a system transition
+	iTester.RequestSystemTransition(iTestState, ETraverseChildrenFirst);
+	test.Printf(_L("Requested system transition\n"));
+
+	// wait for test transitions to complete
+	CActiveScheduler::Start();
+	test.Printf(_L("....transition completed\n"));
+
+	iTester.ValidateTestResults();
+
+	if(iAckPrevTran)
+		test.Printf(_L("Now request another transition for which the domain members should ack both transitions)\n"));
+	else
+		test.Printf(_L("Now request another transition for which the domain members should ack only the last transitions)\n"));
+
+	iTester.SetExpectedValues(iTester.gTestMemberCount*2, 2);
+	aStateSpec = GetMinDeferralState();
+	iTestState =  aStateSpec.iState;
+
+	iShouldAck = ETrue;
+	// request a system transition
+	iTester.RequestSystemTransition(iTestState, ETraverseChildrenFirst);
+	test.Printf(_L("Requested system transition\n"));
+
+	// wait for test transitions to complete
+	CActiveScheduler::Start();
+	test.Printf(_L("....transition completed\n"));
+
+	iTester.ValidateTestResults();
+	}
+
+void TestAckPrevTransAfterNewTransStart::Release()
+	{
+	delete this;
+	}
+
+void TestAckPrevTransAfterNewTransStart::HandleTransitionL(CDomainMemberKeepAlive* aDmMember)
+	{
+	TInt ackError = iTester.TransitionNotification(*aDmMember);
+	if(iShouldAck == EFalse)
+		{
+		aDmMember->GetState();
+		// request another notification (even if we didn't acknowledge the last one)
+		aDmMember->RequestTransitionNotification();
+		test.Printf(_L("....Return without acknowledging\n"));
+		return;
+		}
+
+	if(iAckPrevTran)
+		{
+		test.Printf(_L("....Acknowledge the first transition\n"));
+		/* First ack the previous notification */
+		aDmMember->AcknowledgeLastState(ackError);
+		}
+	else
+		{
+		test.Printf(_L("Skipping to acknowledge the first transition...\n"));
+		/* We are not going to ack the previous notification handled in the above if condition 
+	   Intentionally not acking and continuing to do a GetState to handle the next notification */
+		}
+
+	test.Printf(_L("Acknowledge the second transition\n"));
+	/* Now handle the current notification */
+	aDmMember->GetState();
+	aDmMember->AcknowledgeLastState(ackError);
+	}
+
+TInt TestAckPrevTransAfterNewTransStart::HandleDeferralError(TInt aError)
+	{
+	if(!iShouldAck)
+		test(aError == KErrNotSupported);
+	else
+		test_Equal(KErrCompletion, aError);
+
+	return KErrNone;
+	}
+
+////////////////////////////////////////////////////////////////////////////////////
+//                      TC 1.1.2.3.1    and    TC 1.1.2.3.2                       //
+////////////////////////////////////////////////////////////////////////////////////
+class TestCancelTransitonWithMemberAck : public MDomainMemberTests
+	{
+public:
+	TestCancelTransitonWithMemberAck(CDmDomainKeepAliveTest& aTester, TInt aErrorCode) : 
+			iTester(aTester), iCancelCount(0), iErrorCode(aErrorCode) {}
+	// from MDmKeepAliveTest
+	void Perform();
+	void Release();
+	void HandleTransitionL(CDomainMemberKeepAlive* aDmMember);
+	TInt HandleDeferralError(TInt aError);
+	void DoAsynMemberAck(CDomainMemberKeepAlive* aDmMember);
+	static TInt CancelTransitionTimerCallback(TAny* obj);
+	static TInt DelayTimerCallback(TAny* obj);
+	void StopScheduler();
+private:
+	CDmDomainKeepAliveTest& iTester;
+	TUint iTransitionTime;
+	TUint iCancelCount;
+	TInt  iErrorCode;
+	CPeriodic *iCancelTransitionTimer;
+	CPeriodic *iDelayTimer;
+	};
+
+TInt TestCancelTransitonWithMemberAck::CancelTransitionTimerCallback(TAny* obj)
+	{
+    TestCancelTransitonWithMemberAck* thisTest = static_cast<TestCancelTransitonWithMemberAck*>(obj);
+
+	thisTest->iTester.CancelTransition();
+	thisTest->iCancelTransitionTimer->Cancel();
+	return KErrNone;
+	}
+
+TInt TestCancelTransitonWithMemberAck::DelayTimerCallback(TAny* obj)
+	{
+    TestCancelTransitonWithMemberAck* thisTest = static_cast<TestCancelTransitonWithMemberAck*>(obj);
+
+	thisTest->iDelayTimer->Cancel();
+	thisTest->StopScheduler();
+	return KErrNone;
+	}
+
+void TestCancelTransitonWithMemberAck::StopScheduler()
+	{
+	CActiveScheduler::Stop();
+	}
+
+void TestCancelTransitonWithMemberAck::Perform()
+	{
+	test.Printf(_L("****************TestCancelTransitonWithMemberAck****************\n"));
+	test.Next(_L("Test state transition cancelation...."));
+	test.Printf(_L("that acknowledes KErrNone......\n"));
+
+	iTester.SetExpectedValues(iTester.gLeafMemberCount, 1);
+
+	SDmStateSpecV1 aStateSpec = GetMaxDeferralState();
+
+	iTestState =  aStateSpec.iState;
+	iTransitionTime = aStateSpec.iTimeoutMs * aStateSpec.iDeferralLimit / 2;
+
+	// request a system transition
+	iTester.RequestSystemTransition(iTestState, ETraverseChildrenFirst);
+	test.Printf(_L("Requested system transition\n"));
+
+	iCancelTransitionTimer = CPeriodic::NewL(CActive::EPriorityHigh);
+
+	TCallBack cancelCb(CancelTransitionTimerCallback, this);
+	iCancelTransitionTimer->Start(aStateSpec.iTimeoutMs, aStateSpec.iTimeoutMs, cancelCb);
+
+	// wait for test transitions to complete
+	CActiveScheduler::Start();
+	test.Printf(_L("....transition cancelled\n"));
+
+	iDelayTimer = CPeriodic::NewL(CActive::EPriorityStandard);
+
+	TCallBack delayCb(DelayTimerCallback, this);
+	TUint delayTime = iTransitionTime * 3;
+	iDelayTimer->Start(delayTime, delayTime, delayCb);
+
+	CActiveScheduler::Start();
+	test.Printf(_L("........expected members got cancelation notified\n"));
+
+	iTester.DoAsynMemberAck();
+
+	iTester.ValidateTestResults();
+	}
+
+void TestCancelTransitonWithMemberAck::Release()
+	{
+	delete iDelayTimer;
+	delete iCancelTransitionTimer;
+	delete this;
+	}
+
+void TestCancelTransitonWithMemberAck::HandleTransitionL(CDomainMemberKeepAlive* aDmMember)
+	{
+	iTester.TransitionNotification(*aDmMember);
+
+	aDmMember->GetState();
+	}
+
+TInt TestCancelTransitonWithMemberAck::HandleDeferralError(TInt aError)
+	{
+	// KErrNotReady is possible if the cancellation
+	// ocurred in between member deferrrals
+	test(aError == KErrCancel || aError == KErrNotReady);
+	test(++iCancelCount <= iTester.gLeafMemberCount);
+	return KErrNone;
+	}
+
+void TestCancelTransitonWithMemberAck::DoAsynMemberAck(CDomainMemberKeepAlive* aDmMember)
+	{
+	aDmMember->AcknowledgeLastState(iErrorCode);
+	}
+
+////////////////////////////////////////////////////////////////////////////////////
+//                                TC 1.1.2.3.3                                    //
+////////////////////////////////////////////////////////////////////////////////////
+class TestCancelTransitonNeverAck : public MDomainMemberTests // TC1.1.2.3.3
+	{
+public:
+	TestCancelTransitonNeverAck(CDmDomainKeepAliveTest& aTester) : iTester(aTester), iCancelCount(0), iShouldAck(EFalse){}
+	// from MDmKeepAliveTest
+	void Perform();
+	void Release();
+	void HandleTransitionL(CDomainMemberKeepAlive* aDmMember);
+	TInt HandleDeferralError(TInt aError);
+	static TInt CancelTransitionTimerCallback(TAny* obj);
+	static TInt DelayTimerCallback(TAny* obj);
+	void StopScheduler();
+private:
+	CDmDomainKeepAliveTest& iTester;
+	TUint iTransitionTime;
+	TUint iCancelCount;
+	TBool iShouldAck;
+	CPeriodic *iCancelTransitionTimer;
+	CPeriodic *iDelayTimer;
+	};
+
+TInt TestCancelTransitonNeverAck::CancelTransitionTimerCallback(TAny* obj)
+	{
+    TestCancelTransitonNeverAck* thisTest = static_cast<TestCancelTransitonNeverAck*>(obj);
+
+	thisTest->iTester.CancelTransition();
+	thisTest->iCancelTransitionTimer->Cancel();
+	return KErrNone;
+	}
+
+TInt TestCancelTransitonNeverAck::DelayTimerCallback(TAny* obj)
+	{
+    TestCancelTransitonNeverAck* thisTest = static_cast<TestCancelTransitonNeverAck*>(obj);
+
+	thisTest->iDelayTimer->Cancel();
+	thisTest->StopScheduler();
+	return KErrNone;
+	}
+
+void TestCancelTransitonNeverAck::StopScheduler()
+	{
+	CActiveScheduler::Stop();
+	}
+
+void TestCancelTransitonNeverAck::Perform()
+	{
+	test.Printf(_L("****************TestCancelTransitonNeverAck****************\n"));
+	test.Next(_L("Test state transition cancelation...."));
+	test.Printf(_L("that never acknowledes ......\n"));
+
+	iTester.SetExpectedValues(iTester.gLeafMemberCount, 1);
+
+	SDmStateSpecV1 aStateSpec = GetMaxDeferralState();
+
+	iTestState =  aStateSpec.iState;
+	iTransitionTime = aStateSpec.iTimeoutMs * aStateSpec.iDeferralLimit / 2;
+
+	// request a system transition
+	iTester.RequestSystemTransition(iTestState, ETraverseChildrenFirst);
+	test.Printf(_L("Requested system transition\n"));
+
+	iCancelTransitionTimer = CPeriodic::NewL(CActive::EPriorityHigh);
+
+	TCallBack cancelCb(CancelTransitionTimerCallback, this);
+	iCancelTransitionTimer->Start(iTransitionTime, iTransitionTime, cancelCb);
+
+	// wait for test transitions to complete
+	CActiveScheduler::Start();
+	test.Printf(_L("....transition cancelled\n"));
+
+	iDelayTimer = CPeriodic::NewL(CActive::EPriorityStandard);
+
+	TCallBack delayCb(DelayTimerCallback, this);
+	TUint delayTime = iTransitionTime * 3;
+	iDelayTimer->Start(delayTime, delayTime, delayCb);
+
+	CActiveScheduler::Start();
+	test.Printf(_L("........expected members got cancelation notified\n"));
+
+	iTester.ValidateTestResults();
+
+	test.Printf(_L("Now request another transition for which the domain members should ack only the last transitions)\n"));
+
+	iTester.SetExpectedValues(iTester.gTestMemberCount + iTester.gLeafMemberCount, 2);
+	aStateSpec = GetMinDeferralState();
+
+	iTestState =  aStateSpec.iState;
+
+	iShouldAck = ETrue;
+	// request a system transition
+	iTester.RequestSystemTransition(iTestState, ETraverseChildrenFirst);
+	test.Printf(_L("Requested system transition\n"));
+
+	// wait for test transitions to complete
+	CActiveScheduler::Start();
+	test.Printf(_L(".......transition completed\n"));
+
+	iTester.ValidateTestResults();
+	}
+
+void TestCancelTransitonNeverAck::Release()
+	{
+	delete iDelayTimer;
+	delete iCancelTransitionTimer;
+	delete this;
+	}
+
+void TestCancelTransitonNeverAck::HandleTransitionL(CDomainMemberKeepAlive* aDmMember)
+	{
+	TInt ackError = iTester.TransitionNotification(*aDmMember);
+
+	if(iShouldAck == EFalse)
+		{
+		aDmMember->GetState();
+
+		// request another notification (even if we didn't acknowledge the last one)
+		aDmMember->RequestTransitionNotification();
+		test.Printf(_L("Return without acknowledging...\n"));
+		return;
+		}
+
+	test.Printf(_L("Skipping to acknowledge the first transition...\n"));
+	/* We are not going to ack the previous notification handled in the above if condition 
+	   Intentionally not acking and continuing to do a GetState to handle the next notification */
+
+	test.Printf(_L("Acknowledge the second transition...\n"));
+	/* Now handle the current notification */
+	aDmMember->GetState();
+	aDmMember->AcknowledgeLastState(ackError);
+	}
+
+TInt TestCancelTransitonNeverAck::HandleDeferralError(TInt aError)
+	{
+	if(!iShouldAck)
+		{
+		// KErrNotReady is possible if the cancellation
+		// ocurred in between member deferrrals
+		test(aError == KErrCancel || aError == KErrNotReady);
+		}
+	else
+		test_Equal(KErrCompletion, aError);
+
+	if(aError == KErrCancel || (aError == KErrNotReady && !iShouldAck))
+		test(++iCancelCount <= iTester.gLeafMemberCount);
+
+	return KErrNone;
+	}
+
+////////////////////////////////////////////////////////////////////////////////////
+//                           CDmDomainKeepAliveTest                               //
+////////////////////////////////////////////////////////////////////////////////////
+void CDmDomainKeepAliveTest::Init(MDomainMemberTests* aTest)
+	{
+	TInt r = RDmDomainManager::AddDomainHierarchy(KDmHierarchyIdTestV2);
+	test_KErrNone(r);
+
+	r = iTestDomainManager.Connect(KDmHierarchyIdTestV2);
+	test_KErrNone(r);
+
+	iTransitionsCompleted = 0;
+	iTestNotifications = 0;
+	gTestMemberCount = 0;
+	gLeafMemberCount = 0;
+
+	// Add some test hierarchy members
+	test_TRAP(iTestMembers[gTestMemberCount++] = CDomainMemberKeepAlive::NewL(KDmHierarchyIdTestV2, KDmIdRoot, ORDINAL_FROM_DOMAINID0(KDmIdRoot), aTest));
+
+	test_TRAP(iTestMembers[gTestMemberCount++] = CDomainMemberKeepAlive::NewL(KDmHierarchyIdTestV2, KDmIdRoot, ORDINAL_FROM_DOMAINID0(KDmIdRoot), aTest));
+	
+	// row 1
+	test_TRAP(iTestMembers[gTestMemberCount++] = CDomainMemberKeepAlive::NewL(KDmHierarchyIdTestV2, KDmIdTestA, ORDINAL_FROM_DOMAINID1(KDmIdRoot, KDmIdTestA), aTest));
+
+	test_TRAP(iTestMembers[gTestMemberCount++] = CDomainMemberKeepAlive::NewL(KDmHierarchyIdTestV2, KDmIdTestB, ORDINAL_FROM_DOMAINID1(KDmIdRoot, KDmIdTestB), aTest));
+
+	test_TRAP(iTestMembers[gTestMemberCount++] = CDomainMemberKeepAlive::NewL(KDmHierarchyIdTestV2, KDmIdTestC, ORDINAL_FROM_DOMAINID1(KDmIdRoot, KDmIdTestC), aTest));
+	
+	// row2
+	test_TRAP(iTestMembers[gTestMemberCount++] = CDomainMemberKeepAlive::NewL(KDmHierarchyIdTestV2, KDmIdTestAA, ORDINAL_FROM_DOMAINID2(KDmIdRoot, KDmIdTestA, KDmIdTestAA), aTest));
+	gLeafMemberCount++;
+
+	test_TRAP(iTestMembers[gTestMemberCount++] = CDomainMemberKeepAlive::NewL(KDmHierarchyIdTestV2, KDmIdTestAB, ORDINAL_FROM_DOMAINID2(KDmIdRoot, KDmIdTestA, KDmIdTestAB), aTest));
+
+	test_TRAP(iTestMembers[gTestMemberCount++] = CDomainMemberKeepAlive::NewL(KDmHierarchyIdTestV2, KDmIdTestBA, ORDINAL_FROM_DOMAINID2(KDmIdRoot, KDmIdTestB, KDmIdTestBA), aTest));
+	gLeafMemberCount++;
+
+	test_TRAP(iTestMembers[gTestMemberCount++] = CDomainMemberKeepAlive::NewL(KDmHierarchyIdTestV2, KDmIdTestCA, ORDINAL_FROM_DOMAINID2(KDmIdRoot, KDmIdTestC, KDmIdTestCA), aTest));
+	
+	// row 3
+	test_TRAP(iTestMembers[gTestMemberCount++] = CDomainMemberKeepAlive::NewL(KDmHierarchyIdTestV2, KDmIdTestABA, ORDINAL_FROM_DOMAINID3(KDmIdRoot, KDmIdTestA, KDmIdTestAB, KDmIdTestABA), aTest));
+	gLeafMemberCount++;
+
+	test_TRAP(iTestMembers[gTestMemberCount++] = CDomainMemberKeepAlive::NewL(KDmHierarchyIdTestV2, KDmIdTestABB, ORDINAL_FROM_DOMAINID3(KDmIdRoot, KDmIdTestA, KDmIdTestAB, KDmIdTestABB), aTest));
+	gLeafMemberCount++;
+
+	test_TRAP(iTestMembers[gTestMemberCount++] = CDomainMemberKeepAlive::NewL(KDmHierarchyIdTestV2, KDmIdTestCAA, ORDINAL_FROM_DOMAINID3(KDmIdRoot, KDmIdTestC, KDmIdTestCA, KDmIdTestCAA), aTest));
+	gLeafMemberCount++;
+
+	}
+
+void CDmDomainKeepAliveTest::SetExpectedValues(TInt aTestNotificationsExpected, TInt aTransitionsExpected)
+	{
+	iTestNotificationsExpected = aTestNotificationsExpected;
+	iTransitionsExpected = aTransitionsExpected;
+	}
+
+void CDmDomainKeepAliveTest::ValidateTestResults()
+	{
+	test.Printf(_L("ValidateResults().....\n"));
+
+	test.Printf(_L("iTestNotifications = %d iTestNotificationsExpected = %d\n"), iTestNotifications ,
+				iTestNotificationsExpected);
+	test(iTestNotifications == iTestNotificationsExpected);
+	}
+
+void CDmDomainKeepAliveTest::UnInit()
+	{
+	iTestDomainManager.Close();
+
+	// cleanup
+	
+	for (TUint i = 0; i<gTestMemberCount; i++)
+		delete iTestMembers[i];
+	}
+
+void CDmDomainKeepAliveTest::RequestSystemTransition(TDmDomainState aTestState, TDmTraverseDirection aDirection) 
+	{
+	iTestDomainManager.RequestSystemTransition(aTestState, aDirection, CActive::iStatus);
+	CActive::SetActive();
+	}
+
+void CDmDomainKeepAliveTest::Perform()
+	{
+ 	__UHEAP_MARK;
+
+	CActiveScheduler::Add(this);
+
+	MDomainMemberTests* tests[] = 
+		{
+			new TestTransitionWithDeferral0(*this), // TC 1.1.2.1.1 (with deferral count 0)
+			new TestAckWithinDeferral(*this), // TC 1.1.2.1.1 (with max deferral count)
+			new TestAckAfterDomainDeferralExpiry(*this), // TC 1.1.2.2.1 (But still ongoing with other domain)
+			new TestAckAfterTransitionCompletes(*this), // TC 1.1.2.2.2
+			new TestAckPrevTransAfterNewTransStart(*this, ETrue), // TC 1.1.2.2.3
+			new TestAckPrevTransAfterNewTransStart(*this, EFalse), // TC 1.1.2.2.4
+			new TestCancelTransitonWithMemberAck(*this, KErrNone), // TC1.1.2.3.1
+			new TestCancelTransitonWithMemberAck(*this, KErrCompletion), // TC1.1.2.3.2
+			new TestCancelTransitonNeverAck(*this), // TC1.1.2.3.3
+		};
+
+	for (unsigned int i = 0; i < sizeof(tests)/sizeof(*tests); ++i)
+		{
+		test(tests[i] != NULL);
+		Init(tests[i]);
+		iCurrentTest = tests[i];
+		tests[i]->Perform();
+		tests[i]->Release();
+		UnInit();
+		}
+	__UHEAP_MARKEND;
+	}
+
+void CDmDomainKeepAliveTest::DoAsynMemberAck()
+	{
+	for (TUint i = 0; i<gTestMemberCount; i++)
+		{
+		if(iTestMembers[i]->iShouldAck)
+			{
+			TBuf16<4> buf;
+			GetDomainDesc(iTestMembers[i]->Ordinal(), buf);
+			test.Printf(_L("Request current test to ack %S.......\n"), &buf);
+			iCurrentTest->DoAsynMemberAck(iTestMembers[i]);
+			iTestMembers[i]->iShouldAck = EFalse;
+			}
+		}
+	}
+
+void CDmDomainKeepAliveTest::CancelTransition()
+	{
+	iTestDomainManager.CancelTransition();
+	}
+
+	// This handles a transition notification from a test domain member.
+TInt CDmDomainKeepAliveTest::TransitionNotification(MDmDomainMember& aDomainMember)
+	{
+	TInt status = aDomainMember.Status();
+
+	iTestNotifications++;
+
+	test (aDomainMember.HierarchyId() == KDmHierarchyIdTestV2);
+
+	TBuf16<4> buf;
+	GetDomainDesc(aDomainMember.Ordinal(), buf);
+
+	test.Printf(_L("TransitionNotification Hierarchy = %d, domain = %S, iOrdinal = 0x%08X, state = 0x%x, status = %d\n"), 
+		aDomainMember.HierarchyId(), &buf, aDomainMember.Ordinal(), aDomainMember.State(), status);
+
+	return KErrNone;
+	}
+
+void CDmDomainKeepAliveTest::RunL()
+	{
+	iTransitionsCompleted++;
+
+	TInt error = iStatus.Int();
+
+	test.Printf(_L("CDmDomainKeepAliveTest::RunL() error = %d, iTransitionsCompleted %d iTransitionsExpected %d\n"), 
+		error, iTransitionsCompleted, iTransitionsExpected);
+
+	if (iTransitionsCompleted == iTransitionsExpected)
+		CActiveScheduler::Stop();
+	}
+
+void CDmDomainKeepAliveTest::DoCancel()
+	{
+	test(0);
+	}
+
+void CDmDomainKeepAliveTest::Release()
+	{
+	delete this;
+	}
+
+
+TUint CDmDomainKeepAliveTest::gTestMemberCount = 0;
+TUint CDmDomainKeepAliveTest::gLeafMemberCount = 0;
+
+
+/**
+   DeferAcknowledgement() with status KErrServerBusy.
+
+   Client receives notification, defers once and then defers again before the
+   next notification.
+*/
+class ActiveMember : public CActive
+	{
+public:
+	ActiveMember(CDmTestMember* aMember)
+		: CActive(CActive::EPriorityHigh), iMember(aMember)
+		{
+		CActiveScheduler::Add(this);
+		}
+	~ActiveMember()
+		{
+		Cancel();
+		}
+	void Defer()
+		{
+		iMember->iDomain.DeferAcknowledgement(iStatus);
+		SetActive();
+		}
+	void DoCancel()
+		{
+		iMember->iDomain.CancelDeferral();
+		}
+protected:
+	CDmTestMember* const iMember;
+	};
+
+
+class TestServerBusy : public ActiveMember
+	{
+public:
+	TestServerBusy(CDmTestMember* aMember);
+	~TestServerBusy();
+	void PrimeTimer();
+private:
+	void RunL();
+private:
+	RTimer iTimer;
+	TBool iDeferred;
+	const TInt iInstance;
+	static TInt iInstances;
+	};
+
+TInt TestServerBusy::iInstances = 0;
+
+
+TestServerBusy::TestServerBusy(CDmTestMember* aMember)
+	: ActiveMember(aMember), iDeferred(EFalse), iInstance(++iInstances)
+	{
+	const TInt r = iTimer.CreateLocal();
+	test_KErrNone(r);
+	}
+
+
+TestServerBusy::~TestServerBusy()
+	{
+	Cancel();
+	iTimer.Close();
+	iInstances--;
+	}
+
+
+void TestServerBusy::PrimeTimer()
+	{
+	// let the timers fire at different times (first one in 1ms, second one in
+	// 50ms)
+	const TTimeIntervalMicroSeconds32 t = (iInstance == 1) ? 1000 : 50000;
+	iTimer.After(iStatus, t);
+	SetActive();
+	}
+
+
+void TestServerBusy::RunL()
+	{
+	RDebug::Printf("TestServerBusy(#%d)::RunL(): %d", iInstance, iStatus.Int());
+	if (!iDeferred)
+		{
+		iDeferred = ETrue;
+		Defer();
+		}
+	else if (iInstance == 2)
+		{
+		// This is the test (TC 1.1.1.7.1):
+		test_Equal(KErrServerBusy, iStatus.Int());
+		}
+	else if (iInstance == 1)
+		{
+		// Acknowledge at last
+		test_KErrNone(iStatus.Int());
+		iMember->Acknowledge();
+		}
+	else
+		test(0);
+	}
+
+
+class CDmDeferralTestKErrServerBusy : public CDmDeferralTest
+	{
+public:
+	CDmDeferralTestKErrServerBusy(TDmHierarchyId aId, TDmDomainState aState);
+	~CDmDeferralTestKErrServerBusy();
+	// from CDmDeferralTest
+	void DoPerform();
+	// from MDmTest
+	TInt TransitionNotification(MDmDomainMember& aDomainMember);
+	void TransitionRequestComplete();
+private:
+	TestServerBusy* iDeferral1;
+	TestServerBusy* iDeferral2;
+	};
+
+
+CDmDeferralTestKErrServerBusy::CDmDeferralTestKErrServerBusy(TDmHierarchyId aId,
+															 TDmDomainState aState)
+	: CDmDeferralTest(aId, aState)
+	{
+	}
+
+
+CDmDeferralTestKErrServerBusy::~CDmDeferralTestKErrServerBusy()
+	{
+	delete iDeferral1;
+	delete iDeferral2;
+	}
+
+
+void CDmDeferralTestKErrServerBusy::DoPerform()
+	{
+	test.Next(_L("CDmDeferralTestKErrServerBusy"));
+
+	iMember = new CDmTestMember(iHierarchyId, KDmIdTestCAA, 0, this);
+	test_NotNull(iMember);
+
+	iDeferral1 = new TestServerBusy(iMember);
+	test_NotNull(iDeferral1);
+	iDeferral2 = new TestServerBusy(iMember);
+	test_NotNull(iDeferral2);
+
+	iManager.RequestSystemTransition(iState, ETraverseDefault, CActive::iStatus);
+	}
+
+
+TInt CDmDeferralTestKErrServerBusy::TransitionNotification(MDmDomainMember&)
+	{
+	RDebug::Printf("CDmDeferralTestKErrServerBusy::TransitionNotification()");
+
+	iDeferral1->PrimeTimer();
+
+	iDeferral2->PrimeTimer();
+
+	// don't acknowledge yet
+	return KErrAbort;
+	}
+
+
+void CDmDeferralTestKErrServerBusy::TransitionRequestComplete()
+	{
+	RDebug::Printf("CDmDeferralTestKErrServerBusy::TransitionRequestComplete()");
+	}
+
+
+/**
+   DeferAcknowledgement() with status KErrCancel.
+
+   1. Client receives notification, defers once and then cancels before the next
+   notification.
+   2. Client receives notification, cancels deferral without one outstanding.
+*/
+class TestCancel : public ActiveMember
+	{
+public:
+	TestCancel(CDmTestMember* aMember)
+		: ActiveMember(aMember)
+		{
+		}
+	void RunL()
+		{
+		RDebug::Printf("TestCancel::RunL(): %d", iStatus.Int());
+
+		// This is the test (TC 1.1.1.4.1):
+		test_Equal(KErrCancel, iStatus.Int());
+
+		// Acknowledge at last
+		iMember->Acknowledge();
+		}
+	};
+
+
+class CDmDeferralTestKErrCancel : public CDmDeferralTest
+	{
+public:
+	CDmDeferralTestKErrCancel(TDmHierarchyId aId, TDmDomainState aState, TBool aDeferFirst);
+	~CDmDeferralTestKErrCancel();
+	// from CDmDeferralTest
+	void DoPerform();
+	// from MDmTest
+	TInt TransitionNotification(MDmDomainMember& aDomainMember);
+	void TransitionRequestComplete();
+private:
+	TestCancel* iCancel;
+	const TBool iDeferFirst;
+	};
+
+
+CDmDeferralTestKErrCancel::CDmDeferralTestKErrCancel(TDmHierarchyId aId,
+													 TDmDomainState aState,
+													 TBool aDeferFirst)
+	: CDmDeferralTest(aId, aState), iDeferFirst(aDeferFirst)
+	{
+	}
+
+
+CDmDeferralTestKErrCancel::~CDmDeferralTestKErrCancel()
+	{
+	delete iCancel;
+	}
+
+
+void CDmDeferralTestKErrCancel::DoPerform()
+	{
+	test.Next(_L("CDmDeferralTestKErrCancel"));
+
+	iMember = new CDmTestMember(iHierarchyId, KDmIdTestABA, 0, this);
+	test_NotNull(iMember);
+
+	iCancel = new TestCancel(iMember);
+	test_NotNull(iCancel);
+
+	iManager.RequestSystemTransition(iState, ETraverseDefault, CActive::iStatus);
+	}
+
+
+TInt CDmDeferralTestKErrCancel::TransitionNotification(MDmDomainMember&)
+	{
+	RDebug::Printf("CDmDeferralTestKErrCancel::TransitionNotification()");
+
+	if (iDeferFirst)
+		{
+		// Test case 1: First ask for a deferral...
+		iCancel->Defer();
+		}
+
+	// Test cases 1 & 2: Cancel deferral request.
+
+	// RDmDomainSession::CancelDeferral() checks if
+	// RSessionBase::SendReceive(EDmStateCancelDeferral) returned KErrNone;
+	// if not it will panic the client. (TC 1.1.1.4.2)
+
+	iMember->iDomain.CancelDeferral();
+
+	if (iDeferFirst)
+		{
+		// don't acknowledge yet (RunL() will)
+		return KErrAbort;
+		}
+	else
+		{
+		return KErrNone;
+		}
+	}
+
+
+void CDmDeferralTestKErrCancel::TransitionRequestComplete()
+	{
+	RDebug::Printf("CDmDeferralTestKErrCancel::TransitionRequestComplete()");
+	}
+
+
+/**
+   DeferAcknowledgement() with status KErrNotReady.
+
+   1. Client defers before a transition notification.
+   2. Client receives notification, defers once and then defers again after the
+   next notification.
+*/
+class TestNotReady : public ActiveMember
+	{
+public:
+	TestNotReady(CDmTestMember* aMember)
+		: ActiveMember(aMember)
+		{
+		}
+	void RunL()
+		{
+		RDebug::Printf("TestNotReady::RunL(): %d", iStatus.Int());
+
+		// This is the test (TC 1.1.1.5.1):
+		test_Equal(KErrNotReady, iStatus.Int());
+
+		CActiveScheduler::Stop();
+		}
+	};
+
+
+class CDmDeferralTestKErrNotReady : public CDmDeferralTest
+	{
+public:
+	CDmDeferralTestKErrNotReady(TDmHierarchyId aId, TDmDomainState aState);
+	~CDmDeferralTestKErrNotReady();
+	// from CDmDeferralTest
+	void DoPerform();
+	// from MDmTest
+	TInt TransitionNotification(MDmDomainMember& aDomainMember);
+	void TransitionRequestComplete();
+private:
+	TestNotReady* iNotReady;
+	};
+
+
+CDmDeferralTestKErrNotReady::CDmDeferralTestKErrNotReady(TDmHierarchyId aId,
+														 TDmDomainState aState)
+	: CDmDeferralTest(aId, aState)
+	{
+	}
+
+
+CDmDeferralTestKErrNotReady::~CDmDeferralTestKErrNotReady()
+	{
+	delete iNotReady;
+	}
+
+
+void CDmDeferralTestKErrNotReady::DoPerform()
+	{
+	test.Next(_L("CDmDeferralTestKErrNotReady"));
+
+	iMember = new CDmTestMember(iHierarchyId, KDmIdTestABA, 0, this);
+	test_NotNull(iMember);
+
+	iNotReady = new TestNotReady(iMember);
+	test_NotNull(iNotReady);
+
+	iNotReady->Defer();
+	CActiveScheduler::Start();
+
+	iManager.RequestSystemTransition(iState, ETraverseDefault, CActive::iStatus);
+	}
+
+
+TInt CDmDeferralTestKErrNotReady::TransitionNotification(MDmDomainMember&)
+	{
+	RDebug::Printf("CDmDeferralTestKErrNotReady::TransitionNotification()");
+
+	// don't acknowledge yet
+	return KErrAbort;
+	}
+
+
+void CDmDeferralTestKErrNotReady::TransitionRequestComplete()
+	{
+	RDebug::Printf("CDmDeferralTestKErrNotReady::TransitionRequestComplete()");
+
+	TRequestStatus status;
+	iMember->iDomain.DeferAcknowledgement(status);
+	User::WaitForRequest(status);
+
+	RDebug::Printf("Deferral status: %d", status.Int());
+
+	// This is the test (TC 1.1.1.5.2):
+	test_Equal(KErrNotReady, status.Int());
+
+	}
+
+
+/**
+   Policy interface tests - negative tests.
+
+   1. Ordinals return null or error.
+   2. Structure returned contains invalid values.
+*/
+class CDmPolicyInterfaceTest : public MDmTest
+	{
+public:
+	void Perform();
+	void Release();
+	TInt TransitionNotification(MDmDomainMember&)
+		{
+		return KErrNone;
+		}
+	void TransitionRequestComplete()
+		{}
+	};
+
+
+void CDmPolicyInterfaceTest::Perform()
+	{
+	test.Next(_L("CDmPolicyInterfaceTest"));
+
+	// In domainpolicy95.dll ordinal 4 (DmPolicy::GetStateSpec) returns an
+	// error. This will lead to the failure of the following call, which will
+	// also execute the destructors of classes CDmHierarchy and
+	// CHierarchySettings.
+	TInt r = RDmDomainManager::AddDomainHierarchy(KDmHierarchyIdTestV2_95);
+
+	// This is the test (TC 1.4.2.1):
+	test_Equal(KDmErrBadDomainSpec, r);
+
+	// domainpolicy94.dll contains garbage values in the SDmStateSpecV1 struct.
+	r = RDmDomainManager::AddDomainHierarchy(KDmHierarchyIdTestV2_94);
+
+	// This is the test (TC 1.4.2.2):
+	test_Equal(KDmErrBadDomainSpec, r);
+	}
+
+
+void CDmPolicyInterfaceTest::Release()
+	{
+	delete this;
+	}
+
+
+/////////////////////// Failure Policy Tests //////////////////////////////////
+// 2.4 [M] Domain Controller DC5 (different failure policies for different 
+//         system state transitions)
+//    * TC 2.4.1 Create V2 policy where some states are "stop" and some are 
+//      "continue" on failure, get member(s) to fail 
+//
+
+class CDmFailurePolicyTest : public CActive, public MDmTest
+	{
+public:
+	CDmFailurePolicyTest(TDmDomainState aState, TDmTransitionFailurePolicy aPolicy);
+	~CDmFailurePolicyTest();
+		
+	// from CActive
+	void RunL();
+	
+	// from MDmTest
+	void Perform();
+	void Release();
+	TInt TransitionNotification(MDmDomainMember&);
+	void TransitionRequestComplete()
+		{}
+		
+private:
+	// from CActive
+	virtual void DoCancel()
+		{ test(0); }
+		
+private:
+	RDmDomainManager iManager;
+	CDmTestMember*	 iMembers[2];
+	
+	TDmDomainState				iDmState;
+	TDmTransitionFailurePolicy	iFailPolicy;
+	};
+
+
+CDmFailurePolicyTest::CDmFailurePolicyTest(TDmDomainState aState, TDmTransitionFailurePolicy aPolicy)
+	: CActive(CActive::EPriorityStandard), iDmState(aState), iFailPolicy(aPolicy)
+	{
+	iMembers[0] = iMembers[1] = 0;
+	}
+	
+CDmFailurePolicyTest::~CDmFailurePolicyTest()
+	{
+	Cancel();
+	for (int i = 0; i < 2; i++)
+		delete iMembers[i], iMembers[i]= 0;
+	iManager.Close();
+	}
+
+void CDmFailurePolicyTest::Perform()
+	{
+	test.Next(_L("CDmFailurePolicyTest"));
+	
+	RDebug::Printf("CDmFailurePolicyTest::Perform: iFailPolicy(%d)", iFailPolicy);
+
+	// 1. Set up test hierarchy/domain & join it
+	TInt r = RDmDomainManager::AddDomainHierarchy(KDmHierarchyIdTestV2);
+	test_KErrNone(r);
+	r = iManager.Connect(KDmHierarchyIdTestV2);
+	test_KErrNone(r);
+
+	// 2. Create the two members needed for this test. First does not ackn.
+	iMembers[0] = new CDmTestMember(KDmHierarchyIdTestV2, KDmIdTestB, (iFailPolicy<<8)+0, this);
+	test_NotNull(iMembers[0]);
+	iMembers[1] = new CDmTestMember(KDmHierarchyIdTestV2, KDmIdTestBA, (iFailPolicy<<8)+1, this);
+	test_NotNull(iMembers[1]);
+
+	// 3. Initiate state transition from iInitState to iDmState
+	CActiveScheduler::Add(this);
+	iManager.RequestDomainTransition(KDmIdTestB, iDmState, ETraverseParentsFirst, iStatus);
+	CActive::SetActive();
+	CActiveScheduler::Start();
+
+	// Close iManager when this object is destroyed in destructor
+	}
+
+TInt CDmFailurePolicyTest::TransitionNotification(MDmDomainMember& aMember)
+	{
+	RDebug::Printf("CDmFailurePolicyTest::TransitionNotification: aMember(%d)", aMember.Ordinal());
+	
+    if ((aMember.Ordinal() & 0xff ) == 0)		// Member in domain B
+	{
+		if (((aMember.Ordinal() & 0xff00) >> 8) == 0) // Stop policy
+		{
+			return KErrAbort; // Dont let this member in domain B ackn.
+		}
+		else // Continue policy
+		{
+			return KErrCommsParity; // Ackn with bizarre error
+		}	
+    }
+    
+	// Should only reach here for Members of sub-domain BA
+	return KErrNone;
+	}
+
+
+void CDmFailurePolicyTest::RunL()
+	{
+	RDebug::Printf("CDmFailurePolicyTest::RunL: istatus(%d)", iStatus.Int());
+	
+	// Handle Transition completion code here. Should be a time out.
+	
+	// Based on failure policy check to see if the second member was transitioned
+	// (continue) or whether it was not (stop). Since ETraverseParentsFirst is used
+	// in the transition iMember[0] in domain B should fail and the iMember [1]
+	// in domain BA may or may not then be transitioned....
+	
+	test_Equal(1, iMembers[0]->Notifications());
+	
+	if (iFailPolicy == ETransitionFailureContinue)
+		{
+		test_Equal(KErrCommsParity, iStatus.Int());		
+		test_Equal(1, iMembers[1]->Notifications()); // Proves it did continue with transition
+		}
+	else if (iFailPolicy == ETransitionFailureStop)
+		{
+		test_Equal(KErrTimedOut, iStatus.Int());
+		test_Equal(0, iMembers[1]->Notifications()); // Proves it did stop transition
+		}
+	else
+		{
+		test(0); // Panic default case
+		}	
+		
+	test.Printf(_L("Test passed - failure policy (%d)\n"), iFailPolicy);
+	
+	CActiveScheduler::Stop();
+	}
+
+
+void CDmFailurePolicyTest::Release()
+	{
+	RDebug::Printf("CDmFailurePolicyTest::Release");
+	delete this;
+	}
+
+/****************************** CDmDomainKeepAlive Functional coverage test ******************************/
+// CDmKeepAliveFuncCov
+class CDmKeepAliveFuncCov : public CDmDomainKeepAlive
+	{
+public:
+	enum TMemKeepAliveCovTests { ECovHandleError, ECovDoCancel };
+
+	static CDmKeepAliveFuncCov* NewL(TDmHierarchyId aHierarchy, TDmDomainId aId);
+	~CDmKeepAliveFuncCov();
+
+	// from CDmDomainKeepAlive
+	void HandleTransitionL();
+private:
+	CDmKeepAliveFuncCov(TDmHierarchyId aHierarchy, TDmDomainId aId);
+
+public:
+	TMemKeepAliveCovTests iDmMemCov;
+	};
+
+CDmKeepAliveFuncCov* CDmKeepAliveFuncCov::NewL(TDmHierarchyId aHierarchy, TDmDomainId aId)
+	{
+	CDmKeepAliveFuncCov* self=new (ELeave) CDmKeepAliveFuncCov(aHierarchy, aId);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+
+	self->RequestTransitionNotification();
+
+	CleanupStack::Pop();
+	return self;
+	}
+
+CDmKeepAliveFuncCov::~CDmKeepAliveFuncCov()
+	{
+	Cancel();
+	}
+
+CDmKeepAliveFuncCov::CDmKeepAliveFuncCov(TDmHierarchyId aHierarchy, TDmDomainId aId):
+	CDmDomainKeepAlive(aHierarchy, aId)
+	{
+	}
+
+void CDmKeepAliveFuncCov::HandleTransitionL()
+	{
+	switch(iDmMemCov)
+		{
+		case ECovHandleError:
+			// Simply ack. Since the request transition is for 0 deferral 
+			// KErrNotSupported will anyways happen
+			GetState();
+			AcknowledgeLastState(KErrNone);
+			RequestTransitionNotification();
+			break;
+		case ECovDoCancel:
+			// do nothing, let the keep alive deferrals be active and let the CDmKeepAliveFuncCovTest delete this object
+			CActiveScheduler::Stop();
+			break;
+		default:
+			User::Leave(KErrUnknown);
+			break;
+		}
+	}
+
+class CDmDomainManFuncCov : public CDmDomainManager
+	{
+public:
+	static CDmDomainManFuncCov* NewL(TDmHierarchyId aHierarchy);
+	~CDmDomainManFuncCov();
+
+	// from CDmDomainManager
+	void RunL();
+private:
+	CDmDomainManFuncCov(TDmHierarchyId aHierarchy);
+	};
+
+CDmDomainManFuncCov* CDmDomainManFuncCov::NewL(TDmHierarchyId aHierarchy)
+	{
+	CDmDomainManFuncCov* self=new (ELeave) CDmDomainManFuncCov(aHierarchy);
+	CleanupStack::PushL(self);
+
+	self->ConstructL();
+	CleanupStack::Pop();
+	return self;
+	}
+
+CDmDomainManFuncCov::~CDmDomainManFuncCov()
+	{
+	Cancel();
+	}
+
+CDmDomainManFuncCov::CDmDomainManFuncCov(TDmHierarchyId aHierarchy) :
+	CDmDomainManager(aHierarchy)
+	{
+	}
+
+void CDmDomainManFuncCov::RunL()
+	{
+	CActiveScheduler::Stop();
+	}
+
+class CDmKeepAliveFuncCovTest : public CActive, public MDmTest
+	{
+public:
+	CDmKeepAliveFuncCovTest() : CActive(CActive::EPriorityStandard) {};
+	void Perform();
+	void Release();
+
+	TInt TransitionNotification(MDmDomainMember&) { return KErrNone; };
+	void TransitionRequestComplete() {};
+
+		// from CActive
+	void RunL() {};
+	virtual void DoCancel()
+		{
+		test(0);
+		}
+
+public:
+	CDmDomainManFuncCov*		iTestDomainManager;
+	};
+
+void CDmKeepAliveFuncCovTest::Perform()
+	{
+ 	__UHEAP_MARK;
+
+	CActiveScheduler::Add(this);
+
+	test.Printf(_L("****************CFunctionalCoverageTest****************\n"));
+	test.Next(_L("Test to perform code coverage"));
+
+	TInt r = CDmDomainManager::AddDomainHierarchy(KDmHierarchyIdTestV2);
+	test(r == KErrNone);
+
+	TRAP_IGNORE(iTestDomainManager = CDmDomainManFuncCov::NewL(KDmHierarchyIdTestV2));
+	test (iTestDomainManager != NULL);
+
+	CDmKeepAliveFuncCov* member = NULL;
+	// Add some test hierarchy members
+	TRAP(r, member = CDmKeepAliveFuncCov::NewL(KDmHierarchyIdTestV2, KDmIdRoot));
+	test(member != NULL);
+
+	SDmStateSpecV1 aStateSpec = Get0DeferralState();
+
+	TDmDomainState		testState =  aStateSpec.iState;
+
+	// request a system transition
+	iTestDomainManager->RequestSystemTransition(testState, ETraverseChildrenFirst);
+	test.Printf(_L("Requested system transition\n"));
+
+	member->iDmMemCov = CDmKeepAliveFuncCov::ECovHandleError;
+
+	test.Printf(_L("HandleDeferralError functional coverage...\n"));
+	// wait for test transition to complete
+	CActiveScheduler::Start();
+
+	test.Printf(_L("......system transition completed\n"));
+
+	aStateSpec = GetMaxDeferralState();
+	testState =  aStateSpec.iState;
+
+	// request a system transition
+	iTestDomainManager->RequestSystemTransition(testState, ETraverseChildrenFirst);
+	test.Printf(_L("Requested system transition\n"));
+
+	member->iDmMemCov = CDmKeepAliveFuncCov::ECovDoCancel;
+	test.Printf(_L("DoCancel functional coverage...\n"));
+	// wait for the member to call CActiveScheduler::Stop
+	CActiveScheduler::Start();
+	delete member;
+
+	// wait for test transition to complete
+	CActiveScheduler::Start();
+	test.Printf(_L("......system transition completed\n"));
+
+	// Add some test hierarchy members
+	TRAP(r, member = CDmKeepAliveFuncCov::NewL(KDmHierarchyIdTestV2, KDmIdRoot));
+	test(member != NULL);
+
+	aStateSpec = GetMaxDeferralState();
+	testState =  aStateSpec.iState;
+
+	// request a system transition
+	iTestDomainManager->RequestSystemTransition(testState, ETraverseChildrenFirst);
+	test.Printf(_L("Requested system transition\n"));
+
+	member->iDmMemCov = CDmKeepAliveFuncCov::ECovDoCancel; // just so that the member will call CActiveScheduler::Stop
+
+	test.Printf(_L("DoCancel functional coverage...\n"));
+	// wait for the member to call CActiveScheduler::Stop
+	CActiveScheduler::Start();
+
+	delete iTestDomainManager;
+	delete member;
+
+	__UHEAP_MARKEND;
+	}
+
+void CDmKeepAliveFuncCovTest::Release()
+	{
+	delete this;
+	}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// --- Main() ---
+
+GLDEF_C TInt E32Main()
+	{
+	CTrapCleanup* trapHandler = CTrapCleanup::New();
+	test(trapHandler != NULL);
+
+	CActiveScheduler* scheduler = new CActiveScheduler();
+	test(scheduler != NULL);
+	CActiveScheduler::Install(scheduler);
+
+	// Turn off evil lazy dll unloading
+	RLoader l;
+	test(l.Connect() == KErrNone);
+	test(l.CancelLazyDllUnload()== KErrNone);
+	l.Close();
+
+	// Default number of iteration
+    TInt iter = 1;
+
+	TInt len = User::CommandLineLength();
+	if (len)
+		{
+		// Copy the command line in a buffer
+		HBufC* hb = HBufC::NewMax(len);
+		test(hb != NULL);
+		TPtr cmd((TUint16*) hb->Ptr(), len);
+		User::CommandLine(cmd);
+		// Extract the number of iterations
+		TLex l(cmd);
+		TInt i;
+		TInt r = l.Val(i);
+		if (r == KErrNone)
+			iter = i;
+		else
+			// strange command - silently ignore
+			{}
+		delete hb;
+		}
+
+	test.Title();
+
+	test.Start(_L("Test starting..."));
+
+	test.Printf(_L("Go for %d iterations\n"), iter);
+
+	// Remember the number of open handles. Just for a sanity check
+	TInt start_thc, start_phc;
+	RThread().HandleCount(start_phc, start_thc);
+
+	for (TInt i = 1; i <= iter; i++)
+		{
+		test.Printf(_L("\nThis iteration: %d\n"), i);
+
+		MDmTest* tests[] =
+			{
+			// DM Client PlatSec tests
+			new CDmTestPlatSec(TPtrC(KSecuritySlavePath1)),
+			new CDmTestPlatSec(TPtrC(KSecuritySlavePath2)),
+			new CDmTestPlatSec(TPtrC(KSecuritySlavePath3)),
+
+			// Domain Member R-Class API tests
+			new CDmDeferralTestKErrNone(KDmHierarchyIdTestV2, EShutdownCritical, 1, ETrue), // TC 1.1.1.1.1
+			new CDmDeferralTestKErrNone(KDmHierarchyIdTestV2, EShutdownCritical, 2, ETrue), // TC 1.1.1.1.2
+			new CDmDeferralTestKErrNone(KDmHierarchyIdTestV2, EShutdownCritical, 1, EFalse), // TC 1.1.1.1.3
+			new CDmDeferralTestCompletion(KDmHierarchyIdTestV2, EBackupMode), // TC 1.1.1.2.1
+			new CDmDeferralTestKErrNotSupported(KDmHierarchyIdTestV2, EShutdownCritical, 6), // TC 1.1.1.3.1
+			new CDmDeferralTestKErrNotSupported(KDmHierarchyIdTestV2, ENormalRunning, 1), // TC 1.1.1.3.2
+			new CDmDeferralTestKErrNotSupported(KDmHierarchyIdTest, EBackupMode, 1), // TC 1.1.1.3.3
+			new CDmDeferralTestKErrCancel(KDmHierarchyIdTestV2, EBackupMode, ETrue), // TC 1.1.1.4.1
+			new CDmDeferralTestKErrCancel(KDmHierarchyIdTestV2, EBackupMode, EFalse), // TC 1.1.1.4.2
+			new CDmDeferralTestKErrNotReady(KDmHierarchyIdTestV2, EBackupMode), // TC 1.1.1.5.1
+			new CDmDeferralTestKErrServerBusy(KDmHierarchyIdTestV2, ERestoreMode), // TC 1.1.1.7.1
+
+			new CDmDeferralTestKErrNone(KDmHierarchyIdTestV2, ERestoreMode, 0, ETrue), // TC 1.2.0
+			new CDmDeferralTestKErrNone(KDmHierarchyIdTestV2, ERestoreMode, 1, ETrue), // TC 1.2.1
+			new CDmDeferralTestKErrNone(KDmHierarchyIdTestV2, ERestoreMode, 2, ETrue), // TC 1.2.2
+			new CDmDeferralTestKErrNone(KDmHierarchyIdTestV2, ERestoreMode, 3, ETrue), // TC 1.2.3
+
+			new	CDmDeferralMixed(KDmHierarchyIdTestV2, EShutdownCritical, 3, ETrue,EFalse), // TC 1.3.1
+			new	CDmDeferralMixed(KDmHierarchyIdTestV2, EShutdownCritical, 3, ETrue,ETrue),  // TC 1.3.2
+
+			// Domain Member C-Class API tests
+			new CDmDomainKeepAliveTest(),
+
+			// Policy State Spec Failure Policy tests - transition timeouts
+			//   ETransitionFailureUsePolicyFromOrdinal3
+			new CDmFailurePolicyTest(EStartupCriticalStatic, HierarchyPolicy.iFailurePolicy),
+			new CDmFailurePolicyTest(EStartupCriticalDynamic, ETransitionFailureStop),
+			new CDmFailurePolicyTest(ENormalRunning, ETransitionFailureContinue),
+
+			// Policy Interface tests
+			new CDmPolicyInterfaceTest(),
+
+			// Functional coverage test
+			new CDmKeepAliveFuncCovTest(),
+			};
+
+		for (TUint j = 0; j < sizeof(tests)/sizeof(*tests); j++)
+			{
+			test(tests[j] != NULL);
+			tests[j]->Perform();
+			tests[j]->Release();
+			}
+		}
+
+	test.End();
+
+	// Sanity check for open handles and for pending requests
+	TInt end_thc, end_phc;
+	RThread().HandleCount(end_phc, end_thc);
+	test(start_thc == end_thc);
+	test(start_phc == end_phc);
+	test(RThread().RequestCount() >= 0);
+
+	delete scheduler;
+	delete trapHandler;
+
+	return KErrNone;
+	}