lowlevellibsandfws/pluginfw/Framework/SimpleTests/t_finalclose.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 18 Aug 2010 11:27:44 +0300
changeset 52 bf6a71c50e42
parent 0 e4d67989cc36
permissions -rw-r--r--
Revision: 201033 Kit: 201033

// 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:
//

#include <e32test.h>
#include <e32panic.h>
#include <f32file.h>
#include <bautils.h>
#include "../EcomTestUtils/EcomTestUtils.h"
#include "LoadManager.h"
#include <ecom/ecom.h>
#include "EComUidCodes.h"
#include "Interface.h" // interface to Plugins

_LIT(KEComExDllOnC, "c:\\sys\\bin\\EComExample5.dll");
_LIT(KEComRscFileOnZ, "z:\\RAMOnly\\EComExample5.rsc");
_LIT(KEComRscFileOnC, "c:\\resource\\plugins\\EComExample5.rsc");

_LIT(KEComExampleDllOnC,		"C:\\sys\\bin\\EComExample.dll");
_LIT(KEComExample2DllOnC,		"C:\\sys\\bin\\EComExample2.dll");
_LIT(KEComExample3DllOnC,		"C:\\sys\\bin\\EComExample3.dll");

_LIT(KEComExampleRscOnC,		"C:\\resource\\plugins\\EComExample.rsc");
_LIT(KEComExample2RscOnC,		"C:\\resource\\plugins\\EComExample2.rsc");
_LIT(KEComExample3RscOnC,		"C:\\resource\\plugins\\EComExample3.rsc");

_LIT(KEComExampleRscOnZ,		"Z:\\RAMOnly\\EComExample.rsc");
_LIT(KEComExample2RscOnZ,		"Z:\\RAMOnly\\EComExample2.rsc");
_LIT(KEComExample3RscOnZ,		"Z:\\RAMOnly\\EComExample3.rsc");


_LIT(KEComExDllOnZ, "z:\\RAMOnly\\EComExample5.dll");
_LIT(KEComExampleDllOnZ,			"Z:\\RAMOnly\\EComExample.dll");
_LIT(KEComExample2DllOnZ,		"Z:\\RAMOnly\\EComExample2.dll");
_LIT(KEComExample3DllOnZ,		"Z:\\RAMOnly\\EComExample3.dll");

/** Test cases covered in this test code:
1.	Thread create imp destroy then not calling FinalClose() will cause a panic inside the thread( capture this panic)(memory leak)

2.	Thread list implementation then not calling FinalClose() will cause a panic inside the thread(capture this panic)(memory leak).

3.	Thread Create Impl1, Create Impl2, Destroy Impl2, Destory Impl1 then FinalClose() no memory leak.

4.	Thread create Impl1, call FinalClose() 2x, Destroy Impl1 then FinalClose() to show that FinalClose() can be called many times with no unknown consequence.

5.	REComSession::public constructor (without OpenL), called FinalClose () 2x, then Close(), no problem and memory leak.

6.	REComSession::OpenL,call Close() then call FinalClose() to show no memory leak problem.

7.  Test calling REComSession::FinalClose() to show no memory leak, errors, crash problem
*/

LOCAL_D RTest test(_L("Final Close Test"));

class RFinalCloseTest
	{
public:
	//Test case 1
	static TInt Create_Destroy_Without_FinalClose(TAny*);
	static TInt Create_Destroy_With_FinalCloseL();
	static TInt Create_Destroy_TestL();

	//Test case 2
	static TInt ListImpl_Without_FinalClose(TAny*);
	static TInt ListImpl_With_FinalCloseL();
	static void ListImplementation_TestL();

	//Test case 3
	static void Create_Destroy2_With_FinalCloseL();

	//Test case 4
	static void Create_Destroy3_With_FinalCloseL();

	//Test case 5
	static void Create_Destroy4_With_FinalCloseL();

	//Test case 6
	static void FinalClose();

	//Test case 7
	static void NonConstructL_Create_Destroy();

	static void ThreadPanicTest(const TDesC& aName,TThreadFunction aFunction);
	};

/**
Test creating an implementation, deleting the implementation
and then call FinalClose(). Check that there is no crash and memory leak

@SYMTestCaseID          SYSLIB-ECOM-CT-0759
@SYMTestCaseDesc	    Tests for creating and destroying an implementation
@SYMTestPriority 	    High
@SYMTestActions  	    Create and delete a new implementation with UID and initialisation parameters.
                        Call up REComSession::FinalClose
						Check for no crash and memory leaks.
@SYMTestExpectedResults The test must not fail.
@SYMREQ                 REQ0000
*/
TInt RFinalCloseTest::Create_Destroy_With_FinalCloseL()
	{
	__UHEAP_MARK;

	Create_Destroy_TestL();

	REComSession::FinalClose();

	__UHEAP_MARKEND;
	return KErrNone;
	}

