package org.limewire.util; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.limewire.util.GenericsUtils.ScanMode; public class GenericsUtilsTest extends TestCase { // TODO: test maps private static enum Kind { COLLECTION, LIST, SET } private static enum Type { NORMAL, HAS_EXTRA, EMPTY } public GenericsUtilsTest(String name) { super(name); } public static Test suite() { TestSuite suite = new TestSuite(); for(Kind kind : Kind.values()) { for(ScanMode mode : ScanMode.values()) { for(Type type : Type.values()) { suite.addTest(newTest(kind, mode, type)); } } } return suite; } public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } private static Test newTest(final Kind kind, final ScanMode scanMode, final Type type) { return new TestCase("Test for: " + kind + ", mode: " + scanMode + ", of type: " + type) { @Override protected void runTest() throws Throwable { try { switch(kind) { case COLLECTION: if(scanMode != ScanMode.NEW_COPY_REMOVED) { scanResult(GenericsUtils.scanForCollection(listFor(type), Number.class, scanMode), type); } else { scanResult(GenericsUtils.scanForCollection(listFor(type), Number.class, scanMode, TypeSafeNumberList.class), type); } break; case LIST: if(scanMode != ScanMode.NEW_COPY_REMOVED) { scanResult(GenericsUtils.scanForList(listFor(type), Number.class, scanMode), type); } else { scanResult(GenericsUtils.scanForList(listFor(type), Number.class, scanMode, TypeSafeNumberList.class), type); } break; case SET: if(scanMode != ScanMode.NEW_COPY_REMOVED) { scanResult(GenericsUtils.scanForSet(setFor(type), Number.class, scanMode), type); } else { scanResult(GenericsUtils.scanForSet(setFor(type), Number.class, scanMode, TypeSafeNumberSet.class), type); } break; } } catch(ClassCastException cce) { if(scanMode != ScanMode.EXCEPTION) { throw cce; } assertEquals("wanted an instanceof: class java.lang.Number, but was: [NotANumber] of type: java.lang.String", cce.getMessage()); } } }; } private static void scanResult(Collection result, Type type) { switch(type) { case EMPTY: assertEquals(0, result.size()); break; case HAS_EXTRA: assertEquals(3, result.size()); if(result instanceof Set) { assertTrue(result.contains(1)); assertTrue(result.contains(2)); assertTrue(result.contains(4)); } else { Iterator i = result.iterator(); assertEquals(1, i.next()); assertEquals(2, i.next()); assertEquals(4, i.next()); assertFalse(i.hasNext()); } break; case NORMAL: assertEquals(4, result.size()); if(result instanceof Set) { assertTrue(result.contains(1)); assertTrue(result.contains(2)); assertTrue(result.contains(3)); assertTrue(result.contains(4)); } else { Iterator i = result.iterator(); assertEquals(1, i.next()); assertEquals(2, i.next()); assertEquals(3, i.next()); assertEquals(4, i.next()); assertFalse(i.hasNext()); } break; } } @SuppressWarnings("unchecked") private static List listFor(Type type) { ArrayList l = new ArrayList(); switch(type) { case EMPTY: break; case HAS_EXTRA: l.add(1); l.add(2); l.add("NotANumber"); l.add(4); break; case NORMAL: l.add(1); l.add(2); l.add(3); l.add(4); break; } return l; } @SuppressWarnings("unchecked") private static Set setFor(Type type) { HashSet l = new HashSet(); switch(type) { case EMPTY: break; case HAS_EXTRA: l.add(1); l.add(2); l.add("NotANumber"); l.add(4); break; case NORMAL: l.add(1); l.add(2); l.add(3); l.add(4); break; } return l; } public static class TypeSafeNumberList extends ArrayList<Number> { @Override public boolean add(Number e) { if (!Number.class.isInstance(e)) { throw new IllegalStateException(); } return super.add(e); } @Override public void add(int index, Number element) { if (!Number.class.isInstance(element)) { throw new IllegalStateException(); } super.add(index, element); } @Override public boolean addAll(Collection<? extends Number> c) { boolean added = false; for(Number n : c) { added |= add(n); } return added; } } public static class TypeSafeNumberSet extends HashSet<Number> { @Override public boolean add(Number e) { if (!Number.class.isInstance(e)) { throw new IllegalStateException(); } return super.add(e); } @Override public boolean addAll(Collection<? extends Number> c) { boolean added = false; for(Number n : c) { added |= add(n); } return added; } } }