lowlevellibsandfws/pluginfw/Framework/SimpleTests/t_rogueplugin.cpp
author Stefan Karlsson <stefan.karlsson@nokia.com>
Mon, 29 Mar 2010 12:27:51 +0100
branchCompilerCompatibility
changeset 14 69a2780c0013
parent 0 e4d67989cc36
permissions -rw-r--r--
Merge.

// Copyright (c) 2006-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 <ecom/ecom.h>
#include "Interface.h" // ECOM CExampleInterface class
#include "exampleNine.h" // CRoguePlugin class


//Test utils for copying plugin to C
#include "EcomTestUtils.h"

_LIT(KTestTitle, "DEF094656 Rogue plugin should not override build-in");

LOCAL_D RTest TheTest(_L("Rogue plugin with duplicated Impl. UID"));

LOCAL_D TBool correctTypeCastPassed = EFalse;

_LIT(KRoguePluginDllOnZ,	"Z:\\RAMOnly\\exampleNine.dll");
_LIT(KRoguePluginDllOnC,	"C:\\sys\\bin\\exampleNine.dll");
_LIT(KRoguePluginRscOnZ,	"Z:\\RAMOnly\\exampleNine.rsc");
_LIT(KRoguePluginRscOnC,	"C:\\resource\\plugins\\exampleNine.rsc");

/** Copy the rogue plugin to C: drive
*/
LOCAL_C void CopyPluginsL()
    {
	// Copy the dlls and .rsc files on to RAM
	EComTestUtils::FileManCopyFileL(KRoguePluginDllOnZ, KRoguePluginDllOnC);
	EComTestUtils::FileManCopyFileL(KRoguePluginRscOnZ, KRoguePluginRscOnC);
	// Pause in case ECOM server is already up and running and needs
	// time to activate the scanning timer active object.
	User::After(3000000);
	}

/** Remove resource file and dll copied to C: drive
*/
LOCAL_C void DeleteTestPlugin()
	{
	TRAPD(ignoreErr, EComTestUtils::FileManDeleteFileL(KRoguePluginRscOnC));
	TRAP(ignoreErr, EComTestUtils::RLoaderDeleteFileL(KRoguePluginDllOnC));
	}

/**
Test rogue plugin trying to override a ROM based plugin by
duplicating the legitimate DLL's implementation UID (different
interface UID so that ECOM not treat it as an update).

@SYMTestCaseID			SYSLIB-ECOM-CIT-3161
@SYMTestCaseDesc	    Copy a rogue plugin to C drive. This plugin duplicates the
						implementation UID of a built-in dll. Test if the rogue
						plugin will over shadow the built-in dll.
@SYMTestPriority		High
@SYMTestActions			1. copy the rsc and dll of the rogue plugin to C:
						2. Use the CreateImplementation API which does not specify
						   the i/f UID to instantiate the built-in implementation.
						   Test the instance works normally.
						3. Repeat 2 but instantiate the pointer as the rogue plugin
						   class. Pass NULL as the initialising param in the call
						   to CreateImplementationL. Because the actual plugin returned by
						   ECOM needs this initParam, KERN-EXEC 3 panic occurs.
@SYMTestExpectedResults	The test must not fail.
@SYMDEF					DEF094656
*/
LOCAL_C void DEF094656_TestCaseL()
	{
	// DuplicateImplUidTestL SYSLIB-ECOM-CT-3157 is similar to this testcase.
	// CT-3157 tests higher driver letter > lower driver letter,
	// and lower i/f UID > higher i/f UID.

	// Note that this function is expected to panic. Hence not bother
	// with __UHEAP_MARK.

	//Check if the rogue plugin is in the registry.
	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CIT-3161 "));
	RImplInfoPtrArray ifArray;
	REComSession::ListImplementationsL(KRogueInterfaceUid, ifArray);

	TInt count = ifArray.Count();
	TheTest.Printf(_L("Found %d implementations of I/f 0x%X"), count, KRogueInterfaceUid.iUid);

	TheTest(count == 1);
	TheTest(KRogueImplUid == ifArray[0]->ImplementationUid());

	ifArray.ResetAndDestroy();

	TUid dtor_key;
	// Initialisation parameter needed by CImplementationClassOne
	CExampleInterface::TExampleInterfaceInitParams initParams;
	initParams.integer		= 0;
	initParams.descriptor	= NULL;

	// First test creating the correct class.
	CExampleInterface* correctDll = reinterpret_cast<CExampleInterface*>(
		REComSession::CreateImplementationL(KRogueImplUid,
											dtor_key,
											&initParams) );
	TheTest(correctDll != NULL);

	TUid testUid = correctDll->ImplId();
	// the example plugins should return the value 10009DC3.
	TheTest(testUid == KRogueImplUid);

	REComSession::DestroyedImplementation(dtor_key);
	delete correctDll;

	// Indicate to thread creator that first stage test passed.
	correctTypeCastPassed = ETrue;

	// This create should crash because the plugin returned by
	// ECOM is really CImplementationClassOne which needs a properly
	// constructed initParam.
	CRoguePlugin* wrongDll = reinterpret_cast<CRoguePlugin*>(
		REComSession::CreateImplementationL(KRogueImplUid,
											dtor_key,
											NULL) );

	// If gets here then someone has changed CImplementationClassOne::NewL
	// or 10009DC3 has been updated by another implementation.
	if (wrongDll)
		{
		REComSession::DestroyedImplementation(dtor_key);
		delete wrongDll;
		}

	REComSession::FinalClose();

	TheTest(EFalse);
	}

