fontservices/fontstore/tfs/T_FNTMEM.CPP
changeset 0 1fb32624e06b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fontservices/fontstore/tfs/T_FNTMEM.CPP	Tue Feb 02 02:02:46 2010 +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 <graphics/openfontrasterizer.h>
+
+#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(numFacesBefore<numFacesAfterLoadOriginals);
+		TUint numAllocsAfterLoadOriginals=iHeap->Count();
+		
+		
+		//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)
+
+