graphicsresourceservices/graphicsresourceimplementation/test/src/tgraphicsresourcesecondprocess.cpp
author Shabe Razvi <shaber@symbian.org>
Fri, 21 May 2010 17:25:10 +0100
changeset 79 5b97810c83ff
parent 36 01a6848ebfd7
child 103 2717213c588a
permissions -rw-r--r--
Workaround for Bug 1362 - libGLES_CM.dll isn't contributed

// Copyright (c) 2007-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:
//

/**
 @file
 @test
 @internalComponent - Graphics Resource API Conformance Test Suite
*/

#include <e32debug.h>
#include "tgraphicsresourcemultiprocessthread.h"
#include "tgraphicsresourceteststepbase.h"

/**
Helper function to test the equivalence of two TSgImageInfo structures.

@param   aInfo1 A TSgImageInfo structure to compare.
@param   aInfo2 A TSgImageInfo structure to compare.

@return  ETrue if the two are identical, EFalse otherwise.
*/
TBool CompareInfos(TSgImageInfo& aInfo1, TSgImageInfo& aInfo2)
	{
	TBool result = EFalse;
	if(aInfo1.iPixelFormat == aInfo2.iPixelFormat
		&& aInfo1.iSizeInPixels == aInfo2.iSizeInPixels
		&& aInfo1.iUsage | aInfo2.iUsage)
		{
		result = ETrue;
		}
	return result;
	}

/**
Opens an image in a different process.
@param aInfo The test information passed from outside the current thread
@return The test result indicating which tests passed
*/
TInt TestOpenImageL(TSgProcessTestInfo& aInfo)
	{
	TSgDrawableId id = aInfo.iDrawableId;
	TSgImageInfo imageInfo1 = aInfo.iImageInfo;
	
	RSgImage image;
	TInt result = 0;

	if(KErrNone == image.Open(id))
		{
		result |=  EFirstTestPassed;
		}
	
	TSgImageInfo imageInfo2;
	TInt attribVal = KMaxTInt;
	if(KErrNone == image.GetInfo(imageInfo2))
		{
		result |= ESecondTestPassed;
		}
	if(CompareInfos(imageInfo1, imageInfo2))
		{
		result |= EThirdTestPassed;
		}
	if (image.Id() != KSgNullDrawableId)
		{
		result |= EFourthTestPassed;
		}
	if(image.Id() == id)
		{
		result |= EFifthTestPassed;
		}
	if (id == aInfo.iDrawableId)
		{
		result |= ESixthTestPassed;
		}	
	TUid uid = { 0x12345678 };
	if (KErrNotSupported == image.GetAttribute(uid, attribVal))
	    {
	    result |= ESeventhTestPassed;
	    }
	if (KErrArgument == image.GetAttribute(KNullUid, attribVal))
	    {
	    result |= EEighthTestPassed;
	    }
	image.Close();

	return result;
	}

/**
Opens an image in a different process into a RSgDrawable object.
@param aInfo The test information passed from outside the current thread
@return The test result indicating which tests passed
*/
TInt TestOpenDrawableL(TSgProcessTestInfo& aInfo)
	{
	TSgDrawableId id = aInfo.iDrawableId;
	
	RSgDrawable drawable;
	TInt result = 0;
	
	if(KErrNone == drawable.Open(id))
		{
		result |=  EFirstTestPassed;
		}
	TSgDrawableId id2 = drawable.Id();
	if(id2 != KSgNullDrawableId)
		{
		result |= ESecondTestPassed;
		}
	if(id2 == id)
		{
		result |= EThirdTestPassed;
		}

	drawable.Close();
	return result;
	}

