/*
 * 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.slider.server.appmaster.model.history

import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import org.apache.hadoop.yarn.api.records.Container
import org.apache.hadoop.yarn.api.records.Priority
import org.apache.hadoop.yarn.api.records.Resource
import org.apache.hadoop.yarn.client.api.AMRMClient
import org.apache.slider.api.ResourceKeys
import org.apache.slider.providers.ProviderRole
import org.apache.slider.server.appmaster.model.mock.BaseMockAppStateTest
import org.apache.slider.server.appmaster.model.mock.MockContainer
import org.apache.slider.server.appmaster.model.mock.MockFactory
import org.apache.slider.server.appmaster.model.mock.MockNodeId
import org.apache.slider.server.appmaster.state.*
import org.junit.Before
import org.junit.Test

/**
 * Test container events at the role history level -one below
 * the App State
 */
@Slf4j
@CompileStatic
class TestRoleHistoryContainerEvents extends BaseMockAppStateTest {

  @Override
  String getTestName() {
    return "TestRoleHistoryContainerEvents"
  }

  NodeInstance age1Active4 = nodeInstance(1, 4, 0, 0)
  NodeInstance age2Active2 = nodeInstance(2, 2, 0, 1)
  NodeInstance age3Active0 = nodeInstance(3, 0, 0, 0)
  NodeInstance age4Active1 = nodeInstance(4, 1, 0, 0)
  NodeInstance age2Active0 = nodeInstance(2, 0, 0, 0)
  NodeInstance empty = new NodeInstance("empty", MockFactory.ROLE_COUNT)
  
  String roleName = "test"

  List<NodeInstance> nodes = [age2Active2, age2Active0, age4Active1, age1Active4, age3Active0]
  RoleHistory roleHistory = new RoleHistory(MockFactory.ROLES)

  Resource resource

  @Before
  public void setupRH() {
    roleHistory.onStart(fs, historyPath)
    roleHistory.insert(nodes)
    roleHistory.buildAvailableNodeLists();
    resource = Resource.newInstance(ResourceKeys.DEF_YARN_CORES,
                                    ResourceKeys.DEF_YARN_MEMORY);
  }

  @Test
  public void testFindAndCreate() throws Throwable {
    int role = 0
    ProviderRole provRole = new ProviderRole(roleName, role)
    RoleStatus roleStatus = new RoleStatus(provRole)

    AMRMClient.ContainerRequest request =
        roleHistory.requestNode(roleStatus, resource);

    List<String> nodes = request.getNodes()
    assert nodes != null
    assert nodes.size() == 1
    String hostname = nodes[0]
    assert hostname == age3Active0.hostname

    //build a container
    MockContainer container = factory.newContainer()
    container.nodeId = new MockNodeId(hostname, 0)
    container.priority = request.getPriority()
    roleHistory.onContainerAssigned(container);

    NodeMap nodemap = roleHistory.cloneNodemap();
    NodeInstance allocated = nodemap.get(hostname)
    NodeEntry roleEntry = allocated.get(role)
    assert roleEntry.starting == 1
    assert !roleEntry.available
    RoleInstance ri = new RoleInstance(container);
    //start it
    roleHistory.onContainerStartSubmitted(container, ri)
    //later, declare that it started
    roleHistory.onContainerStarted(container)
    assert roleEntry.starting == 0
    assert !roleEntry.available
    assert roleEntry.active == 1
    assert roleEntry.live == 1
  }