/**
Test creating an implementation, deleting the implementation
Never call FinalClose() to show memory leak panic

@SYMTestCaseID          SYSLIB-ECOM-CT-0760
@SYMTestCaseDesc	    Tests for creating and destroying an implementation
@SYMTestPriority 	    High
@SYMTestActions  	    Create and delete a new implementation with UID and initialisation parameters.
                    	FinalClose is omitted to show memory leak panic
@SYMTestExpectedResults The test must not fail.
@SYMREQ                 REQ0000
*/
TInt RFinalCloseTest::Create_Destroy_Without_FinalClose(TAny*)
	{
	
	__UHEAP_MARK;
	CTrapCleanup* threadcleanup = CTrapCleanup::New();

	TRAPD(err,Create_Destroy_TestL());

	test(err==KErrNone);
	//This FinalClose() is purposely omitted for testing the PANIC
	//REComSession::FinalClose();

	delete threadcleanup;
	__UHEAP_MARKEND;
	return KErrNone;
	}

//The test code for creating and destroying an implementation
//To be used in the two test cases above
TInt RFinalCloseTest::Create_Destroy_TestL()
	{
	TUid dTorKey;
	TUid implUid={0x101F8478};

	// Set up some empty initialisation parameters
	CExampleInterface::TExampleInterfaceInitParams initParams;
	initParams.integer		= 0;
	initParams.descriptor	= NULL;

	CExampleInterface* dllPtr = REINTERPRET_CAST(CExampleInterface*,
							REComSession::CreateImplementationL(implUid,dTorKey,&initParams));

	//Check the return implementation instantiation has the same implementation uid
	test(dllPtr->ImplId()==implUid);
	//The returned Uid to be used in Destruction should match the implementation uid as well
	CInstanceInfoSimple* instanceInfo = reinterpret_cast <CInstanceInfoSimple*> (dTorKey.iUid);
	test(instanceInfo->ImplementationUid()==implUid);

	REComSession::DestroyedImplementation(dTorKey);

	delete dllPtr;
	dllPtr=0;

	return KErrNone;
	}

//The test code for listing implementation of an interface Uid.
//The test also verify all the implementations in the list by
//checking all the implementation Uid and their version.
void RFinalCloseTest::ListImplementation_TestL()
	{
	/**
	Some Plugin in Z that can be used for testing purposes
	Interface UID	DLL	UID		Implementation UID	Version		DllFile
	-------------------------------------------------------------------
	0x10009DC0		0x10009DB1	0x10009DC3			1		Z:\\..\\EComExample.dll		old_version
					0x10009DB1	0x10009DC4			1		Z:\\..\\EComExample.dll		old_version
					0x10009DB3	0x10009DC3			2		Z:\\..\\EComExample2.dll	=
					0x10009DB3	0x10009DC4			2		Z:\\..\\EComExample2.dll	=
					0x101F8477	0x101F8478			1		Z:\\..\\EComExample3.dll	=
					0x101F8479  0x101F847A			1		Z:\\..\\EComExample4.dll	=
					0x10009DB2	0x10009DC5			1		Z:\\..\\Suidical.dll		=

	*/
	TUid interfaceUid={0x10009DC0};
	RImplInfoPtrArray implArray;

	//Array of all the expected implementation Uid;
	RArray<TInt> expectedUidArray;
	expectedUidArray.Append(0x10009DC3);
	expectedUidArray.Append(0x10009DC4);
	expectedUidArray.Append(0x101F8478);
	expectedUidArray.Append(0x101F847A);
	expectedUidArray.Append(0x10009DC5);

	REComSession::ListImplementationsL(interfaceUid,implArray);

	//Expected number of implementations retured=5
	//This line has been removed as it is not safe to always assume there will be
	//a fixed number of implementations based on an the interface 0x10009DC0.
	//test(implArray.Count()==5);


	//Check that the implementation uid returned matched the specs above
	for (TInt i=0;i<implArray.Count();i++)
	{
		TUid implUid=implArray[i]->ImplementationUid();
		if (expectedUidArray.Find(implUid.iUid)!=KErrNotFound)
			{
			//check for the latest version for 10009DC3 & 10009DC4
			if (implUid.iUid==0x10009DC3 || implUid.iUid==0x10009DC4)
				test(implArray[i]->Version()==2);
			//all the other implementations have version 1
			else
				test(implArray[i]->Version()==1);
			}
	}
	expectedUidArray.Reset();
	expectedUidArray.Close();
	implArray.ResetAndDestroy();
	}

