View Javadoc
1   /*
2   ClassFanOutComplexity
3   max = 24
4   excludedClasses = (default)ArrayIndexOutOfBoundsException, ArrayList, Boolean, Byte, \
5                     Character, Class, Collection, Deprecated, Deque, Double, DoubleStream, \
6                     EnumSet, Exception, Float, FunctionalInterface, HashMap, HashSet, \
7                     IllegalArgumentException, IllegalStateException, IndexOutOfBoundsException, \
8                     IntStream, Integer, LinkedHashMap, LinkedHashSet, LinkedList, List, Long, \
9                     LongStream, Map, NullPointerException, Object, Optional, OptionalDouble, \
10                    OptionalInt, OptionalLong, Override, Queue, RuntimeException, SafeVarargs, \
11                    SecurityException, Set, Short, SortedMap, SortedSet, Stream, String, \
12                    StringBuffer, StringBuilder, SuppressWarnings, Throwable, TreeMap, TreeSet, \
13                    UnsupportedOperationException, Void, boolean, byte, char, double, float, \
14                    int, long, short, var, void
15  excludeClassesRegexps = (default)^$
16  excludedPackages = (default)
17  
18  
19  */
20  
21  package com.puppycrawl.tools.checkstyle.checks.metrics.classfanoutcomplexity;
22  
23  import static com.google.common.base.Preconditions.checkArgument;
24  import static com.google.common.base.Preconditions.checkNotNull;
25  import static com.google.common.base.Throwables.throwIfUnchecked;
26  
27  import java.io.Serializable;
28  import java.lang.reflect.Constructor;
29  import java.lang.reflect.InvocationTargetException;
30  import java.lang.reflect.Method;
31  import java.lang.reflect.Modifier;
32  import java.lang.reflect.Parameter;
33  import java.util.Collection;
34  import java.util.List;
35  import java.util.Map;
36  import java.util.Set;
37  
38  import javax.annotation.Nullable;
39  
40  import org.junit.Assert;
41  
42  import com.google.common.annotations.VisibleForTesting;
43  import com.google.common.base.Objects;
44  import com.google.common.collect.ArrayListMultimap;
45  import com.google.common.collect.ImmutableList;
46  import com.google.common.collect.ListMultimap;
47  import com.google.common.collect.Lists;
48  import com.google.common.collect.MutableClassToInstanceMap;
49  import com.google.common.collect.Ordering;
50  import com.google.common.collect.Sets;
51  import com.google.common.primitives.Ints;
52  import com.google.common.reflect.Invokable;
53  import com.google.common.reflect.Reflection;
54  import com.google.common.reflect.TypeToken;
55  import com.tngtech.archunit.thirdparty.com.google.common.annotations.GwtIncompatible;
56  import junit.framework.AssertionFailedError;
57  
58  
59  /**
60   * Tester that runs automated sanity tests for any given class. A typical use case is to test static
61   * factory classes like:
62   *
63   * <pre>
64   * interface Book {...}
65   * public class Books {
66   *   public static Book hardcover(String title) {...}
67   *   public static Book paperback(String title) {...}
68   * }
69   * </pre>
70   *
71   * <p>And all the created {@code Book} instances can be tested with:
72   *
73   * <pre>
74   * new InputClassFanOutComplexityRemoveIncorrectAnnotationToken()
75   *     .forAllPublicStaticMethods(Books.class)
76   *     .thatReturn(Book.class)
77   *     .testEquals(); // or testNulls(), testSerializable() etc.
78   * </pre>
79   *
80   * @author Ben Yu
81   * @since 14.0
82   */
83  @MyAnnotation
84  @GwtIncompatible
85  public final class InputClassFanOutComplexityRemoveIncorrectAnnotationToken {
86      private static final Ordering<Invokable<?, ?>> BY_METHOD_NAME =
87              new Ordering<Invokable<?, ?>>() {
88                  @Override
89                  public int compare(Invokable<?, ?> left, Invokable<?, ?> right) {
90                      return left.getName().compareTo(right.getName());
91                  }
92              };
93  
94      private static final Ordering<Invokable<?, ?>> BY_PARAMETERS =
95              new Ordering<Invokable<?, ?>>() {
96                  @Override
97                  public int compare(Invokable<?, ?> left, Invokable<?, ?> right) {
98                      return Ordering.usingToString().compare(left.getParameters(),
99                              right.getParameters());
100                 }
101             };
102 
103     private static final Ordering<Invokable<?, ?>> BY_NUMBER_OF_PARAMETERS =
104             new Ordering<Invokable<?, ?>>() {
105                 @Override
106                 public int compare(Invokable<?, ?> left, Invokable<?, ?> right) {
107                     return Ints.compare(left.getParameters().size(), right.getParameters().size());
108                 }
109             };
110 
111     private final MutableClassToInstanceMap<Object> defaultValues =
112             MutableClassToInstanceMap.create();
113     private final ListMultimap<Class<?>, Object> distinctValues = ArrayListMultimap.create();
114     private final NullPointerTester nullPointerTester = new NullPointerTester();
115 
116     public InputClassFanOutComplexityRemoveIncorrectAnnotationToken() {
117         // TODO(benyu): bake these into ArbitraryInstances.
118         setDefault(byte.class, (byte) 1);
119         setDefault(Byte.class, (byte) 1);
120         setDefault(short.class, (short) 1);
121         setDefault(Short.class, (short) 1);
122         setDefault(int.class, 1);
123         setDefault(Integer.class, 1);
124         setDefault(long.class, 1L);
125         setDefault(Long.class, 1L);
126         setDefault(float.class, 1F);
127         setDefault(Float.class, 1F);
128         setDefault(double.class, 1D);
129         setDefault(Double.class, 1D);
130         setDefault(Class.class, Class.class);
131     }
132 
133     private static boolean hashCodeInsensitiveToArgReference(
134             Invokable<?, ?> factory, List<Object> args, int i, Object alternateArg)
135             throws FactoryMethodReturnsNullException, InvocationTargetException,
136             IllegalAccessException {
137         List<Object> tentativeArgs = Lists.newArrayList(args);
138         tentativeArgs.set(i, alternateArg);
139         return createInstance(factory, tentativeArgs).hashCode()
140                 == createInstance(factory, args).hashCode();
141     }
142 
143     @Nullable
144     private static Object generateDummyArg(Parameter param, FreshValueGenerator generator)
145             throws ParameterNotInstantiableException {
146         if (isNullable(param)) {
147             return null;
148         }
149         Object arg = generator.generateFresh(null);
150         if (arg == null) {
151             throw new ParameterNotInstantiableException(param);
152         }
153         return arg;
154     }
155 
156     private static boolean isNullable(Parameter param) {
157         return true;
158     }
159 
160     private static <X extends Throwable> void throwFirst(List<X> exceptions) throws X {
161         if (!exceptions.isEmpty()) {
162             throw exceptions.get(0);
163         }
164     }
165 
166     /**
167      * Factories with the least number of parameters are listed first.
168      */
169     private static <T> ImmutableList<Invokable<?, ? extends T>> getFactories(TypeToken<T> type) {
170         List<Invokable<?, ? extends T>> factories = Lists.newArrayList();
171         for (Method method : type.getRawType().getDeclaredMethods()) {
172             Invokable<?, ?> invokable = type.method(method);
173             if (!invokable.isPrivate()
174                     && !invokable.isSynthetic()
175                     && invokable.isStatic()
176                     && type.isSupertypeOf(invokable.getReturnType())) {
177                 @SuppressWarnings("unchecked") // guarded by isAssignableFrom()
178                 Invokable<?, ? extends T> factory = (Invokable<?, ? extends T>) invokable;
179                 factories.add(factory);
180             }
181         }
182         if (!Modifier.isAbstract(type.getRawType().getModifiers())) {
183             for (Constructor<?> constructor : type.getRawType().getDeclaredConstructors()) {
184                 Invokable<T, T> invokable = type.constructor(constructor);
185                 if (!invokable.isPrivate() && !invokable.isSynthetic()) {
186                     factories.add(invokable);
187                 }
188             }
189         }
190         for (Invokable<?, ?> factory : factories) {
191             factory.setAccessible(true);
192         }
193         // Sorts methods/constructors with least number of parameters first since it's likely
194         // easier to
195         // fill dummy parameter values for them. Ties are broken by name then by the string
196         // form of the
197         // parameter list.
198         return BY_NUMBER_OF_PARAMETERS
199                 .compound(BY_METHOD_NAME)
200                 .compound(BY_PARAMETERS)
201                 .immutableSortedCopy(factories);
202     }
203 
204     private static <T> T createInstance(Invokable<?, ? extends T> factory, List<?> args)
205             throws FactoryMethodReturnsNullException, InvocationTargetException,
206             IllegalAccessException {
207         T instance = invoke(factory, args);
208         if (instance == null) {
209             throw new FactoryMethodReturnsNullException(factory);
210         }
211         return instance;
212     }
213 
214     private static <T> @Nullable T invoke(Invokable<?, ? extends T> factory, List<?> args)
215             throws InvocationTargetException, IllegalAccessException {
216         T returnValue = factory.invoke(null, args.toArray());
217         if (returnValue == null) {
218             Assert.assertTrue(
219                     factory + " returns null but it's not annotated with @Nullable",
220                     isNullable(null));
221         }
222         return returnValue;
223     }
224 
225     /**
226      * Sets the default value for {@code type}. The default value isn't used in testing {@link
227      * Object#equals} because more than one sample instances are needed for testing inequality.
228      * To set
229      * distinct values for equality testing, use {@link #setDistinctValues} instead.
230      */
231     public <T> InputClassFanOutComplexityRemoveIncorrectAnnotationToken setDefault(Class<T> type,
232                                                                                    T value) {
233         nullPointerTester.setDefault(type, value);
234         defaultValues.putInstance(type, value);
235         return this;
236     }
237 
238     /**
239      * Sets distinct values for {@code type}, so that when a class {@code Foo} is tested for {@link
240      * Object#equals} and {@link Object#hashCode}, and its construction requires a
241      * parameter of {@code
242      * type}, the distinct values of {@code type} can be passed as parameters to create {@code Foo}
243      * instances that are unequal.
244      *
245      * <p>Calling {@code setDistinctValues(type, v1, v2)} also sets the default value for
246      * {@code type}
247      * that's used for {@link #testNulls}.
248      *
249      * <p>Only necessary for types where
250      * {@link InputClassFanOutComplexityRemoveIncorrectAnnotationToken} doesn't
251      * already know how to create
252      * distinct values.
253      *
254      * @return this tester instance
255      * @since 17.0
256      */
257     public <T> InputClassFanOutComplexityRemoveIncorrectAnnotationToken
258     setDistinctValues(Class<T> type, T value1, T value2) {
259         checkNotNull(type);
260         checkNotNull(value1);
261         checkNotNull(value2);
262         checkArgument(!Objects.equal(value1, value2), "Duplicate value provided.");
263         distinctValues.replaceValues(type, ImmutableList.of(value1, value2));
264         setDefault(type, value1);
265         return this;
266     }
267 
268     /**
269      * Tests that {@code cls} properly checks null on all constructor and method parameters that
270      * aren't annotated nullable (according to the rules of {@link NullPointerTester}). In details:
271      *
272      * <ul>
273      *   <li>All non-private static methods are checked such that passing null for any parameter
274      *       that's not annotated nullable should throw {@link NullPointerException}.
275      *   <li>If there is any non-private constructor or non-private static factory method
276      *   declared by
277      *       {@code cls}, all non-private instance methods will be checked too using the instance
278      *       created by invoking the constructor or static factory method.
279      *   <li>If there is any non-private constructor or non-private static factory method
280      *   declared by
281      *       {@code cls}:
282      *       <ul>
283      *         <li>Test will fail if default value for a parameter cannot be determined.
284      *         <li>Test will fail if the factory method returns null so testing instance methods is
285      *             impossible.
286      *         <li>Test will fail if the constructor or factory method throws exception.
287      *       </ul>
288      *   <li>If there is no non-private constructor or non-private static factory method declared by
289      *       {@code cls}, instance methods are skipped for nulls test.
290      *   <li>Nulls test is not performed on method return values unless the method is a non-private
291      *       static factory method whose return type is {@code cls} or {@code cls}'s subtype.
292      * </ul>
293      */
294     public void testNulls(Class<?> cls) {
295         try {
296             doTestNulls(cls, Visibility.PACKAGE_PRIVATE);
297         } catch (Exception e) {
298             throwIfUnchecked(e);
299             throw new RuntimeException(e);
300         }
301     }
302 
303     void doTestNulls(Class<?> cls, Visibility visibility)
304             throws ParameterNotInstantiableException, IllegalAccessException,
305             InvocationTargetException,
306             FactoryMethodReturnsNullException {
307         if (!Modifier.isAbstract(cls.getModifiers())) {
308             nullPointerTester.testConstructors(cls, visibility);
309         }
310         nullPointerTester.testStaticMethods(cls, visibility);
311         if (hasInstanceMethodToTestNulls(cls, visibility)) {
312             Object instance = instantiate(cls);
313             if (instance != null) {
314                 nullPointerTester.testInstanceMethods(instance, visibility);
315             }
316         }
317     }
318 
319     private boolean hasInstanceMethodToTestNulls(Class<?> c, Visibility visibility) {
320         for (Method method : nullPointerTester.getInstanceMethodsToTest(c, visibility)) {
321             for (com.google.common.reflect.Parameter param : Invokable.from(method)
322                     .getParameters()) {
323                 if (!NullPointerTester.isPrimitiveOrNullable(param)) {
324                     return true;
325                 }
326             }
327         }
328         return false;
329     }
330 
331     /**
332      * Tests the {@link Object#equals} and {@link Object#hashCode} of {@code cls}. In details:
333      *
334      * <ul>
335      *   <li>The non-private constructor or non-private static factory method with the most
336      *   parameters
337      *       is used to construct the sample instances. In case of tie, the candidate constructors
338      *       or
339      *       factories are tried one after another until one can be used to construct sample
340      *       instances.
341      *   <li>For the constructor or static factory method used to construct instances, it's checked
342      *       that when equal parameters are passed, the result instance should also be equal; and
343      *       vice
344      *       versa.
345      *   <li>If a non-private constructor or non-private static factory method exists:
346      *       <ul>
347      *         <li>Test will fail if default value for a parameter cannot be determined.
348      *         <li>Test will fail if the factory method returns null so testing instance methods is
349      *             impossible.
350      *         <li>Test will fail if the constructor or factory method throws exception.
351      *       </ul>
352      *   <li>If there is no non-private constructor or non-private static factory method declared by
353      *       {@code cls}, no test is performed.
354      *   <li>Equality test is not performed on method return values unless the method is a
355      *   non-private
356      *       static factory method whose return type is {@code cls} or {@code cls}'s subtype.
357      *   <li>Inequality check is not performed against state mutation methods such as {@link
358      *       List#add}, or functional update methods such as {@link
359      *       com.google.common.base.Joiner#skipNulls}.
360      * </ul>
361      *
362      * <p>Note that constructors taking a builder object cannot be tested effectively because
363      * semantics of builder can be arbitrarily complex. Still, a factory class can be created in the
364      * test to facilitate equality testing. For example:
365      *
366      * <pre>
367      * public class FooTest {
368      *
369      *   private static class FooFactoryForTest {
370      *     public static Foo create(String a, String b, int c, boolean d) {
371      *       return Foo.builder()
372      *           .setA(a)
373      *           .setB(b)
374      *           .setC(c)
375      *           .setD(d)
376      *           .build();
377      *     }
378      *   }
379      *
380      *   public void testEquals() {
381      *     new InputClassFanOutComplexityRemoveIncorrectAnnotationToken()
382      *       .forAllPublicStaticMethods(FooFactoryForTest.class)
383      *       .thatReturn(Foo.class)
384      *       .testEquals();
385      *   }
386      * }
387      * </pre>
388      *
389      * <p>It will test that Foo objects created by the {@code create(a, b, c, d)} factory
390      * method with
391      * equal parameters are equal and vice versa, thus indirectly tests the builder equality.
392      */
393     public void testEquals(Class<?> cls) {
394         try {
395             doTestEquals(cls);
396         } catch (Exception e) {
397             throwIfUnchecked(e);
398             throw new RuntimeException(e);
399         }
400     }
401 
402     void doTestEquals(Class<?> cls)
403             throws ParameterNotInstantiableException, ParameterHasNoDistinctValueException,
404             IllegalAccessException, InvocationTargetException, FactoryMethodReturnsNullException {
405         if (cls.isEnum()) {
406             return;
407         }
408         List<? extends Invokable<?, ?>> factories = Lists.reverse(getFactories(TypeToken.of(cls)));
409         if (factories.isEmpty()) {
410             return;
411         }
412         int numberOfParameters = factories.get(0).getParameters().size();
413         List<ParameterNotInstantiableException> paramErrors = Lists.newArrayList();
414         List<ParameterHasNoDistinctValueException> distinctValueErrors = Lists.newArrayList();
415         List<InvocationTargetException> instantiationExceptions = Lists.newArrayList();
416         List<FactoryMethodReturnsNullException> nullErrors = Lists.newArrayList();
417         // Try factories with the greatest number of parameters.
418         for (Invokable<?, ?> factory : factories) {
419             if (factory.getParameters().size() == numberOfParameters) {
420                 try {
421                     testEqualsUsing(factory);
422                     return;
423                 } catch (ParameterNotInstantiableException e) {
424                     paramErrors.add(e);
425                 } catch (ParameterHasNoDistinctValueException e) {
426                     distinctValueErrors.add(e);
427                 } catch (InvocationTargetException e) {
428                     instantiationExceptions.add(e);
429                 } catch (FactoryMethodReturnsNullException e) {
430                     nullErrors.add(e);
431                 }
432             }
433         }
434         throwFirst(paramErrors);
435         throwFirst(distinctValueErrors);
436         throwFirst(instantiationExceptions);
437         throwFirst(nullErrors);
438     }
439 
440     /**
441      * Instantiates {@code cls} by invoking one of its non-private constructors or non-private
442      * static
443      * factory methods with the parameters automatically provided using dummy values.
444      *
445      * @return The instantiated instance, or {@code null} if the class has no non-private
446      * constructor
447      * or factory method to be constructed.
448      */
449     <T> @Nullable T instantiate(Class<T> cls)
450             throws ParameterNotInstantiableException, IllegalAccessException,
451             InvocationTargetException,
452             FactoryMethodReturnsNullException {
453         if (cls.isEnum()) {
454             T[] constants = cls.getEnumConstants();
455             if (constants.length > 0) {
456                 return constants[0];
457             }
458             else {
459                 return null;
460             }
461         }
462         TypeToken<T> type = TypeToken.of(cls);
463         List<ParameterNotInstantiableException> paramErrors = Lists.newArrayList();
464         List<InvocationTargetException> instantiationExceptions = Lists.newArrayList();
465         List<FactoryMethodReturnsNullException> nullErrors = Lists.newArrayList();
466         for (Invokable<?, ? extends T> factory : getFactories(type)) {
467             T instance;
468             try {
469                 instance = instantiate(factory);
470             } catch (ParameterNotInstantiableException e) {
471                 paramErrors.add(e);
472                 continue;
473             } catch (InvocationTargetException e) {
474                 instantiationExceptions.add(e);
475                 continue;
476             }
477             if (instance == null) {
478                 nullErrors.add(new FactoryMethodReturnsNullException(factory));
479             }
480             else {
481                 return instance;
482             }
483         }
484         throwFirst(paramErrors);
485         throwFirst(instantiationExceptions);
486         throwFirst(nullErrors);
487         return null;
488     }
489 
490     /**
491      * Instantiates using {@code factory}. If {@code factory} is annotated nullable and
492      * returns null,
493      * null will be returned.
494      *
495      * @throws ParameterNotInstantiableException if the static methods cannot be invoked because the
496      *                                           default value of a parameter cannot be determined.
497      * @throws IllegalAccessException            if the class isn't public or is nested inside a
498      * non-public
499      *                                           class, preventing its methods from being
500      *                                           accessible.
501      * @throws InvocationTargetException         if a static method threw exception.
502      */
503     private <T> @Nullable T instantiate(Invokable<?, ? extends T> factory)
504             throws ParameterNotInstantiableException, InvocationTargetException,
505             IllegalAccessException {
506         return invoke(factory, getDummyArguments(factory));
507     }
508 
509     /**
510      * Returns an object responsible for performing sanity tests against the return values of all
511      * public static methods declared by {@code cls}, excluding superclasses.
512      */
513     public FactoryMethodReturnValueTester forAllPublicStaticMethods(Class<?> cls) {
514         ImmutableList.Builder<Invokable<?, ?>> builder = ImmutableList.builder();
515         for (Method method : cls.getDeclaredMethods()) {
516             Invokable<?, ?> invokable = Invokable.from(method);
517             invokable.setAccessible(true);
518             if (invokable.isPublic() && invokable.isStatic() && !invokable.isSynthetic()) {
519                 builder.add(invokable);
520             }
521         }
522         return new FactoryMethodReturnValueTester(cls, builder.build(), "public static methods");
523     }
524 
525     private void testEqualsUsing(final Invokable<?, ?> factory)
526             throws ParameterNotInstantiableException, ParameterHasNoDistinctValueException,
527             IllegalAccessException, InvocationTargetException, FactoryMethodReturnsNullException {
528         ImmutableList<com.google.common.reflect.Parameter> params = factory.getParameters();
529         List<FreshValueGenerator> argGenerators = Lists.newArrayListWithCapacity(params.size());
530         List<Object> args = Lists.newArrayListWithCapacity(params.size());
531         for (com.google.common.reflect.Parameter param : params) {
532             FreshValueGenerator generator = newFreshValueGenerator();
533             argGenerators.add(generator);
534             args.add(generateDummyArg(null, generator));
535         }
536         Object instance = createInstance(factory, args);
537         List<Object> equalArgs = generateEqualFactoryArguments(factory, null, args);
538         // Each group is a List of items, each item has a list of factory args.
539         final List<List<List<Object>>> argGroups = Lists.newArrayList();
540         argGroups.add(ImmutableList.of(args, equalArgs));
541         EqualsTester tester =
542                 new EqualsTester();
543         tester.addEqualityGroup(instance, createInstance(factory, equalArgs));
544         for (int i = 0; i < params.size(); i++) {
545             List<Object> newArgs = Lists.newArrayList(args);
546             Object newArg = argGenerators.get(i).generateFresh(params.get(i).getType());
547 
548             if (newArg == null || Objects.equal(args.get(i), newArg)) {
549                 if (params.get(i).getType().getRawType().isEnum()) {
550                     continue; // Nothing better we can do if it's single-value enum
551                 }
552                 throw new ParameterHasNoDistinctValueException(null);
553             }
554             newArgs.set(i, newArg);
555             tester.addEqualityGroup(createInstance(factory, newArgs));
556             argGroups.add(ImmutableList.of(newArgs));
557         }
558         tester.testEquals();
559     }
560 
561     /**
562      * Returns dummy factory arguments that are equal to {@code args} but may be different
563      * instances,
564      * to be used to construct a second instance of the same equality group.
565      */
566     private List<Object> generateEqualFactoryArguments(
567             Invokable<?, ?> factory, List<Parameter> params, List<Object> args)
568             throws ParameterNotInstantiableException, FactoryMethodReturnsNullException,
569             InvocationTargetException, IllegalAccessException {
570         List<Object> equalArgs = Lists.newArrayList(args);
571         for (int i = 0; i < args.size(); i++) {
572             Parameter param = params.get(i);
573             Object arg = args.get(i);
574             // Use new fresh value generator because 'args' were populated with new fresh generator
575             // each.
576             // Two newFreshValueGenerator() instances should normally generate equal value sequence.
577             Object shouldBeEqualArg = generateDummyArg(param, newFreshValueGenerator());
578             if (arg != shouldBeEqualArg
579                     && Objects.equal(arg, shouldBeEqualArg)
580                     && hashCodeInsensitiveToArgReference(factory, args, i, shouldBeEqualArg)
581                     && hashCodeInsensitiveToArgReference(
582                     factory, args, i, generateDummyArg(param, newFreshValueGenerator()))) {
583                 // If the implementation uses identityHashCode(), referential equality is
584                 // probably intended. So no point in using an equal-but-different factory argument.
585                 // We check twice to avoid confusion caused by accidental hash collision.
586                 equalArgs.set(i, shouldBeEqualArg);
587             }
588         }
589         return equalArgs;
590     }
591 
592     // distinctValues is a type-safe class-values mapping, but we don't have a type-safe data
593     // structure to hold the mappings.
594     @SuppressWarnings({"unchecked", "rawtypes"})
595     private FreshValueGenerator newFreshValueGenerator() {
596         FreshValueGenerator generator =
597                 new FreshValueGenerator() {
598                     Object interfaceMethodCalled(Class<?> interfaceType, Method method) {
599                         return getDummyValue(TypeToken.of(interfaceType).method(method)
600                                 .getReturnType());
601                     }
602                 };
603         for (Map.Entry<Class<?>, Collection<Object>> entry : distinctValues.asMap().entrySet()) {
604             generator.addSampleInstances(entry.getKey(), entry.getValue());
605         }
606         return generator;
607     }
608 
609     private List<Object> getDummyArguments(Invokable<?, ?> invokable)
610             throws ParameterNotInstantiableException {
611         List<Object> args = Lists.newArrayList();
612         for (com.google.common.reflect.Parameter param : invokable.getParameters()) {
613             if (isNullable(null)) {
614                 args.add(null);
615                 continue;
616             }
617             Object defaultValue = getDummyValue(param.getType());
618             if (defaultValue == null) {
619                 throw new ParameterNotInstantiableException(null);
620             }
621             args.add(defaultValue);
622         }
623         return args;
624     }
625 
626     private <T> T getDummyValue(TypeToken<T> type) {
627         Class<? super T> rawType = type.getRawType();
628         @SuppressWarnings("unchecked") // Assume all default values are generics safe.
629         T defaultValue = (T) defaultValues.getInstance(rawType);
630         if (defaultValue != null) {
631             return defaultValue;
632         }
633         @SuppressWarnings("unchecked") // ArbitraryInstances always returns generics-safe dummies.
634         T value = (T) ArbitraryInstances.get(rawType);
635         if (value != null) {
636             return value;
637         }
638         if (rawType.isInterface()) {
639             return new SerializableDummyProxy(this).newProxy(type);
640         }
641         return null;
642     }
643 
644     /**
645      * Thrown if the test tries to invoke a constructor or static factory method but failed because
646      * the dummy value of a constructor or method parameter is unknown.
647      */
648     @VisibleForTesting
649     static class ParameterNotInstantiableException extends Exception {
650         public ParameterNotInstantiableException(Parameter parameter) {
651             super(
652                     "Cannot determine value for parameter "
653                             + parameter
654                             + " of "
655                             + parameter.getName());
656         }
657     }
658 
659     /**
660      * Thrown if the test fails to generate two distinct non-null values of a constructor or factory
661      * parameter in order to test {@link Object#equals} and {@link Object#hashCode} of the declaring
662      * class.
663      */
664     @VisibleForTesting
665     static class ParameterHasNoDistinctValueException extends Exception {
666         ParameterHasNoDistinctValueException(Parameter parameter) {
667             super(
668                     "Cannot generate distinct value for parameter "
669                             + parameter
670                             + " of "
671                             + parameter);
672         }
673     }
674 
675     /**
676      * Thrown if the test tries to invoke a static factory method to test instance methods but the
677      * factory returned null.
678      */
679     @VisibleForTesting
680     static class FactoryMethodReturnsNullException extends Exception {
681         public FactoryMethodReturnsNullException(Invokable<?, ?> factory) {
682             super(factory + " returns null and cannot be used to test instance methods.");
683         }
684     }
685 
686     static class NullPointerTester {
687 
688         public static boolean isPrimitiveOrNullable(com.google.common.reflect.Parameter param) {
689             return true;
690         }
691 
692         public <T> void setDefault(Class<T> type, T value) {
693         }
694 
695         public void testConstructors(Class<?> cls, Visibility visibility) {
696         }
697 
698         public void testStaticMethods(Class<?> cls, Visibility visibility) {
699         }
700 
701         public void testInstanceMethods(Object instance, Visibility visibility) {
702         }
703 
704         public Method[] getInstanceMethodsToTest(Class<?> c, Visibility visibility) {
705             return null;
706         }
707 
708         public void testAllPublicInstanceMethods(Object instance) {
709         }
710     }
711 
712     static class SerializableTester {
713         public static void reserialize(Object instance) {
714         }
715 
716         public static void reserializeAndAssert(Object instance) {
717         }
718     }
719 
720     static class ArbitraryInstances {
721         public static <T> Object get(Class<? super T> rawType) {
722             return null;
723         }
724     }
725 
726     /**
727      * Runs sanity tests against return values of static factory methods declared by a class.
728      */
729     public final class FactoryMethodReturnValueTester {
730         private final Set<String> packagesToTest = Sets.newHashSet();
731         private final Class<?> declaringClass;
732         private final ImmutableList<Invokable<?, ?>> factories;
733         private final String factoryMethodsDescription;
734         private Class<?> returnTypeToTest = Object.class;
735 
736         private FactoryMethodReturnValueTester(
737                 Class<?> declaringClass,
738                 ImmutableList<Invokable<?, ?>> factories,
739                 String factoryMethodsDescription) {
740             this.declaringClass = declaringClass;
741             this.factories = factories;
742             this.factoryMethodsDescription = factoryMethodsDescription;
743             packagesToTest.add(Reflection.getPackageName(declaringClass));
744         }
745 
746         /**
747          * Specifies that only the methods that are declared to return {@code returnType} or its
748          * subtype
749          * are tested.
750          *
751          * @return this tester object
752          */
753         public FactoryMethodReturnValueTester thatReturn(Class<?> returnType) {
754             returnTypeToTest = returnType;
755             return this;
756         }
757 
758         /**
759          * Tests null checks against the instance methods of the return values, if any.
760          *
761          * <p>Test fails if default value cannot be determined for a constructor or factory
762          * method
763          * parameter, or if the constructor or factory method throws exception.
764          *
765          * @return this tester
766          */
767         public FactoryMethodReturnValueTester testNulls() throws Exception {
768             for (Invokable<?, ?> factory : getFactoriesToTest()) {
769                 Object instance = instantiate(factory);
770                 if (instance != null
771                         && packagesToTest.contains(Reflection
772                         .getPackageName(instance.getClass()))) {
773                     try {
774                         nullPointerTester.testAllPublicInstanceMethods(instance);
775                     } catch (AssertionError e) {
776                         AssertionError error =
777                                 new AssertionFailedError("Null check failed on return value of "
778                                         + factory);
779                         error.initCause(e);
780                         throw error;
781                     }
782                 }
783             }
784             return this;
785         }
786 
787         /**
788          * Tests {@link Object#equals} and {@link Object#hashCode} against the return values of the
789          * static methods, by asserting that when equal parameters are passed to the same static
790          * method,
791          * the return value should also be equal; and vice versa.
792          *
793          * <p>Test fails if default value cannot be determined for a constructor or factory method
794          * parameter, or if the constructor or factory method throws exception.
795          *
796          * @return this tester
797          */
798         public FactoryMethodReturnValueTester testEquals() throws Exception {
799             for (Invokable<?, ?> factory : getFactoriesToTest()) {
800                 try {
801                     testEqualsUsing(factory);
802                 } catch (FactoryMethodReturnsNullException e) {
803                     // If the factory returns null, we just skip it.
804                 }
805             }
806             return this;
807         }
808 
809         /**
810          * Runs serialization test on the return values of the static methods.
811          *
812          * <p>Test fails if default value cannot be determined for a constructor or factory method
813          * parameter, or if the constructor or factory method throws exception.
814          *
815          * @return this tester
816          */
817         public FactoryMethodReturnValueTester testSerializable() throws Exception {
818             for (Invokable<?, ?> factory : getFactoriesToTest()) {
819                 Object instance = instantiate(factory);
820                 if (instance != null) {
821                     try {
822                         SerializableTester.reserialize(instance);
823                     } catch (RuntimeException e) {
824                         AssertionError error =
825                                 new AssertionFailedError("Serialization failed " +
826                                         "on return value of " + factory);
827                         error.initCause(e.getCause());
828                         throw error;
829                     }
830                 }
831             }
832             return this;
833         }
834 
835         /**
836          * Runs equals and serialization test on the return values.
837          *
838          * <p>Test fails if default value cannot be determined for a constructor or factory method
839          * parameter, or if the constructor or factory method throws exception.
840          *
841          * @return this tester
842          */
843         public FactoryMethodReturnValueTester testEqualsAndSerializable() throws Exception {
844             for (Invokable<?, ?> factory : getFactoriesToTest()) {
845                 try {
846                     testEqualsUsing(factory);
847                 } catch (FactoryMethodReturnsNullException e) {
848                     // If the factory returns null, we just skip it.
849                 }
850                 Object instance = instantiate(factory);
851                 if (instance != null) {
852                     try {
853                         SerializableTester.reserializeAndAssert(instance);
854                     } catch (RuntimeException e) {
855                         AssertionError error =
856                                 new AssertionFailedError("Serialization " +
857                                         "failed on return value of " + factory);
858                         error.initCause(e.getCause());
859                         throw error;
860                     } catch (AssertionFailedError e) {
861                         AssertionError error =
862                                 new AssertionFailedError(
863                                         "Return value of " + factory + " reserialized " +
864                                                 "to an unequal value");
865                         error.initCause(e);
866                         throw error;
867                     }
868                 }
869             }
870             return this;
871         }
872 
873         private ImmutableList<Invokable<?, ?>> getFactoriesToTest() {
874             ImmutableList.Builder<Invokable<?, ?>> builder = ImmutableList.builder();
875             for (Invokable<?, ?> factory : factories) {
876                 if (returnTypeToTest.isAssignableFrom(factory.getReturnType().getRawType())) {
877                     builder.add(factory);
878                 }
879             }
880             ImmutableList<Invokable<?, ?>> factoriesToTest = builder.build();
881             Assert.assertFalse(
882                     "No "
883                             + factoryMethodsDescription
884                             + " that return "
885                             + returnTypeToTest.getName()
886                             + " or subtype are found in "
887                             + declaringClass
888                             + ".",
889                     factoriesToTest.isEmpty());
890             return factoriesToTest;
891         }
892     }
893 
894     private final class SerializableDummyProxy extends DummyProxy implements Serializable {
895 
896         private final transient InputClassFanOutComplexityRemoveIncorrectAnnotationToken tester;
897 
898         SerializableDummyProxy(InputClassFanOutComplexityRemoveIncorrectAnnotationToken tester) {
899             this.tester = new InputClassFanOutComplexityRemoveIncorrectAnnotationToken();
900         }
901 
902         <R> R dummyReturnValue(TypeToken<R> returnType) {
903             return tester.getDummyValue(returnType);
904         }
905 
906         @Override
907         public boolean equals(Object obj) {
908             return obj instanceof SerializableDummyProxy;
909         }
910 
911         @Override
912         public int hashCode() {
913             return 0;
914         }
915 
916         public <T> T newProxy(TypeToken<T> type) {
917             return null;
918         }
919     }
920 
921     class FreshValueGenerator {
922         public Object generateFresh(TypeToken<?> type) {
923             return null;
924         }
925 
926         public void addSampleInstances(Class key, Collection<Object> value) {
927         }
928     }
929 
930     class DummyProxy {
931     }
932 
933     class EqualsTester {
934         public void addEqualityGroup(Object instance, Object instance1) {
935         }
936 
937         public <T> void addEqualityGroup(T instance) {
938         }
939 
940         public void testEquals() {
941         }
942     }
943 
944     class ItemReporter {
945     }
946 
947     interface Visibility {
948 
949         Visibility PACKAGE_PRIVATE = null;
950 
951     }
952 
953 }
954