function testTree_MultipleCrossColumnIndices() {
  var treeBefore =
      'select(value_pred(CrossColumnTable.string1 gt StringValue1))\n' +
      '-select(value_pred(CrossColumnTable.integer2 gt 100))\n' +
      '--select(value_pred(CrossColumnTable.integer1 gte 400))\n' +
      '---select(value_pred(CrossColumnTable.string2 eq StringValue2))\n' +
      '----table_access(CrossColumnTable)\n';

  var treeAfter =
      'select(value_pred(CrossColumnTable.integer2 gt 100))\n' +
      '-select(value_pred(CrossColumnTable.integer1 gte 400))\n' +
      '--table_access_by_row_id(CrossColumnTable)\n' +
      '---index_range_scan(CrossColumnTable.idx_crossNull, ' +
          '(StringValue1, unbound],[StringValue2, StringValue2], natural)\n';

  var indices = cct.getIndices();
  lf.testing.util.simulateIndexCost(
      propertyReplacer, indexStore, indices[0], 100);
  lf.testing.util.simulateIndexCost(
      propertyReplacer, indexStore, indices[1], 10);

  var constructTree = function() {
    var queryContext = new lf.query.SelectContext(hr.db.getSchema());
    queryContext.from = [cct];
    queryContext.where = lf.op.and(
        cct.string1.gt('StringValue1'),
        cct.integer2.gt(100),
        cct.integer1.gte(400),
        cct.string2.eq('StringValue2'));

    var selectNode1 = createSelectStep(queryContext, 0);
    var selectNode2 = createSelectStep(queryContext, 1);
    var selectNode3 = createSelectStep(queryContext, 2);
    var selectNode4 = createSelectStep(queryContext, 3);
    var tableAccessNode = new lf.proc.TableAccessFullStep(
        hr.db.getGlobal(), queryContext.from[0]);
    selectNode1.addChild(selectNode2);
    selectNode2.addChild(selectNode3);
    selectNode3.addChild(selectNode4);
    selectNode4.addChild(tableAccessNode);

    return {
      queryContext: queryContext,
      root: selectNode1
    };
  };

  lf.testing.treeutil.assertTreeTransformation(
      constructTree(), treeBefore, treeAfter, pass);
}
Tests a tree where
 - two cross-column indices exist, each index is indexing two columns (one of
   which is a nullable index).
 - two predicates exist for the first cross-column index.
 - two predicates exist for the second cross-column index.

 It ensures that the most selective index is chosen by the optimizer and that
 the predicates are correctly replaced by an IndexRangeScanStep in the tree.