/**************************************************************************
* 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.WeakHashMap; //complete the package name ...
import gnu.testlet.Testlet;
import gnu.testlet.TestHarness;
import java.util.*; // at least the class you are testing ...
import java.lang.reflect.*;
/**
* this file contains test for java.util.WeakHashMap <br>
* (this is a Modified version of SMHashMapTest with extra features to test the behaviour
* WeakReferences ...)
*/
public class AcuniaWeakHashMapTest implements Testlet {
protected TestHarness th;
protected Vector keys;
public void test (TestHarness harness) {
th = harness;
th.setclass("java.util.WeakHashMap");
test_WeakHashMap();
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_behaviour();
test_WeakRefBehaviour();
}
protected WeakHashMap buildHM() {
WeakHashMap hm = new WeakHashMap();
keys = new Vector(16);
String s;
for (int i=0 ; i < 15 ; i++) {
s = "a"+i;
hm.put(s , s+" value");
keys.add(s);
}
hm.put(null,null);
keys.add(null);
return hm;
}
/**
* implemented. <br>
*
*/
public void test_WeakHashMap(){
th.checkPoint("WeakHashMap(int)");
WeakHashMap hm = new WeakHashMap(1);
try { new WeakHashMap(-1);
th.fail("should throw an IllegalArgumentException");
}
catch(IllegalArgumentException iae) { th.check(true); }
th.checkPoint("WeakHashMap(int,float)");
try {new WeakHashMap(-1,0.1f);
th.fail("should throw an IllegalArgumentException -- 1");
}
catch(IllegalArgumentException iae) { th.check(true); }
try { new WeakHashMap(1,-0.1f);
th.fail("should throw an IllegalArgumentException -- 2");
}
catch(IllegalArgumentException iae) { th.check(true); }
try { new WeakHashMap(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");
WeakHashMap 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");
WeakHashMap hm = new WeakHashMap();
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");
WeakHashMap hm = new WeakHashMap();
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");
WeakHashMap hm = new WeakHashMap();
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");
WeakHashMap hm = new WeakHashMap();
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");
WeakHashMap 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");
WeakHashMap hm = new WeakHashMap();
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");
WeakHashMap hm = new WeakHashMap();
hm.putAll(new Hashtable());
th.check(hm.isEmpty() , "nothing addad");
hm.putAll(buildHM());
Vector store = keys;
th.check(hm.size() , 16 , "checking if all enough elements are added -- 1");
th.check(hm, 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");
store = keys;
th.check(hm, (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");
WeakHashMap 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");
WeakHashMap 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 );
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());
me.setValue(this);
th.check(hm.get(me.getKey()) , this, "set is supported");
}
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 WeakHashMap");
it= s.iterator();
hm.put(null,"sdf");
try {
it.next();
th.fail("should throw a ConcurrentModificationException -- 3");
}
catch(ConcurrentModificationException cme){ th.check(true); }
hm.put(null,"sdf");
it = s.iterator();
hm.clear();
hm.put(null,"sdf");
System.gc();
th.check(hm.size(), 1, "checking null key");
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");
WeakHashMap 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 WeakHashMap");
}
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");
WeakHashMap 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 WeakHashMap");
}
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); }
}
/**
* 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 final String st ="a";
private final Byte b =new Byte((byte)97);
private final Short sh=new Short((short)97);
private final Integer i = new Integer(97);
private final Long l = new Long(97L);
private int sqnce = 1;
public void test_behaviour(){
th.checkPoint("behaviour testing");
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(WeakHashMap 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);
WeakHashMap h = new WeakHashMap(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((float)j);
h.put(f,f);
}
th.check(h.size() == 105,"size checking -- 1 got: "+h.size());
check_presence(h);
for ( ; j < 200 ; j++ ){
f = new Float((float)j);
h.put(f,f);
}
th.check(h.size() == 205,"size checking -- 2 got: "+h.size());
check_presence(h);
for ( ; j < 300 ; j++ ){
f = new Float((float)j);
h.put(f,f);
}
th.check(h.size() == 305,"size checking -- 3 got: "+h.size());
check_presence(h);
//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((float)j);
h.remove(f);
}
th.check(h.size() == 205,"size checking -- 4 got: "+h.size());
check_presence(h);
for ( ; j > 99 ; j-- ){
f = new Float((float)j);
h.remove(f);
}
th.check(h.size() == 105,"size checking -- 5 got: "+h.size());
check_presence(h);
for ( ; j > -1 ; j-- ){
f = new Float((float)j);
h.remove(f);
}
th.check(h.size() == 5 ,"size checking -- 6 got: "+h.size());
th.debug(h.toString());
check_presence(h);
}
/**
** implemented
**
*/
public void test_WeakRefBehaviour(){
th.checkPoint("behaviour testing of 'null' key");
WeakHashMap hm = buildHM();
keys = null;
hm.put(null,"abc");
th.check(hm.get(null),"abc" , "checking presence of 'null'");
for(int i = 0 ; i < 10 ; i++){
System.gc();
if(hm.size() == 1){
break;
}
}
th.check(hm.size() , 1, "only 'null' key should remain");
th.checkPoint("behaviour testing of WeakReferences");
hm = buildHM();
hm.remove(null);
Iterator it = hm.entrySet().iterator();
int size = hm.size();
while(it.hasNext()){
java.util.Map.Entry entry = (java.util.Map.Entry) it.next();
keys.remove(entry.getKey());
entry = null;
System.gc();
th.check(hm.size() , size--);
}
hm = buildHM();
it = hm.entrySet().iterator();
size = hm.size();
while(it.hasNext()){
java.util.Map.Entry entry = (java.util.Map.Entry) it.next();
it.remove();
th.check(hm.size() , --size);
}
try {
it.remove();
th.fail("should throw an IllegalStateException");
}
catch(IllegalStateException ise){
th.check(true);
}
Integer key = new Integer(25);
hm.clear();
hm.put(key,key);
key = new Integer(25);
th.check(hm.put(key, "REMOVE ME"), key, "checking put");
for(int i = 0 ; i < 10 ; i++){
System.gc();
if(hm.size() == 0){
break;
}
try {
Thread.sleep(200);
}
catch(InterruptedException ie){}
}
th.check(hm.size(), 0 , "only first key counts");
}
}