@Test
  public void bptree_txn_11() {
    BPlusTree bpt1 = createBPTree();
    BPlusTree bpt2 = createBPTree();
    assertNotEquals(bpt1.getComponentId(), bpt2.getComponentId());

    Transactional thing = transactional(bpt1, bpt2);

    // Commit 1
    Txn.executeWrite(
        thing,
        () -> {
          IndexTestLib.add(bpt1, 2, 1);
          IndexTestLib.add(bpt2, 3, 4, 5);
        });
    Txn.executeRead(
        thing,
        () -> {
          IndexTestLib.testIndexContents(bpt2, 3, 4, 5);
          IndexTestLib.testIndexContents(bpt1, 1, 2);
        });

    // Abort
    thing.begin(ReadWrite.WRITE);
    IndexTestLib.add(bpt1, 9, 10);
    IndexTestLib.delete(bpt2, 3, 11);
    thing.abort();
    Txn.executeRead(
        thing,
        () -> {
          IndexTestLib.testIndexContents(bpt2, 3, 4, 5);
          IndexTestLib.testIndexContents(bpt1, 1, 2);
        });

    // Commit 2
    Txn.executeWrite(
        thing,
        () -> {
          IndexTestLib.delete(bpt1, 1, 3);
          IndexTestLib.add(bpt1, 4);
          IndexTestLib.add(bpt2, 11, 12, 13);
        });
    Txn.executeRead(
        thing,
        () -> {
          IndexTestLib.testIndexContents(bpt2, 3, 4, 5, 11, 12, 13);
          IndexTestLib.testIndexContents(bpt1, 2, 4);
        });
  }
 protected void testClear(int N) {
   int[] keys = new int[N]; // Slice is 1000.
   for (int i = 0; i < keys.length; i++) keys[i] = i;
   RangeIndex rIndex = makeRangeIndex(3);
   add(rIndex, keys);
   if (N > 0) assertFalse(rIndex.isEmpty());
   rIndex.clear();
   assertTrue(rIndex.isEmpty());
 }
 @Test
 public void tree_iter_0_05() {
   int[] keys = {1, 2, 3, 4, 5};
   RangeIndex rIndex = makeRangeIndex(5);
   add(rIndex, keys);
   List<Integer> x = toIntList(rIndex.iterator(r(1), r(0)));
   List<Integer> expected = toIntList();
   assertEquals(expected, x);
 }
 @Test
 public void tree_iter_2_09() {
   int[] keys = {1, 2, 3, 4, /* 5, 6, */ 7, 8, 9, 10, 11};
   RangeIndex rIndex = makeRangeIndex(2);
   add(rIndex, keys);
   List<Integer> x = toIntList(rIndex.iterator(r(5), r(7)));
   List<Integer> expected = toIntList();
   assertEquals(expected, x);
 }
 @Test
 public void tree_iter_2_08() {
   int[] keys = {1, 2, 3, 4, 5, 6, 7, 8, 9};
   RangeIndex rIndex = makeRangeIndex(2);
   add(rIndex, keys);
   List<Integer> x = toIntList(rIndex.iterator(r(0), r(99)));
   List<Integer> expected = toIntList(keys);
   assertEquals(expected, x);
 }
 @Test
 public void tree_iter_2_01() {
   int[] keys = {0, 2, 4, 6, 8, 1, 3, 5, 7, 9};
   RangeIndex rIndex = makeRangeIndex(2);
   add(rIndex, keys);
   List<Integer> x = toIntList(rIndex.iterator(r(4), r(6)));
   List<Integer> expected = toIntList(4, 5);
   assertEquals(expected, x);
 }
 @Test
 public void tree_ret_2() {
   int[] keys = {1, 2, 3, 4, 5};
   RangeIndex rIndex = makeRangeIndex(2);
   add(rIndex, keys);
   boolean b = rIndex.delete(intToRecord(9));
   assertFalse(b);
   b = rIndex.insert(intToRecord(1));
   assertFalse(b);
 }
 // Commit - only the first changes the root.
 @Test
 public void bptree_txn_02() {
   BPlusTree bpt = createBPTree();
   int outerRootIdx1 = bpt.getRootId();
   Transactional thing = transactional(bpt);
   Txn.executeWrite(
       thing,
       () -> {
         int rootIdx1 = bpt.getRootId();
         assertEquals("Inside txn (1)", outerRootIdx1, rootIdx1);
         IndexTestLib.add(bpt, 1);
         int rootIdx2 = bpt.getRootId();
         assertNotEquals("Inside txn (2)", rootIdx1, rootIdx2);
         IndexTestLib.add(bpt, 2, 3, 4);
         int rootIdx3 = bpt.getRootId();
         assertEquals("Inside txn (3)", rootIdx2, rootIdx3);
       });
   int outerRootIdx2 = bpt.getRootId();
   assertNotEquals("After txn", outerRootIdx1, outerRootIdx2);
 }
  // Two trees
  @Test
  public void bptree_txn_10() {
    BPlusTree bpt1 = createBPTree();
    BPlusTree bpt2 = createBPTree();
    assertNotEquals(bpt1.getComponentId(), bpt2.getComponentId());

    Transactional thing = transactional(bpt1, bpt2);
    Txn.executeWrite(
        thing,
        () -> {
          IndexTestLib.add(bpt1, 1, 2, 3);
          IndexTestLib.add(bpt2, 4, 5);
        });
    Txn.executeRead(
        thing,
        () -> {
          IndexTestLib.testIndexContents(bpt2, 4, 5);
          IndexTestLib.testIndexContents(bpt1, 1, 2, 3);
        });
  }
  // Root
  @Test
  public void tree_iter_0_01() {
    int[] keys = {1, 2, 3, 4, 5};
    RangeIndex rIndex = makeRangeIndex(5);
    add(rIndex, keys);
    Iterator<Record> iter = rIndex.iterator(r(2), r(4));
    while (iter.hasNext()) iter.next();

    List<Integer> x = toIntList(rIndex.iterator(r(2), r(4)));
    List<Integer> expected = toIntList(2, 3);
    assertEquals(expected, x);
  }
 // Abort
 @Test
 public void bptree_txn_03() {
   BPlusTree bpt = createBPTree();
   int outerRootIdx1 = bpt.getRootId();
   Transactional thing = transactional(bpt);
   thing.begin(ReadWrite.WRITE);
   IndexTestLib.add(bpt, 1, 2, 3, 4);
   thing.abort();
   thing.end();
   int outerRootIdx2 = bpt.getRootId();
   assertEquals("After txn", outerRootIdx1, outerRootIdx2);
 }
 // Commit
 @Test
 public void bptree_txn_01() {
   BPlusTree bpt = createBPTree();
   assertNotNull(bpt.getComponentId());
   int outerRootIdx1 = bpt.getRootId();
   Transactional thing = transactional(bpt);
   Txn.executeWrite(
       thing,
       () -> {
         IndexTestLib.add(bpt, 1, 2, 3, 4);
       });
   int outerRootIdx2 = bpt.getRootId();
   assertNotEquals("After txn", outerRootIdx1, outerRootIdx2);
 }
 // Two transactions, second a delete no-op.
 // Relies on all blocks not being min0size so not rebalanced.
 @Test
 public void bptree_txn_06() {
   BPlusTree bpt = createBPTree();
   int outerRootIdx1 = bpt.getRootId();
   Transactional thing = transactional(bpt);
   Txn.executeWrite(
       thing,
       () -> {
         IndexTestLib.add(bpt, 1, 2, 3);
       });
   int outerRootIdx2 = bpt.getRootId();
   assertNotEquals("After txn(1)", outerRootIdx1, outerRootIdx2);
   Txn.executeWrite(
       thing,
       () -> {
         IndexTestLib.delete(bpt, 5, 6);
       });
   int outerRootIdx3 = bpt.getRootId();
   assertNotEquals("After txn (2)", outerRootIdx1, outerRootIdx3);
   assertEquals("After txn (3)", outerRootIdx2, outerRootIdx3);
 }