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