/*
 * 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.appstate

import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.yarn.api.records.Container
import org.apache.slider.api.StatusKeys
import org.apache.slider.server.appmaster.model.mock.BaseMockAppStateTest
import org.apache.slider.server.appmaster.model.mock.MockRecordFactory
import org.apache.slider.server.appmaster.model.mock.MockRoles
import org.apache.slider.server.appmaster.operations.AbstractRMOperation
import org.apache.slider.server.appmaster.state.*
import org.junit.Test

/**
 * Test that if you have >1 role, the right roles are chosen for release.
 */
@CompileStatic
@Slf4j
class TestMockAppStateRebuildOnAMRestart extends BaseMockAppStateTest
    implements MockRoles {

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

  @Test
  public void testRebuild() throws Throwable {

    int r0 = 1
    int r1 = 2
    int r2 = 3
    role0Status.desired = r0
    role1Status.desired = r1
    role2Status.desired = r2
    List<RoleInstance> instances = createAndStartNodes()

    int clusterSize = r0 + r1 + r2
    assert instances.size() == clusterSize

    //clone the list
    List<RoleInstance> cloned = [];
    List<Container> containers = []
    instances.each { RoleInstance elt ->
      cloned.add(elt.clone() as RoleInstance)
      containers.add(elt.container)
    }
    NodeMap nodemap = appState.roleHistory.cloneNodemap()

    // now destroy the app state
    appState = new AppState(new MockRecordFactory())

    //and rebuild
    appState.buildInstance(
        factory.newInstanceDefinition(r0, r1, r2),
        new Configuration(),
        new Configuration(false),
        factory.ROLES,
        fs,
        historyPath,
        containers,
        null, new SimpleReleaseSelector())

    assert appState.getStartedCountainerCount() == clusterSize

    appState.getRoleHistory().dump();

    //check that the app state direct structures match
    List<RoleInstance> r0live = appState.enumLiveNodesInRole(ROLE0)
    List<RoleInstance> r1live = appState.enumLiveNodesInRole(ROLE1)
    List<RoleInstance> r2live = appState.enumLiveNodesInRole(ROLE2)

    assert r0 == r0live.size()
    assert r1 == r1live.size()
    assert r2 == r2live.size()

    //now examine the role history
    NodeMap newNodemap = appState.roleHistory.cloneNodemap()

    for (NodeInstance nodeInstance : newNodemap.values()) {
      String hostname = nodeInstance.hostname
      NodeInstance orig = nodemap[hostname]
      assertNotNull("Null entry in original nodemap for " + hostname, orig)

      for (int i = 0; i < ROLE_COUNT; i++) {
        
        assert (nodeInstance.getActiveRoleInstances(i) ==
                orig.getActiveRoleInstances(i))
        NodeEntry origRE = orig.getOrCreate(i)
        NodeEntry newRE = nodeInstance.getOrCreate(i)
        assert origRE.live == newRE.live
        assert newRE.starting == 0
      }
    }
    List<AbstractRMOperation> ops = appState.reviewRequestAndReleaseNodes()
    assert ops.size() == 0

    def status = appState.getClusterStatus()
    // verify the AM restart container count was set
    String restarted = status.getInfo(
        StatusKeys.INFO_CONTAINERS_AM_RESTART)
    assert restarted != null;
    //and that the count == 1 master + the region servers
    assert Integer.parseInt(restarted) == containers.size()
  }
}
