• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.testing;
18 
19 import static com.google.common.base.Preconditions.checkArgument;
20 
21 import com.google.common.annotations.GwtIncompatible;
22 import com.google.common.base.CharMatcher;
23 import com.google.common.base.Charsets;
24 import com.google.common.base.Defaults;
25 import com.google.common.base.Equivalence;
26 import com.google.common.base.Joiner;
27 import com.google.common.base.Predicate;
28 import com.google.common.base.Predicates;
29 import com.google.common.base.Splitter;
30 import com.google.common.base.Stopwatch;
31 import com.google.common.base.Ticker;
32 import com.google.common.collect.BiMap;
33 import com.google.common.collect.ClassToInstanceMap;
34 import com.google.common.collect.ImmutableBiMap;
35 import com.google.common.collect.ImmutableClassToInstanceMap;
36 import com.google.common.collect.ImmutableCollection;
37 import com.google.common.collect.ImmutableList;
38 import com.google.common.collect.ImmutableListMultimap;
39 import com.google.common.collect.ImmutableMap;
40 import com.google.common.collect.ImmutableMultimap;
41 import com.google.common.collect.ImmutableMultiset;
42 import com.google.common.collect.ImmutableSet;
43 import com.google.common.collect.ImmutableSetMultimap;
44 import com.google.common.collect.ImmutableSortedMap;
45 import com.google.common.collect.ImmutableSortedMultiset;
46 import com.google.common.collect.ImmutableSortedSet;
47 import com.google.common.collect.ImmutableTable;
48 import com.google.common.collect.Iterators;
49 import com.google.common.collect.ListMultimap;
50 import com.google.common.collect.MapDifference;
51 import com.google.common.collect.Maps;
52 import com.google.common.collect.Multimap;
53 import com.google.common.collect.Multimaps;
54 import com.google.common.collect.Multiset;
55 import com.google.common.collect.Ordering;
56 import com.google.common.collect.PeekingIterator;
57 import com.google.common.collect.Range;
58 import com.google.common.collect.RowSortedTable;
59 import com.google.common.collect.SetMultimap;
60 import com.google.common.collect.Sets;
61 import com.google.common.collect.SortedMapDifference;
62 import com.google.common.collect.SortedMultiset;
63 import com.google.common.collect.SortedSetMultimap;
64 import com.google.common.collect.Table;
65 import com.google.common.collect.Tables;
66 import com.google.common.collect.TreeBasedTable;
67 import com.google.common.collect.TreeMultimap;
68 import com.google.common.io.ByteSink;
69 import com.google.common.io.ByteSource;
70 import com.google.common.io.ByteStreams;
71 import com.google.common.io.CharSink;
72 import com.google.common.io.CharSource;
73 import com.google.common.primitives.Primitives;
74 import com.google.common.primitives.UnsignedInteger;
75 import com.google.common.primitives.UnsignedLong;
76 import com.google.errorprone.annotations.Keep;
77 import java.io.ByteArrayInputStream;
78 import java.io.ByteArrayOutputStream;
79 import java.io.File;
80 import java.io.InputStream;
81 import java.io.OutputStream;
82 import java.io.PrintStream;
83 import java.io.PrintWriter;
84 import java.io.Reader;
85 import java.io.Serializable;
86 import java.io.StringReader;
87 import java.io.StringWriter;
88 import java.io.Writer;
89 import java.lang.reflect.AnnotatedElement;
90 import java.lang.reflect.Array;
91 import java.lang.reflect.Constructor;
92 import java.lang.reflect.Field;
93 import java.lang.reflect.GenericDeclaration;
94 import java.lang.reflect.InvocationTargetException;
95 import java.lang.reflect.Modifier;
96 import java.lang.reflect.Type;
97 import java.math.BigDecimal;
98 import java.math.BigInteger;
99 import java.nio.Buffer;
100 import java.nio.ByteBuffer;
101 import java.nio.CharBuffer;
102 import java.nio.DoubleBuffer;
103 import java.nio.FloatBuffer;
104 import java.nio.IntBuffer;
105 import java.nio.LongBuffer;
106 import java.nio.ShortBuffer;
107 import java.nio.charset.Charset;
108 import java.util.ArrayDeque;
109 import java.util.Arrays;
110 import java.util.Collection;
111 import java.util.Comparator;
112 import java.util.Currency;
113 import java.util.Deque;
114 import java.util.Iterator;
115 import java.util.List;
116 import java.util.ListIterator;
117 import java.util.Locale;
118 import java.util.Map;
119 import java.util.NavigableMap;
120 import java.util.NavigableSet;
121 import java.util.Queue;
122 import java.util.Random;
123 import java.util.Set;
124 import java.util.SortedMap;
125 import java.util.SortedSet;
126 import java.util.UUID;
127 import java.util.concurrent.BlockingDeque;
128 import java.util.concurrent.BlockingQueue;
129 import java.util.concurrent.ConcurrentHashMap;
130 import java.util.concurrent.ConcurrentMap;
131 import java.util.concurrent.ConcurrentNavigableMap;
132 import java.util.concurrent.ConcurrentSkipListMap;
133 import java.util.concurrent.CountDownLatch;
134 import java.util.concurrent.Executor;
135 import java.util.concurrent.LinkedBlockingDeque;
136 import java.util.concurrent.ScheduledThreadPoolExecutor;
137 import java.util.concurrent.ThreadFactory;
138 import java.util.concurrent.ThreadPoolExecutor;
139 import java.util.concurrent.TimeUnit;
140 import java.util.logging.Level;
141 import java.util.logging.Logger;
142 import java.util.regex.MatchResult;
143 import java.util.regex.Matcher;
144 import java.util.regex.Pattern;
145 import javax.annotation.CheckForNull;
146 
147 /**
148  * Supplies an arbitrary "default" instance for a wide range of types, often useful in testing
149  * utilities.
150  *
151  * <p>Covers arrays, enums and common types defined in {@code java.lang}, {@code java.lang.reflect},
152  * {@code java.io}, {@code java.nio}, {@code java.math}, {@code java.util}, {@code
153  * java.util.concurrent}, {@code java.util.regex}, {@code com.google.common.base}, {@code
154  * com.google.common.collect} and {@code com.google.common.primitives}. In addition, if the type
155  * exposes at least one public static final constant of the same type, one of the constants will be
156  * used; or if the class exposes a public parameter-less constructor then it will be "new"d and
157  * returned.
158  *
159  * <p>All default instances returned by {@link #get} are generics-safe. Clients won't get type
160  * errors for using {@code get(Comparator.class)} as a {@code Comparator<Foo>}, for example.
161  * Immutable empty instances are returned for collection types; {@code ""} for string; {@code 0} for
162  * number types; reasonable default instance for other stateless types. For mutable types, a fresh
163  * instance is created each time {@code get()} is called.
164  *
165  * @author Kevin Bourrillion
166  * @author Ben Yu
167  * @since 12.0
168  */
169 @GwtIncompatible
170 public final class ArbitraryInstances {
171 
172   private static final Ordering<Field> BY_FIELD_NAME =
173       new Ordering<Field>() {
174         @Override
175         public int compare(Field left, Field right) {
176           return left.getName().compareTo(right.getName());
177         }
178       };
179 
180   /**
181    * Returns a new {@code MatchResult} that corresponds to a successful match. Apache Harmony (used
182    * in Android) requires a successful match in order to generate a {@code MatchResult}:
183    * http://goo.gl/5VQFmC
184    */
newMatchResult()185   private static MatchResult newMatchResult() {
186     Matcher matcher = Pattern.compile(".").matcher("X");
187     matcher.find();
188     return matcher.toMatchResult();
189   }
190 
191   private static final ClassToInstanceMap<Object> DEFAULTS =
192       ImmutableClassToInstanceMap.builder()
193           // primitives
194           .put(Object.class, "")
195           .put(Number.class, 0)
196           .put(UnsignedInteger.class, UnsignedInteger.ZERO)
197           .put(UnsignedLong.class, UnsignedLong.ZERO)
198           .put(BigInteger.class, BigInteger.ZERO)
199           .put(BigDecimal.class, BigDecimal.ZERO)
200           .put(CharSequence.class, "")
201           .put(String.class, "")
202           .put(Pattern.class, Pattern.compile(""))
203           .put(MatchResult.class, newMatchResult())
204           .put(TimeUnit.class, TimeUnit.SECONDS)
205           .put(Charset.class, Charsets.UTF_8)
206           .put(Currency.class, Currency.getInstance(Locale.US))
207           .put(Locale.class, Locale.US)
208           .put(UUID.class, UUID.randomUUID())
209           // common.base
210           .put(CharMatcher.class, CharMatcher.none())
211           .put(Joiner.class, Joiner.on(','))
212           .put(Splitter.class, Splitter.on(','))
213           .put(com.google.common.base.Optional.class, com.google.common.base.Optional.absent())
214           .put(Predicate.class, Predicates.alwaysTrue())
215           .put(Equivalence.class, Equivalence.equals())
216           .put(Ticker.class, Ticker.systemTicker())
217           .put(Stopwatch.class, Stopwatch.createUnstarted())
218           // io types
219           .put(InputStream.class, new ByteArrayInputStream(new byte[0]))
220           .put(ByteArrayInputStream.class, new ByteArrayInputStream(new byte[0]))
221           .put(Readable.class, new StringReader(""))
222           .put(Reader.class, new StringReader(""))
223           .put(StringReader.class, new StringReader(""))
224           .put(Buffer.class, ByteBuffer.allocate(0))
225           .put(CharBuffer.class, CharBuffer.allocate(0))
226           .put(ByteBuffer.class, ByteBuffer.allocate(0))
227           .put(ShortBuffer.class, ShortBuffer.allocate(0))
228           .put(IntBuffer.class, IntBuffer.allocate(0))
229           .put(LongBuffer.class, LongBuffer.allocate(0))
230           .put(FloatBuffer.class, FloatBuffer.allocate(0))
231           .put(DoubleBuffer.class, DoubleBuffer.allocate(0))
232           .put(File.class, new File(""))
233           .put(ByteSource.class, ByteSource.empty())
234           .put(CharSource.class, CharSource.empty())
235           .put(ByteSink.class, NullByteSink.INSTANCE)
236           .put(CharSink.class, NullByteSink.INSTANCE.asCharSink(Charsets.UTF_8))
237           // All collections are immutable empty. So safe for any type parameter.
238           .put(Iterator.class, ImmutableSet.of().iterator())
239           .put(PeekingIterator.class, Iterators.peekingIterator(ImmutableSet.of().iterator()))
240           .put(ListIterator.class, ImmutableList.of().listIterator())
241           .put(Iterable.class, ImmutableSet.of())
242           .put(Collection.class, ImmutableList.of())
243           .put(ImmutableCollection.class, ImmutableList.of())
244           .put(List.class, ImmutableList.of())
245           .put(ImmutableList.class, ImmutableList.of())
246           .put(Set.class, ImmutableSet.of())
247           .put(ImmutableSet.class, ImmutableSet.of())
248           .put(SortedSet.class, ImmutableSortedSet.of())
249           .put(ImmutableSortedSet.class, ImmutableSortedSet.of())
250           .put(NavigableSet.class, Sets.unmodifiableNavigableSet(Sets.newTreeSet()))
251           .put(Map.class, ImmutableMap.of())
252           .put(ImmutableMap.class, ImmutableMap.of())
253           .put(SortedMap.class, ImmutableSortedMap.of())
254           .put(ImmutableSortedMap.class, ImmutableSortedMap.of())
255           .put(NavigableMap.class, Maps.unmodifiableNavigableMap(Maps.newTreeMap()))
256           .put(Multimap.class, ImmutableMultimap.of())
257           .put(ImmutableMultimap.class, ImmutableMultimap.of())
258           .put(ListMultimap.class, ImmutableListMultimap.of())
259           .put(ImmutableListMultimap.class, ImmutableListMultimap.of())
260           .put(SetMultimap.class, ImmutableSetMultimap.of())
261           .put(ImmutableSetMultimap.class, ImmutableSetMultimap.of())
262           .put(
263               SortedSetMultimap.class,
264               Multimaps.unmodifiableSortedSetMultimap(TreeMultimap.create()))
265           .put(Multiset.class, ImmutableMultiset.of())
266           .put(ImmutableMultiset.class, ImmutableMultiset.of())
267           .put(SortedMultiset.class, ImmutableSortedMultiset.of())
268           .put(ImmutableSortedMultiset.class, ImmutableSortedMultiset.of())
269           .put(BiMap.class, ImmutableBiMap.of())
270           .put(ImmutableBiMap.class, ImmutableBiMap.of())
271           .put(Table.class, ImmutableTable.of())
272           .put(ImmutableTable.class, ImmutableTable.of())
273           .put(RowSortedTable.class, Tables.unmodifiableRowSortedTable(TreeBasedTable.create()))
274           .put(ClassToInstanceMap.class, ImmutableClassToInstanceMap.builder().build())
275           .put(ImmutableClassToInstanceMap.class, ImmutableClassToInstanceMap.builder().build())
276           .put(Comparable.class, ByToString.INSTANCE)
277           .put(Comparator.class, AlwaysEqual.INSTANCE)
278           .put(Ordering.class, AlwaysEqual.INSTANCE)
279           .put(Range.class, Range.all())
280           .put(MapDifference.class, Maps.difference(ImmutableMap.of(), ImmutableMap.of()))
281           .put(
282               SortedMapDifference.class,
283               Maps.difference(ImmutableSortedMap.of(), ImmutableSortedMap.of()))
284           // reflect
285           .put(AnnotatedElement.class, Object.class)
286           .put(GenericDeclaration.class, Object.class)
287           .put(Type.class, Object.class)
288           .build();
289 
290   /**
291    * type → implementation. Inherently mutable interfaces and abstract classes are mapped to their
292    * default implementations and are "new"d upon get().
293    */
294   private static final ConcurrentMap<Class<?>, Class<?>> implementations = Maps.newConcurrentMap();
295 
setImplementation(Class<T> type, Class<? extends T> implementation)296   private static <T> void setImplementation(Class<T> type, Class<? extends T> implementation) {
297     checkArgument(type != implementation, "Don't register %s to itself!", type);
298     checkArgument(
299         !DEFAULTS.containsKey(type), "A default value was already registered for %s", type);
300     checkArgument(
301         implementations.put(type, implementation) == null,
302         "Implementation for %s was already registered",
303         type);
304   }
305 
306   static {
setImplementation(Appendable.class, StringBuilder.class)307     setImplementation(Appendable.class, StringBuilder.class);
setImplementation(BlockingQueue.class, LinkedBlockingDeque.class)308     setImplementation(BlockingQueue.class, LinkedBlockingDeque.class);
setImplementation(BlockingDeque.class, LinkedBlockingDeque.class)309     setImplementation(BlockingDeque.class, LinkedBlockingDeque.class);
setImplementation(ConcurrentMap.class, ConcurrentHashMap.class)310     setImplementation(ConcurrentMap.class, ConcurrentHashMap.class);
setImplementation(ConcurrentNavigableMap.class, ConcurrentSkipListMap.class)311     setImplementation(ConcurrentNavigableMap.class, ConcurrentSkipListMap.class);
setImplementation(CountDownLatch.class, Dummies.DummyCountDownLatch.class)312     setImplementation(CountDownLatch.class, Dummies.DummyCountDownLatch.class);
setImplementation(Deque.class, ArrayDeque.class)313     setImplementation(Deque.class, ArrayDeque.class);
setImplementation(OutputStream.class, ByteArrayOutputStream.class)314     setImplementation(OutputStream.class, ByteArrayOutputStream.class);
setImplementation(PrintStream.class, Dummies.InMemoryPrintStream.class)315     setImplementation(PrintStream.class, Dummies.InMemoryPrintStream.class);
setImplementation(PrintWriter.class, Dummies.InMemoryPrintWriter.class)316     setImplementation(PrintWriter.class, Dummies.InMemoryPrintWriter.class);
setImplementation(Queue.class, ArrayDeque.class)317     setImplementation(Queue.class, ArrayDeque.class);
setImplementation(Random.class, Dummies.DeterministicRandom.class)318     setImplementation(Random.class, Dummies.DeterministicRandom.class);
setImplementation( ScheduledThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class)319     setImplementation(
320         ScheduledThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class);
setImplementation(ThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class)321     setImplementation(ThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class);
setImplementation(Writer.class, StringWriter.class)322     setImplementation(Writer.class, StringWriter.class);
setImplementation(Runnable.class, Dummies.DummyRunnable.class)323     setImplementation(Runnable.class, Dummies.DummyRunnable.class);
setImplementation(ThreadFactory.class, Dummies.DummyThreadFactory.class)324     setImplementation(ThreadFactory.class, Dummies.DummyThreadFactory.class);
setImplementation(Executor.class, Dummies.DummyExecutor.class)325     setImplementation(Executor.class, Dummies.DummyExecutor.class);
326   }
327 
328   @SuppressWarnings("unchecked") // it's a subtype map
329   @CheckForNull
getImplementation(Class<T> type)330   private static <T> Class<? extends T> getImplementation(Class<T> type) {
331     return (Class<? extends T>) implementations.get(type);
332   }
333 
334   private static final Logger logger = Logger.getLogger(ArbitraryInstances.class.getName());
335 
336   /**
337    * Returns an arbitrary instance for {@code type}, or {@code null} if no arbitrary instance can be
338    * determined.
339    */
340   @CheckForNull
get(Class<T> type)341   public static <T> T get(Class<T> type) {
342     T defaultValue = DEFAULTS.getInstance(type);
343     if (defaultValue != null) {
344       return defaultValue;
345     }
346     Class<? extends T> implementation = getImplementation(type);
347     if (implementation != null) {
348       return get(implementation);
349     }
350     if (type.isEnum()) {
351       T[] enumConstants = type.getEnumConstants();
352       return (enumConstants.length == 0) ? null : enumConstants[0];
353     }
354     if (type.isArray()) {
355       return createEmptyArray(type);
356     }
357     T jvmDefault = Defaults.defaultValue(Primitives.unwrap(type));
358     if (jvmDefault != null) {
359       return jvmDefault;
360     }
361     if (Modifier.isAbstract(type.getModifiers()) || !Modifier.isPublic(type.getModifiers())) {
362       return arbitraryConstantInstanceOrNull(type);
363     }
364     final Constructor<T> constructor;
365     try {
366       constructor = type.getConstructor();
367     } catch (NoSuchMethodException e) {
368       return arbitraryConstantInstanceOrNull(type);
369     }
370     constructor.setAccessible(true); // accessibility check is too slow
371     try {
372       return constructor.newInstance();
373       /*
374        * Do not merge the 2 catch blocks below. javac would infer a type of
375        * ReflectiveOperationException, which Animal Sniffer would reject. (Old versions of
376        * Android don't *seem* to mind, but there might be edge cases of which we're unaware.)
377        */
378     } catch (InstantiationException impossible) {
379       throw new AssertionError(impossible);
380     } catch (IllegalAccessException impossible) {
381       throw new AssertionError(impossible);
382     } catch (InvocationTargetException e) {
383       logger.log(Level.WARNING, "Exception while invoking default constructor.", e.getCause());
384       return arbitraryConstantInstanceOrNull(type);
385     }
386   }
387 
388   @CheckForNull
arbitraryConstantInstanceOrNull(Class<T> type)389   private static <T> T arbitraryConstantInstanceOrNull(Class<T> type) {
390     Field[] fields = type.getDeclaredFields();
391     Arrays.sort(fields, BY_FIELD_NAME);
392     for (Field field : fields) {
393       if (Modifier.isPublic(field.getModifiers())
394           && Modifier.isStatic(field.getModifiers())
395           && Modifier.isFinal(field.getModifiers())) {
396         if (field.getGenericType() == field.getType() && type.isAssignableFrom(field.getType())) {
397           field.setAccessible(true);
398           try {
399             T constant = type.cast(field.get(null));
400             if (constant != null) {
401               return constant;
402             }
403           } catch (IllegalAccessException impossible) {
404             throw new AssertionError(impossible);
405           }
406         }
407       }
408     }
409     return null;
410   }
411 
createEmptyArray(Class<T> arrayType)412   private static <T> T createEmptyArray(Class<T> arrayType) {
413     return arrayType.cast(Array.newInstance(arrayType.getComponentType(), 0));
414   }
415 
416   // Internal implementations of some classes, with public default constructor that get() needs.
417   private static final class Dummies {
418 
419     public static final class InMemoryPrintStream extends PrintStream {
InMemoryPrintStream()420       public InMemoryPrintStream() {
421         super(new ByteArrayOutputStream());
422       }
423     }
424 
425     public static final class InMemoryPrintWriter extends PrintWriter {
InMemoryPrintWriter()426       public InMemoryPrintWriter() {
427         super(new StringWriter());
428       }
429     }
430 
431     public static final class DeterministicRandom extends Random {
432       @Keep
DeterministicRandom()433       public DeterministicRandom() {
434         super(0);
435       }
436     }
437 
438     public static final class DummyScheduledThreadPoolExecutor extends ScheduledThreadPoolExecutor {
DummyScheduledThreadPoolExecutor()439       public DummyScheduledThreadPoolExecutor() {
440         super(1);
441       }
442     }
443 
444     public static final class DummyCountDownLatch extends CountDownLatch {
DummyCountDownLatch()445       public DummyCountDownLatch() {
446         super(0);
447       }
448     }
449 
450     public static final class DummyRunnable implements Runnable, Serializable {
451       @Override
run()452       public void run() {}
453     }
454 
455     public static final class DummyThreadFactory implements ThreadFactory, Serializable {
456       @Override
newThread(Runnable r)457       public Thread newThread(Runnable r) {
458         return new Thread(r);
459       }
460     }
461 
462     public static final class DummyExecutor implements Executor, Serializable {
463       @Override
execute(Runnable command)464       public void execute(Runnable command) {}
465     }
466   }
467 
468   private static final class NullByteSink extends ByteSink implements Serializable {
469     private static final NullByteSink INSTANCE = new NullByteSink();
470 
471     @Override
openStream()472     public OutputStream openStream() {
473       return ByteStreams.nullOutputStream();
474     }
475   }
476 
477   // Compare by toString() to satisfy 2 properties:
478   // 1. compareTo(null) should throw NullPointerException
479   // 2. the order is deterministic and easy to understand, for debugging purpose.
480   @SuppressWarnings("ComparableType")
481   private static final class ByToString implements Comparable<Object>, Serializable {
482     private static final ByToString INSTANCE = new ByToString();
483 
484     @Override
compareTo(Object o)485     public int compareTo(Object o) {
486       return toString().compareTo(o.toString());
487     }
488 
489     @Override
toString()490     public String toString() {
491       return "BY_TO_STRING";
492     }
493 
readResolve()494     private Object readResolve() {
495       return INSTANCE;
496     }
497   }
498 
499   // Always equal is a valid total ordering. And it works for any Object.
500   private static final class AlwaysEqual extends Ordering<Object> implements Serializable {
501     private static final AlwaysEqual INSTANCE = new AlwaysEqual();
502 
503     @Override
compare(Object o1, Object o2)504     public int compare(Object o1, Object o2) {
505       return 0;
506     }
507 
508     @Override
toString()509     public String toString() {
510       return "ALWAYS_EQUAL";
511     }
512 
readResolve()513     private Object readResolve() {
514       return INSTANCE;
515     }
516   }
517 
ArbitraryInstances()518   private ArbitraryInstances() {}
519 }
520