/* * #! * Ontopia Engine * #- * Copyright (C) 2001 - 2013 The Ontopia Project * #- * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * !# */ package net.ontopia.utils; import java.util.ArrayList; import java.util.ConcurrentModificationException; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import java.util.Random; import java.util.Set; import junit.framework.TestCase; public class CompactHashSetTest extends TestCase { protected Set set; public CompactHashSetTest(String name) { super(name); } public void setUp() { set = new CompactHashSet(); } protected void tearDown() { } // --- Test cases public void testEmpty() { assertTrue("empty set doesn't know it's empty", set.isEmpty()); assertTrue("empty set size != 0", set.size() == 0); assertTrue("iterator on empty set has next element", !set.iterator().hasNext()); assertTrue("empty set claims to contain object", !set.contains("hei")); set.clear(); assertTrue("empty set size != 0", set.size() == 0); } public void testAdd() { set.add("hei"); assertTrue("set with 1 element thinks it's empty", !set.isEmpty()); assertTrue("set size != 1", set.size() == 1); assertTrue("add thinks object just added is not contained", !set.add("hei")); assertTrue("set with 1 element thinks it's empty", !set.isEmpty()); assertTrue("set size != 1", set.size() == 1); assertTrue("set thinks new object is already contained", set.add("hei2")); assertTrue("set size != 2", set.size() == 2); assertTrue("add thinks object just added is not contained", !set.add("hei")); assertTrue("add thinks object just added is not contained", !set.add("hei2")); } public void testContains() { set.add("hei"); assertTrue("set doesn't think just added object is contained", set.contains("hei")); assertTrue("set thinks not added object is contained", !set.contains("hei2")); } public void testIterator1() { set.add("hei"); Iterator it = set.iterator(); assertTrue("iterator from set(1) doesn't think it has a next", it.hasNext()); assertTrue("iterator didn't find object in set", it.next().equals("hei")); assertTrue("iterator from set(1) thinks it has a second object", !it.hasNext()); } public void testIterator2() { set.add("hei"); set.add("hei2"); Iterator it = set.iterator(); assertTrue("iterator from set(2) doesn't think it has a first", it.hasNext()); Object obj = it.next(); assertTrue("iterator didn't find object in set", obj.equals("hei") || obj.equals("hei2")); assertTrue("iterator from set(2) doesn't think it has a second object", it.hasNext()); obj = it.next(); assertTrue("iterator didn't find object in set", obj.equals("hei") || obj.equals("hei2")); assertTrue("iterator from set(2) thinks it has a third object", !it.hasNext()); } public void testIterator3() { set.add("hei"); set.add("hei2"); set.add("hei3"); Set otherSet = new HashSet(); Iterator it = set.iterator(); while (it.hasNext()) otherSet.add(it.next()); assertTrue("not all objects in set(3) iterated to", set.containsAll(otherSet) && otherSet.containsAll(set)); } public void testIteratorRemove() { set.add("hei"); set.add("hei2"); set.add("hei3"); Set otherSet = new HashSet(); Iterator it = set.iterator(); try { it.remove(); fail("could remove before iterator.next() called first time."); } catch (IllegalStateException e) { } while (it.hasNext()) { Object x = it.next(); if ("hei2".equals(x)) it.remove(); else otherSet.add(x); } assertTrue("set(2).size() != 2", set.size() == 2); assertTrue("iterator.remove() did not remove object", !set.contains("hei2")); assertTrue("set(2) not equal otherSet(2)", otherSet.equals(set)); try { try { it.next(); fail("could call next after !iterator.hasNext()."); } catch (NoSuchElementException e) { } it.remove(); fail("could remove when iterator.next() after last."); } catch (IllegalStateException e) { } } public void testConcurrentModification() { set.add("hei"); set.add("hei3"); set.add("hei4"); set.add("hei5"); Iterator it = set.iterator(); set.add("hei2"); try { it.next(); fail("set modification not detected"); } catch (ConcurrentModificationException e) { } it = set.iterator(); try { it.next(); set.remove("hei4"); it.next(); fail("set modification not detected"); } catch (ConcurrentModificationException e) { } it = set.iterator(); set.clear(); try { it.next(); fail("set modification not detected"); } catch (ConcurrentModificationException e) { } } public void testClear() { set.add("hei"); set.add("hei2"); set.clear(); testEmpty(); } public void testRehash() { set.add("hei"); set.add("hei2"); set.add("hei3"); set.add("hei4"); set.add("bei"); set.add("bei2"); set.add("bei3"); set.add("bei4"); set.add("_hei"); set.add("_hei2"); set.add("_hei3"); set.add("_hei4"); set.add("_bei"); set.add("_bei2"); set.add("_bei3"); set.add("_bei4"); set.add("$_hei"); set.add("$_hei2"); set.add("$_hei3"); set.add("$_hei4"); set.add("$_bei"); set.add("$_bei2"); set.add("$_bei3"); set.add("$_bei4"); assertTrue("set(24).size() != 24", set.size() == 24); assertTrue("contained object lost", set.contains("hei")); assertTrue("contained object lost", set.contains("hei2")); assertTrue("contained object lost", set.contains("hei3")); assertTrue("contained object lost", set.contains("hei4")); assertTrue("contained object lost", set.contains("_hei")); assertTrue("contained object lost", set.contains("_hei2")); assertTrue("contained object lost", set.contains("_hei3")); assertTrue("contained object lost", set.contains("_hei4")); assertTrue("contained object lost", set.contains("$_hei")); assertTrue("contained object lost", set.contains("$_hei2")); assertTrue("contained object lost", set.contains("$_hei3")); assertTrue("contained object lost", set.contains("$_hei4")); } public void testHashcodeNastiness() { Object o1 = new ObjectWithStupidHashCode("o1"); Object o2 = new ObjectWithStupidHashCode("o2"); Object o3 = new ObjectWithStupidHashCode("o3"); Object o4 = new ObjectWithStupidHashCode("o4"); Object o5 = new ObjectWithStupidHashCode("o5"); Object o6 = new ObjectWithStupidHashCode("o6"); assertTrue("object number 1 was already there!", set.add(o1)); assertTrue("object number 2 was already there!", set.add(o2)); assertTrue("object number 3 was already there!", set.add(o3)); assertTrue("object number 4 was already there!", set.add(o4)); assertTrue("object number 5 was already there!", set.add(o5)); assertTrue("object number 6 was already there!", set.add(o6)); assertTrue("object number 1 was lost!", set.contains(o1)); assertTrue("object number 2 was lost!", set.contains(o2)); assertTrue("object number 3 was lost!", set.contains(o3)); assertTrue("object number 4 was lost!", set.contains(o4)); assertTrue("object number 5 was lost!", set.contains(o5)); assertTrue("object number 6 was lost!", set.contains(o6)); assertTrue("object number 1 was lost! (2)", set.remove(o1)); assertTrue("object number 2 was lost! (2)", set.remove(o2)); assertTrue("object number 3 was lost! (2)", set.remove(o3)); assertTrue("object number 4 was lost! (2)", set.remove(o4)); assertTrue("object number 5 was lost! (2)", set.remove(o5)); assertTrue("object number 6 was lost! (2)", set.remove(o6)); assertTrue("wrong set size", set.size() == 0); assertTrue("object number 1 still present!", !set.contains(o1)); assertTrue("object number 2 still present!", !set.contains(o2)); assertTrue("object number 3 still present!", !set.contains(o3)); assertTrue("object number 4 still present!", !set.contains(o4)); assertTrue("object number 5 still present!", !set.contains(o5)); assertTrue("object number 6 still present!", !set.contains(o6)); } public void testNull() { set.add(null); assertTrue("null was not found", set.contains(null)); assertTrue("null was not found with iterator", set.iterator().next() == null); } public void testNull2() { assertTrue("null was found", !set.contains(null)); } public void testNull3() { set.add(null); Object[] array = set.toArray(); assertTrue("wrong size of array", array.length == 1); assertTrue("array doesn't contain null: " + array[0], array[0] == null); } public void testNull4() { set.add(null); Object[] array = set.toArray(new Object[1]); assertTrue("wrong size of array", array.length == 1); assertTrue("array doesn't contain null: " + array[0], array[0] == null); } public void testRemove() { set.add("hei"); assertTrue("remove didn't know element was in set", set.remove("hei")); assertTrue("removing only element in set does not make it empty", set.isEmpty()); } public void testRemove2() { set.add("hei"); set.add("hei2"); set.add("hei3"); assertTrue("remove didn't know element was in set", set.remove("hei")); assertTrue("member count wrong after remove", set.size() == 2); assertTrue("element not removed by remove", !set.contains("hei")); assertTrue("remove didn't know element was in set", set.remove("hei2")); assertTrue("member count wrong after remove", set.size() == 1); assertTrue("element not removed by remove", !set.contains("hei2")); assertTrue("remove didn't know element was in set", set.remove("hei3")); assertTrue("member count wrong after remove", set.size() == 0); assertTrue("element not removed by remove", !set.contains("hei3")); assertTrue("removing all elements in set does not make it empty", set.isEmpty()); } public void testRemoveAll() { set.add("hei"); set.add("hei2"); set.add("hei3"); List list = new ArrayList(); list.add("hei2"); list.add("hei4"); set.removeAll(list); assertTrue("wrong set element lost after removeAll", set.contains("hei")); assertTrue("wrong set element lost after removeAll", set.contains("hei3")); assertTrue("element not removed by removeAll", !set.contains("hei2")); assertTrue("wrong set size after removeAll", set.size() == 2); } public void testRemoveIteration() { testRemoveAll(); checkIterator(); } public void testRemoveModification() { set.add("hei"); set.add("hei123"); set.add("hei5"); Iterator it = set.iterator(); set.remove("hei123"); try { it.next(); fail("set modification not detected"); } catch (ConcurrentModificationException e) { } } public void testRemoveAndAdd() { set.add("Lars Marius"); set.add("Steve"); set.add("Geir Ove"); set.add("Kal Ahmed"); set.add("Pam Gennusa"); set.add("Murray Woodman"); set.add("Sylvia Schwab"); set.add("Ann Wrightson"); assertTrue("wrong set size", set.size() == 8); checkIterator(); set.remove("Kal Ahmed"); set.remove("Pam Gennusa"); set.remove("Murray Woodman"); set.remove("Ann Wrightson"); set.add("Niko Schmuck"); assertTrue("wrong set size after modification (1)", set.size() == 5); checkIterator(); assertTrue("element lost!", set.contains("Lars Marius")); assertTrue("element lost!", set.contains("Steve")); assertTrue("element lost!", set.contains("Geir Ove")); assertTrue("element lost!", set.contains("Sylvia Schwab")); assertTrue("element lost!", set.contains("Niko Schmuck")); assertTrue("element not gone!", !set.contains("Kal Ahmed")); assertTrue("element not gone!", !set.contains("Pam Gennusa")); assertTrue("element not gone!", !set.contains("Murray Woodman")); assertTrue("element not gone!", !set.contains("Ann Wrightson")); set.add("Harald Kuhn"); set.remove("Harald Kuhn"); set.remove("Niko Schmuck"); assertTrue("wrong set size after modification (2)", set.size() == 4); checkIterator(); assertTrue("element lost!", set.contains("Lars Marius")); assertTrue("element lost!", set.contains("Steve")); assertTrue("element lost!", set.contains("Geir Ove")); assertTrue("element lost!", set.contains("Sylvia Schwab")); assertTrue("element not gone!", !set.contains("Niko Schmuck")); assertTrue("element not gone!", !set.contains("Harald Kuhn")); set.add("Graham Moore"); set.add("Pam Gennusa"); assertTrue("wrong set size after modification (3)", set.size() == 6); checkIterator(); assertTrue("element lost!", set.contains("Lars Marius")); assertTrue("element lost!", set.contains("Steve")); assertTrue("element lost!", set.contains("Geir Ove")); assertTrue("element lost!", set.contains("Sylvia Schwab")); assertTrue("element lost!", set.contains("Graham Moore")); assertTrue("element lost!", set.contains("Pam Gennusa")); } public void testRemoveRehash() { set.add("hei"); set.add("hei2"); set.add("hei3"); set.add("hei4"); set.add("bei"); set.add("bei2"); set.add("bei3"); set.add("bei4"); set.add("_hei"); set.add("_hei2"); set.add("_hei3"); set.add("_hei4"); set.add("_bei"); set.add("_bei2"); set.add("_bei3"); set.add("_bei4"); set.add("$_hei"); set.add("$_hei2"); set.add("$_hei3"); set.add("$_hei4"); set.add("$_bei"); set.add("$_bei2"); set.add("$_bei3"); set.add("$_bei4"); Iterator it = new ArrayList(set).iterator(); while (it.hasNext()) assertTrue("object to be removed not found", set.remove(it.next())); set.add("hei"); set.add("hei2"); set.add("hei3"); set.add("hei4"); set.add("bei"); set.add("bei2"); set.add("bei3"); set.add("bei4"); set.add("_hei"); set.add("_hei2"); set.add("_hei3"); set.add("_hei4"); set.add("_bei"); set.add("_bei2"); set.add("_bei3"); set.add("_bei4"); set.add("$_hei"); set.add("$_hei2"); set.add("$_hei3"); set.add("$_hei4"); set.add("$_bei"); set.add("$_bei2"); set.add("$_bei3"); set.add("$_bei4"); set.add("xyxhei"); set.add("xyxhei2"); set.add("xyxhei3"); set.add("xyxhei4"); set.add("xyxbei"); set.add("xyxbei2"); set.add("xyxbei3"); set.add("xyxbei4"); set.add("xyx_hei"); set.add("xyx_hei2"); set.add("xyx_hei3"); set.add("xyx_hei4"); set.add("xyx_bei"); set.add("xyx_bei2"); set.add("xyx_bei3"); set.add("xyx_bei4"); set.add("xyx$_hei"); set.add("xyx$_hei2"); set.add("xyx$_hei3"); set.add("xyx$_hei4"); set.add("xyx$_bei"); set.add("xyx$_bei2"); set.add("xyx$_bei3"); set.add("xyx$_bei4"); assertTrue("wrong size of reconstituted set", set.size() == 48); } public void testProbabilistic() { Random random = new Random(); Set hashset = new HashSet(); for (int ix = 0; ix < 10000; ix++) { Integer value = new Integer(random.nextInt(100)); if (random.nextBoolean()) { // we're adding assertTrue("add returned wrong value", set.add(value) == hashset.add(value)); assertTrue("size was wrong after add", set.size() == hashset.size()); assertTrue("added object not found", set.contains(value)); } else { // we're removing assertTrue("remove returned wrong value", set.remove(value) == hashset.remove(value)); assertTrue("size was wrong after remove", set.size() == hashset.size()); assertTrue("removed object found", !set.contains(value)); } checkIterator(); checkToArray(); } } public void testIteratorRemove2() { set.add("1"); set.add("2"); set.add("3"); set.add("4"); assertTrue("wrong size", set.size() == 4); Iterator it = set.iterator(); while (it.hasNext()) { if (it.next().equals("2")) it.remove(); } assertTrue("1 was lost!", set.contains("1")); assertFalse("2 was not removed!", set.contains("2")); assertTrue("3 was lost!", set.contains("3")); assertTrue("4 was lost!", set.contains("4")); assertTrue("wrong number of elements", set.size() == 3); } public void testIteratorRemove3() { set.add("1"); set.add("2"); set.add("3"); set.add("4"); assertTrue("wrong size", set.size() == 4); Iterator it = set.iterator(); it.next(); Iterator it2 = set.iterator(); it.remove(); // whoa! try { it2.next(); // should fail, because we modified the set fail("undetected modification"); } catch (ConcurrentModificationException e) { // as required } } public void testIteratorRemove4() { set.add("1"); set.add("2"); set.add("3"); set.add("4"); assertTrue("wrong size", set.size() == 4); Iterator it = set.iterator(); it.next(); it.remove(); it.next(); // verifies that removing a value doesn't cause ConcModExc assertTrue("wrong size", set.size() == 3); } // --- Internal helper methods private void checkIterator() { List list = new ArrayList(); Iterator it = set.iterator(); while (it.hasNext()) list.add(it.next()); assertTrue("wrong number of elements found", list.size() == set.size()); assertTrue("not all objects in set iterated to", set.containsAll(list) && list.containsAll(set)); } private void checkToArray() { Object[] ints = new Integer[1]; ints = set.toArray(ints); List list = new ArrayList(); for (int ix = 0; ix < ints.length && ints[ix] != null; ix++) list.add(ints[ix]); assertTrue("wrong number of elements found", list.size() == set.size()); assertTrue("not all objects in set iterated to", set.containsAll(list) && list.containsAll(set)); } // --- Internal test object private class ObjectWithStupidHashCode { private String name; public ObjectWithStupidHashCode(String name) { this.name = name; } public int hashCode() { return 0; } public String toString() { return "<ObjectWithStupidHashCode " + name + ">"; } public boolean equals(Object other) { return ((ObjectWithStupidHashCode) other).name.equals(name); } } }