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.Queue; 122 import java.util.Random; 123 import java.util.Set; 124 import java.util.SortedMap; 125 import java.util.SortedSet; 126 import java.util.concurrent.BlockingDeque; 127 import java.util.concurrent.BlockingQueue; 128 import java.util.concurrent.ConcurrentHashMap; 129 import java.util.concurrent.ConcurrentMap; 130 import java.util.concurrent.ConcurrentNavigableMap; 131 import java.util.concurrent.ConcurrentSkipListMap; 132 import java.util.concurrent.CountDownLatch; 133 import java.util.concurrent.Executor; 134 import java.util.concurrent.LinkedBlockingDeque; 135 import java.util.concurrent.ScheduledThreadPoolExecutor; 136 import java.util.concurrent.ThreadFactory; 137 import java.util.concurrent.ThreadPoolExecutor; 138 import java.util.concurrent.TimeUnit; 139 import java.util.logging.Level; 140 import java.util.logging.Logger; 141 import java.util.regex.MatchResult; 142 import java.util.regex.Matcher; 143 import java.util.regex.Pattern; 144 import org.checkerframework.checker.nullness.compatqual.NullableDecl; 145 146 /** 147 * Supplies an arbitrary "default" instance for a wide range of types, often useful in testing 148 * utilities. 149 * 150 * <p>Covers arrays, enums and common types defined in {@code java.lang}, {@code java.lang.reflect}, 151 * {@code java.io}, {@code java.nio}, {@code java.math}, {@code java.util}, {@code 152 * java.util.concurrent}, {@code java.util.regex}, {@code com.google.common.base}, {@code 153 * com.google.common.collect} and {@code com.google.common.primitives}. In addition, if the type 154 * exposes at least one public static final constant of the same type, one of the constants will be 155 * used; or if the class exposes a public parameter-less constructor then it will be "new"d and 156 * returned. 157 * 158 * <p>All default instances returned by {@link #get} are generics-safe. Clients won't get type 159 * errors for using {@code get(Comparator.class)} as a {@code Comparator<Foo>}, for example. 160 * Immutable empty instances are returned for collection types; {@code ""} for string; {@code 0} for 161 * number types; reasonable default instance for other stateless types. For mutable types, a fresh 162 * instance is created each time {@code get()} is called. 163 * 164 * @author Kevin Bourrillion 165 * @author Ben Yu 166 * @since 12.0 167 */ 168 @Beta 169 @GwtIncompatible 170 public final class ArbitraryInstances { 171 172 private static final Ordering<Field> BY_FIELD_NAME = 173 new Ordering<Field>() { 174 @Override 175 public int compare(Field left, Field right) { 176 return left.getName().compareTo(right.getName()); 177 } 178 }; 179 180 /** 181 * Returns a new {@code MatchResult} that corresponds to a successful match. Apache Harmony (used 182 * in Android) requires a successful match in order to generate a {@code MatchResult}: 183 * http://goo.gl/5VQFmC 184 */ newMatchResult()185 private static MatchResult newMatchResult() { 186 Matcher matcher = Pattern.compile(".").matcher("X"); 187 matcher.find(); 188 return matcher.toMatchResult(); 189 } 190 191 private static final ClassToInstanceMap<Object> DEFAULTS = 192 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(com.google.common.base.Optional.class, com.google.common.base.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(ImmutableSet.of().iterator())) 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( 262 SortedSetMultimap.class, 263 Multimaps.unmodifiableSortedSetMultimap(TreeMultimap.create())) 264 .put(Multiset.class, ImmutableMultiset.of()) 265 .put(ImmutableMultiset.class, ImmutableMultiset.of()) 266 .put(SortedMultiset.class, ImmutableSortedMultiset.of()) 267 .put(ImmutableSortedMultiset.class, ImmutableSortedMultiset.of()) 268 .put(BiMap.class, ImmutableBiMap.of()) 269 .put(ImmutableBiMap.class, ImmutableBiMap.of()) 270 .put(Table.class, ImmutableTable.of()) 271 .put(ImmutableTable.class, ImmutableTable.of()) 272 .put(RowSortedTable.class, Tables.unmodifiableRowSortedTable(TreeBasedTable.create())) 273 .put(ClassToInstanceMap.class, ImmutableClassToInstanceMap.builder().build()) 274 .put(ImmutableClassToInstanceMap.class, ImmutableClassToInstanceMap.builder().build()) 275 .put(Comparable.class, ByToString.INSTANCE) 276 .put(Comparator.class, AlwaysEqual.INSTANCE) 277 .put(Ordering.class, AlwaysEqual.INSTANCE) 278 .put(Range.class, Range.all()) 279 .put(MapDifference.class, Maps.difference(ImmutableMap.of(), ImmutableMap.of())) 280 .put( 281 SortedMapDifference.class, 282 Maps.difference(ImmutableSortedMap.of(), ImmutableSortedMap.of())) 283 // reflect 284 .put(AnnotatedElement.class, Object.class) 285 .put(GenericDeclaration.class, Object.class) 286 .put(Type.class, Object.class) 287 .build(); 288 289 /** 290 * type → implementation. Inherently mutable interfaces and abstract classes are mapped to their 291 * default implementations and are "new"d upon get(). 292 */ 293 private static final ConcurrentMap<Class<?>, Class<?>> implementations = Maps.newConcurrentMap(); 294 setImplementation(Class<T> type, Class<? extends T> implementation)295 private static <T> void setImplementation(Class<T> type, Class<? extends T> implementation) { 296 checkArgument(type != implementation, "Don't register %s to itself!", type); 297 checkArgument( 298 !DEFAULTS.containsKey(type), "A default value was already registered for %s", type); 299 checkArgument( 300 implementations.put(type, implementation) == null, 301 "Implementation for %s was already registered", 302 type); 303 } 304 305 static { setImplementation(Appendable.class, StringBuilder.class)306 setImplementation(Appendable.class, StringBuilder.class); setImplementation(BlockingQueue.class, LinkedBlockingDeque.class)307 setImplementation(BlockingQueue.class, LinkedBlockingDeque.class); setImplementation(BlockingDeque.class, LinkedBlockingDeque.class)308 setImplementation(BlockingDeque.class, LinkedBlockingDeque.class); setImplementation(ConcurrentMap.class, ConcurrentHashMap.class)309 setImplementation(ConcurrentMap.class, ConcurrentHashMap.class); setImplementation(ConcurrentNavigableMap.class, ConcurrentSkipListMap.class)310 setImplementation(ConcurrentNavigableMap.class, ConcurrentSkipListMap.class); setImplementation(CountDownLatch.class, Dummies.DummyCountDownLatch.class)311 setImplementation(CountDownLatch.class, Dummies.DummyCountDownLatch.class); setImplementation(Deque.class, ArrayDeque.class)312 setImplementation(Deque.class, ArrayDeque.class); setImplementation(OutputStream.class, ByteArrayOutputStream.class)313 setImplementation(OutputStream.class, ByteArrayOutputStream.class); setImplementation(PrintStream.class, Dummies.InMemoryPrintStream.class)314 setImplementation(PrintStream.class, Dummies.InMemoryPrintStream.class); setImplementation(PrintWriter.class, Dummies.InMemoryPrintWriter.class)315 setImplementation(PrintWriter.class, Dummies.InMemoryPrintWriter.class); setImplementation(Queue.class, ArrayDeque.class)316 setImplementation(Queue.class, ArrayDeque.class); setImplementation(Random.class, Dummies.DeterministicRandom.class)317 setImplementation(Random.class, Dummies.DeterministicRandom.class); setImplementation( ScheduledThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class)318 setImplementation( 319 ScheduledThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class); setImplementation(ThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class)320 setImplementation(ThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class); setImplementation(Writer.class, StringWriter.class)321 setImplementation(Writer.class, StringWriter.class); setImplementation(Runnable.class, Dummies.DummyRunnable.class)322 setImplementation(Runnable.class, Dummies.DummyRunnable.class); setImplementation(ThreadFactory.class, Dummies.DummyThreadFactory.class)323 setImplementation(ThreadFactory.class, Dummies.DummyThreadFactory.class); setImplementation(Executor.class, Dummies.DummyExecutor.class)324 setImplementation(Executor.class, Dummies.DummyExecutor.class); 325 } 326 327 @SuppressWarnings("unchecked") // it's a subtype map 328 @NullableDecl getImplementation(Class<T> type)329 private static <T> Class<? extends T> getImplementation(Class<T> type) { 330 return (Class<? extends T>) implementations.get(type); 331 } 332 333 private static final Logger logger = Logger.getLogger(ArbitraryInstances.class.getName()); 334 335 /** 336 * Returns an arbitrary instance for {@code type}, or {@code null} if no arbitrary instance can be 337 * determined. 338 */ 339 @NullableDecl get(Class<T> type)340 public static <T> T get(Class<T> type) { 341 T defaultValue = DEFAULTS.getInstance(type); 342 if (defaultValue != null) { 343 return defaultValue; 344 } 345 Class<? extends T> implementation = getImplementation(type); 346 if (implementation != null) { 347 return get(implementation); 348 } 349 if (type.isEnum()) { 350 T[] enumConstants = type.getEnumConstants(); 351 return (enumConstants.length == 0) ? null : enumConstants[0]; 352 } 353 if (type.isArray()) { 354 return createEmptyArray(type); 355 } 356 T jvmDefault = Defaults.defaultValue(Primitives.unwrap(type)); 357 if (jvmDefault != null) { 358 return jvmDefault; 359 } 360 if (Modifier.isAbstract(type.getModifiers()) || !Modifier.isPublic(type.getModifiers())) { 361 return arbitraryConstantInstanceOrNull(type); 362 } 363 final Constructor<T> constructor; 364 try { 365 constructor = type.getConstructor(); 366 } catch (NoSuchMethodException e) { 367 return arbitraryConstantInstanceOrNull(type); 368 } 369 constructor.setAccessible(true); // accessibility check is too slow 370 try { 371 return constructor.newInstance(); 372 } catch (InstantiationException | IllegalAccessException impossible) { 373 throw new AssertionError(impossible); 374 } catch (InvocationTargetException e) { 375 logger.log(Level.WARNING, "Exception while invoking default constructor.", e.getCause()); 376 return arbitraryConstantInstanceOrNull(type); 377 } 378 } 379 380 @NullableDecl arbitraryConstantInstanceOrNull(Class<T> type)381 private static <T> T arbitraryConstantInstanceOrNull(Class<T> type) { 382 Field[] fields = type.getDeclaredFields(); 383 Arrays.sort(fields, BY_FIELD_NAME); 384 for (Field field : fields) { 385 if (Modifier.isPublic(field.getModifiers()) 386 && Modifier.isStatic(field.getModifiers()) 387 && Modifier.isFinal(field.getModifiers())) { 388 if (field.getGenericType() == field.getType() && type.isAssignableFrom(field.getType())) { 389 field.setAccessible(true); 390 try { 391 T constant = type.cast(field.get(null)); 392 if (constant != null) { 393 return constant; 394 } 395 } catch (IllegalAccessException impossible) { 396 throw new AssertionError(impossible); 397 } 398 } 399 } 400 } 401 return null; 402 } 403 createEmptyArray(Class<T> arrayType)404 private static <T> T createEmptyArray(Class<T> arrayType) { 405 return arrayType.cast(Array.newInstance(arrayType.getComponentType(), 0)); 406 } 407 408 // Internal implementations of some classes, with public default constructor that get() needs. 409 private static final class Dummies { 410 411 public static final class InMemoryPrintStream extends PrintStream { InMemoryPrintStream()412 public InMemoryPrintStream() { 413 super(new ByteArrayOutputStream()); 414 } 415 } 416 417 public static final class InMemoryPrintWriter extends PrintWriter { InMemoryPrintWriter()418 public InMemoryPrintWriter() { 419 super(new StringWriter()); 420 } 421 } 422 423 public static final class DeterministicRandom extends Random { DeterministicRandom()424 public DeterministicRandom() { 425 super(0); 426 } 427 } 428 429 public static final class DummyScheduledThreadPoolExecutor extends ScheduledThreadPoolExecutor { DummyScheduledThreadPoolExecutor()430 public DummyScheduledThreadPoolExecutor() { 431 super(1); 432 } 433 } 434 435 public static final class DummyCountDownLatch extends CountDownLatch { DummyCountDownLatch()436 public DummyCountDownLatch() { 437 super(0); 438 } 439 } 440 441 public static final class DummyRunnable implements Runnable, Serializable { 442 @Override run()443 public void run() {} 444 } 445 446 public static final class DummyThreadFactory implements ThreadFactory, Serializable { 447 @Override newThread(Runnable r)448 public Thread newThread(Runnable r) { 449 return new Thread(r); 450 } 451 } 452 453 public static final class DummyExecutor implements Executor, Serializable { 454 @Override execute(Runnable command)455 public void execute(Runnable command) {} 456 } 457 } 458 459 private static final class NullByteSink extends ByteSink implements Serializable { 460 private static final NullByteSink INSTANCE = new NullByteSink(); 461 462 @Override openStream()463 public OutputStream openStream() { 464 return ByteStreams.nullOutputStream(); 465 } 466 } 467 468 // Compare by toString() to satisfy 2 properties: 469 // 1. compareTo(null) should throw NullPointerException 470 // 2. the order is deterministic and easy to understand, for debugging purpose. 471 @SuppressWarnings("ComparableType") 472 private static final class ByToString implements Comparable<Object>, Serializable { 473 private static final ByToString INSTANCE = new ByToString(); 474 475 @Override compareTo(Object o)476 public int compareTo(Object o) { 477 return toString().compareTo(o.toString()); 478 } 479 480 @Override toString()481 public String toString() { 482 return "BY_TO_STRING"; 483 } 484 readResolve()485 private Object readResolve() { 486 return INSTANCE; 487 } 488 } 489 490 // Always equal is a valid total ordering. And it works for any Object. 491 private static final class AlwaysEqual extends Ordering<Object> implements Serializable { 492 private static final AlwaysEqual INSTANCE = new AlwaysEqual(); 493 494 @Override compare(Object o1, Object o2)495 public int compare(Object o1, Object o2) { 496 return 0; 497 } 498 499 @Override toString()500 public String toString() { 501 return "ALWAYS_EQUAL"; 502 } 503 readResolve()504 private Object readResolve() { 505 return INSTANCE; 506 } 507 } 508 ArbitraryInstances()509 private ArbitraryInstances() {} 510 } 511