/*
* eXist Open Source Native XML Database
* Copyright (C) 2001-06 Wolfgang M. Meier
* wolfgang@exist-db.org
* http://exist.sourceforge.net
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
package org.exist.util.hashtable;
import java.util.Iterator;
import java.util.Random;
import junit.framework.TestCase;
/**
* @author Wolfgang Meier (wolfgang@exist-db.org)
*/
public class HashtableTest extends TestCase {
private int tabSize = 100000;
private Object values[] = new Object[tabSize];
public static void main(String[] args) {
junit.textui.TestRunner.run(HashtableTest.class);
}
public HashtableTest(String testname) {
super(testname);
}
public void testPut() {
int keys[] = new int[tabSize];
Int2ObjectHashMap table = new Int2ObjectHashMap(tabSize);
Random rand = new Random(System.currentTimeMillis());
System.out.println("Generating " + tabSize + " random keys...");
for(int i = 0; i < tabSize; i++) {
do {
keys[i] = rand.nextInt(Integer.MAX_VALUE);
} while(table.get(keys[i]) != null);
values[i] = new String("a" + keys[i]);
table.put(keys[i], values[i]);
}
System.out.println("Testing get(key) ...");
for(int i = 0; i < tabSize; i++) {
Object v = table.get(keys[i]);
assertEquals( values[i], v );
}
System.out.println("Testing remove(key) ...");
int r;
for(int i = 0; i < tabSize / 10; i++) {
do {
r = rand.nextInt(tabSize - 1);
} while(values[r] == null);
table.remove(keys[r]);
values[r] = null;
}
for(int i = 0; i <tabSize; i++) {
while(values[i] == null)
i++;
String v = (String)table.get(keys[i]);
assertNotNull("Key not found", v);
assertEquals(values[i], v);
}
int c = 0;
for(Iterator i = table.iterator(); i.hasNext(); c++) {
Integer v = (Integer)i.next();
}
System.out.println(table.size() + " = " + c);
System.out.println("maxRehash: " + table.getMaxRehash());
assertEquals(table.size(), c);
}
public void testObjectHashMap() {
String keys[] = new String[tabSize];
long values[] = new long[tabSize];
Object2LongHashMap table = new Object2LongHashMap(tabSize / 4);
Random rand = new Random(System.currentTimeMillis());
System.out.println("Generating " + tabSize + " random keys...");
for(int i = 0; i < tabSize; i++) {
do {
keys[i] = "/db/" + rand.nextInt(Integer.MAX_VALUE);
} while(table.get(keys[i]) != -1);
values[i] = rand.nextInt(Integer.MAX_VALUE);
table.put(keys[i], values[i]);
}
System.out.println("Testing get(key) ...");
for(int i = 0; i < tabSize; i++) {
long k = table.get(keys[i]);
assertEquals( values[i], k );
}
System.out.println("Remove/add keys ...");
for(int i = 0; i < tabSize * 10; i++) {
int idx0 = rand.nextInt(tabSize);
table.remove(keys[idx0]);
int idx1 = rand.nextInt(tabSize);
table.remove(keys[idx1]);
table.put(keys[idx0], values[idx0]);
table.put(keys[idx1], values[idx1]);
}
System.out.println("Testing get(key) ...");
for(int i = 0; i < tabSize; i++) {
long k = table.get(keys[i]);
assertEquals( values[i], k );
}
}
public void testSequencedMap() {
long keys[] = new long[tabSize];
SequencedLongHashMap table = new SequencedLongHashMap(tabSize);
Random rand = new Random(System.currentTimeMillis());
System.out.println("Generating " + tabSize + " random keys...");
for(int i = 0; i < tabSize; i++) {
do {
keys[i] = rand.nextInt(Integer.MAX_VALUE);
} while(table.get(keys[i]) != null);
values[i] = new String("a" + keys[i]);
table.put(keys[i], values[i]);
}
// check SequencedLongHashMap.get()
for(int i = 0; i < tabSize; i++) {
Object v = table.get(keys[i]);
assertEquals( values[i], v);
}
// check SequencedLongHashMap.iterator()
int c = 0;
for(Iterator i = table.iterator(); i.hasNext(); c++) {
Long v = (Long)i.next();
assertEquals(keys[c], v.longValue());
}
assertEquals(c, table.size());
// remove 1000 random items
for(int i = 0; i < 10000; i++) {
int k;
do {
k = rand.nextInt(tabSize - 1);
} while(values[k] == null);
table.remove(keys[k]);
values[k] = null;
assertNull(table.get(keys[k]));
}
System.out.println("Hashtable size: " + table.size());
// iterate through the sequence again
int k = 0;
c = 0;
for(Iterator i = table.iterator(); i.hasNext(); k++, c++) {
while(values[k] == null)
k++;
Long v = (Long)i.next();
assertTrue("Value has been removed and should be null", values[k] != null);
assertEquals("Keys don't match", keys[k], v.longValue());
}
assertEquals("Hashtable size is incorrect", table.size(), values.length - 10000);
assertEquals("Hashtable size is incorrect", table.size(), c);
System.gc();
// add some new items
for(int i = 0; i < values.length; i++) {
if(values[i] == null) {
do {
keys[i] = rand.nextInt(Integer.MAX_VALUE);
} while(table.get(keys[i]) != null);
values[i] = new String("a" + keys[i]);
table.put(keys[i], values[i]);
}
}
assertEquals(values.length, table.size());
// check SequencedLongHashMap.get()
for(int i = 0; i < tabSize; i++) {
Object v = table.get(keys[i]);
assertEquals( values[i], v);
}
// update keys
for (int i = 0; i < tabSize; i++) {
Object v = table.get(keys[i]);
values[i] = "b" + v;
table.put(keys[i], values[i]);
}
// check SequencedLongHashMap.get()
for(int i = 0; i < tabSize; i++) {
Object v = table.get(keys[i]);
assertEquals( values[i], v);
}
// check SequencedLongHashMap.iterator()
c = 0;
for(Iterator i = table.iterator(); i.hasNext(); c++) {
Long v = (Long)i.next();
}
assertEquals(c, table.size());
System.gc();
for(int i = 0; i < values.length; i++) {
table.removeFirst();
}
System.gc();
Iterator iter = table.iterator();
assertFalse("Hashtable should be empty", iter.hasNext());
assertTrue(table.size() == 0);
System.out.println("Hashtable size: " + table.size());
System.out.println("maxRehash: " + table.getMaxRehash());
}
public void testSequencedMap2() {
long[] l = { 10, 100, 50, 250, 100, 15, 35, 250, 100, 65, 45, 50, 65, 80, 90, 70, 250, 100 };
long[] expected = { 15, 35, 45, 50, 65, 80, 90, 70, 250, 100 };
SequencedLongHashMap table = new SequencedLongHashMap(tabSize);
for (int i = 0; i < l.length; i++) {
table.put(l[i], "k" + l[i]);
}
table.removeFirst();
SequencedLongHashMap.Entry next = table.getFirstEntry();
int i = 0;
while(next != null) {
assertEquals(next.getKey(), expected[i]);
System.out.print(next.getKey());
System.out.print(' ');
next = next.getNext();
i++;
}
System.out.println();
}
}