LOCAL_C void ThreadMainL()
	{
	CConsoleBase* newConsole = Console::NewL(KTestTitle,
		TSize(KConsFullScreen, KConsFullScreen));

	// Thread creator needs to save the original console because this
	// thread is expected to crash, hence cannot cleanup.
	TheTest.SetConsole(newConsole);
	DEF094656_TestCaseL();
	TheTest.SetConsole(NULL);

	delete newConsole;
	}

LOCAL_C TInt ThreadFunc(TAny*)
	{
	__UHEAP_MARK;
	CTrapCleanup* threadcleanup = CTrapCleanup::New();
	TRAPD(err, ThreadMainL());
	delete threadcleanup;
	__UHEAP_MARKEND;
	return err;
	}

LOCAL_C void RunTestThreadL()
	{
	__UHEAP_MARK;

	CopyPluginsL();

	_LIT(KThreadName, "RoguePluginTest");

	TBool jit = User::JustInTime();
	User::SetJustInTime(EFalse);

	TheTest.Start(KTestTitle);

	// Save the console because the created thread must use its own
	// console.
	CConsoleBase* savedConsole = TheTest.Console();

	RThread tt;
	TInt err = tt.Create(KThreadName, &ThreadFunc, KDefaultStackSize,
		KMinHeapSize, 0x100000, 0);
	User::LeaveIfError(err);

	TRequestStatus status;
	tt.Logon(status);
	tt.Resume();

	User::WaitForRequest(status);

	// restore console
	TheTest.SetConsole(savedConsole);

	TExitCategoryName exitcategory = tt.ExitCategory();
	TExitType exittype = tt.ExitType();
	TInt exitReason = tt.ExitReason();
	tt.Close();

	TheTest.Printf(_L("Thread exit type %d, reason %d, category %S"), exittype, exitReason, &exitcategory);

	User::SetJustInTime(jit);
	DeleteTestPlugin();

	// Check if tt thread passes this checkpoint
	TheTest(correctTypeCastPassed);

	// Check if tt thread die of KERN-EXEC.
	_LIT(KKernExec, "KERN-EXEC");
	TheTest(exitcategory.CompareF(KKernExec) == 0);

	TheTest.End();
	TheTest.Close();

	__UHEAP_MARKEND;
	}

GLDEF_C TInt E32Main()
	{
	__UHEAP_MARK;

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

	TRAP_IGNORE( RunTestThreadL() );

	delete scheduler;
	delete cleanup;

	__UHEAP_MARKEND;
	return KErrNone;
	}