• 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.Beta;
22 import com.google.common.annotations.GwtIncompatible;
23 import com.google.common.base.CharMatcher;
24 import com.google.common.base.Charsets;
25 import com.google.common.base.Defaults;
26 import com.google.common.base.Equivalence;
27 import com.google.common.base.Joiner;
28 import com.google.common.base.Predicate;
29 import com.google.common.base.Predicates;
30 import com.google.common.base.Splitter;
31 import com.google.common.base.Stopwatch;
32 import com.google.common.base.Ticker;
33 import com.google.common.collect.BiMap;
34 import com.google.common.collect.ClassToInstanceMap;
35 import com.google.common.collect.ImmutableBiMap;
36 import com.google.common.collect.ImmutableClassToInstanceMap;
37 import com.google.common.collect.ImmutableCollection;
38 import com.google.common.collect.ImmutableList;
39 import com.google.common.collect.ImmutableListMultimap;
40 import com.google.common.collect.ImmutableMap;
41 import com.google.common.collect.ImmutableMultimap;
42 import com.google.common.collect.ImmutableMultiset;
43 import com.google.common.collect.ImmutableSet;
44 import com.google.common.collect.ImmutableSetMultimap;
45 import com.google.common.collect.ImmutableSortedMap;
46 import com.google.common.collect.ImmutableSortedMultiset;
47 import com.google.common.collect.ImmutableSortedSet;
48 import com.google.common.collect.ImmutableTable;
49 import com.google.common.collect.Iterators;
50 import com.google.common.collect.ListMultimap;
51 import com.google.common.collect.MapDifference;
52 import com.google.common.collect.Maps;
53 import com.google.common.collect.Multimap;
54 import com.google.common.collect.Multimaps;
55 import com.google.common.collect.Multiset;
56 import com.google.common.collect.Ordering;
57 import com.google.common.collect.PeekingIterator;
58 import com.google.common.collect.Range;
59 import com.google.common.collect.RowSortedTable;
60 import com.google.common.collect.SetMultimap;
61 import com.google.common.collect.Sets;
62 import com.google.common.collect.SortedMapDifference;
63 import com.google.common.collect.SortedMultiset;
64 import com.google.common.collect.SortedSetMultimap;
65 import com.google.common.collect.Table;
66 import com.google.common.collect.Tables;
67 import com.google.common.collect.TreeBasedTable;
68 import com.google.common.collect.TreeMultimap;
69 import com.google.common.io.ByteSink;
70 import com.google.common.io.ByteSource;
71 import com.google.common.io.ByteStreams;
72 import com.google.common.io.CharSink;
73 import com.google.common.io.CharSource;
74 import com.google.common.primitives.Primitives;
75 import com.google.common.primitives.UnsignedInteger;
76 import com.google.common.primitives.UnsignedLong;
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.concurrent.BlockingDeque;
127 import java.util.concurrent.BlockingQueue;
128 import java.util.concurrent.ConcurrentHashMap;
129 import java.util.concurrent.ConcurrentMap;
130 import java.util.concurrent.ConcurrentNavigableMap;
131 import java.util.concurrent.ConcurrentSkipListMap;
132 import java.util.concurrent.CountDownLatch;
133 import java.util.concurrent.Executor;
134 import java.util.concurrent.LinkedBlockingDeque;
135 import java.util.concurrent.ScheduledThreadPoolExecutor;
136 import java.util.concurrent.ThreadFactory;
137 import java.util.concurrent.ThreadPoolExecutor;
138 import java.util.concurrent.TimeUnit;
139 import java.util.logging.Level;
140 import java.util.logging.Logger;
141 import java.util.regex.MatchResult;
142 import java.util.regex.Matcher;
143 import java.util.regex.Pattern;
144 import org.checkerframework.checker.nullness.compatqual.NullableDecl;
145 
146 /**
147  * Supplies an arbitrary "default" instance for a wide range of types, often useful in testing
148  * utilities.
149  *
150  * <p>Covers arrays, enums and common types defined in {@code java.lang}, {@code java.lang.reflect},
151  * {@code java.io}, {@code java.nio}, {@code java.math}, {@code java.util}, {@code
152  * java.util.concurrent}, {@code java.util.regex}, {@code com.google.common.base}, {@code
153  * com.google.common.collect} and {@code com.google.common.primitives}. In addition, if the type
154  * exposes at least one public static final constant of the same type, one of the constants will be
155  * used; or if the class exposes a public parameter-less constructor then it will be "new"d and
156  * returned.
157  *
158  * <p>All default instances returned by {@link #get} are generics-safe. Clients won't get type
159  * errors for using {@code get(Comparator.class)} as a {@code Comparator<Foo>}, for example.
160  * Immutable empty instances are returned for collection types; {@code ""} for string; {@code 0} for
161  * number types; reasonable default instance for other stateless types. For mutable types, a fresh
162  * instance is created each time {@code get()} is called.
163  *
164  * @author Kevin Bourrillion
165  * @author Ben Yu
166  * @since 12.0
167  */
168 @Beta
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           // common.base
209           .put(CharMatcher.class, CharMatcher.none())
210           .put(Joiner.class, Joiner.on(','))
211           .put(Splitter.class, Splitter.on(','))
212           .put(com.google.common.base.Optional.class, com.google.common.base.Optional.absent())
213           .put(Predicate.class, Predicates.alwaysTrue())
214           .put(Equivalence.class, Equivalence.equals())
215           .put(Ticker.class, Ticker.systemTicker())
216           .put(Stopwatch.class, Stopwatch.createUnstarted())
217           // io types
218           .put(InputStream.class, new ByteArrayInputStream(new byte[0]))
219           .put(ByteArrayInputStream.class, new ByteArrayInputStream(new byte[0]))
220           .put(Readable.class, new StringReader(""))
221           .put(Reader.class, new StringReader(""))
222           .put(StringReader.class, new StringReader(""))
223           .put(Buffer.class, ByteBuffer.allocate(0))
224           .put(CharBuffer.class, CharBuffer.allocate(0))
225           .put(ByteBuffer.class, ByteBuffer.allocate(0))
226           .put(ShortBuffer.class, ShortBuffer.allocate(0))
227           .put(IntBuffer.class, IntBuffer.allocate(0))
228           .put(LongBuffer.class, LongBuffer.allocate(0))
229           .put(FloatBuffer.class, FloatBuffer.allocate(0))
230           .put(DoubleBuffer.class, DoubleBuffer.allocate(0))
231           .put(File.class, new File(""))
232           .put(ByteSource.class, ByteSource.empty())
233           .put(CharSource.class, CharSource.empty())
234           .put(ByteSink.class, NullByteSink.INSTANCE)
235           .put(CharSink.class, NullByteSink.INSTANCE.asCharSink(Charsets.UTF_8))
236           // All collections are immutable empty. So safe for any type parameter.
237           .put(Iterator.class, ImmutableSet.of().iterator())
238           .put(PeekingIterator.class, Iterators.peekingIterator(ImmutableSet.of().iterator()))
239           .put(ListIterator.class, ImmutableList.of().listIterator())
240           .put(Iterable.class, ImmutableSet.of())
241           .put(Collection.class, ImmutableList.of())
242           .put(ImmutableCollection.class, ImmutableList.of())
243           .put(List.class, ImmutableList.of())
244           .put(ImmutableList.class, ImmutableList.of())
245           .put(Set.class, ImmutableSet.of())
246           .put(ImmutableSet.class, ImmutableSet.of())
247           .put(SortedSet.class, ImmutableSortedSet.of())
248           .put(ImmutableSortedSet.class, ImmutableSortedSet.of())
249           .put(NavigableSet.class, Sets.unmodifiableNavigableSet(Sets.newTreeSet()))
250           .put(Map.class, ImmutableMap.of())
251           .put(ImmutableMap.class, ImmutableMap.of())
252           .put(SortedMap.class, ImmutableSortedMap.of())
253           .put(ImmutableSortedMap.class, ImmutableSortedMap.of())
254           .put(NavigableMap.class, Maps.unmodifiableNavigableMap(Maps.newTreeMap()))
255           .put(Multimap.class, ImmutableMultimap.of())
256           .put(ImmutableMultimap.class, ImmutableMultimap.of())
257           .put(ListMultimap.class, ImmutableListMultimap.of())
258           .put(ImmutableListMultimap.class, ImmutableListMultimap.of())
259           .put(SetMultimap.class, ImmutableSetMultimap.of())
260           .put(ImmutableSetMultimap.class, ImmutableSetMultimap.of())
261           .put(
262               SortedSetMultimap.class,
263               Multimaps.unmodifiableSortedSetMultimap(TreeMultimap.create()))
264           .put(Multiset.class, ImmutableMultiset.of())
265           .put(ImmutableMultiset.class, ImmutableMultiset.of())
266           .put(SortedMultiset.class, ImmutableSortedMultiset.of())
267           .put(ImmutableSortedMultiset.class, ImmutableSortedMultiset.of())
268           .put(BiMap.class, ImmutableBiMap.of())
269           .put(ImmutableBiMap.class, ImmutableBiMap.of())
270           .put(Table.class, ImmutableTable.of())
271           .put(ImmutableTable.class, ImmutableTable.of())
272           .put(RowSortedTable.class, Tables.unmodifiableRowSortedTable(TreeBasedTable.create()))
273           .put(ClassToInstanceMap.class, ImmutableClassToInstanceMap.builder().build())
274           .put(ImmutableClassToInstanceMap.class, ImmutableClassToInstanceMap.builder().build())
275           .put(Comparable.class, ByToString.INSTANCE)
276           .put(Comparator.class, AlwaysEqual.INSTANCE)
277           .put(Ordering.class, AlwaysEqual.INSTANCE)
278           .put(Range.class, Range.all())
279           .put(MapDifference.class, Maps.difference(ImmutableMap.of(), ImmutableMap.of()))
280           .put(
281               SortedMapDifference.class,
282               Maps.difference(ImmutableSortedMap.of(), ImmutableSortedMap.of()))
283           // reflect
284           .put(AnnotatedElement.class, Object.class)
285           .put(GenericDeclaration.class, Object.class)
286           .put(Type.class, Object.class)
287           .build();
288 
289   /**
290    * type → implementation. Inherently mutable interfaces and abstract classes are mapped to their
291    * default implementations and are "new"d upon get().
292    */
293   private static final ConcurrentMap<Class<?>, Class<?>> implementations = Maps.newConcurrentMap();
294 
setImplementation(Class<T> type, Class<? extends T> implementation)295   private static <T> void setImplementation(Class<T> type, Class<? extends T> implementation) {
296     checkArgument(type != implementation, "Don't register %s to itself!", type);
297     checkArgument(
298         !DEFAULTS.containsKey(type), "A default value was already registered for %s", type);
299     checkArgument(
300         implementations.put(type, implementation) == null,
301         "Implementation for %s was already registered",
302         type);
303   }
304 
305   static {
setImplementation(Appendable.class, StringBuilder.class)306     setImplementation(Appendable.class, StringBuilder.class);
setImplementation(BlockingQueue.class, LinkedBlockingDeque.class)307     setImplementation(BlockingQueue.class, LinkedBlockingDeque.class);
setImplementation(BlockingDeque.class, LinkedBlockingDeque.class)308     setImplementation(BlockingDeque.class, LinkedBlockingDeque.class);
setImplementation(ConcurrentMap.class, ConcurrentHashMap.class)309     setImplementation(ConcurrentMap.class, ConcurrentHashMap.class);
setImplementation(ConcurrentNavigableMap.class, ConcurrentSkipListMap.class)310     setImplementation(ConcurrentNavigableMap.class, ConcurrentSkipListMap.class);
setImplementation(CountDownLatch.class, Dummies.DummyCountDownLatch.class)311     setImplementation(CountDownLatch.class, Dummies.DummyCountDownLatch.class);
setImplementation(Deque.class, ArrayDeque.class)312     setImplementation(Deque.class, ArrayDeque.class);
setImplementation(OutputStream.class, ByteArrayOutputStream.class)313     setImplementation(OutputStream.class, ByteArrayOutputStream.class);
setImplementation(PrintStream.class, Dummies.InMemoryPrintStream.class)314     setImplementation(PrintStream.class, Dummies.InMemoryPrintStream.class);
setImplementation(PrintWriter.class, Dummies.InMemoryPrintWriter.class)315     setImplementation(PrintWriter.class, Dummies.InMemoryPrintWriter.class);
setImplementation(Queue.class, ArrayDeque.class)316     setImplementation(Queue.class, ArrayDeque.class);
setImplementation(Random.class, Dummies.DeterministicRandom.class)317     setImplementation(Random.class, Dummies.DeterministicRandom.class);
setImplementation( ScheduledThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class)318     setImplementation(
319         ScheduledThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class);
setImplementation(ThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class)320     setImplementation(ThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class);
setImplementation(Writer.class, StringWriter.class)321     setImplementation(Writer.class, StringWriter.class);
setImplementation(Runnable.class, Dummies.DummyRunnable.class)322     setImplementation(Runnable.class, Dummies.DummyRunnable.class);
setImplementation(ThreadFactory.class, Dummies.DummyThreadFactory.class)323     setImplementation(ThreadFactory.class, Dummies.DummyThreadFactory.class);
setImplementation(Executor.class, Dummies.DummyExecutor.class)324     setImplementation(Executor.class, Dummies.DummyExecutor.class);
325   }
326 
327   @SuppressWarnings("unchecked") // it's a subtype map
328   @NullableDecl
getImplementation(Class<T> type)329   private static <T> Class<? extends T> getImplementation(Class<T> type) {
330     return (Class<? extends T>) implementations.get(type);
331   }
332 
333   private static final Logger logger = Logger.getLogger(ArbitraryInstances.class.getName());
334 
335   /**
336    * Returns an arbitrary instance for {@code type}, or {@code null} if no arbitrary instance can be
337    * determined.
338    */
339   @NullableDecl
get(Class<T> type)340   public static <T> T get(Class<T> type) {
341     T defaultValue = DEFAULTS.getInstance(type);
342     if (defaultValue != null) {
343       return defaultValue;
344     }
345     Class<? extends T> implementation = getImplementation(type);
346     if (implementation != null) {
347       return get(implementation);
348     }
349     if (type.isEnum()) {
350       T[] enumConstants = type.getEnumConstants();
351       return (enumConstants.length == 0) ? null : enumConstants[0];
352     }
353     if (type.isArray()) {
354       return createEmptyArray(type);
355     }
356     T jvmDefault = Defaults.defaultValue(Primitives.unwrap(type));
357     if (jvmDefault != null) {
358       return jvmDefault;
359     }
360     if (Modifier.isAbstract(type.getModifiers()) || !Modifier.isPublic(type.getModifiers())) {
361       return arbitraryConstantInstanceOrNull(type);
362     }
363     final Constructor<T> constructor;
364     try {
365       constructor = type.getConstructor();
366     } catch (NoSuchMethodException e) {
367       return arbitraryConstantInstanceOrNull(type);
368     }
369     constructor.setAccessible(true); // accessibility check is too slow
370     try {
371       return constructor.newInstance();
372     } catch (InstantiationException | IllegalAccessException impossible) {
373       throw new AssertionError(impossible);
374     } catch (InvocationTargetException e) {
375       logger.log(Level.WARNING, "Exception while invoking default constructor.", e.getCause());
376       return arbitraryConstantInstanceOrNull(type);
377     }
378   }
379 
380   @NullableDecl
arbitraryConstantInstanceOrNull(Class<T> type)381   private static <T> T arbitraryConstantInstanceOrNull(Class<T> type) {
382     Field[] fields = type.getDeclaredFields();
383     Arrays.sort(fields, BY_FIELD_NAME);
384     for (Field field : fields) {
385       if (Modifier.isPublic(field.getModifiers())
386           && Modifier.isStatic(field.getModifiers())
387           && Modifier.isFinal(field.getModifiers())) {
388         if (field.getGenericType() == field.getType() && type.isAssignableFrom(field.getType())) {
389           field.setAccessible(true);
390           try {
391             T constant = type.cast(field.get(null));
392             if (constant != null) {
393               return constant;
394             }
395           } catch (IllegalAccessException impossible) {
396             throw new AssertionError(impossible);
397           }
398         }
399       }
400     }
401     return null;
402   }
403 
createEmptyArray(Class<T> arrayType)404   private static <T> T createEmptyArray(Class<T> arrayType) {
405     return arrayType.cast(Array.newInstance(arrayType.getComponentType(), 0));
406   }
407 
408   // Internal implementations of some classes, with public default constructor that get() needs.
409   private static final class Dummies {
410 
411     public static final class InMemoryPrintStream extends PrintStream {
InMemoryPrintStream()412       public InMemoryPrintStream() {
413         super(new ByteArrayOutputStream());
414       }
415     }
416 
417     public static final class InMemoryPrintWriter extends PrintWriter {
InMemoryPrintWriter()418       public InMemoryPrintWriter() {
419         super(new StringWriter());
420       }
421     }
422 
423     public static final class DeterministicRandom extends Random {
DeterministicRandom()424       public DeterministicRandom() {
425         super(0);
426       }
427     }
428 
429     public static final class DummyScheduledThreadPoolExecutor extends ScheduledThreadPoolExecutor {
DummyScheduledThreadPoolExecutor()430       public DummyScheduledThreadPoolExecutor() {
431         super(1);
432       }
433     }
434 
435     public static final class DummyCountDownLatch extends CountDownLatch {
DummyCountDownLatch()436       public DummyCountDownLatch() {
437         super(0);
438       }
439     }
440 
441     public static final class DummyRunnable implements Runnable, Serializable {
442       @Override
run()443       public void run() {}
444     }
445 
446     public static final class DummyThreadFactory implements ThreadFactory, Serializable {
447       @Override
newThread(Runnable r)448       public Thread newThread(Runnable r) {
449         return new Thread(r);
450       }
451     }
452 
453     public static final class DummyExecutor implements Executor, Serializable {
454       @Override
execute(Runnable command)455       public void execute(Runnable command) {}
456     }
457   }
458 
459   private static final class NullByteSink extends ByteSink implements Serializable {
460     private static final NullByteSink INSTANCE = new NullByteSink();
461 
462     @Override
openStream()463     public OutputStream openStream() {
464       return ByteStreams.nullOutputStream();
465     }
466   }
467 
468   // Compare by toString() to satisfy 2 properties:
469   // 1. compareTo(null) should throw NullPointerException
470   // 2. the order is deterministic and easy to understand, for debugging purpose.
471   @SuppressWarnings("ComparableType")
472   private static final class ByToString implements Comparable<Object>, Serializable {
473     private static final ByToString INSTANCE = new ByToString();
474 
475     @Override
compareTo(Object o)476     public int compareTo(Object o) {
477       return toString().compareTo(o.toString());
478     }
479 
480     @Override
toString()481     public String toString() {
482       return "BY_TO_STRING";
483     }
484 
readResolve()485     private Object readResolve() {
486       return INSTANCE;
487     }
488   }
489 
490   // Always equal is a valid total ordering. And it works for any Object.
491   private static final class AlwaysEqual extends Ordering<Object> implements Serializable {
492     private static final AlwaysEqual INSTANCE = new AlwaysEqual();
493 
494     @Override
compare(Object o1, Object o2)495     public int compare(Object o1, Object o2) {
496       return 0;
497     }
498 
499     @Override
toString()500     public String toString() {
501       return "ALWAYS_EQUAL";
502     }
503 
readResolve()504     private Object readResolve() {
505       return INSTANCE;
506     }
507   }
508 
ArbitraryInstances()509   private ArbitraryInstances() {}
510 }
511