/******************************************************************************* * 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 java.util.Objects.*; import static org.junit.Assert.*; import java.lang.reflect.Method; import java.util.Arrays; import java.util.List; import org.junit.Test; import com.analog.lyric.collect.Supers; import com.google.common.collect.ImmutableList; public class TestSupers { static enum E1 { A,B,C; } static enum E2 { A,B,C; } static interface I {} static interface J {} static interface K extends I {} static interface L extends I {} static interface M extends K, L {} static class A {} static class B extends A {} static class C extends A {} static class D extends B {} static final class E extends D {} static class F extends C implements L {} @Test public void testNarrowArrayOf() { narrowArrayOfTestCase(A.class, new Object[] {new B(), new C()}); narrowArrayOfTestCase(E.class, new Object[] {new E(), new E()}); A[] a = (A[]) Supers.narrowArrayOf(A.class, 0, new Object[0]); assertEquals(A.class, a.getClass().getComponentType()); A[] a2 = Supers.narrowArrayOf(A.class, 0, a); assertSame(a, a2); A[] a3 = new A[] { new A(), new B(), new C() }; assertSame(a3, Supers.narrowArrayOf(A.class, a3)); assertNull(Supers.narrowArrayOf(B.class, a3)); Object[] o3 = new Object[] { a3[0], a3[1], a3[2] }; A[] a4 = Supers.narrowArrayOf(A.class, o3); assertArrayEquals(a3, a4); assertEquals(A.class, requireNonNull(a4).getClass().getComponentType()); } private <T> void narrowArrayOfTestCase(Class<?> expectedComponentType, T[] elements) { T[] copy = Supers.narrowArrayOf(elements); assertArrayEquals(elements, copy); assertEquals(expectedComponentType, copy.getClass().getComponentType()); ImmutableList<Class<?>> supers = Supers.superClasses(expectedComponentType); for (int depth = 0; depth < supers.size(); ++ depth) { copy = Supers.narrowArrayOf(Object.class, depth, elements); assertArrayEquals(elements, copy); assertEquals(supers.get(depth), copy.getClass().getComponentType()); copy = Supers.narrowArrayOf(supers.get(depth), 0, elements); assertArrayEquals(elements, copy); assertEquals(supers.get(depth), copy.getClass().getComponentType()); } copy = Supers.narrowArrayOf(Object.class, supers.size(), elements); assertArrayEquals(elements, copy); assertEquals(expectedComponentType, copy.getClass().getComponentType()); } @Test public void testInvokeMethod() { try { assertEquals(3, Supers.invokeMethod("foo", "length")); assertEquals(3, Supers.invokeMethod("foobar", String.class, "indexOf", "bar")); assertEquals("foobar", Supers.invokeMethod(String.class, "format", "foo%s", "bar")); assertEquals("foobar", Supers.invokeMethod(String.class, "format", "foo%s", new Object[] {"bar"})); assertEquals("foobar", Supers.invokeMethod(String.class, "format", "foobar")); assertEquals("foobar", Supers.invokeMethod(String.class, "format", "foobar", new Object[] {})); // FIXME - Supers.invokeMethod support for auto boxing of primitives // Supers.invokeMethod(Arrays.class, "asList", 1,2,3); List<?> list = (List<?>)Supers.invokeMethod(Arrays.class, "asList", "1", "2", "3"); requireNonNull(list); assertArrayEquals(new Object[] {"1", "2", "3",}, list.toArray()); // Test invocation of method implemented in a non-public subclass assertEquals(42, Supers.invokeMethod(TestSupers2.makePrivateClass1(), "bar")); assertEquals(23, Supers.invokeMethod(TestSupers2.makePrivateClass1(), "bar", 23)); assertEquals(23, Supers.invokeMethod(TestSupers2.makePrivateClass2(), "foo")); assertEquals(-12, Supers.invokeMethod(TestSupers2.makePrivateClass2(), "foo", 12)); } catch (Exception ex) { fail(ex.toString()); } } /** * Tests {@link Supers#isSubclassOf} and {@link Supers#isStrictSubclassOf}. */ @Test public void testIsSubclassOf() { assertTrue(Supers.isSubclassOf(A.class, A.class)); assertFalse(Supers.isStrictSubclassOf(A.class, A.class)); assertTrue(Supers.isSubclassOf(D.class, A.class)); assertTrue(Supers.isStrictSubclassOf(D.class, A.class)); assertFalse(Supers.isSubclassOf(A.class, D.class)); assertFalse(Supers.isStrictSubclassOf(A.class, D.class)); } @Test public void testLookupMethod() { try { Method m; try { m = Supers.lookupMethod("foo", "bar"); fail("expected NoSuchMethodException"); } catch (NoSuchMethodException ex) { } try { m = Supers.lookupMethod("foo", "indexOf", 2.35); fail("expected NoSuchMethodException"); } catch (NoSuchMethodException ex) { } m = Supers.lookupMethod("foo", "length"); assertEquals("length", m.getName()); m = Supers.lookupMethod("foo", "indexOf", 0); assertEquals("indexOf", m.getName()); assertArrayEquals(new Object[] { Integer.TYPE }, m.getParameterTypes()); m = Supers.lookupMethod("foo", "indexOf", "f"); assertEquals("indexOf", m.getName()); assertArrayEquals(new Object[] { String.class }, m.getParameterTypes()); m = Supers.lookupMethod("foo", "indexOf", new Object[] { null } ); assertEquals("indexOf", m.getName()); assertArrayEquals(new Object[] { String.class }, m.getParameterTypes()); m = Supers.lookupMethod("foo", "format", "%s", "x"); assertEquals("format", m.getName()); assertArrayEquals(new Object[] { String.class, Object[].class }, m.getParameterTypes()); m = Supers.lookupMethod(String.class, "format", "hi"); assertEquals("format", m.getName()); assertArrayEquals(new Object[] { String.class, Object[].class }, m.getParameterTypes()); m = Supers.lookupMethod(Arrays.class, "asList", 1, 2, 3); assertEquals("asList", m.getName()); } catch (Exception ex) { fail(ex.toString()); } expectThrow(NoSuchMethodException.class, "No method in String with signature compatible with doesNotExist\\(\\)", Supers.class, "lookupMethod", "foo", "doesNotExist"); expectThrow(NoSuchMethodException.class, ".*with size\\(null,\\s?int\\)", Supers.class, "lookupMethod", "foo", "size", null, 23); } @Test public void testNearestCommonSuperclass() { assertEquals(A.class, Supers.nearestCommonSuperClass(A.class, A.class)); assertEquals(A.class, Supers.nearestCommonSuperClass(A.class, B.class)); assertEquals(A.class, Supers.nearestCommonSuperClass(B.class, A.class)); assertEquals(Integer.TYPE, Supers.nearestCommonSuperClass(Integer.TYPE, Integer.TYPE)); assertNull(Supers.nearestCommonSuperClass(Integer.TYPE, Long.TYPE)); assertNull(Supers.nearestCommonSuperClass(Object.class, Integer.TYPE)); assertEquals(Object.class, Supers.nearestCommonSuperClass(K.class, L.class)); assertEquals(Object.class, Supers.nearestCommonSuperClass(F.class, M.class)); assertEquals(A.class, Supers.nearestCommonSuperClass(B.class, C.class)); assertEquals(A.class, Supers.nearestCommonSuperClass(F.class, D.class)); assertEquals(Object.class, Supers.nearestCommonSuperClass(D.class, A[].class)); assertEquals(Object.class, Supers.nearestCommonSuperClass(new Integer[0])); assertEquals(B.class, Supers.nearestCommonSuperClass(new A[] {new B()} )); assertEquals(Object.class, Supers.nearestCommonSuperClass(new Object[] { null, null, null })); assertEquals(A.class, Supers.nearestCommonSuperClass(null, null, new A(), new B())); assertEquals(A.class, Supers.nearestCommonSuperClass(new B(), new C())); assertEquals(F.class, Supers.nearestCommonSuperClass(new I[] {new F(), null})); assertEquals(E1.class, Supers.nearestCommonSuperClass(new E1[] { E1.A, E1.B })); assertEquals(E.class, Supers.nearestCommonSuperClass(new E[] { new E() })); assertEquals(A.class, Supers.nearestCommonSuperClass(new A[] { new A(), new B() })); } @Test public void testNumberOfSuperClasses() { assertEquals(0, Supers.numberOfSuperClasses(Object.class)); assertEquals(1, Supers.numberOfSuperClasses(Long[].class)); assertEquals(2, Supers.numberOfSuperClasses(E1.class)); assertEquals(1, Supers.numberOfSuperClasses(A.class)); assertEquals(2, Supers.numberOfSuperClasses(B.class)); assertEquals(4, Supers.numberOfSuperClasses(E.class)); } @Test public void testSuperClasses() { assertEquals( ImmutableList.of(), Supers.superClasses(Object.class)); assertEquals( ImmutableList.<Class<?>>of(), Supers.superClasses(Integer.TYPE)); assertEquals( ImmutableList.of(Object.class), Supers.superClasses(A.class)); assertEquals( ImmutableList.of(Object.class, A.class, B.class), Supers.superClasses(D.class)); } }