/**************************************************************************
* Copyright (c) 2001 by Acunia N.V. All rights reserved. *
* *
* This software is copyrighted by and is the sole property of Acunia N.V. *
* and its licensors, if any. All rights, title, ownership, or other *
* interests in the software remain the property of Acunia N.V. and its *
* licensors, if any. *
* *
* This software may only be used in accordance with the corresponding *
* license agreement. Any unauthorized use, duplication, transmission, *
* distribution or disclosure of this software is expressly forbidden. *
* *
* This Copyright notice may not be removed or modified without prior *
* written consent of Acunia N.V. *
* *
* Acunia N.V. reserves the right to modify this software without notice. *
* *
* Acunia N.V. *
* Vanden Tymplestraat 35 info@acunia.com *
* 3000 Leuven http://www.acunia.com *
* Belgium - EUROPE *
**************************************************************************/
package gnu.testlet.wonka.util.HashMap; //complete the package name ...
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;
import gnu.testlet.Testlet;
import gnu.testlet.TestHarness;
/**
* this file contains test for java.util.HashMap <br>
*
*/
public class SMHashMapTest implements Testlet
{
protected TestHarness th;
public void test (TestHarness harness) {
th = harness;
th.setclass("java.util.HashMap");
test_HashMap();
test_get();
test_containsKey();
test_containsValue();
test_isEmpty();
test_size();
test_clear();
test_put();
test_putAll();
test_remove();
test_entrySet();
test_keySet();
test_values();
test_clone();
test_behaviour();
}
protected HashMap buildHM() {
HashMap hm = new HashMap();
String s;
for (int i=0 ; i < 15 ; i++) {
s = "a"+i;
hm.put(s , s+" value");
}
hm.put(null,null);
return hm;
}
/**
* implemented. <br>
*
*/
public void test_HashMap(){
Field lf = null;
try {
lf = HashMap.class.getDeclaredField("loadFactor");
// th.debug("DEBUG -- found loadFactor");
lf.setAccessible(true);
}
catch(Exception e){}
HashMap hm;
th.checkPoint("HashMap()");
hm = new HashMap();
try {
th.check( lf.getFloat(hm) == 0.75f, "checking value of loadFactor");
}
catch (Exception e) { th.fail("no exception wanted !!!, got "+e); }
th.checkPoint("HashMap(java.util.Map)");
HashMap hm1 = buildHM();
hm = new HashMap(hm1);
try {
th.check( lf.getFloat(hm) == 0.75f, "checking value of loadFactor");
}
catch (Exception e) { th.fail("no exception wanted !!!, got "+e); }
th.check(hm.size() == 16 , "all elements are put, got "+hm.size());
th.check(hm.get(null) == null , "test key and value pairs -- 1");
th.check("a1 value".equals(hm.get("a1")) , "test key and value pairs -- 2");
th.check("a10 value".equals(hm.get("a10")) , "test key and value pairs -- 3");
th.check("a0 value".equals(hm.get("a0")) , "test key and value pairs -- 4");
hm = new HashMap(new Hashtable());
th.check(hm.size() == 0 , "no elements are put, got "+hm.size());
try {
new HashMap(null);
th.fail("should throw a NullPointerException");
}
catch(NullPointerException ne) {th.check(true);}
th.checkPoint("HashMap(int)");
hm = new HashMap(1);
try {
th.check( lf.getFloat(hm) == 0.75f, "checking value of loadFactor");
}
catch (Exception e) { th.fail("no exception wanted !!!, got "+e); }
try { new HashMap(-1);
th.fail("should throw an IllegalArgumentException");
}
catch(IllegalArgumentException iae) { th.check(true); }
th.checkPoint("HashMap(int,float)");
hm = new HashMap(10,0.5f);
try {
th.check( lf.getFloat(hm) == 0.5f, "checking value of loadFactor, got "+lf.getFloat(hm));
}
catch (Exception e) { th.fail("no exception wanted !!!, got "+e); }
hm = new HashMap(10,1.5f);
try {
th.check( lf.getFloat(hm) , 1.5f, "checking value of loadFactor, got "+lf.getFloat(hm));
}
catch (Exception e) { th.fail("no exception wanted !!!, got "+e); }
try {new HashMap(-1,0.1f);
th.fail("should throw an IllegalArgumentException -- 1");
}
catch(IllegalArgumentException iae) { th.check(true); }
try { new HashMap(1,-0.1f);
th.fail("should throw an IllegalArgumentException -- 2");
}
catch(IllegalArgumentException iae) { th.check(true); }
try { new HashMap(1,0.0f);
th.fail("should throw an IllegalArgumentException -- 2");
}
catch(IllegalArgumentException iae) { th.check(true); }
}
/**
* implemented. <br>
*
*/
public void test_get(){
th.checkPoint("get(java.lang.Object)java.lang.Object");
HashMap hm = buildHM();
th.check(hm.get(null) == null , "checking get -- 1");
th.check(hm.get(this) == null , "checking get -- 2");
hm.put("a" ,this);
th.check("a1 value".equals(hm.get("a1")), "checking get -- 3");
th.check("a11 value".equals(hm.get("a11")), "checking get -- 4");
th.check( hm.get(new Integer(97)) == null , "checking get -- 5");
}
/**
* implemented. <br>
*
*/
public void test_containsKey(){
th.checkPoint("containsKey(java.lang.Object)boolean");
HashMap hm = new HashMap();
hm.clear();
th.check(! hm.containsKey(null) ,"Map is empty");
hm.put("a" ,this);
th.check(! hm.containsKey(null) ,"Map does not containsthe key -- 1");
th.check( hm.containsKey("a") ,"Map does contain the key -- 2");
hm = buildHM();
th.check( hm.containsKey(null) ,"Map does contain the key -- 3");
th.check(! hm.containsKey(this) ,"Map does not contain the key -- 4");
}
/**
* implemented. <br>
*
*/
public void test_containsValue(){
th.checkPoint("containsValue(java.lang.Object)boolean");
HashMap hm = new HashMap();
hm.clear();
th.check(! hm.containsValue(null) ,"Map is empty");
hm.put("a" ,this);
th.check(! hm.containsValue(null) ,"Map does not containsthe value -- 1");
th.check(! hm.containsValue("a") ,"Map does not contain the value -- 2");
th.check( hm.containsValue(this) ,"Map does contain the value -- 3");
hm = buildHM();
th.check( hm.containsValue(null) ,"Map does contain the value -- 4");
th.check(! hm.containsValue(this) ,"Map does not contain the value -- 5");
th.check(! hm.containsValue("a1value") ,"Map does not contain the value -- 6");
}
/**
* implemented. <br>
*
*/
public void test_isEmpty(){
th.checkPoint("isEmpty()boolean");
HashMap hm = new HashMap();
th.check( hm.isEmpty() ,"Map is empty");
hm.put("a" ,this);
th.check(! hm.isEmpty() ,"Map is not empty");
}
/**
* implemented. <br>
*
*/
public void test_size(){
th.checkPoint("size()int");
HashMap hm = new HashMap();
th.check(hm.size() == 0 ,"Map is empty");
hm.put("a" ,this);
th.check(hm.size() == 1 ,"Map has 1 element");
hm = buildHM();
th.check(hm.size() == 16 ,"Map has 16 elements");
}
/**
* implemented. <br>
*
*/
public void test_clear(){
th.checkPoint("clear()void");
HashMap hm = buildHM();
hm.clear();
th.check(hm.size() == 0 ,"Map is cleared -- 1");
th.check(hm.isEmpty() ,"Map is cleared -- 2");
}
/**
* implemented. <br>
* is tested also in the other parts ...
*/
public void test_put(){
th.checkPoint("put(java.lang.Object,java.lang.Object)java.lang.Object");
HashMap hm = new HashMap();
th.check( hm.put(null , this ) == null , "check on return value -- 1");
th.check( hm.get(null) == this , "check on value -- 1");
th.check( hm.put(null , "a" ) == this , "check on return value -- 2");
th.check( "a".equals(hm.get(null)) , "check on value -- 2");
th.check( "a".equals(hm.put(null , "a" )), "check on return value -- 3");
th.check( "a".equals(hm.get(null)) , "check on value -- 3");
th.check( hm.size() == 1 , "only one key added");
th.check( hm.put("a" , null ) == null , "check on return value -- 4");
th.check( hm.get("a") == null , "check on value -- 4");
th.check( hm.put("a" , this ) == null , "check on return value -- 5");
th.check( hm.get("a") == this , "check on value -- 5");
th.check( hm.size() == 2 , "two keys added");
}
/**
* implemented. <br>
*
*/
public void test_putAll(){
th.checkPoint("putAll(java.util.Map)void");
HashMap hm = new HashMap();
hm.putAll(new Hashtable());
th.check(hm.isEmpty() , "nothing addad");
hm.putAll(buildHM());
th.check(hm.size() == 16 , "checking if all enough elements are added -- 1");
th.check(hm.equals(buildHM()) , "check on all elements -- 1");
hm.put(null ,this);
hm.putAll(buildHM());
th.check(hm.size() == 16 , "checking if all enough elements are added -- 2");
th.check(hm.equals(buildHM()) , "check on all elements -- 2");
try {
hm.putAll(null);
th.fail("should throw a NullPointerException");
}
catch(NullPointerException npe) { th.check(true); }
}
/**
* implemented. <br>
*
*/
public void test_remove(){
th.checkPoint("remove(java.lang.Object)java.lang.Object");
HashMap hm = buildHM();
th.check(hm.remove(null) == null , "checking return value -- 1");
th.check(hm.remove(null) == null , "checking return value -- 2");
th.check(!hm.containsKey(null) , "checking removed key -- 1");
th.check(!hm.containsValue(null) , "checking removed value -- 1");
for (int i = 0 ; i < 15 ; i++) {
th.check( ("a"+i+" value").equals(hm.remove("a"+i)), " removing a"+i);
}
th.check(hm.isEmpty() , "checking if al is gone");
}
/**
* implemented. <br>
* uses AbstractSet --> check only the overwritten methods ... !
* iterator and size
* fail-fast iterator !
* add not supported !
* check the Map.Entry Objects ...
*/
public void test_entrySet(){
th.checkPoint("entrySet()java.util.Set");
HashMap hm = buildHM();
Set s = hm.entrySet();
Iterator it= s.iterator();
java.util.Map.Entry me=null;
it.next();
try {
s.add("ADDING");
th.fail("should throw an UnsupportedOperationException");
}
catch (UnsupportedOperationException uoe) { th.check(true); }
th.check( s.size() == 16 );
hm.remove("a12");
th.check( s.size() == 15 );
th.check(it.hasNext());
try {
it.next();
th.fail("should throw a ConcurrentModificationException -- 1");
}
catch(ConcurrentModificationException cme){ th.check(true); }
try {
it.remove();
th.fail("should throw a ConcurrentModificationException -- 2");
}
catch(ConcurrentModificationException cme){ th.check(true); }
// th.debug(hm.debug());
it= s.iterator();
try {
me = (java.util.Map.Entry)it.next();
// Thread.sleep(600L);
if (me.getKey()==null) me = (java.util.Map.Entry)it.next();
th.check( me.hashCode() , (me.getValue().hashCode() ^ me.getKey().hashCode()),"verifying hashCode");
th.check(! me.equals(it.next()));
}
catch(Exception e) { th.fail("got unwanted exception ,got "+e);
th.debug("got ME key = "+me+" and value = "+me.getKey());}
try {
// th.debug("got ME key = "+me.getKey()+" and value = "+me.getValue());
Object o = me.getValue();
th.check(me.setValue(this), o, "set is allowed");
}
catch(UnsupportedOperationException uoe) {
th.fail("should NOT throw an UnsupportedOperationException");
}
it= s.iterator();
Vector v = new Vector();
Object ob;
v.addAll(s);
while (it.hasNext()) {
ob = it.next();
it.remove();
if (!v.remove(ob))
th.debug("Object "+ob+" not in the Vector");
}
th.check( v.isEmpty() , "all elements gone from the vector");
// for (int k=0 ; k < v.size() ; k++ ) { th.debug("got "+v.get(k)+" as element "+k); }
th.check( hm.isEmpty() , "all elements removed from the HashMap");
it= s.iterator();
hm.put(null,"sdf");
try {
it.next();
th.fail("should throw a ConcurrentModificationException -- 3");
}
catch(ConcurrentModificationException cme){ th.check(true); }
it= s.iterator();
hm.clear();
try {
it.next();
th.fail("should throw a ConcurrentModificationException -- 4");
}
catch(ConcurrentModificationException cme){ th.check(true); }
}
/**
* implemented. <br>
* uses AbstractSet --> check only the overwritten methods ... !
* iterator and size
* fail-fast iterator !
* add not supported !
*/
public void test_keySet(){
th.checkPoint("keySet()java.util.Set");
HashMap hm = buildHM();
th.check( hm.size() == 16 , "checking map size(), got "+hm.size());
Set s=null;
Object [] o;
Iterator it;
try {
s = hm.keySet();
th.check( s != null ,"s != null");
th.check(s.size() == 16 ,"checking size keyset, got "+s.size());
o = s.toArray();
th.check( o != null ,"o != null");
th.check( o.length == 16 ,"checking length, got "+o.length);
// for (int i = 0 ; i < o.length ; i++ ){ th.debug("element "+i+" is "+o[i]); }
it = s.iterator();
Vector v = new Vector();
Object ob;
v.addAll(s);
while ( it.hasNext() ) {
ob = it.next();
it.remove();
if (!v.remove(ob))
th.debug("Object "+ob+" not in the Vector");
}
th.check( v.isEmpty() , "all elements gone from the vector");
th.check( hm.isEmpty() , "all elements removed from the HashMap");
}
catch (Exception e) { th.fail("got bad Exception -- got "+e); }
try {
s.add("ADDING");
th.fail("should throw an UnsupportedOperationException");
}
catch (UnsupportedOperationException uoe) { th.check(true); }
}
/**
* implemented. <br>
* uses AbstractCollection --> check only the overwritten methods ... !
* iterator and size
* fail-fast iterator !
* add not supported !
*/
public void test_values(){
th.checkPoint("values()java.util.Collection");
HashMap hm = buildHM();
th.check( hm.size() == 16 , "checking map size(), got "+hm.size());
Collection s=null;
Object [] o;
Iterator it;
try {
s = hm.values();
th.check( s != null ,"s != null");
th.check(s.size() == 16 ,"checking size keyset, got "+s.size());
o = s.toArray();
th.check( o != null ,"o != null");
th.check( o.length == 16 ,"checking length, got "+o.length);
// for (int i = 0 ; i < o.length ; i++ ){ th.debug("element "+i+" is "+o[i]); }
it = s.iterator();
Vector v = new Vector();
Object ob;
v.addAll(s);
while ( it.hasNext() ) {
ob = it.next();
it.remove();
if (!v.remove(ob))
th.debug("Object "+ob+" not in the Vector");
}
th.check( v.isEmpty() , "all elements gone from the vector");
th.check( hm.isEmpty() , "all elements removed from the HashMap");
}
catch (Exception e) { th.fail("got bad Exception -- got "+e); }
try {
s.add("ADDING");
th.fail("should throw an UnsupportedOperationException");
}
catch (UnsupportedOperationException uoe) { th.check(true); }
}
/**
* implemented. <br>
*
*/
public void test_clone(){
th.checkPoint("clone()java.lang.Object");
HashMap hm = buildHM();
Object o = hm.clone();
th.check( o != hm , "clone is not the same object");
th.check( hm.equals(o) , "clone is equal to Map");
hm.put("a","b");
th.check(! hm.equals(o) , "clone doesn't change if Map changes");
}
/**
* the goal of this test is to see how the hashtable behaves if we do a lot put's and removes. <br>
* we perform this test for different loadFactors and a low initialsize <br>
* we try to make it difficult for the table by using objects with same hashcode
*/
private static final String st ="a";
private static final Byte b = new Byte((byte)97);
private static final Short sh= new Short((short)97);
private static final Integer i = new Integer(97);
private static final Long l = new Long(97L);
private int sqnce = 1;
public void test_behaviour(){
th.checkPoint("behaviour testing");
// do_behaviourtest(0.2f);
do_behaviourtest(0.70f);
do_behaviourtest(0.75f);
do_behaviourtest(0.95f);
do_behaviourtest(1.0f);
}
protected void sleep(int time){
try { Thread.sleep(time); }
catch (Exception e) {}
}
protected void check_presence(HashMap h){
th.check( h.get(st) != null, "checking presence st -- sequence "+sqnce);
th.check( h.get(sh) != null, "checking presence sh -- sequence "+sqnce);
th.check( h.get(i) != null, "checking presence i -- sequence "+sqnce);
th.check( h.get(b) != null, "checking presence b -- sequence "+sqnce);
th.check( h.get(l) != null, "checking presence l -- sequence "+sqnce);
sqnce++;
}
protected void do_behaviourtest(float loadFactor) {
th.checkPoint("behaviour testing with loadFactor "+loadFactor);
HashMap h = new HashMap(11 , loadFactor);
int j=0;
Float f;
h.put(st,"a"); h.put(b,"byte"); h.put(sh,"short"); h.put(i,"int"); h.put(l,"long");
check_presence(h);
sqnce = 1;
for ( ; j < 100 ; j++ )
{ f = new Float(j);
h.put(f,f);
// sleep(5);
}
th.check(h.size() == 105,"size checking -- 1 got: "+h.size());
check_presence(h);
// sleep(500);
for ( ; j < 200 ; j++ )
{ f = new Float(j);
h.put(f,f);
// sleep(10);
}
th.check(h.size() == 205,"size checking -- 2 got: "+h.size());
check_presence(h);
// sleep(50);
for ( ; j < 300 ; j++ )
{ f = new Float(j);
h.put(f,f);
// sleep(10);
}
th.check(h.size() == 305,"size checking -- 3 got: "+h.size());
check_presence(h);
// sleep(50);
// replacing values -- checking if we get a non-zero value
th.check("a".equals(h.put(st,"na")), "replacing values -- 1 - st");
th.check("byte".equals(h.put(b,"nbyte")), "replacing values -- 2 - b");
th.check("short".equals(h.put(sh,"nshort")), "replacing values -- 3 -sh");
th.check("int".equals(h.put(i,"nint")) , "replacing values -- 4 -i");
th.check("long".equals(h.put(l,"nlong")), "replacing values -- 5 -l");
for ( ; j > 199 ; j-- )
{ f = new Float(j);
h.remove(f);
// sleep(10);
}
// sleep(150);
th.check(h.size() == 205,"size checking -- 4 got: "+h.size());
check_presence(h);
for ( ; j > 99 ; j-- )
{ f = new Float(j);
h.remove(f);
// sleep(5);
}
th.check(h.size() == 105,"size checking -- 5 got: "+h.size());
check_presence(h);
// sleep(1500);
for ( ; j > -1 ; j-- )
{ f = new Float(j);
h.remove(f);
// sleep(5);
}
th.check(h.size() == 5 ,"size checking -- 6 got: "+h.size());
//th.debug(h.toString());
check_presence(h);
// sleep(500);
}
}