lluuidhashmap_tut.cpp

Go to the documentation of this file.
00001 
00034 #include <tut/tut.h>
00035 #include "linden_common.h"
00036 #include "lluuidhashmap.h"
00037 #include "llsdserialize.h"
00038 
00039 namespace tut
00040 {
00041         class UUIDTableEntry
00042         {
00043         public:
00044                 UUIDTableEntry()
00045                 {
00046                         mID.setNull();
00047                         mValue = 0;
00048                 }
00049                 
00050                 UUIDTableEntry(const LLUUID& id, U32 value)
00051                 {
00052                         mID = id;
00053                         mValue = value;
00054                 }
00055 
00056                 ~UUIDTableEntry(){};
00057 
00058                 static BOOL uuidEq(const LLUUID &uuid, const UUIDTableEntry &id_pair)
00059                 {
00060                         if (uuid == id_pair.mID)
00061                         {
00062                                 return TRUE;
00063                         }
00064                         return FALSE;
00065                 }
00066 
00067                 const LLUUID& getID() { return mID; }
00068                 const U32& getValue() { return mValue; }
00069 
00070         protected:
00071                 LLUUID  mID;
00072                 U32  mValue;
00073         };
00074 
00075         struct hashmap_test
00076         {
00077         };
00078 
00079         typedef test_group<hashmap_test> hash_index_t;
00080         typedef hash_index_t::object hash_index_object_t;
00081         tut::hash_index_t tut_hash_index("hashmap_test");
00082 
00083         // stress test
00084         template<> template<>
00085         void hash_index_object_t::test<1>()
00086         {
00087                 LLUUIDHashMap<UUIDTableEntry, 32>       hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
00088                 const int numElementsToCheck = 32*256*32;
00089                 std::vector<LLUUID> idList(numElementsToCheck);
00090                 int i;
00091                 
00092                 for (i = 0; i < numElementsToCheck; i++)
00093                 {
00094                         LLUUID id;
00095                         id.generate();
00096                         UUIDTableEntry entry(id, i);
00097                         hashTable.set(id, entry);
00098                         idList[i] = id;
00099                 }
00100 
00101                 for (i = 0; i < numElementsToCheck; i++)
00102                 {
00103                         LLUUID idToCheck = idList[i];
00104                         UUIDTableEntry entryToCheck = hashTable.get(idToCheck);
00105                         ensure("set/get did not work", entryToCheck.getID() == idToCheck && entryToCheck.getValue() == (size_t)i);
00106                 }
00107 
00108                 for (i = 0; i < numElementsToCheck; i++)
00109                 {
00110                         LLUUID idToCheck = idList[i];
00111                         if (i % 2 != 0)
00112                         {
00113                                 hashTable.remove(idToCheck);
00114                         }
00115                 }
00116 
00117                 for (i = 0; i < numElementsToCheck; i++)
00118                 {
00119                         LLUUID idToCheck = idList[i];
00120                         ensure("remove or check did not work", (i % 2 == 0 && hashTable.check(idToCheck)) || (i % 2 != 0 && !hashTable.check(idToCheck)));
00121                 }
00122         }
00123 
00124         // test removing all but one element. 
00125         template<> template<>
00126         void hash_index_object_t::test<2>()
00127         {
00128                 LLUUIDHashMap<UUIDTableEntry, 2>        hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
00129                 const int numElementsToCheck = 5;
00130                 std::vector<LLUUID> idList(numElementsToCheck*10);
00131                 int i;
00132                 
00133                 for (i = 0; i < numElementsToCheck; i++)
00134                 {
00135                         LLUUID id;
00136                         id.generate();
00137                         UUIDTableEntry entry(id, i);
00138                         hashTable.set(id, entry);
00139                         idList[i] = id;
00140                 }
00141 
00142                 ensure("getLength failed", hashTable.getLength() == numElementsToCheck);
00143 
00144                 // remove all but the last element
00145                 for (i = 0; i < numElementsToCheck-1; i++)
00146                 {
00147                         LLUUID idToCheck = idList[i];
00148                         hashTable.remove(idToCheck);
00149                 }
00150 
00151                 // there should only be one element left now.
00152                 ensure("getLength failed", hashTable.getLength() == 1);
00153 
00154                 for (i = 0; i < numElementsToCheck; i++)
00155                 {
00156                         LLUUID idToCheck = idList[i];
00157                         if (i != numElementsToCheck - 1)
00158                         {
00159                                 ensure("remove did not work", hashTable.check(idToCheck)  == FALSE);
00160                         }
00161                         else
00162                         {
00163                                 UUIDTableEntry entryToCheck = hashTable.get(idToCheck);
00164                                 ensure("remove did not work", entryToCheck.getID() == idToCheck && entryToCheck.getValue() == (size_t)i);
00165                         }
00166                 }
00167         }
00168 
00169         // test overriding of value already set. 
00170         template<> template<>
00171         void hash_index_object_t::test<3>()
00172         {
00173                 LLUUIDHashMap<UUIDTableEntry, 5>        hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
00174                 const int numElementsToCheck = 10;
00175                 std::vector<LLUUID> idList(numElementsToCheck);
00176                 int i;
00177                 
00178                 for (i = 0; i < numElementsToCheck; i++)
00179                 {
00180                         LLUUID id;
00181                         id.generate();
00182                         UUIDTableEntry entry(id, i);
00183                         hashTable.set(id, entry);
00184                         idList[i] = id;
00185                 }
00186 
00187                 for (i = 0; i < numElementsToCheck; i++)
00188                 {
00189                         LLUUID id = idList[i];
00190                         // set new entry with value = i+numElementsToCheck
00191                         UUIDTableEntry entry(id, i+numElementsToCheck);
00192                         hashTable.set(id, entry);
00193                 }
00194 
00195                 for (i = 0; i < numElementsToCheck; i++)
00196                 {
00197                         LLUUID idToCheck = idList[i];
00198                         UUIDTableEntry entryToCheck = hashTable.get(idToCheck);
00199                         ensure("set/get did not work", entryToCheck.getID() == idToCheck && entryToCheck.getValue() == (size_t)(i+numElementsToCheck));
00200                 }
00201         }
00202 
00203         // test removeAll() 
00204         template<> template<>
00205         void hash_index_object_t::test<4>()
00206         {
00207                 LLUUIDHashMap<UUIDTableEntry, 5>        hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
00208                 const int numElementsToCheck = 10;
00209                 std::vector<LLUUID> idList(numElementsToCheck);
00210                 int i;
00211                 
00212                 for (i = 0; i < numElementsToCheck; i++)
00213                 {
00214                         LLUUID id;
00215                         id.generate();
00216                         UUIDTableEntry entry(id, i);
00217                         hashTable.set(id, entry);
00218                         idList[i] = id;
00219                 }
00220 
00221                 hashTable.removeAll();
00222                 ensure("removeAll failed", hashTable.getLength() == 0);
00223         }
00224 
00225 
00226         // test sparse map - force it by creating 256 entries that fall into 256 different nodes 
00227         template<> template<>
00228         void hash_index_object_t::test<5>()
00229         {
00230                 LLUUIDHashMap<UUIDTableEntry, 2>        hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
00231                 const int numElementsToCheck = 256;
00232                 std::vector<LLUUID> idList(numElementsToCheck);
00233                 int i;
00234                 
00235                 for (i = 0; i < numElementsToCheck; i++)
00236                 {
00237                         LLUUID id;
00238                         id.generate();
00239                         // LLUUIDHashMap uses mData[0] to pick the bucket
00240                         // overwrite mData[0] so that it ranges from 0 to 255
00241                         id.mData[0] = i; 
00242                         UUIDTableEntry entry(id, i);
00243                         hashTable.set(id, entry);
00244                         idList[i] = id;
00245                 }
00246 
00247                 for (i = 0; i < numElementsToCheck; i++)
00248                 {
00249                         LLUUID idToCheck = idList[i];
00250                         UUIDTableEntry entryToCheck = hashTable.get(idToCheck);
00251                         ensure("set/get did not work for sparse map", entryToCheck.getID() == idToCheck && entryToCheck.getValue() == (size_t)i);
00252                 }
00253 
00254                 for (i = 0; i < numElementsToCheck; i++)
00255                 {
00256                         LLUUID idToCheck = idList[i];
00257                         if (i % 2 != 0)
00258                         {
00259                                 hashTable.remove(idToCheck);
00260                         }
00261                 }
00262 
00263                 for (i = 0; i < numElementsToCheck; i++)
00264                 {
00265                         LLUUID idToCheck = idList[i];
00266                         ensure("remove or check did not work for sparse map", (i % 2 == 0 && hashTable.check(idToCheck)) || (i % 2 != 0 && !hashTable.check(idToCheck)));
00267                 }
00268         }
00269 
00270         // iterator
00271         template<> template<>
00272         void hash_index_object_t::test<6>()
00273         {
00274                 LLUUIDHashMap<UUIDTableEntry, 2>        hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
00275                 LLUUIDHashMapIter<UUIDTableEntry, 2> hashIter(&hashTable);
00276                 const int numElementsToCheck = 256;
00277                 std::vector<LLUUID> idList(numElementsToCheck);
00278                 int i;
00279                 
00280                 for (i = 0; i < numElementsToCheck; i++)
00281                 {
00282                         LLUUID id;
00283                         id.generate();
00284                         // LLUUIDHashMap uses mData[0] to pick the bucket
00285                         // overwrite mData[0] so that it ranges from 0 to 255
00286                         // to create a sparse map
00287                         id.mData[0] = i; 
00288                         UUIDTableEntry entry(id, i);
00289                         hashTable.set(id, entry);
00290                         idList[i] = id;
00291                 }
00292 
00293                 hashIter.first();
00294                 int numElementsIterated = 0;
00295                 while(!hashIter.done())
00296                 {
00297                         numElementsIterated++;
00298                         UUIDTableEntry tableEntry = *hashIter;
00299                         LLUUID id = tableEntry.getID();
00300                         hashIter.next();
00301                         ensure("Iteration failed for sparse map", tableEntry.getValue() < (size_t)numElementsToCheck && idList[tableEntry.getValue()] ==  tableEntry.getID());
00302                 }
00303 
00304                 ensure("iteration count failed", numElementsIterated == numElementsToCheck);
00305         }
00306 
00307         // remove after middle of iteration
00308         template<> template<>
00309         void hash_index_object_t::test<7>()
00310         {
00311                 LLUUIDHashMap<UUIDTableEntry, 2>        hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
00312                 LLUUIDHashMapIter<UUIDTableEntry, 2> hashIter(&hashTable);
00313                 const int numElementsToCheck = 256;
00314                 std::vector<LLUUID> idList(numElementsToCheck);
00315                 int i;
00316                 
00317                 LLUUID uuidtoSearch;
00318                 for (i = 0; i < numElementsToCheck; i++)
00319                 {
00320                         LLUUID id;
00321                         id.generate();
00322                         // LLUUIDHashMap uses mData[0] to pick the bucket
00323                         // overwrite mData[0] so that it ranges from 0 to 255
00324                         // to create a sparse map
00325                         id.mData[0] = i; 
00326                         UUIDTableEntry entry(id, i);
00327                         hashTable.set(id, entry);
00328                         idList[i] = id;
00329 
00330                         // pick uuid somewhere in the middle
00331                         if (i == 5)
00332                         {
00333                                 uuidtoSearch = id;
00334                         }
00335                 }
00336 
00337                 hashIter.first();
00338                 int numElementsIterated = 0;
00339                 while(!hashIter.done())
00340                 {
00341                         numElementsIterated++;
00342                         UUIDTableEntry tableEntry = *hashIter;
00343                         LLUUID id = tableEntry.getID();
00344                         if (uuidtoSearch == id)
00345                         {
00346                                 break;
00347                         }
00348                         hashIter.next();
00349                 }
00350 
00351                 // current iterator implementation will not allow any remove operations
00352                 // until ALL elements have been iterated over. this seems to be 
00353                 // an unnecessary restriction. Iterator should have a method to
00354                 // reset() its state so that further operations (inckuding remove)
00355                 // can be performed on the HashMap without having to iterate thru 
00356                 // all the remaining nodes. 
00357                 
00358 //               hashIter.reset();
00359 //               hashTable.remove(uuidtoSearch);
00360 //               ensure("remove after iteration reset failed", hashTable.check(uuidtoSearch) == FALSE);
00361         }
00362 }

Generated on Thu Jul 1 06:09:25 2010 for Second Life Viewer by  doxygen 1.4.7