/**
The test code for testing the proper use of ListImplementationsL where
after calling that function we call REComSession::FinalClose()

@SYMTestCaseID          SYSLIB-ECOM-CT-0761
@SYMTestCaseDesc	    Tests for proper listing of implementation of an interface UID
@SYMTestPriority 	    High
@SYMTestActions  	    Call up REComSession::FinalClose after ListImplementation_TestL
@SYMTestExpectedResults The test must not fail.
@SYMREQ                 REQ0000
*/
TInt RFinalCloseTest::ListImpl_With_FinalCloseL()
	{
	__UHEAP_MARK;

	ListImplementation_TestL();

	REComSession::FinalClose();

	__UHEAP_MARKEND;

	return KErrNone;
	}

/**
The test code for testing the improper use of ListImplementationsL where
after the call, we never invoke REComSession::FinalClose().This will
result in some memory leak panic.

@SYMTestCaseID          SYSLIB-ECOM-CT-0762
@SYMTestCaseDesc	    Tests for proper listing of implementation of an interface UID
@SYMTestPriority 	    High
@SYMTestActions  	    Call to REComSession::FinalClose is omitted to show memory leak panic
@SYMTestExpectedResults The test must not fail.
@SYMREQ                 REQ0000
*/
TInt RFinalCloseTest::ListImpl_Without_FinalClose(TAny*)
	{
	
	__UHEAP_MARK;

	CTrapCleanup* threadcleanup = CTrapCleanup::New();
	TRAPD(err,ListImplementation_TestL());
	test(err==KErrNone);

	//This FinalClose() is purposely omitted for testing the PANIC
	//REComSession::FinalClose();

	delete threadcleanup;
	__UHEAP_MARKEND;
	return KErrNone;
	}
/**
The test code for testing the implementation creation and deletion
where we create two different implementation using two different plugins
destroy them and call FinalClose() to show there is no problem and memory leak

@SYMTestCaseID          SYSLIB-ECOM-CT-0763
@SYMTestCaseDesc	    Tests for proper creation and deletion of implementation using two different plugins
@SYMTestPriority 	    High
@SYMTestActions  	    Create the implementation with a call to REComSession::CreateImplementationL twice with different UIDs
                        Signal the destruction of an interface implementation to ECOM with a call to REComSession::DestroyedImplementation
						Call up REComSession::FinalClose
@SYMTestExpectedResults The test must not fail.
@SYMREQ                 REQ0000
*/
void RFinalCloseTest::Create_Destroy2_With_FinalCloseL()
	{
	__UHEAP_MARK;

	TUid implUid1={0x10009DC3};
	TUid implUid2={0x101F847A};
	TUid dTorKey1;
	TUid dTorKey2;
	// Set up some empty initialisation parameters
	CExampleInterface::TExampleInterfaceInitParams initParams;
	initParams.integer		= 0;
	initParams.descriptor	= NULL;

	//Creating implementation 1
	CExampleInterface* impl1 = REINTERPRET_CAST(CExampleInterface*,
							REComSession::CreateImplementationL(implUid1,dTorKey1,&initParams));
	test(impl1->ImplId()==implUid1);

	//Creating implementation 2
	CExampleInterface* impl2 = REINTERPRET_CAST(CExampleInterface*,
							REComSession::CreateImplementationL(implUid2,dTorKey2,&initParams));
	test(impl2->ImplId()==implUid2);

	//Destroy implementation 2
	REComSession::DestroyedImplementation(dTorKey2);

	delete impl2;
	impl2=0;

	//Now Destroy implementation 1
	REComSession::DestroyedImplementation(dTorKey1);

	delete impl1;
	impl1=0;

	REComSession::FinalClose();

	__UHEAP_MARKEND;

	}

