1 /*
   2  * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package test.javafx.collections;
  27 
  28 import com.sun.javafx.collections.NonIterableChange.SimplePermutationChange;
  29 import com.sun.javafx.collections.ObservableListWrapper;
  30 import java.util.ArrayList;
  31 import java.util.HashMap;
  32 import java.util.List;
  33 import java.util.Collections;
  34 import java.util.Arrays;
  35 import java.util.Comparator;
  36 import java.util.Map;
  37 
  38 import javafx.beans.Observable;
  39 import javafx.beans.property.SimpleObjectProperty;
  40 import javafx.collections.FXCollections;
  41 import javafx.collections.ListChangeListener;
  42 import javafx.collections.ObservableList;
  43 import javafx.collections.ObservableListWrapperShim;
  44 import javafx.collections.transformation.FilteredList;
  45 import javafx.collections.transformation.SortedList;
  46 import org.junit.Before;
  47 import org.junit.Test;
  48 import static org.junit.Assert.* ;
  49 import static org.junit.Assert.assertEquals;
  50 
  51 public class SortedListTest {
  52 
  53     private ObservableList<String> list;
  54     private MockListObserver<String> mockListObserver;
  55     private SortedList<String> sortedList;
  56 
  57     @Before
  58     public void setUp() {
  59         list = FXCollections.observableArrayList();
  60         list.addAll("a", "c", "d", "c");
  61         sortedList = list.sorted();
  62         mockListObserver = new MockListObserver<String>();
  63         sortedList.addListener(mockListObserver);
  64     }
  65 
  66     @Test
  67     public void testNoChange() {
  68         assertEquals(Arrays.asList("a", "c", "c", "d"), sortedList);
  69         mockListObserver.check0();
  70 
  71         compareIndices();
  72     }
  73 
  74     @Test
  75     public void testAdd() {
  76         list.clear();
  77         mockListObserver.clear();
  78         assertEquals(Collections.emptyList(), sortedList);
  79         list.addAll("a", "c", "d", "c");
  80         assertEquals(Arrays.asList("a", "c", "c", "d"), sortedList);
  81         mockListObserver.check1AddRemove(sortedList, Collections.<String>emptyList(), 0, 4);
  82         assertEquals(0, sortedList.getSourceIndex(0));
  83         assertEquals(2, sortedList.getSourceIndex(3));
  84 
  85         compareIndices();
  86     }
  87 
  88     //TODO: replace with sorted.getViewIndex when JDK-8139848 is fixed
  89     private <E> int getViewIndex(SortedList<E> sorted, int sourceIndex) {
  90         for (int i = 0; i < sorted.size(); i++) {
  91             if (sourceIndex == sorted.getSourceIndex(i)) {
  92                 return i;
  93             }
  94         }
  95         return -1;
  96     }
  97 
  98     private <E> void compareIndices(SortedList<E> sorted) {
  99         ObservableList<? extends E> source = sorted.getSource();
 100         for (int i = 0; i < sorted.size(); i++) {
 101             // i as a view index
 102             int sourceIndex = sorted.getSourceIndex(i);
 103             assertEquals(i, getViewIndex(sorted, sourceIndex));
 104             assertSame(sorted.get(i), source.get(sourceIndex));
 105 
 106             // i as a source index
 107             int viewIndex = getViewIndex(sorted, i);
 108             assertEquals(i, sorted.getSourceIndex(viewIndex));
 109             assertSame(source.get(i), sorted.get(viewIndex));
 110         }
 111     }
 112 
 113     private void compareIndices() {
 114         compareIndices(sortedList);
 115     }
 116 
 117     @Test
 118     public void testAddSingle() {
 119         list.add("b");
 120         assertEquals(Arrays.asList("a", "b", "c", "c", "d"), sortedList);
 121         mockListObserver.check1AddRemove(sortedList, Collections.<String>emptyList(), 1, 2);
 122         assertEquals(0, sortedList.getSourceIndex(0));
 123         assertEquals(4, sortedList.getSourceIndex(1));
 124         assertEquals(1, sortedList.getSourceIndex(2));
 125         assertEquals(3, sortedList.getSourceIndex(3));
 126         assertEquals(2, sortedList.getSourceIndex(4));
 127 
 128         compareIndices();
 129     }
 130 
 131     @Test
 132     public void testRemove() {
 133         list.removeAll(Arrays.asList("c")); // removes "c", "d", "c", adds "d"
 134         assertEquals(Arrays.asList("a", "d"), sortedList);
 135         mockListObserver.check1AddRemove(sortedList, Arrays.asList("c", "c"), 1, 1);
 136         assertEquals(0, sortedList.getSourceIndex(0));
 137         assertEquals(1, sortedList.getSourceIndex(1));
 138         mockListObserver.clear();
 139         list.removeAll(Arrays.asList("a", "d"));
 140         mockListObserver.check1AddRemove(sortedList, Arrays.asList("a", "d"), 0, 0);
 141 
 142         compareIndices();
 143     }
 144 
 145     @Test
 146     public void testRemoveSingle() {
 147         list.remove("a");
 148         assertEquals(Arrays.asList("c", "c", "d"), sortedList);
 149         mockListObserver.check1AddRemove(sortedList, Arrays.asList("a"), 0, 0);
 150         assertEquals(0, sortedList.getSourceIndex(0));
 151         assertEquals(2, sortedList.getSourceIndex(1));
 152         assertEquals(1, sortedList.getSourceIndex(2));
 153 
 154         compareIndices();
 155     }
 156 
 157     @Test
 158     public void testMultipleOperations() {
 159         list.remove(2);
 160         assertEquals(Arrays.asList("a", "c", "c"), sortedList);
 161         mockListObserver.check1AddRemove(sortedList, Arrays.asList("d"), 3, 3);
 162         mockListObserver.clear();
 163         list.add("b");
 164         assertEquals(Arrays.asList("a", "b", "c", "c"), sortedList);
 165         mockListObserver.check1AddRemove(sortedList, Collections.<String>emptyList(), 1, 2);
 166 
 167         compareIndices();
 168     }
 169 
 170     @Test
 171     public void testPureRemove() {
 172         list.removeAll(Arrays.asList("c", "d"));
 173         mockListObserver.check1AddRemove(sortedList, Arrays.asList("c", "c", "d"), 1, 1);
 174         assertEquals(0, sortedList.getSourceIndex(0));
 175 
 176         compareIndices();
 177     }
 178 
 179     @Test
 180     public void testChangeComparator() {
 181         SimpleObjectProperty<Comparator<String>> op =
 182                 new SimpleObjectProperty<>(Comparator.naturalOrder());
 183 
 184         sortedList = new SortedList<>(list);
 185         assertEquals(Arrays.asList("a", "c", "d", "c"), sortedList);
 186         compareIndices();
 187 
 188         sortedList.comparatorProperty().bind(op);
 189         assertEquals(Arrays.asList("a", "c", "c", "d"), sortedList);
 190         compareIndices();
 191 
 192         sortedList.addListener(mockListObserver);
 193 
 194         op.set((Comparator<String>) (String o1, String o2) -> -o1.compareTo(o2));
 195         assertEquals(Arrays.asList("d", "c", "c", "a"), sortedList);
 196         mockListObserver.check1Permutation(sortedList, new int[] {3, 1, 2, 0}); // could be also 3, 2, 1, 0, but the algorithm goes this way
 197         compareIndices();
 198 
 199         mockListObserver.clear();
 200         op.set(null);
 201         assertEquals(Arrays.asList("a", "c", "d", "c"), sortedList);
 202         mockListObserver.check1Permutation(sortedList, new int[] {2, 1, 3, 0});
 203         compareIndices();
 204     }
 205 
 206 
 207    /**
 208      * A slightly updated test provided by "Kleopatra" (http://javafx-jira.kenai.com/browse/RT-14400)
 209      */
 210     @Test
 211     public void testSourceIndex() {
 212         final ObservableList<Double> sourceList = FXCollections.observableArrayList(
 213                 1300., 400., 600.
 214               );
 215         // the list to be removed again, note that its highest value is greater
 216         // then the highest in the base list before adding
 217         List<Double> other = Arrays.asList(
 218                 50., -300., 4000.
 219         );
 220         sourceList.addAll(other);
 221         // wrap into a sorted list and add a listener to the sorted
 222         final SortedList<Double> sorted = sourceList.sorted();
 223         ListChangeListener<Double> listener = c -> {
 224             assertEquals(Arrays.<Double>asList(400.0, 600.0, 1300.0), c.getList());
 225 
 226             c.next();
 227             assertEquals(Arrays.<Double>asList(-300.0, 50.0), c.getRemoved());
 228             assertEquals(0, c.getFrom());
 229             assertEquals(0, c.getTo());
 230             assertTrue(c.next());
 231             assertEquals(Arrays.<Double>asList(4000.), c.getRemoved());
 232             assertEquals(3, c.getFrom());
 233             assertEquals(3, c.getTo());
 234             assertFalse(c.next());
 235 
 236 
 237             // grab sourceIndex of last (aka: highest) value in sorted list
 238             int sourceIndex = sorted.getSourceIndex(sorted.size() - 1);
 239             assertEquals(0, sourceIndex);
 240         };
 241         sorted.addListener(listener);
 242         sourceList.removeAll(other);
 243 
 244         compareIndices(sorted);
 245     }
 246 
 247     @Test
 248     public void testMutableElement() {
 249         ObservableList<Person> list = createPersonsList();
 250 
 251         SortedList<Person> sorted = list.sorted();
 252         assertEquals(Arrays.asList(
 253                 new Person("five"), new Person("four"), new Person("one"),
 254                 new Person("three"), new Person("two")),
 255                 sorted);
 256         MockListObserver<Person> listener = new MockListObserver<>();
 257         sorted.addListener(listener);
 258         list.get(3).name.set("zero"); // four -> zero
 259         ObservableList<Person> expected = FXCollections.observableArrayList(
 260                 new Person("five"), new Person("one"), new Person("three"),
 261                 new Person("two"), new Person("zero"));
 262         listener.checkPermutation(0, expected, 0, list.size(), new int[]{0, 4, 1, 2, 3});
 263         listener.checkUpdate(1, expected, 4, 5);
 264         assertEquals(expected, sorted);
 265 
 266         compareIndices(sorted);
 267     }
 268 
 269     @Test
 270     public void testMutableElementUnsorted_rt39541() {
 271         ObservableList<Person> list = createPersonsList();
 272         SortedList<Person> unsorted = new SortedList<>(list);
 273         MockListObserver<Person> listener = new MockListObserver<>();
 274         unsorted.addListener(listener);
 275         list.get(3).name.set("zero"); // four -> zero
 276         ObservableList<Person> expected = FXCollections.observableArrayList(
 277                 new Person("one"), new Person("two"), new Person("three"),
 278                 new Person("zero"), new Person("five"));
 279         listener.check1Update(expected, 3, 4);
 280 
 281         compareIndices(unsorted);
 282     }
 283 
 284     @Test
 285     public void testMutableElementUnsortedChain_rt39541() {
 286         ObservableList<Person> items = createPersonsList();
 287 
 288         SortedList<Person> sorted = items.sorted();
 289         SortedList<Person> unsorted = new SortedList<>(sorted);
 290 
 291         assertEquals(sorted, unsorted);
 292 
 293         MockListObserver<Person> listener = new MockListObserver<>();
 294         unsorted.addListener(listener);
 295         items.get(3).name.set("zero"); // "four" -> "zero"
 296         ObservableList<Person> expected = FXCollections.observableArrayList(
 297                 new Person("five"), new Person("one"), new Person("three"),
 298                 new Person("two"), new Person("zero"));
 299         listener.checkPermutation(0, expected, 0, expected.size(), new int[] {0, 4, 1, 2, 3});
 300         listener.checkUpdate(1, expected, 4, 5);
 301         assertEquals(expected, sorted);
 302         assertEquals(expected, unsorted);
 303 
 304         compareIndices(sorted);
 305         compareIndices(unsorted);
 306     }
 307 
 308     @Test
 309     public void testMutableElementSortedFilteredChain() {
 310         ObservableList<Person> items = FXCollections.observableArrayList(
 311                 (Person p) -> new Observable[]{p.name});
 312         items.addAll(
 313                 new Person("b"), new Person("c"), new Person("a"),
 314                 new Person("f"), new Person("e"), new Person("d"));
 315 
 316         FilteredList<Person> filtered = items.filtered(e -> !e.name.get().startsWith("z"));
 317         MockListObserver<Person> filterListener = new MockListObserver<>();
 318         filtered.addListener(filterListener);
 319 
 320         SortedList<Person> sorted = filtered.sorted((x, y) -> x.name.get().compareTo(y.name.get()));
 321         MockListObserver<Person> sortListener = new MockListObserver<>();
 322         sorted.addListener(sortListener);
 323         items.get(2).name.set("z"); // "a" -> "z"
 324         filterListener.check1AddRemove(filtered, Arrays.asList(new Person("z")), 2, 2);
 325         sortListener.check1AddRemove(sorted, Arrays.asList(new Person("z")), 0, 0);
 326         ObservableList<Person> expected = FXCollections.observableArrayList(
 327                 new Person("b"), new Person("c"), new Person("d"),
 328                 new Person("e"), new Person("f"));
 329         assertEquals(expected, sorted);
 330 
 331         compareIndices(sorted);
 332     }
 333 
 334     private ObservableList<Person> createPersonsList() {
 335         ObservableList<Person> list = FXCollections.observableArrayList(
 336                 (Person p) -> new Observable[]{p.name});
 337         list.addAll(
 338                 new Person("one"), new Person("two"), new Person("three"),
 339                 new Person("four"), new Person("five"));
 340         return list;
 341     }
 342 
 343     @Test
 344     public void testNotComparable() {
 345         final Object o1 = new Object() {
 346 
 347             @Override
 348             public String toString() {
 349                 return "c";
 350             }
 351         };
 352         final Object o2 = new Object() {
 353 
 354             @Override
 355             public String toString() {
 356                 return "a";
 357             }
 358         };
 359         final Object o3 = new Object() {
 360 
 361             @Override
 362             public String toString() {
 363                 return "d";
 364             }
 365         };
 366         ObservableList<Object> list = FXCollections.observableArrayList(o1, o2, o3);
 367 
 368         SortedList<Object> sorted = list.sorted();
 369         assertEquals(Arrays.asList(o2, o1, o3), sorted);
 370 
 371         compareIndices(sorted);
 372     }
 373 
 374     @Test
 375     public void testCompareNulls() {
 376         ObservableList<String> list = FXCollections.observableArrayList( "g", "a", null, "z");
 377 
 378         SortedList<String> sorted = list.sorted();
 379         assertEquals(Arrays.asList(null, "a", "g", "z"), sorted);
 380 
 381         compareIndices(sorted);
 382     }
 383 
 384 
 385     private static class Permutator<E> extends ObservableListWrapper<E> {
 386         private List<E> backingList;
 387         public Permutator(List<E> list) {
 388             super(list);
 389             this.backingList = list;
 390         }
 391 
 392         public void swap() {
 393             E first = get(0);
 394             backingList.set(0, get(size() - 1));
 395             backingList.set(size() -1, first);
 396             ObservableListWrapperShim.fireChange(this,
 397                 new SimplePermutationChange(0, size(), new int[] {2, 1, 0}, this));
 398         }
 399 
 400     }
 401     /**
 402      * SortedList cant cope with permutations.
 403      */
 404     @Test
 405     public void testPermutate() {
 406         List<Integer> list = new ArrayList<Integer>();
 407         for (int i = 0; i < 3; i++) {
 408             list.add(i);
 409         }
 410         Permutator<Integer> permutator = new Permutator<Integer>(list);
 411         SortedList<Integer> sorted = new SortedList<Integer>(permutator);
 412         permutator.swap();
 413 
 414         compareIndices(sorted);
 415     }
 416 
 417     @Test
 418     public void testUnsorted() {
 419         SortedList<String> sorted = new SortedList<>(list);
 420         assertEquals(sorted, list);
 421         assertEquals(list, sorted);
 422 
 423         list.removeAll("a", "d");
 424 
 425         assertEquals(sorted, list);
 426 
 427         list.addAll(0, Arrays.asList("a", "b", "c"));
 428 
 429         assertEquals(sorted, list);
 430 
 431         FXCollections.sort(list);
 432 
 433         assertEquals(sorted, list);
 434 
 435         compareIndices(sorted);
 436     }
 437 
 438     @Test
 439     public void testUnsorted2() {
 440         list.setAll("a", "b", "c", "d", "e", "f");
 441         SortedList<String> sorted = new SortedList<>(list);
 442         assertEquals(sorted, list);
 443 
 444         list.removeAll("b", "c", "d");
 445 
 446         assertEquals(sorted, list);
 447 
 448         compareIndices(sorted);
 449     }
 450 
 451     @Test
 452     public void testSortedNaturalOrder() {
 453         assertEquals(Arrays.asList("a", "c", "c", "d"), list.sorted());
 454     }
 455 
 456     @Test
 457     public void testRemoveFromDuplicates() {
 458         String toRemove = new String("A");
 459         String other = new String("A");
 460         list = FXCollections.observableArrayList(other, toRemove);
 461         Comparator<String> c = Comparator.naturalOrder();
 462         SortedList<String> sorted = list.sorted(c);
 463 
 464         list.remove(1);
 465 
 466         assertEquals(1, sorted.size());
 467         assertTrue(sorted.get(0) == other);
 468 
 469         compareIndices(sorted);
 470     }
 471 
 472     @Test
 473     public void testAddAllOnEmpty() {
 474         list = FXCollections.observableArrayList();
 475         SortedList<String> sl = list.sorted(String.CASE_INSENSITIVE_ORDER);
 476         list.addAll("B", "A");
 477 
 478         assertEquals(Arrays.asList("A", "B"), sl);
 479 
 480         compareIndices(sl);
 481     }
 482 
 483     @Test
 484     public void test_rt36353_sortedList() {
 485         ObservableList<String> data = FXCollections.observableArrayList("2", "1", "3");
 486         SortedList<String> sortedList = new SortedList<String>(data);
 487 
 488         HashMap<Integer, Integer> pMap = new HashMap<>();
 489         sortedList.addListener((ListChangeListener<String>) c -> {
 490             while (c.next()) {
 491                 if (c.wasPermutated()) {
 492                     for (int i = c.getFrom(); i < c.getTo(); i++) {
 493                         pMap.put(i, c.getPermutation(i));
 494                     }
 495                 }
 496             }
 497         });
 498 
 499         Map<Integer, Integer> expected = new HashMap<>();
 500 
 501         // comparator that will create list of [1,2,3]. Sort indices based on
 502         // previous order [2,1,3].
 503         sortedList.setComparator((s1,s2) -> s1.compareTo(s2));
 504         assertEquals(FXCollections.observableArrayList("1","2","3"), sortedList);
 505         expected.put(0, 1);     // item "2" has moved from index 0 to index 1
 506         expected.put(1, 0);     // item "1" has moved from index 1 to index 0
 507         expected.put(2, 2);     // item "3" has remained in index 2
 508         assertEquals(expected, pMap);
 509         compareIndices(sortedList);
 510 
 511         // comparator that will create list of [3,2,1]. Sort indices based on
 512         // previous order [1,2,3].
 513         sortedList.setComparator((s1,s2) -> s2.compareTo(s1));
 514         assertEquals(FXCollections.observableArrayList("3","2","1"), sortedList);
 515         expected.clear();
 516         expected.put(0, 2);     // item "1" has moved from index 0 to index 2
 517         expected.put(1, 1);     // item "2" has remained in index 1
 518         expected.put(2, 0);     // item "3" has moved from index 2 to index 0
 519         assertEquals(expected, pMap);
 520         compareIndices(sortedList);
 521 
 522         // null comparator so sort order should return to [2,1,3]. Sort indices based on
 523         // previous order [3,2,1].
 524         sortedList.setComparator(null);
 525         assertEquals(FXCollections.observableArrayList("2","1","3"), sortedList);
 526         expected.clear();
 527         expected.put(0, 2);     // item "3" has moved from index 0 to index 2
 528         expected.put(1, 0);     // item "2" has moved from index 1 to index 0
 529         expected.put(2, 1);     // item "1" has moved from index 2 to index 1
 530         assertEquals(expected, pMap);
 531         compareIndices(sortedList);
 532     }
 533 
 534     @Test
 535     public void testAddWhenUnsorted() {
 536         sortedList.setComparator(null);
 537         mockListObserver.clear();
 538         list.add(2, "b");
 539         assertEquals(5, sortedList.size());
 540         assertEquals(Arrays.asList("a", "c", "b", "d", "c"), sortedList);
 541         mockListObserver.check1AddRemove(sortedList, Collections.emptyList(), 2, 3);
 542         compareIndices();
 543 
 544         mockListObserver.clear();
 545         sortedList.setComparator(Comparator.<String>naturalOrder());
 546         mockListObserver.check1Permutation(sortedList, new int[] {0, 2, 1, 4, 3});
 547         assertEquals(5, sortedList.size());
 548         assertEquals(Arrays.asList("a", "b", "c", "c", "d"), sortedList);
 549         compareIndices();
 550 
 551         mockListObserver.clear();
 552         sortedList.setComparator(null);
 553         assertEquals(5, sortedList.size());
 554         assertEquals(Arrays.asList("a", "c", "b", "d", "c"), sortedList);
 555         mockListObserver.check1Permutation(sortedList, new int[] {0, 2, 1, 4, 3});
 556         compareIndices();
 557     }
 558 
 559     @Test
 560     public void testRemoveWhenUnsorted() {
 561         sortedList.setComparator(null);
 562         mockListObserver.clear();
 563         list.remove(1);
 564         assertEquals(3, sortedList.size());
 565         assertEquals(Arrays.asList("a", "d", "c"), sortedList);
 566         mockListObserver.check1AddRemove(sortedList, Arrays.asList("c"), 1, 1);
 567         compareIndices();
 568 
 569         mockListObserver.clear();
 570         sortedList.setComparator(Comparator.<String>naturalOrder());
 571         mockListObserver.check1Permutation(sortedList, new int[] {0, 2, 1});
 572         assertEquals(3, sortedList.size());
 573         assertEquals(Arrays.asList("a", "c", "d"), sortedList);
 574         compareIndices();
 575 
 576         mockListObserver.clear();
 577         sortedList.setComparator(null);
 578         assertEquals(3, sortedList.size());
 579         assertEquals(Arrays.asList("a", "d", "c"), sortedList);
 580         mockListObserver.check1Permutation(sortedList, new int[] {0, 2, 1});
 581         compareIndices();
 582     }
 583 
 584     @Test
 585     public void testSetWhenUnsorted() {
 586         sortedList.setComparator(null);
 587         mockListObserver.clear();
 588         list.set(1, "e");
 589         assertEquals(4, sortedList.size());
 590         assertEquals(Arrays.asList("a", "e", "d", "c"), sortedList);
 591         mockListObserver.check1AddRemove(sortedList, Arrays.asList("c"), 1, 2);
 592         compareIndices();
 593 
 594         mockListObserver.clear();
 595         sortedList.setComparator(Comparator.<String>naturalOrder());
 596         mockListObserver.check1Permutation(sortedList, new int[] {0, 3, 2, 1});
 597         assertEquals(4, sortedList.size());
 598         assertEquals(Arrays.asList("a", "c", "d", "e"), sortedList);
 599         compareIndices();
 600 
 601         mockListObserver.clear();
 602         sortedList.setComparator(null);
 603         assertEquals(4, sortedList.size());
 604         assertEquals(Arrays.asList("a", "e", "d", "c"), sortedList);
 605         mockListObserver.check1Permutation(sortedList, new int[] {0, 3, 2, 1});
 606         compareIndices();
 607     }
 608 }