PageRenderTime 44ms CodeModel.GetById 18ms app.highlight 22ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/test/lluuidhashmap_tut.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 357 lines | 259 code | 43 blank | 55 comment | 58 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
 29#include <tut/tut.hpp>
 30#include "linden_common.h"
 31#include "lluuidhashmap.h"
 32#include "llsdserialize.h"
 33
 34namespace tut
 35{
 36	class UUIDTableEntry
 37	{
 38	public:
 39		UUIDTableEntry()
 40		{
 41			mID.setNull();
 42			mValue = 0;
 43		}
 44		
 45		UUIDTableEntry(const LLUUID& id, U32 value)
 46		{
 47			mID = id;
 48			mValue = value;
 49		}
 50
 51		~UUIDTableEntry(){};
 52
 53		static BOOL uuidEq(const LLUUID &uuid, const UUIDTableEntry &id_pair)
 54		{
 55			if (uuid == id_pair.mID)
 56			{
 57				return TRUE;
 58			}
 59			return FALSE;
 60		}
 61
 62		const LLUUID& getID() { return mID; }
 63		const U32& getValue() { return mValue; }
 64
 65	protected:
 66		LLUUID	mID;
 67		U32  mValue;
 68	};
 69
 70	struct hashmap_test
 71	{
 72	};
 73
 74	typedef test_group<hashmap_test> hash_index_t;
 75	typedef hash_index_t::object hash_index_object_t;
 76	tut::hash_index_t tut_hash_index("hashmap_test");
 77
 78	// stress test
 79	template<> template<>
 80	void hash_index_object_t::test<1>()
 81	{
 82		LLUUIDHashMap<UUIDTableEntry, 32>	hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
 83		const int numElementsToCheck = 32*256*32;
 84		std::vector<LLUUID> idList(numElementsToCheck);
 85		int i;
 86		
 87		for (i = 0; i < numElementsToCheck; i++)
 88		{
 89			LLUUID id;
 90			id.generate();
 91			UUIDTableEntry entry(id, i);
 92			hashTable.set(id, entry);
 93			idList[i] = id;
 94		}
 95
 96		for (i = 0; i < numElementsToCheck; i++)
 97		{
 98			LLUUID idToCheck = idList[i];
 99			UUIDTableEntry entryToCheck = hashTable.get(idToCheck);
100			ensure("set/get did not work", entryToCheck.getID() == idToCheck && entryToCheck.getValue() == (size_t)i);
101		}
102
103		for (i = 0; i < numElementsToCheck; i++)
104		{
105			LLUUID idToCheck = idList[i];
106			if (i % 2 != 0)
107			{
108				hashTable.remove(idToCheck);
109			}
110		}
111
112		for (i = 0; i < numElementsToCheck; i++)
113		{
114			LLUUID idToCheck = idList[i];
115			ensure("remove or check did not work", (i % 2 == 0 && hashTable.check(idToCheck)) || (i % 2 != 0 && !hashTable.check(idToCheck)));
116		}
117	}
118
119	// test removing all but one element. 
120	template<> template<>
121	void hash_index_object_t::test<2>()
122	{
123		LLUUIDHashMap<UUIDTableEntry, 2>	hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
124		const int numElementsToCheck = 5;
125		std::vector<LLUUID> idList(numElementsToCheck*10);
126		int i;
127		
128		for (i = 0; i < numElementsToCheck; i++)
129		{
130			LLUUID id;
131			id.generate();
132			UUIDTableEntry entry(id, i);
133			hashTable.set(id, entry);
134			idList[i] = id;
135		}
136
137		ensure("getLength failed", hashTable.getLength() == numElementsToCheck);
138
139		// remove all but the last element
140		for (i = 0; i < numElementsToCheck-1; i++)
141		{
142			LLUUID idToCheck = idList[i];
143			hashTable.remove(idToCheck);
144		}
145
146		// there should only be one element left now.
147		ensure("getLength failed", hashTable.getLength() == 1);
148
149		for (i = 0; i < numElementsToCheck; i++)
150		{
151			LLUUID idToCheck = idList[i];
152			if (i != numElementsToCheck - 1)
153			{
154				ensure("remove did not work", hashTable.check(idToCheck)  == FALSE);
155			}
156			else
157			{
158				UUIDTableEntry entryToCheck = hashTable.get(idToCheck);
159				ensure("remove did not work", entryToCheck.getID() == idToCheck && entryToCheck.getValue() == (size_t)i);
160			}
161		}
162	}
163
164	// test overriding of value already set. 
165	template<> template<>
166	void hash_index_object_t::test<3>()
167	{
168		LLUUIDHashMap<UUIDTableEntry, 5>	hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
169		const int numElementsToCheck = 10;
170		std::vector<LLUUID> idList(numElementsToCheck);
171		int i;
172		
173		for (i = 0; i < numElementsToCheck; i++)
174		{
175			LLUUID id;
176			id.generate();
177			UUIDTableEntry entry(id, i);
178			hashTable.set(id, entry);
179			idList[i] = id;
180		}
181
182		for (i = 0; i < numElementsToCheck; i++)
183		{
184			LLUUID id = idList[i];
185			// set new entry with value = i+numElementsToCheck
186			UUIDTableEntry entry(id, i+numElementsToCheck);
187			hashTable.set(id, entry);
188		}
189
190		for (i = 0; i < numElementsToCheck; i++)
191		{
192			LLUUID idToCheck = idList[i];
193			UUIDTableEntry entryToCheck = hashTable.get(idToCheck);
194			ensure("set/get did not work", entryToCheck.getID() == idToCheck && entryToCheck.getValue() == (size_t)(i+numElementsToCheck));
195		}
196	}
197
198	// test removeAll() 
199	template<> template<>
200	void hash_index_object_t::test<4>()
201	{
202		LLUUIDHashMap<UUIDTableEntry, 5>	hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
203		const int numElementsToCheck = 10;
204		std::vector<LLUUID> idList(numElementsToCheck);
205		int i;
206		
207		for (i = 0; i < numElementsToCheck; i++)
208		{
209			LLUUID id;
210			id.generate();
211			UUIDTableEntry entry(id, i);
212			hashTable.set(id, entry);
213			idList[i] = id;
214		}
215
216		hashTable.removeAll();
217		ensure("removeAll failed", hashTable.getLength() == 0);
218	}
219
220
221	// test sparse map - force it by creating 256 entries that fall into 256 different nodes 
222	template<> template<>
223	void hash_index_object_t::test<5>()
224	{
225		LLUUIDHashMap<UUIDTableEntry, 2>	hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
226		const int numElementsToCheck = 256;
227		std::vector<LLUUID> idList(numElementsToCheck);
228		int i;
229		
230		for (i = 0; i < numElementsToCheck; i++)
231		{
232			LLUUID id;
233			id.generate();
234			// LLUUIDHashMap uses mData[0] to pick the bucket
235			// overwrite mData[0] so that it ranges from 0 to 255
236			id.mData[0] = i; 
237			UUIDTableEntry entry(id, i);
238			hashTable.set(id, entry);
239			idList[i] = id;
240		}
241
242		for (i = 0; i < numElementsToCheck; i++)
243		{
244			LLUUID idToCheck = idList[i];
245			UUIDTableEntry entryToCheck = hashTable.get(idToCheck);
246			ensure("set/get did not work for sparse map", entryToCheck.getID() == idToCheck && entryToCheck.getValue() == (size_t)i);
247		}
248
249		for (i = 0; i < numElementsToCheck; i++)
250		{
251			LLUUID idToCheck = idList[i];
252			if (i % 2 != 0)
253			{
254				hashTable.remove(idToCheck);
255			}
256		}
257
258		for (i = 0; i < numElementsToCheck; i++)
259		{
260			LLUUID idToCheck = idList[i];
261			ensure("remove or check did not work for sparse map", (i % 2 == 0 && hashTable.check(idToCheck)) || (i % 2 != 0 && !hashTable.check(idToCheck)));
262		}
263	}
264
265	// iterator
266	template<> template<>
267	void hash_index_object_t::test<6>()
268	{
269		LLUUIDHashMap<UUIDTableEntry, 2>	hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
270		LLUUIDHashMapIter<UUIDTableEntry, 2> hashIter(&hashTable);
271		const int numElementsToCheck = 256;
272		std::vector<LLUUID> idList(numElementsToCheck);
273		int i;
274		
275		for (i = 0; i < numElementsToCheck; i++)
276		{
277			LLUUID id;
278			id.generate();
279			// LLUUIDHashMap uses mData[0] to pick the bucket
280			// overwrite mData[0] so that it ranges from 0 to 255
281			// to create a sparse map
282			id.mData[0] = i; 
283			UUIDTableEntry entry(id, i);
284			hashTable.set(id, entry);
285			idList[i] = id;
286		}
287
288		hashIter.first();
289		int numElementsIterated = 0;
290		while(!hashIter.done())
291		{
292			numElementsIterated++;
293			UUIDTableEntry tableEntry = *hashIter;
294			LLUUID id = tableEntry.getID();
295			hashIter.next();
296			ensure("Iteration failed for sparse map", tableEntry.getValue() < (size_t)numElementsToCheck && idList[tableEntry.getValue()] ==  tableEntry.getID());
297		}
298
299		ensure("iteration count failed", numElementsIterated == numElementsToCheck);
300	}
301
302	// remove after middle of iteration
303	template<> template<>
304	void hash_index_object_t::test<7>()
305	{
306		LLUUIDHashMap<UUIDTableEntry, 2>	hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry());
307		LLUUIDHashMapIter<UUIDTableEntry, 2> hashIter(&hashTable);
308		const int numElementsToCheck = 256;
309		std::vector<LLUUID> idList(numElementsToCheck);
310		int i;
311		
312		LLUUID uuidtoSearch;
313		for (i = 0; i < numElementsToCheck; i++)
314		{
315			LLUUID id;
316			id.generate();
317			// LLUUIDHashMap uses mData[0] to pick the bucket
318			// overwrite mData[0] so that it ranges from 0 to 255
319			// to create a sparse map
320			id.mData[0] = i; 
321			UUIDTableEntry entry(id, i);
322			hashTable.set(id, entry);
323			idList[i] = id;
324
325			// pick uuid somewhere in the middle
326			if (i == 5)
327			{
328				uuidtoSearch = id;
329			}
330		}
331
332		hashIter.first();
333		int numElementsIterated = 0;
334		while(!hashIter.done())
335		{
336			numElementsIterated++;
337			UUIDTableEntry tableEntry = *hashIter;
338			LLUUID id = tableEntry.getID();
339			if (uuidtoSearch == id)
340			{
341				break;
342			}
343			hashIter.next();
344		}
345
346		// current iterator implementation will not allow any remove operations
347		// until ALL elements have been iterated over. this seems to be 
348		// an unnecessary restriction. Iterator should have a method to
349		// reset() its state so that further operations (inckuding remove)
350		// can be performed on the HashMap without having to iterate thru 
351		// all the remaining nodes. 
352		
353//		 hashIter.reset();
354//		 hashTable.remove(uuidtoSearch);
355//		 ensure("remove after iteration reset failed", hashTable.check(uuidtoSearch) == FALSE);
356	}
357}