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