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