001/*
002 * Copyright (C) 2012 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package com.google.common.testing;
018
019import static com.google.common.base.Preconditions.checkArgument;
020import static java.util.Objects.requireNonNull;
021
022import com.google.common.annotations.GwtIncompatible;
023import com.google.common.annotations.J2ktIncompatible;
024import com.google.common.base.CharMatcher;
025import com.google.common.base.Charsets;
026import com.google.common.base.Defaults;
027import com.google.common.base.Equivalence;
028import com.google.common.base.Joiner;
029import com.google.common.base.Predicate;
030import com.google.common.base.Predicates;
031import com.google.common.base.Splitter;
032import com.google.common.base.Stopwatch;
033import com.google.common.base.Ticker;
034import com.google.common.collect.BiMap;
035import com.google.common.collect.ClassToInstanceMap;
036import com.google.common.collect.ImmutableBiMap;
037import com.google.common.collect.ImmutableClassToInstanceMap;
038import com.google.common.collect.ImmutableCollection;
039import com.google.common.collect.ImmutableList;
040import com.google.common.collect.ImmutableListMultimap;
041import com.google.common.collect.ImmutableMap;
042import com.google.common.collect.ImmutableMultimap;
043import com.google.common.collect.ImmutableMultiset;
044import com.google.common.collect.ImmutableSet;
045import com.google.common.collect.ImmutableSetMultimap;
046import com.google.common.collect.ImmutableSortedMap;
047import com.google.common.collect.ImmutableSortedMultiset;
048import com.google.common.collect.ImmutableSortedSet;
049import com.google.common.collect.ImmutableTable;
050import com.google.common.collect.Iterators;
051import com.google.common.collect.ListMultimap;
052import com.google.common.collect.MapDifference;
053import com.google.common.collect.Maps;
054import com.google.common.collect.Multimap;
055import com.google.common.collect.Multimaps;
056import com.google.common.collect.Multiset;
057import com.google.common.collect.Ordering;
058import com.google.common.collect.PeekingIterator;
059import com.google.common.collect.Range;
060import com.google.common.collect.RowSortedTable;
061import com.google.common.collect.SetMultimap;
062import com.google.common.collect.Sets;
063import com.google.common.collect.SortedMapDifference;
064import com.google.common.collect.SortedMultiset;
065import com.google.common.collect.SortedSetMultimap;
066import com.google.common.collect.Table;
067import com.google.common.collect.Tables;
068import com.google.common.collect.TreeBasedTable;
069import com.google.common.collect.TreeMultimap;
070import com.google.common.io.ByteSink;
071import com.google.common.io.ByteSource;
072import com.google.common.io.ByteStreams;
073import com.google.common.io.CharSink;
074import com.google.common.io.CharSource;
075import com.google.common.primitives.Primitives;
076import com.google.common.primitives.UnsignedInteger;
077import com.google.common.primitives.UnsignedLong;
078import com.google.errorprone.annotations.Keep;
079import java.io.ByteArrayInputStream;
080import java.io.ByteArrayOutputStream;
081import java.io.File;
082import java.io.InputStream;
083import java.io.OutputStream;
084import java.io.PrintStream;
085import java.io.PrintWriter;
086import java.io.Reader;
087import java.io.Serializable;
088import java.io.StringReader;
089import java.io.StringWriter;
090import java.io.Writer;
091import java.lang.reflect.AnnotatedElement;
092import java.lang.reflect.Array;
093import java.lang.reflect.Constructor;
094import java.lang.reflect.Field;
095import java.lang.reflect.GenericDeclaration;
096import java.lang.reflect.InvocationTargetException;
097import java.lang.reflect.Modifier;
098import java.lang.reflect.Type;
099import java.math.BigDecimal;
100import java.math.BigInteger;
101import java.nio.Buffer;
102import java.nio.ByteBuffer;
103import java.nio.CharBuffer;
104import java.nio.DoubleBuffer;
105import java.nio.FloatBuffer;
106import java.nio.IntBuffer;
107import java.nio.LongBuffer;
108import java.nio.ShortBuffer;
109import java.nio.charset.Charset;
110import java.util.ArrayDeque;
111import java.util.Arrays;
112import java.util.Collection;
113import java.util.Comparator;
114import java.util.Currency;
115import java.util.Deque;
116import java.util.Iterator;
117import java.util.List;
118import java.util.ListIterator;
119import java.util.Locale;
120import java.util.Map;
121import java.util.NavigableMap;
122import java.util.NavigableSet;
123import java.util.Queue;
124import java.util.Random;
125import java.util.Set;
126import java.util.SortedMap;
127import java.util.SortedSet;
128import java.util.UUID;
129import java.util.concurrent.BlockingDeque;
130import java.util.concurrent.BlockingQueue;
131import java.util.concurrent.ConcurrentHashMap;
132import java.util.concurrent.ConcurrentMap;
133import java.util.concurrent.ConcurrentNavigableMap;
134import java.util.concurrent.ConcurrentSkipListMap;
135import java.util.concurrent.CountDownLatch;
136import java.util.concurrent.Executor;
137import java.util.concurrent.LinkedBlockingDeque;
138import java.util.concurrent.ScheduledThreadPoolExecutor;
139import java.util.concurrent.ThreadFactory;
140import java.util.concurrent.ThreadPoolExecutor;
141import java.util.concurrent.TimeUnit;
142import java.util.logging.Level;
143import java.util.logging.Logger;
144import java.util.regex.MatchResult;
145import java.util.regex.Matcher;
146import java.util.regex.Pattern;
147import 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
174public 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   */
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
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 {
311    setImplementation(Appendable.class, StringBuilder.class);
312    setImplementation(BlockingQueue.class, LinkedBlockingDeque.class);
313    setImplementation(BlockingDeque.class, LinkedBlockingDeque.class);
314    setImplementation(ConcurrentMap.class, ConcurrentHashMap.class);
315    setImplementation(ConcurrentNavigableMap.class, ConcurrentSkipListMap.class);
316    setImplementation(CountDownLatch.class, Dummies.DummyCountDownLatch.class);
317    setImplementation(Deque.class, ArrayDeque.class);
318    setImplementation(OutputStream.class, ByteArrayOutputStream.class);
319    setImplementation(PrintStream.class, Dummies.InMemoryPrintStream.class);
320    setImplementation(PrintWriter.class, Dummies.InMemoryPrintWriter.class);
321    setImplementation(Queue.class, ArrayDeque.class);
322    setImplementation(Random.class, Dummies.DeterministicRandom.class);
323    setImplementation(
324        ScheduledThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class);
325    setImplementation(ThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class);
326    setImplementation(Writer.class, StringWriter.class);
327    setImplementation(Runnable.class, Dummies.DummyRunnable.class);
328    setImplementation(ThreadFactory.class, Dummies.DummyThreadFactory.class);
329    setImplementation(Executor.class, Dummies.DummyExecutor.class);
330  }
331
332  @SuppressWarnings("unchecked") // it's a subtype map
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   */
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
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
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 {
422      public InMemoryPrintStream() {
423        super(new ByteArrayOutputStream());
424      }
425    }
426
427    public static final class InMemoryPrintWriter extends PrintWriter {
428      public InMemoryPrintWriter() {
429        super(new StringWriter());
430      }
431    }
432
433    public static final class DeterministicRandom extends Random {
434      @Keep
435      public DeterministicRandom() {
436        super(0);
437      }
438    }
439
440    public static final class DummyScheduledThreadPoolExecutor extends ScheduledThreadPoolExecutor {
441      public DummyScheduledThreadPoolExecutor() {
442        super(1);
443      }
444    }
445
446    public static final class DummyCountDownLatch extends CountDownLatch {
447      public DummyCountDownLatch() {
448        super(0);
449      }
450    }
451
452    public static final class DummyRunnable implements Runnable, Serializable {
453      @Override
454      public void run() {}
455    }
456
457    public static final class DummyThreadFactory implements ThreadFactory, Serializable {
458      @Override
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
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
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
487    public int compareTo(Object o) {
488      return toString().compareTo(o.toString());
489    }
490
491    @Override
492    public String toString() {
493      return "BY_TO_STRING";
494    }
495
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
507    public int compare(@Nullable Object o1, @Nullable Object o2) {
508      return 0;
509    }
510
511    @Override
512    public String toString() {
513      return "ALWAYS_EQUAL";
514    }
515
516    private Object readResolve() {
517      return INSTANCE;
518    }
519  }
520
521  private ArbitraryInstances() {}
522}