/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.hadoop.yarn.server.resourcemanager.monitor.capacity;

import org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacitySchedulerConfiguration;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;

import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

/**
 * Test class for IntraQueuePreemption scenarios.
 */
public class TestProportionalCapacityPreemptionPolicyIntraQueueUserLimit
    extends
      ProportionalCapacityPreemptionPolicyMockFramework {
  @Before
  public void setup() {
    super.setup();
    conf.setBoolean(
        CapacitySchedulerConfiguration.INTRAQUEUE_PREEMPTION_ENABLED, true);
    policy = new ProportionalCapacityPreemptionPolicy(rmContext, cs, mClock);
  }

  @Test
  public void testSimpleIntraQueuePreemptionWithTwoUsers()
      throws IOException {
    /**
     * Queue structure is:
     *
     * <pre>
     *       root
     *        |
     *        a
     * </pre>
     *
     * Scenario:
     * Preconditions:
     *   Queue total resources: 100
     *   Minimum user limit percent: 50%
     *   +--------------+----------+------+---------+
     *   | APP  | USER  | PRIORITY | USED | PENDING |
     *   +--------------+----------+------+---------+
     *   | app1 | user1 | 1        | 100  | 0       |
     *   | app2 | user2 | 1        | 0    | 30      |
     *   +--------------+----------+------+---------+
     * Hence in queueA of 100, each user has a quota of 50. app1 of high priority
     * has a demand of 0 and its already using 100. app2 from user2 has a demand
     * of 30, and UL is 50. 30 would be preempted from app1.
     */

    // Set max preemption limit as 50%.
    conf.setFloat(CapacitySchedulerConfiguration.
        INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
        (float) 0.5);

    String labelsConfig = "=100,true;";
    String nodesConfig = // n1 has no label
        "n1= res=100";
    String queuesConfig =
        // guaranteed,max,used,pending,reserved
        "root(=[100 100 100 30 0]);" + // root
            "-a(=[100 100 100 30 0])"; // a

    String appsConfig =
    // queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
        "a\t" // app1 in a
            + "(1,1,n1,,100,false,0,user1);" + // app1 a
            "a\t" // app2 in a
            + "(1,1,n1,,0,false,30,user2)";

    buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
    policy.editSchedule();

    // app2 needs more resource and its well under its user-limit. Hence preempt
    // resources from app1.
    verify(mDisp, times(30)).handle(argThat(
        new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
            getAppAttemptId(1))));
  }

  @Test
  public void testNoIntraQueuePreemptionWithSingleUser()
      throws IOException {
    /**
     * Queue structure is:
     *
     * <pre>
     *       root
     *        |
     *        a
     * </pre>
     *
     * Scenario:
     *   Queue total resources: 100
     *   Minimum user limit percent: 50%
     *   +--------------+----------+------+---------+
     *   | APP  | USER  | PRIORITY | USED | PENDING |
     *   +--------------+----------+------+---------+
     *   | app1 | user1 | 1        | 100  | 0       |
     *   | app2 | user1 | 1        | 0    | 30      |
     *   +--------------+----------+------+---------+
     * Given single user, lower priority/late submitted apps has to
     * wait.
     */

    // Set max preemption limit as 50%.
    conf.setFloat(CapacitySchedulerConfiguration.
        INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
        (float) 0.5);

    String labelsConfig = "=100,true;";
    String nodesConfig = // n1 has no label
        "n1= res=100";
    String queuesConfig =
        // guaranteed,max,used,pending,reserved
        "root(=[100 100 100 30 0]);" + // root
            "-a(=[100 100 100 30 0])"; // a

    String appsConfig =
    // queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
        "a\t" // app1 in a
            + "(1,1,n1,,100,false,0,user1);" + // app1 a
            "a\t" // app2 in a
            + "(1,1,n1,,0,false,30,user1)";

    buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
    policy.editSchedule();

    // app2 needs more resource. Since app1,2 are from same user, there wont be
    // any preemption.
    verify(mDisp, times(0)).handle(argThat(
        new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
            getAppAttemptId(1))));
  }

  @Test
  public void testNoIntraQueuePreemptionWithTwoUserUnderUserLimit()
      throws IOException {
    /**
     * Queue structure is:
     *
     * <pre>
     *       root
     *        |
     *        a
     * </pre>
     *
     * Scenario:
     *   Queue total resources: 100
     *   Minimum user limit percent: 50%
     *   +--------------+----------+------+---------+
     *   | APP  | USER  | PRIORITY | USED | PENDING |
     *   +--------------+----------+------+---------+
     *   | app1 | user1 | 1        | 50   | 0       |
     *   | app2 | user2 | 1        | 30   | 30      |
     *   +--------------+----------+------+---------+
     * Hence in queueA of 100, each user has a quota of 50. app1 of high priority
     * has a demand of 0 and its already using 50. app2 from user2 has a demand
     * of 30, and UL is 50. Since app1 is under UL, there should not be any
     * preemption.
     */

    // Set max preemption limit as 50%.
    conf.setFloat(CapacitySchedulerConfiguration.
        INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
        (float) 0.5);

    String labelsConfig = "=100,true;";
    String nodesConfig = // n1 has no label
        "n1= res=100";
    String queuesConfig =
        // guaranteed,max,used,pending,reserved
        "root(=[100 100 80 30 0]);" + // root
            "-a(=[100 100 80 30 0])"; // a

    String appsConfig =
    // queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
        "a\t" // app1 in a
            + "(1,1,n1,,50,false,0,user1);" + // app1 a
            "a\t" // app2 in a
            + "(1,1,n1,,30,false,30,user2)";

    buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
    policy.editSchedule();

    // app2 needs more resource. Since app1,2 are from same user, there wont be
    // any preemption.
    verify(mDisp, times(0)).handle(argThat(
        new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
            getAppAttemptId(1))));
  }

  @Test
  public void testSimpleIntraQueuePreemptionWithTwoUsersWithAppPriority()
      throws IOException {
    /**
     * Queue structure is:
     *
     * <pre>
     *       root
     *        |
     *        a
     * </pre>
     *
     * Scenario:
     *   Queue total resources: 100
     *   Minimum user limit percent: 50%
     *   +--------------+----------+------+---------+
     *   | APP  | USER  | PRIORITY | USED | PENDING |
     *   +--------------+----------+------+---------+
     *   | app1 | user1 | 2        | 100  | 0       |
     *   | app2 | user2 | 1        | 0    | 30      |
     *   +--------------+----------+------+---------+
     * Hence in queueA of 100, each user has a quota of 50. app1 of high priority
     * has a demand of 0 and its already using 100. app2 from user2 has a demand
     * of 30, and UL is 50. 30 would be preempted from app1.
     */

    // Set max preemption limit as 50%.
    conf.setFloat(CapacitySchedulerConfiguration.
        INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
        (float) 0.5);

    String labelsConfig = "=100,true;";
    String nodesConfig = // n1 has no label
        "n1= res=100";
    String queuesConfig =
        // guaranteed,max,used,pending,reserved
        "root(=[100 100 100 30 0]);" + // root
            "-a(=[100 100 100 30 0])"; // a

    String appsConfig =
    // queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
        "a\t" // app1 in a
            + "(2,1,n1,,100,false,0,user1);" + // app1 a
            "a\t" // app2 in a
            + "(1,1,n1,,0,false,30,user2)";

    buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
    policy.editSchedule();

    // app2 needs more resource and its well under its user-limit. Hence preempt
    // resources from app1 even though its priority is more than app2.
    verify(mDisp, times(30)).handle(argThat(
        new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
            getAppAttemptId(1))));
  }

  @Test
  public void testIntraQueuePreemptionOfUserLimitWithMultipleApps()
      throws IOException {
    /**
     * Queue structure is:
     *
     * <pre>
     *       root
     *        |
     *        a
     * </pre>
     *
     * Scenario:
     *   Queue total resources: 100
     *   Minimum user limit percent: 50%
     *   +--------------+----------+------+---------+
     *   | APP  | USER  | PRIORITY | USED | PENDING |
     *   +--------------+----------+------+---------+
     *   | app1 | user1 | 1        | 30   | 30      |
     *   | app2 | user2 | 1        | 20   | 20      |
     *   | app3 | user1 | 1        | 30   | 30      |
     *   | app4 | user2 | 1        | 0    | 10      |
     *   +--------------+----------+------+---------+
     * Hence in queueA of 100, each user has a quota of 50. Now have multiple
     * apps and check for preemption across apps.
     */

    // Set max preemption limit as 50%.
    conf.setFloat(CapacitySchedulerConfiguration.
        INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
        (float) 0.5);

    String labelsConfig = "=100,true;";
    String nodesConfig = // n1 has no label
        "n1= res=100";
    String queuesConfig =
        // guaranteed,max,used,pending,reserved
        "root(=[100 100 80 90 0]);" + // root
            "-a(=[100 100 80 90 0])"; // a

    String appsConfig =
    // queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
        "a\t" // app1 in a
            + "(1,1,n1,,30,false,30,user1);" + // app1 a
            "a\t" // app2 in a
            + "(1,1,n1,,20,false,20,user2);" +
            "a\t" // app3 in a
            + "(1,1,n1,,30,false,30,user1);" +
            "a\t" // app4 in a
            + "(1,1,n1,,0,false,10,user2)";

    buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
    policy.editSchedule();

    // app2/app4 needs more resource and its well under its user-limit. Hence
    // preempt resources from app3 (compare to app1, app3 has low priority).
    verify(mDisp, times(9)).handle(argThat(
        new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
            getAppAttemptId(3))));
  }

  @Test
  public void testNoPreemptionOfUserLimitWithMultipleAppsAndSameUser()
      throws IOException {
    /**
     * Queue structure is:
     *
     * <pre>
     *       root
     *        |
     *        a
     * </pre>
     *
     * Scenario:
     *   Queue total resources: 100
     *   Minimum user limit percent: 50%
     *   +--------------+----------+------+---------+
     *   | APP  | USER  | PRIORITY | USED | PENDING |
     *   +--------------+----------+------+---------+
     *   | app1 | user1 | 1        | 30   | 30      |
     *   | app2 | user1 | 1        | 20   | 20      |
     *   | app3 | user1 | 1        | 30   | 30      |
     *   | app4 | user1 | 1        | 0    | 10      |
     *   +--------------+----------+------+---------+
     * Hence in queueA of 100, each user has a quota of 50. Now have multiple
     * apps and check for preemption across apps.
     */

    // Set max preemption limit as 50%.
    conf.setFloat(CapacitySchedulerConfiguration.
        INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
        (float) 0.5);

    String labelsConfig = "=100,true;";
    String nodesConfig = // n1 has no label
        "n1= res=100";
    String queuesConfig =
        // guaranteed,max,used,pending,reserved
        "root(=[100 100 80 90 0]);" + // root
            "-a(=[100 100 80 90 0])"; // a

    String appsConfig =
    // queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
        "a\t" // app1 in a
            + "(1,1,n1,,30,false,20,user1);" + // app1 a
            "a\t" // app2 in a
            + "(1,1,n1,,20,false,20,user1);" +
            "a\t" // app3 in a
            + "(1,1,n1,,30,false,30,user1);" +
            "a\t" // app4 in a
            + "(1,1,n1,,0,false,10,user1)";

    buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
    policy.editSchedule();

    // app2/app4 needs more resource and its well under its user-limit. Hence
    // preempt resources from app3 (compare to app1, app3 has low priority).
    verify(mDisp, times(0)).handle(argThat(
        new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
            getAppAttemptId(1))));
    verify(mDisp, times(0)).handle(argThat(
        new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
            getAppAttemptId(2))));
    verify(mDisp, times(0)).handle(argThat(
        new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
            getAppAttemptId(3))));
    verify(mDisp, times(0)).handle(argThat(
        new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
            getAppAttemptId(4))));
  }

  @Test
  public void testIntraQueuePreemptionOfUserLimitWitAppsOfDifferentPriority()
      throws IOException {
    /**
     * Queue structure is:
     * <pre>
     *       root
     *        |
     *        a
     * </pre>
     *
     * Scenario:
     *   Queue total resources: 100
     *   Minimum user limit percent: 50%
     *   +--------------+----------+------+---------+
     *   | APP  | USER  | PRIORITY | USED | PENDING |
     *   +--------------+----------+------+---------+
     *   | app1 | user1 | 3        | 30   | 30      |
     *   | app2 | user2 | 1        | 20   | 20      |
     *   | app3 | user1 | 4        | 30   | 0       |
     *   | app4 | user2 | 1        | 0    | 10      |
     *   +--------------+----------+------+---------+
     * Hence in queueA of 100, each user has a quota of 50. Now have multiple
     * apps and check for preemption across apps.
     */

    // Set max preemption limit as 50%.
    conf.setFloat(
        CapacitySchedulerConfiguration.INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
        (float) 0.5);

    String labelsConfig = "=100,true;";
    String nodesConfig = // n1 has no label
        "n1= res=100";
    String queuesConfig =
        // guaranteed,max,used,pending,reserved
        "root(=[100 100 80 60 0]);" + // root
            "-a(=[100 100 80 60 0])"; // b

    String appsConfig =
        // queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
        "a\t" // app1 in a
            + "(3,1,n1,,30,false,30,user1);" + // app1 a
            "a\t" // app2 in a
            + "(1,1,n1,,20,false,20,user2);" + "a\t" // app3 in a
            + "(4,1,n1,,30,false,0,user1);" + "a\t" // app4 in a
            + "(1,1,n1,,0,false,10,user2)";

    buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
    policy.editSchedule();

    // app2/app4 needs more resource and its well under its user-limit. Hence
    // preempt resources from app1 (compare to app3, app1 has low priority).
    verify(mDisp, times(9)).handle(argThat(
        new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
            getAppAttemptId(1))));
  }

  @Test
  public void testIntraQueuePreemptionOfUserLimitInTwoQueues()
      throws IOException {
    /**
     * Queue structure is:
     *
     * <pre>
     *       root
     *      /   \
     *     a     b
     * </pre>
     *
     * Guaranteed resource of a/b are 40:60 Total cluster resource = 100
     * maxIntraQueuePreemptableLimit by default is 50%. This test is to verify
     * that intra-queue preemption could occur in two queues when user-limit
     * irreuglarity is present in queue.
     */

    // Set max preemption limit as 50%.
    conf.setFloat(CapacitySchedulerConfiguration.
            INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
        (float) 0.5);

    String labelsConfig = "=100,true;";
    String nodesConfig = // n1 has no label
        "n1= res=100";
    String queuesConfig =
        // guaranteed,max,used,pending,reserved
        "root(=[100 100 90 80 0]);" + // root
            "-a(=[60 100 55 60 0]);" + // a
            "-b(=[40 100 35 20 0])"; // b

    String appsConfig =
        // queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
        "a\t" // app1 in a
            + "(3,1,n1,,20,false,30,user1);" + // app1 a
            "a\t" // app2 in a
            + "(1,1,n1,,20,false,20,user2);" +
            "a\t" // app3 in a
            + "(4,1,n1,,15,false,0,user1);" +
            "a\t" // app4 in a
            + "(1,1,n1,,0,false,10,user2);" +
            "b\t" // app5 in b
            + "(3,1,n1,,25,false,10,user1);" +
            "b\t" // app6 in b
            + "(1,1,n1,,10,false,10,user2)";

    buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
    policy.editSchedule();

    // app2/app4 needs more resource and its well under its user-limit. Hence
    // preempt resources from app1 (compare to app3, app1 has low priority).
    verify(mDisp, times(4)).handle(argThat(
        new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
            getAppAttemptId(1))));
    verify(mDisp, times(4)).handle(argThat(
        new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
            getAppAttemptId(5))));
  }

  @Test
  public void testIntraQueuePreemptionWithTwoRequestingUsers()
      throws IOException {
    /**
    * Queue structure is:
    *
    * <pre>
    *       root
    *        |
    *        a
    * </pre>
    *
    * Scenario:
    *   Queue total resources: 100
    *   Minimum user limit percent: 50%
    *   +--------------+----------+------+---------+
    *   | APP  | USER  | PRIORITY | USED | PENDING |
    *   +--------------+----------+------+---------+
    *   | app1 | user1 | 1        | 60   | 10      |
    *   | app2 | user2 | 1        | 40   | 10      |
    *   +--------------+----------+------+---------+
    * Hence in queueA of 100, each user has a quota of 50. Now have multiple
    * apps and check for preemption across apps.
    */

    // Set max preemption limit as 50%.
    conf.setFloat(CapacitySchedulerConfiguration.
        INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
        (float) 0.5);

    String labelsConfig = "=100,true;";
    String nodesConfig = // n1 has no label
        "n1= res=100";
    String queuesConfig =
        // guaranteed,max,used,pending,reserved
        "root(=[100 100 100 20 0]);" + // root
            "-a(=[100 100 100 20 0])"; // a

    String appsConfig =
    // queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
        "a\t" // app1 in a
            + "(1,1,n1,,60,false,10,user1);" + // app1 a
            "a\t" // app2 in a
            + "(1,1,n1,,40,false,10,user2)";

    buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
    policy.editSchedule();

    // app2 needs more resource and its well under its user-limit. Hence preempt
    // resources from app1.
    verify(mDisp, times(9)).handle(argThat(
        new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
            getAppAttemptId(1))));
    verify(mDisp, times(0)).handle(argThat(
        new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
            getAppAttemptId(2))));
  }

  @Test
  public void testNoIntraQueuePreemptionIfBelowUserLimitAndLowPriorityExtraUsers()
      throws IOException {
     /**
     * Queue structure is:
     *
     * <pre>
     *       root
     *        |
     *        a
     * </pre>
     *
     * Scenario:
     * Preconditions:
     *   Queue total resources: 100
     *   Minimum user limit percent: 50%
     *   +--------------+----------+------+---------+
     *   | APP  | USER  | PRIORITY | USED | PENDING |
     *   +--------------+----------+------+---------+
     *   | app1 | user1 | 1        | 50   | 0       |
     *   | app2 | user2 | 1        | 50   | 0       |
     *   | app3 | user3 | 0        | 0    | 10      |
     *   +--------------+----------+------+---------+
     * This scenario should never preempt from either user1 or user2
     */

    // Set max preemption per round to 50% (this is different from minimum user
    // limit percent).
    conf.setFloat(CapacitySchedulerConfiguration.
        INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
        (float) 0.7);

    String labelsConfig = "=100,true;";
    String nodesConfig = // n1 has no label
        "n1= res=100";
    String queuesConfig =
        // guaranteed,max,used,pending,reserved
        "root(=[100 100 100 10 0]);" + // root
            "-a(=[100 100 100 10 0])"; // a

    String appsConfig =
    // queueName\t\
    //     (priority,resource,host,label,#repeat,reserved,pending,user)\tMULP;
        "a\t(1,1,n1,,50,false,0,user1)\t50;" + // app1, user1
        "a\t(1,1,n1,,50,false,0,user2)\t50;" + // app2, user2
        "a\t(0,1,n1,,0,false,10,user3)\t50";   // app3, user3

    buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
    policy.editSchedule();

    // app2/app4 needs more resource and its well under its user-limit. Hence
    // preempt resources from app1 (compare to app3, app1 has low priority).
    verify(mDisp, times(0)).handle(argThat(
        new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
            getAppAttemptId(1))));
    verify(mDisp, times(0)).handle(argThat(
        new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
            getAppAttemptId(2))));
  }

  @Test
  public void testNoIntraQueuePreemptionIfBelowUserLimitAndSamePriorityExtraUsers()
      throws IOException {
     /**
     * Queue structure is:
     *
     * <pre>
     *       root
     *        |
     *        a
     * </pre>
     *
     * Scenario:
     * Preconditions:
     *   Queue total resources: 100
     *   Minimum user limit percent: 50%
     *   +--------------+----------+------+---------+
     *   | APP  | USER  | PRIORITY | USED | PENDING |
     *   +--------------+----------+------+---------+
     *   | app1 | user1 | 1        | 50   | 0       |
     *   | app2 | user2 | 1        | 50   | 0       |
     *   | app3 | user3 | 1        | 0    | 10      |
     *   +--------------+----------+------+---------+
     * This scenario should never preempt from either user1 or user2
     */

    // Set max preemption per round to 50% (this is different from minimum user
    // limit percent).
    conf.setFloat(CapacitySchedulerConfiguration.
        INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
        (float) 0.7);

    String labelsConfig = "=100,true;";
    String nodesConfig = // n1 has no label
        "n1= res=100";
    String queuesConfig =
        // guaranteed,max,used,pending,reserved
        "root(=[100 100 100 10 0]);" + // root
            "-a(=[100 100 100 10 0])"; // a

    String appsConfig =
    // queueName\t\
    //     (priority,resource,host,label,#repeat,reserved,pending,user)\tMULP;
        "a\t(1,1,n1,,50,false,0,user1)\t50;" + // app1, user1
        "a\t(1,1,n1,,50,false,0,user2)\t50;" + // app2, user2
        "a\t(1,1,n1,,0,false,10,user3)\t50";   // app3, user3

    buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
    policy.editSchedule();

    // app2/app4 needs more resource and its well under its user-limit. Hence
    // preempt resources from app1 (compare to app3, app1 has low priority).
    verify(mDisp, times(0)).handle(argThat(
        new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
            getAppAttemptId(1))));
    verify(mDisp, times(0)).handle(argThat(
        new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
            getAppAttemptId(2))));
  }

  @Test
  public void testNoIntraQueuePreemptionIfBelowUserLimitAndHighPriorityExtraUsers()
      throws IOException {
     /**
     * Queue structure is:
     *
     * <pre>
     *       root
     *        |
     *        a
     * </pre>
     *
     * Scenario:
     * Preconditions:
     *   Queue total resources: 100
     *   Minimum user limit percent: 50%
     *   +--------------+----------+------+---------+
     *   | APP  | USER  | PRIORITY | USED | PENDING |
     *   +--------------+----------+------+---------+
     *   | app1 | user1 | 1        | 50   | 0       |
     *   | app2 | user2 | 1        | 50   | 0       |
     *   | app3 | user3 | 5        | 0    | 10      |
     *   +--------------+----------+------+---------+
     * This scenario should never preempt from either user1 or user2
     */

    // Set max preemption per round to 50% (this is different from minimum user
    // limit percent).
    conf.setFloat(CapacitySchedulerConfiguration.
        INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
        (float) 0.7);

    String labelsConfig = "=100,true;";
    String nodesConfig = // n1 has no label
        "n1= res=100";
    String queuesConfig =
        // guaranteed,max,used,pending,reserved
        "root(=[100 100 100 10 0]);" + // root
            "-a(=[100 100 100 10 0])"; // a

    String appsConfig =
    // queueName\t\
    //     (priority,resource,host,label,#repeat,reserved,pending,user)\tMULP;
        "a\t(1,1,n1,,50,false,0,user1)\t50;" + // app1, user1
        "a\t(1,1,n1,,50,false,0,user2)\t50;" + // app2, user2
        "a\t(5,1,n1,,0,false,10,user3)\t50";   // app3, user3

    buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
    policy.editSchedule();

    // app2/app4 needs more resource and its well under its user-limit. Hence
    // preempt resources from app1 (compare to app3, app1 has low priority).
    verify(mDisp, times(0)).handle(argThat(
        new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
            getAppAttemptId(1))));
    verify(mDisp, times(0)).handle(argThat(
        new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
            getAppAttemptId(2))));
  }

  @Test
  public void testNoIntraQueuePreemptionWithUserLimitDeadzone()
      throws IOException {
    /**
    * Queue structure is:
    *
    * <pre>
    *       root
    *        |
    *        a
    * </pre>
    *
    * Scenario:
    *   Queue total resources: 100
    *   Minimum user limit percent: 50%
    *   +--------------+----------+------+---------+
    *   | APP  | USER  | PRIORITY | USED | PENDING |
    *   +--------------+----------+------+---------+
    *   | app1 | user1 | 1        | 60   | 10      |
    *   | app2 | user2 | 1        | 40   | 10      |
    *   +--------------+----------+------+---------+
    * Hence in queueA of 100, each user has a quota of 50. Now have multiple
    * apps and check for preemption across apps but also ensure that user's
    * usage not coming under its user-limit.
    */

    // Set max preemption limit as 50%.
    conf.setFloat(CapacitySchedulerConfiguration.
        INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
        (float) 0.5);

    String labelsConfig = "=100,true;";
    String nodesConfig = // n1 has no label
        "n1= res=100";
    String queuesConfig =
        // guaranteed,max,used,pending,reserved
        "root(=[100 100 100 20 0]);" + // root
            "-a(=[100 100 100 20 0])"; // a

    String appsConfig =
    // queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
        "a\t" // app1 in a
            + "(1,3,n1,,20,false,10,user1);" + // app1 a
            "a\t" // app2 in a
            + "(1,1,n1,,40,false,10,user2)";

    buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
    policy.editSchedule();

    // app2 needs more resource and its well under its user-limit. Hence preempt
    // 3 resources (9GB) from app1. We will not preempt last container as it may
    // pull user's usage under its user-limit.
    verify(mDisp, times(3)).handle(argThat(
        new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
            getAppAttemptId(1))));
    verify(mDisp, times(0)).handle(argThat(
        new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
            getAppAttemptId(2))));
  }

  @Test
  public void testIntraQueuePreemptionWithUserLimitDeadzoneAndPriority()
      throws IOException {
    /**
    * Queue structure is:
    *
    * <pre>
    *       root
    *        |
    *        a
    * </pre>
    *
    * Scenario:
    *   Queue total resources: 100
    *   Minimum user limit percent: 50%
    *   +--------------+----------+------+---------+
    *   | APP  | USER  | PRIORITY | USED | PENDING |
    *   +--------------+----------+------+---------+
    *   | app1 | user1 | 1        | 60   | 10      |
    *   | app2 | user2 | 1        | 40   | 10      |
    *   +--------------+----------+------+---------+
    * Hence in queueA of 100, each user has a quota of 50. Now have multiple
    * apps and check for preemption across apps but also ensure that user's
    * usage not coming under its user-limit.
    */

    // Set max preemption limit as 50%.
    conf.setFloat(CapacitySchedulerConfiguration.
        INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
        (float) 0.5);

    String labelsConfig = "=100,true;";
    String nodesConfig = // n1 has no label
        "n1= res=100";
    String queuesConfig =
        // guaranteed,max,used,pending,reserved
        "root(=[100 100 100 20 0]);" + // root
            "-a(=[100 100 100 20 0])"; // a

    String appsConfig =
    // queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
        "a\t" // app1 in a
            + "(1,3,n1,,20,false,10,user1);" + // app1 a
            "a\t" // app2 in a
            + "(2,1,n1,,0,false,10,user1);" + // app1 a
            "a\t" // app2 in a
            + "(1,1,n1,,40,false,20,user2)";

    buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
    policy.editSchedule();

    // app2 needs more resource and its well under its user-limit. Hence preempt
    // 3 resources (9GB) from app1. We will not preempt last container as it may
    // pull user's usage under its user-limit.
    verify(mDisp, times(3)).handle(argThat(
        new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
            getAppAttemptId(1))));
    verify(mDisp, times(0)).handle(argThat(
        new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
            getAppAttemptId(2))));

    // After first round, 3 containers were preempted from app1 and resource
    // distribution will be like below.
    appsConfig =
        // queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
        "a\t" // app1 in a
            + "(1,3,n1,,17,false,10,user1);" + // app1 a
            "a\t" // app2 in a
            + "(2,1,n1,,0,false,10,user1);" + // app2 a
            "a\t" // app2 in a
            + "(1,1,n1,,49,false,11,user2)";

    buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
    policy.editSchedule();

    // app2 has priority demand within same user 'user1'. However user1's used
    // is alredy under UL. Hence no preemption. We will still get 3 container
    // while asserting as it was aleady selected in earlier round.
    verify(mDisp, times(3)).handle(argThat(
        new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
            getAppAttemptId(1))));
  }

  @Test
  public void testSimpleIntraQueuePreemptionOneUserUnderOneUserAtOneUserAbove()
      throws IOException {
    conf.setFloat(CapacitySchedulerConfiguration.
        INTRAQUEUE_PREEMPTION_MAX_ALLOWABLE_LIMIT,
        (float) 0.5);

    String labelsConfig = "=100,true;";
    String nodesConfig = // n1 has no label
        "n1= res=100";
    String queuesConfig =
        // guaranteed,max,used,pending,reserved
        "root(=[100 100 100 1 0]);" + // root
            "-a(=[100 100 100 1 0])"; // a

    String appsConfig =
    // queueName\t(priority,resource,host,expression,#repeat,reserved,pending)
        "a\t" // app1 in a
            + "(1,1,n1,,65,false,0,user1);" +
            "a\t" // app2 in a
            + "(1,1,n1,,35,false,0,user2);" +
            "a\t" // app3 in a
            + "(1,1,n1,,0,false,1,user3)"
            ;

    buildEnv(labelsConfig, nodesConfig, queuesConfig, appsConfig);
    policy.editSchedule();

    // app2 is right at its user limit and app1 needs one resource. Should
    // preempt 1 container.
    verify(mDisp, times(1)).handle(argThat(
        new TestProportionalCapacityPreemptionPolicy.IsPreemptionRequestFor(
            getAppAttemptId(1))));
  }
}
