1/*
2 * Copyright (C) 2012 The Guava Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.common.testing;
18
19import static com.google.common.base.Preconditions.checkArgument;
20
21import com.google.common.annotations.Beta;
22import com.google.common.base.CharMatcher;
23import com.google.common.base.Charsets;
24import com.google.common.base.Defaults;
25import com.google.common.base.Equivalence;
26import com.google.common.base.Joiner;
27import com.google.common.base.Optional;
28import com.google.common.base.Predicate;
29import com.google.common.base.Predicates;
30import com.google.common.base.Splitter;
31import com.google.common.base.Stopwatch;
32import com.google.common.base.Ticker;
33import com.google.common.collect.BiMap;
34import com.google.common.collect.ClassToInstanceMap;
35import com.google.common.collect.ImmutableBiMap;
36import com.google.common.collect.ImmutableClassToInstanceMap;
37import com.google.common.collect.ImmutableCollection;
38import com.google.common.collect.ImmutableList;
39import com.google.common.collect.ImmutableListMultimap;
40import com.google.common.collect.ImmutableMap;
41import com.google.common.collect.ImmutableMultimap;
42import com.google.common.collect.ImmutableMultiset;
43import com.google.common.collect.ImmutableSet;
44import com.google.common.collect.ImmutableSetMultimap;
45import com.google.common.collect.ImmutableSortedMap;
46import com.google.common.collect.ImmutableSortedMultiset;
47import com.google.common.collect.ImmutableSortedSet;
48import com.google.common.collect.ImmutableTable;
49import com.google.common.collect.Iterators;
50import com.google.common.collect.ListMultimap;
51import com.google.common.collect.MapConstraint;
52import com.google.common.collect.MapConstraints;
53import com.google.common.collect.MapDifference;
54import com.google.common.collect.Maps;
55import com.google.common.collect.Multimap;
56import com.google.common.collect.Multimaps;
57import com.google.common.collect.Multiset;
58import com.google.common.collect.Ordering;
59import com.google.common.collect.PeekingIterator;
60import com.google.common.collect.Range;
61import com.google.common.collect.RowSortedTable;
62import com.google.common.collect.SetMultimap;
63import com.google.common.collect.Sets;
64import com.google.common.collect.SortedMapDifference;
65import com.google.common.collect.SortedMultiset;
66import com.google.common.collect.SortedSetMultimap;
67import com.google.common.collect.Table;
68import com.google.common.collect.Tables;
69import com.google.common.collect.TreeBasedTable;
70import com.google.common.collect.TreeMultimap;
71import com.google.common.io.ByteSink;
72import com.google.common.io.ByteSource;
73import com.google.common.io.ByteStreams;
74import com.google.common.io.CharSink;
75import com.google.common.io.CharSource;
76import com.google.common.primitives.Primitives;
77import com.google.common.primitives.UnsignedInteger;
78import com.google.common.primitives.UnsignedLong;
79
80import java.io.ByteArrayInputStream;
81import java.io.ByteArrayOutputStream;
82import java.io.File;
83import java.io.InputStream;
84import java.io.OutputStream;
85import java.io.PrintStream;
86import java.io.PrintWriter;
87import java.io.Reader;
88import java.io.Serializable;
89import java.io.StringReader;
90import java.io.StringWriter;
91import java.io.Writer;
92import java.lang.reflect.AnnotatedElement;
93import java.lang.reflect.Array;
94import java.lang.reflect.Constructor;
95import java.lang.reflect.Field;
96import java.lang.reflect.GenericDeclaration;
97import java.lang.reflect.InvocationTargetException;
98import java.lang.reflect.Modifier;
99import java.lang.reflect.Type;
100import java.math.BigDecimal;
101import java.math.BigInteger;
102import java.nio.Buffer;
103import java.nio.ByteBuffer;
104import java.nio.CharBuffer;
105import java.nio.DoubleBuffer;
106import java.nio.FloatBuffer;
107import java.nio.IntBuffer;
108import java.nio.LongBuffer;
109import java.nio.ShortBuffer;
110import java.nio.charset.Charset;
111import java.util.ArrayDeque;
112import java.util.Arrays;
113import java.util.Collection;
114import java.util.Comparator;
115import java.util.Currency;
116import java.util.Deque;
117import java.util.Iterator;
118import java.util.List;
119import java.util.ListIterator;
120import java.util.Locale;
121import java.util.Map;
122import java.util.NavigableMap;
123import java.util.NavigableSet;
124import java.util.Queue;
125import java.util.Random;
126import java.util.Set;
127import java.util.SortedMap;
128import java.util.SortedSet;
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;
147
148import javax.annotation.Nullable;
149
150/**
151 * Supplies an arbitrary "default" instance for a wide range of types, often useful in testing
152 * utilities.
153 *
154 * <p>Covers arrays, enums and common types defined in {@code java.lang}, {@code java.lang.reflect},
155 * {@code java.io}, {@code java.nio}, {@code java.math}, {@code java.util}, {@code
156 * java.util.concurrent}, {@code java.util.regex}, {@code com.google.common.base}, {@code
157 * com.google.common.collect} and {@code com.google.common.primitives}. In addition, if the type
158 * exposes at least one public static final constant of the same type, one of the constants will be
159 * used; or if the class exposes a public parameter-less constructor then it will be "new"d and
160 * returned.
161 *
162 * <p>All default instances returned by {@link #get} are generics-safe. Clients won't get type
163 * errors for using {@code get(Comparator.class)} as a {@code Comparator<Foo>}, for example.
164 * Immutable empty instances are returned for collection types; {@code ""} for string;
165 * {@code 0} for number types; reasonable default instance for other stateless types. For mutable
166 * types, a fresh instance is created each time {@code get()} is called.
167 *
168 * @author Kevin Bourrillion
169 * @author Ben Yu
170 * @since 12.0
171 */
172@Beta
173public final class ArbitraryInstances {
174
175  private static final Ordering<Field> BY_FIELD_NAME = new Ordering<Field>() {
176    @Override public int compare(Field left, Field right) {
177      return left.getName().compareTo(right.getName());
178    }
179  };
180
181  /**
182   * Returns a new {@code MatchResult} that corresponds to a successful match. Apache Harmony (used
183   * in Android) requires a successful match in order to generate a {@code MatchResult}:
184   * http://goo.gl/5VQFmC
185   */
186  private static MatchResult newMatchResult() {
187    Matcher matcher = Pattern.compile(".").matcher("X");
188    matcher.find();
189    return matcher.toMatchResult();
190  }
191
192  private static final ClassToInstanceMap<Object> DEFAULTS = 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(Optional.class, 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(Iterators.emptyIterator()))
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(SortedSetMultimap.class, Multimaps.unmodifiableSortedSetMultimap(TreeMultimap.create()))
262      .put(Multiset.class, ImmutableMultiset.of())
263      .put(ImmutableMultiset.class, ImmutableMultiset.of())
264      .put(SortedMultiset.class, ImmutableSortedMultiset.of())
265      .put(ImmutableSortedMultiset.class, ImmutableSortedMultiset.of())
266      .put(BiMap.class, ImmutableBiMap.of())
267      .put(ImmutableBiMap.class, ImmutableBiMap.of())
268      .put(Table.class, ImmutableTable.of())
269      .put(ImmutableTable.class, ImmutableTable.of())
270      .put(RowSortedTable.class, Tables.unmodifiableRowSortedTable(TreeBasedTable.create()))
271      .put(ClassToInstanceMap.class, ImmutableClassToInstanceMap.builder().build())
272      .put(ImmutableClassToInstanceMap.class, ImmutableClassToInstanceMap.builder().build())
273      .put(Comparable.class, ByToString.INSTANCE)
274      .put(Comparator.class, AlwaysEqual.INSTANCE)
275      .put(Ordering.class, AlwaysEqual.INSTANCE)
276      .put(Range.class, Range.all())
277      .put(MapConstraint.class, MapConstraints.notNull())
278      .put(MapDifference.class, Maps.difference(ImmutableMap.of(), ImmutableMap.of()))
279      .put(SortedMapDifference.class,
280          Maps.difference(ImmutableSortedMap.of(), ImmutableSortedMap.of()))
281      // reflect
282      .put(AnnotatedElement.class, Object.class)
283      .put(GenericDeclaration.class, Object.class)
284      .put(Type.class, Object.class)
285      .build();
286
287  /**
288   * type -> implementation. Inherently mutable interfaces and abstract classes are mapped to their
289   * default implementations and are "new"d upon get().
290   */
291  private static final ConcurrentMap<Class<?>, Class<?>> implementations = Maps.newConcurrentMap();
292
293  private static <T> void setImplementation(Class<T> type, Class<? extends T> implementation) {
294    checkArgument(type != implementation, "Don't register %s to itself!", type);
295    checkArgument(!DEFAULTS.containsKey(type),
296        "A default value was already registered for %s", type);
297    checkArgument(implementations.put(type, implementation) == null,
298        "Implementation for %s was already registered", type);
299  }
300
301  static {
302    setImplementation(Appendable.class, StringBuilder.class);
303    setImplementation(BlockingQueue.class, LinkedBlockingDeque.class);
304    setImplementation(BlockingDeque.class, LinkedBlockingDeque.class);
305    setImplementation(ConcurrentMap.class, ConcurrentHashMap.class);
306    setImplementation(ConcurrentNavigableMap.class, ConcurrentSkipListMap.class);
307    setImplementation(CountDownLatch.class, Dummies.DummyCountDownLatch.class);
308    setImplementation(Deque.class, ArrayDeque.class);
309    setImplementation(OutputStream.class, ByteArrayOutputStream.class);
310    setImplementation(PrintStream.class, Dummies.InMemoryPrintStream.class);
311    setImplementation(PrintWriter.class, Dummies.InMemoryPrintWriter.class);
312    setImplementation(Queue.class, ArrayDeque.class);
313    setImplementation(Random.class, Dummies.DeterministicRandom.class);
314    setImplementation(ScheduledThreadPoolExecutor.class,
315        Dummies.DummyScheduledThreadPoolExecutor.class);
316    setImplementation(ThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class);
317    setImplementation(Writer.class, StringWriter.class);
318    setImplementation(Runnable.class, Dummies.DummyRunnable.class);
319    setImplementation(ThreadFactory.class, Dummies.DummyThreadFactory.class);
320    setImplementation(Executor.class, Dummies.DummyExecutor.class);
321  }
322
323  @SuppressWarnings("unchecked") // it's a subtype map
324  @Nullable
325  private static <T> Class<? extends T> getImplementation(Class<T> type) {
326    return (Class<? extends T>) implementations.get(type);
327  }
328
329  private static final Logger logger = Logger.getLogger(ArbitraryInstances.class.getName());
330
331  /**
332   * Returns an arbitrary instance for {@code type}, or {@code null} if no arbitrary instance can
333   * be determined.
334   */
335  @Nullable public static <T> T get(Class<T> type) {
336    T defaultValue = DEFAULTS.getInstance(type);
337    if (defaultValue != null) {
338      return defaultValue;
339    }
340    Class<? extends T> implementation = getImplementation(type);
341    if (implementation != null) {
342      return get(implementation);
343    }
344    if (type.isEnum()) {
345      T[] enumConstants = type.getEnumConstants();
346      return (enumConstants.length == 0)
347          ? null
348          : enumConstants[0];
349    }
350    if (type.isArray()) {
351      return createEmptyArray(type);
352    }
353    T jvmDefault = Defaults.defaultValue(Primitives.unwrap(type));
354    if (jvmDefault != null) {
355      return jvmDefault;
356    }
357    if (Modifier.isAbstract(type.getModifiers()) || !Modifier.isPublic(type.getModifiers())) {
358      return arbitraryConstantInstanceOrNull(type);
359    }
360    final Constructor<T> constructor;
361    try {
362      constructor = type.getConstructor();
363    } catch (NoSuchMethodException e) {
364      return arbitraryConstantInstanceOrNull(type);
365    }
366    constructor.setAccessible(true); // accessibility check is too slow
367    try {
368      return constructor.newInstance();
369    } catch (InstantiationException impossible) {
370      throw new AssertionError(impossible);
371    } catch (IllegalAccessException impossible) {
372      throw new AssertionError(impossible);
373    } catch (InvocationTargetException e) {
374      logger.log(Level.WARNING, "Exception while invoking default constructor.", e.getCause());
375      return arbitraryConstantInstanceOrNull(type);
376    }
377  }
378
379  @Nullable private static <T> T arbitraryConstantInstanceOrNull(Class<T> type) {
380    Field[] fields = type.getDeclaredFields();
381    Arrays.sort(fields, BY_FIELD_NAME);
382    for (Field field : fields) {
383      if (Modifier.isPublic(field.getModifiers())
384          && Modifier.isStatic(field.getModifiers())
385          && Modifier.isFinal(field.getModifiers())) {
386        if (field.getGenericType() == field.getType()
387            && type.isAssignableFrom(field.getType())) {
388          field.setAccessible(true);
389          try {
390            T constant = type.cast(field.get(null));
391            if (constant != null) {
392              return constant;
393            }
394          } catch (IllegalAccessException impossible) {
395            throw new AssertionError(impossible);
396          }
397        }
398      }
399    }
400    return null;
401  }
402
403  private static <T> T createEmptyArray(Class<T> arrayType) {
404    return arrayType.cast(Array.newInstance(arrayType.getComponentType(), 0));
405  }
406
407  // Internal implementations of some classes, with public default constructor that get() needs.
408  private static final class Dummies {
409
410    public static final class InMemoryPrintStream extends PrintStream {
411      public InMemoryPrintStream() {
412        super(new ByteArrayOutputStream());
413      }
414    }
415
416    public static final class InMemoryPrintWriter extends PrintWriter {
417      public InMemoryPrintWriter() {
418        super(new StringWriter());
419      }
420    }
421
422    public static final class DeterministicRandom extends Random {
423      @SuppressWarnings("unused") // invoked by reflection
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 public void run() {}
443    }
444
445    public static final class DummyThreadFactory implements ThreadFactory, Serializable {
446      @Override public Thread newThread(Runnable r) {
447        return new Thread(r);
448      }
449    }
450
451    public static final class DummyExecutor implements Executor, Serializable {
452      @Override public void execute(Runnable command) {}
453    }
454  }
455
456  private static final class NullByteSink extends ByteSink implements Serializable {
457    private static final NullByteSink INSTANCE = new NullByteSink();
458
459    @Override public OutputStream openStream() {
460      return ByteStreams.nullOutputStream();
461    }
462  }
463
464  // Compare by toString() to satisfy 2 properties:
465  // 1. compareTo(null) should throw NullPointerException
466  // 2. the order is deterministic and easy to understand, for debugging purpose.
467  private static final class ByToString implements Comparable<Object>, Serializable {
468    private static final ByToString INSTANCE = new ByToString();
469
470    @Override public int compareTo(Object o) {
471      return toString().compareTo(o.toString());
472    }
473
474    @Override public String toString() {
475      return "BY_TO_STRING";
476    }
477
478    private Object readResolve() {
479      return INSTANCE;
480    }
481  }
482
483  // Always equal is a valid total ordering. And it works for any Object.
484  private static final class AlwaysEqual extends Ordering<Object> implements Serializable {
485    private static final AlwaysEqual INSTANCE = new AlwaysEqual();
486
487    @Override public int compare(Object o1, Object o2) {
488      return 0;
489    }
490
491    @Override public String toString() {
492      return "ALWAYS_EQUAL";
493    }
494
495    private Object readResolve() {
496      return INSTANCE;
497    }
498  }
499
500  private ArbitraryInstances() {}
501}
502