/**
The test code for testing that REComSession::FinalClose() can be called many times
without introducing any strange behaviour, memory leak and crash problem.

@SYMTestCaseID          SYSLIB-ECOM-CT-0764
@SYMTestCaseDesc	    Tests to show that FinalClose() can be called many times with no unknown consequence.
@SYMTestPriority 	    High
@SYMTestActions  	    Create the implementation with some empty initialisation parameters
						Call up REComSession::FinalClose twice before destroying the implementation and once after the deletion
                        Check for any strange behaviour, memory leak and crash problem.
@SYMTestExpectedResults The test must not fail.
@SYMREQ                 REQ0000
*/
void RFinalCloseTest::Create_Destroy3_With_FinalCloseL()
	{
	__UHEAP_MARK;
	TUid implUid1={0x10009DC3};
	TUid dTorKey1;
	// Set up some empty initialisation parameters
	CExampleInterface::TExampleInterfaceInitParams initParams;
	initParams.integer		= 0;
	initParams.descriptor	= NULL;

	//Creating implementation 1
	CExampleInterface* impl1 = REINTERPRET_CAST(CExampleInterface*,
							REComSession::CreateImplementationL(implUid1,dTorKey1,&initParams));
	test(impl1->ImplId()==implUid1);

	//Called FinalClose() twice
	REComSession::FinalClose();
	REComSession::FinalClose();

	REComSession::DestroyedImplementation(dTorKey1);
	delete impl1;

	REComSession::FinalClose();

	__UHEAP_MARKEND;
	}

/**
The test code for testing the functionality of REComSession::FinalClose()
without introducing any strange behaviour,memory leak and crash problem

@SYMTestCaseID          SYSLIB-ECOM-CT-0765
@SYMTestCaseDesc	    Tests for the REComSession::FinalClose() function
@SYMTestPriority 	    High
@SYMTestActions  	    Open and close single connection to the the ECom server.
                        Call FinalClose, to check for any strange behaviour,memory leak and crash problem
@SYMTestExpectedResults The test must not fail.
@SYMREQ                 REQ0000
*/
void RFinalCloseTest::Create_Destroy4_With_FinalCloseL()
	{
	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-0765 "));
	__UHEAP_MARK;

	REComSession& ecomsession = ecomsession.OpenL();

	ecomsession.Close();

	REComSession::FinalClose();

	__UHEAP_MARKEND;
	}
/**
The test code for testing the functionality of REComSession::FinalClose()
without introducing any strange behaviour,memory leak and crash problem

@SYMTestCaseID          SYSLIB-ECOM-CT-0766
@SYMTestCaseDesc	    Tests for the REComSession::FinalClose() function
@SYMTestPriority 	    High
@SYMTestActions  	    Call FinalClose() function,to check for any memory leak and crash problem
@SYMTestExpectedResults The test must not fail.
@SYMREQ                 REQ0000
*/
void RFinalCloseTest::FinalClose()
	{
	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-0766 "));
	__UHEAP_MARK;

	REComSession::FinalClose();

	__UHEAP_MARKEND;
	}

LOCAL_C void NonConstructL_Create_Destroy_helper()
	{
	REComSession session;
	}

/**
@SYMTestCaseID          SYSLIB-ECOM-CT-0767
@SYMTestCaseDesc	    Tests for the REComSession::FinalClose() function
@SYMTestPriority 	    High
@SYMTestActions  	    Open and close connection to ECOM server
                        Check for any memory leak and crash problem
@SYMTestExpectedResults The test must not fail.
@SYMREQ                 REQ0000
*/
void RFinalCloseTest::NonConstructL_Create_Destroy()
	{
	__UHEAP_MARK;

	// Test 1
	::NonConstructL_Create_Destroy_helper();

	// Test 2
	REComSession* ptr = new REComSession;
	delete ptr;

	__UHEAP_MARKEND;
	}

/**
The test code is used for capturing the PANIC that occurs as a result of not
calling REComSession::FinalClose() when using ECOM plugins.

@SYMTestCaseID          SYSLIB-ECOM-CT-0768
@SYMTestCaseDesc	    Tests for PANIC when REComSession::FinalClose() is called using ECOM plugins
@SYMTestPriority 	    High
@SYMTestActions  	    Check for memory leak panic
@SYMTestExpectedResults The test must not fail.
@SYMREQ                 REQ0000
*/
void RFinalCloseTest::ThreadPanicTest(const TDesC& aName,TThreadFunction aFunction)
	{
	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-0768 "));
	test.Next(aName);
	TRequestStatus threadStatus;
	RThread thread;
	TBool jit;
	jit=User::JustInTime();
	User::SetJustInTime(EFalse);

	TInt err=thread.Create(aName,aFunction,KDefaultStackSize*8,KMinHeapSize,0x100000,0);
	test(err==KErrNone);
	thread.Logon(threadStatus)	;
	thread.Resume();

	User::WaitForRequest(threadStatus);

	//Now check why the thread Exit

	test(thread.ExitType()==EExitPanic);
	test(thread.ExitReason()==0);
	//A memory leak will have the exit category of form ALLOC:xxxxxx
	//test.Printf(_L("Exit xcat: %S"), thread.ExitCategory().Left(6));
	test(thread.ExitCategory().Left(6).CompareF(_L("ALLOC:"))==0);
	thread.Close();
	User::SetJustInTime(jit);
	}

