public static RLESparseResourceAllocation merge(ResourceCalculator resCalc,
      Resource clusterResource, RLESparseResourceAllocation a,
      RLESparseResourceAllocation b, RLEOperator operator, long start, long end)
      throws PlanningException {
    NavigableMap<Long, Resource> cumA =
        a.getRangeOverlapping(start, end).getCumulative();
    NavigableMap<Long, Resource> cumB =
        b.getRangeOverlapping(start, end).getCumulative();
    NavigableMap<Long, Resource> out =
        merge(resCalc, clusterResource, cumA, cumB, start, end, operator);
    return new RLESparseResourceAllocation(out, resCalc);
  }
@Test
  public void testMergesubtractTestNonNegative() throws PlanningException {

    // starting with default array example
    TreeMap<Long, Resource> a = new TreeMap<>();
    TreeMap<Long, Resource> b = new TreeMap<>();

    setupArrays(a, b);

    RLESparseResourceAllocation rleA =
        new RLESparseResourceAllocation(a, new DefaultResourceCalculator());
    RLESparseResourceAllocation rleB =
        new RLESparseResourceAllocation(b, new DefaultResourceCalculator());

    try {
      RLESparseResourceAllocation out =
          RLESparseResourceAllocation.merge(new DefaultResourceCalculator(),
              Resource.newInstance(100 * 128 * 1024, 100 * 32), rleA, rleB,
              RLEOperator.subtractTestNonNegative, 0, 60);
      fail();
    } catch (PlanningException pe) {
      // Expected!
    }

    // NOTE a is empty!! so the subtraction is implicitly considered negative
    // and the test should fail

    a = new TreeMap<>();
    b = new TreeMap<>();
    b.put(11L, Resource.newInstance(5, 6));

    rleA = new RLESparseResourceAllocation(a, new DefaultResourceCalculator());
    rleB = new RLESparseResourceAllocation(b, new DefaultResourceCalculator());

    try {
      RLESparseResourceAllocation out =
          RLESparseResourceAllocation.merge(new DefaultResourceCalculator(),
              Resource.newInstance(100 * 128 * 1024, 100 * 32), rleA, rleB,
              RLEOperator.subtractTestNonNegative, 0, 60);
      fail();
    } catch (PlanningException pe) {
      // Expected!
    }

    // Testing that the subtractTestNonNegative detects problems even if only
    // one
    // of the resource dimensions is "<0"
    a.put(10L, Resource.newInstance(10, 5));
    b.put(11L, Resource.newInstance(5, 6));

    rleA = new RLESparseResourceAllocation(a, new DefaultResourceCalculator());
    rleB = new RLESparseResourceAllocation(b, new DefaultResourceCalculator());

    try {
      RLESparseResourceAllocation out =
          RLESparseResourceAllocation.merge(new DefaultResourceCalculator(),
              Resource.newInstance(100 * 128 * 1024, 100 * 32), rleA, rleB,
              RLEOperator.subtractTestNonNegative, 0, 60);
      fail();
    } catch (PlanningException pe) {
      // Expected!
    }

    // try with reverse setting
    a.put(10L, Resource.newInstance(5, 10));
    b.put(11L, Resource.newInstance(6, 5));

    rleA = new RLESparseResourceAllocation(a, new DefaultResourceCalculator());
    rleB = new RLESparseResourceAllocation(b, new DefaultResourceCalculator());

    try {
      RLESparseResourceAllocation out =
          RLESparseResourceAllocation.merge(new DefaultResourceCalculator(),
              Resource.newInstance(100 * 128 * 1024, 100 * 32), rleA, rleB,
              RLEOperator.subtractTestNonNegative, 0, 60);
      fail();
    } catch (PlanningException pe) {
      // Expected!
    }

    // trying a case that should work
    a.put(10L, Resource.newInstance(10, 6));
    b.put(11L, Resource.newInstance(5, 6));

    rleA = new RLESparseResourceAllocation(a, new DefaultResourceCalculator());
    rleB = new RLESparseResourceAllocation(b, new DefaultResourceCalculator());

    RLESparseResourceAllocation out =
        RLESparseResourceAllocation.merge(new DefaultResourceCalculator(),
            Resource.newInstance(100 * 128 * 1024, 100 * 32), rleA, rleB,
            RLEOperator.subtractTestNonNegative, 0, 60);

  }