cryptomgmtlibs/securitycommonutils/test/source/scstest/scstest.cpp
changeset 8 35751d3474b7
child 15 da2ae96f639b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptomgmtlibs/securitycommonutils/test/source/scstest/scstest.cpp	Thu Sep 10 14:01:51 2009 +0300
@@ -0,0 +1,847 @@
+/*
+* 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 the License "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: 
+* Exercises the test implementation of the session count server,
+* to test the base SCS functionality.
+*
+*/
+
+
+/**
+ @file
+*/
+
+#include <e32ldr.h>
+#include <f32file.h>
+#include <scs/rtestwrapper.h>
+
+#include <scs/scscommon.h>
+#include "scstestcommon.h"
+#include "scstestclient.h"
+
+const TInt KOneSecondUs = 1000 * 1000;		///< One second in microseconds.
+
+/** Top-level test object renders stages and confirms conditions. */
+static RTestWrapper test(_L("SCSTEST"));
+
+/**
+	This session handle is defined at the file level so each individual test
+	does not have to connect to the server.
+ */
+static RScsTestSession sTestSession;
+/**
+	This subsession handle is defined at the file level so each individual test
+	does not have to connect to the server and create a subssesion.
+ */
+static RScsTestSubsession sTestSubsession;
+
+/** Arbitrary integer value used to construct subsession. */
+static const TInt KSubsessValue = 10;
+
+static void LetServerRun()
+/**
+	Sleep for 100ms so the server thread can run to clean up,
+	terminate, or just process the last request which it was sent.
+ */
+	{
+	User::After(100 * 1000);
+	}
+
+// -------- OOM testing --------
+
+static void RunOomTest(TInt (*aAllocFunc)(), void (*aFreeFunc)())
+/**
+	Run the supplied allocator function while forcing OOM on the server side.
+	On failure, this functions tests that the server heap is balanced.  On
+	success, it runs the free function and also tests that the server heap is
+	balanced.
+
+	@param	aAllocFunc		Function which allocates resources on the server heap.
+	@param	aFreeFunc		Frees the resources allocated with aAllocFunc.  It should
+							only be necessary to call this function if aAllocFunc
+							succeeds.  This argument can be NULL if there is no
+							corresponding free function.
+ */
+	{
+	TInt r = KErrNoMemory;
+	
+	for (TInt i = 1; r == KErrNoMemory; ++i)
+		{
+		sTestSession.SetServerHeapFail(i);
+		
+		r = aAllocFunc();
+		
+		test(r == KErrNone || r == KErrNoMemory);
+		if (r == KErrNone && aFreeFunc != NULL)	
+			aFreeFunc();
+		
+		sTestSession.ResetServerHeapFail();
+		}
+	}
+
+// -------- panic testing --------
+
+/**
+	To test that a client is panicked, pass a function with this
+	signature to TestPanic.  It will be called from a new thread.
+	
+	@see TestPanic
+ */
+typedef void (*TPanicFunc)(RScsTestSession&);
+
+static void ConfirmPanicReason(RThread aThread, TInt aExpectedReason)
+/**
+	Test the supplied thread was panicked with category
+	ScsImpl::KScsClientPanicCat and the supplied reason.
+
+	@param	aThread			Panicked thread.
+	@param	aExpectedReason	The thread should have been panicked with
+							this reason.
+	@see ScsImpl::KScsClientPanicCat
+ */
+	{
+	TExitType exitType = aThread.ExitType();
+	TExitCategoryName exitCat = aThread.ExitCategory();
+	TInt exitReason = aThread.ExitReason();
+	
+	test(exitType == EExitPanic);
+	test(exitCat == ScsImpl::KScsClientPanicCat);
+	test(exitReason == aExpectedReason);
+	}
+
+static TInt TestPanicEntrypoint(TAny* aPtr)
+/**
+	This entrypoint is called by the panic thread.  The
+	function connects to the SCS test server and passes
+	the handle to the function that should be panicked.
+
+	@param	aPtr			Standard entrypoint argument.  This is actually
+							a pointer to the function to call with the connected
+							session.
+	@return					KErrNone.  Required to satisfy entrypoint signature.
+ */
+	{
+	RScsTestSession s;
+	TInt r = s.Connect();
+	test(r == KErrNone);
+	
+	TPanicFunc f = TAnyPtrToFuncPtr<TPanicFunc>(aPtr);
+	f(s);
+	
+	test(EFalse);			// should not reach here
+	return KErrNone;
+	}
+
+static void TestPanic(TPanicFunc aFunc, TInt aExpectedReason)
+/**
+	Create a thread which should be panicked because it will
+	pass invalid data to the SCS test server.  Test the thread
+	is panicked with the expected category and reason.
+
+	@param	aFunc			Function to call from panic thread.
+	@param	aExpectedReason	Reason with which the thread should
+							be panicked.
+ */
+	{
+	RThread thd;
+	TInt r = thd.Create(
+		_L("ScsTestPanic"), TestPanicEntrypoint,
+		KDefaultStackSize, KMinHeapSize, KMinHeapSize, (TAny*) aFunc);
+	test(r == KErrNone);
+	
+	TRequestStatus rs;
+	thd.Rendezvous(rs);
+	test(rs == KRequestPending);
+	TBool jit = User::JustInTime();
+	User::SetJustInTime(EFalse);
+	thd.Resume();
+	
+	User::WaitForRequest(rs);
+	User::SetJustInTime(jit);
+	ConfirmPanicReason(thd, aExpectedReason);
+	thd.Close();
+	}
+
+// -------- open / close --------
+
+/** Handle to a session which the test code attempts to open in server-side OOM. */
+RScsTestSession sOomTestSession;
+
+static TInt OpenOomSession()
+/**
+	This function is invoked by RunOomTest.  It just
+	attempts to connect to the SCS test server.
+
+	@return					Return code from RScsTestSession::Connect.
+	@see CloseOomSession
+ */
+	{
+	return sOomTestSession.Connect();
+	}
+
+static void CloseOomSession()
+/**
+	Closes the session which was opened by OpenOomSession.
+
+	@see OpenOomSession
+	@pre OpenOomSession was successfully opened by OpenOomSession.
+ */
+	{
+	sOomTestSession.Close();
+	}
+
+static void TestServerDeath()
+	{
+	test.Start(_L("TestServerDeath"));
+
+	test.Next(_L("Starting server without shutdown timer"));
+	// Create marker file to get server to run without a activity timeout
+	RFs fs;
+	TInt r = fs.Connect();
+	test(r == KErrNone);
+	(void) fs.Delete(KDisableScsTestServerTimeout());
+
+	RFile file;
+	r = file.Create(fs, KDisableScsTestServerTimeout(), EFileShareAny|EFileWrite);
+	test(r == KErrNone);
+	file.Close();
+
+	// Start server
+	RScsTestSession scsts;
+	r = scsts.Connect();
+	test(r == KErrNone);
+	
+	test.Next(_L("Checking ShutdownServer is not allowed"));
+	r = scsts.ShutdownServer();
+	test(r == KErrNotSupported);
+
+
+	test.Next(_L("Doing an async call to check server does not attempt to restart the timer and crash"));
+	TPckgBuf<TInt> x1 = 1;
+	TRequestStatus rs1;
+	scsts.Treble(x1, rs1);
+	User::WaitForRequest(rs1);
+
+	test.Printf(_L("NukeServer - scstestserver.exe SHOULD panic\n"));
+	r = scsts.NukeServer();
+	test(r == KErrServerTerminated);
+
+	
+	(void) fs.Delete(KDisableScsTestServerTimeout());
+	fs.Close();
+	scsts.Close();
+	test.End();
+	}
+
+static void TestOpenClose()
+/**
+	Attempt to connect to the server when supplying default,
+	lower, and higher version numbers.  Attempt to open a session
+	in server-side OOM.
+ */
+	{
+	test.Start(_L("TestOpenClose"));
+
+	TInt r;
+	RScsTestSession scsts;
+	
+	// default version
+	r = scsts.Connect();
+	test(r == KErrNone);
+	scsts.Close();
+	
+	// lower-than-supported version
+	TVersion v = ScsTestImpl::Version();
+	--v.iMajor;
+	r = scsts.Connect(v);
+	test(r == KErrNone);
+	scsts.Close();
+
+	// supported version (should be same as default)
+	++v.iMajor;
+	r = scsts.Connect(v);
+	test(r == KErrNone);
+	scsts.Close();
+
+	// greater-than-supported version
+	++v.iMajor;
+	r = scsts.Connect(v);
+	test(r == KErrNotSupported);
+	
+	// test opening session when server running out of memory
+	r = sTestSession.Connect();		// required to send OOM commands
+	test(r == KErrNone);
+	
+	RunOomTest(OpenOomSession, CloseOomSession);
+	
+	sTestSession.Close();
+
+#if 0
+	// Test closing server with an out standing request
+	r = scsts.Connect();
+	test(r == KErrNone);
+	test(r == KErrNone);
+	TPckgBuf<TInt> x1 = 1;
+	TRequestStatus rs1;
+	scsts.Treble(x1, rs1);
+	// Bypass the presession close
+	RSessionBase *session = &scsts;
+	session->Close();
+	User::WaitForRequest(rs1);
+	test(rs1 == KErrCancel);
+#endif
+	
+	test.End();
+	}
+
+// -------- invalid session function --------
+
+static void TestInvalidSessionFunction()
+/**
+	Send an unrecognized SCS code and confirm that it is
+	rejected with KErrNotSupported.  This tests the SCS
+	implementation.
+	
+	Send an unrecognized function identifier to the session
+	and confirm that it is also rejected with KErrNotSupported.
+	This tests the test server session implementation.
+ */
+	{
+	test.Start(_L("TestInvalidSessionFunction"));
+	
+	TInt r;
+	
+	r = sTestSession.SendCustomFunction(ScsImpl::EScsUnused);
+	test(r == KErrNotSupported);
+	
+	r = sTestSession.SendCustomFunction(ScsImpl::ECallSessionFunc | ScsTestImpl::ESessUnused);
+	test(r == KErrNotSupported);
+	
+	test.End();
+	}
+
+// -------- synchronous session function --------
+
+static void TestSyncSessionFunction()
+/**
+	Send a recognized function to the SCS test session,
+	and confirm that it is executed correctly.
+ */
+	{
+	test.Start(_L("TestSyncSessionFunction"));
+
+	TInt x = 3;
+	TInt r = sTestSession.Double(x);
+	test(r == KErrNone);
+	test(x == 6);
+	
+	test.End();
+	}
+
+// -------- asynchronous session function --------
+
+static TInt LaunchSessionTrebleOom()
+/**
+	Attempt to launch an asynchronous command on a session
+	under OOM conditions.
+ */
+	{
+	TPckgBuf<TInt> x = 3;
+	TRequestStatus rs;
+	sTestSession.Treble(x, rs);
+	User::WaitForRequest(rs);
+	
+	if (rs == KErrNone)
+		{
+		test(x() == 9);
+		}
+	
+	return rs.Int();
+	}
+
+static void TestAsyncInvalidDescPanic(RScsTestSession& aSession)
+/**
+	Pass an invalid descriptor to the SCS test server.
+	The current thread should be panicked.
+
+	@param	aSession		Open session to SCS test server,
+							supplied by TestPanic.
+	@see TestPanic
+ */
+	{
+	TDes8* nullDes8 = 0;
+	TRequestStatus rs;
+	aSession.Treble(*nullDes8, rs);
+	User::WaitForRequest(rs);
+	}
+
+static void TestRequeueOutstandingPanic(RScsTestSession& aSession)
+/**
+	Attempt to requeue an asynchronous request which is still
+	outstanding.  The current thread should be panicked.
+
+	@param	aSession		Connected session to SCS test server.
+	@see TestPanic
+ */
+	{
+	TPckgBuf<TInt> x1 = 1;
+	TRequestStatus rs1;
+	aSession.Treble(x1, rs1);
+	
+	TPckgBuf<TInt> x2 = 2;
+	TRequestStatus rs2;
+	aSession.Treble(x2, rs2);
+	
+	User::WaitForRequest(rs1, rs2);
+	User::WaitForRequest(rs1, rs2);
+	}
+
+static void TestAsyncSessionFunction()
+/**
+	Test asynchronous session-relative functions.
+
+	Launch a request and wait for it to complete.
+
+	Launch a request and cancel it.
+
+	Launch a request with an invalid descriptor.
+
+	Cancel a request which is not outstanding.
+
+	Launch a request in OOM.
+
+	Launch an asynchronous request on a session and wait
+	for it to complete.
+ */
+	{
+	test.Start(_L("TestAsyncSessionFunction"));
+	
+	TInt r;
+	
+	LaunchSessionTrebleOom();
+	
+	// test launching async request in OOM
+	RunOomTest(LaunchSessionTrebleOom, NULL);
+
+	// cancel async request
+	TPckgBuf<TInt> x = 3;
+	TRequestStatus rs;
+	sTestSession.Treble(x, rs);
+	sTestSession.CancelTreble();
+	User::WaitForRequest(rs);
+	test(rs == KErrCancel);
+
+	// bad descriptor panic
+	TestPanic(TestAsyncInvalidDescPanic, ScsImpl::EScsClBadDesc);
+	
+	// safely cancel async request which is not queued
+	sTestSession.CancelTreble();
+	
+	// panic if requeue outstanding request
+	TestPanic(TestRequeueOutstandingPanic, ScsImpl::EScsClAsyncAlreadyQueued);
+	
+	// test outstanding request cancelled when session closed with RScsSessionBase::Close
+	RScsTestSession asyncSession;
+	r = asyncSession.Connect();
+	test(r == KErrNone);
+	x() = 4;
+	asyncSession.Treble(x, rs);
+	asyncSession.Close();
+	User::After(ScsTestImpl::KTrebleTimerDelayUs + KOneSecondUs);
+	test(rs == KErrCancel);
+	User::WaitForRequest(rs);
+
+	// test outstanding request not cancelled when session closed with RSessionBase::Close
+	r = asyncSession.Connect();
+	test(r == KErrNone);
+	x() = 4;
+	asyncSession.Treble(x, rs);
+	asyncSession.RSessionBase::Close();
+	User::After(ScsTestImpl::KTrebleTimerDelayUs + KOneSecondUs);
+	test(rs == KRequestPending);		// client request not cancelled or completed
+	
+	test.End();
+	}
+
+// -------- open / close subsession --------
+
+/**
+	This subsession handle is opened in OOM testing.
+
+	@see OpenOomSubsession
+	@see CloseOomSubsession
+ */
+RScsTestSubsession sOomSubsession;
+
+static TInt OpenOomSubsession()
+/**
+	Attempt to open a subsession in OOM.
+
+	@see CloseOomSubsession
+	@see RunOomTest
+ */
+	{
+	return sOomSubsession.Create(sTestSession, 10);
+	}
+
+static void CloseOomSubsession()
+/**
+	Free the subsession which was opened in OOM.
+
+	@see OpenOomSubsession
+	@see RunOomTest
+ */
+	{
+	sOomSubsession.Close();
+	}
+
+static void TestOpenCloseSubsession()
+/**
+	Test opening and closing a subsession, including
+	opening in OOM.
+ */
+	{
+	test.Start(_L("TestOpenCloseSubsession"));
+	
+	TInt r;
+	
+	RScsTestSubsession ss;
+	r = ss.Create(sTestSession, 10);
+	test(r == KErrNone);
+	ss.Close();
+	
+	// test creating in OOM
+	RunOomTest(OpenOomSubsession, CloseOomSubsession);
+	
+	test.End();
+	}
+
+// -------- invalid subsession function --------
+
+static void TestInvalidSubsessionFunction()
+/**
+	Pass an unrecognized function to a subession and test
+	the subsession handles it properly.  This tests the SCS
+	test implementation, rather than the SCS itself.
+ */
+	{
+	test.Start(_L("TestInvalidSubsessionFunction"));
+
+	TInt r = sTestSubsession.SendFunction(ScsTestImpl::ESubsessUnused);	
+	test(r == KErrNotSupported);
+	
+	test.End();
+	}
+
+// -------- synchronous subsession function --------
+
+static void TestBadHandlePanic(RScsTestSession& aSession)
+/**
+	Call a subsession function passing in an invalid handle.
+	The current thread should be panicked.
+
+	@param	aSession		Open session to SCS test server,
+							supplied by TestPanic.
+	@see TestPanic
+ */
+	{
+	RScsTestSubsession ss;
+	TInt r = ss.Create(aSession, 10);
+	test(r == KErrNone);
+	
+	// modify the subsession handle
+	TUint8* addrOfHandle;
+	addrOfHandle = (TUint8*)&ss;
+	addrOfHandle += sizeof(RSessionBase);
+	*((TInt*)addrOfHandle) ^= ~0;
+	
+	TInt x = 3;
+	r = ss.Quadruple(x);	// should be panicked with EScsClBadHandle
+	}
+
+static void TestSyncSubsessionFunction()
+/**
+	Call a synchronous function on a subsession.  This ensures
+	the request is routed to the subsession by the SCS.  Also test
+	the SCS correctly handles an invalid subsession handle.
+ */
+	{
+	test.Start(_L("TestSyncSubsessionFunction"));
+	
+	TInt x = -1;
+	TInt r = sTestSubsession.Quadruple(x);
+	test(r == KErrNone);
+	test(x == 4 * KSubsessValue);
+	
+	TestPanic(TestBadHandlePanic, ScsImpl::EScsClBadHandle);
+	
+	test.End();
+	}
+
+// -------- asynchronous subsession function --------
+
+static TInt LaunchSsTrebleOom()
+/**
+	Launch an asynchronous request on a subsession in OOM.
+
+	@see RunOomTest
+ */
+	{
+	TPckgBuf<TInt> x = 3;
+	TRequestStatus rs;
+	sTestSubsession.Treble(x, rs);
+	User::WaitForRequest(rs);
+	
+	if (rs == KErrNone)
+		{
+		test(x() == 9);
+		}
+	
+	return rs.Int();
+	}
+
+static void TestAsyncSubsessionFunction()
+/**
+	Test queueing and cancelling asynchronous requests on a subsession.
+ */
+	{
+	test.Start(_L("TestAsyncSubsessionFunction"));
+	
+	TPckgBuf<TInt> x = 7;
+	TRequestStatus rs;
+	sTestSubsession.Treble(x, rs);
+	User::WaitForRequest(rs);
+	test(rs == KErrNone);
+	test(x() == 21);
+	
+	// test launching async request in OOM
+	RunOomTest(LaunchSsTrebleOom, NULL);
+
+	// cancel async request
+	sTestSubsession.Treble(x, rs);
+	sTestSubsession.CancelTreble();
+	User::WaitForRequest(rs);
+	test(rs == KErrCancel);
+
+	// cancel when no outstanding request
+	sTestSubsession.CancelTreble();
+
+	test.End();
+	}
+
+// -------- leak subsession --------
+
+static void TestLeakSubsession()
+/**
+	Test closing a session with a remaining subsession;
+	ensure server does not leak memory.
+ */
+	{
+	test.Start(_L("TestLeakSubsession"));
+	
+	TInt r;
+	
+	sTestSession.SetServerHeapFail(KMaxTInt);
+	
+	RScsTestSession s;
+	r = s.Connect();
+	test(r == KErrNone);
+	
+	RScsTestSubsession ss;
+	r = ss.Create(s, KSubsessValue);
+	test(r == KErrNone);
+	
+	s.Close();
+	LetServerRun();			// 100ms, let server clean up
+	sTestSession.ResetServerHeapFail();
+	
+	test.End();
+	}
+
+// -------- correct async requests cancelled  --------
+
+static void TestCorrectAsyncCancelled()
+/**
+	Test the correct requests are cancelled.
+ */
+	{	
+	test.Start(_L("TestCorrectAsyncCancelled"));
+	
+	TInt r;
+	
+	RScsTestSession s1;
+	r = s1.Connect();
+	test(r == KErrNone);
+	
+	RScsTestSubsession ss1a;
+	r = ss1a.Create(s1, KSubsessValue);
+	test(r == KErrNone);
+	
+	RScsTestSubsession ss1b;
+	r = ss1b.Create(s1, KSubsessValue);
+	test(r == KErrNone);
+	
+	RScsTestSession s2;
+	r = s2.Connect();
+	test(r == KErrNone);
+	
+	RScsTestSubsession ss2a;
+	r = ss2a.Create(s2, KSubsessValue);
+	test(r == KErrNone);
+	
+	TRequestStatus r1, r1a, r1b, r2, r2a;
+	TPckgBuf<TInt> i1(10), i1a(20), i1b(30), i2(40), i2a(50);
+	
+	s1.Treble(i1, r1);
+	ss1a.Treble(i1a, r1a);
+	ss1b.Treble(i1b, r1b);
+	s2.Treble(i2, r2);
+	ss2a.Treble(i2a, r2a);
+	
+	test(r1 == KRequestPending);
+	test(r1a == KRequestPending);
+	test(r1b == KRequestPending);
+	test(r2 == KRequestPending);
+	test(r2a == KRequestPending);
+	
+	ss1a.CancelTreble();				// subsession doesn't affect parent or siblings
+	LetServerRun();
+	test(r1 == KRequestPending);
+	test(r1a == KErrCancel);
+	test(r1b == KRequestPending);
+	test(r2 == KRequestPending);
+	test(r2a == KRequestPending);
+	
+	s2.CancelTreble();					// session doesn't affect child
+	LetServerRun();
+	test(r1 == KRequestPending);
+	test(r1a == KErrCancel);
+	test(r1b == KRequestPending);
+	test(r2 == KErrCancel);
+	test(r2a == KRequestPending);
+	
+	ss2a.Close();						// close subsession cancels outstanding request
+	LetServerRun();
+	test(r1 == KRequestPending);
+	test(r1a == KErrCancel);
+	test(r1b == KRequestPending);
+	test(r2 == KErrCancel);
+	test(r2a == KErrCancel);
+	
+	// consume pending signals
+	User::WaitForRequest(r1);
+	User::WaitForRequest(r1a);
+	User::WaitForRequest(r1b);
+	User::WaitForRequest(r2);
+	User::WaitForRequest(r2a);
+	
+	test(r1 == KErrNone);
+	test(r1a == KErrCancel);
+	test(r1b == KErrNone);
+	test(r2 == KErrCancel);
+	test(r2a == KErrCancel);
+	
+	s1.Close();
+	s2.Close();
+	
+	test.End();
+	}
+
+// -------- entrypoint --------
+
+
+void MainL()
+	{
+	test.Title(_L("c:\\scstest.log"));
+	test.Start(_L(" @SYMTestCaseID:SEC-SCSTEST-0001 scstest "));
+
+	TestServerDeath();
+
+	TestOpenClose();
+	
+	TInt r = sTestSession.Connect();
+	test(r == KErrNone);
+	
+	TestInvalidSessionFunction();
+	TestSyncSessionFunction();
+	TestAsyncSessionFunction();
+	
+	TestOpenCloseSubsession();
+	
+	r = sTestSubsession.Create(sTestSession, KSubsessValue);
+	test(r == KErrNone);
+	
+	TestInvalidSubsessionFunction();
+	TestSyncSubsessionFunction();
+	TestAsyncSubsessionFunction();
+	TestLeakSubsession();
+	TestCorrectAsyncCancelled();
+	
+	sTestSubsession.Close();
+	sTestSession.ShutdownServer(); // Synchronous shutdown of server
+
+	test.End();
+	test.Close();
+	}
+
+void PanicIfError(TInt r)
+	{
+	if(r != KErrNone)
+		{
+		User::Panic(_L("upstest failed: "), r);
+		}
+	}
+
+
+TInt E32Main()
+/**
+	Executable entrypoint establishes connection with SCS test server
+	and then invokes tests for each functional area.
+ */
+	{
+	// disable lazy DLL unloading so kernel heap balances at end
+	RLoader l;
+	PanicIfError(l.Connect());
+	PanicIfError(l.CancelLazyDllUnload());
+	l.Close();
+
+	(void)test.Console();
+	
+	__UHEAP_MARK;
+	__KHEAP_MARK;
+	
+	// allocating a cleanup stack also installs it
+	CTrapCleanup* tc = CTrapCleanup::New();
+	if (tc == 0)
+		return KErrNoMemory;
+
+	TRAPD(err, MainL());
+	PanicIfError(err);
+
+	
+	delete tc;
+	
+	// The kernel appears to leave some memory allocated related to
+	// econs.dll (maybe some sort of internal cache), which is
+	// indirectly used by the test code, so we need to ignore this
+	// allocation to allow our test to pass...
+	User::__DbgMarkEnd(TRUE,1);
+	__UHEAP_MARKEND;
+	
+	
+	return KErrNone;
+	}
+
+
+// End of file