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