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