/* Glazed Lists (c) 2003-2006 */ /* http://publicobject.com/glazedlists/ publicobject.com,*/ /* O'Dell Engineering Ltd.*/ package ca.odell.glazedlists; import ca.odell.glazedlists.event.ListEvent; import ca.odell.glazedlists.event.ListEventListener; import ca.odell.glazedlists.impl.testing.GlazedListsTests; import ca.odell.glazedlists.impl.testing.ListConsistencyListener; import ca.odell.glazedlists.matchers.Matchers; import junit.framework.TestCase; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; /** * Verifies that EventList matches the List API. * * @author <a href="mailto:jesse@swank.ca">Jesse Wilson</a> */ public class EventListTest extends TestCase { /** * Validates that removeAll() works. * * @see <a href="https://glazedlists.dev.java.net/issues/show_bug.cgi?id=169">Bug 169</a> */ public void testRemoveAll() { List<String> jesse = GlazedListsTests.stringToList("JESSE"); List<String> wilson = GlazedListsTests.stringToList("WILSON"); // create the reference list List<String> jesseArrayList = new ArrayList<String>(); jesseArrayList.addAll(jesse); jesseArrayList.removeAll(wilson); // test the BasicEventList list List<String> jesseBasicEventList = new BasicEventList<String>(); installConsistencyListener(jesseBasicEventList); jesseBasicEventList.addAll(jesse); jesseBasicEventList.removeAll(wilson); assertEquals(jesseArrayList, jesseBasicEventList); // test the SortedList list List<String> jesseSortedList = new SortedList<String>(new BasicEventList<String>(), null); jesseSortedList.addAll(jesse); jesseSortedList.removeAll(wilson); assertEquals(jesseArrayList, jesseSortedList); List<String> removeMultipleTestList = GlazedListsTests.stringToList("booblah"); removeMultipleTestList.removeAll(GlazedListsTests.stringToList("bo")); assertEquals(GlazedListsTests.stringToList("lah"), removeMultipleTestList); } /** * Validates that retainAll() works. */ public void testRetainAll() { List<String> jesse = GlazedListsTests.stringToList("JESSE"); List<String> wilson = GlazedListsTests.stringToList("WILSON"); // create the reference list List<String> jesseArrayList = new ArrayList<String>(); jesseArrayList.addAll(jesse); jesseArrayList.retainAll(wilson); // test the BasicEventList list List<String> jesseBasicEventList = new BasicEventList<String>(); installConsistencyListener(jesseBasicEventList); jesseBasicEventList.addAll(jesse); jesseBasicEventList.retainAll(wilson); assertEquals(jesseArrayList, jesseBasicEventList); // test the SortedList list List<String> jesseSortedList = new SortedList<String>(new BasicEventList<String>(), null); jesseSortedList.addAll(jesse); jesseSortedList.retainAll(wilson); assertEquals(jesseArrayList, jesseSortedList); } /** * Validates that contains() works with null. */ public void testContainsNull() { // get all different list types List<List<String>> listTypes = new ArrayList<List<String>>(); listTypes.add(new ArrayList<String>()); listTypes.add(new BasicEventList<String>()); listTypes.add(SortedList.create(new BasicEventList<String>())); // test all different list types for(Iterator<List<String>> i = listTypes.iterator(); i.hasNext();) { List<String> list = i.next(); // test a list that doesn't contain nulls list.clear(); list.addAll(Arrays.asList(new String[] { "Molson", "Sleeman", "Labatts", "Western" })); assertEquals(false, list.contains(null)); assertEquals(true, list.contains("Western")); // test a list that does contain nulls list.clear(); list.addAll(Arrays.asList(new String[] { null, "Sleeman", null, "Western" })); assertEquals(true, list.contains(null)); assertEquals(true, list.contains("Western")); assertEquals(false, list.contains("Molson")); } } /** * Validates that containsAll() works with null. */ public void testContainsAllNull() { // get all different list types List<List<String>> listTypes = new ArrayList<List<String>>(); listTypes.add(new ArrayList<String>()); listTypes.add(new BasicEventList<String>()); listTypes.add(SortedList.create(new BasicEventList<String>())); // test all different list types for(Iterator<List<String>> i = listTypes.iterator(); i.hasNext();) { List<String> list = i.next(); // test a list that doesn't contain nulls list.clear(); list.addAll(Arrays.asList(new String[] { "Molson", "Sleeman", "Labatts", "Western" })); assertEquals(true, list.containsAll(Arrays.asList(new String[] { "Sleeman", "Molson" }))); assertEquals(false, list.containsAll(Arrays.asList(new String[] { "Molson", null }))); assertEquals(false, list.containsAll(Arrays.asList(new String[] { "Molson", "Busch" }))); // test a list that does contain nulls list.clear(); list.addAll(Arrays.asList(new String[] { null, "Sleeman", null, "Western" })); assertEquals(false, list.containsAll(Arrays.asList(new String[] { "Sleeman", "Molson" }))); assertEquals(true, list.containsAll(Arrays.asList(new String[] { "Sleeman", "Western" }))); assertEquals(true, list.containsAll(Arrays.asList(new String[] { "Western", null }))); assertEquals(true, list.containsAll(Arrays.asList(new String[] { null, null }))); } } /** * Validates that indexOf() works with null. */ public void testIndexOfNull() { // get all different list types List<List<String>> listTypes = new ArrayList<List<String>>(); listTypes.add(new ArrayList<String>()); listTypes.add(new BasicEventList<String>()); listTypes.add(SortedList.create(new BasicEventList<String>())); // test all different list types for(Iterator<List<String>> i = listTypes.iterator(); i.hasNext();) { List<String> list = i.next(); // test a list that doesn't contain nulls list.clear(); list.addAll(Arrays.asList(new String[] { "Molson", "Sleeman", "Labatts", "Western" })); assertTrue(-1 == list.indexOf(null)); assertTrue(-1 != list.indexOf("Western")); // test a list that does contain nulls list.clear(); list.addAll(Arrays.asList(new String[] { null, "Sleeman", null, "Western" })); assertTrue(-1 != list.indexOf(null)); assertTrue(-1 != list.indexOf("Western")); assertTrue(-1 == list.indexOf("Molson")); } } /** * Validates that lastIndexOf() works with null. */ public void testLastIndexOfNull() { // get all different list types List<List<String>> listTypes = new ArrayList<List<String>>(); listTypes.add(new ArrayList<String>()); listTypes.add(new BasicEventList<String>()); listTypes.add(SortedList.create(new BasicEventList<String>())); // test all different list types for(Iterator<List<String>> i = listTypes.iterator(); i.hasNext();) { List<String> list = i.next(); // test a list that doesn't contain nulls list.clear(); list.addAll(Arrays.asList(new String[] { "Molson", "Sleeman", "Labatts", "Western" })); assertTrue(-1 == list.lastIndexOf(null)); assertTrue(-1 != list.lastIndexOf("Western")); // test a list that does contain nulls list.clear(); list.addAll(Arrays.asList(new String[] { null, "Sleeman", null, "Western" })); assertTrue(-1 != list.lastIndexOf(null)); assertTrue(-1 != list.lastIndexOf("Western")); assertTrue(-1 == list.lastIndexOf("Molson")); } } /** * Validates that remove() works with null. */ public void testRemoveNull() { // get all different list types List<List<String>> listTypes = new ArrayList<List<String>>(); listTypes.add(new ArrayList<String>()); listTypes.add(new BasicEventList<String>()); listTypes.add(SortedList.create(new BasicEventList<String>())); // test all different list types for(Iterator<List<String>> i = listTypes.iterator(); i.hasNext();) { List<String> list = i.next(); installConsistencyListener(list); // test a list that doesn't contain nulls list.clear(); list.addAll(Arrays.asList(new String[] { "Molson", "Sleeman", "Labatts", "Western" })); assertEquals(false, list.remove(null)); assertEquals(true, list.remove("Sleeman")); // test a list that does contain nulls list.clear(); list.addAll(Arrays.asList(new String[] { null, "Sleeman", null, "Western" })); assertEquals(true, list.remove(null)); assertEquals(true, list.remove("Western")); assertEquals(false, list.remove("Molson")); } } /** * Validates that removeAll() works with null. */ public void testRemoveAllNull() { // get all different list types List<List<String>> listTypes = new ArrayList<List<String>>(); listTypes.add(new ArrayList<String>()); listTypes.add(new BasicEventList<String>()); listTypes.add(SortedList.create(new BasicEventList<String>())); // test all different list types for(Iterator<List<String>> i = listTypes.iterator(); i.hasNext();) { List<String> list = i.next(); // test a list that doesn't contain nulls list.clear(); list.addAll(Arrays.asList(new String[] { "Molson", "Sleeman", "Labatts", "Western" })); assertEquals(true, list.removeAll(Arrays.asList(new String[] { "Western", null }))); assertEquals(false, list.removeAll(Arrays.asList(new String[] { null, "Busch" }))); // test a list that does contain nulls list.clear(); list.addAll(Arrays.asList(new String[] { null, "Sleeman", null, "Western" })); assertEquals(true, list.removeAll(Arrays.asList(new String[] { "Western", "Busch" }))); assertEquals(true, list.removeAll(Arrays.asList(new String[] { "Sleeman", null }))); assertEquals(false, list.removeAll(Arrays.asList(new String[] { "Western", null }))); } } /** * Validates that retainAll() works with null. */ public void testRetainAllNull() { // get all different list types List<List<String>> listTypes = new ArrayList<List<String>>(); listTypes.add(new ArrayList<String>()); listTypes.add(new BasicEventList<String>()); listTypes.add(SortedList.create(new BasicEventList<String>())); // test all different list types for(Iterator<List<String>> i = listTypes.iterator(); i.hasNext();) { List<String> list = i.next(); // test a list that doesn't contain nulls list.clear(); list.addAll(Arrays.asList(new String[] { "Molson", "Sleeman", "Labatts", "Western" })); assertEquals(true, list.retainAll(Arrays.asList(new String[] { "Western", null }))); assertEquals(true, list.retainAll(Arrays.asList(new String[] { "Moslon", null }))); // test a list that does contain nulls list.clear(); list.addAll(Arrays.asList(new String[] { null, "Sleeman", null, "Western" })); assertEquals(true, list.retainAll(Arrays.asList(new String[] { "Western", null }))); assertEquals(true, list.retainAll(Arrays.asList(new String[] { "Moslon", null }))); } } /** * Validates that hashCode() works with null. */ public void testHashCodeNull() { // get all different list types List<List<String>> listTypes = new ArrayList<List<String>>(); listTypes.add(new ArrayList<String>()); listTypes.add(new BasicEventList<String>()); listTypes.add(SortedList.create(new BasicEventList<String>())); // test all different list types for(Iterator<List<String>> i = listTypes.iterator(); i.hasNext();) { List<String> list = i.next(); List<String> copy = new ArrayList<String>(); // test a list that doesn't contain nulls list.clear(); copy.clear(); list.addAll(Arrays.asList(new String[] { "Molson", "Sleeman", "Labatts", "Western" })); copy.addAll(list); assertEquals(copy.hashCode(), list.hashCode()); assertTrue(list.equals(copy)); copy.set(0, "Busch"); assertFalse(list.equals(copy)); // test a list that does contain nulls list.clear(); copy.clear(); list.addAll(Arrays.asList(new String[] { null, "Sleeman", null, "Western" })); copy.addAll(list); assertEquals(copy.hashCode(), list.hashCode()); assertTrue(list.equals(copy)); copy.set(0, "Busch"); assertFalse(list.equals(copy)); } } /** * Test that the {@link GlazedLists#eventListOf(Object[])} factory * method works. */ public void testGlazedListsEventListUsingVarArgs() { // make sure they have different backing stores EventList<String> eventList = GlazedLists.eventListOf(new String[] {"A", "B"}); assertEquals(Arrays.asList(new String[] {"A", "B"}), eventList); // make sure null is supported EventList<String> empty = GlazedLists.eventListOf((String[]) null); assertEquals(Collections.EMPTY_LIST, empty); } /** * Test that the {@link GlazedLists#eventList(java.util.Collection)} factory * method works. * * @see <a href="https://glazedlists.dev.java.net/issues/show_bug.cgi?id=234">Bug 234</a> */ public void testGlazedListsEventList() { // make sure they have different backing stores List<String> list = new ArrayList<String>(); EventList<String> eventList = GlazedLists.eventList(list); assertEquals(list, eventList); list.add("A"); assertTrue(!list.equals(eventList)); eventList.add("B"); assertTrue(!list.equals(eventList)); // make sure null is supported EventList<String> empty = GlazedLists.eventList((Collection) null); assertEquals(Collections.EMPTY_LIST, empty); } /** * Tests the {@link GlazedLists#syncEventListToList(EventList, List)} * factory method. */ public void testGlazedListsSync() { EventList<String> source = new BasicEventList<String>(); source.add("McCallum"); source.add("Keith"); List<String> target = new ArrayList<String>(); target.add("Greene"); ListEventListener<String> listener = GlazedLists.syncEventListToList(source, target); assertEquals(source, target); source.add("Szakra"); assertEquals(source, target); source.addAll(Arrays.asList(new String[] { "Moore", "Holmes" })); assertEquals(source, target); source.add(1, "Burris"); assertEquals(source, target); source.set(1, "Crandell"); assertEquals(source, target); Collections.sort(source); assertEquals(source, target); source.clear(); assertEquals(source, target); source.removeListEventListener(listener); source.add("Davis"); assertFalse(source.equals(target)); } public void testEventListTypeSafety() { EventList<Object> source = new BasicEventList<Object>(); final Set<Class> acceptedTypes = new HashSet<Class>(); acceptedTypes.add(null); acceptedTypes.add(Integer.class); acceptedTypes.add(String.class); ListEventListener typeSafetyListener = GlazedLists.typeSafetyListener(source, acceptedTypes); source.add(null); source.add(new Integer(0)); source.add("Testing"); try { source.add(new Long(23)); fail("Expected an IllegalArgumentException for disallowed type"); } catch (IllegalArgumentException e) { // expected } // the source list is in an inconsistent state so we rebuild the list source = new BasicEventList<Object>(); typeSafetyListener = GlazedLists.typeSafetyListener(source, acceptedTypes); source.add(null); try { source.set(0, new Long(23)); fail("Expected an IllegalArgumentException for disallowed type"); } catch (IllegalArgumentException e) { // expected } // recover from the exception source.clear(); source.removeListEventListener(typeSafetyListener); // these should now succeed now that we're not using the type safety checker any longer source.add(new Long(23)); source.set(0, new Long(23)); } public void testEventListLock() { final EventList<String> source = new BasicEventList<String>(); // asymmetric unlocking of the readlock should fail-fast try { source.getReadWriteLock().readLock().unlock(); fail("failed to receive an IllegalStateException when unlocking and unlocked readlock"); } catch (IllegalMonitorStateException iae) {} // asymmetric unlocking of the writelock should fail-fast try { source.getReadWriteLock().writeLock().unlock(); fail("failed to receive an IllegalStateException when unlocking and unlocked writelock"); } catch (IllegalMonitorStateException iae) {} // symmetric locking/unlocking of the readlock should succeed source.getReadWriteLock().readLock().lock(); source.getReadWriteLock().readLock().unlock(); // symmetric locking/unlocking of the writelock should succeed source.getReadWriteLock().writeLock().lock(); source.getReadWriteLock().writeLock().unlock(); } public void testRemoveAllOnView() { EventList<String> original = new BasicEventList<String>(); original.addAll(GlazedListsTests.stringToList("ABCDE")); FilterList<String> filtered = new FilterList<String>(original, Matchers.trueMatcher()); filtered.removeAll(filtered); assertEquals(Collections.EMPTY_LIST, original); } public void testRetainAllOnSelf() { EventList<String> original = new BasicEventList<String>(); original.addAll(GlazedListsTests.stringToList("ABCDE")); original.retainAll(original); assertEquals(GlazedListsTests.stringToList("ABCDE"), original); } public void testSublistClear() { EventList<String> original = new BasicEventList<String>(); original.addAll(GlazedListsTests.stringToList("ABCDE")); Iterator<String> iterator = original.subList(2, 4).iterator(); iterator.next(); iterator.remove(); iterator.next(); iterator.remove(); assertEquals(GlazedListsTests.stringToList("ABE"), original); } public void testAddAllFromView() { EventList<Integer> original = new BasicEventList<Integer>(); original.addAll(Arrays.asList(new Integer[] { new Integer(0), new Integer(10), new Integer(20), new Integer(30), new Integer(40) })); FilterList<Integer> filtered = new FilterList<Integer>(original, GlazedListsTests.matchAtLeast(20)); original.addAll(filtered); assertEquals(Arrays.asList(new Integer[] { new Integer(0), new Integer(10), new Integer(20), new Integer(30), new Integer(40), new Integer(20), new Integer(30), new Integer(40) }), original); } public void testSimpleAddAll() { EventList<String> source = new BasicEventList<String>(); installConsistencyListener(source); FilterList<String> filterList = new FilterList<String>(source, Matchers.trueMatcher()); filterList.addAll(GlazedListsTests.stringToList("JESSE")); assertEquals(GlazedListsTests.stringToList("JESSE"), source); assertEquals(GlazedListsTests.stringToList("JESSE"), filterList); } public void testReplace() { EventList<String> source = new BasicEventList<String>(); installConsistencyListener(source); source.addAll(GlazedListsTests.stringToList("ROUGHRIDERS")); source.set(2, "G"); source.set(0, "T"); source.set(4, "R"); source.set(1, "I"); source.set(3, "E"); assertEquals(GlazedListsTests.stringToList("TIGERRIDERS"), source); } /** * This test case was generated from a problem that we received in the field. * It occured when a crazy amount of list events were being combined into one, * and we failed to create a simpler test case that still demonstrated the * problematic behaviour. This is probably due to the way that we sort list * events while processing them. */ public void testCombineEvents() { TransactionList<Object> list = new TransactionList<Object>(new BasicEventList<Object>(), true); for (int i = 0; i < 16; i++) list.add(new Integer(0)); ListConsistencyListener.install(list); list.beginEvent(); for(int i = 0; i < 4; i++) list.add(8, new Object()); for(int j = 7; j >= 0; j--) { for(int i = 0; i < 10; i++) list.add(j, new Object()); } list.remove(55); list.remove(95); list.remove(14); list.remove(22); list.remove(27); list.remove(78); list.remove(1); list.remove(85); list.remove(52); list.remove(14); list.remove(39); list.remove(38); list.remove(61); list.remove(69); list.remove(8); list.remove(57); list.remove(10); list.remove(5); list.remove(71); list.remove(60); list.remove(42); list.remove(21); list.remove(15); list.remove(59); list.remove(15); list.remove(14); list.remove(24); list.remove(43); list.remove(35); list.remove(12); list.remove(11); list.remove(34); list.remove(42); list.remove(32); list.remove(19); list.add(32, new Integer(92)); list.remove(44); list.remove(19); list.remove(45); list.remove(55); list.remove(23); list.remove(11); list.remove(8); list.remove(50); list.remove(29); list.remove(31); list.remove(33); list.remove(45); list.remove(15); list.remove(25); list.remove(8); list.add(40, new Integer(95)); list.remove(32); list.remove(3); list.remove(26); list.remove(14); list.remove(36); list.add(39, new Integer(96)); list.remove(34); list.remove(21); list.remove(13); list.remove(32); list.remove(30); list.add(36, new Integer(97)); list.remove(43); list.remove(2); list.remove(34); list.remove(35); list.remove(17); list.add(39, new Integer(98)); for(int i = 0; i < 5; i++) { list.remove(list.size() - 1); } list.add(29, new Integer(99)); for(int i = 0; i < 5; i++) { list.remove(list.size() - 1); } list.add(22, new Integer(100)); for(int i = 0; i < 5; i++) { list.remove(list.size() - 1); } list.set(25, new Integer(101)); // critical for(int j = 0; j < 4; j++) { for(int i = 0; i < 5; i++) list.remove(0); list.add(0, new Integer(102)); } for(int i = 0; i < 10; i++) list.remove(0); list.add(0, new Integer(107)); for(int i = 0; i < 2; i++) list.remove(0); list.commitEvent(); } public void testGenericsOfListEvent() { final EventList<? extends String> source = GlazedLists.eventListOf((String[]) null); source.addListEventListener(new ListEventListener<Object>() { public void listChanged(ListEvent<Object> listChanges) { listChanges.next(); Object o = listChanges.getSourceList().get(listChanges.getIndex()); assertEquals(String.class, o.getClass()); } }); source.addListEventListener(new ListEventListener<String>() { public void listChanged(ListEvent<String> listChanges) { listChanges.next(); String s = listChanges.getSourceList().get(listChanges.getIndex()); assertEquals(String.class, s.getClass()); } }); ((EventList)source).add("Test"); } /** * Install a consistency listener to the specified list. */ private static void installConsistencyListener(List list) { if(list instanceof BasicEventList) { ListConsistencyListener<String> listConsistencyListener = ListConsistencyListener.install((BasicEventList)list); listConsistencyListener.setPreviousElementTracked(true); } } }