Back to index

lightning-sunbird  0.9+nobinonly
TestHashtables.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is C++ hashtable templates.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Benjamin Smedberg.
00019  * Portions created by the Initial Developer are Copyright (C) 2002
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "nsTHashtable.h"
00039 #include "nsBaseHashtable.h"
00040 #include "nsDataHashtable.h"
00041 #include "nsInterfaceHashtable.h"
00042 #include "nsClassHashtable.h"
00043 
00044 #include "nsCOMPtr.h"
00045 #include "nsISupports.h"
00046 #include "nsCRT.h"
00047 #include "nsCOMArray.h"
00048 
00049 class TestUniChar // for nsClassHashtable
00050 {
00051 public:
00052   TestUniChar(PRUint32 aWord)
00053   {
00054     printf("    TestUniChar::TestUniChar() %u\n", aWord);
00055     mWord = aWord;
00056   }
00057 
00058   ~TestUniChar()
00059   {
00060     printf("    TestUniChar::~TestUniChar() %u\n", mWord);
00061   }
00062 
00063   PRUint32 GetChar() const { return mWord; }
00064 
00065 private:
00066   PRUint32 mWord;
00067 };
00068 
00069 struct EntityNode {
00070   const char*   mStr; // never owns buffer
00071   PRUint32       mUnicode;
00072 };
00073 
00074 EntityNode gEntities[] = {
00075   {"nbsp",160},
00076   {"iexcl",161},
00077   {"cent",162},
00078   {"pound",163},
00079   {"curren",164},
00080   {"yen",165},
00081   {"brvbar",166},
00082   {"sect",167},
00083   {"uml",168},
00084   {"copy",169},
00085   {"ordf",170},
00086   {"laquo",171},
00087   {"not",172},
00088   {"shy",173},
00089   {"reg",174},
00090   {"macr",175}
00091 };
00092 
00093 #define ENTITY_COUNT (sizeof(gEntities)/sizeof(EntityNode))
00094 
00095 class EntityToUnicodeEntry : public PLDHashEntryHdr
00096 {
00097 public:
00098   typedef const char* KeyType;
00099   typedef const char* KeyTypePointer;
00100 
00101   EntityToUnicodeEntry(const char* aKey) { mNode = nsnull; }
00102   EntityToUnicodeEntry(const EntityToUnicodeEntry& aEntry) { mNode = aEntry.mNode; }
00103   ~EntityToUnicodeEntry() { };
00104 
00105   const char* GetKeyPointer() const { return mNode->mStr; }
00106   PRBool KeyEquals(const char* aEntity) const { return !strcmp(mNode->mStr, aEntity); }
00107   static const char* KeyToPointer(const char* aEntity) { return aEntity; }
00108   static PLDHashNumber HashKey(const char* aEntity) { return nsCRT::HashCode(aEntity); }
00109   enum { ALLOW_MEMMOVE = PR_TRUE };
00110 
00111   const EntityNode* mNode;
00112 };
00113 
00114 PLDHashOperator
00115 nsTEnumGo(EntityToUnicodeEntry* aEntry, void* userArg) {
00116   printf("  enumerated \"%s\" = %u\n", 
00117          aEntry->mNode->mStr, aEntry->mNode->mUnicode);
00118 
00119   return PL_DHASH_NEXT;
00120 }
00121 
00122 PLDHashOperator
00123 nsTEnumStop(EntityToUnicodeEntry* aEntry, void* userArg) {
00124   printf("  enumerated \"%s\" = %u\n",
00125          aEntry->mNode->mStr, aEntry->mNode->mUnicode);
00126 
00127   return PL_DHASH_REMOVE;
00128 }
00129 
00130 void
00131 testTHashtable(nsTHashtable<EntityToUnicodeEntry>& hash, PRUint32 numEntries) {
00132   printf("Filling hash with %d entries.\n", numEntries);
00133 
00134   PRUint32 i;
00135   for (i = 0; i < numEntries; ++i) {
00136     printf("  Putting entry \"%s\"...", gEntities[i].mStr);
00137     EntityToUnicodeEntry* entry =
00138       hash.PutEntry(gEntities[i].mStr);
00139 
00140     if (!entry) {
00141       printf("FAILED\n");
00142       exit (2);
00143     }
00144     printf("OK...");
00145 
00146     if (entry->mNode) {
00147       printf("entry already exists!\n");
00148       exit (3);
00149     }
00150     printf("\n");
00151 
00152     entry->mNode = &gEntities[i];
00153   }
00154 
00155   printf("Testing Get:\n");
00156 
00157   for (i = 0; i < numEntries; ++i) {
00158     printf("  Getting entry \"%s\"...", gEntities[i].mStr);
00159     EntityToUnicodeEntry* entry =
00160       hash.GetEntry(gEntities[i].mStr);
00161 
00162     if (!entry) {
00163       printf("FAILED\n");
00164       exit (4);
00165     }
00166 
00167     printf("Found %u\n", entry->mNode->mUnicode);
00168   }
00169 
00170   printf("Testing non-existent entries...");
00171 
00172   EntityToUnicodeEntry* entry =
00173     hash.GetEntry("xxxy");
00174 
00175   if (entry) {
00176     printf("FOUND! BAD!\n");
00177     exit (5);
00178   }
00179 
00180   printf("not found; good.\n");
00181 
00182   printf("Enumerating:\n");
00183   PRUint32 count = hash.EnumerateEntries(nsTEnumGo, nsnull);
00184   if (count != numEntries) {
00185     printf("  Bad count!\n");
00186     exit (6);
00187   }
00188 }
00189 
00190 PLDHashOperator
00191 nsDEnumRead(const PRUint32& aKey, const char* aData, void* userArg) {
00192   printf("  enumerated %u = \"%s\"\n", aKey, aData);
00193   return PL_DHASH_NEXT;
00194 }
00195 
00196 PLDHashOperator
00197 nsDEnum(const PRUint32& aKey, const char*& aData, void* userArg) {
00198   printf("  enumerated %u = \"%s\"\n", aKey, aData);
00199   return PL_DHASH_NEXT;
00200 }
00201 
00202 PLDHashOperator
00203 nsCEnumRead(const nsACString& aKey, TestUniChar* aData, void* userArg) {
00204   printf("  enumerated \"%s\" = %c\n",
00205          PromiseFlatCString(aKey).get(), aData->GetChar());
00206   return PL_DHASH_NEXT;
00207 }
00208 
00209 PLDHashOperator
00210 nsCEnum(const nsACString& aKey, nsAutoPtr<TestUniChar>& aData, void* userArg) {
00211     printf("  enumerated \"%s\" = %c\n", 
00212            PromiseFlatCString(aKey).get(), aData->GetChar());
00213   return PL_DHASH_NEXT;
00214 }
00215 
00216 //
00217 // all this nsIFoo stuff was copied wholesale from TestCOMPTr.cpp
00218 //
00219 
00220 #define NS_IFOO_IID \
00221 { 0x6f7652e0,  0xee43, 0x11d1, \
00222  { 0x9c, 0xc3, 0x00, 0x60, 0x08, 0x8c, 0xa6, 0xb3 } }
00223 
00224 class IFoo : public nsISupports
00225   {
00226     public:
00227       NS_DEFINE_STATIC_IID_ACCESSOR(NS_IFOO_IID)
00228 
00229     public:
00230       IFoo();
00231 
00232       NS_IMETHOD_(nsrefcnt) AddRef();
00233       NS_IMETHOD_(nsrefcnt) Release();
00234       NS_IMETHOD QueryInterface( const nsIID&, void** );
00235 
00236       NS_IMETHOD SetString(const nsACString& /*in*/ aString);
00237       NS_IMETHOD GetString(nsACString& /*out*/ aString);
00238 
00239       static void print_totals();
00240 
00241     private:
00242       ~IFoo();
00243 
00244       unsigned int refcount_;
00245 
00246       static unsigned int total_constructions_;
00247       static unsigned int total_destructions_;
00248       nsCString mString;
00249   };
00250 
00251 unsigned int IFoo::total_constructions_;
00252 unsigned int IFoo::total_destructions_;
00253 
00254 void
00255 IFoo::print_totals()
00256   {
00257     printf("total constructions/destructions --> %d/%d\n",
00258            total_constructions_, total_destructions_);
00259   }
00260 
00261 IFoo::IFoo()
00262     : refcount_(0)
00263   {
00264     ++total_constructions_;
00265     printf("  new IFoo@%p [#%d]\n",
00266            NS_STATIC_CAST(void*, this), total_constructions_);
00267   }
00268 
00269 IFoo::~IFoo()
00270   {
00271     ++total_destructions_;
00272     printf("IFoo@%p::~IFoo() [#%d]\n",
00273            NS_STATIC_CAST(void*, this), total_destructions_);
00274   }
00275 
00276 nsrefcnt
00277 IFoo::AddRef()
00278   {
00279     ++refcount_;
00280     printf("IFoo@%p::AddRef(), refcount --> %d\n", 
00281            NS_STATIC_CAST(void*, this), refcount_);
00282     return refcount_;
00283   }
00284 
00285 nsrefcnt
00286 IFoo::Release()
00287   {
00288     int wrap_message = (refcount_ == 1);
00289     if ( wrap_message )
00290       printf(">>");
00291       
00292     --refcount_;
00293     printf("IFoo@%p::Release(), refcount --> %d\n",
00294            NS_STATIC_CAST(void*, this), refcount_);
00295 
00296     if ( !refcount_ )
00297       {
00298         printf("  delete IFoo@%p\n", NS_STATIC_CAST(void*, this));
00299         delete this;
00300       }
00301 
00302     if ( wrap_message )
00303       printf("  delete IFoo@%p\n", NS_STATIC_CAST(void*, this));
00304 
00305     return refcount_;
00306   }
00307 
00308 nsresult
00309 IFoo::QueryInterface( const nsIID& aIID, void** aResult )
00310   {
00311     printf("IFoo@%p::QueryInterface()\n", NS_STATIC_CAST(void*, this));
00312     nsISupports* rawPtr = 0;
00313     nsresult status = NS_OK;
00314 
00315     if ( aIID.Equals(GetIID()) )
00316       rawPtr = this;
00317     else
00318       {
00319         nsID iid_of_ISupports = NS_ISUPPORTS_IID;
00320         if ( aIID.Equals(iid_of_ISupports) )
00321           rawPtr = NS_STATIC_CAST(nsISupports*, this);
00322         else
00323           status = NS_ERROR_NO_INTERFACE;
00324       }
00325 
00326     NS_IF_ADDREF(rawPtr);
00327     *aResult = rawPtr;
00328 
00329     return status;
00330   }
00331 
00332 nsresult
00333 IFoo::SetString(const nsACString& aString)
00334 {
00335   mString = aString;
00336   return NS_OK;
00337 }
00338 
00339 nsresult
00340 IFoo::GetString(nsACString& aString)
00341 {
00342   aString = mString;
00343   return NS_OK;
00344 }
00345 
00346 nsresult
00347 CreateIFoo( IFoo** result )
00348     // a typical factory function (that calls AddRef)
00349   {
00350     printf("    >>CreateIFoo() --> ");
00351     IFoo* foop = new IFoo();
00352     printf("IFoo@%p\n", NS_STATIC_CAST(void*, foop));
00353 
00354     foop->AddRef();
00355     *result = foop;
00356 
00357     printf("<<CreateIFoo()\n");
00358     return 0;
00359   }
00360 
00361 PLDHashOperator
00362 nsIEnumRead(const PRUint32& aKey, IFoo* aFoo, void* userArg) {
00363   nsCAutoString str;
00364   aFoo->GetString(str);
00365 
00366   printf("  enumerated %u = \"%s\"\n", aKey, str.get());
00367   return PL_DHASH_NEXT;
00368 }
00369 
00370 PLDHashOperator
00371 nsIEnum(const PRUint32& aKey, nsCOMPtr<IFoo>& aData, void* userArg) {
00372   nsCAutoString str;
00373   aData->GetString(str);
00374 
00375   printf("  enumerated %u = \"%s\"\n", aKey, str.get());
00376   return PL_DHASH_NEXT;
00377 }
00378 
00379 PLDHashOperator
00380 nsIEnum2Read(nsISupports* aKey, PRUint32 aData, void* userArg) {
00381   nsCAutoString str;
00382   nsCOMPtr<IFoo> foo = do_QueryInterface(aKey);
00383   foo->GetString(str);
00384 
00385 
00386   printf("  enumerated \"%s\" = %u\n", str.get(), aData);
00387   return PL_DHASH_NEXT;
00388 }
00389 
00390 PLDHashOperator
00391 nsIEnum2(nsISupports* aKey, PRUint32& aData, void* userArg) {
00392   nsCAutoString str;
00393   nsCOMPtr<IFoo> foo = do_QueryInterface(aKey);
00394   foo->GetString(str);
00395 
00396   printf("  enumerated \"%s\" = %u\n", str.get(), aData);
00397   return PL_DHASH_NEXT;
00398 }
00399 
00400 int
00401 main(void) {
00402   // check an nsTHashtable
00403   nsTHashtable<EntityToUnicodeEntry> EntityToUnicode;
00404 
00405   printf("Initializing nsTHashtable...");
00406   if (!EntityToUnicode.Init(ENTITY_COUNT)) {
00407     printf("FAILED\n");
00408     exit (1);
00409   }
00410   printf("OK\n");
00411 
00412   printf("Partially filling nsTHashtable:\n");
00413   testTHashtable(EntityToUnicode, 5);
00414 
00415   printf("Enumerate-removing...\n");
00416   PRUint32 count = EntityToUnicode.EnumerateEntries(nsTEnumStop, nsnull);
00417   if (count != 5) {
00418     printf("wrong count\n");
00419     exit (7);
00420   }
00421   printf("OK\n");
00422 
00423   printf("Check enumeration...");
00424   count = EntityToUnicode.EnumerateEntries(nsTEnumGo, nsnull);
00425   if (count) {
00426     printf("entries remain in table!\n");
00427     exit (8);
00428   }
00429   printf("OK\n");
00430 
00431   printf("Filling nsTHashtable:\n");
00432   testTHashtable(EntityToUnicode, ENTITY_COUNT);
00433 
00434   printf("Clearing...");
00435   EntityToUnicode.Clear();
00436   printf("OK\n");
00437 
00438   printf("Check enumeration...");
00439   count = EntityToUnicode.EnumerateEntries(nsTEnumGo, nsnull);
00440   if (count) {
00441     printf("entries remain in table!\n");
00442     exit (9);
00443   }
00444   printf("OK\n");
00445 
00446   //
00447   // now check a data-hashtable
00448   //
00449 
00450   nsDataHashtable<nsUint32HashKey,const char*> UniToEntity;
00451 
00452   printf("Initializing nsDataHashtable...");
00453   if (!UniToEntity.Init(ENTITY_COUNT)) {
00454     printf("FAILED\n");
00455     exit (10);
00456   }
00457   printf("OK\n");
00458 
00459   printf("Filling hash with %d entries.\n", ENTITY_COUNT);
00460 
00461   PRUint32 i;
00462   for (i = 0; i < ENTITY_COUNT; ++i) {
00463     printf("  Putting entry %u...", gEntities[i].mUnicode);
00464     if (!UniToEntity.Put(gEntities[i].mUnicode, gEntities[i].mStr)) {
00465       printf("FAILED\n");
00466       exit (11);
00467     }
00468     printf("OK...\n");
00469   }
00470 
00471   printf("Testing Get:\n");
00472   const char* str;
00473 
00474   for (i = 0; i < ENTITY_COUNT; ++i) {
00475     printf("  Getting entry %u...", gEntities[i].mUnicode);
00476     if (!UniToEntity.Get(gEntities[i].mUnicode, &str)) {
00477       printf("FAILED\n");
00478       exit (12);
00479     }
00480 
00481     printf("Found %s\n", str);
00482   }
00483 
00484   printf("Testing non-existent entries...");
00485   if (UniToEntity.Get(99446, &str)) {
00486     printf("FOUND! BAD!\n");
00487     exit (13);
00488   }
00489       
00490   printf("not found; good.\n");
00491       
00492   printf("Enumerating:\n");
00493   
00494   count = UniToEntity.EnumerateRead(nsDEnumRead, nsnull);
00495   if (count != ENTITY_COUNT) {
00496     printf("  Bad count!\n");
00497     exit (14);
00498   }
00499   
00500   printf("Clearing...");
00501   UniToEntity.Clear();
00502   printf("OK\n");
00503 
00504   printf("Checking count...");
00505   count = UniToEntity.Enumerate(nsDEnum, nsnull);
00506   if (count) {
00507     printf("  Clear did not remove all entries.\n");
00508     exit (15);
00509   }
00510 
00511   printf("OK\n");
00512 
00513   //
00514   // now check a thread-safe data-hashtable
00515   //
00516 
00517   nsDataHashtableMT<nsUint32HashKey,const char*> UniToEntityL;
00518 
00519   printf("Initializing nsDataHashtableMT...");
00520   if (!UniToEntityL.Init(ENTITY_COUNT)) {
00521     printf("FAILED\n");
00522     exit (10);
00523   }
00524   printf("OK\n");
00525 
00526   printf("Filling hash with %d entries.\n", ENTITY_COUNT);
00527 
00528   for (i = 0; i < ENTITY_COUNT; ++i) {
00529     printf("  Putting entry %u...", gEntities[i].mUnicode);
00530     if (!UniToEntityL.Put(gEntities[i].mUnicode, gEntities[i].mStr)) {
00531       printf("FAILED\n");
00532       exit (11);
00533     }
00534     printf("OK...\n");
00535   }
00536 
00537   printf("Testing Get:\n");
00538 
00539   for (i = 0; i < ENTITY_COUNT; ++i) {
00540     printf("  Getting entry %u...", gEntities[i].mUnicode);
00541     if (!UniToEntityL.Get(gEntities[i].mUnicode, &str)) {
00542       printf("FAILED\n");
00543       exit (12);
00544     }
00545 
00546     printf("Found %s\n", str);
00547   }
00548 
00549   printf("Testing non-existent entries...");
00550   if (UniToEntityL.Get(99446, &str)) {
00551     printf("FOUND! BAD!\n");
00552     exit (13);
00553   }
00554       
00555   printf("not found; good.\n");
00556       
00557   printf("Enumerating:\n");
00558   
00559   count = UniToEntityL.EnumerateRead(nsDEnumRead, nsnull);
00560   if (count != ENTITY_COUNT) {
00561     printf("  Bad count!\n");
00562     exit (14);
00563   }
00564   
00565   printf("Clearing...");
00566   UniToEntityL.Clear();
00567   printf("OK\n");
00568 
00569   printf("Checking count...");
00570   count = UniToEntityL.Enumerate(nsDEnum, nsnull);
00571   if (count) {
00572     printf("  Clear did not remove all entries.\n");
00573     exit (15);
00574   }
00575 
00576   printf("OK\n");
00577 
00578   //
00579   // now check a class-hashtable
00580   //
00581 
00582   nsClassHashtable<nsCStringHashKey,TestUniChar> EntToUniClass;
00583 
00584   printf("Initializing nsClassHashtable...");
00585   if (!EntToUniClass.Init(ENTITY_COUNT)) {
00586     printf("FAILED\n");
00587     exit (16);
00588   }
00589   printf("OK\n");
00590 
00591   printf("Filling hash with %d entries.\n", ENTITY_COUNT);
00592 
00593   for (i = 0; i < ENTITY_COUNT; ++i) {
00594     printf("  Putting entry %u...", gEntities[i].mUnicode);
00595     TestUniChar* temp = new TestUniChar(gEntities[i].mUnicode);
00596 
00597     if (!EntToUniClass.Put(nsDependentCString(gEntities[i].mStr), temp)) {
00598       printf("FAILED\n");
00599       delete temp;
00600       exit (17);
00601     }
00602     printf("OK...\n");
00603   }
00604 
00605   printf("Testing Get:\n");
00606   TestUniChar* myChar;
00607 
00608   for (i = 0; i < ENTITY_COUNT; ++i) {
00609     printf("  Getting entry %s...", gEntities[i].mStr);
00610     if (!EntToUniClass.Get(nsDependentCString(gEntities[i].mStr), &myChar)) {
00611       printf("FAILED\n");
00612       exit (18);
00613     }
00614 
00615     printf("Found %c\n", myChar->GetChar());
00616   }
00617 
00618   printf("Testing non-existent entries...");
00619   if (EntToUniClass.Get(NS_LITERAL_CSTRING("xxxx"), &myChar)) {
00620     printf("FOUND! BAD!\n");
00621     exit (19);
00622   }
00623       
00624   printf("not found; good.\n");
00625       
00626   printf("Enumerating:\n");
00627   
00628   count = EntToUniClass.EnumerateRead(nsCEnumRead, nsnull);
00629   if (count != ENTITY_COUNT) {
00630     printf("  Bad count!\n");
00631     exit (20);
00632   }
00633   
00634   printf("Clearing...\n");
00635   EntToUniClass.Clear();
00636   printf("  Clearing OK\n");
00637 
00638   printf("Checking count...");
00639   count = EntToUniClass.Enumerate(nsCEnum, nsnull);
00640   if (count) {
00641     printf("  Clear did not remove all entries.\n");
00642     exit (21);
00643   }
00644 
00645   printf("OK\n");
00646 
00647   //
00648   // now check a thread-safe class-hashtable
00649   //
00650 
00651   nsClassHashtableMT<nsCStringHashKey,TestUniChar> EntToUniClassL;
00652 
00653   printf("Initializing nsClassHashtableMT...");
00654   if (!EntToUniClassL.Init(ENTITY_COUNT)) {
00655     printf("FAILED\n");
00656     exit (16);
00657   }
00658   printf("OK\n");
00659 
00660   printf("Filling hash with %d entries.\n", ENTITY_COUNT);
00661 
00662   for (i = 0; i < ENTITY_COUNT; ++i) {
00663     printf("  Putting entry %u...", gEntities[i].mUnicode);
00664     TestUniChar* temp = new TestUniChar(gEntities[i].mUnicode);
00665 
00666     if (!EntToUniClassL.Put(nsDependentCString(gEntities[i].mStr), temp)) {
00667       printf("FAILED\n");
00668       delete temp;
00669       exit (17);
00670     }
00671     printf("OK...\n");
00672   }
00673 
00674   printf("Testing Get:\n");
00675 
00676   for (i = 0; i < ENTITY_COUNT; ++i) {
00677     printf("  Getting entry %s...", gEntities[i].mStr);
00678     if (!EntToUniClassL.Get(nsDependentCString(gEntities[i].mStr), &myChar)) {
00679       printf("FAILED\n");
00680       exit (18);
00681     }
00682 
00683     printf("Found %c\n", myChar->GetChar());
00684   }
00685 
00686   printf("Testing non-existent entries...");
00687   if (EntToUniClassL.Get(NS_LITERAL_CSTRING("xxxx"), &myChar)) {
00688     printf("FOUND! BAD!\n");
00689     exit (19);
00690   }
00691       
00692   printf("not found; good.\n");
00693       
00694   printf("Enumerating:\n");
00695   
00696   count = EntToUniClassL.EnumerateRead(nsCEnumRead, nsnull);
00697   if (count != ENTITY_COUNT) {
00698     printf("  Bad count!\n");
00699     exit (20);
00700   }
00701   
00702   printf("Clearing...\n");
00703   EntToUniClassL.Clear();
00704   printf("  Clearing OK\n");
00705 
00706   printf("Checking count...");
00707   count = EntToUniClassL.Enumerate(nsCEnum, nsnull);
00708   if (count) {
00709     printf("  Clear did not remove all entries.\n");
00710     exit (21);
00711   }
00712 
00713   printf("OK\n");
00714 
00715   //
00716   // now check a data-hashtable with an interface key
00717   //
00718 
00719   nsDataHashtable<nsISupportsHashKey,PRUint32> EntToUniClass2;
00720 
00721   printf("Initializing nsDataHashtable with interface key...");
00722   if (!EntToUniClass2.Init(ENTITY_COUNT)) {
00723     printf("FAILED\n");
00724     exit (22);
00725   }
00726   printf("OK\n");
00727 
00728   printf("Filling hash with %d entries.\n", ENTITY_COUNT);
00729 
00730   nsCOMArray<IFoo> fooArray;
00731 
00732   for (i = 0; i < ENTITY_COUNT; ++i) {
00733     printf("  Putting entry %u...", gEntities[i].mUnicode);
00734     nsCOMPtr<IFoo> foo;
00735     CreateIFoo(getter_AddRefs(foo));
00736     foo->SetString(nsDependentCString(gEntities[i].mStr));
00737     
00738     
00739     fooArray.InsertObjectAt(foo, i);
00740 
00741     if (!EntToUniClass2.Put(foo, gEntities[i].mUnicode)) {
00742       printf("FAILED\n");
00743       exit (23);
00744     }
00745     printf("OK...\n");
00746   }
00747 
00748   printf("Testing Get:\n");
00749   PRUint32 myChar2;
00750 
00751   for (i = 0; i < ENTITY_COUNT; ++i) {
00752     printf("  Getting entry %s...", gEntities[i].mStr);
00753     
00754     if (!EntToUniClass2.Get(fooArray[i], &myChar2)) {
00755       printf("FAILED\n");
00756       exit (24);
00757     }
00758 
00759     printf("Found %c\n", myChar2);
00760   }
00761 
00762   printf("Testing non-existent entries...");
00763   if (EntToUniClass2.Get((nsISupports*) 0x55443316, &myChar2)) {
00764     printf("FOUND! BAD!\n");
00765     exit (25);
00766   }
00767       
00768   printf("not found; good.\n");
00769       
00770   printf("Enumerating:\n");
00771   
00772   count = EntToUniClass2.EnumerateRead(nsIEnum2Read, nsnull);
00773   if (count != ENTITY_COUNT) {
00774     printf("  Bad count!\n");
00775     exit (26);
00776   }
00777   
00778   printf("Clearing...\n");
00779   EntToUniClass2.Clear();
00780   printf("  Clearing OK\n");
00781 
00782   printf("Checking count...");
00783   count = EntToUniClass2.Enumerate(nsIEnum2, nsnull);
00784   if (count) {
00785     printf("  Clear did not remove all entries.\n");
00786     exit (27);
00787   }
00788 
00789   printf("OK\n");
00790 
00791   //
00792   // now check an interface-hashtable with an PRUint32 key
00793   //
00794 
00795   nsInterfaceHashtable<nsUint32HashKey,IFoo> UniToEntClass2;
00796 
00797   printf("Initializing nsInterfaceHashtable...");
00798   if (!UniToEntClass2.Init(ENTITY_COUNT)) {
00799     printf("FAILED\n");
00800     exit (28);
00801   }
00802   printf("OK\n");
00803 
00804   printf("Filling hash with %d entries.\n", ENTITY_COUNT);
00805 
00806   for (i = 0; i < ENTITY_COUNT; ++i) {
00807     printf("  Putting entry %u...", gEntities[i].mUnicode);
00808     nsCOMPtr<IFoo> foo;
00809     CreateIFoo(getter_AddRefs(foo));
00810     foo->SetString(nsDependentCString(gEntities[i].mStr));
00811     
00812     if (!UniToEntClass2.Put(gEntities[i].mUnicode, foo)) {
00813       printf("FAILED\n");
00814       exit (29);
00815     }
00816     printf("OK...\n");
00817   }
00818 
00819   printf("Testing Get:\n");
00820 
00821   for (i = 0; i < ENTITY_COUNT; ++i) {
00822     printf("  Getting entry %s...", gEntities[i].mStr);
00823     
00824     nsCOMPtr<IFoo> myEnt;
00825     if (!UniToEntClass2.Get(gEntities[i].mUnicode, getter_AddRefs(myEnt))) {
00826       printf("FAILED\n");
00827       exit (30);
00828     }
00829     
00830     nsCAutoString str;
00831     myEnt->GetString(str);
00832     printf("Found %s\n", str.get());
00833   }
00834 
00835   printf("Testing non-existent entries...");
00836   nsCOMPtr<IFoo> myEnt;
00837   if (UniToEntClass2.Get(9462, getter_AddRefs(myEnt))) {
00838     printf("FOUND! BAD!\n");
00839     exit (31);
00840   }
00841       
00842   printf("not found; good.\n");
00843       
00844   printf("Enumerating:\n");
00845   
00846   count = UniToEntClass2.EnumerateRead(nsIEnumRead, nsnull);
00847   if (count != ENTITY_COUNT) {
00848     printf("  Bad count!\n");
00849     exit (32);
00850   }
00851   
00852   printf("Clearing...\n");
00853   UniToEntClass2.Clear();
00854   printf("  Clearing OK\n");
00855 
00856   printf("Checking count...");
00857   count = UniToEntClass2.Enumerate(nsIEnum, nsnull);
00858   if (count) {
00859     printf("  Clear did not remove all entries.\n");
00860     exit (33);
00861   }
00862 
00863   printf("OK\n");
00864 
00865   //
00866   // now check a thread-safe interface hashtable
00867   //
00868 
00869   nsInterfaceHashtableMT<nsUint32HashKey,IFoo> UniToEntClass2L;
00870 
00871   printf("Initializing nsInterfaceHashtableMT...");
00872   if (!UniToEntClass2L.Init(ENTITY_COUNT)) {
00873     printf("FAILED\n");
00874     exit (28);
00875   }
00876   printf("OK\n");
00877 
00878   printf("Filling hash with %d entries.\n", ENTITY_COUNT);
00879 
00880   for (i = 0; i < ENTITY_COUNT; ++i) {
00881     printf("  Putting entry %u...", gEntities[i].mUnicode);
00882     nsCOMPtr<IFoo> foo;
00883     CreateIFoo(getter_AddRefs(foo));
00884     foo->SetString(nsDependentCString(gEntities[i].mStr));
00885     
00886     if (!UniToEntClass2L.Put(gEntities[i].mUnicode, foo)) {
00887       printf("FAILED\n");
00888       exit (29);
00889     }
00890     printf("OK...\n");
00891   }
00892 
00893   printf("Testing Get:\n");
00894 
00895   for (i = 0; i < ENTITY_COUNT; ++i) {
00896     printf("  Getting entry %s...", gEntities[i].mStr);
00897     
00898     nsCOMPtr<IFoo> myEnt;
00899     if (!UniToEntClass2L.Get(gEntities[i].mUnicode, getter_AddRefs(myEnt))) {
00900       printf("FAILED\n");
00901       exit (30);
00902     }
00903     
00904     nsCAutoString str;
00905     myEnt->GetString(str);
00906     printf("Found %s\n", str.get());
00907   }
00908 
00909   printf("Testing non-existent entries...");
00910   if (UniToEntClass2L.Get(9462, getter_AddRefs(myEnt))) {
00911     printf("FOUND! BAD!\n");
00912     exit (31);
00913   }
00914       
00915   printf("not found; good.\n");
00916       
00917   printf("Enumerating:\n");
00918   
00919   count = UniToEntClass2L.EnumerateRead(nsIEnumRead, nsnull);
00920   if (count != ENTITY_COUNT) {
00921     printf("  Bad count!\n");
00922     exit (32);
00923   }
00924   
00925   printf("Clearing...\n");
00926   UniToEntClass2L.Clear();
00927   printf("  Clearing OK\n");
00928 
00929   printf("Checking count...");
00930   count = UniToEntClass2L.Enumerate(nsIEnum, nsnull);
00931   if (count) {
00932     printf("  Clear did not remove all entries.\n");
00933     exit (33);
00934   }
00935 
00936   printf("OK\n");
00937 
00938   return 0;
00939 }