/**
 * 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.nodemanager.containermanager.scheduler;

import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.UnsupportedFileSystemException;
import org.apache.hadoop.yarn.api.protocolrecords.GetContainerStatusesRequest;
import org.apache.hadoop.yarn.api.protocolrecords.StartContainerRequest;
import org.apache.hadoop.yarn.api.protocolrecords.StartContainersRequest;
import org.apache.hadoop.yarn.api.records.ContainerId;
import org.apache.hadoop.yarn.api.records.ContainerLaunchContext;
import org.apache.hadoop.yarn.api.records.ContainerState;
import org.apache.hadoop.yarn.api.records.ContainerStatus;
import org.apache.hadoop.yarn.api.records.ContainerSubState;
import org.apache.hadoop.yarn.api.records.ExecutionType;
import org.apache.hadoop.yarn.api.records.Resource;
import org.apache.hadoop.yarn.api.records.ResourceUtilization;
import org.apache.hadoop.yarn.api.records.Token;
import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.exceptions.ConfigurationException;
import org.apache.hadoop.yarn.exceptions.YarnException;
import org.apache.hadoop.yarn.server.nodemanager.ContainerExecutor;
import org.apache.hadoop.yarn.server.nodemanager.Context;
import org.apache.hadoop.yarn.server.nodemanager.DefaultContainerExecutor;
import org.apache.hadoop.yarn.server.nodemanager.DeletionService;
import org.apache.hadoop.yarn.server.nodemanager.LocalDirsHandlerService;
import org.apache.hadoop.yarn.server.nodemanager.NodeStatusUpdater;
import org.apache.hadoop.yarn.server.nodemanager.containermanager.BaseContainerManagerTest;
import org.apache.hadoop.yarn.server.nodemanager.containermanager.ContainerManagerImpl;
import org.apache.hadoop.yarn.server.nodemanager.containermanager.application.Application;
import org.apache.hadoop.yarn.server.nodemanager.containermanager.container.Container;
import org.apache.hadoop.yarn.server.nodemanager.containermanager.launcher.ContainerLaunch;
import org.apache.hadoop.yarn.server.nodemanager.containermanager.launcher.ContainersLauncher;
import org.apache.hadoop.yarn.server.nodemanager.executor.ContainerSignalContext;
import org.apache.hadoop.yarn.server.nodemanager.executor.ContainerStartContext;
import org.apache.hadoop.yarn.server.nodemanager.metrics.NodeManagerMetrics;
import org.apache.hadoop.yarn.server.utils.BuilderUtils;
import org.junit.Assert;
import org.junit.Test;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


/**
 * Test ContainerScheduler behaviors when NM overallocation is turned on.
 */
