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