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