/******************************************************************************* * Copyright 2014 Analog Devices, Inc. * * 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 com.analog.lyric.collect.tests; import static com.analog.lyric.util.test.ExceptionTester.*; import static org.junit.Assert.*; import java.lang.reflect.Constructor; import java.util.ArrayDeque; import java.util.Collection; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.ConcurrentLinkedQueue; import org.junit.Test; import com.analog.lyric.collect.BinaryHeap; import com.analog.lyric.collect.ConstructorRegistry; import com.analog.lyric.collect.IHeap; /** * Test for {@link ConstructorRegistry} * * @since 0.07 * @author Christopher Barber */ public class TestConstructorRegistry { @Test public void test() { String lyricCollectPackage = IHeap.class.getPackage().getName(); ConstructorRegistry<IHeap<?>> heapRegistry = new ConstructorRegistry<>(IHeap.class); assertTrue(heapRegistry.isEmpty()); assertInvariants(heapRegistry); assertNull(heapRegistry.get(42)); // not a string key assertNull(heapRegistry.get("DoesNotExist")); assertNull(heapRegistry.getClassOrNull("DoesNotExist")); assertNull(heapRegistry.instantiateOrNull("DoesNotExist")); assertNull(heapRegistry.get("ArrayUtil")); expectThrow(RuntimeException.class, heapRegistry, "getClass", "DoesNotExist"); expectThrow(RuntimeException.class, heapRegistry, "instantiate", "DoesNotExist"); assertArrayEquals(new String[] { lyricCollectPackage }, heapRegistry.getPackages()); assertSame(BinaryHeap.class, heapRegistry.getClassOrNull("BinaryHeap")); assertInvariants(heapRegistry); assertEquals(2 * BinaryHeap.class.getConstructors().length, heapRegistry.size()); assertTrue(heapRegistry.containsKey("BinaryHeap")); heapRegistry.reset(); assertArrayEquals(new String[] { lyricCollectPackage }, heapRegistry.getPackages()); assertTrue(heapRegistry.isEmpty()); ConstructorRegistry<Collection<?>> collectionRegistry = new ConstructorRegistry<>(Collection.class, lyricCollectPackage); assertTrue(collectionRegistry.isEmpty()); assertInvariants(collectionRegistry); collectionRegistry.loadAll(); assertFalse(collectionRegistry.isEmpty()); assertTrue(collectionRegistry.containsKey("BinaryHeap")); assertTrue(collectionRegistry.containsKey("UniquePriorityQueue")); assertFalse(collectionRegistry.containsKey("Tuple")); // is abstract assertTrue(collectionRegistry.containsKey("Tuple2")); assertNull(collectionRegistry.get("Tuple2")); collectionRegistry.addPackage("java.util"); assertArrayEquals(new String[] { lyricCollectPackage, "java.util" }, collectionRegistry.getPackages()); assertSame(ArrayDeque.class, collectionRegistry.getClassOrNull("ArrayDeque")); assertInvariants(collectionRegistry); collectionRegistry.addClass(ConcurrentLinkedQueue.class); assertSame(ConcurrentLinkedQueue.class, collectionRegistry.getClass("ConcurrentLinkedQueue")); // package is not added in this case: assertArrayEquals(new String[] { lyricCollectPackage, "java.util" }, collectionRegistry.getPackages()); assertInvariants(collectionRegistry); expectThrow(IllegalArgumentException.class, ".*not a subclass.*", collectionRegistry, "addClass", Object.class); expectThrow(IllegalArgumentException.class, ".*does not have an accessible constructor.*", collectionRegistry, "addClass", CollectionWithoutConstructor.class); collectionRegistry.reset(); assertTrue(collectionRegistry.isEmpty()); assertArrayEquals(new String[] { lyricCollectPackage }, collectionRegistry.getPackages()); assertInvariants(collectionRegistry); try { assertNull(collectionRegistry.get("ConcurrentLinkedDeque")); assertEquals(ConcurrentLinkedDeque.class.getConstructor(), collectionRegistry.get("java.util.concurrent.ConcurrentLinkedDeque")); assertNull(collectionRegistry.get("ConcurrentLinkedDeque")); } catch (NoSuchMethodException ex) { fail(ex.toString()); } } private <T> void assertInvariants(ConstructorRegistry<T> registry) { Class<? super T> superClass = registry.getSuperClass(); int size = registry.size(); Set<Map.Entry<String,Constructor<T>>> entries = registry.entrySet(); Set<String> keys = registry.keySet(); Collection<Constructor<T>> constructors = registry.values(); assertEquals(size, entries.size()); assertTrue(size >= keys.size()); assertEquals(size, constructors.size()); for (Map.Entry<String, Constructor<T>> entry : entries) { String name = entry.getKey(); Constructor<T> constructor = entry.getValue(); assertTrue(keys.contains(name)); assertTrue(registry.containsKey(name)); assertTrue(registry.containsValue(constructor)); assertSame(constructor, registry.get(name, constructor.getParameterTypes())); Class<? super T> c = constructor.getDeclaringClass(); assertTrue(superClass.isAssignableFrom(c)); assertSame(c, registry.getClass(name)); if (name.contains(".")) { assertEquals(name, c.getCanonicalName()); } else { assertEquals(name, c.getSimpleName()); } if (constructor.getParameterTypes().length == 0) { T instance = registry.instantiate(name); assertSame(c, instance.getClass()); } } } public abstract static class CollectionWithoutConstructor<T> implements Collection<T> { public CollectionWithoutConstructor(int bogusArg) { } } }