/**
Opens an image in a different process with different invalid operations.
@param aInfo The test information passed from outside the current thread
@return The test result indicating which tests passed
*/
TInt TestOpenImageInvalidL(TSgProcessTestInfo& aInfo)
	{	
	TSgDrawableId id = aInfo.iDrawableId;
	TSgImageInfo imageInfo = aInfo.iImageInfo;
	
	RSgImage image;
	TInt result = 0;
	
	//create image
	if(KErrNone == image.Create(imageInfo, NULL, 0))
		{
		result |= EFirstTestPassed;
		}
	//  non-empty handle
	if(KErrInUse == image.Open(id))
		{
		result |= ESecondTestPassed;
		}
	image.Close();
	
	//  null drawable id	
	if(KErrArgument == image.Open(KSgNullDrawableId))
		{
		result |= EThirdTestPassed;
		}
	image.Close();
	
	//  non-existing drawable id
	TSgDrawableId fakeid = {0xFFFFFFFFFFFFFFFFU};
	if(KErrNotFound == image.Open(fakeid))
		{
		result |= EFourthTestPassed;
		}
	image.Close();
	
	//Valid Drawable Id
	if (KErrNone == image.Open(id))
		{
		result |= EFifthTestPassed;
		}
	image.Close();
	return result;
	}

/**
Opens a drawable in a different process with different invalid operations.
@param aInfo The test information passed from outside the current thread
@return The test result indicating which tests passed
*/
TInt TestOpenDrawableInvalidL()
	{	
	RSgDrawable  drawable;
	TInt result = 0;
	
	//null drawable id	
	if(KErrArgument == drawable.Open(KSgNullDrawableId))
		{
		result |= EFirstTestPassed;
		}
	drawable.Close();
	
	//non-existing drawable id
	TSgDrawableId fakeid = {0xFFFFFFFFFFFFFFFFU};
	if(KErrNotFound == drawable.Open(fakeid))
		{
		result |= ESecondTestPassed;
		}
	drawable.Close();
		
	//non-empty handle
	//create an image
	TSgImageInfo info1;
	info1.iSizeInPixels = TSize(8, 8);
	info1.iUsage = ESgUsageBitOpenVgImage;
	info1.iPixelFormat = EUidPixelFormatRGB_565;

	
	RSgImage image;
	TInt err = image.Create(info1, NULL, 0);
	if(KErrNoMemory == err)
		{
		result = KErrNoMemory;
		}
	else if(KErrNone != err)
		{
		result = err;
		}
	else
		{		
		if(KErrNone == drawable.Open(image.Id()))
			{
			result |= EThirdTestPassed;
			
			if (KErrInUse == drawable.Open(image.Id()))
				{
				result |= EFourthTestPassed;
				}
			}		
		drawable.Close();
		}
	image.Close();
	return result;
	}

TInt TestCloseDriverOpenResources(RSgDriver& aDriver)
	{
	RSgImage image;
	TSgImageInfo info1;
	info1.iSizeInPixels = TSize(8, 8);
	info1.iUsage = ESgUsageBitOpenVgImage;
	info1.iPixelFormat = EUidPixelFormatRGB_565;
	
	TInt result = image.Create(info1, KCrossImageData, KCrossImageDataStride);
	
	if (result == KErrNone)
		{
		//Close the driver without closing the image.
		aDriver.Close(); //Should panic with SGRES2
		}
	
	return result;
	}

/**
Method executed by secondary thread for test TestOpenImageMulththreadedL
*/
_LIT(KTestOpenImageMultithreadedSem1, "TestOpenImageMulththreadedSem1");
_LIT(KTestOpenImageMultithreadedSem2, "TestOpenImageMulththreadedSem2");

TInt OpenImageMultiSecondThread(TAny* aAny)
	{
	TInt err = KErrNone;
	TSgProcessTestInfo* info = static_cast<TSgProcessTestInfo*>(aAny);	

	RSemaphore sem[2];
	err = sem[0].OpenGlobal(KTestOpenImageMultithreadedSem1, EOwnerThread);
	if (err != KErrNone)
		{
		return err;
		}
	err = sem[1].OpenGlobal(KTestOpenImageMultithreadedSem2, EOwnerThread);
	if (err != KErrNone)
		{
		sem[0].Close();
		return err;
		}

	RSgImage sgImage; 
	err = sgImage.Open(info->iDrawableId);

	sem[0].Signal();
	sem[1].Wait();

	sgImage.Close();	
	sem[0].Signal();
	return err;	
	}

