@Test
 public void testItemsRemoveRange() {
   int[] indices = new int[] {3, 5, 1};
   indicesList.addIndices(indices);
   // items we expect to appear in removed
   List removedItems = new ArrayList();
   removedItems.add(3);
   removedItems.add(5);
   report.clear();
   // remove items at 3...5, inclusive
   items.remove(3, 6);
   assertEquals(1, indicesList.size());
   //        report.prettyPrint();
   indices = new int[] {1};
   for (int i = 0; i < indices.length; i++) {
     assertEquals("expected value at " + i, indices[i], indicesList.get(i).intValue());
   }
   assertEquals(1, report.getEventCount());
   assertTrue(
       "expected single replaced but was" + report.getLastChange(),
       wasSingleRemoved(report.getLastChange()));
   Change c = report.getLastChange();
   c.next();
   assertEquals(2, c.getRemovedSize());
   assertEquals(removedItems, c.getRemoved());
 }
 @Test
 public void testAddSingle() {
   int index = 3;
   indicesList.addIndices(index);
   assertEquals(1, indicesList.size());
   assertEquals(index, indicesList.get(0).intValue());
   assertEquals(1, report.getEventCount());
 }
 @Test
 public void testSetAlreadySetNoNotification() {
   int[] indices = new int[] {3, 5, 1};
   indicesList.addIndices(indices);
   report.clear();
   indicesList.setIndices(indices);
   assertEquals(0, report.getEventCount());
 }
 /**
  * Test get if index off range. Changed implementation to throw IndexOOB (off range access is
  * always a programming error)
  */
 @Test(expected = IndexOutOfBoundsException.class)
 public void testGetOffRange() {
   int[] indices = new int[] {3, 5, 1};
   indicesList.addIndices(indices);
   assertEquals(indices.length, indicesList.size());
   assertEquals(-1, indicesList.get(-1).intValue());
   assertEquals(-1, indicesList.get(indices.length).intValue());
 }
 /**
  * Optimized contains (same as core in selectedIndicesSeq), need to test if still working.
  *
  * <p>https://javafx-jira.kenai.com/browse/RT-39776
  */
 @Test
 public void testContains() {
   int[] indices = new int[] {3, 5, 1};
   indicesList.addIndices(indices);
   report.clear();
   for (int i : indices) {
     assertTrue("index must be contained: " + i, indicesList.contains(i));
   }
 }
 /**
  * Optimized contains (same as core in selectedIndicesSeq), need to test if still working.
  *
  * <p>https://javafx-jira.kenai.com/browse/RT-39776
  */
 @Test
 public void testContainsNot() {
   int[] indices = new int[] {3, 5, 1};
   indicesList.addIndices(indices);
   report.clear();
   int[] notContained = new int[] {0, 7, 4, 2};
   for (int i : notContained) {
     assertFalse("index must not be contained: " + i, indicesList.contains(i));
   }
 }
 @Test
 public void testItemSetAt() {
   int index = 3;
   indicesList.setIndices(index);
   report.clear();
   items.set(index, "replaced-element-at-3");
   assertEquals(1, indicesList.size());
   assertEquals(index, indicesList.get(0).intValue());
   assertEquals(0, report.getEventCount());
 }
 /** Source index is same as get, kind of. */
 @Test
 public void testSourceIndexInRange() {
   int[] indices = new int[] {3, 5, 1};
   indicesList.addIndices(indices);
   assertEquals(indices.length, indicesList.size());
   Arrays.sort(indices);
   for (int i = 0; i < indices.length; i++) {
     assertEquals("sourceIndex " + i, indices[i], indicesList.getSourceIndex(i));
   }
 }
 /**
  * Since extraction of IndicesBase Changed behaviour of sourceChange: valid only from before
  * endChange to after endChange!
  */
 @Test
 @Ignore
 public void testChangeOnClearItems() {
   int[] indices = new int[] {3, 5, 1};
   indicesList.addIndices(indices);
   report.clear();
   ListChangeReport itemsReport = new ListChangeReport(items);
   //        new PrintingListChangeListener("Items removed before", indicesList);
   items.clear();
   assertEquals(itemsReport.getLastChange(), indicesList.getSourceChange());
 }
 @Test
 public void testChangeNullOnDirectAddAfterItemsModified() {
   int[] indices = new int[] {3, 5, 1};
   indicesList.addIndices(indices);
   report.clear();
   ListChangeReport itemsReport = new ListChangeReport(items);
   //        new PrintingListChangeListener("Items removed before", indicesList);
   items.remove(0);
   indicesList.addIndices(6);
   assertEquals(null, indicesList.getSourceChange());
 }
  @Test
  public void testAddMoreNotification() {
    int[] indices = new int[] {3, 5, 1};
    indicesList.addIndices(indices);
    report.clear();
    int[] more = new int[] {2, 7, 4};
    indicesList.addIndices(more);

    assertEquals(1, report.getEventCount());
    assertEquals(3, getChangeCount(report.getLastChange()));
  }
 /**
  * Test notification on setAll if there are already set indices. Changed implementation due to
  * RT-39776, test assumption incorrect.
  */
 @Test
 public void testSetAllNotificationIfHasSet() {
   int[] indices = new int[] {3, 5, 1};
   indicesList.addIndices(indices);
   report.clear();
   indicesList.setAllIndices();
   //        report.prettyPrint();
   assertEquals(items.size(), indicesList.size());
   assertEquals(1, report.getEventCount());
   Change c = report.getLastChange();
   assertEquals(4, getChangeCount(c, ChangeType.ADDED));
 }
 @Test
 public void testAddMultiple() {
   int[] indices = new int[] {3, 5, 1};
   indicesList.addIndices(indices);
   assertEquals(indices.length, indicesList.size());
   Arrays.sort(indices);
   for (int i = 0; i < indices.length; i++) {
     assertEquals("expected value at " + i, indices[i], indicesList.get(i).intValue());
   }
   assertEquals(1, report.getEventCount());
   assertTrue("got a single added", wasSingleAdded(report.getLastChange()));
 }
  @Test
  public void testItemsReplacedBefore() {
    int[] indices = new int[] {3, 5, 1};
    indicesList.addIndices(indices);
    report.clear();

    items.set(0, "newItem");
    Arrays.sort(indices);
    for (int i = 0; i < indices.length; i++) {
      assertEquals("expected value at " + i, indices[i], indicesList.get(i).intValue());
    }
    assertEquals("selectedIndices unchanged", 0, report.getEventCount());
  }
 /**
  * Try to let indexMappedItems handle their own cleanup on changes to items: make sourceChange a
  * property and test if we can force notification order.
  *
  * <p>Changed implementation: the sourceChange is != only from before endChange to after
  * endChange, so we get 2 notifications, the last with a null.
  */
 @Test
 public void testSourceChangeProperty() {
   int[] indices = new int[] {3, 5, 1};
   indicesList.addIndices(indices);
   report.clear();
   ChangeReport cr = new ChangeReport(indicesList.sourceChangeProperty());
   items.add(0, "something");
   assertEquals(2, cr.getEventCount());
   //        Change c = (Change) cr.getLastOldValue(0);
   //        // PENDING JW: really? there might be several listeners (theoretically)
   //        // with no responsibility to reset the change - such that each
   //        // interested party has to reset before usage anyway
   //        assertTrue("expect change reset", c.next());
 }
 @Test
 public void testItemsRemovedBefore() {
   int[] indices = new int[] {3, 5, 1};
   indicesList.addIndices(indices);
   report.clear();
   items.remove(0);
   for (int i = 0; i < indices.length; i++) {
     indices[i] = indices[i] - 1;
   }
   Arrays.sort(indices);
   for (int i = 0; i < indices.length; i++) {
     assertEquals("expected value at " + i, indices[i], indicesList.get(i).intValue());
   }
   assertEquals(1, report.getEventCount());
 }
 @Test
 public void testClearSomeIndicesNotification() {
   int[] indices = new int[] {3, 5, 1};
   indicesList.addIndices(indices);
   report.clear();
   int[] clear = new int[] {5, 1};
   //        new PrintingListChangeListener("clearSomeNotification", indicesList);
   indicesList.clearIndices(clear);
   assertEquals(1, indicesList.size());
   assertEquals(1, report.getEventCount());
   assertEquals(
       "must be 2 disjoint removes",
       2,
       getChangeCount(report.getLastChange(), ChangeType.REMOVED));
 }
  @Test
  public void testItemsSetAll() {
    int[] indices = new int[] {3, 5, 1};
    indicesList.addIndices(indices);
    report.clear();

    items.setAll("one", "two", "three");
    //        LOG.info("setAll" + report.getLastChange());

    assertEquals("all cleared", 0, indicesList.size());
    assertEquals(1, report.getEventCount());
    assertTrue(
        "expected single removed, but was " + report.getLastChange(),
        wasSingleRemoved(report.getLastChange()));
  }
 /**
  * The spec is: keep the selected on-replace-item - this means no change to the indicesList, no
  * notification.
  */
 @Test
 public void testItemsReplacedAt() {
   int[] indices = new int[] {3, 5, 1};
   indicesList.addIndices(indices);
   report.clear();
   ListChangeReport itemsReport = new ListChangeReport(items);
   items.set(3, "newItem");
   //        itemsReport.prettyPrint();
   Arrays.sort(indices);
   for (int i = 0; i < indices.length; i++) {
     assertEquals("expected value at " + i, indices[i], indicesList.get(i).intValue());
   }
   assertEquals("selectedIndices unchanged", 0, report.getEventCount());
   //        report.prettyPrint();
   //        assertTrue("singleReplaced ", wasSingleReplaced(report.getLastChange()));
 }
  @Test
  public void testItemsSetAllSmallerSize() {
    int[] indices = new int[] {3, 5, 1};
    indicesList.addIndices(indices);
    report.clear();

    ObservableList<String> other = createObservableList(true);
    other.remove(1);
    items.setAll(other);

    assertEquals("all cleared", 0, indicesList.size());
    assertEquals(1, report.getEventCount());
    assertTrue(
        "expected single removed, but was " + report.getLastChange(),
        wasSingleRemoved(report.getLastChange()));
  }
 @Test
 public void testItemsPermutate() {
   int[] indices = new int[] {1, 3, 5};
   indicesList.addIndices(indices);
   report.clear();
   ListChangeReport itemsReport = new ListChangeReport(items);
   // permutation on items
   // [0->8, 1->7, 2->6, 3->5, 4->4, 5->3, 6->2, 7->1, 8->0]
   items.sort(null);
   //        itemsReport.prettyPrint();
   int[] permutated = new int[] {3, 5, 7};
   //        LOG.info("sortedItems" + itemsReport.getLastChange());
   //        LOG.info("sorted: " + report.getLastChange());
   //        report.prettyPrint();
   assertEquals(1, report.getEventCount());
   assertEquals(1, getChangeCount(report.getLastChange(), ChangeType.REPLACED));
   Change c = report.getLastChange();
   c.reset();
   c.next();
   assertEquals("added size same", permutated.length, c.getAddedSize());
   for (int i = 0; i < permutated.length; i++) {
     assertEquals("added at " + i, permutated[i], c.getAddedSubList().get(i));
   }
   assertEquals("removed size same", indices.length, c.getRemovedSize());
   for (int i = 0; i < indices.length; i++) {
     assertEquals("removed at" + i, indices[i], c.getRemoved().get(i));
   }
   //        LOG.info("" + indicesList);
 }
  @Test
  public void testItemsSetAllSameSize() {
    int[] indices = new int[] {3, 5, 1};
    indicesList.addIndices(indices);
    report.clear();
    //        new PrintingListChangeListener("SetAll Same size", indicesList);
    ObservableList<String> other = createObservableList(true);
    // make it not equal
    other.set(0, "otherItem");
    items.setAll(other);

    assertEquals("all cleared", 0, indicesList.size());
    assertEquals(1, report.getEventCount());
    assertTrue(
        "expected single removed, but was " + report.getLastChange(),
        wasSingleRemoved(report.getLastChange()));
  }
 /**
  * Since extraction of IndicesBase Changed behaviour of sourceChange: valid only from before
  * endChange to after endChange!
  */
 @Test
 @Ignore
 public void testSourceChangeNotificationSequence() {
   int[] indices = new int[] {3, 5, 1};
   indicesList.addIndices(indices);
   report.clear();
   List<Object> changes = new ArrayList();
   ChangeListener cpl = (source, old, value) -> changes.add(value);
   indicesList.sourceChangeProperty().addListener(cpl);
   ListChangeListener lcl = c -> changes.add(c);
   indicesList.addListener(lcl);
   ChangeReport cr = new ChangeReport(indicesList.sourceChangeProperty());
   items.add(0, "something");
   assertEquals(2, changes.size());
   assertEquals(cr.getLastNewValue(), changes.get(0));
   assertEquals(report.getLastChange(), changes.get(1));
 }
 @Test
 public void testItemsRemovedAtAndBetween() {
   int[] indices = new int[] {1, 3, 5, 7};
   indicesList.addIndices(indices);
   report.clear();
   //        new PrintingListChangeListener("Items removed at 2/4", indicesList);
   items.removeAll(items.get(3), items.get(6));
   indices = new int[] {1, 4, 5};
   assertEquals(indices.length, indicesList.size());
   for (int i = 0; i < indices.length; i++) {
     assertEquals("expected value at " + i, indices[i], indicesList.get(i).intValue());
   }
   assertEquals(1, report.getEventCount());
   assertTrue(
       "expected single replaced but was" + report.getLastChange(),
       wasSingleReplaced(report.getLastChange()));
 }
 @Test
 public void testItemsAddedBefore() {
   int[] indices = new int[] {3, 5, 1};
   indicesList.addIndices(indices);
   report.clear();
   //        new PrintingListChangeListener("Item added at 0", indicesList);
   items.add(0, "newItem");
   for (int i = 0; i < indices.length; i++) {
     indices[i] = indices[i] + 1;
   }
   Arrays.sort(indices);
   for (int i = 0; i < indices.length; i++) {
     assertEquals("expected value at " + i, indices[i], indicesList.get(i).intValue());
   }
   assertEquals(1, report.getEventCount());
   assertTrue(
       "expected single replaced, but was " + report.getLastChange(),
       wasSingleReplaced(report.getLastChange()));
 }
 @Test
 public void testClearIndicesNotification() {
   int[] indices = new int[] {3, 5, 1};
   indicesList.addIndices(indices);
   report.clear();
   indicesList.clearIndices(indices);
   assertEquals(0, indicesList.size());
   assertEquals(1, report.getEventCount());
   assertTrue("must be single remove", wasSingleRemoved(report.getLastChange()));
   Change c = report.getLastChange();
   c.reset();
   c.next();
   Arrays.sort(indices);
   List base = new ArrayList();
   for (int i = 0; i < indices.length; i++) {
     base.add(indices[i]);
   }
   assertEquals(base, c.getRemoved());
 }
 @Test
 public void testItemsClear() {
   int index = 0;
   indicesList.addIndices(index);
   report.clear();
   //        new PrintingListChangeListener("clear", indicesList);
   items.clear();
   assertEquals(1, report.getEventCount());
   assertTrue(wasSingleRemoved(report.getLastChange()));
 }
 @Test
 public void testSetIndices() {
   int[] indices = new int[] {3, 5, 1};
   indicesList.addIndices(indices);
   report.clear();
   int[] setIndices = new int[] {2, 4, 6, 7};
   indicesList.setIndices(setIndices);
   assertEquals(setIndices.length, indicesList.size());
   assertEquals(1, report.getEventCount());
   assertTrue(wasSingleReplaced(report.getLastChange()));
   Change c = report.getLastChange();
   c.reset();
   c.next();
   Arrays.sort(indices);
   List base = new ArrayList();
   for (int i = 0; i < indices.length; i++) {
     base.add(indices[i]);
   }
   assertEquals(base, c.getRemoved());
 }
 @Test
 public void testItemsRemovedBeforeAndWithFirst() {
   int[] indices = new int[] {3, 5, 1};
   indicesList.addIndices(indices);
   report.clear();
   //        new PrintingListChangeListener("Items removed at 0/1", indicesList);
   items.removeAll(items.get(0), items.get(1));
   assertEquals(indices.length - 1, indicesList.size());
   Arrays.sort(indices);
   indices = Arrays.copyOfRange(indices, 1, 3);
   for (int i = 0; i < indices.length; i++) {
     indices[i] = indices[i] - 2;
   }
   for (int i = 0; i < indices.length; i++) {
     assertEquals("expected value at " + i, indices[i], indicesList.get(i).intValue());
   }
   assertEquals(1, report.getEventCount());
   assertTrue(
       "expected single replaced, but was " + report.getLastChange(),
       wasSingleReplaced(report.getLastChange()));
 }
 /** Remove items in between selected. */
 @Test
 public void testItemsRemovedBetweenReally() {
   int[] indices = new int[] {3, 5, 1};
   indicesList.addIndices(indices);
   report.clear();
   items.removeAll(items.get(2), items.get(4));
   assertEquals(indices.length, indicesList.size());
   indices = new int[] {1, 2, 3};
   for (int i = 0; i < indices.length; i++) {
     assertEquals("expected value at " + i, indices[i], indicesList.get(i).intValue());
   }
   assertEquals(1, report.getEventCount());
   assertTrue(
       "expected single replaced but was" + report.getLastChange(),
       wasSingleReplaced(report.getLastChange()));
   Change c = report.getLastChange();
   c.next();
   assertEquals(2, c.getAddedSize());
   assertEquals(c.getAddedSize(), c.getRemovedSize());
   //        report.prettyPrint();
 }