  @Test
  public void testCreateAndRelease() throws Throwable {
    int role = 1
    ProviderRole provRole = new ProviderRole(roleName, role)
    RoleStatus roleStatus = new RoleStatus(provRole)

    //verify it is empty
    assert roleHistory.listActiveNodes(role).empty

    AMRMClient.ContainerRequest request =
        roleHistory.requestNode(roleStatus, resource);

    List<String> nodes = request.nodes
    assert nodes == null

    //pick an idle host
    String hostname = age3Active0.hostname;

    //build a container
    MockContainer container = factory.newContainer()
    container.nodeId = new MockNodeId(hostname, 0)
    container.priority = request.priority
    roleHistory.onContainerAssigned(container);

    NodeMap nodemap = roleHistory.cloneNodemap();
    NodeInstance allocated = nodemap.get(hostname)
    NodeEntry roleEntry = allocated.get(role)
    assert roleEntry.starting == 1
    assert !roleEntry.available
    RoleInstance ri = new RoleInstance(container);
    //start it
    roleHistory.onContainerStartSubmitted(container, ri)
    //later, declare that it started
    roleHistory.onContainerStarted(container)
    assert roleEntry.starting == 0
    assert !roleEntry.available
    assert roleEntry.active == 1
    assert roleEntry.live == 1

    // now pick that instance to destroy
    List<NodeInstance> activeNodes = roleHistory.listActiveNodes(role)


    assert activeNodes.size() == 1
    NodeInstance target = activeNodes[0]
    assert target == allocated
    roleHistory.onContainerReleaseSubmitted(container);
    assert roleEntry.releasing == 1
    assert roleEntry.live == 1
    assert roleEntry.active == 0

    // release completed
    roleHistory.onReleaseCompleted(container, true)
    assert roleEntry.releasing == 0
    assert roleEntry.live == 0
    assert roleEntry.active == 0

    // verify it is empty
    assert roleHistory.listActiveNodes(role).empty

    // ask for a container and expect to get the recently released one
    AMRMClient.ContainerRequest request2 =
        roleHistory.requestNode(roleStatus, resource);

    List<String> nodes2 = request2.nodes
    assert nodes2 != null
    String hostname2 = nodes2[0]

    //pick an idle host
    assert hostname2 == age3Active0.hostname;
  }


  @Test
  public void testStartWithoutWarning() throws Throwable {
    int role = 0
    //pick an idle host
    String hostname = age3Active0.hostname;
    //build a container
    MockContainer container = factory.newContainer()
    container.nodeId = new MockNodeId(hostname, 0)
    container.priority = ContainerPriority.createPriority(0, false)
    
    NodeMap nodemap = roleHistory.cloneNodemap();
    NodeInstance allocated = nodemap.get(hostname)
    NodeEntry roleEntry = allocated.get(role)

    RoleInstance ri = new RoleInstance(container);
    //tell RH that it started
    roleHistory.onContainerStarted(container)
    assert roleEntry.starting == 0
    assert !roleEntry.available
    assert roleEntry.active == 1
    assert roleEntry.live == 1
  }

  @Test
  public void testStartFailed() throws Throwable {
    int role = 0
    ProviderRole provRole = new ProviderRole(roleName, role)
    RoleStatus roleStatus = new RoleStatus(provRole)

    AMRMClient.ContainerRequest request =
        roleHistory.requestNode(roleStatus, resource);

    String hostname = request.getNodes()[0]
    assert hostname == age3Active0.hostname

    //build a container
    MockContainer container = factory.newContainer()
    container.nodeId = new MockNodeId(hostname, 0)
    container.priority = request.getPriority()
    roleHistory.onContainerAssigned(container);

    NodeMap nodemap = roleHistory.cloneNodemap();
    NodeInstance allocated = nodemap.get(hostname)
    NodeEntry roleEntry = allocated.get(role)
    assert roleEntry.starting == 1
    assert !roleEntry.available
    RoleInstance ri = new RoleInstance(container);
    //start it
    roleHistory.onContainerStartSubmitted(container, ri)
    //later, declare that it failed on startup
    assert !roleHistory.onNodeManagerContainerStartFailed(container)
    assert roleEntry.starting == 0
    assert roleEntry.startFailed == 1
    assert roleEntry.failed == 1
    assert roleEntry.available
    assert roleEntry.active == 0
    assert roleEntry.live == 0
  }
  
