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