--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/system/t_cobj.cpp Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,1185 @@
+// 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 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:
+// e32test\system\t_cobj.cpp
+// Overview:
+// Test CObject, CObjectIx, CObjectCon, CObjectConIx classes
+// API Information:
+// CObject, CObjectIx, CObjectCon, CObjectConIx
+// Details:
+// - Test the CObjectIx class by adding and removing CObject objects
+// in the same order, in reverse order and in random order.
+// - Test adding many CObject objects to a CObjectConIx and test that
+// the returned handle is as expected.
+// - Perform a speed test on CObjectCon for both named and unnamed
+// objects.
+// - Check that the CObject, CObjectCon, CObjectIx and CObjectConIx methods
+// are in the DLL by calling each one.
+// - Test the CObject, CObjectCon, CObjectIx and CObjectConIx methods and
+// verify the results are as expected.
+// - Test all the objects together: create two containers, find objects by
+// name in a variety of ways, delete objects and verify the results are
+// as expected.
+// Platforms/Drives/Compatibility:
+// All.
+// Assumptions/Requirement/Pre-requisites:
+// Failures and causes:
+// Base Port information:
+//
+//
+
+#include <e32std.h>
+#include <e32std_private.h>
+#include <e32base.h>
+#include <e32base_private.h>
+#include <e32test.h>
+#include <e32svr.h>
+#include <e32ver.h>
+#include "../misc/prbs.h"
+
+struct TCObjectDump
+ {
+ TInt iAccessCount;
+ CObject* iOwner;
+ CObjectCon* iContainer;
+ HBufC* iName;
+ };
+
+void CObject::__DbgTest(void* pCObjectDump) const
+ {
+ ((TCObjectDump*)pCObjectDump)->iAccessCount=iAccessCount;
+ ((TCObjectDump*)pCObjectDump)->iOwner=iOwner;
+ ((TCObjectDump*)pCObjectDump)->iContainer=iContainer;
+ ((TCObjectDump*)pCObjectDump)->iName=iName;
+ }
+
+LOCAL_D RTest test(_L("T_COBJ"));
+LOCAL_D TName gName;
+LOCAL_D TName gName1;
+LOCAL_D TName gName2;
+LOCAL_D TFullName gFullName;
+LOCAL_D TFullName gFullName1;
+LOCAL_D TFullName gFullName2;
+
+class RTestHeap : public RAllocator
+ {
+public:
+ enum TOp {EOpNone=0, EOpAlloc=1, EOpFree=2, EOpReAlloc=3};
+
+ struct TOpInfo
+ {
+ TInt iOp;
+ TAny* iPtrArg;
+ TInt iIntArg;
+ TAny* iResult;
+ };
+public:
+ static RTestHeap* Install();
+ void Uninstall();
+ TInt GetLastOp(TOpInfo& aInfo);
+ virtual TAny* Alloc(TInt aSize);
+ virtual void Free(TAny* aPtr);
+ virtual TAny* ReAlloc(TAny* aPtr, TInt aSize, TInt aMode);
+ virtual TInt AllocLen(const TAny* aCell) const;
+ virtual TInt Compress();
+ virtual void Reset();
+ virtual TInt AllocSize(TInt& aTotalAllocSize) const;
+ virtual TInt Available(TInt& aBiggestBlock) const;
+ virtual TInt DebugFunction(TInt aFunc, TAny* a1, TAny* a2);
+public:
+ RAllocator* iA;
+ TOpInfo iLastOp;
+ };
+
+RTestHeap* RTestHeap::Install()
+ {
+ RTestHeap* p = new RTestHeap;
+ test(p!=0);
+ p->iA = &User::Heap();
+ p->iLastOp.iOp = EOpNone;
+ User::SwitchHeap(p);
+ return p;
+ }
+
+void RTestHeap::Uninstall()
+ {
+ User::SwitchHeap(iA);
+ delete this;
+ }
+
+TInt RTestHeap::GetLastOp(RTestHeap::TOpInfo& aInfo)
+ {
+ memcpy(&aInfo, &iLastOp, sizeof(TOpInfo));
+ iLastOp.iOp = EOpNone;
+ return (aInfo.iOp == EOpNone) ? KErrNotFound : KErrNone;
+ }
+
+TAny* RTestHeap::Alloc(TInt aSize)
+ {
+ TAny* p = iA->Alloc(aSize);
+ iLastOp.iOp = EOpAlloc;
+ iLastOp.iPtrArg = 0;
+ iLastOp.iIntArg = aSize;
+ iLastOp.iResult = p;
+ return p;
+ }
+
+void RTestHeap::Free(TAny* aPtr)
+ {
+ iLastOp.iOp = EOpFree;
+ iLastOp.iPtrArg = aPtr;
+ iLastOp.iIntArg = 0;
+ iLastOp.iResult = 0;
+ iA->Free(aPtr);
+ }
+
+TAny* RTestHeap::ReAlloc(TAny* aPtr, TInt aSize, TInt aMode=0)
+ {
+ TAny* p = iA->ReAlloc(aPtr,aSize,aMode);
+ iLastOp.iOp = EOpReAlloc;
+ iLastOp.iPtrArg = aPtr;
+ iLastOp.iIntArg = aSize;
+ iLastOp.iResult = p;
+ return p;
+ }
+
+TInt RTestHeap::AllocLen(const TAny* aCell) const
+ {
+ TInt l = iA->AllocLen(aCell);
+ return l;
+ }
+
+TInt RTestHeap::Compress()
+ {
+ TInt l = iA->Compress();
+ return l;
+ }
+
+void RTestHeap::Reset()
+ {
+ iA->Reset();
+ }
+
+TInt RTestHeap::AllocSize(TInt& aTotalAllocSize) const
+ {
+ TInt s;
+ TInt r = iA->AllocSize(s);
+ aTotalAllocSize = s;
+ return r;
+ }
+
+TInt RTestHeap::Available(TInt& aBiggestBlock) const
+ {
+ TInt s;
+ TInt r = iA->Available(s);
+ aBiggestBlock = s;
+ return r;
+ }
+
+TInt RTestHeap::DebugFunction(TInt aFunc, TAny* a1=NULL, TAny* a2=NULL)
+ {
+ TInt r = iA->DebugFunction(aFunc, a1, a2);
+ return r;
+ }
+
+
+
+
+class TestCObjects
+ {
+public:
+ void Test1(void);
+ void Test2(void);
+ void Test3(void);
+ void Test4(void);
+ void Test5(void);
+ void Test6(void);
+ void Test7(void);
+ void Test8(void);
+private:
+ static void GetObjName(TName& aDest,const CObject& aObj);
+ static void GetObjFullName(TFullName& aDest,const CObject& aObj);
+ };
+
+
+GLDEF_C void TestCObjects::Test1(void)
+ {
+ // Check CObject methods are in the DLL
+ CObject* pCObject=new CObject;
+ CObject* temp=new CObject;
+
+ pCObject->Open();
+ pCObject->Close();
+ gName=pCObject->Name();
+ TPtrC aDesR(_S("a name"));
+ pCObject->SetName(&aDesR);
+ pCObject->SetNameL(&aDesR);
+ gFullName=pCObject->FullName();
+ pCObject->Owner();
+ pCObject->SetOwner(temp);
+ pCObject->Close(); // deletes object when iAccessCount==0
+ temp->Close();
+ }
+
+GLDEF_C void TestCObjects::Test2(void)
+ {
+ // Check CObjectCon methods are in the DLL
+ CObjectCon* pCObjectCon=CObjectCon::NewL();
+ CObject* pCObject=new CObject;
+ TInt aFindHandle=0;
+
+ pCObjectCon->AddL(pCObject);
+ pCObjectCon->At(aFindHandle);
+ User::ValidateName(_L("a name"));
+ pCObjectCon->CheckUniqueFullName(pCObject, _L("a name"));
+ pCObjectCon->FindByName(aFindHandle, _L("a name"), gName);
+ pCObjectCon->FindByFullName(aFindHandle, _L("a Name"), gFullName);
+ pCObjectCon->UniqueID();
+ pCObjectCon->Count();
+ pCObjectCon->Remove(pCObject);
+ pCObject->Close();
+ delete pCObjectCon;
+ }
+
+GLDEF_C void TestCObjects::Test3(void)
+ {
+ // Check the CObjectIx methods are in the DLL
+ CObjectIx* pCObjectIx=CObjectIx::NewL();
+ pCObjectIx->Count();
+ test(pCObjectIx->At(0)==NULL);
+ delete pCObjectIx;
+ pCObjectIx=CObjectIx::NewL();
+ test(pCObjectIx->Count()==0);
+ CObjectConIx* pCObjectConIx=CObjectConIx::NewL();
+ delete pCObjectConIx;
+ pCObjectConIx=CObjectConIx::NewL();
+ CObjectCon* pCObjectCon=pCObjectConIx->CreateL();
+ test(pCObjectCon->Count()==0);
+ CObject* pCObject= new CObject;
+ test(pCObject!=NULL);
+
+ TInt find;
+ TName name;
+ TInt r=pCObjectCon->FindByName(find,_L("Name"),name);
+ test(r==KErrNotFound);
+ TFullName fullName;
+ r=pCObjectCon->FindByFullName(find,_L("Full Name"),fullName);
+ test(r==KErrNotFound);
+
+
+ pCObjectCon->AddL(pCObject);
+ test(pCObjectCon->Count()==1);
+ test(pCObjectIx->Count(pCObject)==0);
+ pCObjectIx->AddL(pCObject);
+ test(pCObjectIx->Count(pCObject)==1);
+ pCObjectIx->Count();
+ pCObjectIx->At(0, 0);
+ pCObjectIx->At(0);
+// pCObjectIx->Remove(0);
+ delete pCObjectIx;
+ delete pCObjectConIx;
+// delete pCObjectCon;
+// pCObject->Close();
+ }
+
+GLDEF_C void TestCObjects::Test4(void)
+ {
+ // Check CObjectConIx methods are in the DLL
+ CObjectConIx* pCObjectConIx=CObjectConIx::NewL();
+ CObjectCon* pCObjectCon=pCObjectConIx->CreateL();
+ pCObjectConIx->Lookup(0);
+ pCObjectConIx->Remove(pCObjectCon);
+ delete pCObjectConIx;
+ }
+
+GLDEF_C void TestCObjects::Test5(void)
+ {
+ // Test the methods of the CObject class
+ TCObjectDump CObjectDump;
+ CObject* a=new CObject;
+ CObject* b=new CObject;
+ a->__DbgTest(&CObjectDump);
+ test(CObjectDump.iAccessCount==1 && CObjectDump.iOwner==NULL && CObjectDump.iContainer==NULL);
+ a->Open();
+ a->__DbgTest(&CObjectDump);
+ test(CObjectDump.iAccessCount==2);
+ a->Close();
+ a->__DbgTest(&CObjectDump);
+ test(CObjectDump.iAccessCount==1);
+ TPtrC aDesR(_L("aName"));
+ a->SetName(&aDesR);
+ gName=a->Name();
+ test(gName==_L("aName"));
+ gFullName=a->FullName();
+ test(gFullName==_L("aName"));
+ TPtrC aDesR2(_L("Owner"));
+ b->SetName(&aDesR2);
+ a->SetOwner(b);
+ test(a->Owner()==b);
+ gFullName=a->FullName();
+ test(gFullName==_L("Owner::aName"));
+ a->Close(); // Calls the destructor via the call to delete
+// To Do: set iContainer to something then call Close()
+ }
+
+
+GLDEF_C void TestCObjects::Test6(void)
+ {
+ // Test the methods of CObjectCon
+ TCObjectDump dump1, dump2;
+ TInt aFindHandle=0;
+ CObject *pObj1=new CObject,
+ *pObj2=new CObject,
+ *pObj3=new CObject,
+ *temp;
+ CObjectCon* pCon=CObjectCon::NewL();
+
+ test(User::ValidateName(_L("xxx*xxx"))==KErrBadName);
+ test(User::ValidateName(_L("xxx?xxx"))==KErrBadName);
+ test(User::ValidateName(_L("xxx:xxx"))==KErrBadName);
+ test(User::ValidateName(_L("xxxxxxx"))==KErrNone);
+
+ TPtrC name1(_S("Obj1")), name2(_S("Obj2")), name3(_S("Owner"));
+ pObj1->SetName(&name1);
+ pObj2->SetName(&name2);
+ pObj3->SetName(&name3);
+
+ test(pCon->Count()==0);
+ pCon->AddL(pObj1);
+ test(pCon->Count()==1);
+ pCon->AddL(pObj2);
+ test(pCon->Count()==2);
+
+ aFindHandle=0;
+ test(pCon->FindByName(aFindHandle, _L("xxx"), gName)==KErrNotFound);
+ aFindHandle=0;
+ GetObjName(gName1,*pObj1);
+ test(pCon->FindByName(aFindHandle, gName1, gName)==KErrNone);
+ test(aFindHandle==0);
+ aFindHandle=2;
+ GetObjName(gName1,*pObj1);
+ test(pCon->FindByName(aFindHandle, gName1, gName)==KErrNotFound);
+ aFindHandle=0;
+ GetObjName(gName1,*pObj2);
+ test(pCon->FindByName(aFindHandle, gName1, gName)==KErrNone);
+ test(aFindHandle==1);
+
+ aFindHandle=0;
+ test(pCon->FindByFullName(aFindHandle, _L("xxx"), gFullName)==KErrNotFound);
+ aFindHandle=0;
+ GetObjName(gName1,*pObj1);
+ test(pCon->FindByFullName(aFindHandle, gName1, gFullName)==KErrNone);
+ test(aFindHandle==0);
+ GetObjName(gName1,*pObj2);
+ test(pCon->FindByFullName(aFindHandle, gName1, gFullName)==KErrNone);
+ test(aFindHandle==1);
+
+ pObj1->SetOwner(pObj3);
+ pObj2->SetOwner(pObj3);
+ aFindHandle=0;
+ test(pCon->FindByFullName(aFindHandle, _L("xxx"), gFullName)==KErrNotFound);
+ aFindHandle=0;
+ GetObjFullName(gFullName1,*pObj1);
+ test(pCon->FindByFullName(aFindHandle, gFullName1, gFullName)==KErrNone);
+ test(aFindHandle==0);
+ GetObjFullName(gFullName1,*pObj2);
+ test(pCon->FindByFullName(aFindHandle, gFullName1, gFullName)==KErrNone);
+ test(aFindHandle==1);
+
+
+ test(pCon->CheckUniqueFullName(pObj3, _L("aname"))==KErrNone);
+ GetObjName(gName1,*pObj1);
+ test(pCon->CheckUniqueFullName(pObj3, gName1)==KErrAlreadyExists);
+ pCon->Remove(pObj1);
+ test(pCon->CheckUniqueFullName(pObj3, gName1)==KErrNone);
+ test(pCon->Count()==1);
+ pCon->AddL(pObj3);
+ test(pCon->Count()==2);
+ aFindHandle=0;
+ test(pCon->FindByName(aFindHandle, gName1, gName)==KErrNotFound);
+ aFindHandle=0;
+ GetObjFullName(gFullName1,*pObj1);
+ test(pCon->FindByFullName(aFindHandle, gFullName1, gFullName)==KErrNotFound);
+ aFindHandle=0;
+ GetObjName(gName1,*pObj2);
+ test(pCon->FindByName(aFindHandle, gName1, gName)==KErrNone);
+ test(aFindHandle==0);
+ GetObjFullName(gFullName1,*pObj2);
+ test(pCon->FindByFullName(aFindHandle, gFullName1, gFullName)==KErrNone);
+ test(aFindHandle==0);
+ GetObjName(gName1,*pObj3);
+ test(pCon->FindByName(aFindHandle, gName1, gName)==KErrNone);
+ test(aFindHandle==1);
+ aFindHandle=0;
+ test(pCon->FindByFullName(aFindHandle, _L("Owner"), gFullName)==KErrNone);
+ test(aFindHandle==1);
+
+
+ pObj2->__DbgTest(&dump1);
+ temp=pCon->At(0);
+ temp->__DbgTest(&dump2);
+ test(dump1.iAccessCount==dump2.iAccessCount && dump1.iOwner==dump2.iOwner &&
+ dump1.iName==dump2.iName &&dump1.iContainer==dump2.iContainer);
+ pObj3->__DbgTest(&dump1);
+ temp=pCon->At(1);
+ temp->__DbgTest(&dump2);
+ test(dump1.iAccessCount==dump2.iAccessCount && dump1.iOwner==dump2.iOwner &&
+ dump1.iName==dump2.iName &&dump1.iContainer==dump2.iContainer);
+
+ pCon->Remove(pObj2);
+ pCon->Remove(pObj3);
+ test(pCon->Count()==0);
+ delete pCon;
+
+ // Test expansion and shrinking
+ __UHEAP_MARK;
+ pCon=CObjectCon::NewL();
+ CObject** obj = new CObject*[2048];
+ test(obj!=0);
+ TInt i;
+ for (i=0; i<2048; ++i)
+ {
+ obj[i] = new CObject;
+ test(obj[i] != 0);
+ }
+
+ RTestHeap* h = RTestHeap::Install();
+
+ const TInt xov_values[] = {0,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048};
+ const TInt xov2_values[] = {1472, 960, 704, 448, 320, 192, 128, 96, 64, 48, 32, 24, 16, 12, 8, 6, 0};
+ const TInt* xov_ptr = xov_values;
+ const TInt* xov2_ptr = xov2_values;
+ TInt sz = 0;
+ TInt xov = 0;
+ TAny* ptr = 0;
+ for (i=1; i<=2048; ++i)
+ {
+ pCon->AddL(obj[i-1]);
+ test(pCon->Count()==i);
+ RTestHeap::TOpInfo opi;
+ TInt r = h->GetLastOp(opi);
+ if (i*4 <= sz)
+ {
+ test(r==KErrNotFound);
+ continue;
+ }
+ test(r==KErrNone);
+ test.Printf(_L("Realloc at %d -> %d\n"), i, opi.iIntArg);
+ test(i-1 == xov);
+ test(opi.iOp == RTestHeap::EOpReAlloc);
+ test(opi.iPtrArg == ptr);
+ // recalc xov
+ xov = *++xov_ptr;
+ test(opi.iIntArg == xov*4);
+ sz = xov*4;
+ test(opi.iResult != 0);
+ ptr = opi.iResult;
+ }
+
+ xov = *xov2_ptr;
+ for (i=2047; i>=0; --i)
+ {
+ pCon->Remove(obj[i]);
+ test(pCon->Count()==i);
+ RTestHeap::TOpInfo opi;
+ TInt r = h->GetLastOp(opi);
+ if (i>xov)
+ {
+ test(r==KErrNotFound);
+ continue;
+ }
+ test(r==KErrNone);
+ test.Printf(_L("Realloc at %d -> %d\n"), i, opi.iIntArg);
+ test(i == xov);
+ if (i==0)
+ {
+ test(opi.iOp == RTestHeap::EOpReAlloc || opi.iOp == RTestHeap::EOpFree);
+ }
+ else
+ {
+ test(opi.iOp = RTestHeap::EOpReAlloc);
+ test(opi.iResult == ptr);
+ }
+ test(opi.iPtrArg == ptr);
+ // recalc xov
+ xov = *++xov2_ptr;
+ sz = *--xov_ptr;
+ test(opi.iIntArg == sz*4);
+ }
+
+ delete pCon;
+ for (i=0; i<2048; ++i)
+ obj[i]->Close();
+ delete[] obj;
+ h->Uninstall();
+ __UHEAP_MARKEND;
+ }
+
+
+GLDEF_C void TestCObjects::Test7(void)
+ {
+ // Test the methods of CObjectIx
+
+ // Before an object can be added to a ConIx it first has to be added to a container because the
+ // CObjectIx::Add method references theObject->iContainer->iName. But theObject->iContainer field
+ // is only set (within the CObjectCon::Add method) IF the container has first been created by the
+ // CObjectConIx::Create method, otherwise it is NULL and adding it to a CObjectIx will fail.
+ CObjectIx *pIx=CObjectIx::NewL();
+ CObjectConIx *pConIx=CObjectConIx::NewL();
+ CObjectCon *pCon1=pConIx->CreateL(),
+ *pCon2=pConIx->CreateL();
+ CObject *pObj1=new CObject,
+ *pObj2=new CObject,
+ *pObj3=new CObject,
+ *temp;
+ TInt aHandle1, aHandle2, aHandle3;
+ TCObjectDump dump1, dump2;
+ TPtrC name1(_S("Obj1")), name2(_S("Obj2")), name3(_S("Obj3"));
+
+ // Create two containers with Obj1 and Obj2 in the first and Obj3 in the second
+ pObj1->SetName(&name1);
+ pObj2->SetName(&name2);
+ pObj3->SetName(&name3);
+ pCon1->AddL(pObj1);
+ pCon1->AddL(pObj2);
+ pCon2->AddL(pObj3);
+ aHandle1=pIx->AddL(pObj1);
+ aHandle2=pIx->AddL(pObj2);
+ aHandle3=pIx->AddL(pObj3);
+ // At(TInt aHandle)
+ pObj1->__DbgTest(&dump1);
+ temp=pIx->At(aHandle1);
+ temp->__DbgTest(&dump2);
+ test(dump1.iAccessCount==dump2.iAccessCount && dump1.iOwner==dump2.iOwner &&
+ dump1.iContainer==dump2.iContainer && dump1.iName==dump2.iName);
+ pObj2->__DbgTest(&dump1);
+ temp=pIx->At(aHandle2);
+ temp->__DbgTest(&dump2);
+ test(dump1.iAccessCount==dump2.iAccessCount && dump1.iOwner==dump2.iOwner &&
+ dump1.iContainer==dump2.iContainer && dump1.iName==dump2.iName);
+ pObj3->__DbgTest(&dump1);
+ temp=pIx->At(aHandle3);
+ temp->__DbgTest(&dump2);
+ test(dump1.iAccessCount==dump2.iAccessCount && dump1.iOwner==dump2.iOwner &&
+ dump1.iContainer==dump2.iContainer && dump1.iName==dump2.iName);
+ // At(TInt aHandle, TInt aUniqueID);
+ pObj1->__DbgTest(&dump1);
+ temp=pIx->At(aHandle1, 1);
+ temp->__DbgTest(&dump2);
+ test(dump1.iAccessCount==dump2.iAccessCount && dump1.iOwner==dump2.iOwner &&
+ dump1.iContainer==dump2.iContainer && dump1.iName==dump2.iName);
+ pObj2->__DbgTest(&dump1);
+ temp=pIx->At(aHandle2, 1);
+ temp->__DbgTest(&dump2);
+ test(dump1.iAccessCount==dump2.iAccessCount && dump1.iOwner==dump2.iOwner &&
+ dump1.iContainer==dump2.iContainer && dump1.iName==dump2.iName);
+ pObj3->__DbgTest(&dump1);
+ temp=pIx->At(aHandle3, 2);
+ temp->__DbgTest(&dump2);
+ test(dump1.iAccessCount==dump2.iAccessCount && dump1.iOwner==dump2.iOwner &&
+ dump1.iContainer==dump2.iContainer && dump1.iName==dump2.iName);
+ // Remove(Tint aHandle)
+ pIx->Remove(aHandle2);
+ pObj1->__DbgTest(&dump1);
+ temp=pIx->At(aHandle1);
+ temp->__DbgTest(&dump2);
+ test(dump1.iAccessCount==dump2.iAccessCount && dump1.iOwner==dump2.iOwner &&
+ dump1.iContainer==dump2.iContainer && dump1.iName==dump2.iName);
+ pObj3->__DbgTest(&dump1);
+ temp=pIx->At(aHandle3);
+ temp->__DbgTest(&dump2);
+ test(dump1.iAccessCount==dump2.iAccessCount && dump1.iOwner==dump2.iOwner &&
+ dump1.iContainer==dump2.iContainer && dump1.iName==dump2.iName);
+ pIx->Remove(aHandle1);
+ pIx->Remove(aHandle3);
+ // pIx->Remove(aHandle3); this will cause a crash
+
+ // Removing an object from a CObjectIx calls the objects close method hence in this case
+ // deleting it
+ //delete pCon1; // The destructor for a container deletes its contained objects
+ //delete pCon2;
+ delete pConIx; // The CObjectConIx destructor deletes its containers
+ delete pIx; // The CObjectIx destructor calls close on all its objects
+ }
+
+GLDEF_C void TestCObjects::Test8(void)
+ {
+ // Test all objects together
+ CObjectIx *pIx=CObjectIx::NewL();
+ CObjectConIx *pConIx=CObjectConIx::NewL();
+ CObjectCon *pCon1=pConIx->CreateL(),
+ *pCon2=pConIx->CreateL();
+ CObject *pObj1=new CObject,
+ *pObj2=new CObject,
+ *pObj3=new CObject,
+ *pObj4=new CObject,
+ *pObj5=new CObject,
+ *temp;
+ TInt tempHandle;
+ TPtrC name1(_S("Obj1")), name2(_S("Obj2")), name3(_S("Obj3")), name4(_S("Obj4")), name5(_S("Obj5"));
+
+ // Create two containers with Obj1,Obj2, Obj3 in the first and Obj4 and Obj5 in the second
+ // Obj1 owns Obj2 which owns Obj3
+ pObj1->SetName(&name1);
+ pObj2->SetName(&name2);
+ pObj2->SetOwner(pObj1);
+ pObj3->SetName(&name3);
+ pObj3->SetOwner(pObj2);
+ pObj4->SetName(&name4);
+ pObj5->SetName(&name5);
+ pCon1->AddL(pObj1);
+ pCon1->AddL(pObj2);
+ pCon1->AddL(pObj3);
+ pCon2->AddL(pObj4);
+ pCon2->AddL(pObj5);
+ pIx->AddL(pObj1);
+ pIx->AddL(pObj2);
+ pIx->AddL(pObj3);
+ pIx->AddL(pObj4);
+ pIx->AddL(pObj5);
+
+
+ tempHandle=0;
+ GetObjName(gName1,*pObj1);
+ pCon1->FindByName(tempHandle, gName1, gName);
+ temp=pCon1->At(tempHandle);
+ GetObjName(gName2,*temp);
+ test(gName2==gName1);
+ tempHandle=0;
+ GetObjFullName(gFullName1,*pObj1);
+ pCon1->FindByFullName(tempHandle, gFullName1, gFullName);
+ temp=pCon1->At(tempHandle);
+ GetObjName(gName2,*temp);
+ test(gName2==gName1);
+
+ tempHandle=0;
+ GetObjName(gName1,*pObj2);
+ pCon1->FindByName(tempHandle, gName1, gName);
+ temp=pCon1->At(tempHandle);
+ GetObjName(gName2,*temp);
+ test(gName2==gName1);
+ tempHandle=0;
+ GetObjFullName(gFullName1,*pObj2);
+ pCon1->FindByFullName(tempHandle, gFullName1, gFullName);
+ temp=pCon1->At(tempHandle);
+ GetObjName(gName2,*temp);
+ test(gName2==gName1);
+
+ tempHandle=0;
+ GetObjName(gName1,*pObj3);
+ pCon1->FindByName(tempHandle, gName1, gName);
+ temp=pCon1->At(tempHandle);
+ GetObjName(gName2,*temp);
+ test(gName2==gName1);
+ tempHandle=0;
+ GetObjFullName(gFullName1,*pObj3);
+ pCon1->FindByFullName(tempHandle, gFullName1, gFullName);
+ temp=pCon1->At(tempHandle);
+ GetObjName(gName2,*temp);
+ test(gName2==gName1);
+
+ tempHandle=0;
+ GetObjName(gName1,*pObj4);
+ pCon2->FindByName(tempHandle, gName1, gName);
+ temp=pCon2->At(tempHandle);
+ GetObjName(gName2,*temp);
+ test(gName2==gName1);
+ tempHandle=0;
+ GetObjFullName(gFullName1,*pObj4);
+ pCon2->FindByFullName(tempHandle, gFullName1, gFullName);
+ temp=pCon2->At(tempHandle);
+ GetObjName(gName2,*temp);
+ test(gName1==gName2);
+
+ tempHandle=0;
+ GetObjName(gName1,*pObj5);
+ pCon2->FindByName(tempHandle, gName1, gName);
+ temp=pCon2->At(tempHandle);
+ GetObjName(gName2,*temp);
+ test(gName2==gName1);
+ tempHandle=0;
+ GetObjFullName(gFullName1,*pObj5);
+ pCon2->FindByFullName(tempHandle, gFullName1, gFullName);
+ temp=pCon2->At(tempHandle);
+ GetObjName(gName2,*temp);
+ test(gName2==gName1);
+
+
+ tempHandle=0;
+ test(pCon1->FindByName(tempHandle, _L("*1"), gName)==KErrNone);
+ GetObjName(gName1,*pObj1);
+ test(gName==gName1);
+ tempHandle=0;
+ test(pCon1->FindByFullName(tempHandle, _L("*::*"), gFullName)==KErrNone);
+ GetObjFullName(gFullName1,*pObj2);
+ test(gFullName==gFullName1);
+ GetObjName(gName1,*pObj3);
+ for(tempHandle=0;gName!=gName1;pCon1->FindByName(tempHandle, _L("????"),gName)) {};
+ test(gName==gName1);
+
+
+ pObj1->Close(); // Deletes it and removes it from its container
+ pObj3->Close();
+ tempHandle=0;
+ test(pCon1->FindByName(tempHandle, _L("Obj1"), gName)==KErrNotFound);
+ tempHandle=0;
+ test(pCon1->FindByName(tempHandle, _L("Obj3"), gName)==KErrNotFound);
+ tempHandle=0;
+ GetObjName(gName1,*pObj2);
+ test(pCon1->FindByName(tempHandle, gName1, gName)==KErrNone);
+ test(gName==gName1);
+ tempHandle=0;
+ //CObject* x=new CObject;
+ //x->SetName(_L("xxxx"));
+ //pCon1->FindByFullName(tempHandle, pObj2->FullName(), aFullName);
+ // FullName is set to Xxxx::Obj2
+
+ }
+
+GLDEF_C void TestCObjects::GetObjName(TName& aDest,const CObject& aObj)
+//
+// Utility function to reduce stack usage in functions, and so get rid of __chkstk errors
+//
+ {
+ aDest=aObj.Name();
+ }
+
+GLDEF_C void TestCObjects::GetObjFullName(TFullName& aDest,const CObject& aObj)
+//
+// Utility function to reduce stack usage in functions, and so get rid of __chkstk errors
+//
+ {
+ aDest=aObj.FullName();
+ }
+
+void testHandles()
+
+ {
+
+ CObjectConIx* myConIx=CObjectConIx::NewL();
+ CObjectCon* myCon= myConIx->CreateL();
+ CObjectIx* myIx=CObjectIx::NewL();
+ test(myCon->UniqueID()!=0);
+
+ for (TInt i=0;i<0x4006; i++)
+ {
+ CObject* myObj=new CObject;
+ myCon->AddL(myObj);
+ TInt handle=myIx->AddL(myObj);
+ if ((handle&0xffff0000)==0x3fff0000)
+ test.Printf(_L("Created biggest handle\n"));
+ test (handle!=0);
+ myIx->Remove(handle);
+ }
+ delete myIx;
+ delete myConIx;
+ }
+
+void testSpeed()
+
+ {
+
+ const TInt numObjects=0x600;
+ CObjectConIx* myConIx=CObjectConIx::NewL();
+ CObjectCon* myCon= myConIx->CreateL();
+// CObjectIx* myIx=CObjectIx::NewL();
+ TTime start;
+ TTime end;
+ TInt64 diff;
+ TInt i;
+
+ start.HomeTime();
+ for (i=0;i<numObjects; i++)
+ {
+ CObject* myObj=new CObject;
+ TName name;
+ name.Format(_L("CObject%d"),i);
+ myObj->SetName(&name);
+ myCon->AddL(myObj);
+ }
+ end.HomeTime();
+ diff=(end.Int64()-start.Int64())/100000;
+ test.Printf(_L("Time for 0x%08x named objects = %d tenths of secs\n"),numObjects,I64INT(diff));
+
+// If run as a manual test (when enhancements to RTEST arrive)
+// test.Printf(_L("Press a key to continue with these spammy tests\n"));
+// test.Getch();
+
+ const TInt numObjects2=0x600;
+// CObjectConIx* myConIx2=CObjectConIx::NewL();
+ CObjectCon* myCon2= myConIx->CreateL();
+// CObjectIx* myIx2=CObjectIx::NewL();
+
+ start.HomeTime();
+ for (i=0;i<numObjects2; i++)
+ {
+ CObject* myObj=new CObject;
+ TName name;
+ name.Format(_L("CObject%d"),i);
+ myCon2->AddL(myObj);
+ }
+ end.HomeTime();
+ diff=(end.Int64()-start.Int64())/100000;
+ test.Printf(_L("Time for 0x%08x unnamed objects = %d tenths of secs\n"),numObjects2,I64INT(diff));
+
+
+// If run as a manual test (when enhancements to RTEST arrive)
+// test.Printf(_L("Press a key to continue with these spammy tests\n"));
+// test.Getch();
+
+ // delete myIx;
+// delete myConIx;
+ }
+
+
+
+const TInt KObjectIndexMask=0x7fff;
+
+//Tests CObjectIx class
+class TestCObjectIx
+ {
+public:
+ void StartL(void);
+ ~TestCObjectIx();
+private:
+ void Test1(TInt aSize);
+ void Test2(TInt aSize);
+ void Test3(TInt aSize, TBool aPerformanceTest);
+ inline TInt Index(TInt aHandle) {return(aHandle&KObjectIndexMask);}
+
+private:
+ struct COBjAndHandle
+ {
+ CObject* iObject;
+ TInt iHandle;
+ };
+
+ CObjectConIx* iMyConIx;
+ CObjectCon* iMyCon;
+ CObjectIx* iMyIx;
+ TUint iSeed[2];
+ COBjAndHandle* iObjAndHandle;
+ };
+
+const TInt KMaxTestObjects = (1<<11);
+
+//Runs all tests (methods) of the class
+void TestCObjectIx::StartL(void)
+{
+ TInt i;
+ iMyConIx=CObjectConIx::NewL();
+ iMyCon= iMyConIx->CreateL();
+ iObjAndHandle = (COBjAndHandle*) User::AllocL(KMaxTestObjects * sizeof(COBjAndHandle));
+
+ test.Title();
+ test.Start(_L("Test CObjectIx"));
+
+ test.Next(_L("Add and remove objects in the same order..."));
+ TUint32 startTime = User::NTickCount();
+ for (i=1;i<2000;i=i+10) Test1(i);
+ test.Printf(_L("...done in %d msec\n"), User::NTickCount()-startTime);
+
+ test.Next(_L("Add and remove objects in the reverse order..."));
+ startTime = User::NTickCount();
+ for (i=1;i<2000;i=i+10) Test2(i);
+ test.Printf(_L("...done in %d msec\n"), User::NTickCount()-startTime);
+
+ test.Next(_L("Add and remove objects in random order..."));
+ iSeed[0]=User::TickCount();
+ test.Printf(_L("The initial seed for the random function is: S0=%xh S1=%xh\n"), iSeed[0], iSeed[1]);
+ for (i=2;i<=KMaxTestObjects/2; i<<=1)
+ Test3(i-1, EFalse);
+
+ test.Next(_L("Add and remove objects in random order - performance test..."));
+ iSeed[0]=0;
+ iSeed[1]=1;
+ startTime = User::NTickCount();
+ for (i=2;i<=KMaxTestObjects; i<<=1)
+ Test3(i-1, ETrue);
+ test.Printf(_L("...done in %d msec\n"), User::NTickCount()-startTime);
+ test.Printf(_L("CAUTION: Test changed in May 2005. Comparison of timings with those before then are not valid.\n"));
+
+ test.End();
+}
+
+TestCObjectIx::~TestCObjectIx()
+ {
+ delete iMyConIx;
+ delete [] iObjAndHandle;
+ }
+
+//Adds a number of CObjects to CObjectIx, then removes them in the same order.
+void TestCObjectIx::Test1(TInt aSize)
+{
+ TInt i;
+ iMyIx=CObjectIx::NewL();
+
+ for (i=0; i<aSize; i++) //Add
+ {
+ if( (iObjAndHandle[i].iObject = new CObject) == NULL) User::Leave(KErrNoMemory);
+ iMyCon->AddL(iObjAndHandle[i].iObject);
+ iObjAndHandle[i].iHandle = iMyIx->AddL(iObjAndHandle[i].iObject);
+ }
+
+ for (i=0; i<aSize; i++) //Remove
+ iMyIx->Remove(iObjAndHandle[i].iHandle);
+
+ delete iMyIx;
+ iMyIx=0;
+}
+
+
+//Adds a number of CObjects to CObjectIx, then removes them in the reverse order.
+void TestCObjectIx::Test2(TInt aSize)
+{
+ TInt i;
+ iMyIx=CObjectIx::NewL();
+
+ for (i=0; i<aSize; i++) //Add
+ {
+ if( (iObjAndHandle[i].iObject = new CObject) == NULL) User::Leave(KErrNoMemory);
+ iMyCon->AddL(iObjAndHandle[i].iObject);
+ iObjAndHandle[i].iHandle = iMyIx->AddL(iObjAndHandle[i].iObject);
+ }
+
+ for (i=aSize-1; i>=aSize; i--) //Remove
+ iMyIx->Remove(iObjAndHandle[i].iHandle);
+
+ delete iMyIx;
+ iMyIx=0;
+}
+
+
+//Adds and removes random number of CObjects to/from CObjectIx.
+void TestCObjectIx::Test3(TInt aSize, TBool aPerformanceTest)
+{
+ TInt index, x;
+ if(!aPerformanceTest)
+ test.Printf(_L("Testing size %d.The seeds are: S0=%xh S1=%xh\n"), aSize, iSeed[0], iSeed[1]);
+
+ //---Create & init the objects we need
+ for (x=0; x<aSize; x++) iObjAndHandle[x].iObject = NULL; //initialize the array
+ iMyIx=CObjectIx::NewL();
+
+ for (x = 0; x<100; x++)
+ {
+
+ //---Add the random number of objects (in random order)---
+ TInt toAdd=Random(iSeed)%(aSize-iMyIx->ActiveCount()+1);
+ //test.Printf(_L("Adding %d objects\n"), toAdd );
+ while (toAdd--)
+ {
+ index=Random(iSeed)%aSize;
+ while (iObjAndHandle[index].iObject) //Find the next NULL pointer
+ { ++index; if(index>=aSize) index=0; }
+ if( (iObjAndHandle[index].iObject = new CObject) == NULL) User::Leave(KErrNoMemory);
+ iMyCon->AddL(iObjAndHandle[index].iObject);
+ iObjAndHandle[index].iHandle = iMyIx->AddL(iObjAndHandle[index].iObject);
+ //test.Printf(_L("%d(%d) "), index,iObjAndHandle[index].iHandle & 0x7fff );
+ }
+ //test.Printf(_L("\n"));
+
+
+ //---Remove the random number of objects (in random order)---
+ TInt toRemove=Random(iSeed)%(iMyIx->ActiveCount()+1);
+ //test.Printf(_L("Removing %d objects: "), toRemove );
+ while (toRemove--)
+ {
+ index=Random(iSeed)%aSize;
+ while (!iObjAndHandle[index].iObject) //Find the next non-NULL pointer
+ { ++index; if(index>=aSize) index=0; }
+ //test.Printf(_L("%d(%d) "), index,iObjAndHandle[index].iHandle & 0x7fff );
+ iMyIx->Remove(iObjAndHandle[index].iHandle);
+ iObjAndHandle[index].iObject=NULL;
+ }
+ //test.Printf(_L("\n"));
+
+
+ //---Test data consistency---
+ if(aPerformanceTest) continue;
+
+ TInt objNum=0;
+ for (index=0;index<aSize;index++)
+ {
+ if (iObjAndHandle[index].iObject)
+ {
+ objNum++;
+ //Test At(TInt aHandle) method
+ test(iObjAndHandle[index].iObject == iMyIx->At(iObjAndHandle[index].iHandle));
+ //Test Count(CObject* aObject) method
+ test(1==iMyIx->Count(iObjAndHandle[index].iObject));
+ //Test At(CObject* aObject) method
+ test(iObjAndHandle[index].iHandle==iMyIx->At(iObjAndHandle[index].iObject));
+ //Test operator[](TInt index) method
+ test(iObjAndHandle[index].iObject==(*iMyIx)[Index(iObjAndHandle[index].iHandle)]);
+ }
+ }
+
+ test (objNum==iMyIx->ActiveCount());
+ //test.Printf(_L("%d objects in array\n"), objNum);
+ }
+
+ delete iMyIx;
+ iMyIx=NULL;
+}
+
+// Test that things work when the unique ID of the object container grows larger
+// than 15 bits
+void TestCObjectConIxL(void)
+ {
+ const TInt KCObjectConLimit = 65535;
+ _LIT(KAnyMatch, "*");
+
+ __UHEAP_MARK;
+
+ CObjectConIx* conIx = CObjectConIx::NewL();
+ CObjectIx* ix = CObjectIx::NewL();
+ TInt i;
+
+ test.Next(_L("Test repeated add/remove of object containers"));
+ for (i = 0 ; i < KCObjectConLimit * 2 ; ++i)
+ {
+ CObjectCon* con = conIx->CreateL();
+ CObject* obj = new (ELeave) CObject();
+ con->AddL(obj);
+
+ TInt handle = ix->AddL(obj);
+ test(ix->At(handle) == obj);
+ test(ix->At(handle, con->UniqueID()) == obj);
+
+ TName name;
+ TInt findHandle = 0;
+ test(con->FindByName(findHandle, KAnyMatch, name) == KErrNone);
+ test(con->AtL(findHandle) == obj);
+ test(con->At(findHandle) == obj);
+ test(conIx->Lookup(findHandle) == con);
+ test(con->FindByName(findHandle, KAnyMatch, name) == KErrNotFound);
+
+ TFullName fullName;
+ findHandle = 0;
+ test(con->FindByFullName(findHandle, KAnyMatch, fullName) == KErrNone);
+ test(con->AtL(findHandle) == obj);
+ test(con->At(findHandle) == obj);
+ test(conIx->Lookup(findHandle) == con);
+ test(con->FindByFullName(findHandle, KAnyMatch, fullName) == KErrNotFound);
+
+ ix->Remove(handle);
+ conIx->Remove(con);
+ }
+
+ test.Next(_L("Test adding maximum possible number of object containers"));
+ RPointerArray<CObjectCon> cons;
+ for (i = 0 ; i < KCObjectConLimit ; ++i)
+ {
+ CObjectCon* con = conIx->CreateL();
+ cons.AppendL(con);
+ }
+ TRAPD(err, conIx->CreateL());
+ test(err == KErrOverflow);
+
+ test.Next(_L("Test unique IDs are really unique after ID value has wrapped"));
+ for (i = 100 ; i < KCObjectConLimit ; ++i)
+ {
+ CObjectCon* con = cons[i];
+ conIx->Remove(con);
+ }
+ for (i = 100 ; i < 200 ; ++i)
+ {
+ CObjectCon* con = conIx->CreateL();
+ cons[i] = con;
+ }
+ for (i = 0 ; i < 200 ; ++i)
+ {
+ TName name;
+ TInt findHandle = 0;
+ CObjectCon* con = cons[i];
+
+ CObject* obj = new (ELeave) CObject();
+ con->AddL(obj);
+
+ test(con->FindByName(findHandle, KAnyMatch, name) == KErrNone);
+ test(conIx->Lookup(findHandle) == con);
+
+ obj->Close();
+ }
+ for (i = 0 ; i < 200 ; ++i)
+ {
+ CObjectCon* con = cons[i];
+ conIx->Remove(con);
+ }
+ cons.Close();
+
+ delete ix;
+ delete conIx;
+
+ __UHEAP_MARKEND;
+ }
+
+GLDEF_C TInt E32Main()
+ {
+
+ CTrapCleanup* trapHandler=CTrapCleanup::New();
+ test(trapHandler!=NULL);
+
+ test.Title();
+ test.Start(_L("TEST METHODS ARE IN THE DLL"));
+
+ __UHEAP_MARK;
+
+ TestCObjectIx* TCobjectIx = new TestCObjectIx;
+ TRAPD(ret, TCobjectIx->StartL());
+ test(KErrNone == ret);
+ delete TCobjectIx;
+
+ __UHEAP_MARKEND;
+
+ test.Next(_L("Generate lots of handles"));
+ testHandles();
+
+ test.Next(_L("Test CObjectCon is fast enough"));
+ testSpeed();
+
+ TestCObjects T;
+ test.Next(_L("CObject methods"));
+ T.Test1();
+ test.Next(_L("CObjectCon methods"));
+ T.Test2();
+ test.Next(_L("CObjectIx methods"));
+ T.Test3();
+ test.Next(_L("CObjectConIx methods"));
+ T.Test4();
+ test.Next(_L("TEST THE METHODS"));
+ test.Next(_L("CObject"));
+ T.Test5();
+ test.Next(_L("CObjectCon"));
+ T.Test6();
+ test.Next(_L("CObjectIx"));
+ T.Test7();
+
+ //////////////////////////////
+ // PROPER TESTING STARTS HERE
+ //////////////////////////////
+ test.Next(_L("All objects"));
+ T.Test8();
+
+ test.Next(_L("CObjectConIx"));
+ TRAPD(err, TestCObjectConIxL());
+ if (err != KErrNone)
+ test.Printf(_L("TestCObjectConIxL left with %d\n"), err);
+ test(err == KErrNone);
+
+ test.End();
+
+ delete trapHandler;
+ return(KErrNone);
+ }