2
* Copyright (C) 2012 The Guava Authors
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
8
* http://www.apache.org/licenses/LICENSE-2.0
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.
17
package com.google.common.testing;
19
import static com.google.common.base.Preconditions.checkArgument;
20
import static java.util.Objects.requireNonNull;
22
import com.google.common.annotations.GwtIncompatible;
23
import com.google.common.annotations.J2ktIncompatible;
24
import com.google.common.base.CharMatcher;
25
import com.google.common.base.Charsets;
26
import com.google.common.base.Defaults;
27
import com.google.common.base.Equivalence;
28
import com.google.common.base.Joiner;
29
import com.google.common.base.Predicate;
30
import com.google.common.base.Predicates;
31
import com.google.common.base.Splitter;
32
import com.google.common.base.Stopwatch;
33
import com.google.common.base.Ticker;
34
import com.google.common.collect.BiMap;
35
import com.google.common.collect.ClassToInstanceMap;
36
import com.google.common.collect.ImmutableBiMap;
37
import com.google.common.collect.ImmutableClassToInstanceMap;
38
import com.google.common.collect.ImmutableCollection;
39
import com.google.common.collect.ImmutableList;
40
import com.google.common.collect.ImmutableListMultimap;
41
import com.google.common.collect.ImmutableMap;
42
import com.google.common.collect.ImmutableMultimap;
43
import com.google.common.collect.ImmutableMultiset;
44
import com.google.common.collect.ImmutableSet;
45
import com.google.common.collect.ImmutableSetMultimap;
46
import com.google.common.collect.ImmutableSortedMap;
47
import com.google.common.collect.ImmutableSortedMultiset;
48
import com.google.common.collect.ImmutableSortedSet;
49
import com.google.common.collect.ImmutableTable;
50
import com.google.common.collect.Iterators;
51
import com.google.common.collect.ListMultimap;
52
import com.google.common.collect.MapDifference;
53
import com.google.common.collect.Maps;
54
import com.google.common.collect.Multimap;
55
import com.google.common.collect.Multimaps;
56
import com.google.common.collect.Multiset;
57
import com.google.common.collect.Ordering;
58
import com.google.common.collect.PeekingIterator;
59
import com.google.common.collect.Range;
60
import com.google.common.collect.RowSortedTable;
61
import com.google.common.collect.SetMultimap;
62
import com.google.common.collect.Sets;
63
import com.google.common.collect.SortedMapDifference;
64
import com.google.common.collect.SortedMultiset;
65
import com.google.common.collect.SortedSetMultimap;
66
import com.google.common.collect.Table;
67
import com.google.common.collect.Tables;
68
import com.google.common.collect.TreeBasedTable;
69
import com.google.common.collect.TreeMultimap;
70
import com.google.common.io.ByteSink;
71
import com.google.common.io.ByteSource;
72
import com.google.common.io.ByteStreams;
73
import com.google.common.io.CharSink;
74
import com.google.common.io.CharSource;
75
import com.google.common.primitives.Primitives;
76
import com.google.common.primitives.UnsignedInteger;
77
import com.google.common.primitives.UnsignedLong;
78
import com.google.errorprone.annotations.Keep;
79
import java.io.ByteArrayInputStream;
80
import java.io.ByteArrayOutputStream;
82
import java.io.InputStream;
83
import java.io.OutputStream;
84
import java.io.PrintStream;
85
import java.io.PrintWriter;
87
import java.io.Serializable;
88
import java.io.StringReader;
89
import java.io.StringWriter;
91
import java.lang.reflect.AnnotatedElement;
92
import java.lang.reflect.Array;
93
import java.lang.reflect.Constructor;
94
import java.lang.reflect.Field;
95
import java.lang.reflect.GenericDeclaration;
96
import java.lang.reflect.InvocationTargetException;
97
import java.lang.reflect.Modifier;
98
import java.lang.reflect.Type;
99
import java.math.BigDecimal;
100
import java.math.BigInteger;
101
import java.nio.Buffer;
102
import java.nio.ByteBuffer;
103
import java.nio.CharBuffer;
104
import java.nio.DoubleBuffer;
105
import java.nio.FloatBuffer;
106
import java.nio.IntBuffer;
107
import java.nio.LongBuffer;
108
import java.nio.ShortBuffer;
109
import java.nio.charset.Charset;
110
import java.util.ArrayDeque;
111
import java.util.Arrays;
112
import java.util.Collection;
113
import java.util.Comparator;
114
import java.util.Currency;
115
import java.util.Deque;
116
import java.util.Iterator;
117
import java.util.List;
118
import java.util.ListIterator;
119
import java.util.Locale;
121
import java.util.NavigableMap;
122
import java.util.NavigableSet;
123
import java.util.Optional;
124
import java.util.OptionalDouble;
125
import java.util.OptionalInt;
126
import java.util.OptionalLong;
127
import java.util.Queue;
128
import java.util.Random;
130
import java.util.SortedMap;
131
import java.util.SortedSet;
132
import java.util.UUID;
133
import java.util.concurrent.BlockingDeque;
134
import java.util.concurrent.BlockingQueue;
135
import java.util.concurrent.ConcurrentHashMap;
136
import java.util.concurrent.ConcurrentMap;
137
import java.util.concurrent.ConcurrentNavigableMap;
138
import java.util.concurrent.ConcurrentSkipListMap;
139
import java.util.concurrent.CountDownLatch;
140
import java.util.concurrent.Executor;
141
import java.util.concurrent.LinkedBlockingDeque;
142
import java.util.concurrent.ScheduledThreadPoolExecutor;
143
import java.util.concurrent.ThreadFactory;
144
import java.util.concurrent.ThreadPoolExecutor;
145
import java.util.concurrent.TimeUnit;
146
import java.util.logging.Level;
147
import java.util.logging.Logger;
148
import java.util.regex.MatchResult;
149
import java.util.regex.Matcher;
150
import java.util.regex.Pattern;
151
import java.util.stream.Stream;
152
import org.checkerframework.checker.nullness.qual.Nullable;
155
* Supplies an arbitrary "default" instance for a wide range of types, often useful in testing
158
* <p>Covers arrays, enums and common types defined in {@code java.lang}, {@code java.lang.reflect},
159
* {@code java.io}, {@code java.nio}, {@code java.math}, {@code java.util}, {@code
160
* java.util.concurrent}, {@code java.util.regex}, {@code com.google.common.base}, {@code
161
* com.google.common.collect} and {@code com.google.common.primitives}. In addition, if the type
162
* exposes at least one public static final constant of the same type, one of the constants will be
163
* used; or if the class exposes a public parameter-less constructor then it will be "new"d and
166
* <p>All default instances returned by {@link #get} are generics-safe. Clients won't get type
167
* errors for using {@code get(Comparator.class)} as a {@code Comparator<Foo>}, for example.
168
* Immutable empty instances are returned for collection types; {@code ""} for string; {@code 0} for
169
* number types; reasonable default instance for other stateless types. For mutable types, a fresh
170
* instance is created each time {@code get()} is called.
172
* @author Kevin Bourrillion
178
@ElementTypesAreNonnullByDefault
179
public final class ArbitraryInstances {
181
private static final Ordering<Field> BY_FIELD_NAME =
182
new Ordering<Field>() {
184
public int compare(Field left, Field right) {
185
return left.getName().compareTo(right.getName());
190
* Returns a new {@code MatchResult} that corresponds to a successful match. Apache Harmony (used
191
* in Android) requires a successful match in order to generate a {@code MatchResult}:
192
* http://goo.gl/5VQFmC
194
private static MatchResult createMatchResult() {
195
Matcher matcher = Pattern.compile(".").matcher("X");
197
return matcher.toMatchResult();
200
private static final ClassToInstanceMap<Object> DEFAULTS =
201
ImmutableClassToInstanceMap.builder()
203
.put(Object.class, "")
204
.put(Number.class, 0)
205
.put(UnsignedInteger.class, UnsignedInteger.ZERO)
206
.put(UnsignedLong.class, UnsignedLong.ZERO)
207
.put(BigInteger.class, BigInteger.ZERO)
208
.put(BigDecimal.class, BigDecimal.ZERO)
209
.put(CharSequence.class, "")
210
.put(String.class, "")
211
.put(Pattern.class, Pattern.compile(""))
212
.put(MatchResult.class, createMatchResult())
213
.put(TimeUnit.class, TimeUnit.SECONDS)
214
.put(Charset.class, Charsets.UTF_8)
215
.put(Currency.class, Currency.getInstance(Locale.US))
216
.put(Locale.class, Locale.US)
217
.put(Optional.class, Optional.empty())
218
.put(OptionalInt.class, OptionalInt.empty())
219
.put(OptionalLong.class, OptionalLong.empty())
220
.put(OptionalDouble.class, OptionalDouble.empty())
221
.put(UUID.class, UUID.randomUUID())
223
.put(CharMatcher.class, CharMatcher.none())
224
.put(Joiner.class, Joiner.on(','))
225
.put(Splitter.class, Splitter.on(','))
226
.put(com.google.common.base.Optional.class, com.google.common.base.Optional.absent())
227
.put(Predicate.class, Predicates.alwaysTrue())
228
.put(Equivalence.class, Equivalence.equals())
229
.put(Ticker.class, Ticker.systemTicker())
230
.put(Stopwatch.class, Stopwatch.createUnstarted())
232
.put(InputStream.class, new ByteArrayInputStream(new byte[0]))
233
.put(ByteArrayInputStream.class, new ByteArrayInputStream(new byte[0]))
234
.put(Readable.class, new StringReader(""))
235
.put(Reader.class, new StringReader(""))
236
.put(StringReader.class, new StringReader(""))
237
.put(Buffer.class, ByteBuffer.allocate(0))
238
.put(CharBuffer.class, CharBuffer.allocate(0))
239
.put(ByteBuffer.class, ByteBuffer.allocate(0))
240
.put(ShortBuffer.class, ShortBuffer.allocate(0))
241
.put(IntBuffer.class, IntBuffer.allocate(0))
242
.put(LongBuffer.class, LongBuffer.allocate(0))
243
.put(FloatBuffer.class, FloatBuffer.allocate(0))
244
.put(DoubleBuffer.class, DoubleBuffer.allocate(0))
245
.put(File.class, new File(""))
246
.put(ByteSource.class, ByteSource.empty())
247
.put(CharSource.class, CharSource.empty())
248
.put(ByteSink.class, NullByteSink.INSTANCE)
249
.put(CharSink.class, NullByteSink.INSTANCE.asCharSink(Charsets.UTF_8))
250
// All collections are immutable empty. So safe for any type parameter.
251
.put(Iterator.class, ImmutableSet.of().iterator())
252
.put(PeekingIterator.class, Iterators.peekingIterator(ImmutableSet.of().iterator()))
253
.put(ListIterator.class, ImmutableList.of().listIterator())
254
.put(Iterable.class, ImmutableSet.of())
255
.put(Collection.class, ImmutableList.of())
256
.put(ImmutableCollection.class, ImmutableList.of())
257
.put(List.class, ImmutableList.of())
258
.put(ImmutableList.class, ImmutableList.of())
259
.put(Set.class, ImmutableSet.of())
260
.put(ImmutableSet.class, ImmutableSet.of())
261
.put(SortedSet.class, ImmutableSortedSet.of())
262
.put(ImmutableSortedSet.class, ImmutableSortedSet.of())
263
.put(NavigableSet.class, Sets.unmodifiableNavigableSet(Sets.newTreeSet()))
264
.put(Map.class, ImmutableMap.of())
265
.put(ImmutableMap.class, ImmutableMap.of())
266
.put(SortedMap.class, ImmutableSortedMap.of())
267
.put(ImmutableSortedMap.class, ImmutableSortedMap.of())
268
.put(NavigableMap.class, Maps.unmodifiableNavigableMap(Maps.newTreeMap()))
269
.put(Multimap.class, ImmutableMultimap.of())
270
.put(ImmutableMultimap.class, ImmutableMultimap.of())
271
.put(ListMultimap.class, ImmutableListMultimap.of())
272
.put(ImmutableListMultimap.class, ImmutableListMultimap.of())
273
.put(SetMultimap.class, ImmutableSetMultimap.of())
274
.put(ImmutableSetMultimap.class, ImmutableSetMultimap.of())
276
SortedSetMultimap.class,
277
Multimaps.unmodifiableSortedSetMultimap(TreeMultimap.create()))
278
.put(Multiset.class, ImmutableMultiset.of())
279
.put(ImmutableMultiset.class, ImmutableMultiset.of())
280
.put(SortedMultiset.class, ImmutableSortedMultiset.of())
281
.put(ImmutableSortedMultiset.class, ImmutableSortedMultiset.of())
282
.put(BiMap.class, ImmutableBiMap.of())
283
.put(ImmutableBiMap.class, ImmutableBiMap.of())
284
.put(Table.class, ImmutableTable.of())
285
.put(ImmutableTable.class, ImmutableTable.of())
286
.put(RowSortedTable.class, Tables.unmodifiableRowSortedTable(TreeBasedTable.create()))
287
.put(ClassToInstanceMap.class, ImmutableClassToInstanceMap.builder().build())
288
.put(ImmutableClassToInstanceMap.class, ImmutableClassToInstanceMap.builder().build())
289
.put(Comparable.class, ByToString.INSTANCE)
290
.put(Comparator.class, AlwaysEqual.INSTANCE)
291
.put(Ordering.class, AlwaysEqual.INSTANCE)
292
.put(Range.class, Range.all())
293
.put(MapDifference.class, Maps.difference(ImmutableMap.of(), ImmutableMap.of()))
295
SortedMapDifference.class,
296
Maps.difference(ImmutableSortedMap.of(), ImmutableSortedMap.of()))
298
.put(AnnotatedElement.class, Object.class)
299
.put(GenericDeclaration.class, Object.class)
300
.put(Type.class, Object.class)
304
* type → implementation. Inherently mutable interfaces and abstract classes are mapped to their
305
* default implementations and are "new"d upon get().
307
private static final ConcurrentMap<Class<?>, Class<?>> implementations = Maps.newConcurrentMap();
309
private static <T> void setImplementation(Class<T> type, Class<? extends T> implementation) {
310
checkArgument(type != implementation, "Don't register %s to itself!", type);
312
!DEFAULTS.containsKey(type), "A default value was already registered for %s", type);
314
implementations.put(type, implementation) == null,
315
"Implementation for %s was already registered",
320
setImplementation(Appendable.class, StringBuilder.class);
321
setImplementation(BlockingQueue.class, LinkedBlockingDeque.class);
322
setImplementation(BlockingDeque.class, LinkedBlockingDeque.class);
323
setImplementation(ConcurrentMap.class, ConcurrentHashMap.class);
324
setImplementation(ConcurrentNavigableMap.class, ConcurrentSkipListMap.class);
325
setImplementation(CountDownLatch.class, Dummies.DummyCountDownLatch.class);
326
setImplementation(Deque.class, ArrayDeque.class);
327
setImplementation(OutputStream.class, ByteArrayOutputStream.class);
328
setImplementation(PrintStream.class, Dummies.InMemoryPrintStream.class);
329
setImplementation(PrintWriter.class, Dummies.InMemoryPrintWriter.class);
330
setImplementation(Queue.class, ArrayDeque.class);
331
setImplementation(Random.class, Dummies.DeterministicRandom.class);
333
ScheduledThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class);
334
setImplementation(ThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class);
335
setImplementation(Writer.class, StringWriter.class);
336
setImplementation(Runnable.class, Dummies.DummyRunnable.class);
337
setImplementation(ThreadFactory.class, Dummies.DummyThreadFactory.class);
338
setImplementation(Executor.class, Dummies.DummyExecutor.class);
341
@SuppressWarnings("unchecked") // it's a subtype map
342
private static <T> @Nullable Class<? extends T> getImplementation(Class<T> type) {
343
return (Class<? extends T>) implementations.get(type);
346
private static final Logger logger = Logger.getLogger(ArbitraryInstances.class.getName());
349
* Returns an arbitrary instance for {@code type}, or {@code null} if no arbitrary instance can be
352
public static <T> @Nullable T get(Class<T> type) {
353
T defaultValue = DEFAULTS.getInstance(type);
354
if (defaultValue != null) {
357
Class<? extends T> implementation = getImplementation(type);
358
if (implementation != null) {
359
return get(implementation);
361
if (type == Stream.class) {
362
return type.cast(Stream.empty());
365
T[] enumConstants = type.getEnumConstants();
366
return (enumConstants == null || enumConstants.length == 0) ? null : enumConstants[0];
368
if (type.isArray()) {
369
return createEmptyArray(type);
371
T jvmDefault = Defaults.defaultValue(Primitives.unwrap(type));
372
if (jvmDefault != null) {
375
if (Modifier.isAbstract(type.getModifiers()) || !Modifier.isPublic(type.getModifiers())) {
376
return arbitraryConstantInstanceOrNull(type);
378
final Constructor<T> constructor;
380
constructor = type.getConstructor();
381
} catch (NoSuchMethodException e) {
382
return arbitraryConstantInstanceOrNull(type);
384
constructor.setAccessible(true); // accessibility check is too slow
386
return constructor.newInstance();
387
} catch (InstantiationException | IllegalAccessException impossible) {
388
throw new AssertionError(impossible);
389
} catch (InvocationTargetException e) {
390
logger.log(Level.WARNING, "Exception while invoking default constructor.", e.getCause());
391
return arbitraryConstantInstanceOrNull(type);
395
private static <T> @Nullable T arbitraryConstantInstanceOrNull(Class<T> type) {
396
Field[] fields = type.getDeclaredFields();
397
Arrays.sort(fields, BY_FIELD_NAME);
398
for (Field field : fields) {
399
if (Modifier.isPublic(field.getModifiers())
400
&& Modifier.isStatic(field.getModifiers())
401
&& Modifier.isFinal(field.getModifiers())) {
402
if (field.getGenericType() == field.getType() && type.isAssignableFrom(field.getType())) {
403
field.setAccessible(true);
405
T constant = type.cast(field.get(null));
406
if (constant != null) {
409
} catch (IllegalAccessException impossible) {
410
throw new AssertionError(impossible);
418
private static <T> T createEmptyArray(Class<T> arrayType) {
419
// getComponentType() is non-null because we call createEmptyArray only with an array type.
420
return arrayType.cast(Array.newInstance(requireNonNull(arrayType.getComponentType()), 0));
423
// Internal implementations of some classes, with public default constructor that get() needs.
424
private static final class Dummies {
426
public static final class InMemoryPrintStream extends PrintStream {
427
public InMemoryPrintStream() {
428
super(new ByteArrayOutputStream());
432
public static final class InMemoryPrintWriter extends PrintWriter {
433
public InMemoryPrintWriter() {
434
super(new StringWriter());
438
public static final class DeterministicRandom extends Random {
440
public DeterministicRandom() {
445
public static final class DummyScheduledThreadPoolExecutor extends ScheduledThreadPoolExecutor {
446
public DummyScheduledThreadPoolExecutor() {
451
public static final class DummyCountDownLatch extends CountDownLatch {
452
public DummyCountDownLatch() {
457
public static final class DummyRunnable implements Runnable, Serializable {
462
public static final class DummyThreadFactory implements ThreadFactory, Serializable {
464
public Thread newThread(Runnable r) {
465
return new Thread(r);
469
public static final class DummyExecutor implements Executor, Serializable {
471
public void execute(Runnable command) {}
475
private static final class NullByteSink extends ByteSink implements Serializable {
476
private static final NullByteSink INSTANCE = new NullByteSink();
479
public OutputStream openStream() {
480
return ByteStreams.nullOutputStream();
484
// Compare by toString() to satisfy 2 properties:
485
// 1. compareTo(null) should throw NullPointerException
486
// 2. the order is deterministic and easy to understand, for debugging purpose.
487
@SuppressWarnings("ComparableType")
488
private static final class ByToString implements Comparable<Object>, Serializable {
489
private static final ByToString INSTANCE = new ByToString();
492
public int compareTo(Object o) {
493
return toString().compareTo(o.toString());
497
public String toString() {
498
return "BY_TO_STRING";
501
private Object readResolve() {
506
// Always equal is a valid total ordering. And it works for any Object.
507
private static final class AlwaysEqual extends Ordering<@Nullable Object>
508
implements Serializable {
509
private static final AlwaysEqual INSTANCE = new AlwaysEqual();
512
public int compare(@Nullable Object o1, @Nullable Object o2) {
517
public String toString() {
518
return "ALWAYS_EQUAL";
521
private Object readResolve() {
526
private ArbitraryInstances() {}