xpcom/tests/TestHashtables.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "nsTHashtable.h"
     7 #include "nsBaseHashtable.h"
     8 #include "nsDataHashtable.h"
     9 #include "nsInterfaceHashtable.h"
    10 #include "nsClassHashtable.h"
    12 #include "nsCOMPtr.h"
    13 #include "nsISupports.h"
    14 #include "nsCOMArray.h"
    15 #include "mozilla/Attributes.h"
    17 #include <stdio.h>
    19 namespace TestHashtables {
    21 class TestUniChar // for nsClassHashtable
    22 {
    23 public:
    24   TestUniChar(uint32_t aWord)
    25   {
    26     printf("    TestUniChar::TestUniChar() %u\n", aWord);
    27     mWord = aWord;
    28   }
    30   ~TestUniChar()
    31   {
    32     printf("    TestUniChar::~TestUniChar() %u\n", mWord);
    33   }
    35   uint32_t GetChar() const { return mWord; }
    37 private:
    38   uint32_t mWord;
    39 };
    41 struct EntityNode {
    42   const char*   mStr; // never owns buffer
    43   uint32_t       mUnicode;
    44 };
    46 EntityNode gEntities[] = {
    47   {"nbsp",160},
    48   {"iexcl",161},
    49   {"cent",162},
    50   {"pound",163},
    51   {"curren",164},
    52   {"yen",165},
    53   {"brvbar",166},
    54   {"sect",167},
    55   {"uml",168},
    56   {"copy",169},
    57   {"ordf",170},
    58   {"laquo",171},
    59   {"not",172},
    60   {"shy",173},
    61   {"reg",174},
    62   {"macr",175}
    63 };
    65 #define ENTITY_COUNT (unsigned(sizeof(gEntities)/sizeof(EntityNode)))
    67 class EntityToUnicodeEntry : public PLDHashEntryHdr
    68 {
    69 public:
    70   typedef const char* KeyType;
    71   typedef const char* KeyTypePointer;
    73   EntityToUnicodeEntry(const char* aKey) { mNode = nullptr; }
    74   EntityToUnicodeEntry(const EntityToUnicodeEntry& aEntry) { mNode = aEntry.mNode; }
    75   ~EntityToUnicodeEntry() { }
    77   bool KeyEquals(const char* aEntity) const { return !strcmp(mNode->mStr, aEntity); }
    78   static const char* KeyToPointer(const char* aEntity) { return aEntity; }
    79   static PLDHashNumber HashKey(const char* aEntity) { return mozilla::HashString(aEntity); }
    80   enum { ALLOW_MEMMOVE = true };
    82   const EntityNode* mNode;
    83 };
    85 PLDHashOperator
    86 nsTEnumGo(EntityToUnicodeEntry* aEntry, void* userArg) {
    87   printf("  enumerated \"%s\" = %u\n", 
    88          aEntry->mNode->mStr, aEntry->mNode->mUnicode);
    90   return PL_DHASH_NEXT;
    91 }
    93 PLDHashOperator
    94 nsTEnumStop(EntityToUnicodeEntry* aEntry, void* userArg) {
    95   printf("  enumerated \"%s\" = %u\n",
    96          aEntry->mNode->mStr, aEntry->mNode->mUnicode);
    98   return PL_DHASH_REMOVE;
    99 }
   101 void
   102 testTHashtable(nsTHashtable<EntityToUnicodeEntry>& hash, uint32_t numEntries) {
   103   printf("Filling hash with %d entries.\n", numEntries);
   105   uint32_t i;
   106   for (i = 0; i < numEntries; ++i) {
   107     printf("  Putting entry \"%s\"...", gEntities[i].mStr);
   108     EntityToUnicodeEntry* entry =
   109       hash.PutEntry(gEntities[i].mStr);
   111     if (!entry) {
   112       printf("FAILED\n");
   113       exit (2);
   114     }
   115     printf("OK...");
   117     if (entry->mNode) {
   118       printf("entry already exists!\n");
   119       exit (3);
   120     }
   121     printf("\n");
   123     entry->mNode = &gEntities[i];
   124   }
   126   printf("Testing Get:\n");
   128   for (i = 0; i < numEntries; ++i) {
   129     printf("  Getting entry \"%s\"...", gEntities[i].mStr);
   130     EntityToUnicodeEntry* entry =
   131       hash.GetEntry(gEntities[i].mStr);
   133     if (!entry) {
   134       printf("FAILED\n");
   135       exit (4);
   136     }
   138     printf("Found %u\n", entry->mNode->mUnicode);
   139   }
   141   printf("Testing nonexistent entries...");
   143   EntityToUnicodeEntry* entry =
   144     hash.GetEntry("xxxy");
   146   if (entry) {
   147     printf("FOUND! BAD!\n");
   148     exit (5);
   149   }
   151   printf("not found; good.\n");
   153   printf("Enumerating:\n");
   154   uint32_t count = hash.EnumerateEntries(nsTEnumGo, nullptr);
   155   if (count != numEntries) {
   156     printf("  Bad count!\n");
   157     exit (6);
   158   }
   159 }
   161 PLDHashOperator
   162 nsDEnumRead(const uint32_t& aKey, const char* aData, void* userArg) {
   163   printf("  enumerated %u = \"%s\"\n", aKey, aData);
   164   return PL_DHASH_NEXT;
   165 }
   167 PLDHashOperator
   168 nsDEnum(const uint32_t& aKey, const char*& aData, void* userArg) {
   169   printf("  enumerated %u = \"%s\"\n", aKey, aData);
   170   return PL_DHASH_NEXT;
   171 }
   173 PLDHashOperator
   174 nsCEnumRead(const nsACString& aKey, TestUniChar* aData, void* userArg) {
   175   printf("  enumerated \"%s\" = %c\n",
   176          PromiseFlatCString(aKey).get(), aData->GetChar());
   177   return PL_DHASH_NEXT;
   178 }
   180 PLDHashOperator
   181 nsCEnum(const nsACString& aKey, nsAutoPtr<TestUniChar>& aData, void* userArg) {
   182     printf("  enumerated \"%s\" = %c\n", 
   183            PromiseFlatCString(aKey).get(), aData->GetChar());
   184   return PL_DHASH_NEXT;
   185 }
   187 //
   188 // all this nsIFoo stuff was copied wholesale from TestCOMPtr.cpp
   189 //
   191 #define NS_IFOO_IID \
   192 { 0x6f7652e0,  0xee43, 0x11d1, \
   193  { 0x9c, 0xc3, 0x00, 0x60, 0x08, 0x8c, 0xa6, 0xb3 } }
   195 class IFoo MOZ_FINAL : public nsISupports
   196   {
   197     public:
   198       NS_DECLARE_STATIC_IID_ACCESSOR(NS_IFOO_IID)
   200       IFoo();
   202       NS_IMETHOD_(MozExternalRefCountType) AddRef();
   203       NS_IMETHOD_(MozExternalRefCountType) Release();
   204       NS_IMETHOD QueryInterface( const nsIID&, void** );
   206       NS_IMETHOD SetString(const nsACString& /*in*/ aString);
   207       NS_IMETHOD GetString(nsACString& /*out*/ aString);
   209       static void print_totals();
   211     private:
   212       ~IFoo();
   214       unsigned int refcount_;
   216       static unsigned int total_constructions_;
   217       static unsigned int total_destructions_;
   218       nsCString mString;
   219   };
   221 NS_DEFINE_STATIC_IID_ACCESSOR(IFoo, NS_IFOO_IID)
   223 unsigned int IFoo::total_constructions_;
   224 unsigned int IFoo::total_destructions_;
   226 void
   227 IFoo::print_totals()
   228   {
   229     printf("total constructions/destructions --> %d/%d\n",
   230            total_constructions_, total_destructions_);
   231   }
   233 IFoo::IFoo()
   234     : refcount_(0)
   235   {
   236     ++total_constructions_;
   237     printf("  new IFoo@%p [#%d]\n",
   238            static_cast<void*>(this), total_constructions_);
   239   }
   241 IFoo::~IFoo()
   242   {
   243     ++total_destructions_;
   244     printf("IFoo@%p::~IFoo() [#%d]\n",
   245            static_cast<void*>(this), total_destructions_);
   246   }
   248 MozExternalRefCountType
   249 IFoo::AddRef()
   250   {
   251     ++refcount_;
   252     printf("IFoo@%p::AddRef(), refcount --> %d\n", 
   253            static_cast<void*>(this), refcount_);
   254     return refcount_;
   255   }
   257 MozExternalRefCountType
   258 IFoo::Release()
   259   {
   260     int newcount = --refcount_;
   261     if ( newcount == 0 )
   262       printf(">>");
   264     printf("IFoo@%p::Release(), refcount --> %d\n",
   265            static_cast<void*>(this), refcount_);
   267     if ( newcount == 0 )
   268       {
   269         printf("  delete IFoo@%p\n", static_cast<void*>(this));
   270         printf("<<IFoo@%p::Release()\n", static_cast<void*>(this));
   271         delete this;
   272       }
   274     return newcount;
   275   }
   277 nsresult
   278 IFoo::QueryInterface( const nsIID& aIID, void** aResult )
   279   {
   280     printf("IFoo@%p::QueryInterface()\n", static_cast<void*>(this));
   281     nsISupports* rawPtr = 0;
   282     nsresult status = NS_OK;
   284     if ( aIID.Equals(NS_GET_IID(IFoo)) )
   285       rawPtr = this;
   286     else
   287       {
   288         nsID iid_of_ISupports = NS_ISUPPORTS_IID;
   289         if ( aIID.Equals(iid_of_ISupports) )
   290           rawPtr = static_cast<nsISupports*>(this);
   291         else
   292           status = NS_ERROR_NO_INTERFACE;
   293       }
   295     NS_IF_ADDREF(rawPtr);
   296     *aResult = rawPtr;
   298     return status;
   299   }
   301 nsresult
   302 IFoo::SetString(const nsACString& aString)
   303 {
   304   mString = aString;
   305   return NS_OK;
   306 }
   308 nsresult
   309 IFoo::GetString(nsACString& aString)
   310 {
   311   aString = mString;
   312   return NS_OK;
   313 }
   315 nsresult
   316 CreateIFoo( IFoo** result )
   317     // a typical factory function (that calls AddRef)
   318   {
   319     printf("    >>CreateIFoo() --> ");
   320     IFoo* foop = new IFoo();
   321     printf("IFoo@%p\n", static_cast<void*>(foop));
   323     foop->AddRef();
   324     *result = foop;
   326     printf("<<CreateIFoo()\n");
   327     return NS_OK;
   328   }
   330 PLDHashOperator
   331 nsIEnumRead(const uint32_t& aKey, IFoo* aFoo, void* userArg) {
   332   nsAutoCString str;
   333   aFoo->GetString(str);
   335   printf("  enumerated %u = \"%s\"\n", aKey, str.get());
   336   return PL_DHASH_NEXT;
   337 }
   339 PLDHashOperator
   340 nsIEnum(const uint32_t& aKey, nsCOMPtr<IFoo>& aData, void* userArg) {
   341   nsAutoCString str;
   342   aData->GetString(str);
   344   printf("  enumerated %u = \"%s\"\n", aKey, str.get());
   345   return PL_DHASH_NEXT;
   346 }
   348 PLDHashOperator
   349 nsIEnum2Read(nsISupports* aKey, uint32_t aData, void* userArg) {
   350   nsAutoCString str;
   351   nsCOMPtr<IFoo> foo = do_QueryInterface(aKey);
   352   foo->GetString(str);
   355   printf("  enumerated \"%s\" = %u\n", str.get(), aData);
   356   return PL_DHASH_NEXT;
   357 }
   359 PLDHashOperator
   360 nsIEnum2(nsISupports* aKey, uint32_t& aData, void* userArg) {
   361   nsAutoCString str;
   362   nsCOMPtr<IFoo> foo = do_QueryInterface(aKey);
   363   foo->GetString(str);
   365   printf("  enumerated \"%s\" = %u\n", str.get(), aData);
   366   return PL_DHASH_NEXT;
   367 }
   369 }
   371 using namespace TestHashtables;
   373 int
   374 main(void) {
   375   // check an nsTHashtable
   376   printf("Initializing nsTHashtable...");
   377   nsTHashtable<EntityToUnicodeEntry> EntityToUnicode(ENTITY_COUNT);
   378   printf("OK\n");
   380   printf("Partially filling nsTHashtable:\n");
   381   testTHashtable(EntityToUnicode, 5);
   383   printf("Enumerate-removing...\n");
   384   uint32_t count = EntityToUnicode.EnumerateEntries(nsTEnumStop, nullptr);
   385   if (count != 5) {
   386     printf("wrong count\n");
   387     exit (7);
   388   }
   389   printf("OK\n");
   391   printf("Check enumeration...");
   392   count = EntityToUnicode.EnumerateEntries(nsTEnumGo, nullptr);
   393   if (count) {
   394     printf("entries remain in table!\n");
   395     exit (8);
   396   }
   397   printf("OK\n");
   399   printf("Filling nsTHashtable:\n");
   400   testTHashtable(EntityToUnicode, ENTITY_COUNT);
   402   printf("Clearing...");
   403   EntityToUnicode.Clear();
   404   printf("OK\n");
   406   printf("Check enumeration...");
   407   count = EntityToUnicode.EnumerateEntries(nsTEnumGo, nullptr);
   408   if (count) {
   409     printf("entries remain in table!\n");
   410     exit (9);
   411   }
   412   printf("OK\n");
   414   //
   415   // now check a data-hashtable
   416   //
   418   printf("Initializing nsDataHashtable...");
   419   nsDataHashtable<nsUint32HashKey,const char*> UniToEntity(ENTITY_COUNT);
   420   printf("OK\n");
   422   printf("Filling hash with %u entries.\n", ENTITY_COUNT);
   424   uint32_t i;
   425   for (i = 0; i < ENTITY_COUNT; ++i) {
   426     printf("  Putting entry %u...", gEntities[i].mUnicode);
   427     UniToEntity.Put(gEntities[i].mUnicode, gEntities[i].mStr);
   428     printf("OK...\n");
   429   }
   431   printf("Testing Get:\n");
   432   const char* str;
   434   for (i = 0; i < ENTITY_COUNT; ++i) {
   435     printf("  Getting entry %u...", gEntities[i].mUnicode);
   436     if (!UniToEntity.Get(gEntities[i].mUnicode, &str)) {
   437       printf("FAILED\n");
   438       exit (12);
   439     }
   441     printf("Found %s\n", str);
   442   }
   444   printf("Testing nonexistent entries...");
   445   if (UniToEntity.Get(99446, &str)) {
   446     printf("FOUND! BAD!\n");
   447     exit (13);
   448   }
   450   printf("not found; good.\n");
   452   printf("Enumerating:\n");
   454   count = UniToEntity.EnumerateRead(nsDEnumRead, nullptr);
   455   if (count != ENTITY_COUNT) {
   456     printf("  Bad count!\n");
   457     exit (14);
   458   }
   460   printf("Clearing...");
   461   UniToEntity.Clear();
   462   printf("OK\n");
   464   printf("Checking count...");
   465   count = UniToEntity.Enumerate(nsDEnum, nullptr);
   466   if (count) {
   467     printf("  Clear did not remove all entries.\n");
   468     exit (15);
   469   }
   471   printf("OK\n");
   473   //
   474   // now check a class-hashtable
   475   //
   477   printf("Initializing nsClassHashtable...");
   478   nsClassHashtable<nsCStringHashKey,TestUniChar> EntToUniClass(ENTITY_COUNT);
   479   printf("OK\n");
   481   printf("Filling hash with %u entries.\n", ENTITY_COUNT);
   483   for (i = 0; i < ENTITY_COUNT; ++i) {
   484     printf("  Putting entry %u...", gEntities[i].mUnicode);
   485     TestUniChar* temp = new TestUniChar(gEntities[i].mUnicode);
   487     EntToUniClass.Put(nsDependentCString(gEntities[i].mStr), temp);
   488     printf("OK...\n");
   489   }
   491   printf("Testing Get:\n");
   492   TestUniChar* myChar;
   494   for (i = 0; i < ENTITY_COUNT; ++i) {
   495     printf("  Getting entry %s...", gEntities[i].mStr);
   496     if (!EntToUniClass.Get(nsDependentCString(gEntities[i].mStr), &myChar)) {
   497       printf("FAILED\n");
   498       exit (18);
   499     }
   501     printf("Found %c\n", myChar->GetChar());
   502   }
   504   printf("Testing nonexistent entries...");
   505   if (EntToUniClass.Get(NS_LITERAL_CSTRING("xxxx"), &myChar)) {
   506     printf("FOUND! BAD!\n");
   507     exit (19);
   508   }
   510   printf("not found; good.\n");
   512   printf("Enumerating:\n");
   514   count = EntToUniClass.EnumerateRead(nsCEnumRead, nullptr);
   515   if (count != ENTITY_COUNT) {
   516     printf("  Bad count!\n");
   517     exit (20);
   518   }
   520   printf("Clearing...\n");
   521   EntToUniClass.Clear();
   522   printf("  Clearing OK\n");
   524   printf("Checking count...");
   525   count = EntToUniClass.Enumerate(nsCEnum, nullptr);
   526   if (count) {
   527     printf("  Clear did not remove all entries.\n");
   528     exit (21);
   529   }
   531   printf("OK\n");
   533   //
   534   // now check a data-hashtable with an interface key
   535   //
   537   printf("Initializing nsDataHashtable with interface key...");
   538   nsDataHashtable<nsISupportsHashKey,uint32_t> EntToUniClass2(ENTITY_COUNT);
   539   printf("OK\n");
   541   printf("Filling hash with %u entries.\n", ENTITY_COUNT);
   543   nsCOMArray<IFoo> fooArray;
   545   for (i = 0; i < ENTITY_COUNT; ++i) {
   546     printf("  Putting entry %u...", gEntities[i].mUnicode);
   547     nsCOMPtr<IFoo> foo;
   548     CreateIFoo(getter_AddRefs(foo));
   549     foo->SetString(nsDependentCString(gEntities[i].mStr));
   552     fooArray.InsertObjectAt(foo, i);
   554     EntToUniClass2.Put(foo, gEntities[i].mUnicode);
   555     printf("OK...\n");
   556   }
   558   printf("Testing Get:\n");
   559   uint32_t myChar2;
   561   for (i = 0; i < ENTITY_COUNT; ++i) {
   562     printf("  Getting entry %s...", gEntities[i].mStr);
   564     if (!EntToUniClass2.Get(fooArray[i], &myChar2)) {
   565       printf("FAILED\n");
   566       exit (24);
   567     }
   569     printf("Found %c\n", myChar2);
   570   }
   572   printf("Testing nonexistent entries...");
   573   if (EntToUniClass2.Get((nsISupports*) 0x55443316, &myChar2)) {
   574     printf("FOUND! BAD!\n");
   575     exit (25);
   576   }
   578   printf("not found; good.\n");
   580   printf("Enumerating:\n");
   582   count = EntToUniClass2.EnumerateRead(nsIEnum2Read, nullptr);
   583   if (count != ENTITY_COUNT) {
   584     printf("  Bad count!\n");
   585     exit (26);
   586   }
   588   printf("Clearing...\n");
   589   EntToUniClass2.Clear();
   590   printf("  Clearing OK\n");
   592   printf("Checking count...");
   593   count = EntToUniClass2.Enumerate(nsIEnum2, nullptr);
   594   if (count) {
   595     printf("  Clear did not remove all entries.\n");
   596     exit (27);
   597   }
   599   printf("OK\n");
   601   //
   602   // now check an interface-hashtable with an uint32_t key
   603   //
   605   printf("Initializing nsInterfaceHashtable...");
   606   nsInterfaceHashtable<nsUint32HashKey,IFoo> UniToEntClass2(ENTITY_COUNT);
   607   printf("OK\n");
   609   printf("Filling hash with %u entries.\n", ENTITY_COUNT);
   611   for (i = 0; i < ENTITY_COUNT; ++i) {
   612     printf("  Putting entry %u...", gEntities[i].mUnicode);
   613     nsCOMPtr<IFoo> foo;
   614     CreateIFoo(getter_AddRefs(foo));
   615     foo->SetString(nsDependentCString(gEntities[i].mStr));
   617     UniToEntClass2.Put(gEntities[i].mUnicode, foo);
   618     printf("OK...\n");
   619   }
   621   printf("Testing Get:\n");
   623   for (i = 0; i < ENTITY_COUNT; ++i) {
   624     printf("  Getting entry %s...", gEntities[i].mStr);
   626     nsCOMPtr<IFoo> myEnt;
   627     if (!UniToEntClass2.Get(gEntities[i].mUnicode, getter_AddRefs(myEnt))) {
   628       printf("FAILED\n");
   629       exit (30);
   630     }
   632     nsAutoCString str;
   633     myEnt->GetString(str);
   634     printf("Found %s\n", str.get());
   635   }
   637   printf("Testing nonexistent entries...");
   638   nsCOMPtr<IFoo> myEnt;
   639   if (UniToEntClass2.Get(9462, getter_AddRefs(myEnt))) {
   640     printf("FOUND! BAD!\n");
   641     exit (31);
   642   }
   644   printf("not found; good.\n");
   646   printf("Enumerating:\n");
   648   count = UniToEntClass2.EnumerateRead(nsIEnumRead, nullptr);
   649   if (count != ENTITY_COUNT) {
   650     printf("  Bad count!\n");
   651     exit (32);
   652   }
   654   printf("Clearing...\n");
   655   UniToEntClass2.Clear();
   656   printf("  Clearing OK\n");
   658   printf("Checking count...");
   659   count = UniToEntClass2.Enumerate(nsIEnum, nullptr);
   660   if (count) {
   661     printf("  Clear did not remove all entries.\n");
   662     exit (33);
   663   }
   665   printf("OK\n");
   667   return 0;
   668 }

mercurial