sl@0: // Copyright (c) 2007-2010 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: // sl@0: sl@0: /** sl@0: @file sl@0: @test sl@0: @internalComponent - Graphics Resource API Conformance Test Suite sl@0: */ sl@0: sl@0: #include sl@0: #include "tgraphicsresourcemultiprocessthread.h" sl@0: #include "tgraphicsresourceteststepbase.h" sl@0: sl@0: /** sl@0: Helper function to test the equivalence of two TSgImageInfo structures. sl@0: sl@0: @param aInfo1 A TSgImageInfo structure to compare. sl@0: @param aInfo2 A TSgImageInfo structure to compare. sl@0: sl@0: @return ETrue if the two are identical, EFalse otherwise. sl@0: */ sl@0: TBool CompareInfos(TSgImageInfo& aInfo1, TSgImageInfo& aInfo2) sl@0: { sl@0: TBool result = EFalse; sl@0: if(aInfo1.iPixelFormat == aInfo2.iPixelFormat sl@0: && aInfo1.iSizeInPixels == aInfo2.iSizeInPixels sl@0: && aInfo1.iUsage == aInfo2.iUsage) sl@0: { sl@0: result = ETrue; sl@0: } sl@0: return result; sl@0: } sl@0: sl@0: /** sl@0: Opens an image in a different process. sl@0: @param aInfo The test information passed from outside the current thread sl@0: @return The test result indicating which tests passed sl@0: */ sl@0: TInt TestOpenImageL(TSgProcessTestInfo& aInfo) sl@0: { sl@0: TSgDrawableId id = aInfo.iDrawableId; sl@0: TSgImageInfo imageInfo1 = aInfo.iImageInfo; sl@0: sl@0: RSgImage image; sl@0: TInt result = 0; sl@0: sl@0: if(KErrNone == image.Open(id)) sl@0: { sl@0: result |= EFirstTestPassed; sl@0: } sl@0: sl@0: TSgImageInfo imageInfo2; sl@0: TInt attribVal = KMaxTInt; sl@0: if(KErrNone == image.GetInfo(imageInfo2)) sl@0: { sl@0: result |= ESecondTestPassed; sl@0: } sl@0: if(CompareInfos(imageInfo1, imageInfo2)) sl@0: { sl@0: result |= EThirdTestPassed; sl@0: } sl@0: if (image.Id() != KSgNullDrawableId) sl@0: { sl@0: result |= EFourthTestPassed; sl@0: } sl@0: if(image.Id() == id) sl@0: { sl@0: result |= EFifthTestPassed; sl@0: } sl@0: TUid uid = { 0x12345678 }; sl@0: if (KErrNotSupported == image.GetAttribute(uid, attribVal)) sl@0: { sl@0: result |= ESixthTestPassed; sl@0: } sl@0: if (KErrArgument == image.GetAttribute(KNullUid, attribVal)) sl@0: { sl@0: result |= ESeventhTestPassed; sl@0: } sl@0: image.Close(); sl@0: sl@0: return result; sl@0: } sl@0: sl@0: /** sl@0: Opens an image in a different process into a RSgDrawable object. sl@0: @param aInfo The test information passed from outside the current thread sl@0: @return The test result indicating which tests passed sl@0: */ sl@0: TInt TestOpenDrawableL(TSgProcessTestInfo& aInfo) sl@0: { sl@0: TSgDrawableId id = aInfo.iDrawableId; sl@0: sl@0: RSgDrawable drawable; sl@0: TInt result = 0; sl@0: sl@0: if(KErrNone == drawable.Open(id)) sl@0: { sl@0: result |= EFirstTestPassed; sl@0: } sl@0: TSgDrawableId id2 = drawable.Id(); sl@0: if(id2 != KSgNullDrawableId) sl@0: { sl@0: result |= ESecondTestPassed; sl@0: } sl@0: if(id2 == id) sl@0: { sl@0: result |= EThirdTestPassed; sl@0: } sl@0: sl@0: drawable.Close(); sl@0: return result; sl@0: } sl@0: sl@0: /** sl@0: Opens an image in a different process with different invalid operations. sl@0: @param aInfo The test information passed from outside the current thread sl@0: @return The test result indicating which tests passed sl@0: */ sl@0: TInt TestOpenImageInvalidL(TSgProcessTestInfo& aInfo) sl@0: { sl@0: TSgDrawableId id = aInfo.iDrawableId; sl@0: TSgImageInfo imageInfo = aInfo.iImageInfo; sl@0: sl@0: RSgImage image; sl@0: TInt result = 0; sl@0: sl@0: //create image sl@0: if(KErrNone == image.Create(imageInfo, NULL, 0)) sl@0: { sl@0: result |= EFirstTestPassed; sl@0: } sl@0: // non-empty handle sl@0: if(KErrInUse == image.Open(id)) sl@0: { sl@0: result |= ESecondTestPassed; sl@0: } sl@0: image.Close(); sl@0: sl@0: // null drawable id sl@0: if(KErrArgument == image.Open(KSgNullDrawableId)) sl@0: { sl@0: result |= EThirdTestPassed; sl@0: } sl@0: image.Close(); sl@0: sl@0: // non-existing drawable id sl@0: TSgDrawableId fakeid = {0xFFFFFFFFFFFFFFFFU}; sl@0: if(KErrNotFound == image.Open(fakeid)) sl@0: { sl@0: result |= EFourthTestPassed; sl@0: } sl@0: image.Close(); sl@0: sl@0: //Valid Drawable Id sl@0: if (KErrNone == image.Open(id)) sl@0: { sl@0: result |= EFifthTestPassed; sl@0: } sl@0: image.Close(); sl@0: return result; sl@0: } sl@0: sl@0: /** sl@0: Opens a drawable in a different process with different invalid operations. sl@0: @param aInfo The test information passed from outside the current thread sl@0: @return The test result indicating which tests passed sl@0: */ sl@0: TInt TestOpenDrawableInvalidL() sl@0: { sl@0: RSgDrawable drawable; sl@0: TInt result = 0; sl@0: sl@0: //null drawable id sl@0: if(KErrArgument == drawable.Open(KSgNullDrawableId)) sl@0: { sl@0: result |= EFirstTestPassed; sl@0: } sl@0: drawable.Close(); sl@0: sl@0: //non-existing drawable id sl@0: TSgDrawableId fakeid = {0xFFFFFFFFFFFFFFFFU}; sl@0: if(KErrNotFound == drawable.Open(fakeid)) sl@0: { sl@0: result |= ESecondTestPassed; sl@0: } sl@0: drawable.Close(); sl@0: sl@0: //non-empty handle sl@0: //create an image sl@0: TSgImageInfo info1; sl@0: info1.iSizeInPixels = TSize(8, 8); sl@0: info1.iUsage = ESgUsageBitOpenVgImage; sl@0: info1.iPixelFormat = EUidPixelFormatRGB_565; sl@0: sl@0: sl@0: RSgImage image; sl@0: TInt err = image.Create(info1, NULL, 0); sl@0: if(KErrNoMemory == err) sl@0: { sl@0: result = KErrNoMemory; sl@0: } sl@0: else if(KErrNone != err) sl@0: { sl@0: result = err; sl@0: } sl@0: else sl@0: { sl@0: if(KErrNone == drawable.Open(image.Id())) sl@0: { sl@0: result |= EThirdTestPassed; sl@0: sl@0: if (KErrInUse == drawable.Open(image.Id())) sl@0: { sl@0: result |= EFourthTestPassed; sl@0: } sl@0: } sl@0: drawable.Close(); sl@0: } sl@0: image.Close(); sl@0: return result; sl@0: } sl@0: sl@0: TInt TestCloseDriverOpenResources(RSgDriver& aDriver) sl@0: { sl@0: RSgImage image; sl@0: TSgImageInfo info1; sl@0: info1.iSizeInPixels = TSize(8, 8); sl@0: info1.iUsage = ESgUsageBitOpenVgImage; sl@0: info1.iPixelFormat = EUidPixelFormatRGB_565; sl@0: sl@0: TInt result = image.Create(info1, KCrossImageData, KCrossImageDataStride); sl@0: sl@0: if (result == KErrNone) sl@0: { sl@0: //Close the driver without closing the image. sl@0: aDriver.Close(); //Should panic with SGRES2 sl@0: } sl@0: sl@0: return result; sl@0: } sl@0: sl@0: /** sl@0: Method executed by secondary thread for test TestOpenImageMulththreadedL sl@0: */ sl@0: _LIT(KTestOpenImageMultithreadedSem1, "TestOpenImageMultithreadedSem1"); sl@0: _LIT(KTestOpenImageMultithreadedSem2, "TestOpenImageMultithreadedSem2"); sl@0: sl@0: TInt OpenImageMultiSecondThread(TAny* aAny) sl@0: { sl@0: TInt err = KErrNone; sl@0: TSgProcessTestInfo* info = static_cast(aAny); sl@0: sl@0: RSemaphore sem[2]; sl@0: err = sem[0].OpenGlobal(KTestOpenImageMultithreadedSem1, EOwnerThread); sl@0: if (err != KErrNone) sl@0: { sl@0: return err; sl@0: } sl@0: err = sem[1].OpenGlobal(KTestOpenImageMultithreadedSem2, EOwnerThread); sl@0: if (err != KErrNone) sl@0: { sl@0: sem[0].Close(); sl@0: return err; sl@0: } sl@0: sl@0: RSgImage sgImage; sl@0: err = sgImage.Open(info->iDrawableId); sl@0: sl@0: sem[0].Signal(); sl@0: sem[1].Wait(); sl@0: sl@0: sgImage.Close(); sl@0: sem[0].Signal(); sl@0: return err; sl@0: } sl@0: sl@0: /** sl@0: Creates a second thread which will initially open a handle to the passed TSgDrawableId. sl@0: The main thread then opens a new handle to the image. sl@0: The second thread will then close its handle to the image. sl@0: The main thread will then attempt to access the data of the image. sl@0: */ sl@0: TInt TestOpenImageMultithreadedL(TSgProcessTestInfo& aInfo) sl@0: { sl@0: TInt result = 0; sl@0: sl@0: //create two semaphores sl@0: RSemaphore sem[2]; sl@0: User::LeaveIfError(sem[0].CreateGlobal(KTestOpenImageMultithreadedSem1, 0, EOwnerThread)); sl@0: CleanupClosePushL(sem[0]); sl@0: User::LeaveIfError(sem[1].CreateGlobal(KTestOpenImageMultithreadedSem2, 0, EOwnerThread)); sl@0: CleanupClosePushL(sem[1]); sl@0: sl@0: //create secondary thread sl@0: _LIT(KSecondaryThreadName, "TestOpenImageMultithreadedL"); sl@0: RThread thread; sl@0: User::LeaveIfError(thread.Create(KSecondaryThreadName, OpenImageMultiSecondThread, KDefaultStackSize, KSecondThreadMinHeapSize, KSecondThreadMaxHeapSize, &aInfo)); sl@0: thread.Resume(); sl@0: sl@0: // Make the second thread open the image before this thread. sl@0: sem[0].Wait(); sl@0: sl@0: // Second thread has opened image, now primary thread opens image sl@0: RSgImage sgImage; sl@0: TInt err = sgImage.Open(aInfo.iDrawableId); sl@0: CleanupClosePushL(sgImage); sl@0: sem[1].Signal(); sl@0: sem[0].Wait(); sl@0: sl@0: // Second thread has closed image and terminated, now wait for thread to clean-up sl@0: User::After(100000); sl@0: sl@0: if (err == KErrNone) sl@0: { sl@0: // Do something that requires data access of sgImage, in this case, creating a copy. sl@0: result |= EFirstTestPassed; sl@0: RSgImage sgImageCopy; sl@0: err = sgImageCopy.Create(aInfo.iImageInfo, sgImage); sl@0: sgImageCopy.Close(); sl@0: if (err == KErrNone) sl@0: { sl@0: result |= ESecondTestPassed; sl@0: } sl@0: } sl@0: sl@0: CleanupStack::PopAndDestroy(3); // sgImage, sem[0], sem[1] sl@0: return result; sl@0: } sl@0: sl@0: TInt MainL() sl@0: { sl@0: TPckgBuf infoPkg; sl@0: User::LeaveIfError(User::GetDesParameter(KSecondProcessParametersSlot, infoPkg)); sl@0: TSgProcessTestInfo& info = infoPkg(); sl@0: TSgresTestCase testCase = info.iTestCase; sl@0: TInt result = 0; sl@0: sl@0: RSgDriver sgDriver; sl@0: CleanupClosePushL(sgDriver); sl@0: sl@0: if(KErrNone == sgDriver.Open()) sl@0: { sl@0: switch(testCase) sl@0: { sl@0: case ESgresSecondProcessOpenImage: sl@0: result = TestOpenImageL(info); sl@0: break; sl@0: case ESgresSecondProcessOpenDrawable: sl@0: result = TestOpenDrawableL(info); sl@0: break; sl@0: case ESgresSecondProcessOpenImageInvalid: sl@0: result = TestOpenImageInvalidL(info); sl@0: break; sl@0: case ESgresSecondProcessOpenDrawableInvalid: sl@0: result = TestOpenDrawableInvalidL(); sl@0: break; sl@0: case ESgresSecondProcessPanicDriverCloseOpenResources: sl@0: result = TestCloseDriverOpenResources(sgDriver); sl@0: break; sl@0: case ESgresSecondProcessOpenImageMultithreaded: sl@0: result = TestOpenImageMultithreadedL(info); sl@0: break; sl@0: } sl@0: } sl@0: sl@0: CleanupStack::PopAndDestroy(&sgDriver); sl@0: sl@0: return result; sl@0: } sl@0: sl@0: GLDEF_C TInt E32Main() sl@0: { sl@0: __UHEAP_MARK; sl@0: CTrapCleanup* cleanupStack = CTrapCleanup::New(); sl@0: if(cleanupStack == NULL) sl@0: { sl@0: return KErrNoMemory; sl@0: } sl@0: TInt ret = 0; sl@0: TRAP_IGNORE(ret=MainL()); sl@0: delete cleanupStack; sl@0: __UHEAP_MARKEND; sl@0: return ret; sl@0: }