/************************************************************************** * 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.Hashtable; import java.util.Collection; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.Set; import gnu.testlet.Testlet; import gnu.testlet.TestHarness; /** * This file contains testcode for java.util.Hashtable <br> * --> some basic test are performed by basic.java <br> * Large parts of this file is commented out <br> * --> the tested methods are not in wonka <br> * <br> * if Map interface is tested --> revise this code ! */ public class SMHashtableTest implements Testlet { protected TestHarness th; public void test (TestHarness harness) { th = harness; th.setclass("java.util.Hashtable"); test_Hashtable(); test_elements(); test_get (); test_keys (); test_contains(); test_containsKey(); test_containsValue(); test_isEmpty(); test_size(); test_put(); test_putAll (); test_remove(); test_entrySet(); test_keySet(); test_values(); test_clone(); test_equals(); test_hashCode(); test_toString(); test_rehash(); test_behaviour(); } public Hashtable buildknownHt() { Hashtable ht = new Hashtable(19); Float f; for (int i =0; i < 11; i++) { f = new Float((float)i); ht.put( f , f ); } return ht; } /** * implemented. <br> * testing this is not easy since we cannot get the values of <br> * the properties we pass to the hashtable --> code looked OK <br> * we just make the objects and do some basic testing. */ public void test_Hashtable(){ th.checkPoint("Hashtable()"); Hashtable h = new Hashtable(); h = new Hashtable(233, 0.5f); // what happens if initialsize is 0, -1 or Integer.MAX_VALUE ???? try { h = new Hashtable(0); th.check(true,"test 1"); h = new Hashtable(25); th.check(true,"test 2"); } catch (Exception e) {th.fail("shouldn't throw an exception -- "+e);} try { h = new Hashtable(-233); th.fail("should throw an IllegalArgumentException"); } catch (IllegalArgumentException ie) { th.check(true,"test 3");} // what happens if loadfactor is 0.0f, -1.0f or 2345.56f ???? try { h = new Hashtable(233, 23.0f); th.check(true,"test 4"); } catch (Exception e) {th.fail("shouldn't throw an exception -- "+e);} try { h = new Hashtable(233, 0.0f); th.fail("should throw an IllegalArgumentException"); } catch (IllegalArgumentException ie) { th.check(true,"test 5");} try { h = new Hashtable(233 ,-1.0f); th.fail("should throw an IllegalArgumentException"); } catch (IllegalArgumentException ie) { th.check(true,"test 6");} //the interface MAP is not yet defined so the following test are not yet usefull // h = new Hashtable(buildknownHt()); // th.check (h.size() == 11 , "the map had 11 enries"); try { h = new Hashtable(null); th.fail("should throw a NullPointerException"); } catch (NullPointerException ne) {th.check(true);} } /** * implemented. * */ public void test_elements(){ th.checkPoint("elements()java.util.Enumeration"); Hashtable ht = buildknownHt(); Object o; Float f; Enumeration e = (Enumeration) ht.elements(); int i = 0; while (e.hasMoreElements()){ i++; f= (Float) e.nextElement(); o = ht.get( f ); th.check( o != null,"each element is unique -- nr "+i); ht.remove(f); } th.check(i == 11, "we should have 11 elements"); th.check(ht.size() == 0); e = new Hashtable().elements(); th.check( e != null , "elements should return a non-null value"); th.check(!e.hasMoreElements(), "e should not have elements"); } /** * implemented. * */ public void test_get(){ th.checkPoint("get(java.lang.Object)java.lang.Object"); Hashtable hte=new Hashtable(),ht = buildknownHt(); try { ht.get(null); th.fail("should throw NullPointerException"); } catch (NullPointerException ne) { th.check(true); } th.check( ht.get(new Object()) == null ,"gives back null if not in -- 1"); Float f = (Float) ht.elements().nextElement(); Float g = new Float(f.floatValue()+0.00001); th.check( ht.get(g) == null ,"gives back null if not in -- 2"); th.check( ht.get(f) == f,"key and element are same so get(f)==f -- 1"); // if we change the value of hte then the hashcode of hte changes --> but hte is still in the Hashtable ht.put(hte,hte); hte.put(f,f); hte.put(g,g); th.check( ht.get(hte) == hte , "changing the hashcode of a key --> key must be found"); } /** * implemented. * */ public void test_keys(){ th.checkPoint("keys()java.util.Enumeration"); Hashtable ht = buildknownHt(); Object o; Float f; Enumeration e = (Enumeration) ht.keys(); int i = 0; while (e.hasMoreElements()){ i++; f= (Float) e.nextElement(); o = ht.get( f ); th.check( o != null,"each key is unique -- nr "+i); ht.remove(f); } th.check(i == 11, "we should have 11 key"); th.check(ht.size() == 0); e = new Hashtable().keys(); th.check( e != null , "keys should return a non-null value"); th.check(!e.hasMoreElements(), "e should not have keys"); ht = new Hashtable(); e = ht.keys(); th.check(! e.hasMoreElements() , "empty HT Enum has no elements"); ht.put("abcd","value"); e = ht.keys(); th.check(e.hasMoreElements() , "HT Enum stil has elements"); th.check("abcd".equals(e.nextElement()) ,"checking returned value"); th.check(! e.hasMoreElements() , "HT Enum enumerated all elements"); } /** * implemented. * */ public void test_contains(){ th.checkPoint("contains(java.lang.Object)boolean"); Hashtable ht= buildknownHt(); Float f = new Float(10.0); th.check(ht.contains( f ),"contains uses equals -- 1"); f = new Float(11.0); th.check(!ht.contains( f ),"contains uses equals -- 2"); Double d = new Double(5.0); th.check(!ht.contains( d ),"contains uses equals -- 3"); ht.put(f,d); th.check(ht.contains( d ),"contains uses equals -- 4"); try { ht.contains(null); th.fail("should throw NullPointerException"); } catch (NullPointerException ne) { th.check(true); } } /** * implemented. * */ public void test_containsKey(){ th.checkPoint("containsKey(java.lang.Object)boolean"); Hashtable ht= buildknownHt(); Float f = new Float(10.0); th.check(ht.containsKey( f ),"containsKey uses equals -- 1"); f = new Float(11.0); th.check(!ht.containsKey( f ),"containsKey uses equals -- 2"); Double d = new Double(5.0); th.check(!ht.containsKey( d ),"containsKey uses equals -- 3"); ht.put(d,f); th.check(ht.containsKey( d ),"containsKey uses equals -- 4"); try { ht.containsKey(null); th.fail("should throw NullPointerException"); } catch (NullPointerException ne) { th.check(true); } } /** * implemented. * */ public void test_containsValue(){ th.checkPoint("containsValue(java.lang.Object)boolean"); Hashtable ht= buildknownHt(); Float f = new Float(10.0); th.check(ht.containsValue( f ),"containsValue uses equals -- 1"); f = new Float(11.0); th.check(!ht.containsValue( f ),"containsValue uses equals -- 2"); Double d = new Double(5.0); th.check(!ht.containsValue( d ),"containsValue uses equals -- 3"); ht.put(d,f); th.check(!ht.containsValue( d ),"containsValue uses equals -- 4"); d = new Double(89.0); ht.put(f,d); th.check(ht.containsValue( d ),"containsValue uses equals -- 5"); try { ht.containsValue(null); th.fail("should throw NullPointerException"); } catch (NullPointerException ne) { th.check(true); } } /** * implemented. * */ public void test_isEmpty(){ th.checkPoint("isEmpty()boolean"); Hashtable ht= buildknownHt(); th.check(!ht.isEmpty(), "ht is not empty -- 1"); ht.clear(); th.check(ht.isEmpty(),"hashtable should be empty --> after clear"); ht.put(new Object(),ht); th.check(!ht.isEmpty(), "ht is not empty -- 2"); } /** * implemented. * */ public void test_size(){ th.checkPoint("size()int"); Hashtable ht= buildknownHt(); th.check( ht.size() == 11 ); } /** * implemented. * */ public void test_clear(){ th.checkPoint("clear()void"); Hashtable ht = new Hashtable(); ht.clear(); ht = buildknownHt(); if (!ht.isEmpty()) { ht.clear(); th.check(ht.isEmpty(),"hashtable should be empty --> after clear"); try { ht.clear(); //shouldnot throw any exception th.check(ht.isEmpty(),"hashtable should be empty --> after 2nd clear"); } catch (Exception e) { th.fail("clear should not throw "+e); } } } /** * implemented. * */ public void test_put(){ th.checkPoint("put(java.lang.Object,java.lang.Object)java.lang.Object"); Hashtable h = buildknownHt(); Float f = new Float(33.0f); Double d = new Double(343.0); th.check( h.put(f,f) == null ,"key f in not used"); th.check( h.get(f) == f, "make sure element is put there -- 1"); th.check( h.put(f,d) == f ,"key f in used --> return old element"); th.check( h.get(f) == d, "make sure element is put there -- 2"); try { h.put(null, d); th.fail("should throw NullPointerException -- 1"); } catch (NullPointerException ne) { th.check(true); } try { h.put(d,null); th.fail("should throw NullPointerException -- 2"); } catch (NullPointerException ne) { th.check(true); } try { h.put(null,null); th.fail("should throw NullPointerException -- 3"); } catch (NullPointerException ne) { th.check(true); } } /** * implemented. <br> * --> needs more testing with objects with Map interface */ public void test_putAll(){ th.checkPoint("putAll(java.util.Map)void"); Hashtable h = new Hashtable(); h.putAll(buildknownHt()); th.check(h.size() == 11 && h.equals(buildknownHt())); Double d =new Double(34.0); Float f = new Float(2.0); h.put(f,d); h.putAll(buildknownHt()); th.check(h.size() == 11 && h.equals(buildknownHt())); h.put(d,d); h.putAll(buildknownHt()); th.check(h.size() == 12 && (!h.equals(buildknownHt()))); try { h.putAll(null); th.fail("should throw NullPointerException"); } catch (NullPointerException ne) { th.check(true); } } /** * implemented. * */ public void test_remove(){ th.checkPoint("remove(java.lang.Object)java.lang.Object"); Hashtable h = buildknownHt(); Float f = new Float(33.0f); int i= h.size(); try { h.remove(null); th.fail("should throw NullPointerException -- 1"); } catch (NullPointerException ne) { th.check(true); } th.check(h.remove(f) == null, "key not there so return null"); th.check(h.size() == i, "check on size -- 1"); for (int j=0 ; j < 11 ; j++) { f = new Float((float)j); th.check(h.remove(f).equals(f), "key is there so return element -- "+j); th.check(h.size() == --i, "check on size after removing -- "+j); } } /** * implemented. * */ public void test_entrySet(){ th.checkPoint("entrySet()java.util.Set"); Hashtable h = buildknownHt(); Set s = h.entrySet(); // th.debug("past Set construction"); int j; java.util.Map.Entry m; th.check(s.size() == 11); Object [] ao = s.toArray(); for (j=0 ; j < ao.length ; j++){ // th.debug("got element "+j+":"+ao[j]); } Iterator i = s.iterator(); // th.debug("past iterator"); for (j =0 ; true ; j++) { if (!i.hasNext()) break; m = (java.util.Map.Entry)i.next(); if (j==50) break; } th.check( j == 11 , "Iterator of Set must not do an Inf Loop, got j"+j); } /** * implemented. * */ public void test_keySet(){ th.checkPoint("keySet()java.util.Set"); Hashtable h = buildknownHt(); Set s = h.keySet(); th.check(s.size() == 11); for (int i = 0; i < 11 ; i++) { th.check(s.contains(new Float((float)i)),"check if all keys are given -- "+i); } } /** * implemented. * */ public void test_values(){ th.checkPoint("values()java.util.Collection"); Hashtable h = buildknownHt(); Collection c = h.values(); th.check(c.size() == 11); for (int i = 0; i < 11 ; i++) { th.check(c.contains(new Float((float)i)),"check if all values are given -- "+i); } } /** * implemented. * */ public void test_clone(){ th.checkPoint("clone()java.lang.Object"); Hashtable ht2,ht1 = buildknownHt(); ht2 = (Hashtable) ht1.clone(); th.check( ht2.size() == 11 ,"checking size -- got: "+ht2.size()); th.check( ht2.equals( ht1) ,"clone gives back equal hashtables"); Object o; Float f; Enumeration e = (Enumeration) ht1.elements(); for (int i=0; i < 11; i++) { f= (Float) e.nextElement(); o = ht2.get( f ); th.check( f == (Float) o,"key and element are the same"); } f= (Float) ht1.elements().nextElement(); ht2.remove(f); th.check(ht1.size() == 11 , "changes in clone do not affect original"); ht1.put(ht2,ht1); th.check(ht2.size() == 10 , "changes in original do not affect clone"); ht1 =new Hashtable(); ht2 = (Hashtable) ht1.clone(); th.check(ht2.size() == 0 , "cloning an empty hashtable must work"); } /** * implemented. * */ public void test_equals(){ th.checkPoint("equals(java.lang.Object)boolean"); Hashtable h2= buildknownHt(),h1 = buildknownHt(); th.check(h2.equals(h1),"hashtables are equal -- 1"); h2.remove(new Float(2.0f)); th.check(!h2.equals(h1),"hashtables are not equal"); h1.remove(new Float(2.0f)); th.check(h2.equals(h1),"hashtables are equal -- 2"); th.check(!h2.equals(new Float(3.0)),"hashtables is not equal to Float"); } /** * implemented. * */ public void test_hashCode(){ th.checkPoint("hashCode()int"); Hashtable h = new Hashtable(13); th.check( buildknownHt().hashCode() == buildknownHt().hashCode() ); Integer i = new Integer(4545); String s = new String("string"); Double d = new Double(23245.6); Object o = new Object(); h.put(i,s); th.check(h.hashCode() == (i.hashCode() ^ s.hashCode())); h.put(d,o); th.check(h.hashCode() == (i.hashCode() ^ s.hashCode())+(d.hashCode() ^ o.hashCode())); } /** * implemented. * */ public void test_toString(){ th.checkPoint("toString()java.lang.String"); Hashtable h = new Hashtable(13,0.75f); th.check(h.toString().equals("{}"), "got: "+h); h.put("SmartMove","Fantastic"); th.check(h.toString().equals("{SmartMove=Fantastic}"), "got: "+h); h.put("nr 1",new Float(23.0)); // the order is not specified th.check(h.toString().equals("{SmartMove=Fantastic, nr 1=23.0}")|| h.toString().equals("{nr 1=23.0, SmartMove=Fantastic}"), "got: "+h); h.remove("SmartMove"); th.check(h.toString().equals("{nr 1=23.0}"), "got: "+h); } /** * implemented. * */ public void test_rehash(){ th.checkPoint("rehash()void"); // simple test to see if rehash doesn't cause a crash Hashtable h = new Hashtable(3 , 0.5f); try { h.put("Smart","Move"); h.put("rehash","now"); th.check(h.size() == 2); } catch (Exception e) {th.fail("caught exception "+e);} } /** * 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.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(Hashtable 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); Hashtable h = new Hashtable(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); // 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((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((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((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((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((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); } }