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;
020
021import com.google.common.annotations.GwtIncompatible;
022import com.google.common.annotations.J2ktIncompatible;
023import com.google.common.base.CharMatcher;
024import com.google.common.base.Charsets;
025import com.google.common.base.Defaults;
026import com.google.common.base.Equivalence;
027import com.google.common.base.Joiner;
028import com.google.common.base.Predicate;
029import com.google.common.base.Predicates;
030import com.google.common.base.Splitter;
031import com.google.common.base.Stopwatch;
032import com.google.common.base.Ticker;
033import com.google.common.collect.BiMap;
034import com.google.common.collect.ClassToInstanceMap;
035import com.google.common.collect.ImmutableBiMap;
036import com.google.common.collect.ImmutableClassToInstanceMap;
037import com.google.common.collect.ImmutableCollection;
038import com.google.common.collect.ImmutableList;
039import com.google.common.collect.ImmutableListMultimap;
040import com.google.common.collect.ImmutableMap;
041import com.google.common.collect.ImmutableMultimap;
042import com.google.common.collect.ImmutableMultiset;
043import com.google.common.collect.ImmutableSet;
044import com.google.common.collect.ImmutableSetMultimap;
045import com.google.common.collect.ImmutableSortedMap;
046import com.google.common.collect.ImmutableSortedMultiset;
047import com.google.common.collect.ImmutableSortedSet;
048import com.google.common.collect.ImmutableTable;
049import com.google.common.collect.Iterators;
050import com.google.common.collect.ListMultimap;
051import com.google.common.collect.MapDifference;
052import com.google.common.collect.Maps;
053import com.google.common.collect.Multimap;
054import com.google.common.collect.Multimaps;
055import com.google.common.collect.Multiset;
056import com.google.common.collect.Ordering;
057import com.google.common.collect.PeekingIterator;
058import com.google.common.collect.Range;
059import com.google.common.collect.RowSortedTable;
060import com.google.common.collect.SetMultimap;
061import com.google.common.collect.Sets;
062import com.google.common.collect.SortedMapDifference;
063import com.google.common.collect.SortedMultiset;
064import com.google.common.collect.SortedSetMultimap;
065import com.google.common.collect.Table;
066import com.google.common.collect.Tables;
067import com.google.common.collect.TreeBasedTable;
068import com.google.common.collect.TreeMultimap;
069import com.google.common.io.ByteSink;
070import com.google.common.io.ByteSource;
071import com.google.common.io.ByteStreams;
072import com.google.common.io.CharSink;
073import com.google.common.io.CharSource;
074import com.google.common.primitives.Primitives;
075import com.google.common.primitives.UnsignedInteger;
076import com.google.common.primitives.UnsignedLong;
077import com.google.errorprone.annotations.Keep;
078import java.io.ByteArrayInputStream;
079import java.io.ByteArrayOutputStream;
080import java.io.File;
081import java.io.InputStream;
082import java.io.OutputStream;
083import java.io.PrintStream;
084import java.io.PrintWriter;
085import java.io.Reader;
086import java.io.Serializable;
087import java.io.StringReader;
088import java.io.StringWriter;
089import java.io.Writer;
090import java.lang.reflect.AnnotatedElement;
091import java.lang.reflect.Array;
092import java.lang.reflect.Constructor;
093import java.lang.reflect.Field;
094import java.lang.reflect.GenericDeclaration;
095import java.lang.reflect.InvocationTargetException;
096import java.lang.reflect.Modifier;
097import java.lang.reflect.Type;
098import java.math.BigDecimal;
099import java.math.BigInteger;
100import java.nio.Buffer;
101import java.nio.ByteBuffer;
102import java.nio.CharBuffer;
103import java.nio.DoubleBuffer;
104import java.nio.FloatBuffer;
105import java.nio.IntBuffer;
106import java.nio.LongBuffer;
107import java.nio.ShortBuffer;
108import java.nio.charset.Charset;
109import java.util.ArrayDeque;
110import java.util.Arrays;
111import java.util.Collection;
112import java.util.Comparator;
113import java.util.Currency;
114import java.util.Deque;
115import java.util.Iterator;
116import java.util.List;
117import java.util.ListIterator;
118import java.util.Locale;
119import java.util.Map;
120import java.util.NavigableMap;
121import java.util.NavigableSet;
122import java.util.Queue;
123import java.util.Random;
124import java.util.Set;
125import java.util.SortedMap;
126import java.util.SortedSet;
127import java.util.UUID;
128import java.util.concurrent.BlockingDeque;
129import java.util.concurrent.BlockingQueue;
130import java.util.concurrent.ConcurrentHashMap;
131import java.util.concurrent.ConcurrentMap;
132import java.util.concurrent.ConcurrentNavigableMap;
133import java.util.concurrent.ConcurrentSkipListMap;
134import java.util.concurrent.CountDownLatch;
135import java.util.concurrent.Executor;
136import java.util.concurrent.LinkedBlockingDeque;
137import java.util.concurrent.ScheduledThreadPoolExecutor;
138import java.util.concurrent.ThreadFactory;
139import java.util.concurrent.ThreadPoolExecutor;
140import java.util.concurrent.TimeUnit;
141import java.util.logging.Level;
142import java.util.logging.Logger;
143import java.util.regex.MatchResult;
144import java.util.regex.Matcher;
145import java.util.regex.Pattern;
146import org.checkerframework.checker.nullness.qual.Nullable;
147
148/**
149 * Supplies an arbitrary "default" instance for a wide range of types, often useful in testing
150 * utilities.
151 *
152 * <p>Covers arrays, enums and common types defined in {@code java.lang}, {@code java.lang.reflect},
153 * {@code java.io}, {@code java.nio}, {@code java.math}, {@code java.util}, {@code
154 * java.util.concurrent}, {@code java.util.regex}, {@code com.google.common.base}, {@code
155 * com.google.common.collect} and {@code com.google.common.primitives}. In addition, if the type
156 * exposes at least one public static final constant of the same type, one of the constants will be
157 * used; or if the class exposes a public parameter-less constructor then it will be "new"d and
158 * returned.
159 *
160 * <p>All default instances returned by {@link #get} are generics-safe. Clients won't get type
161 * errors for using {@code get(Comparator.class)} as a {@code Comparator<Foo>}, for example.
162 * Immutable empty instances are returned for collection types; {@code ""} for string; {@code 0} for
163 * number types; reasonable default instance for other stateless types. For mutable types, a fresh
164 * instance is created each time {@code get()} is called.
165 *
166 * @author Kevin Bourrillion
167 * @author Ben Yu
168 * @since 12.0
169 */
170@GwtIncompatible
171@J2ktIncompatible
172@ElementTypesAreNonnullByDefault
173public final class ArbitraryInstances {
174
175  private static final Ordering<Field> BY_FIELD_NAME =
176      new Ordering<Field>() {
177        @Override
178        public int compare(Field left, Field right) {
179          return left.getName().compareTo(right.getName());
180        }
181      };
182
183  /**
184   * Returns a new {@code MatchResult} that corresponds to a successful match. Apache Harmony (used
185   * in Android) requires a successful match in order to generate a {@code MatchResult}:
186   * http://goo.gl/5VQFmC
187   */
188  private static MatchResult newMatchResult() {
189    Matcher matcher = Pattern.compile(".").matcher("X");
190    matcher.find();
191    return matcher.toMatchResult();
192  }
193
194  private static final ClassToInstanceMap<Object> DEFAULTS =
195      ImmutableClassToInstanceMap.builder()
196          // primitives
197          .put(Object.class, "")
198          .put(Number.class, 0)
199          .put(UnsignedInteger.class, UnsignedInteger.ZERO)
200          .put(UnsignedLong.class, UnsignedLong.ZERO)
201          .put(BigInteger.class, BigInteger.ZERO)
202          .put(BigDecimal.class, BigDecimal.ZERO)
203          .put(CharSequence.class, "")
204          .put(String.class, "")
205          .put(Pattern.class, Pattern.compile(""))
206          .put(MatchResult.class, newMatchResult())
207          .put(TimeUnit.class, TimeUnit.SECONDS)
208          .put(Charset.class, Charsets.UTF_8)
209          .put(Currency.class, Currency.getInstance(Locale.US))
210          .put(Locale.class, Locale.US)
211          .put(UUID.class, UUID.randomUUID())
212          // common.base
213          .put(CharMatcher.class, CharMatcher.none())
214          .put(Joiner.class, Joiner.on(','))
215          .put(Splitter.class, Splitter.on(','))
216          .put(com.google.common.base.Optional.class, com.google.common.base.Optional.absent())
217          .put(Predicate.class, Predicates.alwaysTrue())
218          .put(Equivalence.class, Equivalence.equals())
219          .put(Ticker.class, Ticker.systemTicker())
220          .put(Stopwatch.class, Stopwatch.createUnstarted())
221          // io types
222          .put(InputStream.class, new ByteArrayInputStream(new byte[0]))
223          .put(ByteArrayInputStream.class, new ByteArrayInputStream(new byte[0]))
224          .put(Readable.class, new StringReader(""))
225          .put(Reader.class, new StringReader(""))
226          .put(StringReader.class, new StringReader(""))
227          .put(Buffer.class, ByteBuffer.allocate(0))
228          .put(CharBuffer.class, CharBuffer.allocate(0))
229          .put(ByteBuffer.class, ByteBuffer.allocate(0))
230          .put(ShortBuffer.class, ShortBuffer.allocate(0))
231          .put(IntBuffer.class, IntBuffer.allocate(0))
232          .put(LongBuffer.class, LongBuffer.allocate(0))
233          .put(FloatBuffer.class, FloatBuffer.allocate(0))
234          .put(DoubleBuffer.class, DoubleBuffer.allocate(0))
235          .put(File.class, new File(""))
236          .put(ByteSource.class, ByteSource.empty())
237          .put(CharSource.class, CharSource.empty())
238          .put(ByteSink.class, NullByteSink.INSTANCE)
239          .put(CharSink.class, NullByteSink.INSTANCE.asCharSink(Charsets.UTF_8))
240          // All collections are immutable empty. So safe for any type parameter.
241          .put(Iterator.class, ImmutableSet.of().iterator())
242          .put(PeekingIterator.class, Iterators.peekingIterator(ImmutableSet.of().iterator()))
243          .put(ListIterator.class, ImmutableList.of().listIterator())
244          .put(Iterable.class, ImmutableSet.of())
245          .put(Collection.class, ImmutableList.of())
246          .put(ImmutableCollection.class, ImmutableList.of())
247          .put(List.class, ImmutableList.of())
248          .put(ImmutableList.class, ImmutableList.of())
249          .put(Set.class, ImmutableSet.of())
250          .put(ImmutableSet.class, ImmutableSet.of())
251          .put(SortedSet.class, ImmutableSortedSet.of())
252          .put(ImmutableSortedSet.class, ImmutableSortedSet.of())
253          .put(NavigableSet.class, Sets.unmodifiableNavigableSet(Sets.newTreeSet()))
254          .put(Map.class, ImmutableMap.of())
255          .put(ImmutableMap.class, ImmutableMap.of())
256          .put(SortedMap.class, ImmutableSortedMap.of())
257          .put(ImmutableSortedMap.class, ImmutableSortedMap.of())
258          .put(NavigableMap.class, Maps.unmodifiableNavigableMap(Maps.newTreeMap()))
259          .put(Multimap.class, ImmutableMultimap.of())
260          .put(ImmutableMultimap.class, ImmutableMultimap.of())
261          .put(ListMultimap.class, ImmutableListMultimap.of())
262          .put(ImmutableListMultimap.class, ImmutableListMultimap.of())
263          .put(SetMultimap.class, ImmutableSetMultimap.of())
264          .put(ImmutableSetMultimap.class, ImmutableSetMultimap.of())
265          .put(
266              SortedSetMultimap.class,
267              Multimaps.unmodifiableSortedSetMultimap(TreeMultimap.create()))
268          .put(Multiset.class, ImmutableMultiset.of())
269          .put(ImmutableMultiset.class, ImmutableMultiset.of())
270          .put(SortedMultiset.class, ImmutableSortedMultiset.of())
271          .put(ImmutableSortedMultiset.class, ImmutableSortedMultiset.of())
272          .put(BiMap.class, ImmutableBiMap.of())
273          .put(ImmutableBiMap.class, ImmutableBiMap.of())
274          .put(Table.class, ImmutableTable.of())
275          .put(ImmutableTable.class, ImmutableTable.of())
276          .put(RowSortedTable.class, Tables.unmodifiableRowSortedTable(TreeBasedTable.create()))
277          .put(ClassToInstanceMap.class, ImmutableClassToInstanceMap.builder().build())
278          .put(ImmutableClassToInstanceMap.class, ImmutableClassToInstanceMap.builder().build())
279          .put(Comparable.class, ByToString.INSTANCE)
280          .put(Comparator.class, AlwaysEqual.INSTANCE)
281          .put(Ordering.class, AlwaysEqual.INSTANCE)
282          .put(Range.class, Range.all())
283          .put(MapDifference.class, Maps.difference(ImmutableMap.of(), ImmutableMap.of()))
284          .put(
285              SortedMapDifference.class,
286              Maps.difference(ImmutableSortedMap.of(), ImmutableSortedMap.of()))
287          // reflect
288          .put(AnnotatedElement.class, Object.class)
289          .put(GenericDeclaration.class, Object.class)
290          .put(Type.class, Object.class)
291          .build();
292
293  /**
294   * type → implementation. Inherently mutable interfaces and abstract classes are mapped to their
295   * default implementations and are "new"d upon get().
296   */
297  private static final ConcurrentMap<Class<?>, Class<?>> implementations = Maps.newConcurrentMap();
298
299  private static <T> void setImplementation(Class<T> type, Class<? extends T> implementation) {
300    checkArgument(type != implementation, "Don't register %s to itself!", type);
301    checkArgument(
302        !DEFAULTS.containsKey(type), "A default value was already registered for %s", type);
303    checkArgument(
304        implementations.put(type, implementation) == null,
305        "Implementation for %s was already registered",
306        type);
307  }
308
309  static {
310    setImplementation(Appendable.class, StringBuilder.class);
311    setImplementation(BlockingQueue.class, LinkedBlockingDeque.class);
312    setImplementation(BlockingDeque.class, LinkedBlockingDeque.class);
313    setImplementation(ConcurrentMap.class, ConcurrentHashMap.class);
314    setImplementation(ConcurrentNavigableMap.class, ConcurrentSkipListMap.class);
315    setImplementation(CountDownLatch.class, Dummies.DummyCountDownLatch.class);
316    setImplementation(Deque.class, ArrayDeque.class);
317    setImplementation(OutputStream.class, ByteArrayOutputStream.class);
318    setImplementation(PrintStream.class, Dummies.InMemoryPrintStream.class);
319    setImplementation(PrintWriter.class, Dummies.InMemoryPrintWriter.class);
320    setImplementation(Queue.class, ArrayDeque.class);
321    setImplementation(Random.class, Dummies.DeterministicRandom.class);
322    setImplementation(
323        ScheduledThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class);
324    setImplementation(ThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class);
325    setImplementation(Writer.class, StringWriter.class);
326    setImplementation(Runnable.class, Dummies.DummyRunnable.class);
327    setImplementation(ThreadFactory.class, Dummies.DummyThreadFactory.class);
328    setImplementation(Executor.class, Dummies.DummyExecutor.class);
329  }
330
331  @SuppressWarnings("unchecked") // it's a subtype map
332  private static <T> @Nullable Class<? extends T> getImplementation(Class<T> type) {
333    return (Class<? extends T>) implementations.get(type);
334  }
335
336  private static final Logger logger = Logger.getLogger(ArbitraryInstances.class.getName());
337
338  /**
339   * Returns an arbitrary instance for {@code type}, or {@code null} if no arbitrary instance can be
340   * determined.
341   */
342  public static <T> @Nullable 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 == null || 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  private static <T> @Nullable T arbitraryConstantInstanceOrNull(Class<T> type) {
390    Field[] fields = type.getDeclaredFields();
391    Arrays.sort(fields, BY_FIELD_NAME);
392    for (Field field : fields) {
393      if (Modifier.isPublic(field.getModifiers())
394          && Modifier.isStatic(field.getModifiers())
395          && Modifier.isFinal(field.getModifiers())) {
396        if (field.getGenericType() == field.getType() && type.isAssignableFrom(field.getType())) {
397          field.setAccessible(true);
398          try {
399            T constant = type.cast(field.get(null));
400            if (constant != null) {
401              return constant;
402            }
403          } catch (IllegalAccessException impossible) {
404            throw new AssertionError(impossible);
405          }
406        }
407      }
408    }
409    return null;
410  }
411
412  private static <T> T createEmptyArray(Class<T> arrayType) {
413    return arrayType.cast(Array.newInstance(arrayType.getComponentType(), 0));
414  }
415
416  // Internal implementations of some classes, with public default constructor that get() needs.
417  private static final class Dummies {
418
419    public static final class InMemoryPrintStream extends PrintStream {
420      public InMemoryPrintStream() {
421        super(new ByteArrayOutputStream());
422      }
423    }
424
425    public static final class InMemoryPrintWriter extends PrintWriter {
426      public InMemoryPrintWriter() {
427        super(new StringWriter());
428      }
429    }
430
431    public static final class DeterministicRandom extends Random {
432      @Keep
433      public DeterministicRandom() {
434        super(0);
435      }
436    }
437
438    public static final class DummyScheduledThreadPoolExecutor extends ScheduledThreadPoolExecutor {
439      public DummyScheduledThreadPoolExecutor() {
440        super(1);
441      }
442    }
443
444    public static final class DummyCountDownLatch extends CountDownLatch {
445      public DummyCountDownLatch() {
446        super(0);
447      }
448    }
449
450    public static final class DummyRunnable implements Runnable, Serializable {
451      @Override
452      public void run() {}
453    }
454
455    public static final class DummyThreadFactory implements ThreadFactory, Serializable {
456      @Override
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
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
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
485    public int compareTo(Object o) {
486      return toString().compareTo(o.toString());
487    }
488
489    @Override
490    public String toString() {
491      return "BY_TO_STRING";
492    }
493
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<@Nullable Object>
501      implements Serializable {
502    private static final AlwaysEqual INSTANCE = new AlwaysEqual();
503
504    @Override
505    public int compare(@Nullable Object o1, @Nullable Object o2) {
506      return 0;
507    }
508
509    @Override
510    public String toString() {
511      return "ALWAYS_EQUAL";
512    }
513
514    private Object readResolve() {
515      return INSTANCE;
516    }
517  }
518
519  private ArbitraryInstances() {}
520}