/**
Copies the Plugins to specific folder for testing purpose
*/
LOCAL_C void CopyPlugins()
    {
	// Copy the dlls and .rsc files on to RAM
	TRAPD(err, EComTestUtils::FileManCopyFileL(KEComExDllOnZ, KEComExDllOnC));
	test(err==KErrNone);

	TRAP(err, EComTestUtils::FileManCopyFileL(KEComRscFileOnZ, KEComRscFileOnC));
	test(err==KErrNone);

	TRAP(err, EComTestUtils::FileManCopyFileL(KEComExampleDllOnZ, KEComExampleDllOnC));
	test(err==KErrNone);
	TRAP(err, EComTestUtils::FileManCopyFileL(KEComExample2DllOnZ, KEComExample2DllOnC));
	test(err==KErrNone);
 	TRAP(err, EComTestUtils::FileManCopyFileL(KEComExample3DllOnZ, KEComExample3DllOnC));
	test(err==KErrNone);

	TRAP(err, EComTestUtils::FileManCopyFileL(KEComExampleRscOnZ, KEComExampleRscOnC));
	test(err==KErrNone);
	TRAP(err, EComTestUtils::FileManCopyFileL(KEComExample2RscOnZ, KEComExample2RscOnC));
	test(err==KErrNone);
	TRAP(err, EComTestUtils::FileManCopyFileL(KEComExample3RscOnZ, KEComExample3RscOnC));
	test(err==KErrNone);
	}

// Deleting plugin from the RAM for cleanup purpose
inline LOCAL_C void DeleteTestPlugin()
	{
	TRAPD(err, EComTestUtils::FileManDeleteFileL(KEComExDllOnC));
	TRAP(err, EComTestUtils::FileManDeleteFileL(KEComRscFileOnC));
 	TRAP(err, EComTestUtils::FileManDeleteFileL(KEComExampleDllOnC));
 	TRAP(err, EComTestUtils::FileManDeleteFileL(KEComExample2DllOnC));
 	TRAP(err, EComTestUtils::FileManDeleteFileL(KEComExample3DllOnC));
 	TRAP(err, EComTestUtils::FileManDeleteFileL(KEComExampleRscOnC));
 	TRAP(err, EComTestUtils::FileManDeleteFileL(KEComExample2RscOnC));
 	TRAP(err, EComTestUtils::FileManDeleteFileL(KEComExample3RscOnC));
	}

LOCAL_C void RunTestL()
	{
	__UHEAP_MARK;
	//Basic ECOM test
	test.Next(_L("FinalClose"));
	RFinalCloseTest::FinalClose();
	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-0759 Create_Destroy_With_FinalCloseL "));
	RFinalCloseTest::Create_Destroy_With_FinalCloseL();
	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-0761 ListImpl_With_FinalCloseL "));
	RFinalCloseTest::ListImpl_With_FinalCloseL();
	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-0763 Create_Destroy2_With_FinalCloseL "));
	RFinalCloseTest::Create_Destroy2_With_FinalCloseL();
	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-0764 Create_Destroy3_With_FinalCloseL "));
	RFinalCloseTest::Create_Destroy3_With_FinalCloseL();
	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-0767 NonConstructL_Create_Destroy "));
	RFinalCloseTest::NonConstructL_Create_Destroy();

	//ECOM FinalClose() Panic Test
	#if defined(_DEBUG)
	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-0760 "));
	RFinalCloseTest::ThreadPanicTest(_L("Create Destroy Panic Testing"),RFinalCloseTest::Create_Destroy_Without_FinalClose);
	test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-0762 "));
	RFinalCloseTest::ThreadPanicTest(_L("List Implementation Panic Testing"),RFinalCloseTest::ListImpl_Without_FinalClose);
	#endif

	__UHEAP_MARKEND;
	}

GLDEF_C TInt E32Main()
	{
	__UHEAP_MARK;

	test.Title();
	test.Start(_L("Final Close tests."));

	CopyPlugins();

	CTrapCleanup* cleanup = CTrapCleanup::New();
	CActiveScheduler* scheduler = new(ELeave)CActiveScheduler;
	CActiveScheduler::Install(scheduler);

	TRAPD(err,RunTestL());
	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();

	delete scheduler;
	delete cleanup;

	test.End();
	test.Close();

	__UHEAP_MARKEND;
	return(0);
	}