• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 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.collect;
18 
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.collect.Lists.newArrayList;
21 import static com.google.common.testing.SerializableTester.reserialize;
22 import static com.google.common.testing.SerializableTester.reserializeAndAssert;
23 import static com.google.common.truth.Truth.assertThat;
24 import static java.util.Arrays.asList;
25 
26 import com.google.common.annotations.GwtCompatible;
27 import com.google.common.annotations.GwtIncompatible;
28 import com.google.common.base.Function;
29 import com.google.common.base.Functions;
30 import com.google.common.collect.Ordering.ArbitraryOrdering;
31 import com.google.common.collect.Ordering.IncomparableValueException;
32 import com.google.common.collect.testing.Helpers;
33 import com.google.common.primitives.Ints;
34 import com.google.common.testing.EqualsTester;
35 import com.google.common.testing.NullPointerTester;
36 import java.util.Arrays;
37 import java.util.Collections;
38 import java.util.Comparator;
39 import java.util.Iterator;
40 import java.util.List;
41 import java.util.Random;
42 import java.util.RandomAccess;
43 import junit.framework.TestCase;
44 import org.checkerframework.checker.nullness.qual.Nullable;
45 
46 /**
47  * Unit tests for {@code Ordering}.
48  *
49  * @author Jesse Wilson
50  */
51 @GwtCompatible(emulated = true)
52 public class OrderingTest extends TestCase {
53   // TODO(cpovirk): some of these are inexplicably slow (20-30s) under GWT
54 
55   private final Ordering<Number> numberOrdering = new NumberOrdering();
56 
testAllEqual()57   public void testAllEqual() {
58     Ordering<Object> comparator = Ordering.allEqual();
59     assertSame(comparator, comparator.reverse());
60 
61     assertEquals(0, comparator.compare(null, null));
62     assertEquals(0, comparator.compare(new Object(), new Object()));
63     assertEquals(0, comparator.compare("apples", "oranges"));
64     assertSame(comparator, reserialize(comparator));
65     assertEquals("Ordering.allEqual()", comparator.toString());
66 
67     List<String> strings = ImmutableList.of("b", "a", "d", "c");
68     assertEquals(strings, comparator.sortedCopy(strings));
69     assertEquals(strings, comparator.immutableSortedCopy(strings));
70   }
71 
72   // From https://github.com/google/guava/issues/1342
testComplicatedOrderingExample()73   public void testComplicatedOrderingExample() {
74     Integer nullInt = (Integer) null;
75     Ordering<Iterable<Integer>> example =
76         Ordering.<Integer>natural().nullsFirst().reverse().lexicographical().reverse().nullsLast();
77     List<Integer> list1 = Lists.newArrayList();
78     List<Integer> list2 = Lists.newArrayList(1);
79     List<Integer> list3 = Lists.newArrayList(1, 1);
80     List<Integer> list4 = Lists.newArrayList(1, 2);
81     List<Integer> list5 = Lists.newArrayList(1, null, 2);
82     List<Integer> list6 = Lists.newArrayList(2);
83     List<Integer> list7 = Lists.newArrayList(nullInt);
84     List<Integer> list8 = Lists.newArrayList(nullInt, nullInt);
85     List<List<Integer>> list =
86         Lists.newArrayList(list1, list2, list3, list4, list5, list6, list7, list8, null);
87     List<List<Integer>> sorted = example.sortedCopy(list);
88 
89     // [[null, null], [null], [1, null, 2], [1, 1], [1, 2], [1], [2], [], null]
90     assertThat(sorted)
91         .containsExactly(
92             Lists.newArrayList(nullInt, nullInt),
93             Lists.newArrayList(nullInt),
94             Lists.newArrayList(1, null, 2),
95             Lists.newArrayList(1, 1),
96             Lists.newArrayList(1, 2),
97             Lists.newArrayList(1),
98             Lists.newArrayList(2),
99             Lists.newArrayList(),
100             null)
101         .inOrder();
102   }
103 
testNatural()104   public void testNatural() {
105     Ordering<Integer> comparator = Ordering.natural();
106     Helpers.testComparator(comparator, Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE);
107     try {
108       comparator.compare(1, null);
109       fail();
110     } catch (NullPointerException expected) {
111     }
112     try {
113       comparator.compare(null, 2);
114       fail();
115     } catch (NullPointerException expected) {
116     }
117     try {
118       comparator.compare(null, null);
119       fail();
120     } catch (NullPointerException expected) {
121     }
122     assertSame(comparator, reserialize(comparator));
123     assertEquals("Ordering.natural()", comparator.toString());
124   }
125 
testFrom()126   public void testFrom() {
127     Ordering<String> caseInsensitiveOrdering = Ordering.from(String.CASE_INSENSITIVE_ORDER);
128     assertEquals(0, caseInsensitiveOrdering.compare("A", "a"));
129     assertTrue(caseInsensitiveOrdering.compare("a", "B") < 0);
130     assertTrue(caseInsensitiveOrdering.compare("B", "a") > 0);
131 
132     @SuppressWarnings("deprecation") // test of deprecated method
133     Ordering<String> orderingFromOrdering = Ordering.from(Ordering.<String>natural());
134     new EqualsTester()
135         .addEqualityGroup(caseInsensitiveOrdering, Ordering.from(String.CASE_INSENSITIVE_ORDER))
136         .addEqualityGroup(orderingFromOrdering, Ordering.natural())
137         .testEquals();
138   }
139 
testExplicit_none()140   public void testExplicit_none() {
141     Comparator<Integer> c = Ordering.explicit(Collections.<Integer>emptyList());
142     try {
143       c.compare(0, 0);
144       fail();
145     } catch (IncomparableValueException expected) {
146       assertEquals(0, expected.value);
147     }
148     reserializeAndAssert(c);
149   }
150 
testExplicit_one()151   public void testExplicit_one() {
152     Comparator<Integer> c = Ordering.explicit(0);
153     assertEquals(0, c.compare(0, 0));
154     try {
155       c.compare(0, 1);
156       fail();
157     } catch (IncomparableValueException expected) {
158       assertEquals(1, expected.value);
159     }
160     reserializeAndAssert(c);
161     assertEquals("Ordering.explicit([0])", c.toString());
162   }
163 
testExplicitMax_b297601553()164   public void testExplicitMax_b297601553() {
165     Ordering<Integer> c = Ordering.explicit(1, 2, 3);
166 
167     // TODO(b/297601553): this should probably throw an CCE since 0 isn't explicitly listed
168     assertEquals(0, (int) c.max(asList(0)));
169     try {
170       c.max(asList(0, 1));
171       fail();
172     } catch (IncomparableValueException expected) {
173       assertEquals(0, expected.value);
174     }
175   }
176 
testExplicit_two()177   public void testExplicit_two() {
178     Comparator<Integer> c = Ordering.explicit(42, 5);
179     assertEquals(0, c.compare(5, 5));
180     assertTrue(c.compare(5, 42) > 0);
181     assertTrue(c.compare(42, 5) < 0);
182     try {
183       c.compare(5, 666);
184       fail();
185     } catch (IncomparableValueException expected) {
186       assertEquals(666, expected.value);
187     }
188     new EqualsTester()
189         .addEqualityGroup(c, Ordering.explicit(42, 5))
190         .addEqualityGroup(Ordering.explicit(5, 42))
191         .addEqualityGroup(Ordering.explicit(42))
192         .testEquals();
193     reserializeAndAssert(c);
194   }
195 
196   public void testExplicit_sortingExample() {
197     Comparator<Integer> c = Ordering.explicit(2, 8, 6, 1, 7, 5, 3, 4, 0, 9);
198     List<Integer> list = Arrays.asList(0, 3, 5, 6, 7, 8, 9);
199     Collections.sort(list, c);
200     assertThat(list).containsExactly(8, 6, 7, 5, 3, 0, 9).inOrder();
201     reserializeAndAssert(c);
202   }
203 
204   public void testExplicit_withDuplicates() {
205     try {
206       Ordering.explicit(1, 2, 3, 4, 2);
207       fail();
208     } catch (IllegalArgumentException expected) {
209     }
210   }
211 
212   // A more limited test than the one that follows, but this one uses the
213   // actual public API.
214   public void testArbitrary_withoutCollisions() {
215     List<Object> list = Lists.newArrayList();
216     for (int i = 0; i < 50; i++) {
217       list.add(new Object());
218     }
219 
220     Ordering<Object> arbitrary = Ordering.arbitrary();
221     Collections.sort(list, arbitrary);
222 
223     // Now we don't care what order it's put the list in, only that
224     // comparing any pair of elements gives the answer we expect.
225     Helpers.testComparator(arbitrary, list);
226 
227     assertEquals("Ordering.arbitrary()", arbitrary.toString());
228   }
229 
230   public void testArbitrary_withCollisions() {
231     List<Integer> list = Lists.newArrayList();
232     for (int i = 0; i < 50; i++) {
233       list.add(i);
234     }
235 
236     Ordering<Object> arbitrary =
237         new ArbitraryOrdering() {
238           @Override
239           int identityHashCode(Object object) {
240             return ((Integer) object) % 5; // fake tons of collisions!
241           }
242         };
243 
244     // Don't let the elements be in such a predictable order
245     list = shuffledCopy(list, new Random(1));
246 
247     Collections.sort(list, arbitrary);
248 
249     // Now we don't care what order it's put the list in, only that
250     // comparing any pair of elements gives the answer we expect.
251     Helpers.testComparator(arbitrary, list);
252   }
253 
254   public void testUsingToString() {
255     Ordering<Object> ordering = Ordering.usingToString();
256     Helpers.testComparator(ordering, 1, 12, 124, 2);
257     assertEquals("Ordering.usingToString()", ordering.toString());
258     assertSame(ordering, reserialize(ordering));
259   }
260 
261   // use an enum to get easy serializability
262   private enum CharAtFunction implements Function<String, Character> {
263     AT0(0),
264     AT1(1),
265     AT2(2),
266     AT3(3),
267     AT4(4),
268     AT5(5),
269     ;
270 
271     final int index;
272 
273     CharAtFunction(int index) {
274       this.index = index;
275     }
276 
277     @Override
278     public Character apply(String string) {
279       return string.charAt(index);
280     }
281   }
282 
283   private static Ordering<String> byCharAt(int index) {
284     return Ordering.natural().onResultOf(CharAtFunction.values()[index]);
285   }
286 
287   public void testCompound_static() {
288     Comparator<String> comparator =
289         Ordering.compound(
290             ImmutableList.of(
291                 byCharAt(0), byCharAt(1), byCharAt(2), byCharAt(3), byCharAt(4), byCharAt(5)));
292     Helpers.testComparator(
293         comparator,
294         ImmutableList.of(
295             "applesauce",
296             "apricot",
297             "artichoke",
298             "banality",
299             "banana",
300             "banquet",
301             "tangelo",
302             "tangerine"));
303     reserializeAndAssert(comparator);
304   }
305 
306   public void testCompound_instance() {
307     Comparator<String> comparator = byCharAt(1).compound(byCharAt(0));
308     Helpers.testComparator(
309         comparator,
310         ImmutableList.of("red", "yellow", "violet", "blue", "indigo", "green", "orange"));
311   }
312 
313   public void testCompound_instance_generics() {
314     Ordering<Object> objects = Ordering.explicit((Object) 1);
315     Ordering<Number> numbers = Ordering.explicit((Number) 1);
316     Ordering<Integer> integers = Ordering.explicit(1);
317 
318     // Like by like equals like
319     Ordering<Number> a = numbers.compound(numbers);
320 
321     // The compound takes the more specific type of the two, regardless of order
322 
323     Ordering<Number> b = numbers.compound(objects);
324     Ordering<Number> c = objects.compound(numbers);
325 
326     Ordering<Integer> d = numbers.compound(integers);
327     Ordering<Integer> e = integers.compound(numbers);
328 
329     // This works with three levels too (IDEA falsely reports errors as noted
330     // below. Both javac and eclipse handle these cases correctly.)
331 
332     Ordering<Number> f = numbers.compound(objects).compound(objects); // bad IDEA
333     Ordering<Number> g = objects.compound(numbers).compound(objects);
334     Ordering<Number> h = objects.compound(objects).compound(numbers);
335 
336     Ordering<Number> i = numbers.compound(objects.compound(objects));
337     Ordering<Number> j = objects.compound(numbers.compound(objects)); // bad IDEA
338     Ordering<Number> k = objects.compound(objects.compound(numbers));
339 
340     // You can also arbitrarily assign a more restricted type - not an intended
341     // feature, exactly, but unavoidable (I think) and harmless
342     Ordering<Integer> l = objects.compound(numbers);
343 
344     // This correctly doesn't work:
345     // Ordering<Object> m = numbers.compound(objects);
346 
347     // Sadly, the following works in javac 1.6, but at least it fails for
348     // eclipse, and is *correctly* highlighted red in IDEA.
349     // Ordering<Object> n = objects.compound(numbers);
350   }
351 
352   public void testReverse() {
353     Ordering<Number> reverseOrder = numberOrdering.reverse();
354     Helpers.testComparator(reverseOrder, Integer.MAX_VALUE, 1, 0, -1, Integer.MIN_VALUE);
355 
356     new EqualsTester()
357         .addEqualityGroup(reverseOrder, numberOrdering.reverse())
358         .addEqualityGroup(Ordering.natural().reverse())
359         .addEqualityGroup(Collections.reverseOrder())
360         .testEquals();
361   }
362 
363   public void testReverseOfReverseSameAsForward() {
364     // Not guaranteed by spec, but it works, and saves us from testing
365     // exhaustively
366     assertSame(numberOrdering, numberOrdering.reverse().reverse());
367   }
368 
369   private enum StringLengthFunction implements Function<String, Integer> {
370     StringLength;
371 
372     @Override
373     public Integer apply(String string) {
374       return string.length();
375     }
376   }
377 
378   private static final Ordering<Integer> DECREASING_INTEGER = Ordering.natural().reverse();
379 
380   public void testOnResultOf_natural() {
381     Comparator<String> comparator =
382         Ordering.natural().onResultOf(StringLengthFunction.StringLength);
383     assertTrue(comparator.compare("to", "be") == 0);
384     assertTrue(comparator.compare("or", "not") < 0);
385     assertTrue(comparator.compare("that", "to") > 0);
386 
387     new EqualsTester()
388         .addEqualityGroup(
389             comparator, Ordering.natural().onResultOf(StringLengthFunction.StringLength))
390         .addEqualityGroup(DECREASING_INTEGER)
391         .testEquals();
392     reserializeAndAssert(comparator);
393     assertEquals("Ordering.natural().onResultOf(StringLength)", comparator.toString());
394   }
395 
396   public void testOnResultOf_chained() {
397     Comparator<String> comparator =
398         DECREASING_INTEGER.onResultOf(StringLengthFunction.StringLength);
399     assertTrue(comparator.compare("to", "be") == 0);
400     assertTrue(comparator.compare("not", "or") < 0);
401     assertTrue(comparator.compare("to", "that") > 0);
402 
403     new EqualsTester()
404         .addEqualityGroup(
405             comparator, DECREASING_INTEGER.onResultOf(StringLengthFunction.StringLength))
406         .addEqualityGroup(DECREASING_INTEGER.onResultOf(Functions.constant(1)))
407         .addEqualityGroup(Ordering.natural())
408         .testEquals();
409     reserializeAndAssert(comparator);
410     assertEquals("Ordering.natural().reverse().onResultOf(StringLength)", comparator.toString());
411   }
412 
413   @SuppressWarnings("unchecked") // dang varargs
414   public void testLexicographical() {
415     Ordering<String> ordering = Ordering.natural();
416     Ordering<Iterable<String>> lexy = ordering.lexicographical();
417 
418     ImmutableList<String> empty = ImmutableList.of();
419     ImmutableList<String> a = ImmutableList.of("a");
420     ImmutableList<String> aa = ImmutableList.of("a", "a");
421     ImmutableList<String> ab = ImmutableList.of("a", "b");
422     ImmutableList<String> b = ImmutableList.of("b");
423 
424     Helpers.testComparator(lexy, empty, a, aa, ab, b);
425 
426     new EqualsTester()
427         .addEqualityGroup(lexy, ordering.lexicographical())
428         .addEqualityGroup(numberOrdering.lexicographical())
429         .addEqualityGroup(Ordering.natural())
430         .testEquals();
431   }
432 
433   public void testNullsFirst() {
434     Ordering<Integer> ordering = Ordering.natural().nullsFirst();
435     Helpers.testComparator(ordering, null, Integer.MIN_VALUE, 0, 1);
436 
437     new EqualsTester()
438         .addEqualityGroup(ordering, Ordering.natural().nullsFirst())
439         .addEqualityGroup(numberOrdering.nullsFirst())
440         .addEqualityGroup(Ordering.natural())
441         .testEquals();
442   }
443 
444   public void testNullsLast() {
445     Ordering<Integer> ordering = Ordering.natural().nullsLast();
446     Helpers.testComparator(ordering, 0, 1, Integer.MAX_VALUE, null);
447 
448     new EqualsTester()
449         .addEqualityGroup(ordering, Ordering.natural().nullsLast())
450         .addEqualityGroup(numberOrdering.nullsLast())
451         .addEqualityGroup(Ordering.natural())
452         .testEquals();
453   }
454 
455   public void testBinarySearch() {
456     List<Integer> ints = Lists.newArrayList(0, 2, 3, 5, 7, 9);
457     assertEquals(4, numberOrdering.binarySearch(ints, 7));
458   }
459 
460   public void testSortedCopy() {
461     List<Integer> unsortedInts = Collections.unmodifiableList(Arrays.asList(5, 0, 3, null, 0, 9));
462     List<Integer> sortedInts = numberOrdering.nullsLast().sortedCopy(unsortedInts);
463     assertEquals(Arrays.asList(0, 0, 3, 5, 9, null), sortedInts);
464 
465     assertEquals(
466         Collections.emptyList(), numberOrdering.sortedCopy(Collections.<Integer>emptyList()));
467   }
468 
469   public void testImmutableSortedCopy() {
470     ImmutableList<Integer> unsortedInts = ImmutableList.of(5, 3, 0, 9, 3);
471     ImmutableList<Integer> sortedInts = numberOrdering.immutableSortedCopy(unsortedInts);
472     assertEquals(Arrays.asList(0, 3, 3, 5, 9), sortedInts);
473 
474     assertEquals(
475         Collections.<Integer>emptyList(),
476         numberOrdering.immutableSortedCopy(Collections.<Integer>emptyList()));
477 
478     List<Integer> listWithNull = Arrays.asList(5, 3, null, 9);
479     try {
480       Ordering.natural().nullsFirst().immutableSortedCopy(listWithNull);
481       fail();
482     } catch (NullPointerException expected) {
483     }
484   }
485 
486   public void testIsOrdered() {
487     assertFalse(numberOrdering.isOrdered(asList(5, 3, 0, 9)));
488     assertFalse(numberOrdering.isOrdered(asList(0, 5, 3, 9)));
489     assertTrue(numberOrdering.isOrdered(asList(0, 3, 5, 9)));
490     assertTrue(numberOrdering.isOrdered(asList(0, 0, 3, 3)));
491     assertTrue(numberOrdering.isOrdered(asList(0, 3)));
492     assertTrue(numberOrdering.isOrdered(Collections.singleton(1)));
493     assertTrue(numberOrdering.isOrdered(Collections.<Integer>emptyList()));
494   }
495 
496   public void testIsStrictlyOrdered() {
497     assertFalse(numberOrdering.isStrictlyOrdered(asList(5, 3, 0, 9)));
498     assertFalse(numberOrdering.isStrictlyOrdered(asList(0, 5, 3, 9)));
499     assertTrue(numberOrdering.isStrictlyOrdered(asList(0, 3, 5, 9)));
500     assertFalse(numberOrdering.isStrictlyOrdered(asList(0, 0, 3, 3)));
501     assertTrue(numberOrdering.isStrictlyOrdered(asList(0, 3)));
502     assertTrue(numberOrdering.isStrictlyOrdered(Collections.singleton(1)));
503     assertTrue(numberOrdering.isStrictlyOrdered(Collections.<Integer>emptyList()));
504   }
505 
506   public void testLeastOfIterable_empty_0() {
507     List<Integer> result = numberOrdering.leastOf(Arrays.<Integer>asList(), 0);
508     assertTrue(result instanceof RandomAccess);
509     assertListImmutable(result);
510     assertEquals(ImmutableList.<Integer>of(), result);
511   }
512 
513   public void testLeastOfIterator_empty_0() {
514     List<Integer> result = numberOrdering.leastOf(Iterators.<Integer>emptyIterator(), 0);
515     assertTrue(result instanceof RandomAccess);
516     assertListImmutable(result);
517     assertEquals(ImmutableList.<Integer>of(), result);
518   }
519 
520   public void testLeastOfIterable_empty_1() {
521     List<Integer> result = numberOrdering.leastOf(Arrays.<Integer>asList(), 1);
522     assertTrue(result instanceof RandomAccess);
523     assertListImmutable(result);
524     assertEquals(ImmutableList.<Integer>of(), result);
525   }
526 
527   public void testLeastOfIterator_empty_1() {
528     List<Integer> result = numberOrdering.leastOf(Iterators.<Integer>emptyIterator(), 1);
529     assertTrue(result instanceof RandomAccess);
530     assertListImmutable(result);
531     assertEquals(ImmutableList.<Integer>of(), result);
532   }
533 
534   public void testLeastOfIterable_simple_negativeOne() {
535     try {
536       numberOrdering.leastOf(Arrays.asList(3, 4, 5, -1), -1);
537       fail();
538     } catch (IllegalArgumentException expected) {
539     }
540   }
541 
542   public void testLeastOfIterator_simple_negativeOne() {
543     try {
544       numberOrdering.leastOf(Iterators.forArray(3, 4, 5, -1), -1);
545       fail();
546     } catch (IllegalArgumentException expected) {
547     }
548   }
549 
550   public void testLeastOfIterable_singleton_0() {
551     List<Integer> result = numberOrdering.leastOf(Arrays.asList(3), 0);
552     assertTrue(result instanceof RandomAccess);
553     assertListImmutable(result);
554     assertEquals(ImmutableList.<Integer>of(), result);
555   }
556 
557   public void testLeastOfIterator_singleton_0() {
558     List<Integer> result = numberOrdering.leastOf(Iterators.singletonIterator(3), 0);
559     assertTrue(result instanceof RandomAccess);
560     assertListImmutable(result);
561     assertEquals(ImmutableList.<Integer>of(), result);
562   }
563 
564   public void testLeastOfIterable_simple_0() {
565     List<Integer> result = numberOrdering.leastOf(Arrays.asList(3, 4, 5, -1), 0);
566     assertTrue(result instanceof RandomAccess);
567     assertListImmutable(result);
568     assertEquals(ImmutableList.<Integer>of(), result);
569   }
570 
571   public void testLeastOfIterator_simple_0() {
572     List<Integer> result = numberOrdering.leastOf(Iterators.forArray(3, 4, 5, -1), 0);
573     assertTrue(result instanceof RandomAccess);
574     assertListImmutable(result);
575     assertEquals(ImmutableList.<Integer>of(), result);
576   }
577 
578   public void testLeastOfIterable_simple_1() {
579     List<Integer> result = numberOrdering.leastOf(Arrays.asList(3, 4, 5, -1), 1);
580     assertTrue(result instanceof RandomAccess);
581     assertListImmutable(result);
582     assertEquals(ImmutableList.of(-1), result);
583   }
584 
585   public void testLeastOfIterator_simple_1() {
586     List<Integer> result = numberOrdering.leastOf(Iterators.forArray(3, 4, 5, -1), 1);
587     assertTrue(result instanceof RandomAccess);
588     assertListImmutable(result);
589     assertEquals(ImmutableList.of(-1), result);
590   }
591 
592   public void testLeastOfIterable_simple_nMinusOne_withNullElement() {
593     List<Integer> list = Arrays.asList(3, null, 5, -1);
594     List<Integer> result = Ordering.natural().nullsLast().leastOf(list, list.size() - 1);
595     assertTrue(result instanceof RandomAccess);
596     assertListImmutable(result);
597     assertEquals(ImmutableList.of(-1, 3, 5), result);
598   }
599 
600   public void testLeastOfIterator_simple_nMinusOne_withNullElement() {
601     Iterator<Integer> itr = Iterators.forArray(3, null, 5, -1);
602     List<Integer> result = Ordering.natural().nullsLast().leastOf(itr, 3);
603     assertTrue(result instanceof RandomAccess);
604     assertListImmutable(result);
605     assertEquals(ImmutableList.of(-1, 3, 5), result);
606   }
607 
608   public void testLeastOfIterable_simple_nMinusOne() {
609     List<Integer> list = Arrays.asList(3, 4, 5, -1);
610     List<Integer> result = numberOrdering.leastOf(list, list.size() - 1);
611     assertTrue(result instanceof RandomAccess);
612     assertListImmutable(result);
613     assertEquals(ImmutableList.of(-1, 3, 4), result);
614   }
615 
616   public void testLeastOfIterator_simple_nMinusOne() {
617     List<Integer> list = Arrays.asList(3, 4, 5, -1);
618     List<Integer> result = numberOrdering.leastOf(list.iterator(), list.size() - 1);
619     assertTrue(result instanceof RandomAccess);
620     assertListImmutable(result);
621     assertEquals(ImmutableList.of(-1, 3, 4), result);
622   }
623 
624   public void testLeastOfIterable_simple_n() {
625     List<Integer> list = Arrays.asList(3, 4, 5, -1);
626     List<Integer> result = numberOrdering.leastOf(list, list.size());
627     assertTrue(result instanceof RandomAccess);
628     assertListImmutable(result);
629     assertEquals(ImmutableList.of(-1, 3, 4, 5), result);
630   }
631 
632   public void testLeastOfIterator_simple_n() {
633     List<Integer> list = Arrays.asList(3, 4, 5, -1);
634     List<Integer> result = numberOrdering.leastOf(list.iterator(), list.size());
635     assertTrue(result instanceof RandomAccess);
636     assertListImmutable(result);
637     assertEquals(ImmutableList.of(-1, 3, 4, 5), result);
638   }
639 
640   public void testLeastOfIterable_simple_n_withNullElement() {
641     List<Integer> list = Arrays.asList(3, 4, 5, null, -1);
642     List<Integer> result = Ordering.natural().nullsLast().leastOf(list, list.size());
643     assertTrue(result instanceof RandomAccess);
644     assertListImmutable(result);
645     assertEquals(Arrays.asList(-1, 3, 4, 5, null), result);
646   }
647 
648   public void testLeastOfIterator_simple_n_withNullElement() {
649     List<Integer> list = Arrays.asList(3, 4, 5, null, -1);
650     List<Integer> result = Ordering.natural().nullsLast().leastOf(list.iterator(), list.size());
651     assertTrue(result instanceof RandomAccess);
652     assertListImmutable(result);
653     assertEquals(Arrays.asList(-1, 3, 4, 5, null), result);
654   }
655 
656   public void testLeastOfIterable_simple_nPlusOne() {
657     List<Integer> list = Arrays.asList(3, 4, 5, -1);
658     List<Integer> result = numberOrdering.leastOf(list, list.size() + 1);
659     assertTrue(result instanceof RandomAccess);
660     assertListImmutable(result);
661     assertEquals(ImmutableList.of(-1, 3, 4, 5), result);
662   }
663 
664   public void testLeastOfIterator_simple_nPlusOne() {
665     List<Integer> list = Arrays.asList(3, 4, 5, -1);
666     List<Integer> result = numberOrdering.leastOf(list.iterator(), list.size() + 1);
667     assertTrue(result instanceof RandomAccess);
668     assertListImmutable(result);
669     assertEquals(ImmutableList.of(-1, 3, 4, 5), result);
670   }
671 
672   public void testLeastOfIterable_ties() {
673     Integer foo = new Integer(Integer.MAX_VALUE - 10);
674     Integer bar = new Integer(Integer.MAX_VALUE - 10);
675 
676     assertNotSame(foo, bar);
677     assertEquals(foo, bar);
678 
679     List<Integer> list = Arrays.asList(3, foo, bar, -1);
680     List<Integer> result = numberOrdering.leastOf(list, list.size());
681     assertEquals(ImmutableList.of(-1, 3, foo, bar), result);
682   }
683 
684   public void testLeastOfIterator_ties() {
685     Integer foo = new Integer(Integer.MAX_VALUE - 10);
686     Integer bar = new Integer(Integer.MAX_VALUE - 10);
687 
688     assertNotSame(foo, bar);
689     assertEquals(foo, bar);
690 
691     List<Integer> list = Arrays.asList(3, foo, bar, -1);
692     List<Integer> result = numberOrdering.leastOf(list.iterator(), list.size());
693     assertEquals(ImmutableList.of(-1, 3, foo, bar), result);
694   }
695 
696   @GwtIncompatible // slow
697   public void testLeastOf_reconcileAgainstSortAndSublist() {
698     runLeastOfComparison(1000, 300, 20);
699   }
700 
701   public void testLeastOf_reconcileAgainstSortAndSublistSmall() {
702     runLeastOfComparison(10, 30, 2);
703   }
704 
705   private static void runLeastOfComparison(int iterations, int elements, int seeds) {
706     Random random = new Random(42);
707     Ordering<Integer> ordering = Ordering.natural();
708 
709     for (int i = 0; i < iterations; i++) {
710       List<Integer> list = Lists.newArrayList();
711       for (int j = 0; j < elements; j++) {
712         list.add(random.nextInt(10 * i + j + 1));
713       }
714 
715       for (int seed = 1; seed < seeds; seed++) {
716         int k = random.nextInt(10 * seed);
717         assertEquals(ordering.sortedCopy(list).subList(0, k), ordering.leastOf(list, k));
718       }
719     }
720   }
721 
722   public void testLeastOfIterableLargeK() {
723     List<Integer> list = Arrays.asList(4, 2, 3, 5, 1);
724     assertEquals(Arrays.asList(1, 2, 3, 4, 5), Ordering.natural().leastOf(list, Integer.MAX_VALUE));
725   }
726 
727   public void testLeastOfIteratorLargeK() {
728     List<Integer> list = Arrays.asList(4, 2, 3, 5, 1);
729     assertEquals(
730         Arrays.asList(1, 2, 3, 4, 5),
731         Ordering.natural().leastOf(list.iterator(), Integer.MAX_VALUE));
732   }
733 
734   public void testGreatestOfIterable_simple() {
735     /*
736      * If greatestOf() promised to be implemented as reverse().leastOf(), this
737      * test would be enough. It doesn't... but we'll cheat and act like it does
738      * anyway. There's a comment there to remind us to fix this if we change it.
739      */
740     List<Integer> list = Arrays.asList(3, 1, 3, 2, 4, 2, 4, 3);
741     assertEquals(Arrays.asList(4, 4, 3, 3), numberOrdering.greatestOf(list, 4));
742   }
743 
744   public void testGreatestOfIterator_simple() {
745     /*
746      * If greatestOf() promised to be implemented as reverse().leastOf(), this
747      * test would be enough. It doesn't... but we'll cheat and act like it does
748      * anyway. There's a comment there to remind us to fix this if we change it.
749      */
750     List<Integer> list = Arrays.asList(3, 1, 3, 2, 4, 2, 4, 3);
751     assertEquals(Arrays.asList(4, 4, 3, 3), numberOrdering.greatestOf(list.iterator(), 4));
752   }
753 
754   private static void assertListImmutable(List<Integer> result) {
755     try {
756       result.set(0, 1);
757       fail();
758     } catch (UnsupportedOperationException expected) {
759       // pass
760     }
761   }
762 
763   public void testIteratorMinAndMax() {
764     List<Integer> ints = Lists.newArrayList(5, 3, 0, 9);
765     assertEquals(9, (int) numberOrdering.max(ints.iterator()));
766     assertEquals(0, (int) numberOrdering.min(ints.iterator()));
767 
768     // when the values are the same, the first argument should be returned
769     Integer a = new Integer(4);
770     Integer b = new Integer(4);
771     ints = Lists.newArrayList(a, b, b);
772     assertSame(a, numberOrdering.max(ints.iterator()));
773     assertSame(a, numberOrdering.min(ints.iterator()));
774   }
775 
776   public void testIteratorMinExhaustsIterator() {
777     List<Integer> ints = Lists.newArrayList(9, 0, 3, 5);
778     Iterator<Integer> iterator = ints.iterator();
779     assertEquals(0, (int) numberOrdering.min(iterator));
780     assertFalse(iterator.hasNext());
781   }
782 
783   public void testIteratorMaxExhaustsIterator() {
784     List<Integer> ints = Lists.newArrayList(9, 0, 3, 5);
785     Iterator<Integer> iterator = ints.iterator();
786     assertEquals(9, (int) numberOrdering.max(iterator));
787     assertFalse(iterator.hasNext());
788   }
789 
790   public void testIterableMinAndMax() {
791     List<Integer> ints = Lists.newArrayList(5, 3, 0, 9);
792     assertEquals(9, (int) numberOrdering.max(ints));
793     assertEquals(0, (int) numberOrdering.min(ints));
794 
795     // when the values are the same, the first argument should be returned
796     Integer a = new Integer(4);
797     Integer b = new Integer(4);
798     ints = Lists.newArrayList(a, b, b);
799     assertSame(a, numberOrdering.max(ints));
800     assertSame(a, numberOrdering.min(ints));
801   }
802 
803   public void testVarargsMinAndMax() {
804     // try the min and max values in all positions, since some values are proper
805     // parameters and others are from the varargs array
806     assertEquals(9, (int) numberOrdering.max(9, 3, 0, 5, 8));
807     assertEquals(9, (int) numberOrdering.max(5, 9, 0, 3, 8));
808     assertEquals(9, (int) numberOrdering.max(5, 3, 9, 0, 8));
809     assertEquals(9, (int) numberOrdering.max(5, 3, 0, 9, 8));
810     assertEquals(9, (int) numberOrdering.max(5, 3, 0, 8, 9));
811     assertEquals(0, (int) numberOrdering.min(0, 3, 5, 9, 8));
812     assertEquals(0, (int) numberOrdering.min(5, 0, 3, 9, 8));
813     assertEquals(0, (int) numberOrdering.min(5, 3, 0, 9, 8));
814     assertEquals(0, (int) numberOrdering.min(5, 3, 9, 0, 8));
815     assertEquals(0, (int) numberOrdering.min(5, 3, 0, 9, 0));
816 
817     // when the values are the same, the first argument should be returned
818     Integer a = new Integer(4);
819     Integer b = new Integer(4);
820     assertSame(a, numberOrdering.max(a, b, b));
821     assertSame(a, numberOrdering.min(a, b, b));
822   }
823 
824   public void testParameterMinAndMax() {
825     assertEquals(5, (int) numberOrdering.max(3, 5));
826     assertEquals(5, (int) numberOrdering.max(5, 3));
827     assertEquals(3, (int) numberOrdering.min(3, 5));
828     assertEquals(3, (int) numberOrdering.min(5, 3));
829 
830     // when the values are the same, the first argument should be returned
831     Integer a = new Integer(4);
832     Integer b = new Integer(4);
833     assertSame(a, numberOrdering.max(a, b));
834     assertSame(a, numberOrdering.min(a, b));
835   }
836 
837   private static class NumberOrdering extends Ordering<Number> {
838     @Override
839     public int compare(Number a, Number b) {
840       return ((Double) a.doubleValue()).compareTo(b.doubleValue());
841     }
842 
843     @Override
844     public int hashCode() {
845       return NumberOrdering.class.hashCode();
846     }
847 
848     @Override
849     public boolean equals(@Nullable Object other) {
850       return other instanceof NumberOrdering;
851     }
852 
853     private static final long serialVersionUID = 0;
854   }
855 
856   /*
857    * Now we have monster tests that create hundreds of Orderings using different
858    * combinations of methods, then checks compare(), binarySearch() and so
859    * forth on each one.
860    */
861 
862   // should periodically try increasing this, but it makes the test run long
863   private static final int RECURSE_DEPTH = 2;
864 
865   public void testCombinationsExhaustively_startingFromNatural() {
866     testExhaustively(Ordering.<String>natural(), "a", "b", "d");
867   }
868 
869   @GwtIncompatible // too slow
870   public void testCombinationsExhaustively_startingFromExplicit() {
871     testExhaustively(Ordering.explicit("a", "b", "c", "d"), "a", "b", "d");
872   }
873 
874   @GwtIncompatible // too slow
875   public void testCombinationsExhaustively_startingFromUsingToString() {
876     testExhaustively(Ordering.usingToString(), 1, 12, 2);
877   }
878 
879   @GwtIncompatible // too slow
880   public void testCombinationsExhaustively_startingFromFromComparator() {
881     testExhaustively(Ordering.from(String.CASE_INSENSITIVE_ORDER), "A", "b", "C", "d");
882   }
883 
884   @GwtIncompatible // too slow
885   public void testCombinationsExhaustively_startingFromArbitrary() {
886     Ordering<Object> arbitrary = Ordering.arbitrary();
887     Object[] array = {1, "foo", new Object()};
888 
889     // There's no way to tell what the order should be except empirically
890     Arrays.sort(array, arbitrary);
891     testExhaustively(arbitrary, array);
892   }
893 
894   /**
895    * Requires at least 3 elements in {@code strictlyOrderedElements} in order to test the varargs
896    * version of min/max.
897    */
898   private static <T> void testExhaustively(
899       Ordering<? super T> ordering, T... strictlyOrderedElements) {
900     checkArgument(
901         strictlyOrderedElements.length >= 3,
902         "strictlyOrderedElements " + "requires at least 3 elements");
903     List<T> list = Arrays.asList(strictlyOrderedElements);
904 
905     // for use calling Collection.toArray later
906     T[] emptyArray = Platform.newArray(strictlyOrderedElements, 0);
907 
908     // shoot me, but I didn't want to deal with wildcards through the whole test
909     @SuppressWarnings("unchecked")
910     Scenario<T> starter = new Scenario<>((Ordering) ordering, list, emptyArray);
911     verifyScenario(starter, 0);
912   }
913 
914   private static <T> void verifyScenario(Scenario<T> scenario, int level) {
915     scenario.testCompareTo();
916     scenario.testIsOrdered();
917     scenario.testMinAndMax();
918     scenario.testBinarySearch();
919     scenario.testSortedCopy();
920 
921     if (level < RECURSE_DEPTH) {
922       for (OrderingMutation alteration : OrderingMutation.values()) {
923         verifyScenario(alteration.mutate(scenario), level + 1);
924       }
925     }
926   }
927 
928   /**
929    * An aggregation of an ordering with a list (of size > 1) that should prove to be in strictly
930    * increasing order according to that ordering.
931    */
932   private static class Scenario<T> {
933     final Ordering<T> ordering;
934     final List<T> strictlyOrderedList;
935     final T[] emptyArray;
936 
937     Scenario(Ordering<T> ordering, List<T> strictlyOrderedList, T[] emptyArray) {
938       this.ordering = ordering;
939       this.strictlyOrderedList = strictlyOrderedList;
940       this.emptyArray = emptyArray;
941     }
942 
943     void testCompareTo() {
944       Helpers.testComparator(ordering, strictlyOrderedList);
945     }
946 
947     void testIsOrdered() {
948       assertTrue(ordering.isOrdered(strictlyOrderedList));
949       assertTrue(ordering.isStrictlyOrdered(strictlyOrderedList));
950     }
951 
952     @SuppressWarnings("unchecked") // generic arrays and unchecked cast
953     void testMinAndMax() {
954       List<T> shuffledList = Lists.newArrayList(strictlyOrderedList);
955       shuffledList = shuffledCopy(shuffledList, new Random(5));
956 
957       T min = strictlyOrderedList.get(0);
958       T max = strictlyOrderedList.get(strictlyOrderedList.size() - 1);
959 
960       T first = shuffledList.get(0);
961       T second = shuffledList.get(1);
962       T third = shuffledList.get(2);
963       T[] rest = shuffledList.subList(3, shuffledList.size()).toArray(emptyArray);
964 
965       assertEquals(min, ordering.min(shuffledList));
966       assertEquals(min, ordering.min(shuffledList.iterator()));
967       assertEquals(min, ordering.min(first, second, third, rest));
968       assertEquals(min, ordering.min(min, max));
969       assertEquals(min, ordering.min(max, min));
970 
971       assertEquals(max, ordering.max(shuffledList));
972       assertEquals(max, ordering.max(shuffledList.iterator()));
973       assertEquals(max, ordering.max(first, second, third, rest));
974       assertEquals(max, ordering.max(min, max));
975       assertEquals(max, ordering.max(max, min));
976     }
977 
978     void testBinarySearch() {
979       for (int i = 0; i < strictlyOrderedList.size(); i++) {
980         assertEquals(i, ordering.binarySearch(strictlyOrderedList, strictlyOrderedList.get(i)));
981       }
982       List<T> newList = Lists.newArrayList(strictlyOrderedList);
983       T valueNotInList = newList.remove(1);
984       assertEquals(-2, ordering.binarySearch(newList, valueNotInList));
985     }
986 
987     void testSortedCopy() {
988       List<T> shuffledList = Lists.newArrayList(strictlyOrderedList);
989       shuffledList = shuffledCopy(shuffledList, new Random(5));
990 
991       assertEquals(strictlyOrderedList, ordering.sortedCopy(shuffledList));
992 
993       if (!strictlyOrderedList.contains(null)) {
994         assertEquals(strictlyOrderedList, ordering.immutableSortedCopy(shuffledList));
995       }
996     }
997   }
998 
999   /**
1000    * A means for changing an Ordering into another Ordering. Each instance is responsible for
1001    * creating the alternate Ordering, and providing a List that is known to be ordered, based on an
1002    * input List known to be ordered according to the input Ordering.
1003    */
1004   private enum OrderingMutation {
1005     REVERSE {
1006       @Override
1007       <T> Scenario<?> mutate(Scenario<T> scenario) {
1008         List<T> newList = Lists.newArrayList(scenario.strictlyOrderedList);
1009         Collections.reverse(newList);
1010         return new Scenario<T>(scenario.ordering.reverse(), newList, scenario.emptyArray);
1011       }
1012     },
1013     NULLS_FIRST {
1014       @Override
1015       <T> Scenario<?> mutate(Scenario<T> scenario) {
1016         @SuppressWarnings("unchecked")
1017         List<T> newList = Lists.newArrayList((T) null);
1018         for (T t : scenario.strictlyOrderedList) {
1019           if (t != null) {
1020             newList.add(t);
1021           }
1022         }
1023         return new Scenario<T>(scenario.ordering.nullsFirst(), newList, scenario.emptyArray);
1024       }
1025     },
1026     NULLS_LAST {
1027       @Override
1028       <T> Scenario<?> mutate(Scenario<T> scenario) {
1029         List<T> newList = Lists.newArrayList();
1030         for (T t : scenario.strictlyOrderedList) {
1031           if (t != null) {
1032             newList.add(t);
1033           }
1034         }
1035         newList.add(null);
1036         return new Scenario<T>(scenario.ordering.nullsLast(), newList, scenario.emptyArray);
1037       }
1038     },
1039     ON_RESULT_OF {
1040       @Override
1041       <T> Scenario<?> mutate(final Scenario<T> scenario) {
1042         Ordering<Integer> ordering =
1043             scenario.ordering.onResultOf(
1044                 new Function<Integer, T>() {
1045                   @Override
1046                   public T apply(@Nullable Integer from) {
1047                     return scenario.strictlyOrderedList.get(from);
1048                   }
1049                 });
1050         List<Integer> list = Lists.newArrayList();
1051         for (int i = 0; i < scenario.strictlyOrderedList.size(); i++) {
1052           list.add(i);
1053         }
1054         return new Scenario<>(ordering, list, new Integer[0]);
1055       }
1056     },
1057     COMPOUND_THIS_WITH_NATURAL {
1058       @SuppressWarnings("unchecked") // raw array
1059       @Override
1060       <T> Scenario<?> mutate(Scenario<T> scenario) {
1061         List<Composite<T>> composites = Lists.newArrayList();
1062         for (T t : scenario.strictlyOrderedList) {
1063           composites.add(new Composite<T>(t, 1));
1064           composites.add(new Composite<T>(t, 2));
1065         }
1066         Ordering<Composite<T>> ordering =
1067             scenario
1068                 .ordering
1069                 .onResultOf(Composite.<T>getValueFunction())
1070                 .compound(Ordering.natural());
1071         return new Scenario<Composite<T>>(ordering, composites, new Composite[0]);
1072       }
1073     },
1074     COMPOUND_NATURAL_WITH_THIS {
1075       @SuppressWarnings("unchecked") // raw array
1076       @Override
1077       <T> Scenario<?> mutate(Scenario<T> scenario) {
1078         List<Composite<T>> composites = Lists.newArrayList();
1079         for (T t : scenario.strictlyOrderedList) {
1080           composites.add(new Composite<T>(t, 1));
1081         }
1082         for (T t : scenario.strictlyOrderedList) {
1083           composites.add(new Composite<T>(t, 2));
1084         }
1085         Ordering<Composite<T>> ordering =
1086             Ordering.natural()
1087                 .compound(scenario.ordering.onResultOf(Composite.<T>getValueFunction()));
1088         return new Scenario<Composite<T>>(ordering, composites, new Composite[0]);
1089       }
1090     },
1091     LEXICOGRAPHICAL {
1092       @SuppressWarnings("unchecked") // dang varargs
1093       @Override
1094       <T> Scenario<?> mutate(Scenario<T> scenario) {
1095         List<Iterable<T>> words = Lists.newArrayList();
1096         words.add(Collections.<T>emptyList());
1097         for (T t : scenario.strictlyOrderedList) {
1098           words.add(Arrays.asList(t));
1099           for (T s : scenario.strictlyOrderedList) {
1100             words.add(Arrays.asList(t, s));
1101           }
1102         }
1103         return new Scenario<Iterable<T>>(
1104             scenario.ordering.lexicographical(), words, new Iterable[0]);
1105       }
1106     },
1107     ;
1108 
1109     abstract <T> Scenario<?> mutate(Scenario<T> scenario);
1110   }
1111 
1112   /**
1113    * A dummy object we create so that we can have something meaningful to have a compound ordering
1114    * over.
1115    */
1116   private static class Composite<T> implements Comparable<Composite<T>> {
1117     final T value;
1118     final int rank;
1119 
1120     Composite(T value, int rank) {
1121       this.value = value;
1122       this.rank = rank;
1123     }
1124 
1125     // natural order is by rank only; the test will compound() this with the
1126     // order of 't'.
1127     @Override
1128     public int compareTo(Composite<T> that) {
1129       return Ints.compare(rank, that.rank);
1130     }
1131 
1132     static <T> Function<Composite<T>, T> getValueFunction() {
1133       return new Function<Composite<T>, T>() {
1134         @Override
1135         public T apply(Composite<T> from) {
1136           return from.value;
1137         }
1138       };
1139     }
1140   }
1141 
1142   @GwtIncompatible // NullPointerTester
1143   public void testNullPointerExceptions() {
1144     NullPointerTester tester = new NullPointerTester();
1145     tester.testAllPublicStaticMethods(Ordering.class);
1146 
1147     // any Ordering<Object> instance that accepts nulls should be good enough
1148     tester.testAllPublicInstanceMethods(Ordering.usingToString().nullsFirst());
1149   }
1150 
1151   private static <T> List<T> shuffledCopy(List<T> in, Random random) {
1152     List<T> mutable = newArrayList(in);
1153     List<T> out = newArrayList();
1154     while (!mutable.isEmpty()) {
1155       out.add(mutable.remove(random.nextInt(mutable.size())));
1156     }
1157     return out;
1158   }
1159 }
1160