public class TestContainerSchedulerWithOverAllocation
    extends BaseContainerManagerTest {
  private static final int NM_OPPORTUNISTIC_QUEUE_LIMIT = 3;

  static {
    LOG = LoggerFactory.getLogger(TestContainerSchedulerQueuing.class);
  }

  public TestContainerSchedulerWithOverAllocation()
      throws UnsupportedFileSystemException {
  }

  @Override
  protected ContainerExecutor createContainerExecutor() {
    DefaultContainerExecutor exec =
        new LongRunningContainerSimulatingContainerExecutor();
    exec.setConf(conf);
    return exec;
  }

  @Override
  protected ContainerManagerImpl createContainerManager(
      DeletionService delSrvc) {
    return new LongRunningContainerSimulatingContainersManager(
        context, exec, delSrvc, nodeStatusUpdater, metrics, dirsHandler, user);
  }

  @Override
  public void setup() throws IOException {
    conf.setInt(
        YarnConfiguration.NM_OPPORTUNISTIC_CONTAINERS_MAX_QUEUE_LENGTH,
        NM_OPPORTUNISTIC_QUEUE_LIMIT);
    conf.setFloat(
        YarnConfiguration.NM_OVERALLOCATION_CPU_UTILIZATION_THRESHOLD,
        0.75f);
    conf.setFloat(
        YarnConfiguration.NM_OVERALLOCATION_MEMORY_UTILIZATION_THRESHOLD,
        0.75f);
    conf.setFloat(YarnConfiguration.NM_OVERALLOCATION_CPU_PREEMPTION_THRESHOLD,
        0.8f);
    conf.setFloat(
        YarnConfiguration.NM_OVERALLOCATION_MEMORY_PREEMPTION_THRESHOLD, 0.8f);
    conf.setInt(YarnConfiguration.NM_OVERALLOCATION_PREEMPTION_CPU_COUNT, 2);
    // disable the monitor thread in ContainersMonitor to allow control over
    // when opportunistic containers are launched with over-allocation
    conf.setBoolean(YarnConfiguration.NM_CONTAINER_MONITOR_ENABLED, false);
    super.setup();
  }

  /**
   * Start one GUARANTEED and one OPPORTUNISTIC container, which in aggregate do
   * not exceed the capacity of the node. Both containers are expected to start
   * running immediately.
   */
  @Test
  public void testStartMultipleContainersWithoutOverallocation()
      throws Exception {
    containerManager.start();

    StartContainersRequest allRequests = StartContainersRequest.newInstance(
        new ArrayList<StartContainerRequest>() { {
          add(createStartContainerRequest(0,
              BuilderUtils.newResource(1024, 1), ExecutionType.OPPORTUNISTIC));
          add(createStartContainerRequest(1,
              BuilderUtils.newResource(1024, 1), ExecutionType.GUARANTEED));
        } }
    );
    containerManager.startContainers(allRequests);

    BaseContainerManagerTest.waitForContainerSubState(
        containerManager, createContainerId(0), ContainerSubState.RUNNING);
    BaseContainerManagerTest.waitForContainerSubState(
        containerManager, createContainerId(1), ContainerSubState.RUNNING);

    verifyContainerStatuses(new HashMap<ContainerId, ContainerSubState>() {
      {
        put(createContainerId(0), ContainerSubState.RUNNING);
        put(createContainerId(1), ContainerSubState.RUNNING);
      }
    });
  }

  /**
   * Start one GUARANTEED and one OPPORTUNISTIC containers whose utilization
   * is very low relative to their resource request, resulting in a low node
   * utilization. Then start another OPPORTUNISTIC containers which requests
   * more than what's left unallocated on the node. Due to overallocation
   * being turned on and node utilization being low, the second OPPORTUNISTIC
   * container is also expected to be launched immediately.
   */
  @Test
  public void testStartOppContainersWithPartialOverallocationLowUtilization()
      throws Exception {
    containerManager.start();

    containerManager.startContainers(StartContainersRequest.newInstance(
        new ArrayList<StartContainerRequest>() {
          {
            add(createStartContainerRequest(0,
                BuilderUtils.newResource(1024, 1), ExecutionType.GUARANTEED));
            add(createStartContainerRequest(1,
                BuilderUtils.newResource(824, 1), ExecutionType.GUARANTEED));
          }
        }
    ));
    BaseContainerManagerTest.waitForContainerSubState(
        containerManager, createContainerId(0), ContainerSubState.RUNNING);
    BaseContainerManagerTest.waitForContainerSubState(
        containerManager, createContainerId(1), ContainerSubState.RUNNING);

    // the current containers utilization is low, only 512MBs out of 2GBs and
    // 0.5 out 4 vcores are being used.
    setContainerResourceUtilization(
        ResourceUtilization.newInstance(512, 0, 0.5f));

    // start a container that requests more than what's left unallocated
    // 512 + 1024 + 824 > 2048
    containerManager.startContainers(StartContainersRequest.newInstance(
        Collections.singletonList(
            createStartContainerRequest(2,
                BuilderUtils.newResource(512, 1), ExecutionType.OPPORTUNISTIC))
    ));
    ((ContainerManagerForTest) containerManager).drainAsyncEvents();

    // this container is not expected to be started immediately because
    // opportunistic containers cannot be started if the node would be
    // over-allocated
    BaseContainerManagerTest.waitForContainerSubState(
        containerManager, createContainerId(2), ContainerSubState.SCHEDULED);

    verifyContainerStatuses(new HashMap<ContainerId, ContainerSubState>() {
      {
        put(createContainerId(0), ContainerSubState.RUNNING);
        put(createContainerId(1), ContainerSubState.RUNNING);
        put(createContainerId(2), ContainerSubState.SCHEDULED);
      }
    });

    // try to start opportunistic containers out of band.
    ((ContainerManagerForTest) containerManager)
        .checkNodeResourceUtilization();

    // this container is expected to be started immediately because there
    // are (memory: 1024, vcore: 0.625) available based on over-allocation
    BaseContainerManagerTest.waitForContainerSubState(
        containerManager, createContainerId(2), ContainerSubState.RUNNING);

    verifyContainerStatuses(new HashMap<ContainerId, ContainerSubState>() {
      {
        put(createContainerId(0), ContainerSubState.RUNNING);
        put(createContainerId(1), ContainerSubState.RUNNING);
        put(createContainerId(2), ContainerSubState.RUNNING);
      }
    });
  }

  /**
   * Start one GUARANTEED and one OPPORTUNISTIC containers which utilizes most
   * of the resources they requested, resulting in a high node utilization.
   * Then start another OPPORTUNISTIC containers which requests more than what's
   * left unallocated on the node. Because of the high resource utilization on
   * the node, the projected utilization, if we were to start the second
   * OPPORTUNISTIC container immediately, will go over the NM overallocation
   * threshold, so the second OPPORTUNISTIC container is expected to be queued.
   */
  @Test
  public void testQueueOppContainerWithPartialOverallocationHighUtilization()
      throws Exception {
    containerManager.start();

    containerManager.startContainers(StartContainersRequest.newInstance(
        new ArrayList<StartContainerRequest>() {
          {
            add(createStartContainerRequest(0,
                BuilderUtils.newResource(1024, 1), ExecutionType.GUARANTEED));
            add(createStartContainerRequest(1,
                BuilderUtils.newResource(824, 1), ExecutionType.GUARANTEED));
          }
        }
    ));
    BaseContainerManagerTest.waitForContainerSubState(
        containerManager, createContainerId(0), ContainerSubState.RUNNING);
    BaseContainerManagerTest.waitForContainerSubState(
        containerManager, createContainerId(1), ContainerSubState.RUNNING);

    // the containers memory utilization is high, 1500 MBs out of 2GBs and
    // but the cpu utilization, 0.5 out of 4 vcores, is low
    setContainerResourceUtilization(
        ResourceUtilization.newInstance(1500, 0, 0.5f));

    // start a container that requests more than what's left unallocated
    // 512 + 1024 + 824 > 2048
    containerManager.startContainers(StartContainersRequest.newInstance(
        Collections.singletonList(
            createStartContainerRequest(2,
                BuilderUtils.newResource(512, 1), ExecutionType.OPPORTUNISTIC))
    ));

    // try to start opportunistic containers out of band because they can
    // not be launched at container scheduler event if the node would be
    // over-allocated.
    ((ContainerManagerForTest) containerManager)
        .checkNodeResourceUtilization();

    // this container will not start immediately because there is not
    // enough resource available at the moment either in terms of
    // resources unallocated or in terms of the actual utilization
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(2), ContainerSubState.SCHEDULED);

    verifyContainerStatuses(new HashMap<ContainerId, ContainerSubState>() {
      {
        put(createContainerId(0), ContainerSubState.RUNNING);
        put(createContainerId(1), ContainerSubState.RUNNING);
        put(createContainerId(2), ContainerSubState.SCHEDULED);
      }
    });
  }

  /**
   * Start two GUARANTEED containers which in aggregate takes up the whole node
   * capacity, yet whose utilization is low relative to their resource request,
   * resulting in a low node resource utilization. Then try to start another
   * OPPORTUNISTIC containers. Because the resource utilization across the node
   * is low and overallocation being turned on, the OPPORTUNISTIC container is
   * expected to be launched immediately even though there is no resources left
   * unallocated.
   */
  @Test
  public void testStartOppContainersWithOverallocationLowUtilization()
      throws Exception {
    containerManager.start();

    containerManager.startContainers(StartContainersRequest.newInstance(
        new ArrayList<StartContainerRequest>() {
          {
            add(createStartContainerRequest(0,
                BuilderUtils.newResource(1024, 1), ExecutionType.GUARANTEED));
            add(createStartContainerRequest(1,
                BuilderUtils.newResource(1024, 1), ExecutionType.GUARANTEED));
          }
        }
    ));
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(0), ContainerSubState.RUNNING);
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(1), ContainerSubState.RUNNING);

    // the current containers utilization is low, 800 MBs out of 2GBs and
    // 0.5 out of 4 vcores are being used
    setContainerResourceUtilization(
        ResourceUtilization.newInstance(800, 0, 0.5f));

    // start a container when there is no resources left unallocated.
    containerManager.startContainers(StartContainersRequest.newInstance(
        Collections.singletonList(
            createStartContainerRequest(2,
                BuilderUtils.newResource(512, 1), ExecutionType.OPPORTUNISTIC))
    ));
    ((ContainerManagerForTest) containerManager).drainAsyncEvents();

    // this container is not expected to be started immediately because
    // opportunistic containers cannot be started if the node would be
    // over-allocated
    BaseContainerManagerTest.waitForContainerSubState(
        containerManager, createContainerId(2), ContainerSubState.SCHEDULED);

    verifyContainerStatuses(new HashMap<ContainerId, ContainerSubState>() {
      {
        put(createContainerId(0), ContainerSubState.RUNNING);
        put(createContainerId(1), ContainerSubState.RUNNING);
        put(createContainerId(2), ContainerSubState.SCHEDULED);
      }
    });

    // try to start opportunistic containers out of band.
    ((ContainerManagerForTest) containerManager)
        .checkNodeResourceUtilization();

    // this container is expected to be started because there is resources
    // available because the actual utilization is very low
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(2), ContainerSubState.RUNNING);

    verifyContainerStatuses(new HashMap<ContainerId, ContainerSubState>() {
      {
        put(createContainerId(0), ContainerSubState.RUNNING);
        put(createContainerId(1), ContainerSubState.RUNNING);
        put(createContainerId(2), ContainerSubState.RUNNING);
      }
    });
  }


  /**
   * Start two GUARANTEED containers which in aggregate take up the whole node
   * capacity and fully utilize the resources they requested. Then try to start
   * four OPPORTUNISTIC containers of which three will be queued and one will be
   * killed because of the max queue length is 3.
   */
  @Test
  public void testQueueOppContainersWithFullUtilization() throws Exception {
    containerManager.start();

    containerManager.startContainers(StartContainersRequest.newInstance(
        new ArrayList<StartContainerRequest>() {
          {
            add(createStartContainerRequest(0,
                BuilderUtils.newResource(1024, 1), ExecutionType.GUARANTEED));
            add(createStartContainerRequest(1,
                BuilderUtils.newResource(1024, 1), ExecutionType.GUARANTEED));
          }
        }
    ));
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(0), ContainerSubState.RUNNING);
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(1), ContainerSubState.RUNNING);

    // the containers are fully utilizing their memory, 2048 MBs out of
    // 2 GBs, but cpu utlization, 0.5 out of 4 vcores, is low
    setContainerResourceUtilization(
        ResourceUtilization.newInstance(2048, 0, 0.5f));

    // start more OPPORTUNISTIC containers than what the OPPORTUNISTIC container
    // queue can hold when there is no unallocated resource left.
    List<StartContainerRequest> moreContainerRequests =
        new ArrayList<>(NM_OPPORTUNISTIC_QUEUE_LIMIT + 1);
    for (int a = 0; a < NM_OPPORTUNISTIC_QUEUE_LIMIT + 1; a++) {
      moreContainerRequests.add(
          createStartContainerRequest(2 + a,
              BuilderUtils.newResource(512, 1), ExecutionType.OPPORTUNISTIC));
    }
    containerManager.startContainers(
        StartContainersRequest.newInstance(moreContainerRequests));
    ((ContainerManagerForTest) containerManager).drainAsyncEvents();

    // All OPPORTUNISTIC containers but the last one should be queued.
    // The last OPPORTUNISTIC container to launch should be killed.
    BaseContainerManagerTest.waitForContainerState(
        containerManager, createContainerId(NM_OPPORTUNISTIC_QUEUE_LIMIT + 2),
        ContainerState.COMPLETE);

    HashMap<ContainerId, ContainerSubState> expectedContainerStatus =
        new HashMap<>();
    expectedContainerStatus.put(
        createContainerId(0), ContainerSubState.RUNNING);
    expectedContainerStatus.put(
        createContainerId(1), ContainerSubState.RUNNING);
    expectedContainerStatus.put(
        createContainerId(NM_OPPORTUNISTIC_QUEUE_LIMIT),
        ContainerSubState.DONE);
    for (int i = 0; i < NM_OPPORTUNISTIC_QUEUE_LIMIT; i++) {
      expectedContainerStatus.put(
          createContainerId(i + 2), ContainerSubState.SCHEDULED);
    }
    verifyContainerStatuses(expectedContainerStatus);
  }

  /**
   * Start two GUARANTEED containers that together does not take up the
   * whole node. Then try to start one OPPORTUNISTIC container that will
   * fit into the remaining unallocated space on the node.
   * The OPPORTUNISTIC container is expected to start even though the
   * current node utilization is above the NM overallocation threshold,
   * because it's always safe to launch containers as long as the node
   * has not been fully allocated.
   */
  @Test
  public void testStartOppContainerWithHighUtilizationNoOverallocation()
      throws Exception {
    containerManager.start();

    containerManager.startContainers(StartContainersRequest.newInstance(
        new ArrayList<StartContainerRequest>() {
          {
            add(createStartContainerRequest(0,
                BuilderUtils.newResource(1200, 1), ExecutionType.GUARANTEED));
            add(createStartContainerRequest(1,
                BuilderUtils.newResource(400, 1), ExecutionType.GUARANTEED));
          }
        }
    ));
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(0), ContainerSubState.RUNNING);
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(1), ContainerSubState.RUNNING);

    // containers utilization is above the over-allocation threshold
    // 1600 MBs out of 2GBs and 2 out of 4 vcores are being used.
    setContainerResourceUtilization(
        ResourceUtilization.newInstance(1600, 0, 2.0f));

    // start a container that can just fit in the remaining unallocated space
    containerManager.startContainers(StartContainersRequest.newInstance(
        Collections.singletonList(
            createStartContainerRequest(2,
                BuilderUtils.newResource(400, 1), ExecutionType.OPPORTUNISTIC))
    ));

    // the OPPORTUNISTIC container can be safely launched even though
    // the container utilization is above the NM overallocation threshold
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(2), ContainerSubState.RUNNING);

    verifyContainerStatuses(new HashMap<ContainerId, ContainerSubState>() {
      {
        put(createContainerId(0), ContainerSubState.RUNNING);
        put(createContainerId(1), ContainerSubState.RUNNING);
        put(createContainerId(2), ContainerSubState.RUNNING);
      }
    });
  }

  /**
   * Start two OPPORTUNISTIC containers first whose utilization is low relative
   * to the resources they requested, resulting in a low node utilization. Then
   * try to start a GUARANTEED container which requests more than what's left
   * unallocated on the node. Because the node utilization is low and NM
   * overallocation is turned on, the GUARANTEED container is expected to be
   * started immediately without killing any running OPPORTUNISTIC containers.
   */
  @Test
  public void testKillNoOppContainersWithPartialOverallocationLowUtilization()
      throws Exception {
    containerManager.start();

    containerManager.startContainers(StartContainersRequest.newInstance(
        new ArrayList<StartContainerRequest>() {
          {
            add(createStartContainerRequest(0,
                BuilderUtils.newResource(1024, 1),
                ExecutionType.OPPORTUNISTIC));
            add(createStartContainerRequest(1,
                BuilderUtils.newResource(824, 1),
                ExecutionType.OPPORTUNISTIC));
          }
        }
    ));
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(0), ContainerSubState.RUNNING);
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(1), ContainerSubState.RUNNING);

    // containers utilization is low, only 512 MBs out of 2GBs and 0.5
    // out of 4 vcores are being used
    setContainerResourceUtilization(
        ResourceUtilization.newInstance(512, 0, 0.5f));

    // start a GUARANTEED container that requests more than what's left
    // unallocated on the node: (512  + 1024 + 824) > 2048
    containerManager.startContainers(StartContainersRequest.newInstance(
        Collections.singletonList(
            createStartContainerRequest(2,
                BuilderUtils.newResource(512, 1), ExecutionType.GUARANTEED))
    ));

    // the GUARANTEED container is expected be launched immediately without
    // killing any OPPORTUNISTIC containers.
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(2), ContainerSubState.RUNNING);

    verifyContainerStatuses(new HashMap<ContainerId, ContainerSubState>() {
      {
        put(createContainerId(0), ContainerSubState.RUNNING);
        put(createContainerId(1), ContainerSubState.RUNNING);
        put(createContainerId(2), ContainerSubState.RUNNING);
      }
    });
  }

  /**
   * Start two OPPORTUNISTIC containers whose utilization will be high relative
   * to the resources they requested, resulting in a high node utilization.
   * Then try to start a GUARANTEED container which requests more than what's
   * left unallocated on the node. Because the node is under high utilization,
   * the second OPPORTUNISTIC container is expected to be killed in order to
   * make room for the GUARANTEED container.
   */
  @Test
  public void testKillOppContainersWithPartialOverallocationHighUtilization()
      throws Exception {
    containerManager.start();

    containerManager.startContainers(StartContainersRequest.newInstance(
        new ArrayList<StartContainerRequest>() {
          {
            add(createStartContainerRequest(0,
                BuilderUtils.newResource(1024, 1),
                ExecutionType.OPPORTUNISTIC));
            add(createStartContainerRequest(1,
                BuilderUtils.newResource(824, 1),
                ExecutionType.OPPORTUNISTIC));
          }
        }
    ));
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(0), ContainerSubState.RUNNING);
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(1), ContainerSubState.RUNNING);

    // the containers memory utilization is very high, 1800 MBs out of
    // 2GBs of memory is being used. But the cpu utilization, 0.5 out of
    // 4 vcores is very low.
    setContainerResourceUtilization(
        ResourceUtilization.newInstance(1800, 0, 0.5f));

    // start a GUARANTEED container that requests more than what's left
    // unallocated on the node 512 + 1024 + 824 > 2048
    containerManager.startContainers(StartContainersRequest.newInstance(
        Collections.singletonList(
            createStartContainerRequest(2,
                BuilderUtils.newResource(512, 1), ExecutionType.GUARANTEED))
    ));

    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(2), ContainerSubState.RUNNING);
    // the last launched OPPORTUNISTIC container is expected to be killed
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(1), ContainerSubState.DONE);

    GetContainerStatusesRequest statRequest = GetContainerStatusesRequest.
        newInstance(new ArrayList<ContainerId>() {
          {
            add(createContainerId(0));
            add(createContainerId(1));
            add(createContainerId(2));
          }
        });
    List<ContainerStatus> containerStatuses = containerManager
        .getContainerStatuses(statRequest).getContainerStatuses();
    for (ContainerStatus status : containerStatuses) {
      if (status.getContainerId().equals(createContainerId(1))) {
        Assert.assertTrue(status.getDiagnostics().contains(
            "Container Killed to make room for Guaranteed Container"));
      } else {
        Assert.assertEquals(status.getContainerId() + " is not RUNNING",
            ContainerSubState.RUNNING, status.getContainerSubState());
      }
      System.out.println("\nStatus : [" + status + "]\n");
    }
  }


  /**
   * Start three OPPORTUNISTIC containers which in aggregates exceeds the
   * capacity of the node, yet whose utilization is low relative
   * to the resources they requested, resulting in a low node utilization.
   * Then try to start a GUARANTEED container. Even though the node has
   * nothing left unallocated, it is expected to start immediately
   * without killing any running OPPORTUNISTIC containers because the node
   * utilization is very low and overallocation is turned on.
   */
  @Test
  public void testKillNoOppContainersWithOverallocationLowUtilization()
      throws Exception {
    containerManager.start();

    containerManager.startContainers(StartContainersRequest.newInstance(
        new ArrayList<StartContainerRequest>() {
          {
            add(createStartContainerRequest(0,
                BuilderUtils.newResource(1024, 1),
                ExecutionType.OPPORTUNISTIC));
            add(createStartContainerRequest(1,
                BuilderUtils.newResource(1024, 1),
                ExecutionType.OPPORTUNISTIC));
            add(createStartContainerRequest(2,
                BuilderUtils.newResource(1024, 1),
                ExecutionType.OPPORTUNISTIC));
          }
        }
    ));
    ((ContainerManagerForTest) containerManager).drainAsyncEvents();

    // Two OPPORTUNISTIC containers are expected to start with the
    // unallocated resources, but one will be queued because no
    // over-allocation is allowed at container scheduler events.
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(0), ContainerSubState.RUNNING);
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(1), ContainerSubState.RUNNING);
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(2), ContainerSubState.SCHEDULED);

    // try to start the opportunistic container out of band because it can
    // not be launched at container scheduler event if the node would be
    // over-allocated.
    ((ContainerManagerForTest) containerManager)
        .checkNodeResourceUtilization();

    // now the queued opportunistic container should also start
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(2), ContainerSubState.RUNNING);

    // the containers utilization is low, 1024 MBs out of 2GBs and 0.5
    // out of 4 vcores are being used.
    setContainerResourceUtilization(
        ResourceUtilization.newInstance(1024, 0, 0.5f));

    // start a GUARANTEED container that requests more than what's left
    // unallocated on the node: (512  + 1024 + 824) > 2048
    containerManager.startContainers(StartContainersRequest.newInstance(
        Collections.singletonList(
            createStartContainerRequest(3,
                BuilderUtils.newResource(512, 1), ExecutionType.GUARANTEED))
    ));

    // the GUARANTEED container is expected be launched immediately without
    // killing any OPPORTUNISTIC containers
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(3), ContainerSubState.RUNNING);

    verifyContainerStatuses(new HashMap<ContainerId, ContainerSubState>() {
      {
        put(createContainerId(0), ContainerSubState.RUNNING);
        put(createContainerId(1), ContainerSubState.RUNNING);
        put(createContainerId(2), ContainerSubState.RUNNING);
        put(createContainerId(3), ContainerSubState.RUNNING);
      }
    });
  }

  /**
   * Start two OPPORTUNISTIC containers followed by one GUARANTEED container,
   * which in aggregate exceeds the capacity of the node. The first two
   * OPPORTUNISTIC containers use almost no resources whereas the GUARANTEED
   * one utilizes nearly all of its resource requested. Then try to start two
   * more OPPORTUNISTIC containers. The two OPPORTUNISTIC containers are
   * expected to be queued immediately. Upon the completion of the
   * resource-usage-heavy GUARANTEED container, both OPPORTUNISTIC containers
   * are expected to start.
   */
  @Test
  public void testStartOppContainersUponContainerCompletion() throws Exception {
    containerManager.start();

    containerManager.startContainers(StartContainersRequest.newInstance(
        new ArrayList<StartContainerRequest>() {
          {
            add(createStartContainerRequest(0,
                BuilderUtils.newResource(512, 1), ExecutionType.OPPORTUNISTIC));
            add(createStartContainerRequest(1,
                BuilderUtils.newResource(512, 1), ExecutionType.OPPORTUNISTIC));
            add(createStartContainerRequest(2,
                BuilderUtils.newResource(1024, 1), ExecutionType.GUARANTEED));
          }
        }
    ));

    // All three containers are all expected to start immediately
    // because the node utilization is low (0 at the point)
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(0), ContainerSubState.RUNNING);
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(1), ContainerSubState.RUNNING);
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(2), ContainerSubState.RUNNING);

    // the container memory utilization is at the overallocation threshold
    // 2048 * 0.75 = 1536 MB, the cpu utilization is 2 out of 4 vcores.
    setContainerResourceUtilization(
        ResourceUtilization.newInstance(1536, 0, 2.0f));

    containerManager.startContainers(StartContainersRequest.newInstance(
        new ArrayList<StartContainerRequest>() {
          {
            add(createStartContainerRequest(3,
                BuilderUtils.newResource(512, 1), ExecutionType.OPPORTUNISTIC));
            add(createStartContainerRequest(4,
                BuilderUtils.newResource(800, 1), ExecutionType.OPPORTUNISTIC));
          }
        }
    ));
    // the two new OPPORTUNISTIC containers are expected to be queued
    verifyContainerStatuses(new HashMap<ContainerId, ContainerSubState>() {
      {
        put(createContainerId(3), ContainerSubState.SCHEDULED);
        put(createContainerId(4), ContainerSubState.SCHEDULED);
      }
    });

    // the GUARANTEED container is completed releasing resources, the
    // utilization goes down to 100 MB out of 2GBs of memory and 0.8
    // out of 4 vcores
    setContainerResourceUtilization(
        ResourceUtilization.newInstance(100, 0, 0.8f));
    allowContainerToSucceed(2);
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(2), ContainerSubState.DONE);

    ((ContainerManagerForTest) containerManager).drainAsyncEvents();

    // only one OPPORTUNISTIC container is start because no over-allocation
    // is allowed to start OPPORTUNISTIC containers at container finish event.
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(3), ContainerSubState.RUNNING);
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(4), ContainerSubState.SCHEDULED);

    verifyContainerStatuses(new HashMap<ContainerId, ContainerSubState>() {
      {
        put(createContainerId(0), ContainerSubState.RUNNING);
        put(createContainerId(1), ContainerSubState.RUNNING);
        put(createContainerId(2), ContainerSubState.DONE);
        put(createContainerId(3), ContainerSubState.RUNNING);
        put(createContainerId(4), ContainerSubState.SCHEDULED);
      }
    });

    // now try to start the OPPORTUNISTIC container that was queued because
    // we don't start OPPORTUNISTIC containers at container finish event if
    // the node would be over-allocated
    ((ContainerManagerForTest) containerManager)
        .checkNodeResourceUtilization();
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(4), ContainerSubState.RUNNING);
    verifyContainerStatuses(new HashMap<ContainerId, ContainerSubState>() {
      {
        put(createContainerId(0), ContainerSubState.RUNNING);
        put(createContainerId(1), ContainerSubState.RUNNING);
        put(createContainerId(2), ContainerSubState.DONE);
        put(createContainerId(3), ContainerSubState.RUNNING);
        put(createContainerId(4), ContainerSubState.RUNNING);
      }
    });
  }

  /**
   * Start one GUARANTEED container that consumes all the resources on the
   * node and keeps running, followed by two OPPORTUNISTIC containers that
   * will be queued forever because there is no containers starting or
   * finishing. Then try to start OPPORTUNISTIC containers out of band.
   */
  @Test
  public void testStartOpportunisticContainersOutOfBand() throws Exception {
    containerManager.start();

    containerManager.startContainers(StartContainersRequest.newInstance(
        Collections.singletonList(
            createStartContainerRequest(0,
                BuilderUtils.newResource(2048, 4), ExecutionType.GUARANTEED))));
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(0), ContainerSubState.RUNNING);

    // the container is fully utilizing its resources, 2GBs out of its 2GBs of
    // memory and 4 out of 4 vcores
    setContainerResourceUtilization(
        ResourceUtilization.newInstance(2048, 0, 4.0f));

    // send two OPPORTUNISTIC container requests that are expected to be queued
    containerManager.startContainers(StartContainersRequest.newInstance(
        new ArrayList<StartContainerRequest>() {
          {
            add(createStartContainerRequest(1,
                BuilderUtils.newResource(512, 1), ExecutionType.OPPORTUNISTIC));
            add(createStartContainerRequest(2,
                BuilderUtils.newResource(512, 1), ExecutionType.OPPORTUNISTIC));
          }
        }
    ));
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(1), ContainerSubState.SCHEDULED);
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(2), ContainerSubState.SCHEDULED);

    // the containers memory utilization dropped to the overallocation threshold
    // 0.75 * 2048 = 1536 MBs. The cpu utilization, 2 out of 4 vcores is also
    // below the cpu overallocation threshold.
    setContainerResourceUtilization(
        ResourceUtilization.newInstance(1536, 0, 2.0f));

    // try to start opportunistic containers out of band.
    ((ContainerManagerForTest) containerManager)
        .checkNodeResourceUtilization();

    // no containers in queue are expected to be launched because the
    // containers utilization is not below the over-allocation threshold
    verifyContainerStatuses(new HashMap<ContainerId, ContainerSubState>() {
      {
        put(createContainerId(0), ContainerSubState.RUNNING);
        put(createContainerId(1), ContainerSubState.SCHEDULED);
        put(createContainerId(2), ContainerSubState.SCHEDULED);
      }
    });

    // the GUARANTEED container is completed releasing resources, now the
    // utilization is 100 MBs out of 2GBs of memory and 0.8 out of 4 vcores
    setContainerResourceUtilization(
        ResourceUtilization.newInstance(100, 0, 0.8f));

    // the containers utilization dropped way below the overallocation threshold
    // 512 MBs < 2048 * 0.75 = 1536 MBs, 0.5 vcores < 4 vcores * 0.75 = 3 vcores
    setContainerResourceUtilization(
        ResourceUtilization.newInstance(512, 0, 0.5f));

    ((ContainerManagerForTest) containerManager)
        .checkNodeResourceUtilization();

    // the two OPPORTUNISTIC containers are expected to be launched
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(1), ContainerSubState.RUNNING);
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(2), ContainerSubState.RUNNING);

    verifyContainerStatuses(new HashMap<ContainerId, ContainerSubState>() {
      {
        put(createContainerId(0), ContainerSubState.RUNNING);
        put(createContainerId(1), ContainerSubState.RUNNING);
        put(createContainerId(2), ContainerSubState.RUNNING);
      }
    });
  }

  /**
   * Start a GUARANTEED container, an OPPORTUNISTIC container, a GUARANTEED
   * container and another OPPORTUNISTIC container in order. When the node
   * memory utilization is over its preemption threshold, the two OPPORTUNISTIC
   * containers should be killed.
   */
  @Test
  public void testPreemptOpportunisticContainersUponHighMemoryUtilization()
      throws Exception {
    containerManager.start();

    // try to start four containers at once. the first GUARANTEED container
    // that requests (1024 MB, 1 vcore) can be launched because there is
    // (2048 MB, 4 vcores) unallocated. The second container, which is
    // OPPORTUNISTIC, can also be launched because it asks for 512 MB, 1 vcore
    // which is less than what is left unallocated after launching the first
    // one GUARANTEED container, (1024 MB, 3 vcores).
    // The 3rd container, which is GUARANTEED, can also be launched because
    // the node resource utilization utilization is zero such that
    // over-allocation kicks in. The 4th one, an OPPORTUNISTIC container,
    // will be queued because OPPORTUNISTIC containers can only be
    // launched when node resource utilization is checked, if launching them
    // would cause node over-allocation.
    containerManager.startContainers(StartContainersRequest.newInstance(
        new ArrayList<StartContainerRequest>() {
          {
            add(createStartContainerRequest(0,
                BuilderUtils.newResource(1024, 1), ExecutionType.GUARANTEED));
            add(createStartContainerRequest(1,
                BuilderUtils.newResource(512, 1), ExecutionType.OPPORTUNISTIC));
            add(createStartContainerRequest(2,
                BuilderUtils.newResource(1024, 1), ExecutionType.GUARANTEED));
            add(createStartContainerRequest(3,
                BuilderUtils.newResource(300, 1), ExecutionType.OPPORTUNISTIC));
          }
        }
    ));
    ((ContainerManagerForTest) containerManager).drainAsyncEvents();

    // the first three containers are all expected to start
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(0), ContainerSubState.RUNNING);
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(1), ContainerSubState.RUNNING);
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(2), ContainerSubState.RUNNING);
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(3), ContainerSubState.SCHEDULED);

    // try to check node resource utilization and start the second
    // opportunistic containers out of band. Because the node resource
    // utilization is zero at the moment, over-allocation will kick in
    // and the container will be launched.
    ((ContainerManagerForTest) containerManager)
        .checkNodeResourceUtilization();
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(3), ContainerSubState.RUNNING);

    // the containers memory utilization is over the preemption threshold
    // (2048 > 2048 * 0.8 = 1638.4). the cpu utilization, 2 out of 4 vcores
    // is below its preemption threshold
    setContainerResourceUtilization(
        ResourceUtilization.newInstance(2048, 0, 2.0f));
    ((ContainerManagerForTest) containerManager)
        .checkNodeResourceUtilization();

    // (2048 - 2048 * 0.8) = 409.6 MB of memory needs to be reclaimed,
    // which shall result in both OPPORTUNISTIC containers to be preempted.
    // (Preempting the most recently launched OPPORTUNISTIC container, that
    // is the 4th container, would only release at most 300 MB of memory)
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(1), ContainerSubState.DONE);
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(3), ContainerSubState.DONE);

    verifyContainerStatuses(new HashMap<ContainerId, ContainerSubState>() {
      {
        put(createContainerId(0), ContainerSubState.RUNNING);
        put(createContainerId(1), ContainerSubState.DONE);
        put(createContainerId(2), ContainerSubState.RUNNING);
        put(createContainerId(3), ContainerSubState.DONE);
      }
    });

  }

  /**
   * Start a GUARANTEED container followed by an OPPORTUNISTIC container, which
   * in aggregates does not take more than the capacity of the node.
   * When the node memory utilization is above the preemption threshold, the
   * OPPORTUNISTIC container should not be killed because the node is not being
   * over-allocated.
   */
  @Test
  public void testNoPreemptionUponHighMemoryUtilizationButNoOverallocation()
      throws Exception {
    containerManager.start();

    // start two containers, one GUARANTEED and one OPPORTUNISTIC, that together
    // take up all the allocations (2048 MB of memory and 4 vcores available on
    // the node). They can be both launched immediately because there are enough
    // allocations to do so. When the two containers fully utilize their
    // resource requests, that is, the node is being 100% utilized, the
    // OPPORTUNISTIC container shall continue to run because the node is
    // not be over-allocated.
    containerManager.startContainers(StartContainersRequest.newInstance(
        new ArrayList<StartContainerRequest>() {
          {
            add(createStartContainerRequest(0,
                BuilderUtils.newResource(1024, 2),
                ExecutionType.GUARANTEED));
            add(createStartContainerRequest(1,
                BuilderUtils.newResource(1024, 2),
                ExecutionType.OPPORTUNISTIC));
          }
        }
    ));
    // both containers shall be launched immediately because there are
    // enough allocations to do so
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(0), ContainerSubState.RUNNING);
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(1), ContainerSubState.RUNNING);

    // the node is being fully utilized, which is above the preemption
    // threshold (2048 * 0.75 = 1536 MB, 4 * 0.75 = 3 vcores)
    setContainerResourceUtilization(
        ResourceUtilization.newInstance(2048, 0, 4.0f));
    ((ContainerManagerForTest) containerManager)
        .checkNodeResourceUtilization();

    // no containers shall be preempted because the node is not being
    // over-allocated so it is safe to allow the node to be fully utilized
    verifyContainerStatuses(new HashMap<ContainerId, ContainerSubState>() {
      {
        put(createContainerId(0), ContainerSubState.RUNNING);
        put(createContainerId(1), ContainerSubState.RUNNING);
      }
    });
  }

  /**
   * Start a GUARANTEED container, an OPPORTUNISTIC container, a GUARANTEED
   * container and another OPPORTUNISTIC container in order. When the node
   * cpu utilization is over its preemption threshold a few times in a row,
   * the two OPPORTUNISTIC containers should be killed one by one.
   */
  @Test
  public void testPreemptionUponHighCPUUtilization() throws Exception {
    containerManager.start();

    // try to start 4 containers at once. The first container, can be
    // safely launched immediately (2048 MB, 4 vcores left unallocated).
    // The second container, can also be launched immediately, because
    // there is enough resources unallocated after launching the first
    // container (2048 - 512 = 1536 MB, 4 - 2 = 2 vcores). After launching
    // the first two containers, there are 1024 MBs of memory and 1 vcore
    // left unallocated, so there is not enough allocation to launch the
    // third container. But because the third container is GUARANTEED and
    // the node resource utilization is zero, we can launch it based on
    // over-allocation (the projected resource utilization will be 512 MB
    // of memory and 2 vcores, below the over-allocation threshold)
    // The fourth container, which is OPPORTUNISTIC, will be queued because
    // OPPORTUNISTIC containers can not be launched based on over-allocation
    // upon container start requests (they can only be launched when node
    // resource utilization is checked in ContainersMonitor)
    containerManager.startContainers(StartContainersRequest.newInstance(
        new ArrayList<StartContainerRequest>() {
          {
            add(createStartContainerRequest(0,
                BuilderUtils.newResource(512, 2), ExecutionType.GUARANTEED));
            add(createStartContainerRequest(1,
                BuilderUtils.newResource(512, 1), ExecutionType.OPPORTUNISTIC));
            add(createStartContainerRequest(2,
                BuilderUtils.newResource(512, 2), ExecutionType.GUARANTEED));
            add(createStartContainerRequest(3,
                BuilderUtils.newResource(512, 1), ExecutionType.OPPORTUNISTIC));
          }
        }
    ));
    ((ContainerManagerForTest) containerManager).drainAsyncEvents();
    // the first three containers are expected to start. The first two
    // can be launched based on free allocation, the third can be
    // launched based on over-allocation
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(0), ContainerSubState.RUNNING);
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(1), ContainerSubState.RUNNING);
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(2), ContainerSubState.RUNNING);

    // try to start second opportunistic containers out of band.
    ((ContainerManagerForTest) containerManager)
        .checkNodeResourceUtilization();

    // the second opportunistic container is expected to start because
    // the node resource utilization is at zero, the projected utilization
    // is 512 MBs of memory and 1 vcore
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(3), ContainerSubState.RUNNING);

    final float fullCpuUtilization = 1.0f * 4;

    // the containers CPU utilization is over its preemption threshold
    // (0.8f * 4 = 3.2 vcores) for the first time
    setContainerResourceUtilization(
        ResourceUtilization.newInstance(2048, 0, fullCpuUtilization));
    ((ContainerManagerForTest) containerManager)
        .checkNodeResourceUtilization();

    // all containers should continue to be running because we don't
    // preempt OPPORTUNISTIC containers right away
    verifyContainerStatuses(new HashMap<ContainerId, ContainerSubState>() {
      {
        put(createContainerId(0), ContainerSubState.RUNNING);
        put(createContainerId(1), ContainerSubState.RUNNING);
        put(createContainerId(2), ContainerSubState.RUNNING);
        put(createContainerId(3), ContainerSubState.RUNNING);
      }
    });

    // the containers CPU utilization is over its preemption threshold
    // (0.8f * 4 = 3.2 vcores) for the second time
    setContainerResourceUtilization(
        ResourceUtilization.newInstance(2048, 0, fullCpuUtilization));
    ((ContainerManagerForTest) containerManager)
        .checkNodeResourceUtilization();

    // all containers should continue to be running because we don't preempt
    // OPPORTUNISTIC containers when the cpu is over the preemption threshold
    // (0.8f) the second time
    verifyContainerStatuses(new HashMap<ContainerId, ContainerSubState>() {
      {
        put(createContainerId(0), ContainerSubState.RUNNING);
        put(createContainerId(1), ContainerSubState.RUNNING);
        put(createContainerId(2), ContainerSubState.RUNNING);
        put(createContainerId(3), ContainerSubState.RUNNING);
      }
    });

    // the containers CPU utilization is over the preemption threshold
    // (0.8f * 4 = 3.2 vcores) for the third time
    setContainerResourceUtilization(
        ResourceUtilization.newInstance(2048, 0, fullCpuUtilization));
    ((ContainerManagerForTest) containerManager)
        .checkNodeResourceUtilization();

    // because CPU utilization is over its preemption threshold three times
    // consecutively, the amount of cpu utilization over the preemption
    // threshold, that is, 1.0 - 0.8 = 0.2f CPU needs to be reclaimed and
    // as a result, the most recently launched OPPORTUNISTIC container should
    // be killed
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(3), ContainerSubState.DONE);
    verifyContainerStatuses(new HashMap<ContainerId, ContainerSubState>() {
      {
        put(createContainerId(0), ContainerSubState.RUNNING);
        put(createContainerId(1), ContainerSubState.RUNNING);
        put(createContainerId(2), ContainerSubState.RUNNING);
        put(createContainerId(3), ContainerSubState.DONE);
      }
    });

    // again, the containers CPU utilization is over the preemption threshold
    // (0.8f * 4) for the first time (the cpu over-limit count is reset every
    // time a preemption is triggered)
    setContainerResourceUtilization(
        ResourceUtilization.newInstance(2048, 0, fullCpuUtilization));
    ((ContainerManagerForTest) containerManager)
        .checkNodeResourceUtilization();

    // no CPU resource is expected to be reclaimed when the CPU utilization
    // goes over the preemption threshold the first time
    verifyContainerStatuses(new HashMap<ContainerId, ContainerSubState>() {
      {
        put(createContainerId(0), ContainerSubState.RUNNING);
        put(createContainerId(1), ContainerSubState.RUNNING);
        put(createContainerId(2), ContainerSubState.RUNNING);
        put(createContainerId(3), ContainerSubState.DONE);
      }
    });

    // the containers CPU utilization is over the preemption threshold
    // (0.8f * 4 = 3.2 vcores) for the second time
    setContainerResourceUtilization(
        ResourceUtilization.newInstance(2048, 0, fullCpuUtilization));
    ((ContainerManagerForTest) containerManager)
        .checkNodeResourceUtilization();

    // still no CPU resource is expected to be reclaimed when the CPU
    // utilization goes over the preemption threshold the second time
    verifyContainerStatuses(new HashMap<ContainerId, ContainerSubState>() {
      {
        put(createContainerId(0), ContainerSubState.RUNNING);
        put(createContainerId(1), ContainerSubState.RUNNING);
        put(createContainerId(2), ContainerSubState.RUNNING);
        put(createContainerId(3), ContainerSubState.DONE);
      }
    });

    // the containers CPU utilization is over the preemption threshold
    // for the third time
    setContainerResourceUtilization(
        ResourceUtilization.newInstance(2048, 0, fullCpuUtilization));
    ((ContainerManagerForTest) containerManager)
        .checkNodeResourceUtilization();

    // because CPU utilization is over its preemption threshold three times
    // consecutively, the amount of cpu utilization over the preemption
    // threshold, that is, (1.0 - 0.8) * 4 = 0.8f CPU needs to be reclaimed
    // and as a result, the other OPPORTUNISTIC container should be killed
    BaseContainerManagerTest.waitForContainerSubState(containerManager,
        createContainerId(1), ContainerSubState.DONE);
    verifyContainerStatuses(new HashMap<ContainerId, ContainerSubState>() {
      {
        put(createContainerId(0), ContainerSubState.RUNNING);
        put(createContainerId(1), ContainerSubState.DONE);
        put(createContainerId(2), ContainerSubState.RUNNING);
        put(createContainerId(3), ContainerSubState.DONE);
      }
    });
  }


  private void setContainerResourceUtilization(ResourceUtilization usage) {
    ((ContainerMonitorForTest) containerManager.getContainersMonitor())
        .setContainerResourceUsage(usage);
  }

  private void allowContainerToSucceed(int containerId) {
    ((LongRunningContainerSimulatingContainerExecutor) this.exec)
        .containerSucceeded(createContainerId(containerId));
  }


  protected StartContainerRequest createStartContainerRequest(
      int containerId, Resource resource, ExecutionType executionType)
      throws IOException {
    ContainerLaunchContext containerLaunchContext =
        recordFactory.newRecordInstance(ContainerLaunchContext.class);
    Token containerToken = createContainerToken(
        createContainerId(containerId),
        DUMMY_RM_IDENTIFIER, context.getNodeId(), user, resource,
        context.getContainerTokenSecretManager(),
        null, executionType);

    return StartContainerRequest.newInstance(
        containerLaunchContext, containerToken);
  }

  protected void verifyContainerStatuses(
      Map<ContainerId, ContainerSubState> expected)
      throws IOException, YarnException {
    List<ContainerId> statList = new ArrayList<>(expected.keySet());
    GetContainerStatusesRequest statRequest =
        GetContainerStatusesRequest.newInstance(statList);
    List<ContainerStatus> containerStatuses = containerManager
        .getContainerStatuses(statRequest).getContainerStatuses();

    for (ContainerStatus status : containerStatuses) {
      ContainerId containerId = status.getContainerId();
      Assert.assertEquals(containerId + " is in unexpected state",
          expected.get(containerId), status.getContainerSubState());
    }
  }

  /**
   * A container manager that sends a dummy container pid while it's cleaning
   * up running containers. Used along with
   * LongRunningContainerSimulatingContainerExecutor to simulate long running
   * container processes for testing purposes.
   */
  private static class LongRunningContainerSimulatingContainersManager
      extends ContainerManagerForTest {

    LongRunningContainerSimulatingContainersManager(
        Context context, ContainerExecutor exec,
        DeletionService deletionContext,
        NodeStatusUpdater nodeStatusUpdater,
        NodeManagerMetrics metrics,
        LocalDirsHandlerService dirsHandler, String user) {
        super(context, exec, deletionContext,
          nodeStatusUpdater, metrics, dirsHandler, user);
    }

    /**
     * Create a container launcher that signals container processes
     * with a dummy pid. The container processes are simulated in
     * LongRunningContainerSimulatingContainerExecutor which does
     * not write a pid file on behalf of containers to launch, so
     * the pid does not matter.
     */
    @Override
    protected ContainersLauncher createContainersLauncher(
        Context context, ContainerExecutor exec) {
      ContainerManagerImpl containerManager = this;
      return new ContainersLauncher(context, dispatcher, exec, dirsHandler,
          this) {
        @Override
        protected ContainerLaunch createContainerLaunch(
            Application app, Container container) {
          return new ContainerLaunch(context, getConfig(), dispatcher,
              exec, app, container, dirsHandler, containerManager) {
            @Override
            protected String getContainerPid(Path pidFilePath)
                throws Exception {
              return "123";
            }
          };
        }
      };
    }
  }

  /**
   * A container executor that simulates long running container processes
   * by having container launch threads sleep infinitely until it's given
   * a signal to finish with either a success or failure exit code.
   */
  private static class LongRunningContainerSimulatingContainerExecutor
      extends DefaultContainerExecutor {
    private ConcurrentHashMap<ContainerId, ContainerFinishLatch> containers =
        new ConcurrentHashMap<>();

    public void containerSucceeded(ContainerId containerId) {
      ContainerFinishLatch containerFinishLatch = containers.get(containerId);
      if (containerFinishLatch != null) {
        containerFinishLatch.toSucceed();
      }
    }

    public void containerFailed(ContainerId containerId) {
      ContainerFinishLatch containerFinishLatch = containers.get(containerId);
      if (containerFinishLatch != null) {
        containerFinishLatch.toFail();
      }
    }

    /**
     * Simulate long running container processes by having container launcher
     * threads wait infinitely for a signal to finish.
     */
    @Override
    public int launchContainer(ContainerStartContext ctx)
        throws IOException, ConfigurationException {
      ContainerId container = ctx.getContainer().getContainerId();
      containers.putIfAbsent(container, new ContainerFinishLatch(container));

      // simulate a long running container process by having the
      // container launch thread sleep forever until it's given a
      // signal to finish with a exit code.
      while (!containers.get(container).toProceed) {
        try {
          Thread.sleep(100);
        } catch (InterruptedException e) {
          return -1;
        }
      }

      return containers.get(container).getContainerExitCode();
    }

    /**
     * Override signalContainer() so that simulated container processes
     * are properly cleaned up.
     */
    @Override
    public boolean signalContainer(ContainerSignalContext ctx)
        throws IOException {
      containerSucceeded(ctx.getContainer().getContainerId());
      return true;
    }

    /**
     * A signal that container launch threads wait for before exiting
     * in order to simulate long running container processes.
     */
    private static final class ContainerFinishLatch {
      volatile boolean toProceed;
      int exitCode;
      ContainerId container;

      ContainerFinishLatch(ContainerId containerId) {
        exitCode = 0;
        toProceed = false;
        container = containerId;
      }

      void toSucceed() {
        exitCode = 0;
        toProceed = true;
      }

      void toFail() {
        exitCode = -101;
        toProceed = true;
      }

      int getContainerExitCode() {
        // read barrier of toProceed to make sure the exit code is not stale
        if (toProceed) {
          LOG.debug(container + " finished with exit code: " + exitCode);
        }
        return exitCode;
      }
    }
  }
}
