• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.testing;
18 
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static java.nio.charset.StandardCharsets.UTF_8;
21 import static java.util.Objects.requireNonNull;
22 
23 import com.google.common.annotations.GwtIncompatible;
24 import com.google.common.annotations.J2ktIncompatible;
25 import com.google.common.base.CharMatcher;
26 import com.google.common.base.Defaults;
27 import com.google.common.base.Equivalence;
28 import com.google.common.base.Joiner;
29 import com.google.common.base.Predicate;
30 import com.google.common.base.Predicates;
31 import com.google.common.base.Splitter;
32 import com.google.common.base.Stopwatch;
33 import com.google.common.base.Ticker;
34 import com.google.common.collect.BiMap;
35 import com.google.common.collect.ClassToInstanceMap;
36 import com.google.common.collect.ImmutableBiMap;
37 import com.google.common.collect.ImmutableClassToInstanceMap;
38 import com.google.common.collect.ImmutableCollection;
39 import com.google.common.collect.ImmutableList;
40 import com.google.common.collect.ImmutableListMultimap;
41 import com.google.common.collect.ImmutableMap;
42 import com.google.common.collect.ImmutableMultimap;
43 import com.google.common.collect.ImmutableMultiset;
44 import com.google.common.collect.ImmutableSet;
45 import com.google.common.collect.ImmutableSetMultimap;
46 import com.google.common.collect.ImmutableSortedMap;
47 import com.google.common.collect.ImmutableSortedMultiset;
48 import com.google.common.collect.ImmutableSortedSet;
49 import com.google.common.collect.ImmutableTable;
50 import com.google.common.collect.Iterators;
51 import com.google.common.collect.ListMultimap;
52 import com.google.common.collect.MapDifference;
53 import com.google.common.collect.Maps;
54 import com.google.common.collect.Multimap;
55 import com.google.common.collect.Multimaps;
56 import com.google.common.collect.Multiset;
57 import com.google.common.collect.Ordering;
58 import com.google.common.collect.PeekingIterator;
59 import com.google.common.collect.Range;
60 import com.google.common.collect.RowSortedTable;
61 import com.google.common.collect.SetMultimap;
62 import com.google.common.collect.Sets;
63 import com.google.common.collect.SortedMapDifference;
64 import com.google.common.collect.SortedMultiset;
65 import com.google.common.collect.SortedSetMultimap;
66 import com.google.common.collect.Table;
67 import com.google.common.collect.Tables;
68 import com.google.common.collect.TreeBasedTable;
69 import com.google.common.collect.TreeMultimap;
70 import com.google.common.io.ByteSink;
71 import com.google.common.io.ByteSource;
72 import com.google.common.io.ByteStreams;
73 import com.google.common.io.CharSink;
74 import com.google.common.io.CharSource;
75 import com.google.common.primitives.Primitives;
76 import com.google.common.primitives.UnsignedInteger;
77 import com.google.common.primitives.UnsignedLong;
78 import com.google.errorprone.annotations.Keep;
79 import java.io.ByteArrayInputStream;
80 import java.io.ByteArrayOutputStream;
81 import java.io.File;
82 import java.io.InputStream;
83 import java.io.OutputStream;
84 import java.io.PrintStream;
85 import java.io.PrintWriter;
86 import java.io.Reader;
87 import java.io.Serializable;
88 import java.io.StringReader;
89 import java.io.StringWriter;
90 import java.io.Writer;
91 import java.lang.reflect.AnnotatedElement;
92 import java.lang.reflect.Array;
93 import java.lang.reflect.Constructor;
94 import java.lang.reflect.Field;
95 import java.lang.reflect.GenericDeclaration;
96 import java.lang.reflect.InvocationTargetException;
97 import java.lang.reflect.Modifier;
98 import java.lang.reflect.Type;
99 import java.math.BigDecimal;
100 import java.math.BigInteger;
101 import java.nio.Buffer;
102 import java.nio.ByteBuffer;
103 import java.nio.CharBuffer;
104 import java.nio.DoubleBuffer;
105 import java.nio.FloatBuffer;
106 import java.nio.IntBuffer;
107 import java.nio.LongBuffer;
108 import java.nio.ShortBuffer;
109 import java.nio.charset.Charset;
110 import java.util.ArrayDeque;
111 import java.util.Arrays;
112 import java.util.Collection;
113 import java.util.Comparator;
114 import java.util.Currency;
115 import java.util.Deque;
116 import java.util.Iterator;
117 import java.util.List;
118 import java.util.ListIterator;
119 import java.util.Locale;
120 import java.util.Map;
121 import java.util.NavigableMap;
122 import java.util.NavigableSet;
123 import java.util.Optional;
124 import java.util.OptionalDouble;
125 import java.util.OptionalInt;
126 import java.util.OptionalLong;
127 import java.util.Queue;
128 import java.util.Random;
129 import java.util.Set;
130 import java.util.SortedMap;
131 import java.util.SortedSet;
132 import java.util.UUID;
133 import java.util.concurrent.BlockingDeque;
134 import java.util.concurrent.BlockingQueue;
135 import java.util.concurrent.ConcurrentHashMap;
136 import java.util.concurrent.ConcurrentMap;
137 import java.util.concurrent.ConcurrentNavigableMap;
138 import java.util.concurrent.ConcurrentSkipListMap;
139 import java.util.concurrent.CountDownLatch;
140 import java.util.concurrent.Executor;
141 import java.util.concurrent.LinkedBlockingDeque;
142 import java.util.concurrent.ScheduledThreadPoolExecutor;
143 import java.util.concurrent.ThreadFactory;
144 import java.util.concurrent.ThreadPoolExecutor;
145 import java.util.concurrent.TimeUnit;
146 import java.util.logging.Level;
147 import java.util.logging.Logger;
148 import java.util.regex.MatchResult;
149 import java.util.regex.Matcher;
150 import java.util.regex.Pattern;
151 import java.util.stream.Stream;
152 import 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
179 public 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    * 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
193    */
createMatchResult()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, 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(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 
setImplementation(Class<T> type, Class<? extends T> implementation)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 {
setImplementation(Appendable.class, StringBuilder.class)320     setImplementation(Appendable.class, StringBuilder.class);
setImplementation(BlockingQueue.class, LinkedBlockingDeque.class)321     setImplementation(BlockingQueue.class, LinkedBlockingDeque.class);
setImplementation(BlockingDeque.class, LinkedBlockingDeque.class)322     setImplementation(BlockingDeque.class, LinkedBlockingDeque.class);
setImplementation(ConcurrentMap.class, ConcurrentHashMap.class)323     setImplementation(ConcurrentMap.class, ConcurrentHashMap.class);
setImplementation(ConcurrentNavigableMap.class, ConcurrentSkipListMap.class)324     setImplementation(ConcurrentNavigableMap.class, ConcurrentSkipListMap.class);
setImplementation(CountDownLatch.class, Dummies.DummyCountDownLatch.class)325     setImplementation(CountDownLatch.class, Dummies.DummyCountDownLatch.class);
setImplementation(Deque.class, ArrayDeque.class)326     setImplementation(Deque.class, ArrayDeque.class);
setImplementation(OutputStream.class, ByteArrayOutputStream.class)327     setImplementation(OutputStream.class, ByteArrayOutputStream.class);
setImplementation(PrintStream.class, Dummies.InMemoryPrintStream.class)328     setImplementation(PrintStream.class, Dummies.InMemoryPrintStream.class);
setImplementation(PrintWriter.class, Dummies.InMemoryPrintWriter.class)329     setImplementation(PrintWriter.class, Dummies.InMemoryPrintWriter.class);
setImplementation(Queue.class, ArrayDeque.class)330     setImplementation(Queue.class, ArrayDeque.class);
setImplementation(Random.class, Dummies.DeterministicRandom.class)331     setImplementation(Random.class, Dummies.DeterministicRandom.class);
setImplementation( ScheduledThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class)332     setImplementation(
333         ScheduledThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class);
setImplementation(ThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class)334     setImplementation(ThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class);
setImplementation(Writer.class, StringWriter.class)335     setImplementation(Writer.class, StringWriter.class);
setImplementation(Runnable.class, Dummies.DummyRunnable.class)336     setImplementation(Runnable.class, Dummies.DummyRunnable.class);
setImplementation(ThreadFactory.class, Dummies.DummyThreadFactory.class)337     setImplementation(ThreadFactory.class, Dummies.DummyThreadFactory.class);
setImplementation(Executor.class, Dummies.DummyExecutor.class)338     setImplementation(Executor.class, Dummies.DummyExecutor.class);
339   }
340 
341   @SuppressWarnings("unchecked") // it's a subtype map
getImplementation(Class<T> type)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    */
get(Class<T> type)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 
arbitraryConstantInstanceOrNull(Class<T> type)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 
createEmptyArray(Class<T> arrayType)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 {
InMemoryPrintStream()427       public InMemoryPrintStream() {
428         super(new ByteArrayOutputStream());
429       }
430     }
431 
432     public static final class InMemoryPrintWriter extends PrintWriter {
InMemoryPrintWriter()433       public InMemoryPrintWriter() {
434         super(new StringWriter());
435       }
436     }
437 
438     public static final class DeterministicRandom extends Random {
439       @Keep
DeterministicRandom()440       public DeterministicRandom() {
441         super(0);
442       }
443     }
444 
445     public static final class DummyScheduledThreadPoolExecutor extends ScheduledThreadPoolExecutor {
DummyScheduledThreadPoolExecutor()446       public DummyScheduledThreadPoolExecutor() {
447         super(1);
448       }
449     }
450 
451     public static final class DummyCountDownLatch extends CountDownLatch {
DummyCountDownLatch()452       public DummyCountDownLatch() {
453         super(0);
454       }
455     }
456 
457     public static final class DummyRunnable implements Runnable, Serializable {
458       @Override
run()459       public void run() {}
460     }
461 
462     public static final class DummyThreadFactory implements ThreadFactory, Serializable {
463       @Override
newThread(Runnable r)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
execute(Runnable command)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
openStream()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
compareTo(Object o)492     public int compareTo(Object o) {
493       return toString().compareTo(o.toString());
494     }
495 
496     @Override
toString()497     public String toString() {
498       return "BY_TO_STRING";
499     }
500 
readResolve()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     @SuppressWarnings("UnusedVariable") // intentionally weird Comparator
compare(@ullable Object o1, @Nullable Object o2)513     public int compare(@Nullable Object o1, @Nullable Object o2) {
514       return 0;
515     }
516 
517     @Override
toString()518     public String toString() {
519       return "ALWAYS_EQUAL";
520     }
521 
readResolve()522     private Object readResolve() {
523       return INSTANCE;
524     }
525   }
526 
ArbitraryInstances()527   private ArbitraryInstances() {}
528 }
529