  @Test
  public void testStartFailedWithoutWarning() throws Throwable {
    int role = 0
    ProviderRole provRole = new ProviderRole(roleName, role)
    RoleStatus roleStatus = new RoleStatus(provRole)
    AMRMClient.ContainerRequest request =
        roleHistory.requestNode(roleStatus, resource);

    String hostname = request.getNodes()[0]
    assert hostname == age3Active0.hostname

    //build a container
    MockContainer container = factory.newContainer()
    container.nodeId = new MockNodeId(hostname, 0)
    container.priority = request.getPriority()

    NodeMap nodemap = roleHistory.cloneNodemap();
    NodeInstance allocated = nodemap.get(hostname)
    NodeEntry roleEntry = allocated.get(role)

    assert !roleHistory.onNodeManagerContainerStartFailed(container)
    assert roleEntry.starting == 0
    assert roleEntry.startFailed == 1
    assert roleEntry.failed == 1
    assert roleEntry.available
    assert roleEntry.active == 0
    assert roleEntry.live == 0
  }
  
  @Test
  public void testContainerFailed() throws Throwable {
    describe("fail a container without declaring it as starting")

    int role = 0
    ProviderRole provRole = new ProviderRole(roleName, role)
    RoleStatus roleStatus = new RoleStatus(provRole)
    AMRMClient.ContainerRequest request =
        roleHistory.requestNode(roleStatus, resource);

    String hostname = request.getNodes()[0]
    assert hostname == age3Active0.hostname

    //build a container
    MockContainer container = factory.newContainer()
    container.nodeId = new MockNodeId(hostname, 0)
    container.priority = request.getPriority()
    roleHistory.onContainerAssigned(container);

    NodeMap nodemap = roleHistory.cloneNodemap();
    NodeInstance allocated = nodemap.get(hostname)
    NodeEntry roleEntry = allocated.get(role)
    assert roleEntry.starting == 1
    assert !roleEntry.available
    RoleInstance ri = new RoleInstance(container);
    //start it
    roleHistory.onContainerStartSubmitted(container, ri)
    roleHistory.onContainerStarted(container)

    //later, declare that it failed
    roleHistory.onFailedContainer(container, false)
    assert roleEntry.starting == 0
    assert roleEntry.available
    assert roleEntry.active == 0
    assert roleEntry.live == 0
  }
  
  @Test
  public void testContainerFailedWithoutWarning() throws Throwable {
    describe( "fail a container without declaring it as starting")
    int role = 0
    ProviderRole provRole = new ProviderRole(roleName, role)
    RoleStatus roleStatus = new RoleStatus(provRole)
    AMRMClient.ContainerRequest request =
        roleHistory.requestNode(roleStatus, resource);

    String hostname = request.getNodes()[0]
    assert hostname == age3Active0.hostname

    //build a container
    MockContainer container = factory.newContainer()
    container.nodeId = new MockNodeId(hostname, 0)
    container.priority = request.getPriority()


    NodeMap nodemap = roleHistory.cloneNodemap();
    NodeInstance allocated = nodemap.get(hostname)
    NodeEntry roleEntry = allocated.get(role)
    assert roleEntry.available
    roleHistory.onFailedContainer(container, false)
    assert roleEntry.starting == 0
    assert roleEntry.failed == 1
    assert roleEntry.available
    assert roleEntry.active == 0
    assert roleEntry.live == 0
  }

  @Test
  public void testAllocationListPrep() throws Throwable {
    describe("test prepareAllocationList")
    int role = 0
    ProviderRole provRole = new ProviderRole(roleName, role)
    RoleStatus roleStatus = new RoleStatus(provRole)
    AMRMClient.ContainerRequest request =
        roleHistory.requestNode(roleStatus, resource);

    String hostname = request.getNodes()[0]
    assert hostname == age3Active0.hostname

    MockContainer container1 = factory.newContainer()
    container1.nodeId = new MockNodeId(hostname, 0)
    container1.priority = Priority.newInstance(0);

    MockContainer container2 = factory.newContainer()
    container2.nodeId = new MockNodeId(hostname, 0)
    container2.priority = Priority.newInstance(1);

    // put containers in List with role == 1 first
    List<Container> containers = [ (Container) container2, (Container) container1 ]
    List<Container> sortedContainers = roleHistory.prepareAllocationList(containers)

    // verify that the first container has role == 0 after sorting
    MockContainer c1 = (MockContainer) sortedContainers[0]
    assert c1.priority.getPriority() == 0
    MockContainer c2 = (MockContainer) sortedContainers[1]
    assert c2.priority.getPriority() == 1
  }
}
