@Test
public void testPerQueueDisablePreemptionHierarchical() {

  int[][] qData = new int[][] {
    //  /    A              D
    //            B    C         E    F
    { 200, 100,  50,  50, 100,  10,  90 },  // abs
    { 200, 200, 200, 200, 200, 200, 200 },  // maxCap
    { 200, 110,  60,  50,  90,  90,   0 },  // used
    {  10,   0,   0,   0,  10,   0,  10 },  // pending
    {   0,   0,   0,   0,   0,   0,   0 },  // reserved
    //          appA appB      appC appD
    {   4,   2,   1,   1,   2,   1,   1 },  // apps
    {  -1,  -1,   1,   1,  -1,   1,   1 },  // req granularity
    {   2,   2,   0,   0,   2,   0,   0 },  // subqueues
  };
  ProportionalCapacityPreemptionPolicy policy = buildPolicy(qData);
  policy.editSchedule();
  // verify capacity taken from queueB (appA), not queueE (appC) despite 
  // queueE being far over its absolute capacity because queueA (queueB's
  // parent) is over capacity and queueD (queueE's parent) is not.
  ApplicationAttemptId expectedAttemptOnQueueB = 
      ApplicationAttemptId.newInstance(
          appA.getApplicationId(), appA.getAttemptId());
  assertTrue("appA should be running on queueB",
      mCS.getAppsInQueue("queueB").contains(expectedAttemptOnQueueB));
  verify(mDisp, times(9)).handle(argThat(new IsPreemptionRequestFor(appA)));
  // Need to call setup() again to reset mDisp
  setup();
  // Turn off preemption for queueB and it's children
  schedConf.setPreemptionDisabled("root.queueA.queueB", true);
  ProportionalCapacityPreemptionPolicy policy2 = buildPolicy(qData);
  policy2.editSchedule();
  ApplicationAttemptId expectedAttemptOnQueueC = 
      ApplicationAttemptId.newInstance(
          appB.getApplicationId(), appB.getAttemptId());
  ApplicationAttemptId expectedAttemptOnQueueE = 
      ApplicationAttemptId.newInstance(
          appC.getApplicationId(), appC.getAttemptId());
  // Now, all of queueB's (appA) over capacity is not preemptable, so neither
  // is queueA's. Verify that capacity is taken from queueE (appC).
  assertTrue("appB should be running on queueC",
      mCS.getAppsInQueue("queueC").contains(expectedAttemptOnQueueC));
  assertTrue("appC should be running on queueE",
      mCS.getAppsInQueue("queueE").contains(expectedAttemptOnQueueE));
  // Resources should have come from queueE (appC) and neither of queueA's
  // children.
  verify(mDisp, never()).handle(argThat(new IsPreemptionRequestFor(appA)));
  verify(mDisp, times(9)).handle(argThat(new IsPreemptionRequestFor(appC)));
}