kerneltest/e32test/device/t_newldd.cpp
changeset 0 a41df078684a
child 285 ff5437e4337c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/device/t_newldd.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,352 @@
+// Copyright (c) 2008-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:
+//
+
+#define __E32TEST_EXTENSION__
+#include <e32test.h>
+#include <e32def.h>
+#include <e32def_private.h>
+#include "t_newldd.h"
+#include "t_new_classes.h"
+
+RTest test(_L("Testing Operator New"));
+
+TInt RNewLddTest::DoControl(TInt aFunction)
+	{
+	return RBusLogicalChannel::DoControl(aFunction);
+	}
+
+TInt RNewLddTest::Open()
+	{
+	return DoCreate(KLddName,TVersion(0,1,1),KNullUnit,NULL,NULL);
+	}
+
+RNewLddTest lddconn;
+
+TInt TestNew()
+	{
+	return lddconn.DoControl(RNewLddTest::ENew);
+	}
+TInt TestPlacementVectorNew()
+	{
+	return lddconn.DoControl(RNewLddTest::EPlacementVectorNew);
+	}
+TInt TestVectorNew()
+	{
+	return lddconn.DoControl(RNewLddTest::EVectorNew);
+	}
+TInt TestPlacementNew()
+	{
+	return lddconn.DoControl(RNewLddTest::EPlacementNew);
+	}
+
+void UserSideTestNewOOM()
+	{
+	RDebug::Printf("User-Side: operator new OOM");
+	//OOM tests: should not throw
+	
+	#define TEST_NEW_OOM(CLASS) \
+	RDebug::Printf("new " #CLASS);\
+		{\
+		CLASS* p##CLASS = new CLASS;\
+		test_Equal(NULL, p##CLASS);\
+		}
+
+	TEST_NEW_OOM(XVeryLargeClassCtorAndDtor);
+	TEST_NEW_OOM(XVeryLargeClassCtorOnly);
+	TEST_NEW_OOM(XVeryLargeClassDtorOnly);
+	TEST_NEW_OOM(XVeryLargeClassNoTors);
+	}
+
+void UserSideTestNewConstruction()
+	{
+	RDebug::Printf("User-Side: operator new non-OOM");
+	//Non-OOM:
+	
+
+	#define TEST_NEW_CONSTRUCTION(CLASS) \
+	RDebug::Printf("new " #CLASS);\
+		{\
+		CLASS* p##CLASS = new CLASS;\
+		test_NotNull(p##CLASS);\
+		test_Equal(EConstructed, (p##CLASS)->iState);\
+		delete p##CLASS;\
+		}
+
+	TEST_NEW_CONSTRUCTION(XCtorAndDtor)
+	TEST_NEW_CONSTRUCTION(XCtorOnly)
+
+
+	#define TEST_NEW(CLASS) \
+	RDebug::Printf("new " #CLASS);\
+		{\
+		CLASS* p##CLASS = new CLASS;\
+		test_NotNull(p##CLASS);\
+		delete p##CLASS;\
+		}
+	TEST_NEW(XDtorOnly)
+	TEST_NEW(XNoTors)
+	}
+	
+void UserSideTestNew()
+	{
+	UserSideTestNewOOM();
+	UserSideTestNewConstruction();
+	}
+
+void TrappedUserSideTestNew()
+	{
+	RDebug::Printf("TRAPPED User-Side: operator new");
+	//OOM tests: should not throw
+
+	#define TEST_NEW_ELEAVE_OOM(CLASS) \
+	RDebug::Printf("new(ELeave) " #CLASS);\
+		{\
+		TRAPD(r, new(ELeave) (CLASS));\
+		test_Equal(KErrNoMemory, r);\
+		}
+
+	TEST_NEW_ELEAVE_OOM(XVeryLargeClassCtorAndDtor);
+	TEST_NEW_ELEAVE_OOM(XVeryLargeClassCtorOnly);
+	TEST_NEW_ELEAVE_OOM(XVeryLargeClassDtorOnly);
+	TEST_NEW_ELEAVE_OOM(XVeryLargeClassNoTors);
+
+
+
+	RDebug::Printf("User-Side: operator new non-OOM");
+	//Non-OOM:
+
+	#define TEST_NEW_ELEAVE(CLASS, TEST_CTOR ) \
+	RDebug::Printf("new(ELeave) " #CLASS);\
+		{\
+		CLASS* p##CLASS=NULL;\
+		TRAPD(r, p##CLASS = new(ELeave) (CLASS));\
+		test_KErrNone(r);\
+		volatile TBool testCtor=(TEST_CTOR);\
+		if(testCtor)\
+			{\
+			test_Equal(EConstructed, (p##CLASS)->iState);\
+			}\
+		delete p##CLASS;\
+		}
+
+	TEST_NEW_ELEAVE(XCtorAndDtor, ETrue);
+	TEST_NEW_ELEAVE(XCtorOnly, ETrue);
+	TEST_NEW_ELEAVE(XDtorOnly, EFalse);
+	TEST_NEW_ELEAVE(XNoTors, EFalse);
+	}
+
+
+#define TEST_ARRAY_CONSTRUCTION(ARRAY, LENGTH)\
+	{\
+	for(TInt i=0; i<(LENGTH); ++i)\
+		{\
+		test_Equal(EConstructed, ARRAY[i].iState);\
+		}\
+	}
+
+void UserSideTestVectorNew()
+	{
+	RDebug::Printf("User-Side:vector operator new");
+	RDebug::Printf("OOM tests");
+
+	#define TEST_VEC_NEW_OOM(CLASS) \
+	RDebug::Printf("new " #CLASS "[%d]", KOOMArraySize );\
+		{\
+		CLASS* p##CLASS = new CLASS[KOOMArraySize];\
+		test_Equal(NULL, p##CLASS);\
+		}
+
+	TEST_VEC_NEW_OOM(XCtorAndDtor);
+	TEST_VEC_NEW_OOM(XCtorOnly);
+	TEST_VEC_NEW_OOM(XDtorOnly);
+	TEST_VEC_NEW_OOM(XNoTors);
+	
+	RDebug::Printf("non-OOM tests");
+
+	#define TEST_VEC_NEW(CLASS, ARRAY_LENGTH, TEST_CTOR) \
+	RDebug::Printf("new " #CLASS "[%d]", ARRAY_LENGTH);\
+		{\
+		CLASS* p##CLASS = new CLASS[(ARRAY_LENGTH)];\
+		test_NotNull(p##CLASS);\
+		volatile TBool testCtor=(TEST_CTOR);\
+		if(testCtor)\
+			{\
+			TEST_ARRAY_CONSTRUCTION(p##CLASS, ARRAY_LENGTH);\
+			}\
+		delete[] p##CLASS;\
+		}
+
+	TEST_VEC_NEW(XCtorAndDtor, KTestArrayLength, ETrue);
+	TEST_VEC_NEW(XCtorOnly, KTestArrayLength, ETrue);
+	TEST_VEC_NEW(XDtorOnly, KTestArrayLength, EFalse);
+	TEST_VEC_NEW(XNoTors, KTestArrayLength, EFalse);
+	}
+
+void TrappedUserSideTestVectorNew()
+	{
+	RDebug::Printf("User-Side:vector operator new");
+	RDebug::Printf("OOM tests");
+
+	#define TEST_VEC_NEW_ELEAVE_OOM(CLASS) \
+	RDebug::Printf("new(ELeave) " #CLASS "[%d]", KOOMArraySize );\
+		{\
+	   	TRAPD(r, new(ELeave) CLASS[KOOMArraySize];)\
+		test_Equal(KErrNoMemory, r);\
+		}
+
+	TEST_VEC_NEW_ELEAVE_OOM(XCtorAndDtor);
+	TEST_VEC_NEW_ELEAVE_OOM(XCtorOnly);
+	TEST_VEC_NEW_ELEAVE_OOM(XDtorOnly);
+	TEST_VEC_NEW_ELEAVE_OOM(XNoTors);
+
+
+
+	RDebug::Printf("non-OOM tests");
+	#define TEST_VEC_NEW_ELEAVE(CLASS, ARRAY_LENGTH, TEST_CTOR) \
+	RDebug::Printf("new(ELeave) " #CLASS "[%d]", ARRAY_LENGTH);\
+		{\
+		CLASS* p##CLASS = NULL;\
+		TRAPD(r, p##CLASS = new(ELeave) CLASS[(ARRAY_LENGTH)]);\
+		test_KErrNone(r);\
+		TBool testCtor=(TEST_CTOR);\
+		if(testCtor)\
+			{\
+			TEST_ARRAY_CONSTRUCTION(p##CLASS, ARRAY_LENGTH);\
+			}\
+		delete[] p##CLASS;\
+		}
+
+	TEST_VEC_NEW_ELEAVE(XCtorAndDtor, KTestArrayLength, ETrue);
+	TEST_VEC_NEW_ELEAVE(XCtorOnly, KTestArrayLength, ETrue);
+	TEST_VEC_NEW_ELEAVE(XDtorOnly, KTestArrayLength, EFalse);
+	TEST_VEC_NEW_ELEAVE(XNoTors, KTestArrayLength, EFalse);
+	}
+
+void UserSideTestPlacementNew()
+	{
+	RDebug::Printf("::UserSideTestPlacementNew");
+	
+	#define TEST_PLACMENT_NEW(CLASS, POST_CTOR_STATE, POST_DTOR_STATE)\
+		{\
+		void* someram = User::AllocZ(sizeof(CLASS));\
+		test_NotNull(someram);\
+		RDebug::Printf("new (someram) " #CLASS);\
+		CLASS* p##CLASS = new (someram) CLASS;\
+		test_Equal(someram, p##CLASS);\
+		test_Equal(POST_CTOR_STATE, p##CLASS->iState);\
+		p##CLASS->~CLASS();\
+		test_Equal(POST_DTOR_STATE, p##CLASS->iState);\
+		User::Free(someram);\
+		p##CLASS=NULL;\
+		}\
+
+	TEST_PLACMENT_NEW(XCtorAndDtor, EConstructed, EDeconstructed);
+	TEST_PLACMENT_NEW(XCtorOnly, EConstructed, EConstructed);
+	TEST_PLACMENT_NEW(XDtorOnly, ENull, EDeconstructed);
+	TEST_PLACMENT_NEW(XNoTors, ENull, ENull);
+	}
+
+
+void UserSideTestPlacementVectorNew()
+	{
+	__UHEAP_MARK;
+
+	RDebug::Printf("::UserSideTestPlacementVectorNew");
+
+	#define TEST_VEC_PLACEMENT_NEW(CLASS, ARRAY_LENGTH, POST_CTOR_STATE, POST_DTOR_STATE)\
+	RDebug::Printf("new(someram) " #CLASS "[%d]", ARRAY_LENGTH);\
+		{\
+		void* someram = User::AllocZ(sizeof(CLASS) * ARRAY_LENGTH);\
+		test_NotNull(someram);\
+		CLASS* p##CLASS = new (someram) CLASS[(ARRAY_LENGTH)];\
+		for(TInt i=0; i<(ARRAY_LENGTH); ++i)\
+			{\
+			test_Equal(POST_CTOR_STATE, p##CLASS[i].iState);\
+			p##CLASS[i].~CLASS();\
+			test_Equal(POST_DTOR_STATE, p##CLASS[i].iState);\
+			}\
+		User::Free(someram);\
+		}
+
+	TEST_VEC_PLACEMENT_NEW(XCtorAndDtor, KTestArrayLength, EConstructed, EDeconstructed);
+	TEST_VEC_PLACEMENT_NEW(XCtorOnly, KTestArrayLength, EConstructed, EConstructed);
+	TEST_VEC_PLACEMENT_NEW(XDtorOnly, KTestArrayLength, ENull, EDeconstructed);
+	TEST_VEC_PLACEMENT_NEW(XNoTors, KTestArrayLength, ENull, ENull);
+
+	__UHEAP_MARKEND;
+	}
+
+
+TInt E32Main()
+	{
+	__UHEAP_MARK;
+
+	test.Start(_L("Testing operator new"));
+	
+	test.Next(_L("Installing LDD"));
+	TInt r=User::LoadLogicalDevice(KKInstallLddName);
+	test(r==KErrNone || r==KErrAlreadyExists);
+	
+	__KHEAP_MARK;
+
+	#define TEST_THIS(X) test.Next(_L(#X)); (X)
+	
+	TEST_THIS(UserSideTestNew());
+	TEST_THIS(UserSideTestPlacementNew());
+
+// Workaround for bug in MSVC6/CW compilers. The following test case fails on
+// WINS, WINSCW and X86 targets (not X86GCC), where the placement vector new
+// operator does not behave as expected, ultimately resulting in heap corruption
+// when the parameter to placement array new is passed on the stack.
+#if !(defined(__WINS__) || (defined(__VC32__) && (_MSC_VER < 1300)))
+	TEST_THIS(UserSideTestPlacementVectorNew());
+#else
+	test.Next(_L("Emulator and/or VC32 - Skipped: UserSideTestPlacementVectorNew"));
+#endif
+
+	TEST_THIS(UserSideTestVectorNew());
+	TEST_THIS(TrappedUserSideTestNew());
+	TEST_THIS(TrappedUserSideTestVectorNew());
+	
+	r=lddconn.Open();
+	test_KErrNone(r);
+
+	test.Next(_L("Kernel-side:Normal operator new"));
+	r = TestNew();
+	test_KErrNone(r);
+		
+	test.Next(_L("Kernel-side:Placement operator new"));
+	r = TestPlacementNew();
+	test_KErrNone(r);
+
+	test.Next(_L("Kernel-side:Placement Vector operator new"));
+	r = TestPlacementVectorNew();
+	test_KErrNone(r);
+
+	test.Next(_L("Kernel-side:Vector operator new"));
+	r = TestVectorNew();
+	test_KErrNone(r);
+
+	r = RTest::CloseHandleAndWaitForDestruction(lddconn);
+	test_KErrNone(r);
+
+	test.End();
+	test.Close();
+
+	__KHEAP_MARKEND;
+	__UHEAP_MARKEND;
+	return KErrNone;
+	}
+