11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/* 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2005 The Guava Authors 31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License"); 51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * you may not use this file except in compliance with the License. 61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * You may obtain a copy of the License at 71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0 91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software 111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS, 121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * See the License for the specific language governing permissions and 141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * limitations under the License. 151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.testing; 181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 197dd252788645e940eada959bdde927426e2531c9Paul Duffinimport static com.google.common.base.Preconditions.checkArgument; 207dd252788645e940eada959bdde927426e2531c9Paul Duffinimport static com.google.common.base.Preconditions.checkNotNull; 217dd252788645e940eada959bdde927426e2531c9Paul Duffin 221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.Beta; 230888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport com.google.common.base.Converter; 247dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.base.Objects; 257dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.collect.ClassToInstanceMap; 267dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.collect.ImmutableList; 271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.Lists; 281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.Maps; 297dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.collect.MutableClassToInstanceMap; 307dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.reflect.Invokable; 317dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.reflect.Parameter; 327dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.reflect.Reflection; 337dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.reflect.TypeToken; 341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport junit.framework.Assert; 361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport junit.framework.AssertionFailedError; 371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.lang.reflect.Constructor; 391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.lang.reflect.InvocationTargetException; 401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.lang.reflect.Member; 411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.lang.reflect.Method; 421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.lang.reflect.Modifier; 437dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.ParameterizedType; 447dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.lang.reflect.Type; 451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Arrays; 461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.List; 477dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.util.concurrent.ConcurrentMap; 481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport javax.annotation.Nullable; 501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/** 527dd252788645e940eada959bdde927426e2531c9Paul Duffin * A test utility that verifies that your methods and constructors throw {@link 537dd252788645e940eada959bdde927426e2531c9Paul Duffin * NullPointerException} or {@link UnsupportedOperationException} whenever null 547dd252788645e940eada959bdde927426e2531c9Paul Duffin * is passed to a parameter that isn't annotated with {@link Nullable}. 557dd252788645e940eada959bdde927426e2531c9Paul Duffin * 567dd252788645e940eada959bdde927426e2531c9Paul Duffin * <p>The tested methods and constructors are invoked -- each time with one 577dd252788645e940eada959bdde927426e2531c9Paul Duffin * parameter being null and the rest not null -- and the test fails if no 587dd252788645e940eada959bdde927426e2531c9Paul Duffin * expected exception is thrown. {@code NullPointerTester} uses best effort to 597dd252788645e940eada959bdde927426e2531c9Paul Duffin * pick non-null default values for many common JDK and Guava types, and also 607dd252788645e940eada959bdde927426e2531c9Paul Duffin * for interfaces and public classes that have public parameter-less 617dd252788645e940eada959bdde927426e2531c9Paul Duffin * constructors. When the non-null default value for a particular parameter type 627dd252788645e940eada959bdde927426e2531c9Paul Duffin * cannot be provided by {@code NullPointerTester}, the caller can provide a 637dd252788645e940eada959bdde927426e2531c9Paul Duffin * custom non-null default value for the parameter type via {@link #setDefault}. 641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Kevin Bourrillion 661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 10.0 671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@Beta 691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic final class NullPointerTester { 70dbd967a6e5c96cc1a97c5521f88dc1564ba2f81bPaul Duffin 717dd252788645e940eada959bdde927426e2531c9Paul Duffin private final ClassToInstanceMap<Object> defaults = 727dd252788645e940eada959bdde927426e2531c9Paul Duffin MutableClassToInstanceMap.create(); 737dd252788645e940eada959bdde927426e2531c9Paul Duffin private final List<Member> ignoredMembers = Lists.newArrayList(); 74dbd967a6e5c96cc1a97c5521f88dc1564ba2f81bPaul Duffin 750888a09821a98ac0680fad765217302858e70fa4Paul Duffin private ExceptionTypePolicy policy = ExceptionTypePolicy.NPE_OR_UOE; 760888a09821a98ac0680fad765217302858e70fa4Paul Duffin 771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Sets a default value that can be used for any parameter of type 791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code type}. Returns this object. 801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public <T> NullPointerTester setDefault(Class<T> type, T value) { 827dd252788645e940eada959bdde927426e2531c9Paul Duffin defaults.putInstance(type, checkNotNull(value)); 831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return this; 841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 877dd252788645e940eada959bdde927426e2531c9Paul Duffin * Ignore {@code method} in the tests that follow. Returns this object. 887dd252788645e940eada959bdde927426e2531c9Paul Duffin * 897dd252788645e940eada959bdde927426e2531c9Paul Duffin * @since 13.0 901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 917dd252788645e940eada959bdde927426e2531c9Paul Duffin public NullPointerTester ignore(Method method) { 927dd252788645e940eada959bdde927426e2531c9Paul Duffin ignoredMembers.add(checkNotNull(method)); 931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return this; 941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 977dd252788645e940eada959bdde927426e2531c9Paul Duffin * Runs {@link #testConstructor} on every constructor in class {@code c} that 987dd252788645e940eada959bdde927426e2531c9Paul Duffin * has at least {@code minimalVisibility}. 991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1007dd252788645e940eada959bdde927426e2531c9Paul Duffin public void testConstructors(Class<?> c, Visibility minimalVisibility) { 1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (Constructor<?> constructor : c.getDeclaredConstructors()) { 1027dd252788645e940eada959bdde927426e2531c9Paul Duffin if (minimalVisibility.isVisible(constructor) && !isIgnored(constructor)) { 1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert testConstructor(constructor); 1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1097dd252788645e940eada959bdde927426e2531c9Paul Duffin * Runs {@link #testConstructor} on every public constructor in class {@code 1107dd252788645e940eada959bdde927426e2531c9Paul Duffin * c}. 1117dd252788645e940eada959bdde927426e2531c9Paul Duffin */ 1127dd252788645e940eada959bdde927426e2531c9Paul Duffin public void testAllPublicConstructors(Class<?> c) { 1137dd252788645e940eada959bdde927426e2531c9Paul Duffin testConstructors(c, Visibility.PUBLIC); 1147dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1157dd252788645e940eada959bdde927426e2531c9Paul Duffin 1167dd252788645e940eada959bdde927426e2531c9Paul Duffin /** 1177dd252788645e940eada959bdde927426e2531c9Paul Duffin * Runs {@link #testMethod} on every static method of class {@code c} that has 1187dd252788645e940eada959bdde927426e2531c9Paul Duffin * at least {@code minimalVisibility}, including those "inherited" from 1197dd252788645e940eada959bdde927426e2531c9Paul Duffin * superclasses of the same package. 1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1217dd252788645e940eada959bdde927426e2531c9Paul Duffin public void testStaticMethods(Class<?> c, Visibility minimalVisibility) { 1227dd252788645e940eada959bdde927426e2531c9Paul Duffin for (Method method : minimalVisibility.getStaticMethods(c)) { 1237dd252788645e940eada959bdde927426e2531c9Paul Duffin if (!isIgnored(method)) { 1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert testMethod(null, method); 1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1307dd252788645e940eada959bdde927426e2531c9Paul Duffin * Runs {@link #testMethod} on every public static method of class {@code c}, 1317dd252788645e940eada959bdde927426e2531c9Paul Duffin * including those "inherited" from superclasses of the same package. 1327dd252788645e940eada959bdde927426e2531c9Paul Duffin */ 1337dd252788645e940eada959bdde927426e2531c9Paul Duffin public void testAllPublicStaticMethods(Class<?> c) { 1347dd252788645e940eada959bdde927426e2531c9Paul Duffin testStaticMethods(c, Visibility.PUBLIC); 1357dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1367dd252788645e940eada959bdde927426e2531c9Paul Duffin 1377dd252788645e940eada959bdde927426e2531c9Paul Duffin /** 1387dd252788645e940eada959bdde927426e2531c9Paul Duffin * Runs {@link #testMethod} on every instance method of the class of 1397dd252788645e940eada959bdde927426e2531c9Paul Duffin * {@code instance} with at least {@code minimalVisibility}, including those 1407dd252788645e940eada959bdde927426e2531c9Paul Duffin * inherited from superclasses of the same package. 1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1427dd252788645e940eada959bdde927426e2531c9Paul Duffin public void testInstanceMethods(Object instance, Visibility minimalVisibility) { 1437dd252788645e940eada959bdde927426e2531c9Paul Duffin for (Method method : getInstanceMethodsToTest(instance.getClass(), minimalVisibility)) { 1447dd252788645e940eada959bdde927426e2531c9Paul Duffin testMethod(instance, method); 1457dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1467dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1477dd252788645e940eada959bdde927426e2531c9Paul Duffin 1487dd252788645e940eada959bdde927426e2531c9Paul Duffin ImmutableList<Method> getInstanceMethodsToTest(Class<?> c, Visibility minimalVisibility) { 1497dd252788645e940eada959bdde927426e2531c9Paul Duffin ImmutableList.Builder<Method> builder = ImmutableList.builder(); 1507dd252788645e940eada959bdde927426e2531c9Paul Duffin for (Method method : minimalVisibility.getInstanceMethods(c)) { 1517dd252788645e940eada959bdde927426e2531c9Paul Duffin if (!isIgnored(method)) { 1527dd252788645e940eada959bdde927426e2531c9Paul Duffin builder.add(method); 1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1557dd252788645e940eada959bdde927426e2531c9Paul Duffin return builder.build(); 1567dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1577dd252788645e940eada959bdde927426e2531c9Paul Duffin 1587dd252788645e940eada959bdde927426e2531c9Paul Duffin /** 1597dd252788645e940eada959bdde927426e2531c9Paul Duffin * Runs {@link #testMethod} on every public instance method of the class of 1607dd252788645e940eada959bdde927426e2531c9Paul Duffin * {@code instance}, including those inherited from superclasses of the same 1617dd252788645e940eada959bdde927426e2531c9Paul Duffin * package. 1627dd252788645e940eada959bdde927426e2531c9Paul Duffin */ 1637dd252788645e940eada959bdde927426e2531c9Paul Duffin public void testAllPublicInstanceMethods(Object instance) { 1647dd252788645e940eada959bdde927426e2531c9Paul Duffin testInstanceMethods(instance, Visibility.PUBLIC); 1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Verifies that {@code method} produces a {@link NullPointerException} 1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * or {@link UnsupportedOperationException} whenever <i>any</i> of its 1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * non-{@link Nullable} parameters are null. 1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @param instance the instance to invoke {@code method} on, or null if 1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code method} is static 1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1757dd252788645e940eada959bdde927426e2531c9Paul Duffin public void testMethod(@Nullable Object instance, Method method) { 1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Class<?>[] types = method.getParameterTypes(); 1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (int nullIndex = 0; nullIndex < types.length; nullIndex++) { 1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert testMethodParameter(instance, method, nullIndex); 1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Verifies that {@code ctor} produces a {@link NullPointerException} or 1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link UnsupportedOperationException} whenever <i>any</i> of its 1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * non-{@link Nullable} parameters are null. 1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1877dd252788645e940eada959bdde927426e2531c9Paul Duffin public void testConstructor(Constructor<?> ctor) { 1887dd252788645e940eada959bdde927426e2531c9Paul Duffin Class<?> declaringClass = ctor.getDeclaringClass(); 1897dd252788645e940eada959bdde927426e2531c9Paul Duffin checkArgument(Modifier.isStatic(declaringClass.getModifiers()) 1907dd252788645e940eada959bdde927426e2531c9Paul Duffin || declaringClass.getEnclosingClass() == null, 1917dd252788645e940eada959bdde927426e2531c9Paul Duffin "Cannot test constructor of non-static inner class: %s", declaringClass.getName()); 1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Class<?>[] types = ctor.getParameterTypes(); 1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (int nullIndex = 0; nullIndex < types.length; nullIndex++) { 1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert testConstructorParameter(ctor, nullIndex); 1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Verifies that {@code method} produces a {@link NullPointerException} or 2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link UnsupportedOperationException} when the parameter in position {@code 2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * paramIndex} is null. If this parameter is marked {@link Nullable}, this 2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * method does nothing. 2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @param instance the instance to invoke {@code method} on, or null if 2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code method} is static 2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 2077dd252788645e940eada959bdde927426e2531c9Paul Duffin public void testMethodParameter( 2087dd252788645e940eada959bdde927426e2531c9Paul Duffin @Nullable final Object instance, final Method method, int paramIndex) { 2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert method.setAccessible(true); 2107dd252788645e940eada959bdde927426e2531c9Paul Duffin testParameter(instance, invokable(instance, method), paramIndex, method.getDeclaringClass()); 2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Verifies that {@code ctor} produces a {@link NullPointerException} or 2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link UnsupportedOperationException} when the parameter in position {@code 2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * paramIndex} is null. If this parameter is marked {@link Nullable}, this 2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * method does nothing. 2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 2197dd252788645e940eada959bdde927426e2531c9Paul Duffin public void testConstructorParameter(Constructor<?> ctor, int paramIndex) { 2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ctor.setAccessible(true); 2217dd252788645e940eada959bdde927426e2531c9Paul Duffin testParameter(null, Invokable.from(ctor), paramIndex, ctor.getDeclaringClass()); 2227dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2237dd252788645e940eada959bdde927426e2531c9Paul Duffin 2247dd252788645e940eada959bdde927426e2531c9Paul Duffin /** Visibility of any method or constructor. */ 2257dd252788645e940eada959bdde927426e2531c9Paul Duffin public enum Visibility { 2267dd252788645e940eada959bdde927426e2531c9Paul Duffin 2277dd252788645e940eada959bdde927426e2531c9Paul Duffin PACKAGE { 2287dd252788645e940eada959bdde927426e2531c9Paul Duffin @Override boolean isVisible(int modifiers) { 2297dd252788645e940eada959bdde927426e2531c9Paul Duffin return !Modifier.isPrivate(modifiers); 2307dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2317dd252788645e940eada959bdde927426e2531c9Paul Duffin }, 2327dd252788645e940eada959bdde927426e2531c9Paul Duffin 2337dd252788645e940eada959bdde927426e2531c9Paul Duffin PROTECTED { 2347dd252788645e940eada959bdde927426e2531c9Paul Duffin @Override boolean isVisible(int modifiers) { 2357dd252788645e940eada959bdde927426e2531c9Paul Duffin return Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers); 2367dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2377dd252788645e940eada959bdde927426e2531c9Paul Duffin }, 2387dd252788645e940eada959bdde927426e2531c9Paul Duffin 2397dd252788645e940eada959bdde927426e2531c9Paul Duffin PUBLIC { 2407dd252788645e940eada959bdde927426e2531c9Paul Duffin @Override boolean isVisible(int modifiers) { 2417dd252788645e940eada959bdde927426e2531c9Paul Duffin return Modifier.isPublic(modifiers); 2427dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2437dd252788645e940eada959bdde927426e2531c9Paul Duffin }; 2447dd252788645e940eada959bdde927426e2531c9Paul Duffin 2457dd252788645e940eada959bdde927426e2531c9Paul Duffin abstract boolean isVisible(int modifiers); 2467dd252788645e940eada959bdde927426e2531c9Paul Duffin 2477dd252788645e940eada959bdde927426e2531c9Paul Duffin /** 2487dd252788645e940eada959bdde927426e2531c9Paul Duffin * Returns {@code true} if {@code member} is visible under {@code this} 2497dd252788645e940eada959bdde927426e2531c9Paul Duffin * visibility. 2507dd252788645e940eada959bdde927426e2531c9Paul Duffin */ 2517dd252788645e940eada959bdde927426e2531c9Paul Duffin final boolean isVisible(Member member) { 2527dd252788645e940eada959bdde927426e2531c9Paul Duffin return isVisible(member.getModifiers()); 2537dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2547dd252788645e940eada959bdde927426e2531c9Paul Duffin 2557dd252788645e940eada959bdde927426e2531c9Paul Duffin final Iterable<Method> getStaticMethods(Class<?> cls) { 2567dd252788645e940eada959bdde927426e2531c9Paul Duffin ImmutableList.Builder<Method> builder = ImmutableList.builder(); 2577dd252788645e940eada959bdde927426e2531c9Paul Duffin for (Method method : getVisibleMethods(cls)) { 2587dd252788645e940eada959bdde927426e2531c9Paul Duffin if (Invokable.from(method).isStatic()) { 2597dd252788645e940eada959bdde927426e2531c9Paul Duffin builder.add(method); 2607dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2617dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2627dd252788645e940eada959bdde927426e2531c9Paul Duffin return builder.build(); 2637dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2647dd252788645e940eada959bdde927426e2531c9Paul Duffin 2657dd252788645e940eada959bdde927426e2531c9Paul Duffin final Iterable<Method> getInstanceMethods(Class<?> cls) { 2667dd252788645e940eada959bdde927426e2531c9Paul Duffin ConcurrentMap<Signature, Method> map = Maps.newConcurrentMap(); 2677dd252788645e940eada959bdde927426e2531c9Paul Duffin for (Method method : getVisibleMethods(cls)) { 2687dd252788645e940eada959bdde927426e2531c9Paul Duffin if (!Invokable.from(method).isStatic()) { 2697dd252788645e940eada959bdde927426e2531c9Paul Duffin map.putIfAbsent(new Signature(method), method); 2701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2717dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2727dd252788645e940eada959bdde927426e2531c9Paul Duffin return map.values(); 2737dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2747dd252788645e940eada959bdde927426e2531c9Paul Duffin 2757dd252788645e940eada959bdde927426e2531c9Paul Duffin private ImmutableList<Method> getVisibleMethods(Class<?> cls) { 2767dd252788645e940eada959bdde927426e2531c9Paul Duffin // Don't use cls.getPackage() because it does nasty things like reading 2777dd252788645e940eada959bdde927426e2531c9Paul Duffin // a file. 2787dd252788645e940eada959bdde927426e2531c9Paul Duffin String visiblePackage = Reflection.getPackageName(cls); 2797dd252788645e940eada959bdde927426e2531c9Paul Duffin ImmutableList.Builder<Method> builder = ImmutableList.builder(); 2807dd252788645e940eada959bdde927426e2531c9Paul Duffin for (Class<?> type : TypeToken.of(cls).getTypes().classes().rawTypes()) { 2817dd252788645e940eada959bdde927426e2531c9Paul Duffin if (!Reflection.getPackageName(type).equals(visiblePackage)) { 2827dd252788645e940eada959bdde927426e2531c9Paul Duffin break; 2831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2847dd252788645e940eada959bdde927426e2531c9Paul Duffin for (Method method : type.getDeclaredMethods()) { 2857dd252788645e940eada959bdde927426e2531c9Paul Duffin if (!method.isSynthetic() && isVisible(method)) { 2867dd252788645e940eada959bdde927426e2531c9Paul Duffin builder.add(method); 2877dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2897dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2907dd252788645e940eada959bdde927426e2531c9Paul Duffin return builder.build(); 2917dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2927dd252788645e940eada959bdde927426e2531c9Paul Duffin } 2937dd252788645e940eada959bdde927426e2531c9Paul Duffin 2947dd252788645e940eada959bdde927426e2531c9Paul Duffin // TODO(benyu): Use labs/reflect/Signature if it graduates. 2957dd252788645e940eada959bdde927426e2531c9Paul Duffin private static final class Signature { 2967dd252788645e940eada959bdde927426e2531c9Paul Duffin private final String name; 2977dd252788645e940eada959bdde927426e2531c9Paul Duffin private final ImmutableList<Class<?>> parameterTypes; 2987dd252788645e940eada959bdde927426e2531c9Paul Duffin 2997dd252788645e940eada959bdde927426e2531c9Paul Duffin Signature(Method method) { 3007dd252788645e940eada959bdde927426e2531c9Paul Duffin this(method.getName(), ImmutableList.copyOf(method.getParameterTypes())); 3017dd252788645e940eada959bdde927426e2531c9Paul Duffin } 3027dd252788645e940eada959bdde927426e2531c9Paul Duffin 3037dd252788645e940eada959bdde927426e2531c9Paul Duffin Signature(String name, ImmutableList<Class<?>> parameterTypes) { 3047dd252788645e940eada959bdde927426e2531c9Paul Duffin this.name = name; 3057dd252788645e940eada959bdde927426e2531c9Paul Duffin this.parameterTypes = parameterTypes; 3067dd252788645e940eada959bdde927426e2531c9Paul Duffin } 3077dd252788645e940eada959bdde927426e2531c9Paul Duffin 3087dd252788645e940eada959bdde927426e2531c9Paul Duffin @Override public boolean equals(Object obj) { 3097dd252788645e940eada959bdde927426e2531c9Paul Duffin if (obj instanceof Signature) { 3107dd252788645e940eada959bdde927426e2531c9Paul Duffin Signature that = (Signature) obj; 3117dd252788645e940eada959bdde927426e2531c9Paul Duffin return name.equals(that.name) 3127dd252788645e940eada959bdde927426e2531c9Paul Duffin && parameterTypes.equals(that.parameterTypes); 3137dd252788645e940eada959bdde927426e2531c9Paul Duffin } 3147dd252788645e940eada959bdde927426e2531c9Paul Duffin return false; 3157dd252788645e940eada959bdde927426e2531c9Paul Duffin } 3167dd252788645e940eada959bdde927426e2531c9Paul Duffin 3177dd252788645e940eada959bdde927426e2531c9Paul Duffin @Override public int hashCode() { 3187dd252788645e940eada959bdde927426e2531c9Paul Duffin return Objects.hashCode(name, parameterTypes); 3197dd252788645e940eada959bdde927426e2531c9Paul Duffin } 3201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 3237dd252788645e940eada959bdde927426e2531c9Paul Duffin * Verifies that {@code invokable} produces a {@link NullPointerException} or 3241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link UnsupportedOperationException} when the parameter in position {@code 3251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * paramIndex} is null. If this parameter is marked {@link Nullable}, this 3261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * method does nothing. 3271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 3287dd252788645e940eada959bdde927426e2531c9Paul Duffin * @param instance the instance to invoke {@code invokable} on, or null if 3297dd252788645e940eada959bdde927426e2531c9Paul Duffin * {@code invokable} is static 3301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 3317dd252788645e940eada959bdde927426e2531c9Paul Duffin private void testParameter(Object instance, Invokable<?, ?> invokable, 3327dd252788645e940eada959bdde927426e2531c9Paul Duffin int paramIndex, Class<?> testedClass) { 3337dd252788645e940eada959bdde927426e2531c9Paul Duffin if (isPrimitiveOrNullable(invokable.getParameters().get(paramIndex))) { 3341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return; // there's nothing to test 3351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3367dd252788645e940eada959bdde927426e2531c9Paul Duffin Object[] params = buildParamList(invokable, paramIndex); 3371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 3387dd252788645e940eada959bdde927426e2531c9Paul Duffin @SuppressWarnings("unchecked") // We'll get a runtime exception if the type is wrong. 3397dd252788645e940eada959bdde927426e2531c9Paul Duffin Invokable<Object, ?> unsafe = (Invokable<Object, ?>) invokable; 3407dd252788645e940eada959bdde927426e2531c9Paul Duffin unsafe.invoke(instance, params); 3410888a09821a98ac0680fad765217302858e70fa4Paul Duffin Assert.fail("No exception thrown for parameter at index " + paramIndex 3420888a09821a98ac0680fad765217302858e70fa4Paul Duffin + " from " + invokable + Arrays.toString(params) + " for " + testedClass); 3431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (InvocationTargetException e) { 3441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Throwable cause = e.getCause(); 3450888a09821a98ac0680fad765217302858e70fa4Paul Duffin if (policy.isExpectedType(cause)) { 3461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return; 3471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert AssertionFailedError error = new AssertionFailedError( 3497dd252788645e940eada959bdde927426e2531c9Paul Duffin "wrong exception thrown from " + invokable + ": " + cause); 3501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert error.initCause(cause); 3511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw error; 3527dd252788645e940eada959bdde927426e2531c9Paul Duffin } catch (IllegalAccessException e) { 3537dd252788645e940eada959bdde927426e2531c9Paul Duffin throw new RuntimeException(e); 3541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3577dd252788645e940eada959bdde927426e2531c9Paul Duffin private static String bestAvailableString( 3587dd252788645e940eada959bdde927426e2531c9Paul Duffin TypeToken type, int position, Invokable<?, ?> invokable) { 3597dd252788645e940eada959bdde927426e2531c9Paul Duffin checkNotNull(type); 3607dd252788645e940eada959bdde927426e2531c9Paul Duffin try { 3617dd252788645e940eada959bdde927426e2531c9Paul Duffin return type.toString(); 3627dd252788645e940eada959bdde927426e2531c9Paul Duffin } catch (NullPointerException androidBug6636) { 3637dd252788645e940eada959bdde927426e2531c9Paul Duffin // http://stackoverflow.com/a/8169250/28465 3647dd252788645e940eada959bdde927426e2531c9Paul Duffin return String.format("unknown (arg %s of %s)", position, invokable); 3651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3687dd252788645e940eada959bdde927426e2531c9Paul Duffin private Object[] buildParamList(Invokable<?, ?> invokable, int indexOfParamToSetToNull) { 3697dd252788645e940eada959bdde927426e2531c9Paul Duffin ImmutableList<Parameter> params = invokable.getParameters(); 3707dd252788645e940eada959bdde927426e2531c9Paul Duffin Object[] args = new Object[params.size()]; 3711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3727dd252788645e940eada959bdde927426e2531c9Paul Duffin for (int i = 0; i < args.length; i++) { 3737dd252788645e940eada959bdde927426e2531c9Paul Duffin Parameter param = params.get(i); 374dbd967a6e5c96cc1a97c5521f88dc1564ba2f81bPaul Duffin if (i != indexOfParamToSetToNull) { 3757dd252788645e940eada959bdde927426e2531c9Paul Duffin args[i] = getDefaultValue(param.getType()); 3760888a09821a98ac0680fad765217302858e70fa4Paul Duffin Assert.assertTrue( 3770888a09821a98ac0680fad765217302858e70fa4Paul Duffin "Can't find or create a sample instance for type '" 3780888a09821a98ac0680fad765217302858e70fa4Paul Duffin + bestAvailableString(param.getType(), i, invokable) 3790888a09821a98ac0680fad765217302858e70fa4Paul Duffin + "'; please provide one using NullPointerTester.setDefault()", 3800888a09821a98ac0680fad765217302858e70fa4Paul Duffin args[i] != null || isNullable(param)); 381dbd967a6e5c96cc1a97c5521f88dc1564ba2f81bPaul Duffin } 3821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3837dd252788645e940eada959bdde927426e2531c9Paul Duffin return args; 3841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3867dd252788645e940eada959bdde927426e2531c9Paul Duffin private <T> T getDefaultValue(TypeToken<T> type) { 3877dd252788645e940eada959bdde927426e2531c9Paul Duffin // We assume that all defaults are generics-safe, even if they aren't, 3887dd252788645e940eada959bdde927426e2531c9Paul Duffin // we take the risk. 3897dd252788645e940eada959bdde927426e2531c9Paul Duffin @SuppressWarnings("unchecked") 3907dd252788645e940eada959bdde927426e2531c9Paul Duffin T defaultValue = (T) defaults.getInstance(type.getRawType()); 3917dd252788645e940eada959bdde927426e2531c9Paul Duffin if (defaultValue != null) { 3927dd252788645e940eada959bdde927426e2531c9Paul Duffin return defaultValue; 3937dd252788645e940eada959bdde927426e2531c9Paul Duffin } 3940888a09821a98ac0680fad765217302858e70fa4Paul Duffin @SuppressWarnings("unchecked") // All arbitrary instances are generics-safe 3950888a09821a98ac0680fad765217302858e70fa4Paul Duffin T arbitrary = (T) ArbitraryInstances.get(type.getRawType()); 3960888a09821a98ac0680fad765217302858e70fa4Paul Duffin if (arbitrary != null) { 3970888a09821a98ac0680fad765217302858e70fa4Paul Duffin return arbitrary; 3987dd252788645e940eada959bdde927426e2531c9Paul Duffin } 3997dd252788645e940eada959bdde927426e2531c9Paul Duffin if (type.getRawType() == Class.class) { 4007dd252788645e940eada959bdde927426e2531c9Paul Duffin // If parameter is Class<? extends Foo>, we return Foo.class 4017dd252788645e940eada959bdde927426e2531c9Paul Duffin @SuppressWarnings("unchecked") 4027dd252788645e940eada959bdde927426e2531c9Paul Duffin T defaultClass = (T) getFirstTypeParameter(type.getType()).getRawType(); 4037dd252788645e940eada959bdde927426e2531c9Paul Duffin return defaultClass; 4047dd252788645e940eada959bdde927426e2531c9Paul Duffin } 4057dd252788645e940eada959bdde927426e2531c9Paul Duffin if (type.getRawType() == TypeToken.class) { 4067dd252788645e940eada959bdde927426e2531c9Paul Duffin // If parameter is TypeToken<? extends Foo>, we return TypeToken<Foo>. 4077dd252788645e940eada959bdde927426e2531c9Paul Duffin @SuppressWarnings("unchecked") 4087dd252788645e940eada959bdde927426e2531c9Paul Duffin T defaultType = (T) getFirstTypeParameter(type.getType()); 4097dd252788645e940eada959bdde927426e2531c9Paul Duffin return defaultType; 4107dd252788645e940eada959bdde927426e2531c9Paul Duffin } 4110888a09821a98ac0680fad765217302858e70fa4Paul Duffin if (type.getRawType() == Converter.class) { 4120888a09821a98ac0680fad765217302858e70fa4Paul Duffin TypeToken<?> convertFromType = type.resolveType( 4130888a09821a98ac0680fad765217302858e70fa4Paul Duffin Converter.class.getTypeParameters()[0]); 4140888a09821a98ac0680fad765217302858e70fa4Paul Duffin TypeToken<?> convertToType = type.resolveType( 4150888a09821a98ac0680fad765217302858e70fa4Paul Duffin Converter.class.getTypeParameters()[1]); 4160888a09821a98ac0680fad765217302858e70fa4Paul Duffin @SuppressWarnings("unchecked") // returns default for both F and T 4170888a09821a98ac0680fad765217302858e70fa4Paul Duffin T defaultConverter = (T) defaultConverter(convertFromType, convertToType); 4180888a09821a98ac0680fad765217302858e70fa4Paul Duffin return defaultConverter; 4190888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 4207dd252788645e940eada959bdde927426e2531c9Paul Duffin if (type.getRawType().isInterface()) { 4217dd252788645e940eada959bdde927426e2531c9Paul Duffin return newDefaultReturningProxy(type); 4227dd252788645e940eada959bdde927426e2531c9Paul Duffin } 4237dd252788645e940eada959bdde927426e2531c9Paul Duffin return null; 4247dd252788645e940eada959bdde927426e2531c9Paul Duffin } 4257dd252788645e940eada959bdde927426e2531c9Paul Duffin 4260888a09821a98ac0680fad765217302858e70fa4Paul Duffin private <F, T> Converter<F, T> defaultConverter( 4270888a09821a98ac0680fad765217302858e70fa4Paul Duffin final TypeToken<F> convertFromType, final TypeToken<T> convertToType) { 4280888a09821a98ac0680fad765217302858e70fa4Paul Duffin return new Converter<F, T>() { 4290888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override protected T doForward(F a) { 4300888a09821a98ac0680fad765217302858e70fa4Paul Duffin return doConvert(convertToType); 4310888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 4320888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override protected F doBackward(T b) { 4330888a09821a98ac0680fad765217302858e70fa4Paul Duffin return doConvert(convertFromType); 4340888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 4350888a09821a98ac0680fad765217302858e70fa4Paul Duffin 4360888a09821a98ac0680fad765217302858e70fa4Paul Duffin private /*static*/ <S> S doConvert(TypeToken<S> type) { 4370888a09821a98ac0680fad765217302858e70fa4Paul Duffin return checkNotNull(getDefaultValue(type)); 4380888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 4390888a09821a98ac0680fad765217302858e70fa4Paul Duffin }; 4400888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 4410888a09821a98ac0680fad765217302858e70fa4Paul Duffin 4427dd252788645e940eada959bdde927426e2531c9Paul Duffin private static TypeToken<?> getFirstTypeParameter(Type type) { 4437dd252788645e940eada959bdde927426e2531c9Paul Duffin if (type instanceof ParameterizedType) { 4447dd252788645e940eada959bdde927426e2531c9Paul Duffin return TypeToken.of( 4457dd252788645e940eada959bdde927426e2531c9Paul Duffin ((ParameterizedType) type).getActualTypeArguments()[0]); 4467dd252788645e940eada959bdde927426e2531c9Paul Duffin } else { 4477dd252788645e940eada959bdde927426e2531c9Paul Duffin return TypeToken.of(Object.class); 4487dd252788645e940eada959bdde927426e2531c9Paul Duffin } 4491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4517dd252788645e940eada959bdde927426e2531c9Paul Duffin private <T> T newDefaultReturningProxy(final TypeToken<T> type) { 4527dd252788645e940eada959bdde927426e2531c9Paul Duffin return new DummyProxy() { 4537dd252788645e940eada959bdde927426e2531c9Paul Duffin @Override <R> R dummyReturnValue(TypeToken<R> returnType) { 4547dd252788645e940eada959bdde927426e2531c9Paul Duffin return getDefaultValue(returnType); 4557dd252788645e940eada959bdde927426e2531c9Paul Duffin } 4567dd252788645e940eada959bdde927426e2531c9Paul Duffin }.newProxy(type); 4577dd252788645e940eada959bdde927426e2531c9Paul Duffin } 4587dd252788645e940eada959bdde927426e2531c9Paul Duffin 4597dd252788645e940eada959bdde927426e2531c9Paul Duffin private static Invokable<?, ?> invokable(@Nullable Object instance, Method method) { 4607dd252788645e940eada959bdde927426e2531c9Paul Duffin if (instance == null) { 4617dd252788645e940eada959bdde927426e2531c9Paul Duffin return Invokable.from(method); 4627dd252788645e940eada959bdde927426e2531c9Paul Duffin } else { 4637dd252788645e940eada959bdde927426e2531c9Paul Duffin return TypeToken.of(instance.getClass()).method(method); 4647dd252788645e940eada959bdde927426e2531c9Paul Duffin } 4651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4677dd252788645e940eada959bdde927426e2531c9Paul Duffin static boolean isPrimitiveOrNullable(Parameter param) { 4680888a09821a98ac0680fad765217302858e70fa4Paul Duffin return param.getType().getRawType().isPrimitive() || isNullable(param); 4690888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 4700888a09821a98ac0680fad765217302858e70fa4Paul Duffin 4710888a09821a98ac0680fad765217302858e70fa4Paul Duffin private static boolean isNullable(Parameter param) { 4720888a09821a98ac0680fad765217302858e70fa4Paul Duffin return param.isAnnotationPresent(Nullable.class); 4731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private boolean isIgnored(Member member) { 4761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return member.isSynthetic() || ignoredMembers.contains(member); 4771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4780888a09821a98ac0680fad765217302858e70fa4Paul Duffin 4790888a09821a98ac0680fad765217302858e70fa4Paul Duffin /** 4800888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Strategy for exception type matching used by {@link NullPointerTester}. 4810888a09821a98ac0680fad765217302858e70fa4Paul Duffin */ 4820888a09821a98ac0680fad765217302858e70fa4Paul Duffin private enum ExceptionTypePolicy { 4830888a09821a98ac0680fad765217302858e70fa4Paul Duffin 4840888a09821a98ac0680fad765217302858e70fa4Paul Duffin /** 4850888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Exceptions should be {@link NullPointerException} or 4860888a09821a98ac0680fad765217302858e70fa4Paul Duffin * {@link UnsupportedOperationException}. 4870888a09821a98ac0680fad765217302858e70fa4Paul Duffin */ 4880888a09821a98ac0680fad765217302858e70fa4Paul Duffin NPE_OR_UOE() { 4890888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override 4900888a09821a98ac0680fad765217302858e70fa4Paul Duffin public boolean isExpectedType(Throwable cause) { 4910888a09821a98ac0680fad765217302858e70fa4Paul Duffin return cause instanceof NullPointerException 4920888a09821a98ac0680fad765217302858e70fa4Paul Duffin || cause instanceof UnsupportedOperationException; 4930888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 4940888a09821a98ac0680fad765217302858e70fa4Paul Duffin }, 4950888a09821a98ac0680fad765217302858e70fa4Paul Duffin 4960888a09821a98ac0680fad765217302858e70fa4Paul Duffin /** 4970888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Exceptions should be {@link NullPointerException}, 4980888a09821a98ac0680fad765217302858e70fa4Paul Duffin * {@link IllegalArgumentException}, or 4990888a09821a98ac0680fad765217302858e70fa4Paul Duffin * {@link UnsupportedOperationException}. 5000888a09821a98ac0680fad765217302858e70fa4Paul Duffin */ 5010888a09821a98ac0680fad765217302858e70fa4Paul Duffin NPE_IAE_OR_UOE() { 5020888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Override 5030888a09821a98ac0680fad765217302858e70fa4Paul Duffin public boolean isExpectedType(Throwable cause) { 5040888a09821a98ac0680fad765217302858e70fa4Paul Duffin return cause instanceof NullPointerException 5050888a09821a98ac0680fad765217302858e70fa4Paul Duffin || cause instanceof IllegalArgumentException 5060888a09821a98ac0680fad765217302858e70fa4Paul Duffin || cause instanceof UnsupportedOperationException; 5070888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 5080888a09821a98ac0680fad765217302858e70fa4Paul Duffin }; 5090888a09821a98ac0680fad765217302858e70fa4Paul Duffin 5100888a09821a98ac0680fad765217302858e70fa4Paul Duffin public abstract boolean isExpectedType(Throwable cause); 5110888a09821a98ac0680fad765217302858e70fa4Paul Duffin } 5121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 513