• 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.nio.charset.StandardCharsets.UTF_8;
21 import static java.util.Objects.requireNonNull;
22 
23 import com.google.common.annotations.GwtIncompatible;
24 import com.google.common.annotations.J2ktIncompatible;
25 import com.google.common.base.CharMatcher;
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    * https://cs.android.com/android/platform/superproject/+/android-2.3.7_r1:libcore/luni/src/main/java/java/util/regex/Matcher.java;l=550;drc=5850271b4ab93ebc27c1d49169a348c6be3c7f04
188    */
createMatchResult()189   private static MatchResult createMatchResult() {
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, createMatchResult())
208           .put(TimeUnit.class, TimeUnit.SECONDS)
209           .put(Charset.class, 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(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     } catch (InstantiationException | IllegalAccessException impossible) {
376       throw new AssertionError(impossible);
377     } catch (InvocationTargetException e) {
378       logger.log(Level.WARNING, "Exception while invoking default constructor.", e.getCause());
379       return arbitraryConstantInstanceOrNull(type);
380     }
381   }
382 
arbitraryConstantInstanceOrNull(Class<T> type)383   private static <T> @Nullable T arbitraryConstantInstanceOrNull(Class<T> type) {
384     Field[] fields = type.getDeclaredFields();
385     Arrays.sort(fields, BY_FIELD_NAME);
386     for (Field field : fields) {
387       if (Modifier.isPublic(field.getModifiers())
388           && Modifier.isStatic(field.getModifiers())
389           && Modifier.isFinal(field.getModifiers())) {
390         if (field.getGenericType() == field.getType() && type.isAssignableFrom(field.getType())) {
391           field.setAccessible(true);
392           try {
393             T constant = type.cast(field.get(null));
394             if (constant != null) {
395               return constant;
396             }
397           } catch (IllegalAccessException impossible) {
398             throw new AssertionError(impossible);
399           }
400         }
401       }
402     }
403     return null;
404   }
405 
createEmptyArray(Class<T> arrayType)406   private static <T> T createEmptyArray(Class<T> arrayType) {
407     // getComponentType() is non-null because we call createEmptyArray only with an array type.
408     return arrayType.cast(Array.newInstance(requireNonNull(arrayType.getComponentType()), 0));
409   }
410 
411   // Internal implementations of some classes, with public default constructor that get() needs.
412   private static final class Dummies {
413 
414     public static final class InMemoryPrintStream extends PrintStream {
InMemoryPrintStream()415       public InMemoryPrintStream() {
416         super(new ByteArrayOutputStream());
417       }
418     }
419 
420     public static final class InMemoryPrintWriter extends PrintWriter {
InMemoryPrintWriter()421       public InMemoryPrintWriter() {
422         super(new StringWriter());
423       }
424     }
425 
426     public static final class DeterministicRandom extends Random {
427       @Keep
DeterministicRandom()428       public DeterministicRandom() {
429         super(0);
430       }
431     }
432 
433     public static final class DummyScheduledThreadPoolExecutor extends ScheduledThreadPoolExecutor {
DummyScheduledThreadPoolExecutor()434       public DummyScheduledThreadPoolExecutor() {
435         super(1);
436       }
437     }
438 
439     public static final class DummyCountDownLatch extends CountDownLatch {
DummyCountDownLatch()440       public DummyCountDownLatch() {
441         super(0);
442       }
443     }
444 
445     public static final class DummyRunnable implements Runnable, Serializable {
446       @Override
run()447       public void run() {}
448     }
449 
450     public static final class DummyThreadFactory implements ThreadFactory, Serializable {
451       @Override
newThread(Runnable r)452       public Thread newThread(Runnable r) {
453         return new Thread(r);
454       }
455     }
456 
457     public static final class DummyExecutor implements Executor, Serializable {
458       @Override
execute(Runnable command)459       public void execute(Runnable command) {}
460     }
461   }
462 
463   private static final class NullByteSink extends ByteSink implements Serializable {
464     private static final NullByteSink INSTANCE = new NullByteSink();
465 
466     @Override
openStream()467     public OutputStream openStream() {
468       return ByteStreams.nullOutputStream();
469     }
470   }
471 
472   // Compare by toString() to satisfy 2 properties:
473   // 1. compareTo(null) should throw NullPointerException
474   // 2. the order is deterministic and easy to understand, for debugging purpose.
475   @SuppressWarnings("ComparableType")
476   private static final class ByToString implements Comparable<Object>, Serializable {
477     private static final ByToString INSTANCE = new ByToString();
478 
479     @Override
compareTo(Object o)480     public int compareTo(Object o) {
481       return toString().compareTo(o.toString());
482     }
483 
484     @Override
toString()485     public String toString() {
486       return "BY_TO_STRING";
487     }
488 
readResolve()489     private Object readResolve() {
490       return INSTANCE;
491     }
492   }
493 
494   // Always equal is a valid total ordering. And it works for any Object.
495   private static final class AlwaysEqual extends Ordering<@Nullable Object>
496       implements Serializable {
497     private static final AlwaysEqual INSTANCE = new AlwaysEqual();
498 
499     @Override
500     @SuppressWarnings("UnusedVariable") // intentionally weird Comparator
compare(@ullable Object o1, @Nullable Object o2)501     public int compare(@Nullable Object o1, @Nullable Object o2) {
502       return 0;
503     }
504 
505     @Override
toString()506     public String toString() {
507       return "ALWAYS_EQUAL";
508     }
509 
readResolve()510     private Object readResolve() {
511       return INSTANCE;
512     }
513   }
514 
ArbitraryInstances()515   private ArbitraryInstances() {}
516 }
517