diff -r c55016431358 -r 0a7b44b10206 symport/e32test/buffer/t_hashtab.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/symport/e32test/buffer/t_hashtab.cpp Thu Jun 25 15:59:54 2009 +0100 @@ -0,0 +1,2439 @@ +// 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 "Symbian Foundation License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// e32test/buffer/t_hashtab.cpp +// +// + +#include +#include +#include + +#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 TIntSet; +typedef RHashSet TNameSet; +typedef RPtrHashSet TStringSet8; +typedef RPtrHashSet TStringSet16; +typedef RPtrHashMap TStringMap8; +typedef RPtrHashMap 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 DesC8Array; +RPointerArray 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 + ******************************************************************************/ +template +void Union(RHashSet& aD, const RHashSet& aS) + { + TInt c = aS.Count(); + TInt c2 = c; + TInt d0 = aD.Count(); + TInt d1 = d0; + typename RHashSet::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 +void Subtract(RHashSet& aD, const RHashSet& aS) + { + TInt c = aS.Count(); + TInt c2 = c; + TInt d0 = aD.Count(); + TInt d1 = d0; + TInt nfd = 0; + typename RHashSet::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 +void Intersect(RHashSet& aD, const RHashSet& aS) + { + typename RHashSet::TIter iD(aD); + FOREVER + { + const T* p = iD.Next(); + if (!p) + break; + if (!aS.Find(*p)) + iD.RemoveCurrent(); + } + } + +template +void CheckIdentical(const RHashSet& aA, const RHashSet& aB) + { + test(aA.Count()==aB.Count()); + TInt c = aA.Count(); + typename RHashSet::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::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 + ******************************************************************************/ +template +void Union(RPtrHashSet& aD, const RPtrHashSet& aS) + { + TInt c = aS.Count(); + TInt c2 = c; + TInt d0 = aD.Count(); + TInt d1 = d0; + typename RPtrHashSet::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 +void Subtract(RPtrHashSet& aD, const RPtrHashSet& aS) + { + TInt c = aS.Count(); + TInt c2 = c; + TInt d0 = aD.Count(); + TInt d1 = d0; + TInt nfd = 0; + typename RPtrHashSet::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 +void Intersect(RPtrHashSet& aD, const RPtrHashSet& aS) + { + typename RPtrHashSet::TIter iD(aD); + FOREVER + { + const T* p = iD.Next(); + if (!p) + break; + if (!aS.Find(*p)) + iD.RemoveCurrent(); + } + } + +template +void CheckIdentical(const RPtrHashSet& aA, const RPtrHashSet& aB) + { + test(aA.Count()==aB.Count()); + TInt c = aA.Count(); + typename RPtrHashSet::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::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 + ******************************************************************************/ +template +void UnionTransform(RHashMap& aD, const RHashSet& aS, V (*aTransform)(const K&) ) + { + TInt c = aS.Count(); + TInt c2 = c; + TInt d0 = aD.Count(); + TInt d1 = d0; + typename RHashSet::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 +void UnionMap(RHashSet& aD, const RHashSet& aS, const RHashMap& aM) + { + TInt c = aS.Count(); + TInt c2 = c; + TInt d0 = aD.Count(); + TInt d1 = d0; + typename RHashSet::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 +void UnionKeys(RHashSet& aD, const RHashMap& aM) + { + typename RHashMap::TIter iM(aM); + FOREVER + { + const K* p = iM.NextKey(); + if (!p) + break; + aD.Insert(*p); + } + } + + +template +void UnionValues(RHashSet& aD, const RHashMap& aM) + { + typename RHashMap::TIter iM(aM); + FOREVER + { + const K* p = iM.NextKey(); + if (!p) + break; + const V* q = iM.CurrentValue(); + aD.Insert(*q); + } + } + + +template +void UnionTransform(RHashMap& aD, const RHashMap& aS, V (*aTransform)(const V&) ) + { + TInt c = aS.Count(); + TInt c2 = c; + TInt d0 = aD.Count(); + TInt d1 = d0; + typename RHashMap::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 +void UnionInverse(RHashMap& aD, const RHashMap& aS) + { + TInt c = aS.Count(); + TInt c2 = c; + TInt d0 = aD.Count(); + TInt d1 = d0; + typename RHashMap::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 +void SetMap(RHashMap& aM, const V& aV) + { + typename RHashMap::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 + ******************************************************************************/ +template +void UnionTransform(RPtrHashMap& aD, const RPtrHashMap& aS, V* (*aTransform)(const V*) ) + { + TInt c = aS.Count(); + TInt c2 = c; + TInt d0 = aD.Count(); + TInt d1 = d0; + typename RPtrHashMap::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 +void UnionInverse(RPtrHashMap& aD, const RPtrHashMap& a1) + { + typename RPtrHashMap::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 +void UnionCompose(RPtrHashMap& aD, const RPtrHashMap& a1, const RPtrHashMap& a2) + { + typename RPtrHashMap::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 +void CheckIdenticalMaps(const RPtrHashMap& aA, const RPtrHashMap& aB) + { + test(aA.Count()==aB.Count()); + TInt c = aA.Count(); + const K* p; + const V* q; + typename RPtrHashMap::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::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::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::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< hs; // empty + RHashSet::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< 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& aM) + { + TBuf<256> buf; + buf.Copy(TPtrC8((const TUint8*)aTitle)); + test.Printf(_L("%S\n"), &buf); + RHashMap::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& aS) + { + TBuf<256> buf; + buf.Copy(TPtrC8((const TUint8*)aTitle)); + test.Printf(_L("%S\n"), &buf); + RHashSet::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 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(ht, 17); + + ht.Close(); + + PrintNumberInWords(2000); + PrintNumberInWords(2001); + PrintNumberInWords(131072); + PrintNumberInWords(111111); + PrintNumberInWords(524288); + + INTSET(all); + Populate(all,0,1000,1); + RHashMap to_words(&DefaultHash::Integer, &DefaultIdentity::Integer); + UnionTransform(to_words, all, &NumberInWords); + RHashMap from_words(&HashTestName, &TestNameIdentity); + UnionInverse(from_words, to_words); +// Print("TO WORDS:", to_words); + INTSET(primes); + PrimeSieve(primes, 1, 100); +// Print("Primes 1-100", primes); + RHashMap prime_map(&DefaultHash::Integer, &DefaultIdentity::Integer); + UnionTransform(prime_map, primes, &NumberInWords); +// Print("Prime map 1-100", prime_map); + INTSET(pmkeys); + UnionKeys(pmkeys, prime_map); + NAMESET(pmval); + NAMESET(pmval2); + UnionValues(pmval, prime_map); + CheckIdentical(pmkeys, primes); + INTSET(pr2); + UnionMap(pr2, pmval, from_words); + CheckIdentical(pr2, primes); + pr2.Close(); + Union(pmval2, pmval); +// Print("pmval",pmval); +// Print("pmval2",pmval2); + CheckIdentical(pmval2, pmval); + UnionMap(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(pr3, all, to_words); + all.Close(); + CCheck(pr3); + + Populate(m,4,1000,2); + UnionMap(nm, m, to_words); + m.Close(); + Subtract(pr3, nm); + nm.Close(); + + Populate(m,6,1000,3); + UnionMap(nm, m, to_words); + m.Close(); + Subtract(pr3, nm); + nm.Close(); + + Populate(m,10,1000,5); + UnionMap(nm, m, to_words); + m.Close(); + Subtract(pr3, nm); + nm.Close(); + + Populate(m,14,1000,7); + UnionMap(nm, m, to_words); + m.Close(); + Subtract(pr3, nm); + nm.Close(); + + Populate(m,22,1000,11); + UnionMap(nm, m, to_words); + m.Close(); + Subtract(pr3, nm); + nm.Close(); + + Populate(m,26,1000,13); + UnionMap(nm, m, to_words); + m.Close(); + Subtract(pr3, nm); + nm.Close(); + + Populate(m,34,1000,17); + UnionMap(nm, m, to_words); + m.Close(); + Subtract(pr3, nm); + nm.Close(); + + Populate(m,38,1000,19); + UnionMap(nm, m, to_words); + m.Close(); + Subtract(pr3, nm); + nm.Close(); + + Populate(m,46,1000,23); + UnionMap(nm, m, to_words); + m.Close(); + Subtract(pr3, nm); + nm.Close(); + + Populate(m,58,1000,29); + UnionMap(nm, m, to_words); + m.Close(); + Subtract(pr3, nm); + nm.Close(); + + Populate(m,62,1000,31); + UnionMap(nm, m, to_words); + m.Close(); + Subtract(pr3, nm); + nm.Close(); + +// Print("pr3",pr3); + PrimeSieve(primes, 1, 1000); + UnionMap(nm, primes, to_words); + CheckIdentical(nm, pr3); + CCheck(pr3); + UnionMap(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 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 hm(&istrh8, &istrid8); + RPtrHashSet::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 HM(&istrh16, &istrid16); + RPtrHashSet::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(mapi, map); + UnionCompose(map2, map, map); + UnionCompose(map3, map, mapi); + CheckIdenticalMaps(map3, id); + map3.Close(); + UnionCompose(map3, map2, mapi); + CheckIdenticalMaps(map3, map); + map3.Close(); + for (i=0; i<4096; ++i) + { + TInt r = map3.Insert(DesC8Array[i], DesC8Array[(i+2)&0xfff]); + test(r==KErrNone); + } + CheckIdenticalMaps(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); + } + +#ifndef __TOOLS2__ +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 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=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=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 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=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=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 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=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=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>8); break; + }; + h ^= c; + i = (i+1)&3; + } + return mp(h); + } + +void TestHash(TInt* aIn, TUint32 aExpected) + { + THashFunction32 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 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 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 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 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 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]; + TDesC8* ptr; + test.Next(_L("Test Des8 pointer hash")); + for (ptr=i; ptr i[5]; + TDesC16* ptr; + test.Next(_L("Test Des16 pointer hash")); + for (ptr=i; ptr +void TestHashMapPtr(RHashMap &map, K ptr, V* i) +{ + test(map.Reserve(5) == KErrNone); + for (ptr=i;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 mp; + TestHashMapPtr(mp, ptr, i); + + TInt32 i1[5]; + TInt32 *ptr1=i1; + RHashMap mp1; + TestHashMapPtr(mp1,ptr1,i1); + + TUint i2[5]; + TUint *ptr2=i2; + RHashMap mp2; + TestHashMapPtr(mp2,ptr2,i2); + + TUint32 i3[5]; + TUint32 *ptr3=i3; + RHashMap mp3; + TestHashMapPtr(mp3,ptr3,i3); + + TBuf8<5> i4[5]; + TBuf8<5> *ptr4=i4; + RHashMap 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 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. +*/ +#ifndef __TOOLS2__ +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 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(); + } +#endif + +TInt E32Main() + { + test.Title(); + +#ifndef __TOOLS2__ + test(HAL::Get(HAL::ENanoTickPeriod, NanoTickPeriod)==KErrNone); + test.Printf(_L("NanoTickPeriod %dus\n"), NanoTickPeriod); +#endif + + __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(); + + +#ifndef __TOOLS2__ + TestOOM(); + Benchmark(); + TestSmallReserve(); +#endif + + test.End(); + + __UHEAP_MARKEND; + return 0; + }