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