/* * Copyright 2010 Google 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.google.gwt.inject.rebind.reflect; import com.google.gwt.inject.rebind.reflect.subpackage.BogusTypeLiteralMaker; import com.google.inject.TypeLiteral; import junit.framework.TestCase; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.List; import java.util.Map; public class ReflectUtilTest extends TestCase { public void testGetUserPackageName_privateClass() { try { ReflectUtil.getUserPackageName(new TypeLiteral<PrivateClass>() {}); fail("Expected IllegalArgumentException."); } catch (IllegalArgumentException expected) { } } public void testGetUserPackageName_privateClass_nested() { try { ReflectUtil.getUserPackageName(new TypeLiteral<List<PrivateClass>>() {}); fail("Expected IllegalArgumentException."); } catch (IllegalArgumentException expected) { } } public void testGetUserPackageName_privateClass_inArray() { try { ReflectUtil.getUserPackageName(new TypeLiteral<PrivateClass[]>() {}); fail("Expected IllegalArgumentException."); } catch (IllegalArgumentException expected) { } } public void testGetUserPackageName_privateClass_inTypeBound() { try { ReflectUtil.getUserPackageName(new TypeLiteral<List<? extends PrivateClass>>() {}); fail("Expected IllegalArgumentException."); } catch (IllegalArgumentException expected) { } } public void testGetUserPackageName_privateClass_deeplyHidden() { try { ReflectUtil.getUserPackageName(new TypeLiteral<List<? extends List<PrivateClass[]>>>() {}); fail("Expected IllegalArgumentException."); } catch (IllegalArgumentException expected) { } } public void testGetUserPackageName_impossibleClass() { // Check a class that has no private components, but would have to be // accessed from two packages simultaneously. // First check that the parts are OK. assertEquals("com.google.gwt.inject.rebind.reflect", ReflectUtil.getUserPackageName( TypeLiteral.get(HasProtectedInnerClass.ProtectedInnerClass.class))); assertEquals("com.google.gwt.inject.rebind.reflect.subpackage", ReflectUtil.getUserPackageName(BogusTypeLiteralMaker.getProtectedClassTypeLiteral())); try { ReflectUtil.getUserPackageName(BogusTypeLiteralMaker.getBogusTypeLiteral()); fail("Expected IllegalArgumentException."); } catch (IllegalArgumentException expected) { } } public void testGetUserPackageName_unparameterized() { assertEquals("java.util", ReflectUtil.getUserPackageName(TypeLiteral.get(Map.class))); } public void testGetUserPackageName_usesToplevelIfAllPublic() { assertEquals("java.util", ReflectUtil.getUserPackageName(new TypeLiteral<Map<TestCase, Integer>>() {})); } public void testGetUserPackageName_outerNameIsPackagePrivate() { assertEquals("com.google.gwt.inject.rebind.reflect", ReflectUtil.getUserPackageName(new TypeLiteral<Generic<List<Integer>>>() {})); } public void testGetUserPackageName_innerNestedNameHasPackagePrivateParent() { assertEquals("com.google.gwt.inject.rebind.reflect", ReflectUtil.getUserPackageName(new TypeLiteral<List<Nested.PublicNested>>() {})); } public void testGetUserPackageName_innerNestedNameHasPublicParent() { assertEquals("java.util", ReflectUtil.getUserPackageName( new TypeLiteral<List<PublicNested.DoublePublicNested>>() {})); } public void testGetUserPackageName_onePackagePrivateName() { assertEquals("com.google.gwt.inject.rebind.reflect", ReflectUtil.getUserPackageName( new TypeLiteral<Map<TypeLiteral<Integer>, TypeLiteral<ExampleException>>>() {})); } public void testGetUserPackageName_oneProtectedName() { assertEquals("com.google.gwt.inject.rebind.reflect", ReflectUtil.getUserPackageName( new TypeLiteral<Map<TypeLiteral<Integer>, TypeLiteral<ProtectedClass>>>() {})); } public void testGetUserPackageName_twoPackagePrivateNames() { assertEquals("com.google.gwt.inject.rebind.reflect", ReflectUtil.getUserPackageName(new TypeLiteral<Generic<List<ExampleException>>>() {})); } public void testGetUserPackageName_array() { assertEquals("com.google.gwt.inject.rebind.reflect", ReflectUtil.getUserPackageName(new TypeLiteral<ExampleException[]>() {})); } public void testGetUserPackageName_wildcard_public() { assertEquals("java.util", ReflectUtil.getUserPackageName(new TypeLiteral<List<?>>() {})); } public void testGetUserPackageName_wildcard_private() { assertEquals("com.google.gwt.inject.rebind.reflect", ReflectUtil.getUserPackageName(new TypeLiteral<Generic<?>>() {})); } public void testGetUserPackageName_wildcard_withUpperBound() { assertEquals("com.google.gwt.inject.rebind.reflect", ReflectUtil.getUserPackageName(new TypeLiteral<List<? extends ExampleException>>() {})); } public void testGetUserPackageName_wildcard_withLowerBound() { assertEquals("com.google.gwt.inject.rebind.reflect", ReflectUtil.getUserPackageName(new TypeLiteral<List<? super ExampleException>>() {})); } public void testGetUserPackageName_allAtOnce() { assertEquals("com.google.gwt.inject.rebind.reflect", ReflectUtil.getUserPackageName( new TypeLiteral<List<Generic<? extends List<ExampleException[]>[]>>>() {})); } public void testGetSourceName() throws NoSourceNameException { assertEquals("com.google.gwt.inject.rebind.reflect.ReflectUtilTest", ReflectUtil.getSourceName(ReflectUtilTest.class)); } public void testGetSourceName_nestedClass() throws NoSourceNameException { assertEquals("com.google.gwt.inject.rebind.reflect.ReflectUtilTest.Nested", ReflectUtil.getSourceName(Nested.class)); } public void testGetSourceName_typeLiteral() throws NoSourceNameException { assertEquals("com.google.gwt.inject.rebind.reflect.ReflectUtilTest", ReflectUtil.getSourceName(TypeLiteral.get(ReflectUtilTest.class))); } public void testGetSourceName_parametrizedType() throws NoSourceNameException { assertEquals( "com.google.gwt.inject.rebind.reflect.ReflectUtilTest.Parametrized<java.lang.String>", ReflectUtil.getSourceName(new TypeLiteral<Parametrized<String>>() {})); } public void testGetSourceName_primitive() throws NoSourceNameException, NoSuchMethodException { assertEquals("int", ReflectUtil.getSourceName(Integer.TYPE)); Method method = ReflectUtilTest.class.getDeclaredMethod("testGetSourceName_primitive"); assertEquals("void", ReflectUtil.getSourceName(method.getReturnType())); assertEquals("java.lang.Integer", ReflectUtil.getSourceName(Integer.class)); } public void testGetSourceName_typeVariable() throws NoSourceNameException, NoSuchMethodException { Method method = ReflectUtilTest.class.getDeclaredMethod("typeVariableMethod"); assertEquals("T", ReflectUtil.getSourceName(method.getTypeParameters()[0])); } public void testGetSourceName_anonymous() { try { ReflectUtil.getSourceName(new ReflectUtilTest() {}.getClass()); fail("Expected NoSourceNameException."); } catch (NoSourceNameException e) { // Expected. } } public void testGetSourceName_array() throws NoSourceNameException { assertEquals("java.lang.String[]", ReflectUtil.getSourceName(String[].class)); } public void testSignatureBuilder() throws NoSuchMethodException, NoSourceNameException { MethodLiteral<?, ?> method = getMethod(TypeLiteral.get(ReflectUtilTest.class), "simpleMethod"); assertEquals("private void simpleMethod()", ReflectUtil.signatureBuilder(method).build()); } public void testSignatureBuilder_constructor() throws NoSuchMethodException, NoSourceNameException { assertEquals("protected com.google.gwt.inject.rebind.reflect.ReflectUtilTest.ConstructorType()", ReflectUtil.signatureBuilder(getConstructor(TypeLiteral.get(ConstructorType.class))) .build()); } public void testSignatureBuilder_parameters() throws NoSuchMethodException, NoSourceNameException { MethodLiteral<?, ?> method = getMethod(TypeLiteral.get(ReflectUtilTest.class), "methodWithParameters", String.class, Integer.class); assertEquals("private void methodWithParameters(java.lang.String _0, java.lang.Integer _1)", ReflectUtil.signatureBuilder(method).build()); } public void testSignatureBuilder_overriddenModifiers() throws NoSuchMethodException, NoSourceNameException { MethodLiteral<?, ?> method = getMethod(TypeLiteral.get(ReflectUtilTest.class), "simpleMethod"); int modifiers = method.getModifiers() & ~Modifier.PRIVATE | Modifier.ABSTRACT | Modifier.PUBLIC; assertEquals("public abstract void simpleMethod()", ReflectUtil.signatureBuilder(method) .withParameterNames(new String[0]) .withModifiers(modifiers) .build()); } public void testSignatureBuilder_typeParametrizedMethod() throws NoSuchMethodException, NoSourceNameException { MethodLiteral<?, ?> method = getMethod(TypeLiteral.get(ReflectUtilTest.class), "parametrizedMethod", Object.class); assertEquals( "private <T extends java.lang.CharSequence & java.util.Map, V> T parametrizedMethod(V _0)", ReflectUtil.signatureBuilder(method).build()); } public void testSignatureBuilder_paramNames() throws NoSuchMethodException, NoSourceNameException { MethodLiteral<?, ?> method = getMethod(TypeLiteral.get(ReflectUtilTest.class), "methodWithParameters", String.class, Integer.class); assertEquals("private void methodWithParameters(java.lang.String bar, java.lang.Integer foo)", ReflectUtil.signatureBuilder(method) .withParameterNames(new String[] { "bar", "foo" }) .build()); try { ReflectUtil.signatureBuilder(method).withParameterNames(new String[] { "bar" }).build(); fail("Expected IllegalArgumentException."); } catch (IllegalArgumentException e) { // Expected } } public void testSignatureBuilder_exceptions() throws NoSuchMethodException, NoSourceNameException { MethodLiteral<?, ?> method = getMethod(TypeLiteral.get(ReflectUtilTest.class), "throwingMethod"); assertEquals( "private void throwingMethod() throws java.lang.IllegalArgumentException, " + "com.google.gwt.inject.rebind.reflect.ReflectUtilTest.ExampleException", ReflectUtil.signatureBuilder(method).build()); } public void testSignatureBuilder_parametrizedDeclaringType() throws NoSuchMethodException, NoSourceNameException { TypeLiteral<ParametrizedMethods<CharSequence, ExampleException, String>> type = new TypeLiteral<ParametrizedMethods<CharSequence, ExampleException, String>>() {}; MethodLiteral<?, ?> methodWithParameters = getMethod(type, "methodWithParameters", Object.class, CharSequence.class); assertEquals("void methodWithParameters(java.lang.CharSequence _0, java.lang.String _1)", ReflectUtil.signatureBuilder(methodWithParameters).build()); MethodLiteral<?, ?> returningMethod = getMethod(type, "returningMethod"); assertEquals("java.lang.CharSequence returningMethod()", ReflectUtil.signatureBuilder(returningMethod).build()); MethodLiteral<?, ?> throwingMethod = getMethod(type, "throwingMethod"); assertEquals("void throwingMethod() " + "throws com.google.gwt.inject.rebind.reflect.ReflectUtilTest.ExampleException", ReflectUtil.signatureBuilder(throwingMethod).build()); MethodLiteral<?, ?> parametrizedMethod = getMethod(type, "parametrizedMethod"); assertEquals("<V extends T> V parametrizedMethod()", ReflectUtil.signatureBuilder(parametrizedMethod).build()); } public void testGetTypeVariableDefinition() throws NoSourceNameException, NoSuchMethodException { Method method = ReflectUtilTest.class.getDeclaredMethod("typeVariableMethod"); assertEquals("T extends java.lang.CharSequence", ReflectUtil.getTypeVariableDefinition(method.getTypeParameters()[0])); Method combinedMethod = ReflectUtilTest.class.getDeclaredMethod("combinedTypeVariableMethod"); assertEquals( "T extends java.lang.CharSequence & java.util.Map<java.lang.String, java.lang.String>", ReflectUtil.getTypeVariableDefinition(combinedMethod.getTypeParameters()[0])); } private MethodLiteral<?, ?> getConstructor(TypeLiteral<?> type) throws NoSuchMethodException { return MethodLiteral.get(type.getRawType().getDeclaredConstructor(), type); } private MethodLiteral<?, ?> getMethod(TypeLiteral<?> type, String methodName, Class... paramTypes) throws NoSuchMethodException { return MethodLiteral.get(type.getRawType().getDeclaredMethod(methodName, paramTypes), type); } // // All following types and members are used as test data. // static class Nested { static class DoublyNested {} public static class PublicNested { } } static abstract class Parametrized<T extends CharSequence> {} private <T extends CharSequence, V> T typeVariableMethod() { return null; } private <T extends CharSequence & Map<String, String>> T combinedTypeVariableMethod() { return null; } private void simpleMethod() {} private void methodWithParameters(String param1, Integer param2) {} private void throwingMethod() throws IllegalArgumentException, ExampleException {} private <T extends CharSequence & Map, V> T parametrizedMethod(V param) { return null; } static class ConstructorType { protected ConstructorType() {} } static class ExampleException extends Exception {} static class ParametrizedMethods<T, E extends Exception, C extends CharSequence> { void methodWithParameters(T param1, C param2) {} T returningMethod() { return null; } void throwingMethod() throws E {} <V extends T> V parametrizedMethod() { return null; } } static class Generic<T> { } private static class PrivateClass { } protected static class ProtectedClass { } public static class PublicNested { public static class DoublePublicNested { } } public static class HasProtectedInnerClass { protected static class ProtectedInnerClass { } } }