sl@0: // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: // All rights reserved.
sl@0: // This component and the accompanying materials are made available
sl@0: // under the terms of "Eclipse Public License v1.0"
sl@0: // which accompanies this distribution, and is available
sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: //
sl@0: // Initial Contributors:
sl@0: // Nokia Corporation - initial contribution.
sl@0: //
sl@0: // Contributors:
sl@0: //
sl@0: // Description:
sl@0: // CEComServer and CEComSession OOM tests
sl@0: // 
sl@0: //
sl@0: 
sl@0: #include <e32test.h>
sl@0: #include <e32math.h>
sl@0: #include <bautils.h>
sl@0: #include "EComServerStart.h"
sl@0: #include "EComServer.h"
sl@0: #include "EComServerSession.h"
sl@0: #include "EcomTestUtils.h"
sl@0: #include "EcomTestIniFileUtils.h"
sl@0: #include "ServerStartupManager.h"
sl@0: #include "Discoverer.h"
sl@0: #include "DiscovererObserver.h"
sl@0: 
sl@0: static RTest TheTest(_L("ECOM Server - OOM test"));
sl@0: const TUid KCExampleInterfaceUid = {0x10009DC0};
sl@0: static RFs TheFs;
sl@0: 
sl@0: static void KillEComServerL()
sl@0: 	{
sl@0: 	//Need to ensure that the EComServer process is killed before even starting this test by using
sl@0:    	//the EComTestUtils library
sl@0:    	_LIT(KEComServerProcessName,"ecomserver");
sl@0:    	TRAPD(error, EComTestUtils::KillProcessL(KEComServerProcessName));
sl@0:    	error=error;
sl@0: 	}
sl@0: 
sl@0: //
sl@0: //
sl@0: //Test macroes and functions
sl@0: //
sl@0: //
sl@0: 
sl@0: static void Check(TInt aValue, TInt aLine)
sl@0: 	{
sl@0: 	if(!aValue)
sl@0: 		{
sl@0: 		TheTest(EFalse, aLine);
sl@0: 		}
sl@0: 	}
sl@0: static  void Check(TInt aValue, TInt aExpected, TInt aLine)
sl@0: 	{
sl@0: 	if(aValue != aExpected)
sl@0: 		{
sl@0: 		RDebug::Print(_L("*** Expected error: %d, got: %d\r\n"), aExpected, aValue);
sl@0: 		TheTest(EFalse, aLine);
sl@0: 		}
sl@0: 	}
sl@0: #define TEST(arg) ::Check((arg), __LINE__)
sl@0: #define TEST2(aValue, aExpected) ::Check(aValue, aExpected, __LINE__)
sl@0: 
sl@0: //
sl@0: //
sl@0: 
sl@0: void NewLC_OOMTestL()
sl@0: 	{
sl@0: 	TInt processHandlesS = 0;
sl@0: 	TInt threadHandlesS = 0;
sl@0: 	TInt processHandlesE = 0;
sl@0: 	TInt threadHandlesE = 0;
sl@0: 	RThread().HandleCount(processHandlesS, threadHandlesS);
sl@0: 	for(TInt count=1;;count +=100)
sl@0: 		{
sl@0: 		// Setting Heap failure for OOM test
sl@0: 		__UHEAP_SETFAIL(RHeap::EDeterministic, count);
sl@0: 		__UHEAP_MARK;
sl@0: 
sl@0: 		CEComServer* ecomServer = NULL;
sl@0: 		TRAPD(err, ecomServer = CEComServer::NewLC();
sl@0: 				   CleanupStack::PopAndDestroy(ecomServer));
sl@0: 		if(err == KErrNoMemory)
sl@0: 			{
sl@0: 			__UHEAP_MARKEND;
sl@0: 			}
sl@0: 		else if(err == KErrNone)
sl@0: 			{
sl@0: 			__UHEAP_MARKEND;
sl@0: 			RDebug::Print(_L("The test succeeded at heap failure rate=%d.\n"), count);
sl@0: 			break;
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			__UHEAP_MARKEND;
sl@0: 			TEST2(err, KErrNone);
sl@0: 			}
sl@0: 		__UHEAP_RESET;
sl@0: 		}
sl@0: 	__UHEAP_RESET;
sl@0: 	RThread().HandleCount(processHandlesE, threadHandlesE);
sl@0: 	TEST(processHandlesS == processHandlesE);
sl@0: 	TEST(threadHandlesS == threadHandlesE);
sl@0: 	}
sl@0: 
sl@0: void ListImplementations_OOMTestL()
sl@0: 	{
sl@0: 	TInt processHandlesS = 0;
sl@0: 	TInt threadHandlesS = 0;
sl@0: 	TInt processHandlesE = 0;
sl@0: 	TInt threadHandlesE = 0;
sl@0: 	RThread().HandleCount(processHandlesS, threadHandlesS);
sl@0: 
sl@0: 
sl@0: 	for(TInt count=1;;++count)
sl@0: 		{
sl@0: 		CEComServer* ecomServer = CEComServer::NewLC();
sl@0: 		// Setting Heap failure for OOM test
sl@0: 		__UHEAP_SETFAIL(RHeap::EDeterministic, count);
sl@0: 		__UHEAP_MARK;
sl@0: 
sl@0: 		TClientRequest clientReq;
sl@0: 		RArray<TUid> extendedInterfaces;
sl@0: 		CleanupClosePushL(extendedInterfaces);
sl@0: 		RImplInfoArray* ifArray=NULL;
sl@0: 		TRAPD(err, ifArray = ecomServer->ListImplementationsL(KCExampleInterfaceUid,extendedInterfaces,clientReq));
sl@0: 		CleanupStack::PopAndDestroy(&extendedInterfaces);
sl@0: 		if (ifArray!=NULL)
sl@0: 			{
sl@0: 			ifArray->Close();
sl@0: 			delete ifArray;
sl@0: 			}
sl@0: 		if(err == KErrNoMemory)
sl@0: 			{
sl@0: 			CleanupStack::PopAndDestroy(ecomServer);
sl@0: 			__UHEAP_MARKEND;
sl@0: 			}
sl@0: 		else if(err == KErrNone)
sl@0: 			{
sl@0: 			CleanupStack::PopAndDestroy(ecomServer);
sl@0: 			__UHEAP_MARKEND;
sl@0: 			//implInfoArray should not be deleted! The caller does not take the ownership.
sl@0: 			RDebug::Print(_L("The test succeeded at heap failure rate=%d.\n"), count);
sl@0: 			break;
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			CleanupStack::PopAndDestroy(ecomServer);
sl@0: 			__UHEAP_MARKEND;
sl@0: 			TEST2(err, KErrNone);
sl@0: 			}
sl@0: 		__UHEAP_RESET;
sl@0: 		}
sl@0: 	__UHEAP_RESET;
sl@0: 	//CleanupStack::PopAndDestroy(ecomServer);
sl@0: 	RThread().HandleCount(processHandlesE, threadHandlesE);
sl@0: 	TEST(processHandlesS == processHandlesE);
sl@0: 	TEST(threadHandlesS == threadHandlesE);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID			SYSLIB-ECOM-CT-3714
sl@0: @SYMTestCaseDesc 		Tests CEComServer::ListImplementationsL	with customer resolver.
sl@0: @SYMTestPriority 		High
sl@0: @SYMTestActions  		Calls ListImplementationsL(TUid,TUid,const RExtendedInterfacesArray&,const TClientRequest&)
sl@0: 						with customer resolver.
sl@0: @SYMTestExpectedResults No OOM errors.
sl@0: @SYMDEF 				DEF111196
sl@0: */
sl@0: void ListImplementations_OOMTest1L()
sl@0: 	{
sl@0: 	TInt processHandlesS = 0;
sl@0: 	TInt threadHandlesS = 0;
sl@0: 	TInt processHandlesE = 0;
sl@0: 	TInt threadHandlesE = 0;
sl@0: 	RThread().HandleCount(processHandlesS, threadHandlesS);
sl@0: 
sl@0: 
sl@0: 	for(TInt count=1;;++count)
sl@0: 		{
sl@0: 		CEComServer* ecomServer = CEComServer::NewLC();
sl@0: 		// Setting Heap failure for OOM test
sl@0: 		__UHEAP_SETFAIL(RHeap::EDeterministic, count);
sl@0: 		__UHEAP_MARK;
sl@0: 
sl@0: 		TUid resolverUid = {0x10009DD0};
sl@0: 
sl@0: 		TClientRequest clientReq;
sl@0: 		RArray<TUid> extendedInterfaces;
sl@0: 		CleanupClosePushL(extendedInterfaces);
sl@0: 		RImplInfoArray* ifArray=NULL;
sl@0: 
sl@0: 		TRAPD(err, ifArray = ecomServer->ListImplementationsL(KCExampleInterfaceUid,resolverUid,extendedInterfaces,clientReq));
sl@0: 		CleanupStack::PopAndDestroy(&extendedInterfaces);
sl@0: 		if (ifArray!=NULL)
sl@0: 			{
sl@0: 			ifArray->Close();
sl@0: 			delete ifArray;
sl@0: 			}
sl@0: 		if(err == KErrNoMemory)
sl@0: 			{
sl@0: 			CleanupStack::PopAndDestroy(ecomServer);
sl@0: 			__UHEAP_MARKEND;
sl@0: 			}
sl@0: 		else if(err == KErrNone)
sl@0: 			{
sl@0: 			CleanupStack::PopAndDestroy(ecomServer);
sl@0: 			__UHEAP_MARKEND;
sl@0: 			//implInfoArray should not be deleted! The caller does not take the ownership.
sl@0: 			RDebug::Print(_L("The test succeeded at heap failure rate=%d.\n"), count);
sl@0: 			break;
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			CleanupStack::PopAndDestroy(ecomServer);
sl@0: 			__UHEAP_MARKEND;
sl@0: 			TEST2(err, KErrNone);
sl@0: 			}
sl@0: 		__UHEAP_RESET;
sl@0: 		}
sl@0: 	__UHEAP_RESET;
sl@0: 	//CleanupStack::PopAndDestroy(ecomServer);
sl@0: 	RThread().HandleCount(processHandlesE, threadHandlesE);
sl@0: 	TEST(processHandlesS == processHandlesE);
sl@0: 	TEST(threadHandlesS == threadHandlesE);
sl@0: 	}
sl@0: 
sl@0: void GetResolvedDllInfo_OOMTestL()
sl@0: 	{
sl@0: 	TInt processHandlesS = 0;
sl@0: 	TInt threadHandlesS = 0;
sl@0: 	TInt processHandlesE = 0;
sl@0: 	TInt threadHandlesE = 0;
sl@0: 	RThread().HandleCount(processHandlesS, threadHandlesS);
sl@0: 
sl@0: 	CEComServer* ecomServer = CEComServer::NewLC();
sl@0: 	TClientRequest clientReq;
sl@0: 	RArray<TUid> extendedInterfaces;
sl@0: 	CleanupClosePushL(extendedInterfaces);
sl@0: 	RImplInfoArray* implInfoArray = ecomServer->ListImplementationsL(KCExampleInterfaceUid,extendedInterfaces,clientReq);
sl@0: 	CleanupStack::PopAndDestroy(&extendedInterfaces);
sl@0: 
sl@0: 	TEST(implInfoArray->Count() > 0);
sl@0: 
sl@0: 	for(TInt count=1;;++count)
sl@0: 		{
sl@0: 		// Setting Heap failure for OOM test
sl@0: 		__UHEAP_SETFAIL(RHeap::EDeterministic, count);
sl@0: 		__UHEAP_MARK;
sl@0: 
sl@0: 		TEntry dllInfo;
sl@0: 		TUid dtorIdKey;
sl@0: 		TClientRequest clntRq;
sl@0: 		CImplementationInformation* info = (*implInfoArray)[0];
sl@0: 		TRAPD(err, ecomServer->GetResolvedDllInfoL(info->ImplementationUid(),
sl@0: 												   dllInfo, dtorIdKey, clntRq));
sl@0: 		if(err == KErrNoMemory)
sl@0: 			{
sl@0: 			__UHEAP_MARKEND;
sl@0: 			}
sl@0: 		else if(err == KErrNone)
sl@0: 			{
sl@0: 			__UHEAP_MARKEND;
sl@0: 			RDebug::Print(_L("The test succeeded at heap failure rate=%d.\n"), count);
sl@0: 			break;
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			__UHEAP_MARKEND;
sl@0: 			TEST2(err, KErrNone);
sl@0: 			}
sl@0: 		__UHEAP_RESET;
sl@0: 		}
sl@0: 	__UHEAP_RESET;
sl@0: 	//implInfoArray should be deleted! The caller takes the ownership.
sl@0: 	if (implInfoArray!=NULL)
sl@0: 		{
sl@0: 		implInfoArray->Close();
sl@0: 		delete implInfoArray;
sl@0: 		}
sl@0: 	CleanupStack::PopAndDestroy(ecomServer);
sl@0: 	RThread().HandleCount(processHandlesE, threadHandlesE);
sl@0: 	TEST(processHandlesS == processHandlesE);
sl@0: 	TEST(threadHandlesS == threadHandlesE);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID		SYSLIB-ECOM-CT-0177
sl@0: @SYMTestCaseDesc 	Check that IsSSA works when ecomsrvr has different values.
sl@0: @SYMTestPriority 	High
sl@0: @SYMTestActions  	Check that IsSSA returns ETrue when ecomsrvr ini does not exist.
sl@0:                     Check that IsSSA returns the value in the ecomsrvr ini file when
sl@0:                     the file exists.
sl@0: @SYMTestExpectedResults The test must not fail.
sl@0: @SYMPREQ PREQ967
sl@0: */
sl@0: void IsSsa_TestL()
sl@0: 	{
sl@0: 	TInt processHandlesS = 0;
sl@0: 	TInt threadHandlesS = 0;
sl@0: 	TInt processHandlesE = 0;
sl@0: 	TInt threadHandlesE = 0;
sl@0: 	RThread().HandleCount(processHandlesS, threadHandlesS);
sl@0: 
sl@0: 	TBool res;
sl@0: 
sl@0: 	TestEnableDisableSsaL(TheTest, TheFs);
sl@0: 
sl@0:     /*****************************************************************/
sl@0: 	//test that IsSSA() returns ETrue when ecomsrvr.ini file does
sl@0: 	//not exist.
sl@0: 
sl@0: 	//enable ssa
sl@0: 	EnableSsa(TheTest, TheFs);
sl@0: 
sl@0: 	//test that IsSSA() returns ETrue
sl@0: 	CEComServer* server=CEComServer::NewLC();
sl@0: 	res = server->IsSSA(TheFs);
sl@0: 	CleanupStack::PopAndDestroy();
sl@0: 	ResetSsa(TheTest, TheFs);
sl@0: 	TEST(res);
sl@0: 
sl@0:     /*****************************************************************/
sl@0: 	//test that IsSSA() returns EFalse when ecomsrvr.ini file exists.
sl@0: 
sl@0: 	//disable ssa
sl@0: 	DisableSsa(TheTest, TheFs);
sl@0: 
sl@0: 	//test that IsSSA() returns EFalse
sl@0: 	server=CEComServer::NewLC();
sl@0: 	res = server->IsSSA(TheFs);
sl@0: 	CleanupStack::PopAndDestroy();
sl@0: 	ResetSsa(TheTest, TheFs);
sl@0: 	TEST(!res);
sl@0: 
sl@0: 	RThread().HandleCount(processHandlesE, threadHandlesE);
sl@0: 	TEST(processHandlesS == processHandlesE);
sl@0: 	TEST(threadHandlesS == threadHandlesE);
sl@0: 	}
sl@0: 
sl@0: 
sl@0: /**
sl@0: Thread entry point for test thread.
sl@0: Kills the existing ECOM server and launches a new instance
sl@0: 
sl@0: */
sl@0: TInt ServerStartThreadEntryL(TAny* /*a*/)
sl@0: 	{
sl@0: 	__UHEAP_MARK;
sl@0: 
sl@0: 	//Threshold set so that a OOM failure occur whilst constructing CEComServer::iRegistryData
sl@0: 	const TInt KFailThreshold = 500;
sl@0: 
sl@0: 	TInt dummy;
sl@0: 	TAny* ptr  = NULL;
sl@0: 
sl@0: 	::KillEComServerL();
sl@0: 
sl@0: 	//Invoking OOM failure by allocating most of the heap before running the server
sl@0: 	RHeap heap = User::Heap();
sl@0: 	TInt avail = heap.Available(dummy);
sl@0:     ptr = User::Alloc(avail-KFailThreshold);
sl@0: 
sl@0: 	TEST(ptr != NULL); //Check that the allocation was sucessful
sl@0: 
sl@0: 	TInt result = ServerStart();
sl@0: 	delete ptr;
sl@0: 
sl@0: 	__UHEAP_MARKEND;
sl@0: 
sl@0: 	return result;
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID		SYSLIB-ECOM-CT-3163
sl@0: @SYMTestCaseDesc 	Verify the startup behaviour of the ECOM server under OOM conditions
sl@0: @SYMTestPriority 	High
sl@0: @SYMTestActions  	Generate an OOM condition.
sl@0: 					Create a new thread which will launch the ECOM server.
sl@0: 					Wait for the thread to exit and check the thread exit type
sl@0: 					and reason to verify behaviour.
sl@0: @SYMTestExpectedResults The test must not fail.
sl@0: @SYMDEF DEF094675
sl@0: */
sl@0: void StartServer_OOMTest()
sl@0: 	{
sl@0: 
sl@0: 	_LIT(KStartThreadName,"Server Start Thread");
sl@0: 
sl@0: 	//Create a new thread to launch the ECOM server
sl@0: 	RThread testThread;
sl@0: 	testThread.Create(KStartThreadName, ServerStartThreadEntryL,
sl@0: 				KDefaultStackSize,KMinHeapSize,KMinHeapSize,NULL);
sl@0: 	TRequestStatus status;
sl@0: 	testThread.Logon(status);
sl@0: 	testThread.Resume();
sl@0: 
sl@0: 	//Wait for the thread to exit
sl@0: 	User::WaitForRequest(status);
sl@0: 
sl@0: 	//Obtain exit type and reason for test thread
sl@0: 	TExitType exitType = testThread.ExitType();
sl@0: 	TInt exitReason = testThread.ExitReason();
sl@0: 
sl@0: 	//close the thread handle
sl@0: 	testThread.Close();
sl@0: 
sl@0: 	//Verify the exit reason and exit code
sl@0: 	//Exit type is TExitType::EExitKill when E32Main() exit normally
sl@0: 	TEST(exitType == EExitKill);
sl@0: 	TEST(exitReason == KErrNoMemory);
sl@0: 
sl@0: 	}
sl@0: 
sl@0: void DoTestL()
sl@0: 	{
sl@0: 	TheTest.Start(_L("CEComServer::NewLC - OOM test"));
sl@0: 	::NewLC_OOMTestL();
sl@0: 
sl@0: 	TheTest.Next(_L("CEComServer::ListImplementationsL - OOM test"));
sl@0: 	::ListImplementations_OOMTestL();
sl@0: 
sl@0: 	TheTest.Next(_L("CEComServer::GetResolvedDllInfoL - OOM test"));
sl@0: 	::GetResolvedDllInfo_OOMTestL();
sl@0: 
sl@0: 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-0177 CEComServer::IsSsa test "));
sl@0: 	::IsSsa_TestL();
sl@0: 
sl@0: 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-3163 Server Startup Panic test "));
sl@0:     ::StartServer_OOMTest();
sl@0: 
sl@0:     TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-3714 CEComServer::ListImplementationsL with customer resolver - OOM test "));
sl@0: 	::ListImplementations_OOMTest1L();
sl@0: 
sl@0: 	}
sl@0: 
sl@0: TInt E32Main()
sl@0: 	{
sl@0: 	__UHEAP_MARK;
sl@0: 
sl@0:     ::KillEComServerL();
sl@0: 
sl@0: 	CTrapCleanup* tc = CTrapCleanup::New();
sl@0: 	TEST(tc != NULL);
sl@0: 
sl@0: 	TEST2(TheFs.Connect(), KErrNone);
sl@0: 
sl@0: 	CActiveScheduler* activeSched = new CActiveScheduler;
sl@0: 	TEST(activeSched != NULL);
sl@0: 	CActiveScheduler::Install(activeSched);
sl@0: 
sl@0: 	TheTest.Title();
sl@0: 	TRAPD(err, ::DoTestL());
sl@0: 	TEST2(err, KErrNone);
sl@0: 
sl@0: 	ResetSsa(TheTest, TheFs);
sl@0: 
sl@0: 	TheTest.End();
sl@0: 	TheTest.Close();
sl@0: 
sl@0: 	delete activeSched;
sl@0: 
sl@0: 	TheFs.Close();
sl@0: 
sl@0: 	delete tc;
sl@0: 
sl@0: 	__UHEAP_MARKEND;
sl@0: 
sl@0: 	User::Heap().Check();
sl@0: 	return KErrNone;
sl@0: 	}