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