aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/test/lluuidhashmap_tut.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/test/lluuidhashmap_tut.cpp')
-rw-r--r--linden/indra/test/lluuidhashmap_tut.cpp359
1 files changed, 359 insertions, 0 deletions
diff --git a/linden/indra/test/lluuidhashmap_tut.cpp b/linden/indra/test/lluuidhashmap_tut.cpp
new file mode 100644
index 0000000..a787326
--- /dev/null
+++ b/linden/indra/test/lluuidhashmap_tut.cpp
@@ -0,0 +1,359 @@
1/**
2 * @file lluuidhashmap_tut.cpp
3 * @author Adroit
4 * @date 2007-02
5 * @brief Test cases for LLUUIDHashMap
6 *
7 * Copyright (c) 2007-2007, Linden Research, Inc.
8 *
9 * Second Life Viewer Source Code
10 * The source code in this file ("Source Code") is provided by Linden Lab
11 * to you under the terms of the GNU General Public License, version 2.0
12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2
16 *
17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception
21 *
22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above,
24 * and agree to abide by those obligations.
25 *
26 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
27 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
28 * COMPLETENESS OR PERFORMANCE.
29 */
30
31#include <tut/tut.h>
32#include "linden_common.h"
33#include "lluuidhashmap.h"
34#include "llsdserialize.h"
35
36namespace tut
37{
38 class UUIDTableEntry
39 {
40 public:
41 UUIDTableEntry()
42 {
43 mID.setNull();
44 mValue = 0;
45 }
46
47 UUIDTableEntry(const LLUUID& id, U32 value)
48 {
49 mID = id;
50 mValue = value;
51 }
52
53 ~UUIDTableEntry(){};
54
55 static BOOL uuidEq(const LLUUID &uuid, const UUIDTableEntry &id_pair)
56 {
57 if (uuid == id_pair.mID)
58 {
59 return TRUE;
60 }
61 return FALSE;
62 }
63
64 const LLUUID& getID() { return mID; }
65 const U32& getValue() { return mValue; }
66
67 protected:
68 LLUUID mID;
69 U32 mValue;
70 };
71
72 struct hashmap_test
73 {
74 };
75
76 typedef test_group<hashmap_test> hash_index_t;
77 typedef hash_index_t::object hash_index_object_t;
78 tut::hash_index_t tut_hash_index("hashmap_test");
79
80 // stress test
81 template<> template<>
82 void hash_index_object_t::test<1>()
83 {
84 LLUUIDHashMap<UUIDTableEntry, 32> hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
85 const int numElementsToCheck = 32*256*32;
86 std::vector<LLUUID> idList(numElementsToCheck);
87 int i;
88
89 for (i = 0; i < numElementsToCheck; i++)
90 {
91 LLUUID id;
92 id.generate();
93 UUIDTableEntry entry(id, i);
94 hashTable.set(id, entry);
95 idList[i] = id;
96 }
97
98 for (i = 0; i < numElementsToCheck; i++)
99 {
100 LLUUID idToCheck = idList[i];
101 UUIDTableEntry entryToCheck = hashTable.get(idToCheck);
102 ensure("set/get did not work", entryToCheck.getID() == idToCheck && entryToCheck.getValue() == (size_t)i);
103 }
104
105 for (i = 0; i < numElementsToCheck; i++)
106 {
107 LLUUID idToCheck = idList[i];
108 if (i % 2 != 0)
109 {
110 hashTable.remove(idToCheck);
111 }
112 }
113
114 for (i = 0; i < numElementsToCheck; i++)
115 {
116 LLUUID idToCheck = idList[i];
117 ensure("remove or check did not work", (i % 2 == 0 && hashTable.check(idToCheck)) || (i % 2 != 0 && !hashTable.check(idToCheck)));
118 }
119 }
120
121 // test removing all but one element.
122 template<> template<>
123 void hash_index_object_t::test<2>()
124 {
125 LLUUIDHashMap<UUIDTableEntry, 2> hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
126 const int numElementsToCheck = 5;
127 std::vector<LLUUID> idList(numElementsToCheck*10);
128 int i;
129
130 for (i = 0; i < numElementsToCheck; i++)
131 {
132 LLUUID id;
133 id.generate();
134 UUIDTableEntry entry(id, i);
135 hashTable.set(id, entry);
136 idList[i] = id;
137 }
138
139 ensure("getLength failed", hashTable.getLength() == numElementsToCheck);
140
141 // remove all but the last element
142 for (i = 0; i < numElementsToCheck-1; i++)
143 {
144 LLUUID idToCheck = idList[i];
145 hashTable.remove(idToCheck);
146 }
147
148 // there should only be one element left now.
149 ensure("getLength failed", hashTable.getLength() == 1);
150
151 for (i = 0; i < numElementsToCheck; i++)
152 {
153 LLUUID idToCheck = idList[i];
154 if (i != numElementsToCheck - 1)
155 {
156 ensure("remove did not work", hashTable.check(idToCheck) == FALSE);
157 }
158 else
159 {
160 UUIDTableEntry entryToCheck = hashTable.get(idToCheck);
161 ensure("remove did not work", entryToCheck.getID() == idToCheck && entryToCheck.getValue() == (size_t)i);
162 }
163 }
164 }
165
166 // test overriding of value already set.
167 template<> template<>
168 void hash_index_object_t::test<3>()
169 {
170 LLUUIDHashMap<UUIDTableEntry, 5> hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
171 const int numElementsToCheck = 10;
172 std::vector<LLUUID> idList(numElementsToCheck);
173 int i;
174
175 for (i = 0; i < numElementsToCheck; i++)
176 {
177 LLUUID id;
178 id.generate();
179 UUIDTableEntry entry(id, i);
180 hashTable.set(id, entry);
181 idList[i] = id;
182 }
183
184 for (i = 0; i < numElementsToCheck; i++)
185 {
186 LLUUID id = idList[i];
187 // set new entry with value = i+numElementsToCheck
188 UUIDTableEntry entry(id, i+numElementsToCheck);
189 hashTable.set(id, entry);
190 }
191
192 for (i = 0; i < numElementsToCheck; i++)
193 {
194 LLUUID idToCheck = idList[i];
195 UUIDTableEntry entryToCheck = hashTable.get(idToCheck);
196 ensure("set/get did not work", entryToCheck.getID() == idToCheck && entryToCheck.getValue() == (size_t)(i+numElementsToCheck));
197 }
198 }
199
200 // test removeAll()
201 template<> template<>
202 void hash_index_object_t::test<4>()
203 {
204 LLUUIDHashMap<UUIDTableEntry, 5> hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
205 const int numElementsToCheck = 10;
206 std::vector<LLUUID> idList(numElementsToCheck);
207 int i;
208
209 for (i = 0; i < numElementsToCheck; i++)
210 {
211 LLUUID id;
212 id.generate();
213 UUIDTableEntry entry(id, i);
214 hashTable.set(id, entry);
215 idList[i] = id;
216 }
217
218 hashTable.removeAll();
219 ensure("removeAll failed", hashTable.getLength() == 0);
220 }
221
222
223 // test sparse map - force it by creating 256 entries that fall into 256 different nodes
224 template<> template<>
225 void hash_index_object_t::test<5>()
226 {
227 LLUUIDHashMap<UUIDTableEntry, 2> hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
228 const int numElementsToCheck = 256;
229 std::vector<LLUUID> idList(numElementsToCheck);
230 int i;
231
232 for (i = 0; i < numElementsToCheck; i++)
233 {
234 LLUUID id;
235 id.generate();
236 // LLUUIDHashMap uses mData[0] to pick the bucket
237 // overwrite mData[0] so that it ranges from 0 to 255
238 id.mData[0] = i;
239 UUIDTableEntry entry(id, i);
240 hashTable.set(id, entry);
241 idList[i] = id;
242 }
243
244 for (i = 0; i < numElementsToCheck; i++)
245 {
246 LLUUID idToCheck = idList[i];
247 UUIDTableEntry entryToCheck = hashTable.get(idToCheck);
248 ensure("set/get did not work for sparse map", entryToCheck.getID() == idToCheck && entryToCheck.getValue() == (size_t)i);
249 }
250
251 for (i = 0; i < numElementsToCheck; i++)
252 {
253 LLUUID idToCheck = idList[i];
254 if (i % 2 != 0)
255 {
256 hashTable.remove(idToCheck);
257 }
258 }
259
260 for (i = 0; i < numElementsToCheck; i++)
261 {
262 LLUUID idToCheck = idList[i];
263 ensure("remove or check did not work for sparse map", (i % 2 == 0 && hashTable.check(idToCheck)) || (i % 2 != 0 && !hashTable.check(idToCheck)));
264 }
265 }
266
267 // iterator
268 template<> template<>
269 void hash_index_object_t::test<6>()
270 {
271 LLUUIDHashMap<UUIDTableEntry, 2> hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
272 LLUUIDHashMapIter<UUIDTableEntry, 2> hashIter(&hashTable);
273 const int numElementsToCheck = 256;
274 std::vector<LLUUID> idList(numElementsToCheck);
275 int i;
276
277 for (i = 0; i < numElementsToCheck; i++)
278 {
279 LLUUID id;
280 id.generate();
281 // LLUUIDHashMap uses mData[0] to pick the bucket
282 // overwrite mData[0] so that it ranges from 0 to 255
283 // to create a sparse map
284 id.mData[0] = i;
285 UUIDTableEntry entry(id, i);
286 hashTable.set(id, entry);
287 idList[i] = id;
288 }
289
290 hashIter.first();
291 int numElementsIterated = 0;
292 while(!hashIter.done())
293 {
294 numElementsIterated++;
295 UUIDTableEntry tableEntry = *hashIter;
296 LLUUID id = tableEntry.getID();
297 hashIter.next();
298 ensure("Iteration failed for sparse map", tableEntry.getValue() < (size_t)numElementsToCheck && idList[tableEntry.getValue()] == tableEntry.getID());
299 }
300
301 ensure("iteration count failed", numElementsIterated == numElementsToCheck);
302 }
303
304 // remove after middle of iteration
305 template<> template<>
306 void hash_index_object_t::test<7>()
307 {
308 LLUUIDHashMap<UUIDTableEntry, 2> hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
309 LLUUIDHashMapIter<UUIDTableEntry, 2> hashIter(&hashTable);
310 const int numElementsToCheck = 256;
311 std::vector<LLUUID> idList(numElementsToCheck);
312 int i;
313
314 LLUUID uuidtoSearch;
315 for (i = 0; i < numElementsToCheck; i++)
316 {
317 LLUUID id;
318 id.generate();
319 // LLUUIDHashMap uses mData[0] to pick the bucket
320 // overwrite mData[0] so that it ranges from 0 to 255
321 // to create a sparse map
322 id.mData[0] = i;
323 UUIDTableEntry entry(id, i);
324 hashTable.set(id, entry);
325 idList[i] = id;
326
327 // pick uuid somewhere in the middle
328 if (i == 5)
329 {
330 uuidtoSearch = id;
331 }
332 }
333
334 hashIter.first();
335 int numElementsIterated = 0;
336 while(!hashIter.done())
337 {
338 numElementsIterated++;
339 UUIDTableEntry tableEntry = *hashIter;
340 LLUUID id = tableEntry.getID();
341 if (uuidtoSearch == id)
342 {
343 break;
344 }
345 hashIter.next();
346 }
347
348 // current iterator implementation will not allow any remove operations
349 // until ALL elements have been iterated over. this seems to be
350 // an unnecessary restriction. Iterator should have a method to
351 // reset() its state so that further operations (inckuding remove)
352 // can be performed on the HashMap without having to iterate thru
353 // all the remaining nodes.
354
355// hashIter.reset();
356// hashTable.remove(uuidtoSearch);
357// ensure("remove after iteration reset failed", hashTable.check(uuidtoSearch) == FALSE);
358 }
359}