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