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