xml/xmlexpatparser/test/rtest/tsrc/t_xmlparserheap.cpp
changeset 0 e35f40988205
equal deleted inserted replaced
-1:000000000000 0:e35f40988205
       
     1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // This tests the failure of CExpat's internal heap.  It is a separate test executable
       
    15 // because it is statically linked to the xml parser object code and bypasses Ecom
       
    16 // 
       
    17 //
       
    18 
       
    19 #include <e32test.h>
       
    20 #include "contenthandlers.h"
       
    21 #include "xmlparserplugin.h"
       
    22 
       
    23 #include <xml/plugins/charsetconverter.h>
       
    24 #include <xml/stringdictionarycollection.h>
       
    25 
       
    26 using namespace Xml;
       
    27 
       
    28 GLDEF_D RTest test(_L("Expat heap test"));  // must be called test, as the e32test macros rely on this
       
    29 
       
    30 
       
    31 TPtrC8 KNamespaceTest =
       
    32 	_L8("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
       
    33 	"<!--"
       
    34 	"	namespace.xml - xml test file with known content for use with t_xmlparser"
       
    35 	"	Copyright (c) 2003, Symbian Ltd."
       
    36 	"	All Rights Reserved"
       
    37 	"-->"
       
    38 	""
       
    39 	"<RootElement rabbits:att=\"value\">"
       
    40 	" <Element xmlns=\"http://www.symbian.com\" att=\"value\">"
       
    41 	"  <elprefix:Element xmlns:elprefix=\"http://element.uri\" att=\"value\">"
       
    42 	"   <Element xmlns:attprefix=\"http://attribute.uri\" attprefix:att=\"value\"/>"
       
    43 	"   <Element attprefix:att=\"value\"/>"
       
    44 	"  </elprefix:Element>"
       
    45 	" </Element>"
       
    46 	"</RootElement>");
       
    47 
       
    48 
       
    49 // ---------------------------------------------------
       
    50 
       
    51 
       
    52 /**
       
    53 @SYMTestCaseID 		 		SYSLIB-XML-CT-3746
       
    54 @SYMTestCaseDesc		    Creating OOM conditions and parsing.
       
    55 @SYMTestPriority 		    Medium
       
    56 @SYMTestActions  		    In OOM conditions, creating a parser and then parsing chunks.
       
    57 @SYMTestExpectedResults 	The parser should behave as expected in the OOM conditions.
       
    58 @SYMPREQ 		 		 	PREQ230
       
    59 */
       
    60 LOCAL_C void ExpatOomTestL()
       
    61 	{
       
    62 	//
       
    63 	// Allocate paraphernalia required for CXmlParserPlugin
       
    64 	//
       
    65 	TSimpleContentHandler contentHandler;
       
    66 
       
    67 	RElementStack elementStack;
       
    68 	CleanupClosePushL(elementStack);
       
    69 
       
    70 	CCharSetConverter* charSetConverter = CCharSetConverter::NewL();
       
    71 	CleanupStack::PushL(charSetConverter);
       
    72 
       
    73 	RStringDictionaryCollection stringDictionaryCollection;
       
    74 	stringDictionaryCollection.OpenL();
       
    75 	CleanupClosePushL(stringDictionaryCollection);
       
    76 
       
    77 	TParserInitParams initParams;
       
    78 	initParams.iCharSetConverter = charSetConverter;
       
    79 	initParams.iContentHandler = &contentHandler;
       
    80 	initParams.iStringDictionaryCollection = &stringDictionaryCollection;
       
    81 	initParams.iElementStack = &elementStack;
       
    82 
       
    83 
       
    84 	/*
       
    85 	The following fragment forces the internal heap to fail during parser
       
    86 	construction and checks that this causes no leaks from the user heap
       
    87 	*/
       
    88 	TInt error;
       
    89 	TInt count = 0;
       
    90 	CXmlParserPlugin* parser = 0;
       
    91 	User::__DbgMarkStart(RHeap::EUser);
       
    92 
       
    93 	do
       
    94 		{
       
    95 		User::__DbgMarkEnd(RHeap::EUser,0);
       
    96 		User::__DbgMarkStart(RHeap::EUser);
       
    97 		count++;
       
    98 		TRAP(error, parser=CXmlParserPlugin::NewL(&initParams, count))
       
    99 		} while(error==KErrNoMemory);
       
   100 
       
   101 	CleanupReleasePushL(*parser);
       
   102 
       
   103 
       
   104 	/*
       
   105 	Next we parse the namespace test file and cause the heap to heap to fail.
       
   106 
       
   107 	Using the namespace test file ensures Expat is allocating prefixes and uri
       
   108 	bindings internally.
       
   109 	*/
       
   110 	count = 0;
       
   111 	RHeap* heap = parser->GetInternalHeap();
       
   112 	heap->__DbgMarkStart();
       
   113 
       
   114 	TInt err=KErrNone;
       
   115 	do
       
   116 		{
       
   117 		contentHandler.iError = KErrNone;
       
   118 
       
   119 		heap->__DbgMarkEnd(0);
       
   120 		heap->__DbgSetAllocFail(RHeap::EFailNext, ++count);
       
   121 		heap->__DbgMarkStart();
       
   122 		TRAP(err, parser->ParseLastChunkL(KNamespaceTest));
       
   123 		} while(err==KErrNoMemory);
       
   124 
       
   125 	test(err==KErrNone);
       
   126 	heap->__DbgMarkEnd(0);
       
   127 
       
   128 
       
   129 	/*
       
   130 	Now set the user heap to fail on the next allocation and parse the
       
   131 	document again.  This causes the CExpat handler function to leave,
       
   132 	in turn causing the parser to be de-allocated.
       
   133 
       
   134 	This is in preparation for the next test.
       
   135 	*/
       
   136 	contentHandler.iError = KErrNone;
       
   137 	heap->__DbgSetAllocFail(RHeap::ENone,1);  // __RHEAP_RESET
       
   138 	heap->__DbgMarkStart();
       
   139 	User::__DbgSetAllocFail(RHeap::EUser, RHeap::EFailNext, 1);
       
   140 	TRAP(err, parser->ParseLastChunkL(KNamespaceTest));
       
   141 	test(err==KErrNoMemory);
       
   142 	heap->__DbgMarkEnd(0);
       
   143 
       
   144 
       
   145 	/*
       
   146 	We have a CExpat in an error state with the internal parser deleted.  Now
       
   147 	cause systematic heap failure while attempting to reset the parser and
       
   148 	parse a document.
       
   149 
       
   150 	This will test reset failure and correct handling in CXmlParserPlugin.
       
   151 	*/
       
   152 	count = 0;
       
   153 	heap->__DbgMarkStart();
       
   154 
       
   155 	do
       
   156 		{
       
   157 		heap->__DbgMarkEnd(0);
       
   158 		heap->__DbgSetAllocFail(RHeap::EFailNext, ++count);
       
   159 		heap->__DbgMarkStart();
       
   160 		parser->EnableFeature(EReportNamespaceMapping);
       
   161 		TRAP(err, parser->ParseLastChunkL(KNamespaceTest));
       
   162 
       
   163 		} while(err==KErrNoMemory);
       
   164 
       
   165 	test(err==KErrNone);
       
   166 	heap->__DbgMarkEnd(0);
       
   167 
       
   168 	CleanupStack::PopAndDestroy(4);
       
   169 	User::__DbgMarkEnd(RHeap::EUser,0);
       
   170 }
       
   171 
       
   172 
       
   173 // ---------------------------------------------------
       
   174 // RunTestL
       
   175 // MainL
       
   176 // E32Main
       
   177 //
       
   178 // Top-level functions
       
   179 
       
   180 
       
   181 LOCAL_C void RunTestL()
       
   182 	{
       
   183 	test.Start(_L(" @SYMTestCaseID:SYSLIB-XML-CT-3746 Expat parser Out-of-Memory test "));
       
   184 
       
   185 // Ridiculous device to get around MSVC6 linker-compiler plot to rule the world
       
   186 #ifdef _DEBUG
       
   187 	volatile TInt releaseBuild = 0;
       
   188 #else
       
   189 	volatile TInt releaseBuild = 1;
       
   190 #endif
       
   191 
       
   192 	if(releaseBuild)
       
   193 		test.Printf(_L("This test is not supported in UREL builds\n"));
       
   194 	else
       
   195 		ExpatOomTestL();
       
   196 
       
   197 	test.End();
       
   198 	}
       
   199 
       
   200 LOCAL_C void MainL()
       
   201 	{
       
   202 	CleanupClosePushL(test);
       
   203 
       
   204 	TRAPD(error, RunTestL());
       
   205 	test(error==KErrNone);
       
   206 
       
   207 	CleanupStack::PopAndDestroy(&test);
       
   208 	}
       
   209 
       
   210 TInt E32Main()
       
   211 	{
       
   212 	__UHEAP_MARK;
       
   213 	CTrapCleanup* cleanup=CTrapCleanup::New();
       
   214 	if(!cleanup)
       
   215 		return KErrNoMemory;
       
   216 
       
   217 	TRAPD(error, MainL());
       
   218 
       
   219 	delete cleanup;
       
   220 	__UHEAP_MARKEND;
       
   221 
       
   222 	return error;
       
   223 	}