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