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