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