diff -r 000000000000 -r bde4ae8d615e os/textandloc/fontservices/fontstore/tfs/T_FNTMEM.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/textandloc/fontservices/fontstore/tfs/T_FNTMEM.CPP Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,636 @@ +/* +* Copyright (c) 1995-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 "T_FNTMEM.H" +#include "T_FSOPEN.H" +#include + +#ifdef __WINS__ + _LIT(KEonFontFileName,"z:\\resource\\fonts\\eon14.gdr"); +#else + _LIT(KEonFontFileName,"z:\\resource\\fonts\\eon.gdr"); +#endif + +// 'dummy' open fonts, as used by T_FSOPEN +_LIT(KFontDummy,"z:\\PlatTest\\Graphics\\TestData\\dummy_fonts\\dummy"); +//_LIT(KFontDummy_b,"z:\\PlatTest\\Graphics\\TestData\\dummy_fonts\\dummy_b"); +//_LIT(KFontDummy_i,"z:\\PlatTest\\Graphics\\TestData\\dummy_fonts\\dummy_i"); +//_LIT(KFontDummy_bi,"z:\\PlatTest\\Graphics\\TestData\\dummy_fonts\\dummy_bi"); + + + +CTFntMem::CTFntMem(CTestStep* aStep): + CTGraphicsBase(aStep), + iHeap(NULL) + { + iHeap = UserHeap::ChunkHeap(NULL,0x80000,0x80000); + INFO_PRINTF1(_L("FontStore")); + } + +void CTFntMem::RunTestCaseL(TInt aCurTestCase) + { + ((CTFntMemStep*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName); + switch(aCurTestCase) + { + case 1: + ((CTFntMemStep*)iStep)->SetTestStepID(_L("GRAPHICS-FNTSTORE-0024")); + TRAPD(err,TestNewL()); + TEST(err == KErrNone); + break; + case 2: // OOM handling for bitmap fonts + ((CTFntMemStep*)iStep)->SetTestStepID(_L("GRAPHICS-FNTSTORE-0025")); + TRAP(err,TestAddFileL(KEonFontFileName)); + TEST(err == KErrNone); + break; + case 3: // OOM handling for open fonts + ((CTFntMemStep*)iStep)->SetTestStepID(_L("GRAPHICS-FNTSTORE-0025")); + TRAP(err,TestAddFileL(KFontDummy)); + TEST(err == KErrNone); + break; + case 5: // OOM handling for second reference to a bitmap font + ((CTFntMemStep*)iStep)->SetTestStepID(_L("GRAPHICS-FNTSTORE-0026")); + TRAP(err,TestAddFileTwiceL(KEonFontFileName)); + TEST(err == KErrNone); + break; + case 6: // OOM handling for second reference to an open font + ((CTFntMemStep*)iStep)->SetTestStepID(_L("GRAPHICS-FNTSTORE-0026")); + TRAP(err,TestAddFileTwiceL(KFontDummy)); + TEST(err == KErrNone); + break; + case 7: + ((CTFntMemStep*)iStep)->SetTestStepID(_L("GRAPHICS-FNTSTORE-0027")); + TRAP(err,TestGetNearestFontToDesignHeightInTwipsL()); + TEST(err == KErrNone); + break; + case 8: + ((CTFntMemStep*)iStep)->SetTestStepID(_L("GRAPHICS-NearestOpenFontLeaksDEF095184-0001")); + TRAP(err,TestGetNearestOpenFontLeaksL()); + TEST(err == KErrNone); + break; + case 9: + ((CTFntMemStep*)iStep)->SetTestStepID(_L("GRAPHICS-CTFbs-TestDuplicateFontFileEntries-0002")); + TRAP(err,TestDuplicateBitmapFontFileEntriesL()); + TEST(err == KErrNone); + break; + case 10: + ((CTFntMemStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName); + ((CTFntMemStep*)iStep)->CloseTMSGraphicsStep(); + TestComplete(); + break; + default: + ((CTFntMemStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName); + break; + } + ((CTFntMemStep*)iStep)->RecordTestResultL(); + } + +/** + @SYMTestCaseID + GRAPHICS-FNTSTORE-0024 + + @SYMTestCaseDesc + Simulates out of memory errors of the heap when trying to allocate + memory for a CFontStore object. + + @SYMTestActions + 1. Cancels simulated heap allocation failure for the current thread's heap. + 2. Simulates heap allocation failure for the current thread's heap. + 3. Marks the start of checking the current thread's heap. + 4. In a loop, tries to create a new CFontStore object with a pointer to + the heap class used for memory allocation. + 5. Checking is done to see if the CFontStore was allocated or + if out of memory. The loop is broken when an object is created correctly. + + @SYMTestExpectedResults + Test should pass +*/ +void CTFntMem::TestNewL() + { + INFO_PRINTF1(_L("NewL")); + + TInt ret=KErrGeneral; + CFontStore *fs=NULL; + TInt failRate=1; + + while (ret!=KErrNone) + { + __UHEAP_RESET; + __UHEAP_SETFAIL(RHeap::EDeterministic,failRate); + __UHEAP_MARK; + TRAP(ret,fs=CFontStore::NewL(iHeap)); + RDebug::Print(_L("fs %d failrate %d, error %d\n"),fs,failRate, ret); + if (ret==KErrNoMemory) + { + __UHEAP_MARKEND; + __UHEAP_RESET; + TEST(fs==NULL); + } + else if(ret==KErrNone) + { + delete fs; + __UHEAP_MARKEND; + __UHEAP_RESET; + __UHEAP_SETFAIL(RHeap::ENone,failRate); + } + else + User::Panic(_L("Unknown error"),ret); + failRate++; + } + } + +/** + @SYMTestCaseID + GRAPHICS-FNTSTORE-0025 + + @SYMTestCaseDesc + Tests the Out Of Memory handling for bitmap- and open fonts. + + @SYMTestActions + 1. Finds or creates a font file object to support a font file. + If an appropriate font file object exists then no new open font file is created. + In this case the reference count of the font file object is incremented. + 2. Allocates the object from the heap and then initialises its contents + to binary zeroes. + 3. Installs and takes ownership of an Open Font rasterizer + 4. Releases a hold on one or all font file objects (COpenFontFiles or CFontStoreFiles) + If aFileUid identifies a font file object, then the reference count for this + object is decremented. If this brings the reference count down to zero then + the font file object is removed from the font store, as well as the fonts + and typefaces associated with this file. + If, on the other hand, aFileUid's value is NULL, then all font file objects + are removed, along with all fonts and typefaces in the font store. + 5. Simulates heap allocation failure for the current thread's heap. + 6. Tries to add a font file to the font store and checks for memory allocation errors. + + @SYMTestExpectedResults + Test should pass +*/ +void CTFntMem::TestAddFileL(const TDesC& aFileName) + { + INFO_PRINTF2(_L("AddFileL(\"%S\")"), &aFileName); + TInt failRate=1; + CFontStore *fs=CFontStore::NewL(iHeap); + + // Install the dummy rasterizer - used for 'Open Font's + COpenFontRasterizer* r = CDummyRasterizer::NewL(); + CleanupStack::PushL(r); + fs->InstallRasterizerL(r); + CleanupStack::Pop(); + + (void)fs->AddFileL(aFileName); + fs->RemoveFile(KNullUid); + TInt ret=KErrGeneral; + + while (ret!=KErrNone) + { + __UHEAP_RESET; + __UHEAP_MARK; + __UHEAP_SETFAIL(RHeap::EDeterministic,failRate); + TRAP(ret, (void)fs->AddFileL(aFileName)); + RDebug::Print(_L("NumTypefaces %d failrate %d, error %d\n"),fs->NumTypefaces(), failRate, ret); + if (ret==KErrNoMemory) + { + fs->RemoveFile(KNullUid); + __UHEAP_MARKEND; + __UHEAP_RESET; + TEST(fs->NumTypefaces()==0); + } + else if(ret==KErrNone) + { + fs->RemoveFile(KNullUid); + delete fs; + __UHEAP_MARKEND; + __UHEAP_RESET; + __UHEAP_SETFAIL(RHeap::ENone,failRate); + } + else + User::Panic(_L("Unknown error"),ret); + failRate++; + } + } + +/** + @SYMTestCaseID + GRAPHICS-FNTSTORE-0026 + + @SYMTestCaseDesc + Tests the Out Of Memory handling for second reference to a bitmap font and open fonts. + + @SYMTestActions + 1. Finds or creates a font file object to support a font file. + If an appropriate font file object exists then no new open font file is created. + In this case the reference count of the font file object is incremented. + 2. Allocates the object from the heap and then initialises its contents. + to binary zeroes. + 3. Installs and takes ownership of an Open Font rasterizer. + 4. Loads a font file. + 5. Simulates heap allocation failure for the current thread's heap. + 6. Tries to add a font file a second time to the font store and checks for memory allocation errors. + 7. Removes all font file objects. + + @SYMTestExpectedResults + Test should pass +*/ +void CTFntMem::TestAddFileTwiceL(const TDesC& aFileName) + { + INFO_PRINTF2(_L("AddFileTwiceL(\"%S\")"), &aFileName); + TInt failRate=1; + CFontStore *fs=CFontStore::NewL(iHeap); + + // Install the dummy rasterizer - used for 'Open Font's + COpenFontRasterizer* r = CDummyRasterizer::NewL(); + CleanupStack::PushL(r); + fs->InstallRasterizerL(r); + CleanupStack::Pop(); + + // load the font file + (void)fs->AddFileL(aFileName); + TInt ret=KErrGeneral; + + while (ret!=KErrNone) + { + __UHEAP_SETFAIL(RHeap::EDeterministic,failRate); + __UHEAP_MARK; + TRAP(ret, (void)fs->AddFileL(aFileName)); + RDebug::Print(_L("NumTypefaces %d failrate %d, error %d\n"),fs->NumTypefaces(), failRate, ret); + + // neither success or failure should use more memory + __UHEAP_MARKEND; + __UHEAP_RESET; + + if ( (ret != KErrNoMemory) && (ret != KErrNone) ) + { + User::Panic(_L("Unknown error"),ret); + } + failRate++; + } + + fs->RemoveFile(KNullUid); + delete fs; + } + +/** + @SYMTestCaseID + GRAPHICS-FNTSTORE-0027 + + @SYMTestCaseDesc + Tests the function GetNearestFontToDesignHeightInTwips in Out Of Memory + error conditions. + + @SYMTestActions + 1. Creates a new CFontStore object. + 2. Adds a font file to the font store. + 3. Creates a bitmap font object. + 4. Gets the nearest font to design height in twips of the DejaVu Sans Condensed font. + 5. Releases a hold on one or all font file objects (COpenFontFiles or CFontStoreFiles) + If aFileUid identifies a font file object, then the reference count for this + object is decremented. If this brings the reference count down to zero then + the font file object is removed from the font store, as well as the fonts + and typefaces associated with this file. + If, on the other hand, aFileUid's value is NULL, then all font file objects + are removed, along with all fonts and typefaces in the font store. + 6. Simulates heap allocation failure for the current thread's heap. + 7. Tries to get the nearest font to design height in twips for the font and + checks for memory allocation errors. + 8. Deallocates the CFontStore object. + + @SYMTestExpectedResults + Test should pass +*/ +void CTFntMem::TestGetNearestFontToDesignHeightInTwipsL() + { + INFO_PRINTF1(_L("GetNearestFontToDesignHeightInTwips")); + CFontStore *fs=CFontStore::NewL(iHeap); + (void)fs->AddFileL(KEonFontFileName); + TInt failRate=1; + CBitmapFont *font; + TFontSpec spec(_L("DejaVu Sans Condensed"),200); + TInt ret; + ret=fs->GetNearestFontToDesignHeightInTwips((CFont *&) font,spec); + TEST(ret==KErrNone); + if (ret!=KErrNone || font==NULL) + return; //otherwise the memory faulting test loop will deadlock! + fs->ReleaseFont(font); + ret=KErrNoMemory; + while(ret!=KErrNone) + { + __UHEAP_RESET; + __UHEAP_SETFAIL(RHeap::EDeterministic,failRate); + __UHEAP_MARK; + __RHEAP_MARK(iHeap); + font=NULL; + ret=fs->GetNearestFontToDesignHeightInTwips((CFont *&) font,spec); + RDebug::Print(_L("Font %d failrate %d\n"),font,failRate); + if (ret==KErrNoMemory) + { + TEST(font==NULL); + __RHEAP_MARKEND(iHeap); + __UHEAP_MARKEND; + } + else if(ret==KErrNone) + { + fs->ReleaseFont(font); + font=NULL; + __RHEAP_MARKEND(iHeap); + __UHEAP_MARKEND; + __UHEAP_SETFAIL(RHeap::ENone,failRate); + } + else + User::Panic(_L("Unknown error"),ret); + failRate++; + } + + delete fs; + } +//---------------- +/** +@SYMTestCaseID GRAPHICS-NearestOpenFontLeaksDEF095184-0001 +@SYMTestPriority Med +@SYMREQ DEF095184 + +@SYMTestCaseDesc +Leak in font finder + +@SYMTestActions +Tests for leak case loading both nearest open and bitmap font. +The first call to GetNearestFontToDesignHeightInTwips loads the bitmap font. +The looped calls change the memory fault frequency until this succeeds, +but the open font is returned instead, and then until the bitmap font is again returned. +The test fontspec is specially chosen to cause these different results, + and the test code is not working if the differing results are not fetched. + +@SYMTestExpectedResults +failrate 1: KErrNoMemory +failrate 2: Same font returned +failrate 3: Different font returned +failrate 4: Same font returned +No leaks. +Note that the exact results may change fail rates +if underlying changes are made to the font store. + +**/ +void CTFntMem::TestGetNearestOpenFontLeaksL() + { + INFO_PRINTF1(_L("TestGetNearestOpenFontLeaksL")); + CFontStore *fs=CFontStore::NewL(iHeap); + CleanupStack::PushL(fs); + // Install the dummy rasterizer - used for 'Open Font's + COpenFontRasterizer* r = CDummyRasterizer::NewL(); + CleanupStack::PushL(r); + fs->InstallRasterizerL(r); + //Need one of each font flavour + (void)fs->AddFileL(KFontDummy); + (void)fs->AddFileL(KEonFontFileName); + CleanupStack::Pop(r); + CleanupStack::Pop(fs); + bool differentResultFetched=false; + CBitmapFont *firstFont; + + //Manufacture this font so that the bitmap font is favoured + //Note that the best I could do was get them equal, but that is enough to get bitmap chosen! + //Blank name is required to allow the dummy open font to be selected by similarity + TFontSpec reqSpec(_L(""),190); + reqSpec.iFontStyle.SetBitmapType(EMonochromeGlyphBitmap); + TFontSpec firstSpec; + TInt ret; + //first run - tests that the code actually works before faulting the memory + ret=fs->GetNearestFontToDesignHeightInTwips((CFont *&) firstFont,reqSpec); + TEST(ret==KErrNone); + TEST(firstFont!=NULL); + if (ret!=KErrNone || firstFont==NULL) + { + return; //otherwise the memory faulting test loop will deadlock! + } + if (firstFont) + { + firstSpec=firstFont->FontSpecInTwips(); + fs->ReleaseFont(firstFont); + } + ret=KErrNoMemory; + TInt failRate=1; + while(ret!=KErrNone || (failRate<30 && !differentResultFetched)) + { + CBitmapFont *font=NULL; + __UHEAP_RESET; + __RHEAP_SETFAIL(iHeap,RHeap::EDeterministic,failRate); + __UHEAP_MARK; + __RHEAP_MARK(iHeap); + TFontSpec spec(reqSpec); + ret=fs->GetNearestFontToDesignHeightInTwips((CFont *&) font,reqSpec); + if (ret==KErrNoMemory) + { + RDebug::Print(_L("failrate %d: KErrNoMemory\n"),failRate); + TEST(font==NULL); + } + else if(ret==KErrNone) + { + TEST(font!=NULL); + if (font) + { + TFontSpec spec=font->FontSpecInTwips(); + if (!(spec==firstSpec)) + { + differentResultFetched=true; + ret=KErrNoMemory; //actually there was a handled memory fault + RDebug::Print(_L("failrate %d: Different font returned\n"),failRate); + } + else + { + RDebug::Print(_L("failrate %d: Same font returned\n"),failRate); + } + } + else + { + RDebug::Print(_L("failrate %d: Error: NULL font returned\n"),failRate); + } + fs->ReleaseFont(font); + font=NULL; + } + else + { + User::Panic(_L("Unexpected error"),ret); + } + __RHEAP_CHECK(iHeap,0); + __RHEAP_MARKEND(iHeap); + __UHEAP_MARKEND; + __RHEAP_SETFAIL(iHeap,RHeap::ENone,failRate); + failRate++; + } + if (!differentResultFetched) + { + INFO_PRINTF1(_L("Test did not return different results under memory stress (unexpected)")); + } + delete fs; + } + + +//The "bad" versions of these standard fonts have been hacked to give specific results +_LIT(KFBSERVFontFileBitmap, "Z:\\resource\\fonts\\ceurope.GDR"); +//This file has the master GUID nobbled, but all the guid and typeface entries are duplicates. +_LIT(KFBSERVFontFileBadBitmap1, "Z:\\PlatTest\\Graphics\\TestData\\uniquified_fonts\\XXeuro.GDR"); +//This file has the master GUID nobbled, one of the 8 fonts, and one of the typefaces has also been nobbled. +_LIT(KFBSERVFontFileBadBitmap2, "Z:\\PlatTest\\Graphics\\TestData\\uniquified_fonts\\YYeuro.GDR"); +enum {KNobbledFontEnum=0x10ff5912}; //official code for LatinBold17 is 0x10005912 +_LIT(NobbledTypefaceName, "XatinBold17"); + + + /** + @SYMTestCaseID GRAPHICS-CTFbs-TestDuplicateFontFileEntries-0002 + + @SYMDEF DEF094692 + + @SYMTestCaseDesc If Bitmap fonts are loaded that are marginally unique compared to the + existing fonts then they are not actually added to the typeface system, and may even be discarded. + + @SYMTestPriority Med + + @SYMTestStatus Implemented + + @SYMTestActions \n + The original versions of the Bitmapfonts are first loaded to ensure that they have actually been loaded. + A version of the bitmap font which is identical except for the file UID should be rejected + Verify that the unique data for the next test does not already exist + A version of the bitmap font which has just 1 unique bitmap will be loaded, but only 1 typeface entry will be added. + Verify that the unique data for the previous test now does exist + The memory allocations through these steps should be deterministic + + API Calls: AddFile\n + + @SYMTestExpectedResults The test expects: + The original versions should load without changing the number of typefaces + The second load should return the same UID for the font + The identical fonts should return captured fail codes, and not change the typeface counts + The semi-identical font should perform a single increase to UIDs and typefaces + */ +void CTFntMem::TestDuplicateBitmapFontFileEntriesL() + { + + INFO_PRINTF1(_L("Test Load semi-duplicate bitmap font files")); + __RHEAP_MARK(iHeap); + __UHEAP_MARK; + CFontStore *fs=CFontStore::NewL(iHeap); + CleanupStack::PushL(fs); + + TInt numFacesBefore=fs->NumTypefaces(); + TUid aIdBitMap1=TUid::Null(); + TUint numAllocsBefore=iHeap->Count(); + TUid aIdBitMap2=TUid::Null(); + TUid aIdBitMap3=TUid::Null(); + //make sure the originals of these fonts were safely opened + //both should simply cause a reference-count increase on the originator files. + TRAPD(err1,aIdBitMap1=fs->AddFileL(KFBSERVFontFileBitmap)); + TEST(err1==KErrNone); + if (err1) + { + INFO_PRINTF1(_L("One of the expected fonts was missing. Test abandoned.")); + } + else + { + TInt numFacesAfterLoadOriginals=fs->NumTypefaces(); + TEST(numFacesBeforeCount(); + + + //This bitmap font file contains no new fonts, so will ultimately be discarded + //The master UID has been nobbled so the file is not considered identical to its originator + TRAPD(err3,aIdBitMap2=fs->AddFileL(KFBSERVFontFileBadBitmap1)); + TEST(err3==KErrAlreadyExists && aIdBitMap2==TUid::Null()); + if (err3!=KErrAlreadyExists) + INFO_PRINTF2(_L("Unexpected error code was %d"),err3); + TInt numFacesAfterLoadBadFile3=fs->NumTypefaces(); + TEST(numFacesAfterLoadOriginals==numFacesAfterLoadBadFile3); + TUint numAllocsAfterLoadBadFile3=iHeap->Count(); + TEST(numAllocsAfterLoadBadFile3==numAllocsAfterLoadOriginals); + + //Before loading the next test check that the new data about to be added does not already exist + CFont *font=NULL; + TAlgStyle algStyle; + TFontSpec fontSpec(NobbledTypefaceName,10); + + TInt err5a1=fs->GetFontById(font,TUid::Uid(KNobbledFontEnum),algStyle); + TEST(font==NULL); //the nobbled UID should not already exist + + font=NULL; + + TInt err5a2=fs->GetNearestFontInPixels(font, fontSpec); + if (font) + { + TFontSpec specNoMatch=font->FontSpecInTwips(); + TEST(specNoMatch.iTypeface.iName!=NobbledTypefaceName); //Nobbled font name should not be known yet + fs->ReleaseFont(font); + } + + //This bitmap font file contains one new typeface and font + //Actually, they are bit file edited versions of existing ones! + TInt numAllocsBeforeLoadBadFile5 = iHeap->Count(); + TRAPD(err5,aIdBitMap3=fs->AddFileL(KFBSERVFontFileBadBitmap2)); + TEST(err5==KErrNone); + if (err5!=KErrNone) + INFO_PRINTF2(_L("Unexpected error code was %d"),err5); + + //The number of typefaces has now increased + TInt numFacesAfterLoadBadFile5=fs->NumTypefaces(); + TEST(numFacesAfterLoadOriginals+1==numFacesAfterLoadBadFile5); + TUint numAllocsAfterLoadBadFile5=iHeap->Count(); + TEST(numAllocsAfterLoadBadFile5==numAllocsBeforeLoadBadFile5+2); + + + TInt err5b1=fs->GetFontById(font,TUid::Uid(KNobbledFontEnum),algStyle); + TEST(err5b1==KErrNone && font!=NULL); //the nobbled UID should now exist + if (err5b1!=KErrNone) + INFO_PRINTF2(_L("Unexpected error code was %d"),err5b1); + + CFont *font2=NULL; + TInt err5b2=fs->GetNearestFontInPixels(font2, fontSpec); + TEST(err5b2==KErrNone && font2!=NULL); + if (err5b2!=KErrNone) + INFO_PRINTF2(_L("Unexpected error code was %d"),err5b2); + if (font2!=NULL) + { + TFontSpec specMatches=font->FontSpecInTwips(); + TEST(specMatches.iTypeface.iName==NobbledTypefaceName); //the nobbled typeface should now exist + } + TEST(font==font2); + if (font) + fs->ReleaseFont(font); + if (font2) + fs->ReleaseFont(font2); + } + + if (aIdBitMap1!=TUid::Null()) fs->RemoveFile(aIdBitMap1); + if (aIdBitMap2!=TUid::Null()) fs->RemoveFile(aIdBitMap2); + if (aIdBitMap3!=TUid::Null()) fs->RemoveFile(aIdBitMap3); + + //The added typeface should have been uninstalled + TInt numFacesAfterUninstall=fs->NumTypefaces(); + TEST(numFacesAfterUninstall==numFacesBefore); + TUint numAllocsAfterUninstall=iHeap->Count(); + + CleanupStack::PopAndDestroy(fs); + __UHEAP_CHECK(0); + __UHEAP_MARKEND; + __RHEAP_CHECK(iHeap,0); + __RHEAP_MARKEND(iHeap); + + } + + +//-------------- +__CONSTRUCT_STEP__(FntMem) + +