/**
Creates a second thread which will initially open a handle to the passed TSgDrawableId.
The main thread then opens a new handle to the image.
The second thread will then close its handle to the image.
The main thread will then attempt to access the data of the image.
 */
TInt TestOpenImageMulththreadedL(TSgProcessTestInfo& aInfo)
	{
	TInt result = 0;
	
	//create a semaphore
	RSemaphore sem[2];
	User::LeaveIfError(sem[0].CreateGlobal(KTestOpenImageMultithreadedSem1, 0, EOwnerThread));
	CleanupClosePushL(sem[0]);
	User::LeaveIfError(sem[1].CreateGlobal(KTestOpenImageMultithreadedSem2, 0, EOwnerThread));
	CleanupClosePushL(sem[1]);
		
	//create secondary thread
	_LIT(KMultipleThreadName, "TestOpenImageMulththreadedL");
	RThread thread;
	TBuf<50> threadName(KMultipleThreadName);
	User::LeaveIfError(thread.Create(threadName, OpenImageMultiSecondThread, KDefaultStackSize, KSecondThreadMinHeapSize, KSecondThreadMaxHeapSize, &aInfo));
	thread.Resume();
	
	// Make the second thread open the image before this thread.
	sem[0].Wait();

	// Second thread has opened image, now primary thread opens image
	RSgImage sgImage;
	TInt err = sgImage.Open(aInfo.iDrawableId);
	CleanupClosePushL(sgImage);
	sem[1].Signal();
	sem[0].Wait();
		
	// Second thread has closed image and terminated, now wait for thread to clean-up
	User::After(100000);

	if (err == KErrNone)
		{
		// Do something that requires data access of sgImage, in this case, creating a copy.
		result |= EFirstTestPassed;
		RSgImage sgImageCopy;
		err = sgImageCopy.Create(aInfo.iImageInfo, sgImage);
		sgImageCopy.Close();
		if (err == KErrNone)
			{
			result |= ESecondTestPassed;
			}	
		}
	
	CleanupStack::PopAndDestroy(3); // sgImage, sem[0], sem[1]		
	return result;	
	}

TInt MainL()
	{				
	TPckgBuf<TSgProcessTestInfo> infoPkg;
	User::LeaveIfError(User::GetDesParameter(KSecondProcessParametersSlot, infoPkg));
	TSgProcessTestInfo& info = infoPkg();
	TSgresTestCase testCase = info.iTestCase;
	TInt result = 0;

	RSgDriver sgDriver;
	CleanupClosePushL(sgDriver);
	
	if(KErrNone == sgDriver.Open())
		{
		switch(testCase)
			{
			case ESgresSecondProcessOpenImage:
				result = TestOpenImageL(info);
				break;
			case ESgresSecondProcessOpenDrawable:
				result = TestOpenDrawableL(info);
				break;
			case ESgresSecondProcessOpenImageInvalid:
				result = TestOpenImageInvalidL(info);
				break;
			case ESgresSecondProcessOpenDrawableInvalid:
				result = TestOpenDrawableInvalidL();
				break;
			case ESgresSecondProcessPanicDriverCloseOpenResources:
				result = TestCloseDriverOpenResources(sgDriver);
				break;
			case ESgresSecondProcessOpenImageMultithreaded:
				result = TestOpenImageMulththreadedL(info);
				break;
			}
		}	
	
	CleanupStack::PopAndDestroy(&sgDriver);
	
	return result;
	}

GLDEF_C TInt E32Main()
	{
	__UHEAP_MARK;
	CTrapCleanup* cleanupStack = CTrapCleanup::New();
	if(cleanupStack == NULL)
		{
		return KErrNoMemory;
		}
	TInt ret = 0;
	TRAP_IGNORE(ret=MainL());
	delete cleanupStack;
	__UHEAP_MARKEND;
	return ret;
	}