/******************************************************************************* * 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.options.tests; import static com.analog.lyric.util.test.ExceptionTester.*; import static org.junit.Assert.*; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import java.util.regex.Pattern; import org.junit.Test; import com.analog.lyric.options.AmbiguousOptionNameException; import com.analog.lyric.options.GenericOptionKey; import com.analog.lyric.options.IOptionKey; import com.analog.lyric.options.IntegerOptionKey; import com.analog.lyric.options.OptionKey; import com.analog.lyric.options.OptionKeys; import com.analog.lyric.options.OptionRegistry; import com.analog.lyric.options.StringOptionKey; import com.google.common.collect.Iterables; /** * Test for {@link OptionRegistry} class * * @since 0.06 * @author CBarber */ public class TestOptionRegistry { @Test public void testRegistry() { OptionRegistry registry = new OptionRegistry(); assertTrue(registry.autoLoadKeys()); assertEquals(0, registry.size()); assertInvariants(registry); assertEquals(4, registry.addFromClasses(getClass())); assertEquals(0, registry.addFromClasses(getClass())); assertInvariants(registry); assertEquals(4, registry.size()); assertEquals(2, registry.getAllMatching(".*\\.S\\d").size()); assertEquals(1, registry.getAllMatching(Pattern.compile(".*\\.S2")).size()); assertNull(registry.get("SomeOptions.A")); StringOptionKey FooA = com.analog.lyric.options.tests.foo.SomeOptions.A; StringOptionKey FooB = com.analog.lyric.options.tests.foo.SomeOptions.B; StringOptionKey FooD = com.analog.lyric.options.tests.foo.SomeOptions.D; StringOptionKey BarA = com.analog.lyric.options.tests.bar.SomeOptions.A; // StringOptionKey BarB = com.analog.lyric.options.tests.bar.SomeOptions.B; StringOptionKey BarC = com.analog.lyric.options.tests.bar.SomeOptions.C; // Test autoloading assertEquals(FooA, registry.get(FooA.canonicalName())); assertEquals(FooA, registry.get("SomeOptions.A")); // Other options in same class also get loaded assertEquals(FooB, registry.get("SomeOptions.B")); assertEquals(FooD, registry.get("SomeOptions.D")); assertInvariants(registry); assertEquals(BarC, registry.get(BarC.canonicalName())); assertEquals(BarC, registry.get("SomeOptions.C")); assertEquals(FooD, registry.get("SomeOptions.D")); assertNull(registry.get("SomeOptions.doesNotExist")); try { registry.get("SomeOptions.A"); fail("should not get here"); } catch (AmbiguousOptionNameException ex) { // In order in which they were added... assertArrayEquals(new Object[] { FooA, BarA }, ex.ambiguousKeys().toArray()); } assertInvariants(registry); expectThrow(NoSuchElementException.class, "Unknown option key 'DoesNot.exist'", registry, "asKey", "DoesNot.exist"); expectThrow(IllegalArgumentException.class, "Expected String or IOptionKey instead of 'Integer'", registry, "asKey", 42); assertNull(registry.get("this.class.does.not.exist")); assertEquals(false, registry.add(OptionKeys.declaredInClass(BarA.getDeclaringClass()))); registry = new OptionRegistry(false); assertInvariants(registry); assertEquals(0, registry.size()); assertNull(registry.get(FooA.canonicalName())); } @Test public void testOptionKeys() { testOptionKeys(Object.class); testOptionKeys(getClass()); testOptionKeys(FieldOptions.class, FieldOptions.I23, FieldOptions.I42, FieldOptions.S1, FieldOptions.S2); } private void testOptionKeys(Class<?> declaringClass, IOptionKey<?> ... expected) { OptionKeys keys = OptionKeys.declaredInClass(declaringClass); assertSame(keys, OptionKeys.declaredInClass(declaringClass)); assertSame(keys, keys.clone()); assertSame(declaringClass, keys.declaringClass()); assertEquals(expected.length, keys.values().size()); Set<String> keySet = keys.keySet(); Set<Map.Entry<String,IOptionKey<?>>> entrySet = keys.entrySet(); assertEquals(keySet.size(), entrySet.size()); for (Map.Entry<String, IOptionKey<?>> entry : entrySet) { String name = entry.getKey(); IOptionKey<?> key = keys.get(name); assertNotNull(key); assertTrue(keySet.contains(name)); assertTrue(keys.containsValue(key)); assertTrue(keys.containsKey(name)); @SuppressWarnings("unchecked") IOptionKey<?> key2 = new GenericOptionKey<Serializable>(key.getDeclaringClass(), key.name(), (Class<Serializable>) key.type(), key.defaultValue()); assertFalse(keys.containsValue(key2)); } assertFalse(keys.containsKey("does not exist")); assertFalse(keys.containsValue("does not exist")); assertNull(keys.get("does not exist")); Map<String,IOptionKey<?>> map = new HashMap<String,IOptionKey<?>>(); map.putAll(keys); assertEquals(map, keys); assertEquals(map.hashCode(), keys.hashCode()); } private void assertInvariants(OptionRegistry registry) { ArrayList<IOptionKey<?>> all1 = new ArrayList<>(); Iterables.addAll(all1, registry); assertEquals(all1.size(), registry.size()); for (IOptionKey<?> key : registry) { assertSame(key, registry.get(OptionKey.canonicalName(key))); assertSame(key, registry.asKey(key)); assertSame(key, registry.asKey(OptionKey.canonicalName(key))); try { assertEquals(key, registry.get(OptionKey.qualifiedName(key))); } catch (AmbiguousOptionNameException ex) { assertEquals(OptionKey.qualifiedName(key), ex.optionName()); assertNotEquals(1, ex.ambiguousKeys().size()); assertTrue(ex.ambiguousKeys().indexOf(key) >= 0); } } assertNull(registry.get("this-key-does-not-exist")); ArrayList<IOptionKey<?>> all2 = registry.getAllMatching(".*"); assertEquals(all1, all2); ArrayList<IOptionKey<?>> all3 = new ArrayList<>(); Collection<OptionKeys> allKeys = registry.getOptionKeys(); for (OptionKeys keys : allKeys) { for (IOptionKey<?> key : keys.values()) { all3.add(key); } } assertEquals(all1, all3); assertTrue(registry.getAllMatching("does-not-exist").isEmpty()); } static class PackageProtectedFieldOptions { public static final IOptionKey<String> S42 = new StringOptionKey(FieldOptions.class, "S42", "42"); } public static class FieldOptions { public static final OptionKey<String> S1 = new StringOptionKey(FieldOptions.class, "S1", "s"); public static final OptionKey<String> S2 = new StringOptionKey(FieldOptions.class, "S2", "s"); public static final OptionKey<Integer> I42 = new IntegerOptionKey(FieldOptions.class, "I42", 42); public static final OptionKey<Integer> I23 = new IntegerOptionKey(FieldOptions.class, "I23", 23); // An alias public static final OptionKey<String> S1A = S1; // // These should not be registered: // public static IOptionKey<String> NOT_FINAL = new StringOptionKey(FieldOptions.class, "NOT_FINAL", "x"); protected static final IOptionKey<String> NOT_PUBLIC = new StringOptionKey(FieldOptions.class, "NOT_PUBLIC", "x"); public final static String NOT_AN_OPTION = "NOT_AN_OPTION"; } }