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