kerneltest/e32test/buffer/t_hashtab.cpp
changeset 0 a41df078684a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/buffer/t_hashtab.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,2433 @@
+// Copyright (c) 2005-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/buffer/t_hashtab.cpp
+// 
+//
+
+#include <e32test.h>
+#include <e32hashtab.h>
+#include <hal.h>
+
+#if defined(__VC32__) || defined(__CW32__)
+typedef unsigned short wch;
+#else
+typedef wchar_t wch;
+#endif
+
+
+RTest test(_L("T_HASHTAB"));
+TInt NanoTickPeriod;
+
+typedef TBuf8<80> TTestName;
+typedef RHashSet<TInt> TIntSet;
+typedef RHashSet<TTestName> TNameSet;
+typedef RPtrHashSet<TDesC8> TStringSet8;
+typedef RPtrHashSet<TDesC16> TStringSet16;
+typedef RPtrHashMap<TDesC8,TDesC8> TStringMap8;
+typedef RPtrHashMap<TDesC16,TDesC16> TStringMap16;
+
+#define INTSET(x)	TIntSet x
+#define NAMESET(x)	TNameSet x(&HashTestName, &TestNameIdentity)
+#define STRSET8(x)	TStringSet8 x
+#define STRSET16(x)	TStringSet16 x
+#define STRMAP8(x)	TStringMap8 x
+#define STRMAP16(x)	TStringMap16 x
+
+RPointerArray<TDesC8> DesC8Array;
+RPointerArray<TDesC16> DesC16Array;
+
+class HashTest : public RHashTableBase
+	{
+public:
+	HashTest() : RHashTableBase(0,0,0,0) {}
+	using RHashTableBase::ConsistencyCheck;
+	using RHashTableBase::Count;
+	};
+
+void CCheck(RHashTableBase& aHT)
+	{
+	TUint32 ci[1024];
+	TUint32 dc;
+	TUint32 cmp;
+	HashTest* h = (HashTest*)&aHT;
+	h->ConsistencyCheck(&dc, &cmp, 1024, ci);
+	test.Printf(_L("Count = %d, Deleted = %d, Cmp = %d\n"), h->Count(), dc, cmp);
+	TInt i;
+	for (i=0; i<1024; ++i)
+		{
+		if (ci[i])
+			test.Printf(_L("%d chains of length %d\n"), ci[i], i);
+		}
+	}
+
+const char* Numbers[] =
+	{
+	"zero",
+	"one",
+	"two",
+	"three",
+	"four",
+	"five",
+	"six",
+	"seven",
+	"eight",
+	"nine",
+	"ten",
+	"eleven",
+	"twelve",
+	"thirteen",
+	"fourteen",
+	"fifteen",
+	"sixteen",
+	"seventeen",
+	"eighteen",
+	"nineteen",
+	"twenty",
+	"thirty",
+	"forty",
+	"fifty",
+	"sixty",
+	"seventy",
+	"eighty",
+	"ninety",
+	"hundred",
+	"thousand"
+	};
+
+TTestName NumberInWords(const TInt& aNum)
+	{
+	TInt a = aNum;
+	TTestName n;
+	if (a<20)
+		{
+		n.Copy((const TUint8*)Numbers[a]);
+		return n;
+		}
+	if (a<100)
+		{
+		TInt tens = a/10;
+		TInt units = a%10;
+		n.Copy((const TUint8*)Numbers[tens-2+20]);
+		if (units)
+			{
+			n.Append(' ');
+			n.Append(TPtrC8((const TUint8*)Numbers[units]));
+			}
+		return n;
+		}
+	if (a<1000)
+		{
+		TInt h = a/100;
+		n.Copy((const TUint8*)Numbers[h]);
+		n.Append(' ');
+		n.Append(TPtrC8((const TUint8*)Numbers[28]));
+		a%=100;
+		if (a)
+			{
+			TTestName n2(NumberInWords(a));
+			n.Append(_L8(" and "));
+			n+=n2;
+			}
+		return n;
+		}
+	TInt t = a/1000;
+	n = NumberInWords(t);
+	n.Append(' ');
+	n.Append(TPtrC8((const TUint8*)Numbers[29]));
+	a%=1000;
+	if (a)
+		{
+		TTestName n2(NumberInWords(a));
+		if (a<100)
+			n.Append(_L8(" and "));
+		else
+			n.Append(' ');
+		n+=n2;
+		}
+	return n;
+	}
+
+void PrintNumberInWords(TInt a)
+	{
+	TBuf<256> buf;
+	TTestName n(NumberInWords(a));
+	buf.Copy(n);
+	test.Printf(_L("%d: %S\n"), a, &buf);
+	}
+
+TUint32 HashTestName(const TTestName& aN)
+	{
+	return DefaultHash::Des8(aN);
+	}
+
+TBool TestNameIdentity(const TTestName& aA, const TTestName& aB)
+	{
+	return aA == aB;
+	}
+
+/******************************************************************************
+ * Utility functions for RHashSet<T>
+ ******************************************************************************/
+template <class T>
+void Union(RHashSet<T>& aD, const RHashSet<T>& aS)
+	{
+	TInt c = aS.Count();
+	TInt c2 = c;
+	TInt d0 = aD.Count();
+	TInt d1 = d0;
+	typename RHashSet<T>::TIter iS(aS);
+	FOREVER
+		{
+		const T* p = iS.Next();
+		if (!p)
+			break;
+		--c2;
+		TInt r = aD.Insert(*p);
+		test(r==KErrNone);
+		++d1;
+		}
+	test(d1 == aD.Count());
+	test(c2 == 0);
+	}
+
+template <class T>
+void Subtract(RHashSet<T>& aD, const RHashSet<T>& aS)
+	{
+	TInt c = aS.Count();
+	TInt c2 = c;
+	TInt d0 = aD.Count();
+	TInt d1 = d0;
+	TInt nfd = 0;
+	typename RHashSet<T>::TIter iS(aS);
+	FOREVER
+		{
+		const T* p = iS.Next();
+		if (!p)
+			break;
+		--c2;
+		TInt r = aD.Remove(*p);
+		test(r==KErrNone || r==KErrNotFound);
+		if (r==KErrNotFound)
+			++nfd;
+		else
+			--d1;
+		}
+	test(d1 == aD.Count());
+	test(c2 == 0);
+	test( (d0-d1) + nfd == c);
+	}
+
+template <class T>
+void Intersect(RHashSet<T>& aD, const RHashSet<T>& aS)
+	{
+	typename RHashSet<T>::TIter iD(aD);
+	FOREVER
+		{
+		const T* p = iD.Next();
+		if (!p)
+			break;
+		if (!aS.Find(*p))
+			iD.RemoveCurrent();
+		}
+	}
+
+template <class T>
+void CheckIdentical(const RHashSet<T>& aA, const RHashSet<T>& aB)
+	{
+	test(aA.Count()==aB.Count());
+	TInt c = aA.Count();
+	typename RHashSet<T>::TIter iA(aA);
+	FOREVER
+		{
+		const T* p = iA.Next();
+		if (!p)
+			break;
+		--c;
+		test(aB.Find(*p)!=0);
+		}
+	test(c==0);
+	c = aA.Count();
+	typename RHashSet<T>::TIter iB(aB);
+	FOREVER
+		{
+		const T* p = iB.Next();
+		if (!p)
+			break;
+		--c;
+		test(aA.Find(*p)!=0);
+		}
+	test(c==0);
+	}
+
+
+/******************************************************************************
+ * Utility functions for RPtrHashSet<T>
+ ******************************************************************************/
+template <class T>
+void Union(RPtrHashSet<T>& aD, const RPtrHashSet<T>& aS)
+	{
+	TInt c = aS.Count();
+	TInt c2 = c;
+	TInt d0 = aD.Count();
+	TInt d1 = d0;
+	typename RPtrHashSet<T>::TIter iS(aS);
+	FOREVER
+		{
+		const T* p = iS.Next();
+		if (!p)
+			break;
+		--c2;
+		TInt r = aD.Insert(p);
+		test(r==KErrNone);
+		++d1;
+		}
+	test(d1 == aD.Count());
+	test(c2 == 0);
+	}
+
+template <class T>
+void Subtract(RPtrHashSet<T>& aD, const RPtrHashSet<T>& aS)
+	{
+	TInt c = aS.Count();
+	TInt c2 = c;
+	TInt d0 = aD.Count();
+	TInt d1 = d0;
+	TInt nfd = 0;
+	typename RPtrHashSet<T>::TIter iS(aS);
+	FOREVER
+		{
+		const T* p = iS.Next();
+		if (!p)
+			break;
+		--c2;
+		TInt r = aD.Remove(p);
+		test(r==KErrNone || r==KErrNotFound);
+		if (r==KErrNotFound)
+			++nfd;
+		else
+			--d1;
+		}
+	test(d1 == aD.Count());
+	test(c2 == 0);
+	test( (d0-d1) + nfd == c);
+	}
+
+template <class T>
+void Intersect(RPtrHashSet<T>& aD, const RPtrHashSet<T>& aS)
+	{
+	typename RPtrHashSet<T>::TIter iD(aD);
+	FOREVER
+		{
+		const T* p = iD.Next();
+		if (!p)
+			break;
+		if (!aS.Find(*p))
+			iD.RemoveCurrent();
+		}
+	}
+
+template <class T>
+void CheckIdentical(const RPtrHashSet<T>& aA, const RPtrHashSet<T>& aB)
+	{
+	test(aA.Count()==aB.Count());
+	TInt c = aA.Count();
+	typename RPtrHashSet<T>::TIter iA(aA);
+	FOREVER
+		{
+		const T* p = iA.Next();
+		if (!p)
+			break;
+		--c;
+		test(aB.Find(*p)!=0);
+		}
+	test(c==0);
+	c = aA.Count();
+	typename RPtrHashSet<T>::TIter iB(aB);
+	FOREVER
+		{
+		const T* p = iB.Next();
+		if (!p)
+			break;
+		--c;
+		test(aA.Find(*p)!=0);
+		}
+	test(c==0);
+	}
+
+
+/******************************************************************************
+ * Utility functions for RHashMap<K,V>
+ ******************************************************************************/
+template <class K, class V>
+void UnionTransform(RHashMap<K,V>& aD, const RHashSet<K>& aS, V (*aTransform)(const K&) )
+	{
+	TInt c = aS.Count();
+	TInt c2 = c;
+	TInt d0 = aD.Count();
+	TInt d1 = d0;
+	typename RHashSet<K>::TIter iS(aS);
+	FOREVER
+		{
+		const K* p = iS.Next();
+		if (!p)
+			break;
+		--c2;
+		TInt r = aD.Insert(*p, (*aTransform)(*p) );
+		test(r==KErrNone);
+		++d1;
+		}
+	test(d1 == aD.Count());
+	test(c2 == 0);
+	}
+
+
+template <class K, class V>
+void UnionMap(RHashSet<V>& aD, const RHashSet<K>& aS, const RHashMap<K,V>& aM)
+	{
+	TInt c = aS.Count();
+	TInt c2 = c;
+	TInt d0 = aD.Count();
+	TInt d1 = d0;
+	typename RHashSet<K>::TIter iS(aS);
+	FOREVER
+		{
+		const K* p = iS.Next();
+		if (!p)
+			break;
+		--c2;
+		const V* q = aM.Find(*p);
+		if (!q)
+			continue;
+		TInt r = aD.Insert(*q);
+		test(r==KErrNone);
+		++d1;
+		}
+	test(d1 == aD.Count());
+	test(c2 == 0);
+	}
+
+
+template <class K, class V>
+void UnionKeys(RHashSet<K>& aD, const RHashMap<K,V>& aM)
+	{
+	typename RHashMap<K,V>::TIter iM(aM);
+	FOREVER
+		{
+		const K* p = iM.NextKey();
+		if (!p)
+			break;
+		aD.Insert(*p);
+		}
+	}
+
+
+template <class K, class V>
+void UnionValues(RHashSet<V>& aD, const RHashMap<K,V>& aM)
+	{
+	typename RHashMap<K,V>::TIter iM(aM);
+	FOREVER
+		{
+		const K* p = iM.NextKey();
+		if (!p)
+			break;
+		const V* q = iM.CurrentValue();
+		aD.Insert(*q);
+		}
+	}
+
+
+template <class K, class V>
+void UnionTransform(RHashMap<K,V>& aD, const RHashMap<K,V>& aS, V (*aTransform)(const V&) )
+	{
+	TInt c = aS.Count();
+	TInt c2 = c;
+	TInt d0 = aD.Count();
+	TInt d1 = d0;
+	typename RHashMap<K,V>::TIter iS(aS);
+	FOREVER
+		{
+		const K* p = iS.NextKey();
+		if (!p)
+			break;
+		--c2;
+		TInt r = aD.Insert(*p, (*aTransform)(*iS.CurrentValue()) );
+		test(r==KErrNone);
+		++d1;
+		}
+	test(d1 == aD.Count());
+	test(c2 == 0);
+	}
+
+
+template <class K, class V>
+void UnionInverse(RHashMap<V,K>& aD, const RHashMap<K,V>& aS)
+	{
+	TInt c = aS.Count();
+	TInt c2 = c;
+	TInt d0 = aD.Count();
+	TInt d1 = d0;
+	typename RHashMap<K,V>::TIter iS(aS);
+	FOREVER
+		{
+		const K* p = iS.NextKey();
+		if (!p)
+			break;
+		--c2;
+		const V* q = iS.CurrentValue();
+		TInt r = aD.Insert(*q, *p);
+		test(r==KErrNone);
+		++d1;
+		}
+	test(d1 == aD.Count());
+	test(c2 == 0);
+	}
+
+template <class K, class V>
+void SetMap(RHashMap<V,K>& aM, const V& aV)
+	{
+	typename RHashMap<K,V>::TIter iM(aM);
+	FOREVER
+		{
+		const K* p = iM.NextKey();
+		if (!p)
+			break;
+		V* q = iM.CurrentValue();
+		*q = aV;
+		test(*q == aV);
+		}
+	}
+
+
+/******************************************************************************
+ * Utility functions for RPtrHashMap<K,V>
+ ******************************************************************************/
+template <class K, class V>
+void UnionTransform(RPtrHashMap<K,V>& aD, const RPtrHashMap<K,V>& aS, V* (*aTransform)(const V*) )
+	{
+	TInt c = aS.Count();
+	TInt c2 = c;
+	TInt d0 = aD.Count();
+	TInt d1 = d0;
+	typename RPtrHashMap<K,V>::TIter iS(aS);
+	FOREVER
+		{
+		const K* p = iS.NextKey();
+		if (!p)
+			break;
+		--c2;
+		TInt r = aD.Insert(p, (*aTransform)(iS.CurrentValue()) );
+		test(r==KErrNone);
+		++d1;
+		}
+	test(d1 == aD.Count());
+	test(c2 == 0);
+	}
+
+
+template <class A, class B>
+void UnionInverse(RPtrHashMap<B,A>& aD, const RPtrHashMap<A,B>& a1)
+	{
+	typename RPtrHashMap<A,B>::TIter iter(a1);
+	const A* pA;
+	while ( (pA=iter.NextKey()) != 0 )
+		{
+		const B* pB = iter.CurrentValue();
+		TInt r = aD.Insert(pB, pA);
+		test(r==KErrNone);
+		}
+	}
+
+
+template <class A, class B, class C>
+void UnionCompose(RPtrHashMap<A,C>& aD, const RPtrHashMap<A,B>& a1, const RPtrHashMap<B,C>& a2)
+	{
+	typename RPtrHashMap<A,B>::TIter iter(a1);
+	const A* pA;
+	while ( (pA=iter.NextKey()) != 0 )
+		{
+		const B* pB = iter.CurrentValue();
+		const C* pC = a2.Find(*pB);
+		if (pC)
+			{
+			TInt r = aD.Insert(pA, pC);
+			test(r==KErrNone);
+			}
+		}
+	}
+
+
+template <class K, class V>
+void CheckIdenticalMaps(const RPtrHashMap<K,V>& aA, const RPtrHashMap<K,V>& aB)
+	{
+	test(aA.Count()==aB.Count());
+	TInt c = aA.Count();
+	const K* p;
+	const V* q;
+	typename RPtrHashMap<K,V>::TIter iA(aA);
+	while( (p=iA.NextKey()) != 0)
+		{
+		--c;
+		q = aB.Find(*p);
+		test(q && q==iA.CurrentValue());
+		}
+	test(c==0);
+	c = aB.Count();
+	typename RPtrHashMap<K,V>::TIter iB(aB);
+	while( (p=iB.NextKey()) != 0)
+		{
+		--c;
+		q = aA.Find(*p);
+		test(q && q==iB.CurrentValue());
+		}
+	test(c==0);
+	}
+
+
+
+
+
+/******************************************************************************
+ * Tests of TIntSet
+ ******************************************************************************/
+void Populate(TIntSet& aH, TInt aS, TInt aE, TInt aM)
+	{
+	TInt x = aS;
+	for (; x<=aE; x+=aM)
+		aH.Insert(x);
+	}
+
+void PrimeSieve(TIntSet& aH, TInt aStart, TInt aEnd)
+	{
+	TInt x;
+	TInt e = (aEnd&1) ? aEnd : aEnd-1;
+	TInt s = (aStart<2) ? 2 : aStart|1;
+	for (x=s; x<=e; ++x)
+		{
+//		test.Printf(_L("add %d\n"),x);
+		aH.Insert(x);
+		}
+	TInt m=2;
+	FOREVER
+		{
+		for (; m*m<=e && !aH.Find(m); ++m)
+			{}
+		if (m*m > e)
+			break;
+		for (x=m*2; x<=e; x+=m)
+			{
+//			test.Printf(_L("remove %d\n"),x);
+			aH.Remove(x);
+			}
+		++m;
+		}
+	}
+
+TBool IsPrime(TInt x)
+	{
+	if (x==2)
+		return ETrue;
+	if (!(x&1))
+		return EFalse;
+	TInt d;
+	for (d=3; d*d<=x; d+=2)
+		{
+		if (x%d==0)
+			return EFalse;
+		}
+	return ETrue;
+	}
+
+void CheckSieveOutput(TIntSet& aH)
+	{
+	RHashSet<TInt>::TIter iter(aH);
+	TInt min = KMaxTInt;
+	TInt max = KMinTInt;
+	TInt c = 0;
+	test.Printf(_L("%d elements:\n"),aH.Count());
+	FOREVER
+		{
+		const TInt* p = iter.Next();
+		if (!p)
+			break;
+		++c;
+		if (*p>max) max=*p;
+		if (*p<min) min=*p;
+//		test.Printf(_L("%d\n"),*p);
+		test(IsPrime(*p));
+		}
+	test(c==aH.Count());
+	TInt x;
+	if (min==2)
+		{
+		test(aH.Find(2)!=0);
+		min++;
+		}
+	for (x=min; x<=max; x+=2)
+		{
+		if (IsPrime(x))
+			test(aH.Find(x)!=0);
+		}
+	for (x=min; x<=max; x+=2)
+		{
+		if (IsPrime(x))
+			test(aH.Find(x)==&aH.FindL(x));
+		else
+			{
+			TRAPD(rr,aH.FindL(x));
+			test(rr==KErrNotFound);
+			}
+		}
+	}
+
+TUint32 CheckSmallHashSet(const TIntSet& aA)
+	{
+	TUint32 m = 0;
+	RHashSet<TInt>::TIter iter(aA);
+	FOREVER
+		{
+		const TInt* p = iter.Next();
+		if (!p)
+			break;
+		m |= (1<<*p);
+		}
+	return m;
+	}
+
+void AddToSmallHashSet(TIntSet& aA, TUint32 aMask)
+	{
+	CheckSmallHashSet(aA);
+	TInt i;
+	TInt r;
+	for (i=0; i<32; ++i)
+		{
+		if (aMask & (1<<i))
+			{
+			r = aA.Insert(i);
+			test(r==KErrNone);
+			}
+		}
+	}
+
+void RemoveFromSmallHashSet(TIntSet& aA, TUint32 aMask)
+	{
+	TUint32 m = CheckSmallHashSet(aA);
+	TInt i;
+	TInt r;
+	for (i=0; i<32; ++i)
+		{
+		if (aMask & (1<<i))
+			{
+			r = aA.Remove(i);
+			if (m & (1<<i))
+				test(r==KErrNone);
+			else
+				test(r==KErrNotFound);
+			}
+		}
+	}
+
+void TestHashSet()
+	{
+	test.Next(_L("Test RHashSet"));
+
+	INTSET(hs);
+	CCheck(hs);		// check consistency for empty table
+	INTSET(hs2);
+	INTSET(hs3);
+	PrimeSieve(hs, 1, 100);
+	CheckSieveOutput(hs);
+	test(hs.Reserve(1000)==KErrNone);
+	CCheck(hs);
+	CheckSieveOutput(hs);	// check that Reserve() preserves existing entries
+
+	INTSET(m1);
+	INTSET(m2);
+	INTSET(m3);
+	INTSET(m5);
+	INTSET(m7);
+	Populate(m1,2,100,1);
+	Populate(m2,4,100,2);
+	Populate(m3,6,100,3);
+	Populate(m5,10,100,5);
+	Populate(m7,14,100,7);
+	Union(hs3, m1);
+	Subtract(hs3, m2);
+	Subtract(hs3, m3);
+	Subtract(hs3, m5);
+	Subtract(hs3, m7);
+	CheckSieveOutput(hs3);
+	CheckIdentical(hs,hs3);
+	hs3.Close();
+	INTSET(cm2);
+	INTSET(cm3);
+	INTSET(cm5);
+	INTSET(cm7);
+	Union(cm2, m1);
+	Subtract(cm2, m2);
+	Union(cm3, m1);
+	Subtract(cm3, m3);
+	Union(cm5, m1);
+	Subtract(cm5, m5);
+	Union(cm7, m1);
+	Subtract(cm7, m7);
+	Union(hs3, m1);
+	Intersect(hs3, cm7);
+	Intersect(hs3, cm3);
+	Intersect(hs3, cm5);
+	Intersect(hs3, cm2);
+	CheckSieveOutput(hs3);
+	CheckIdentical(hs,hs3);
+	hs3.Close();
+
+
+	cm2.Close();
+	cm3.Close();
+	cm5.Close();
+	cm7.Close();
+	m1.Close();
+	m2.Close();
+	m3.Close();
+	m5.Close();
+	m7.Close();
+
+	PrimeSieve(hs2, 1, 1000);
+	CheckSieveOutput(hs2);
+	test(hs2.Reserve(1000)==KErrNone);
+	CCheck(hs2);
+	CheckSieveOutput(hs2);	// check that Reserve() preserves existing entries
+
+	PrimeSieve(hs, 100, 997);
+	CheckSieveOutput(hs);
+	CCheck(hs);
+	CheckIdentical(hs,hs2);
+
+	hs2.Close();
+	Union(hs2, hs);
+	CheckIdentical(hs,hs2);
+	CheckSieveOutput(hs2);
+
+	hs2.Close();
+	hs.Close();
+
+	test(CheckSmallHashSet(hs)==0);
+	AddToSmallHashSet(hs, 1);
+	test(CheckSmallHashSet(hs)==1);
+	AddToSmallHashSet(hs, 4);
+	test(CheckSmallHashSet(hs)==5);
+	AddToSmallHashSet(hs, 0x80000001);
+	test(CheckSmallHashSet(hs)==0x80000005);
+	AddToSmallHashSet(hs, 0x317217f8);
+	test(CheckSmallHashSet(hs)==0xb17217fd);
+	RemoveFromSmallHashSet(hs, 0x00000007);
+	test(CheckSmallHashSet(hs)==0xb17217f8);
+	RemoveFromSmallHashSet(hs, 0xffffffff);
+	test(CheckSmallHashSet(hs)==0);
+	hs.Close();
+	}
+
+void TestHashIter()
+	{
+	test.Next(_L("Test iterators"));
+
+	RHashSet<TInt> hs;		// empty
+	RHashSet<TInt>::TIter iter(hs);
+	test(iter.Next() == 0);
+	test(iter.Current() == 0);
+	iter.RemoveCurrent();
+	test(iter.Next() == 0);
+	test(iter.Current() == 0);
+
+	test(hs.Insert(1) == KErrNone);
+	test(hs.Insert(2) == KErrNone);
+	test(hs.Insert(3) == KErrNone);
+	iter.Reset();
+	TUint mask = 14;
+	TInt i;
+	for (i=0; i<3; ++i)
+		{
+		const TInt* p = iter.Next();
+		test(p!=0);
+		TInt x = *p;
+		test (x>=1 && x<=3 && (mask&(1<<x))!=0);
+		mask &= ~(1<<x);
+		}
+	test(iter.Next() == 0);
+	test(mask==0);
+	test(CheckSmallHashSet(hs)==0x0e);
+	test(hs.Insert(4) == KErrNone);
+	test(hs.Insert(5) == KErrNone);
+	test(hs.Insert(6) == KErrNone);
+	test(hs.Insert(7) == KErrNone);
+	test(CheckSmallHashSet(hs)==0xfe);
+	iter.Reset();
+	while(iter.Next())
+		{
+		if ((*iter.Current() & 1) == 0)
+			iter.RemoveCurrent();
+		}
+	test(CheckSmallHashSet(hs)==0xaa);
+	iter.Reset();
+	while(iter.Next())
+		{
+		iter.RemoveCurrent();
+		}
+	test(CheckSmallHashSet(hs)==0);
+	iter.Reset();
+	test(iter.Next() == 0);
+	test(iter.Current() == 0);
+	RHashSet<TInt> empty;
+	CheckIdentical(hs, empty);
+#ifdef _DEBUG
+	__UHEAP_FAILNEXT(1);
+	test(empty.Insert(1)==KErrNoMemory);
+	test(empty.Insert(1)==KErrNone);
+	empty.Close();
+	__UHEAP_FAILNEXT(1);
+	test(hs.Insert(1)==KErrNone);
+	hs.Close();
+	__UHEAP_FAILNEXT(1);
+	test(hs.Insert(1)==KErrNoMemory);
+#endif
+	hs.Close();
+	}
+
+void Print(const char* aTitle, const RHashMap<TInt,TTestName>& aM)
+	{
+	TBuf<256> buf;
+	buf.Copy(TPtrC8((const TUint8*)aTitle));
+	test.Printf(_L("%S\n"), &buf);
+	RHashMap<TInt,TTestName>::TIter iter(aM);
+	FOREVER
+		{
+		const TInt* p = iter.NextKey();
+		if (!p) break;
+		buf.Copy(*iter.CurrentValue());
+		test.Printf(_L("%d: %S\n"), *p, &buf);
+		}
+	}
+
+void Print(const char* aTitle, const RHashSet<TTestName>& aS)
+	{
+	TBuf<256> buf;
+	buf.Copy(TPtrC8((const TUint8*)aTitle));
+	test.Printf(_L("%S\n"), &buf);
+	RHashSet<TTestName>::TIter iter(aS);
+	FOREVER
+		{
+		if (!iter.Next())
+			break;
+		buf.Copy(*iter.Current());
+		test.Printf(_L("%S\n"), &buf);
+		}
+	}
+
+void TestHashMap()
+	{
+	test.Next(_L("Test RHashMap"));
+
+	RHashMap<TInt,TInt> ht;
+	CCheck(ht);		// check consistency for empty table
+	TInt x;
+	for (x=0; x<200; x++)
+		{
+		TInt r = ht.Insert(x*x, x);
+		test(r==KErrNone);
+		}
+	test(ht.Count()==200);
+
+	TInt z = 0;
+	TInt y;
+	for (x=0; x<40000; x++)
+		{
+		const TInt* e = ht.Find(x);
+		if (e)
+			{
+			const TInt& ee = ht.FindL(x);
+			test(&ee==e);
+			y = *e;
+//			test.Printf(_L("Find(%d) -> %d\n"), x, y);
+			test(x == z*z);
+			test(y == z);
+			++z;
+			}
+		else
+			{
+			TRAPD(rr, ht.FindL(x));
+			test(rr==KErrNotFound);
+			}
+		}
+	CCheck(ht);
+
+	for (x=0; x<200; x++)
+		{
+		TInt r = ht.Insert(x*x*x, x);
+		test(r==KErrNone);
+		}
+	test(ht.Count()==200*2-6);
+	CCheck(ht);
+
+	TInt sq = 0;
+	TInt cb = 0;
+	for (x=0; x<8000000; x++)
+		{
+		const TInt* e = ht.Find(x);
+		if (e)
+			{
+			const TInt& ee = ht.FindL(x);
+			test(&ee==e);
+			y = *e;
+//			test.Printf(_L("Find(%d) -> %d\n"), x, y);
+			if (x == cb*cb*cb)
+				{
+				test(y==cb);
+				++cb;
+				if (x == sq*sq)
+					++sq;
+				}
+			else if (x == sq*sq)
+				{
+				test(y==sq);
+				++sq;
+				}
+			}
+		}
+
+	for (x=0; x<200; x++)
+		{
+		TInt r = ht.Remove(x*x);
+		test(r==KErrNone);
+		}
+	test(ht.Count()==200-6);
+	CCheck(ht);
+
+	cb = 2;
+	for (x=2; x<8000000; x++)
+		{
+		const TInt* e = ht.Find(x);
+		if (e)
+			{
+			const TInt& ee = ht.FindL(x);
+			test(&ee==e);
+			y = *e;
+//			test.Printf(_L("Find(%d) -> %d\n"), x, y);
+			if (cb == 4 || cb == 9 || cb == 16 || cb == 25) ++cb;
+			test(x == cb*cb*cb);
+			test(y == cb);
+			++cb;
+			}
+		}
+
+	SetMap<TInt,TInt>(ht, 17);
+
+	ht.Close();
+
+	PrintNumberInWords(2000);
+	PrintNumberInWords(2001);
+	PrintNumberInWords(131072);
+	PrintNumberInWords(111111);
+	PrintNumberInWords(524288);
+
+	INTSET(all);
+	Populate(all,0,1000,1);
+	RHashMap<TInt,TTestName> to_words(&DefaultHash::Integer, &DefaultIdentity::Integer);
+	UnionTransform<TInt,TTestName>(to_words, all, &NumberInWords);
+	RHashMap<TTestName,TInt> from_words(&HashTestName, &TestNameIdentity);
+	UnionInverse<TInt,TTestName>(from_words, to_words);
+//	Print("TO WORDS:", to_words);
+	INTSET(primes);
+	PrimeSieve(primes, 1, 100);
+//	Print("Primes 1-100", primes);
+	RHashMap<TInt,TTestName> prime_map(&DefaultHash::Integer, &DefaultIdentity::Integer);
+	UnionTransform<TInt,TTestName>(prime_map, primes, &NumberInWords);
+//	Print("Prime map 1-100", prime_map);
+	INTSET(pmkeys);
+	UnionKeys<TInt,TTestName>(pmkeys, prime_map);
+	NAMESET(pmval);
+	NAMESET(pmval2);
+	UnionValues<TInt,TTestName>(pmval, prime_map);
+	CheckIdentical(pmkeys, primes);
+	INTSET(pr2);
+	UnionMap<TTestName,TInt>(pr2, pmval, from_words);
+	CheckIdentical(pr2, primes);
+	pr2.Close();
+	Union(pmval2, pmval);
+//	Print("pmval",pmval);
+//	Print("pmval2",pmval2);
+	CheckIdentical(pmval2, pmval);
+	UnionMap<TTestName,TInt>(pr2, pmval2, from_words);
+	CheckIdentical(pr2, primes);
+
+	pr2.Close();
+	pmval.Close();
+	pmval2.Close();
+	pmkeys.Close();
+	prime_map.Close();
+	primes.Close();
+	all.Close();
+
+	INTSET(m);
+	Populate(all,2,1000,1);
+
+	NAMESET(pr3);
+	NAMESET(nm);
+	UnionMap<TInt,TTestName>(pr3, all, to_words);
+	all.Close();
+	CCheck(pr3);
+
+	Populate(m,4,1000,2);
+	UnionMap<TInt,TTestName>(nm, m, to_words);
+	m.Close();
+	Subtract(pr3, nm);
+	nm.Close();
+
+	Populate(m,6,1000,3);
+	UnionMap<TInt,TTestName>(nm, m, to_words);
+	m.Close();
+	Subtract(pr3, nm);
+	nm.Close();
+
+	Populate(m,10,1000,5);
+	UnionMap<TInt,TTestName>(nm, m, to_words);
+	m.Close();
+	Subtract(pr3, nm);
+	nm.Close();
+
+	Populate(m,14,1000,7);
+	UnionMap<TInt,TTestName>(nm, m, to_words);
+	m.Close();
+	Subtract(pr3, nm);
+	nm.Close();
+
+	Populate(m,22,1000,11);
+	UnionMap<TInt,TTestName>(nm, m, to_words);
+	m.Close();
+	Subtract(pr3, nm);
+	nm.Close();
+
+	Populate(m,26,1000,13);
+	UnionMap<TInt,TTestName>(nm, m, to_words);
+	m.Close();
+	Subtract(pr3, nm);
+	nm.Close();
+
+	Populate(m,34,1000,17);
+	UnionMap<TInt,TTestName>(nm, m, to_words);
+	m.Close();
+	Subtract(pr3, nm);
+	nm.Close();
+
+	Populate(m,38,1000,19);
+	UnionMap<TInt,TTestName>(nm, m, to_words);
+	m.Close();
+	Subtract(pr3, nm);
+	nm.Close();
+
+	Populate(m,46,1000,23);
+	UnionMap<TInt,TTestName>(nm, m, to_words);
+	m.Close();
+	Subtract(pr3, nm);
+	nm.Close();
+
+	Populate(m,58,1000,29);
+	UnionMap<TInt,TTestName>(nm, m, to_words);
+	m.Close();
+	Subtract(pr3, nm);
+	nm.Close();
+
+	Populate(m,62,1000,31);
+	UnionMap<TInt,TTestName>(nm, m, to_words);
+	m.Close();
+	Subtract(pr3, nm);
+	nm.Close();
+
+//	Print("pr3",pr3);
+	PrimeSieve(primes, 1, 1000);
+	UnionMap<TInt,TTestName>(nm, primes, to_words);
+	CheckIdentical(nm, pr3);
+	CCheck(pr3);
+	UnionMap<TTestName,TInt>(m, pr3, from_words);
+	CheckIdentical(m, primes);
+
+	m.Close();
+	nm.Close();
+	primes.Close();
+	pr3.Close();
+	from_words.Close();
+	to_words.Close();
+	}
+
+void PopulateArray8(TInt aMax)
+	{
+	TInt i;
+	for (i=0; i<aMax; ++i)
+		{
+		TTestName n(NumberInWords(i));
+		HBufC8* p = n.Alloc();
+		test(p!=0);
+		TInt r = DesC8Array.Append(p);
+		test(r==KErrNone);
+		}
+	}
+
+void PopulateArray16(TInt aMax)
+	{
+	TInt i;
+	for (i=0; i<aMax; ++i)
+		{
+		TTestName n(NumberInWords(i));
+		TBuf<128> n16;
+		n16.Copy(n);
+		HBufC16* p = n16.Alloc();
+		test(p!=0);
+		TInt r = DesC16Array.Append(p);
+		test(r==KErrNone);
+		}
+	}
+
+TUint32 istrh8(const TDesC8* const & a)
+	{
+	return DefaultHash::Des8(*a);
+	}
+
+TBool istrid8(const TDesC8* const & aA, const TDesC8* const & aB)
+	{
+	return *aA == *aB;
+	}
+
+TUint32 istrh16(const TDesC16* const & a)
+	{
+	return DefaultHash::Des16(*a);
+	}
+
+TBool istrid16(const TDesC16* const & aA, const TDesC16* const & aB)
+	{
+	return *aA == *aB;
+	}
+
+void TestPtrHashSet()
+	{
+	test.Next(_L("Test RPtrHashSet"));
+
+	STRSET8(s);
+	CCheck(s);		// check consistency for empty table
+	RHashMap<const TDesC8*, TInt> hm(&istrh8, &istrid8);
+	RPtrHashSet<TDesC8>::TIter iter(s);
+	const TDesC8* q;
+	TInt i;
+	for (i=0; i<4096; ++i)
+		{
+		TInt r = s.Insert(DesC8Array[i]);
+		test(r==KErrNone);
+		r = hm.Insert(DesC8Array[i], i);
+		test(r==KErrNone);
+		}
+	CCheck(s);
+	for (i=0; i<4100; ++i)
+		{
+		TTestName n(NumberInWords(i));
+		const TDesC8* p = s.Find(n);
+		if (i<4096)
+			{
+			const TDesC8& pp = s.FindL(n);
+			test(p && *p==n && p==DesC8Array[i]);
+			test(&pp == p);
+			}
+		else
+			{
+			test(!p);
+			TRAPD(rr,s.FindL(n));
+			test(rr==KErrNotFound);
+			}
+		}
+	while((q=iter.Next())!=0)
+		{
+		const TInt* qi = hm.Find(q);
+		test(qi!=0 && *qi>=0 && *qi<4096);
+		test(DesC8Array[*qi]==q);
+		}
+	for (i=0; i<4100; i+=2)
+		{
+		TTestName n(NumberInWords(i));
+		TInt r = s.Remove(&n);
+		if (i<4096)
+			test(r==KErrNone);
+		else
+			test(r==KErrNotFound);
+		}
+	test(s.Count()==2048);
+	CCheck(s);
+	for (i=0; i<4100; ++i)
+		{
+		TTestName n(NumberInWords(i));
+		const TDesC8* p = s.Find(n);
+		if (i<4096 && (i&1))
+			test(p && *p==n && p==DesC8Array[i]);
+		else
+			test(!p);
+		}
+	iter.Reset();
+	while((q=iter.Next())!=0)
+		{
+		const TInt* qi = hm.Find(q);
+		test(qi!=0 && *qi>=0 && *qi<4096 && (*qi&1));
+		test(DesC8Array[*qi]==q);
+		}
+	for (i=2; i<4096; i+=4)
+		{
+		TInt r = s.Insert(DesC8Array[i]);
+		test(r==KErrNone);
+		}
+	test(s.Count()==3072);
+	CCheck(s);
+	for (i=0; i<4100; ++i)
+		{
+		TTestName n(NumberInWords(i));
+		const TDesC8* p = s.Find(n);
+		if (i<4096 && (i&3))
+			test(p && *p==n && p==DesC8Array[i]);
+		else
+			test(!p);
+		}
+	iter.Reset();
+	while((q=iter.Next())!=0)
+		{
+		const TInt* qi = hm.Find(q);
+		test(qi!=0 && *qi>=0 && *qi<4096 && (*qi&3));
+		test(DesC8Array[*qi]==q);
+		}
+	s.Close();
+
+	// test ResetAndDestroy
+	for (i=0; i<16; ++i)
+		{
+		TInt r = s.Insert(DesC8Array[i]->Alloc());
+		test(r==KErrNone);
+		}
+	iter.Reset();
+	while((q=iter.Next())!=0)
+		{
+		const TInt* qi = hm.Find(q);
+		test(qi!=0 && *qi>=0 && *qi<16);
+		test(*DesC8Array[*qi]==*q);
+		test(DesC8Array[*qi]!=q);
+		}
+	s.ResetAndDestroy();
+	hm.Close();
+
+
+	STRSET16(S);
+	RHashMap<const TDesC16*, TInt> HM(&istrh16, &istrid16);
+	RPtrHashSet<TDesC16>::TIter ITER(S);
+	const TDesC16* Q;
+	for (i=0; i<4096; ++i)
+		{
+		TInt r = S.Insert(DesC16Array[i]);
+		test(r==KErrNone);
+		r = HM.Insert(DesC16Array[i], i);
+		test(r==KErrNone);
+		}
+	CCheck(S);
+	for (i=0; i<4100; ++i)
+		{
+		TTestName n(NumberInWords(i));
+		TBuf<80> buf;
+		buf.Copy(n);
+		const TDesC16* p = S.Find(buf);
+		if (i<4096)
+			test(p && *p==buf && p==DesC16Array[i]);
+		else
+			test(!p);
+		}
+	while((Q=ITER.Next())!=0)
+		{
+		const TInt* qi = HM.Find(Q);
+		test(qi!=0 && *qi>=0 && *qi<4096);
+		test(DesC16Array[*qi]==Q);
+		}
+	for (i=0; i<4100; i+=2)
+		{
+		TTestName n(NumberInWords(i));
+		TBuf<80> buf;
+		buf.Copy(n);
+		TInt r = S.Remove(&buf);
+		if (i<4096)
+			test(r==KErrNone);
+		else
+			test(r==KErrNotFound);
+		}
+	test(S.Count()==2048);
+	CCheck(S);
+	for (i=0; i<4100; ++i)
+		{
+		TTestName n(NumberInWords(i));
+		TBuf<80> buf;
+		buf.Copy(n);
+		const TDesC16* p = S.Find(buf);
+		if (i<4096 && (i&1))
+			test(p && *p==buf && p==DesC16Array[i]);
+		else
+			test(!p);
+		}
+	ITER.Reset();
+	while((Q=ITER.Next())!=0)
+		{
+		const TInt* qi = HM.Find(Q);
+		test(qi!=0 && *qi>=0 && *qi<4096 && (*qi&1));
+		test(DesC16Array[*qi]==Q);
+		}
+	for (i=2; i<4096; i+=4)
+		{
+		TInt r = S.Insert(DesC16Array[i]);
+		test(r==KErrNone);
+		}
+	test(S.Count()==3072);
+	CCheck(S);
+	for (i=0; i<4100; ++i)
+		{
+		TTestName n(NumberInWords(i));
+		TBuf<80> buf;
+		buf.Copy(n);
+		const TDesC16* p = S.Find(buf);
+		if (i<4096 && (i&3))
+			test(p && *p==buf && p==DesC16Array[i]);
+		else
+			test(!p);
+		}
+	ITER.Reset();
+	while((Q=ITER.Next())!=0)
+		{
+		const TInt* qi = HM.Find(Q);
+		test(qi!=0 && *qi>=0 && *qi<4096 && (*qi&3));
+		test(DesC16Array[*qi]==Q);
+		}
+	S.Close();
+
+	// test ResetAndDestroy
+	for (i=0; i<16; ++i)
+		{
+		TInt r = S.Insert(DesC16Array[i]->Alloc());
+		test(r==KErrNone);
+		}
+	ITER.Reset();
+	while((Q=ITER.Next())!=0)
+		{
+		const TInt* qi = HM.Find(Q);
+		test(qi!=0 && *qi>=0 && *qi<16);
+		test(*DesC16Array[*qi]==*Q);
+		test(DesC16Array[*qi]!=Q);
+		}
+	S.ResetAndDestroy();
+	HM.Close();
+	}
+
+void TestPtrHashMap()
+	{
+	test.Next(_L("Test RPtrHashMap"));
+
+	STRMAP8(map);
+	CCheck(map);		// check consistency for empty table
+	STRMAP8(id);
+	TInt i;
+	for (i=0; i<4096; ++i)
+		{
+		TInt r = map.Insert(DesC8Array[i], DesC8Array[(i+1)&0xfff]);
+		test(r==KErrNone);
+		r = id.Insert(DesC8Array[i], DesC8Array[i]);
+		test(r==KErrNone);
+		}
+	for (i=0; i<4096; ++i)
+		{
+		const TDesC8* p = map.Find(*DesC8Array[i]);
+		test(p == DesC8Array[(i+1)&0xfff]);
+		const TDesC8& pp = map.FindL(*DesC8Array[i]);
+		test(&pp == p);
+		}
+	TRAPD(rr,map.FindL(_L8("two")));
+	test(rr==KErrNone);
+	TRAP(rr,map.FindL(_L8("twx")));
+	test(rr==KErrNotFound);
+	CCheck(map);
+	STRMAP8(map2);
+	STRMAP8(mapi);
+	STRMAP8(map3);
+	UnionInverse<TDesC8,TDesC8>(mapi, map);
+	UnionCompose<TDesC8,TDesC8,TDesC8>(map2, map, map);
+	UnionCompose<TDesC8,TDesC8,TDesC8>(map3, map, mapi);
+	CheckIdenticalMaps<TDesC8,TDesC8>(map3, id);
+	map3.Close();
+	UnionCompose<TDesC8,TDesC8,TDesC8>(map3, map2, mapi);
+	CheckIdenticalMaps<TDesC8,TDesC8>(map3, map);
+	map3.Close();
+	for (i=0; i<4096; ++i)
+		{
+		TInt r = map3.Insert(DesC8Array[i], DesC8Array[(i+2)&0xfff]);
+		test(r==KErrNone);
+		}
+	CheckIdenticalMaps<TDesC8,TDesC8>(map3, map2);
+	map3.Close();
+
+	mapi.Close();
+	map2.Close();
+	id.Close();
+	map.Close();
+
+	// test ResetAndDestroy()
+	for(i=0; i<16; ++i)
+		{
+		TInt r = map.Insert(DesC8Array[i]->Alloc(), DesC8Array[i*i]->Alloc());
+		test(r==KErrNone);
+		}
+	map.ResetAndDestroy();
+	}
+
+void TestOOM()
+	{
+	// Max out memory and check it still works
+	test.Next(_L("Test OOM"));
+
+	TInt x = 0;
+	TInt n = 0;
+	TInt r;
+	INTSET(set);
+	FOREVER
+		{
+		x += 0x58b90bfb;
+		r = set.Insert(x);
+		if (r != KErrNone)
+			break;
+		++n;
+		}
+	test(r==KErrNoMemory);
+	TRAPD(rr,set.InsertL(x));
+	test(rr==KErrNoMemory);
+	test.Printf(_L("%d integers stored\n"), n);
+	test(set.Count()==n);
+	TRAP(rr,set.InsertL(0x58b90bfb));	// already there
+	test(rr==KErrNone);	// should succeed
+
+	// final count should be a power of 2 minus 1
+	test( (n&(n+1)) == 0 );
+
+	x = 0;
+	TInt i;
+	for (i=0; i<=n; ++i)		// check everything has been stored correctly
+		{
+		x += 0x58b90bfb;
+		const TInt* p = set.Find(x);
+		if (i < n)
+			test(p && *p == x);
+		else
+			test(!p);
+		}
+	set.Close();
+	TInt nn;
+	for (nn=256; nn<=n+256; nn+=256)
+		{
+		r = set.Reserve(nn);
+		set.Close();
+		if (r!=KErrNone)
+			break;
+		}
+	test.Printf(_L("Max reserve %d\n"),nn);
+	TInt thresh = 3*((n+1)>>2);
+	test(nn == thresh + 256);
+	}
+
+class RDummyAllocator : public RAllocator
+	{
+public:
+	virtual TAny* Alloc(TInt) {test(0); return 0;}
+	virtual void Free(TAny*) {test(0);}
+	virtual TAny* ReAlloc(TAny*, TInt, TInt) {test(0); return 0;}
+	virtual TInt AllocLen(const TAny*) const  {test(0); return 0;}
+	virtual TInt Compress() {test(0); return 0;}
+	virtual void Reset() {test(0);}
+	virtual TInt AllocSize(TInt&) const  {test(0); return 0;}
+	virtual TInt Available(TInt&) const  {test(0); return 0;}
+	virtual TInt DebugFunction(TInt, TAny*, TAny*) {test(0); return 0;}
+	virtual TInt Extension_(TUint, TAny*&, TAny*) {test(0); return 0;}
+	};
+
+void IntegerBenchmark(TInt aCount, TBool aReserve)
+	{
+	RArray<TInt> array;
+	TUint32 before, after, diff;
+	TInt x=0;
+	TInt i;
+	double avg;
+
+	test.Printf(_L("**** INTEGER BENCHMARKS ***\n"));
+
+	if (!aReserve)
+		{
+		before = User::NTickCount();
+		for (i=0; i<aCount; ++i)
+			{
+			x += 0x58b90bfb;
+			TInt r = array.InsertInOrder(x);
+			test(r==KErrNone);
+			}
+		after = User::NTickCount();
+		diff = after - before;
+		diff *= NanoTickPeriod;
+		avg = (double)diff / (double)aCount;
+		test.Printf(_L("ARRAY:      %d insertions take %dus (%.2gus each)\n"), aCount, diff, avg);
+
+		x=0;
+		before = User::NTickCount();
+		for (i=0; i<aCount; ++i)
+			{
+			x += 0x58b90bfb;
+			TInt r = array.FindInOrder(x);
+			test(r>=0);
+			}
+		after = User::NTickCount();
+		diff = after - before;
+		diff *= NanoTickPeriod;
+		avg = (double)diff / (double)aCount;
+		test.Printf(_L("ARRAY:      %d successful finds take %dus (%.2gus each)\n"), aCount, diff, avg);
+
+		before = User::NTickCount();
+		for (i=0; i<aCount; ++i)
+			{
+			x += 0x58b90bfb;
+			TInt r = array.FindInOrder(x);
+			test(r==KErrNotFound);
+			}
+		after = User::NTickCount();
+		diff = after - before;
+		diff *= NanoTickPeriod;
+		avg = (double)diff / (double)aCount;
+		test.Printf(_L("ARRAY:      %d unsuccessful finds take %dus (%.2gus each)\n"), aCount, diff, avg);
+
+		x=0;
+		before = User::NTickCount();
+		for (i=0; i<aCount; ++i)
+			{
+			x += 0x58b90bfb;
+			TInt r = array.FindInOrder(x);
+			test(r>=0);
+			array.Remove(r);
+			}
+		after = User::NTickCount();
+		diff = after - before;
+		diff *= NanoTickPeriod;
+		avg = (double)diff / (double)aCount;
+		test.Printf(_L("ARRAY:      %d deletions take %dus (%.2gus each)\n"), aCount, diff, avg);
+		array.Close();
+		}
+
+	INTSET(set);
+	x=0;
+	RAllocator* pA = 0;
+	RDummyAllocator da;
+	if (aReserve)
+		{
+		test(set.Reserve(aCount)==KErrNone);
+		pA = User::SwitchAllocator(&da);			// check that no memory accesses occur
+		test(set.Reserve(10)==KErrNone);			// shouldn't need to do anything
+		test(set.Reserve(aCount/2)==KErrNone);		// shouldn't need to do anything
+		test(set.Reserve(aCount)==KErrNone);		// shouldn't need to do anything
+		}
+	before = User::NTickCount();
+	for (i=0; i<aCount; ++i)
+		{
+		x += 0x58b90bfb;
+		TInt r = set.Insert(x);	// we have no heap here so this tests that Reserve() has preallocated sufficient memory
+		test(r==KErrNone);
+		}
+	after = User::NTickCount();
+	diff = after - before;
+	diff *= NanoTickPeriod;
+	avg = (double)diff / (double)aCount;
+	if (aReserve)
+		User::SwitchAllocator(pA);
+	test.Printf(_L("HASH TABLE: %d insertions take %dus (%.2gus each)\n"), aCount, diff, avg);
+
+	x=0;
+	before = User::NTickCount();
+	for (i=0; i<aCount; ++i)
+		{
+		x += 0x58b90bfb;
+		const TInt* p = set.Find(x);
+		test(p!=0);
+		}
+	after = User::NTickCount();
+	diff = after - before;
+	diff *= NanoTickPeriod;
+	avg = (double)diff / (double)aCount;
+	test.Printf(_L("HASH TABLE: %d successful finds take %dus (%.2gus each)\n"), aCount, diff, avg);
+
+	before = User::NTickCount();
+	for (i=0; i<aCount; ++i)
+		{
+		x += 0x58b90bfb;
+		const TInt* p = set.Find(x);
+		test(!p);
+		}
+	after = User::NTickCount();
+	diff = after - before;
+	diff *= NanoTickPeriod;
+	avg = (double)diff / (double)aCount;
+	test.Printf(_L("HASH TABLE: %d unsuccessful finds take %dus (%.2gus each)\n"), aCount, diff, avg);
+
+	x=0;
+	before = User::NTickCount();
+	for (i=0; i<aCount; ++i)
+		{
+		x += 0x58b90bfb;
+		TInt r = set.Remove(x);
+		test(r==KErrNone);
+		}
+	after = User::NTickCount();
+	diff = after - before;
+	diff *= NanoTickPeriod;
+	avg = (double)diff / (double)aCount;
+	test.Printf(_L("HASH TABLE: %d deletions take %dus (%.2gus each)\n"), aCount, diff, avg);
+	set.Close();
+	}
+
+TInt des8order(const TDesC8& aA, const TDesC8& aB)
+	{
+	return aA.Compare(aB);
+	}
+
+void StringBenchmark8(TInt aCount, TBool aReserve)
+	{
+	RPointerArray<TDesC8> array;
+	TUint32 before, after, diff;
+	TInt x=0;
+	TInt i;
+	double avg;
+	const TDesC8** base = (const TDesC8**)&DesC8Array[0];
+	test(base[1331] == DesC8Array[1331]);
+
+	test.Printf(_L("**** 8 BIT STRING BENCHMARKS ***\n"));
+
+	if (!aReserve)
+		{
+		before = User::NTickCount();
+		for (i=0; i<aCount; ++i)
+			{
+			x = (x+4339)&0x3fff;
+			TInt r = array.InsertInOrder(base[x], &des8order);
+			test(r==KErrNone);
+			}
+		after = User::NTickCount();
+		diff = after - before;
+		diff *= NanoTickPeriod;
+		avg = (double)diff / (double)aCount;
+		test.Printf(_L("ARRAY:      %d insertions take %dus (%.2gus each)\n"), aCount, diff, avg);
+
+		x=0;
+		before = User::NTickCount();
+		for (i=0; i<aCount; ++i)
+			{
+			x = (x+4339)&0x3fff;
+			TInt r = array.FindInOrder(base[x], &des8order);
+			test(r>=0);
+			}
+		after = User::NTickCount();
+		diff = after - before;
+		diff *= NanoTickPeriod;
+		avg = (double)diff / (double)aCount;
+		test.Printf(_L("ARRAY:      %d successful finds take %dus (%.2gus each)\n"), aCount, diff, avg);
+
+		before = User::NTickCount();
+		for (i=0; i<aCount; ++i)
+			{
+			x = (x+4339)&0x3fff;
+			TInt r = array.FindInOrder(base[x], &des8order);
+			test(r==KErrNotFound);
+			}
+		after = User::NTickCount();
+		diff = after - before;
+		diff *= NanoTickPeriod;
+		avg = (double)diff / (double)aCount;
+		test.Printf(_L("ARRAY:      %d unsuccessful finds take %dus (%.2gus each)\n"), aCount, diff, avg);
+
+		x=0;
+		before = User::NTickCount();
+		for (i=0; i<aCount; ++i)
+			{
+			x = (x+4339)&0x3fff;
+			TInt r = array.FindInOrder(base[x], &des8order);
+			test(r>=0);
+			array.Remove(r);
+			}
+		after = User::NTickCount();
+		diff = after - before;
+		diff *= NanoTickPeriod;
+		avg = (double)diff / (double)aCount;
+		test.Printf(_L("ARRAY:      %d deletions take %dus (%.2gus each)\n"), aCount, diff, avg);
+		array.Close();
+		}
+
+	STRSET8(set);
+	x=0;
+	if (aReserve)
+		test(set.Reserve(aCount)==KErrNone);
+	before = User::NTickCount();
+	for (i=0; i<aCount; ++i)
+		{
+		x = (x+4339)&0x3fff;
+		TInt r = set.Insert(base[x]);
+		test(r==KErrNone);
+		}
+	after = User::NTickCount();
+	diff = after - before;
+	diff *= NanoTickPeriod;
+	avg = (double)diff / (double)aCount;
+	test.Printf(_L("HASH TABLE: %d insertions take %dus (%.2gus each)\n"), aCount, diff, avg);
+
+	x=0;
+	before = User::NTickCount();
+	for (i=0; i<aCount; ++i)
+		{
+		x = (x+4339)&0x3fff;
+		const TDesC8* p = set.Find(*base[x]);
+		test(p!=0);
+		}
+	after = User::NTickCount();
+	diff = after - before;
+	diff *= NanoTickPeriod;
+	avg = (double)diff / (double)aCount;
+	test.Printf(_L("HASH TABLE: %d successful finds take %dus (%.2gus each)\n"), aCount, diff, avg);
+
+	before = User::NTickCount();
+	for (i=0; i<aCount; ++i)
+		{
+		x = (x+4339)&0x3fff;
+		const TDesC8* p = set.Find(*base[x]);
+		test(!p);
+		}
+	after = User::NTickCount();
+	diff = after - before;
+	diff *= NanoTickPeriod;
+	avg = (double)diff / (double)aCount;
+	test.Printf(_L("HASH TABLE: %d unsuccessful finds take %dus (%.2gus each)\n"), aCount, diff, avg);
+
+	x=0;
+	before = User::NTickCount();
+	for (i=0; i<aCount; ++i)
+		{
+		x = (x+4339)&0x3fff;
+		TInt r = set.Remove(base[x]);
+		test(r==KErrNone);
+		}
+	after = User::NTickCount();
+	diff = after - before;
+	diff *= NanoTickPeriod;
+	avg = (double)diff / (double)aCount;
+	test.Printf(_L("HASH TABLE: %d deletions take %dus (%.2gus each)\n"), aCount, diff, avg);
+	set.Close();
+	}
+
+TInt des16order(const TDesC16& aA, const TDesC16& aB)
+	{
+	return aA.Compare(aB);
+	}
+
+void StringBenchmark16(TInt aCount, TBool aReserve)
+	{
+	RPointerArray<TDesC16> array;
+	TUint32 before, after, diff;
+	TInt x=0;
+	TInt i;
+	double avg;
+	const TDesC16** base = (const TDesC16**)&DesC16Array[0];
+	test(base[1331] == DesC16Array[1331]);
+
+	test.Printf(_L("**** 16 BIT STRING BENCHMARKS ***\n"));
+
+	if (!aReserve)
+		{
+		before = User::NTickCount();
+		for (i=0; i<aCount; ++i)
+			{
+			x = (x+4339)&0x3fff;
+			TInt r = array.InsertInOrder(base[x], &des16order);
+			test(r==KErrNone);
+			}
+		after = User::NTickCount();
+		diff = after - before;
+		diff *= NanoTickPeriod;
+		avg = (double)diff / (double)aCount;
+		test.Printf(_L("ARRAY:      %d insertions take %dus (%.2gus each)\n"), aCount, diff, avg);
+
+		x=0;
+		before = User::NTickCount();
+		for (i=0; i<aCount; ++i)
+			{
+			x = (x+4339)&0x3fff;
+			TInt r = array.FindInOrder(base[x], &des16order);
+			test(r>=0);
+			}
+		after = User::NTickCount();
+		diff = after - before;
+		diff *= NanoTickPeriod;
+		avg = (double)diff / (double)aCount;
+		test.Printf(_L("ARRAY:      %d successful finds take %dus (%.2gus each)\n"), aCount, diff, avg);
+
+		before = User::NTickCount();
+		for (i=0; i<aCount; ++i)
+			{
+			x = (x+4339)&0x3fff;
+			TInt r = array.FindInOrder(base[x], &des16order);
+			test(r==KErrNotFound);
+			}
+		after = User::NTickCount();
+		diff = after - before;
+		diff *= NanoTickPeriod;
+		avg = (double)diff / (double)aCount;
+		test.Printf(_L("ARRAY:      %d unsuccessful finds take %dus (%.2gus each)\n"), aCount, diff, avg);
+
+		x=0;
+		before = User::NTickCount();
+		for (i=0; i<aCount; ++i)
+			{
+			x = (x+4339)&0x3fff;
+			TInt r = array.FindInOrder(base[x], &des16order);
+			test(r>=0);
+			array.Remove(r);
+			}
+		after = User::NTickCount();
+		diff = after - before;
+		diff *= NanoTickPeriod;
+		avg = (double)diff / (double)aCount;
+		test.Printf(_L("ARRAY:      %d deletions take %dus (%.2gus each)\n"), aCount, diff, avg);
+		array.Close();
+		}
+
+	STRSET16(set);
+	x=0;
+	if (aReserve)
+		test(set.Reserve(aCount)==KErrNone);
+	before = User::NTickCount();
+	for (i=0; i<aCount; ++i)
+		{
+		x = (x+4339)&0x3fff;
+		TInt r = set.Insert(base[x]);
+		test(r==KErrNone);
+		}
+	after = User::NTickCount();
+	diff = after - before;
+	diff *= NanoTickPeriod;
+	avg = (double)diff / (double)aCount;
+	test.Printf(_L("HASH TABLE: %d insertions take %dus (%.2gus each)\n"), aCount, diff, avg);
+
+	x=0;
+	before = User::NTickCount();
+	for (i=0; i<aCount; ++i)
+		{
+		x = (x+4339)&0x3fff;
+		const TDesC16* p = set.Find(*base[x]);
+		test(p!=0);
+		}
+	after = User::NTickCount();
+	diff = after - before;
+	diff *= NanoTickPeriod;
+	avg = (double)diff / (double)aCount;
+	test.Printf(_L("HASH TABLE: %d successful finds take %dus (%.2gus each)\n"), aCount, diff, avg);
+
+	before = User::NTickCount();
+	for (i=0; i<aCount; ++i)
+		{
+		x = (x+4339)&0x3fff;
+		const TDesC16* p = set.Find(*base[x]);
+		test(!p);
+		}
+	after = User::NTickCount();
+	diff = after - before;
+	diff *= NanoTickPeriod;
+	avg = (double)diff / (double)aCount;
+	test.Printf(_L("HASH TABLE: %d unsuccessful finds take %dus (%.2gus each)\n"), aCount, diff, avg);
+
+	x=0;
+	before = User::NTickCount();
+	for (i=0; i<aCount; ++i)
+		{
+		x = (x+4339)&0x3fff;
+		TInt r = set.Remove(base[x]);
+		test(r==KErrNone);
+		}
+	after = User::NTickCount();
+	diff = after - before;
+	diff *= NanoTickPeriod;
+	avg = (double)diff / (double)aCount;
+	test.Printf(_L("HASH TABLE: %d deletions take %dus (%.2gus each)\n"), aCount, diff, avg);
+	set.Close();
+	}
+
+void Benchmark()
+	{
+	test.Next(_L("Benchmarks ..."));
+
+	IntegerBenchmark(1000, EFalse);
+	IntegerBenchmark(1000, ETrue);
+	IntegerBenchmark(2000, EFalse);
+	IntegerBenchmark(2000, ETrue);
+	IntegerBenchmark(4000, EFalse);
+	IntegerBenchmark(4000, ETrue);
+	IntegerBenchmark(8000, EFalse);
+	IntegerBenchmark(8000, ETrue);
+	IntegerBenchmark(16000, EFalse);
+	IntegerBenchmark(16000, ETrue);
+	IntegerBenchmark(32000, EFalse);
+	IntegerBenchmark(32000, ETrue);
+
+	PopulateArray8(16384);
+	StringBenchmark8(1000, EFalse);
+	StringBenchmark8(2000, EFalse);
+	StringBenchmark8(4000, EFalse);
+	StringBenchmark8(8000, EFalse);
+	DesC8Array.ResetAndDestroy();
+
+	PopulateArray16(16384);
+	StringBenchmark16(1000, EFalse);
+	StringBenchmark16(2000, EFalse);
+	StringBenchmark16(4000, EFalse);
+	StringBenchmark16(8000, EFalse);
+	DesC16Array.ResetAndDestroy();
+	}
+
+
+TUint32 mp(TUint32 x)
+	{
+	TUint32 x3 = x+(x<<1);
+	TUint32 x7 = x+(x3<<1);
+	TUint32 x15 = x+(x7<<1);
+	TUint32 y = x + (x7<<3) + (x3<<7) + (x15<<11) + (x7<<16) + (x3<<20) + (x15<<25) + (x<<31);
+	return y;
+	}
+
+TUint32 strh(const char* aIn)
+	{
+	TUint32 h = 0;
+	TInt i = 0;
+	while (*aIn)
+		{
+		if (i==0)
+			h = mp(h);
+		TUint32 c = *aIn++;
+		c <<= (8*i);
+		h ^= c;
+		i = (i+1)&3;
+		}
+	return mp(h);
+	}
+
+TUint32 strh(const wch* aIn)
+	{
+	TUint32 h = 0;
+	TInt i = 0;
+	while (*aIn)
+		{
+		if (i==0)
+			h = mp(h);
+		TUint32 c = *aIn++;
+		switch (i)
+			{
+			case 0:		break;
+			case 1:		c<<=16; break;
+			case 2:		c<<=8; break;
+			default:	c=(c<<24)|(c>>8); break;
+			};
+		h ^= c;
+		i = (i+1)&3;
+		}
+	return mp(h);
+	}
+
+void TestHash(TInt* aIn, TUint32 aExpected)
+	{
+	THashFunction32<TInt*> hf(&DefaultHash::IntegerPtr);
+	TUint32 out = hf.Hash(aIn);
+	test(aExpected == mp((TUint32)aIn));
+	if (out != aExpected)
+		{
+		test.Printf(_L("Hashing %08x Expected %08x Got %08x\n"), aIn, aExpected, out);
+		test(0);
+		}
+	}
+
+void TestHash(TDesC8* aIn, TUint32 aExpected)
+	{
+	THashFunction32<TDesC8*> hf(&DefaultHash::Des8Ptr);
+	TUint32 out = hf.Hash(aIn);
+	test(aExpected == mp((TUint32)aIn));
+	if (out != aExpected)
+		{
+		test.Printf(_L("Hashing %08x Expected %08x Got %08x\n"), aIn, aExpected, out);
+		test(0);
+		}
+	}
+
+void TestHash(TDesC16* aIn, TUint32 aExpected)
+	{
+	THashFunction32<TDesC16*> hf(&DefaultHash::Des16Ptr);
+	TUint32 out = hf.Hash(aIn);
+	test(aExpected == mp((TUint32)aIn));
+	if (out != aExpected)
+		{
+		test.Printf(_L("Hashing %08x Expected %08x Got %08x\n"), aIn, aExpected, out);
+		test(0);
+		}
+	}
+
+
+void TestHash(TInt aIn, TUint32 aExpected)
+	{
+	THashFunction32<TInt> hf(&DefaultHash::Integer);
+	TUint32 out = hf.Hash(aIn);
+	test(aExpected == mp((TUint32)aIn));
+	if (out != aExpected)
+		{
+		test.Printf(_L("Hashing %08x Expected %08x Got %08x\n"), aIn, aExpected, out);
+		test(0);
+		}
+	}
+
+void TestHash(const char* aIn, TUint32 aExpected)
+	{
+	THashFunction32<TDesC8> hf(&DefaultHash::Des8);
+	TPtrC8 p((const TUint8*)aIn);
+	TUint32 out = hf.Hash(p);
+	test(aExpected == strh(aIn));
+	if (out != aExpected)
+		{
+		TBuf<256> buf;
+		buf.Copy(p);
+		test.Printf(_L("Hashing %S (len %d) Expected %08x Got %08x\n"), &buf, p.Length(), aExpected, out);
+		test(0);
+		}
+	}
+
+void TestHash(const wch* aIn)
+	{
+	THashFunction32<TDesC16> hf(&DefaultHash::Des16);
+	TPtrC16 p((const TUint16*)aIn);
+	TUint32 out = hf.Hash(p);
+	TUint32 exp = strh(aIn);
+	if (out != exp)
+		{
+		test.Printf(_L("Hashing %S (len %d) Expected %08x Got %08x\n"), &p, p.Size(), exp, out);
+		test(0);
+		}
+	}
+
+void TestHash()
+	{
+	test.Next(_L("Test integer hash"));
+	TestHash(1,0x9e3779b9);
+	TestHash(2,0x3c6ef372);
+	TestHash(4,0x78dde6e4);
+	TestHash(8,0xf1bbcdc8);
+	TestHash(16,0xe3779b90);
+	TestHash(0xc90fdaa2,0xbf999112);
+	TestHash(0xb504f334,0x7fb35494);
+	TestHash(0xddb3d743,0xd11a3a6b);
+	TestHash(0xadf85458,0x873a8b98);
+	TestHash(0x11730859,0xb4321951);
+	TestHash(0x64636261,0x8628f119);
+	}
+
+void TestIntegerPtrHash()
+	{
+	TInt i[5];
+	TInt* ptr;
+	test.Next(_L("Test Integer pointer hash"));
+	for (ptr=i; ptr<i+5; ptr++)
+		{
+		TestHash(ptr, DefaultHash::IntegerPtr(ptr));
+		}
+	}
+
+void TestDes8PtrHash()
+	{
+	TBuf8<8> i[5];
+	TDesC8* ptr;
+	test.Next(_L("Test Des8 pointer hash"));
+	for (ptr=i; ptr<i+5; ptr++)
+		{
+		TestHash(ptr, DefaultHash::Des8Ptr(ptr));
+		}
+	}
+
+void TestDes16PtrHash()
+	{
+	TBuf16<8> i[5];
+	TDesC16* ptr;
+	test.Next(_L("Test Des16 pointer hash"));
+	for (ptr=i; ptr<i+5; ptr++)
+		{
+		TestHash(ptr, DefaultHash::Des16Ptr(ptr));
+		}
+	}
+
+const char teststr[] = "zyxwvutsrq";
+void TestStringHash()
+	{
+	test.Next(_L("Test 8 bit string hash"));
+	TestHash("",0x0);
+	TestHash("a",0xf3051f19);
+	TestHash("b",0x913c98d2);
+	TestHash("ab",0x2f9df119);
+	TestHash("ba",0x965bb1d2);
+	TestHash("abc",0x4228f119);
+	TestHash("abcd",0x8628f119);
+	TestHash("abcde",0xb75e1e9c);
+	TestHash("abcdef",0x3693149c);
+	TestHash("abcdefg",0xc1c2149c);
+	TestHash("abcdefgh",0xe9c2149c);
+	TestHash("abcdefghi",0x5fcbf20d);
+	TestHash("abcdefghj",0xfe036bc6);
+
+	TestHash(teststr, 0x108ca51e);
+	TestHash(teststr+1, 0x551002ad);
+	TestHash(teststr+2, 0x37dc0d6c);
+	TestHash(teststr+3, 0x2937f92c);
+	TestHash(teststr+4, 0xf0818a94);
+	TestHash(teststr+5, 0xb1b25f1c);
+	TestHash(teststr+6, 0x7a3342d4);
+	TestHash(teststr+7, 0x81c9101b);
+	TestHash(teststr+8, 0xf16edd62);
+	TestHash(teststr+9, 0xd67cbaa9);
+	TestHash(teststr+10, 0);
+
+	char t[16];
+	int i,j;
+	for (i=0; i<=4; ++i)
+		{
+		for (j=0; j<=10; ++j)
+			{
+			const char* s = teststr + j;
+			int l = User::StringLength((const TUint8*)s);
+			memset(t, 0xbb, 16);
+			memcpy(t+i, s, l+1);
+			TUint32 h;
+			switch (j)
+				{
+				case 0: h = 0x108ca51e; break;
+				case 1: h = 0x551002ad; break;
+				case 2: h = 0x37dc0d6c; break;
+				case 3: h = 0x2937f92c; break;
+				case 4: h = 0xf0818a94; break;
+				case 5: h = 0xb1b25f1c; break;
+				case 6: h = 0x7a3342d4; break;
+				case 7: h = 0x81c9101b; break;
+				case 8: h = 0xf16edd62; break;
+				case 9: h = 0xd67cbaa9; break;
+				default: h = 0; break;
+				};
+			TestHash(t+i, h);
+			}
+		}
+	}
+
+const wch wteststr[] = L"zyxwvutsrq";
+void TestWStringHash()
+	{
+	test.Next(_L("Test 16 bit string hash"));
+	TestHash(L"");
+	TestHash(L"a");
+	TestHash(L"b");
+	TestHash(L"ab");
+	TestHash(L"ba");
+	TestHash(L"abc");
+	TestHash(L"abcd");
+	TestHash(L"abcde");
+	TestHash(L"abcdef");
+	TestHash(L"abcdefg");
+	TestHash(L"abcdefgh");
+	TestHash(L"abcdefghi");
+	TestHash(L"abcdefghj");
+
+	TestHash(wteststr);
+	TestHash(wteststr+1);
+	TestHash(wteststr+2);
+	TestHash(wteststr+3);
+	TestHash(wteststr+4);
+	TestHash(wteststr+5);
+	TestHash(wteststr+6);
+	TestHash(wteststr+7);
+	TestHash(wteststr+8);
+	TestHash(wteststr+9);
+	TestHash(wteststr+10);
+
+	wch t[16];
+	int i,j;
+	for (i=0; i<=4; ++i)
+		{
+		for (j=0; j<=10; ++j)
+			{
+			const wch* s = wteststr + j;
+			int l = User::StringLength((const TUint16*)s);
+			memset(t, 0xbb, 2*16);
+			memcpy(t+i, s, 2*(l+1));
+			TestHash(t+i);
+			}
+		}
+	}
+template <class K,class V> 
+void TestHashMapPtr(RHashMap<K,V> &map, K ptr, V* i)
+{
+	test(map.Reserve(5) == KErrNone);
+	for (ptr=i;ptr<i+5;ptr++)
+		{
+		test(map.Insert(ptr,*ptr) == KErrNone);
+		}
+	for (ptr=i+4;ptr>=i;ptr--)
+		{
+		test(*(map.Find(ptr)) == *ptr);
+		}
+	test(map.Count() == 5);
+	test(map.Remove(i) == KErrNone);
+	test(map.Count()==4);
+	test(map.Find(i)==NULL);
+	map.Close();
+}
+
+void TestPtrHashMaps()
+	{	
+
+	test.Next(_L("Test RHashMap of default pointer types"));
+	TInt i[5];
+	TInt *ptr=i;
+	RHashMap<TInt*,TInt> mp;
+	TestHashMapPtr(mp, ptr, i);
+
+	TInt32 i1[5];
+	TInt32 *ptr1=i1;
+	RHashMap<TInt32*,TInt32> mp1;
+	TestHashMapPtr(mp1,ptr1,i1);
+	
+	TUint i2[5];
+	TUint *ptr2=i2;
+	RHashMap<TUint*,TUint> mp2;
+	TestHashMapPtr(mp2,ptr2,i2);
+
+	TUint32 i3[5];
+	TUint32 *ptr3=i3;
+	RHashMap<TUint32*,TUint32> mp3;
+	TestHashMapPtr(mp3,ptr3,i3);
+
+	TBuf8<5> i4[5];
+	TBuf8<5> *ptr4=i4;
+	RHashMap<TDesC8*,TDesC8> mp4;
+	for (ptr4=i4; ptr4 < i4+5; ptr4++) 
+		{
+		test(mp4.Insert(ptr4,*ptr4) == KErrNone);
+		}
+	for (ptr4=i4+4; ptr4 >= i4; ptr4--) 
+		{
+		test(*(mp4.Find(ptr4)) == *ptr4);
+		}
+	test(mp4.Count()==5);
+	test(mp4.Remove(i4) == KErrNone);
+	test(mp4.Find(i4) == NULL);
+	test(mp4.Count()==4);
+	mp4.Close();
+
+
+	TBuf16<5> i5[5];
+	TBuf16<5> *ptr5=i5;
+	RHashMap<TDesC16*,TDesC16> mp5;
+	for (ptr5=i5; ptr5 < i5+5; ptr5++) 
+		{
+		test(mp5.Insert(ptr5,*ptr5) == KErrNone);
+		}
+	for (ptr5=i5+4; ptr5 >= i5; ptr5--) 
+		{
+		test(*(mp5.Find(ptr5)) == *ptr5);
+		}
+	test(mp5.Count()==5);
+	test(mp5.Remove(i5) == KErrNone);
+	test(mp5.Find(i5) == NULL);
+	test(mp5.Count()==4);
+	mp5.Close();
+	
+}
+
+/** Tests that Reserve() will always allocate memory for new tables 
+	even for small reserve sizes
+	See DEF087906.
+*/
+void TestSmallReserve()
+	{
+	test.Next(_L("Test RHashTableBase::Reserve preallocates memory, even for small no of elements"));
+	RAllocator* pA = 0;
+	RDummyAllocator da;
+	
+	// Reserve should allocate the memory required for the table of 1 element
+	INTSET(set);
+	RHashMap<TInt,TInt> hashMap;
+	
+	test(set.Reserve(1) == KErrNone);
+	test(hashMap.Reserve(1) == KErrNone);
+	
+	pA = User::SwitchAllocator(&da);
+	
+	// No more memory should be allocated for the table as it should
+	// have been already allocated by Reserve()
+	test(set.Insert(123) == KErrNone);
+	test(hashMap.Insert(123,456) == KErrNone);
+	
+	// Switch back to allow set to be closed
+	User::SwitchAllocator(pA);
+	set.Close();
+	hashMap.Close();
+	}
+	
+
+TInt E32Main()
+	{
+	test.Title();
+
+	test(HAL::Get(HAL::ENanoTickPeriod, NanoTickPeriod)==KErrNone);
+	test.Printf(_L("NanoTickPeriod %dus\n"), NanoTickPeriod);
+
+	__UHEAP_MARK;
+
+	test.Start(_L("Testing hash tables"));
+
+	TestHash();
+	TestStringHash();
+	TestWStringHash();
+	TestIntegerPtrHash();
+	TestDes8PtrHash();
+	TestDes16PtrHash();
+
+	TestHashSet();
+	TestHashIter();
+	TestHashMap();
+	TestPtrHashMaps();
+
+	PopulateArray8(4096);
+	PopulateArray16(4096);
+	TestPtrHashSet();
+	TestPtrHashMap();
+	DesC16Array.ResetAndDestroy();
+	DesC8Array.ResetAndDestroy();
+
+
+	TestOOM();
+	Benchmark();
+	TestSmallReserve();
+
+	test.End();
+
+	__UHEAP_MARKEND;
+	return 0;
+	}