/indra/test/lluuidhashmap_tut.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 357 lines · 259 code · 43 blank · 55 comment · 60 complexity · 8fa005baa6bdbf6445f4100bf512c3ce MD5 · raw file

  1. /**
  2. * @file lluuidhashmap_tut.cpp
  3. * @author Adroit
  4. * @date 2007-02
  5. * @brief Test cases for LLUUIDHashMap
  6. *
  7. * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  8. * Second Life Viewer Source Code
  9. * Copyright (C) 2010, Linden Research, Inc.
  10. *
  11. * This library is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU Lesser General Public
  13. * License as published by the Free Software Foundation;
  14. * version 2.1 of the License only.
  15. *
  16. * This library is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  19. * Lesser General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU Lesser General Public
  22. * License along with this library; if not, write to the Free Software
  23. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  24. *
  25. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  26. * $/LicenseInfo$
  27. */
  28. #include <tut/tut.hpp>
  29. #include "linden_common.h"
  30. #include "lluuidhashmap.h"
  31. #include "llsdserialize.h"
  32. namespace tut
  33. {
  34. class UUIDTableEntry
  35. {
  36. public:
  37. UUIDTableEntry()
  38. {
  39. mID.setNull();
  40. mValue = 0;
  41. }
  42. UUIDTableEntry(const LLUUID& id, U32 value)
  43. {
  44. mID = id;
  45. mValue = value;
  46. }
  47. ~UUIDTableEntry(){};
  48. static BOOL uuidEq(const LLUUID &uuid, const UUIDTableEntry &id_pair)
  49. {
  50. if (uuid == id_pair.mID)
  51. {
  52. return TRUE;
  53. }
  54. return FALSE;
  55. }
  56. const LLUUID& getID() { return mID; }
  57. const U32& getValue() { return mValue; }
  58. protected:
  59. LLUUID mID;
  60. U32 mValue;
  61. };
  62. struct hashmap_test
  63. {
  64. };
  65. typedef test_group<hashmap_test> hash_index_t;
  66. typedef hash_index_t::object hash_index_object_t;
  67. tut::hash_index_t tut_hash_index("hashmap_test");
  68. // stress test
  69. template<> template<>
  70. void hash_index_object_t::test<1>()
  71. {
  72. LLUUIDHashMap<UUIDTableEntry, 32> hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
  73. const int numElementsToCheck = 32*256*32;
  74. std::vector<LLUUID> idList(numElementsToCheck);
  75. int i;
  76. for (i = 0; i < numElementsToCheck; i++)
  77. {
  78. LLUUID id;
  79. id.generate();
  80. UUIDTableEntry entry(id, i);
  81. hashTable.set(id, entry);
  82. idList[i] = id;
  83. }
  84. for (i = 0; i < numElementsToCheck; i++)
  85. {
  86. LLUUID idToCheck = idList[i];
  87. UUIDTableEntry entryToCheck = hashTable.get(idToCheck);
  88. ensure("set/get did not work", entryToCheck.getID() == idToCheck && entryToCheck.getValue() == (size_t)i);
  89. }
  90. for (i = 0; i < numElementsToCheck; i++)
  91. {
  92. LLUUID idToCheck = idList[i];
  93. if (i % 2 != 0)
  94. {
  95. hashTable.remove(idToCheck);
  96. }
  97. }
  98. for (i = 0; i < numElementsToCheck; i++)
  99. {
  100. LLUUID idToCheck = idList[i];
  101. ensure("remove or check did not work", (i % 2 == 0 && hashTable.check(idToCheck)) || (i % 2 != 0 && !hashTable.check(idToCheck)));
  102. }
  103. }
  104. // test removing all but one element.
  105. template<> template<>
  106. void hash_index_object_t::test<2>()
  107. {
  108. LLUUIDHashMap<UUIDTableEntry, 2> hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
  109. const int numElementsToCheck = 5;
  110. std::vector<LLUUID> idList(numElementsToCheck*10);
  111. int i;
  112. for (i = 0; i < numElementsToCheck; i++)
  113. {
  114. LLUUID id;
  115. id.generate();
  116. UUIDTableEntry entry(id, i);
  117. hashTable.set(id, entry);
  118. idList[i] = id;
  119. }
  120. ensure("getLength failed", hashTable.getLength() == numElementsToCheck);
  121. // remove all but the last element
  122. for (i = 0; i < numElementsToCheck-1; i++)
  123. {
  124. LLUUID idToCheck = idList[i];
  125. hashTable.remove(idToCheck);
  126. }
  127. // there should only be one element left now.
  128. ensure("getLength failed", hashTable.getLength() == 1);
  129. for (i = 0; i < numElementsToCheck; i++)
  130. {
  131. LLUUID idToCheck = idList[i];
  132. if (i != numElementsToCheck - 1)
  133. {
  134. ensure("remove did not work", hashTable.check(idToCheck) == FALSE);
  135. }
  136. else
  137. {
  138. UUIDTableEntry entryToCheck = hashTable.get(idToCheck);
  139. ensure("remove did not work", entryToCheck.getID() == idToCheck && entryToCheck.getValue() == (size_t)i);
  140. }
  141. }
  142. }
  143. // test overriding of value already set.
  144. template<> template<>
  145. void hash_index_object_t::test<3>()
  146. {
  147. LLUUIDHashMap<UUIDTableEntry, 5> hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
  148. const int numElementsToCheck = 10;
  149. std::vector<LLUUID> idList(numElementsToCheck);
  150. int i;
  151. for (i = 0; i < numElementsToCheck; i++)
  152. {
  153. LLUUID id;
  154. id.generate();
  155. UUIDTableEntry entry(id, i);
  156. hashTable.set(id, entry);
  157. idList[i] = id;
  158. }
  159. for (i = 0; i < numElementsToCheck; i++)
  160. {
  161. LLUUID id = idList[i];
  162. // set new entry with value = i+numElementsToCheck
  163. UUIDTableEntry entry(id, i+numElementsToCheck);
  164. hashTable.set(id, entry);
  165. }
  166. for (i = 0; i < numElementsToCheck; i++)
  167. {
  168. LLUUID idToCheck = idList[i];
  169. UUIDTableEntry entryToCheck = hashTable.get(idToCheck);
  170. ensure("set/get did not work", entryToCheck.getID() == idToCheck && entryToCheck.getValue() == (size_t)(i+numElementsToCheck));
  171. }
  172. }
  173. // test removeAll()
  174. template<> template<>
  175. void hash_index_object_t::test<4>()
  176. {
  177. LLUUIDHashMap<UUIDTableEntry, 5> hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
  178. const int numElementsToCheck = 10;
  179. std::vector<LLUUID> idList(numElementsToCheck);
  180. int i;
  181. for (i = 0; i < numElementsToCheck; i++)
  182. {
  183. LLUUID id;
  184. id.generate();
  185. UUIDTableEntry entry(id, i);
  186. hashTable.set(id, entry);
  187. idList[i] = id;
  188. }
  189. hashTable.removeAll();
  190. ensure("removeAll failed", hashTable.getLength() == 0);
  191. }
  192. // test sparse map - force it by creating 256 entries that fall into 256 different nodes
  193. template<> template<>
  194. void hash_index_object_t::test<5>()
  195. {
  196. LLUUIDHashMap<UUIDTableEntry, 2> hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
  197. const int numElementsToCheck = 256;
  198. std::vector<LLUUID> idList(numElementsToCheck);
  199. int i;
  200. for (i = 0; i < numElementsToCheck; i++)
  201. {
  202. LLUUID id;
  203. id.generate();
  204. // LLUUIDHashMap uses mData[0] to pick the bucket
  205. // overwrite mData[0] so that it ranges from 0 to 255
  206. id.mData[0] = i;
  207. UUIDTableEntry entry(id, i);
  208. hashTable.set(id, entry);
  209. idList[i] = id;
  210. }
  211. for (i = 0; i < numElementsToCheck; i++)
  212. {
  213. LLUUID idToCheck = idList[i];
  214. UUIDTableEntry entryToCheck = hashTable.get(idToCheck);
  215. ensure("set/get did not work for sparse map", entryToCheck.getID() == idToCheck && entryToCheck.getValue() == (size_t)i);
  216. }
  217. for (i = 0; i < numElementsToCheck; i++)
  218. {
  219. LLUUID idToCheck = idList[i];
  220. if (i % 2 != 0)
  221. {
  222. hashTable.remove(idToCheck);
  223. }
  224. }
  225. for (i = 0; i < numElementsToCheck; i++)
  226. {
  227. LLUUID idToCheck = idList[i];
  228. ensure("remove or check did not work for sparse map", (i % 2 == 0 && hashTable.check(idToCheck)) || (i % 2 != 0 && !hashTable.check(idToCheck)));
  229. }
  230. }
  231. // iterator
  232. template<> template<>
  233. void hash_index_object_t::test<6>()
  234. {
  235. LLUUIDHashMap<UUIDTableEntry, 2> hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
  236. LLUUIDHashMapIter<UUIDTableEntry, 2> hashIter(&hashTable);
  237. const int numElementsToCheck = 256;
  238. std::vector<LLUUID> idList(numElementsToCheck);
  239. int i;
  240. for (i = 0; i < numElementsToCheck; i++)
  241. {
  242. LLUUID id;
  243. id.generate();
  244. // LLUUIDHashMap uses mData[0] to pick the bucket
  245. // overwrite mData[0] so that it ranges from 0 to 255
  246. // to create a sparse map
  247. id.mData[0] = i;
  248. UUIDTableEntry entry(id, i);
  249. hashTable.set(id, entry);
  250. idList[i] = id;
  251. }
  252. hashIter.first();
  253. int numElementsIterated = 0;
  254. while(!hashIter.done())
  255. {
  256. numElementsIterated++;
  257. UUIDTableEntry tableEntry = *hashIter;
  258. LLUUID id = tableEntry.getID();
  259. hashIter.next();
  260. ensure("Iteration failed for sparse map", tableEntry.getValue() < (size_t)numElementsToCheck && idList[tableEntry.getValue()] == tableEntry.getID());
  261. }
  262. ensure("iteration count failed", numElementsIterated == numElementsToCheck);
  263. }
  264. // remove after middle of iteration
  265. template<> template<>
  266. void hash_index_object_t::test<7>()
  267. {
  268. LLUUIDHashMap<UUIDTableEntry, 2> hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
  269. LLUUIDHashMapIter<UUIDTableEntry, 2> hashIter(&hashTable);
  270. const int numElementsToCheck = 256;
  271. std::vector<LLUUID> idList(numElementsToCheck);
  272. int i;
  273. LLUUID uuidtoSearch;
  274. for (i = 0; i < numElementsToCheck; i++)
  275. {
  276. LLUUID id;
  277. id.generate();
  278. // LLUUIDHashMap uses mData[0] to pick the bucket
  279. // overwrite mData[0] so that it ranges from 0 to 255
  280. // to create a sparse map
  281. id.mData[0] = i;
  282. UUIDTableEntry entry(id, i);
  283. hashTable.set(id, entry);
  284. idList[i] = id;
  285. // pick uuid somewhere in the middle
  286. if (i == 5)
  287. {
  288. uuidtoSearch = id;
  289. }
  290. }
  291. hashIter.first();
  292. int numElementsIterated = 0;
  293. while(!hashIter.done())
  294. {
  295. numElementsIterated++;
  296. UUIDTableEntry tableEntry = *hashIter;
  297. LLUUID id = tableEntry.getID();
  298. if (uuidtoSearch == id)
  299. {
  300. break;
  301. }
  302. hashIter.next();
  303. }
  304. // current iterator implementation will not allow any remove operations
  305. // until ALL elements have been iterated over. this seems to be
  306. // an unnecessary restriction. Iterator should have a method to
  307. // reset() its state so that further operations (inckuding remove)
  308. // can be performed on the HashMap without having to iterate thru
  309. // all the remaining nodes.
  310. // hashIter.reset();
  311. // hashTable.remove(uuidtoSearch);
  312. // ensure("remove after iteration reset failed", hashTable.check(uuidtoSearch) == FALSE);
  313. }
  314. }