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